BSD 4_3 release
[unix-history] / usr / src / lib / libc / gen / popen.c
CommitLineData
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)
95f51977 8static char sccsid[] = "@(#)popen.c 5.4 (Berkeley) 3/26/86";
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
18extern char *malloc();
19
20static int *popen_pid;
21static int nfiles;
01a56307
BJ
22
23FILE *
24popen(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
64pclose(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}