]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/bpipe.c
Add the updated version of the the win32 pathname fix.
[bacula/bacula] / bacula / src / lib / bpipe.c
index 45fffe4447cae1c02bed921778e8a6eae87c9001..12a5d8b925397c591c0a329e84314ff79d0165ee 100644 (file)
@@ -6,7 +6,7 @@
  *   Version $Id$
  */
 /*
-   Copyright (C) 2002-2005 Kern Sibbald
+   Copyright (C) 2002-2006 Kern Sibbald
 
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
 #include "bacula.h"
 #include "jcr.h"
 
-int execvp_errors[] = {EACCES, ENOEXEC, EFAULT, EINTR, E2BIG,
-                     ENAMETOOLONG, ENOMEM, ETXTBSY, ENOENT};
+int execvp_errors[] = {
+        EACCES,
+        ENOEXEC,
+        EFAULT,
+        EINTR,
+        E2BIG,
+        ENAMETOOLONG,
+        ENOMEM,
+#ifndef HAVE_WIN32
+        ETXTBSY,
+#endif
+        ENOENT
+};
 int num_execvp_errors = (int)(sizeof(execvp_errors)/sizeof(int));
 
 
@@ -62,13 +73,13 @@ BPIPE *open_bpipe(char *prog, int wait, const char *mode)
       printf("argc=%d argv=%s:\n", i, bargv[i]);
    }
 #endif
-   free_pool_memory(tprog);
 
    /* Each pipe is one way, write one end, read the other, so we need two */
    if (mode_write && pipe(writep) == -1) {
       save_errno = errno;
       free(bpipe);
       errno = save_errno;
+      free_pool_memory(tprog);
       return NULL;
    }
    if (mode_read && pipe(readp) == -1) {
@@ -79,6 +90,7 @@ BPIPE *open_bpipe(char *prog, int wait, const char *mode)
       }
       free(bpipe);
       errno = save_errno;
+      free_pool_memory(tprog);
       return NULL;
    }
    /* Start worker process */
@@ -95,6 +107,7 @@ BPIPE *open_bpipe(char *prog, int wait, const char *mode)
       }
       free(bpipe);
       errno = save_errno;
+      free_pool_memory(tprog);
       return NULL;
 
    case 0:                            /* child */
@@ -120,11 +133,10 @@ BPIPE *open_bpipe(char *prog, int wait, const char *mode)
       }
       exit(255);                      /* unknown errno */
 
-
-
    default:                           /* parent */
       break;
    }
+   free_pool_memory(tprog);
    if (mode_read) {
       close(readp[1]);                /* close unused parent fds */
       bpipe->rfd = fdopen(readp[0], "r"); /* open file descriptor */
@@ -220,8 +232,12 @@ int close_bpipe(BPIPE *bpipe)
          }
          Dmsg1(800, "child status=%d\n", stat & ~b_errno_exit);
       } else if (WIFSIGNALED(chldstatus)) {  /* process died */
+#ifndef HAVE_WIN32
          stat = WTERMSIG(chldstatus);
-         Dmsg1(800, "Child died from signale %d\n", stat);
+#else
+#warning "WTERMSIG undefined in Win32 !!!"
+#endif
+         Dmsg1(800, "Child died from signal %d\n", stat);
          stat |= b_errno_signal;      /* exit signal returned */
       }
    }
@@ -239,6 +255,9 @@ int close_bpipe(BPIPE *bpipe)
  *   of seconds. Program killed if wait exceeded. Optionally
  *   return the output from the program (normally a single line).
  *
+ *   If the watchdog kills the program, fgets returns, and ferror is set
+ *   to 1 (=>SUCCESS), so we check if the watchdog killed the program.
+ *
  * Contrary to my normal calling conventions, this program
  *
  *  Returns: 0 on success
