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[] = {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]);
66 /* Each pipe is one way, write one end, read the other, so we need two */
67 if (mode_write && pipe(writep) == -1) {
71 free_pool_memory(tprog);
74 if (mode_read && pipe(readp) == -1) {
82 free_pool_memory(tprog);
85 /* Start worker process */
86 switch (bpipe->worker_pid = fork()) {
99 free_pool_memory(tprog);
105 dup2(writep[0], 0); /* Dup our write to his stdin */
108 close(readp[0]); /* Close unused child fds */
109 dup2(readp[1], 1); /* dup our read to his stdout */
110 dup2(readp[1], 2); /* and his stderr */
112 closelog(); /* close syslog if open */
113 for (i=3; i<=32; i++) { /* close any open file descriptors */
116 execvp(bargv[0], bargv); /* call the program */
117 /* Convert errno into an exit code for later analysis */
118 for (i=0; i< num_execvp_errors; i++) {
119 if (execvp_errors[i] == errno) {
120 exit(200 + i); /* exit code => errno */
123 exit(255); /* unknown errno */
125 default: /* parent */
128 free_pool_memory(tprog);
130 close(readp[1]); /* close unused parent fds */
131 bpipe->rfd = fdopen(readp[0], "r"); /* open file descriptor */
135 bpipe->wfd = fdopen(writep[1], "w");
137 bpipe->worker_stime = time(NULL);
140 bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
145 /* Close the write pipe only */
146 int close_wpipe(BPIPE *bpipe)
152 if (fclose(bpipe->wfd) != 0) {
161 * Close both pipes and free resources
163 * Returns: 0 on success
166 int close_bpipe(BPIPE *bpipe)
185 if (bpipe->wait == 0) {
186 wait_option = 0; /* wait indefinitely */
188 wait_option = WNOHANG; /* don't hang */
190 remaining_wait = bpipe->wait;
192 /* wait for worker child to exit */
194 Dmsg2(800, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option);
196 wpid = waitpid(bpipe->worker_pid, &chldstatus, wait_option);
197 } while (wpid == -1 && (errno == EINTR || errno == EAGAIN));
198 if (wpid == bpipe->worker_pid || wpid == -1) {
200 Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
201 wpid==-1?strerror(errno):"none");
204 Dmsg3(800, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
205 wpid==-1?strerror(errno):"none");
206 if (remaining_wait > 0) {
207 bmicrosleep(1, 0); /* wait one second */
210 stat = ETIME; /* set error status */
212 break; /* don't wait any longer */
216 if (WIFEXITED(chldstatus)) { /* process exit()ed */
217 stat = WEXITSTATUS(chldstatus);
219 Dmsg1(800, "Non-zero status %d returned from child.\n", stat);
220 stat |= b_errno_exit; /* exit status returned */
222 Dmsg1(800, "child status=%d\n", stat & ~b_errno_exit);
223 } else if (WIFSIGNALED(chldstatus)) { /* process died */
224 stat = WTERMSIG(chldstatus);
225 Dmsg1(800, "Child died from signale %d\n", stat);
226 stat |= b_errno_signal; /* exit signal returned */
229 if (bpipe->timer_id) {
230 stop_child_timer(bpipe->timer_id);
233 Dmsg1(800, "returning stat = %d\n", stat);
239 * Run an external program. Optionally wait a specified number
240 * of seconds. Program killed if wait exceeded. Optionally
241 * return the output from the program (normally a single line).
243 * If the watchdog kills the program, fgets returns, and ferror is set
244 * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
246 * Contrary to my normal calling conventions, this program
248 * Returns: 0 on success
249 * non-zero on error == berrno status
251 int run_program(char *prog, int wait, POOLMEM *results)
257 mode = (char *)(results != NULL ? "r" : "");
258 bpipe = open_bpipe(prog, wait, mode);
264 int len = sizeof_pool_memory(results) - 1;
265 fgets(results, len, bpipe->rfd);
267 if (feof(bpipe->rfd)) {
270 stat1 = ferror(bpipe->rfd);
273 Dmsg2(150, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
274 } else if (stat1 != 0) {
275 Dmsg1(150, "Run program fgets stat=%d\n", stat1);
276 if (bpipe->timer_id) {
277 Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
278 /* NB: I'm not sure it is really useful for run_program. Without the
279 * following lines run_program would not detect if the program was killed
280 * by the watchdog. */
281 if (bpipe->timer_id->killed) {
283 pm_strcat(results, _("Program killed by Bacula watchdog (timeout)\n"));
290 stat2 = close_bpipe(bpipe);
291 stat1 = stat2 != 0 ? stat2 : stat1;
292 Dmsg1(150, "Run program returning %d\n", stat1);
297 * Run an external program. Optionally wait a specified number
298 * of seconds. Program killed if wait exceeded (it is done by the
299 * watchdog, as fgets is a blocking function).
301 * If the watchdog kills the program, fgets returns, and ferror is set
302 * to 1 (=>SUCCESS), so we check if the watchdog killed the program.
304 * Return the full output from the program (not only the first line).
306 * Contrary to my normal calling conventions, this program
308 * Returns: 0 on success
309 * non-zero on error == berrno status
312 int run_program_full_output(char *prog, int wait, POOLMEM *results)
319 const int bufsize = 32000;
321 if (results == NULL) {
322 return run_program(prog, wait, NULL);
325 sm_check(__FILE__, __LINE__, false);
327 tmp = get_pool_memory(PM_MESSAGE);
328 buf = (char *)malloc(bufsize+1);
331 bpipe = open_bpipe(prog, wait, mode);
339 sm_check(__FILE__, __LINE__, false);
343 fgets(buf, bufsize, bpipe->rfd);
346 if (feof(bpipe->rfd)) {
348 Dmsg1(900, "Run program fgets stat=%d\n", stat1);
351 stat1 = ferror(bpipe->rfd);
355 Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.strerror());
357 } else if (stat1 != 0) {
358 Dmsg1(900, "Run program fgets stat=%d\n", stat1);
359 if (bpipe->timer_id) {
360 Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
361 if (bpipe->timer_id->killed) {
362 pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
369 int len = sizeof_pool_memory(results) - 1;
370 bstrncpy(results, tmp, len);
371 Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
372 stat2 = close_bpipe(bpipe);
373 stat1 = stat2 != 0 ? stat2 : stat1;
375 Dmsg1(900, "Run program returning %d\n", stat1);
376 free_pool_memory(tmp);
382 * Build argc and argv from a string
384 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv)
391 for (i=0; i<max_argv; i++)
396 while (*p && (*p == ' ' || *p == '\t'))
398 if (*p == '\"' || *p == '\'') {
403 while (*p && argc < MAX_ARGV) {
406 while (*q && *q != quote)
410 while (*q && *q != ' ')
417 while (*p && (*p == ' ' || *p == '\t'))
419 if (*p == '\"' || *p == '\'') {