]> git.sur5r.net Git - bacula/bacula/blobdiff - bacula/src/lib/bpipe.c
Fix bat crash due to alignment diff in bat and core code
[bacula/bacula] / bacula / src / lib / bpipe.c
index 3f142bb8cbe77691cb345a7756dc6370449c36d3..5586d6baf7ce6279e6566b27624bdbe75178185b 100644 (file)
@@ -1,3 +1,30 @@
+/*
+   Bacula® - The Network Backup Solution
+
+   Copyright (C) 2002-2008 Free Software Foundation Europe e.V.
+
+   The main author of Bacula is Kern Sibbald, with contributions from
+   many others, a complete list can be found in the file AUTHORS.
+   This program is Free Software; you can redistribute it and/or
+   modify it under the terms of version two of the GNU General Public
+   License as published by the Free Software Foundation and included
+   in the file LICENSE.
+
+   This program is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+   02110-1301, USA.
+
+   Bacula® is a registered trademark of Kern Sibbald.
+   The licensor of Bacula is the Free Software Foundation Europe
+   (FSFE), Fiduciary Program, Sumatrastrasse 25, 8006 Zürich,
+   Switzerland, email:ftf@fsfeurope.org.
+*/
 /*
  *   bpipe.c bi-directional pipe
  *
@@ -5,20 +32,6 @@
  *
  *   Version $Id$
  */
-/*
-   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
-   version 2 as amended with additional clauses defined in the
-   file LICENSE in the main source directory.
-
-   This program is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
-   the file LICENSE for additional details.
-
- */
 
 
 #include "bacula.h"
@@ -150,7 +163,7 @@ BPIPE *open_bpipe(char *prog, int wait, const char *mode)
    bpipe->worker_stime = time(NULL);
    bpipe->wait = wait;
    if (wait > 0) {
-      bpipe->timer_id = start_child_timer(bpipe->worker_pid, wait);
+      bpipe->timer_id = start_child_timer(NULL, bpipe->worker_pid, wait);
    }
    return bpipe;
 }
@@ -209,9 +222,10 @@ int close_bpipe(BPIPE *bpipe)
          wpid = waitpid(bpipe->worker_pid, &chldstatus, wait_option);
       } while (wpid == -1 && (errno == EINTR || errno == EAGAIN));
       if (wpid == bpipe->worker_pid || wpid == -1) {
+         berrno be;
          stat = errno;
          Dmsg3(800, "Got break wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
-            wpid==-1?strerror(errno):"none");
+            wpid==-1?be.bstrerror():"none");
          break;
       }
       Dmsg3(800, "Got wpid=%d status=%d ERR=%s\n", wpid, chldstatus,
@@ -312,44 +326,41 @@ static void build_argc_argv(char *cmd, int *bargc, char *bargv[], int max_argv)
  *  Returns: 0 on success
  *           non-zero on error == berrno status
  */
-int run_program(char *prog, int wait, POOLMEM *results)
+int run_program(char *prog, int wait, POOLMEM *&results)
 {
    BPIPE *bpipe;
    int stat1, stat2;
    char *mode;
 
-   mode = (char *)(results != NULL ? "r" : "");
+   mode = (char *)"r";
    bpipe = open_bpipe(prog, wait, mode);
    if (!bpipe) {
       return ENOENT;
    }
-   if (results) {
-      results[0] = 0;
-      int len = sizeof_pool_memory(results) - 1;
-      fgets(results, len, bpipe->rfd);
-      results[len] = 0;
-      if (feof(bpipe->rfd)) {
-         stat1 = 0;
-      } else {
-         stat1 = ferror(bpipe->rfd);
-      }
-      if (stat1 < 0) {
-         Dmsg2(150, "Run program fgets stat=%d ERR=%s\n", stat1, strerror(errno));
-      } else if (stat1 != 0) {
-         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"));
-            }
+   results[0] = 0;
+   int len = sizeof_pool_memory(results) - 1;
+   fgets(results, len, bpipe->rfd);
+   results[len] = 0;
+   if (feof(bpipe->rfd)) {
+      stat1 = 0;
+   } else {
+      stat1 = ferror(bpipe->rfd);
+   }
+   if (stat1 < 0) {
+      berrno be;
+      Dmsg2(150, "Run program fgets stat=%d ERR=%s\n", stat1, be.bstrerror(errno));
+   } else if (stat1 != 0) {
+      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_strcpy(results, _("Program killed by Bacula (timeout)\n"));
          }
       }
-   } else {
-      stat1 = 0;
    }
    stat2 = close_bpipe(bpipe);
    stat1 = stat2 != 0 ? stat2 : stat1;
@@ -373,7 +384,7 @@ int run_program(char *prog, int wait, POOLMEM *results)
  *           non-zero on error == berrno status
  *
  */
-int run_program_full_output(char *prog, int wait, POOLMEM *results)
+int run_program_full_output(char *prog, int wait, POOLMEM *&results)
 {
    BPIPE *bpipe;
    int stat1, stat2;
@@ -382,21 +393,16 @@ int run_program_full_output(char *prog, int wait, POOLMEM *results)
    char *buf;
    const int bufsize = 32000;
 
-   if (results == NULL) {
-      return run_program(prog, wait, NULL);
-   }
    
    sm_check(__FILE__, __LINE__, false);
 
    tmp = get_pool_memory(PM_MESSAGE);
    buf = (char *)malloc(bufsize+1);
    
+   results[0] = 0;
    mode = (char *)"r";
    bpipe = open_bpipe(prog, wait, mode);
    if (!bpipe) {
-      if (results) {
-         results[0] = 0;
-      }
       return ENOENT;
    }
    
@@ -416,22 +422,28 @@ int run_program_full_output(char *prog, int wait, POOLMEM *results)
       }
       if (stat1 < 0) {
          berrno be;
-         Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.strerror());
+         Dmsg2(200, "Run program fgets stat=%d ERR=%s\n", stat1, be.bstrerror());
          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;
-            }
+         if (bpipe->timer_id && bpipe->timer_id->killed) {
+            Dmsg1(250, "Run program saw fgets killed=%d\n", bpipe->timer_id->killed);
+            break;
          }
       }
    }
-   int len = sizeof_pool_memory(results) - 1;
-   bstrncpy(results, tmp, len);
+   /*
+    * We always check whether the timer killed the program. We would see
+    * an eof even when it does so we just have to trust the killed flag
+    * and set the timer values to avoid edge cases where the program ends
+    * just as the timer kills it.
+    */
+   if (bpipe->timer_id && bpipe->timer_id->killed) {
+      Dmsg1(150, "Run program fgets killed=%d\n", bpipe->timer_id->killed);
+      pm_strcpy(tmp, _("Program killed by Bacula (timeout)\n"));
+      stat1 = ETIME;
+   }
+   pm_strcpy(results, tmp);
    Dmsg3(1900, "resadr=0x%x reslen=%d res=%s\n", results, strlen(results), results);
    stat2 = close_bpipe(bpipe);
    stat1 = stat2 != 0 ? stat2 : stat1;