Imported Upstream version 2.5.1p3
[debian/amanda] / client-src / sendsize.c
index c13f8754d28ceaa0f248953bea4fa77f08aa92b0..e99071c24f9747a25d079fd2ee4374e9c2463656 100644 (file)
@@ -24,7 +24,7 @@
  * file named AUTHORS, in the root directory of this distribution.
  */
 /* 
- * $Id: sendsize.c,v 1.97.2.13.4.6.2.23 2003/10/24 20:38:23 kovert Exp $
+ * $Id: sendsize.c,v 1.171.2.4 2006/12/22 14:42:42 martinea Exp $
  *
  * send estimated backup sizes using dump
  */
@@ -38,6 +38,8 @@
 #include "getfsent.h"
 #include "version.h"
 #include "client_util.h"
+#include "clientconf.h"
+#include "amandad.h"
 
 #ifdef SAMBA_CLIENT
 #include "findpass.h"
@@ -76,9 +78,14 @@ typedef struct level_estimates_s {
 typedef struct disk_estimates_s {
     struct disk_estimates_s *next;
     char *amname;
+    char *qamname;
     char *amdevice;
+    char *qamdevice;
     char *dirname;
+    char *qdirname;
     char *program;
+    char *calcprog;
+    int program_is_wrapper;
     int spindle;
     pid_t child;
     int done;
@@ -93,24 +100,29 @@ static char *our_feature_string = NULL;
 static g_option_t *g_options = NULL;
 
 /* local functions */
-int main P((int argc, char **argv));
-void add_diskest P((char *disk, char *amdevice, int level, int spindle,
-                   char *prog, option_t *options));
-void calc_estimates P((disk_estimates_t *est));
-void free_estimates P((disk_estimates_t *est));
-void dump_calc_estimates P((disk_estimates_t *));
-void smbtar_calc_estimates P((disk_estimates_t *));
-void gnutar_calc_estimates P((disk_estimates_t *));
-void generic_calc_estimates P((disk_estimates_t *));
-
-
-int main(argc, argv)
-int argc;
-char **argv;
+int main(int argc, char **argv);
+void add_diskest(char *disk, char *amdevice, int level, int spindle, 
+                   int program_is_wrapper, char *prog, char *calcprog,
+                   option_t *options);
+void calc_estimates(disk_estimates_t *est);
+void free_estimates(disk_estimates_t *est);
+void dump_calc_estimates(disk_estimates_t *);
+void star_calc_estimates(disk_estimates_t *);
+void smbtar_calc_estimates(disk_estimates_t *);
+void gnutar_calc_estimates(disk_estimates_t *);
+void wrapper_calc_estimates(disk_estimates_t *);
+void generic_calc_estimates(disk_estimates_t *);
+
+
+int
+main(
+    int                argc,
+    char **    argv)
 {
     int level, spindle;
-    char *prog, *disk, *amdevice, *dumpdate;
+    char *prog, *calcprog, *dumpdate;
     option_t *options = NULL;
+    int program_is_wrapper;
     disk_estimates_t *est;
     disk_estimates_t *est1;
     disk_estimates_t *est_prev;
@@ -118,34 +130,41 @@ char **argv;
     char *s, *fp;
     int ch;
     char *err_extra = NULL;
-    int fd;
-    unsigned long malloc_hist_1, malloc_size_1;
-    unsigned long malloc_hist_2, malloc_size_2;
     int done;
     int need_wait;
     int dumpsrunning;
+    char *disk = NULL;
+    char *qdisk = NULL;
+    char *qlist = NULL;
+    char *amdevice = NULL;
+    char *qamdevice = NULL;
+    char *conffile;
+    char *amandates_file;
+    int   amandates_read = 0;
+#if defined(USE_DBMALLOC)
+    unsigned long malloc_hist_1, malloc_size_1;
+    unsigned long malloc_hist_2, malloc_size_2;
+#endif
 
+    (void)argc;        /* Quiet unused parameter warning */
+    (void)argv;        /* Quiet unused parameter warning */
 
     /* initialize */
 
-    for(fd = 3; fd < FD_SETSIZE; fd++) {
-       /*
-        * Make sure nobody spoofs us with a lot of extra open files
-        * that would cause an open we do to get a very high file
-        * descriptor, which in turn might be used as an index into
-        * an array (e.g. an fd_set).
-        */
-       close(fd);
-    }
-
+    safe_fd(-1, 0);
     safe_cd();
 
     set_pname("sendsize");
 
+    /* Don't die when child closes pipe */
+    signal(SIGPIPE, SIG_IGN);
+
+#if defined(USE_DBMALLOC)
     malloc_size_1 = malloc_inuse(&malloc_hist_1);
+#endif
 
     erroutput_type = (ERR_INTERACTIVE|ERR_SYSLOG);
-    dbopen();
+    dbopen(DBG_SUBDIR_CLIENT);
     startclock();
     dbprintf(("%s: version %s\n", get_pname(), version()));
 
@@ -154,13 +173,20 @@ char **argv;
 
     set_debug_prefix_pid(getpid());
 
-    /* handle all service requests */
+    conffile = vstralloc(CONFIG_DIR, "/", "amanda-client.conf", NULL);
+    if (read_clientconf(conffile) > 0) {
+       error("error reading conffile: %s", conffile);
+       /*NOTREACHED*/
+    }
+    amfree(conffile);
 
-    start_amandates(0);
+    /* handle all service requests */
 
     for(; (line = agets(stdin)) != NULL; free(line)) {
+       if (line[0] == '\0')
+           continue;
 #define sc "OPTIONS "
-       if(strncmp(line, sc, sizeof(sc)-1) == 0) {
+       if(strncmp(line, sc, SIZEOF(sc)-1) == 0) {
 #undef sc
            g_options = parse_g_options(line+8, 1);
            if(!g_options->hostname) {
@@ -181,73 +207,135 @@ char **argv;
            }
            printf("\n");
            fflush(stdout);
+
+           if (g_options->config) {
+               conffile = vstralloc(CONFIG_DIR, "/", g_options->config, "/",
+                                    "amanda-client.conf", NULL);
+               if (read_clientconf(conffile) > 0) {
+                   error("error reading conffile: %s", conffile);
+                   /*NOTREACHED*/
+               }
+               amfree(conffile);
+
+               dbrename(g_options->config, DBG_SUBDIR_CLIENT);
+           }
+
            continue;
        }
 
+       if (amandates_read == 0) {
+           amandates_file = client_getconf_str(CLN_AMANDATES);
+           if(!start_amandates(amandates_file, 0))
+               error("error [opening %s: %s]", amandates_file,
+                     strerror(errno));
+           amandates_read = 1;
+       }
+
        s = line;
        ch = *s++;
 
        skip_whitespace(s, ch);                 /* find the program name */
        if(ch == '\0') {
-           err_extra = "no program name";
+           err_extra = stralloc("no program name");
            goto err;                           /* no program name */
        }
        prog = s - 1;
        skip_non_whitespace(s, ch);
        s[-1] = '\0';
 
+       program_is_wrapper=0;
+       if(strcmp(prog,"DUMPER")==0) {
+           program_is_wrapper=1;
+           skip_whitespace(s, ch);             /* find dumper name */
+           if (ch == '\0') {
+               goto err;                       /* no program */
+           }
+           prog = s - 1;
+           skip_non_whitespace(s, ch);
+           s[-1] = '\0';
+       }
+
+       if(strncmp(prog, "CALCSIZE", 8) == 0) {
+           skip_whitespace(s, ch);             /* find the program name */
+           if(ch == '\0') {
+               err_extra = stralloc("no program name");
+               goto err;
+           }
+           calcprog = s - 1;
+           skip_non_whitespace(s, ch);
+           s[-1] = '\0';
+       }
+       else {
+           calcprog = NULL;
+       }
+
        skip_whitespace(s, ch);                 /* find the disk name */
        if(ch == '\0') {
-           err_extra = "no disk name";
+           err_extra = stralloc("no disk name");
            goto err;                           /* no disk name */
        }
-       disk = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
+
+       if (qdisk != NULL)
+           amfree(qdisk);
+       if (disk != NULL)
+           amfree(disk);
+
+       fp = s - 1;
+       skip_quoted_string(s, ch);
+       s[-1] = '\0';                           /* terminate the disk name */
+       qdisk = stralloc(fp);
+       disk = unquote_string(qdisk);
 
        skip_whitespace(s, ch);                 /* find the device or level */
        if (ch == '\0') {
-           err_extra = "bad level";
+           err_extra = stralloc("bad level");
            goto err;
        }
        if(!isdigit((int)s[-1])) {
            fp = s - 1;
-           skip_non_whitespace(s, ch);
+           skip_quoted_string(s, ch);
            s[-1] = '\0';
-           amdevice = stralloc(fp);
+           qamdevice = stralloc(fp);
+           amdevice = unquote_string(qamdevice);
            skip_whitespace(s, ch);             /* find level number */
        }
        else {
            amdevice = stralloc(disk);
+           qamdevice = stralloc(qdisk);
        }
 
                                                /* find the level number */
        if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
-           err_extra = "bad level";
+           err_extra = stralloc("bad level");
            goto err;                           /* bad level */
        }
+       if (level < 0 || level >= DUMP_LEVELS) {
+           err_extra = stralloc("bad level");
+           goto err;
+       }
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);                 /* find the dump date */
        if(ch == '\0') {
-           err_extra = "no dumpdate";
+           err_extra = stralloc("no dumpdate");
            goto err;                           /* no dumpdate */
        }
        dumpdate = s - 1;
        skip_non_whitespace(s, ch);
        s[-1] = '\0';
+       (void)dumpdate;                         /* XXX: Set but not used */
 
        spindle = 0;                            /* default spindle */
 
        skip_whitespace(s, ch);                 /* find the spindle */
        if(ch != '\0') {
            if(sscanf(s - 1, "%d", &spindle) != 1) {
-               err_extra = "bad spindle";
+               err_extra = stralloc("bad spindle");
                goto err;                       /* bad spindle */
            }
            skip_integer(s, ch);
 
-           skip_whitespace(s, ch);             /* find the exclusion list */
+           skip_whitespace(s, ch);             /* find the parameters */
            if(ch != '\0') {
                if(strncmp(s-1, "OPTIONS |;",10) == 0) {
                    options = parse_options(s + 8,
@@ -257,32 +345,61 @@ char **argv;
                                            0);
                }
                else {
-                   options = alloc(sizeof(option_t));
+                   options = alloc(SIZEOF(option_t));
                    init_options(options);
-                   if(strncmp(s-1, "exclude-file=", 13) == 0) {
-                       options->exclude_file =
-                               append_sl(options->exclude_file, s+12);
-                   }
-                   if(strncmp(s-1, "exclude-list=", 13) == 0) {
-                       options->exclude_list =
-                               append_sl(options->exclude_list, s+12);
-                   }
-
-                   skip_non_whitespace(s, ch);
-                   if(ch) {
-                       err_extra = "extra text at end";
-                       goto err;               /* should have gotten to end */
+                   while (ch != '\0') {
+                       if(strncmp(s-1, "exclude-file=", 13) == 0) {
+                           qlist = unquote_string(s+12);
+                           options->exclude_file =
+                               append_sl(options->exclude_file, qlist);
+                           amfree(qlist);
+                       } else if(strncmp(s-1, "exclude-list=", 13) == 0) {
+                           options->exclude_list =
+                               append_sl(options->exclude_list, qlist);
+                           qlist = unquote_string(s+12);
+                           amfree(qlist);
+                       } else if(strncmp(s-1, "include-file=", 13) == 0) {
+                           options->include_file =
+                               append_sl(options->include_file, qlist);
+                           qlist = unquote_string(s+12);
+                           amfree(qlist);
+                       } else if(strncmp(s-1, "include-list=", 13) == 0) {
+                           options->include_list =
+                               append_sl(options->include_list, qlist);
+                           qlist = unquote_string(s+12);
+                           amfree(qlist);
+                       } else {
+                           err_extra = vstralloc("Invalid parameter (",
+                               s-1, ")", NULL);
+                           goto err;           /* should have gotten to end */
+                       }
+                       skip_quoted_string(s, ch);
+                       skip_whitespace(s, ch); /* find the inclusion list */
+                       amfree(qlist);
                    }
                }
            }
            else {
-               options = alloc(sizeof(option_t));
+               options = alloc(SIZEOF(option_t));
                init_options(options);
            }
        }
+       else {
+           options = alloc(SIZEOF(option_t));
+           init_options(options);
+       }
 
-       add_diskest(disk, amdevice, level, spindle, prog, options);
+       /*@ignore@*/
+       add_diskest(disk, amdevice, level, spindle, program_is_wrapper, prog, calcprog, options);
+       /*@end@*/
+       amfree(disk);
+       amfree(qdisk);
        amfree(amdevice);
+       amfree(qamdevice);
+    }
+    if (g_options == NULL) {
+       error("Missing OPTIONS line in sendsize input\n");
+       /*NOTREACHED*/
     }
     amfree(line);
 
@@ -309,6 +426,7 @@ char **argv;
            child_pid = wait(&child_status);
            if(child_pid == -1) {
                error("wait failed: %s", strerror(errno));
+               /*NOTREACHED*/
            }
            if(WIFSIGNALED(child_status)) {
                dbprintf(("%s: child %ld terminated with signal %d\n",
@@ -395,6 +513,7 @@ char **argv;
                exit(0);
            } else if(est->child == -1) {
                error("calc_estimates fork failed: %s", strerror(errno));
+               /*NOTREACHED*/
            }
            dumpsrunning++;                     /* parent */
        }
@@ -412,17 +531,17 @@ char **argv;
     our_features = NULL;
     am_release_feature_set(g_options->features);
     g_options->features = NULL;
-    amfree(g_options->str);
     amfree(g_options->hostname);
+    amfree(g_options->str);
     amfree(g_options);
 
+#if defined(USE_DBMALLOC)
     malloc_size_2 = malloc_inuse(&malloc_hist_2);
 
     if(malloc_size_1 != malloc_size_2) {
-#if defined(USE_DBMALLOC)
        malloc_list(dbfd(), malloc_hist_1, malloc_hist_2);
-#endif
     }
+#endif
 
     dbclose();
     return 0;
@@ -432,21 +551,33 @@ char **argv;
              debug_prefix_time(NULL),
              err_extra ? ": " : "",
              err_extra ? err_extra : ""));
+    amfree(err_extra);
     dbclose();
     return 1;
 }
 
 
-void add_diskest(disk, amdevice, level, spindle, prog, options)
-char *disk, *amdevice, *prog;
-int level, spindle;
-option_t *options;
+void
+add_diskest(
+    char *     disk,
+    char *     amdevice,
+    int                level,
+    int                spindle,
+    int                program_is_wrapper,
+    char *     prog,
+    char *     calcprog,
+    option_t * options)
 {
     disk_estimates_t *newp, *curp;
     amandates_t *amdp;
     int dumplev, estlev;
     time_t dumpdate;
 
+    if (level < 0)
+       level = 0;
+    if (level >= DUMP_LEVELS)
+       level = DUMP_LEVELS - 1;
+
     for(curp = est_list; curp != NULL; curp = curp->next) {
        if(strcmp(curp->amname, disk) == 0) {
            /* already have disk info, just note the level request */
@@ -456,6 +587,7 @@ option_t *options;
                free_sl(options->exclude_list);
                free_sl(options->include_file);
                free_sl(options->include_list);
+               amfree(options->auth);
                amfree(options->str);
                amfree(options);
            }
@@ -463,14 +595,22 @@ option_t *options;
        }
     }
 
-    newp = (disk_estimates_t *) alloc(sizeof(disk_estimates_t));
-    memset(newp, 0, sizeof(*newp));
+    newp = (disk_estimates_t *) alloc(SIZEOF(disk_estimates_t));
+    memset(newp, 0, SIZEOF(*newp));
     newp->next = est_list;
     est_list = newp;
     newp->amname = stralloc(disk);
+    newp->qamname = quote_string(disk);
     newp->amdevice = stralloc(amdevice);
+    newp->qamdevice = quote_string(amdevice);
     newp->dirname = amname_to_dirname(newp->amdevice);
+    newp->qdirname = quote_string(newp->dirname);
     newp->program = stralloc(prog);
+    if(calcprog != NULL)
+       newp->calcprog = stralloc(calcprog);
+    else
+       newp->calcprog = NULL;
+    newp->program_is_wrapper = program_is_wrapper;
     newp->spindle = spindle;
     newp->est[level].needestimate = 1;
     newp->options = options;
@@ -490,12 +630,16 @@ option_t *options;
 }
 
 
