Update.
[platform/upstream/glibc.git] / libio / oldiopopen.c
1 /* Copyright (C) 1998, 1999, 2000, 2001, 2002 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 #define _IO_USE_OLD_IO_FILE
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 #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 #include <shlib-compat.h>
58 #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
59
60 #ifndef _IO_pipe
61 #ifdef _LIBC
62 #define _IO_pipe __pipe
63 #else
64 #define _IO_pipe pipe
65 #endif
66 extern int _IO_pipe __P ((int des[2]));
67 #endif
68
69 #ifndef _IO_dup2
70 #ifdef _LIBC
71 #define _IO_dup2 __dup2
72 #else
73 #define _IO_dup2 dup2
74 #endif
75 extern int _IO_dup2 __P ((int fd, int fd2));
76 #endif
77
78 #ifndef _IO_waitpid
79 #ifdef _LIBC
80 #define _IO_waitpid __waitpid
81 #else
82 #define _IO_waitpid waitpid
83 #endif
84 #endif
85
86 #ifndef _IO_execl
87 #define _IO_execl execl
88 #endif
89 #ifndef _IO__exit
90 #define _IO__exit _exit
91 #endif
92
93 #ifndef _IO_close
94 #ifdef _LIBC
95 #define _IO_close __close
96 #else
97 #define _IO_close close
98 #endif
99 #endif
100
101 struct _IO_proc_file
102 {
103   struct _IO_FILE_plus file;
104   /* Following fields must match those in class procbuf (procbuf.h) */
105   _IO_pid_t pid;
106   struct _IO_proc_file *next;
107 };
108 typedef struct _IO_proc_file _IO_proc_file;
109
110 static struct _IO_proc_file *old_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_old_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 = old_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 old_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 = old_proc_file_chain;
191   old_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_old_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   } *new_f;
216   _IO_FILE *fp;
217
218   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
219   if (new_f == NULL)
220     return NULL;
221 #ifdef _IO_MTSAFE_IO
222   new_f->fpx.file.file._lock = &new_f->lock;
223 #endif
224   fp = &new_f->fpx.file.file;
225   INTUSE(_IO_init) (fp, 0);
226   _IO_JUMPS (&new_f->fpx.file) = &_IO_old_proc_jumps;
227   _IO_old_file_init (&new_f->fpx.file);
228 #if  !_IO_UNIFIED_JUMPTABLES
229   new_f->fpx.file.vtable = NULL;
230 #endif
231   if (_IO_old_proc_open (fp, command, mode) != NULL)
232     return fp;
233   INTUSE(_IO_un_link) (&new_f->fpx.file);
234   free (new_f);
235   return NULL;
236 }
237
238 int
239 _IO_old_proc_close (fp)
240      _IO_FILE *fp;
241 {
242   /* This is not name-space clean. FIXME! */
243 #if _IO_HAVE_SYS_WAIT
244   int wstatus;
245   _IO_proc_file **ptr = &old_proc_file_chain;
246   _IO_pid_t wait_pid;
247   int status = -1;
248
249   /* Unlink from old_proc_file_chain. */
250 #ifdef _IO_MTSAFE_IO
251   _IO_cleanup_region_start_noarg (unlock);
252   _IO_lock_lock (proc_file_chain_lock);
253 #endif
254   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
255     {
256       if (*ptr == (_IO_proc_file *) fp)
257         {
258           *ptr = (*ptr)->next;
259           status = 0;
260           break;
261         }
262     }
263 #ifdef _IO_MTSAFE_IO
264   _IO_lock_unlock (proc_file_chain_lock);
265   _IO_cleanup_region_end (0);
266 #endif
267
268   if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
269     return -1;
270   /* POSIX.2 Rationale:  "Some historical implementations either block
271      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
272      for the child process to terminate.  Since this behavior is not
273      described in POSIX.2, such implementations are not conforming." */
274   do
275     {
276       wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
277     }
278   while (wait_pid == -1 && errno == EINTR);
279   if (wait_pid == -1)
280     return -1;
281   return wstatus;
282 #else /* !_IO_HAVE_SYS_WAIT */
283   return -1;
284 #endif
285 }
286
287 struct _IO_jump_t _IO_old_proc_jumps = {
288   JUMP_INIT_DUMMY,
289   JUMP_INIT(finish, _IO_old_file_finish),
290   JUMP_INIT(overflow, _IO_old_file_overflow),
291   JUMP_INIT(underflow, _IO_old_file_underflow),
292   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
293   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
294   JUMP_INIT(xsputn, _IO_old_file_xsputn),
295   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
296   JUMP_INIT(seekoff, _IO_old_file_seekoff),
297   JUMP_INIT(seekpos, _IO_default_seekpos),
298   JUMP_INIT(setbuf, _IO_old_file_setbuf),
299   JUMP_INIT(sync, _IO_old_file_sync),
300   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
301   JUMP_INIT(read, INTUSE(_IO_file_read)),
302   JUMP_INIT(write, _IO_old_file_write),
303   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
304   JUMP_INIT(close, _IO_old_proc_close),
305   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
306   JUMP_INIT(showmanyc, _IO_default_showmanyc),
307   JUMP_INIT(imbue, _IO_default_imbue)
308 };
309
310 strong_alias (_IO_old_popen, __old_popen)
311 compat_symbol (libc, _IO_old_popen, _IO_popen, GLIBC_2_0);
312 compat_symbol (libc, __old_popen, popen, GLIBC_2_0);
313 compat_symbol (libc, _IO_old_proc_open, _IO_proc_open, GLIBC_2_0);
314 compat_symbol (libc, _IO_old_proc_close, _IO_proc_close, GLIBC_2_0);
315
316 #endif