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) |
c5980113 | 12 | static 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 | 25 | static pid_t *pids; |
01a56307 BJ |
26 | |
27 | FILE * | |
633d7ef6 | 28 | popen(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 | 83 | int |
633d7ef6 | 84 | pclose(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 | } |