xref: /csrg-svn/lib/libc/gen/popen.c (revision 35451)
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 published
6  * in UNIX Review, Vol. 6, No. 8.
7  *
8  * Redistribution and use in source and binary forms are permitted
9  * provided that the above copyright notice and this paragraph are
10  * duplicated in all such forms and that any documentation,
11  * advertising materials, and other materials related to such
12  * distribution and use acknowledge that the software was developed
13  * by the University of California, Berkeley.  The name of the
14  * University may not be used to endorse or promote products derived
15  * from this software without specific prior written permission.
16  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19  */
20 
21 #if defined(LIBC_SCCS) && !defined(lint)
22 static char sccsid[] = "@(#)popen.c	5.6 (Berkeley) 08/31/88";
23 #endif /* LIBC_SCCS and not lint */
24 
25 #include <stdio.h>
26 
27 #define	MAXFILES	32
28 
29 typedef struct {
30 	int pid;
31 	int status;
32 } PID_STRUCT;
33 
34 PID_STRUCT pids[MAXFILES];
35 
36 FILE *
37 popen(program, type)
38 char *program, *type;
39 {
40 	char **argv;
41 	int pdes[2], pid;
42 	FILE *iop;
43 
44 	if (*type != 'r' && *type != 'w')
45 		return NULL;
46 	if (pipe(pdes) < 0)
47 		return NULL;
48 	switch(pid = fork()) {
49 	case -1:
50 		iop = NULL;
51 		break;
52 	case 0:			/* child */
53 		if (*type == 'r') {
54 			close(1);
55 			dup(pdes[1]);
56 		}
57 		else {
58 			close(0);
59 			dup(pdes[0]);
60 		}
61 		close(pdes[1]);
62 		close(pdes[0]);
63 		execl("/bin/sh", "sh", "-c", program, NULL);
64 		exit(-1);
65 		/* NOTREACHED */
66 	default:
67 		if (*type == 'r') {
68 			iop = fdopen(pdes[0], "r");
69 			close(pdes[1]);
70 		} else {
71 			iop = fdopen(pdes[0], "w");
72 			close(pdes[0]);
73 		}
74 		break;
75 	}
76 	if (iop != NULL)
77 		pids[fileno(iop)].pid = pid;
78 	else {
79 		close(pdes[0]);
80 		close(pdes[1]);
81 	}
82 	return iop;
83 }
84 
85 pclose(iop)
86 FILE *iop;
87 {
88 	int status;
89 	int pid, fdes, i;
90 
91 	fdes = fileno(iop);
92 	fclose(iop);
93 	if (pids[fdes].pid == 0)
94 		return pids[fdes].status;
95 	for (;;) {
96 		pid = wait(&status);
97 		if (pid < 0)
98 			return -1;
99 		if (pid == pids[fdes].pid) {
100 			pids[fdes].pid = 0;
101 			return status;
102 		}
103 		for (i = 0; i < MAXFILES; i++)
104 			if (pids[i].pid == pid) {
105 				pids[i].pid = 0;
106 				pids[i].status = status;
107 				break;
108 			}
109 	}
110 }
111