|
|
1.1 root 1: /*
2: * Copyright (c) 1988 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software written by Ken Arnold and
6: * published in UNIX Review, Vol. 6, No. 8.
7: *
8: * Redistribution and use in source and binary forms are permitted
9: * provided that: (1) source distributions retain this entire copyright
10: * notice and comment, and (2) distributions including binaries display
11: * the following acknowledgement: ``This product includes software
12: * developed by the University of California, Berkeley and its contributors''
13: * in the documentation or other materials provided with the distribution
14: * and in all advertising materials mentioning features or use of this
15: * software. Neither the name of the University nor the names of its
16: * contributors may be used to endorse or promote products derived
17: * from this software without specific prior written permission.
18: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
19: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
20: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
21: */
22:
23: #if defined(LIBC_SCCS) && !defined(lint)
24: static char sccsid[] = "@(#)popen.c 5.14 (Berkeley) 6/1/90";
25: #endif /* LIBC_SCCS and not lint */
26:
27: #include <sys/param.h>
28: #include <sys/signal.h>
29: #include <sys/wait.h>
30: #include <errno.h>
31: #include <stdio.h>
32: #include <unistd.h>
33: #include <paths.h>
34:
35: static pid_t *pids;
36:
37: FILE *
38: popen(program, type)
39: char *program, *type;
40: {
41: FILE *iop;
42: int pdes[2], fds, pid;
43: char *malloc();
44:
45: if (*type != 'r' && *type != 'w' || type[1])
46: return (NULL);
47:
48: if (pids == NULL) {
49: if ((fds = getdtablesize()) <= 0)
50: return (NULL);
51: if ((pids = (pid_t *)malloc((u_int)(fds * sizeof(int)))) == NULL)
52: return (NULL);
53: bzero((char *)pids, fds * sizeof(pid_t));
54: }
55: if (pipe(pdes) < 0)
56: return (NULL);
57: switch (pid = vfork()) {
58: case -1: /* error */
59: (void) close(pdes[0]);
60: (void) close(pdes[1]);
61: return (NULL);
62: /* NOTREACHED */
63: case 0: /* child */
64: if (*type == 'r') {
65: if (pdes[1] != STDOUT_FILENO) {
66: (void) dup2(pdes[1], STDOUT_FILENO);
67: (void) close(pdes[1]);
68: }
69: (void) close(pdes[0]);
70: } else {
71: if (pdes[0] != STDIN_FILENO) {
72: (void) dup2(pdes[0], STDIN_FILENO);
73: (void) close(pdes[0]);
74: }
75: (void) close(pdes[1]);
76: }
77: execl(_PATH_BSHELL, "sh", "-c", program, NULL);
78: _exit(127);
79: /* NOTREACHED */
80: }
81: /* parent; assume fdopen can't fail... */
82: if (*type == 'r') {
83: iop = fdopen(pdes[0], type);
84: (void) close(pdes[1]);
85: } else {
86: iop = fdopen(pdes[1], type);
87: (void) close(pdes[0]);
88: }
89: pids[fileno(iop)] = pid;
90: return (iop);
91: }
92:
93: pclose(iop)
94: FILE *iop;
95: {
96: extern int errno;
97: register int fdes;
98: int omask;
99: union wait pstat;
100: pid_t pid, waitpid();
101:
102: /*
103: * pclose returns -1 if stream is not associated with a
104: * `popened' command, if already `pclosed', or waitpid
105: * returns an error.
106: */
107: if (pids == NULL || pids[fdes = fileno(iop)] == 0)
108: return (-1);
109: (void) fclose(iop);
110: omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
111: do {
112: pid = waitpid(pids[fdes], &pstat, 0);
113: } while (pid == -1 && errno == EINTR);
114: (void) sigsetmask(omask);
115: pids[fdes] = 0;
116: return (pid == -1 ? -1 : pstat.w_status);
117: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.