Merge commit 'upstream/3.1.0'
[debian/amanda] / server-src / reporter.c
diff --git a/server-src/reporter.c b/server-src/reporter.c
deleted file mode 100644 (file)
index 3b0410b..0000000
+++ /dev/null
@@ -1,3081 +0,0 @@
-/*
- * Amanda, The Advanced Maryland Automatic Network Disk Archiver
- * Copyright (c) 1991-1998, 2000 University of Maryland at College Park
- * All Rights Reserved.
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of U.M. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission.  U.M. makes no representations about the
- * suitability of this software for any purpose.  It is provided "as is"
- * without express or implied warranty.
- *
- * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Author: James da Silva, Systems Design and Analysis Group
- *                        Computer Science Department
- *                        University of Maryland at College Park
- */
-/*
- * $Id: reporter.c,v 1.132 2006/08/28 17:02:48 martinea Exp $
- *
- * nightly Amanda Report generator
- */
-/*
- * report format
- *     tape label message
- *     error messages
- *     strange messages
- *     summary stats
- *     details for errors
- *     details for strange
- *     notes
- *     success summary
- */
-
-#include "amanda.h"
-#include "conffile.h"
-#include "columnar.h"
-#include "tapefile.h"
-#include "diskfile.h"
-#include "infofile.h"
-#include "logfile.h"
-#include "version.h"
-#include "util.h"
-#include "timestamp.h"
-#include "holding.h"
-
-/* don't have (or need) a skipped type except internally to reporter */
-#define L_SKIPPED      L_MARKER
-
-
-#define STATUS_STRANGE   2
-#define STATUS_FAILED    4
-#define STATUS_MISSING   8
-#define STATUS_TAPE     16
-
-typedef struct line_s {
-    struct line_s *next, *last;
-    char *str;
-} line_t;
-
-typedef struct timedata_s {
-    logtype_t result;
-    double origsize, outsize;
-    char *datestamp;
-    double sec, kps;
-    int filenum;
-    char *tapelabel;
-    int totpart;
-} timedata_t;
-
-typedef struct repdata_s {
-    disk_t *disk;
-    char *datestamp;
-    double est_nsize, est_csize;
-    timedata_t taper;
-    timedata_t dumper;
-    timedata_t chunker;
-    timedata_t planner;
-    int level;
-    struct repdata_s *next;
-} repdata_t;
-
-#define data(dp) ((repdata_t *)(dp)->up)
-
-static struct cumulative_stats {
-    int dumpdisks, tapedisks, tapechunks;
-    double taper_time, dumper_time;
-    double outsize, origsize, tapesize;
-    double coutsize, corigsize;                        /* compressed dump only */
-} stats[3];
-
-static int dumpdisks[10], tapedisks[10], tapechunks[10];       /* by-level breakdown of disk count */
-
-typedef struct taper_s {
-    char *label;
-    double taper_time;
-    double coutsize, corigsize;
-    int tapedisks, tapechunks;
-    struct taper_s *next;
-} taper_t;
-
-static taper_t *stats_by_tape = NULL;
-static taper_t *current_tape = NULL;
-
-typedef struct X_summary_s {
-    char *hostname;
-    char *diskname;
-    int  level;
-    char *str;
-    struct X_summary_s *next;
-} X_summary_t;
-
-static X_summary_t *first_strange=NULL, *last_strange=NULL;
-static X_summary_t *first_failed=NULL, *last_failed=NULL;
-
-static double total_time, startup_time, planner_time;
-
-/* count files to tape */
-static int tapefcount = 0;
-
-static int exit_status = 0;
-static char *run_datestamp;
-static char *tape_labels = NULL;
-static int last_run_tapes = 0;
-static int degraded_mode = 0; /* defined in driverio too */
-static int normal_run = 0;
-static int amflush_run = 0;
-static int got_finish = 0;
-static int cmdlogfname = 0;
-static char *ghostname = NULL;
-
-static char *tapestart_error = NULL;
-
-static FILE *logfile, *mailf;
-
-static FILE *postscript;
-static char *printer;
-
-static disklist_t diskq;
-static disklist_t sortq;
-
-static line_t *errsum = NULL;
-static line_t *errdet = NULL;
-static line_t *strangedet = NULL;
-static line_t *notes = NULL;
-
-static char MaxWidthsRequested = 0;    /* determined via config data */
-
-static char *displayunit;
-static long int unitdivisor;
-
-/* local functions */
-int main(int argc, char **argv);
-
-static char *  nicedate(const char * datestamp);
-static char *  prefix(char *host, char *disk, int level);
-static char *  prefixstrange(char *host, char *disk, int level,
-                       size_t len_host, size_t len_disk);
-static char *  Rule(int From, int To);
-static char *  sDivZero(double a, double b, int cn);
-static char *  TextRule(int From, int To, char *s);
-static int     ColWidth(int From, int To);
-static int     contline_next(void);
-static int     sort_by_name(disk_t *a, disk_t *b);
-static repdata_t *find_repdata(disk_t *dp, char *datestamp, int level);
-static repdata_t *handle_chunk(logtype_t logtype);
-static repdata_t *handle_success(logtype_t logtype);
-static void    addline(line_t **lp, char *str);
-static void    addtoX_summary(X_summary_t **first, X_summary_t **last,
-                              char *host, char *disk, int level, char *str);
-static void    bogus_line(const char *);
-static void    CalcMaxWidth(void);
-static void    CheckFloatMax(ColumnInfo *cd, double d);
-static void    CheckIntMax(ColumnInfo *cd, int n);
-static void    CheckStringMax(ColumnInfo *cd, char *s);
-static void    copy_template_file(char *lbl_templ);
-static void    do_postscript_output(void);
-static void    generate_missing(void);
-static void    generate_bad_estimate(void);
-static void    handle_disk(void);
-static void    handle_error(void);
-static void    handle_failed(void);
-static void    handle_finish(void);
-static void    handle_note(void);
-static void    handle_partial(void);
-static void    handle_start(void);
-static void    handle_stats(void);
-static void    handle_strange(void);
-static void    handle_summary(void);
-static void    output_lines(line_t *lp, FILE *f);
-static void    output_stats(void);
-static void    output_X_summary(X_summary_t *first);
-static void    output_summary(void);
-static void    output_tapeinfo(void);
-static void    sort_disks(void);
-static void    usage(void);
-
-static int
-ColWidth(
-    int                From,
-    int                To)
-{
-    int i, Width= 0;
-    for (i=From; i<=To && ColumnData[i].Name != NULL; i++) {
-       Width+= ColumnData[i].PrefixSpace + ColumnData[i].Width;
-    }
-    return Width;
-}
-
-static char *
-Rule(
-    int                From,
-    int                To)
-{
-    int i, ThisLeng;
-    int Leng= ColWidth(0, ColumnDataCount());
-    char *RuleSpace= alloc((size_t)(Leng+1));
-    ThisLeng= ColWidth(From, To);
-    for (i=0;i<ColumnData[From].PrefixSpace; i++)
-       RuleSpace[i]= ' ';
-    for (; i<ThisLeng; i++)
-       RuleSpace[i]= '-';
-    RuleSpace[ThisLeng]= '\0';
-    return RuleSpace;
-}
-
-static char *
-TextRule(
-    int                From,
-    int                To,
-    char *     s)
-{
-    ColumnInfo *cd= &ColumnData[From];
-    int leng;
-    int nbrules, i, txtlength;
-    int RuleSpaceSize= ColWidth(0, ColumnDataCount());
-    char *RuleSpace= alloc((size_t)RuleSpaceSize), *tmp;
-
-    leng = (int)strlen(s);
-    if(leng >= (RuleSpaceSize - cd->PrefixSpace))
-       leng = RuleSpaceSize - cd->PrefixSpace - 1;
-    g_snprintf(RuleSpace, (size_t)RuleSpaceSize, "%*s%*.*s ", cd->PrefixSpace, "", 
-            leng, leng, s);
-    txtlength = cd->PrefixSpace + leng + 1;
-    nbrules = ColWidth(From,To) - txtlength;
-    for(tmp=RuleSpace + txtlength, i=nbrules ; i>0; tmp++,i--)
-       *tmp='-';
-    *tmp = '\0';
-    return RuleSpace;
-}
-
-static char *
-sDivZero(
-    double     a,
-    double     b,
-    int                cn)
-{
-    ColumnInfo *cd= &ColumnData[cn];
-    static char PrtBuf[256];
-    if (!isnormal(b))
-       g_snprintf(PrtBuf, SIZEOF(PrtBuf),
-         "%*s", cd->Width, "-- ");
-    else
-       g_snprintf(PrtBuf, SIZEOF(PrtBuf),
-         cd->Format, cd->Width, cd->Precision, a/b);
-    return PrtBuf;
-}
-
-static int
-contline_next(void)
-{
-    int ch;
-
-    if ((ch = getc(logfile)) != EOF) {
-           if (ungetc(ch, logfile) == EOF) {
-               if (ferror(logfile)) {
-                   error(_("ungetc failed: %s\n"), strerror(errno));
-                   /*NOTREACHED*/
-               }
-               error(_("ungetc failed: EOF\n"));
-               /*NOTREACHED*/
-           }
-    }
-    return ch == ' ';
-}
-
-static void
-addline(
-    line_t **  lp,
-    char *     str)
-{
-    line_t *new, *p;
-
-    /* allocate new line node */
-    new = (line_t *) alloc(SIZEOF(line_t));
-    new->next = NULL;
-    new->last = NULL;
-    new->str = stralloc(str);
-
-    /* add to end of list */
-    p = *lp;
-    if (p == NULL) {
-       *lp = new;
-    } else {
-       if (p->last) {
-           p->last->next = new;
-       } else {
-           p->next = new;
-       }
-       p->last = new;
-    }
-}
-
-static void
-usage(void)
-{
-    error(_("Usage: amreport conf [-i] [-M address] [-f output-file] [-l logfile] [-p postscript-file] [-o configoption]*"));
-    /*NOTREACHED*/
-}
-
-int
-main(
-    int                argc,
-    char **    argv)
-{
-    char *conf_diskfile;
-    char *conf_tapelist;
-    char *conf_infofile;
-    char *logfname, *psfname, *outfname, *subj_str = NULL;
-    tapetype_t *tp;
-    int opt;
-    char *mail_cmd = NULL, *printer_cmd = NULL;
-    extern int optind;
-    char * cwd = NULL;
-    char *ColumnSpec = "";
-    char *errstr = NULL;
-    int cn;
-    int mailout = 1;
-    char *mailto = NULL;
-    char *lbl_templ = NULL;
-    config_overwrites_t *cfg_ovr = NULL;
-    char *cfg_opt = NULL;
-    char *mailer;
-
-    /*
-     * Configure program for internationalization:
-     *   1) Only set the message locale for now.
-     *   2) Set textdomain for all amanda related programs to "amanda"
-     *      We don't want to be forced to support dozens of message catalogs.
-     */  
-    setlocale(LC_MESSAGES, "C");
-    textdomain("amanda"); 
-
-    safe_fd(-1, 0);
-
-    set_pname("amreport");
-
-    dbopen(DBG_SUBDIR_SERVER);
-
-    /* Don't die when child closes pipe */
-    signal(SIGPIPE, SIG_IGN);
-
-    /* Process options */
-    
-    erroutput_type = ERR_INTERACTIVE;
-    outfname = NULL;
-    psfname = NULL;
-    logfname = NULL;
-    cmdlogfname = 0;
-
-    cwd = g_get_current_dir();
-    if (cwd == NULL) {
-       error(_("Cannot determine current working directory: %s"),
-             strerror(errno));
-       /*NOTREACHED*/
-    }
-
-    if (argc >= 2) {
-       if (argv[1][0] == '-') {
-           usage();
-           return 1;
-       }
-
-       /* get the config name and move past it */
-       cfg_opt = argv[1];
-       --argc; ++argv;
-
-       cfg_ovr = new_config_overwrites(argc/2);
-       while((opt = getopt(argc, argv, "o:M:f:l:p:i")) != EOF) {
-           switch(opt) {
-           case 'i': 
-               mailout = 0;
-               break;
-            case 'M':
-               if (mailto != NULL) {
-                   error(_("you may specify at most one -M"));
-                   /*NOTREACHED*/
-               }
-                mailto = stralloc(optarg);
-               if(!validate_mailto(mailto)) {
-                   error(_("mail address has invalid characters"));
-                   /*NOTREACHED*/
-               }
-                break;
-            case 'f':
-               if (outfname != NULL) {
-                   error(_("you may specify at most one -f"));
-                   /*NOTREACHED*/
-               }
-               if (*optarg == '/') {
-                    outfname = stralloc(optarg);
-               } else {
-                    outfname = vstralloc(cwd, "/", optarg, NULL);
-               }
-                break;
-            case 'l':
-               cmdlogfname = 1;
-               if (logfname != NULL) {
-                   error(_("you may specify at most one -l"));
-                   /*NOTREACHED*/
-               }
-               if (*optarg == '/') {
-                   logfname = stralloc(optarg);
-               } else {
-                    logfname = vstralloc(cwd, "/", optarg, NULL);
-               }
-                break;
-            case 'p':
-               if (psfname != NULL) {
-                   error(_("you may specify at most one -p"));
-                   /*NOTREACHED*/
-               }
-               if (*optarg == '/') {
-                    psfname = stralloc(optarg);
-               } else {
-                    psfname = vstralloc(cwd, "/", optarg, NULL);
-               }
-                break;
-           case 'o':
-               add_config_overwrite_opt(cfg_ovr, optarg);
-               break;
-            case '?':
-               usage();
-               return 1;
-            default:
-               break;
-           }
-       }
-
-       argc -= optind;
-       argv += optind;
-    }
-    if( !mailout && mailto ){
-       g_printf(_("You cannot specify both -i & -M at the same time\n"));
-       exit(1);
-    }
-
-    amfree(cwd);
-
-    /* read configuration files */
-
-    /* ignore any errors reading the config file (amreport can run without a config) */
-    config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_USE_CWD, cfg_opt);
-    apply_config_overwrites(cfg_ovr);
-
-    if (config_errors(NULL) >= CFGERR_WARNINGS) {
-       config_print_errors();
-    }
-
-    check_running_as(RUNNING_AS_DUMPUSER);
-
-    dbrename(get_config_name(), DBG_SUBDIR_SERVER);
-
-    safe_cd(); /* must be called *after* config_init() */
-
-    mailer = getconf_str(CNF_MAILER);
-    if (mailer && *mailer == '\0')
-       mailer = NULL;
-    if (!mailer && !outfname) {
-       g_printf(_("You must run amreport with '-f <output file>' because a mailer is not defined\n"));
-       exit (1);
-    }
-
-    conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
-    /* Ignore error from read_diskfile */
-    read_diskfile(conf_diskfile, &diskq);
-    amfree(conf_diskfile);
-    if(mailout && !mailto && 
-       getconf_seen(CNF_MAILTO) && strlen(getconf_str(CNF_MAILTO)) > 0) {
-               mailto = getconf_str(CNF_MAILTO);
-                if(!validate_mailto(mailto)){
-                  mailto = NULL;
-                }
-    }
-    
-    conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST));
-    /* Ignore error from read_tapelist */
-    read_tapelist(conf_tapelist);
-    amfree(conf_tapelist);
-    conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE));
-    if(open_infofile(conf_infofile)) {
-       error(_("could not open info db \"%s\""), conf_infofile);
-       /*NOTREACHED*/
-    }
-    amfree(conf_infofile);
-
-    displayunit = getconf_str(CNF_DISPLAYUNIT);
-    unitdivisor = getconf_unit_divisor();
-
-    ColumnSpec = getconf_str(CNF_COLUMNSPEC);
-    if(SetColumnDataFromString(ColumnData, ColumnSpec, &errstr) < 0) {
-       curlog = L_ERROR;
-       curprog = P_REPORTER;
-       curstr = errstr;
-       handle_error();
-        amfree(errstr);
-       curstr = NULL;
-       ColumnSpec = "";                /* use the default */
-       if(SetColumnDataFromString(ColumnData, ColumnSpec, &errstr) < 0) {
-           curlog = L_ERROR;
-           curprog = P_REPORTER;
-           curstr = errstr;
-           handle_error();
-            amfree(errstr);
-           curstr = NULL;
-       }
-    }
-    for (cn = 0; ColumnData[cn].Name != NULL; cn++) {
-       if (ColumnData[cn].MaxWidth) {
-           MaxWidthsRequested = 1;
-           break;
-       }
-    }
-
-    if(!logfname) {
-       char *conf_logdir;
-
-       conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
-       logfname = vstralloc(conf_logdir, "/", "log", NULL);
-       amfree(conf_logdir);
-    }
-
-    if((logfile = fopen(logfname, "r")) == NULL) {
-       curlog = L_ERROR;
-       curprog = P_REPORTER;
-       curstr = vstralloc(_("could not open log "),
-                          logfname,
-                          ": ",
-                          strerror(errno),
-                          NULL);
-       handle_error();
-       amfree(curstr);
-    }
-
-    while(logfile && get_logline(logfile)) {
-       switch(curlog) {
-       case L_START:        handle_start(); break;
-       case L_FINISH:       handle_finish(); break;
-
-       case L_INFO:         handle_note(); break;
-       case L_WARNING:      handle_note(); break;
-
-       case L_SUMMARY:      handle_summary(); break;
-       case L_STATS:        handle_stats(); break;
-
-       case L_ERROR:        handle_error(); break;
-       case L_FATAL:        handle_error(); break;
-
-       case L_DISK:         handle_disk(); break;
-
-       case L_DONE:         handle_success(curlog); break;
-       case L_SUCCESS:      handle_success(curlog); break;
-       case L_CHUNKSUCCESS: handle_success(curlog); break;
-       case L_PART:         handle_chunk(curlog); break;
-       case L_PARTPARTIAL:  handle_chunk(curlog); break;
-       case L_CHUNK:        handle_chunk(curlog); break;
-       case L_PARTIAL:      handle_partial(); break;
-       case L_STRANGE:      handle_strange(); break;
-       case L_FAIL:         handle_failed(); break;
-
-       default:
-           curlog = L_ERROR;
-           curprog = P_REPORTER;
-           curstr = vstrallocf(_("unexpected log line: %s"), curstr);
-           handle_error();
-           amfree(curstr);
-       }
-    }
-    afclose(logfile);
-    close_infofile();
-    if(!amflush_run) {
-       generate_missing();
-       generate_bad_estimate();
-    }
-
-    subj_str = vstralloc(getconf_str(CNF_ORG),
-                        " ", amflush_run ? "AMFLUSH" : "AMANDA",
-                        " ", "MAIL REPORT FOR",
-                        " ", nicedate(run_datestamp ? run_datestamp : "0"),
-                        NULL);
-       
-    /* lookup the tapetype and printer type from the amanda.conf file. */
-    tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
-    printer = getconf_str(CNF_PRINTER);
-
-    /* ignore SIGPIPE so if a child process dies we do not also go away */
-    signal(SIGPIPE, SIG_IGN);
-
-    /* open pipe to print spooler if necessary) */
-
-    if(psfname) {
-       /* if the postscript_label_template (tp->lbl_templ) field is not */
-       /* the empty string (i.e. it is set to something), open the      */
-       /* postscript debugging file for writing.                        */
-       if (tp)
-           lbl_templ = tapetype_get_lbl_templ(tp);
-       if (tp && lbl_templ && strcmp(lbl_templ, "") != 0) {
-           if ((postscript = fopen(psfname, "w")) == NULL) {
-               curlog = L_ERROR;
-               curprog = P_REPORTER;
-               curstr = vstrallocf(_("could not open %s: %s"),
-                                  psfname,
-                                  strerror(errno));
-               handle_error();
-               amfree(curstr);
-           }
-       }
-    } else {
-#ifdef LPRCMD
-       if (strcmp(printer, "") != 0)   /* alternate printer is defined */
-           /* print to the specified printer */
-#ifdef LPRFLAG
-           printer_cmd = vstralloc(LPRCMD, " ", LPRFLAG, printer, NULL);
-#else
-           printer_cmd = vstralloc(LPRCMD, NULL);
-#endif
-       else
-           /* print to the default printer */
-           printer_cmd = vstralloc(LPRCMD, NULL);
-#endif
-       if (tp)
-           lbl_templ = tapetype_get_lbl_templ(tp);
-       if (tp && lbl_templ && strcmp(lbl_templ, "") != 0) {
-#ifdef LPRCMD
-           if ((postscript = popen(printer_cmd, "w")) == NULL) {
-               curlog = L_ERROR;
-               curprog = P_REPORTER;
-               curstr = vstrallocf(_("could not open pipe to %s: %s"),
-                                  printer_cmd, strerror(errno));
-               handle_error();
-               amfree(curstr);
-           }
-#else
-           curlog = L_ERROR;
-           curprog = P_REPORTER;
-           curstr = vstrallocf(_("no printer command defined"));
-           handle_error();
-           amfree(curstr);
-#endif
-       }
-    }
-
-    sort_disks();
-
-    /* open pipe to mailer */
-
-    if(outfname) {
-       /* output to a file */
-       if((mailf = fopen(outfname,"w")) == NULL) {
-           error(_("could not open output file: %s %s"), outfname, strerror(errno));
-           /*NOTREACHED*/
-       }
-        if (mailto != NULL) {
-               g_fprintf(mailf, "To: %s\n", mailto);
-               g_fprintf(mailf, "Subject: %s\n\n", subj_str);
-       }
-
-    } else if (mailer) {
-       if(mailto) {
-           send_amreport_t send_amreport;
-           int             do_mail;
-
-           send_amreport = getconf_send_amreport(CNF_SEND_AMREPORT_ON);
-           do_mail = send_amreport == SEND_AMREPORT_ALL ||
-                     (send_amreport == SEND_AMREPORT_STRANGE &&
-                      (!got_finish || first_failed || errsum ||
-                       first_strange || errdet || strangedet)) ||
-                     (send_amreport == SEND_AMREPORT_ERROR &&
-                      (!got_finish || first_failed || errsum || errdet));
-           if (do_mail) {
-               mail_cmd = vstralloc(mailer,
-                            " -s", " \"", subj_str, "\"",
-                            " ", mailto, NULL);
-               if((mailf = popen(mail_cmd, "w")) == NULL) {
-                   error(_("could not open pipe to \"%s\": %s"),
-                         mail_cmd, strerror(errno));
-                   /*NOTREACHED*/
-               }
-           }
-       }
-       else {
-           if (mailout) {
-                g_printf(_("No mail sent! "));
-               g_printf(_("No valid mail address has been specified in amanda.conf or on the commmand line\n"));
-           }
-           mailf = NULL;
-       }
-    }
-
-    amfree(subj_str);
-
-    if(mailf) {
-
-       if(!got_finish) fputs(_("*** THE DUMPS DID NOT FINISH PROPERLY!\n\n"), mailf);
-
-       if (ghostname) {
-           g_fprintf(mailf, _("Hostname: %s\n"), ghostname);
-           g_fprintf(mailf, _("Org     : %s\n"), getconf_str(CNF_ORG));
-           g_fprintf(mailf, _("Config  : %s\n"), get_config_name());
-           g_fprintf(mailf, _("Date    : %s\n"),
-                   nicedate(run_datestamp ? run_datestamp : "0"));
-           g_fprintf(mailf,"\n");
-       }
-
-       output_tapeinfo();
-
-       if(first_failed || errsum) {
-               g_fprintf(mailf,_("\nFAILURE DUMP SUMMARY:\n"));
-               if(first_failed) output_X_summary(first_failed);
-               if(errsum) output_lines(errsum, mailf);
-       }
-       if(first_strange) {
-               g_fprintf(mailf,_("\nSTRANGE DUMP SUMMARY:\n"));
-               if(first_strange) output_X_summary(first_strange);
-       }
-       fputs("\n\n", mailf);
-       
-       output_stats();
-       
-       if(errdet) {
-               g_fprintf(mailf,"\n\f\n");
-               g_fprintf(mailf,_("FAILED DUMP DETAILS:\n"));
-               output_lines(errdet, mailf);
-       }
-       if(strangedet) {
-               g_fprintf(mailf,"\n\f\n");
-               g_fprintf(mailf,_("STRANGE DUMP DETAILS:\n"));
-               output_lines(strangedet, mailf);
-       }
-       if(notes) {
-               g_fprintf(mailf,"\n\f\n");
-               g_fprintf(mailf,_("NOTES:\n"));
-               output_lines(notes, mailf);
-       }
-       if(sortq.head != NULL) {
-               g_fprintf(mailf,"\n\f\n");
-               g_fprintf(mailf,_("DUMP SUMMARY:\n"));
-               output_summary();
-       }
-       g_fprintf(mailf,_("\n(brought to you by Amanda version %s)\n"),
-               version());
-    }
-
-    if (postscript) {
-       do_postscript_output();
-    }
-
-
-    /* close postscript file */
-    if (psfname && postscript) {
-       /* it may be that postscript is NOT opened */
-       afclose(postscript);
-    }
-    else {
-       if (postscript != NULL && pclose(postscript) != 0) {
-           error(_("printer command failed: %s"), printer_cmd);
-           /*NOTREACHED*/
-       }
-       postscript = NULL;
-    }
-
-    /* close output file */
-    if(outfname) {
-        afclose(mailf);
-    }
-    else if(mailf) {
-       int exitcode;
-        if((exitcode = pclose(mailf)) != 0) {
-           char *exitstr = str_exit_status("mail command", exitcode);
-            error("%s", exitstr);
-           /*NOTREACHED*/
-       }
-        mailf = NULL;
-    }
-
-    clear_tapelist();
-    free_disklist(&diskq);
-    amfree(run_datestamp);
-    amfree(tape_labels);
-    amfree(printer_cmd);
-    amfree(mail_cmd);
-    amfree(logfname);
-
-    dbclose();
-    return exit_status;
-}
-
-/* ----- */
-
-#define mb(f)  ((f)/1024)              /* kbytes -> mbutes */
-#define du(f)  ((f)/unitdivisor)       /* kbytes -> displayunit */
-#define pct(f) ((f)*100.0)             /* percent */
-#define hrmn(f) ((int)(f)+30)/3600, (((int)(f)+30)%3600)/60
-#define mnsc(f) ((int)(f+0.5))/60, ((int)(f+0.5)) % 60
-
-#define divzero(fp,a,b)                            \
-    do {                                           \
-       double q = (b);                     \
-       if (!isnormal(q))                   \
-           g_fprintf((fp),"  -- ");        \
-       else if ((q = (a)/q) >= 99999.95)   \
-           g_fprintf((fp), "#####");       \
-       else if (q >= 999.95)               \
-           g_fprintf((fp), "%5.0lf",q);    \
-       else                                \
-           g_fprintf((fp), "%5.1lf",q);    \
-    } while(0)
-#define divzero_wide(fp,a,b)               \
-    do {                                           \
-       double q = (b);                     \
-       if (!isnormal(q))                   \
-           g_fprintf((fp),"    -- ");      \
-       else if ((q = (a)/q) >= 9999999.95) \
-           g_fprintf((fp), "#######");     \
-       else if (q >= 99999.95)             \
-           g_fprintf((fp), "%7.0lf",q);    \
-       else                                \
-           g_fprintf((fp), "%7.1lf",q);    \
-    } while(0)
-
-static void
-output_stats(void)
-{
-    double idle_time;
-    tapetype_t *tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
-    off_t tapesize;
-    off_t marksize;
-    int lv, first;
-
-    if (tp) {
-       tapesize = tapetype_get_length(tp);
-       marksize = tapetype_get_filemark(tp);
-    } else {
-       tapesize = 100 * 1024 * 1024;
-       marksize = 1   * 1024 * 1024;
-    }
-
-    stats[2].dumpdisks   = stats[0].dumpdisks   + stats[1].dumpdisks;
-    stats[2].tapedisks   = stats[0].tapedisks   + stats[1].tapedisks;
-    stats[2].tapechunks  = stats[0].tapechunks  + stats[1].tapechunks;
-    stats[2].outsize     = stats[0].outsize     + stats[1].outsize;
-    stats[2].origsize    = stats[0].origsize    + stats[1].origsize;
-    stats[2].tapesize    = stats[0].tapesize    + stats[1].tapesize;
-    stats[2].coutsize    = stats[0].coutsize    + stats[1].coutsize;
-    stats[2].corigsize   = stats[0].corigsize   + stats[1].corigsize;
-    stats[2].taper_time  = stats[0].taper_time  + stats[1].taper_time;
-    stats[2].dumper_time = stats[0].dumper_time + stats[1].dumper_time;
-
-    if(!got_finish)    /* no driver finish line, estimate total run time */
-       total_time = stats[2].taper_time + planner_time;
-
-    idle_time = (total_time - startup_time) - stats[2].taper_time;
-    if(idle_time < 0) idle_time = 0.0;
-
-    g_fprintf(mailf,_("STATISTICS:\n"));
-    g_fprintf(mailf,
-           _("                          Total       Full      Incr.\n"));
-    g_fprintf(mailf,
-           _("                        --------   --------   --------\n"));
-
-    g_fprintf(mailf,
-           _("Estimate Time (hrs:min)   %2d:%02d\n"), hrmn(planner_time));
-
-    g_fprintf(mailf,
-           _("Run Time (hrs:min)        %2d:%02d\n"), hrmn(total_time));
-
-    g_fprintf(mailf,
-           _("Dump Time (hrs:min)       %2d:%02d      %2d:%02d      %2d:%02d\n"),
-           hrmn(stats[2].dumper_time), hrmn(stats[0].dumper_time),
-           hrmn(stats[1].dumper_time));
-
-    g_fprintf(mailf,
-           _("Output Size (meg)      %8.1lf   %8.1lf   %8.1lf\n"),
-           mb(stats[2].outsize), mb(stats[0].outsize), mb(stats[1].outsize));
-
-    g_fprintf(mailf,
-           _("Original Size (meg)    %8.1lf   %8.1lf   %8.1lf\n"),
-           mb(stats[2].origsize), mb(stats[0].origsize),
-           mb(stats[1].origsize));
-
-    g_fprintf(mailf, _("Avg Compressed Size (%%)   "));
-    divzero(mailf, pct(stats[2].coutsize),stats[2].corigsize);
-    fputs(_("      "), mailf);
-    divzero(mailf, pct(stats[0].coutsize),stats[0].corigsize);
-    fputs(_("      "), mailf);
-    divzero(mailf, pct(stats[1].coutsize),stats[1].corigsize);
-
-    if(stats[1].dumpdisks > 0) fputs(_("   (level:#disks ...)"), mailf);
-    putc('\n', mailf);
-
-    g_fprintf(mailf,
-           _("Filesystems Dumped         %4d       %4d       %4d"),
-           stats[2].dumpdisks, stats[0].dumpdisks, stats[1].dumpdisks);
-
-    if(stats[1].dumpdisks > 0) {
-       first = 1;
-       for(lv = 1; lv < 10; lv++) if(dumpdisks[lv]) {
-           fputs(first?_("   ("):_(" "), mailf);
-           first = 0;
-           g_fprintf(mailf, _("%d:%d"), lv, dumpdisks[lv]);
-       }
-       putc(')', mailf);
-    }
-    putc('\n', mailf);
-
-    g_fprintf(mailf, _("Avg Dump Rate (k/s)     "));
-    divzero_wide(mailf, stats[2].outsize,stats[2].dumper_time);
-    fputs(_("    "), mailf);
-    divzero_wide(mailf, stats[0].outsize,stats[0].dumper_time);
-    fputs(_("    "), mailf);
-    divzero_wide(mailf, stats[1].outsize,stats[1].dumper_time);
-    putc('\n', mailf);
-
-    putc('\n', mailf);
-    g_fprintf(mailf,
-           _("Tape Time (hrs:min)       %2d:%02d      %2d:%02d      %2d:%02d\n"),
-           hrmn(stats[2].taper_time), hrmn(stats[0].taper_time),
-           hrmn(stats[1].taper_time));
-
-    g_fprintf(mailf,
-           _("Tape Size (meg)        %8.1lf   %8.1lf   %8.1lf\n"),
-           mb(stats[2].tapesize), mb(stats[0].tapesize),
-           mb(stats[1].tapesize));
-
-    g_fprintf(mailf, _("Tape Used (%%)             "));
-    divzero(mailf, pct(stats[2].tapesize+marksize*(stats[2].tapedisks+stats[2].tapechunks)),(double)tapesize);
-    fputs(_("      "), mailf);
-    divzero(mailf, pct(stats[0].tapesize+marksize*(stats[0].tapedisks+stats[0].tapechunks)),(double)tapesize);
-    fputs(_("      "), mailf);
-    divzero(mailf, pct(stats[1].tapesize+marksize*(stats[1].tapedisks+stats[1].tapechunks)),(double)tapesize);
-
-    if(stats[1].tapedisks > 0) fputs(_("   (level:#disks ...)"), mailf);
-    putc('\n', mailf);
-
-    g_fprintf(mailf,
-           _("Filesystems Taped          %4d       %4d       %4d"),
-           stats[2].tapedisks, stats[0].tapedisks, stats[1].tapedisks);
-
-    if(stats[1].tapedisks > 0) {
-       first = 1;
-       for(lv = 1; lv < 10; lv++) if(tapedisks[lv]) {
-           fputs(first?_("   ("):_(" "), mailf);
-           first = 0;
-           g_fprintf(mailf, _("%d:%d"), lv, tapedisks[lv]);
-       }
-       putc(')', mailf);
-    }
-    putc('\n', mailf);
-
-    if(stats[1].tapechunks > 0) fputs(_("   (level:#chunks ...)"), mailf);
-    putc('\n', mailf);
-
-    g_fprintf(mailf,
-           _("Chunks Taped               %4d       %4d       %4d"),
-           stats[2].tapechunks, stats[0].tapechunks, stats[1].tapechunks);
-
-    if(stats[1].tapechunks > 0) {
-       first = 1;
-       for(lv = 1; lv < 10; lv++) if(tapechunks[lv]) {
-           fputs(first?_("   ("):_(" "), mailf);
-           first = 0;
-           g_fprintf(mailf, _("%d:%d"), lv, tapechunks[lv]);
-       }
-       putc(')', mailf);
-    }
-    putc('\n', mailf);
-
-    g_fprintf(mailf, _("Avg Tp Write Rate (k/s) "));
-    divzero_wide(mailf, stats[2].tapesize,stats[2].taper_time);
-    fputs(_("    "), mailf);
-    divzero_wide(mailf, stats[0].tapesize,stats[0].taper_time);
-    fputs(_("    "), mailf);
-    divzero_wide(mailf, stats[1].tapesize,stats[1].taper_time);
-    putc('\n', mailf);
-
-    if(stats_by_tape) {
-       int label_length = (int)strlen(stats_by_tape->label) + 5;
-       g_fprintf(mailf,_("\nUSAGE BY TAPE:\n"));
-       g_fprintf(mailf,_("  %-*s  Time      Size      %%    Nb    Nc\n"),
-               label_length, _("Label"));
-       for(current_tape = stats_by_tape; current_tape != NULL;
-           current_tape = current_tape->next) {
-           g_fprintf(mailf, _("  %-*s"), label_length, current_tape->label);
-           g_fprintf(mailf, _(" %2d:%02d"), hrmn(current_tape->taper_time));
-           g_fprintf(mailf, _(" %8.0lf%s  "), du(current_tape->coutsize), displayunit);
-           divzero(mailf, pct(current_tape->coutsize + marksize *
-                  (current_tape->tapedisks+current_tape->tapechunks)),
-                  (double)tapesize);
-           g_fprintf(mailf, _("  %4d"), current_tape->tapedisks);
-           g_fprintf(mailf, _("  %4d\n"), current_tape->tapechunks);
-       }
-    }
-}
-
-/* ----- */
-
-static void
-output_tapeinfo(void)
-{
-    tape_t *tp;
-    int run_tapes;
-    int skip = 0;
-    int i, nb_new_tape;
-
-    if (last_run_tapes > 0) {
-       if(amflush_run)
-           g_fprintf(mailf,
-                   plural(_("The dumps were flushed to tape %s.\n"),
-                          _("The dumps were flushed to tapes %s.\n"),
-                          last_run_tapes),
-                   tape_labels ? tape_labels : "");
-       else
-           g_fprintf(mailf,
-                   plural(_("These dumps were to tape %s.\n"),
-                          _("These dumps were to tapes %s.\n"),
-                          last_run_tapes),
-                   tape_labels ? tape_labels : "");
-    }
-
-    if(degraded_mode) {
-       g_fprintf(mailf,
-               _("*** A TAPE ERROR OCCURRED: %s.\n"), tapestart_error);
-    }
-    if (cmdlogfname == 1) {
-       if(degraded_mode) {
-           fputs(_("Some dumps may have been left in the holding disk.\n"),
-                 mailf);
-           g_fprintf(mailf,"\n");
-       }
-    }  else {
-       GSList *holding_list, *holding_file;
-       off_t  h_size = 0, mh_size;
-
-       holding_list = holding_get_files_for_flush(NULL);
-       for(holding_file=holding_list; holding_file != NULL;
-                                      holding_file = holding_file->next) {
-           mh_size = holding_file_size((char *)holding_file->data, 1);
-           if (mh_size > 0)
-               h_size += mh_size;
-       }
-
-       if (h_size > 0) {
-           g_fprintf(mailf,
-                   _("There are %lld%s of dumps left in the holding disk.\n"),
-                   (long long)du(h_size), displayunit);
-           if (getconf_boolean(CNF_AUTOFLUSH)) {
-               g_fprintf(mailf, _("They will be flushed on the next run.\n"));
-           } else {
-               g_fprintf(mailf, _("Run amflush to flush them to tape.\n"));
-           }
-           g_fprintf(mailf,"\n");
-       } else if (degraded_mode) {
-           g_fprintf(mailf, _("No dumps are left in the holding disk. %lld%s\n"), (long long)h_size, displayunit);
-           g_fprintf(mailf,"\n");
-       }
-    }
-
-    tp = lookup_last_reusable_tape(skip);
-
-    run_tapes = getconf_int(CNF_RUNTAPES);
-
-    if (run_tapes == 1)
-       fputs(_("The next tape Amanda expects to use is: "), mailf);
-    else if(run_tapes > 1)
-       g_fprintf(mailf, _("The next %d tapes Amanda expects to use are: "),
-               run_tapes);
-
-    nb_new_tape = 0;
-    for (i=0 ; i < run_tapes ; i++) {
-       if(tp != NULL) {
-           if (nb_new_tape > 0) {
-               if (nb_new_tape == 1)
-                   g_fprintf(mailf, _("1 new tape, "));
-               else
-                   g_fprintf(mailf, _("%d new tapes, "), nb_new_tape);
-               nb_new_tape = 0;
-           }
-           g_fprintf(mailf, "%s", tp->label);
-           if (i < run_tapes-1) fputs(", ", mailf);
-       } else {
-           nb_new_tape++;
-       }
-       skip++;
-
-       tp = lookup_last_reusable_tape(skip);
-    }
-    if (nb_new_tape > 0) {
-       if (nb_new_tape == 1)
-           g_fprintf(mailf, _("1 new tape"));
-       else
-           g_fprintf(mailf, _("%d new tapes"), nb_new_tape);
-    }
-    fputs(".\n", mailf);
-
-    run_tapes = getconf_int(CNF_RUNTAPES);
-    print_new_tapes(mailf, run_tapes);
-}
-
-/* ----- */
-static void
-output_X_summary(
-    X_summary_t *first)
-{
-    size_t len_host=0, len_disk=0;
-    X_summary_t *strange;
-    char *str = NULL;
-
-    for(strange=first; strange != NULL; strange = strange->next) {
-       if(strlen(strange->hostname) > len_host)
-           len_host = strlen(strange->hostname);
-       if(strlen(strange->diskname) > len_disk)
-           len_disk = strlen(strange->diskname);
-    }
-    for(strange=first; strange != NULL; strange = strange->next) {
-       str = vstralloc("  ", prefixstrange(strange->hostname, strange->diskname, strange->level, len_host, len_disk),
-                       "  ", strange->str, NULL);
-       g_fprintf(mailf, "%s\n", str);
-       amfree(str);
-    }
-}
-
-static void
-output_lines(
-    line_t *   lp,
-    FILE *     f)
-{
-    line_t *next;
-
-    while(lp) {
-       fputs(lp->str, f);
-       amfree(lp->str);
-       fputc('\n', f);
-       next = lp->next;
-       amfree(lp);
-       lp = next;
-    }
-}
-
-/* ----- */
-
-static int
-sort_by_name(
-    disk_t *   a,
-    disk_t *   b)
-{
-    int rc;
-
-    rc = strcmp(a->host->hostname, b->host->hostname);
-    if(rc == 0) rc = strcmp(a->name, b->name);
-    return rc;
-}
-
-static void
-sort_disks(void)
-{
-    disk_t *dp;
-
-    sortq.head = sortq.tail = NULL;
-    while(!empty(diskq)) {
-       dp = dequeue_disk(&diskq);
-       if(data(dp) == NULL) { /* create one */
-           find_repdata(dp, run_datestamp, 0);
-       }
-       insert_disk(&sortq, dp, sort_by_name);
-    }
-}
-
-static void
-CheckStringMax(
-    ColumnInfo *cd,
-    char *     s)
-{
-    if (cd->MaxWidth) {
-       int l = (int)strlen(s);
-
-       if (cd->Width < l)
-           cd->Width= l;
-    }
-}
-
-static void
-CheckIntMax(
-    ColumnInfo *cd,
-    int                n)
-{
-    if (cd->MaxWidth) {
-       char testBuf[200];
-       int l;
-
-       g_snprintf(testBuf, SIZEOF(testBuf),
-         cd->Format, cd->Width, cd->Precision, n);
-       l = (int)strlen(testBuf);
-       if (cd->Width < l)
-           cd->Width= l;
-    }
-}
-
-static void
-CheckFloatMax(
-    ColumnInfo *cd,
-    double     d)
-{
-    if (cd->MaxWidth) {
-       char testBuf[200];
-       int l;
-
-       g_snprintf(testBuf, SIZEOF(testBuf),
-         cd->Format, cd->Width, cd->Precision, d);
-       l = (int)strlen(testBuf);
-       if (cd->Width < l)
-           cd->Width= l;
-    }
-}
-
-static int HostName;
-static int Disk;
-static int Level;
-static int OrigKB;
-static int OutKB;
-static int Compress;
-static int DumpTime;
-static int DumpRate;
-static int TapeTime;
-static int TapeRate;
-
-static void
-CalcMaxWidth(void)
-{
-    /* we have to look for columspec's, that require the recalculation.
-     * we do here the same loops over the sortq as is done in
-     * output_summary. So, if anything is changed there, we have to
-     * change this here also.
-     *                                                 ElB, 1999-02-24.
-     */
-    disk_t *dp;
-    double f;
-    repdata_t *repdata;
-    char *qdevname;
-    int i, l;
-
-    for (i=0;ColumnData[i].Name != NULL; i++) {
-       if (ColumnData[i].MaxWidth) {
-           l = (int)strlen(ColumnData[i].Title);
-           if (ColumnData[i].Width < l)
-               ColumnData[i].Width= l;
-       }
-    }
-
-    for(dp = sortq.head; dp != NULL; dp = dp->next) {
-      if(dp->todo) {
-       for(repdata = data(dp); repdata != NULL; repdata = repdata->next) {
-           char TimeRateBuffer[40];
-
-           CheckStringMax(&ColumnData[HostName], dp->host->hostname);
-           qdevname = quote_string(dp->name);
-           CheckStringMax(&ColumnData[Disk], qdevname);
-           amfree(qdevname);
-           if (repdata->dumper.result == L_BOGUS && 
-               repdata->taper.result == L_BOGUS)
-               continue;
-           CheckIntMax(&ColumnData[Level], repdata->level);
-            if(repdata->dumper.result == L_SUCCESS || 
-                   repdata->dumper.result == L_CHUNKSUCCESS) {
-               CheckFloatMax(&ColumnData[OrigKB],
-                             (double)du(repdata->dumper.origsize));
-               CheckFloatMax(&ColumnData[OutKB],
-                             (double)du(repdata->dumper.outsize));
-               if(abs(repdata->dumper.outsize - repdata->dumper.origsize)< 32)
-                   f = 0.0;
-               else 
-                   f = repdata->dumper.origsize;
-               CheckStringMax(&ColumnData[Compress], 
-                       sDivZero(pct(repdata->dumper.outsize), f, Compress));
-
-               if(!amflush_run)
-                   g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer),
-                               "%3d:%02d", mnsc(repdata->dumper.sec));
-               else
-                   g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer),
-                               " ");
-               CheckStringMax(&ColumnData[DumpTime], TimeRateBuffer);
-
-               CheckFloatMax(&ColumnData[DumpRate], repdata->dumper.kps); 
-           }
-
-           if(repdata->taper.result == L_FAIL) {
-               CheckStringMax(&ColumnData[TapeTime], "FAILED");
-               continue;
-           }
-           if(repdata->taper.result == L_SUCCESS ||
-              repdata->taper.result == L_CHUNKSUCCESS)
-               g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer), 
-                 "%3d:%02d", mnsc(repdata->taper.sec));
-           else
-               g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer),
-                 " ");
-           CheckStringMax(&ColumnData[TapeTime], TimeRateBuffer);
-
-           if(repdata->taper.result == L_SUCCESS ||
-                   repdata->taper.result == L_CHUNKSUCCESS)
-               CheckFloatMax(&ColumnData[TapeRate], repdata->taper.kps);
-           else
-               CheckStringMax(&ColumnData[TapeRate], " ");
-       }
-      }
-    }
-}
-
-static void
-output_summary(void)
-{
-    disk_t *dp;
-    repdata_t *repdata;
-    char *ds="DUMPER STATS";
-    char *ts=" TAPER STATS";
-    char *tmp;
-
-    int i, h, w1, wDump, wTape;
-    double outsize, origsize;
-    double f;
-    int cdWidth;
-
-    HostName = StringToColumn("HostName");
-    Disk = StringToColumn("Disk");
-    Level = StringToColumn("Level");
-    OrigKB = StringToColumn("OrigKB");
-    OutKB = StringToColumn("OutKB");
-    Compress = StringToColumn("Compress");
-    DumpTime = StringToColumn("DumpTime");
-    DumpRate = StringToColumn("DumpRate");
-    TapeTime = StringToColumn("TapeTime");
-    TapeRate = StringToColumn("TapeRate");
-
-    /* at first determine if we have to recalculate our widths */
-    if (MaxWidthsRequested)
-       CalcMaxWidth();
-
-    /* title for Dumper-Stats */
-    w1= ColWidth(HostName, Level);
-    wDump= ColWidth(OrigKB, DumpRate);
-    wTape= ColWidth(TapeTime, TapeRate);
-
-    /* print centered top titles */
-    h = (int)strlen(ds);
-    if (h > wDump) {
-       h = 0;
-    } else {
-       h = (wDump-h)/2;
-    }
-    g_fprintf(mailf, "%*s", w1+h, "");
-    g_fprintf(mailf, "%-*s", wDump-h, ds);
-    h = (int)strlen(ts);
-    if (h > wTape) {
-       h = 0;
-    } else {
-       h = (wTape-h)/2;
-    }
-    g_fprintf(mailf, "%*s", h, "");
-    g_fprintf(mailf, "%-*s", wTape-h, ts);
-    fputc('\n', mailf);
-
-    /* print the titles */
-    for (i=0; ColumnData[i].Name != NULL; i++) {
-       char *fmt;
-       ColumnInfo *cd= &ColumnData[i];
-       g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-       if (cd->Format[1] == '-')
-           fmt= "%-*s";
-       else
-           fmt= "%*s";
-       if(strcmp(cd->Title,"ORIG-KB") == 0) {
-           /* cd->Title must be re-allocated in write-memory */
-           cd->Title = stralloc("ORIG-KB");
-           cd->Title[5] = displayunit[0];
-       }
-       if(strcmp(cd->Title,"OUT-KB") == 0) {
-           /* cd->Title must be re-allocated in write-memory */
-           cd->Title = stralloc("OUT-KB");
-           cd->Title[4] = displayunit[0];
-       }
-       g_fprintf(mailf, fmt, cd->Width, cd->Title);
-    }
-    fputc('\n', mailf);
-
-    /* print the rules */
-    fputs(tmp=Rule(HostName, Level), mailf); amfree(tmp);
-    fputs(tmp=Rule(OrigKB, DumpRate), mailf); amfree(tmp);
-    fputs(tmp=Rule(TapeTime, TapeRate), mailf); amfree(tmp);
-    fputc('\n', mailf);
-
-    for(dp = sortq.head; dp != NULL; dp = dp->next) {
-      if(dp->todo) {
-       ColumnInfo *cd;
-       char TimeRateBuffer[40];
-       for(repdata = data(dp); repdata != NULL; repdata = repdata->next) {
-           char *devname;
-           char *qdevname;
-           size_t devlen;
-
-           cd= &ColumnData[HostName];
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           g_fprintf(mailf, cd->Format, cd->Width, cd->Width, dp->host->hostname);
-
-           cd= &ColumnData[Disk];
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           devname = sanitize_string(dp->name);
-           qdevname = quote_string(devname);
-           devlen = strlen(qdevname);
-           if (devlen > (size_t)cd->Width) {
-               int nb = 1;
-               if (strcmp(devname, qdevname)) {
-                   nb = 2;
-                   fputc('"', mailf); 
-               }
-               fputc('-', mailf); 
-               g_fprintf(mailf, cd->Format, cd->Width-nb, cd->Precision-nb,
-                       qdevname+devlen - (cd->Width-nb) );
-           }
-           else
-               g_fprintf(mailf, cd->Format, cd->Width, cd->Width, qdevname);
-           amfree(devname);
-           amfree(qdevname);
-           cd= &ColumnData[Level];
-           if (repdata->dumper.result == L_BOGUS &&
-               repdata->taper.result  == L_BOGUS) {
-             if(amflush_run){
-               g_fprintf(mailf, "%*s%s\n", cd->PrefixSpace+cd->Width, "",
-                       tmp=TextRule(OrigKB, TapeRate, "NO FILE TO FLUSH"));
-             } else {
-               g_fprintf(mailf, "%*s%s\n", cd->PrefixSpace+cd->Width, "",
-                       tmp=TextRule(OrigKB, TapeRate, "MISSING"));
-             }
-             amfree(tmp);
-             continue;
-           }
-           
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           g_fprintf(mailf, cd->Format, cd->Width, cd->Precision,repdata->level);
-
-           if (repdata->dumper.result == L_SKIPPED) {
-               g_fprintf(mailf, "%s\n",
-                       tmp=TextRule(OrigKB, TapeRate, "SKIPPED"));
-               amfree(tmp);
-               continue;
-           }
-           if (repdata->dumper.result == L_FAIL && (repdata->chunker.result != L_PARTIAL && repdata->taper.result  != L_PARTIAL)) {
-               g_fprintf(mailf, "%s\n",
-                       tmp=TextRule(OrigKB, TapeRate, "FAILED"));
-               amfree(tmp);
-               exit_status |= STATUS_FAILED;
-               continue;
-           }
-
-           if(repdata->dumper.result == L_SUCCESS ||
-              repdata->dumper.result == L_CHUNKSUCCESS)
-               origsize = repdata->dumper.origsize;
-           else if(repdata->taper.result == L_SUCCESS ||
-                   repdata->taper.result == L_PARTIAL)
-               origsize = repdata->taper.origsize;
-           else
-               origsize = repdata->chunker.origsize;
-
-           if(repdata->taper.result == L_SUCCESS ||
-              repdata->taper.result == L_CHUNKSUCCESS)
-               outsize  = repdata->taper.outsize;
-           else if(repdata->chunker.result == L_SUCCESS ||
-                   repdata->chunker.result == L_PARTIAL ||
-                   repdata->chunker.result == L_CHUNKSUCCESS)
-               outsize  = repdata->chunker.outsize;
-           else if (repdata->taper.result == L_PARTIAL)
-               outsize  = repdata->taper.outsize;
-           else
-               outsize  = repdata->dumper.outsize;
-
-           cd= &ColumnData[OrigKB];
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           if(isnormal(origsize))
-               g_fprintf(mailf, cd->Format, cd->Width, cd->Precision, du(origsize));
-           else
-               g_fprintf(mailf, "%*.*s", cd->Width, cd->Width, "");
-
-           cd= &ColumnData[OutKB];
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-
-           g_fprintf(mailf, cd->Format, cd->Width, cd->Precision, du(outsize));
-               
-           cd= &ColumnData[Compress];
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-
-           if(abs(outsize - origsize) < 32)
-               f = 0.0;
-           else if(origsize < 1.0)
-               f = 0.0;
-           else
-               f = origsize;
-
-           fputs(sDivZero(pct(outsize), f, Compress), mailf);
-
-           cd= &ColumnData[DumpTime];
-           cdWidth = 0;
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           if(repdata->dumper.result == L_SUCCESS ||
-              repdata->dumper.result == L_CHUNKSUCCESS) {
-               g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer),
-                 "%3d:%02d", mnsc(repdata->dumper.sec)); 
-               g_fprintf(mailf, cd->Format, cd->Width, cd->Width,
-                         TimeRateBuffer);
-           } else {
-               cdWidth = cd->Width;
-           }
-
-           cd= &ColumnData[DumpRate];
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           if (repdata->dumper.result == L_SUCCESS ||
-               repdata->dumper.result == L_CHUNKSUCCESS) {
-               g_fprintf(mailf, cd->Format, cd->Width, cd->Precision,
-                         repdata->dumper.kps);
-           } else if (repdata->dumper.result == L_FAIL) {
-               if (repdata->chunker.result == L_PARTIAL ||
-                   repdata->taper.result == L_PARTIAL) {
-                   int i;
-                   cdWidth += cd->Width;
-                   i = (cdWidth - strlen("PARTIAL")) / 2;
-                   g_fprintf(mailf, "%*s%*s", cdWidth-i, "PARTIAL", i, "");
-               } else {
-                   int i;
-                   cdWidth += cd->Width;
-                   i = (cdWidth - strlen("FAILED")) / 2;
-                   g_fprintf(mailf, "%*s%*s", cdWidth-i, "FAILED", i, "");
-               }
-           } else if (repdata->dumper.result == L_BOGUS) {
-               int i;
-               cdWidth += cd->Width;
-               i = (cdWidth - strlen("FLUSH")) / 2;
-               g_fprintf(mailf, "%*s%*s", cdWidth-i, "FLUSH", i, "");
-           } else {
-               cdWidth += cd->Width;
-               g_fprintf(mailf, "%*s", cdWidth, "");
-           }
-
-           cd= &ColumnData[TapeTime];
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           if(repdata->taper.result == L_FAIL) {
-               g_fprintf(mailf, "%s\n",
-                       tmp=TextRule(TapeTime, TapeRate, "FAILED "));
-               amfree(tmp);
-               continue;
-           }
-
-           if(repdata->taper.result == L_SUCCESS || 
-              repdata->taper.result == L_PARTIAL ||
-              repdata->taper.result == L_CHUNKSUCCESS)
-               g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer),
-                 "%3d:%02d", mnsc(repdata->taper.sec));
-           else
-               g_snprintf(TimeRateBuffer, SIZEOF(TimeRateBuffer),
-                 " ");
-           g_fprintf(mailf, cd->Format, cd->Width, cd->Width, TimeRateBuffer);
-
-           cd= &ColumnData[TapeRate];
-           g_fprintf(mailf, "%*s", cd->PrefixSpace, "");
-           if(repdata->taper.result == L_SUCCESS || 
-              repdata->taper.result == L_PARTIAL ||
-              repdata->taper.result == L_CHUNKSUCCESS)
-               g_fprintf(mailf, cd->Format, cd->Width, cd->Precision, repdata->taper.kps);
-           else
-               g_fprintf(mailf, "%*s", cd->Width, " ");
-
-           if (repdata->chunker.result == L_PARTIAL)
-               g_fprintf(mailf, " PARTIAL");
-           else if(repdata->taper.result == L_PARTIAL)
-               g_fprintf(mailf, " TAPE-PARTIAL");
-
-           fputc('\n', mailf);
-       }
-      }
-    }
-}
-
-static void
-bogus_line(
-    const char *err_text)
-{
-    char * s;
-    s = g_strdup_printf(_("line %d of log is bogus: <%s %s %s>\n"),
-                        curlinenum, 
-                        logtype_str[curlog], program_str[curprog], curstr);
-    g_printf("%s\n", s);
-    g_printf(_("  Scan failed at: <%s>\n"), err_text);
-    addline(&errsum, s);
-    amfree(s);
-}
-
-
-/*
- * Formats an integer of the form YYYYMMDDHHMMSS into the string
- * "Monthname DD, YYYY".  A pointer to the statically allocated string
- * is returned, so it must be copied to other storage (or just printed)
- * before calling nicedate() again.
- */
-static char *
-nicedate(
-    const char *datestamp)
-{
-    static char nice[64];
-    char date[9];
-    int  numdate;
-    static char *months[13] = {
-               T_("BogusMonth"),
-               T_("January"),
-               T_("February"),
-               T_("March"),
-               T_("April"),
-               T_("May"),
-               T_("June"),
-               T_("July"),
-               T_("August"),
-               T_("September"),
-               T_("October"),
-               T_("November"),
-               T_("December")
-    };
-    int year, month, day;
-
-    strncpy(date, datestamp, 8);
-    date[8] = '\0';
-    numdate = atoi(date);
-    year  = numdate / 10000;
-    day   = numdate % 100;
-    month = (numdate / 100) % 100;
-    if (month > 12 )
-       month = 0;
-
-    g_snprintf(nice, SIZEOF(nice), "%s %d, %d", _(months[month]), day, year);
-
-    return nice;
-}
-
-static void
-handle_start(void)
-{
-    static int started = 0;
-    char *label;
-    char *s, *fp;
-    int ch;
-
-    switch(curprog) {
-    case P_TAPER:
-       s = curstr;
-       ch = *s++;
-
-       skip_whitespace(s, ch);
-       if(ch == '\0' || strncmp_const_skip(s - 1, "datestamp", s, ch) != 0) {
-           bogus_line(s - 1);
-           return;
-       }
-
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           bogus_line(s - 1);
-           return;
-       }
-       fp = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       run_datestamp = newstralloc(run_datestamp, fp);
-       s[-1] = (char)ch;
-
-       skip_whitespace(s, ch);
-       if(ch == '\0' || strncmp_const_skip(s - 1, "label", s, ch) != 0) {
-           bogus_line(s - 1);
-           return;
-       }
-
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           bogus_line(s - 1);
-           return;
-       }
-       fp = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-
-       label = stralloc(fp);
-       s[-1] = (char)ch;
-
-       if(tape_labels) {
-           fp = vstralloc(tape_labels, ", ", label, NULL);
-           amfree(tape_labels);
-           tape_labels = fp;
-       } else {
-           tape_labels = stralloc(label);
-       }
-
-       last_run_tapes++;
-
-       if(stats_by_tape == NULL) {
-           stats_by_tape = current_tape = (taper_t *)alloc(SIZEOF(taper_t));
-       }
-       else {
-           current_tape->next = (taper_t *)alloc(SIZEOF(taper_t));
-           current_tape = current_tape->next;
-       }
-       current_tape->label = label;
-       current_tape->taper_time = 0.0;
-       current_tape->coutsize = 0.0;
-       current_tape->corigsize = 0.0;
-       current_tape->tapedisks = 0;
-       current_tape->tapechunks = 0;
-       current_tape->next = NULL;
-       tapefcount = 0;
-
-       return;
-    case P_PLANNER:
-       normal_run = 1;
-       break;
-    case P_DRIVER:
-       break;
-    case P_AMFLUSH:
-       amflush_run = 1;
-       break;
-    default:
-       ;
-    }
-
-    if(!started) {
-       s = curstr;
-       ch = *s++;
-
-       skip_whitespace(s, ch);
-       if(ch == '\0' || strncmp_const_skip(s - 1, "date", s, ch) != 0) {
-           return;                             /* ignore bogus line */
-       }
-
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           bogus_line(s - 1);
-           return;
-       }
-       fp = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       run_datestamp = newstralloc(run_datestamp, fp);
-       s[-1] = (char)ch;
-
-       started = 1;
-    }
-    if(amflush_run && normal_run) {
-       amflush_run = 0;
-       addline(&notes,
-     _("  reporter: both amflush and planner output in log, ignoring amflush."));
-    }
-}
-
-
-static void
-handle_finish(void)
-{
-    char *s;
-    int ch;
-    double a_time;
-
-    if(curprog == P_DRIVER || curprog == P_AMFLUSH || curprog == P_PLANNER) {
-       s = curstr;
-       ch = *s++;
-
-       skip_whitespace(s, ch);
-       if(ch == '\0' || strncmp_const_skip(s - 1, "date", s, ch) != 0) {
-           bogus_line(s - 1);
-           return;
-       }
-
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           bogus_line(s - 1);
-           return;
-       }
-       skip_non_whitespace(s, ch);     /* ignore the date string */
-
-       skip_whitespace(s, ch);
-       if(ch == '\0' || strncmp_const_skip(s - 1, "time", s, ch) != 0) {
-           /* older planner doesn't write time */
-           if(curprog == P_PLANNER) return;
-           bogus_line(s - 1);
-           return;
-       }
-
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           bogus_line(s - 1);
-           return;
-       }
-       if(sscanf(s - 1, "%lf", &a_time) != 1) {
-           bogus_line(s - 1);
-           return;
-       }
-       if(curprog == P_PLANNER) {
-           planner_time = a_time;
-       }
-       else {
-           total_time = a_time;
-           got_finish = 1;
-       }
-    }
-}
-
-static void
-handle_stats(void)
-{
-    char *s, *fp;
-    int ch;
-    char *hostname, *diskname, *datestamp, *qdiskname;
-    int level = 0;
-    double sec, kps, nbytes, cbytes;
-    repdata_t *repdata;
-    disk_t *dp;
-
-    if(curprog == P_DRIVER) {
-       s = curstr;
-       ch = *s++;
-
-       skip_whitespace(s, ch);
-       if(ch != '\0' && strncmp_const_skip(s - 1, "startup time", s, ch) == 0) {
-           skip_whitespace(s, ch);
-           if(ch == '\0') {
-               bogus_line(s - 1);
-               return;
-           }
-           if(sscanf(s - 1, "%lf", &startup_time) != 1) {
-               bogus_line(s - 1);
-               return;
-           }
-           planner_time = startup_time;
-       }
-       else if(ch != '\0' && strncmp_const_skip(s - 1, "hostname", s, ch) == 0) {
-           skip_whitespace(s, ch);
-           if(ch == '\0') {
-               bogus_line(s - 1);
-               return;
-           }
-           ghostname = stralloc(s-1);
-       }
-       else if(ch != '\0' && strncmp_const_skip(s - 1, "estimate", s, ch) == 0) {
-           skip_whitespace(s, ch);
-           if(ch == '\0') {
-               bogus_line(s - 1);
-               return;
-           }
-           fp = s - 1;
-           skip_non_whitespace(s, ch);
-           s[-1] = '\0';
-           hostname = stralloc(fp);
-           s[-1] = (char)ch;
-
-           skip_whitespace(s, ch);
-           if(ch == '\0') {
-               bogus_line(s - 1);
-               amfree(hostname);
-               return;
-           }
-
-           qdiskname = s - 1;
-           skip_quoted_string(s, ch);
-           s[-1] = '\0';
-           diskname = unquote_string(qdiskname);
-           s[-1] = (char)ch;
-
-           skip_whitespace(s, ch);
-           if(ch == '\0') {
-               bogus_line(s - 1);
-               amfree(hostname);
-               amfree(diskname);
-               return;
-           }
-           fp = s - 1;
-           skip_non_whitespace(s, ch);
-           s[-1] = '\0';
-           datestamp = stralloc(fp);
-           s[-1] = (char)ch;
-           skip_whitespace(s, ch);
-
-           if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
-               bogus_line(s - 1);
-               amfree(hostname);
-               amfree(diskname);
-               amfree(datestamp);
-               return;
-           }
-           skip_integer(s, ch);
-           if(level < 0 || level > 9) {
-               amfree(hostname);
-               amfree(diskname);
-               amfree(datestamp);
-               return;
-           }
-
-           skip_whitespace(s, ch);
-
-           if(sscanf(s - 1,"[sec %lf nkb %lf ckb %lf kps %lf",
-                     &sec, &nbytes, &cbytes, &kps) != 4)  {
-               bogus_line(s - 1);
-               amfree(hostname);
-               amfree(diskname);
-               amfree(datestamp);
-               return;
-           }
-
-           dp = lookup_disk(hostname, diskname);
-           if(dp == NULL) {
-               addtoX_summary(&first_failed, &last_failed,
-                              hostname, diskname, level,
-                              _("ERROR [not in disklist]"));
-               exit_status |= STATUS_FAILED;
-               amfree(hostname);
-               amfree(diskname);
-               amfree(datestamp);
-               return;
-           }
-
-           repdata = find_repdata(dp, datestamp, level);
-
-           repdata->est_nsize = nbytes;
-           repdata->est_csize = cbytes;
-
-           amfree(hostname);
-           amfree(diskname);
-           amfree(datestamp);
-       }
-       else {
-           bogus_line(s - 1);
-           return;
-       }
-#undef sc
-
-    }
-}
-
-
-static void
-handle_note(void)
-{
-    char *str = NULL;
-    char *pidstr;
-
-    if (curprog == P_DRIVER &&
-       BSTRNCMP(curstr, "Taper protocol error") == 0) {
-       exit_status |= STATUS_TAPE;
-    }
-    pidstr = strchr(curstr,' ');
-    if (pidstr) {
-       pidstr++;
-    }
-    /* Don't report the pid lines */
-    if ((!pidstr || BSTRNCMP(pidstr, "pid ") != 0) &&
-       BSTRNCMP(curstr, "pid-done ") != 0) {
-       str = vstrallocf("  %s: %s", program_str[curprog], curstr);
-       addline(&notes, str);
-       amfree(str);
-    }
-}
-
-
-/* ----- */
-
-static void
-handle_error(void)
-{
-    char *s = NULL, *nl;
-    int ch;
-
-    if(curlog == L_ERROR && curprog == P_TAPER) {
-       s = curstr;
-       ch = *s++;
-
-       skip_whitespace(s, ch);
-       if(ch != '\0' && strncmp_const_skip(s - 1, "no-tape", s, ch) == 0) {
-           skip_whitespace(s, ch);
-           if(ch != '\0') {
-               if((nl = strchr(s - 1, '\n')) != NULL) {
-                   *nl = '\0';
-               }
-               tapestart_error = newstralloc(tapestart_error, s - 1);
-               if(nl) *nl = '\n';
-               degraded_mode = 1;
-               exit_status |= STATUS_TAPE;;
-               return;
-           }
-           /* else some other tape error, handle like other errors */
-       }
-       /* else some other tape error, handle like other errors */
-    }
-    s = vstrallocf("  %s: %s %s", program_str[curprog],
-                 logtype_str[curlog], curstr);
-    addline(&errsum, s);
-    amfree(s);
-}
-
-/* ----- */
-
-static void
-handle_summary(void)
-{
-    bogus_line(curstr);
-}
-
-/* ----- */
-
-static int nb_disk=0;
-static void
-handle_disk(void)
-{
-    disk_t *dp;
-    char *s, *fp, *qdiskname;
-    int ch;
-    char *hostname = NULL, *diskname = NULL;
-
-    if(curprog != P_PLANNER && curprog != P_AMFLUSH) {
-       bogus_line(curstr);
-       return;
-    }
-
-    if(nb_disk==0) {
-       for(dp = diskq.head; dp != NULL; dp = dp->next)
-           dp->todo = 0;
-    }
-    nb_disk++;
-
-    s = curstr;
-    ch = *s++;
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       return;
-    }
-    fp = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    hostname = newstralloc(hostname, fp);
-    s[-1] = (char)ch;
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       amfree(hostname);
-       return;
-    }
-    qdiskname = s - 1;
-    skip_quoted_string(s, ch);
-    s[-1] = '\0';
-    diskname = unquote_string(qdiskname);
-    s[-1] = (char)ch;
-
-    dp = lookup_disk(hostname, diskname);
-    if(dp == NULL) {
-       dp = add_disk(&diskq, hostname, diskname);
-    }
-
-    amfree(hostname);
-    amfree(diskname);
-    dp->todo = 1;
-}
-
-/* XXX Just a placeholder, in case we decide to do something with L_CHUNK
- * log entries.  Right now they're just the equivalent of L_SUCCESS, but only
- * for a split chunk of the overall dumpfile.
- */
-static repdata_t *
-handle_chunk(
-    logtype_t logtype)
-{
-    disk_t *dp;
-    double sec, kps, kbytes;
-    timedata_t *sp;
-    int i;
-    char *s, *fp;
-    int ch;
-    char *hostname = NULL;
-    char *diskname = NULL;
-    repdata_t *repdata;
-    int level, chunk;
-    char *datestamp;
-    char *label = NULL;
-    int fileno;
-    int totpart;
-    
-    if(curprog != P_TAPER) {
-       bogus_line(curstr);
-       return NULL;
-    }
-    
-    s = curstr;
-    ch = *s++;
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       return NULL;
-    }
-
-    if (logtype == L_PART || logtype == L_PARTPARTIAL) {
-       fp = s - 1;
-       skip_non_whitespace(s, ch);
-       s[-1] = '\0';
-       label = stralloc(fp);
-       s[-1] = (char)ch;
-    
-       skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf(s - 1, "%d", &fileno) != 1) {
-           bogus_line(s - 1);
-           amfree(label);
-           return NULL;
-       }
-       /* set tapefcount, it is increased below */
-       tapefcount = fileno - 1;
-       skip_integer(s, ch);
-       skip_whitespace(s, ch);
-       if(ch == '\0') {
-           bogus_line(s - 1);
-           amfree(label);
-           return NULL;
-       }
-       amfree(label);
-    }
-
-    fp = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    hostname = stralloc(fp);
-    s[-1] = (char)ch;
-    
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       amfree(hostname);
-       return NULL;
-    }
-    fp = s - 1;
-    skip_quoted_string(s, ch);
-    s[-1] = '\0';
-    diskname = unquote_string(fp);
-    s[-1] = (char)ch;
-    
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       amfree(hostname);
-       amfree(diskname);
-       return NULL;
-    }
-    fp = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    datestamp = stralloc(fp);
-    s[-1] = (char)ch;
-    skip_whitespace(s, ch);
-    if(ch == '\0' || sscanf(s - 1, "%d", &chunk) != 1) {
-       bogus_line(s - 1);
-       amfree(hostname);
-       amfree(diskname);
-       amfree(datestamp);
-       return NULL;
-    }
-    skip_integer(s, ch);
-
-    if (ch != '\0' && s[-1] == '/') {
-       s++; ch = s[-1];
-       if (sscanf(s - 1, "%d", &totpart) != 1) {
-           bogus_line(s - 1);
-           amfree(hostname);
-           amfree(diskname);
-           amfree(datestamp);
-           return NULL;
-       }
-       skip_integer(s, ch);
-    }
-
-    skip_whitespace(s, ch);
-    if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
-       bogus_line(s - 1);
-       amfree(hostname);
-       amfree(diskname);
-       amfree(datestamp);
-       return NULL;
-    }
-    skip_integer(s, ch);
-    
-    /*@ignore@*/
-    if(level < 0 || level > 9) {
-       amfree(hostname);
-       amfree(diskname);
-       amfree(datestamp);
-       return NULL;
-    }
-    /*@end@*/
-    skip_whitespace(s, ch);
-    if(sscanf(s - 1,"[sec %lf kb %lf kps %lf", &sec, &kbytes, &kps) != 3)  {
-       bogus_line(s - 1);
-       amfree(hostname);
-       amfree(diskname);
-       amfree(datestamp);
-       return NULL;
-    }
-    
-    
-    dp = lookup_disk(hostname, diskname);
-    if(dp == NULL) {
-       char *str = NULL;
-       
-       str = vstrallocf(_("  %s ERROR [not in disklist]"),
-                       prefix(hostname, diskname, level));
-       addline(&errsum, str);
-       amfree(str);
-       amfree(hostname);
-       amfree(diskname);
-       amfree(datestamp);
-       return NULL;
-    }
-    
-    repdata = find_repdata(dp, datestamp, level);
-    
-    sp = &(repdata->taper);
-    
-    i = level > 0;
-    
-    amfree(hostname);
-    amfree(diskname);
-    amfree(datestamp);
-    
-    if(current_tape == NULL) {
-       error("current_tape == NULL");
-    }
-    ++tapefcount;
-    if (sp->filenum == 0) {
-       sp->filenum = tapefcount;
-       sp->tapelabel = current_tape->label;
-    }
-    tapechunks[level] +=1;
-    stats[i].tapechunks +=1;
-    current_tape->taper_time += sec;
-    current_tape->coutsize += kbytes;
-    current_tape->tapechunks += 1;
-    return repdata;
-}
-
-static repdata_t *
-handle_success(
-    logtype_t  logtype)
-{
-    disk_t *dp;
-    double sec = 0.0;
-    double kps = 0.0;
-    double kbytes = 0.0;
-    double origkb = 0.0;
-    timedata_t *sp;
-    int i;
-    char *s, *fp, *qdiskname;
-    int ch;
-    char *hostname = NULL;
-    char *diskname = NULL;
-    repdata_t *repdata;
-    int level = 0;
-    int totpart = 0;
-    char *datestamp;
-
-    (void)logtype;
-
-    if(curprog != P_TAPER && curprog != P_DUMPER && curprog != P_PLANNER &&
-       curprog != P_CHUNKER) {
-       bogus_line(curstr);
-       return NULL;
-    }
-
-    s = curstr;
-    ch = *s++;
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       return NULL;
-    }
-    fp = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    hostname = stralloc(fp);
-    s[-1] = (char)ch;
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       amfree(hostname);
-       return NULL;
-    }
-    qdiskname = s - 1;
-    skip_quoted_string(s, ch);
-    s[-1] = '\0';
-    diskname = unquote_string(qdiskname);
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       amfree(hostname);
-       amfree(diskname);
-       return NULL;
-    }
-    fp = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    datestamp = stralloc(fp);
-    s[-1] = (char)ch;
-
-    //datestamp is optional
-    if(strlen(datestamp) < 6) {
-       totpart = atoi(datestamp);
-       datestamp = newstralloc(datestamp, run_datestamp);
-    }
-    else {
-       skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf(s - 1, "%d", &totpart) != 1) {
-           bogus_line(s - 1);
-           amfree(hostname);
-           amfree(diskname);
-           amfree(datestamp);
-           return NULL;
-       }
-       skip_integer(s, ch);
-    }
-
-    skip_whitespace(s, ch);
-
-    //totpart is optional
-    if (*(s-1) == '"')
-       s++;
-    if (*(s-1) == '[') {
-       level = totpart;
-       totpart = -1;
-    } else {
-       if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
-           bogus_line(s - 1);
-           amfree(hostname);
-           amfree(diskname);
-           amfree(datestamp);
-           return NULL;
-       }
-       skip_integer(s, ch);
-       skip_whitespace(s, ch);
-    }
-
-
-    if(level < 0 || level > 9) {
-       amfree(hostname);
-       amfree(diskname);
-       amfree(datestamp);
-       return NULL;
-    }
-
-                               /* Planner success messages (for skipped
-                                  dumps) do not contain statistics */
-    if(curprog != P_PLANNER) {
-       if(*(s - 1) == '"')
-           s++;
-       if((curprog != P_DUMPER)
-           || (sscanf(s - 1,"[sec %lf kb %lf kps %lf orig-kb %lf", 
-                 &sec, &kbytes, &kps, &origkb) != 4))  {
-           origkb = -1;
-           if(sscanf(s - 1,"[sec %lf kb %lf kps %lf",
-                     &sec, &kbytes, &kps) != 3) {
-               bogus_line(s - 1);
-               amfree(hostname);
-               amfree(diskname);
-               amfree(datestamp);
-               return NULL;
-           }
-       }
-       else {
-           if(!isnormal(origkb))
-               origkb = 0.1;
-       }
-       if (curprog == P_TAPER && logtype == L_PARTIAL) {
-           char *t = strchr(s-1,']');
-           if (t) {
-               char *errmsg, *u;
-               errmsg = unquote_string(t+1);
-               u = vstrallocf("  %s: partial %s: %s",
-                              prefix(hostname, diskname, level),
-                              program_str[curprog], errmsg);
-               addline(&errsum, u);
-           }
-       }
-    }
-
-
-    dp = lookup_disk(hostname, diskname);
-    if(dp == NULL) {
-       addtoX_summary(&first_failed, &last_failed, hostname, qdiskname, level,
-                      _("ERROR [not in disklist]"));
-       exit_status |= STATUS_FAILED;
-       amfree(hostname);
-       amfree(diskname);
-       amfree(datestamp);
-       return NULL;
-    }
-
-    repdata = find_repdata(dp, datestamp, level);
-
-    if(curprog == P_PLANNER) {
-       repdata->dumper.result = L_SKIPPED;
-       amfree(hostname);
-       amfree(diskname);
-       amfree(datestamp);
-       return repdata;
-    }
-
-    if(curprog == P_TAPER)
-       sp = &(repdata->taper);
-    else if(curprog == P_DUMPER)
-       sp = &(repdata->dumper);
-    else sp = &(repdata->chunker);
-
-    i = level > 0;
-
-    if (origkb < 0.0 && (curprog == P_CHUNKER || curprog == P_TAPER) &&
-       isnormal(repdata->dumper.outsize)) {
-       /* take origkb from DUMPER line */
-       origkb = repdata->dumper.outsize;
-    } else if (origkb < 0.0) {
-       /* take origkb from infofile, needed for amflush */
-       info_t inf;
-       struct tm *tm;
-       int Idatestamp;
-
-       get_info(hostname, diskname, &inf);
-        tm = localtime(&inf.inf[level].date);
-       if (tm) {
-            Idatestamp = 10000*(tm->tm_year+1900) +
-                        100*(tm->tm_mon+1) + tm->tm_mday;
-       } else {
-           Idatestamp = 19000101;
-       }
-
-       if(atoi(datestamp) == Idatestamp) {
-           /* grab original size from record */
-           origkb = (double)inf.inf[level].size;
-       }
-       else
-           origkb = 0.0;
-    }
-
-    if (curprog == P_DUMPER &&
-       (sp->result == L_FAIL || sp->result == L_PARTIAL)) {
-       addtoX_summary(&first_failed, &last_failed, hostname, qdiskname, level,
-                      _("was successfully retried"));
-    }
-
-    amfree(hostname);
-    amfree(diskname);
-    amfree(datestamp);
-
-    sp->result = L_SUCCESS;
-    sp->datestamp = repdata->datestamp;
-    sp->sec = sec;
-    sp->kps = kps;
-    sp->origsize = origkb;
-    sp->outsize = kbytes;
-
-    if(curprog == P_TAPER) {
-       if(current_tape == NULL) {
-           error(_("current_tape == NULL"));
-           /*NOTREACHED*/
-       }
-       stats[i].taper_time += sec;
-       if (sp->filenum == 0) {
-           sp->filenum = ++tapefcount;
-           sp->tapelabel = current_tape->label;
-       }
-       sp->totpart = totpart;
-       tapedisks[level] +=1;
-       stats[i].tapedisks +=1;
-       stats[i].tapesize += kbytes;
-       sp->outsize = kbytes;
-       if(!isnormal(repdata->chunker.outsize) && isnormal(repdata->dumper.outsize)) { /* dump to tape */
-           stats[i].outsize += kbytes;
-           if (abs(kbytes - origkb) >= 32) {
-               /* server compressed */
-               stats[i].corigsize += origkb;
-               stats[i].coutsize += kbytes;
-           }
-       }
-       current_tape->tapedisks += 1;
-    }
-
-    if(curprog == P_DUMPER) {
-       stats[i].dumper_time += sec;
-       if (abs(kbytes - origkb) < 32) {
-           /* not client compressed */
-           sp->origsize = kbytes;
-       }
-       else {
-           /* client compressed */
-           stats[i].corigsize += sp->origsize;
-           stats[i].coutsize += kbytes;
-       }
-       dumpdisks[level] +=1;
-       stats[i].dumpdisks +=1;
-       stats[i].origsize += sp->origsize;
-    }
-
-    if(curprog == P_CHUNKER) {
-       sp->outsize = kbytes;
-       stats[i].outsize += kbytes;
-       if (abs(kbytes - origkb) >= 32) {
-           /* server compressed */
-           stats[i].corigsize += origkb;
-           stats[i].coutsize += kbytes;
-       }
-    }
-    return repdata;
-}
-
-static void
-handle_partial(void)
-{
-    repdata_t *repdata;
-    timedata_t *sp;
-
-    repdata = handle_success(L_PARTIAL);
-    if (!repdata)
-       return;
-
-    if(curprog == P_TAPER)
-       sp = &(repdata->taper);
-    else if(curprog == P_DUMPER)
-       sp = &(repdata->dumper);
-    else sp = &(repdata->chunker);
-
-    sp->result = L_PARTIAL;
-}
-
-static void
-handle_strange(void)
-{
-    char *str = NULL;
-    char *strangestr = NULL;
-    repdata_t *repdata;
-    char *qdisk;
-
-    repdata = handle_success(L_SUCCESS);
-    if (!repdata)
-       return;
-
-    qdisk = quote_string(repdata->disk->name);
-
-    addline(&strangedet,"");
-    str = vstrallocf("/-- %s STRANGE",
-               prefix(repdata->disk->host->hostname, qdisk, repdata->level));
-    addline(&strangedet, str);
-    amfree(str);
-
-    while(contline_next()) {
-       char *s, ch;
-       get_logline(logfile);
-       s = curstr;
-       if(strncmp_const_skip(curstr, "sendbackup: warning ", s, ch) == 0) {
-           strangestr = newstralloc(strangestr, s);
-       }
-       addline(&strangedet, curstr);
-    }
-    addline(&strangedet,"\\--------");
-
-    str = vstrallocf("STRANGE %s", strangestr? strangestr : _("(see below)"));
-    addtoX_summary(&first_strange, &last_strange,
-                  repdata->disk->host->hostname, qdisk, repdata->level, str);
-    exit_status |= STATUS_STRANGE;
-    amfree(qdisk);
-    amfree(str);
-    amfree(strangestr);
-}
-
-static void
-handle_failed(void)
-{
-    disk_t *dp;
-    char *hostname;
-    char *diskname;
-    char *datestamp;
-    char *errstr;
-    int level = 0;
-    char *s, *fp, *qdiskname;
-    int ch;
-    char *str = NULL;
-    repdata_t *repdata;
-    timedata_t *sp;
-
-    hostname = NULL;
-    diskname = NULL;
-
-    s = curstr;
-    ch = *s++;
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       return;
-    }
-    hostname = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       return;
-    }
-    qdiskname = s - 1;
-    skip_quoted_string(s, ch);
-    s[-1] = '\0';
-    diskname = unquote_string(qdiskname);
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       amfree(diskname);
-       return;
-    }
-    fp = s - 1;
-    skip_non_whitespace(s, ch);
-    s[-1] = '\0';
-    datestamp = stralloc(fp);
-
-    if(strlen(datestamp) < 3) { /* there is no datestamp, it's the level */
-       level = atoi(datestamp);
-       datestamp = newstralloc(datestamp, run_datestamp);
-    }
-    else { /* read the level */
-       skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
-           bogus_line(s - 1);
-           amfree(datestamp);
-           amfree(diskname);
-           return;
-       }
-       skip_integer(s, ch);
-    }
-
-    skip_whitespace(s, ch);
-    if(ch == '\0') {
-       bogus_line(s - 1);
-       amfree(datestamp);
-       amfree(diskname);
-       return;
-    }
-    errstr = s - 1;
-    if((s = strchr(errstr, '\n')) != NULL) {
-       *s = '\0';
-    }
-
-    dp = lookup_disk(hostname, diskname);
-    amfree(diskname);
-    if(dp == NULL) {
-       addtoX_summary(&first_failed, &last_failed, hostname, qdiskname, level,
-                      _("ERROR [not in disklist]"));
-    } else {
-       repdata = find_repdata(dp, datestamp, level);
-
-       if(curprog == P_TAPER)
-           sp = &(repdata->taper);
-       else if (curprog == P_PLANNER)
-           sp = &(repdata->planner);
-       else sp = &(repdata->dumper);
-
-       if(sp->result != L_SUCCESS)
-           sp->result = L_FAIL;
-    }
-    amfree(datestamp);
-
-    if (!((curprog == P_CHUNKER &&
-          strcmp(errstr, "[dumper returned FAILED]") == 0) ||
-         (curprog == P_CHUNKER &&
-          strcmp(errstr, "[Not enough holding disk space]") == 0) ||
-         (curprog == P_CHUNKER &&
-          strcmp(errstr, "[cannot read header: got 0 bytes instead of 32768]") == 0))) {
-       str = vstrallocf(_("FAILED %s"), errstr);
-       addtoX_summary(&first_failed, &last_failed, hostname, qdiskname, level,
-                      str);
-       amfree(str);
-    }
-
-    if(curprog == P_DUMPER) {
-       addline(&errdet,"");
-       str = vstrallocf("/-- %s FAILED %s",
-                       prefix(hostname, qdiskname, level), 
-                       errstr);
-       addline(&errdet, str);
-       amfree(str);
-       while(contline_next()) {
-           get_logline(logfile);
-           addline(&errdet, curstr);
-       }
-       addline(&errdet,"\\--------");
-       exit_status |= STATUS_FAILED;
-    }
-    return;
-}
-
-
-static void
-generate_missing(void)
-{
-    disk_t *dp;
-    char *qdisk;
-
-    for(dp = diskq.head; dp != NULL; dp = dp->next) {
-       if(dp->todo && data(dp) == NULL) {
-           qdisk = quote_string(dp->name);
-           addtoX_summary(&first_failed, &last_failed, dp->host->hostname,
-                          qdisk, -987, _("RESULTS MISSING"));
-           exit_status |= STATUS_MISSING;
-           amfree(qdisk);
-       }
-    }
-}
-
-static void
-generate_bad_estimate(void)
-{
-    disk_t *dp;
-    repdata_t *repdata;
-    char s[1000];
-    double outsize;
-
-    for(dp = diskq.head; dp != NULL; dp = dp->next) {
-       if(dp->todo) {
-           for(repdata = data(dp); repdata != NULL; repdata = repdata->next) {
-               if(repdata->est_csize >= 0.1) {
-                   if(repdata->taper.result == L_SUCCESS ||
-                      repdata->taper.result == L_CHUNKSUCCESS)
-                       outsize  = repdata->taper.outsize;
-                   else if(repdata->chunker.result == L_SUCCESS ||
-                           repdata->chunker.result == L_PARTIAL ||
-                           repdata->chunker.result == L_CHUNKSUCCESS)
-                       outsize  = repdata->chunker.outsize;
-                   else if(repdata->taper.result == L_PARTIAL)
-                       outsize  = repdata->taper.outsize;
-                   else
-                       outsize  = repdata->dumper.outsize;
-
-                   if( (repdata->est_csize * 0.9 > outsize) && ( repdata->est_csize - outsize > 1.0e5 ) ) {
-                       g_snprintf(s, 1000,
-                               _("  big estimate: %s %s %d"),
-                                repdata->disk->host->hostname,
-                                repdata->disk->name,
-                                repdata->level);
-                       s[999] = '\0';
-                       addline(&notes, s);
-                       g_snprintf(s, 1000,
-                                _("                est: %.0lf%s    out %.0lf%s"),
-                                du(repdata->est_csize), displayunit,
-                                du(outsize), displayunit);
-                       s[999] = '\0';
-                       addline(&notes, s);
-                   }
-                   else if( (repdata->est_csize * 1.1 < outsize) && (outsize - repdata->est_csize > 1.0e5 ) ) {
-                       g_snprintf(s, 1000,
-                               _("  small estimate: %s %s %d"),
-                                repdata->disk->host->hostname,
-                                repdata->disk->name,
-                                repdata->level);
-                       s[999] = '\0';
-                       addline(&notes, s);
-                       g_snprintf(s, 1000,
-                                _("                  est: %.0lf%s    out %.0lf%s"),
-                                du(repdata->est_csize), displayunit,
-                                du(outsize), displayunit);
-                       s[999] = '\0';
-                       addline(&notes, s);
-                   }
-               }
-           }
-       }
-    }
-}
-
-static char *
-prefix (
-    char *     host,
-    char *     disk,
-    int                level)
-{
-    static char *str = NULL;
-
-    if (level == -987) {
-       str = newvstrallocf(str, " %s %s",
-                       host ? host : _("(host?)"),
-                       disk ? disk : _("(disk?)"));
-    } else {
-       str = newvstrallocf(str, " %s %s lev %d",
-                       host ? host : _("(host?)"),
-                       disk ? disk : _("(disk?)"),
-                       level);
-    }
-    return str;
-}
-
-
-static char *
-prefixstrange (
-    char *     host,
-    char *     disk,
-    int                level,
-    size_t     len_host,
-    size_t     len_disk)
-{
-    char *h, *d;
-    size_t l;
-    static char *str = NULL;
-
-    h=alloc(len_host+1);
-    if(host) {
-       strncpy(h, host, len_host);
-    } else {
-       strncpy(h, _("(host?)"), len_host);
-    }
-    h[len_host] = '\0';
-    for(l = strlen(h); l < len_host; l++) {
-       h[l] = ' ';
-    }
-    d=alloc(len_disk+1);
-    if(disk) {
-       strncpy(d, disk, len_disk);
-    } else {
-       strncpy(d, _("(disk?)"), len_disk);
-    }
-    d[len_disk] = '\0';
-    for(l = strlen(d); l < len_disk; l++) {
-       d[l] = ' ';
-    }
-    if (level == -987) {
-       str = newvstrallocf(str, " %s %s", h, d);
-    } else {
-       str = newvstrallocf(str, " %s %s lev %d", h, d, level);
-    }
-    amfree(h);
-    amfree(d);
-    return str;
-}
-
-
-static void
-addtoX_summary (
-    X_summary_t **first,
-    X_summary_t **last,
-    char        *host,
-    char        *disk,
-    int                  level,
-    char        *str)
-{
-    X_summary_t *X_summary;
-
-    X_summary = alloc(SIZEOF(X_summary_t));
-    X_summary->hostname = stralloc(host);
-    X_summary->diskname = stralloc(disk);
-    X_summary->level    = level;
-    X_summary->str      = stralloc(str);
-    X_summary->next = NULL;
-    if (*first == NULL) {
-       *first = X_summary;
-    }
-    else {
-        (*last)->next = X_summary;
-    }
-    *last = X_summary;
-}
-
-static void
-copy_template_file(
-    char *     lbl_templ)
-{
-  char buf[BUFSIZ];
-  int fd;
-  ssize_t numread;
-
-  lbl_templ = config_dir_relative(lbl_templ);
-  if ((fd = open(lbl_templ, 0)) < 0) {
-    curlog = L_ERROR;
-    curprog = P_REPORTER;
-    curstr = vstrallocf(_("could not open PostScript template file %s: %s"),
-                      lbl_templ, strerror(errno));
-    handle_error();
-    amfree(curstr);
-    amfree(lbl_templ);
-    afclose(postscript);
-    return;
-  }
-  while ((numread = read(fd, buf, SIZEOF(buf))) > 0) {
-    if (fwrite(buf, (size_t)numread, 1, postscript) != 1) {
-      curlog = L_ERROR;
-      curprog = P_REPORTER;
-      curstr = vstrallocf(_("error copying PostScript template file %s: %s"),
-                        lbl_templ, strerror(errno));
-      handle_error();
-      amfree(curstr);
-      amfree(lbl_templ);
-      afclose(postscript);
-      return;
-    }
-  }
-  if (numread < 0) {
-    curlog = L_ERROR;
-    curprog = P_REPORTER;
-    curstr = vstrallocf(_("error reading PostScript template file %s: %s"),
-                      lbl_templ, strerror(errno));
-    handle_error();
-    amfree(curstr);
-    amfree(lbl_templ);
-    afclose(postscript);
-    return;
-  }
-  close(fd);
-  amfree(lbl_templ);
-}
-
-static repdata_t *
-find_repdata(
-    /*@keep@*/ disk_t *dp,
-               char *  datestamp,
-               int     level)
-{
-    repdata_t *repdata, *prev;
-
-    if(!datestamp)
-       datestamp = run_datestamp;
-    prev = NULL;
-    for(repdata = data(dp); repdata != NULL && (repdata->level != level || strcmp(repdata->datestamp,datestamp)!=0); repdata = repdata->next) {
-       prev = repdata;
-    }
-    if(!repdata) {
-       repdata = (repdata_t *)alloc(SIZEOF(repdata_t));
-       memset(repdata, '\0', SIZEOF(repdata_t));
-       repdata->disk = dp;
-       repdata->datestamp = stralloc(datestamp ? datestamp : "");
-       repdata->level = level;
-       repdata->dumper.result = L_BOGUS;
-       repdata->taper.result = L_BOGUS;
-       repdata->next = NULL;
-       if(prev)
-           prev->next = repdata;
-       else
-           dp->up = (void *)repdata;
-    }
-    return repdata;
-}
-
-
-static void
-do_postscript_output(void)
-{
-    tapetype_t *tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
-    disk_t *dp;
-    repdata_t *repdata;
-    double outsize, origsize;
-    off_t tapesize;
-    off_t marksize;
-
-    if (!tp)
-       return;
-
-    tapesize = tapetype_get_length(tp);
-    marksize = tapetype_get_filemark(tp);
-
-    for(current_tape = stats_by_tape; current_tape != NULL;
-           current_tape = current_tape->next) {
-
-       if (current_tape->label == NULL) {
-           break;
-       }
-
-       copy_template_file(tapetype_get_lbl_templ(tp));
-
-       if (postscript == NULL)
-           return;
-
-       /* generate a few elements */
-       g_fprintf(postscript,"(%s) DrawDate\n\n",
-                   nicedate(run_datestamp ? run_datestamp : "0"));
-       g_fprintf(postscript,_("(Amanda Version %s) DrawVers\n"),version());
-       g_fprintf(postscript,"(%s) DrawTitle\n", current_tape->label);
-
-       /* Stats */
-       g_fprintf(postscript, "(Total Size:        %6.1lf MB) DrawStat\n",
-             mb(current_tape->coutsize));
-       g_fprintf(postscript, _("(Tape Used (%%)       "));
-       divzero(postscript, pct(current_tape->coutsize + 
-                               marksize * (current_tape->tapedisks + current_tape->tapechunks)),
-                               (double)tapesize);
-       g_fprintf(postscript," %%) DrawStat\n");
-       g_fprintf(postscript, _("(Compression Ratio:  "));
-       divzero(postscript, pct(current_tape->coutsize),current_tape->corigsize);
-       g_fprintf(postscript," %%) DrawStat\n");
-       g_fprintf(postscript,_("(Filesystems Taped: %4d) DrawStat\n"),
-                 current_tape->tapedisks);
-
-       /* Summary */
-
-       g_fprintf(postscript,
-             "(-) (%s) (-) (  0) (      32) (      32) DrawHost\n",
-             current_tape->label);
-
-       for(dp = sortq.head; dp != NULL; dp = dp->next) {
-           if (dp->todo == 0) {
-                continue;
-           }
-           for(repdata = data(dp); repdata != NULL; repdata = repdata->next) {
-
-               if(repdata->taper.tapelabel != current_tape->label) {
-                   continue;
-               }
-
-               if(repdata->dumper.result == L_SUCCESS ||
-                  repdata->dumper.result == L_PARTIAL)
-                   origsize = repdata->dumper.origsize;
-               else
-                   origsize = repdata->taper.origsize;
-
-               if(repdata->taper.result == L_SUCCESS ||
-                  repdata->taper.result == L_PARTIAL)
-                   outsize  = repdata->taper.outsize;
-               else
-                   outsize  = repdata->dumper.outsize;
-
-               if (repdata->taper.result == L_SUCCESS ||
-                   repdata->taper.result == L_PARTIAL) {
-                   if(isnormal(origsize)) {
-                       g_fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8.0lf) (%8.0lf) DrawHost\n",
-                           dp->host->hostname, dp->name, repdata->level,
-                           repdata->taper.filenum, origsize, 
-                           outsize);
-                   }
-                   else {
-                       g_fprintf(postscript,"(%s) (%s) (%d) (%3.0d) (%8s) (%8.0lf) DrawHost\n",
-                           dp->host->hostname, dp->name, repdata->level,
-                           repdata->taper.filenum, "", 
-                           outsize);
-                   }
-               }
-           }
-       }
-       
-       g_fprintf(postscript,"\nshowpage\n");
-    }
-}