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