-void free_estimates(est)
-disk_estimates_t *est;
+void
+free_estimates(
+    disk_estimates_t * est)
 {
     amfree(est->amname);
+    amfree(est->qamname);
     amfree(est->amdevice);
+    amfree(est->qamdevice);
     amfree(est->dirname);
+    amfree(est->qdirname);
     amfree(est->program);
     if(est->options) {
        free_sl(est->options->exclude_file);
@@ -503,6 +647,7 @@ disk_estimates_t *est;
        free_sl(est->options->include_file);
        free_sl(est->options->include_list);
        amfree(est->options->str);
+       amfree(est->options->auth);
        amfree(est->options);
     }
 }
@@ -512,13 +657,17 @@ disk_estimates_t *est;
  *
  */
 
-void calc_estimates(est)
-disk_estimates_t *est;
+void
+calc_estimates(
+    disk_estimates_t * est)
 {
-    dbprintf(("%s: calculating for amname '%s', dirname '%s', spindle %d\n",
+    dbprintf(("%s: calculating for amname %s, dirname %s, spindle %d\n",
              debug_prefix_time(NULL),
-             est->amname, est->dirname, est->spindle));
-
+             est->qamname, est->qdirname, est->spindle));
+       
+    if(est->program_is_wrapper ==  1)
+       wrapper_calc_estimates(est);
+    else
 #ifndef USE_GENERIC_CALCSIZE
     if(strcmp(est->program, "DUMP") == 0)
        dump_calc_estimates(est);
@@ -535,109 +684,223 @@ disk_estimates_t *est;
          gnutar_calc_estimates(est);
        else
 #endif
-         generic_calc_estimates(est);
+#ifdef SAMBA_CLIENT
+         if (est->amdevice[0] == '/' && est->amdevice[1] == '/')
+           dbprintf(("%s: Can't use CALCSIZE for samba estimate: %s %s\n",
+                     debug_prefix_time(NULL),
+                     est->qamname, est->qdirname));
+         else
+#endif
+           generic_calc_estimates(est);
 
-    dbprintf(("%s: done with amname '%s', dirname '%s', spindle %d\n",
+    dbprintf(("%s: done with amname %s dirname %s spindle %d\n",
              debug_prefix_time(NULL),
-             est->amname, est->dirname, est->spindle));
+             est->qamname, est->qdirname, est->spindle));
+}
+
+/*
+ * ------------------------------------------------------------------------
+ *
+ */
+
+/* local functions */
+off_t getsize_dump(char *disk, char *amdevice, int level, option_t *options);
+off_t getsize_star(char *disk, char *amdevice, int level,
+                      option_t *options, time_t dumpsince);
+off_t getsize_smbtar(char *disk, char *amdevice, int level, option_t *options);
+off_t getsize_gnutar(char *disk, char *amdevice, int level,
+                      option_t *options, time_t dumpsince);
+off_t getsize_wrapper(char *program, char *disk, char *amdevice, int level,
+                       option_t *options, time_t dumpsince);
+off_t handle_dumpline(char *str);
+double first_num(char *str);
+
+void
+wrapper_calc_estimates(
+    disk_estimates_t * est)
+{
+  int level;
+  off_t size;
+
+  for(level = 0; level < DUMP_LEVELS; level++) {
+      if (est->est[level].needestimate) {
+         dbprintf(("%s: getting size via wrapper for %s level %d\n",
+                   debug_prefix_time(NULL), est->qamname, level));
+         size = getsize_wrapper(est->program, est->amname, est->amdevice,
+                       level, est->options, est->est[level].dumpsince);
+
+         amflock(1, "size");
+
+         if (fseek(stdout, 0L, SEEK_END) < 0) {
+             dbprintf(("wrapper_calc_estimates: warning - seek failed: %s\n",
+                       strerror(errno)));
+         }
+
+         printf("%s %d SIZE " OFF_T_FMT "\n", est->qamname, level,
+                (OFF_T_FMT_TYPE)size);
+         fflush(stdout);
+
+         amfunlock(1, "size");
+      }
+  }
 }
 
