2 * bpipe.c bi-directional pipe
4 * Kern Sibbald, November MMII
9 Copyright (C) 2002-2005 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[] = {EACCES, ENOEXEC, EFAULT, EINTR, E2BIG,
28 ENAMETOOLONG, ENOMEM, ETXTBSY, ENOENT};
29 int num_execvp_errors = (int)(sizeof(execvp_errors)/sizeof(int));
33 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_arg);
36 * Run an external program. Optionally wait a specified number
37 * of seconds. Program killed if wait exceeded. We open
38 * a bi-directional pipe so that the user can read from and
39 * write to the program.
41 BPIPE *open_bpipe(char *prog, int wait, const char *mode)
43 char *bargv[MAX_ARGV];
45 int readp[2], writep[2];
47 int mode_read, mode_write;
51 bpipe = (BPIPE *)malloc(sizeof(BPIPE));
52 memset(bpipe, 0, sizeof(BPIPE));
53 mode_read = (mode[0] == 'r');
54 mode_write = (mode[0] == 'w' || mode[1] == 'w');
55 /* Build arguments for running program. */
56 tprog = get_pool_memory(PM_FNAME);
57 pm_strcpy(tprog, prog);
58 build_argc_argv(tprog, &bargc, bargv, MAX_ARGV);
60 printf("argc=%d\n", bargc);
61 for (i=0; i<bargc; i++) {
62 printf("argc=%d argv=%s:\n", i, bargv[i]);
65 free_pool_memory(tprog);
67 /* Each pipe is one way, write one end, read the other, so we need two */
68 if (mode_write && pipe(writep) == -1) {
74 if (mode_read && pipe(readp) == -1) {
84 /* Start worker process */
85 switch (bpipe->worker_pid = fork()) {
103 dup2(writep[0], 0); /* Dup our write to his stdin */
106 close(readp[0]); /* Close unused child fds */
107 dup2(readp[1], 1); /* dup our read to his stdout */
108 dup2(readp[1], 2); /* and his stderr */
110 closelog(); /* close syslog if open */
111 for (i=3; i<=32; i++) { /* close any open file descriptors */
114 execvp(bargv[0], bargv); /* call the program */
115 /* Convert errno into an exit code for later analysis */
116 for (i=0; i< num_execvp_errors; i++) {
117 if (execvp_errors[i] == errno) {
118 exit(200 + i); /* exit code => errno */
121 exit(255); /* unknown errno */
125 default: /* parent */
129 close(readp[1]); /* close unused parent fds */
130 bpipe->rfd = fdopen(readp[0], "r"); /* open file descriptor */
134 bpipe->wfd = fdopen(writep[1], "w");
136 bpipe->worker_stime = time(NULL);
139 bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
144 /* Close the write pipe only */
145 int close_wpipe(BPIPE *bpipe)
151 if (fclose(bpipe->wfd) != 0) {
160 * Close both pipes and free resources
162 * Returns: 0 on success
165 int close_bpipe(BPIPE *bpipe)
184 if (bpipe->wait == 0) {
185 wait_option = 0; /* wait indefinitely */
187 wait_option = WNOHANG; /* don't hang */
189 remaining_wait = bpipe->wait;
191 /* wait for worker child to exit */
193 Dmsg2(800, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option);
195 wpid = waitpid(bpipe->worker_pid, &chldstatus, wait_option);
196 } while (wpid == -1 && (errno == EINTR || errno == EAGAIN));
197 if (wpid == bpipe->worker_pid || wpid == -1) {
199 Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
200 wpid==-1?strerror(errno):"none");
203 Dmsg3(800, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
204 wpid==-1?strerror(errno):"none");
205 if (remaining_wait > 0) {
206 bmicrosleep(1, 0); /* wait one second */
209 stat = ETIME; /* set error status */
211 break; /* don't wait any longer */
215 if (WIFEXITED(chldstatus)) { /* process exit()ed */
216 stat = WEXITSTATUS(chldstatus);
218 Dmsg1(800, "Non-zero status %d returned from child.\n", stat);
219 stat |= b_errno_exit; /* exit status returned */
221 Dmsg1(800, "child status=%d\n", stat & ~b_errno_exit);
222 } else if (WIFSIGNALED(chldstatus)) { /* process died */
223 stat = WTERMSIG(chldstatus);
224 Dmsg1(800, "Child died from signale %d\n", stat);
225 stat |= b_errno_signal; /* exit signal returned */
228 if (bpipe->timer_id) {
229 stop_child_timer(bpipe->timer_id);
232 Dmsg1(800, "returning stat = %d\n", stat);
238 * Run an external program. Optionally wait a specified number
239 * of seconds. Program killed if wait exceeded. Optionally
240 * return the output from the program (normally a single line).
242 * If the watchdog kills the program, fgets returns, and ferror is set
243 * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
245 * Contrary to my normal calling conventions, this program
247 * Returns: 0 on success
248 * non-zero on error == berrno status
250 int run_program(char *prog, int wait, POOLMEM *results)
256 mode = (char *)(results != NULL ? "r" : "");
257 bpipe = open_bpipe(prog, wait, mode);
263 int len = sizeof_pool_memory(results) - 1;
264 fgets(results, len, bpipe->rfd);
266 if (feof(bpipe->rfd)) {
269 stat1 = ferror(bpipe->rfd);
272 Dmsg2(100, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
273 } else if (stat1 != 0) {
274 Dmsg1(100, "Run program fgets stat=%d\n", stat1);
275 if (bpipe->timer_id) {
276 Dmsg1(100, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
277 /* NB: I'm not sure it is really useful for run_program. Without the
278 * following lines run_program would not detect if the program was killed
279 * by the watchdog. */
280 if (bpipe->timer_id->killed) {
282 pm_strcat(results, _("Program killed by Bacula watchdog (timeout)\n"));
289 stat2 = close_bpipe(bpipe);
290 stat1 = stat2 != 0 ? stat2 : stat1;
291 Dmsg1(100, "Run program returning %d\n", stat1);
296 * Run an external program. Optionally wait a specified number
297 * of seconds. Program killed if wait exceeded (it is done by the
298 * watchdog, as fgets is a blocking function).
300 * If the watchdog kills the program, fgets returns, and ferror is set
301 * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
303 * Return the full output from the program (not only the first line).
305 * Contrary to my normal calling conventions, this program
307 * Returns: 0 on success
308 * non-zero on error == berrno status
311 int run_program_full_output(char *prog, int wait, POOLMEM *results)
318 const int bufsize = 32000;
320 if (results == NULL) {
321 return run_program(prog, wait, NULL);
324 sm_check(__FILE__, __LINE__, false);
326 tmp = get_pool_memory(PM_MESSAGE);
327 buf = (char *)malloc(bufsize+1);
330 bpipe = open_bpipe(prog, wait, mode);
338 sm_check(__FILE__, __LINE__, false);
341 fgets(buf, sizeof(buf), bpipe->rfd);
343 if (feof(bpipe->rfd)) {
345 Dmsg1(900, "Run program fgets stat=%d\n", stat1);
348 stat1 = ferror(bpipe->rfd);
352 Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.strerror());
354 } else if (stat1 != 0) {
355 Dmsg1(900, "Run program fgets stat=%d\n", stat1);
356 if (bpipe->timer_id) {
357 Dmsg1(100, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
358 if (bpipe->timer_id->killed) {
359 pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
366 int len = sizeof_pool_memory(results) - 1;
367 bstrncpy(results, tmp, len);
368 Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
369 stat2 = close_bpipe(bpipe);
370 stat1 = stat2 != 0 ? stat2 : stat1;
372 Dmsg1(900, "Run program returning %d\n", stat);
373 free_pool_memory(tmp);
379 * Build argc and argv from a string
381 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv)
388 for (i=0; i<max_argv; i++)
393 while (*p && (*p == ' ' || *p == '\t'))
395 if (*p == '\"' || *p == '\'') {
400 while (*p && argc < MAX_ARGV) {
403 while (*q && *q != quote)
407 while (*q && *q != ' ')
414 while (*p && (*p == ' ' || *p == '\t'))
416 if (*p == '\"' || *p == '\'') {