1 /* Copyright (C) 1991, 1992, 1993, 1996, 1997 Free Software Foundation, Inc.
2 This file is part of the GNU C Library.
4 The GNU C Library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public License as
6 published by the Free Software Foundation; either version 2 of the
7 License, or (at your option) any later version.
9 The GNU C Library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
14 You should have received a copy of the GNU Library General Public
15 License along with the GNU C Library; see the file COPYING.LIB. If not,
16 write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA. */
24 #include <sys/types.h>
29 #define SH_PATH "/bin/sh" /* Shell to run. */
30 #define SH_NAME "sh" /* Name to give it. */
32 /* Structure describing a popen child. */
35 pid_t pid
; /* PID of the child. */
36 __ptr_t cookie
; /* Original cookie from fdopen. */
37 __io_functions funcs
; /* Original functions from fdopen. */
40 /* io_functions for pipe streams.
41 These all simply call the corresponding
42 original function with the original cookie. */
44 #define FUNC(type, name, args) \
45 static type __CONCAT(child_,name) args __CONCAT(name,decl) \
47 struct child *c = (struct child *) cookie; \
49 __ptr_t cookie = c->cookie; \
50 return (*c->funcs.__CONCAT(__,name)) args; \
54 #define readdecl void *cookie; register char *buf; register size_t n;
55 FUNC (int, read
, (cookie
, buf
, n
))
56 #define writedecl void *cookie; register const char *buf; register size_t n;
57 FUNC (int, write
, (cookie
, buf
, n
))
58 #define seekdecl void *cookie; fpos_t *pos; int whence;
59 FUNC (int, seek
, (cookie
, pos
, whence
))
60 #define closedecl void *cookie;
61 FUNC (int, close
, (cookie
))
62 #define filenodecl void *cookie;
63 FUNC (int, fileno
, (cookie
))
65 static const __io_functions child_funcs
66 = { child_read
, child_write
, child_seek
, child_close
, child_fileno
};
68 /* Open a new stream that is a one-way pipe to a
69 child process running the given shell command. */
80 if (command
== NULL
|| mode
== NULL
|| (*mode
!= 'r' && *mode
!= 'w'))
86 /* Create the pipe. */
87 if (pipe (pipedes
) < 0)
90 /* Fork off the child. */
92 if (pid
== (pid_t
) -1)
94 /* The fork failed. */
95 (void) close (pipedes
[0]);
96 (void) close (pipedes
[1]);
99 else if (pid
== (pid_t
) 0)
101 /* We are the child side. Make the write side of
102 the pipe be stdin or the read side be stdout. */
104 const char *new_argv
[4];
106 if ((*mode
== 'w' ? dup2(pipedes
[STDIN_FILENO
], STDIN_FILENO
) :
107 dup2 (pipedes
[STDOUT_FILENO
], STDOUT_FILENO
)) < 0)
110 /* Close the pipe descriptors. */
111 (void) close (pipedes
[STDIN_FILENO
]);
112 (void) close (pipedes
[STDOUT_FILENO
]);
114 /* Exec the shell. */
115 new_argv
[0] = SH_NAME
;
117 new_argv
[2] = command
;
119 (void) execve (SH_PATH
, (char *const *) new_argv
, environ
);
120 /* Die if it failed. */
124 /* We are the parent side. */
126 /* Close the irrelevant side of the pipe and open the relevant side as a
127 new stream. Mark our side of the pipe to close on exec, so new children
131 (void) close (pipedes
[STDOUT_FILENO
]);
132 (void) fcntl (pipedes
[STDIN_FILENO
], F_SETFD
, FD_CLOEXEC
);
133 stream
= fdopen (pipedes
[STDIN_FILENO
], mode
);
137 (void) close (pipedes
[STDIN_FILENO
]);
138 (void) fcntl (pipedes
[STDOUT_FILENO
], F_SETFD
, FD_CLOEXEC
);
139 stream
= fdopen (pipedes
[STDOUT_FILENO
], mode
);
145 child
= (struct child
*) malloc (sizeof (struct child
));
150 /* Make sure STREAM has its functions set before
151 we try to squirrel them away in CHILD. */
152 extern void __stdio_check_funcs
__P ((FILE *));
153 __stdio_check_funcs (stream
);
157 child
->cookie
= stream
->__cookie
;
158 child
->funcs
= stream
->__io_funcs
;
159 stream
->__cookie
= (void *) child
;
160 stream
->__io_funcs
= child_funcs
;
161 stream
->__ispipe
= 1;
166 /* The stream couldn't be opened or the child structure couldn't be
167 allocated. Kill the child and close the other side of the pipe. */
169 (void) kill (pid
, SIGKILL
);
171 (void) close (pipedes
[*mode
== 'r' ? STDOUT_FILENO
: STDIN_FILENO
]);
173 (void) fclose (stream
);
175 (void) waitpid (pid
, (int *) NULL
, 0);
180 dead
= wait ((int *) NULL
);
181 while (dead
> 0 && dead
!= pid
);
189 /* Close a stream opened by popen and return its status.
190 Returns -1 if the stream was not opened by popen. */
193 register FILE *stream
;
199 if (!__validfp (stream
) || !stream
->__ispipe
)
201 __set_errno (EINVAL
);
205 c
= (struct child
*) stream
->__cookie
;
207 stream
->__cookie
= c
->cookie
;
208 stream
->__io_funcs
= c
->funcs
;
210 stream
->__ispipe
= 0;
215 dead
= waitpid (pid
, &status
, 0);
218 dead
= wait (&status
);
219 while (dead
> 0 && dead
!= pid
);