lintian doesn't like orphan packages with uploaders...
[debian/amanda] / server-src / amadmin.c
index b7069b4c9b2cfacdc6988e606da832d0a8baac68..f51b17e7f8cc5b9eb88559e641c542039c2d6a96 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
  * Copyright (c) 1991-1998 University of Maryland at College Park
+ * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
 #include "find.h"
 #include "util.h"
 #include "timestamp.h"
+#include "server_util.h"
+#include <getopt.h>
 
 disklist_t diskq;
 
 int main(int argc, char **argv);
 void usage(void);
+static void estimate(int argc, char **argv);
+static void estimate_one(disk_t *dp);
 void force(int argc, char **argv);
 void force_one(disk_t *dp);
 void unforce(int argc, char **argv);
@@ -75,6 +80,8 @@ static int next_level0(disk_t *dp, info_t *info);
 int bump_thresh(int level);
 void export_db(int argc, char **argv);
 void import_db(int argc, char **argv);
+void hosts(int argc, char **argv);
+void dles(int argc, char **argv);
 void disklist(int argc, char **argv);
 void disklist_one(disk_t *dp);
 void show_version(int argc, char **argv);
@@ -83,6 +90,13 @@ static void show_config(int argc, char **argv);
 static char *conf_tapelist = NULL;
 static char *displayunit;
 static long int unitdivisor;