-void generic_calc_estimates(est)
-disk_estimates_t *est;
+
+void
+generic_calc_estimates(
+    disk_estimates_t * est)
 {
+    int pipefd = -1, nullfd = -1;
     char *cmd;
-    char *argv[DUMP_LEVELS*2+10];
+    char *my_argv[DUMP_LEVELS*2+22];
     char number[NUM_STR_SIZE];
-    int i, level, argc, calcpid;
+    int i, level, my_argc, status;
+    pid_t calcpid;
+    int nb_exclude = 0;
+    int nb_include = 0;
+    char *file_exclude = NULL;
+    char *file_include = NULL;
+    times_t start_time;
+    FILE *dumpout = NULL;
+    off_t size = (off_t)1;
+    char *line = NULL;
+    char *match_expr;
 
     cmd = vstralloc(libexecdir, "/", "calcsize", versionsuffix(), NULL);
 
-    argc = 0;
-    argv[argc++] = stralloc("calcsize");
-    argv[argc++] = stralloc(est->program);
-#ifdef BUILTIN_EXCLUDE_SUPPORT
-    if(est->exclude && *est->exclude) {
-       argv[argc++] = stralloc("-X");
-       argv[argc++] = stralloc(est->exclude);
+    my_argc = 0;
+
+    my_argv[my_argc++] = stralloc("calcsize");
+    if (g_options->config)
+       my_argv[my_argc++] = stralloc(g_options->config);
+    else
+       my_argv[my_argc++] = stralloc("NOCONFIG");
+
+    my_argv[my_argc++] = stralloc(est->calcprog);
+
+    my_argv[my_argc++] = stralloc(est->amname);
+    my_argv[my_argc++] = stralloc(est->dirname);
+
+
+    if(est->options->exclude_file)
+       nb_exclude += est->options->exclude_file->nb_element;
+    if(est->options->exclude_list)
+       nb_exclude += est->options->exclude_list->nb_element;
+    if(est->options->include_file)
+       nb_include += est->options->include_file->nb_element;
+    if(est->options->include_list)
+       nb_include += est->options->include_list->nb_element;
+
+    if(nb_exclude > 0)
+       file_exclude = build_exclude(est->amname,
+               est->amdevice, est->options, 0);
+    if(nb_include > 0)
+       file_include = build_include(est->amname,
+               est->amdevice, est->options, 0);
+
+    if(file_exclude) {
+       my_argv[my_argc++] = stralloc("-X");
+       my_argv[my_argc++] = file_exclude;
     }
-#endif
-    argv[argc++] = stralloc(est->amdevice);
-    argv[argc++] = stralloc(est->dirname);
 
-    dbprintf(("%s: running cmd: %s", debug_prefix_time(NULL), argv[0]));
-    for(i=0; i<argc; ++i)
-       dbprintf((" %s", argv[i]));
+    if(file_include) {
+       my_argv[my_argc++] = stralloc("-I");
+       my_argv[my_argc++] = file_include;
+    }
+    start_time = curclock();
+
+    dbprintf(("%s: running cmd: %s", debug_prefix_time(NULL), my_argv[0]));
+    for(i=0; i<my_argc; ++i)
+       dbprintf((" %s", my_argv[i]));
 
     for(level = 0; level < DUMP_LEVELS; level++) {
        if(est->est[level].needestimate) {
-           ap_snprintf(number, sizeof(number), "%d", level);
-           argv[argc++] = stralloc(number); 
+           snprintf(number, SIZEOF(number), "%d", level);
+           my_argv[my_argc++] = stralloc(number); 
            dbprintf((" %s", number));
-           ap_snprintf(number, sizeof(number),
+           snprintf(number, SIZEOF(number),
                        "%ld", (long)est->est[level].dumpsince);
-           argv[argc++] = stralloc(number); 
+           my_argv[my_argc++] = stralloc(number); 
            dbprintf((" %s", number));
        }
     }
-    argv[argc] = NULL;
+    my_argv[my_argc] = NULL;
     dbprintf(("\n"));
 
     fflush(stderr); fflush(stdout);
 
-    switch(calcpid = fork()) {
-    case -1:
-        error("%s: fork returned: %s", cmd, strerror(errno));
-    default:
-        break;
-    case 0:
-       execve(cmd, argv, safe_env());
-       error("%s: execve returned: %s", cmd, strerror(errno));
-       exit(1);
-    }
-    for(i = 0; i < argc; i++) {
-       amfree(argv[i]);
+    if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+       dbprintf(("Cannot access /dev/null : %s\n", strerror(errno)));
+       goto common_exit;
     }
+
+    calcpid = pipespawnv(cmd, STDERR_PIPE, &nullfd, &nullfd, &pipefd, my_argv);
     amfree(cmd);
 
-    dbprintf(("%s: waiting for %s \"%s\" child\n",
-             debug_prefix_time(NULL), argv[0], est->amdevice));
-    wait(NULL);
-    dbprintf(("%s: after %s \"%s\" wait\n",
-             debug_prefix_time(NULL), argv[0], est->amdevice));
-}
+    dumpout = fdopen(pipefd,"r");
+    if (!dumpout) {
+       error("Can't fdopen: %s", strerror(errno));
+       /*NOTREACHED*/
+    }
+    match_expr = vstralloc(est->qamname," %d SIZE " OFF_T_FMT, NULL);
+    for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
+       if (line[0] == '\0')
+           continue;
+       if(sscanf(line, match_expr, &level, &size) == 2) {
+           printf("%s\n", line); /* write to amandad */
+           dbprintf(("%s: estimate size for %s level %d: " OFF_T_FMT " KB\n",
+                     debug_prefix(NULL),
+                     est->qamname,
+                     level,
+                     size));
+       }
+    }
+    amfree(match_expr);
 
+    dbprintf(("%s: waiting for %s %s child (pid=%d)\n",
+             debug_prefix_time(NULL), my_argv[0], est->qamdevice, calcpid));
+    wait(&status);
+    dbprintf(("%s: after %s %s wait: child pid=%d status=%d\n",
+             debug_prefix_time(NULL), my_argv[0], est->qamdevice,
+             calcpid, WEXITSTATUS(status)));
 
-/*
- * ------------------------------------------------------------------------
- *
- */
+    dbprintf(("%s: .....\n", debug_prefix_time(NULL)));
+    dbprintf(("%s: estimate time for %s: %s\n",
+             debug_prefix(NULL),
+             est->qamname,
+             walltime_str(timessub(curclock(), start_time))));
 
-/* local functions */
-void dump_calc_estimates P((disk_estimates_t *est));
-long getsize_dump P((char *disk, char *amdevice, int level, option_t *options));
-long getsize_smbtar P((char *disk, char *amdevice, int level, option_t *options));
-long getsize_gnutar P((char *disk, char *amdevice, int level,
-                      option_t *options, time_t dumpsince));
-long handle_dumpline P((char *str));
-double first_num P((char *str));
-
-void dump_calc_estimates(est)
-disk_estimates_t *est;
+common_exit:
+    for(i = 0; i < my_argc; i++) {
+       amfree(my_argv[i]);
+    }
+    amfree(cmd);
+}
+
+
+void
+dump_calc_estimates(
+    disk_estimates_t * est)
 {
     int level;
-    long size;
+    off_t size;
 
     for(level = 0; level < DUMP_LEVELS; level++) {
        if(est->est[level].needestimate) {
            dbprintf(("%s: getting size via dump for %s level %d\n",
-                     debug_prefix_time(NULL), est->amname, level));
-           size = getsize_dump(est->amname, est->amdevice,level, est->options);
+                     debug_prefix_time(NULL), est->qamname, level));
+           size = getsize_dump(est->amname, est->amdevice,
+                       level, est->options);
 
            amflock(1, "size");
 
-           fseek(stdout, (off_t)0, SEEK_SET);
+           if (fseek(stdout, 0L, SEEK_END) < 0) {
+               dbprintf(("dump_calc_estimates: warning - seek failed: %s\n",
+                               strerror(errno)));
+           }
 
-           printf("%s %d SIZE %ld\n", est->amname, level, size);
+           printf("%s %d SIZE " OFF_T_FMT "\n",
+                  est->qamname, level, (OFF_T_FMT_TYPE)size);
            fflush(stdout);
 
            amfunlock(1, "size");
@@ -646,23 +909,28 @@ disk_estimates_t *est;
 }
 
 #ifdef SAMBA_CLIENT
