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 /* Atomically set the O_CLOEXEC flag for the pipe end used by the
144 child process (to avoid leaking the file descriptor in case of a
145 concurrent fork). This is later reverted in the child process.
146 When popen returns, the parent pipe end can be O_CLOEXEC or not,
147 depending on the 'e' open mode, but there is only one flag which
148 controls both descriptors. The parent end is adjusted below,
149 after creating the child process. (In the child process, the
150 parent end should be closed on execve, so O_CLOEXEC remains set
151 there.) */
152 if (__pipe2 (pipe_fds, O_CLOEXEC) < 0)
153 return NULL;
154
155 if (do_read)
156 {
157 parent_end = pipe_fds[0];
158 child_end = pipe_fds[1];
159 read_or_write = _IO_NO_WRITES;
160 }
161 else
162 {
163 parent_end = pipe_fds[1];
164 child_end = pipe_fds[0];
165 read_or_write = _IO_NO_READS;
166 }
167
168 ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
169 if (child_pid == 0)
170 {
171 int child_std_end = do_read ? 1 : 0;
172 struct _IO_proc_file *p;
173
174 if (child_end != child_std_end)
175 _IO_dup2 (child_end, child_std_end);
176 else
177 /* The descriptor is already the one we will use. But it must
178 not be marked close-on-exec. Undo the effects. */
179 __fcntl (child_end, F_SETFD, 0);
180 /* POSIX.2: "popen() shall ensure that any streams from previous
181 popen() calls that remain open in the parent process are closed
182 in the new child process." */
183 for (p = proc_file_chain; p; p = p->next)
184 {
185 int fd = _IO_fileno ((_IO_FILE *) p);
186
187 /* If any stream from previous popen() calls has fileno
188 child_std_end, it has been already closed by the dup2 syscall
189 above. */
190 if (fd != child_std_end)
191 _IO_close (fd);
192 }
193
194 _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
195 _IO__exit (127);
196 }
197 _IO_close (child_end);
198 if (child_pid < 0)
199 {
200 _IO_close (parent_end);
201 return NULL;
202 }
203
204 if (!do_cloexec)
205 /* Undo the effects of the pipe2 call which set the
206 close-on-exec flag. */
207 __fcntl (parent_end, F_SETFD, 0);
208
209 _IO_fileno (fp) = parent_end;
210
211 /* Link into proc_file_chain. */
212#ifdef _IO_MTSAFE_IO
213 _IO_cleanup_region_start_noarg (unlock);
214 _IO_lock_lock (proc_file_chain_lock);
215#endif
216 ((_IO_proc_file *) fp)->next = proc_file_chain;
217 proc_file_chain = (_IO_proc_file *) fp;
218#ifdef _IO_MTSAFE_IO
219 _IO_lock_unlock (proc_file_chain_lock);
220 _IO_cleanup_region_end (0);
221#endif
222
223 _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
224 return fp;
225}
226
227_IO_FILE *
228_IO_new_popen (const char *command, const char *mode)
229{
230 struct locked_FILE
231 {
232 struct _IO_proc_file fpx;
233#ifdef _IO_MTSAFE_IO
234 _IO_lock_t lock;
235#endif
236 } *new_f;
237 _IO_FILE *fp;
238
239 new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
240 if (new_f == NULL)
241 return NULL;
242#ifdef _IO_MTSAFE_IO
243 new_f->fpx.file.file._lock = &new_f->lock;
244#endif
245 fp = &new_f->fpx.file.file;
246 _IO_init_internal (fp, 0);
247 _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
248 _IO_new_file_init_internal (&new_f->fpx.file);
249#if !_IO_UNIFIED_JUMPTABLES
250 new_f->fpx.file.vtable = NULL;
251#endif
252 if (_IO_new_proc_open (fp, command, mode) != NULL)
253 return (_IO_FILE *) &new_f->fpx.file;
254 _IO_un_link (&new_f->fpx.file);
255 free (new_f);
256 return NULL;
257}
258
259int
260_IO_new_proc_close (_IO_FILE *fp)
261{
262 /* This is not name-space clean. FIXME! */
263 int wstatus;
264 _IO_proc_file **ptr = &proc_file_chain;
265 _IO_pid_t wait_pid;
266 int status = -1;
267
268 /* Unlink from proc_file_chain. */
269#ifdef _IO_MTSAFE_IO
270 _IO_cleanup_region_start_noarg (unlock);
271 _IO_lock_lock (proc_file_chain_lock);
272#endif
273 for ( ; *ptr != NULL; ptr = &(*ptr)->next)
274 {
275 if (*ptr == (_IO_proc_file *) fp)
276 {
277 *ptr = (*ptr)->next;
278 status = 0;
279 break;
280 }
281 }
282#ifdef _IO_MTSAFE_IO
283 _IO_lock_unlock (proc_file_chain_lock);
284 _IO_cleanup_region_end (0);
285#endif
286
287 if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
288 return -1;
289 /* POSIX.2 Rationale: "Some historical implementations either block
290 or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
291 for the child process to terminate. Since this behavior is not
292 described in POSIX.2, such implementations are not conforming." */
293 do
294 {
295 wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
296 }
297 while (wait_pid == -1 && errno == EINTR);
298 if (wait_pid == -1)
299 return -1;
300 return wstatus;
301}
302
303static const struct _IO_jump_t _IO_proc_jumps libio_vtable = {
304 JUMP_INIT_DUMMY,
305 JUMP_INIT(finish, _IO_new_file_finish),
306 JUMP_INIT(overflow, _IO_new_file_overflow),
307 JUMP_INIT(underflow, _IO_new_file_underflow),
308 JUMP_INIT(uflow, _IO_default_uflow),
309 JUMP_INIT(pbackfail, _IO_default_pbackfail),
310 JUMP_INIT(xsputn, _IO_new_file_xsputn),
311 JUMP_INIT(xsgetn, _IO_default_xsgetn),
312 JUMP_INIT(seekoff, _IO_new_file_seekoff),
313 JUMP_INIT(seekpos, _IO_default_seekpos),
314 JUMP_INIT(setbuf, _IO_new_file_setbuf),
315 JUMP_INIT(sync, _IO_new_file_sync),
316 JUMP_INIT(doallocate, _IO_file_doallocate),
317 JUMP_INIT(read, _IO_file_read),
318 JUMP_INIT(write, _IO_new_file_write),
319 JUMP_INIT(seek, _IO_file_seek),
320 JUMP_INIT(close, _IO_new_proc_close),
321 JUMP_INIT(stat, _IO_file_stat),
322 JUMP_INIT(showmanyc, _IO_default_showmanyc),
323 JUMP_INIT(imbue, _IO_default_imbue)
324};
325
326strong_alias (_IO_new_popen, __new_popen)
327versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
328versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
329versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
330versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);
331