2 * bpipe.c bi-directional pipe
4 * Kern Sibbald, November MMII
9 Copyright (C) 2002-2006 Kern Sibbald
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 version 2 as amended with additional clauses defined in the
14 file LICENSE in the main source directory.
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 the file LICENSE for additional details.
27 int execvp_errors[] = {
40 int num_execvp_errors = (int)(sizeof(execvp_errors)/sizeof(int));
44 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_arg);
47 * Run an external program. Optionally wait a specified number
48 * of seconds. Program killed if wait exceeded. We open
49 * a bi-directional pipe so that the user can read from and
50 * write to the program.
52 BPIPE *open_bpipe(char *prog, int wait, const char *mode)
54 char *bargv[MAX_ARGV];
56 int readp[2], writep[2];
58 int mode_read, mode_write;
62 bpipe = (BPIPE *)malloc(sizeof(BPIPE));
63 memset(bpipe, 0, sizeof(BPIPE));
64 mode_read = (mode[0] == 'r');
65 mode_write = (mode[0] == 'w' || mode[1] == 'w');
66 /* Build arguments for running program. */
67 tprog = get_pool_memory(PM_FNAME);
68 pm_strcpy(tprog, prog);
69 build_argc_argv(tprog, &bargc, bargv, MAX_ARGV);
71 printf("argc=%d\n", bargc);
72 for (i=0; i<bargc; i++) {
73 printf("argc=%d argv=%s:\n", i, bargv[i]);
77 /* Each pipe is one way, write one end, read the other, so we need two */
78 if (mode_write && pipe(writep) == -1) {
82 free_pool_memory(tprog);
85 if (mode_read && pipe(readp) == -1) {
93 free_pool_memory(tprog);
96 /* Start worker process */
97 switch (bpipe->worker_pid = fork()) {
110 free_pool_memory(tprog);
116 dup2(writep[0], 0); /* Dup our write to his stdin */
119 close(readp[0]); /* Close unused child fds */
120 dup2(readp[1], 1); /* dup our read to his stdout */
121 dup2(readp[1], 2); /* and his stderr */
123 closelog(); /* close syslog if open */
124 for (i=3; i<=32; i++) { /* close any open file descriptors */
127 execvp(bargv[0], bargv); /* call the program */
128 /* Convert errno into an exit code for later analysis */
129 for (i=0; i< num_execvp_errors; i++) {
130 if (execvp_errors[i] == errno) {
131 exit(200 + i); /* exit code => errno */
134 exit(255); /* unknown errno */
136 default: /* parent */
139 free_pool_memory(tprog);
141 close(readp[1]); /* close unused parent fds */
142 bpipe->rfd = fdopen(readp[0], "r"); /* open file descriptor */
146 bpipe->wfd = fdopen(writep[1], "w");
148 bpipe->worker_stime = time(NULL);
151 bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
156 /* Close the write pipe only */
157 int close_wpipe(BPIPE *bpipe)
163 if (fclose(bpipe->wfd) != 0) {
172 * Close both pipes and free resources
174 * Returns: 0 on success
177 int close_bpipe(BPIPE *bpipe)
196 if (bpipe->wait == 0) {
197 wait_option = 0; /* wait indefinitely */
199 wait_option = WNOHANG; /* don't hang */
201 remaining_wait = bpipe->wait;
203 /* wait for worker child to exit */
205 Dmsg2(800, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option);
207 wpid = waitpid(bpipe->worker_pid, &chldstatus, wait_option);
208 } while (wpid == -1 && (errno == EINTR || errno == EAGAIN));
209 if (wpid == bpipe->worker_pid || wpid == -1) {
211 Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
212 wpid==-1?strerror(errno):"none");
215 Dmsg3(800, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
216 wpid==-1?strerror(errno):"none");
217 if (remaining_wait > 0) {
218 bmicrosleep(1, 0); /* wait one second */
221 stat = ETIME; /* set error status */
223 break; /* don't wait any longer */
227 if (WIFEXITED(chldstatus)) { /* process exit()ed */
228 stat = WEXITSTATUS(chldstatus);
230 Dmsg1(800, "Non-zero status %d returned from child.\n", stat);
231 stat |= b_errno_exit; /* exit status returned */
233 Dmsg1(800, "child status=%d\n", stat & ~b_errno_exit);
234 } else if (WIFSIGNALED(chldstatus)) { /* process died */
236 stat = WTERMSIG(chldstatus);
238 #warning "WTERMSIG undefined in Win32 !!!"
240 Dmsg1(800, "Child died from signal %d\n", stat);
241 stat |= b_errno_signal; /* exit signal returned */
244 if (bpipe->timer_id) {
245 stop_child_timer(bpipe->timer_id);
248 Dmsg1(800, "returning stat = %d\n", stat);
254 * Run an external program. Optionally wait a specified number
255 * of seconds. Program killed if wait exceeded. Optionally
256 * return the output from the program (normally a single line).
258 * If the watchdog kills the program, fgets returns, and ferror is set
259 * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
261 * Contrary to my normal calling conventions, this program
263 * Returns: 0 on success
264 * non-zero on error == berrno status
266 int run_program(char *prog, int wait, POOLMEM *results)
272 mode = (char *)(results != NULL ? "r" : "");
273 bpipe = open_bpipe(prog, wait, mode);
279 int len = sizeof_pool_memory(results) - 1;
280 fgets(results, len, bpipe->rfd);
282 if (feof(bpipe->rfd)) {
285 stat1 = ferror(bpipe->rfd);
288 Dmsg2(150, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
289 } else if (stat1 != 0) {
290 Dmsg1(150, "Run program fgets stat=%d\n", stat1);
291 if (bpipe->timer_id) {
292 Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
293 /* NB: I'm not sure it is really useful for run_program. Without the
294 * following lines run_program would not detect if the program was killed
295 * by the watchdog. */
296 if (bpipe->timer_id->killed) {
298 pm_strcat(results, _("Program killed by Bacula watchdog (timeout)\n"));
305 stat2 = close_bpipe(bpipe);
306 stat1 = stat2 != 0 ? stat2 : stat1;
307 Dmsg1(150, "Run program returning %d\n", stat1);
312 * Run an external program. Optionally wait a specified number
313 * of seconds. Program killed if wait exceeded (it is done by the
314 * watchdog, as fgets is a blocking function).
316 * If the watchdog kills the program, fgets returns, and ferror is set
317 * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
319 * Return the full output from the program (not only the first line).
321 * Contrary to my normal calling conventions, this program
323 * Returns: 0 on success
324 * non-zero on error == berrno status
327 int run_program_full_output(char *prog, int wait, POOLMEM *results)
334 const int bufsize = 32000;
336 if (results == NULL) {
337 return run_program(prog, wait, NULL);
340 sm_check(__FILE__, __LINE__, false);
342 tmp = get_pool_memory(PM_MESSAGE);
343 buf = (char *)malloc(bufsize+1);
346 bpipe = open_bpipe(prog, wait, mode);
354 sm_check(__FILE__, __LINE__, false);
358 fgets(buf, bufsize, bpipe->rfd);
361 if (feof(bpipe->rfd)) {
363 Dmsg1(900, "Run program fgets stat=%d\n", stat1);
366 stat1 = ferror(bpipe->rfd);
370 Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.strerror());
372 } else if (stat1 != 0) {
373 Dmsg1(900, "Run program fgets stat=%d\n", stat1);
374 if (bpipe->timer_id) {
375 Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
376 if (bpipe->timer_id->killed) {
377 pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
384 int len = sizeof_pool_memory(results) - 1;
385 bstrncpy(results, tmp, len);
386 Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
387 stat2 = close_bpipe(bpipe);
388 stat1 = stat2 != 0 ? stat2 : stat1;
390 Dmsg1(900, "Run program returning %d\n", stat1);
391 free_pool_memory(tmp);
397 * Build argc and argv from a string
399 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv)
406 for (i=0; i<max_argv; i++)
411 while (*p && (*p == ' ' || *p == '\t'))
413 if (*p == '\"' || *p == '\'') {
418 while (*p && argc < MAX_ARGV) {
421 while (*q && *q != quote)
425 while (*q && *q != ' ')
432 while (*p && (*p == ' ' || *p == '\t'))
434 if (*p == '\"' || *p == '\'') {