-void smbtar_calc_estimates(est)
-disk_estimates_t *est;
+void
+smbtar_calc_estimates(
+    disk_estimates_t * est)
 {
     int level;
-    long size;
+    off_t size;
 
     for(level = 0; level < DUMP_LEVELS; level++) {
        if(est->est[level].needestimate) {
            dbprintf(("%s: getting size via smbclient for %s level %d\n",
-                     debug_prefix_time(NULL), est->amname, level));
+                     debug_prefix_time(NULL), est->qamname, level));
            size = getsize_smbtar(est->amname, est->amdevice, level, est->options);
 
            amflock(1, "size");
 
-           fseek(stdout, (off_t)0, SEEK_SET);
+           if (fseek(stdout, 0L, SEEK_END) < 0) {
+               dbprintf(("smbtar_calc_estimates: warning - seek failed: %s\n",
+                               strerror(errno)));
+           }
 
-           printf("%s %d SIZE %ld\n", est->amname, level, size);
+           printf("%s %d SIZE " OFF_T_FMT "\n",
+                  est->qamname, level, (OFF_T_FMT_TYPE)size);
            fflush(stdout);
 
            amfunlock(1, "size");
@@ -672,24 +940,29 @@ disk_estimates_t *est;
 #endif
 
 #ifdef GNUTAR
-void gnutar_calc_estimates(est)
-disk_estimates_t *est;
+void
+gnutar_calc_estimates(
+    disk_estimates_t * est)
 {
   int level;
-  long size;
+  off_t size;
 
   for(level = 0; level < DUMP_LEVELS; level++) {
       if (est->est[level].needestimate) {
          dbprintf(("%s: getting size via gnutar for %s level %d\n",
-                   debug_prefix_time(NULL), est->amname, level));
+                   debug_prefix_time(NULL), est->qamname, level));
          size = getsize_gnutar(est->amname, est->amdevice, level,
                                est->options, est->est[level].dumpsince);
 
          amflock(1, "size");
 
-         fseek(stdout, (off_t)0, SEEK_SET);
+         if (fseek(stdout, 0L, SEEK_END) < 0) {
+             dbprintf(("gnutar_calc_estimates: warning - seek failed: %s\n",
+                               strerror(errno)));
+         }
 
-         printf("%s %d SIZE %ld\n", est->amname, level, size);
+         printf("%s %d SIZE " OFF_T_FMT "\n",
+                est->qamname, level, (OFF_T_FMT_TYPE)size);
          fflush(stdout);
 
          amfunlock(1, "size");
@@ -703,12 +976,13 @@ typedef struct regex_s {
     int scale;
 } regex_t;
 
+/*@ignore@*/
 regex_t re_size[] = {
 #ifdef DUMP
     {"  DUMP: estimated -*[0-9][0-9]* tape blocks", 1024},
     {"  DUMP: [Ee]stimated [0-9][0-9]* blocks", 512},
-    {"  DUMP: [Ee]stimated [0-9][0-9]* bytes", 1},            /* Ultrix 4.4 */
-    {" UFSDUMP: estimated [0-9][0-9]* blocks", 512},           /* NEC EWS-UX */
+    {"  DUMP: [Ee]stimated [0-9][0-9]* bytes", 1},             /* Ultrix 4.4 */
+    {" UFSDUMP: estimated [0-9][0-9]* blocks", 512},           /* NEC EWS-UX */
     {"dump: Estimate: [0-9][0-9]* tape blocks", 1024},             /* OSF/1 */
     {"backup: There are an estimated [0-9][0-9]* tape blocks.",1024}, /* AIX */
     {"backup: estimated [0-9][0-9]* 1k blocks", 1024},               /* AIX */
@@ -716,37 +990,33 @@ regex_t re_size[] = {
     {"backup: [0-9][0-9]* tape blocks on [0-9][0-9]* tape(s)",1024},  /* AIX */
     {"backup: [0-9][0-9]* 1k blocks on [0-9][0-9]* volume(s)",1024},  /* AIX */
     {"dump: Estimate: [0-9][0-9]* blocks being output to pipe",1024},
-                                                              /* DU 4.0 dump */
-    {"dump: Dumping [0-9][0-9]* bytes, ", 1},                /* DU 4.0 vdump */
-    {"DUMP: estimated [0-9][0-9]* KB output", 1024},                 /* HPUX */
-    {"DUMP: estimated [0-9][0-9]* KB\\.", 1024},                 /* NetApp */
-    {"  UFSDUMP: estimated [0-9][0-9]* blocks", 512},               /* Sinix */
+                                                             /* DU 4.0 dump  */
+    {"dump: Dumping [0-9][0-9]* bytes, ", 1},                /* DU 4.0 vdump */
+    {"DUMP: estimated [0-9][0-9]* KB output", 1024},                 /* HPUX */
+    {"DUMP: estimated [0-9][0-9]* KB\\.", 1024},                   /* NetApp */
+    {"  UFSDUMP: estimated [0-9][0-9]* blocks", 512},               /* Sinix */
 
 #ifdef HAVE_DUMP_ESTIMATE
     {"[0-9][0-9]* blocks, [0-9][0-9]*.[0-9][0-9]* volumes", 1024},
-                                                          /* DU 3.2g dump -E */
-    {"^[0-9][0-9]* blocks$", 1024},                      /* DU 4.0 dump  -E */
-    {"^[0-9][0-9]*$", 1},                             /* Solaris ufsdump -S */
+                                                          /* DU 3.2g dump -E */
+    {"^[0-9][0-9]* blocks$", 1024},                       /* DU 4.0 dump  -E */
+    {"^[0-9][0-9]*$", 1},                              /* Solaris ufsdump -S */
 #endif
 #endif
 
 #ifdef VDUMP
-    {"vdump: Dumping [0-9][0-9]* bytes, ", 1},               /* OSF/1 vdump */
+    {"vdump: Dumping [0-9][0-9]* bytes, ", 1},                /* OSF/1 vdump */
 #endif
     
 #ifdef VXDUMP
-    {"vxdump: estimated [0-9][0-9]* blocks", 512},          /* HPUX's vxdump */
-    {"  VXDUMP: estimated [0-9][0-9]* blocks", 512},                /* Sinix */
+    {"vxdump: estimated [0-9][0-9]* blocks", 512},          /* HPUX's vxdump */
+    {"  VXDUMP: estimated [0-9][0-9]* blocks", 512},                /* Sinix */
 #endif
 
 #ifdef XFSDUMP
     {"xfsdump: estimated dump size: [0-9][0-9]* bytes", 1},  /* Irix 6.2 xfs */
 #endif
 
-#ifdef USE_QUICK_AND_DIRTY_ESTIMATES
-    {"amqde estimate: [0-9][0-9]* kb", 1024},                      /* amqde */
-#endif
-    
 #ifdef GNUTAR
     {"Total bytes written: [0-9][0-9]*", 1},               /* Gnutar client */
 #endif
@@ -763,16 +1033,18 @@ regex_t re_size[] = {
 
     { NULL, 0 }
 };
-
-
-long getsize_dump(disk, amdevice, level, options)
-    char *disk, *amdevice;
-    int level;
-    option_t *options;
+/*@end@*/
+
+off_t
+getsize_dump(
+    char       *disk,
+    char       *amdevice,
+    int                level,
+    option_t * options)
 {
     int pipefd[2], nullfd, stdoutfd, killctl[2];
     pid_t dumppid;
-    long size;
+    off_t size;
     FILE *dumpout;
     char *dumpkeys = NULL;
     char *device = NULL;
@@ -784,21 +1056,55 @@ long getsize_dump(disk, amdevice, level, options)
     char level_str[NUM_STR_SIZE];
     int s;
     times_t start_time;
+    char *qdisk = quote_string(disk);
+    char *qdevice;
+    char *config;
+#if defined(DUMP) || defined(VDUMP) || defined(VXDUMP) || defined(XFSDUMP)
+    int is_rundump = 1;
+#endif
+
+    (void)options;     /* Quiet unused parameter warning */
+
+    (void)getsize_smbtar;      /* Quiet unused parameter warning */
 
-    ap_snprintf(level_str, sizeof(level_str), "%d", level);
+    snprintf(level_str, SIZEOF(level_str), "%d", level);
 
     device = amname_to_devname(amdevice);
+    qdevice = quote_string(device);
     fstype = amname_to_fstype(amdevice);
 
-    dbprintf(("%s: calculating for device '%s' with '%s'\n",
-             debug_prefix_time(NULL), device, fstype));
+    dbprintf(("%s: calculating for device %s with %s\n",
+             debug_prefix_time(NULL), qdevice, fstype));
 
     cmd = vstralloc(libexecdir, "/rundump", versionsuffix(), NULL);
     rundump_cmd = stralloc(cmd);
-
-    stdoutfd = nullfd = open("/dev/null", O_RDWR);
+    if (g_options->config)
+        config = g_options->config;
+    else
+        config = "NOCONFIG";
+    if ((stdoutfd = nullfd = open("/dev/null", O_RDWR)) == -1) {
+       dbprintf(("getsize_dump could not open /dev/null: %s\n",
+                 strerror(errno)));
+       amfree(cmd);
+       amfree(rundump_cmd);
+       amfree(fstype);
+       amfree(device);
+       amfree(qdevice);
+       amfree(qdisk);
+       return(-1);
+    }
     pipefd[0] = pipefd[1] = killctl[0] = killctl[1] = -1;
-    pipe(pipefd);
+    if (pipe(pipefd) < 0) {
+       dbprintf(("getsize_dump could create data pipes: %s\n",
+                 strerror(errno)));
+       amfree(cmd);
+       amfree(rundump_cmd);
+       amfree(fstype);
+       amfree(device);
+       amfree(qdevice);
+       amfree(qdisk);
+       return(-1);
+    }
 
 #ifdef XFSDUMP                                         /* { */
 #ifdef DUMP                                            /* { */
@@ -807,9 +1113,9 @@ long getsize_dump(disk, amdevice, level, options)
     if (1)
 #endif                                                 /* } */
     {
-        name = stralloc(" (xfsdump)");
+       name = stralloc(" (xfsdump)");
        dbprintf(("%s: running \"%s%s -F -J -l %s - %s\"\n",
-                 debug_prefix_time(NULL), cmd, name, level_str, device));
+                 debug_prefix_time(NULL), cmd, name, level_str, qdevice));
     }
     else
 #endif                                                 /* } */
@@ -821,14 +1127,16 @@ long getsize_dump(disk, amdevice, level, options)
 #endif                                                 /* } */
     {
 #ifdef USE_RUNDUMP
-        name = stralloc(" (vxdump)");
+       name = stralloc(" (vxdump)");
 #else
        name = stralloc("");
        cmd = newstralloc(cmd, VXDUMP);
+       config = skip_argument;
+       is_rundump = 0;
 #endif
        dumpkeys = vstralloc(level_str, "s", "f", NULL);
-        dbprintf(("%s: running \"%s%s %s 1048576 - %s\"\n",
-                 debug_prefix_time(NULL), cmd, name, dumpkeys, device));
+       dbprintf(("%s: running \"%s%s %s 1048576 - %s\"\n",
+                 debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice));
     }
     else
 #endif                                                 /* } */
@@ -841,10 +1149,12 @@ long getsize_dump(disk, amdevice, level, options)
     {
        name = stralloc(" (vdump)");
        amfree(device);
+       amfree(qdevice);
        device = amname_to_dirname(amdevice);
+       qdevice = quote_string(device);
        dumpkeys = vstralloc(level_str, "b", "f", NULL);
        dbprintf(("%s: running \"%s%s %s 60 - %s\"\n",
-                 debug_prefix_time(NULL), cmd, name, dumpkeys, device));
+                 debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice));
     }
     else
 #endif                                                 /* } */
@@ -859,20 +1169,28 @@ long getsize_dump(disk, amdevice, level, options)
 # else                                                 /* } { */
        name = stralloc("");
        cmd = newstralloc(cmd, DUMP);
+        config = skip_argument;
+       is_rundump = 0;
 # endif                                                        /* } */
 
 # ifdef AIX_BACKUP                                     /* { */
        dumpkeys = vstralloc("-", level_str, "f", NULL);
        dbprintf(("%s: running \"%s%s %s - %s\"\n",
-                 debug_prefix_time(NULL), cmd, name, dumpkeys, device));
+                 debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice));
 # else                                                 /* } { */
