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