1 /*
2 * Copyright (c) 1995, by Sun Microsystems, Inc.
3 * All rights reserved.
4 */
5
6 #pragma ident "%Z%%M% %I% %E% SMI"
7 /* from UCB 5.2 85/06/05 */
8
9 /*
10 * Copyright (c) 1980 Regents of the University of California.
11 * All rights reserved. The Berkeley software License Agreement
12 * specifies the terms and conditions for redistribution.
13 */
14
15 #include <stdio.h>
16 #include <signal.h>
17 #include <vfork.h>
18
19 #define tst(a,b) (*mode == 'r'? (b) : (a))
20 #define RDR 0
21 #define WTR 1
22
23 extern char *malloc();
24 extern int execl(), vfork(), pipe(), close(), fcntl();
25
26 static int *popen_pid;
27 static int nfiles;
28
29 FILE *
popen(cmd,mode)30 popen(cmd,mode)
31 char *cmd;
32 char *mode;
33 {
34 int p[2];
35 register int *poptr;
36 register int myside, hisside, pid;
37
38 if (nfiles <= 0)
39 nfiles = getdtablesize();
40 if (popen_pid == NULL) {
41 popen_pid = (int *)malloc(nfiles * sizeof *popen_pid);
42 if (popen_pid == NULL)
43 return (NULL);
44 for (pid = 0; pid < nfiles; pid++)
45 popen_pid[pid] = -1;
46 }
47 if (pipe(p) < 0)
48 return (NULL);
49 myside = tst(p[WTR], p[RDR]);
50 hisside = tst(p[RDR], p[WTR]);
51 if ((pid = vfork()) == 0) {
52 /* myside and hisside reverse roles in child */
53 int stdio;
54
55 /* close all pipes from other popen's */
56 for (poptr = popen_pid; poptr < popen_pid+nfiles; poptr++) {
57 if(*poptr >= 0)
58 close(poptr - popen_pid);
59 }
60 stdio = tst(0, 1);
61 (void) close(myside);
62 if (hisside != stdio) {
63 (void) dup2(hisside, stdio);
64 (void) close(hisside);
65 }
66 (void) execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
67 _exit(127);
68 }
69 if (pid == -1) {
70 close(myside);
71 close(hisside);
72 return (NULL);
73 }
74 popen_pid[myside] = pid;
75 close(hisside);
76 return (fdopen(myside, mode));
77 }
78
79 int
pclose(ptr)80 pclose(ptr)
81 FILE *ptr;
82 {
83 int child = -1;
84 int pid, status, omask;
85
86 if (popen_pid != NULL) {
87 child = popen_pid[fileno(ptr)];
88 popen_pid[fileno(ptr)] = -1;
89 }
90 fclose(ptr);
91 if (child == -1)
92 return (-1);
93 omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
94 while ((pid = waitpid(child, &status, 0)) != child && pid != -1)
95 ;
96 (void) sigsetmask(omask);
97 return (pid == -1 ? -1 : status);
98 }
99