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