x86-64: Skip zero length in __mem[pcpy|move|set]_erms
[glibc.git] / libio / iopopen.c
blob2eff45b4c80b5cd65c02e1eae0e3befdf4e3d0f5
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>.
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.
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.
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/>.
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. */
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>
39 struct _IO_proc_file
41 struct _IO_FILE_plus file;
42 /* Following fields must match those in class procbuf (procbuf.h) */
43 pid_t pid;
44 struct _IO_proc_file *next;
46 typedef struct _IO_proc_file _IO_proc_file;
48 static const struct _IO_jump_t _IO_proc_jumps;
50 static struct _IO_proc_file *proc_file_chain;
52 #ifdef _IO_MTSAFE_IO
53 static _IO_lock_t proc_file_chain_lock = _IO_lock_initializer;
55 static void
56 unlock (void *not_used)
58 _IO_lock_unlock (proc_file_chain_lock);
60 #endif
62 FILE *
63 _IO_new_proc_open (FILE *fp, const char *command, const char *mode)
65 int read_or_write;
66 int parent_end, child_end;
67 int pipe_fds[2];
68 pid_t child_pid;
70 int do_read = 0;
71 int do_write = 0;
72 int do_cloexec = 0;
73 while (*mode != '\0')
74 switch (*mode++)
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;
91 if ((do_read ^ do_write) == 0)
92 goto errout;
94 if (_IO_file_is_open (fp))
95 return NULL;
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;
109 if (do_read)
111 parent_end = pipe_fds[0];
112 child_end = pipe_fds[1];
113 read_or_write = _IO_NO_WRITES;
115 else
117 parent_end = pipe_fds[1];
118 child_end = pipe_fds[0];
119 read_or_write = _IO_NO_READS;
122 ((_IO_proc_file *) fp)->pid = child_pid = __fork ();
123 if (child_pid == 0)
125 int child_std_end = do_read ? 1 : 0;
126 struct _IO_proc_file *p;
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)
139 int fd = _IO_fileno ((FILE *) p);
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);
148 execl ("/bin/sh", "sh", "-c", command, (char *) 0);
149 _exit (127);
151 __close_nocancel (child_end);
152 if (child_pid < 0)
154 __close_nocancel (parent_end);
155 return NULL;
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);
163 _IO_fileno (fp) = parent_end;
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
177 _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
178 return fp;
181 FILE *
182 _IO_new_popen (const char *command, const char *mode)
184 struct locked_FILE
186 struct _IO_proc_file fpx;
187 #ifdef _IO_MTSAFE_IO
188 _IO_lock_t lock;
189 #endif
190 } *new_f;
191 FILE *fp;
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_new_proc_open (fp, command, mode) != NULL)
204 return (FILE *) &new_f->fpx.file;
205 _IO_un_link (&new_f->fpx.file);
206 free (new_f);
207 return NULL;
211 _IO_new_proc_close (FILE *fp)
213 /* This is not name-space clean. FIXME! */
214 int wstatus;
215 _IO_proc_file **ptr = &proc_file_chain;
216 pid_t wait_pid;
217 int status = -1;
219 /* Unlink from proc_file_chain. */
220 #ifdef _IO_MTSAFE_IO
221 _IO_cleanup_region_start_noarg (unlock);
222 _IO_lock_lock (proc_file_chain_lock);
223 #endif
224 for ( ; *ptr != NULL; ptr = &(*ptr)->next)
226 if (*ptr == (_IO_proc_file *) fp)
228 *ptr = (*ptr)->next;
229 status = 0;
230 break;
233 #ifdef _IO_MTSAFE_IO
234 _IO_lock_unlock (proc_file_chain_lock);
235 _IO_cleanup_region_end (0);
236 #endif
238 if (status < 0 || __close_nocancel (_IO_fileno(fp)) < 0)
239 return -1;
240 /* POSIX.2 Rationale: "Some historical implementations either block
241 or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
242 for the child process to terminate. Since this behavior is not
243 described in POSIX.2, such implementations are not conforming." */
246 wait_pid = __waitpid_nocancel (((_IO_proc_file *) fp)->pid, &wstatus, 0);
248 while (wait_pid == -1 && errno == EINTR);
249 if (wait_pid == -1)
250 return -1;
251 return wstatus;
254 static const struct _IO_jump_t _IO_proc_jumps libio_vtable = {
255 JUMP_INIT_DUMMY,
256 JUMP_INIT(finish, _IO_new_file_finish),
257 JUMP_INIT(overflow, _IO_new_file_overflow),
258 JUMP_INIT(underflow, _IO_new_file_underflow),
259 JUMP_INIT(uflow, _IO_default_uflow),
260 JUMP_INIT(pbackfail, _IO_default_pbackfail),
261 JUMP_INIT(xsputn, _IO_new_file_xsputn),
262 JUMP_INIT(xsgetn, _IO_default_xsgetn),
263 JUMP_INIT(seekoff, _IO_new_file_seekoff),
264 JUMP_INIT(seekpos, _IO_default_seekpos),
265 JUMP_INIT(setbuf, _IO_new_file_setbuf),
266 JUMP_INIT(sync, _IO_new_file_sync),
267 JUMP_INIT(doallocate, _IO_file_doallocate),
268 JUMP_INIT(read, _IO_file_read),
269 JUMP_INIT(write, _IO_new_file_write),
270 JUMP_INIT(seek, _IO_file_seek),
271 JUMP_INIT(close, _IO_new_proc_close),
272 JUMP_INIT(stat, _IO_file_stat),
273 JUMP_INIT(showmanyc, _IO_default_showmanyc),
274 JUMP_INIT(imbue, _IO_default_imbue)
277 strong_alias (_IO_new_popen, __new_popen)
278 versioned_symbol (libc, _IO_new_popen, _IO_popen, GLIBC_2_1);
279 versioned_symbol (libc, __new_popen, popen, GLIBC_2_1);
280 versioned_symbol (libc, _IO_new_proc_open, _IO_proc_open, GLIBC_2_1);
281 versioned_symbol (libc, _IO_new_proc_close, _IO_proc_close, GLIBC_2_1);