Imported Upstream version 2.6.0p2
[debian/amanda] / server-src / amadmin.c
index d1ea05784dbeba3b5bc7c60fdece7c29b4624642..9acacbc87238be1ea4347959a36025cb4b687be4 100644 (file)
  *                        University of Maryland at College Park
  */
 /*
- * $Id: amadmin.c,v 1.124.2.1 2006/11/01 14:45:39 martinea Exp $
+ * $Id: amadmin.c,v 1.124 2006/07/26 15:17:37 martinea Exp $
  *
  * controlling process for the Amanda backup system
  */
 #include "amanda.h"
+#include "cmdline.h"
 #include "conffile.h"
 #include "diskfile.h"
 #include "tapefile.h"
@@ -38,6 +39,8 @@
 #include "version.h"
 #include "holding.h"
 #include "find.h"
+#include "util.h"
+#include "timestamp.h"
 
 disklist_t diskq;
 
@@ -60,6 +63,7 @@ void info_one(disk_t *dp);
 void due(int argc, char **argv);
 void due_one(disk_t *dp);
 void find(int argc, char **argv);
+void holding(int argc, char **argv);
 void delete(int argc, char **argv);
 void delete_one(disk_t *dp);
 void balance(int argc, char **argv);
@@ -75,7 +79,6 @@ void disklist(int argc, char **argv);
 void disklist_one(disk_t *dp);
 void show_version(int argc, char **argv);
 static void show_config(int argc, char **argv);
-static void check_dumpuser(void);
 
 static char *conf_tapelist = NULL;
 static char *displayunit;
@@ -87,48 +90,48 @@ static const struct {
     const char *usage;
 } cmdtab[] = {
     { "version", show_version,
-       "\t\t\t\t\t# Show version info." },
+       T_("\t\t\t\t\t# Show version info.") },
     { "config", show_config,
-       "\t\t\t\t\t# Show configuration." },
+       T_("\t\t\t\t\t# Show configuration.") },
     { "force", force,
-       " [<hostname> [<disks>]* ]+\t\t# Force level 0 at next run." },
+       T_(" [<hostname> [<disks>]* ]+\t\t# Force level 0 at next run.") },
     { "unforce", unforce,
-       " [<hostname> [<disks>]* ]+\t# Clear force command." },
+       T_(" [<hostname> [<disks>]* ]+\t# Clear force command.") },
     { "force-bump", force_bump,
-       " [<hostname> [<disks>]* ]+\t# Force bump at next run." },
+       T_(" [<hostname> [<disks>]* ]+\t# Force bump at next run.") },
     { "force-no-bump", force_no_bump,
-       " [<hostname> [<disks>]* ]+\t# Force no-bump at next run." },
+       T_(" [<hostname> [<disks>]* ]+\t# Force no-bump at next run.") },
     { "unforce-bump", unforce_bump,
-       " [<hostname> [<disks>]* ]+\t# Clear bump command." },
+       T_(" [<hostname> [<disks>]* ]+\t# Clear bump command.") },
     { "disklist", disklist,
-       " [<hostname> [<disks>]* ]*\t# Debug disklist entries." },
+       T_(" [<hostname> [<disks>]* ]*\t# Debug disklist entries.") },
     { "reuse", reuse,
-       " <tapelabel> ...\t\t # re-use this tape." },
+       T_(" <tapelabel> ...\t\t # re-use this tape.") },
     { "no-reuse", noreuse,
-       " <tapelabel> ...\t # never re-use this tape." },
+       T_(" <tapelabel> ...\t # never re-use this tape.") },
     { "find", find,
-       " [<hostname> [<disks>]* ]*\t # Show which tapes these dumps are on." },
+       T_(" [<hostname> [<disks>]* ]*\t # Show which tapes these dumps are on.") },
+    { "holding", holding,
+       T_(" {list [ -l ] |delete} [ <hostname> [ <disk> [ <datestamp> [ .. ] ] ] ]+\t # Show or delete holding disk contents.") },
     { "delete", delete,
-       " [<hostname> [<disks>]* ]+ # Delete from database." },
+       T_(" [<hostname> [<disks>]* ]+ # Delete from database.") },
     { "info", info,
-       " [<hostname> [<disks>]* ]*\t # Show current info records." },
+       T_(" [<hostname> [<disks>]* ]*\t # Show current info records.") },
     { "due", due,
-       " [<hostname> [<disks>]* ]*\t # Show due date." },
+       T_(" [<hostname> [<disks>]* ]*\t # Show due date.") },
     { "balance", balance,
-       " [-days <num>]\t\t # Show nightly dump size balance." },
+       T_(" [--days <num>]\t\t # Show nightly dump size balance.") },
     { "tape", tape,
-       " [-days <num>]\t\t # Show which tape is due next." },
+       T_(" [--days <num>]\t\t # Show which tape is due next.") },
     { "bumpsize", bumpsize,
-       "\t\t\t # Show current bump thresholds." },
+       T_("\t\t\t # Show current bump thresholds.") },
     { "export", export_db,
-       " [<hostname> [<disks>]* ]* # Export curinfo database to stdout." },
+       T_(" [<hostname> [<disks>]* ]* # Export curinfo database to stdout.") },
     { "import", import_db,
-       "\t\t\t\t # Import curinfo database from stdin." },
+       T_("\t\t\t\t # Import curinfo database from stdin.") },
 };
 #define        NCMDS   (int)(sizeof(cmdtab) / sizeof(cmdtab[0]))
 
