Fri Feb 9 12:40:19 1996 Brendan Kehoe <brendan@lisa.cygnus.com>
[kopensolaris-gnu/glibc.git] / libio / iopopen.c
1 /*
2 Copyright (C) 1993 Free Software Foundation
3
4 This file is part of the GNU IO Library.  This library is free
5 software; you can redistribute it and/or modify it under the
6 terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option)
8 any later version.
9
10 This 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
13 GNU 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 the Free
17 Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
18
19 As a special exception, if you link this library with files
20 compiled with a GNU compiler to produce an executable, this does not cause
21 the resulting executable to be covered by the GNU General Public License.
22 This exception does not however invalidate any other reasons why
23 the executable file might be covered by the GNU General Public License. */
24
25 /*  written by Per Bothner (bothner@cygnus.com) */
26
27 #define _POSIX_SOURCE
28 #include "libioP.h"
29 #if _IO_HAVE_SYS_WAIT
30 #include <signal.h>
31 #include <unistd.h>
32 #ifdef __STDC__
33 #include <stdlib.h>
34 #endif
35 #include <sys/types.h>
36 #include <sys/wait.h>
37
38 #ifndef _IO_fork
39 #define _IO_fork vfork /* defined in libiberty, if needed */
40 _IO_pid_t _IO_fork();
41 #endif
42
43 #endif /* _IO_HAVE_SYS_WAIT */
44
45 #ifndef _IO_pipe
46 #define _IO_pipe pipe
47 extern int _IO_pipe();
48 #endif
49
50 #ifndef _IO_dup2
51 #define _IO_dup2 dup2
52 extern int _IO_dup2();
53 #endif
54
55 #ifndef _IO_waitpid
56 #define _IO_waitpid waitpid
57 #endif
58
59 #ifndef _IO_execl
60 #define _IO_execl execl
61 #endif
62 #ifndef _IO__exit
63 #define _IO__exit _exit
64 #endif
65
66 struct _IO_proc_file
67 {
68   struct _IO_FILE_plus file;
69   /* Following fields must match those in class procbuf (procbuf.h) */
70   _IO_pid_t pid;
71   struct _IO_proc_file *next;
72 };
73 typedef struct _IO_proc_file _IO_proc_file;
74
75 static struct _IO_proc_file *proc_file_chain = NULL;
76
77 _IO_FILE *
78 DEFUN(_IO_proc_open, (fp, command, mode),
79       _IO_FILE* fp AND const char *command AND const char *mode)
80 {
81 #if _IO_HAVE_SYS_WAIT
82   int read_or_write;
83   int pipe_fds[2];
84   int parent_end, child_end;
85   _IO_pid_t child_pid;
86   if (_IO_file_is_open(fp))
87     return NULL;
88   if (_IO_pipe(pipe_fds) < 0)
89     return NULL;
90   if (mode[0] == 'r')
91     {
92       parent_end = pipe_fds[0];
93       child_end = pipe_fds[1];
94       read_or_write = _IO_NO_WRITES;
95     }
96   else
97     {
98       parent_end = pipe_fds[1];
99       child_end = pipe_fds[0];
100       read_or_write = _IO_NO_READS;
101     }
102   ((_IO_proc_file*)fp)->pid = child_pid = _IO_fork();
103   if (child_pid == 0)
104     {
105       int child_std_end = mode[0] == 'r' ? 1 : 0;
106       _IO_close(parent_end);
107       if (child_end != child_std_end)
108         {
109           _IO_dup2(child_end, child_std_end);
110           _IO_close(child_end);
111         }
112       /* Posix.2:  "popen() shall ensure that any streams from previous
113          popen() calls that remain open in the parent process are closed
114          in the new child process." */
115       while (proc_file_chain)
116         {
117           _IO_close (_IO_fileno ((_IO_FILE *) proc_file_chain));
118           proc_file_chain = proc_file_chain->next;
119         }
120
121       _IO_execl("/bin/sh", "sh", "-c", command, NULL);
122       _IO__exit(127);
123     }
124   _IO_close(child_end);
125   if (child_pid < 0)
126     {
127       _IO_close(parent_end);
128       return NULL;
129     }
130   _IO_fileno(fp) = parent_end;
131
132   /* Link into proc_file_chain. */
133   ((_IO_proc_file*)fp)->next = proc_file_chain;
134   proc_file_chain = (_IO_proc_file*)fp;
135
136   _IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
137   return fp;
138 #else /* !_IO_HAVE_SYS_WAIT */
139   return NULL;
140 #endif
141 }
142
143 _IO_FILE *
144 DEFUN(_IO_popen, (command, mode),
145       const char *command AND const char *mode)
146 {
147   _IO_proc_file *fpx = (_IO_proc_file*)malloc(sizeof(_IO_proc_file));
148   _IO_FILE *fp = (_IO_FILE*)fpx;
149   if (fp == NULL)
150     return NULL;
151   _IO_init(fp, 0);
152   _IO_JUMPS(fp) = &_IO_proc_jumps;
153   _IO_file_init(fp);
154 #if  !_IO_UNIFIED_JUMPTABLES
155   ((struct _IO_FILE_plus*)fp)->vtable = NULL;
156 #endif
157   if (_IO_proc_open (fp, command, mode) != NULL)
158     return fp;
159   free (fpx);
160   return NULL;
161 }
162
163 strong_alias (_IO_popen, popen);
164
165 int
166 DEFUN(_IO_proc_close, (fp),
167       _IO_FILE *fp)
168 {
169   /* This is not name-space clean. FIXME! */
170 #if _IO_HAVE_SYS_WAIT
171   int wstatus;
172   _IO_proc_file **ptr = &proc_file_chain;
173   _IO_pid_t wait_pid;
174   int status = -1;
175
176   /* Unlink from proc_file_chain. */
177   for ( ; *ptr != NULL; ptr = &(*ptr)->next)
178     {
179       if (*ptr == (_IO_proc_file*)fp)
180         {
181           *ptr = (*ptr)->next;
182           status = 0;
183           break;
184         }
185     }
186
187   if (status < 0 || _IO_close(_IO_fileno(fp)) < 0)
188     return -1;
189   /* POSIX.2 Rationale:  "Some historical implementations either block
190      or ignore the signals SIGINT, SIGQUIT, and SIGHUP while waiting
191      for the child process to terminate.  Since this behavior is not
192      described in POSIX.2, such implementations are not conforming." */
193   do
194     {
195       wait_pid = _IO_waitpid (((_IO_proc_file*)fp)->pid, &wstatus, 0);
196     } while (wait_pid == -1 && errno == EINTR);
197   if (wait_pid == -1)
198     return -1;
199   return wstatus;
200 #else /* !_IO_HAVE_SYS_WAIT */
201   return -1;
202 #endif
203 }
204
205 struct _IO_jump_t _IO_proc_jumps = {
206   JUMP_INIT_DUMMY,
207   JUMP_INIT(finish, _IO_file_finish),
208   JUMP_INIT(overflow, _IO_file_overflow),
209   JUMP_INIT(underflow, _IO_file_underflow),
210   JUMP_INIT(uflow, _IO_default_uflow),
211   JUMP_INIT(pbackfail, _IO_default_pbackfail),
212   JUMP_INIT(xsputn, _IO_file_xsputn),
213   JUMP_INIT(xsgetn, _IO_default_xsgetn),
214   JUMP_INIT(seekoff, _IO_file_seekoff),
215   JUMP_INIT(seekpos, _IO_default_seekpos),
216   JUMP_INIT(setbuf, _IO_file_setbuf),
217   JUMP_INIT(sync, _IO_file_sync),
218   JUMP_INIT(doallocate, _IO_file_doallocate),
219   JUMP_INIT(read, _IO_file_read),
220   JUMP_INIT(write, _IO_file_write),
221   JUMP_INIT(seek, _IO_file_seek),
222   JUMP_INIT(close, _IO_proc_close),
223   JUMP_INIT(stat, _IO_file_stat)
224 };