]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/lib/bpipe.c
Mark translatable strings in all source files.
[bacula/bacula] / bacula / src / lib / bpipe.c
1 /*
2  *   bpipe.c bi-directional pipe
3  *
4  *    Kern Sibbald, November MMII
5  *
6  *   Version $Id$
7  */
8 /*
9    Copyright (C) 2002-2005 Kern Sibbald
10
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.
15
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.
20
21  */
22
23
24 #include "bacula.h"
25 #include "jcr.h"
26
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));
30
31
32 #define MAX_ARGV 100
33 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_arg);
34
35 /*
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.
40  */
41 BPIPE *open_bpipe(char *prog, int wait, const char *mode)
42 {
43    char *bargv[MAX_ARGV];
44    int bargc, i;
45    int readp[2], writep[2];
46    POOLMEM *tprog;
47    int mode_read, mode_write;
48    BPIPE *bpipe;
49    int save_errno;
50
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);
59 #ifdef  xxxxxx
60    printf("argc=%d\n", bargc);
61    for (i=0; i<bargc; i++) {
62       printf("argc=%d argv=%s:\n", i, bargv[i]);
63    }
64 #endif
65    free_pool_memory(tprog);
66
67    /* Each pipe is one way, write one end, read the other, so we need two */
68    if (mode_write && pipe(writep) == -1) {
69       save_errno = errno;
70       free(bpipe);
71       errno = save_errno;
72       return NULL;
73    }
74    if (mode_read && pipe(readp) == -1) {
75       save_errno = errno;
76       if (mode_write) {
77          close(writep[0]);
78          close(writep[1]);
79       }
80       free(bpipe);
81       errno = save_errno;
82       return NULL;
83    }
84    /* Start worker process */
85    switch (bpipe->worker_pid = fork()) {
86    case -1:                           /* error */
87       save_errno = errno;
88       if (mode_write) {
89          close(writep[0]);
90          close(writep[1]);
91       }
92       if (mode_read) {
93          close(readp[0]);
94          close(readp[1]);
95       }
96       free(bpipe);
97       errno = save_errno;
98       return NULL;
99
100    case 0:                            /* child */
101       if (mode_write) {
102          close(writep[1]);
103          dup2(writep[0], 0);          /* Dup our write to his stdin */
104       }
105       if (mode_read) {
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 */
109       }
110       closelog();                     /* close syslog if open */
111       for (i=3; i<=32; i++) {         /* close any open file descriptors */
112          close(i);
113       }
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 */
119          }
120       }
121       exit(255);                      /* unknown errno */
122
123
124
125    default:                           /* parent */
126       break;
127    }
128    if (mode_read) {
129       close(readp[1]);                /* close unused parent fds */
130       bpipe->rfd = fdopen(readp[0], "r"); /* open file descriptor */
131    }
132    if (mode_write) {
133       close(writep[0]);
134       bpipe->wfd = fdopen(writep[1], "w");
135    }
136    bpipe->worker_stime = time(NULL);
137    bpipe->wait = wait;
138    if (wait > 0) {
139       bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
140    }
141    return bpipe;
142 }
143
144 /* Close the write pipe only */
145 int close_wpipe(BPIPE *bpipe)
146 {
147    int stat = 1;
148
149    if (bpipe->wfd) {
150       fflush(bpipe->wfd);
151       if (fclose(bpipe->wfd) != 0) {
152          stat = 0;
153       }
154       bpipe->wfd = NULL;
155    }
156    return stat;
157 }
158
159 /*
160  * Close both pipes and free resources
161  *
162  *  Returns: 0 on success
163  *           berrno on failure
164  */
165 int close_bpipe(BPIPE *bpipe)
166 {
167    int chldstatus = 0;
168    int stat = 0;
169    int wait_option;
170    int remaining_wait;
171    pid_t wpid = 0;
172
173
174    /* Close pipes */
175    if (bpipe->rfd) {
176       fclose(bpipe->rfd);
177       bpipe->rfd = NULL;
178    }
179    if (bpipe->wfd) {
180       fclose(bpipe->wfd);
181       bpipe->wfd = NULL;
182    }
183
184    if (bpipe->wait == 0) {
185       wait_option = 0;                /* wait indefinitely */
186    } else {
187       wait_option = WNOHANG;          /* don't hang */
188    }
189    remaining_wait = bpipe->wait;
190
191    /* wait for worker child to exit */
192    for ( ;; ) {
193       Dmsg2(800, "Wait for %d opt=%d\n", bpipe->worker_pid, wait_option);
194       do {
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) {
198          stat = errno;
199          Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
200             wpid==-1?strerror(errno):"none");
201          break;
202       }
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 */
207          remaining_wait--;
208       } else {
209          stat = ETIME;                /* set error status */
210          wpid = -1;
211          break;                       /* don't wait any longer */
212       }
213    }
214    if (wpid > 0) {
215       if (WIFEXITED(chldstatus)) {    /* process exit()ed */
216          stat = WEXITSTATUS(chldstatus);
217          if (stat != 0) {
218             Dmsg1(800, "Non-zero status %d returned from child.\n", stat);
219             stat |= b_errno_exit;        /* exit status returned */
220          }
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 */
226       }
227    }
228    if (bpipe->timer_id) {
229       stop_child_timer(bpipe->timer_id);
230    }
231    free(bpipe);
232    Dmsg1(800, "returning stat = %d\n", stat);
233    return stat;
234 }
235
236
237 /*
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).
241  *
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.
244  *
245  * Contrary to my normal calling conventions, this program
246  *
247  *  Returns: 0 on success
248  *           non-zero on error == berrno status
249  */
250 int run_program(char *prog, int wait, POOLMEM *results)
251 {
252    BPIPE *bpipe;
253    int stat1, stat2;
254    char *mode;
255
256    mode = (char *)(results != NULL ? "r" : "");
257    bpipe = open_bpipe(prog, wait, mode);
258    if (!bpipe) {
259       return ENOENT;
260    }
261    if (results) {
262       results[0] = 0;
263       int len = sizeof_pool_memory(results) - 1;
264       fgets(results, len, bpipe->rfd);
265       results[len] = 0;
266       if (feof(bpipe->rfd)) {
267          stat1 = 0;
268       } else {
269          stat1 = ferror(bpipe->rfd);
270       }
271       if (stat1 < 0) {
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) {
281                stat1 = ETIME;
282                pm_strcat(results, _("Program killed by Bacula watchdog (timeout)\n"));
283             }
284          }
285       }
286    } else {
287       stat1 = 0;
288    }
289    stat2 = close_bpipe(bpipe);
290    stat1 = stat2 != 0 ? stat2 : stat1;
291    Dmsg1(100, "Run program returning %d\n", stat1);
292    return stat1;
293 }
294
295 /*
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).
299  *
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.
302  *
303  *   Return the full output from the program (not only the first line).
304  *
305  * Contrary to my normal calling conventions, this program
306  *
307  *  Returns: 0 on success
308  *           non-zero on error == berrno status
309  *
310  */
311 int run_program_full_output(char *prog, int wait, POOLMEM *results)
312 {
313    BPIPE *bpipe;
314    int stat1, stat2;
315    char *mode;
316    POOLMEM* tmp;
317
318    if (results == NULL) {
319       return run_program(prog, wait, NULL);
320    }
321    
322    sm_check(__FILE__, __LINE__, false);
323
324    tmp = get_pool_memory(PM_MESSAGE);
325    
326    mode = (char *)"r";
327    bpipe = open_bpipe(prog, wait, mode);
328    if (!bpipe) {
329       if (results) {
330          results[0] = 0;
331       }
332       return ENOENT;
333    }
334    
335    sm_check(__FILE__, __LINE__, false);
336    tmp[0] = 0;
337    while (1) {
338       char buf[1000];
339       fgets(buf, sizeof(buf), bpipe->rfd);
340       pm_strcat(tmp, buf);
341       if (feof(bpipe->rfd)) {
342          stat1 = 0;
343          Dmsg1(900, "Run program fgets stat=%d\n", stat1);
344          break;
345       } else {
346          stat1 = ferror(bpipe->rfd);
347       }
348       if (stat1 < 0) {
349          berrno be;
350          Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.strerror());
351          break;
352       } else if (stat1 != 0) {
353          Dmsg1(900, "Run program fgets stat=%d\n", stat1);
354          if (bpipe->timer_id) {
355             Dmsg1(100, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
356             if (bpipe->timer_id->killed) {
357                pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
358                stat1 = ETIME;
359                break;
360             }
361          }
362       }
363    }
364    int len = sizeof_pool_memory(results) - 1;
365    bstrncpy(results, tmp, len);
366    Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
367    stat2 = close_bpipe(bpipe);
368    stat1 = stat2 != 0 ? stat2 : stat1;
369    
370    Dmsg1(900, "Run program returning %d\n", stat);
371    free_pool_memory(tmp);
372    return stat1;
373 }
374
375 /*
376  * Build argc and argv from a string
377  */
378 static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv)
379 {
380    int i;
381    char *p, *q, quote;
382    int argc = 0;
383
384    argc = 0;
385    for (i=0; i<max_argv; i++)
386       bargv[i] = NULL;
387
388    p = cmd;
389    quote = 0;
390    while  (*p && (*p == ' ' || *p == '\t'))
391       p++;
392    if (*p == '\"' || *p == '\'') {
393       quote = *p;
394       p++;
395    }
396    if (*p) {
397       while (*p && argc < MAX_ARGV) {
398          q = p;
399          if (quote) {
400             while (*q && *q != quote)
401             q++;
402             quote = 0;
403          } else {
404             while (*q && *q != ' ')
405             q++;
406          }
407          if (*q)
408             *(q++) = '\0';
409          bargv[argc++] = p;
410          p = q;
411          while (*p && (*p == ' ' || *p == '\t'))
412             p++;
413          if (*p == '\"' || *p == '\'') {
414             quote = *p;
415             p++;
416          }
417       }
418    }
419    *bargc = argc;
420 }