add Berkeley specific header; written by Sam Leffler
[unix-history] / usr / src / lib / libc / gen / popen.c
... / ...
CommitLineData
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#if defined(LIBC_SCCS) && !defined(lint)
8static char sccsid[] = "@(#)popen.c 5.5 (Berkeley) %G%";
9#endif LIBC_SCCS and not lint
10
11#include <stdio.h>
12#include <signal.h>
13
14#define tst(a,b) (*mode == 'r'? (b) : (a))
15#define RDR 0
16#define WTR 1
17
18extern char *malloc();
19
20static int *popen_pid;
21static int nfiles;
22
23FILE *
24popen(cmd,mode)
25 char *cmd;
26 char *mode;
27{
28 int p[2];
29 int myside, hisside, pid;
30
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 }
40 if (pipe(p) < 0)
41 return (NULL);
42 myside = tst(p[WTR], p[RDR]);
43 hisside = tst(p[RDR], p[WTR]);
44 if ((pid = vfork()) == 0) {
45 /* myside and hisside reverse roles in child */
46 close(myside);
47 if (hisside != tst(0, 1)) {
48 dup2(hisside, tst(0, 1));
49 close(hisside);
50 }
51 execl("/bin/sh", "sh", "-c", cmd, (char *)NULL);
52 _exit(127);
53 }
54 if (pid == -1) {
55 close(myside);
56 close(hisside);
57 return (NULL);
58 }
59 popen_pid[myside] = pid;
60 close(hisside);
61 return (fdopen(myside, mode));
62}
63
64pclose(ptr)
65 FILE *ptr;
66{
67 long omask;
68 int child, pid, status;
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}