1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30: #ifndef _POSIX_SOURCE
31: # define _POSIX_SOURCE
32: #endif
33: #include "libioP.h"
34: #if _IO_HAVE_SYS_WAIT
35: #include <signal.h>
36: #include <unistd.h>
37: #ifdef __STDC__
38: #include <stdlib.h>
39: #endif
40: #ifdef _LIBC
41: # include <unistd.h>
42: # include <shlib-compat.h>
43: # include <not-cancel.h>
44: #endif
45: #include <sys/types.h>
46: #include <sys/wait.h>
47:
48: #ifndef _IO_fork
49: #ifdef _LIBC
50: #define _IO_fork __fork
51: #else
52: #define _IO_fork fork
53: #endif
54: extern _IO_pid_t _IO_fork (void) __THROW;
55: #endif
56:
57: #endif
58:
59: #ifndef _IO_pipe
60: #ifdef _LIBC
61: #define _IO_pipe __pipe
62: #else
63: #define _IO_pipe pipe
64: #endif
65: extern int _IO_pipe (int des[2]) __THROW;
66: #endif
67:
68: #ifndef _IO_dup2
69: #ifdef _LIBC
70: #define _IO_dup2 __dup2
71: #else
72: #define _IO_dup2 dup2
73: #endif
74: extern int _IO_dup2 (int fd, int fd2) __THROW;
75: #endif
76:
77: #ifndef _IO_waitpid
78: #ifdef _LIBC
79: #define _IO_waitpid waitpid_not_cancel
80: #else
81: #define _IO_waitpid waitpid
82: #endif
83: #endif
84:
85: #ifndef _IO_execl
86: #define _IO_execl execl
87: #endif
88: #ifndef _IO__exit
89: #define _IO__exit _exit
90: #endif
91:
92: #ifndef _IO_close
93: #ifdef _LIBC
94: #define _IO_close close_not_cancel
95: #else
96: #define _IO_close close
97: #endif
98: #endif
99:
100: struct _IO_proc_file
101: {
102: struct _IO_FILE_plus file;
103:
104: _IO_pid_t pid;
105: struct _IO_proc_file *next;
106: };
107: typedef struct _IO_proc_file _IO_proc_file;
108:
109: static const struct _IO_jump_t _IO_proc_jumps;
110:
111: static struct _IO_proc_file *proc_file_chain;
112:
113: #ifdef _IO_MTSAFE_IO
114: static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
115:
116: static void
117: unlock (void *not_used)
118: {
119: _IO_lock_unlock (proc_file_chain_lock);
120: }
121: #endif
122:
123: _IO_FILE *
124: _IO_new_proc_open (fp, command, mode)
125: _IO_FILE *fp;
126: const char *command;
127: const char *mode;
128: {
129: #if _IO_HAVE_SYS_WAIT
130: volatile int read_or_write;
131: volatile int parent_end, child_end;
132: int pipe_fds[2];
133: _IO_pid_t child_pid;
134: if (_IO_file_is_open (fp))
135: return NULL;
136: if (_IO_pipe (pipe_fds) < 0)
137: return NULL;
138: if (mode[0] == 'r' && mode[1] == '\0')
139: {
140: parent_end = pipe_fds[0];
141: child_end = pipe_fds[1];
142: read_or_write = _IO_NO_WRITES;
143: }
144: else if (mode[0] == 'w' && mode[1] == '\0')
145: {
146: parent_end = pipe_fds[1];
147: child_end = pipe_fds[0];
148: read_or_write = _IO_NO_READS;
149: }
150: else
151: {
152: _IO_close (pipe_fds[0]);
153: _IO_close (pipe_fds[1]);
154: __set_errno (EINVAL);
155: return NULL;
156: }
157: ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
158: if (child_pid == 0)
159: {
160: int child_std_end = mode[0] == 'r' ? 1 : 0;
161: struct _IO_proc_file *p;
162:
163: _IO_close (parent_end);
164: if (child_end != child_std_end)
165: {
166: _IO_dup2 (child_end, child_std_end);
167: _IO_close (child_end);
168: }
169:
170:
171:
172: for (p = proc_file_chain; p; p = p->next)
173: {
174: int fd = _IO_fileno ((_IO_FILE *) p);
175:
176:
177:
178:
179: if (fd != child_std_end)
180: _IO_close (fd);
181: }
182:
183: _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
184: _IO__exit (127);
185: }
186: _IO_close (child_end);
187: if (child_pid < 0)
188: {
189: _IO_close (parent_end);
190: return NULL;
191: }
192: _IO_fileno (fp) = parent_end;
193:
194:
195: #ifdef _IO_MTSAFE_IO
196: _IO_cleanup_region_start_noarg (unlock);
197: _IO_lock_lock (proc_file_chain_lock);
198: #endif
199: ((_IO_proc_file *) fp)->next = proc_file_chain;
200: proc_file_chain = (_IO_proc_file *) fp;
201: #ifdef _IO_MTSAFE_IO
202: _IO_lock_unlock (proc_file_chain_lock);
203: _IO_cleanup_region_end (0);
204: #endif
205:
206: _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
207: return fp;
208: #else
209: return NULL;
210: #endif
211: }
212:
213: _IO_FILE *
214: _IO_new_popen (command, mode)
215: const char *command;
216: const char *mode;
217: {
218: struct locked_FILE
219: {
220: struct _IO_proc_file fpx;
221: #ifdef _IO_MTSAFE_IO
222: _IO_lock_t lock;
223: #endif
224: } *new_f;
225: _IO_FILE *fp;
226:
227: new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
228: if (new_f == NULL)
229: return NULL;
230: #ifdef _IO_MTSAFE_IO
231: new_f->fpx.file.file._lock = &new_f->lock;
232: #endif
233: fp = &new_f->fpx.file.file;
234: INTUSE(_IO_init) (fp, 0);
235: _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
236: _IO_new_file_init (&new_f->fpx.file);
237: #if !_IO_UNIFIED_JUMPTABLES
238: new_f->fpx.file.vtable = NULL;
239: #endif
240: if (_IO_new_proc_open (fp, command, mode) != NULL)
241: return (_IO_FILE *) &new_f->fpx.file;
242: INTUSE(_IO_un_link) (&new_f->fpx.file);
243: free (new_f);
244: return NULL;
245: }
246:
247: int
248: _IO_new_proc_close (fp)
249: _IO_FILE *fp;
250: {
251:
252: #if _IO_HAVE_SYS_WAIT
253: int wstatus;
254: _IO_proc_file **ptr = &proc_file_chain;
255: _IO_pid_t wait_pid;
256: int status = -1;
257:
258:
259: #ifdef _IO_MTSAFE_IO
260: _IO_cleanup_region_start_noarg (unlock);
261: _IO_lock_lock (proc_file_chain_lock);
262: #endif
263: for ( ; *ptr != NULL; ptr = &(*ptr)->next)
264: {
265: if (*ptr == (_IO_proc_file *) fp)
266: {
267: *ptr = (*ptr)->next;
268: status = 0;
269: break;
270: }
271: }
272: #ifdef _IO_MTSAFE_IO
273: _IO_lock_unlock (proc_file_chain_lock);
274: _IO_cleanup_region_end (0);
275: #endif
276:
277: if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
278: return -1;
279:
280:
281:
282:
283: do
284: {
285: wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
286: }
287: while (wait_pid == -1 && errno == EINTR);
288: if (wait_pid == -1)
289: return -1;
290: return wstatus;
291: #else
292: return -1;
293: #endif
294: }
295:
296: static const struct _IO_jump_t _IO_proc_jumps = {
297: JUMP_INIT_DUMMY,
298: JUMP_INIT(finish, _IO_new_file_finish),
299: JUMP_INIT(overflow, _IO_new_file_overflow),
300: JUMP_INIT(underflow, _IO_new_file_underflow),
301: JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
302: JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
303: JUMP_INIT(xsputn, _IO_new_file_xsputn),
304: JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
305: JUMP_INIT(seekoff, _IO_new_file_seekoff),
306: JUMP_INIT(seekpos, _IO_default_seekpos),
307: JUMP_INIT(setbuf, _IO_new_file_setbuf),
308: JUMP_INIT(sync, _IO_new_file_sync),
309: JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
310: JUMP_INIT(read, INTUSE(_IO_file_read)),
311: JUMP_INIT(write, _IO_new_file_write),
312: JUMP_INIT(seek, INTUSE(_IO_file_seek)),
313: JUMP_INIT(close, _IO_new_proc_close),
314: JUMP_INIT(stat, INTUSE(_IO_file_stat)),
315: JUMP_INIT(showmanyc, _IO_default_showmanyc),
316: JUMP_INIT(imbue, _IO_default_imbue)
317: };
318:
319: strong_alias (_IO_new_popen, __new_popen)
320: versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
321: versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
322: versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
323: versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);