|
|
1.1 root 1: /*
2: Copyright (C) 1993 Free Software Foundation
3:
4: This file is part of the GNU IO Library. This library is free
5: software; you can redistribute it and/or modify it under the
6: terms of the GNU General Public License as published by the
7: Free Software Foundation; either version 2, or (at your option)
8: any later version.
9:
10: This library is distributed in the hope that it will be useful,
11: but WITHOUT ANY WARRANTY; without even the implied warranty of
12: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13: GNU General Public License for more details.
14:
15: You should have received a copy of the GNU General Public License
16: along with GNU CC; see the file COPYING. If not, write to
17: the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
18:
19: As a special exception, if you link this library with files
20: compiled with a GNU compiler to produce an executable, this does not cause
21: the resulting executable to be covered by the GNU General Public License.
22: This exception does not however invalidate any other reasons why
23: the executable file might be covered by the GNU General Public License. */
24:
25: /* written by Per Bothner ([email protected]) */
26:
27: #include "libioP.h"
28:
29: #if _IO_HAVE_SYS_WAIT
30: #include <signal.h>
31: #include <unistd.h>
32: #ifdef __STDC__
33: /* This is now provided by gcc's fixproto. */
34: #include <stdlib.h>
35: #endif
36: #include <errno.h>
37: #ifndef errno
38: extern int errno;
39: #endif
40: #include <sys/wait.h>
41:
42: #ifndef _IO_fork
43: #define _IO_fork vfork /* defined in libiberty, if needed */
44: _IO_pid_t _IO_fork();
45: #endif
46:
47: #endif /* _IO_HAVE_SYS_WAIT */
48:
49: #ifndef _IO_pipe
50: #define _IO_pipe pipe
51: extern int _IO_pipe();
52: #endif
53:
54: #ifndef _IO_dup2
55: #define _IO_dup2 dup2
56: extern int _IO_dup2();
57: #endif
58:
59: #ifndef _IO_waitpid
60: #define _IO_waitpid waitpid
61: #endif
62:
63: #ifndef _IO_execl
64: #define _IO_execl execl
65: #endif
66: #ifndef _IO__exit
67: #define _IO__exit _exit
68: #endif
69:
70: struct _IO_proc_file
71: {
72: struct _IO_FILE_plus _file;
73: /* Following fields must match those in class procbuf (procbuf.h) */
74: _IO_pid_t _pid;
75: struct _IO_proc_file *_next;
76: };
77: typedef struct _IO_proc_file _IO_proc_file;
78:
79: static struct _IO_proc_file *proc_file_chain = NULL;
80:
81: _IO_FILE *
82: _IO_proc_open(fp, command, mode)
83: _IO_FILE* fp;
84: const char *command;
85: const char *mode;
86: {
87: #if _IO_HAVE_SYS_WAIT
88: int read_or_write;
89: int pipe_fds[2];
90: int parent_end, child_end;
91: _IO_pid_t child_pid;
92: if (_IO_file_is_open(fp))
93: return NULL;
94: if (_IO_pipe(pipe_fds) < 0)
95: return NULL;
96: if (mode[0] == 'r')
97: {
98: parent_end = pipe_fds[0];
99: child_end = pipe_fds[1];
100: read_or_write = _IO_NO_WRITES;
101: }
102: else
103: {
104: parent_end = pipe_fds[1];
105: child_end = pipe_fds[0];
106: read_or_write = _IO_NO_READS;
107: }
108: ((_IO_proc_file*)fp)->_pid = child_pid = _IO_fork();
109: if (child_pid == 0)
110: {
111: int child_std_end = mode[0] == 'r' ? 1 : 0;
112: _IO_close(parent_end);
113: if (child_end != child_std_end)
114: {
115: _IO_dup2(child_end, child_std_end);
116: _IO_close(child_end);
117: }
118: /* Posix.2: "popen() shall ensure that any streams from previous
119: popen() calls that remain open in the parent process are closed
120: in the new child process." */
121: while (proc_file_chain)
122: {
123: _IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain));
124: proc_file_chain = proc_file_chain->_next;
125: }
126:
127: _IO_execl("/bin/sh", "sh", "-c", command, NULL);
128: _IO__exit(127);
129: }
130: _IO_close(child_end);
131: if (child_pid < 0)
132: {
133: _IO_close(parent_end);
134: return NULL;
135: }
136: _IO_fileno(fp) = parent_end;
137:
138: /* Link into proc_file_chain. */
139: ((_IO_proc_file*)fp)->_next = proc_file_chain;
140: proc_file_chain = (_IO_proc_file*)fp;
141:
142: fp->_IO_file_flags
143: = read_or_write | (fp->_IO_file_flags & ~(_IO_NO_READS|_IO_NO_WRITES));
144: return fp;
145: #else /* !_IO_HAVE_SYS_WAIT */
146: return NULL;
147: #endif
148: }
149:
150: _IO_FILE *
151: _IO_popen(command, mode)
152: const char *command;
153: const char *mode;
154: {
155: _IO_proc_file *fpx = (_IO_proc_file*)malloc(sizeof(_IO_proc_file));
156: _IO_FILE *fp = (_IO_FILE*)fpx;
157: if (fp == NULL)
158: return NULL;
159: _IO_init(fp, 0);
160: fp->_jumps = &_IO_proc_jumps;
161: _IO_file_init(fp);
162: ((struct _IO_FILE_plus*)fp)->_vtable = NULL;
163: if (_IO_proc_open (fp, command, mode) != NULL)
164: return fp;
165: free (fpx);
166: return NULL;
167: }
168:
169: int
170: _IO_proc_close(fp)
171: _IO_FILE *fp;
172: {
173: /* This is not name-space clean. FIXME! */
174: #if _IO_HAVE_SYS_WAIT
175: int wstatus;
176: _IO_proc_file **ptr = &proc_file_chain;
177: _IO_pid_t wait_pid;
178: int status = _IO_close(_IO_fileno(fp));
179:
180: /* Unlink from proc_file_chain. */
181: for ( ; *ptr != NULL; ptr = &(*ptr)->_next)
182: {
183: if (*ptr == (_IO_proc_file*)fp)
184: {
185: *ptr = (*ptr)->_next;
186: break;
187: }
188: }
189:
190: if (status < 0)
191: return status;
192: /* POSIX.2 Rationale: "Some historical implementations either block
193: or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
194: for the child process to terminate. Since this behavior is not
195: described in POSIX.2, such implementations are not conforming." */
196: do
197: {
198: wait_pid = _IO_waitpid (((_IO_proc_file*)fp)->_pid, &wstatus, 0);
199: } while (wait_pid == -1 && errno == EINTR);
200: if (wait_pid == -1)
201: return -1;
202: return wstatus;
203: #else /* !_IO_HAVE_SYS_WAIT */
204: return -1;
205: #endif
206: }
207:
208: struct _IO_jump_t _IO_proc_jumps = {
209: _IO_file_overflow,
210: _IO_file_underflow,
211: _IO_file_xsputn,
212: _IO_default_xsgetn,
213: _IO_file_read,
214: _IO_file_write,
215: _IO_file_doallocate,
216: _IO_default_pbackfail,
217: _IO_file_setbuf,
218: _IO_file_sync,
219: _IO_file_finish,
220: _IO_proc_close,
221: _IO_file_stat,
222: _IO_file_seek,
223: _IO_file_seekoff,
224: _IO_default_seekpos,
225: };
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.