Pristine Ack-5.5
[Ack-5.5.git] / lang / cem / libcc.ansi / misc / popen.c
1 /*
2  * popen - open a pipe
3  */
4 /* $Id: popen.c,v 1.5 1994/06/24 11:45:35 ceriel Exp $ */
5
6 #include        <errno.h>
7 #include        <stdio.h>
8 #include        <signal.h>
9 #if     defined(__BSD4_2)
10 union wait {
11         int     w_status;
12 };
13 typedef union wait wait_arg;
14 #else
15 typedef int wait_arg;
16 #endif  /* __BSD4_2 */
17 #include        "../stdio/loc_incl.h"
18
19 int _close(int d);
20 #if defined(__USG)
21 static
22 #endif
23 int _dup2(int oldd, int newd);          /* not present in System 5 */
24 int _execl(const char *name, ... );
25 int _fork(void);
26 int _pipe(int fildes[2]);
27 int _wait(wait_arg *status);
28 void _exit(int status);
29
30 static int pids[FOPEN_MAX];
31
32 FILE *
33 popen(const char *command, const char *type)
34 {
35         int piped[2];
36         int Xtype = *type == 'r' ? 0 : *type == 'w' ? 1 : 2;
37         int pid;
38
39         if (Xtype == 2 ||
40             _pipe(piped) < 0 ||
41             (pid = _fork()) < 0) return 0;
42         
43         if (pid == 0) {
44                 /* child */
45                 register int *p;
46
47                 for (p = pids; p < &pids[ FOPEN_MAX]; p++) {
48                         if (*p) _close(p - pids);
49                 }
50                 _close(piped[Xtype]);
51                 _dup2(piped[!Xtype], !Xtype);
52                 _close(piped[!Xtype]);
53                 _execl("/bin/sh", "sh", "-c", command, (char *) 0);
54                 _exit(127);     /* like system() ??? */
55         }
56
57         pids[piped[Xtype]] = pid;
58         _close(piped[!Xtype]);
59         return fdopen(piped[Xtype], type);
60 }
61
62 #if     defined(__BSD4_2)
63 #define ret_val status.w_status
64 #else
65 #define ret_val status
66 #endif
67
68 int
69 pclose(FILE *stream)
70 {
71         int fd = fileno(stream);
72         wait_arg status;
73         int wret;
74         void (*intsave)(int) = signal(SIGINT, SIG_IGN);
75         void (*quitsave)(int) = signal(SIGQUIT, SIG_IGN);
76
77         fclose(stream);
78         while ((wret = _wait(&status)) != -1) {
79                 if (wret == pids[fd]) break;
80         }
81         if (wret == -1) ret_val = -1;
82         signal(SIGINT, intsave);
83         signal(SIGQUIT, quitsave);
84         pids[fd] = 0;
85         return ret_val;
86 }
87
88 #if     defined(__USG)
89 int _dup(int fildes);
90
91 static int
92 _dup2(int oldd, int newd)
93 {
94         int i = 0, fd, tmp;
95         int fdbuf[FOPEN_MAX];
96
97         /* ignore the error on the close() */
98         tmp = errno; (void) _close(newd); errno = tmp;
99         while ((fd = _dup(oldd)) != newd) {
100                 if (fd == -1) break;
101                 fdbuf[i++] = fd;
102         }
103         tmp = errno;
104         while (--i >= 0) {
105                 _close(fdbuf[i]);
106         }
107         errno = tmp;
108         return -(fd == -1);
109 }
110 #endif  /* __USG */