@@ -266,16 +285,26 @@ int run_program(char *prog, int wait, POOLMEM *results)
          stat1 = ferror(bpipe->rfd);
       }
       if (stat1 < 0) {
-         Dmsg2(100, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
+         Dmsg2(150, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
       } else if (stat1 != 0) {
-         Dmsg1(100, "Run program fgets stat=%d\n", stat1);
+         Dmsg1(150, "Run program fgets stat=%d\n", stat1);
+         if (bpipe->timer_id) {
+            Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
+            /* NB: I'm not sure it is really useful for run_program. Without the
+             * following lines run_program would not detect if the program was killed
+             * by the watchdog. */
+            if (bpipe->timer_id->killed) {
+               stat1 = ETIME;
+               pm_strcat(results, _("Program killed by Bacula watchdog (timeout)\n"));
+            }
+         }
       }
    } else {
       stat1 = 0;
    }
    stat2 = close_bpipe(bpipe);
    stat1 = stat2 != 0 ? stat2 : stat1;
-   Dmsg1(100, "Run program returning %d\n", stat1);
+   Dmsg1(150, "Run program returning %d\n", stat1);
    return stat1;
 }
 
@@ -283,6 +312,10 @@ int run_program(char *prog, int wait, POOLMEM *results)
  * Run an external program. Optionally wait a specified number
  *   of seconds. Program killed if wait exceeded (it is done by the 
  *   watchdog, as fgets is a blocking function).
+ *
+ *   If the watchdog kills the program, fgets returns, and ferror is set
+ *   to 1 (=>SUCCESS), so we check if the watchdog killed the program.
+ *
  *   Return the full output from the program (not only the first line).
  *
  * Contrary to my normal calling conventions, this program
@@ -297,6 +330,8 @@ int run_program_full_output(char *prog, int wait, POOLMEM *results)
    int stat1, stat2;
    char *mode;
    POOLMEM* tmp;
+   char *buf;
+   const int bufsize = 32000;
 
    if (results == NULL) {
       return run_program(prog, wait, NULL);
@@ -305,6 +340,7 @@ int run_program_full_output(char *prog, int wait, POOLMEM *results)
    sm_check(__FILE__, __LINE__, false);
 
    tmp = get_pool_memory(PM_MESSAGE);
+   buf = (char *)malloc(bufsize+1);
    
    mode = (char *)"r";
    bpipe = open_bpipe(prog, wait, mode);
@@ -318,8 +354,9 @@ int run_program_full_output(char *prog, int wait, POOLMEM *results)
    sm_check(__FILE__, __LINE__, false);
    tmp[0] = 0;
    while (1) {
-      char buf[1000];
-      fgets(buf, sizeof(buf), bpipe->rfd);
+      buf[0] = 0;
+      fgets(buf, bufsize, bpipe->rfd);
+      buf[bufsize] = 0;
       pm_strcat(tmp, buf);
       if (feof(bpipe->rfd)) {
          stat1 = 0;
@@ -334,6 +371,14 @@ int run_program_full_output(char *prog, int wait, POOLMEM *results)
          break;
       } else if (stat1 != 0) {
          Dmsg1(900, "Run program fgets stat=%d\n", stat1);
+         if (bpipe->timer_id) {
+            Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
+            if (bpipe->timer_id->killed) {
+               pm_strcat(tmp, _("Program killed by Bacula watchdog (timeout)\n"));
+               stat1 = ETIME;
+               break;
+            }
+         }
       }
    }
    int len = sizeof_pool_memory(results) - 1;
@@ -342,8 +387,9 @@ int run_program_full_output(char *prog, int wait, POOLMEM *results)
    stat2 = close_bpipe(bpipe);
    stat1 = stat2 != 0 ? stat2 : stat1;
    
-   Dmsg1(900, "Run program returning %d\n", stat);
+   Dmsg1(900, "Run program returning %d\n", stat1);
    free_pool_memory(tmp);
+   free(buf);
    return stat1;
 }