]> git.ipfire.org Git - thirdparty/glibc.git/blame - libio/iopopen.c
Update.
[thirdparty/glibc.git] / libio / iopopen.c
CommitLineData
390500b1 1/* Copyright (C) 1993, 1997, 1998, 1999 Free Software Foundation, Inc.
40a55d20
UD
2 This file is part of the GNU IO Library.
3 Written by Per Bothner <bothner@cygnus.com>.
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public License as
7 published by the Free Software Foundation; either version 2, or (at
8 your option) any later version.
9
10 This library is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this library; see the file COPYING. If not, write to
17 the Free Software Foundation, 59 Temple Place - Suite 330, Boston,
18 MA 02111-1307, USA.
19
20 As a special exception, if you link this library with files
21 compiled with a GNU compiler to produce an executable, this does
22 not cause the resulting executable to be covered by the GNU General
23 Public License. This exception does not however invalidate any
24 other reasons why the executable file might be covered by the GNU
25 General Public License. */
196980f5 26
fa0bc87c
RM
27#ifndef _POSIX_SOURCE
28# define _POSIX_SOURCE
29#endif
196980f5
RM
30#include "libioP.h"
31#if _IO_HAVE_SYS_WAIT
32#include <signal.h>
33#include <unistd.h>
34#ifdef __STDC__
35#include <stdlib.h>
36#endif
fa0bc87c
RM
37#ifdef _LIBC
38# include <unistd.h>
39#endif
196980f5
RM
40#include <sys/types.h>
41#include <sys/wait.h>
42
43#ifndef _IO_fork
50304ef0
UD
44#ifdef _LIBC
45#define _IO_fork __vfork
46#else
196980f5 47#define _IO_fork vfork /* defined in libiberty, if needed */
50304ef0 48#endif
fa0bc87c 49extern _IO_pid_t _IO_fork __P ((void));
196980f5
RM
50#endif
51
52#endif /* _IO_HAVE_SYS_WAIT */
53
54#ifndef _IO_pipe
50304ef0
UD
55#ifdef _LIBC
56#define _IO_pipe __pipe
57#else
196980f5 58#define _IO_pipe pipe
50304ef0 59#endif
fa0bc87c 60extern int _IO_pipe __P ((int des[2]));
196980f5
RM
61#endif
62
63#ifndef _IO_dup2
50304ef0
UD
64#ifdef _LIBC
65#define _IO_dup2 __dup2
66#else
196980f5 67#define _IO_dup2 dup2
50304ef0 68#endif
fa0bc87c 69extern int _IO_dup2 __P ((int fd, int fd2));
196980f5
RM
70#endif
71
72#ifndef _IO_waitpid
50304ef0
UD
73#ifdef _LIBC
74#define _IO_waitpid __waitpid
75#else
196980f5
RM
76#define _IO_waitpid waitpid
77#endif
50304ef0 78#endif
196980f5
RM
79
80#ifndef _IO_execl
81#define _IO_execl execl
82#endif
83#ifndef _IO__exit
84#define _IO__exit _exit
85#endif
86
61eb22d3 87#ifndef _IO_close
50304ef0
UD
88#ifdef _LIBC
89#define _IO_close __close
90#else
61eb22d3
UD
91#define _IO_close close
92#endif
50304ef0 93#endif
61eb22d3 94
196980f5
RM
95struct _IO_proc_file
96{
bd355af0 97 struct _IO_FILE_plus file;
196980f5
RM
98 /* Following fields must match those in class procbuf (procbuf.h) */
99 _IO_pid_t pid;
100 struct _IO_proc_file *next;
101};
102typedef struct _IO_proc_file _IO_proc_file;
103
390500b1 104static struct _IO_proc_file *proc_file_chain;
196980f5
RM
105
106_IO_FILE *
7d6a8338 107_IO_new_proc_open (fp, command, mode)
40a55d20
UD
108 _IO_FILE *fp;
109 const char *command;
110 const char *mode;
196980f5
RM
111{
112#if _IO_HAVE_SYS_WAIT
a1470b6f
RM
113 volatile int read_or_write;
114 volatile int parent_end, child_end;
196980f5 115 int pipe_fds[2];
196980f5 116 _IO_pid_t child_pid;
40a55d20 117 if (_IO_file_is_open (fp))
196980f5 118 return NULL;
40a55d20 119 if (_IO_pipe (pipe_fds) < 0)
196980f5 120 return NULL;
f43ce637 121 if (mode[0] == 'r' && mode[1] == '\0')
196980f5
RM
122 {
123 parent_end = pipe_fds[0];
124 child_end = pipe_fds[1];
125 read_or_write = _IO_NO_WRITES;
126 }
f43ce637 127 else if (mode[0] == 'w' && mode[1] == '\0')
196980f5
RM
128 {
129 parent_end = pipe_fds[1];
130 child_end = pipe_fds[0];
131 read_or_write = _IO_NO_READS;
132 }
f43ce637
UD
133 else
134 {
135 __set_errno (EINVAL);
136 return NULL;
137 }
40a55d20 138 ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
196980f5
RM
139 if (child_pid == 0)
140 {
141 int child_std_end = mode[0] == 'r' ? 1 : 0;
3c493630
AS
142 struct _IO_proc_file *p;
143
40a55d20 144 _IO_close (parent_end);
196980f5
RM
145 if (child_end != child_std_end)
146 {
40a55d20
UD
147 _IO_dup2 (child_end, child_std_end);
148 _IO_close (child_end);
196980f5 149 }
40a55d20 150 /* POSIX.2: "popen() shall ensure that any streams from previous
196980f5
RM
151 popen() calls that remain open in the parent process are closed
152 in the new child process." */
3c493630
AS
153 for (p = proc_file_chain; p; p = p->next)
154 _IO_close (_IO_fileno ((_IO_FILE *) p));
196980f5 155
40a55d20
UD
156 _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
157 _IO__exit (127);
196980f5 158 }
40a55d20 159 _IO_close (child_end);
196980f5
RM
160 if (child_pid < 0)
161 {
40a55d20 162 _IO_close (parent_end);
196980f5
RM
163 return NULL;
164 }
40a55d20 165 _IO_fileno (fp) = parent_end;
196980f5
RM
166
167 /* Link into proc_file_chain. */
40a55d20
UD
168 ((_IO_proc_file *) fp)->next = proc_file_chain;
169 proc_file_chain = (_IO_proc_file *) fp;
196980f5
RM
170
171 _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
172 return fp;
173#else /* !_IO_HAVE_SYS_WAIT */
174 return NULL;
175#endif
176}
177
178_IO_FILE *
7d6a8338 179_IO_new_popen (command, mode)
40a55d20
UD
180 const char *command;
181 const char *mode;
196980f5 182{
edf5b2d7
UD
183 struct locked_FILE
184 {
185 struct _IO_proc_file fpx;
499e7464 186#ifdef _IO_MTSAFE_IO
edf5b2d7 187 _IO_lock_t lock;
499e7464 188#endif
edf5b2d7
UD
189 } *new_f;
190 _IO_FILE *fp;
191
192 new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
193 if (new_f == NULL)
196980f5 194 return NULL;
499e7464 195#ifdef _IO_MTSAFE_IO
bd355af0 196 new_f->fpx.file.file._lock = &new_f->lock;
499e7464 197#endif
7ce241a0 198 fp = &new_f->fpx.file.file;
40a55d20
UD
199 _IO_init (fp, 0);
200 _IO_JUMPS (fp) = &_IO_proc_jumps;
7d6a8338 201 _IO_new_file_init (fp);
196980f5 202#if !_IO_UNIFIED_JUMPTABLES
7ce241a0 203 new_f->fpx.file.vtable = NULL;
196980f5 204#endif
7d6a8338 205 if (_IO_new_proc_open (fp, command, mode) != NULL)
196980f5 206 return fp;
7ce241a0 207 _IO_un_link (fp);
edf5b2d7 208 free (new_f);
196980f5
RM
209 return NULL;
210}
211
196980f5 212int
7d6a8338 213_IO_new_proc_close (fp)
40a55d20 214 _IO_FILE *fp;
196980f5
RM
215{
216 /* This is not name-space clean. FIXME! */
217#if _IO_HAVE_SYS_WAIT
218 int wstatus;
219 _IO_proc_file **ptr = &proc_file_chain;
220 _IO_pid_t wait_pid;
221 int status = -1;
222
223 /* Unlink from proc_file_chain. */
224 for ( ; *ptr != NULL; ptr = &(*ptr)->next)
225 {
40a55d20 226 if (*ptr == (_IO_proc_file *) fp)
196980f5
RM
227 {
228 *ptr = (*ptr)->next;
229 status = 0;
230 break;
231 }
232 }
233
40a55d20 234 if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
196980f5
RM
235 return -1;
236 /* POSIX.2 Rationale: "Some historical implementations either block
237 or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
238 for the child process to terminate. Since this behavior is not
239 described in POSIX.2, such implementations are not conforming." */
240 do
241 {
40a55d20
UD
242 wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
243 }
244 while (wait_pid == -1 && errno == EINTR);
196980f5
RM
245 if (wait_pid == -1)
246 return -1;
247 return wstatus;
248#else /* !_IO_HAVE_SYS_WAIT */
249 return -1;
250#endif
251}
252
253struct _IO_jump_t _IO_proc_jumps = {
254 JUMP_INIT_DUMMY,
7d6a8338
UD
255 JUMP_INIT(finish, _IO_new_file_finish),
256 JUMP_INIT(overflow, _IO_new_file_overflow),
257 JUMP_INIT(underflow, _IO_new_file_underflow),
196980f5
RM
258 JUMP_INIT(uflow, _IO_default_uflow),
259 JUMP_INIT(pbackfail, _IO_default_pbackfail),
7d6a8338 260 JUMP_INIT(xsputn, _IO_new_file_xsputn),
196980f5 261 JUMP_INIT(xsgetn, _IO_default_xsgetn),
7d6a8338 262 JUMP_INIT(seekoff, _IO_new_file_seekoff),
196980f5 263 JUMP_INIT(seekpos, _IO_default_seekpos),
7d6a8338
UD
264 JUMP_INIT(setbuf, _IO_new_file_setbuf),
265 JUMP_INIT(sync, _IO_new_file_sync),
196980f5
RM
266 JUMP_INIT(doallocate, _IO_file_doallocate),
267 JUMP_INIT(read, _IO_file_read),
7d6a8338 268 JUMP_INIT(write, _IO_new_file_write),
196980f5 269 JUMP_INIT(seek, _IO_file_seek),
7d6a8338 270 JUMP_INIT(close, _IO_new_proc_close),
dfd2257a
UD
271 JUMP_INIT(stat, _IO_file_stat),
272 JUMP_INIT(showmanyc, _IO_default_showmanyc),
273 JUMP_INIT(imbue, _IO_default_imbue)
196980f5 274};
7d6a8338
UD
275
276#if defined PIC && DO_VERSIONING
277strong_alias (_IO_new_popen, __new_popen)
278default_symbol_version (_IO_new_popen, _IO_popen, GLIBC_2.1);
279default_symbol_version (__new_popen, popen, GLIBC_2.1);
280default_symbol_version (_IO_new_proc_open, _IO_proc_open, GLIBC_2.1);
281default_symbol_version (_IO_new_proc_close, _IO_proc_close, GLIBC_2.1);
282#else
283# ifdef strong_alias
284strong_alias (_IO_new_popen, popen)
285# endif
286# ifdef weak_alias
287weak_alias (_IO_new_popen, _IO_popen)
288weak_alias (_IO_new_proc_open, _IO_proc_open)
289weak_alias (_IO_new_proc_close, _IO_proc_close)
290# endif
291#endif