summaryrefslogtreecommitdiffstats
path: root/plugins/popen.c
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/popen.c')
-rw-r--r--plugins/popen.c69
1 files changed, 45 insertions, 24 deletions
diff --git a/plugins/popen.c b/plugins/popen.c
index 2b9824bc..c596d1e0 100644
--- a/plugins/popen.c
+++ b/plugins/popen.c
@@ -40,7 +40,6 @@
40 40
41#include "./common.h" 41#include "./common.h"
42#include "./utils.h" 42#include "./utils.h"
43#include "../lib/maxfd.h"
44 43
45/* extern so plugin has pid to kill exec'd process on timeouts */ 44/* extern so plugin has pid to kill exec'd process on timeouts */
46extern pid_t *childpid; 45extern pid_t *childpid;
@@ -69,7 +68,7 @@ void popen_timeout_alarm_handler(int /*signo*/);
69#endif 68#endif
70 69
71#ifndef WIFEXITED 70#ifndef WIFEXITED
72# define WIFEXITED(stat_val) (((stat_val)&255) == 0) 71# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
73#endif 72#endif
74 73
75/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */ 74/* 4.3BSD Reno <signal.h> doesn't define SIG_ERR */
@@ -97,24 +96,28 @@ FILE *spopen(const char *cmdstring) {
97 env[1] = NULL; 96 env[1] = NULL;
98 97
99 /* if no command was passed, return with no error */ 98 /* if no command was passed, return with no error */
100 if (cmdstring == NULL) 99 if (cmdstring == NULL) {
101 return (NULL); 100 return (NULL);
101 }
102 102
103 char *cmd = NULL; 103 char *cmd = NULL;
104 /* make copy of command string so strtok() doesn't silently modify it */ 104 /* make copy of command string so strtok() doesn't silently modify it */
105 /* (the calling program may want to access it later) */ 105 /* (the calling program may want to access it later) */
106 cmd = malloc(strlen(cmdstring) + 1); 106 cmd = malloc(strlen(cmdstring) + 1);
107 if (cmd == NULL) 107 if (cmd == NULL) {
108 return NULL; 108 return NULL;
109 }
109 strcpy(cmd, cmdstring); 110 strcpy(cmd, cmdstring);
110 111
111 /* This is not a shell, so we don't handle "???" */ 112 /* This is not a shell, so we don't handle "???" */
112 if (strstr(cmdstring, "\"")) 113 if (strstr(cmdstring, "\"")) {
113 return NULL; 114 return NULL;
115 }
114 116
115 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */ 117 /* allow single quotes, but only if non-whitesapce doesn't occur on both sides */
116 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''")) 118 if (strstr(cmdstring, " ' ") || strstr(cmdstring, "'''")) {
117 return NULL; 119 return NULL;
120 }
118 121
119 int argc; 122 int argc;
120 char **argv = NULL; 123 char **argv = NULL;
@@ -141,15 +144,17 @@ FILE *spopen(const char *cmdstring) {
141 144
142 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */ 145 if (strstr(str, "'") == str) { /* handle SIMPLE quoted strings */
143 str++; 146 str++;
144 if (!strstr(str, "'")) 147 if (!strstr(str, "'")) {
145 return NULL; /* balanced? */ 148 return NULL; /* balanced? */
149 }
146 cmd = 1 + strstr(str, "'"); 150 cmd = 1 + strstr(str, "'");
147 str[strcspn(str, "'")] = 0; 151 str[strcspn(str, "'")] = 0;
148 } else if (strcspn(str, "'") < strcspn(str, " \t\r\n")) { 152 } else if (strcspn(str, "'") < strcspn(str, " \t\r\n")) {
149 /* handle --option='foo bar' strings */ 153 /* handle --option='foo bar' strings */
150 char *tmp = str + strcspn(str, "'") + 1; 154 char *tmp = str + strcspn(str, "'") + 1;
151 if (!strstr(tmp, "'")) 155 if (!strstr(tmp, "'")) {
152 return NULL; /* balanced? */ 156 return NULL; /* balanced? */
157 }
153 tmp += strcspn(tmp, "'") + 1; 158 tmp += strcspn(tmp, "'") + 1;
154 *tmp = 0; 159 *tmp = 0;
155 cmd = tmp + 1; 160 cmd = tmp + 1;
@@ -162,8 +167,9 @@ FILE *spopen(const char *cmdstring) {
162 } 167 }
163 } 168 }
164 169
165 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n")) 170 if (cmd && strlen(cmd) == strspn(cmd, " \t\r\n")) {
166 cmd = NULL; 171 cmd = NULL;
172 }
167 173
168 argv[i++] = str; 174 argv[i++] = str;
169 } 175 }
@@ -172,22 +178,26 @@ FILE *spopen(const char *cmdstring) {
172 long maxfd = mp_open_max(); 178 long maxfd = mp_open_max();
173 179
174 if (childpid == NULL) { /* first time through */ 180 if (childpid == NULL) { /* first time through */
175 if ((childpid = calloc((size_t)maxfd, sizeof(pid_t))) == NULL) 181 if ((childpid = calloc((size_t)maxfd, sizeof(pid_t))) == NULL) {
176 return (NULL); 182 return (NULL);
183 }
177 } 184 }
178 185
179 if (child_stderr_array == NULL) { /* first time through */ 186 if (child_stderr_array == NULL) { /* first time through */
180 if ((child_stderr_array = calloc((size_t)maxfd, sizeof(int))) == NULL) 187 if ((child_stderr_array = calloc((size_t)maxfd, sizeof(int))) == NULL) {
181 return (NULL); 188 return (NULL);
189 }
182 } 190 }
183 191
184 int pfd[2]; 192 int pfd[2];
185 if (pipe(pfd) < 0) 193 if (pipe(pfd) < 0) {
186 return (NULL); /* errno set by pipe() */ 194 return (NULL); /* errno set by pipe() */
195 }
187 196
188 int pfderr[2]; 197 int pfderr[2];
189 if (pipe(pfderr) < 0) 198 if (pipe(pfderr) < 0) {
190 return (NULL); /* errno set by pipe() */ 199 return (NULL); /* errno set by pipe() */
200 }
191 201
192#ifdef REDHAT_SPOPEN_ERROR 202#ifdef REDHAT_SPOPEN_ERROR
193 if (signal(SIGCHLD, popen_sigchld_handler) == SIG_ERR) { 203 if (signal(SIGCHLD, popen_sigchld_handler) == SIG_ERR) {
@@ -196,8 +206,9 @@ FILE *spopen(const char *cmdstring) {
196#endif 206#endif
197 207
198 pid_t pid; 208 pid_t pid;
199 if ((pid = fork()) < 0) 209 if ((pid = fork()) < 0) {
200 return (NULL); /* errno set by fork() */ 210 return (NULL); /* errno set by fork() */
211 }
201 212
202 if (pid == 0) { /* child */ 213 if (pid == 0) { /* child */
203 close(pfd[0]); 214 close(pfd[0]);
@@ -211,17 +222,20 @@ FILE *spopen(const char *cmdstring) {
211 close(pfderr[1]); 222 close(pfderr[1]);
212 } 223 }
213 /* close all descriptors in childpid[] */ 224 /* close all descriptors in childpid[] */
214 for (i = 0; i < maxfd; i++) 225 for (i = 0; i < maxfd; i++) {
215 if (childpid[i] > 0) 226 if (childpid[i] > 0) {
216 close(i); 227 close(i);
228 }
229 }
217 230
218 execve(argv[0], argv, env); 231 execve(argv[0], argv, env);
219 _exit(0); 232 _exit(0);
220 } 233 }
221 234
222 close(pfd[1]); /* parent */ 235 close(pfd[1]); /* parent */
223 if ((child_process = fdopen(pfd[0], "r")) == NULL) 236 if ((child_process = fdopen(pfd[0], "r")) == NULL) {
224 return (NULL); 237 return (NULL);
238 }
225 close(pfderr[1]); 239 close(pfderr[1]);
226 240
227 childpid[fileno(child_process)] = pid; /* remember child pid for this fd */ 241 childpid[fileno(child_process)] = pid; /* remember child pid for this fd */
@@ -230,17 +244,20 @@ FILE *spopen(const char *cmdstring) {
230} 244}
231 245
232int spclose(FILE *fp) { 246int spclose(FILE *fp) {
233 if (childpid == NULL) 247 if (childpid == NULL) {
234 return (1); /* popen() has never been called */ 248 return (1); /* popen() has never been called */
249 }
235 250
236 pid_t pid; 251 pid_t pid;
237 int fd = fileno(fp); 252 int fd = fileno(fp);
238 if ((pid = childpid[fd]) == 0) 253 if ((pid = childpid[fd]) == 0) {
239 return (1); /* fp wasn't opened by popen() */ 254 return (1); /* fp wasn't opened by popen() */
255 }
240 256
241 childpid[fd] = 0; 257 childpid[fd] = 0;
242 if (fclose(fp) == EOF) 258 if (fclose(fp) == EOF) {
243 return (1); 259 return (1);
260 }
244 261
245#ifdef REDHAT_SPOPEN_ERROR 262#ifdef REDHAT_SPOPEN_ERROR
246 while (!childtermd) 263 while (!childtermd)
@@ -248,20 +265,24 @@ int spclose(FILE *fp) {
248#endif 265#endif
249 266
250 int status; 267 int status;
251 while (waitpid(pid, &status, 0) < 0) 268 while (waitpid(pid, &status, 0) < 0) {
252 if (errno != EINTR) 269 if (errno != EINTR) {
253 return (1); /* error other than EINTR from waitpid() */ 270 return (1); /* error other than EINTR from waitpid() */
271 }
272 }
254 273
255 if (WIFEXITED(status)) 274 if (WIFEXITED(status)) {
256 return (WEXITSTATUS(status)); /* return child's termination status */ 275 return (WEXITSTATUS(status)); /* return child's termination status */
276 }
257 277
258 return (1); 278 return (1);
259} 279}
260 280
261#ifdef REDHAT_SPOPEN_ERROR 281#ifdef REDHAT_SPOPEN_ERROR
262void popen_sigchld_handler(int signo) { 282void popen_sigchld_handler(int signo) {
263 if (signo == SIGCHLD) 283 if (signo == SIGCHLD) {
264 childtermd = 1; 284 childtermd = 1;
285 }
265} 286}
266#endif 287#endif
267 288