+#  ifdef HAVE_DUMP_ESTIMATE
+#    define PARAM_DUMP_ESTIMATE HAVE_DUMP_ESTIMATE
+#  else
+#    define PARAM_DUMP_ESTIMATE ""
+#  endif
+#  ifdef HAVE_HONOR_NODUMP
+#    define PARAM_HONOR_NODUMP "h"
+#  else
+#    define PARAM_HONOR_NODUMP ""
+#  endif
        dumpkeys = vstralloc(level_str,
-#  ifdef HAVE_DUMP_ESTIMATE                            /* { */
-                            HAVE_DUMP_ESTIMATE,
-#  endif                                               /* } */
-#  ifdef HAVE_HONOR_NODUMP                             /* { */
-                            "h",
-#  endif                                               /* } */
+                            PARAM_DUMP_ESTIMATE,
+                            PARAM_DUMP_ESTIMATE,
                             "s", "f", NULL);
 
 #  ifdef HAVE_DUMP_ESTIMATE
@@ -881,10 +1199,10 @@ long getsize_dump(disk, amdevice, level, options)
 
 #  ifdef HAVE_HONOR_NODUMP                             /* { */
        dbprintf(("%s: running \"%s%s %s 0 1048576 - %s\"\n",
-                 debug_prefix_time(NULL), cmd, name, dumpkeys, device));
+                 debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice));
 #  else                                                        /* } { */
        dbprintf(("%s: running \"%s%s %s 1048576 - %s\"\n",
-                 debug_prefix_time(NULL), cmd, name, dumpkeys, device));
+                 debug_prefix_time(NULL), cmd, name, dumpkeys, qdevice));
 #  endif                                               /* } */
 # endif                                                        /* } */
     }
@@ -892,9 +1210,15 @@ long getsize_dump(disk, amdevice, level, options)
 #endif                                                 /* } */
     {
        error("no dump program available");
+       /*NOTREACHED*/
     }
 
