]>
Commit | Line | Data |
---|---|---|
390500b1 | 1 | /* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc. |
40a55d20 UD |
2 | This file is part of the GNU IO Library. |
3 | Written by Per Bothner <bothner@cygnus.com>. | |
4 | ||
5 | This library is free software; you can redistribute it and/or | |
6 | modify it under the terms of the GNU General Public License as | |
7 | published by the Free Software Foundation; either version 2, or (at | |
8 | your option) any later version. | |
9 | ||
10 | This library is distributed in the hope that it will be useful, but | |
11 | WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
13 | General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this library; see the file COPYING. If not, write to | |
17 | the Free Software Foundation, 59 Temple Place - Suite 330, Boston, | |
18 | MA 02111-1307, USA. | |
19 | ||
20 | As a special exception, if you link this library with files | |
21 | compiled with a GNU compiler to produce an executable, this does | |
22 | not cause the resulting executable to be covered by the GNU General | |
23 | Public License. This exception does not however invalidate any | |
24 | other reasons why the executable file might be covered by the GNU | |
25 | General Public License. */ | |
196980f5 | 26 | |
fa0bc87c RM |
27 | #ifndef _POSIX_SOURCE |
28 | # define _POSIX_SOURCE | |
29 | #endif | |
196980f5 RM |
30 | #include "libioP.h" |
31 | #if _IO_HAVE_SYS_WAIT | |
32 | #include <signal.h> | |
33 | #include <unistd.h> | |
34 | #ifdef __STDC__ | |
35 | #include <stdlib.h> | |
36 | #endif | |
fa0bc87c RM |
37 | #ifdef _LIBC |
38 | # include <unistd.h> | |
39 | #endif | |
196980f5 RM |
40 | #include <sys/types.h> |
41 | #include <sys/wait.h> | |
42 | ||
43 | #ifndef _IO_fork | |
50304ef0 UD |
44 | #ifdef _LIBC |
45 | #define _IO_fork __vfork | |
46 | #else | |
196980f5 | 47 | #define _IO_fork vfork /* defined in libiberty, if needed */ |
50304ef0 | 48 | #endif |
fa0bc87c | 49 | extern _IO_pid_t _IO_fork __P ((void)); |
196980f5 RM |
50 | #endif |
51 | ||
52 | #endif /* _IO_HAVE_SYS_WAIT */ | |
53 | ||
54 | #ifndef _IO_pipe | |
50304ef0 UD |
55 | #ifdef _LIBC |
56 | #define _IO_pipe __pipe | |
57 | #else | |
196980f5 | 58 | #define _IO_pipe pipe |
50304ef0 | 59 | #endif |
fa0bc87c | 60 | extern int _IO_pipe __P ((int des[2])); |
196980f5 RM |
61 | #endif |
62 | ||
63 | #ifndef _IO_dup2 | |
50304ef0 UD |
64 | #ifdef _LIBC |
65 | #define _IO_dup2 __dup2 | |
66 | #else | |
196980f5 | 67 | #define _IO_dup2 dup2 |
50304ef0 | 68 | #endif |
fa0bc87c | 69 | extern int _IO_dup2 __P ((int fd, int fd2)); |
196980f5 RM |
70 | #endif |
71 | ||
72 | #ifndef _IO_waitpid | |
50304ef0 UD |
73 | #ifdef _LIBC |
74 | #define _IO_waitpid __waitpid | |
75 | #else | |
196980f5 RM |
76 | #define _IO_waitpid waitpid |
77 | #endif | |
50304ef0 | 78 | #endif |
196980f5 RM |
79 | |
80 | #ifndef _IO_execl | |
81 | #define _IO_execl execl | |
82 | #endif | |
83 | #ifndef _IO__exit | |
84 | #define _IO__exit _exit | |
85 | #endif | |
86 | ||
61eb22d3 | 87 | #ifndef _IO_close |
50304ef0 UD |
88 | #ifdef _LIBC |
89 | #define _IO_close __close | |
90 | #else | |
61eb22d3 UD |
91 | #define _IO_close close |
92 | #endif | |
50304ef0 | 93 | #endif |
61eb22d3 | 94 | |
196980f5 RM |
95 | struct _IO_proc_file |
96 | { | |
bd355af0 | 97 | struct _IO_FILE_plus file; |
196980f5 RM |
98 | /* Following fields must match those in class procbuf (procbuf.h) */ |
99 | _IO_pid_t pid; | |
100 | struct _IO_proc_file *next; | |
101 | }; | |
102 | typedef struct _IO_proc_file _IO_proc_file; | |
103 | ||
390500b1 | 104 | static struct _IO_proc_file *proc_file_chain; |
196980f5 RM |
105 | |
106 | _IO_FILE * | |
7d6a8338 | 107 | _IO_new_proc_open (fp, command, mode) |
40a55d20 UD |
108 | _IO_FILE *fp; |
109 | const char *command; | |
110 | const char *mode; | |
196980f5 RM |
111 | { |
112 | #if _IO_HAVE_SYS_WAIT | |
a1470b6f RM |
113 | volatile int read_or_write; |
114 | volatile int parent_end, child_end; | |
196980f5 | 115 | int pipe_fds[2]; |
196980f5 | 116 | _IO_pid_t child_pid; |
40a55d20 | 117 | if (_IO_file_is_open (fp)) |
196980f5 | 118 | return NULL; |
40a55d20 | 119 | if (_IO_pipe (pipe_fds) < 0) |
196980f5 | 120 | return NULL; |
f43ce637 | 121 | if (mode[0] == 'r' && mode[1] == '\0') |
196980f5 RM |
122 | { |
123 | parent_end = pipe_fds[0]; | |
124 | child_end = pipe_fds[1]; | |
125 | read_or_write = _IO_NO_WRITES; | |
126 | } | |
f43ce637 | 127 | else if (mode[0] == 'w' && mode[1] == '\0') |
196980f5 RM |
128 | { |
129 | parent_end = pipe_fds[1]; | |
130 | child_end = pipe_fds[0]; | |
131 | read_or_write = _IO_NO_READS; | |
132 | } | |
f43ce637 UD |
133 | else |
134 | { | |
135 | __set_errno (EINVAL); | |
136 | return NULL; | |
137 | } | |
40a55d20 | 138 | ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork (); |
196980f5 RM |
139 | if (child_pid == 0) |
140 | { | |
141 | int child_std_end = mode[0] == 'r' ? 1 : 0; | |
3c493630 AS |
142 | struct _IO_proc_file *p; |
143 | ||
40a55d20 | 144 | _IO_close (parent_end); |
196980f5 RM |
145 | if (child_end != child_std_end) |
146 | { | |
40a55d20 UD |
147 | _IO_dup2 (child_end, child_std_end); |
148 | _IO_close (child_end); | |
196980f5 | 149 | } |
40a55d20 | 150 | /* POSIX.2: "popen() shall ensure that any streams from previous |
196980f5 RM |
151 | popen() calls that remain open in the parent process are closed |
152 | in the new child process." */ | |
3c493630 AS |
153 | for (p = proc_file_chain; p; p = p->next) |
154 | _IO_close (_IO_fileno ((_IO_FILE *) p)); | |
196980f5 | 155 | |
40a55d20 UD |
156 | _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0); |
157 | _IO__exit (127); | |
196980f5 | 158 | } |
40a55d20 | 159 | _IO_close (child_end); |
196980f5 RM |
160 | if (child_pid < 0) |
161 | { | |
40a55d20 | 162 | _IO_close (parent_end); |
196980f5 RM |
163 | return NULL; |
164 | } | |
40a55d20 | 165 | _IO_fileno (fp) = parent_end; |
196980f5 RM |
166 | |
167 | /* Link into proc_file_chain. */ | |
40a55d20 UD |
168 | ((_IO_proc_file *) fp)->next = proc_file_chain; |
169 | proc_file_chain = (_IO_proc_file *) fp; | |
196980f5 RM |
170 | |
171 | _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES); | |
172 | return fp; | |
173 | #else /* !_IO_HAVE_SYS_WAIT */ | |
174 | return NULL; | |
175 | #endif | |
176 | } | |
177 | ||
178 | _IO_FILE * | |
7d6a8338 | 179 | _IO_new_popen (command, mode) |
40a55d20 UD |
180 | const char *command; |
181 | const char *mode; | |
196980f5 | 182 | { |
edf5b2d7 UD |
183 | struct locked_FILE |
184 | { | |
185 | struct _IO_proc_file fpx; | |
499e7464 | 186 | #ifdef _IO_MTSAFE_IO |
edf5b2d7 | 187 | _IO_lock_t lock; |
499e7464 | 188 | #endif |
edf5b2d7 UD |
189 | } *new_f; |
190 | _IO_FILE *fp; | |
191 | ||
192 | new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE)); | |
193 | if (new_f == NULL) | |
196980f5 | 194 | return NULL; |
499e7464 | 195 | #ifdef _IO_MTSAFE_IO |
bd355af0 | 196 | new_f->fpx.file.file._lock = &new_f->lock; |
499e7464 | 197 | #endif |
7ce241a0 | 198 | fp = &new_f->fpx.file.file; |
40a55d20 UD |
199 | _IO_init (fp, 0); |
200 | _IO_JUMPS (fp) = &_IO_proc_jumps; | |
7d6a8338 | 201 | _IO_new_file_init (fp); |
196980f5 | 202 | #if !_IO_UNIFIED_JUMPTABLES |
7ce241a0 | 203 | new_f->fpx.file.vtable = NULL; |
196980f5 | 204 | #endif |
7d6a8338 | 205 | if (_IO_new_proc_open (fp, command, mode) != NULL) |
196980f5 | 206 | return fp; |
7ce241a0 | 207 | _IO_un_link (fp); |
edf5b2d7 | 208 | free (new_f); |
196980f5 RM |
209 | return NULL; |
210 | } | |
211 | ||
196980f5 | 212 | int |
7d6a8338 | 213 | _IO_new_proc_close (fp) |
40a55d20 | 214 | _IO_FILE *fp; |
196980f5 RM |
215 | { |
216 | /* This is not name-space clean. FIXME! */ | |
217 | #if _IO_HAVE_SYS_WAIT | |
218 | int wstatus; | |
219 | _IO_proc_file **ptr = &proc_file_chain; | |
220 | _IO_pid_t wait_pid; | |
221 | int status = -1; | |
222 | ||
223 | /* Unlink from proc_file_chain. */ | |
224 | for ( ; *ptr != NULL; ptr = &(*ptr)->next) | |
225 | { | |
40a55d20 | 226 | if (*ptr == (_IO_proc_file *) fp) |
196980f5 RM |
227 | { |
228 | *ptr = (*ptr)->next; | |
229 | status = 0; | |
230 | break; | |
231 | } | |
232 | } | |
233 | ||
40a55d20 | 234 | if (status < 0 || _IO_close (_IO_fileno(fp)) < 0) |
196980f5 RM |
235 | return -1; |
236 | /* POSIX.2 Rationale: "Some historical implementations either block | |
237 | or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting | |
238 | for the child process to terminate. Since this behavior is not | |
239 | described in POSIX.2, such implementations are not conforming." */ | |
240 | do | |
241 | { | |
40a55d20 UD |
242 | wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0); |
243 | } | |
244 | while (wait_pid == -1 && errno == EINTR); | |
196980f5 RM |
245 | if (wait_pid == -1) |
246 | return -1; | |
247 | return wstatus; | |
248 | #else /* !_IO_HAVE_SYS_WAIT */ | |
249 | return -1; | |
250 | #endif | |
251 | } | |
252 | ||
253 | struct _IO_jump_t _IO_proc_jumps = { | |
254 | JUMP_INIT_DUMMY, | |
7d6a8338 UD |
255 | JUMP_INIT(finish, _IO_new_file_finish), |
256 | JUMP_INIT(overflow, _IO_new_file_overflow), | |
257 | JUMP_INIT(underflow, _IO_new_file_underflow), | |
196980f5 RM |
258 | JUMP_INIT(uflow, _IO_default_uflow), |
259 | JUMP_INIT(pbackfail, _IO_default_pbackfail), | |
7d6a8338 | 260 | JUMP_INIT(xsputn, _IO_new_file_xsputn), |
196980f5 | 261 | JUMP_INIT(xsgetn, _IO_default_xsgetn), |
7d6a8338 | 262 | JUMP_INIT(seekoff, _IO_new_file_seekoff), |
196980f5 | 263 | JUMP_INIT(seekpos, _IO_default_seekpos), |
7d6a8338 UD |
264 | JUMP_INIT(setbuf, _IO_new_file_setbuf), |
265 | JUMP_INIT(sync, _IO_new_file_sync), | |
196980f5 RM |
266 | JUMP_INIT(doallocate, _IO_file_doallocate), |
267 | JUMP_INIT(read, _IO_file_read), | |
7d6a8338 | 268 | JUMP_INIT(write, _IO_new_file_write), |
196980f5 | 269 | JUMP_INIT(seek, _IO_file_seek), |
7d6a8338 | 270 | JUMP_INIT(close, _IO_new_proc_close), |
dfd2257a UD |
271 | JUMP_INIT(stat, _IO_file_stat), |
272 | JUMP_INIT(showmanyc, _IO_default_showmanyc), | |
273 | JUMP_INIT(imbue, _IO_default_imbue) | |
196980f5 | 274 | }; |
7d6a8338 UD |
275 | |
276 | #if defined PIC && DO_VERSIONING | |
277 | strong_alias (_IO_new_popen, __new_popen) | |
278 | default_symbol_version (_IO_new_popen, _IO_popen, GLIBC_2.1); | |
279 | default_symbol_version (__new_popen, popen, GLIBC_2.1); | |
280 | default_symbol_version (_IO_new_proc_open, _IO_proc_open, GLIBC_2.1); | |
281 | default_symbol_version (_IO_new_proc_close, _IO_proc_close, GLIBC_2.1); | |
282 | #else | |
283 | # ifdef strong_alias | |
284 | strong_alias (_IO_new_popen, popen) | |
285 | # endif | |
286 | # ifdef weak_alias | |
287 | weak_alias (_IO_new_popen, _IO_popen) | |
288 | weak_alias (_IO_new_proc_open, _IO_proc_open) | |
289 | weak_alias (_IO_new_proc_close, _IO_proc_close) | |
290 | # endif | |
291 | #endif |