flag fields are u_int's
[unix-history] / usr / src / lib / libc / gen / popen.c
CommitLineData
b8f253e8 1/*
633d7ef6
KB
2 * Copyright (c) 1988 The Regents of the University of California.
3 * All rights reserved.
4 *
07329fc6
KB
5 * This code is derived from software written by Ken Arnold and
6 * published in UNIX Review, Vol. 6, No. 8.
633d7ef6 7 *
269a7923 8 * %sccs.include.redist.c%
b8f253e8
KM
9 */
10
2ce81398 11#if defined(LIBC_SCCS) && !defined(lint)
c5980113 12static char sccsid[] = "@(#)popen.c 5.15 (Berkeley) %G%";
633d7ef6 13#endif /* LIBC_SCCS and not lint */
99756664 14
07329fc6
KB
15#include <sys/param.h>
16#include <sys/signal.h>
17#include <sys/wait.h>
34e174ed 18#include <errno.h>
01a56307 19#include <stdio.h>
c5980113
DS
20#include <stdlib.h>
21#include <string.h>
cfbb84de 22#include <unistd.h>
24de0d84 23#include <paths.h>
99756664 24
06a6638d 25static pid_t *pids;
01a56307
BJ
26
27FILE *
633d7ef6 28popen(program, type)
c5980113
DS
29 const char *program;
30 const char *type;
01a56307 31{
633d7ef6 32 FILE *iop;
900e9a44 33 int pdes[2], fds, pid;
07329fc6
KB
34
35 if (*type != 'r' && *type != 'w' || type[1])
900e9a44 36 return (NULL);
01a56307 37
06a6638d 38 if (pids == NULL) {
07329fc6 39 if ((fds = getdtablesize()) <= 0)
900e9a44 40 return (NULL);
06a6638d 41 if ((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL)
900e9a44 42 return (NULL);
06a6638d 43 bzero((char *)pids, fds * sizeof(pid_t));
07329fc6 44 }
633d7ef6 45 if (pipe(pdes) < 0)
900e9a44 46 return (NULL);
06a6638d 47 switch (pid = vfork()) {
07329fc6 48 case -1: /* error */
900e9a44
MK
49 (void) close(pdes[0]);
50 (void) close(pdes[1]);
51 return (NULL);
633d7ef6 52 /* NOTREACHED */
07329fc6 53 case 0: /* child */
633d7ef6 54 if (*type == 'r') {
cfbb84de 55 if (pdes[1] != STDOUT_FILENO) {
900e9a44
MK
56 (void) dup2(pdes[1], STDOUT_FILENO);
57 (void) close(pdes[1]);
07329fc6 58 }
900e9a44 59 (void) close(pdes[0]);
633d7ef6 60 } else {
cfbb84de 61 if (pdes[0] != STDIN_FILENO) {
900e9a44
MK
62 (void) dup2(pdes[0], STDIN_FILENO);
63 (void) close(pdes[0]);
07329fc6 64 }
900e9a44 65 (void) close(pdes[1]);
482b978e 66 }
24de0d84 67 execl(_PATH_BSHELL, "sh", "-c", program, NULL);
07329fc6
KB
68 _exit(127);
69 /* NOTREACHED */
01a56307 70 }
07329fc6
KB
71 /* parent; assume fdopen can't fail... */
72 if (*type == 'r') {
73 iop = fdopen(pdes[0], type);
900e9a44 74 (void) close(pdes[1]);
07329fc6
KB
75 } else {
76 iop = fdopen(pdes[1], type);
900e9a44 77 (void) close(pdes[0]);
2337e291 78 }
07329fc6 79 pids[fileno(iop)] = pid;
900e9a44 80 return (iop);
01a56307
BJ
81}
82
c5980113 83int
633d7ef6 84pclose(iop)
07329fc6 85 FILE *iop;
01a56307 86{
07329fc6 87 register int fdes;
06a6638d 88 int omask;
f0dec5e9 89 union wait pstat;
c5980113 90 pid_t pid;
01a56307 91
07329fc6
KB
92 /*
93 * pclose returns -1 if stream is not associated with a
f0dec5e9
KB
94 * `popened' command, if already `pclosed', or waitpid
95 * returns an error.
07329fc6 96 */
06a6638d 97 if (pids == NULL || pids[fdes = fileno(iop)] == 0)
900e9a44
MK
98 return (-1);
99 (void) fclose(iop);
07329fc6 100 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
34e174ed 101 do {
c5980113 102 pid = waitpid(pids[fdes], (int *) &pstat, 0);
34e174ed 103 } while (pid == -1 && errno == EINTR);
900e9a44 104 (void) sigsetmask(omask);
07329fc6 105 pids[fdes] = 0;
900e9a44 106 return (pid == -1 ? -1 : pstat.w_status);
01a56307 107}