Commit | Line | Data |
---|---|---|
b8f253e8 KM |
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 | ||
2ce81398 | 7 | #if defined(LIBC_SCCS) && !defined(lint) |
806a9faf | 8 | static char sccsid[] = "@(#)popen.c 5.4 (Berkeley) %G%"; |
2ce81398 | 9 | #endif LIBC_SCCS and not lint |
99756664 | 10 | |
01a56307 BJ |
11 | #include <stdio.h> |
12 | #include <signal.h> | |
99756664 | 13 | |
01a56307 BJ |
14 | #define tst(a,b) (*mode == 'r'? (b) : (a)) |
15 | #define RDR 0 | |
16 | #define WTR 1 | |
99756664 | 17 | |
fec6f225 S |
18 | extern char *malloc(); |
19 | ||
20 | static int *popen_pid; | |
21 | static int nfiles; | |
01a56307 BJ |
22 | |
23 | FILE * | |
24 | popen(cmd,mode) | |
99756664 SL |
25 | char *cmd; |
26 | char *mode; | |
01a56307 BJ |
27 | { |
28 | int p[2]; | |
99756664 | 29 | int myside, hisside, pid; |
01a56307 | 30 | |
fec6f225 S |
31 | if (nfiles <= 0) |
32 | nfiles = getdtablesize(); | |
33 | if (popen_pid == NULL) { | |
34 | popen_pid = (int *)malloc(nfiles * sizeof *popen_pid); | |
35 | if (popen_pid == NULL) | |
36 | return (NULL); | |
37 | for (pid = 0; pid < nfiles; pid++) | |
38 | popen_pid[pid] = -1; | |
39 | } | |
99756664 SL |
40 | if (pipe(p) < 0) |
41 | return (NULL); | |
01a56307 BJ |
42 | myside = tst(p[WTR], p[RDR]); |
43 | hisside = tst(p[RDR], p[WTR]); | |
fec6f225 | 44 | if ((pid = vfork()) == 0) { |
01a56307 BJ |
45 | /* myside and hisside reverse roles in child */ |
46 | close(myside); | |
482b978e SL |
47 | if (hisside != tst(0, 1)) { |
48 | dup2(hisside, tst(0, 1)); | |
49 | close(hisside); | |
50 | } | |
fec6f225 S |
51 | execl("/bin/sh", "sh", "-c", cmd, (char *)NULL); |
52 | _exit(127); | |
01a56307 | 53 | } |
99756664 | 54 | if (pid == -1) { |
2337e291 MK |
55 | close(myside); |
56 | close(hisside); | |
99756664 | 57 | return (NULL); |
2337e291 | 58 | } |
01a56307 BJ |
59 | popen_pid[myside] = pid; |
60 | close(hisside); | |
99756664 | 61 | return (fdopen(myside, mode)); |
01a56307 BJ |
62 | } |
63 | ||
64 | pclose(ptr) | |
99756664 | 65 | FILE *ptr; |
01a56307 | 66 | { |
99756664 | 67 | int child, pid, status, omask; |
01a56307 | 68 | |
99756664 | 69 | child = popen_pid[fileno(ptr)]; |
fec6f225 | 70 | popen_pid[fileno(ptr)] = -1; |
01a56307 | 71 | fclose(ptr); |
fec6f225 S |
72 | if (child == -1) |
73 | return (-1); | |
74 | omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); | |
99756664 | 75 | while ((pid = wait(&status)) != child && pid != -1) |
01a56307 | 76 | ; |
99756664 SL |
77 | (void) sigsetmask(omask); |
78 | return (pid == -1 ? -1 : status); | |
01a56307 | 79 | } |