Implement "e" flag.
[kopensolaris-gnu/glibc.git] / libio / iopopen.c
1 /* Copyright (C) 1993, 1997-2002, 2003, 2004, 2007, 2008
2    Free Software Foundation, Inc.
3    This file is part of the GNU C Library.
4    Written by Per Bothner <bothner@cygnus.com>.
5
6    The GNU C Library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public
8    License as published by the Free Software Foundation; either
9    version 2.1 of the License, or (at your option) any later version.
10
11    The GNU C Library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15
16    You should have received a copy of the GNU Lesser General Public
17    License along with the GNU C Library; if not, write to the Free
18    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
19    02111-1307 USA.
20
21    As a special exception, if you link the code in this file with
22    files compiled with a GNU compiler to produce an executable,
23    that does not cause the resulting executable to be covered by
24    the GNU Lesser General Public License.  This exception does not
25    however invalidate any other reasons why the executable file
26    might be covered by the GNU Lesser General Public License.
27    This exception applies to code released by its copyright holders
28    in files containing the exception.  */
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 /* defined in libiberty, if needed */
53 #endif
54 extern _IO_pid_t _IO_fork (void) __THROW;
55 #endif
56
57 #endif /* _IO_HAVE_SYS_WAIT */
58
59 #ifndef _IO_dup2
60 #ifdef _LIBC
61 #define _IO_dup2 __dup2
62 #else
63 #define _IO_dup2 dup2
64 #endif
65 extern int _IO_dup2 (int fd, int fd2) __THROW;
66 #endif
67
68 #ifndef _IO_waitpid
69 #ifdef _LIBC
70 #define _IO_waitpid waitpid_not_cancel
71 #else
72 #define _IO_waitpid waitpid
73 #endif
74 #endif
75
76 #ifndef _IO_execl
77 #define _IO_execl execl
78 #endif
79 #ifndef _IO__exit
80 #define _IO__exit _exit
81 #endif
82
83 #ifndef _IO_close
84 #ifdef _LIBC
85 #define _IO_close close_not_cancel
86 #else
87 #define _IO_close close
88 #endif
89 #endif
90
91 struct _IO_proc_file
92 {
93   struct _IO_FILE_plus file;
94   /* Following fields must match those in class procbuf (procbuf.h) */
95   _IO_pid_t pid;
96   struct _IO_proc_file *next;
97 };
98 typedef struct _IO_proc_file _IO_proc_file;
99
100 static const struct _IO_jump_t _IO_proc_jumps;
101
102 static struct _IO_proc_file *proc_file_chain;
103
104 #ifdef _IO_MTSAFE_IO
105 static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
106
107 static void
108 unlock (void *not_used)
109 {
110   _IO_lock_unlock (proc_file_chain_lock);
111 }
112 #endif
113
114 _IO_FILE *
115 _IO_new_proc_open (fp, command, mode)
116      _IO_FILE *fp;
117      const char *command;
118      const char *mode;
119 {
120 #if _IO_HAVE_SYS_WAIT
121   volatile int read_or_write;
122   volatile int parent_end, child_end;
123   int pipe_fds[2];
124   _IO_pid_t child_pid;
125
126   int do_read = 0;
127   int do_write = 0;
128   int do_cloexec = 0;
129   while (*mode != '\0')
130     switch (*mode++)
131       {
132       case 'r':
133         do_read = 1;
134         break;
135       case 'w':
136         do_write = 1;
137         break;
138       case 'e':
139         do_cloexec = 1;
140         break;
141       default:
142       errout:
143         __set_errno (EINVAL);
144         return NULL;
145       }
146
147   if ((do_read ^ do_write) == 0)
148     goto errout;
149
150   if (_IO_file_is_open (fp))
151     return NULL;
152
153 #ifdef O_CLOEXEC
154 # ifndef __ASSUME_PIPE2
155   if (__have_pipe2 >= 0)
156 # endif
157     {
158       int r = __pipe2 (pipe_fds, O_CLOEXEC);
159 # ifndef __ASSUME_PIPE2
160       if (__have_pipe2 == 0)
161         __have_pipe2 = r != -1 || errno != ENOSYS ? 1 : -1;
162
163       if (__have_pipe2 > 0)
164 # endif
165         if (r < 0)
166           return NULL;
167     }
168 #endif
169 #ifndef __ASSUME_PIPE2
170 # ifdef O_CLOEXEC
171   if (__have_pipe2 < 0)
172 # endif
173     if (__pipe (pipe_fds) < 0)
174       return NULL;
175 #endif
176
177   if (do_read)
178     {
179       parent_end = pipe_fds[0];
180       child_end = pipe_fds[1];
181       read_or_write = _IO_NO_WRITES;
182     }
183   else
184     {
185       parent_end = pipe_fds[1];
186       child_end = pipe_fds[0];
187       read_or_write = _IO_NO_READS;
188     }
189
190   ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
191   if (child_pid == 0)
192     {
193       int child_std_end = do_read ? 1 : 0;
194       struct _IO_proc_file *p;
195
196 #ifndef __ASSUME_PIPE2
197       /* If we have pipe2 the descriptor is marked for close-on-exec.  */
198       _IO_close (parent_end);
199 #endif
200       if (child_end != child_std_end)
201         {
202           _IO_dup2 (child_end, child_std_end);
203 #ifndef __ASSUME_PIPE2
204           _IO_close (child_end);
205 #endif
206         }
207 #ifdef O_CLOEXEC
208       else
209         {
210           /* The descriptor is already the one we will use.  But it must
211              not be marked close-on-exec.  Undo the effects.  */
212 # ifndef __ASSUME_PIPE2
213           if (__have_pipe2 > 0)
214 # endif
215             __fcntl (child_end, F_SETFD, 0);
216         }
217 #endif
218       /* POSIX.2:  "popen() shall ensure that any streams from previous
219          popen() calls that remain open in the parent process are closed
220          in the new child process." */
221       for (p = proc_file_chain; p; p = p->next)
222         {
223           int fd = _IO_fileno ((_IO_FILE *) p);
224
225           /* If any stream from previous popen() calls has fileno
226              child_std_end, it has been already closed by the dup2 syscall
227              above.  */
228           if (fd != child_std_end)
229             _IO_close (fd);
230         }
231
232       _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
233       _IO__exit (127);
234     }
235   _IO_close (child_end);
236   if (child_pid < 0)
237     {
238       _IO_close (parent_end);
239       return NULL;
240     }
241
242   if (do_cloexec)
243     {
244 #ifndef __ASSUME_PIPE2
245 # ifdef O_CLOEXEC
246       if (__have_pipe2 < 0)
247 # endif
248         __fcntl (parent_end, F_SETFD, FD_CLOEXEC);
249 #endif
250     }
251   else
252     {
253 #ifdef O_CLOEXEC
254       /* Undo the effects of the pipe2 call which set the
255          close-on-exec flag.  */
256 # ifndef __ASSUME_PIPE2
257       if (__have_pipe2 > 0)
258 # endif
259         __fcntl (parent_end, F_SETFD, 0);
260 #endif
261     }
262
263   _IO_fileno (fp) = parent_end;
264
265   /* Link into proc_file_chain. */
266 #ifdef _IO_MTSAFE_IO
267   _IO_cleanup_region_start_noarg (unlock);
268   _IO_lock_lock (proc_file_chain_lock);
269 #endif
270   ((_IO_proc_file *) fp)->next = proc_file_chain;
271   proc_file_chain = (_IO_proc_file *) fp;
272 #ifdef _IO_MTSAFE_IO
273   _IO_lock_unlock (proc_file_chain_lock);
274   _IO_cleanup_region_end (0);
275 #endif
276
277   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
278   return fp;
279 #else /* !_IO_HAVE_SYS_WAIT */
280   return NULL;
281 #endif
282 }
283
284 _IO_FILE *
285 _IO_new_popen (command, mode)
286      const char *command;
287      const char *mode;
288 {
289   struct locked_FILE
290   {
291     struct _IO_proc_file fpx;
292 #ifdef _IO_MTSAFE_IO
293     _IO_lock_t lock;
294 #endif
295   } *new_f;
296   _IO_FILE *fp;
297
298   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
299   if (new_f == NULL)
300     return NULL;
301 #ifdef _IO_MTSAFE_IO
302   new_f->fpx.file.file._lock = &new_f->lock;
303 #endif
304   fp = &new_f->fpx.file.file;
305   INTUSE(_IO_init) (fp, 0);
306   _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
307   _IO_new_file_init (&new_f->fpx.file);
308 #if  !_IO_UNIFIED_JUMPTABLES
309   new_f->fpx.file.vtable = NULL;
310 #endif
311   if (_IO_new_proc_open (fp, command, mode) != NULL)
312     return (_IO_FILE *) &new_f->fpx.file;
313   INTUSE(_IO_un_link) (&new_f->fpx.file);
314   free (new_f);
315   return NULL;
316 }
317
318 int
319 _IO_new_proc_close (fp)
320      _IO_FILE *fp;
321 {
322   /* This is not name-space clean. FIXME! */
323 #if _IO_HAVE_SYS_WAIT
324   int wstatus;
325   _IO_proc_file **ptr = &proc_file_chain;
326   _IO_pid_t wait_pid;
327   int status = -1;
328
329   /* Unlink from proc_file_chain. */
330 #ifdef _IO_MTSAFE_IO
331   _IO_cleanup_region_start_noarg (unlock);
332   _IO_lock_lock (proc_file_chain_lock);
333 #endif
334   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
335     {
336       if (*ptr == (_IO_proc_file *) fp)
337         {
338           *ptr = (*ptr)->next;
339           status = 0;
340           break;
341         }
342     }
343 #ifdef _IO_MTSAFE_IO
344   _IO_lock_unlock (proc_file_chain_lock);
345   _IO_cleanup_region_end (0);
346 #endif
347
348   if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
349     return -1;
350   /* POSIX.2 Rationale:  "Some historical implementations either block
351      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
352      for the child process to terminate.  Since this behavior is not
353      described in POSIX.2, such implementations are not conforming." */
354   do
355     {
356       wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
357     }
358   while (wait_pid == -1 && errno == EINTR);
359   if (wait_pid == -1)
360     return -1;
361   return wstatus;
362 #else /* !_IO_HAVE_SYS_WAIT */
363   return -1;
364 #endif
365 }
366
367 static const struct _IO_jump_t _IO_proc_jumps = {
368   JUMP_INIT_DUMMY,
369   JUMP_INIT(finish, _IO_new_file_finish),
370   JUMP_INIT(overflow, _IO_new_file_overflow),
371   JUMP_INIT(underflow, _IO_new_file_underflow),
372   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
373   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
374   JUMP_INIT(xsputn, _IO_new_file_xsputn),
375   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
376   JUMP_INIT(seekoff, _IO_new_file_seekoff),
377   JUMP_INIT(seekpos, _IO_default_seekpos),
378   JUMP_INIT(setbuf, _IO_new_file_setbuf),
379   JUMP_INIT(sync, _IO_new_file_sync),
380   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
381   JUMP_INIT(read, INTUSE(_IO_file_read)),
382   JUMP_INIT(write, _IO_new_file_write),
383   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
384   JUMP_INIT(close, _IO_new_proc_close),
385   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
386   JUMP_INIT(showmanyc, _IO_default_showmanyc),
387   JUMP_INIT(imbue, _IO_default_imbue)
388 };
389
390 strong_alias (_IO_new_popen, __new_popen)
391 versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
392 versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
393 versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
394 versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);