]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bpipe.c
Ensure b_sterror() is using the correct size of input buffer
[bacula/bacula] / bacula / src / lib / bpipe.c
1 /*
2    Bacula® - The Network Backup Solution
3
4    Copyright (C) 2002-2014 Free Software Foundation Europe e.V.
5
6    The main author of Bacula is Kern Sibbald, with contributions from many
7    others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    Bacula® is a registered trademark of Kern Sibbald.
15 */
16 /*
17  *   bpipe.c bi-directional pipe
18  *
19  *    Kern Sibbald, November MMII
20  *
21  */
22
23
24 #include "bacula.h"
25 #include "jcr.h"
26
27 int execvp_errors[] = {
28         EACCES,
29         ENOEXEC,
30         EFAULT,
31         EINTR,
32         E2BIG,
33         ENAMETOOLONG,
34         ENOMEM,
35 #ifndef HAVE_WIN32
36         ETXTBSY,
37 #endif
38         ENOENT
39 };
40 int num_execvp_errors = (int)(sizeof(execvp_errors)/sizeof(int));
41
42
43 #define MAX_ARGV 100
44
45 #if !defined(HAVE_WIN32)
46 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_arg);
47
48 void build_sh_argc_argv(char *cmd, int *bargc, char *bargv[], int max_arg)
49 {
50    bargv[0] = (char *)"/bin/sh";
51    bargv[1] = (char *)"-c";
52    bargv[2] = cmd;
53    bargv[3] = NULL;
54    *bargc = 3;
55 }
56
57 /*
58  * Run an external program. Optionally wait a specified number
59  *   of seconds. Program killed if wait exceeded. We open
60  *   a bi-directional pipe so that the user can read from and
61  *   write to the program.
62  */
63 BPIPE *open_bpipe(char *prog, int wait, const char *mode)
64 {
65    char *bargv[MAX_ARGV];
66    int bargc, i;
67    int readp[2], writep[2];
68    POOLMEM *tprog;
69    int mode_read, mode_write, mode_shell;
70    BPIPE *bpipe;
71    int save_errno;
72
73    bpipe = (BPIPE *)malloc(sizeof(BPIPE));
74    memset(bpipe, 0, sizeof(BPIPE));
75    mode_read = (mode[0] == 'r');
76    mode_write = (mode[0] == 'w' || mode[1] == 'w');
77    /* mode is at least 2 bytes long, can be 3, rs, rws, ws */
78    mode_shell = (mode[1] == 's' || (mode[1] && mode[2] == 's'));
79    /* Build arguments for running program. */
80    tprog = get_pool_memory(PM_FNAME);
81    pm_strcpy(tprog, prog);
82    if (mode_shell) {
83       build_sh_argc_argv(tprog, &bargc, bargv, MAX_ARGV);
84
85    } else {
86       build_argc_argv(tprog, &bargc, bargv, MAX_ARGV);
87    }
88 #ifdef  xxxxxx
89    printf("argc=%d\n", bargc);
90    for (i=0; i<bargc; i++) {
91       printf("argc=%d argv=%s:\n", i, bargv[i]);
92    }
93 #endif
94
95    /* Each pipe is one way, write one end, read the other, so we need two */
96    if (mode_write && pipe(writep) == -1) {
97       save_errno = errno;
98       free(bpipe);
99       free_pool_memory(tprog);
100       errno = save_errno;
101       return NULL;
102    }
103    if (mode_read && pipe(readp) == -1) {
104       save_errno = errno;
105       if (mode_write) {
106          close(writep[0]);
107          close(writep[1]);
108       }
109       free(bpipe);
110       free_pool_memory(tprog);
111       errno = save_errno;
112       return NULL;
113    }
114    /* Start worker process */
115    switch (bpipe->worker_pid = fork()) {
116    case -1:                           /* error */
117       save_errno = errno;
118       if (mode_write) {
119          close(writep[0]);
120          close(writep[1]);
121       }
122       if (mode_read) {
123          close(readp[0]);
124          close(readp[1]);
125       }
126       free(bpipe);
127       free_pool_memory(tprog);
128       errno = save_errno;
129       return NULL;
130
131    case 0:                            /* child */
132       if (mode_write) {
133          close(writep[1]);
134          dup2(writep[0], 0);          /* Dup our write to his stdin */
135       }
136       if (mode_read) {
137          close(readp[0]);             /* Close unused child fds */
138          dup2(readp[1], 1);           /* dup our read to his stdout */
139          dup2(readp[1], 2);           /*   and his stderr */
140       }
141 /* Note, the close log cause problems, see bug #1536 */
142 /*    closelog();                        close syslog if open */
143       for (i=3; i<=32; i++) {         /* close any open file descriptors */
144          close(i);
145       }
146       execvp(bargv[0], bargv);        /* call the program */
147       /* Convert errno into an exit code for later analysis */
148       for (i=0; i< num_execvp_errors; i++) {
149          if (execvp_errors[i] == errno) {
150             exit(200 + i);            /* exit code => errno */
151          }
152       }
153       exit(255);                      /* unknown errno */
154
155    default:                           /* parent */
156       break;
157    }
158    free_pool_memory(tprog);
159    if (mode_read) {
160       close(readp[1]);                /* close unused parent fds */
161       bpipe->rfd = fdopen(readp[0], "r"); /* open file descriptor */
162    }
163    if (mode_write) {
164       close(writep[0]);
165       bpipe->wfd = fdopen(writep[1], "w");
166    }
167    bpipe->worker_stime = time(NULL);
168    bpipe->wait = wait;
169    if (wait > 0) {
170       bpipe->timer_id = start_child_timer(NULL, bpipe->worker_pid, wait);
171    }
172    return bpipe;
173 }
174
175 /* Close the write pipe only */
176 int close_wpipe(BPIPE *bpipe)
177 {
178    int stat = 1;
179
180    if (bpipe->wfd) {
181       fflush(bpipe->wfd);
182       if (fclose(bpipe->wfd) != 0) {
183          stat = 0;
184       }
185       bpipe->wfd = NULL;
186    }
187    return stat;
188 }
189
190 /*
191  * Close both pipes and free resources
192  *
193  *  Returns: 0 on success
194  *           berrno on failure
195  */
196 int close_bpipe(BPIPE *bpipe)
197 {
198    int chldstatus = 0;
199    int stat = 0;
200    int wait_option;
201    int remaining_wait;
202    pid_t wpid = 0;
203
204
205    /* Close pipes */
206    if (bpipe->rfd) {
207       fclose(bpipe->rfd);
208       bpipe->rfd = NULL;
209    }
210    if (bpipe->wfd) {
211       fclose(bpipe->wfd);
212       bpipe->wfd = NULL;
213    }
214
215    if (bpipe->wait == 0) {
216       wait_option = 0;                /* wait indefinitely */
217    } else {
218       wait_option = WNOHANG;          /* don't hang */
219    }
220    remaining_wait = bpipe->wait;
221
222    /* wait for worker child to exit */
223    for ( ;; ) {
224       Dmsg2(800, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option);
225       do {
226          wpid = waitpid(bpipe->worker_pid, &chldstatus, wait_option);
227       } while (wpid == -1 && (errno == EINTR || errno == EAGAIN));
228       if (wpid == bpipe->worker_pid || wpid == -1) {
229          berrno be;
230          stat = errno;
231          Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
232             wpid==-1?be.bstrerror():"none");
233          break;
234       }
235       Dmsg3(800, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
236             wpid==-1?strerror(errno):"none");
237       if (remaining_wait > 0) {
238          bmicrosleep(1, 0);           /* wait one second */
239          remaining_wait--;
240       } else {
241          stat = ETIME;                /* set error status */
242          wpid = -1;
243          break;                       /* don't wait any longer */
244       }
245    }
246    if (wpid > 0) {
247       if (WIFEXITED(chldstatus)) {    /* process exit()ed */
248          stat = WEXITSTATUS(chldstatus);
249          if (stat != 0) {
250             Dmsg1(800, "Non-zero status %d returned from child.\n", stat);
251             stat |= b_errno_exit;        /* exit status returned */
252          }
253          Dmsg1(800, "child status=%d\n", stat & ~b_errno_exit);
254       } else if (WIFSIGNALED(chldstatus)) {  /* process died */
255 #ifndef HAVE_WIN32
256          stat = WTERMSIG(chldstatus);
257 #else
258          stat = 1;                    /* fake child status */
259 #endif
260          Dmsg1(800, "Child died from signal %d\n", stat);
261          stat |= b_errno_signal;      /* exit signal returned */
262       }
263    }
264    if (bpipe->timer_id) {
265       stop_child_timer(bpipe->timer_id);
266    }
267    free(bpipe);
268    Dmsg2(800, "returning stat=%d,%d\n", stat & ~(b_errno_exit|b_errno_signal), stat);
269    return stat;
270 }
271
272 /*
273  * Build argc and argv from a string
274  */
275 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv)
276 {
277    int i;
278    char *p, *q, quote;
279    int argc = 0;
280
281    argc = 0;
282    for (i=0; i<max_argv; i++)
283       bargv[i] = NULL;
284
285    p = cmd;
286    quote = 0;
287    while  (*p && (*p == ' ' || *p == '\t'))
288       p++;
289    if (*p == '\"' || *p == '\'') {
290       quote = *p;
291       p++;
292    }
293    if (*p) {
294       while (*p && argc < MAX_ARGV) {
295          q = p;
296          if (quote) {
297             while (*q && *q != quote)
298             q++;
299             quote = 0;
300          } else {
301             while (*q && *q != ' ')
302             q++;
303          }
304          if (*q)
305             *(q++) = '\0';
306          bargv[argc++] = p;
307          p = q;
308          while (*p && (*p == ' ' || *p == '\t'))
309             p++;
310          if (*p == '\"' || *p == '\'') {
311             quote = *p;
312             p++;
313          }
314       }
315    }
316    *bargc = argc;
317 }
318 #endif /* HAVE_WIN32 */
319
320 /*
321  * Run an external program. Optionally wait a specified number
322  *   of seconds. Program killed if wait exceeded. Optionally
323  *   return the output from the program (normally a single line).
324  *
325  *   If the watchdog kills the program, fgets returns, and ferror is set
326  *   to 1 (=>SUCCESS), so we check if the watchdog killed the program.
327  *
328  * Contrary to my normal calling conventions, this program
329  *
330  *  Returns: 0 on success
331  *           non-zero on error == berrno status
332  */
333 int run_program(char *prog, int wait, POOLMEM *&results)
334 {
335    BPIPE *bpipe;
336    int stat1, stat2;
337    char *mode;
338
339    mode = (char *)"r";
340    bpipe = open_bpipe(prog, wait, mode);
341    if (!bpipe) {
342       return ENOENT;
343    }
344    results[0] = 0;
345    int len = sizeof_pool_memory(results) - 1;
346    fgets(results, len, bpipe->rfd);
347    results[len] = 0;
348    if (feof(bpipe->rfd)) {
349       stat1 = 0;
350    } else {
351       stat1 = ferror(bpipe->rfd);
352    }
353    if (stat1 < 0) {
354       berrno be;
355       Dmsg2(150, "Run program fgets stat=%d ERR=%s\n", stat1, be.bstrerror(errno));
356    } else if (stat1 != 0) {
357       Dmsg1(150, "Run program fgets stat=%d\n", stat1);
358       if (bpipe->timer_id) {
359          Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
360          /* NB: I'm not sure it is really useful for run_program. Without the
361           * following lines run_program would not detect if the program was killed
362           * by the watchdog. */
363          if (bpipe->timer_id->killed) {
364             stat1 = ETIME;
365             pm_strcpy(results, _("Program killed by Bacula (timeout)\n"));
366          }
367       }
368    }
369    stat2 = close_bpipe(bpipe);
370    stat1 = stat2 != 0 ? stat2 : stat1;
371    Dmsg1(150, "Run program returning %d\n", stat1);
372    return stat1;
373 }
374
375 /*
376  * Run an external program. Optionally wait a specified number
377  *   of seconds. Program killed if wait exceeded (it is done by the
378  *   watchdog, as fgets is a blocking function).
379  *
380  *   If the watchdog kills the program, fgets returns, and ferror is set
381  *   to 1 (=>SUCCESS), so we check if the watchdog killed the program.
382  *
383  *   Return the full output from the program (not only the first line).
384  *
385  * Contrary to my normal calling conventions, this program
386  *
387  *  Returns: 0 on success
388  *           non-zero on error == berrno status
389  *
390  */
391 int run_program_full_output(char *prog, int wait, POOLMEM *&results)
392 {
393    BPIPE *bpipe;
394    int stat1, stat2;
395    char *mode;
396    POOLMEM* tmp;
397    char *buf;
398    const int bufsize = 32000;
399
400
401    Dsm_check(200);
402
403    tmp = get_pool_memory(PM_MESSAGE);
404    buf = (char *)malloc(bufsize+1);
405
406    results[0] = 0;
407    mode = (char *)"r";
408    bpipe = open_bpipe(prog, wait, mode);
409    if (!bpipe) {
410       stat1 = ENOENT;
411       goto bail_out;
412    }
413
414    Dsm_check(200);
415    tmp[0] = 0;
416    while (1) {
417       buf[0] = 0;
418       fgets(buf, bufsize, bpipe->rfd);
419       buf[bufsize] = 0;
420       pm_strcat(tmp, buf);
421       if (feof(bpipe->rfd)) {
422          stat1 = 0;
423          Dmsg1(900, "Run program fgets stat=%d\n", stat1);
424          break;
425       } else {
426          stat1 = ferror(bpipe->rfd);
427       }
428       if (stat1 < 0) {
429          berrno be;
430          Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.bstrerror());
431          break;
432       } else if (stat1 != 0) {
433          Dmsg1(900, "Run program fgets stat=%d\n", stat1);
434          if (bpipe->timer_id && bpipe->timer_id->killed) {
435             Dmsg1(250, "Run program saw fgets killed=%d\n", bpipe->timer_id->killed);
436             break;
437          }
438       }
439    }
440    /*
441     * We always check whether the timer killed the program. We would see
442     * an eof even when it does so we just have to trust the killed flag
443     * and set the timer values to avoid edge cases where the program ends
444     * just as the timer kills it.
445     */
446    if (bpipe->timer_id && bpipe->timer_id->killed) {
447       Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
448       pm_strcpy(tmp, _("Program killed by Bacula (timeout)\n"));
449       stat1 = ETIME;
450    }
451    pm_strcpy(results, tmp);
452    Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
453    stat2 = close_bpipe(bpipe);
454    stat1 = stat2 != 0 ? stat2 : stat1;
455
456    Dmsg1(900, "Run program returning %d\n", stat1);
457 bail_out:
458    free_pool_memory(tmp);
459    free(buf);
460    return stat1;
461 }