]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/iopopen.c
Update copyright notices with scripts/update-copyrights
[thirdparty/glibc.git] / libio / iopopen.c
CommitLineData
d4697bc9 1/* Copyright (C) 1993-2014 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"
196980f5
RM
32#include <signal.h>
33#include <unistd.h>
196980f5 34#include <stdlib.h>
fa0bc87c
RM
35#ifdef _LIBC
36# include <unistd.h>
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 *
7d6a8338 109_IO_new_proc_open (fp, command, mode)
40a55d20
UD
110 _IO_FILE *fp;
111 const char *command;
112 const char *mode;
196980f5 113{
372aece0
UD
114 int read_or_write;
115 int parent_end, child_end;
196980f5 116 int pipe_fds[2];
196980f5 117 _IO_pid_t child_pid;
d6e0c2a6
UD
118
119 int do_read = 0;
120 int do_write = 0;
121 int do_cloexec = 0;
122 while (*mode != '\0')
123 switch (*mode++)
124 {
125 case 'r':
126 do_read = 1;
127 break;
128 case 'w':
129 do_write = 1;
130 break;
131 case 'e':
132 do_cloexec = 1;
133 break;
134 default:
135 errout:
136 __set_errno (EINVAL);
137 return NULL;
138 }
139
140 if ((do_read ^ do_write) == 0)
141 goto errout;
142
40a55d20 143 if (_IO_file_is_open (fp))
196980f5 144 return NULL;
d6e0c2a6
UD
145
146#ifdef O_CLOEXEC
147# ifndef __ASSUME_PIPE2
148 if (__have_pipe2 >= 0)
149# endif
150 {
151 int r = __pipe2 (pipe_fds, O_CLOEXEC);
152# ifndef __ASSUME_PIPE2
153 if (__have_pipe2 == 0)
154 __have_pipe2 = r != -1 || errno != ENOSYS ? 1 : -1;
155
156 if (__have_pipe2 > 0)
157# endif
158 if (r < 0)
159 return NULL;
160 }
161#endif
162#ifndef __ASSUME_PIPE2
163# ifdef O_CLOEXEC
164 if (__have_pipe2 < 0)
165# endif
166 if (__pipe (pipe_fds) < 0)
167 return NULL;
168#endif
169
170 if (do_read)
196980f5
RM
171 {
172 parent_end = pipe_fds[0];
173 child_end = pipe_fds[1];
174 read_or_write = _IO_NO_WRITES;
175 }
d6e0c2a6 176 else
196980f5
RM
177 {
178 parent_end = pipe_fds[1];
179 child_end = pipe_fds[0];
180 read_or_write = _IO_NO_READS;
181 }
d6e0c2a6 182
40a55d20 183 ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
196980f5
RM
184 if (child_pid == 0)
185 {
d6e0c2a6 186 int child_std_end = do_read ? 1 : 0;
3c493630
AS
187 struct _IO_proc_file *p;
188
d6e0c2a6
UD
189#ifndef __ASSUME_PIPE2
190 /* If we have pipe2 the descriptor is marked for close-on-exec. */
40a55d20 191 _IO_close (parent_end);
d6e0c2a6 192#endif
196980f5
RM
193 if (child_end != child_std_end)
194 {
40a55d20 195 _IO_dup2 (child_end, child_std_end);
d6e0c2a6 196#ifndef __ASSUME_PIPE2
40a55d20 197 _IO_close (child_end);
d6e0c2a6
UD
198#endif
199 }
200#ifdef O_CLOEXEC
201 else
202 {
203 /* The descriptor is already the one we will use. But it must
204 not be marked close-on-exec. Undo the effects. */
205# ifndef __ASSUME_PIPE2
206 if (__have_pipe2 > 0)
207# endif
208 __fcntl (child_end, F_SETFD, 0);
196980f5 209 }
d6e0c2a6 210#endif
40a55d20 211 /* POSIX.2: "popen() shall ensure that any streams from previous
196980f5
RM
212 popen() calls that remain open in the parent process are closed
213 in the new child process." */
3c493630 214 for (p = proc_file_chain; p; p = p->next)
d8d7feef
UD
215 {
216 int fd = _IO_fileno ((_IO_FILE *) p);
217
218 /* If any stream from previous popen() calls has fileno
219 child_std_end, it has been already closed by the dup2 syscall
220 above. */
221 if (fd != child_std_end)
222 _IO_close (fd);
223 }
196980f5 224
40a55d20
UD
225 _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
226 _IO__exit (127);
196980f5 227 }
40a55d20 228 _IO_close (child_end);
196980f5
RM
229 if (child_pid < 0)
230 {
40a55d20 231 _IO_close (parent_end);
196980f5
RM
232 return NULL;
233 }
d6e0c2a6
UD
234
235 if (do_cloexec)
236 {
237#ifndef __ASSUME_PIPE2
238# ifdef O_CLOEXEC
239 if (__have_pipe2 < 0)
240# endif
241 __fcntl (parent_end, F_SETFD, FD_CLOEXEC);
242#endif
243 }
244 else
245 {
246#ifdef O_CLOEXEC
247 /* Undo the effects of the pipe2 call which set the
248 close-on-exec flag. */
249# ifndef __ASSUME_PIPE2
250 if (__have_pipe2 > 0)
251# endif
252 __fcntl (parent_end, F_SETFD, 0);
253#endif
254 }
255
40a55d20 256 _IO_fileno (fp) = parent_end;
196980f5
RM
257
258 /* Link into proc_file_chain. */
9ec9864b 259#ifdef _IO_MTSAFE_IO
34183f57
UD
260 _IO_cleanup_region_start_noarg (unlock);
261 _IO_lock_lock (proc_file_chain_lock);
262#endif
40a55d20
UD
263 ((_IO_proc_file *) fp)->next = proc_file_chain;
264 proc_file_chain = (_IO_proc_file *) fp;
9ec9864b 265#ifdef _IO_MTSAFE_IO
34183f57
UD
266 _IO_lock_unlock (proc_file_chain_lock);
267 _IO_cleanup_region_end (0);
268#endif
196980f5
RM
269
270 _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
271 return fp;
196980f5
RM
272}
273
274_IO_FILE *
7d6a8338 275_IO_new_popen (command, mode)
40a55d20
UD
276 const char *command;
277 const char *mode;
196980f5 278{
edf5b2d7
UD
279 struct locked_FILE
280 {
281 struct _IO_proc_file fpx;
499e7464 282#ifdef _IO_MTSAFE_IO
edf5b2d7 283 _IO_lock_t lock;
499e7464 284#endif
edf5b2d7
UD
285 } *new_f;
286 _IO_FILE *fp;
287
288 new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
289 if (new_f == NULL)
196980f5 290 return NULL;
499e7464 291#ifdef _IO_MTSAFE_IO
bd355af0 292 new_f->fpx.file.file._lock = &new_f->lock;
499e7464 293#endif
7ce241a0 294 fp = &new_f->fpx.file.file;
d18ea0c5 295 _IO_init (fp, 0);
2ca8b1ee
GM
296 _IO_JUMPS (&new_f->fpx.file) = &_IO_proc_jumps;
297 _IO_new_file_init (&new_f->fpx.file);
196980f5 298#if !_IO_UNIFIED_JUMPTABLES
7ce241a0 299 new_f->fpx.file.vtable = NULL;
196980f5 300#endif
7d6a8338 301 if (_IO_new_proc_open (fp, command, mode) != NULL)
2ca8b1ee 302 return (_IO_FILE *) &new_f->fpx.file;
d18ea0c5 303 _IO_un_link (&new_f->fpx.file);
edf5b2d7 304 free (new_f);
196980f5
RM
305 return NULL;
306}
307
196980f5 308int
7d6a8338 309_IO_new_proc_close (fp)
40a55d20 310 _IO_FILE *fp;
196980f5
RM
311{
312 /* This is not name-space clean. FIXME! */
196980f5
RM
313 int wstatus;
314 _IO_proc_file **ptr = &proc_file_chain;
315 _IO_pid_t wait_pid;
316 int status = -1;
317
318 /* Unlink from proc_file_chain. */
9ec9864b 319#ifdef _IO_MTSAFE_IO
34183f57
UD
320 _IO_cleanup_region_start_noarg (unlock);
321 _IO_lock_lock (proc_file_chain_lock);
322#endif
196980f5
RM
323 for ( ; *ptr != NULL; ptr = &(*ptr)->next)
324 {
40a55d20 325 if (*ptr == (_IO_proc_file *) fp)
196980f5
RM
326 {
327 *ptr = (*ptr)->next;
328 status = 0;
329 break;
330 }
331 }
9ec9864b 332#ifdef _IO_MTSAFE_IO
34183f57
UD
333 _IO_lock_unlock (proc_file_chain_lock);
334 _IO_cleanup_region_end (0);
335#endif
196980f5 336
40a55d20 337 if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
196980f5
RM
338 return -1;
339 /* POSIX.2 Rationale: "Some historical implementations either block
340 or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
341 for the child process to terminate. Since this behavior is not
342 described in POSIX.2, such implementations are not conforming." */
343 do
344 {
40a55d20
UD
345 wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
346 }
347 while (wait_pid == -1 && errno == EINTR);
196980f5
RM
348 if (wait_pid == -1)
349 return -1;
350 return wstatus;
196980f5
RM
351}
352
b2637a22 353static const struct _IO_jump_t _IO_proc_jumps = {
196980f5 354 JUMP_INIT_DUMMY,
7d6a8338
UD
355 JUMP_INIT(finish, _IO_new_file_finish),
356 JUMP_INIT(overflow, _IO_new_file_overflow),
357 JUMP_INIT(underflow, _IO_new_file_underflow),
d18ea0c5
AS
358 JUMP_INIT(uflow, _IO_default_uflow),
359 JUMP_INIT(pbackfail, _IO_default_pbackfail),
d64b6ad0 360 JUMP_INIT(xsputn, _IO_new_file_xsputn),
d18ea0c5 361 JUMP_INIT(xsgetn, _IO_default_xsgetn),
d64b6ad0 362 JUMP_INIT(seekoff, _IO_new_file_seekoff),
196980f5 363 JUMP_INIT(seekpos, _IO_default_seekpos),
7d6a8338
UD
364 JUMP_INIT(setbuf, _IO_new_file_setbuf),
365 JUMP_INIT(sync, _IO_new_file_sync),
d18ea0c5
AS
366 JUMP_INIT(doallocate, _IO_file_doallocate),
367 JUMP_INIT(read, _IO_file_read),
7d6a8338 368 JUMP_INIT(write, _IO_new_file_write),
d18ea0c5 369 JUMP_INIT(seek, _IO_file_seek),
7d6a8338 370 JUMP_INIT(close, _IO_new_proc_close),
d18ea0c5 371 JUMP_INIT(stat, _IO_file_stat),
dfd2257a
UD
372 JUMP_INIT(showmanyc, _IO_default_showmanyc),
373 JUMP_INIT(imbue, _IO_default_imbue)
196980f5 374};
7d6a8338 375
7d6a8338 376strong_alias (_IO_new_popen, __new_popen)
fd091d3f
UD
377versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
378versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
379versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
380versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);