2 * bpipe.c bi-directional pipe
4 * Kern Sibbald, November MMII
9 Bacula® - The Network Backup Solution
11 Copyright (C) 2002-2006 Free Software Foundation Europe e.V.
13 The main author of Bacula is Kern Sibbald, with contributions from
14 many others, a complete list can be found in the file AUTHORS.
15 This program is Free Software; you can redistribute it and/or
16 modify it under the terms of version two of the GNU General Public
17 License as published by the Free Software Foundation plus additions
18 that are listed in the file LICENSE.
20 This program is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program; if not, write to the Free Software
27 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
30 Bacula® is a registered trademark of John Walker.
31 The licensor of Bacula is the Free Software Foundation Europe
32 (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
33 Switzerland, email:ftf@fsfeurope.org.
40 int execvp_errors[] = {
53 int num_execvp_errors = (int)(sizeof(execvp_errors)/sizeof(int));
58 #if !defined(HAVE_WIN32)
59 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_arg);
62 * Run an external program. Optionally wait a specified number
63 * of seconds. Program killed if wait exceeded. We open
64 * a bi-directional pipe so that the user can read from and
65 * write to the program.
67 BPIPE *open_bpipe(char *prog, int wait, const char *mode)
69 char *bargv[MAX_ARGV];
71 int readp[2], writep[2];
73 int mode_read, mode_write;
77 bpipe = (BPIPE *)malloc(sizeof(BPIPE));
78 memset(bpipe, 0, sizeof(BPIPE));
79 mode_read = (mode[0] == 'r');
80 mode_write = (mode[0] == 'w' || mode[1] == 'w');
81 /* Build arguments for running program. */
82 tprog = get_pool_memory(PM_FNAME);
83 pm_strcpy(tprog, prog);
84 build_argc_argv(tprog, &bargc, bargv, MAX_ARGV);
86 printf("argc=%d\n", bargc);
87 for (i=0; i<bargc; i++) {
88 printf("argc=%d argv=%s:\n", i, bargv[i]);
92 /* Each pipe is one way, write one end, read the other, so we need two */
93 if (mode_write && pipe(writep) == -1) {
96 free_pool_memory(tprog);
100 if (mode_read && pipe(readp) == -1) {
107 free_pool_memory(tprog);
111 /* Start worker process */
112 switch (bpipe->worker_pid = fork()) {
124 free_pool_memory(tprog);
131 dup2(writep[0], 0); /* Dup our write to his stdin */
134 close(readp[0]); /* Close unused child fds */
135 dup2(readp[1], 1); /* dup our read to his stdout */
136 dup2(readp[1], 2); /* and his stderr */
138 closelog(); /* close syslog if open */
139 for (i=3; i<=32; i++) { /* close any open file descriptors */
142 execvp(bargv[0], bargv); /* call the program */
143 /* Convert errno into an exit code for later analysis */
144 for (i=0; i< num_execvp_errors; i++) {
145 if (execvp_errors[i] == errno) {
146 exit(200 + i); /* exit code => errno */
149 exit(255); /* unknown errno */
151 default: /* parent */
154 free_pool_memory(tprog);
156 close(readp[1]); /* close unused parent fds */
157 bpipe->rfd = fdopen(readp[0], "r"); /* open file descriptor */
161 bpipe->wfd = fdopen(writep[1], "w");
163 bpipe->worker_stime = time(NULL);
166 bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
171 /* Close the write pipe only */
172 int close_wpipe(BPIPE *bpipe)
178 if (fclose(bpipe->wfd) != 0) {
187 * Close both pipes and free resources
189 * Returns: 0 on success
192 int close_bpipe(BPIPE *bpipe)
211 if (bpipe->wait == 0) {
212 wait_option = 0; /* wait indefinitely */
214 wait_option = WNOHANG; /* don't hang */
216 remaining_wait = bpipe->wait;
218 /* wait for worker child to exit */
220 Dmsg2(800, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option);
222 wpid = waitpid(bpipe->worker_pid, &chldstatus, wait_option);
223 } while (wpid == -1 && (errno == EINTR || errno == EAGAIN));
224 if (wpid == bpipe->worker_pid || wpid == -1) {
226 Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
227 wpid==-1?strerror(errno):"none");
230 Dmsg3(800, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
231 wpid==-1?strerror(errno):"none");
232 if (remaining_wait > 0) {
233 bmicrosleep(1, 0); /* wait one second */
236 stat = ETIME; /* set error status */
238 break; /* don't wait any longer */
242 if (WIFEXITED(chldstatus)) { /* process exit()ed */
243 stat = WEXITSTATUS(chldstatus);
245 Dmsg1(800, "Non-zero status %d returned from child.\n", stat);
246 stat |= b_errno_exit; /* exit status returned */
248 Dmsg1(800, "child status=%d\n", stat & ~b_errno_exit);
249 } else if (WIFSIGNALED(chldstatus)) { /* process died */
251 stat = WTERMSIG(chldstatus);
253 stat = 1; /* fake child status */
255 Dmsg1(800, "Child died from signal %d\n", stat);
256 stat |= b_errno_signal; /* exit signal returned */
259 if (bpipe->timer_id) {
260 stop_child_timer(bpipe->timer_id);
263 Dmsg2(800, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat);
268 * Build argc and argv from a string
270 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv)
277 for (i=0; i<max_argv; i++)
282 while (*p && (*p == ' ' || *p == '\t'))
284 if (*p == '\"' || *p == '\'') {
289 while (*p && argc < MAX_ARGV) {
292 while (*q && *q != quote)
296 while (*q && *q != ' ')
303 while (*p && (*p == ' ' || *p == '\t'))
305 if (*p == '\"' || *p == '\'') {
313 #endif /* HAVE_WIN32 */
316 * Run an external program. Optionally wait a specified number
317 * of seconds. Program killed if wait exceeded. Optionally
318 * return the output from the program (normally a single line).
320 * If the watchdog kills the program, fgets returns, and ferror is set
321 * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
323 * Contrary to my normal calling conventions, this program
325 * Returns: 0 on success
326 * non-zero on error == berrno status
328 int run_program(char *prog, int wait, POOLMEM *results)
334 mode = (char *)(results != NULL ? "r" : "");
335 bpipe = open_bpipe(prog, wait, mode);
341 int len = sizeof_pool_memory(results) - 1;
342 fgets(results, len, bpipe->rfd);
344 if (feof(bpipe->rfd)) {
347 stat1 = ferror(bpipe->rfd);
350 Dmsg2(150, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
351 } else if (stat1 != 0) {
352 Dmsg1(150, "Run program fgets stat=%d\n", stat1);
353 if (bpipe->timer_id) {
354 Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
355 /* NB: I'm not sure it is really useful for run_program. Without the
356 * following lines run_program would not detect if the program was killed
357 * by the watchdog. */
358 if (bpipe->timer_id->killed) {
360 pm_strcat(results, _("Program killed by Bacula watchdog (timeout)\n"));
367 stat2 = close_bpipe(bpipe);
368 stat1 = stat2 != 0 ? stat2 : stat1;
369 Dmsg1(150, "Run program returning %d\n", stat1);
374 * Run an external program. Optionally wait a specified number
375 * of seconds. Program killed if wait exceeded (it is done by the
376 * watchdog, as fgets is a blocking function).
378 * If the watchdog kills the program, fgets returns, and ferror is set
379 * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
381 * Return the full output from the program (not only the first line).
383 * Contrary to my normal calling conventions, this program
385 * Returns: 0 on success
386 * non-zero on error == berrno status
389 int run_program_full_output(char *prog, int wait, POOLMEM *results)
396 const int bufsize = 32000;
398 if (results == NULL) {
399 return run_program(prog, wait, NULL);
402 sm_check(__FILE__, __LINE__, false);
404 tmp = get_pool_memory(PM_MESSAGE);
405 buf = (char *)malloc(bufsize+1);
408 bpipe = open_bpipe(prog, wait, mode);
416 sm_check(__FILE__, __LINE__, false);
420 fgets(buf, bufsize, bpipe->rfd);
423 if (feof(bpipe->rfd)) {
425 Dmsg1(900, "Run program fgets stat=%d\n", stat1);
428 stat1 = ferror(bpipe->rfd);
432 Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.strerror());
434 } else if (stat1 != 0) {
435 Dmsg1(900, "Run program fgets stat=%d\n", stat1);
436 if (bpipe->timer_id && bpipe->timer_id->killed) {
437 Dmsg1(250, "Run program saw fgets killed=%d\n", bpipe->timer_id->killed);
443 * We always check whether the timer killed the program. We would see
444 * an eof even when it does so we just have to trust the killed flag
445 * and set the timer values to avoid edge cases where the program ends
446 * just as the timer kills it.
448 if (bpipe->timer_id && bpipe->timer_id->killed) {
449 Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
450 pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
453 int len = sizeof_pool_memory(results) - 1;
454 bstrncpy(results, tmp, len);
455 Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
456 stat2 = close_bpipe(bpipe);
457 stat1 = stat2 != 0 ? stat2 : stat1;
459 Dmsg1(900, "Run program returning %d\n", stat1);
460 free_pool_memory(tmp);