new copyright notice
[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)
269a7923 12static char sccsid[] = "@(#)popen.c 5.14 (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>
cfbb84de 20#include <unistd.h>
24de0d84 21#include <paths.h>
99756664 22
06a6638d 23static pid_t *pids;
01a56307
BJ
24
25FILE *
633d7ef6 26popen(program, type)
07329fc6 27 char *program, *type;
01a56307 28{
633d7ef6 29 FILE *iop;
900e9a44 30 int pdes[2], fds, pid;
07329fc6
KB
31 char *malloc();
32
33 if (*type != 'r' && *type != 'w' || type[1])
900e9a44 34 return (NULL);
01a56307 35
06a6638d 36 if (pids == NULL) {
07329fc6 37 if ((fds = getdtablesize()) <= 0)
900e9a44 38 return (NULL);
06a6638d 39 if ((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL)
900e9a44 40 return (NULL);
06a6638d 41 bzero((char *)pids, fds * sizeof(pid_t));
07329fc6 42 }
633d7ef6 43 if (pipe(pdes) < 0)
900e9a44 44 return (NULL);
06a6638d 45 switch (pid = vfork()) {
07329fc6 46 case -1: /* error */
900e9a44
MK
47 (void) close(pdes[0]);
48 (void) close(pdes[1]);
49 return (NULL);
633d7ef6 50 /* NOTREACHED */
07329fc6 51 case 0: /* child */
633d7ef6 52 if (*type == 'r') {
cfbb84de 53 if (pdes[1] != STDOUT_FILENO) {
900e9a44
MK
54 (void) dup2(pdes[1], STDOUT_FILENO);
55 (void) close(pdes[1]);
07329fc6 56 }
900e9a44 57 (void) close(pdes[0]);
633d7ef6 58 } else {
cfbb84de 59 if (pdes[0] != STDIN_FILENO) {
900e9a44
MK
60 (void) dup2(pdes[0], STDIN_FILENO);
61 (void) close(pdes[0]);
07329fc6 62 }
900e9a44 63 (void) close(pdes[1]);
482b978e 64 }
24de0d84 65 execl(_PATH_BSHELL, "sh", "-c", program, NULL);
07329fc6
KB
66 _exit(127);
67 /* NOTREACHED */
01a56307 68 }
07329fc6
KB
69 /* parent; assume fdopen can't fail... */
70 if (*type == 'r') {
71 iop = fdopen(pdes[0], type);
900e9a44 72 (void) close(pdes[1]);
07329fc6
KB
73 } else {
74 iop = fdopen(pdes[1], type);
900e9a44 75 (void) close(pdes[0]);
2337e291 76 }
07329fc6 77 pids[fileno(iop)] = pid;
900e9a44 78 return (iop);
01a56307
BJ
79}
80
633d7ef6 81pclose(iop)
07329fc6 82 FILE *iop;
01a56307 83{
34e174ed 84 extern int errno;
07329fc6 85 register int fdes;
06a6638d 86 int omask;
f0dec5e9
KB
87 union wait pstat;
88 pid_t pid, waitpid();
01a56307 89
07329fc6
KB
90 /*
91 * pclose returns -1 if stream is not associated with a
f0dec5e9
KB
92 * `popened' command, if already `pclosed', or waitpid
93 * returns an error.
07329fc6 94 */
06a6638d 95 if (pids == NULL || pids[fdes = fileno(iop)] == 0)
900e9a44
MK
96 return (-1);
97 (void) fclose(iop);
07329fc6 98 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
34e174ed
KB
99 do {
100 pid = waitpid(pids[fdes], &pstat, 0);
101 } while (pid == -1 && errno == EINTR);
900e9a44 102 (void) sigsetmask(omask);
07329fc6 103 pids[fdes] = 0;
900e9a44 104 return (pid == -1 ? -1 : pstat.w_status);
01a56307 105}