1 /* Copyright (C) 1991, 1992 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
16 not, write to the Free Software Foundation, Inc., 675 Mass Ave,
17 Cambridge, MA 02139, USA. */
25 #include <sys/types.h>
30 #define SH_PATH "/bin/sh" /* Shell to run. */
31 #define SH_NAME "sh" /* Name to give it. */
33 /* Structure describing a popen child. */
36 /* It is important that the first member of this structure be an `int' that
37 is the file descriptor. This is because the `fileno' function assumes
38 that __cookie(STREAM) points to the file descriptor. */
43 /* Open a new stream that is a one-way pipe to a
44 child process running the given shell command. */
46 DEFUN(popen, (command, mode), CONST char *command AND CONST char *mode)
53 if (command == NULL || mode == NULL || (*mode != 'r' && *mode != 'w'))
59 /* Create the pipe. */
60 if (pipe(pipedes) < 0)
63 /* Fork off the child. */
65 if (pid == (pid_t) -1)
67 /* The fork failed. */
68 (void) close (pipedes[0]);
69 (void) close (pipedes[1]);
72 else if (pid == (pid_t) 0)
74 /* We are the child side. Make the write side of
75 the pipe be stdin or the read side be stdout. */
77 CONST char *new_argv[4];
79 if ((*mode == 'w' ? dup2(pipedes[STDIN_FILENO], STDIN_FILENO) :
80 dup2(pipedes[STDOUT_FILENO], STDOUT_FILENO)) < 0)
83 /* Close the pipe descriptors. */
84 (void) close(pipedes[STDIN_FILENO]);
85 (void) close(pipedes[STDOUT_FILENO]);
88 new_argv[0] = SH_NAME;
90 new_argv[2] = command;
92 (void) execve(SH_PATH, (char *CONST *) new_argv, environ);
93 /* Die if it failed. */
97 /* We are the parent side. */
99 /* Close the irrelevant side of the pipe and open the relevant side as a
100 new stream. Mark our side of the pipe to close on exec, so new children
104 (void) close(pipedes[STDOUT_FILENO]);
105 (void) fcntl (pipedes[STDIN_FILENO], F_SETFD, FD_CLOEXEC);
106 stream = fdopen(pipedes[STDIN_FILENO], mode);
110 (void) close(pipedes[STDIN_FILENO]);
111 (void) fcntl (pipedes[STDOUT_FILENO], F_SETFD, FD_CLOEXEC);
112 stream = fdopen(pipedes[STDOUT_FILENO], mode);
118 child = (struct child *) malloc(sizeof(struct child));
121 child->fd = fileno(stream);
123 stream->__cookie = (PTR) child;
124 stream->__ispipe = 1;
129 /* The stream couldn't be opened or the child structure couldn't be
130 allocated. Kill the child and close the other side of the pipe. */
132 (void) kill(pid, SIGKILL);
134 (void) close(pipedes[*mode == 'r' ? STDOUT_FILENO : STDIN_FILENO]);
136 (void) fclose(stream);
138 (void) waitpid(pid, (int *) NULL, 0);
143 dead = wait ((int *) NULL);
144 while (dead > 0 && dead != pid);
152 /* Close a stream opened by popen and return its status.
153 Returns -1 if the stream was not opened by popen. */
155 DEFUN(pclose, (stream), register FILE *stream)
160 if (!__validfp(stream) || !stream->__ispipe)
166 pid = ((struct child *) stream->__cookie)->pid;
167 free(stream->__cookie);
168 stream->__cookie = (PTR) &stream->__fileno;
169 stream->__ispipe = 0;
174 dead = waitpid (pid, &status, 0);
177 dead = wait (&status);
178 while (dead > 0 && dead != pid);