+static gboolean print_default = 1;
+static gboolean print_source = 0;
+static int opt_days = -1;
+static char *opt_sort = NULL;
+static gboolean exact_match = FALSE;
+static gboolean opt_long = 0;
+static gboolean opt_outdated = 0;
 
 static const struct {
     const char *name;
@@ -93,6 +107,8 @@ static const struct {
        T_("\t\t\t\t\t# Show version info.") },
     { "config", show_config,
        T_("\t\t\t\t\t# Show configuration.") },
+    { "estimate", estimate,
+       T_(" [<hostname> [<disks>]* ]*\t# Print server estimate.") },
     { "force", force,
        T_(" [<hostname> [<disks>]* ]+\t\t# Force level 0 at next run.") },
     { "unforce", unforce,
@@ -105,6 +121,10 @@ static const struct {
        T_(" [<hostname> [<disks>]* ]+\t# Clear bump command.") },
     { "disklist", disklist,
        T_(" [<hostname> [<disks>]* ]*\t# Debug disklist entries.") },
+    { "hosts", hosts,
+       T_("\t\t\t\t\t# Show all distinct hosts in disklist.") },
+    { "dles", dles,
+       T_("\t\t\t\t\t# Show all dles in disklist, one per line.") },
     { "reuse", reuse,
        T_(" <tapelabel> ...\t\t # re-use this tape.") },
     { "no-reuse", noreuse,
@@ -132,6 +152,16 @@ static const struct {
 };
 #define        NCMDS   (int)(sizeof(cmdtab) / sizeof(cmdtab[0]))
 
+static struct option long_options[] = {
+    {"version"       , 0, NULL,  1},
+    {"no-default"    , 0, NULL,  2},
+    {"print-source"  , 0, NULL,  3},
+    {"days"          , 1, NULL,  4},
+    {"sort"          , 1, NULL,  5},
+    {"exact-match"   , 0, NULL,  6},
+    {NULL, 0, NULL, 0}
+};
+
 int
 main(
     int                argc,
@@ -140,7 +170,7 @@ main(
     int i;
     char *conf_diskfile;
     char *conf_infofile;
-    config_overwrites_t *cfg_ovr = NULL;
+    config_overrides_t *cfg_ovr = NULL;
 
     /*
      * Configure program for internationalization:
@@ -161,20 +191,51 @@ main(
 
     dbopen(DBG_SUBDIR_SERVER);
 
-    erroutput_type = ERR_INTERACTIVE;
+    add_amanda_log_handler(amanda_log_stderr);
+
+    cfg_ovr = extract_commandline_config_overrides(&argc, &argv);
+
+    while (1) {
+       int option_index = 0;
+        int c;
+        c = getopt_long(argc, argv, "ld", long_options, &option_index);
+
+       if (c == -1) {
+           break;
+       }
 
-    cfg_ovr = extract_commandline_config_overwrites(&argc, &argv);
+       switch(c) {
+       case 1: printf("amadmin-%s\n", VERSION);
+               return 0;
+       case 2: print_default = 0;
+               break;
+       case 3: print_source = 1;
+               break;
+       case 4: opt_days = atoi(optarg);
+               break;
+       case 5: opt_sort = g_strdup(optarg);
+               break;
+       case 6: exact_match = TRUE;
+               break;
+       case 'l': opt_long = TRUE;
+               break;
+       case 'd': opt_outdated = TRUE;
+               break;
+       default: usage();
+       }
+    }
+    argc -= optind-1, argv += optind-1;
 
     if(argc < 3) usage();
 
+    set_config_overrides(cfg_ovr);
+    config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]);
+
     if(strcmp(argv[2],"version") == 0) {
        show_version(argc, argv);
        goto done;
     }
 
-    config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]);
-    apply_config_overwrites(cfg_ovr);
-
     conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
     read_diskfile(conf_diskfile, &diskq);
     amfree(conf_diskfile);
@@ -235,8 +296,8 @@ usage(void)
 {
     int i;
 
-    g_fprintf(stderr, _("\nUsage: %s%s <conf> <command> {<args>} [-o configoption]* ...\n"),
-           get_pname(), versionsuffix());
+    g_fprintf(stderr, _("\nUsage: %s [--version] [--exact-match] [--no-default] [--print-source] [-o configoption]*\n               <conf> <command> {<args>} ...\n"),
+           get_pname());
     g_fprintf(stderr, _("    Valid <command>s are:\n"));
     for (i = 0; i < NCMDS; i++)
        g_fprintf(stderr, "\t%s%s\n", cmdtab[i].name, _(cmdtab[i].usage));
@@ -313,7 +374,7 @@ diskloop(
        usage();
     }
 
-    errstr = match_disklist(&diskq, argc-3, argv+3);
+    errstr = match_disklist(&diskq, exact_match, argc-3, argv+3);
     if (errstr) {
        g_printf("%s", errstr);
        amfree(errstr);
@@ -333,6 +394,64 @@ diskloop(
 /* ----------------------------------------------- */
 
 
+static void
+estimate_one(
+    disk_t *   dp)
+{
+    char   *hostname = dp->host->hostname;
+    char   *diskname = dp->name;
+    char   *qhost = quote_string(hostname);
+    char   *qdisk = quote_string(diskname);
+    info_t  info;
+    int     stats;
+    gint64  size;
+
+    get_info(hostname, diskname, &info);
+
+    size = internal_server_estimate(dp, &info, 0, &stats);
+    if (stats) {
+       printf("%s %s %d %jd\n", qhost, qdisk, 0, (intmax_t)size);
+    }
+
+    if (info.last_level > 0) {
+       size = internal_server_estimate(dp, &info, info.last_level, &stats);
+       if (stats) {
+           printf("%s %s %d %jd\n", qhost, qdisk, info.last_level,
+                  (intmax_t)size);
+       }
+    }
+
+    if (info.last_level > -1) {
+       size = internal_server_estimate(dp, &info, info.last_level+1, &stats);
+       if (stats) {
+           printf("%s %s %d %jd\n", qhost, qdisk, info.last_level+1,
+                  (intmax_t)size);
+       }
+    }
+
+    amfree(qhost);
+    amfree(qdisk);
+}
+
+
+static void
+estimate(
+    int                argc,
+    char **    argv)
+{
+    disk_t *dp;
+
+    if(argc >= 4)
+       diskloop(argc, argv, "estimate", estimate_one);
+    else
+       for(dp = diskq.head; dp != NULL; dp = dp->next)
+           estimate_one(dp);
+}
+
+
+/* ----------------------------------------------- */
+
+
 void
 force_one(
     disk_t *   dp)
@@ -829,8 +948,8 @@ tape(
 
 void
 balance(
-    int                argc,
-    char **    argv)
+    int                argc G_GNUC_UNUSED,
+    char **    argv G_GNUC_UNUSED)
 {
     disk_t *dp;
     struct balance_stats {
@@ -852,9 +971,10 @@ balance(
     overdue = 0;
     max_overdue = 0;
 
-    if(argc > 4 && strcmp(argv[3],"--days") == 0) {
-       later = atoi(argv[4]);
-       if(later < 0) later = conf_dumpcycle;
+    if (opt_days > 0) {
+       later = opt_days;
+    } else if (opt_days == 0) {
+       later = conf_dumpcycle;
     }
     if(later > 10000) later = 10000;
 
@@ -1037,6 +1157,8 @@ find(
     char *sort_order = NULL;
     find_result_t *output_find;
     char *errstr;
+    char **output_find_log;
+    char **name;
 
     if(argc < 3) {
        g_fprintf(stderr,
@@ -1047,11 +1169,11 @@ find(
 
 
     sort_order = newstralloc(sort_order, DEFAULT_SORT_ORDER);
-    if(argc > 4 && strcmp(argv[3],"--sort") == 0) {
+    if (opt_sort) {
        size_t i, valid_sort=1;
 
-       for(i = strlen(argv[4]); i > 0; i--) {
-           switch (argv[4][i - 1]) {
+       for(i = strlen(opt_sort); i > 0; i--) {
+           switch (opt_sort[i - 1]) {
            case 'h':
            case 'H':
            case 'k':
@@ -1073,31 +1195,51 @@ find(
            }
        }
        if(valid_sort) {
-           sort_order = newstralloc(sort_order, argv[4]);
+           sort_order = newstralloc(sort_order, opt_sort);
        } else {
-           g_printf(_("Invalid sort order: %s\n"), argv[4]);
+           g_printf(_("Invalid sort order: %s\n"), opt_sort);
            g_printf(_("Use default sort order: %s\n"), sort_order);
        }
-       start_argc=6;
-    } else {
-       start_argc=4;
     }
-    errstr = match_disklist(&diskq, argc-(start_argc-1), argv+(start_argc-1));
-    if (errstr) {
-       g_printf("%s", errstr);
-       amfree(errstr);
+    start_argc=4;
+    errstr = match_disklist(&diskq, exact_match, argc-(start_argc-1),
+                                                argv+(start_argc-1));
+
+    /* check all log file exists */
+    output_find_log = find_log();
+    for (name = output_find_log; *name != NULL; name++) {
+        amfree(*name);
     }
+    amfree(output_find_log);
 
-    output_find = find_dump(&diskq);
+    output_find = find_dump(&diskq); /* Add deleted dump to diskq */
     if(argc-(start_argc-1) > 0) {
-       free_find_result(&output_find);
-       errstr = match_disklist(&diskq, argc-(start_argc-1),
-                                       argv+(start_argc-1));
+       find_result_t *afind = NULL;
+       find_result_t *afind_next = NULL;
+       find_result_t *new_output_find = NULL;
+       disk_t *dp;
+
+       amfree(errstr);
+       errstr = match_disklist(&diskq, exact_match, argc-(start_argc-1),
+                                                    argv+(start_argc-1));
        if (errstr) {
            g_printf("%s", errstr);
            amfree(errstr);
        }
-       output_find = find_dump(NULL);
+       for (afind = output_find; afind; afind = afind_next) {
+           afind_next = afind->next;
+           dp = lookup_disk(afind->hostname, afind->diskname);
+           if (dp->todo) {
+               afind->next = new_output_find;
+               new_output_find = afind;
+           } else {
+               amfree(afind);
+           }
+       }
+       output_find = new_output_find;
+    } else if (errstr) {
+       g_printf("%s", errstr);
+       amfree(errstr);
     }
 
     sort_find_result(sort_order, &output_find);
@@ -1114,7 +1256,8 @@ static GSList *
 get_file_list(
     int argc,
     char **argv,
-    int allow_empty)
+    int allow_empty,
+    gboolean exact_match)
 {
     GSList * file_list = NULL;
     GSList * dumplist;
@@ -1122,6 +1265,7 @@ get_file_list(
 
     flags = CMDLINE_PARSE_DATESTAMP;
     if (allow_empty) flags |= CMDLINE_EMPTY_TO_WILDCARD;
+    if (exact_match) flags |= CMDLINE_EXACT_MATCH;
     dumplist = cmdline_parse_dumpspecs(argc, argv, flags);
 
     file_list = cmdline_match_holding(dumplist);
@@ -1362,22 +1506,9 @@ holding(
             return;
 
         case HOLDING_LIST:
+           long_list = opt_long;
+           outdated_list = opt_outdated;
             argc -= 4; argv += 4;
-           while (argc && argv[0][0] == '-') {
-               switch (argv[0][1]) {
-                   case 'l': 
-                       long_list = 1; 
-                       break;
-                   case 'd': /* have to use '-d', and not '-o', because of parse_config */
-                       outdated_list = 1;
-                       break;
-                   default:
-                       g_fprintf(stderr, _("Unknown option -%c\n"), argv[0][1]);
-                       usage();
-                       return;
-               }
-               argc--; argv++;
-           }
 
            /* header */
             if (long_list) {
@@ -1385,7 +1516,7 @@ holding(
                    _("size (kB)"), _("lv"), _("outd"), _("dump specification"));
             }
 
-            file_list = get_file_list(argc, argv, 1);
+            file_list = get_file_list(argc, argv, 1, exact_match);
             for (li = file_list; li != NULL; li = li->next) {
                 char *dumpstr;
                int is_outdated;
@@ -1414,13 +1545,13 @@ holding(
                 amfree(dumpstr);
                dumpfile_free_data(&file);
             }
-            g_slist_free_full(file_list);
+            slist_free_full(file_list, g_free);
             break;
 
         case HOLDING_DELETE:
             argc -= 4; argv += 4;
 
-            file_list = get_file_list(argc, argv, 0);
+            file_list = get_file_list(argc, argv, 0, exact_match);
             for (li = file_list; li != NULL; li = li->next) {
                 g_fprintf(stderr, _("Deleting '%s'\n"), (char *)li->data);
                 /* remove it from the catalog */
@@ -1432,7 +1563,7 @@ holding(
                     error(_("Could not delete '%s'"), (char *)li->data);
                 }
             }
-            g_slist_free_full(file_list);
+            slist_free_full(file_list, g_free);
             break;
     }
 }
@@ -1447,7 +1578,7 @@ int
 bump_thresh(
     int                level)
 {
-    int bump = getconf_int(CNF_BUMPSIZE);
+    gint64 bump = getconf_int64(CNF_BUMPSIZE);
     double mult = getconf_real(CNF_BUMPMULT);
 
     while(--level)
@@ -1469,8 +1600,8 @@ bumpsize(
 
     g_printf(_("Current bump parameters:\n"));
     if(conf_bumppercent == 0) {
-       g_printf(_("  bumpsize %5d KB\t- minimum savings (threshold) to bump level 1 -> 2\n"),
-              getconf_int(CNF_BUMPSIZE));
+       g_printf(_("  bumpsize %5jd KB\t- minimum savings (threshold) to bump level 1 -> 2\n"),
+              (intmax_t)getconf_int64(CNF_BUMPSIZE));
        g_printf(_("  bumpdays %5d\t- minimum days at each level\n"),
               getconf_int(CNF_BUMPDAYS));
        g_printf(_("  bumpmult %5.5lg\t- threshold = bumpsize * bumpmult**(level-1)\n\n"),
@@ -1514,7 +1645,7 @@ export_db(
     char hostname[MAX_HOSTNAME_LENGTH+1];
     int i;
 
-    g_printf(_("CURINFO Version %s CONF %s\n"), version(), getconf_str(CNF_ORG));
+    g_printf(_("CURINFO Version %s CONF %s\n"), VERSION, getconf_str(CNF_ORG));
 
     curtime = time(0);
     if(gethostname(hostname, SIZEOF(hostname)-1) == -1) {
@@ -1544,13 +1675,16 @@ export_one(
 {
     info_t info;
     int i,l;
+    char *qhost, *qdisk;
 
     if(get_info(dp->host->hostname, dp->name, &info)) {
        g_fprintf(stderr, _("Warning: no curinfo record for %s:%s\n"),
                dp->host->hostname, dp->name);
        return;
     }
-    g_printf(_("host: %s\ndisk: %s\n"), dp->host->hostname, dp->name);
+    qhost = quote_string(dp->host->hostname);
+    qdisk = quote_string(dp->name);
+    g_printf(_("host: %s\ndisk: %s\n"), qhost, qdisk);
     g_printf(_("command: %u\n"), info.command);
     g_printf(_("last_level: %d\n"),info.last_level);
     g_printf(_("consecutive_runs: %d\n"),info.consecutive_runs);
@@ -1582,6 +1716,8 @@ export_one(
               (intmax_t)info.history[l].date);
     }
     g_printf("//\n");
+    amfree(qhost);
+    amfree(qdisk);
 }
 
 /* ----------------------------------------------- */
@@ -1626,7 +1762,10 @@ import_db(
     skip_whitespace(s, ch);
     if(ch == '\0'
        || sscanf(s - 1, "%d.%d.%d", &vers_maj, &vers_min, &vers_patch) != 3) {
-       goto bad_header;
+       vers_patch = -1;
+       if (sscanf(s - 1, "%d.%d", &vers_maj, &vers_min) != 2) {
+           goto bad_header;
+       }
     }
 
     skip_integer(s, ch);                       /* skip over major */
@@ -1635,11 +1774,15 @@ import_db(
     }
     ch = *s++;
     skip_integer(s, ch);                       /* skip over minor */
-    if(ch != '.') {
-       goto bad_header;
+    if (vers_patch != -1) {
+       if (ch != '.') {
+           goto bad_header;
+       }
+       ch = *s++;
+       skip_integer(s, ch);                    /* skip over patch */
+    } else {
+       vers_patch = 0;
     }
-    ch = *s++;
-    skip_integer(s, ch);                       /* skip over patch */
 
     hdr = "comment";
     if(ch == '\0') {
@@ -1728,9 +1871,9 @@ import_one(void)
     skip_whitespace(s, ch);
     if(ch == '\0') goto parse_err;
     fp = s-1;
-    skip_non_whitespace(s, ch);
+    skip_quoted_string(s, ch);
     s[-1] = '\0';
-    hostname = stralloc(fp);
+    hostname = unquote_string(fp);
     s[-1] = (char)ch;
 
     skip_whitespace(s, ch);
@@ -1745,9 +1888,9 @@ import_one(void)
     skip_whitespace(s, ch);
     if(ch == '\0') goto parse_err;
     fp = s-1;
-    skip_non_whitespace(s, ch);
+    skip_quoted_string(s, ch);
     s[-1] = '\0';
-    diskname = stralloc(fp);
+    diskname = unquote_string(fp);
     s[-1] = (char)ch;
 
     amfree(line);
@@ -1988,13 +2131,12 @@ disklist_one(
 {
     am_host_t *hp;
     netif_t *ip;
-    sle_t *excl;
-    pp_scriptlist_t pp_scriptlist;
+    dumptype_t *dtype = lookup_dumptype(dp->dtype_name);
 
     hp = dp->host;
     ip = hp->netif;
 
-    g_printf("line %d:\n", dp->line);
+    g_printf("line %d (%s):\n", dp->line, dp->filename);
 
     g_printf("    host %s:\n", hp->hostname);
     g_printf("        interface %s\n",
@@ -2004,177 +2146,11 @@ disklist_one(
 
     g_printf("        program \"%s\"\n", dp->program);
     if (dp->application)
-       g_printf("        application \"%s\"\n", application_name(dp->application));
-    if (dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
-       g_printf("        exclude file");
-       for(excl = dp->exclude_file->first; excl != NULL; excl = excl->next) {
-           g_printf(" \"%s\"", excl->name);
-       }
-       g_printf("\n");
-    }
-    if (dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) {
-       g_printf("        exclude list");
-       if(dp->exclude_optional) g_printf(" optional");
-       for(excl = dp->exclude_list->first; excl != NULL; excl = excl->next) {
-           g_printf(" \"%s\"", excl->name);
-       }
-       g_printf("\n");
-    }
-    if (dp->include_file != NULL && dp->include_file->nb_element > 0) {
-       g_printf("        include file");
-       for(excl = dp->include_file->first; excl != NULL; excl = excl->next) {
-           g_printf(" \"%s\"", excl->name);
-       }
-       g_printf("\n");
-    }
-    if (dp->include_list != NULL && dp->include_list->nb_element > 0) {
-       g_printf("        include list");
-       if (dp->include_optional) g_printf(" optional");
-       for(excl = dp->include_list->first; excl != NULL; excl = excl->next) {
-           g_printf(" \"%s\"", excl->name);
-       }
-       g_printf("\n");
-    }
-    g_printf("        priority %d\n", dp->priority);
-    g_printf("        dumpcycle %d\n", dp->dumpcycle);
-    g_printf("        maxdumps %d\n", dp->maxdumps);
-    g_printf("        maxpromoteday %d\n", dp->maxpromoteday);
-    if (dp->bumppercent > 0) {
-       g_printf("        bumppercent %d\n", dp->bumppercent);
-    }
-    else {
-       g_printf("        bumpsize %lld\n",
-               (long long)dp->bumpsize);
-    }
-    g_printf("        bumpdays %d\n", dp->bumpdays);
-    g_printf("        bumpmult %lf\n", dp->bumpmult);
-
-    g_printf("        strategy ");
-    switch(dp->strategy) {
-    case DS_SKIP:
-       g_printf("SKIP\n");
-       break;
-    case DS_STANDARD:
-       g_printf("STANDARD\n");
-       break;
-    case DS_NOFULL:
-       g_printf("NOFULL\n");
-       break;
-    case DS_NOINC:
-       g_printf("NOINC\n");
-       break;
-    case DS_HANOI:
-       g_printf("HANOI\n");
-       break;
-    case DS_INCRONLY:
-       g_printf("INCRONLY\n");
-       break;
-    }
-    g_printf("        ignore %s\n", (dp->ignore? "YES" : "NO"));
-    g_printf("        estimate ");
-    switch(dp->estimate) {
-    case ES_CLIENT:
-       g_printf("CLIENT\n");
-       break;
-    case ES_SERVER:
-       g_printf("SERVER\n");
-       break;
-    case ES_CALCSIZE:
-       g_printf("CALCSIZE\n");
-       break;
-    }
-
-    g_printf("        compress ");
-    switch(dp->compress) {
-    case COMP_NONE:
-       g_printf("NONE\n");
-       break;
-    case COMP_FAST:
-       g_printf("CLIENT FAST\n");
-       break;
-    case COMP_BEST:
-       g_printf("CLIENT BEST\n");
-       break;
-    case COMP_SERVER_FAST:
-       g_printf("SERVER FAST\n");
-       break;
-    case COMP_SERVER_BEST:
-       g_printf("SERVER BEST\n");
-       break;
-    }
-    if(dp->compress != COMP_NONE) {
-       g_printf("        comprate %.2lf %.2lf\n",
-              dp->comprate[0], dp->comprate[1]);
-    }
-
-    g_printf("        encrypt ");
-    switch(dp->encrypt) {
-    case ENCRYPT_NONE:
-       g_printf("NONE\n");
-       break;
-    case ENCRYPT_CUST:
-       g_printf("CLIENT\n");
-       break;
-    case ENCRYPT_SERV_CUST:
-       g_printf("SERVER\n");
-       break;
-    }
-
-    g_printf("        auth %s\n", dp->security_driver);
-    g_printf("        kencrypt %s\n", (dp->kencrypt? "YES" : "NO"));
-    g_printf("        amandad_path %s\n", dp->amandad_path);
-    g_printf("        client_username %s\n", dp->client_username);
-    g_printf("        ssh_keys %s\n", dp->ssh_keys);
-
-    g_printf("        holdingdisk ");
-    switch(dp->to_holdingdisk) {
-    case HOLD_NEVER:
-       g_printf("NEVER\n");
-       break;
-    case HOLD_AUTO:
-       g_printf("AUTO\n");
-       break;
-    case HOLD_REQUIRED:
-       g_printf("REQUIRED\n");
-       break;
-    }
-
-    g_printf("        record %s\n", (dp->record? "YES" : "NO"));
-    g_printf("        index %s\n", (dp->index? "YES" : "NO"));
-    g_printf("        starttime %04d\n", (int)dp->starttime);
-    if(dp->tape_splitsize > (off_t)0) {
-       g_printf("        tape_splitsize %lld\n",
-              (long long)dp->tape_splitsize);
-    }
-    if(dp->split_diskbuffer) {
-       g_printf("        split_diskbuffer %s\n", dp->split_diskbuffer);
-    }
-    if(dp->fallback_splitsize > (off_t)0) {
-       g_printf("        fallback_splitsize %lldMb\n",
-              (long long)(dp->fallback_splitsize / (off_t)1024));
-    }
-    g_printf("        skip-incr %s\n", (dp->skip_incr? "YES" : "NO"));
-    g_printf("        skip-full %s\n", (dp->skip_full? "YES" : "NO"));
+       g_printf("        application \"%s\"\n", dp->application);
+
+    dump_dumptype(dtype, "  ", print_default, print_source);
+
     g_printf("        spindle %d\n", dp->spindle);
-    pp_scriptlist = dp->pp_scriptlist;
-    while (pp_scriptlist != NULL) {
-       g_printf("        script \"%s\"\n", (pp_script_name(pp_scriptlist->data)));
-       pp_scriptlist = pp_scriptlist->next;
-    }
-
-    {
-       dumptype_t *dtype;
-       char **prop, **p1;;
-
-       dtype = lookup_dumptype(dp->dtype_name);
-       prop = val_t_display_strs(dumptype_getconf((dtype), DUMPTYPE_PROPERTY),
-                                 0);
-       for(p1 = prop; *p1 != NULL; p1++) {
-           g_printf("        property %s\n", *p1);
-           free(*p1);
-       }
-       amfree(prop);
-    }
 
     g_printf("\n");
 }
@@ -2193,6 +2169,44 @@ disklist(
            disklist_one(dp);
 }
 
+/* ----------------------------------------------- */
+
+void
+hosts(
+    int                argc G_GNUC_UNUSED,
+    char **    argv G_GNUC_UNUSED)
+{
+    disk_t *dp;
+    gint sentinel = 1;
+    GHashTable *seen = g_hash_table_new(g_str_hash, g_str_equal);
+
+    /* enumerate all hosts, skipping those that have been seen (since
+     * there may be more than one DLE on a host */
+    for(dp = diskq.head; dp != NULL; dp = dp->next) {
+       char *hostname = dp->host->hostname;
+       if (g_hash_table_lookup(seen, hostname))
+           continue;
+       g_printf("%s\n", hostname);
+       g_hash_table_insert(seen, hostname, &sentinel);
+    }
+    g_hash_table_destroy(seen);
+}
+
+/* ----------------------------------------------- */
+
+void
+dles(
+    int                argc G_GNUC_UNUSED,
+    char **    argv G_GNUC_UNUSED)
+{
+    disk_t *dp;
+
+    for(dp = diskq.head; dp != NULL; dp = dp->next)
+       g_printf("%s %s\n", dp->host->hostname, dp->name);
+}
+
+/* ----------------------------------------------- */
+
 void
 show_version(
     int                argc,
@@ -2212,6 +2226,6 @@ void show_config(
     int argc G_GNUC_UNUSED,
     char **argv G_GNUC_UNUSED)
 {
-    dump_configuration();
+    dump_configuration(print_default, print_source);
 }