1/* Copyright (C) 1993-2018 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#include "libioP.h"
29#include <fcntl.h>
30#include <signal.h>
31#include <unistd.h>
32#include <stdlib.h>
33#include <shlib-compat.h>
34#include <not-cancel.h>
35#include <sys/types.h>
36#include <sys/wait.h>
37#include <kernel-features.h>
38
39struct _IO_proc_file
40{
41 struct _IO_FILE_plus file;
42 /* Following fields must match those in class procbuf (procbuf.h) */
43 _IO_pid_t pid;
44 struct _IO_proc_file *next;
45};
46typedef struct _IO_proc_file _IO_proc_file;
47
48static const struct _IO_jump_t _IO_proc_jumps;
49
50static struct _IO_proc_file *proc_file_chain;
51
52#ifdef _IO_MTSAFE_IO
53static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
54
55static void
56unlock (void *not_used)
57{
58 _IO_lock_unlock (proc_file_chain_lock);
59}
60#endif
61
62_IO_FILE *
63_IO_new_proc_open (_IO_FILE *fp, const char *command, const char *mode)
64{
65 int read_or_write;
66 int parent_end, child_end;
67 int pipe_fds[2];
68 _IO_pid_t child_pid;
69
70 int do_read = 0;
71 int do_write = 0;
72 int do_cloexec = 0;
73 while (*mode != '\0')
74 switch (*mode++)
75 {
76 case 'r':
77 do_read = 1;
78 break;
79 case 'w':
80 do_write = 1;
81 break;
82 case 'e':
83 do_cloexec = 1;
84 break;
85 default:
86 errout:
87 __set_errno (EINVAL);
88 return NULL;
89 }
90
91 if ((do_read ^ do_write) == 0)
92 goto errout;
93
94 if (_IO_file_is_open (fp))
95 return NULL;
96
97 /* Atomically set the O_CLOEXEC flag for the pipe end used by the
98 child process (to avoid leaking the file descriptor in case of a
99 concurrent fork). This is later reverted in the child process.
100 When popen returns, the parent pipe end can be O_CLOEXEC or not,
101 depending on the 'e' open mode, but there is only one flag which
102 controls both descriptors. The parent end is adjusted below,
103 after creating the child process. (In the child process, the
104 parent end should be closed on execve, so O_CLOEXEC remains set
105 there.) */
106 if (__pipe2 (pipe_fds, O_CLOEXEC) < 0)
107 return NULL;
108
109 if (do_read)
110 {
111 parent_end = pipe_fds[0];
112 child_end = pipe_fds[1];
113 read_or_write = _IO_NO_WRITES;
114 }
115 else
116 {
117 parent_end = pipe_fds[1];
118 child_end = pipe_fds[0];
119 read_or_write = _IO_NO_READS;
120 }
121
122 ((_IO_proc_file *) fp)->pid = child_pid = __fork ();
123 if (child_pid == 0)
124 {
125 int child_std_end = do_read ? 1 : 0;
126 struct _IO_proc_file *p;
127
128 if (child_end != child_std_end)
129 __dup2 (child_end, child_std_end);
130 else
131 /* The descriptor is already the one we will use. But it must
132 not be marked close-on-exec. Undo the effects. */
133 __fcntl (child_end, F_SETFD, 0);
134 /* POSIX.2: "popen() shall ensure that any streams from previous
135 popen() calls that remain open in the parent process are closed
136 in the new child process." */
137 for (p = proc_file_chain; p; p = p->next)
138 {
139 int fd = _IO_fileno ((_IO_FILE *) p);
140
141 /* If any stream from previous popen() calls has fileno
142 child_std_end, it has been already closed by the dup2 syscall
143 above. */
144 if (fd != child_std_end)
145 __close_nocancel (fd);
146 }
147
148 execl ("/bin/sh", "sh", "-c", command, (char *) 0);
149 _exit (127);
150 }
151 __close_nocancel (child_end);
152 if (child_pid < 0)
153 {
154 __close_nocancel (parent_end);
155 return NULL;
156 }
157
158 if (!do_cloexec)
159 /* Undo the effects of the pipe2 call which set the
160 close-on-exec flag. */
161 __fcntl (parent_end, F_SETFD, 0);
162
163 _IO_fileno (fp) = parent_end;
164
165 /* Link into proc_file_chain. */
166#ifdef _IO_MTSAFE_IO
167 _IO_cleanup_region_start_noarg (unlock);
168 _IO_lock_lock (proc_file_chain_lock);
169#endif
170 ((_IO_proc_file *) fp)->next = proc_file_chain;
171 proc_file_chain = (_IO_proc_file *) fp;
172#ifdef _IO_MTSAFE_IO
173 _IO_lock_unlock (proc_file_chain_lock);
174 _IO_cleanup_region_end (0);
175#endif
176
177 _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
178 return fp;
179}
180
181_IO_FILE *
182_IO_new_popen (const char *command, const char *mode)
183{
184 struct locked_FILE
185 {
186 struct _IO_proc_file fpx;
187#ifdef _IO_MTSAFE_IO
188 _IO_lock_t lock;
189#endif
190 } *new_f;
191 _IO_FILE *fp;
192
193 new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
194 if (new_f == NULL)
195 return NULL;
196#ifdef _IO_MTSAFE_IO
197 new_f->fpx.file.file._lock = &new_f->lock;
198#endif
199 fp = &new_f->fpx.file.file;
200 _IO_init_internal (fp, 0);
201 _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
202 _IO_new_file_init_internal (&new_f->fpx.file);
203#if !_IO_UNIFIED_JUMPTABLES
204 new_f->fpx.file.vtable = NULL;
205#endif
206 if (_IO_new_proc_open (fp, command, mode) != NULL)
207 return (_IO_FILE *) &new_f->fpx.file;
208 _IO_un_link (&new_f->fpx.file);
209 free (new_f);
210 return NULL;
211}
212
213int
214_IO_new_proc_close (_IO_FILE *fp)
215{
216 /* This is not name-space clean. FIXME! */
217 int wstatus;
218 _IO_proc_file **ptr = &proc_file_chain;
219 _IO_pid_t wait_pid;
220 int status = -1;
221
222 /* Unlink from proc_file_chain. */
223#ifdef _IO_MTSAFE_IO
224 _IO_cleanup_region_start_noarg (unlock);
225 _IO_lock_lock (proc_file_chain_lock);
226#endif
227 for ( ; *ptr != NULL; ptr = &(*ptr)->next)
228 {
229 if (*ptr == (_IO_proc_file *) fp)
230 {
231 *ptr = (*ptr)->next;
232 status = 0;
233 break;
234 }
235 }
236#ifdef _IO_MTSAFE_IO
237 _IO_lock_unlock (proc_file_chain_lock);
238 _IO_cleanup_region_end (0);
239#endif
240
241 if (status < 0 || __close_nocancel (_IO_fileno(fp)) < 0)
242 return -1;
243 /* POSIX.2 Rationale: "Some historical implementations either block
244 or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
245 for the child process to terminate. Since this behavior is not
246 described in POSIX.2, such implementations are not conforming." */
247 do
248 {
249 wait_pid = __waitpid_nocancel (((_IO_proc_file *) fp)->pid, &wstatus, 0);
250 }
251 while (wait_pid == -1 && errno == EINTR);
252 if (wait_pid == -1)
253 return -1;
254 return wstatus;
255}
256
257static const struct _IO_jump_t _IO_proc_jumps libio_vtable = {
258 JUMP_INIT_DUMMY,
259 JUMP_INIT(finish, _IO_new_file_finish),
260 JUMP_INIT(overflow, _IO_new_file_overflow),
261 JUMP_INIT(underflow, _IO_new_file_underflow),
262 JUMP_INIT(uflow, _IO_default_uflow),
263 JUMP_INIT(pbackfail, _IO_default_pbackfail),
264 JUMP_INIT(xsputn, _IO_new_file_xsputn),
265 JUMP_INIT(xsgetn, _IO_default_xsgetn),
266 JUMP_INIT(seekoff, _IO_new_file_seekoff),
267 JUMP_INIT(seekpos, _IO_default_seekpos),
268 JUMP_INIT(setbuf, _IO_new_file_setbuf),
269 JUMP_INIT(sync, _IO_new_file_sync),
270 JUMP_INIT(doallocate, _IO_file_doallocate),
271 JUMP_INIT(read, _IO_file_read),
272 JUMP_INIT(write, _IO_new_file_write),
273 JUMP_INIT(seek, _IO_file_seek),
274 JUMP_INIT(close, _IO_new_proc_close),
275 JUMP_INIT(stat, _IO_file_stat),
276 JUMP_INIT(showmanyc, _IO_default_showmanyc),
277 JUMP_INIT(imbue, _IO_default_imbue)
278};
279
280strong_alias (_IO_new_popen, __new_popen)
281versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
282versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
283versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
284versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);
285