-    pipe(killctl);
+    if (pipe(killctl) < 0) {
+       dbprintf(("%s: Could not create pipe: %s\n",
+               debug_prefix(NULL), strerror(errno)));
+       /* Message will be printed later... */
+       killctl[0] = killctl[1] = -1;
+    }
 
     start_time = curclock();
     switch(dumppid = fork()) {
@@ -905,7 +1229,10 @@ long getsize_dump(disk, amdevice, level, options)
        amfree(cmd);
        amfree(rundump_cmd);
        amfree(device);
+       amfree(qdevice);
+       amfree(qdisk);
        amfree(name);
+       amfree(fstype);
        return -1;
     default:
        break; 
@@ -913,8 +1240,7 @@ long getsize_dump(disk, amdevice, level, options)
        if(SETPGRP == -1)
            SETPGRP_FAILED();
        else if (killctl[0] == -1 || killctl[1] == -1)
-           dbprintf(("%s: pipe for killpgrp failed, trying without killpgrp\n",
-                     debug_prefix(NULL)));
+           dbprintf(("%s: Trying without killpgrp\n", debug_prefix(NULL)));
        else {
            switch(fork()) {
            case -1:
@@ -924,6 +1250,7 @@ long getsize_dump(disk, amdevice, level, options)
 
            default:
            {
+               char *config;
                char *killpgrp_cmd = vstralloc(libexecdir, "/killpgrp",
                                               versionsuffix(), NULL);
                dbprintf(("%s: running %s\n",
@@ -935,7 +1262,12 @@ long getsize_dump(disk, amdevice, level, options)
                close(pipefd[1]);
                close(killctl[1]);
                close(nullfd);
-               execle(killpgrp_cmd, killpgrp_cmd, (char *)0, safe_env());
+               if (g_options->config)
+                   config = g_options->config;
+               else
+                   config = "NOCONFIG";
+               execle(killpgrp_cmd, killpgrp_cmd, config, (char *)0,
+                      safe_env());
                dbprintf(("%s: cannot execute %s: %s\n",
                          debug_prefix(NULL), killpgrp_cmd, strerror(errno)));
                exit(-1);
@@ -961,8 +1293,12 @@ long getsize_dump(disk, amdevice, level, options)
 #else
        if (1)
 #endif
-           execle(cmd, "xfsdump", "-F", "-J", "-l", level_str, "-", device,
-                  (char *)0, safe_env());
+           if (is_rundump)
+               execle(cmd, "rundump", config, "xfsdump", "-F", "-J", "-l",
+                      level_str, "-", device, (char *)0, safe_env());
+           else
+               execle(cmd, "xfsdump", "-F", "-J", "-l",
+                      level_str, "-", device, (char *)0, safe_env());
        else
 #endif
 #ifdef VXDUMP
@@ -971,8 +1307,12 @@ long getsize_dump(disk, amdevice, level, options)
 #else
        if (1)
 #endif
-           execle(cmd, "vxdump", dumpkeys, "1048576", "-", device, (char *)0,
-                  safe_env());
+           if (is_rundump)
+               execle(cmd, "rundump", config, "vxdump", dumpkeys, "1048576",
+                      "-", device, (char *)0, safe_env());
+           else
+               execle(cmd, "vxdump", dumpkeys, "1048576", "-",
+                      device, (char *)0, safe_env());
        else
 #endif
 #ifdef VDUMP
@@ -981,24 +1321,42 @@ long getsize_dump(disk, amdevice, level, options)
 #else
        if (1)
 #endif
-           execle(cmd, "vdump", dumpkeys, "60", "-", device, (char *)0,
-                  safe_env());
+           if (is_rundump)
+               execle(cmd, "rundump", config, "vdump", dumpkeys, "60", "-",
+                      device, (char *)0, safe_env());
+           else
+               execle(cmd, "vdump", dumpkeys, "60", "-",
+                      device, (char *)0, safe_env());
        else
 #endif
 #ifdef DUMP
 # ifdef AIX_BACKUP
-           execle(cmd, "backup", dumpkeys, "-", device, (char *)0, safe_env());
+           if (is_rundump)
+               execle(cmd, "rundump", config, "backup", dumpkeys, "-",
+                      device, (char *)0, safe_env());
+           else
+               execle(cmd, "backup", dumpkeys, "-",
+                      device, (char *)0, safe_env());
 # else
-           execle(cmd, "dump", dumpkeys, 
+           if (is_rundump) {
+               execle(cmd, "rundump", config, "dump", dumpkeys, 
 #ifdef HAVE_HONOR_NODUMP
-                  "0",
+                      "0",
 #endif
-                  "1048576", "-", device, (char *)0, safe_env());
+                      "1048576", "-", device, (char *)0, safe_env());
+           } else {
+               execle(cmd, "dump", dumpkeys, 
+#ifdef HAVE_HONOR_NODUMP
+                      "0",
+#endif
+                      "1048576", "-", device, (char *)0, safe_env());
+           }
 # endif
 #endif
        {
            error("exec %s failed or no dump program available: %s",
                  cmd, strerror(errno));
+           /*NOTREACHED*/
        }
     }
 
@@ -1009,13 +1367,24 @@ long getsize_dump(disk, amdevice, level, options)
     if (killctl[0] != -1)
        aclose(killctl[0]);
     dumpout = fdopen(pipefd[0],"r");
+    if (!dumpout) {
+       error("Can't fdopen: %s", strerror(errno));
+       /*NOTREACHED*/
+    }
 
-    for(size = -1; (line = agets(dumpout)) != NULL; free(line)) {
+    for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
+       if (line[0] == '\0')
+           continue;
        dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
        size = handle_dumpline(line);
-       if(size > -1) {
+       if(size > (off_t)-1) {
            amfree(line);
-           if((line = agets(dumpout)) != NULL) {
+           while ((line = agets(dumpout)) != NULL) {
+               if (line[0] != '\0')
+                   break;
+               amfree(line);
+           }
+           if (line != NULL) {
                dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
            }
            break;
@@ -1026,23 +1395,26 @@ long getsize_dump(disk, amdevice, level, options)
     dbprintf(("%s: .....\n", debug_prefix_time(NULL)));
     dbprintf(("%s: estimate time for %s level %d: %s\n",
              debug_prefix(NULL),
-             disk,
+             qdisk,
              level,
              walltime_str(timessub(curclock(), start_time))));
-    if(size == -1) {
+    if(size == (off_t)-1) {
        dbprintf(("%s: no size line match in %s%s output for \"%s\"\n",
                  debug_prefix(NULL), cmd, name, disk));
        dbprintf(("%s: .....\n", debug_prefix(NULL)));
-    } else if(size == 0 && level == 0) {
+       dbprintf(("%s: Run %s%s manually to check for errors\n",
+                   debug_prefix(NULL), cmd, name));
+    } else if(size == (off_t)0 && level == 0) {
        dbprintf(("%s: possible %s%s problem -- is \"%s\" really empty?\n",
                  debug_prefix(NULL), cmd, name, disk));
        dbprintf(("%s: .....\n", debug_prefix(NULL)));
-    }
-    dbprintf(("%s: estimate size for %s level %d: %ld KB\n",
+    } else {
+           dbprintf(("%s: estimate size for %s level %d: %ld KB\n",
              debug_prefix(NULL),
-             disk,
+             qdisk,
              level,
              size));
+    }
 
     if (killctl[1] != -1) {
        dbprintf(("%s: asking killpgrp to terminate\n",
@@ -1085,10 +1457,10 @@ long getsize_dump(disk, amdevice, level, options)
     }
 
     dbprintf(("%s: waiting for %s%s \"%s\" child\n",
-             debug_prefix_time(NULL), cmd, name, disk));
+             debug_prefix_time(NULL), cmd, name, qdisk));
     wait(NULL);
-    dbprintf(("%s: after %s%s \"%s\" wait\n",
-             debug_prefix_time(NULL), cmd, name, disk));
+    dbprintf(("%s: after %s%s %s wait\n",
+             debug_prefix_time(NULL), cmd, name, qdisk));
 
  terminated:
 
@@ -1096,6 +1468,8 @@ long getsize_dump(disk, amdevice, level, options)
     afclose(dumpout);
 
     amfree(device);
+    amfree(qdevice);
+    amfree(qdisk);
     amfree(fstype);
 
     amfree(cmd);
@@ -1105,24 +1479,29 @@ long getsize_dump(disk, amdevice, level, options)
 }
 
 #ifdef SAMBA_CLIENT
-long getsize_smbtar(disk, amdevice, level, optionns)
-    char *disk, *amdevice;
-    int level;
-    option_t *optionns;
+off_t
+getsize_smbtar(
+    char       *disk,
+    char       *amdevice,
+    int                level,
+    option_t * options)
 {
     int pipefd = -1, nullfd = -1, passwdfd = -1;
-    int dumppid;
-    long size;
+    pid_t dumppid;
+    off_t size;
     FILE *dumpout;
     char *tarkeys, *sharename, *user_and_password = NULL, *domain = NULL;
     char *share = NULL, *subdir = NULL;
-    int lpass;
+    size_t lpass;
     char *pwtext;
-    int pwtext_len;
+    size_t pwtext_len;
     char *line;
     char *pw_fd_env;
     times_t start_time;
     char *error_pn = NULL;
+    char *qdisk = quote_string(disk);
+
+    (void)options;     /* Quiet unused parameter warning */
 
     error_pn = stralloc2(get_pname(), "-smbclient");
 
@@ -1132,14 +1511,16 @@ long getsize_smbtar(disk, amdevice, level, optionns)
        amfree(subdir);
        set_pname(error_pn);
        amfree(error_pn);
-       error("cannot parse disk entry '%s' for share/subdir", disk);
+       error("cannot parse disk entry %s for share/subdir", qdisk);
+       /*NOTREACHED*/
     }
     if ((subdir) && (SAMBA_VERSION < 2)) {
        amfree(share);
        amfree(subdir);
        set_pname(error_pn);
        amfree(error_pn);
-       error("subdirectory specified for share '%s' but samba not v2 or better", disk);
+       error("subdirectory specified for share %s but samba not v2 or better", qdisk);
+       /*NOTREACHED*/
     }
     if ((user_and_password = findpass(share, &domain)) == NULL) {
 
@@ -1150,10 +1531,11 @@ long getsize_smbtar(disk, amdevice, level, optionns)
        set_pname(error_pn);
        amfree(error_pn);
        error("cannot find password for %s", disk);
+       /*NOTREACHED*/
     }
     lpass = strlen(user_and_password);
     if ((pwtext = strchr(user_and_password, '%')) == NULL) {
-       memset(user_and_password, '\0', lpass);
+       memset(user_and_password, '\0', (size_t)lpass);
        amfree(user_and_password);
        if(domain) {
            memset(domain, '\0', strlen(domain));
@@ -1162,11 +1544,12 @@ long getsize_smbtar(disk, amdevice, level, optionns)
        set_pname(error_pn);
        amfree(error_pn);
        error("password field not \'user%%pass\' for %s", disk);
+       /*NOTREACHED*/
     }
     *pwtext++ = '\0';
     pwtext_len = strlen(pwtext);
     if ((sharename = makesharename(share, 0)) == NULL) {
-       memset(user_and_password, '\0', lpass);
+       memset(user_and_password, '\0', (size_t)lpass);
        amfree(user_and_password);
        if(domain) {
            memset(domain, '\0', strlen(domain));
@@ -1175,8 +1558,22 @@ long getsize_smbtar(disk, amdevice, level, optionns)
        set_pname(error_pn);
        amfree(error_pn);
        error("cannot make share name of %s", share);
+       /*NOTREACHED*/
+    }
+    if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+       memset(user_and_password, '\0', (size_t)lpass);
+       amfree(user_and_password);
+       if(domain) {
+           memset(domain, '\0', strlen(domain));
+           amfree(domain);
+       }
+       set_pname(error_pn);
+       amfree(error_pn);
+       amfree(sharename);
+       error("could not open /dev/null: %s\n",
+             strerror(errno));
+       /*NOTREACHED*/
     }
-    nullfd = open("/dev/null", O_RDWR);
 
 #if SAMBA_VERSION >= 2
     if (level == 0)
@@ -1219,17 +1616,18 @@ long getsize_smbtar(disk, amdevice, level, optionns)
        amfree(domain);
     }
     aclose(nullfd);
-    if(pwtext_len > 0 && fullwrite(passwdfd, pwtext, pwtext_len) < 0) {
+    if(pwtext_len > 0 && fullwrite(passwdfd, pwtext, (size_t)pwtext_len) < 0) {
        int save_errno = errno;
 
-       memset(user_and_password, '\0', lpass);
+       memset(user_and_password, '\0', (size_t)lpass);
        amfree(user_and_password);
        aclose(passwdfd);
        set_pname(error_pn);
        amfree(error_pn);
        error("password write failed: %s", strerror(save_errno));
+       /*NOTREACHED*/
     }
-    memset(user_and_password, '\0', lpass);
+    memset(user_and_password, '\0', (size_t)lpass);
     amfree(user_and_password);
     aclose(passwdfd);
     amfree(sharename);
@@ -1237,13 +1635,24 @@ long getsize_smbtar(disk, amdevice, level, optionns)
     amfree(subdir);
     amfree(error_pn);
     dumpout = fdopen(pipefd,"r");
+    if (!dumpout) {
+       error("Can't fdopen: %s", strerror(errno));
+       /*NOTREACHED*/
+    }
 
-    for(size = -1; (line = agets(dumpout)) != NULL; free(line)) {
+    for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
+       if (line[0] == '\0')
+           continue;
        dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
        size = handle_dumpline(line);
        if(size > -1) {
            amfree(line);
-           if((line = agets(dumpout)) != NULL) {
+           while ((line = agets(dumpout)) != NULL) {
+               if (line[0] != '\0')
+                   break;
+               amfree(line);
+           }
+           if(line != NULL) {
                dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
            }
            break;
@@ -1254,50 +1663,54 @@ long getsize_smbtar(disk, amdevice, level, optionns)
     dbprintf(("%s: .....\n", debug_prefix_time(NULL)));
     dbprintf(("%s: estimate time for %s level %d: %s\n",
              debug_prefix(NULL),
-             disk,
+             qdisk,
              level,
              walltime_str(timessub(curclock(), start_time))));
-    if(size == -1) {
+    if(size == (off_t)-1) {
        dbprintf(("%s: no size line match in %s output for \"%s\"\n",
                  debug_prefix(NULL), SAMBA_CLIENT, disk));
        dbprintf(("%s: .....\n", debug_prefix(NULL)));
-    } else if(size == 0 && level == 0) {
+    } else if(size == (off_t)0 && level == 0) {
        dbprintf(("%s: possible %s problem -- is \"%s\" really empty?\n",
                  debug_prefix(NULL), SAMBA_CLIENT, disk));
        dbprintf(("%s: .....\n", debug_prefix(NULL)));
     }
     dbprintf(("%s: estimate size for %s level %d: %ld KB\n",
              debug_prefix(NULL),
-             disk,
+             qdisk,
              level,
              size));
 
     kill(-dumppid, SIGTERM);
 
     dbprintf(("%s: waiting for %s \"%s\" child\n",
-             debug_prefix_time(NULL), SAMBA_CLIENT, disk));
+             debug_prefix_time(NULL), SAMBA_CLIENT, qdisk));
     wait(NULL);
-    dbprintf(("%s: after %s \"%s\" wait\n",
-             debug_prefix_time(NULL), SAMBA_CLIENT, disk));
+    dbprintf(("%s: after %s %s wait\n",
+             debug_prefix_time(NULL), SAMBA_CLIENT, qdisk));
 
     afclose(dumpout);
     pipefd = -1;
 
     amfree(error_pn);
+    amfree(qdisk);
 
     return size;
 }
 #endif
 
 #ifdef GNUTAR
-long getsize_gnutar(disk, amdevice, level, options, dumpsince)
-char *disk, *amdevice;
-int level;
-option_t *options;
-time_t dumpsince;
+off_t
+getsize_gnutar(
+    char       *disk,
+    char       *amdevice,
+    int                level,
+    option_t * options,
+    time_t     dumpsince)
 {
-    int pipefd = -1, nullfd = -1, dumppid;
-    long size = -1;
+    int pipefd = -1, nullfd = -1;
+    pid_t dumppid;
+    off_t size = (off_t)-1;
     FILE *dumpout = NULL;
     char *incrname = NULL;
     char *basename = NULL;
@@ -1316,6 +1729,11 @@ time_t dumpsince;
     char *file_exclude = NULL;
     char *file_include = NULL;
     times_t start_time;
+    int infd, outfd;
+    ssize_t nb;
+    char buf[32768];
+    char *qdisk = quote_string(disk);
+    char *gnutar_list_dir;
 
     if(options->exclude_file) nb_exclude += options->exclude_file->nb_element;
     if(options->exclude_list) nb_exclude += options->exclude_list->nb_element;
@@ -1325,17 +1743,19 @@ time_t dumpsince;
     if(nb_exclude > 0) file_exclude = build_exclude(disk, amdevice, options, 0);
     if(nb_include > 0) file_include = build_include(disk, amdevice, options, 0);
 
-    my_argv = alloc(sizeof(char *) * 21);
+    my_argv = alloc(SIZEOF(char *) * 22);
     i = 0;
 
-#ifdef GNUTAR_LISTED_INCREMENTAL_DIR
-    {
+    gnutar_list_dir = client_getconf_str(CLN_GNUTAR_LIST_DIR);
+    if (strlen(gnutar_list_dir) == 0)
+       gnutar_list_dir = NULL;
+    if (gnutar_list_dir) {
        char number[NUM_STR_SIZE];
        char *s;
        int ch;
        int baselevel;
 
-       basename = vstralloc(GNUTAR_LISTED_INCREMENTAL_DIR,
+       basename = vstralloc(gnutar_list_dir,
                             "/",
                             g_options->hostname,
                             disk,
@@ -1344,12 +1764,12 @@ time_t dumpsince;
         * The loop starts at the first character of the host name,
         * not the '/'.
         */
-       s = basename + sizeof(GNUTAR_LISTED_INCREMENTAL_DIR);
+       s = basename + strlen(gnutar_list_dir) + 1;
        while((ch = *s++) != '\0') {
            if(ch == '/' || isspace(ch)) s[-1] = '_';
        }
 
-       ap_snprintf(number, sizeof(number), "%d", level);
+       snprintf(number, SIZEOF(number), "%d", level);
        incrname = vstralloc(basename, "_", number, ".new", NULL);
        unlink(incrname);
 
@@ -1359,15 +1779,16 @@ time_t dumpsince;
         * be true for a level 0), arrange to read from /dev/null.
         */
        baselevel = level;
-       while (in == NULL) {
+       infd = -1;
+       while (infd == -1) {
            if (--baselevel >= 0) {
-               ap_snprintf(number, sizeof(number), "%d", baselevel);
+               snprintf(number, SIZEOF(number), "%d", baselevel);
                inputname = newvstralloc(inputname,
                                         basename, "_", number, NULL);
            } else {
                inputname = newstralloc(inputname, "/dev/null");
            }
-           if ((in = fopen(inputname, "r")) == NULL) {
+           if ((infd = open(inputname, O_RDONLY)) == -1) {
                int save_errno = errno;
 
                dbprintf(("%s: gnutar: error opening %s: %s\n",
@@ -1381,75 +1802,57 @@ time_t dumpsince;
        /*
         * Copy the previous listed incremental file to the new one.
         */
-       if ((out = fopen(incrname, "w")) == NULL) {
+       if ((outfd = open(incrname, O_WRONLY|O_CREAT, 0600)) == -1) {
            dbprintf(("%s: opening %s: %s\n",
                      debug_prefix(NULL), incrname, strerror(errno)));
            goto common_exit;
        }
 
-       for (; (line = agets(in)) != NULL; free(line)) {
-           if (fputs(line, out) == EOF || putc('\n', out) == EOF) {
+       while ((nb = read(infd, &buf, SIZEOF(buf))) > 0) {
+           if (fullwrite(outfd, &buf, (size_t)nb) < nb) {
                dbprintf(("%s: writing to %s: %s\n",
                           debug_prefix(NULL), incrname, strerror(errno)));
                goto common_exit;
            }
        }
-       amfree(line);
 
-       if (ferror(in)) {
+       if (nb < 0) {
            dbprintf(("%s: reading from %s: %s\n",
                      debug_prefix(NULL), inputname, strerror(errno)));
            goto common_exit;
        }
-       if (fclose(in) == EOF) {
+
+       if (close(infd) != 0) {
            dbprintf(("%s: closing %s: %s\n",
                      debug_prefix(NULL), inputname, strerror(errno)));
-           in = NULL;
            goto common_exit;
        }
-       in = NULL;
-       if (fclose(out) == EOF) {
+       if (close(outfd) != 0) {
            dbprintf(("%s: closing %s: %s\n",
                      debug_prefix(NULL), incrname, strerror(errno)));
-           out = NULL;
            goto common_exit;
        }
-       out = NULL;
 
        amfree(inputname);
        amfree(basename);
     }
-#endif
 
     gmtm = gmtime(&dumpsince);
-    ap_snprintf(dumptimestr, sizeof(dumptimestr),
+    snprintf(dumptimestr, SIZEOF(dumptimestr),
                "%04d-%02d-%02d %2d:%02d:%02d GMT",
                gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
                gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
 
     dirname = amname_to_dirname(amdevice);
 
-
-
-#ifdef USE_QUICK_AND_DIRTY_ESTIMATES
-    ap_snprintf(dumptimestr, sizeof(dumptimestr), "%ld", dumpsince);
-
-    cmd = vstralloc(libexecdir, "/", "amqde", versionsuffix(), NULL);
-
-    my_argv[i++] = vstralloc(libexecdir, "/", "amqde", versionsuffix(), NULL);
-    my_argv[i++] = "-s";
-    my_argv[i++] = dumptimestr;
-    if(file_exclude) { /* at present, this is not used... */
-       my_argv[i++] = "-x";
-       my_argv[i++] = file_exclude;
-    }
-    /* [XXX] need to also consider implementation of --files-from */
-    my_argv[i++] = dirname;
-    my_argv[i++] = NULL;
-#else
-#ifdef GNUTAR
     cmd = vstralloc(libexecdir, "/", "runtar", versionsuffix(), NULL);
+    my_argv[i++] = "runtar";
+    if (g_options->config)
+       my_argv[i++] = g_options->config;
+    else
+       my_argv[i++] = "NOCONFIG";
 
+#ifdef GNUTAR
     my_argv[i++] = GNUTAR;
 #else
     my_argv[i++] = "tar";
@@ -1460,14 +1863,14 @@ time_t dumpsince;
     my_argv[i++] = "--directory";
     my_argv[i++] = dirname;
     my_argv[i++] = "--one-file-system";
-#ifdef GNUTAR_LISTED_INCREMENTAL_DIR
-    my_argv[i++] = "--listed-incremental";
-    my_argv[i++] = incrname;
-#else
-    my_argv[i++] = "--incremental";
-    my_argv[i++] = "--newer";
-    my_argv[i++] = dumptimestr;
-#endif
+    if (gnutar_list_dir) {
+           my_argv[i++] = "--listed-incremental";
+           my_argv[i++] = incrname;
+    } else {
+       my_argv[i++] = "--incremental";
+       my_argv[i++] = "--newer";
+       my_argv[i++] = dumptimestr;
+    }
 #ifdef ENABLE_GNUTAR_ATIME_PRESERVE
     /* --atime-preserve causes gnutar to call
      * utime() after reading files in order to
@@ -1492,26 +1895,39 @@ time_t dumpsince;
     else {
        my_argv[i++] = ".";
     }
-#endif /* USE_QUICK_AND_DIRTY_ESTIMATES */
     my_argv[i++] = NULL;
 
     start_time = curclock();
 
-    nullfd = open("/dev/null", O_RDWR);
+    if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+       dbprintf(("Cannot access /dev/null : %s\n", strerror(errno)));
+       goto common_exit;
+    }
+
     dumppid = pipespawnv(cmd, STDERR_PIPE, &nullfd, &nullfd, &pipefd, my_argv);
-    amfree(cmd);
-    amfree(file_exclude);
-    amfree(file_include);
 
     dumpout = fdopen(pipefd,"r");
+    if (!dumpout) {
+       error("Can't fdopen: %s", strerror(errno));
+       /*NOTREACHED*/
+    }
 
-    for(size = -1; (line = agets(dumpout)) != NULL; free(line)) {
+    for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
+       if (line[0] == '\0')
+           continue;
        dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
        size = handle_dumpline(line);
-       if(size > -1) {
+       if(size > (off_t)-1) {
            amfree(line);
-           if((line = agets(dumpout)) != NULL) {
+           while ((line = agets(dumpout)) != NULL) {
+               if (line[0] != '\0') {
+                   break;
+               }
+               amfree(line);
+           }
+           if (line != NULL) {
                dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
+               break;
            }
            break;
        }
@@ -1521,31 +1937,31 @@ time_t dumpsince;
     dbprintf(("%s: .....\n", debug_prefix_time(NULL)));
     dbprintf(("%s: estimate time for %s level %d: %s\n",
              debug_prefix(NULL),
-             disk,
+             qdisk,
              level,
              walltime_str(timessub(curclock(), start_time))));
-    if(size == -1) {
+    if(size == (off_t)-1) {
        dbprintf(("%s: no size line match in %s output for \"%s\"\n",
                  debug_prefix(NULL), my_argv[0], disk));
        dbprintf(("%s: .....\n", debug_prefix(NULL)));
-    } else if(size == 0 && level == 0) {
+    } else if(size == (off_t)0 && level == 0) {
        dbprintf(("%s: possible %s problem -- is \"%s\" really empty?\n",
                  debug_prefix(NULL), my_argv[0], disk));
        dbprintf(("%s: .....\n", debug_prefix(NULL)));
     }
     dbprintf(("%s: estimate size for %s level %d: %ld KB\n",
              debug_prefix(NULL),
-             disk,
+             qdisk,
              level,
              size));
 
     kill(-dumppid, SIGTERM);
 
     dbprintf(("%s: waiting for %s \"%s\" child\n",
-             debug_prefix_time(NULL), my_argv[0], disk));
+             debug_prefix_time(NULL), my_argv[0], qdisk));
     wait(NULL);
-    dbprintf(("%s: after %s \"%s\" wait\n",
-             debug_prefix_time(NULL), my_argv[0], disk));
+    dbprintf(("%s: after %s %s wait\n",
+             debug_prefix_time(NULL), my_argv[0], qdisk));
 
 common_exit:
 
@@ -1557,6 +1973,10 @@ common_exit:
     amfree(dirname);
     amfree(inputname);
     amfree(my_argv);
+    amfree(qdisk);
+    amfree(cmd);
+    amfree(file_exclude);
+    amfree(file_include);
 
     aclose(nullfd);
     afclose(dumpout);
@@ -1567,12 +1987,173 @@ common_exit:
 }
 #endif
 
+off_t
+getsize_wrapper(
+    char       *program,
+    char       *disk,
+    char       *amdevice,
+    int                level,
+    option_t * options,
+    time_t     dumpsince)
+{
+    int pipefd[2], nullfd;
+    pid_t dumppid;
+    off_t size = (off_t)-1;
+    FILE *dumpout;
+    char *line = NULL;
+    char *cmd = NULL;
+    char dumptimestr[80];
+    struct tm *gmtm;
+    int  i, j;
+    char *argvchild[10];
+    char *newoptstr = NULL;
+    off_t size1, size2;
+    times_t start_time;
+    char *qdisk = quote_string(disk);
+    char *qamdevice = quote_string(amdevice);
+
+    gmtm = gmtime(&dumpsince);
+    snprintf(dumptimestr, SIZEOF(dumptimestr),
+               "%04d-%02d-%02d %2d:%02d:%02d GMT",
+               gmtm->tm_year + 1900, gmtm->tm_mon+1, gmtm->tm_mday,
+               gmtm->tm_hour, gmtm->tm_min, gmtm->tm_sec);
+
+    cmd = vstralloc(DUMPER_DIR, "/", program, NULL);
+
+    i=0;
+    argvchild[i++] = program;
+    argvchild[i++] = "estimate";
+    if(level == 0)
+       argvchild[i++] = "full";
+    else {
+       char levelstr[NUM_STR_SIZE];
+       snprintf(levelstr,SIZEOF(levelstr),"%d",level);
+       argvchild[i++] = "level";
+       argvchild[i++] = levelstr;
+    }
+    argvchild[i++] = amdevice;
+    newoptstr = vstralloc(options->str,"estimate-direct;", NULL);
+    argvchild[i++] = newoptstr;
+    argvchild[i] = NULL;
+
+    dbprintf(("%s: running %s", debug_prefix_time(NULL), cmd));
+    for(j = 1; j < i; j++) {
+       dbprintf((" %s", argvchild[j]));
+    }
+    dbprintf(("\n"));
+
+    if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
+       dbprintf(("Cannot access /dev/null : %s\n", strerror(errno)));
+       goto common_exit;
+    }
+
+    if (pipe(pipefd) < 0) {
+       dbprintf(("getsize_wrapper could create data pipes: %s\n",
+                 strerror(errno)));
+       goto common_exit;
+    }
+
+    start_time = curclock();
+
+    switch(dumppid = fork()) {
+    case -1:
+      size = (off_t)-1;
+      goto common_exit;
+    default:
+      break; /* parent */
+    case 0:
+      dup2(nullfd, 0);
+      dup2(nullfd, 2);
+      dup2(pipefd[1], 1);
+      aclose(pipefd[0]);
+
+      execve(cmd, argvchild, safe_env());
+      error("exec %s failed: %s", cmd, strerror(errno));
+      /*NOTREACHED*/
+    }
+    amfree(newoptstr);
+
+    aclose(pipefd[1]);
+    dumpout = fdopen(pipefd[0],"r");
+    if (!dumpout) {
+       error("Can't fdopen: %s", strerror(errno));
+       /*NOTREACHED*/
+    }
+
+    for(size = (off_t)-1; (line = agets(dumpout)) != NULL; free(line)) {
+       if (line[0] == '\0')
+           continue;
+       dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
+       i = sscanf(line, OFF_T_FMT " " OFF_T_FMT,
+               (OFF_T_FMT_TYPE *)&size1, 
+               (OFF_T_FMT_TYPE *)&size2);
+       if(i == 2) {
+           size = size1 * size2;
+       }
+       if(size > -1) {
+           amfree(line);
+           while ((line = agets(dumpout)) != NULL) {
+               if (line[0] != '\0')
+                   break;
+               amfree(line);
+           }
+           if(line != NULL) {
+               dbprintf(("%s: %s\n", debug_prefix_time(NULL), line));
+           }
+           break;
+       }
+    }
+    amfree(line);
+
+    dbprintf(("%s: .....\n", debug_prefix_time(NULL)));
+    dbprintf(("%s: estimate time for %s level %d: %s\n",
+             debug_prefix(NULL),
+             qamdevice,
+             level,
+             walltime_str(timessub(curclock(), start_time))));
+    if(size == (off_t)-1) {
+       dbprintf(("%s: no size line match in %s output for \"%s\"\n",
+                 debug_prefix(NULL), cmd, qdisk));
+       dbprintf(("%s: .....\n", debug_prefix(NULL)));
+    } else if(size == (off_t)0 && level == 0) {
+       dbprintf(("%s: possible %s problem -- is \"%s\" really empty?\n",
+                 debug_prefix(NULL), cmd, qdisk));
+       dbprintf(("%s: .....\n", debug_prefix(NULL)));
+    }
+    dbprintf(("%s: estimate size for %s level %d: " OFF_T_FMT " KB\n",
+             debug_prefix(NULL),
+             qamdevice,
+             level,
+             size));
+
+    kill(-dumppid, SIGTERM);
+
+    dbprintf(("%s: waiting for %s \"%s\" child\n",
+             debug_prefix_time(NULL), cmd, qdisk));
+    wait(NULL);
+    dbprintf(("%s: after %s %s wait\n",
+             debug_prefix_time(NULL), cmd, qdisk));
+
+    aclose(nullfd);
+    afclose(dumpout);
+
+common_exit:
+
+    amfree(cmd);
+    amfree(newoptstr);
+    amfree(qdisk);
+    amfree(qamdevice);
+    return size;
+}
+
 
-double first_num(str)
-char *str;
 /*
  * Returns the value of the first integer in a string.
  */
+
+double
+first_num(
+    char *     str)
 {
     char *start;
     int ch;
@@ -1584,27 +2165,32 @@ char *str;
     while(isdigit(ch) || (ch == '.')) ch = *str++;
     str[-1] = '\0';
     d = atof(start);
-    str[-1] = ch;
+    str[-1] = (char)ch;
     return d;
 }
 
 
-long handle_dumpline(str)
-char *str;
 /*
  * Checks the dump output line against the error and size regex tables.
  */
+
+off_t
+handle_dumpline(
+    char *     str)
 {
     regex_t *rp;
     double size;
 
     /* check for size match */
+    /*@ignore@*/
     for(rp = re_size; rp->regex != NULL; rp++) {
        if(match(rp->regex, str)) {
            size = ((first_num(str)*rp->scale+1023.0)/1024.0);
-           if(size < 0) size = 1;              /* found on NeXT -- sigh */
-           return (long) size;
+           if(size < 0.0)
+               size = 1.0;             /* found on NeXT -- sigh */
+           return (off_t)size;
        }
     }
-    return -1;
+    /*@end@*/
+    return (off_t)-1;
 }