-static char *conffile;
-
 int
 main(
     int                argc,
@@ -137,80 +140,63 @@ main(
     int i;
     char *conf_diskfile;
     char *conf_infofile;
-    unsigned long malloc_hist_1, malloc_size_1;
-    unsigned long malloc_hist_2, malloc_size_2;
-    int new_argc;
-    char **new_argv;
+    config_overwrites_t *cfg_ovr = NULL;
+
+    /*
+     * 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);
     safe_cd();
 
     set_pname("amadmin");
 
-    dbopen(DBG_SUBDIR_SERVER);
-
     /* Don't die when child closes pipe */
     signal(SIGPIPE, SIG_IGN);
 
-    malloc_size_1 = malloc_inuse(&malloc_hist_1);
+    dbopen(DBG_SUBDIR_SERVER);
 
     erroutput_type = ERR_INTERACTIVE;
 
-    parse_server_conf(argc, argv, &new_argc, &new_argv);
+    cfg_ovr = extract_commandline_config_overwrites(&argc, &argv);
 
-    if(new_argc < 3) usage();
+    if(argc < 3) usage();
 
-    if(strcmp(new_argv[2],"version") == 0) {
-       show_version(new_argc, new_argv);
+    if(strcmp(argv[2],"version") == 0) {
+       show_version(argc, argv);
        goto done;
     }
 
-    config_name = new_argv[1];
-
-    config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
-    conffile = stralloc2(config_dir, CONFFILE_NAME);
-
-    if(read_conffile(conffile)) {
-       error("errors processing config file \"%s\"", conffile);
-       /*NOTREACHED*/
-    }
+    config_init(CONFIG_INIT_EXPLICIT_NAME | CONFIG_INIT_FATAL, argv[1]);
+    apply_config_overwrites(cfg_ovr);
 
     dbrename(config_name, DBG_SUBDIR_SERVER);
 
-    report_bad_conf_arg();
+    check_running_as(RUNNING_AS_DUMPUSER);
 
-    check_dumpuser();
-
-    conf_diskfile = getconf_str(CNF_DISKFILE);
-    if (*conf_diskfile == '/') {
-       conf_diskfile = stralloc(conf_diskfile);
-    } else {
-       conf_diskfile = stralloc2(config_dir, conf_diskfile);
-    }
+    conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
     if (read_diskfile(conf_diskfile, &diskq) < 0) {
-       error("could not load disklist \"%s\"", conf_diskfile);
+       error(_("could not load disklist \"%s\""), conf_diskfile);
        /*NOTREACHED*/
     }
     amfree(conf_diskfile);
 
-    conf_tapelist = getconf_str(CNF_TAPELIST);
-    if (*conf_tapelist == '/') {
-       conf_tapelist = stralloc(conf_tapelist);
-    } else {
-       conf_tapelist = stralloc2(config_dir, conf_tapelist);
-    }
+    conf_tapelist = config_dir_relative(getconf_str(CNF_TAPELIST));
     if(read_tapelist(conf_tapelist)) {
-       error("could not load tapelist \"%s\"", conf_tapelist);
+       error(_("could not load tapelist \"%s\""), conf_tapelist);
        /*NOTREACHED*/
     }
-    conf_infofile = getconf_str(CNF_INFOFILE);
-    if (*conf_infofile == '/') {
-       conf_infofile = stralloc(conf_infofile);
-    } else {
-       conf_infofile = stralloc2(config_dir, conf_infofile);
-    }
+    /* conf_tapelist is not freed yet -- it may be used to write the
+     * tapelist later. */
+
+    conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE));
     if(open_infofile(conf_infofile)) {
-       error("could not open info db \"%s\"", conf_infofile);
+       error(_("could not open info db \"%s\""), conf_infofile);
        /*NOTREACHED*/
     }
     amfree(conf_infofile);
@@ -219,33 +205,22 @@ main(
     unitdivisor = getconf_unit_divisor();
 
     for (i = 0; i < NCMDS; i++)
-       if (strcmp(new_argv[2], cmdtab[i].name) == 0) {
-           (*cmdtab[i].fn)(new_argc, new_argv);
+       if (strcmp(argv[2], cmdtab[i].name) == 0) {
+           (*cmdtab[i].fn)(argc, argv);
            break;
        }
     if (i == NCMDS) {
-       fprintf(stderr, "%s: unknown command \"%s\"\n", new_argv[0], new_argv[2]);
+       g_fprintf(stderr, _("%s: unknown command \"%s\"\n"), argv[0], argv[2]);
        usage();
     }
 
-    free_new_argv(new_argc, new_argv);
-
     close_infofile();
     clear_tapelist();
     amfree(conf_tapelist);
-    amfree(config_dir);
 
 done:
 
-    malloc_size_2 = malloc_inuse(&malloc_hist_2);
-
-    if(malloc_size_1 != malloc_size_2) {
-       malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
-    }
-
-    amfree(conffile);
     free_disklist(&diskq);
-    free_server_config();
     dbclose();
     return 0;
 }
@@ -256,11 +231,11 @@ usage(void)
 {
     int i;
 
-    fprintf(stderr, "\nUsage: %s%s <conf> <command> {<args>} [-o configoption]* ...\n",
+    g_fprintf(stderr, _("\nUsage: %s%s <conf> <command> {<args>} [-o configoption]* ...\n"),
            get_pname(), versionsuffix());
-    fprintf(stderr, "    Valid <command>s are:\n");
+    g_fprintf(stderr, _("    Valid <command>s are:\n"));
     for (i = 0; i < NCMDS; i++)
-       fprintf(stderr, "\t%s%s\n", cmdtab[i].name, cmdtab[i].usage);
+       g_fprintf(stderr, "\t%s%s\n", cmdtab[i].name, _(cmdtab[i].usage));
     exit(1);
 }
 
@@ -275,17 +250,25 @@ seqdatestr(
     int                seq)
 {
     static char str[16];
-    static char *dow[7] = {"Sun","Mon","Tue","Wed","Thu","Fri","Sat"};
+    static char *dow[7] = {
+                       T_("Sun"),
+                       T_("Mon"),
+                       T_("Tue"),
+                       T_("Wed"),
+                       T_("Thu"),
+                       T_("Fri"),
+                       T_("Sat")
+               };
     time_t t = today + seq*SECS_PER_DAY;
     struct tm *tm;
 
     tm = localtime(&t);
 
     if (tm)
-       snprintf(str, SIZEOF(str),
-                "%2d/%02d %3s", tm->tm_mon+1, tm->tm_mday, dow[tm->tm_wday]);
+       g_snprintf(str, SIZEOF(str),
+                "%2d/%02d %3s", tm->tm_mon+1, tm->tm_mday, _(dow[tm->tm_wday]));
     else
-       strcpy(str, "BAD DATE");
+       strcpy(str, _("BAD DATE"));
 
     return str;
 }
@@ -307,40 +290,6 @@ next_level0(
        return dp->dumpcycle - days_diff(info->inf[0].date, today);
 }
 
-static void
-check_dumpuser(void)
-{
-    static int been_here = 0;
-    uid_t uid_me;
-    uid_t uid_dumpuser;
-    char *dumpuser;
-    struct passwd *pw;
-
-    if (been_here) {
-       return;
-    }
-    uid_me = getuid();
-    uid_dumpuser = uid_me;
-    dumpuser = getconf_str(CNF_DUMPUSER);
-
-    if ((pw = getpwnam(dumpuser)) == NULL) {
-       error("cannot look up dump user \"%s\"", dumpuser);
-       /*NOTREACHED*/
-    }
-    uid_dumpuser = pw->pw_uid;
-    if ((pw = getpwuid(uid_me)) == NULL) {
-       error("cannot look up my own uid %ld", (long)uid_me);
-       /*NOTREACHED*/
-    }
-    if (uid_me != uid_dumpuser) {
-       error("ERROR: running as user \"%s\" instead of \"%s\"",
-             pw->pw_name, dumpuser);
-        /*NOTREACHED*/
-    }
-    been_here = 1;
-    return;
-}
-
 /* ----------------------------------------------- */
 
 void
@@ -355,14 +304,14 @@ diskloop(
     char *errstr;
 
     if(argc < 4) {
-       fprintf(stderr,"%s: expecting \"%s [<hostname> [<disks>]* ]+\"\n",
+       g_fprintf(stderr,_("%s: expecting \"%s [<hostname> [<disks>]* ]+\"\n"),
                get_pname(), cmdname);
        usage();
     }
 
     errstr = match_disklist(&diskq, argc-3, argv+3);
     if (errstr) {
-       printf("%s", errstr);
+       g_printf("%s", errstr);
        amfree(errstr);
     }
 
@@ -373,7 +322,7 @@ diskloop(
        }
     }
     if(count==0) {
-       fprintf(stderr,"%s: no disk matched\n",get_pname());
+       g_fprintf(stderr,_("%s: no disk matched\n"),get_pname());
     }
 }
 
@@ -388,21 +337,23 @@ force_one(
     char *diskname = dp->name;
     info_t info;
 
-#if TEXTDB
-    check_dumpuser();
-#endif
     get_info(hostname, diskname, &info);
     SET(info.command, FORCE_FULL);
     if (ISSET(info.command, FORCE_BUMP)) {
        CLR(info.command, FORCE_BUMP);
-       printf("%s: WARNING: %s:%s FORCE_BUMP command was cleared.\n",
+       g_printf(_("%s: WARNING: %s:%s FORCE_BUMP command was cleared.\n"),
               get_pname(), hostname, diskname);
     }
     if(put_info(hostname, diskname, &info) == 0) {
-       printf("%s: %s:%s is set to a forced level 0 at next run.\n",
-              get_pname(), hostname, diskname);
+       if (dp->strategy == DS_INCRONLY) {
+           g_printf(_("%s: %s:%s, full dump done offline, next dump will be at level 1.\n"),
+                    get_pname(), hostname, diskname);
+       } else {
+           g_printf(_("%s: %s:%s is set to a forced level 0 at next run.\n"),
+                    get_pname(), hostname, diskname);
+       }
     } else {
-       fprintf(stderr, "%s: %s:%s could not be forced.\n",
+       g_fprintf(stderr, _("%s: %s:%s could not be forced.\n"),
                get_pname(), hostname, diskname);
     }
 }
@@ -430,21 +381,18 @@ unforce_one(
 
     get_info(hostname, diskname, &info);
     if (ISSET(info.command, FORCE_FULL)) {
-#if TEXTDB
-       check_dumpuser();
-#endif
        CLR(info.command, FORCE_FULL);
        if(put_info(hostname, diskname, &info) == 0){
-           printf("%s: force command for %s:%s cleared.\n",
+           g_printf(_("%s: force command for %s:%s cleared.\n"),
                   get_pname(), hostname, diskname);
        } else {
-           fprintf(stderr,
-                   "%s: force command for %s:%s could not be cleared.\n",
+           g_fprintf(stderr,
+                   _("%s: force command for %s:%s could not be cleared.\n"),
                    get_pname(), hostname, diskname);
        }
     }
     else {
-       printf("%s: no force command outstanding for %s:%s, unchanged.\n",
+       g_printf(_("%s: no force command outstanding for %s:%s, unchanged.\n"),
               get_pname(), hostname, diskname);
     }
 }
@@ -469,26 +417,23 @@ force_bump_one(
     char *diskname = dp->name;
     info_t info;
 
-#if TEXTDB
-    check_dumpuser();
-#endif
     get_info(hostname, diskname, &info);
     SET(info.command, FORCE_BUMP);
     if (ISSET(info.command, FORCE_NO_BUMP)) {
        CLR(info.command, FORCE_NO_BUMP);
-       printf("%s: WARNING: %s:%s FORCE_NO_BUMP command was cleared.\n",
+       g_printf(_("%s: WARNING: %s:%s FORCE_NO_BUMP command was cleared.\n"),
               get_pname(), hostname, diskname);
     }
     if (ISSET(info.command, FORCE_FULL)) {
        CLR(info.command, FORCE_FULL);
-       printf("%s: WARNING: %s:%s FORCE_FULL command was cleared.\n",
+       g_printf(_("%s: WARNING: %s:%s FORCE_FULL command was cleared.\n"),
               get_pname(), hostname, diskname);
     }
     if(put_info(hostname, diskname, &info) == 0) {
-       printf("%s: %s:%s is set to bump at next run.\n",
+       g_printf(_("%s: %s:%s is set to bump at next run.\n"),
               get_pname(), hostname, diskname);
     } else {
-       fprintf(stderr, "%s: %s:%s could not be forced to bump.\n",
+       g_fprintf(stderr, _("%s: %s:%s could not be forced to bump.\n"),
                get_pname(), hostname, diskname);
     }
 }
@@ -514,21 +459,18 @@ force_no_bump_one(
     char *diskname = dp->name;
     info_t info;
 
-#if TEXTDB
-    check_dumpuser();
-#endif
     get_info(hostname, diskname, &info);
     SET(info.command, FORCE_NO_BUMP);
     if (ISSET(info.command, FORCE_BUMP)) {
        CLR(info.command, FORCE_BUMP);
-       printf("%s: WARNING: %s:%s FORCE_BUMP command was cleared.\n",
+       g_printf(_("%s: WARNING: %s:%s FORCE_BUMP command was cleared.\n"),
               get_pname(), hostname, diskname);
     }
     if(put_info(hostname, diskname, &info) == 0) {
-       printf("%s: %s:%s is set to not bump at next run.\n",
+       g_printf(_("%s: %s:%s is set to not bump at next run.\n"),
               get_pname(), hostname, diskname);
     } else {
-       fprintf(stderr, "%s: %s:%s could not be force to not bump.\n",
+       g_fprintf(stderr, _("%s: %s:%s could not be force to not bump.\n"),
                get_pname(), hostname, diskname);
     }
 }
@@ -556,20 +498,17 @@ unforce_bump_one(
 
     get_info(hostname, diskname, &info);
     if (ISSET(info.command, FORCE_BUMP|FORCE_NO_BUMP)) {
-#if TEXTDB
-       check_dumpuser();
-#endif
        CLR(info.command, FORCE_BUMP|FORCE_NO_BUMP);
        if(put_info(hostname, diskname, &info) == 0) {
-           printf("%s: bump command for %s:%s cleared.\n",
+           g_printf(_("%s: bump command for %s:%s cleared.\n"),
                   get_pname(), hostname, diskname);
        } else {
-           fprintf(stderr, "%s: %s:%s bump command could not be cleared.\n",
+           g_fprintf(stderr, _("%s: %s:%s bump command could not be cleared.\n"),
                    get_pname(), hostname, diskname);
        }
     }
     else {
-       printf("%s: no bump command outstanding for %s:%s, unchanged.\n",
+       g_printf(_("%s: no bump command outstanding for %s:%s, unchanged.\n"),
               get_pname(), hostname, diskname);
     }
 }
@@ -595,31 +534,30 @@ reuse(
     int count;
 
     if(argc < 4) {
-       fprintf(stderr,"%s: expecting \"reuse <tapelabel> ...\"\n",
+       g_fprintf(stderr,_("%s: expecting \"reuse <tapelabel> ...\"\n"),
                get_pname());
        usage();
     }
 
-    check_dumpuser();
     for(count=3; count< argc; count++) {
        tp = lookup_tapelabel(argv[count]);
        if ( tp == NULL) {
-           fprintf(stderr, "reuse: tape label %s not found in tapelist.\n",
+           g_fprintf(stderr, _("reuse: tape label %s not found in tapelist.\n"),
                argv[count]);
            continue;
        }
        if( tp->reuse == 0 ) {
            tp->reuse = 1;
-           printf("%s: marking tape %s as reusable.\n",
+           g_printf(_("%s: marking tape %s as reusable.\n"),
                   get_pname(), argv[count]);
        } else {
-           fprintf(stderr, "%s: tape %s already reusable.\n",
+           g_fprintf(stderr, _("%s: tape %s already reusable.\n"),
                    get_pname(), argv[count]);
        }
     }
 
     if(write_tapelist(conf_tapelist)) {
-       error("could not write tapelist \"%s\"", conf_tapelist);
+       error(_("could not write tapelist \"%s\""), conf_tapelist);
        /*NOTREACHED*/
     }
 }
@@ -633,31 +571,30 @@ noreuse(
     int count;
 
     if(argc < 4) {
-       fprintf(stderr,"%s: expecting \"no-reuse <tapelabel> ...\"\n",
+       g_fprintf(stderr,_("%s: expecting \"no-reuse <tapelabel> ...\"\n"),
                get_pname());
        usage();
     }
 
-    check_dumpuser();
     for(count=3; count< argc; count++) {
        tp = lookup_tapelabel(argv[count]);
        if ( tp == NULL) {
-           fprintf(stderr, "no-reuse: tape label %s not found in tapelist.\n",
+           g_fprintf(stderr, _("no-reuse: tape label %s not found in tapelist.\n"),
                argv[count]);
            continue;
        }
        if( tp->reuse == 1 ) {
            tp->reuse = 0;
-           printf("%s: marking tape %s as not reusable.\n",
+           g_printf(_("%s: marking tape %s as not reusable.\n"),
                   get_pname(), argv[count]);
        } else {
-           fprintf(stderr, "%s: tape %s already not reusable.\n",
+           g_fprintf(stderr, _("%s: tape %s already not reusable.\n"),
                    get_pname(), argv[count]);
        }
     }
 
     if(write_tapelist(conf_tapelist)) {
-       error("could not write tapelist \"%s\"", conf_tapelist);
+       error(_("could not write tapelist \"%s\""), conf_tapelist);
        /*NOTREACHED*/
     }
 }
@@ -676,18 +613,18 @@ delete_one(
     info_t info;
 
     if(get_info(hostname, diskname, &info)) {
-       printf("%s: %s:%s NOT currently in database.\n",
+       g_printf(_("%s: %s:%s NOT currently in database.\n"),
               get_pname(), hostname, diskname);
        return;
     }
 
     deleted++;
     if(del_info(hostname, diskname)) {
-       error("couldn't delete %s:%s from database: %s",
+       error(_("couldn't delete %s:%s from database: %s"),
              hostname, diskname, strerror(errno));
         /*NOTREACHED*/
     } else {
-       printf("%s: %s:%s deleted from curinfo database.\n",
+       g_printf(_("%s: %s:%s deleted from curinfo database.\n"),
               get_pname(), hostname, diskname);
     }
 }
@@ -701,8 +638,8 @@ delete(
     diskloop(argc, argv, "delete", delete_one);
 
    if(deleted)
-       printf(
-        "%s: NOTE: you'll have to remove these from the disklist yourself.\n",
+       g_printf(
+        _("%s: NOTE: you'll have to remove these from the disklist yourself.\n"),
         get_pname());
 }
 
@@ -719,44 +656,42 @@ info_one(
 
     get_info(dp->host->hostname, dp->name, &info);
 
-    printf("\nCurrent info for %s %s:\n", dp->host->hostname, dp->name);
+    g_printf(_("\nCurrent info for %s %s:\n"), dp->host->hostname, dp->name);
     if (ISSET(info.command, FORCE_FULL))
-       printf("  (Forcing to level 0 dump at next run)\n");
+       g_printf(_("  (Forcing to level 0 dump at next run)\n"));
     if (ISSET(info.command, FORCE_BUMP))
-       printf("  (Forcing bump at next run)\n");
+       g_printf(_("  (Forcing bump at next run)\n"));
     if (ISSET(info.command, FORCE_NO_BUMP))
-       printf("  (Forcing no-bump at next run)\n");
-    printf("  Stats: dump rates (kps), Full:  %5.1lf, %5.1lf, %5.1lf\n",
+       g_printf(_("  (Forcing no-bump at next run)\n"));
+    g_printf(_("  Stats: dump rates (kps), Full:  %5.1lf, %5.1lf, %5.1lf\n"),
           info.full.rate[0], info.full.rate[1], info.full.rate[2]);
-    printf("                    Incremental:  %5.1lf, %5.1lf, %5.1lf\n",
+    g_printf(_("                    Incremental:  %5.1lf, %5.1lf, %5.1lf\n"),
           info.incr.rate[0], info.incr.rate[1], info.incr.rate[2]);
-    printf("          compressed size, Full: %5.1lf%%,%5.1lf%%,%5.1lf%%\n",
+    g_printf(_("          compressed size, Full: %5.1lf%%,%5.1lf%%,%5.1lf%%\n"),
           info.full.comp[0]*100, info.full.comp[1]*100, info.full.comp[2]*100);
-    printf("                    Incremental: %5.1lf%%,%5.1lf%%,%5.1lf%%\n",
+    g_printf(_("                    Incremental: %5.1lf%%,%5.1lf%%,%5.1lf%%\n"),
           info.incr.comp[0]*100, info.incr.comp[1]*100, info.incr.comp[2]*100);
 
-    printf("  Dumps: lev datestmp  tape             file   origK   compK secs\n");
+    g_printf(_("  Dumps: lev datestmp  tape             file   origK   compK secs\n"));
     for(lev = 0, sp = &info.inf[0]; lev < 9; lev++, sp++) {
        if(sp->date < (time_t)0 && sp->label[0] == '\0') continue;
        tm = localtime(&sp->date);
        if (tm) {
-           printf("          %d  %04d%02d%02d  %-15s  "
-                  OFF_T_FMT " " OFF_T_FMT " " OFF_T_FMT " " TIME_T_FMT "\n",
+           g_printf(_("          %d  %04d%02d%02d  %-15s  %lld %lld %lld %jd\n"),
                   lev, tm->tm_year+1900, tm->tm_mon+1, tm->tm_mday,
                   sp->label,
-                  (OFF_T_FMT_TYPE)sp->filenum,
-                  (OFF_T_FMT_TYPE)sp->size,
-                  (OFF_T_FMT_TYPE)sp->csize,
-                  (TIME_T_FMT_TYPE)sp->secs);
+                  (long long)sp->filenum,
+                  (long long)sp->size,
+                  (long long)sp->csize,
+                  (intmax_t)sp->secs);
        } else {
-           printf("          %d  BAD-DATE  %-15s  "
-                  OFF_T_FMT " " OFF_T_FMT " " OFF_T_FMT " " TIME_T_FMT "\n",
+           g_printf(_("          %d  BAD-DATE  %-15s  %lld %lld %lld %jd\n"),
                   lev,
                   sp->label,
-                  (OFF_T_FMT_TYPE)sp->filenum,
-                  (OFF_T_FMT_TYPE)sp->size,
-                  (OFF_T_FMT_TYPE)sp->csize,
-                  (TIME_T_FMT_TYPE)sp->secs);
+                  (long long)sp->filenum,
+                  (long long)sp->size,
+                  (long long)sp->csize,
+                  (intmax_t)sp->secs);
        }
     }
 }
@@ -788,20 +723,20 @@ due_one(
 
     hp = dp->host;
     if(get_info(hp->hostname, dp->name, &info)) {
-       printf("new disk %s:%s ignored.\n", hp->hostname, dp->name);
+       g_printf(_("new disk %s:%s ignored.\n"), hp->hostname, dp->name);
     }
     else {
        days = next_level0(dp, &info);
        if(days < 0) {
-           printf("Overdue %2d day%s %s:%s\n",
+           g_printf(_("Overdue %2d day%s %s:%s\n"),
                   -days, (-days == 1) ? ": " : "s:",
                   hp->hostname, dp->name);
        }
        else if(days == 0) {
-           printf("Due today: %s:%s\n", hp->hostname, dp->name);
+           g_printf(_("Due today: %s:%s\n"), hp->hostname, dp->name);
        }
        else {
-           printf("Due in %2d day%s %s:%s\n", days,
+           g_printf(_("Due in %2d day%s %s:%s\n"), days,
                   (days == 1) ? ": " : "s:",
                   hp->hostname, dp->name);
        }
@@ -830,14 +765,17 @@ tape(
     int                argc,
     char **    argv)
 {
-    tape_t *tp, *lasttp;
-    int runtapes, i, j;
-    int nb_days = 1;
+    int     nb_days = 1;
+    int     runtapes;
+    tape_t *tp;
+    int     i, j;
+    int     skip;
+    int     nb_new_tape;
 
     if(argc > 4 && strcmp(argv[3],"--days") == 0) {
        nb_days = atoi(argv[4]);
        if(nb_days < 1) {
-           printf("days must be an integer bigger than 0\n");
+           g_printf(_("days must be an integer bigger than 0\n"));
            return;
        }
        if (nb_days > 10000)
@@ -846,54 +784,41 @@ tape(
 
     runtapes = getconf_int(CNF_RUNTAPES);
     tp = lookup_last_reusable_tape(0);
+    skip = 0;
 
     for ( j=0 ; j < nb_days ; j++ ) {
+       nb_new_tape=0;
        for ( i=0 ; i < runtapes ; i++ ) {
            if(i==0)
-               printf("The next Amanda run should go onto ");
-           else
-               printf("                                   ");
+               g_fprintf(stdout, _("The next Amanda run should go onto "));
            if(tp != NULL) {
-               printf("tape %s or a new tape.\n", tp->label);
+               if (nb_new_tape > 0) {
+                   if (nb_new_tape == 1)
+                       g_fprintf(stdout, _("1 new tape.\n"));
+                   else
+                       g_fprintf(stdout, _("%d new tapes.\n"), nb_new_tape);
+                   g_fprintf(stdout, "                                   ");
+                   nb_new_tape = 0;
+               }
+               g_fprintf(stdout, _("tape %s or a new tape.\n"), tp->label);
+               if (i < runtapes-1)
+                   g_fprintf(stdout, "                                   ");
            } else {
-               if (runtapes - i == 1)
-                   printf("1 new tape.\n");
-               else
-                   printf("%d new tapes.\n", runtapes - i);
-               i = runtapes;
+               nb_new_tape++;
            }
-       
-           tp = lookup_last_reusable_tape(i + 1);
-       }
-    }
-    lasttp = lookup_tapepos(lookup_nb_tape());
-    i = runtapes;
-    if(lasttp && i > 0 && strcmp(lasttp->datestamp,"0") == 0) {
-       int c = 0;
-       while(lasttp && i > 0 && strcmp(lasttp->datestamp,"0") == 0) {
-           c++;
-           lasttp = lasttp->prev;
-           i--;
-       }
-       lasttp = lookup_tapepos(lookup_nb_tape());
-       i = runtapes;
-       if(c == 1) {
-           printf("The next new tape already labelled is: %s.\n",
-                  lasttp->label);
+           skip++;
+
+           tp = lookup_last_reusable_tape(skip);
        }
-       else {
-           printf("The next %d new tapes already labelled are: %s", c,
-                  lasttp->label);
-           lasttp = lasttp->prev;
-           c--;
-           while(lasttp && c > 0 && strcmp(lasttp->datestamp,"0") == 0) {
-               printf(", %s", lasttp->label);
-               lasttp = lasttp->prev;
-               c--;
-           }
-           printf(".\n");
+       if (nb_new_tape > 0) {
+           if (nb_new_tape == 1)
+               g_fprintf(stdout, _("1 new tape.\n"));
+           else
+               g_fprintf(stdout, _("%d new tapes.\n"), nb_new_tape);
        }
     }
+
+    print_new_tapes(stdout, nb_days * runtapes);
 }
 
 /* ----------------------------------------------- */
@@ -954,7 +879,7 @@ balance(
 
     for(dp = diskq.head; dp != NULL; dp = dp->next) {
        if(get_info(dp->host->hostname, dp->name, &info)) {
-           printf("new disk %s:%s ignored.\n", dp->host->hostname, dp->name);
+           g_printf(_("new disk %s:%s ignored.\n"), dp->host->hostname, dp->name);
            continue;
        }
        if (dp->strategy == DS_NOFULL) {
@@ -1011,7 +936,7 @@ balance(
     }
 
     if(sp[total].outsize == (off_t)0 && sp[later].outsize == (off_t)0) {
-       printf("\nNo data to report on yet.\n");
+       g_printf(_("\nNo data to report on yet.\n"));
        amfree(sp);
        return;
     }
@@ -1026,9 +951,9 @@ balance(
     }
 
     empty_day = 0;
-    printf("\n due-date  #fs    orig %cB     out %cB   balance\n",
+    g_printf(_("\n due-date  #fs    orig %cB     out %cB   balance\n"),
           displayunit[0], displayunit[0]);
-    printf("----------------------------------------------\n");
+    g_printf("----------------------------------------------\n");
     for(seq = 0; seq < later; seq++) {
        if(sp[seq].disks == 0 &&
           ((seq > 0 && sp[seq-1].disks == 0) ||
@@ -1037,56 +962,61 @@ balance(
        }
        else {
            if(empty_day > 0) {
-               printf("\n");
+               g_printf("\n");
                empty_day = 0;
            }
-           printf("%-9.9s  %3d " OFF_T_FMT " " OFF_T_FMT " ",
+           g_printf(_("%-9.9s  %3d %10lld %10lld "),
                   seqdatestr(seq), sp[seq].disks,
-                  (OFF_T_FMT_TYPE)sp[seq].origsize,
-                  (OFF_T_FMT_TYPE)sp[seq].outsize);
-           if(!sp[seq].outsize) printf("     --- \n");
-           else printf("%+8.1lf%%\n",
+                  (long long)sp[seq].origsize,
+                  (long long)sp[seq].outsize);
+           if(!sp[seq].outsize) g_printf("     --- \n");
+           else g_printf(_("%+8.1lf%%\n"),
                        (((double)sp[seq].outsize - (double)balanced) * 100.0 /
                        (double)balanced));
        }
     }
 
     if(sp[later].disks != 0) {
-       printf("later      %3d " OFF_T_FMT " " OFF_T_FMT " ",
+       g_printf(_("later      %3d %10lld %10lld "),
               sp[later].disks,
-              (OFF_T_FMT_TYPE)sp[later].origsize,
-              (OFF_T_FMT_TYPE)sp[later].outsize);
-       if(!sp[later].outsize) printf("     --- \n");
-       else printf("%+8.1lf%%\n",
+              (long long)sp[later].origsize,
+              (long long)sp[later].outsize);
+       if(!sp[later].outsize) g_printf("     --- \n");
+       else g_printf(_("%+8.1lf%%\n"),
                    (((double)sp[later].outsize - (double)balanced) * 100.0 /
                    (double)balanced));
     }
-    printf("----------------------------------------------\n");
-    printf("TOTAL      %3d " OFF_T_FMT " " OFF_T_FMT " " OFF_T_FMT "\n",
+    g_printf("----------------------------------------------\n");
+    g_printf(_("TOTAL      %3d %10lld %10lld %9lld\n"),
           sp[total].disks,
-          (OFF_T_FMT_TYPE)sp[total].origsize,
-          (OFF_T_FMT_TYPE)sp[total].outsize,
-          (OFF_T_FMT_TYPE)total_balanced);
+          (long long)sp[total].origsize,
+          (long long)sp[total].outsize,
+          (long long)total_balanced);
     if (sp[balance].origsize != sp[total].origsize ||
         sp[balance].outsize != sp[total].outsize ||
        balanced != total_balanced) {
-       printf("BALANCED       " OFF_T_FMT " " OFF_T_FMT " " OFF_T_FMT "\n",
-              (OFF_T_FMT_TYPE)sp[balance].origsize,
-              (OFF_T_FMT_TYPE)sp[balance].outsize,
-              (OFF_T_FMT_TYPE)balanced);
+       g_printf(_("BALANCED       %10lld %10lld %9lld\n"),
+              (long long)sp[balance].origsize,
+              (long long)sp[balance].outsize,
+              (long long)balanced);
     }
     if (sp[distinct].disks != sp[total].disks) {
-       printf("DISTINCT   %3d " OFF_T_FMT " " OFF_T_FMT "\n",
+       g_printf(_("DISTINCT   %3d %10lld %10lld\n"),
               sp[distinct].disks,
-              (OFF_T_FMT_TYPE)sp[distinct].origsize,
-              (OFF_T_FMT_TYPE)sp[distinct].outsize);
+              (long long)sp[distinct].origsize,
+              (long long)sp[distinct].outsize);
     }
-    printf("  (estimated %d run%s per dumpcycle)\n",
-          runs_per_cycle, (runs_per_cycle == 1) ? "" : "s");
+    g_printf(plural(_("  (estimated %d run per dumpcycle)\n"),
+                 _("  (estimated %d runs per dumpcycle)\n"),
+                 runs_per_cycle),
+          runs_per_cycle);
     if (overdue) {
-       printf(" (%d filesystem%s overdue, the most being overdue %d day%s)\n",
-              overdue, (overdue == 1) ? "" : "s",
-              max_overdue, (max_overdue == 1) ? "" : "s");
+       g_printf(plural(_(" (%d filesystem overdue."),
+                     _(" (%d filesystems overdue."), overdue),
+              overdue);
+       g_printf(plural(_(" The most being overdue %d day.)\n"),
+                     _(" The most being overdue %d days.)\n"), max_overdue),
+              max_overdue);
     }
     amfree(sp);
 }
@@ -1105,8 +1035,8 @@ find(
     char *errstr;
 
     if(argc < 3) {
-       fprintf(stderr,
-               "%s: expecting \"find [--sort <hkdlpb>] [hostname [<disk>]]*\"\n",
+       g_fprintf(stderr,
+               _("%s: expecting \"find [--sort <hkdlpbf>] [hostname [<disk>]]*\"\n"),
                get_pname());
        usage();
     }
@@ -1124,6 +1054,8 @@ find(
            case 'K':
            case 'd':
            case 'D':
+           case 'f':
+           case 'F':
            case 'l':
            case 'L':
            case 'p':
@@ -1137,8 +1069,8 @@ find(
        if(valid_sort) {
            sort_order = newstralloc(sort_order, argv[4]);
        } else {
-           printf("Invalid sort order: %s\n", argv[4]);
-           printf("Use default sort order: %s\n", sort_order);
+           g_printf(_("Invalid sort order: %s\n"), argv[4]);
+           g_printf(_("Use default sort order: %s\n"), sort_order);
        }
        start_argc=6;
     } else {
@@ -1146,20 +1078,20 @@ find(
     }
     errstr = match_disklist(&diskq, argc-(start_argc-1), argv+(start_argc-1));
     if (errstr) {
-       printf("%s", errstr);
+       g_printf("%s", errstr);
        amfree(errstr);
     }
 
-    output_find = find_dump(1, &diskq);
+    output_find = find_dump(&diskq);
     if(argc-(start_argc-1) > 0) {
        free_find_result(&output_find);
        errstr = match_disklist(&diskq, argc-(start_argc-1),
                                        argv+(start_argc-1));
        if (errstr) {
-           printf("%s", errstr);
+           g_printf("%s", errstr);
            amfree(errstr);
        }
-       output_find = find_dump(0, NULL);
+       output_find = find_dump(NULL);
     }
 
     sort_find_result(sort_order, &output_find);
@@ -1170,6 +1102,331 @@ find(
 }
 
 
+/* ------------------------ */
+
+static GSList *
+get_file_list(
+    int argc,
+    char **argv,
+    int allow_empty)
+{
+    GSList * file_list = NULL;
+    GSList * dumplist;
+    int flags;
+
+    flags = CMDLINE_PARSE_DATESTAMP;
+    if (allow_empty) flags |= CMDLINE_EMPTY_TO_WILDCARD;
+    dumplist = cmdline_parse_dumpspecs(argc, argv, flags);
+
+    file_list = cmdline_match_holding(dumplist);
+    dumpspec_list_free(dumplist);
+
+    return file_list;
+}
+
+/* Given a file header, find the history element in curinfo most likely
+ * corresponding to that dump (this is not an exact science).
+ *
+ * @param info: the info_t element for this DLE
+ * @param file: the header of the file
+ * @returns: index of the matching history element, or -1 if not found
+ */
+static int
+holding_file_find_history(
+    info_t *info,
+    dumpfile_t *file)
+{
+    int matching_hist_idx = -1;
+    int nhist;
+    int i;
+
+    /* Begin by trying to find the history element matching this dump.
+     * The datestamp on the dump is for the entire run of amdump, while the
+     * 'date' in the history element of 'info' is the time the dump itself
+     * began.  A matching history element, then, is the earliest element
+     * with a 'date' equal to or later than the date of the dumpfile.
+     *
+     * We compare using formatted datestamps; even using seconds since epoch,
+     * we would still face timezone issues, and have to do a reverse (timezone
+     * to gmt) translation.
+     */
+
+    /* get to the end of the history list and search backward */
+    for (nhist = 0; info->history[nhist].level > -1; nhist++) /* empty loop */;
+    for (i = nhist-1; i > -1; i--) {
+        char *info_datestamp = get_timestamp_from_time(info->history[i].date);
+        int order = strcmp(file->datestamp, info_datestamp);
+        amfree(info_datestamp);
+
+        if (order <= 0) {
+            /* only a match if the levels are equal */
+            if (info->history[i].level == file->dumplevel) {
+                matching_hist_idx = i;
+            }
+            break;
+        }
+    }
+
+    return matching_hist_idx;
+}
+
+/* A holding file is 'outdated' if a subsequent dump of the same DLE was made
+ * at the same level or a lower leve; for example, a level 2 dump is outdated if
+ * there is a subsequent level 2, or a subsequent level 0.
+ *
+ * @param file: the header of the file
+ * @returns: true if the file is outdated
+ */
+static int
+holding_file_is_outdated(
+    dumpfile_t *file)
+{
+    info_t info;
+    int matching_hist_idx;
+
+    if (get_info(file->name, file->disk, &info) == -1) {
+       return 0; /* assume it's not outdated */
+    }
+
+    /* if the last level is less than the level of this dump, then
+     * it's outdated */
+    if (info.last_level < file->dumplevel)
+       return 1;
+
+    /* otherwise, we need to see if this dump is the last at its level */
+    matching_hist_idx = holding_file_find_history(&info, file);
+    if (matching_hist_idx == -1) {
+        return 0; /* assume it's not outdated */
+    }
+
+    /* compare the date of the history element with the most recent date
+     * for this level.  If they match, then this is the last dump at this
+     * level, and we checked above for more recent lower-level dumps, so
+     * the dump is not outdated. */
+    if (info.history[matching_hist_idx].date == 
+       info.inf[info.history[matching_hist_idx].level].date) {
+       return 0;
+    } else {
+       return 1;
+    }
+}
+
+static int
+remove_holding_file_from_catalog(
+    char *filename)
+{
+    static int warnings_printed; /* only print once per invocation */
+    dumpfile_t file;
+    info_t info;
+    int matching_hist_idx = -1;
+    history_t matching_hist; /* will be a copy */
+    int i;
+
+    if (!holding_file_get_dumpfile(filename, &file)) {
+        g_printf(_("Could not read holding file %s\n"), filename);
+        return 0;
+    }
+
+    if (get_info(file.name, file.disk, &info) == -1) {
+           g_printf(_("WARNING: No curinfo record for %s:%s\n"), file.name, file.disk);
+           return 1; /* not an error */
+    }
+
+    matching_hist_idx = holding_file_find_history(&info, &file);
+
+    if (matching_hist_idx == -1) {
+        g_printf(_("WARNING: No dump matching %s found in curinfo.\n"), filename);
+       return 1; /* not an error */
+    }
+
+    /* make a copy */
+    matching_hist = info.history[matching_hist_idx];
+
+    /* Remove the history element itself before doing the stats */
+    for (i = matching_hist_idx; i <= NB_HISTORY; i++) {
+        info.history[i] = info.history[i+1];
+    }
+    info.history[NB_HISTORY].level = -1;
+
+    /* Remove stats for that history element, if necessary.  Doing so
+     * will result in an inconsistent set of backups, so we warn the
+     * user and adjust last_level to make the next dump get us a 
+     * consistent picture. */
+    if (matching_hist.date == info.inf[matching_hist.level].date) {
+        /* search for an earlier dump at this level */
+        for (i = matching_hist_idx; info.history[i].level > -1; i++) {
+            if (info.history[i].level == matching_hist.level)
+                break;
+        }
+
+        if (info.history[i].level < 0) {
+            /* not found => zero it out */
+            info.inf[matching_hist.level].date = (time_t)-1; /* flag as not set */
+            info.inf[matching_hist.level].label[0] = '\0';
+        } else {
+            /* found => reconstruct stats as best we can */
+            info.inf[matching_hist.level].size = info.history[i].size;
+            info.inf[matching_hist.level].csize = info.history[i].csize;
+            info.inf[matching_hist.level].secs = info.history[i].secs;
+            info.inf[matching_hist.level].date = info.history[i].date;
+            info.inf[matching_hist.level].filenum = 0; /* we don't know */
+            info.inf[matching_hist.level].label[0] = '\0'; /* we don't know */
+        }
+
+        /* set last_level to the level we just deleted, and set command
+         * appropriately to make sure planner does a new dump at this level
+         * or lower */
+        info.last_level = matching_hist.level;
+        if (info.last_level == 0) {
+            g_printf(_("WARNING: Deleting the most recent full dump; forcing a full dump at next run.\n"));
+            SET(info.command, FORCE_FULL);
+        } else {
+            g_printf(_("WARNING: Deleting the most recent level %d dump; forcing a level %d dump or \nWARNING: lower at next run.\n"),
+                info.last_level, info.last_level);
+            SET(info.command, FORCE_NO_BUMP);
+        }
+
+        /* Search for and display any subsequent runs that depended on this one */
+        warnings_printed = 0;
+        for (i = matching_hist_idx-1; i >= 0; i--) {
+            char *datestamp;
+            if (info.history[i].level <= matching_hist.level) break;
+
+            datestamp = get_timestamp_from_time(info.history[i].date);
+            g_printf(_("WARNING: Level %d dump made %s can no longer be accurately restored.\n"), 
+                info.history[i].level, datestamp);
+            amfree(datestamp);
+
+            warnings_printed = 1;
+        }
+        if (warnings_printed)
+            g_printf(_("WARNING: (note, dates shown above are for dumps, and may be later than the\nWARNING: corresponding run date)\n"));
+    }
+
+    /* recalculate consecutive_runs based on the history: find the first run
+     * at this level, and then count the consecutive runs at that level. This
+     * number may be zero (if we just deleted the last run at this level) */
+    info.consecutive_runs = 0;
+    for (i = 0; info.history[i].level >= 0; i++) {
+        if (info.history[i].level == info.last_level) break;
+    }
+    while (info.history[i+info.consecutive_runs].level == info.last_level)
+        info.consecutive_runs++;
+
+    /* this function doesn't touch the performance stats */
+
+    /* write out the changes */
+    if (put_info(file.name, file.disk, &info) == -1) {
+           g_printf(_("Could not write curinfo record for %s:%s\n"), file.name, file.disk);
+           return 0;
+    }
+
+    return 1;
+}
+
+void
+holding(
+    int                argc,
+    char **    argv)
+{
+    GSList *file_list;
+    GSList *li;
+    enum { HOLDING_USAGE, HOLDING_LIST, HOLDING_DELETE } action = HOLDING_USAGE;
+    int long_list = 0;
+    int outdated_list = 0;
+    dumpfile_t file;
+
+    if (argc < 4)
+        action = HOLDING_USAGE;
+    else if (strcmp(argv[3], "list") == 0 && argc >= 4)
+        action = HOLDING_LIST;
+    else if (strcmp(argv[3], "delete") == 0 && argc > 4)
+        action = HOLDING_DELETE;
+
+    switch (action) {
+        case HOLDING_USAGE:
+            g_fprintf(stderr,
+                    _("%s: expecting \"holding list [-l] [-d]\" or \"holding delete <host> [ .. ]\"\n"),
+                    get_pname());
+            usage();
+            return;
+
+        case HOLDING_LIST:
+            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) {
+                g_printf("%-10s %-2s %-4s %s\n", 
+                   _("size (kB)"), _("lv"), _("outd"), _("dump specification"));
+            }
+
+            file_list = get_file_list(argc, argv, 1);
+            for (li = file_list; li != NULL; li = li->next) {
+                char *dumpstr;
+               int is_outdated;
+
+                if (!holding_file_get_dumpfile((char *)li->data, &file)) {
+                    g_fprintf(stderr, _("Error reading %s\n"), (char *)li->data);
+                    continue;
+                }
+
+               is_outdated = holding_file_is_outdated(&file);
+
+                dumpstr = cmdline_format_dumpspec_components(file.name, file.disk, file.datestamp, NULL);
+               /* only print this entry if we're printing everything, or if it's outdated and
+                * we're only printing outdated files (-o) */
+               if (!outdated_list || is_outdated) {
+                   if (long_list) {
+                       g_printf("%-10lld %-2d %-4s %s\n", 
+                              (long long)holding_file_size((char *)li->data, 0),
+                              file.dumplevel,
+                              is_outdated? " *":"",
+                              dumpstr);
+                   } else {
+                       g_printf("%s\n", dumpstr);
+                   }
+               }
+                amfree(dumpstr);
+            }
+            g_slist_free_full(file_list);
+            break;
+
+        case HOLDING_DELETE:
+            argc -= 4; argv += 4;
+
+            file_list = get_file_list(argc, argv, 0);
+            for (li = file_list; li != NULL; li = li->next) {
+                g_fprintf(stderr, _("Deleting '%s'\n"), (char *)li->data);
+                /* remove it from the catalog */
+                if (!remove_holding_file_from_catalog((char *)li->data))
+                    exit(1);
+
+                /* unlink it */
+                if (!holding_file_unlink((char *)li->data)) {
+                    error(_("Could not delete '%s'"), (char *)li->data);
+                }
+            }
+            g_slist_free_full(file_list);
+            break;
+    }
+}
+
+
 /* ------------------------ */
 
 
@@ -1199,32 +1456,32 @@ bumpsize(
     (void)argc;        /* Quiet unused parameter warning */
     (void)argv;        /* Quiet unused parameter warning */
 
-    printf("Current bump parameters:\n");
+    g_printf(_("Current bump parameters:\n"));
     if(conf_bumppercent == 0) {
-       printf("  bumpsize %5d KB\t- minimum savings (threshold) to bump level 1 -> 2\n",
+       g_printf(_("  bumpsize %5d KB\t- minimum savings (threshold) to bump level 1 -> 2\n"),
               getconf_int(CNF_BUMPSIZE));
-       printf("  bumpdays %5d\t- minimum days at each level\n",
+       g_printf(_("  bumpdays %5d\t- minimum days at each level\n"),
               getconf_int(CNF_BUMPDAYS));
-       printf("  bumpmult %5.5lg\t- threshold = bumpsize * bumpmult**(level-1)\n\n",
+       g_printf(_("  bumpmult %5.5lg\t- threshold = bumpsize * bumpmult**(level-1)\n\n"),
               conf_bumpmult);
 
-       printf("      Bump -> To  Threshold\n");
+       g_printf(_("      Bump -> To  Threshold\n"));
        for(l = 1; l < 9; l++)
-           printf("\t%d  ->  %d  %9d KB\n", l, l+1, bump_thresh(l));
+           g_printf(_("\t%d  ->  %d  %9d KB\n"), l, l+1, bump_thresh(l));
        putchar('\n');
     }
     else {
        double bumppercent = (double)conf_bumppercent;
 
-       printf("  bumppercent %3d %%\t- minimum savings (threshold) to bump level 1 -> 2\n",
+       g_printf(_("  bumppercent %3d %%\t- minimum savings (threshold) to bump level 1 -> 2\n"),
               conf_bumppercent);
-       printf("  bumpdays %5d\t- minimum days at each level\n",
+       g_printf(_("  bumpdays %5d\t- minimum days at each level\n"),
               getconf_int(CNF_BUMPDAYS));
-       printf("  bumpmult %5.5lg\t- threshold = disk_size * bumppercent * bumpmult**(level-1)\n\n",
+       g_printf(_("  bumpmult %5.5lg\t- threshold = disk_size * bumppercent * bumpmult**(level-1)\n\n"),
               conf_bumpmult);
-       printf("      Bump -> To  Threshold\n");
+       g_printf(_("      Bump -> To  Threshold\n"));
        for(l = 1; l < 9; l++) {
-           printf("\t%d  ->  %d  %7.2lf %%\n", l, l+1, bumppercent);
+           g_printf(_("\t%d  ->  %d  %7.2lf %%\n"), l, l+1, bumppercent);
            bumppercent *= conf_bumpmult;
            if(bumppercent >= 100.000) { bumppercent = 100.0;}
        }
@@ -1246,23 +1503,23 @@ export_db(
     char hostname[MAX_HOSTNAME_LENGTH+1];
     int i;
 
-    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) {
-       error("could not determine host name: %s\n", strerror(errno));
+       error(_("could not determine host name: %s\n"), strerror(errno));
        /*NOTREACHED*/
     }
     hostname[SIZEOF(hostname)-1] = '\0';
-    printf("# Generated by:\n#    host: %s\n#    date: %s",
+    g_printf(_("# Generated by:\n#    host: %s\n#    date: %s"),
           hostname, ctime(&curtime));
 
-    printf("#    command:");
+    g_printf(_("#    command:"));
     for(i = 0; i < argc; i++)
-       printf(" %s", argv[i]);
+       g_printf(_(" %s"), argv[i]);
 
-    printf("\n# This file can be merged back in with \"amadmin import\".\n");
-    printf("# Edit only with care.\n");
+    g_printf(_("\n# This file can be merged back in with \"amadmin import\".\n"));
+    g_printf(_("# Edit only with care.\n"));
 
     if(argc >= 4)
        diskloop(argc, argv, "export", export_one);
@@ -1278,42 +1535,42 @@ export_one(
     int i,l;
 
     if(get_info(dp->host->hostname, dp->name, &info)) {
-       fprintf(stderr, "Warning: no curinfo record for %s:%s\n",
+       g_fprintf(stderr, _("Warning: no curinfo record for %s:%s\n"),
                dp->host->hostname, dp->name);
        return;
     }
-    printf("host: %s\ndisk: %s\n", dp->host->hostname, dp->name);
-    printf("command: %u\n", info.command);
-    printf("last_level: %d\n",info.last_level);
-    printf("consecutive_runs: %d\n",info.consecutive_runs);
-    printf("full-rate:");
-    for(i=0;i<AVG_COUNT;i++) printf(" %lf", info.full.rate[i]);
-    printf("\nfull-comp:");
-    for(i=0;i<AVG_COUNT;i++) printf(" %lf", info.full.comp[i]);
-
-    printf("\nincr-rate:");
-    for(i=0;i<AVG_COUNT;i++) printf(" %lf", info.incr.rate[i]);
-    printf("\nincr-comp:");
-    for(i=0;i<AVG_COUNT;i++) printf(" %lf", info.incr.comp[i]);
-    printf("\n");
+    g_printf(_("host: %s\ndisk: %s\n"), dp->host->hostname, dp->name);
+    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);
+    g_printf(_("full-rate:"));
+    for(i=0;i<AVG_COUNT;i++) g_printf(_(" %lf"), info.full.rate[i]);
+    g_printf(_("\nfull-comp:"));
+    for(i=0;i<AVG_COUNT;i++) g_printf(_(" %lf"), info.full.comp[i]);
+
+    g_printf(_("\nincr-rate:"));
+    for(i=0;i<AVG_COUNT;i++) g_printf(_(" %lf"), info.incr.rate[i]);
+    g_printf(_("\nincr-comp:"));
+    for(i=0;i<AVG_COUNT;i++) g_printf(_(" %lf"), info.incr.comp[i]);
+    g_printf("\n");
     for(l=0;l<DUMP_LEVELS;l++) {
        if(info.inf[l].date < (time_t)0 && info.inf[l].label[0] == '\0') continue;
-       printf("stats: %d " OFF_T_FMT " " OFF_T_FMT " " TIME_T_FMT " " TIME_T_FMT " " OFF_T_FMT " %s\n", l,
-              (OFF_T_FMT_TYPE)info.inf[l].size,
-              (OFF_T_FMT_TYPE)info.inf[l].csize,
-              (TIME_T_FMT_TYPE)info.inf[l].secs,
-              (TIME_T_FMT_TYPE)info.inf[l].date,
-              (OFF_T_FMT_TYPE)info.inf[l].filenum,
+       g_printf(_("stats: %d %lld %lld %jd %jd %lld %s\n"), l,
+              (long long)info.inf[l].size,
+              (long long)info.inf[l].csize,
+              (intmax_t)info.inf[l].secs,
+              (intmax_t)info.inf[l].date,
+              (long long)info.inf[l].filenum,
               info.inf[l].label);
     }
     for(l=0;info.history[l].level > -1;l++) {
-       printf("history: %d " OFF_T_FMT " " OFF_T_FMT " " TIME_T_FMT "\n",
+       g_printf(_("history: %d %lld %lld %jd\n"),
               info.history[l].level,
-              (OFF_T_FMT_TYPE)info.history[l].size,
-              (OFF_T_FMT_TYPE)info.history[l].csize,
-              (TIME_T_FMT_TYPE)info.history[l].date);
+              (long long)info.history[l].size,
+              (long long)info.history[l].csize,
+              (intmax_t)info.history[l].date);
     }
-    printf("//\n");
+    g_printf("//\n");
 }
 
 /* ----------------------------------------------- */
@@ -1343,7 +1600,7 @@ import_db(
     /* process header line */
 
     if((line = agets(stdin)) == NULL) {
-       fprintf(stderr, "%s: empty input.\n", get_pname());
+       g_fprintf(stderr, _("%s: empty input.\n"), get_pname());
        return;
     }
 
@@ -1351,13 +1608,10 @@ import_db(
     ch = *s++;
 
     hdr = "version";
-#define sc "CURINFO Version"
-    if(strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) {
+    if(strncmp_const_skip(s - 1, "CURINFO Version", s, ch) != 0) {
        goto bad_header;
     }
-    s += SIZEOF(sc)-1;
     ch = *s++;
-#undef sc
     skip_whitespace(s, ch);
     if(ch == '\0'
        || sscanf(s - 1, "%d.%d.%d", &vers_maj, &vers_min, &vers_patch) != 3) {
@@ -1385,13 +1639,10 @@ import_db(
 
     hdr = "CONF";
     skip_whitespace(s, ch);                    /* find the org keyword */
-#define sc "CONF"
-    if(ch == '\0' || strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) {
+    if(ch == '\0' || strncmp_const_skip(s - 1, "CONF", s, ch) != 0) {
        goto bad_header;
     }
-    s += SIZEOF(sc)-1;
     ch = *s++;
-#undef sc
 
     hdr = "org";
     skip_whitespace(s, ch);                    /* find the org string */
@@ -1405,13 +1656,13 @@ import_db(
            (vers_min != VERSION_MINOR)? vers_min > VERSION_MINOR :
                                         vers_patch > VERSION_PATCH;
     if(newer)
-       fprintf(stderr,
-            "%s: WARNING: input is from newer Amanda version: %d.%d.%d.\n",
+       g_fprintf(stderr,
+            _("%s: WARNING: input is from newer Amanda version: %d.%d.%d.\n"),
                get_pname(), vers_maj, vers_min, vers_patch);
     /*@end@*/
 
     if(strcmp(org, getconf_str(CNF_ORG)) != 0) {
-       fprintf(stderr, "%s: WARNING: input is from different org: %s\n",
+       g_fprintf(stderr, _("%s: WARNING: input is from different org: %s\n"),
                get_pname(), org);
     }
 
@@ -1425,9 +1676,9 @@ import_db(
  bad_header:
 
     /*@i@*/ amfree(line);
-    fprintf(stderr, "%s: bad CURINFO header line in input: %s.\n",
+    g_fprintf(stderr, _("%s: bad CURINFO header line in input: %s.\n"),
            get_pname(), hdr);
-    fprintf(stderr, "    Was the input in \"amadmin export\" format?\n");
+    g_fprintf(stderr, _("    Was the input in \"amadmin export\" format?\n"));
     return;
 }
 
@@ -1438,19 +1689,14 @@ import_one(void)
     info_t info;
     stats_t onestat;
     int rc, level;
-    time_t onedate;
-    time_t *onedate_p = &onedate;
     char *line = NULL;
     char *s, *fp;
     int ch;
     int nb_history, i;
     char *hostname = NULL;
     char *diskname = NULL;
-    time_t *secs_p;
-
-#if TEXTDB
-    check_dumpuser();
-#endif
+    long long off_t_tmp;
+    long long time_t_tmp;
 
     memset(&info, 0, SIZEOF(info_t));
 
@@ -1467,11 +1713,7 @@ import_one(void)
     ch = *s++;
 
     skip_whitespace(s, ch);
-#define sc "host:"
-    if(ch == '\0' || strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) goto parse_err;
-    s += SIZEOF(sc)-1;
-    ch = s[-1];
-#undef sc
+    if(ch == '\0' || strncmp_const_skip(s - 1, "host:", s, ch) != 0) goto parse_err;
     skip_whitespace(s, ch);
     if(ch == '\0') goto parse_err;
     fp = s-1;
@@ -1488,11 +1730,7 @@ import_one(void)
       ch = *s++;
       skip_whitespace(s, ch);
     }
-#define sc "disk:"
-    if(strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) goto parse_err;
-    s += SIZEOF(sc)-1;
-    ch = s[-1];
-#undef sc
+    if(strncmp_const_skip(s - 1, "disk:", s, ch) != 0) goto parse_err;
     skip_whitespace(s, ch);
     if(ch == '\0') goto parse_err;
     fp = s-1;
@@ -1549,11 +1787,11 @@ import_one(void)
     while(1) {
        amfree(line);
        if((line = impget_line()) == NULL) goto shortfile_err;
-       if(strncmp(line, "//", 2) == 0) {
+       if(strncmp_const(line, "//") == 0) {
            /* end of record */
            break;
        }
-       if(strncmp(line, "history:", 8) == 0) {
+       if(strncmp_const(line, "history:") == 0) {
            /* end of record */
            break;
        }
@@ -1563,13 +1801,9 @@ import_one(void)
        ch = *s++;
 
        skip_whitespace(s, ch);
-#define sc "stats:"
-       if(ch == '\0' || strncmp(s - 1, sc, SIZEOF(sc)-1) != 0) {
+       if(ch == '\0' || strncmp_const_skip(s - 1, "stats:", s, ch) != 0) {
            goto parse_err;
        }
-       s += SIZEOF(sc)-1;
-       ch = s[-1];
-#undef sc
 
        skip_whitespace(s, ch);
        if(ch == '\0' || sscanf(s - 1, "%d", &level) != 1) {
@@ -1578,39 +1812,40 @@ import_one(void)
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf(s - 1, OFF_T_FMT,
-                               (OFF_T_FMT_TYPE *)&onestat.size) != 1) {
+       if(ch == '\0' || sscanf(s - 1, "%lld", &off_t_tmp) != 1) {
            goto parse_err;
        }
+       onestat.size = (off_t)off_t_tmp;
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf(s - 1, OFF_T_FMT,
-                               (OFF_T_FMT_TYPE *)&onestat.csize) != 1) {
+       if(ch == '\0' || sscanf(s - 1, "%lld", &off_t_tmp) != 1) {
            goto parse_err;
        }
+       onestat.csize = (off_t)off_t_tmp;
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
-        secs_p = &onestat.secs;
-       if(ch == '\0' || sscanf(s - 1, TIME_T_FMT,
-                               (TIME_T_FMT_TYPE *)secs_p) != 1) {
+       if(ch == '\0' || sscanf(s - 1, "%lld", &time_t_tmp) != 1) {
            goto parse_err;
        }
+        onestat.secs = (time_t)time_t_tmp;
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf(s - 1, TIME_T_FMT,
-                               (TIME_T_FMT_TYPE *)onedate_p) != 1) {
+       if(ch == '\0' || sscanf(s - 1, "%lld", &time_t_tmp) != 1) {
            goto parse_err;
        }
+       /* time_t not guarranteed to be long */
+       /*@i1@*/ onestat.date = (time_t)time_t_tmp;
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
        if(ch != '\0') {
-           if(sscanf(s - 1, OFF_T_FMT, (OFF_T_FMT_TYPE *)&onestat.filenum) != 1) {
+           if(sscanf(s - 1, "%lld", &off_t_tmp) != 1) {
                goto parse_err;
            }
+           onestat.filenum = (off_t)off_t_tmp;
            skip_integer(s, ch);
 
            skip_whitespace(s, ch);
@@ -1624,8 +1859,6 @@ import_one(void)
            }
        }
 
-       /* time_t not guarranteed to be long */
-       /*@i1@*/ onestat.date = onedate;
        if(level < 0 || level > 9) goto parse_err;
 
        info.inf[level] = onestat;
@@ -1636,8 +1869,6 @@ import_one(void)
     }
     while(1) {
        history_t onehistory;
-       time_t date;
-        time_t *date_p = &date;
 
        if(line[0] == '/' && line[1] == '/') {
            info.history[nb_history].level = -2;
@@ -1647,13 +1878,10 @@ import_one(void)
        memset(&onehistory, 0, SIZEOF(onehistory));
        s = line;
        ch = *s++;
-#define sc "history:"
-       if(strncmp(line, sc, SIZEOF(sc)-1) != 0) {
+       if(strncmp_const_skip(line, "history:", s, ch) != 0) {
            break;
        }
-       s += SIZEOF(sc)-1;
-       ch = s[-1];
-#undef sc
+
        skip_whitespace(s, ch);
        if(ch == '\0' || sscanf((s - 1), "%d", &onehistory.level) != 1) {
            break;
@@ -1661,26 +1889,26 @@ import_one(void)
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf((s - 1), OFF_T_FMT,
-                               (OFF_T_FMT_TYPE *)&onehistory.size) != 1) {
+       if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) {
            break;
        }
+       onehistory.size = (off_t)off_t_tmp;
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
-       if(ch == '\0' || sscanf((s - 1), OFF_T_FMT,
-                               (OFF_T_FMT_TYPE *)&onehistory.csize) != 1) {
+       if(ch == '\0' || sscanf((s - 1), "%lld", &off_t_tmp) != 1) {
            break;
        }
+       onehistory.csize = (off_t)off_t_tmp;
        skip_integer(s, ch);
 
        skip_whitespace(s, ch);
-       if((ch == '\0') || (sscanf((s - 1), TIME_T_FMT,
-                               (TIME_T_FMT_TYPE *)date_p) != 1)) {
+       if((ch == '\0') || sscanf((s - 1), "%lld", &time_t_tmp) != 1) {
            break;
        }
+       /* time_t not guarranteed to be long */
+       /*@i1@*/ onehistory.date = (time_t)time_t_tmp;
        skip_integer(s, ch);
-       /*@i1@*/onehistory.date = date; /* time_t not guarranteed to be long */
 
        info.history[nb_history++] = onehistory;
        amfree(line);
@@ -1691,7 +1919,7 @@ import_one(void)
     /* got a full record, now write it out to the database */
 
     if(put_info(hostname, diskname, &info)) {
-       fprintf(stderr, "%s: error writing record for %s:%s\n",
+       g_fprintf(stderr, _("%s: error writing record for %s:%s\n"),
                get_pname(), hostname, diskname);
     }
     amfree(hostname);
@@ -1702,14 +1930,14 @@ import_one(void)
     /*@i@*/ amfree(line);
     amfree(hostname);
     amfree(diskname);
-    fprintf(stderr, "%s: parse error reading import record.\n", get_pname());
+    g_fprintf(stderr, _("%s: parse error reading import record.\n"), get_pname());
     return 0;
 
  shortfile_err:
     /*@i@*/ amfree(line);
     amfree(hostname);
     amfree(diskname);
-    fprintf(stderr, "%s: short file reading import record.\n", get_pname());
+    g_fprintf(stderr, _("%s: short file reading import record.\n"), get_pname());
     return 0;
 }
 
@@ -1735,7 +1963,7 @@ impget_line(void)
        /* otherwise, a blank line, so keep going */
     }
     if(ferror(stdin)) {
-       fprintf(stderr, "%s: reading stdin: %s\n",
+       g_fprintf(stderr, _("%s: reading stdin: %s\n"),
                get_pname(), strerror(errno));
     }
     return NULL;
@@ -1748,175 +1976,174 @@ disklist_one(
     disk_t *   dp)
 {
     am_host_t *hp;
-    interface_t *ip;
+    netif_t *ip;
     sle_t *excl;
 
     hp = dp->host;
     ip = hp->netif;
 
-    printf("line %d:\n", dp->line);
+    g_printf("line %d:\n", dp->line);
 
-    printf("    host %s:\n", hp->hostname);
-    printf("        interface %s\n",
-          ip->name[0] ? ip->name : "default");
-    printf("    disk %s:\n", dp->name);
-    if(dp->device) printf("        device %s\n", dp->device);
+    g_printf("    host %s:\n", hp->hostname);
+    g_printf("        interface %s\n",
+          interface_name(ip->config)[0] ? interface_name(ip->config) : "default");
+    g_printf("    disk %s:\n", dp->name);
+    if(dp->device) g_printf("        device %s\n", dp->device);
 
-    printf("        program \"%s\"\n", dp->program);
+    g_printf("        program \"%s\"\n", dp->program);
     if(dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
-       printf("        exclude file");
+       g_printf("        exclude file");
        for(excl = dp->exclude_file->first; excl != NULL; excl = excl->next) {
-           printf(" \"%s\"", excl->name);
+           g_printf(" \"%s\"", excl->name);
        }
-       printf("\n");
+       g_printf("\n");
     }
     if(dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) {
-       printf("        exclude list");
-       if(dp->exclude_optional) printf(" optional");
+       g_printf("        exclude list");
+       if(dp->exclude_optional) g_printf(" optional");
        for(excl = dp->exclude_list->first; excl != NULL; excl = excl->next) {
-           printf(" \"%s\"", excl->name);
+           g_printf(" \"%s\"", excl->name);
        }
-       printf("\n");
+       g_printf("\n");
     }
     if(dp->include_file != NULL && dp->include_file->nb_element > 0) {
-       printf("        include file");
+       g_printf("        include file");
        for(excl = dp->include_file->first; excl != NULL; excl = excl->next) {
-           printf(" \"%s\"", excl->name);
+           g_printf(" \"%s\"", excl->name);
        }
-       printf("\n");
+       g_printf("\n");
     }
     if(dp->include_list != NULL && dp->include_list->nb_element > 0) {
-       printf("        include list");
-       if(dp->include_optional) printf(" optional");
+       g_printf("        include list");
+       if(dp->include_optional) g_printf(" optional");
        for(excl = dp->include_list->first; excl != NULL; excl = excl->next) {
-           printf(" \"%s\"", excl->name);
+           g_printf(" \"%s\"", excl->name);
        }
-       printf("\n");
+       g_printf("\n");
     }
-    printf("        priority %d\n", dp->priority);
-    printf("        dumpcycle %d\n", dp->dumpcycle);
-    printf("        maxdumps %d\n", dp->maxdumps);
-    printf("        maxpromoteday %d\n", dp->maxpromoteday);
+    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) {
-       printf("        bumppercent %d\n", dp->bumppercent);
+       g_printf("        bumppercent %d\n", dp->bumppercent);
     }
     else {
-       printf("        bumpsize " OFF_T_FMT "\n",
-               (OFF_T_FMT_TYPE)dp->bumpsize);
+       g_printf("        bumpsize %lld\n",
+               (long long)dp->bumpsize);
     }
-    printf("        bumpdays %d\n", dp->bumpdays);
-    printf("        bumpmult %lf\n", dp->bumpmult);
+    g_printf("        bumpdays %d\n", dp->bumpdays);
+    g_printf("        bumpmult %lf\n", dp->bumpmult);
 
-    printf("        strategy ");
+    g_printf("        strategy ");
     switch(dp->strategy) {
     case DS_SKIP:
-       printf("SKIP\n");
+       g_printf("SKIP\n");
        break;
     case DS_STANDARD:
-       printf("STANDARD\n");
+       g_printf("STANDARD\n");
        break;
     case DS_NOFULL:
-       printf("NOFULL\n");
+       g_printf("NOFULL\n");
        break;
     case DS_NOINC:
-       printf("NOINC\n");
+       g_printf("NOINC\n");
        break;
     case DS_HANOI:
-       printf("HANOI\n");
+       g_printf("HANOI\n");
        break;
     case DS_INCRONLY:
-       printf("INCRONLY\n");
+       g_printf("INCRONLY\n");
        break;
     }
-
-    printf("        estimate ");
+    g_printf("        ignore %s\n", (dp->ignore? "YES" : "NO"));
+    g_printf("        estimate ");
     switch(dp->estimate) {
     case ES_CLIENT:
-       printf("CLIENT\n");
+       g_printf("CLIENT\n");
        break;
     case ES_SERVER:
-       printf("SERVER\n");
+       g_printf("SERVER\n");
        break;
     case ES_CALCSIZE:
-       printf("CALCSIZE\n");
+       g_printf("CALCSIZE\n");
        break;
     }
 
-    printf("        compress ");
+    g_printf("        compress ");
     switch(dp->compress) {
     case COMP_NONE:
-       printf("NONE\n");
+       g_printf("NONE\n");
        break;
     case COMP_FAST:
-       printf("CLIENT FAST\n");
+       g_printf("CLIENT FAST\n");
        break;
     case COMP_BEST:
-       printf("CLIENT BEST\n");
+       g_printf("CLIENT BEST\n");
        break;
-    case COMP_SERV_FAST:
-       printf("SERVER FAST\n");
+    case COMP_SERVER_FAST:
+       g_printf("SERVER FAST\n");
        break;
-    case COMP_SERV_BEST:
-       printf("SERVER BEST\n");
+    case COMP_SERVER_BEST:
+       g_printf("SERVER BEST\n");
        break;
     }
     if(dp->compress != COMP_NONE) {
-       printf("        comprate %.2lf %.2lf\n",
+       g_printf("        comprate %.2lf %.2lf\n",
               dp->comprate[0], dp->comprate[1]);
     }
 
-    printf("        encrypt ");
+    g_printf("        encrypt ");
     switch(dp->encrypt) {
     case ENCRYPT_NONE:
-       printf("NONE\n");
+       g_printf("NONE\n");
        break;
     case ENCRYPT_CUST:
-       printf("CLIENT\n");
+       g_printf("CLIENT\n");
        break;
     case ENCRYPT_SERV_CUST:
-       printf("SERVER\n");
+       g_printf("SERVER\n");
        break;
     }
 
-    printf("        auth %s\n", dp->security_driver);
-    printf("        kencrypt %s\n", (dp->kencrypt? "YES" : "NO"));
-    printf("        amandad_path %s\n", dp->amandad_path);
-    printf("        client_username %s\n", dp->client_username);
-    printf("        ssh_keys %s\n", dp->ssh_keys);
+    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);
 
-    printf("        holdingdisk ");
+    g_printf("        holdingdisk ");
     switch(dp->to_holdingdisk) {
     case HOLD_NEVER:
-       printf("NEVER\n");
+       g_printf("NEVER\n");
        break;
     case HOLD_AUTO:
-       printf("AUTO\n");
+       g_printf("AUTO\n");
        break;
     case HOLD_REQUIRED:
-       printf("REQUIRED\n");
+       g_printf("REQUIRED\n");
        break;
     }
 
-    printf("        record %s\n", (dp->record? "YES" : "NO"));
-    printf("        index %s\n", (dp->index? "YES" : "NO"));
-    printf("        starttime %04d\n", (int)dp->starttime);
-   
+    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) {
-       printf("        tape_splitsize " OFF_T_FMT "\n",
-              (OFF_T_FMT_TYPE)dp->tape_splitsize);
+       g_printf("        tape_splitsize %lld\n",
+              (long long)dp->tape_splitsize);
     }
     if(dp->split_diskbuffer) {
-       printf("        split_diskbuffer %s\n", dp->split_diskbuffer);
+       g_printf("        split_diskbuffer %s\n", dp->split_diskbuffer);
     }
     if(dp->fallback_splitsize > (off_t)0) {
-       printf("        fallback_splitsize " OFF_T_FMT "Mb\n",
-              (OFF_T_FMT_TYPE)(dp->fallback_splitsize / (off_t)1024));
+       g_printf("        fallback_splitsize %lldMb\n",
+              (long long)(dp->fallback_splitsize / (off_t)1024));
     }
-    printf("        skip-incr %s\n", (dp->skip_incr? "YES" : "NO"));
-    printf("        skip-full %s\n", (dp->skip_full? "YES" : "NO"));
-    printf("        spindle %d\n", dp->spindle);
+    g_printf("        skip-incr %s\n", (dp->skip_incr? "YES" : "NO"));
+    g_printf("        skip-full %s\n", (dp->skip_full? "YES" : "NO"));
+    g_printf("        spindle %d\n", dp->spindle);
 
-    printf("\n");
+    g_printf("\n");
 }
 
 void
@@ -1944,16 +2171,14 @@ show_version(
     (void)argv;        /* Quiet unused parameter warning */
 
     for(i = 0; version_info[i] != NULL; i++)
-       printf("%s", version_info[i]);
+       g_printf("%s", version_info[i]);
 }
 
 
 void show_config(
-    int argc,
-    char **argv)
+    int argc G_GNUC_UNUSED,
+    char **argv G_GNUC_UNUSED)
 {
-    argc = argc;
-    argv = argv;
-    dump_configuration(conffile);
+    dump_configuration();
 }