xref: /csrg-svn/lib/libc/gen/popen.c (revision 22101)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)popen.c	5.2 (Berkeley) 06/05/85";
9 #endif not lint
10 
11 #include <stdio.h>
12 #include <signal.h>
13 #include <sys/param.h>
14 
15 #define	tst(a,b)	(*mode == 'r'? (b) : (a))
16 #define	RDR	0
17 #define	WTR	1
18 
19 extern	char *malloc();
20 
21 static	int *popen_pid;
22 static	int nfiles;
23 
24 FILE *
25 popen(cmd,mode)
26 	char *cmd;
27 	char *mode;
28 {
29 	int p[2];
30 	int myside, hisside, pid;
31 
32 	if (nfiles <= 0)
33 		nfiles = getdtablesize();
34 	if (popen_pid == NULL) {
35 		popen_pid = (int *)malloc(nfiles * sizeof *popen_pid);
36 		if (popen_pid == NULL)
37 			return (NULL);
38 		for (pid = 0; pid < nfiles; pid++)
39 			popen_pid[pid] = -1;
40 	}
41 	if (pipe(p) < 0)
42 		return (NULL);
43 	myside = tst(p[WTR], p[RDR]);
44 	hisside = tst(p[RDR], p[WTR]);
45 	if ((pid = vfork()) == 0) {
46 		/* myside and hisside reverse roles in child */
47 		close(myside);
48 		if (hisside != tst(0, 1)) {
49 			dup2(hisside, tst(0, 1));
50 			close(hisside);
51 		}
52 		execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
53 		_exit(127);
54 	}
55 	if (pid == -1) {
56 		close(myside);
57 		close(hisside);
58 		return (NULL);
59 	}
60 	popen_pid[myside] = pid;
61 	close(hisside);
62 	return (fdopen(myside, mode));
63 }
64 
65 pclose(ptr)
66 	FILE *ptr;
67 {
68 	int child, pid, status, omask;
69 
70 	child = popen_pid[fileno(ptr)];
71 	popen_pid[fileno(ptr)] = -1;
72 	fclose(ptr);
73 	if (child == -1)
74 		return (-1);
75 	omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP));
76 	while ((pid = wait(&status)) != child && pid != -1)
77 		;
78 	(void) sigsetmask(omask);
79 	return (pid == -1 ? -1 : status);
80 }
81