1: /*
2: * Copyright (c) 1988 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * This code is derived from software written by Ken Arnold and
6: * published in UNIX Review, Vol. 6, No. 8.
7: *
8: * Redistribution and use in source and binary forms are permitted
9: * provided that the above copyright notice and this paragraph are
10: * duplicated in all such forms and that any documentation,
11: * advertising materials, and other materials related to such
12: * distribution and use acknowledge that the software was developed
13: * by the University of California, Berkeley. The name of the
14: * University may not be used to endorse or promote products derived
15: * from this software without specific prior written permission.
16: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19: *
20: */
21:
22: /* this came out of the ftpd sources; it's been modified to avoid the
23: * globbing stuff since we don't need it. also execvp instead of execv.
24: */
25:
26: #if !defined(lint) && defined(DOSCCS)
27: static char sccsid[] = "@(#)popen.c 5.7.2 (2.11BSD) 1999/08/05";
28: #endif
29:
30: #include "cron.h"
31: #include <errno.h>
32: #include <sys/signal.h>
33:
34: #define WANT_GLOBBING 0
35:
36: /*
37: * Special version of popen which avoids call to shell. This insures noone
38: * may create a pipe to a hidden program as a side effect of a list or dir
39: * command.
40: */
41: static PID_T *pids;
42: static int fds;
43:
44: FILE *
45: cron_popen(program, type)
46: char *program, *type;
47: {
48: register char *cp;
49: FILE *iop;
50: int argc, pdes[2];
51: PID_T pid;
52: char *argv[100];
53: #if WANT_GLOBBING
54: char **pop, *vv[2];
55: int gargc;
56: char *gargv[1000];
57: extern char **glob(), **copyblk();
58: #endif
59:
60: if (*type != 'r' && *type != 'w' || type[1])
61: return(NULL);
62:
63: if (!pids) {
64: if ((fds = getdtablesize()) <= 0)
65: return(NULL);
66: if (!(pids = (PID_T *)malloc((u_int)(fds * sizeof(PID_T)))))
67: return(NULL);
68: bzero((char *)pids, fds * sizeof(PID_T));
69: }
70: if (pipe(pdes) < 0)
71: return(NULL);
72:
73: /* break up string into pieces */
74: for (argc = 0, cp = program;; cp = NULL)
75: if (!(argv[argc++] = strtok(cp, " \t\n")))
76: break;
77:
78: #if WANT_GLOBBING
79: /* glob each piece */
80: gargv[0] = argv[0];
81: for (gargc = argc = 1; argv[argc]; argc++) {
82: if (!(pop = glob(argv[argc]))) { /* globbing failed */
83: vv[0] = argv[argc];
84: vv[1] = NULL;
85: pop = copyblk(vv);
86: }
87: argv[argc] = (char *)pop; /* save to free later */
88: while (*pop && gargc < 1000)
89: gargv[gargc++] = *pop++;
90: }
91: gargv[gargc] = NULL;
92: #endif
93:
94: iop = NULL;
95: switch(pid = vfork()) {
96: case -1: /* error */
97: (void)close(pdes[0]);
98: (void)close(pdes[1]);
99: goto pfree;
100: /* NOTREACHED */
101: case 0: /* child */
102: if (*type == 'r') {
103: if (pdes[1] != 1) {
104: dup2(pdes[1], 1);
105: dup2(pdes[1], 2); /* stderr, too! */
106: (void)close(pdes[1]);
107: }
108: (void)close(pdes[0]);
109: } else {
110: if (pdes[0] != 0) {
111: dup2(pdes[0], 0);
112: (void)close(pdes[0]);
113: }
114: (void)close(pdes[1]);
115: }
116: #if WANT_GLOBBING
117: execvp(gargv[0], gargv);
118: #else
119: execvp(argv[0], argv);
120: #endif
121: _exit(1);
122: }
123: /* parent; assume fdopen can't fail... */
124: if (*type == 'r') {
125: iop = fdopen(pdes[0], type);
126: (void)close(pdes[1]);
127: } else {
128: iop = fdopen(pdes[1], type);
129: (void)close(pdes[0]);
130: }
131: pids[fileno(iop)] = pid;
132:
133: pfree:
134: #if WANT_GLOBBING
135: for (argc = 1; argv[argc] != NULL; argc++) {
136: /* blkfree((char **)argv[argc]); */
137: free((char *)argv[argc]);
138: }
139: #endif
140: return(iop);
141: }
142:
143: int
144: cron_pclose(iop)
145: FILE *iop;
146: {
147: register int fdes;
148: sigset_t omask, nmask;
149: WAIT_T stat_loc;
150: register PID_T pid;
151:
152: /*
153: * pclose returns -1 if stream is not associated with a
154: * `popened' command, or, if already `pclosed'.
155: */
156: if (pids == 0 || pids[fdes = fileno(iop)] == 0)
157: return(-1);
158: (void)fclose(iop);
159: sigemptyset(&nmask);
160: sigaddset(&nmask, SIGINT);
161: sigaddset(&nmask, SIGQUIT);
162: sigaddset(&nmask, SIGHUP);
163: sigprocmask(SIG_BLOCK, &nmask, &omask);
164: do {
165: pid = waitpid(pids[fdes], &stat_loc, NULL);
166: } while (pid == -1 && errno == EINTR);
167: (void)sigprocmask(SIG_SETMASK, &omask, NULL);
168: pids[fdes] = 0;
169: return (pid == -1 ? -1 : WEXITSTATUS(stat_loc));
170: }
Defined functions
Defined variables
fds
defined in line
42; used 3 times
Defined macros