|
|
1.1 root 1: /*
2: * Standard I/O library
3: * Make streams to or from a process.
4: *
5: * Modified for use with the COHERENT mail system.
6: * This version of popen closes all file descriptors
7: * above 2 (stderr) in the child process.
8: */
9:
10: #include <stdio.h>
11: #include <signal.h>
12:
13: #define R 0 /* Pipe read descriptor index */
14: #define W 1 /* Pipe write descriptor index */
15:
16: void close_fds();
17:
18: static int poppid[_NFILE];
19:
20: FILE *
21: popen(command, type)
22: char *command, *type;
23: {
24: register mode;
25: register fd;
26: int pd[2];
27:
28: if (pipe(pd) < 0)
29: return (NULL);
30: if (*type == 'w') {
31: mode = W;
32: fd = pd[W];
33: } else {
34: mode = R;
35: fd = pd[R];
36: }
37: if ((poppid[fd] = fork()) < 0) {
38: close(pd[R]);
39: close(pd[W]);
40: return (NULL);
41: }
42: if (poppid[fd] == 0) { /* Child */
43: if (mode == W) {
44: close(pd[W]);
45: close(fileno(stdin));
46: dup(pd[R]);
47: close(pd[R]);
48: } else {
49: close(pd[R]);
50: close(fileno(stdout));
51: dup(pd[W]);
52: close(pd[W]);
53: }
54:
55: /* Clean up any file descriptors which may be laying around. */
56: close_fds();
57:
58: execl("/bin/sh", "sh", "-c", command, NULL);
59: exit(1);
60: }
61: if (mode == W) {
62: close(pd[R]);
63: return (fdopen(pd[W], "w"));
64: } else {
65: close(pd[W]);
66: return (fdopen(pd[R], "r"));
67: }
68: }
69:
70: pclose(stream)
71: FILE *stream;
72: {
73: register fd;
74: register pid, wpid;
75: int status;
76: int (*hupfun)(), (*intfun)(), (*quitfun)();
77:
78: fd = fileno(stream);
79: pid = poppid[fd];
80: poppid[fd] = 0;
81: if (pid==0 || fclose(stream)==EOF)
82: return (-1);
83: hupfun = signal(SIGHUP, SIG_IGN);
84: intfun = signal(SIGINT, SIG_IGN);
85: quitfun = signal(SIGQUIT, SIG_IGN);
86: while ((wpid = wait(&status))!=pid && wpid>=0)
87: ;
88: if (wpid < 0)
89: status = -1;
90: signal(SIGHUP, hupfun);
91: signal(SIGINT, intfun);
92: signal(SIGQUIT, quitfun);
93: return (status);
94: }
95:
96: /* Close all file descriptors above 2 (stderr). */
97: void
98: close_fds()
99: {
100: int fd;
101: for (fd = fileno(stderr) + 1; fd <= _NFILE; ++fd) {
102: (void) close(fd);
103: } /* for fd = stderr to number_of_file_descriptors */
104: } /* close_fds() */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.