|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: static char sccsid[] = "@(#)popen.c 5.15 (Berkeley) 6/25/90";
22: #endif /* not lint */
23:
24: #include "rcv.h"
25: #include <sys/signal.h>
26: #include <sys/wait.h>
27:
28: #define READ 0
29: #define WRITE 1
30: static int *pid;
31:
32: struct fp {
33: FILE *fp;
34: int pipe;
35: struct fp *link;
36: };
37: static struct fp *fp_head;
38:
39: FILE *
40: Fopen(file, mode)
41: char *file, *mode;
42: {
43: FILE *fp;
44:
45: if ((fp = fopen(file, mode)) != NULL)
46: register_file(fp, 0);
47: return fp;
48: }
49:
50: FILE *
51: Fdopen(fd, mode)
52: char *mode;
53: {
54: FILE *fp;
55:
56: if ((fp = fdopen(fd, mode)) != NULL)
57: register_file(fp, 0);
58: return fp;
59: }
60:
61: Fclose(fp)
62: FILE *fp;
63: {
64: unregister_file(fp);
65: return fclose(fp);
66: }
67:
68: FILE *
69: Popen(cmd, mode)
70: char *cmd;
71: char *mode;
72: {
73: int p[2];
74: int myside, hisside, fd0, fd1;
75: FILE *fp;
76:
77: if (pid == 0)
78: pid = (int *) malloc((unsigned) sizeof (int) * getdtablesize());
79: if (pipe(p) < 0)
80: return NULL;
81: if (*mode == 'r') {
82: myside = p[READ];
83: fd0 = -1;
84: hisside = fd1 = p[WRITE];
85: } else {
86: myside = p[WRITE];
87: hisside = fd0 = p[READ];
88: fd1 = -1;
89: }
90: if ((pid[myside] = start_command(cmd, 0, fd0, fd1, NOSTR)) < 0) {
91: close(p[READ]);
92: close(p[WRITE]);
93: return NULL;
94: }
95: (void) close(hisside);
96: if ((fp = fdopen(myside, mode)) != NULL)
97: register_file(fp, 1);
98: return fp;
99: }
100:
101: Pclose(ptr)
102: FILE *ptr;
103: {
104: int i;
105: int omask;
106:
107: i = fileno(ptr);
108: unregister_file(ptr);
109: (void) fclose(ptr);
110: omask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP));
111: i = wait_child(pid[i]);
112: sigsetmask(omask);
113: return i;
114: }
115:
116: close_all_files()
117: {
118:
119: while (fp_head)
120: if (fp_head->pipe)
121: (void) Pclose(fp_head->fp);
122: else
123: (void) Fclose(fp_head->fp);
124: }
125:
126: register_file(fp, pipe)
127: FILE *fp;
128: {
129: struct fp *fpp;
130:
131: if ((fpp = (struct fp *) malloc(sizeof *fpp)) == NULL)
132: panic("Out of memory");
133: fpp->fp = fp;
134: fpp->pipe = pipe;
135: fpp->link = fp_head;
136: fp_head = fpp;
137: }
138:
139: unregister_file(fp)
140: FILE *fp;
141: {
142: struct fp **pp, *p;
143:
144: for (pp = &fp_head; p = *pp; pp = &p->link)
145: if (p->fp == fp) {
146: *pp = p->link;
147: free((char *) p);
148: return;
149: }
150: /* XXX
151: * Ignore this for now; there may still be uncaught
152: * duplicate closes.
153: panic("Invalid file pointer");
154: */
155: }
156:
157: /*
158: * Run a command without a shell, with optional arguments and splicing
159: * of stdin and stdout. The command name can be a sequence of words.
160: * Signals must be handled by the caller.
161: * "Mask" contains the signals to ignore in the new process.
162: * SIGINT is enabled unless it's in the mask.
163: */
164: /*VARARGS4*/
165: run_command(cmd, mask, infd, outfd, a0, a1, a2)
166: char *cmd;
167: int mask, infd, outfd;
168: char *a0, *a1, *a2;
169: {
170: int pid;
171:
172: if ((pid = start_command(cmd, mask, infd, outfd, a0, a1, a2)) < 0)
173: return -1;
174: return wait_command(pid);
175: }
176:
177: /*VARARGS4*/
178: start_command(cmd, mask, infd, outfd, a0, a1, a2)
179: char *cmd;
180: int mask, infd, outfd;
181: char *a0, *a1, *a2;
182: {
183: int pid;
184:
185: if ((pid = vfork()) < 0) {
186: perror("fork");
187: return -1;
188: }
189: if (pid == 0) {
190: char *argv[100];
191: int i = getrawlist(cmd, argv, sizeof argv / sizeof *argv);
192:
193: if ((argv[i++] = a0) != NOSTR &&
194: (argv[i++] = a1) != NOSTR &&
195: (argv[i++] = a2) != NOSTR)
196: argv[i] = NOSTR;
197: prepare_child(mask, infd, outfd);
198: execvp(argv[0], argv);
199: perror(argv[0]);
200: _exit(1);
201: }
202: return pid;
203: }
204:
205: prepare_child(mask, infd, outfd)
206: int mask, infd, outfd;
207: {
208: int i;
209:
210: if (infd >= 0)
211: dup2(infd, 0);
212: if (outfd >= 0)
213: dup2(outfd, 1);
214: for (i = getdtablesize(); --i > 2;)
215: close(i);
216: for (i = 1; i <= NSIG; i++)
217: if (mask & sigmask(i))
218: (void) signal(i, SIG_IGN);
219: if ((mask & sigmask(SIGINT)) == 0)
220: (void) signal(SIGINT, SIG_DFL);
221: (void) sigsetmask(0);
222: }
223:
224: wait_command(pid)
225: int pid;
226: {
227:
228: if (wait_child(pid) < 0) {
229: printf("Fatal error in process.\n");
230: return -1;
231: }
232: return 0;
233: }
234:
235: struct child {
236: int pid;
237: char done;
238: char free;
239: union wait status;
240: struct child *link;
241: };
242: static struct child *child;
243:
244: struct child *
245: findchild(pid)
246: int pid;
247: {
248: register struct child **cpp;
249:
250: for (cpp = &child; *cpp != NULL && (*cpp)->pid != pid;
251: cpp = &(*cpp)->link)
252: ;
253: if (*cpp == NULL) {
254: *cpp = (struct child *) malloc(sizeof (struct child));
255: (*cpp)->pid = pid;
256: (*cpp)->done = (*cpp)->free = 0;
257: (*cpp)->link = NULL;
258: }
259: return *cpp;
260: }
261:
262: delchild(cp)
263: register struct child *cp;
264: {
265: register struct child **cpp;
266:
267: for (cpp = &child; *cpp != cp; cpp = &(*cpp)->link)
268: ;
269: *cpp = cp->link;
270: free((char *) cp);
271: }
272:
273: sigchild()
274: {
275: int pid;
276: union wait status;
277: register struct child *cp;
278:
279: while ((pid = wait3(&status, WNOHANG, (struct timeval *)0)) > 0) {
280: cp = findchild(pid);
281: if (cp->free)
282: delchild(cp);
283: else {
284: cp->done = 1;
285: cp->status = status;
286: }
287: }
288: }
289:
290: union wait wait_status;
291:
292: /*
293: * Wait for a specific child to die.
294: */
295: wait_child(pid)
296: int pid;
297: {
298: int mask = sigblock(sigmask(SIGCHLD));
299: register struct child *cp = findchild(pid);
300:
301: while (!cp->done)
302: sigpause(mask);
303: wait_status = cp->status;
304: delchild(cp);
305: sigsetmask(mask);
306: return wait_status.w_status ? -1 : 0;
307: }
308:
309: /*
310: * Mark a child as don't care.
311: */
312: free_child(pid)
313: int pid;
314: {
315: int mask = sigblock(sigmask(SIGCHLD));
316: register struct child *cp = findchild(pid);
317:
318: if (cp->done)
319: delchild(cp);
320: else
321: cp->free = 1;
322: sigsetmask(mask);
323: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.