Avoid dup3 PLT usage.
[platform/upstream/glibc.git] / libio / iopopen.c
1 /* Copyright (C) 1993, 1997-2002, 2003, 2004, 2007, 2008, 2012
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, see
18    <http://www.gnu.org/licenses/>.
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 #include <stdlib.h>
37 #ifdef _LIBC
38 # include <unistd.h>
39 # include <shlib-compat.h>
40 # include <not-cancel.h>
41 #endif
42 #include <sys/types.h>
43 #include <sys/wait.h>
44 #include <kernel-features.h>
45
46 #ifndef _IO_fork
47 #ifdef _LIBC
48 #define _IO_fork __fork
49 #else
50 #define _IO_fork fork /* defined in libiberty, if needed */
51 #endif
52 extern _IO_pid_t _IO_fork (void) __THROW;
53 #endif
54
55 #endif /* _IO_HAVE_SYS_WAIT */
56
57 #ifndef _IO_dup2
58 #ifdef _LIBC
59 #define _IO_dup2 __dup2
60 #else
61 #define _IO_dup2 dup2
62 #endif
63 extern int _IO_dup2 (int fd, int fd2) __THROW;
64 #endif
65
66 #ifndef _IO_waitpid
67 #ifdef _LIBC
68 #define _IO_waitpid waitpid_not_cancel
69 #else
70 #define _IO_waitpid waitpid
71 #endif
72 #endif
73
74 #ifndef _IO_execl
75 #define _IO_execl execl
76 #endif
77 #ifndef _IO__exit
78 #define _IO__exit _exit
79 #endif
80
81 #ifndef _IO_close
82 #ifdef _LIBC
83 #define _IO_close close_not_cancel
84 #else
85 #define _IO_close close
86 #endif
87 #endif
88
89 struct _IO_proc_file
90 {
91   struct _IO_FILE_plus file;
92   /* Following fields must match those in class procbuf (procbuf.h) */
93   _IO_pid_t pid;
94   struct _IO_proc_file *next;
95 };
96 typedef struct _IO_proc_file _IO_proc_file;
97
98 static const struct _IO_jump_t _IO_proc_jumps;
99
100 static struct _IO_proc_file *proc_file_chain;
101
102 #ifdef _IO_MTSAFE_IO
103 static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
104
105 static void
106 unlock (void *not_used)
107 {
108   _IO_lock_unlock (proc_file_chain_lock);
109 }
110 #endif
111
112 _IO_FILE *
113 _IO_new_proc_open (fp, command, mode)
114      _IO_FILE *fp;
115      const char *command;
116      const char *mode;
117 {
118 #if _IO_HAVE_SYS_WAIT
119   int read_or_write;
120   int parent_end, child_end;
121   int pipe_fds[2];
122   _IO_pid_t child_pid;
123
124   int do_read = 0;
125   int do_write = 0;
126   int do_cloexec = 0;
127   while (*mode != '\0')
128     switch (*mode++)
129       {
130       case 'r':
131         do_read = 1;
132         break;
133       case 'w':
134         do_write = 1;
135         break;
136       case 'e':
137         do_cloexec = 1;
138         break;
139       default:
140       errout:
141         __set_errno (EINVAL);
142         return NULL;
143       }
144
145   if ((do_read ^ do_write) == 0)
146     goto errout;
147
148   if (_IO_file_is_open (fp))
149     return NULL;
150
151 #ifdef O_CLOEXEC
152 # ifndef __ASSUME_PIPE2
153   if (__have_pipe2 >= 0)
154 # endif
155     {
156       int r = __pipe2 (pipe_fds, O_CLOEXEC);
157 # ifndef __ASSUME_PIPE2
158       if (__have_pipe2 == 0)
159         __have_pipe2 = r != -1 || errno != ENOSYS ? 1 : -1;
160
161       if (__have_pipe2 > 0)
162 # endif
163         if (r < 0)
164           return NULL;
165     }
166 #endif
167 #ifndef __ASSUME_PIPE2
168 # ifdef O_CLOEXEC
169   if (__have_pipe2 < 0)
170 # endif
171     if (__pipe (pipe_fds) < 0)
172       return NULL;
173 #endif
174
175   if (do_read)
176     {
177       parent_end = pipe_fds[0];
178       child_end = pipe_fds[1];
179       read_or_write = _IO_NO_WRITES;
180     }
181   else
182     {
183       parent_end = pipe_fds[1];
184       child_end = pipe_fds[0];
185       read_or_write = _IO_NO_READS;
186     }
187
188   ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
189   if (child_pid == 0)
190     {
191       int child_std_end = do_read ? 1 : 0;
192       struct _IO_proc_file *p;
193
194 #ifndef __ASSUME_PIPE2
195       /* If we have pipe2 the descriptor is marked for close-on-exec.  */
196       _IO_close (parent_end);
197 #endif
198       if (child_end != child_std_end)
199         {
200           _IO_dup2 (child_end, child_std_end);
201 #ifndef __ASSUME_PIPE2
202           _IO_close (child_end);
203 #endif
204         }
205 #ifdef O_CLOEXEC
206       else
207         {
208           /* The descriptor is already the one we will use.  But it must
209              not be marked close-on-exec.  Undo the effects.  */
210 # ifndef __ASSUME_PIPE2
211           if (__have_pipe2 > 0)
212 # endif
213             __fcntl (child_end, F_SETFD, 0);
214         }
215 #endif
216       /* POSIX.2:  "popen() shall ensure that any streams from previous
217          popen() calls that remain open in the parent process are closed
218          in the new child process." */
219       for (p = proc_file_chain; p; p = p->next)
220         {
221           int fd = _IO_fileno ((_IO_FILE *) p);
222
223           /* If any stream from previous popen() calls has fileno
224              child_std_end, it has been already closed by the dup2 syscall
225              above.  */
226           if (fd != child_std_end)
227             _IO_close (fd);
228         }
229
230       _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
231       _IO__exit (127);
232     }
233   _IO_close (child_end);
234   if (child_pid < 0)
235     {
236       _IO_close (parent_end);
237       return NULL;
238     }
239
240   if (do_cloexec)
241     {
242 #ifndef __ASSUME_PIPE2
243 # ifdef O_CLOEXEC
244       if (__have_pipe2 < 0)
245 # endif
246         __fcntl (parent_end, F_SETFD, FD_CLOEXEC);
247 #endif
248     }
249   else
250     {
251 #ifdef O_CLOEXEC
252       /* Undo the effects of the pipe2 call which set the
253          close-on-exec flag.  */
254 # ifndef __ASSUME_PIPE2
255       if (__have_pipe2 > 0)
256 # endif
257         __fcntl (parent_end, F_SETFD, 0);
258 #endif
259     }
260
261   _IO_fileno (fp) = parent_end;
262
263   /* Link into proc_file_chain. */
264 #ifdef _IO_MTSAFE_IO
265   _IO_cleanup_region_start_noarg (unlock);
266   _IO_lock_lock (proc_file_chain_lock);
267 #endif
268   ((_IO_proc_file *) fp)->next = proc_file_chain;
269   proc_file_chain = (_IO_proc_file *) fp;
270 #ifdef _IO_MTSAFE_IO
271   _IO_lock_unlock (proc_file_chain_lock);
272   _IO_cleanup_region_end (0);
273 #endif
274
275   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
276   return fp;
277 #else /* !_IO_HAVE_SYS_WAIT */
278   return NULL;
279 #endif
280 }
281
282 _IO_FILE *
283 _IO_new_popen (command, mode)
284      const char *command;
285      const char *mode;
286 {
287   struct locked_FILE
288   {
289     struct _IO_proc_file fpx;
290 #ifdef _IO_MTSAFE_IO
291     _IO_lock_t lock;
292 #endif
293   } *new_f;
294   _IO_FILE *fp;
295
296   new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
297   if (new_f == NULL)
298     return NULL;
299 #ifdef _IO_MTSAFE_IO
300   new_f->fpx.file.file._lock = &new_f->lock;
301 #endif
302   fp = &new_f->fpx.file.file;
303   INTUSE(_IO_init) (fp, 0);
304   _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
305   _IO_new_file_init (&new_f->fpx.file);
306 #if  !_IO_UNIFIED_JUMPTABLES
307   new_f->fpx.file.vtable = NULL;
308 #endif
309   if (_IO_new_proc_open (fp, command, mode) != NULL)
310     return (_IO_FILE *) &new_f->fpx.file;
311   INTUSE(_IO_un_link) (&new_f->fpx.file);
312   free (new_f);
313   return NULL;
314 }
315
316 int
317 _IO_new_proc_close (fp)
318      _IO_FILE *fp;
319 {
320   /* This is not name-space clean. FIXME! */
321 #if _IO_HAVE_SYS_WAIT
322   int wstatus;
323   _IO_proc_file **ptr = &proc_file_chain;
324   _IO_pid_t wait_pid;
325   int status = -1;
326
327   /* Unlink from proc_file_chain. */
328 #ifdef _IO_MTSAFE_IO
329   _IO_cleanup_region_start_noarg (unlock);
330   _IO_lock_lock (proc_file_chain_lock);
331 #endif
332   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
333     {
334       if (*ptr == (_IO_proc_file *) fp)
335         {
336           *ptr = (*ptr)->next;
337           status = 0;
338           break;
339         }
340     }
341 #ifdef _IO_MTSAFE_IO
342   _IO_lock_unlock (proc_file_chain_lock);
343   _IO_cleanup_region_end (0);
344 #endif
345
346   if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
347     return -1;
348   /* POSIX.2 Rationale:  "Some historical implementations either block
349      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
350      for the child process to terminate.  Since this behavior is not
351      described in POSIX.2, such implementations are not conforming." */
352   do
353     {
354       wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
355     }
356   while (wait_pid == -1 && errno == EINTR);
357   if (wait_pid == -1)
358     return -1;
359   return wstatus;
360 #else /* !_IO_HAVE_SYS_WAIT */
361   return -1;
362 #endif
363 }
364
365 static const struct _IO_jump_t _IO_proc_jumps = {
366   JUMP_INIT_DUMMY,
367   JUMP_INIT(finish, _IO_new_file_finish),
368   JUMP_INIT(overflow, _IO_new_file_overflow),
369   JUMP_INIT(underflow, _IO_new_file_underflow),
370   JUMP_INIT(uflow, INTUSE(_IO_default_uflow)),
371   JUMP_INIT(pbackfail, INTUSE(_IO_default_pbackfail)),
372   JUMP_INIT(xsputn, _IO_new_file_xsputn),
373   JUMP_INIT(xsgetn, INTUSE(_IO_default_xsgetn)),
374   JUMP_INIT(seekoff, _IO_new_file_seekoff),
375   JUMP_INIT(seekpos, _IO_default_seekpos),
376   JUMP_INIT(setbuf, _IO_new_file_setbuf),
377   JUMP_INIT(sync, _IO_new_file_sync),
378   JUMP_INIT(doallocate, INTUSE(_IO_file_doallocate)),
379   JUMP_INIT(read, INTUSE(_IO_file_read)),
380   JUMP_INIT(write, _IO_new_file_write),
381   JUMP_INIT(seek, INTUSE(_IO_file_seek)),
382   JUMP_INIT(close, _IO_new_proc_close),
383   JUMP_INIT(stat, INTUSE(_IO_file_stat)),
384   JUMP_INIT(showmanyc, _IO_default_showmanyc),
385   JUMP_INIT(imbue, _IO_default_imbue)
386 };
387
388 strong_alias (_IO_new_popen, __new_popen)
389 versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
390 versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
391 versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
392 versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);