Commit | Line | Data |
---|---|---|
693d8207 GR |
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 | * From Id: popen.c,v 1.5 1994/01/15 20:43:43 vixie Exp | |
21 | */ | |
22 | ||
23 | /* this came out of the ftpd sources; it's been modified to avoid the | |
24 | * globbing stuff since we don't need it. also execvp instead of execv. | |
25 | */ | |
26 | ||
27 | #ifndef lint | |
28 | static char rcsid[] = "$Header: $"; | |
29 | static char sccsid[] = "@(#)popen.c 5.7 (Berkeley) 2/14/89"; | |
30 | #endif /* not lint */ | |
31 | ||
32 | #include "cron.h" | |
33 | #include <sys/signal.h> | |
34 | ||
35 | ||
36 | #define WANT_GLOBBING 0 | |
37 | ||
38 | /* | |
39 | * Special version of popen which avoids call to shell. This insures noone | |
40 | * may create a pipe to a hidden program as a side effect of a list or dir | |
41 | * command. | |
42 | */ | |
43 | static PID_T *pids; | |
44 | static int fds; | |
45 | ||
46 | FILE * | |
47 | cron_popen(program, type) | |
48 | char *program, *type; | |
49 | { | |
50 | register char *cp; | |
51 | FILE *iop; | |
52 | int argc, pdes[2]; | |
53 | PID_T pid; | |
54 | char *argv[100]; | |
55 | #if WANT_GLOBBING | |
56 | char **pop, *vv[2]; | |
57 | int gargc; | |
58 | char *gargv[1000]; | |
59 | extern char **glob(), **copyblk(); | |
60 | #endif | |
61 | ||
62 | if (*type != 'r' && *type != 'w' || type[1]) | |
63 | return(NULL); | |
64 | ||
65 | if (!pids) { | |
66 | if ((fds = getdtablesize()) <= 0) | |
67 | return(NULL); | |
68 | if (!(pids = (PID_T *)malloc((u_int)(fds * sizeof(PID_T))))) | |
69 | return(NULL); | |
70 | bzero((char *)pids, fds * sizeof(PID_T)); | |
71 | } | |
72 | if (pipe(pdes) < 0) | |
73 | return(NULL); | |
74 | ||
75 | /* break up string into pieces */ | |
76 | for (argc = 0, cp = program;; cp = NULL) | |
77 | if (!(argv[argc++] = strtok(cp, " \t\n"))) | |
78 | break; | |
79 | ||
80 | #if WANT_GLOBBING | |
81 | /* glob each piece */ | |
82 | gargv[0] = argv[0]; | |
83 | for (gargc = argc = 1; argv[argc]; argc++) { | |
84 | if (!(pop = glob(argv[argc]))) { /* globbing failed */ | |
85 | vv[0] = argv[argc]; | |
86 | vv[1] = NULL; | |
87 | pop = copyblk(vv); | |
88 | } | |
89 | argv[argc] = (char *)pop; /* save to free later */ | |
90 | while (*pop && gargc < 1000) | |
91 | gargv[gargc++] = *pop++; | |
92 | } | |
93 | gargv[gargc] = NULL; | |
94 | #endif | |
95 | ||
96 | iop = NULL; | |
97 | switch(pid = vfork()) { | |
98 | case -1: /* error */ | |
99 | (void)close(pdes[0]); | |
100 | (void)close(pdes[1]); | |
101 | goto pfree; | |
102 | /* NOTREACHED */ | |
103 | case 0: /* child */ | |
104 | if (*type == 'r') { | |
105 | if (pdes[1] != 1) { | |
106 | dup2(pdes[1], 1); | |
107 | dup2(pdes[1], 2); /* stderr, too! */ | |
108 | (void)close(pdes[1]); | |
109 | } | |
110 | (void)close(pdes[0]); | |
111 | } else { | |
112 | if (pdes[0] != 0) { | |
113 | dup2(pdes[0], 0); | |
114 | (void)close(pdes[0]); | |
115 | } | |
116 | (void)close(pdes[1]); | |
117 | } | |
118 | #if WANT_GLOBBING | |
119 | execvp(gargv[0], gargv); | |
120 | #else | |
121 | execvp(argv[0], argv); | |
122 | #endif | |
123 | _exit(1); | |
124 | } | |
125 | /* parent; assume fdopen can't fail... */ | |
126 | if (*type == 'r') { | |
127 | iop = fdopen(pdes[0], type); | |
128 | (void)close(pdes[1]); | |
129 | } else { | |
130 | iop = fdopen(pdes[1], type); | |
131 | (void)close(pdes[0]); | |
132 | } | |
133 | pids[fileno(iop)] = pid; | |
134 | ||
135 | pfree: | |
136 | #if WANT_GLOBBING | |
137 | for (argc = 1; argv[argc] != NULL; argc++) { | |
138 | /* blkfree((char **)argv[argc]); */ | |
139 | free((char *)argv[argc]); | |
140 | } | |
141 | #endif | |
142 | return(iop); | |
143 | } | |
144 | ||
145 | int | |
146 | cron_pclose(iop) | |
147 | FILE *iop; | |
148 | { | |
149 | register int fdes; | |
150 | int omask; | |
151 | WAIT_T stat_loc; | |
152 | PID_T pid; | |
153 | ||
154 | /* | |
155 | * pclose returns -1 if stream is not associated with a | |
156 | * `popened' command, or, if already `pclosed'. | |
157 | */ | |
158 | if (pids == 0 || pids[fdes = fileno(iop)] == 0) | |
159 | return(-1); | |
160 | (void)fclose(iop); | |
161 | omask = sigblock(sigmask(SIGINT)|sigmask(SIGQUIT)|sigmask(SIGHUP)); | |
162 | while ((pid = wait(&stat_loc)) != pids[fdes] && pid != -1) | |
163 | ; | |
164 | (void)sigsetmask(omask); | |
165 | pids[fdes] = 0; | |
166 | return (pid == -1 ? -1 : WEXITSTATUS(stat_loc)); | |
167 | } |