]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/iopopen.c
Update copyright dates with scripts/update-copyrights.
[thirdparty/glibc.git] / libio / iopopen.c
CommitLineData
bfff8b1b 1/* Copyright (C) 1993-2017 Free Software Foundation, Inc.
41bdb6e2 2 This file is part of the GNU C Library.
40a55d20
UD
3 Written by Per Bothner <bothner@cygnus.com>.
4
41bdb6e2
AJ
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.
40a55d20 9
41bdb6e2
AJ
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
40a55d20 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
41bdb6e2 13 Lesser General Public License for more details.
40a55d20 14
41bdb6e2 15 You should have received a copy of the GNU Lesser General Public
59ba27a6
PE
16 License along with the GNU C Library; if not, see
17 <http://www.gnu.org/licenses/>.
40a55d20 18
41bdb6e2
AJ
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. */
196980f5 27
fa0bc87c
RM
28#ifndef _POSIX_SOURCE
29# define _POSIX_SOURCE
30#endif
196980f5 31#include "libioP.h"
8ae4bb5a 32#include <fcntl.h>
196980f5
RM
33#include <signal.h>
34#include <unistd.h>
196980f5 35#include <stdlib.h>
fa0bc87c 36#ifdef _LIBC
fd091d3f 37# include <shlib-compat.h>
73299943 38# include <not-cancel.h>
fa0bc87c 39#endif
196980f5
RM
40#include <sys/types.h>
41#include <sys/wait.h>
e038616f 42#include <kernel-features.h>
196980f5
RM
43
44#ifndef _IO_fork
50304ef0 45#ifdef _LIBC
64d2a379 46#define _IO_fork __fork
50304ef0 47#else
64d2a379 48#define _IO_fork fork /* defined in libiberty, if needed */
50304ef0 49#endif
79937577 50extern _IO_pid_t _IO_fork (void) __THROW;
196980f5
RM
51#endif
52
196980f5 53#ifndef _IO_dup2
50304ef0
UD
54#ifdef _LIBC
55#define _IO_dup2 __dup2
56#else
196980f5 57#define _IO_dup2 dup2
50304ef0 58#endif
79937577 59extern int _IO_dup2 (int fd, int fd2) __THROW;
196980f5
RM
60#endif
61
62#ifndef _IO_waitpid
50304ef0 63#ifdef _LIBC
73299943 64#define _IO_waitpid waitpid_not_cancel
50304ef0 65#else
196980f5
RM
66#define _IO_waitpid waitpid
67#endif
50304ef0 68#endif
196980f5
RM
69
70#ifndef _IO_execl
71#define _IO_execl execl
72#endif
73#ifndef _IO__exit
74#define _IO__exit _exit
75#endif
76
61eb22d3 77#ifndef _IO_close
50304ef0 78#ifdef _LIBC
73299943 79#define _IO_close close_not_cancel
50304ef0 80#else
61eb22d3
UD
81#define _IO_close close
82#endif
50304ef0 83#endif
61eb22d3 84
196980f5
RM
85struct _IO_proc_file
86{
bd355af0 87 struct _IO_FILE_plus file;
196980f5
RM
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
b2637a22 94static const struct _IO_jump_t _IO_proc_jumps;
d64b6ad0 95
390500b1 96static struct _IO_proc_file *proc_file_chain;
196980f5 97
34183f57
UD
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
196980f5 108_IO_FILE *
9d46370c 109_IO_new_proc_open (_IO_FILE *fp, const char *command, const char *mode)
196980f5 110{
372aece0
UD
111 int read_or_write;
112 int parent_end, child_end;
196980f5 113 int pipe_fds[2];
196980f5 114 _IO_pid_t child_pid;
d6e0c2a6
UD
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
40a55d20 140 if (_IO_file_is_open (fp))
196980f5 141 return NULL;
d6e0c2a6
UD
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)
196980f5
RM
168 {
169 parent_end = pipe_fds[0];
170 child_end = pipe_fds[1];
171 read_or_write = _IO_NO_WRITES;
172 }
d6e0c2a6 173 else
196980f5
RM
174 {
175 parent_end = pipe_fds[1];
176 child_end = pipe_fds[0];
177 read_or_write = _IO_NO_READS;
178 }
d6e0c2a6 179
40a55d20 180 ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
196980f5
RM
181 if (child_pid == 0)
182 {
d6e0c2a6 183 int child_std_end = do_read ? 1 : 0;
3c493630
AS
184 struct _IO_proc_file *p;
185
d6e0c2a6
UD
186#ifndef __ASSUME_PIPE2
187 /* If we have pipe2 the descriptor is marked for close-on-exec. */
40a55d20 188 _IO_close (parent_end);
d6e0c2a6 189#endif
196980f5
RM
190 if (child_end != child_std_end)
191 {
40a55d20 192 _IO_dup2 (child_end, child_std_end);
d6e0c2a6 193#ifndef __ASSUME_PIPE2
40a55d20 194 _IO_close (child_end);
d6e0c2a6
UD
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);
196980f5 206 }
d6e0c2a6 207#endif
40a55d20 208 /* POSIX.2: "popen() shall ensure that any streams from previous
196980f5
RM
209 popen() calls that remain open in the parent process are closed
210 in the new child process." */
3c493630 211 for (p = proc_file_chain; p; p = p->next)
d8d7feef
UD
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 }
196980f5 221
40a55d20
UD
222 _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
223 _IO__exit (127);
196980f5 224 }
40a55d20 225 _IO_close (child_end);
196980f5
RM
226 if (child_pid < 0)
227 {
40a55d20 228 _IO_close (parent_end);
196980f5
RM
229 return NULL;
230 }
d6e0c2a6
UD
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
40a55d20 253 _IO_fileno (fp) = parent_end;
196980f5
RM
254
255 /* Link into proc_file_chain. */
9ec9864b 256#ifdef _IO_MTSAFE_IO
34183f57
UD
257 _IO_cleanup_region_start_noarg (unlock);
258 _IO_lock_lock (proc_file_chain_lock);
259#endif
40a55d20
UD
260 ((_IO_proc_file *) fp)->next = proc_file_chain;
261 proc_file_chain = (_IO_proc_file *) fp;
9ec9864b 262#ifdef _IO_MTSAFE_IO
34183f57
UD
263 _IO_lock_unlock (proc_file_chain_lock);
264 _IO_cleanup_region_end (0);
265#endif
196980f5
RM
266
267 _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
268 return fp;
196980f5
RM
269}
270
271_IO_FILE *
9d46370c 272_IO_new_popen (const char *command, const char *mode)
196980f5 273{
edf5b2d7
UD
274 struct locked_FILE
275 {
276 struct _IO_proc_file fpx;
499e7464 277#ifdef _IO_MTSAFE_IO
edf5b2d7 278 _IO_lock_t lock;
499e7464 279#endif
edf5b2d7
UD
280 } *new_f;
281 _IO_FILE *fp;
282
283 new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
284 if (new_f == NULL)
196980f5 285 return NULL;
499e7464 286#ifdef _IO_MTSAFE_IO
bd355af0 287 new_f->fpx.file.file._lock = &new_f->lock;
499e7464 288#endif
7ce241a0 289 fp = &new_f->fpx.file.file;
db3476af 290 _IO_init_internal (fp, 0);
2ca8b1ee 291 _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
db3476af 292 _IO_new_file_init_internal (&new_f->fpx.file);
196980f5 293#if !_IO_UNIFIED_JUMPTABLES
7ce241a0 294 new_f->fpx.file.vtable = NULL;
196980f5 295#endif
7d6a8338 296 if (_IO_new_proc_open (fp, command, mode) != NULL)
2ca8b1ee 297 return (_IO_FILE *) &new_f->fpx.file;
d18ea0c5 298 _IO_un_link (&new_f->fpx.file);
edf5b2d7 299 free (new_f);
196980f5
RM
300 return NULL;
301}
302
196980f5 303int
9d46370c 304_IO_new_proc_close (_IO_FILE *fp)
196980f5
RM
305{
306 /* This is not name-space clean. FIXME! */
196980f5
RM
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. */
9ec9864b 313#ifdef _IO_MTSAFE_IO
34183f57
UD
314 _IO_cleanup_region_start_noarg (unlock);
315 _IO_lock_lock (proc_file_chain_lock);
316#endif
196980f5
RM
317 for ( ; *ptr != NULL; ptr = &(*ptr)->next)
318 {
40a55d20 319 if (*ptr == (_IO_proc_file *) fp)
196980f5
RM
320 {
321 *ptr = (*ptr)->next;
322 status = 0;
323 break;
324 }
325 }
9ec9864b 326#ifdef _IO_MTSAFE_IO
34183f57
UD
327 _IO_lock_unlock (proc_file_chain_lock);
328 _IO_cleanup_region_end (0);
329#endif
196980f5 330
40a55d20 331 if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
196980f5
RM
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 {
40a55d20
UD
339 wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
340 }
341 while (wait_pid == -1 && errno == EINTR);
196980f5
RM
342 if (wait_pid == -1)
343 return -1;
344 return wstatus;
196980f5
RM
345}
346
db3476af 347static const struct _IO_jump_t _IO_proc_jumps libio_vtable = {
196980f5 348 JUMP_INIT_DUMMY,
7d6a8338
UD
349 JUMP_INIT(finish, _IO_new_file_finish),
350 JUMP_INIT(overflow, _IO_new_file_overflow),
351 JUMP_INIT(underflow, _IO_new_file_underflow),
d18ea0c5
AS
352 JUMP_INIT(uflow, _IO_default_uflow),
353 JUMP_INIT(pbackfail, _IO_default_pbackfail),
d64b6ad0 354 JUMP_INIT(xsputn, _IO_new_file_xsputn),
d18ea0c5 355 JUMP_INIT(xsgetn, _IO_default_xsgetn),
d64b6ad0 356 JUMP_INIT(seekoff, _IO_new_file_seekoff),
196980f5 357 JUMP_INIT(seekpos, _IO_default_seekpos),
7d6a8338
UD
358 JUMP_INIT(setbuf, _IO_new_file_setbuf),
359 JUMP_INIT(sync, _IO_new_file_sync),
d18ea0c5
AS
360 JUMP_INIT(doallocate, _IO_file_doallocate),
361 JUMP_INIT(read, _IO_file_read),
7d6a8338 362 JUMP_INIT(write, _IO_new_file_write),
d18ea0c5 363 JUMP_INIT(seek, _IO_file_seek),
7d6a8338 364 JUMP_INIT(close, _IO_new_proc_close),
d18ea0c5 365 JUMP_INIT(stat, _IO_file_stat),
dfd2257a
UD
366 JUMP_INIT(showmanyc, _IO_default_showmanyc),
367 JUMP_INIT(imbue, _IO_default_imbue)
196980f5 368};
7d6a8338 369
7d6a8338 370strong_alias (_IO_new_popen, __new_popen)
fd091d3f
UD
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);