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