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. */
33 #include <shlib-compat.h>
34 #include <not-cancel.h>
35 #include <sys/types.h>
37 #include <kernel-features.h>
41 struct _IO_FILE_plus file
;
42 /* Following fields must match those in class procbuf (procbuf.h) */
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
;
53 static _IO_lock_t proc_file_chain_lock
= _IO_lock_initializer
;
56 unlock (void *not_used
)
58 _IO_lock_unlock (proc_file_chain_lock
);
63 _IO_new_proc_open (FILE *fp
, const char *command
, const char *mode
)
66 int parent_end
, child_end
;
91 if ((do_read
^ do_write
) == 0)
94 if (_IO_file_is_open (fp
))
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
106 if (__pipe2 (pipe_fds
, O_CLOEXEC
) < 0)
111 parent_end
= pipe_fds
[0];
112 child_end
= pipe_fds
[1];
113 read_or_write
= _IO_NO_WRITES
;
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 ();
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
);
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
144 if (fd
!= child_std_end
)
145 __close_nocancel (fd
);
148 execl ("/bin/sh", "sh", "-c", command
, (char *) 0);
151 __close_nocancel (child_end
);
154 __close_nocancel (parent_end
);
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. */
167 _IO_cleanup_region_start_noarg (unlock
);
168 _IO_lock_lock (proc_file_chain_lock
);
170 ((_IO_proc_file
*) fp
)->next
= proc_file_chain
;
171 proc_file_chain
= (_IO_proc_file
*) fp
;
173 _IO_lock_unlock (proc_file_chain_lock
);
174 _IO_cleanup_region_end (0);
177 _IO_mask_flags (fp
, read_or_write
, _IO_NO_READS
|_IO_NO_WRITES
);
182 _IO_new_popen (const char *command
, const char *mode
)
186 struct _IO_proc_file fpx
;
193 new_f
= (struct locked_FILE
*) malloc (sizeof (struct locked_FILE
));
197 new_f
->fpx
.file
.file
._lock
= &new_f
->lock
;
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
);
211 _IO_new_proc_close (FILE *fp
)
213 /* This is not name-space clean. FIXME! */
215 _IO_proc_file
**ptr
= &proc_file_chain
;
219 /* Unlink from proc_file_chain. */
221 _IO_cleanup_region_start_noarg (unlock
);
222 _IO_lock_lock (proc_file_chain_lock
);
224 for ( ; *ptr
!= NULL
; ptr
= &(*ptr
)->next
)
226 if (*ptr
== (_IO_proc_file
*) fp
)
234 _IO_lock_unlock (proc_file_chain_lock
);
235 _IO_cleanup_region_end (0);
238 if (status
< 0 || __close_nocancel (_IO_fileno(fp
)) < 0)
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
);
254 static const struct _IO_jump_t _IO_proc_jumps libio_vtable
= {
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
);