]> git.ipfire.org Git - thirdparty/glibc.git/blob - libio/iopopen.c
Update.
[thirdparty/glibc.git] / libio / iopopen.c
1 /* Copyright (C) 1993, 1997 Free Software Foundation, Inc.
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. */
26
27 #ifndef _POSIX_SOURCE
28 # define _POSIX_SOURCE
29 #endif
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
37 #ifdef _LIBC
38 # include <unistd.h>
39 #endif
40 #include <sys/types.h>
41 #include <sys/wait.h>
42
43 #ifndef _IO_fork
44 #define _IO_fork vfork /* defined in libiberty, if needed */
45 extern _IO_pid_t _IO_fork __P ((void));
46 #endif
47
48 #endif /* _IO_HAVE_SYS_WAIT */
49
50 #ifndef _IO_pipe
51 #define _IO_pipe pipe
52 extern int _IO_pipe __P ((int des[2]));
53 #endif
54
55 #ifndef _IO_dup2
56 #define _IO_dup2 dup2
57 extern int _IO_dup2 __P ((int fd, int fd2));
58 #endif
59
60 #ifndef _IO_waitpid
61 #define _IO_waitpid waitpid
62 #endif
63
64 #ifndef _IO_execl
65 #define _IO_execl execl
66 #endif
67 #ifndef _IO__exit
68 #define _IO__exit _exit
69 #endif
70
71 #ifndef _IO_close
72 #define _IO_close close
73 #endif
74
75 struct _IO_proc_file
76 {
77 struct _IO_FILE_complete file;
78 /* Following fields must match those in class procbuf (procbuf.h) */
79 _IO_pid_t pid;
80 struct _IO_proc_file *next;
81 };
82 typedef struct _IO_proc_file _IO_proc_file;
83
84 static struct _IO_proc_file *proc_file_chain = NULL;
85
86 _IO_FILE *
87 _IO_proc_open (fp, command, mode)
88 _IO_FILE *fp;
89 const char *command;
90 const char *mode;
91 {
92 #if _IO_HAVE_SYS_WAIT
93 volatile int read_or_write;
94 volatile int parent_end, child_end;
95 int pipe_fds[2];
96 _IO_pid_t child_pid;
97 if (_IO_file_is_open (fp))
98 return NULL;
99 if (_IO_pipe (pipe_fds) < 0)
100 return NULL;
101 if (mode[0] == 'r' && mode[1] == '\0')
102 {
103 parent_end = pipe_fds[0];
104 child_end = pipe_fds[1];
105 read_or_write = _IO_NO_WRITES;
106 }
107 else if (mode[0] == 'w' && mode[1] == '\0')
108 {
109 parent_end = pipe_fds[1];
110 child_end = pipe_fds[0];
111 read_or_write = _IO_NO_READS;
112 }
113 else
114 {
115 __set_errno (EINVAL);
116 return NULL;
117 }
118 ((_IO_proc_file *) fp)->pid = child_pid = _IO_fork ();
119 if (child_pid == 0)
120 {
121 int child_std_end = mode[0] == 'r' ? 1 : 0;
122 _IO_close (parent_end);
123 if (child_end != child_std_end)
124 {
125 _IO_dup2 (child_end, child_std_end);
126 _IO_close (child_end);
127 }
128 /* POSIX.2: "popen() shall ensure that any streams from previous
129 popen() calls that remain open in the parent process are closed
130 in the new child process." */
131 while (proc_file_chain)
132 {
133 _IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain));
134 proc_file_chain = proc_file_chain->next;
135 }
136
137 _IO_execl ("/bin/sh", "sh", "-c", command, (char *) 0);
138 _IO__exit (127);
139 }
140 _IO_close (child_end);
141 if (child_pid < 0)
142 {
143 _IO_close (parent_end);
144 return NULL;
145 }
146 _IO_fileno (fp) = parent_end;
147
148 /* Link into proc_file_chain. */
149 ((_IO_proc_file *) fp)->next = proc_file_chain;
150 proc_file_chain = (_IO_proc_file *) fp;
151
152 _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
153 return fp;
154 #else /* !_IO_HAVE_SYS_WAIT */
155 return NULL;
156 #endif
157 }
158
159 _IO_FILE *
160 _IO_popen (command, mode)
161 const char *command;
162 const char *mode;
163 {
164 struct locked_FILE
165 {
166 struct _IO_proc_file fpx;
167 #ifdef _IO_MTSAFE_IO
168 _IO_lock_t lock;
169 #endif
170 } *new_f;
171 _IO_FILE *fp;
172
173 new_f = (struct locked_FILE *) malloc (sizeof (struct locked_FILE));
174 if (new_f == NULL)
175 return NULL;
176 #ifdef _IO_MTSAFE_IO
177 new_f->fpx.file.plus.file._lock = &new_f->lock;
178 #endif
179 fp = (_IO_FILE*)&new_f->fpx;
180 _IO_init (fp, 0);
181 _IO_JUMPS (fp) = &_IO_proc_jumps;
182 _IO_file_init (fp);
183 #if !_IO_UNIFIED_JUMPTABLES
184 ((struct _IO_FILE_plus *) fp)->vtable = NULL;
185 #endif
186 if (_IO_proc_open (fp, command, mode) != NULL)
187 return fp;
188 free (new_f);
189 return NULL;
190 }
191
192 #ifdef strong_alias
193 strong_alias (_IO_popen, popen);
194 #endif
195
196 int
197 _IO_proc_close (fp)
198 _IO_FILE *fp;
199 {
200 /* This is not name-space clean. FIXME! */
201 #if _IO_HAVE_SYS_WAIT
202 int wstatus;
203 _IO_proc_file **ptr = &proc_file_chain;
204 _IO_pid_t wait_pid;
205 int status = -1;
206
207 /* Unlink from proc_file_chain. */
208 for ( ; *ptr != NULL; ptr = &(*ptr)->next)
209 {
210 if (*ptr == (_IO_proc_file *) fp)
211 {
212 *ptr = (*ptr)->next;
213 status = 0;
214 break;
215 }
216 }
217
218 if (status < 0 || _IO_close (_IO_fileno(fp)) < 0)
219 return -1;
220 /* POSIX.2 Rationale: "Some historical implementations either block
221 or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
222 for the child process to terminate. Since this behavior is not
223 described in POSIX.2, such implementations are not conforming." */
224 do
225 {
226 wait_pid = _IO_waitpid (((_IO_proc_file *) fp)->pid, &wstatus, 0);
227 }
228 while (wait_pid == -1 && errno == EINTR);
229 if (wait_pid == -1)
230 return -1;
231 return wstatus;
232 #else /* !_IO_HAVE_SYS_WAIT */
233 return -1;
234 #endif
235 }
236
237 struct _IO_jump_t _IO_proc_jumps = {
238 JUMP_INIT_DUMMY,
239 JUMP_INIT(finish, _IO_file_finish),
240 JUMP_INIT(overflow, _IO_file_overflow),
241 JUMP_INIT(underflow, _IO_file_underflow),
242 JUMP_INIT(uflow, _IO_default_uflow),
243 JUMP_INIT(pbackfail, _IO_default_pbackfail),
244 JUMP_INIT(xsputn, _IO_file_xsputn),
245 JUMP_INIT(xsgetn, _IO_default_xsgetn),
246 JUMP_INIT(seekoff, _IO_file_seekoff),
247 JUMP_INIT(seekpos, _IO_default_seekpos),
248 JUMP_INIT(setbuf, _IO_file_setbuf),
249 JUMP_INIT(sync, _IO_file_sync),
250 JUMP_INIT(doallocate, _IO_file_doallocate),
251 JUMP_INIT(read, _IO_file_read),
252 JUMP_INIT(write, _IO_file_write),
253 JUMP_INIT(seek, _IO_file_seek),
254 JUMP_INIT(close, _IO_proc_close),
255 JUMP_INIT(stat, _IO_file_stat),
256 JUMP_INIT(showmanyc, _IO_default_showmanyc),
257 JUMP_INIT(imbue, _IO_default_imbue)
258 };