Commit | Line | Data |
---|---|---|
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 | 12 | static 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 | 23 | static pid_t *pids; |
01a56307 BJ |
24 | |
25 | FILE * | |
633d7ef6 | 26 | popen(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 | 81 | pclose(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 | } |