Imported Upstream version 2.6.0
[debian/amanda] / server-src / amcheck.c
index 4498cd7a6bf77a04830c3ae677fe3817dcb6f11c..fdbd8cfb74f3729e52106196edc1223b03c91fbd 100644 (file)
 #include "amanda.h"
 #include "util.h"
 #include "conffile.h"
-#include "statfs.h"
+#include "columnar.h"
+#include "fsusage.h"
 #include "diskfile.h"
 #include "tapefile.h"
-#include "tapeio.h"
 #include "changer.h"
 #include "packet.h"
 #include "security.h"
@@ -47,6 +47,9 @@
 #include "server_util.h"
 #include "pipespawn.h"
 #include "amfeatures.h"
+#include "device.h"
+#include "property.h"
+#include "timestamp.h"
 
 #define BUFFER_SIZE    32768
 
@@ -63,18 +66,16 @@ void usage(void);
 pid_t start_client_checks(int fd);
 pid_t start_server_check(int fd, int do_localchk, int do_tapechk);
 int main(int argc, char **argv);
+int check_tapefile(FILE *outf, char *tapefile);
 int test_server_pgm(FILE *outf, char *dir, char *pgm, int suid, uid_t dumpuid);
 
 void
 usage(void)
 {
-    error("Usage: amcheck%s [-am] [-w] [-sclt] [-M <address>] <conf> [host [disk]* ]* [-o configoption]*", versionsuffix());
+    error(_("Usage: amcheck%s [-am] [-w] [-sclt] [-M <address>] <conf> [host [disk]* ]* [-o configoption]*"), versionsuffix());
     /*NOTREACHED*/
 }
 
-static unsigned long malloc_hist_1, malloc_size_1;
-static unsigned long malloc_hist_2, malloc_size_2;
-
 static am_feature_t *our_features = NULL;
 static char *our_feature_string = NULL;
 static char *displayunit;
@@ -102,19 +103,30 @@ main(
     int mailout;
     int alwaysmail;
     char *tempfname = NULL;
-    char *conffile;
     char *conf_diskfile;
     char *dumpuser;
     struct passwd *pw;
     uid_t uid_me;
-    int    new_argc,   my_argc;
-    char **new_argv, **my_argv;
     char *errstr;
+    config_overwrites_t *cfg_ovr;
+
+    /*
+     * 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("amcheck");
+    /* drop root privileges */
+    if (!set_root_privs(0)) {
+       error(_("amcheck must be run setuid root"));
+    }
 
     /* Don't die when child closes pipe */
     signal(SIGPIPE, SIG_IGN);
@@ -122,18 +134,14 @@ main(
     dbopen(DBG_SUBDIR_SERVER);
 
     memset(buffer, 0, sizeof(buffer));
-    malloc_size_1 = malloc_inuse(&malloc_hist_1);
 
-    snprintf(pid_str, SIZEOF(pid_str), "%ld", (long)getpid());
+    g_snprintf(pid_str, SIZEOF(pid_str), "%ld", (long)getpid());
 
     erroutput_type = ERR_INTERACTIVE;
 
     our_features = am_init_feature_set();
     our_feature_string = am_feature_to_string(our_features);
 
-    if(geteuid() == 0) {
-       seteuid(getuid());
-    }
     uid_me = getuid();
 
     alwaysmail = mailout = overwrite = 0;
@@ -141,17 +149,14 @@ main(
     server_probs = client_probs = 0;
     tempfd = mainfd = -1;
 
-    parse_conf(argc, argv, &new_argc, &new_argv);
-    my_argc = new_argc;
-    my_argv = new_argv;
-
     /* process arguments */
 
-    while((opt = getopt(my_argc, my_argv, "M:mawsclt")) != EOF) {
+    cfg_ovr = new_config_overwrites(argc/2);
+    while((opt = getopt(argc, argv, "M:mawsclto:")) != EOF) {
        switch(opt) {
        case 'M':       mailto=stralloc(optarg);
                        if(!validate_mailto(mailto)){
-                          printf("Invalid characters in mail address\n");
+                          g_printf(_("Invalid characters in mail address\n"));
                           exit(1);
                        }
                        /*FALLTHROUGH*/
@@ -159,7 +164,8 @@ main(
 #ifdef MAILER
                        mailout = 1;
 #else
-                       printf("You can't use -%c because configure didn't find a mailer.\n",
+                       g_printf(_("You can't use -%c because configure didn't "
+                                "find a mailer./usr/bin/mail not found\n"),
                                opt);
                        exit(1);
 #endif
@@ -169,7 +175,8 @@ main(
                        mailout = 1;
                        alwaysmail = 1;
 #else
-                       printf("You can't use -%c because configure didn't find a mailer.\n",
+                       g_printf(_("You can't use -%c because configure didn't "
+                                "find a mailer./usr/bin/mail not found\n"),
                                opt);
                        exit(1);
 #endif
@@ -182,6 +189,8 @@ main(
                        break;
        case 'w':       overwrite = 1;
                        break;
+       case 'o':       add_config_overwrite_opt(cfg_ovr, optarg);
+                       break;
        case 't':       do_tapechk = 1;
                        break;
        case '?':
@@ -189,8 +198,8 @@ main(
            usage();
        }
     }
-    my_argc -= optind, my_argv += optind;
-    if(my_argc < 1) usage();
+    argc -= optind, argv += optind;
+    if(argc < 1) usage();
 
 
     if ((do_localchk | do_clientchk | do_tapechk) == 0) {
@@ -201,27 +210,20 @@ main(
     if(overwrite)
        do_tapechk = 1;
 
-    config_name = stralloc(*my_argv);
-
-    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[0]);
+    apply_config_overwrites(cfg_ovr);
     dbrename(config_name, DBG_SUBDIR_SERVER);
 
-    report_bad_conf_arg();
-
-    amfree(conffile);
     if(mailout && !mailto && 
        (getconf_seen(CNF_MAILTO)==0 || strlen(getconf_str(CNF_MAILTO)) == 0)) {
-       printf("\nNo mail address configured in  amanda.conf\n");
+       g_printf(_("\nWARNING:No mail address configured in  amanda.conf.\n"));
+       g_printf(_("To receive dump results by email configure the "
+                "\"mailto\" parameter in amanda.conf\n"));
         if(alwaysmail)        
-               printf("When using -a option please specify -Maddress also\n\n"); 
+               g_printf(_("When using -a option please specify -Maddress also\n\n")); 
        else
-               printf("Use -Maddress instead of -m\n\n"); 
+               g_printf(_("Use -Maddress instead of -m\n\n")); 
        exit(1);
     }
     if(mailout && !mailto)
@@ -229,58 +231,59 @@ main(
        if(getconf_seen(CNF_MAILTO) && 
           strlen(getconf_str(CNF_MAILTO)) > 0) {
           if(!validate_mailto(getconf_str(CNF_MAILTO))){
-               printf("\nMail address in amanda.conf has invalid characters"); 
-               printf("\nNo email will be sent\n"); 
+               g_printf(_("\nMail address in amanda.conf has invalid characters")); 
+               g_printf(_("\nNo email will be sent\n")); 
                 mailout = 0;
           }
        }
        else {
-         printf("\nNo mail address configured in  amanda.conf\n");
+         g_printf(_("\nNo mail address configured in  amanda.conf\n"));
           if(alwaysmail)        
-               printf("When using -a option please specify -Maddress also\n\n"); 
+               g_printf(_("When using -a option please specify -Maddress also\n\n")); 
          else
-               printf("Use -Maddress instead of -m\n\n"); 
+               g_printf(_("Use -Maddress instead of -m\n\n")); 
          exit(1);
       }
     }
 
     conf_ctimeout = (time_t)getconf_int(CNF_CTIMEOUT);
 
-    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, &origq) < 0) {
-       error("could not load disklist %s", conf_diskfile);
+       error(_("could not load disklist %s. Make sure it exists and has correct permissions"), conf_diskfile);
        /*NOTREACHED*/
     }
-    errstr = match_disklist(&origq, my_argc-1, my_argv+1);
+    errstr = match_disklist(&origq, argc-1, argv+1);
     if (errstr) {
-       printf("%s",errstr);
+       g_printf(_("%s"),errstr);
        amfree(errstr);
     }
     amfree(conf_diskfile);
 
     /*
-     * Make sure we are running as the dump user.
+     * Make sure we are running as the dump user.  Don't use
+     * check_running_as(..) here, because we want to produce more
+     * verbose error messages.
      */
     dumpuser = getconf_str(CNF_DUMPUSER);
     if ((pw = getpwnam(dumpuser)) == NULL) {
-       error("cannot look up dump user \"%s\"", dumpuser);
+       error(_("amanda.conf has dump user configured to \"%s\", but that user does not exist."), dumpuser);
        /*NOTREACHED*/
     }
     uid_dumpuser = pw->pw_uid;
     if ((pw = getpwuid(uid_me)) == NULL) {
-       error("cannot look up my own uid (%ld)", (long)uid_me);
+       error(_("cannot get username for running user, uid %ld is not in your user database."),
+           (long)uid_me);
        /*NOTREACHED*/
     }
+#ifdef CHECK_USERID
     if (uid_me != uid_dumpuser) {
-       error("running as user \"%s\" instead of \"%s\"",
-             pw->pw_name, dumpuser);
+       error(_("running as user \"%s\" instead of \"%s\".\n"
+               "Change user to \"%s\" or change dump user to \"%s\" in amanda.conf"),
+             pw->pw_name, dumpuser, dumpuser, pw->pw_name);
         /*NOTREACHED*/
     }
+#endif
 
     displayunit = getconf_str(CNF_DISPLAYUNIT);
     unitdivisor = getconf_unit_divisor();
@@ -297,7 +300,7 @@ main(
        /* we need the temp file */
        tempfname = vstralloc(AMANDA_TMPDIR, "/amcheck.temp.", pid_str, NULL);
        if((tempfd = open(tempfname, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) {
-           error("could not open %s: %s", tempfname, strerror(errno));
+           error(_("could not open temporary amcheck output file %s: %s. Check permissions"), tempfname, strerror(errno));
            /*NOTREACHED*/
        }
        unlink(tempfname);                      /* so it goes away on close */
@@ -308,7 +311,7 @@ main(
        /* the main fd is a file too */
        mainfname = vstralloc(AMANDA_TMPDIR, "/amcheck.main.", pid_str, NULL);
        if((mainfd = open(mainfname, O_RDWR|O_CREAT|O_TRUNC, 0600)) == -1) {
-           error("could not open %s: %s", mainfname, strerror(errno));
+           error(_("could not open amcheck server output file %s: %s. Check permissions"), mainfname, strerror(errno));
            /*NOTREACHED*/
        }
        unlink(mainfname);                      /* so it goes away on close */
@@ -346,14 +349,11 @@ main(
            server_probs = WIFSIGNALED(retstat) || WEXITSTATUS(retstat);
            serverchk_pid = 0;
        } else {
-           char number[NUM_STR_SIZE];
            char *wait_msg = NULL;
 
-           snprintf(number, SIZEOF(number), "%ld", (long)pid);
-           wait_msg = vstralloc("parent: reaped bogus pid ", number, "\n",
-                                NULL);
+           wait_msg = vstrallocf(_("parent: reaped bogus pid %ld\n"), (long)pid);
            if (fullwrite(mainfd, wait_msg, strlen(wait_msg)) < 0) {
-               error("write main file: %s", strerror(errno));
+               error(_("write main file: %s"), strerror(errno));
                /*NOTREACHED*/
            }
            amfree(wait_msg);
@@ -364,43 +364,33 @@ main(
 
     if(do_clientchk && (do_localchk || do_tapechk)) {
        if(lseek(tempfd, (off_t)0, 0) == (off_t)-1) {
-           error("seek temp file: %s", strerror(errno));
+           error(_("seek temp file: %s"), strerror(errno));
            /*NOTREACHED*/
        }
 
        while((size = fullread(tempfd, buffer, SIZEOF(buffer))) > 0) {
            if (fullwrite(mainfd, buffer, (size_t)size) < 0) {
-               error("write main file: %s", strerror(errno));
+               error(_("write main file: %s"), strerror(errno));
                /*NOTREACHED*/
            }
        }
        if(size < 0) {
-           error("read temp file: %s", strerror(errno));
+           error(_("read temp file: %s"), strerror(errno));
            /*NOTREACHED*/
        }
        aclose(tempfd);
     }
 
-    version_string = vstralloc("\n",
-                              "(brought to you by Amanda ", version(), ")\n",
-                              NULL);
+    version_string = vstrallocf(_("\n(brought to you by Amanda %s)\n"), version());
     if (fullwrite(mainfd, version_string, strlen(version_string)) < 0) {
-       error("write main file: %s", strerror(errno));
+       error(_("write main file: %s"), strerror(errno));
        /*NOTREACHED*/
     }
     amfree(version_string);
-    amfree(config_dir);
-    amfree(config_name);
     amfree(our_feature_string);
     am_release_feature_set(our_features);
     our_features = NULL;
 
-    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);
-    }
-
     /* send mail if requested, but only if there were problems */
 #ifdef MAILER
 
@@ -419,22 +409,20 @@ main(
        char *err = NULL;
        char *extra_info = NULL;
        char *line = NULL;
-       int ret;
        int rc;
-       int sig;
-       char number[NUM_STR_SIZE];
 
        fflush(stdout);
        if(lseek(mainfd, (off_t)0, SEEK_SET) == (off_t)-1) {
-           error("lseek main file: %s", strerror(errno));
+           error(_("lseek main file: %s"), strerror(errno));
            /*NOTREACHED*/
        }
        if(alwaysmail && !(server_probs || client_probs)) {
-           subject = stralloc2(getconf_str(CNF_ORG),
-                           " AMCHECK REPORT: NO PROBLEMS FOUND");
+           subject = vstrallocf(_("%s AMCHECK REPORT: NO PROBLEMS FOUND"),
+                       getconf_str(CNF_ORG));
        } else {
-           subject = stralloc2(getconf_str(CNF_ORG),
-                           " AMANDA PROBLEM: FIX BEFORE RUN, IF POSSIBLE");
+           subject = vstrallocf(
+                       _("%s AMANDA PROBLEM: FIX BEFORE RUN, IF POSSIBLE"),
+                       getconf_str(CNF_ORG));
        }
        /*
         * Variable arg lists are hard to deal with when we do not know
@@ -475,13 +463,13 @@ main(
        while((r = fullread(mainfd, buffer, SIZEOF(buffer))) > 0) {
            if((w = fullwrite(mailfd, buffer, (size_t)r)) != (ssize_t)r) {
                if(w < 0 && errno == EPIPE) {
-                   strappend(extra_info, "EPIPE writing to mail process\n");
+                   strappend(extra_info, _("EPIPE writing to mail process\n"));
                    break;
                } else if(w < 0) {
-                   error("mailfd write: %s", strerror(errno));
+                   error(_("mailfd write: %s"), strerror(errno));
                    /*NOTREACHED*/
                } else {
-                   error("mailfd write: wrote " SSIZE_T_FMT " instead of " SIZE_T_FMT, w, r);
+                   error(_("mailfd write: wrote %zd instead of %zd"), w, r);
                    /*NOTREACHED*/
                }
            }
@@ -489,7 +477,7 @@ main(
        aclose(mailfd);
        ferr = fdopen(errfd, "r");
        if (!ferr) {
-           error("Can't fdopen: %s", strerror(errno));
+           error(_("Can't fdopen: %s"), strerror(errno));
            /*NOTREACHED*/
        }
        for(; (line = agets(ferr)) != NULL; free(line)) {
@@ -502,22 +490,12 @@ main(
        errfd = -1;
        rc = 0;
        while (wait(&retstat) != -1) {
-           if (WIFSIGNALED(retstat)) {
-                   ret = 0;
-                   rc = sig = WTERMSIG(retstat);
-           } else {
-                   sig = 0;
-                   rc = ret = WEXITSTATUS(retstat);
-           }
-           if (rc != 0) {
-                   if (ret == 0) {
-                       strappend(err, "got signal ");
-                       ret = sig;
-                   } else {
-                       strappend(err, "returned ");
-                   }
-                   snprintf(number, SIZEOF(number), "%d", ret);
-                   strappend(err, number);
+           if (!WIFEXITED(retstat) || WEXITSTATUS(retstat) != 0) {
+               char *mailer_error = str_exit_status("mailer", retstat);
+               strappend(err, mailer_error);
+               amfree(mailer_error);
+
+               rc = 1;
            }
        }
        if (rc != 0) {
@@ -525,27 +503,49 @@ main(
                fputs(extra_info, stderr);
                amfree(extra_info);
            }
-           error("error running mailer %s: %s", MAILER, err);
+           error(_("error running mailer %s: %s"), MAILER, err?err:"(unknown)");
            /*NOTREACHED*/
        }
     }
 #endif
-    free_new_argv(new_argc, new_argv);
-    free_server_config();
-
     dbclose();
     return (server_probs || client_probs);
 }
 
 /* --------------------------------------------------- */
 
-int nslots, backwards, found, got_match, tapedays;
-char *datestamp;
-char *first_match_label = NULL, *first_match = NULL, *found_device = NULL;
-char *label;
-char *searchlabel, *labelstr;
-tape_t *tp;
-FILE *errf = NULL;
+static char *datestamp;
+static FILE *errf = NULL;
+
+int check_tapefile(
+    FILE *outf,
+    char *tapefile)
+{
+    struct stat statbuf;
+    char *quoted;
+    int tapebad = 0;
+
+    if (stat(tapefile, &statbuf) == 0) {
+       if (!S_ISREG(statbuf.st_mode)) {
+           quoted = quote_string(tapefile);
+           g_fprintf(outf, _("ERROR: tapelist %s: should be a regular file.\n"),
+                   quoted);
+           tapebad = 1;
+           amfree(quoted);
+       } else if (access(tapefile, F_OK) != 0) {
+           quoted = quote_string(tapefile);
+           g_fprintf(outf, _("ERROR: can't access tapelist %s\n"), quoted);
+           tapebad = 1;
+           amfree(quoted);
+       } else if (access(tapefile, W_OK) != 0) {
+           quoted = quote_string(tapefile);
+           g_fprintf(outf, _("ERROR: tapelist %s: not writable\n"), quoted);
+           tapebad = 1;
+           amfree(quoted);
+       }
+    }
+    return tapebad;
+}
 
 int
 test_server_pgm(
@@ -562,76 +562,199 @@ test_server_pgm(
     pgm = vstralloc(dir, "/", pgm, versionsuffix(), NULL);
     quoted = quote_string(pgm);
     if(stat(pgm, &statbuf) == -1) {
-       fprintf(outf, "ERROR: program %s: does not exist\n",
+       g_fprintf(outf, _("ERROR: program %s: does not exist\n"),
                quoted);
        pgmbad = 1;
     } else if (!S_ISREG(statbuf.st_mode)) {
-       fprintf(outf, "ERROR: program %s: not a file\n",
+       g_fprintf(outf, _("ERROR: program %s: not a file\n"),
                quoted);
        pgmbad = 1;
     } else if (access(pgm, X_OK) == -1) {
-       fprintf(outf, "ERROR: program %s: not executable\n",
+       g_fprintf(outf, _("ERROR: program %s: not executable\n"),
                quoted);
        pgmbad = 1;
+#ifndef SINGLE_USERID
     } else if (suid \
               && dumpuid != 0
               && (statbuf.st_uid != 0 || (statbuf.st_mode & 04000) == 0)) {
-       fprintf(outf, "ERROR: program %s: not setuid-root\n",
+       g_fprintf(outf, _("ERROR: program %s: not setuid-root\n"),
                quoted);
        pgmbad = 1;
+#else
+    /* Quiet unused parameter warnings */
+    (void)suid;
+    (void)dumpuid;
+#endif /* SINGLE_USERID */
     }
     amfree(quoted);
     amfree(pgm);
     return pgmbad;
 }
 
+/* check that the tape is a valid amanda tape
+   Returns TRUE if all tests passed; FALSE otherwise. */
+static gboolean test_tape_status(FILE * outf) {
+    int tape_status;
+    Device * device;
+    GValue property_value;
+    char * label = NULL;
+    char * tapename = NULL;
+    ReadLabelStatusFlags label_status;
+
+    bzero(&property_value, sizeof(property_value));
+    
+    tapename = getconf_str(CNF_TAPEDEV);
+    g_return_val_if_fail(tapename != NULL, FALSE);
+
+    device_api_init();
+    
+    if (!getconf_seen(CNF_TPCHANGER) && getconf_int(CNF_RUNTAPES) != 1) {
+        g_fprintf(outf,
+                _("WARNING: if a tape changer is not available, runtapes "
+                  "must be set to 1\n"));
+        g_fprintf(outf, _("Change the value of the \"runtapes\" parameter in " 
+                        "amanda.conf or configure a tape changer\n"));
+    }
+    
+    tape_status = taper_scan(NULL, &label, &datestamp, &tapename, NULL,
+                             FILE_taperscan_output_callback, outf,
+                             NULL, NULL);
+    if (tape_status < 0) {
+        tape_t *exptape = lookup_last_reusable_tape(0);
+        g_fprintf(outf, _("       (expecting "));
+        if(exptape != NULL) g_fprintf(outf, _("tape %s or "), exptape->label);
+        g_fprintf(outf, _("a new tape)\n"));
+        amfree(label);
+        return FALSE;
+    }
+
+    device = device_open(tapename);
+
+    if (device == NULL) {
+        g_fprintf(outf, "ERROR: Could not open tape device.\n");
+        amfree(label);
+        return FALSE;
+    }
+    
+    device_set_startup_properties_from_config(device);
+    label_status = device_read_label(device);
+
+    if (tape_status == 3 && 
+        !(label_status & READ_LABEL_STATUS_VOLUME_UNLABELED)) {
+        if (label_status == READ_LABEL_STATUS_SUCCESS) {
+            g_fprintf(outf, "WARNING: Volume was unlabeled, but now "
+                    "is labeled \"%s\".\n", device->volume_label);
+        }
+    } else if (label_status != READ_LABEL_STATUS_SUCCESS && tape_status != 3) {
+        char * errstr = 
+            g_english_strjoinv_and_free
+                (g_flags_nick_to_strv(label_status &
+                                       (~READ_LABEL_STATUS_VOLUME_UNLABELED),
+                                       READ_LABEL_STATUS_FLAGS_TYPE), "or");
+        g_fprintf(outf, "WARNING: Reading label the second time failed: "
+                "One of %s.\n", errstr);
+        g_free(errstr);
+    } else if (tape_status != 3 &&
+               (device->volume_label == NULL || label == NULL ||
+                strcmp(device->volume_label, label) != 0)) {
+        g_fprintf(outf, "WARNING: Label mismatch on re-read: "
+                "Got %s first, then %s.\n", label, device->volume_label);
+    }
+    
+    /* If we can't get this property, it's not an error. Maybe the device
+     * doesn't support this property, or needs an actual volume to know
+     * for sure. */
+    if (device_property_get(device, PROPERTY_MEDIUM_TYPE, &property_value)) {
+        g_assert(G_VALUE_TYPE(&property_value) == MEDIA_ACCESS_MODE_TYPE);
+        if (g_value_get_enum(&property_value) ==
+            MEDIA_ACCESS_MODE_WRITE_ONLY) {
+            g_fprintf(outf, "WARNING: Media access mode is WRITE_ONLY, "
+                    "dumps will be thrown away.\n");
+        }
+    }
+    
+    if (overwrite) {
+       char *timestamp = get_undef_timestamp();
+        if (!device_start(device, ACCESS_WRITE, label, timestamp)) {
+            if (tape_status == 3) {
+                g_fprintf(outf, "ERROR: Could not label brand new tape.\n");
+            } else {
+                g_fprintf(outf,
+                        "ERROR: tape %s label ok, but is not writable.\n",
+                        label);
+            }
+           amfree(timestamp);
+            amfree(label);
+            g_object_unref(device);
+            return FALSE;
+        } else { /* Write succeeded. */
+            if (tape_status != 3) {
+                g_fprintf(outf, "Tape %s is writable; rewrote label.\n", label);
+            } else {
+                g_fprintf(outf, "Wrote label %s to brand new tape.\n", label);
+            }
+        }
+       amfree(timestamp);
+    } else { /* !overwrite */
+        g_fprintf(outf, "NOTE: skipping tape-writable test\n");
+        if (tape_status == 3) {
+            g_fprintf(outf,
+                    "Found a brand new tape, will label it %s.\n", 
+                    label);
+        } else {
+            g_fprintf(outf, "Tape %s label ok\n", label);
+        }                    
+    }
+    g_object_unref(device);
+    amfree(label);
+    return TRUE;
+}
+
 pid_t
 start_server_check(
     int                fd,
     int                do_localchk,
     int                do_tapechk)
 {
-    char *tapename;
-    generic_fs_stats_t fs;
+    struct fs_usage fsusage;
     FILE *outf = NULL;
     holdingdisk_t *hdp;
-    pid_t pid;
+    pid_t pid G_GNUC_UNUSED;
     int confbad = 0, tapebad = 0, disklow = 0, logbad = 0;
     int userbad = 0, infobad = 0, indexbad = 0, pgmbad = 0;
     int testtape = do_tapechk;
     tapetype_t *tp = NULL;
     char *quoted;
     int res;
-    struct addrinfo *gaires;
-    struct addrinfo hints;
+    intmax_t kb_avail;
 
     switch(pid = fork()) {
     case -1:
-       error("could not fork server check: %s", strerror(errno));
-       /*NOTREACHED*/
-
+       error(_("could not spawn a process for checking the server: %s"), strerror(errno));
+        g_assert_not_reached();
+        
     case 0:
        break;
-
+        
     default:
        return pid;
     }
-
+    
     dup2(fd, 1);
     dup2(fd, 2);
-
+    
     set_pname("amcheck-server");
-
+    
     startclock();
 
     if((outf = fdopen(fd, "w")) == NULL) {
-       error("fdopen %d: %s", fd, strerror(errno));
+       error(_("fdopen %d: %s"), fd, strerror(errno));
        /*NOTREACHED*/
     }
     errf = outf;
 
-    fprintf(outf, "Amanda Tape Server Host Check\n");
-    fprintf(outf, "-----------------------------\n");
+    g_fprintf(outf, _("Amanda Tape Server Host Check\n"));
+    g_fprintf(outf, "-----------------------------\n");
 
     if (do_localchk || testtape) {
         tp = lookup_tapetype(getconf_str(CNF_TAPETYPE));
@@ -646,57 +769,52 @@ start_server_check(
        char *lbl_templ;
 
        ColumnSpec = getconf_str(CNF_COLUMNSPEC);
-       if(SetColumDataFromString(ColumnData, ColumnSpec, &errstr) < 0) {
-           fprintf(outf, "ERROR: %s\n", errstr);
+       if(SetColumnDataFromString(ColumnData, ColumnSpec, &errstr) < 0) {
+           g_fprintf(outf, _("ERROR: %s\n"), errstr);
            amfree(errstr);
            confbad = 1;
        }
        lbl_templ = tapetype_get_lbl_templ(tp);
        if(strcmp(lbl_templ, "") != 0) {
-           if(strchr(lbl_templ, '/') == NULL) {
-               lbl_templ = stralloc2(config_dir, lbl_templ);
-           } else {
-               lbl_templ = stralloc(lbl_templ);
-           }
+           lbl_templ = config_dir_relative(lbl_templ);
            if(access(lbl_templ, R_OK) == -1) {
-               fprintf(outf,
-                       "ERROR: cannot access lbl_templ file %s: %s\n",
+               g_fprintf(outf,
+                       _("ERROR: cannot read label template (lbl-templ) file %s: %s. Check permissions\n"),
                        lbl_templ,
                        strerror(errno));
                confbad = 1;
            }
 #if !defined(LPRCMD)
-           fprintf(outf, "ERROR: lbl_templ set but no LPRCMD defined, you should reconfigure amanda\n       and make sure it find a lpr or lp command.\n");
+           g_fprintf(outf, _("ERROR:lbl-templ  set but no LPRCMD defined. You should reconfigure amanda\n       and make sure it finds a lpr or lp command.\n"));
            confbad = 1;
 #endif
        }
 
-       /* Double-check that 'localhost' resolves properly */
-#ifdef WORKING_IPV6
-       hints.ai_flags = AI_CANONNAME | AI_V4MAPPED | AI_ALL;
-       hints.ai_family = AF_UNSPEC;
-#else
-       hints.ai_flags = AI_CANONNAME;
-       hints.ai_family = AF_INET;
-#endif
-       hints.ai_socktype = 0;
-       hints.ai_protocol = 0;
-       hints.ai_addrlen = 0;
-       hints.ai_addr = NULL;
-       hints.ai_canonname = NULL;
-       hints.ai_next = NULL;
-       res = getaddrinfo("localhost", NULL, &hints, &gaires);
-#ifdef WORKING_IPV6
-       if (res != 0) {
-           hints.ai_flags = AI_CANONNAME;
-           hints.ai_family = AF_UNSPEC;
-           res = getaddrinfo("localhost", NULL, &hints, &gaires);
+       if (getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED) <
+                                getconf_int(CNF_FLUSH_THRESHOLD_DUMPED)) {
+           g_fprintf(outf, _("WARNING: flush_threshold_dumped (%d) must be less than or equal to flush_threshold_scheduled (%d).\n"), 
+                     getconf_int(CNF_FLUSH_THRESHOLD_DUMPED),
+                     getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED));
        }
-#endif
-       if (res != 0) {
-           fprintf(outf, _("ERROR: Cannot resolve `localhost': %s\n"), gai_strerror(res));
+
+       if (getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED) <
+                                getconf_int(CNF_TAPERFLUSH)) {
+           g_fprintf(outf, _("WARNING: taperflush (%d) must be less than or equal to flush_threshold_scheduled (%d).\n"), 
+                     getconf_int(CNF_TAPERFLUSH),
+                     getconf_int(CNF_FLUSH_THRESHOLD_SCHEDULED));
+       }
+
+       if (getconf_int(CNF_TAPERFLUSH) > 0 &&
+           !getconf_boolean(CNF_AUTOFLUSH)) {
+           g_fprintf(outf, _("WARNING: autoflush must be set to 'yes' if taperflush (%d) is greater that 0.\n"),
+                     getconf_int(CNF_TAPERFLUSH));
+       }
+
+       /* Double-check that 'localhost' resolves properly */
+       if ((res = resolve_hostname("localhost", 0, NULL, NULL) != 0)) {
+           g_fprintf(outf, _("ERROR: Cannot resolve `localhost': %s\n"), gai_strerror(res));
+           confbad = 1;
        }
-       if (gaires) freeaddrinfo(gaires);
     }
 
     /*
@@ -706,30 +824,32 @@ start_server_check(
        /* 
         * entreprise version will do planner/dumper suid check
         */
-       if(access(libexecdir, X_OK) == -1) {
-           quoted = quote_string(libexecdir);
-           fprintf(outf, "ERROR: program dir %s: not accessible\n",
+       if(access(amlibexecdir, X_OK) == -1) {
+           quoted = quote_string(amlibexecdir);
+           g_fprintf(outf, _("ERROR: Directory %s containing Amanda tools is not accessible\n."),
                    quoted);
+           g_fprintf(outf, _("Check permissions\n"));
            pgmbad = 1;
            amfree(quoted);
        } else {
-           if(test_server_pgm(outf, libexecdir, "planner", 1, uid_dumpuser))
+           if(test_server_pgm(outf, amlibexecdir, "planner", 1, uid_dumpuser))
                pgmbad = 1;
-           if(test_server_pgm(outf, libexecdir, "dumper", 1, uid_dumpuser))
+           if(test_server_pgm(outf, amlibexecdir, "dumper", 1, uid_dumpuser))
                pgmbad = 1;
-           if(test_server_pgm(outf, libexecdir, "driver", 0, uid_dumpuser))
+           if(test_server_pgm(outf, amlibexecdir, "driver", 0, uid_dumpuser))
                pgmbad = 1;
-           if(test_server_pgm(outf, libexecdir, "taper", 0, uid_dumpuser))
+           if(test_server_pgm(outf, amlibexecdir, "taper", 0, uid_dumpuser))
                pgmbad = 1;
-           if(test_server_pgm(outf, libexecdir, "amtrmidx", 0, uid_dumpuser))
+           if(test_server_pgm(outf, amlibexecdir, "amtrmidx", 0, uid_dumpuser))
                pgmbad = 1;
-           if(test_server_pgm(outf, libexecdir, "amlogroll", 0, uid_dumpuser))
+           if(test_server_pgm(outf, amlibexecdir, "amlogroll", 0, uid_dumpuser))
                pgmbad = 1;
        }
        if(access(sbindir, X_OK) == -1) {
            quoted = quote_string(sbindir);
-           fprintf(outf, "ERROR: program dir %s: not accessible\n",
+           g_fprintf(outf, _("ERROR: Directory %s containing Amanda tools is not accessible\n"),
                    sbindir);
+           g_fprintf(outf, _("Check permissions\n"));
            pgmbad = 1;
            amfree(quoted);
        } else {
@@ -744,8 +864,9 @@ start_server_check(
        }
        if(access(COMPRESS_PATH, X_OK) == -1) {
            quoted = quote_string(COMPRESS_PATH);
-           fprintf(outf, "WARNING: %s is not executable, server-compression and indexing will not work\n",
-                   quoted);
+           g_fprintf(outf, _("WARNING: %s is not executable, server-compression "
+                           "and indexing will not work. \n"),quoted);
+           g_fprintf(outf, _("Check permissions\n"));
            amfree(quoted);
        }
     }
@@ -758,19 +879,15 @@ start_server_check(
      */
 
     if(do_localchk || do_tapechk) {
-       char *conf_tapelist;
        char *tapefile;
+       char *newtapefile;
        char *tape_dir;
        char *lastslash;
        char *holdfile;
+        char * tapename;
        struct stat statbuf;
        
-       conf_tapelist=getconf_str(CNF_TAPELIST);
-       if (*conf_tapelist == '/') {
-           tapefile = stralloc(conf_tapelist);
-       } else {
-           tapefile = stralloc2(config_dir, conf_tapelist);
-       }
+       tapefile = config_dir_relative(getconf_str(CNF_TAPELIST));
        /*
         * XXX There Really Ought to be some error-checking here... dhw
         */
@@ -783,45 +900,49 @@ start_server_check(
        }
        if(access(tape_dir, W_OK) == -1) {
            quoted = quote_string(tape_dir);
-           fprintf(outf, "ERROR: tapelist dir %s: not writable.\n", quoted);
+           g_fprintf(outf, _("ERROR: tapelist dir %s: not writable.\nCheck permissions\n"), 
+                   quoted);
            tapebad = 1;
            amfree(quoted);
        }
        else if(stat(tapefile, &statbuf) == -1) {
            quoted = quote_string(tape_dir);
-           fprintf(outf, "ERROR: tapelist %s (%s), "
-                   "you must create an empty file.\n",
+           g_fprintf(outf, _("ERROR: tapelist %s (%s), "
+                   "you must create an empty file.\n"),
                    quoted, strerror(errno));
            tapebad = 1;
            amfree(quoted);
        }
-       else if(!S_ISREG(statbuf.st_mode)) {
-           quoted = quote_string(tapefile);
-           fprintf(outf, "ERROR: tapelist %s: should be a regular file.\n",
-                   quoted);
-           tapebad = 1;
-           amfree(quoted);
-       }
-       else if(access(tapefile, F_OK) != 0) {
-           quoted = quote_string(tapefile);
-           fprintf(outf, "ERROR: can't access tapelist %s\n", quoted);
-           tapebad = 1;
-           amfree(quoted);
-       } else if(access(tapefile, F_OK) == 0 && access(tapefile, W_OK) != 0) {
-           quoted = quote_string(tapefile);
-           fprintf(outf, "ERROR: tapelist %s: not writable\n", quoted);
-           tapebad = 1;
-           amfree(quoted);
-       } else if(read_tapelist(tapefile)) {
-           quoted = quote_string(tapefile);
-           fprintf(outf, "ERROR: tapelist %s: parse error\n", quoted);
-           tapebad = 1;
-           amfree(quoted);
+       else {
+           tapebad |= check_tapefile(outf, tapefile);
+           if (tapebad == 0 && read_tapelist(tapefile)) {
+               quoted = quote_string(tapefile);
+               g_fprintf(outf, _("ERROR: tapelist %s: parse error\n"), quoted);
+               tapebad = 1;
+               amfree(quoted);
+           }
+           newtapefile = stralloc2(tapefile, ".new");
+           tapebad |= check_tapefile(outf, newtapefile);
+           amfree(newtapefile);
+           newtapefile = stralloc2(tapefile, ".amlabel");
+           tapebad |= check_tapefile(outf, newtapefile);
+           amfree(newtapefile);
+           newtapefile = stralloc2(tapefile, ".amlabel.new");
+           tapebad |= check_tapefile(outf, newtapefile);
+           amfree(newtapefile);
+           newtapefile = stralloc2(tapefile, ".yesterday");
+           tapebad |= check_tapefile(outf, newtapefile);
+           amfree(newtapefile);
+           newtapefile = stralloc2(tapefile, ".yesterday.new");
+           tapebad |= check_tapefile(outf, newtapefile);
+           amfree(newtapefile);
        }
-       holdfile = vstralloc(config_dir, "/", "hold", NULL);
+       holdfile = config_dir_relative("hold");
        if(access(holdfile, F_OK) != -1) {
            quoted = quote_string(holdfile);
-           fprintf(outf, "WARNING: hold file %s exists\n", holdfile);
+           g_fprintf(outf, _("WARNING: hold file %s exists."), holdfile);
+           g_fprintf(outf, _("Amdump will sleep as long as this file exists.\n"));
+           g_fprintf(outf, _("You might want to delete the existing hold file\n"));
            amfree(quoted);
        }
        amfree(tapefile);
@@ -830,89 +951,92 @@ start_server_check(
        tapename = getconf_str(CNF_TAPEDEV);
        if (tapename == NULL) {
            if (getconf_str(CNF_TPCHANGER) == NULL) {
-               fprintf(outf, "WARNING: No tapedev or tpchanger specified\n");
+               g_fprintf(outf, _("WARNING:Parameter \"tapedev\" or \"tpchanger\" not specified in amanda.conf.\n"));
                testtape = 0;
                do_tapechk = 0;
            }
-       } else if (strncmp_const(tapename, "null:") == 0) {
-           fprintf(outf,
-                   "WARNING: tapedev is %s, dumps will be thrown away\n",
-                   tapename);
-           testtape = 0;
-           do_tapechk = 0;
        }
     }
 
     /* check available disk space */
 
     if(do_localchk) {
-       for(hdp = holdingdisks; hdp != NULL; hdp = hdp->next) {
+       for(hdp = getconf_holdingdisks(); hdp != NULL; hdp = holdingdisk_next(hdp)) {
            quoted = quote_string(holdingdisk_get_diskdir(hdp));
-           if(get_fs_stats(holdingdisk_get_diskdir(hdp), &fs) == -1) {
-               fprintf(outf, "ERROR: holding dir %s (%s), "
-                       "you must create a directory.\n",
+           if(get_fs_usage(holdingdisk_get_diskdir(hdp), NULL, &fsusage) == -1) {
+               g_fprintf(outf, _("ERROR: holding dir %s (%s), "
+                       "you must create a directory.\n"),
                        quoted, strerror(errno));
                disklow = 1;
+               amfree(quoted);
+               continue;
            }
-           else if(access(holdingdisk_get_diskdir(hdp), W_OK) == -1) {
-               fprintf(outf, "ERROR: holding disk %s: not writable: %s.\n",
+
+           /* do the division first to avoid potential integer overflow */
+           if (fsusage.fsu_bavail_top_bit_set)
+               kb_avail = 0;
+           else
+               kb_avail = fsusage.fsu_bavail / 1024 * fsusage.fsu_blocksize;
+
+           if(access(holdingdisk_get_diskdir(hdp), W_OK) == -1) {
+               g_fprintf(outf, _("ERROR: holding disk %s: not writable: %s.\n"),
                        quoted, strerror(errno));
+               g_fprintf(outf, _("Check permissions\n"));
                disklow = 1;
            }
            else if(access(holdingdisk_get_diskdir(hdp), X_OK) == -1) {
-               fprintf(outf, "ERROR: holding disk %s: not searcheable: %s.\n",
+               g_fprintf(outf, _("ERROR: holding disk %s: not searcheable: %s.\n"),
                        quoted, strerror(errno));
-               disklow = 1;
-           }
-           else if(fs.avail == (off_t)-1) {
-               fprintf(outf,
-                       "WARNING: holding disk %s: "
-                       "available space unknown (" OFF_T_FMT" KB requested)\n",
-                       quoted, (OFF_T_FMT_TYPE)holdingdisk_get_disksize(hdp));
+               g_fprintf(outf, _("Check permissions of ancestors of %s\n"), quoted);
                disklow = 1;
            }
            else if(holdingdisk_get_disksize(hdp) > (off_t)0) {
-               if(fs.avail < holdingdisk_get_disksize(hdp)) {
-                   fprintf(outf,
-                           "WARNING: holding disk %s: "
-                           "only " OFF_T_FMT " %sB free ("
-                           OFF_T_FMT " %sB requested)\n", quoted,
-                           (OFF_T_FMT_TYPE)(fs.avail / (off_t)unitdivisor),
+               if(kb_avail == 0) {
+                   g_fprintf(outf,
+                           _("WARNING: holding disk %s: "
+                           "no space available (%lld %sB requested)\n"), quoted,
+                           (long long)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor),
+                           displayunit);
+                   disklow = 1;
+               }
+               else if(kb_avail < holdingdisk_get_disksize(hdp)) {
+                   g_fprintf(outf,
+                           _("WARNING: holding disk %s: "
+                           "only %lld %sB available (%lld %sB requested)\n"), quoted,
+                           (long long)(kb_avail / (off_t)unitdivisor),
                            displayunit,
-                           (OFF_T_FMT_TYPE)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor),
+                           (long long)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor),
                            displayunit);
                    disklow = 1;
                }
                else {
-                   fprintf(outf,
-                           "Holding disk %s: " OFF_T_FMT
-                           " %sB disk space available,"
-                           " using " OFF_T_FMT " %sB as requested\n",
+                   g_fprintf(outf,
+                           _("Holding disk %s: %lld %sB disk space available,"
+                           " using %lld %sB as requested\n"),
                            quoted,
-                           (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor),
+                           (long long)(kb_avail / (off_t)unitdivisor),
                            displayunit,
-                           (OFF_T_FMT_TYPE)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor),
+                           (long long)(holdingdisk_get_disksize(hdp)/(off_t)unitdivisor),
                            displayunit);
                }
            }
            else {
-               if((fs.avail + holdingdisk_get_disksize(hdp)) < (off_t)0) {
-                   fprintf(outf,
-                           "WARNING: holding disk %s: "
-                           "only " OFF_T_FMT " %sB free, using nothing\n",
-                           quoted, (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor),
+               if(kb_avail < -holdingdisk_get_disksize(hdp)) {
+                   g_fprintf(outf,
+                           _("WARNING: holding disk %s: "
+                           "only %lld %sB free, using nothing\n"),
+                           quoted, (long long)(kb_avail / (off_t)unitdivisor),
                            displayunit);
+                   g_fprintf(outf, _("WARNING: Not enough free space specified in amanda.conf\n"));
                    disklow = 1;
                }
                else {
-                   fprintf(outf,
-                           "Holding disk %s: "
-                           OFF_T_FMT " %sB disk space available, using "
-                           OFF_T_FMT " %sB\n",
+                   g_fprintf(outf,
+                           _("Holding disk %s: %lld %sB disk space available, using %lld %sB\n"),
                            quoted,
-                           (OFF_T_FMT_TYPE)(fs.avail/(off_t)unitdivisor),
+                           (long long)(kb_avail/(off_t)unitdivisor),
                            displayunit,
-                           (OFF_T_FMT_TYPE)((fs.avail + holdingdisk_get_disksize(hdp)) / (off_t)unitdivisor),
+                           (long long)((kb_avail + holdingdisk_get_disksize(hdp)) / (off_t)unitdivisor),
                            displayunit);
                }
            }
@@ -929,22 +1053,17 @@ start_server_check(
        struct stat stat_old;
        struct stat statbuf;
 
-       conf_logdir = getconf_str(CNF_LOGDIR);
-       if (*conf_logdir == '/') {
-           conf_logdir = stralloc(conf_logdir);
-       } else {
-           conf_logdir = stralloc2(config_dir, conf_logdir);
-       }
+       conf_logdir = config_dir_relative(getconf_str(CNF_LOGDIR));
        logfile = vstralloc(conf_logdir, "/log", NULL);
 
        quoted = quote_string(conf_logdir);
        if(stat(conf_logdir, &statbuf) == -1) {
-           fprintf(outf, "ERROR: logdir %s (%s), you must create directory.\n",
+           g_fprintf(outf, _("ERROR: logdir %s (%s), you must create directory.\n"),
                    quoted, strerror(errno));
            disklow = 1;
        }
        else if(access(conf_logdir, W_OK) == -1) {
-           fprintf(outf, "ERROR: log dir %s: not writable\n", quoted);
+           g_fprintf(outf, _("ERROR: log dir %s: not writable\n"), quoted);
            logbad = 1;
        }
        amfree(quoted);
@@ -954,7 +1073,7 @@ start_server_check(
            logbad = 2;
            if(access(logfile, W_OK) != 0) {
                quoted = quote_string(logfile);
-               fprintf(outf, "ERROR: log file %s: not writable\n", quoted);
+               g_fprintf(outf, _("ERROR: log file %s: not writable\n"), quoted);
                amfree(quoted);
            }
        }
@@ -963,18 +1082,21 @@ start_server_check(
        quoted = quote_string(olddir);
        if (stat(olddir,&stat_old) == 0) { /* oldlog exist */
            if(!(S_ISDIR(stat_old.st_mode))) {
-               fprintf(outf, "ERROR: oldlog directory %s is not a directory\n",
+               g_fprintf(outf, _("ERROR: oldlog directory %s is not a directory\n"),
                        quoted);
+               g_fprintf(outf, _("Remove the entry and create a new directory\n"));
                logbad = 1;
            }
            if(access(olddir, W_OK) == -1) {
-               fprintf(outf, "ERROR: oldlog dir %s: not writable\n", quoted);
+               g_fprintf(outf, _("ERROR: oldlog dir %s: not writable\n"), quoted);
+               g_fprintf(outf, _("Check permissions\n"));
                logbad = 1;
            }
        }
        else if(lstat(olddir,&stat_old) == 0) {
-           fprintf(outf, "ERROR: oldlog directory %s is not a directory\n",
+           g_fprintf(outf, _("ERROR: oldlog directory %s is not a directory\n"),
                    quoted);
+               g_fprintf(outf, _("Remove the entry and create a new directory\n"));
            logbad = 1;
        }
        amfree(quoted);
@@ -993,86 +1115,15 @@ start_server_check(
     }
 
     if (testtape) {
-       /* check that the tape is a valid amanda tape */
-        int tape_status;
-
-       tapedays = getconf_int(CNF_TAPECYCLE);
-       labelstr = getconf_str(CNF_LABELSTR);
-       tapename = getconf_str(CNF_TAPEDEV);
-
-       if (!getconf_seen(CNF_TPCHANGER) && getconf_int(CNF_RUNTAPES) != 1) {
-           fprintf(outf,
-                   "WARNING: if a tape changer is not available, runtapes must be set to 1\n");
-       }
-
-        tape_status = taper_scan(NULL, &label, &datestamp, &tapename,
-                                FILE_taperscan_output_callback, outf);
-       if (tapename) {
-           if (tape_access(tapename,F_OK) == -1) {
-               fprintf(outf, "ERROR: Can't access device %s: %s\n", tapename,
-                       strerror(errno));
-               tapebad = 1;
-           }
-           if (tape_access(tapename,R_OK) == -1) {
-               fprintf(outf, "ERROR: Can't read device %s: %s\n", tapename,
-                       strerror(errno));
-               tapebad = 1;
-           }
-           if (tape_access(tapename,W_OK) == -1) {
-               fprintf(outf, "ERROR: Can't write to device %s: %s\n", tapename,
-                       strerror(errno));
-               tapebad = 1;
-           }
-       }
-        if (tape_status < 0) {
-           tape_t *exptape = lookup_last_reusable_tape(0);
-           fprintf(outf, "       (expecting ");
-           if(exptape != NULL) fprintf(outf, "tape %s or ", exptape->label);
-           fprintf(outf, "a new tape)\n");
-            tapebad = 1;
-       } else {
-            if (overwrite) {
-                char *wrlabel_status;
-                wrlabel_status = tape_wrlabel(tapename, "X", label,
-                               (unsigned)(tapetype_get_blocksize(tp) * 1024));
-                if (wrlabel_status != NULL) {
-                    if (tape_status == 3) {
-                        fprintf(outf,
-                                "ERROR: Could not label brand new tape: %s\n",
-                                wrlabel_status);
-                    } else {
-                        fprintf(outf,
-                                "ERROR: tape %s label ok, but is not writable (%s)\n",
-                                label, wrlabel_status);
-                    }
-                    tapebad = 1;
-                } else {
-                    if (tape_status != 3) {
-                        fprintf(outf, "Tape %s is writable; rewrote label.\n", label);
-                    } else {
-                        fprintf(outf, "Wrote label %s to brand new tape.\n", label);
-                    }
-                }
-            } else {
-                fprintf(outf, "NOTE: skipping tape-writable test\n");
-                if (tape_status == 3) {
-                    fprintf(outf,
-                            "Found a brand new tape, will label it %s.\n", 
-                            label);
-                } else {
-                    fprintf(outf, "Tape %s label ok\n", label);
-                }                    
-            }
-        }
-       amfree(tapename);
+        tapebad = !test_tape_status(outf);
     } else if (do_tapechk) {
-       fprintf(outf, "WARNING: skipping tape test because amdump or amflush seem to be running\n");
-       fprintf(outf, "WARNING: if they are not, you must run amcleanup\n");
+       g_fprintf(outf, _("WARNING: skipping tape test because amdump or amflush seem to be running\n"));
+       g_fprintf(outf, _("WARNING: if they are not, you must run amcleanup\n"));
     } else if (logbad == 2) {
-       fprintf(outf, "WARNING: amdump or amflush seem to be running\n");
-       fprintf(outf, "WARNING: if they are not, you must run amcleanup\n");
+       g_fprintf(outf, _("WARNING: amdump or amflush seem to be running\n"));
+       g_fprintf(outf, _("WARNING: if they are not, you must run amcleanup\n"));
     } else {
-       fprintf(outf, "NOTE: skipping tape checks\n");
+       g_fprintf(outf, _("NOTE: skipping tape checks\n"));
     }
 
     /*
@@ -1100,83 +1151,73 @@ start_server_check(
        conf_runspercycle = getconf_int(CNF_RUNSPERCYCLE);
 
        if(conf_tapecycle <= conf_runspercycle) {
-               fprintf(outf, "WARNING: tapecycle (%d) <= runspercycle (%d).\n",
+               g_fprintf(outf, _("WARNING: tapecycle (%d) <= runspercycle (%d).\n"),
                        conf_tapecycle, conf_runspercycle);
        }
 
-       conf_infofile = getconf_str(CNF_INFOFILE);
-       if (*conf_infofile == '/') {
-           conf_infofile = stralloc(conf_infofile);
-       } else {
-           conf_infofile = stralloc2(config_dir, conf_infofile);
-       }
+       conf_infofile = config_dir_relative(getconf_str(CNF_INFOFILE));
+       conf_indexdir = config_dir_relative(getconf_str(CNF_INDEXDIR));
 
-       conf_indexdir = getconf_str(CNF_INDEXDIR);
-       if (*conf_indexdir == '/') {
-           conf_indexdir = stralloc(conf_indexdir);
-       } else {
-           conf_indexdir = stralloc2(config_dir, conf_indexdir);
-       }
-
-#if TEXTDB
        quoted = quote_string(conf_infofile);
        if(stat(conf_infofile, &statbuf) == -1) {
            if (errno == ENOENT) {
-               fprintf(outf, "NOTE: conf info dir %s does not exist\n",
+               g_fprintf(outf, _("NOTE: conf info dir %s does not exist\n"),
                        quoted);
-               fprintf(outf, "NOTE: it will be created on the next run.\n");
+               g_fprintf(outf, _("NOTE: it will be created on the next run.\n"));
            } else {
-               fprintf(outf, "ERROR: conf info dir %s (%s)\n",
+               g_fprintf(outf, _("ERROR: conf info dir %s (%s)\n"),
                        quoted, strerror(errno));
                infobad = 1;
            }   
            amfree(conf_infofile);
        } else if (!S_ISDIR(statbuf.st_mode)) {
-           fprintf(outf, "ERROR: info dir %s: not a directory\n", quoted);
+           g_fprintf(outf, _("ERROR: info dir %s: not a directory\n"), quoted);
+           g_fprintf(outf, _("Remove the entry and create a new directory\n"));
            amfree(conf_infofile);
            infobad = 1;
        } else if (access(conf_infofile, W_OK) == -1) {
-           fprintf(outf, "ERROR: info dir %s: not writable\n", quoted);
+           g_fprintf(outf, _("ERROR: info dir %s: not writable\n"), quoted);
+           g_fprintf(outf, _("Check permissions\n"));
            amfree(conf_infofile);
            infobad = 1;
        } else {
            char *errmsg = NULL;
            if (check_infofile(conf_infofile, &origq, &errmsg) == -1) {
-               fprintf(outf, "ERROR: Can't copy infofile: %s\n", errmsg);
+               g_fprintf(outf, "ERROR: Can't copy infofile: %s\n", errmsg);
                infobad = 1;
                amfree(errmsg);
            }
            strappend(conf_infofile, "/");
        }
        amfree(quoted);
-#endif
 
        while(!empty(origq)) {
            hostp = origq.head->host;
            host = sanitise_filename(hostp->hostname);
-#if TEXTDB
            if(conf_infofile) {
                hostinfodir = newstralloc2(hostinfodir, conf_infofile, host);
                quoted = quote_string(hostinfodir);
                if(stat(hostinfodir, &statbuf) == -1) {
                    if (errno == ENOENT) {
-                       fprintf(outf, "NOTE: host info dir %s does not exist\n",
+                       g_fprintf(outf, _("NOTE: host info dir %s does not exist\n"),
                                quoted);
-                       fprintf(outf,
-                               "NOTE: it will be created on the next run.\n");
+                       g_fprintf(outf,
+                               _("NOTE: it will be created on the next run.\n"));
                    } else {
-                       fprintf(outf, "ERROR: host info dir %s (%s)\n",
+                       g_fprintf(outf, _("ERROR: host info dir %s (%s)\n"),
                                quoted, strerror(errno));
                        infobad = 1;
                    }   
                    amfree(hostinfodir);
                } else if (!S_ISDIR(statbuf.st_mode)) {
-                   fprintf(outf, "ERROR: info dir %s: not a directory\n",
+                   g_fprintf(outf, _("ERROR: info dir %s: not a directory\n"),
                            quoted);
+                   g_fprintf(outf, _("Remove the entry and create a new directory\n"));
                    amfree(hostinfodir);
                    infobad = 1;
                } else if (access(hostinfodir, W_OK) == -1) {
-                   fprintf(outf, "ERROR: info dir %s: not writable\n", quoted);
+                   g_fprintf(outf, _("ERROR: info dir %s: not writable\n"), quoted);
+                   g_fprintf(outf, _("Check permissions\n"));
                    amfree(hostinfodir);
                    infobad = 1;
                } else {
@@ -1184,10 +1225,8 @@ start_server_check(
                }
                amfree(quoted);
            }
-#endif
            for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
                disk = sanitise_filename(dp->name);
-#if TEXTDB
                if(hostinfodir) {
                    char *quotedif;
 
@@ -1197,39 +1236,42 @@ start_server_check(
                    quotedif = quote_string(infofile);
                    if(stat(diskdir, &statbuf) == -1) {
                        if (errno == ENOENT) {
-                           fprintf(outf, "NOTE: info dir %s does not exist\n",
+                           g_fprintf(outf, _("NOTE: info dir %s does not exist\n"),
                                quoted);
-                           fprintf(outf,
-                               "NOTE: it will be created on the next run.\n");
+                           g_fprintf(outf,
+                               _("NOTE: it will be created on the next run.\n"));
                        } else {
-                           fprintf(outf, "ERROR: info dir %s (%s)\n",
+                           g_fprintf(outf, _("ERROR: info dir %s (%s)\n"),
                                    quoted, strerror(errno));
                            infobad = 1;
                        }       
                    } else if (!S_ISDIR(statbuf.st_mode)) {
-                       fprintf(outf, "ERROR: info dir %s: not a directory\n",
+                       g_fprintf(outf, _("ERROR: info dir %s: not a directory\n"),
                                quoted);
+                       g_fprintf(outf, _("Remove the entry and create a new directory\n"));
                        infobad = 1;
                    } else if (access(diskdir, W_OK) == -1) {
-                       fprintf(outf, "ERROR: info dir %s: not writable\n",
+                       g_fprintf(outf, _("ERROR: info dir %s: not writable\n"),
                                quoted);
+                       g_fprintf(outf,_("Check permissions\n"));
                        infobad = 1;
                    } else if(stat(infofile, &statbuf) == -1) {
                        if (errno == ENOENT) {
-                           fprintf(outf, "NOTE: info file %s does not exist\n",
+                           g_fprintf(outf, _("NOTE: info file %s does not exist\n"),
                                    quotedif);
-                           fprintf(outf, "NOTE: it will be created on the next run.\n");
+                           g_fprintf(outf, _("NOTE: it will be created on the next run.\n"));
                        } else {
-                           fprintf(outf, "ERROR: info dir %s (%s)\n",
+                           g_fprintf(outf, _("ERROR: info dir %s (%s)\n"),
                                    quoted, strerror(errno));
                            infobad = 1;
                        }       
                    } else if (!S_ISREG(statbuf.st_mode)) {
-                       fprintf(outf, "ERROR: info file %s: not a file\n",
+                       g_fprintf(outf, _("ERROR: info file %s: not a file\n"),
                                quotedif);
+                       g_fprintf(outf, _("Remove the entry and create a new file\n"));
                        infobad = 1;
                    } else if (access(infofile, R_OK) == -1) {
-                       fprintf(outf, "ERROR: info file %s: not readable\n",
+                       g_fprintf(outf, _("ERROR: info file %s: not readable\n"),
                                quotedif);
                        infobad = 1;
                    }
@@ -1237,28 +1279,28 @@ start_server_check(
                    amfree(quoted);
                    amfree(infofile);
                }
-#endif
                if(dp->index) {
                    if(! indexdir_checked) {
                        quoted = quote_string(conf_indexdir);
                        if(stat(conf_indexdir, &statbuf) == -1) {
                            if (errno == ENOENT) {
-                               fprintf(outf, "NOTE: index dir %s does not exist\n",
+                               g_fprintf(outf, _("NOTE: index dir %s does not exist\n"),
                                        quoted);
-                               fprintf(outf, "NOTE: it will be created on the next run.\n");
+                               g_fprintf(outf, _("NOTE: it will be created on the next run.\n"));
                            } else {
-                               fprintf(outf, "ERROR: index dir %s (%s)\n",
+                               g_fprintf(outf, _("ERROR: index dir %s (%s)\n"),
                                        quoted, strerror(errno));
                                indexbad = 1;
                            }   
                            amfree(conf_indexdir);
                        } else if (!S_ISDIR(statbuf.st_mode)) {
-                           fprintf(outf, "ERROR: index dir %s: not a directory\n",
+                           g_fprintf(outf, _("ERROR: index dir %s: not a directory\n"),
                                    quoted);
+                           g_fprintf(outf, _("Remove the entry and create a new directory\n"));
                            amfree(conf_indexdir);
                            indexbad = 1;
                        } else if (access(conf_indexdir, W_OK) == -1) {
-                           fprintf(outf, "ERROR: index dir %s: not writable\n",
+                           g_fprintf(outf, _("ERROR: index dir %s: not writable\n"),
                                    quoted);
                            amfree(conf_indexdir);
                            indexbad = 1;
@@ -1274,22 +1316,23 @@ start_server_check(
                            quoted = quote_string(hostindexdir);
                            if(stat(hostindexdir, &statbuf) == -1) {
                                if (errno == ENOENT) {
-                                   fprintf(outf, "NOTE: index dir %s does not exist\n",
+                                   g_fprintf(outf, _("NOTE: index dir %s does not exist\n"),
                                            quoted);
-                                   fprintf(outf, "NOTE: it will be created on the next run.\n");
+                                   g_fprintf(outf, _("NOTE: it will be created on the next run.\n"));
                                } else {
-                                   fprintf(outf, "ERROR: index dir %s (%s)\n",
+                                   g_fprintf(outf, _("ERROR: index dir %s (%s)\n"),
                                            quoted, strerror(errno));
                                    indexbad = 1;
                                }
                                amfree(hostindexdir);
                            } else if (!S_ISDIR(statbuf.st_mode)) {
-                               fprintf(outf, "ERROR: index dir %s: not a directory\n",
+                               g_fprintf(outf, _("ERROR: index dir %s: not a directory\n"),
                                        quoted);
+                               g_fprintf(outf, _("Remove the entry and create a new directory\n"));
                                amfree(hostindexdir);
                                indexbad = 1;
                            } else if (access(hostindexdir, W_OK) == -1) {
-                               fprintf(outf, "ERROR: index dir %s: not writable\n",
+                               g_fprintf(outf, _("ERROR: index dir %s: not writable\n"),
                                        quoted);
                                amfree(hostindexdir);
                                indexbad = 1;
@@ -1304,20 +1347,21 @@ start_server_check(
                            quoted = quote_string(diskdir);
                            if(stat(diskdir, &statbuf) == -1) {
                                if (errno == ENOENT) {
-                                   fprintf(outf, "NOTE: index dir %s does not exist\n",
+                                   g_fprintf(outf, _("NOTE: index dir %s does not exist\n"),
                                            quoted);
-                                   fprintf(outf, "NOTE: it will be created on the next run.\n");
+                                   g_fprintf(outf, _("NOTE: it will be created on the next run.\n"));
                                } else {
-                                   fprintf(outf, "ERROR: index dir %s (%s)\n",
+                                   g_fprintf(outf, _("ERROR: index dir %s (%s)\n"),
                                        quoted, strerror(errno));
                                    indexbad = 1;
                                }       
                            } else if (!S_ISDIR(statbuf.st_mode)) {
-                               fprintf(outf, "ERROR: index dir %s: not a directory\n",
+                               g_fprintf(outf, _("ERROR: index dir %s: not a directory\n"),
                                        quoted);
+                               g_fprintf(outf, _("Remove the entry and create a new directory\n"));
                                indexbad = 1;
                            } else if (access(diskdir, W_OK) == -1) {
-                               fprintf(outf, "ERROR: index dir %s: is not writable\n",
+                               g_fprintf(outf, _("ERROR: index dir %s: is not writable\n"),
                                        quoted);
                                indexbad = 1;
                            }
@@ -1328,26 +1372,33 @@ start_server_check(
 
                if ( dp->encrypt == ENCRYPT_SERV_CUST ) {
                  if ( dp->srv_encrypt[0] == '\0' ) {
-                   fprintf(outf, "ERROR: server encryption program not specified\n");
+                   g_fprintf(outf, _("ERROR: server encryption program not specified\n"));
+                   g_fprintf(outf, _("Specify \"server_custom_encrypt\" in the dumptype\n"));
                    pgmbad = 1;
                  }
                  else if(access(dp->srv_encrypt, X_OK) == -1) {
-                   fprintf(outf, "ERROR: %s is not executable, server encryption will not work\n",
+                   g_fprintf(outf, _("ERROR: %s is not executable, server encryption will not work\n"),
                            dp->srv_encrypt );
+                  g_fprintf(outf, _("Check file type\n"));
                    pgmbad = 1;
                  }
                }
                if ( dp->compress == COMP_SERVER_CUST ) {
                  if ( dp->srvcompprog[0] == '\0' ) {
-                   fprintf(outf, "ERROR: server custom compression program not specified\n");
+                   g_fprintf(outf, _("ERROR: server custom compression program "
+                                   "not specified\n"));
+                   g_fprintf(outf, _("Specify \"server_custom_compress\" in "
+                                   "the dumptype\n"));
                    pgmbad = 1;
                  }
                  else if(access(dp->srvcompprog, X_OK) == -1) {
                    quoted = quote_string(dp->srvcompprog);
 
-                   fprintf(outf, "ERROR: %s is not executable, server custom compression will not work\n",
+                   g_fprintf(outf, _("ERROR: %s is not executable, server custom "
+                                   "compression will not work\n"),
                            quoted);
                    amfree(quoted);
+                  g_fprintf(outf, _("Check file type\n"));
                    pgmbad = 1;
                  }
                }
@@ -1366,20 +1417,11 @@ start_server_check(
     }
 
     amfree(datestamp);
-    amfree(label);
-    amfree(config_dir);
-    amfree(config_name);
 
-    fprintf(outf, "Server check took %s seconds\n", walltime_str(curclock()));
+    g_fprintf(outf, _("Server check took %s seconds\n"), walltime_str(curclock()));
 
     fflush(outf);
 
-    malloc_size_2 = malloc_inuse(&malloc_hist_2);
-
-    if(malloc_size_1 != malloc_size_2) {
-       malloc_list(fd, malloc_hist_1, malloc_hist_2);
-    }
-
     exit(userbad \
         || confbad \
         || tapebad \
@@ -1424,8 +1466,8 @@ start_host(
     }
 
     if (strcmp(hostp->hostname,"localhost") == 0) {
-       fprintf(outf,
-                    "WARNING: Usage of fully qualified hostname recommended for Client %s.\n",
+       g_fprintf(outf,
+                    _("WARNING: Usage of fully qualified hostname recommended for Client %s.\n"),
                     hostp->hostname);
     }
 
@@ -1449,40 +1491,46 @@ start_host(
 
        if(!am_has_feature(hostp->features, fe_selfcheck_req) &&
           !am_has_feature(hostp->features, fe_selfcheck_req_device)) {
-           fprintf(outf,
-                   "ERROR: Client %s does not support selfcheck REQ packet.\n",
+           g_fprintf(outf,
+                   _("ERROR: Client %s does not support selfcheck REQ packet.\n"),
                    hostp->hostname);
+           g_fprintf(outf, _("Client might be of a very old version\n"));
        }
        if(!am_has_feature(hostp->features, fe_selfcheck_rep)) {
-           fprintf(outf,
-                   "ERROR: Client %s does not support selfcheck REP packet.\n",
+           g_fprintf(outf,
+                   _("ERROR: Client %s does not support selfcheck REP packet.\n"),
                    hostp->hostname);
+           g_fprintf(outf, _("Client might be of a very old version\n"));
        }
        if(!am_has_feature(hostp->features, fe_sendsize_req_options) &&
           !am_has_feature(hostp->features, fe_sendsize_req_no_options) &&
           !am_has_feature(hostp->features, fe_sendsize_req_device)) {
-           fprintf(outf,
-                   "ERROR: Client %s does not support sendsize REQ packet.\n",
+           g_fprintf(outf,
+                   _("ERROR: Client %s does not support sendsize REQ packet.\n"),
                    hostp->hostname);
+           g_fprintf(outf, _("Client might be of a very old version\n"));
        }
        if(!am_has_feature(hostp->features, fe_sendsize_rep)) {
-           fprintf(outf,
-                   "ERROR: Client %s does not support sendsize REP packet.\n",
+           g_fprintf(outf,
+                   _("ERROR: Client %s does not support sendsize REP packet.\n"),
                    hostp->hostname);
+           g_fprintf(outf, _("Client might be of a very old version\n"));
        }
        if(!am_has_feature(hostp->features, fe_sendbackup_req) &&
           !am_has_feature(hostp->features, fe_sendbackup_req_device)) {
-           fprintf(outf,
-                  "ERROR: Client %s does not support sendbackup REQ packet.\n",
+           g_fprintf(outf,
+                  _("ERROR: Client %s does not support sendbackup REQ packet.\n"),
                   hostp->hostname);
+           g_fprintf(outf, _("Client might be of a very old version\n"));
        }
        if(!am_has_feature(hostp->features, fe_sendbackup_rep)) {
-           fprintf(outf,
-                  "ERROR: Client %s does not support sendbackup REP packet.\n",
+           g_fprintf(outf,
+                  _("ERROR: Client %s does not support sendbackup REP packet.\n"),
                   hostp->hostname);
+           g_fprintf(outf, _("Client might be of a very old version\n"));
        }
 
-       snprintf(number, SIZEOF(number), "%d", hostp->maxdumps);
+       g_snprintf(number, SIZEOF(number), "%d", hostp->maxdumps);
        req = vstralloc("SERVICE ", "selfcheck", "\n",
                        "OPTIONS ",
                        has_features ? "features=" : "",
@@ -1524,45 +1572,64 @@ start_host(
            if ((dp->name && qname[0] == '"') || 
                (dp->device && qdevice[0] == '"')) {
                if(!am_has_feature(hostp->features, fe_interface_quoted_text)) {
-                   fprintf(outf,
-                           "WARNING: %s:%s:%s host does not support quoted text\n",
+                   g_fprintf(outf,
+                           _("WARNING: %s:%s:%s host does not support quoted text\n"),
                            hostp->hostname, qname, qdevice);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to "
+                                   "specify a quoted text/device in the disklist, "
+                                   "or don't use quoted text for the device.\n"));
                }
            }
 
            if(dp->device) {
                if(!am_has_feature(hostp->features, fe_selfcheck_req_device)) {
-                   fprintf(outf,
-                    "ERROR: %s:%s (%s): selfcheck does not support device.\n",
+                   g_fprintf(outf,
+                    _("ERROR: %s:%s (%s): selfcheck does not support device.\n"),
                     hostp->hostname, qname, dp->device);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to "
+                                   "specify a diskdevice in the disklist "     
+                                   "or don't specify a diskdevice in the disklist.\n"));       
                }
                if(!am_has_feature(hostp->features, fe_sendsize_req_device)) {
-                   fprintf(outf,
-                    "ERROR: %s:%s (%s): sendsize does not support device.\n",
+                   g_fprintf(outf,
+                    _("ERROR: %s:%s (%s): sendsize does not support device.\n"),
                     hostp->hostname, qname, dp->device);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to "
+                                   "specify a diskdevice in the disklist"      
+                                   " or don't specify a diskdevice in the disklist.\n"));      
                }
                if(!am_has_feature(hostp->features, fe_sendbackup_req_device)) {
-                   fprintf(outf,
-                    "ERROR: %s:%s (%s): sendbackup does not support device.\n",
+                   g_fprintf(outf,
+                    _("ERROR: %s:%s (%s): sendbackup does not support device.\n"),
                     hostp->hostname, qname, dp->device);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to "
+                                   "specify a diskdevice in the disklist"      
+                                   " or don't specify a diskdevice in the disklist.\n"));      
                }
            }
            if(strcmp(dp->program,"DUMP") == 0 || 
               strcmp(dp->program,"GNUTAR") == 0) {
                if(strcmp(dp->program, "DUMP") == 0 &&
                   !am_has_feature(hostp->features, fe_program_dump)) {
-                   fprintf(outf, "ERROR: %s:%s does not support DUMP.\n",
+                   g_fprintf(outf, _("ERROR: %s:%s does not support DUMP.\n"),
                            hostp->hostname, qname);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to use DUMP "
+                                   "or you can use another program.\n"));      
                }
                if(strcmp(dp->program, "GNUTAR") == 0 &&
                   !am_has_feature(hostp->features, fe_program_gnutar)) {
-                   fprintf(outf, "ERROR: %s:%s does not support GNUTAR.\n",
+                   g_fprintf(outf, _("ERROR: %s:%s does not support GNUTAR.\n"),
                            hostp->hostname, qname);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to use GNUTAR "
+                                   "or you can use another program.\n"));      
                }
                if(dp->estimate == ES_CALCSIZE &&
                   !am_has_feature(hostp->features, fe_calcsize_estimate)) {
-                   fprintf(outf, "ERROR: %s:%s does not support CALCSIZE for estimate, using CLIENT.\n",
+                   g_fprintf(outf, _("ERROR: %s:%s does not support CALCSIZE for "
+                                   "estimate, using CLIENT.\n"),
                            hostp->hostname, qname);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to use "
+                                   "CALCSIZE for estimate or don't use CALCSIZE for estimate.\n"));
                    dp->estimate = ES_CLIENT;
                }
                if(dp->estimate == ES_CALCSIZE &&
@@ -1573,21 +1640,28 @@ start_host(
 
                if(dp->compress == COMP_CUST &&
                   !am_has_feature(hostp->features, fe_options_compress_cust)) {
-                 fprintf(outf,
-                         "ERROR: Client %s does not support custom compression.\n",
+                 g_fprintf(outf,
+                         _("ERROR: Client %s does not support custom compression.\n"),
                          hostp->hostname);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to "
+                                   "use custom compression\n"));
+                   g_fprintf(outf, _("Otherwise you can use the default client "
+                                   "compression program.\n"));
                }
                if(dp->encrypt == ENCRYPT_CUST ) {
                  if ( !am_has_feature(hostp->features, fe_options_encrypt_cust)) {
-                   fprintf(outf,
-                           "ERROR: Client %s does not support data encryption.\n",
+                   g_fprintf(outf,
+                           _("ERROR: Client %s does not support data encryption.\n"),
                            hostp->hostname);
+                   g_fprintf(outf, _("You must upgrade amanda on the client to use encryption program.\n"));
                    remote_errors++;
                  } else if ( dp->compress == COMP_SERVER_FAST || 
                              dp->compress == COMP_SERVER_BEST ||
                              dp->compress == COMP_SERVER_CUST ) {
-                   fprintf(outf,
-                           "ERROR: %s: Client encryption with server compression is not supported. See amanda.conf(5) for detail.\n", hostp->hostname);
+                   g_fprintf(outf,
+                           _("ERROR: %s: Client encryption with server compression "
+                             "is not supported. See amanda.conf(5) for detail.\n"), 
+                           hostp->hostname);
                    remote_errors++;
                  } 
                }
@@ -1612,8 +1686,10 @@ start_host(
                }
            } else {
                if(!am_has_feature(hostp->features, fe_program_backup_api)) {
-                   fprintf(outf, "ERROR: %s:%s does not support BACKUP-API.\n",
+                   g_fprintf(outf, _("ERROR: %s:%s does not support BACKUP-API.\n"),
                            hostp->hostname, qname);
+                   g_fprintf(outf, _("Dumptype configuration is not GNUTAR or DUMP."
+                                   " It is case sensitive\n"));
                }
                if(dp->device) {
                    l = vstralloc("BACKUP ",
@@ -1671,12 +1747,12 @@ start_host(
 
     secdrv = security_getdriver(hostp->disks->security_driver);
     if (secdrv == NULL) {
-       error("could not find security driver '%s' for host '%s'",
+       fprintf(stderr, _("Could not find security driver \"%s\" for host \"%s\". auth for this dle is invalid\n"),
              hostp->disks->security_driver, hostp->hostname);
-        /*NOTREACHED*/
+    } else {
+       protocol_sendreq(hostp->hostname, secdrv, amhost_get_security_conf, 
+                        req, conf_ctimeout, handle_result, hostp);
     }
-    protocol_sendreq(hostp->hostname, secdrv, amhost_get_security_conf, 
-                    req, conf_ctimeout, handle_result, hostp);
 
     amfree(req);
 
@@ -1695,7 +1771,7 @@ start_client_checks(
 
     switch(pid = fork()) {
     case -1:
-       error("could not fork client check: %s", strerror(errno));
+       error(_("INTERNAL ERROR:could not fork client check: %s"), strerror(errno));
        /*NOTREACHED*/
 
     case 0:
@@ -1713,13 +1789,13 @@ start_client_checks(
     startclock();
 
     if((outf = fdopen(fd, "w")) == NULL) {
-       error("fdopen %d: %s", fd, strerror(errno));
+       error(_("fdopen %d: %s"), fd, strerror(errno));
        /*NOTREACHED*/
     }
     errf = outf;
 
-    fprintf(outf, "\nAmanda Backup Client Hosts Check\n");
-    fprintf(outf,   "--------------------------------\n");
+    g_fprintf(outf, _("\nAmanda Backup Client Hosts Check\n"));
+    g_fprintf(outf,   "--------------------------------\n");
 
     protocol_init();
 
@@ -1736,22 +1812,15 @@ start_client_checks(
 
     protocol_run();
 
-    fprintf(outf,
-     "Client check: %d host%s checked in %s seconds, %d problem%s found\n",
-           hostcount, (hostcount == 1) ? "" : "s",
-           walltime_str(curclock()),
-           remote_errors, (remote_errors == 1) ? "" : "s");
+    g_fprintf(outf, plural(_("Client check: %d host checked in %s seconds."), 
+                        _("Client check: %d hosts checked in %s seconds."),
+                        hostcount),
+           hostcount, walltime_str(curclock()));
+    g_fprintf(outf, plural(_("  %d problem found.\n"),
+                        _("  %d problems found.\n"), remote_errors),
+           remote_errors);
     fflush(outf);
 
-    amfree(config_dir);
-    amfree(config_name);
-
-    malloc_size_2 = malloc_inuse(&malloc_hist_2);
-
-    if(malloc_size_1 != malloc_size_2) {
-       malloc_list(fd, malloc_hist_1, malloc_hist_2);
-    }
-
     exit(userbad || remote_errors > 0);
     /*NOTREACHED*/
     return 0;
@@ -1775,8 +1844,8 @@ handle_result(
     hostp->up = HOST_READY;
 
     if (pkt == NULL) {
-       fprintf(outf,
-           "WARNING: %s: selfcheck request failed: %s\n", hostp->hostname,
+       g_fprintf(outf,
+           _("WARNING: %s: selfcheck request failed: %s\n"), hostp->hostname,
            security_geterror(sech));
        remote_errors++;
        hostp->up = HOST_DONE;
@@ -1784,7 +1853,7 @@ handle_result(
     }
 
 #if 0
-    fprintf(errf, "got response from %s:\n----\n%s----\n\n",
+    g_fprintf(errf, _("got response from %s:\n----\n%s----\n\n"),
            hostp->hostname, pkt->body);
 #endif
 
@@ -1804,8 +1873,9 @@ handle_result(
                t += SIZEOF("features=")-1;
                am_release_feature_set(hostp->features);
                if((hostp->features = am_string_to_feature(t)) == NULL) {
-                   fprintf(outf, "ERROR: %s: bad features value: %s\n",
+                   g_fprintf(outf, _("ERROR: %s: bad features value: %s\n"),
                            hostp->hostname, line);
+                   g_fprintf(outf, _("The amfeature in the reply packet is invalid\n"));
                }
            }
 
@@ -1827,7 +1897,7 @@ handle_result(
            if(!((hostp->features == NULL) && (pkt->type == P_NAK)
               && ((strcmp(t - 1, "unknown service: noop") == 0)
                   || (strcmp(t - 1, "noop: invalid service") == 0)))) {
-               fprintf(outf, "ERROR: %s%s: %s\n",
+               g_fprintf(outf, _("ERROR: %s%s: %s\n"),
                        (pkt->type == P_NAK) ? "NAK " : "",
                        hostp->hostname,
                        t - 1);
@@ -1837,7 +1907,7 @@ handle_result(
            continue;
        }
 
-       fprintf(outf, "ERROR: %s: unknown response: %s\n",
+       g_fprintf(outf, _("ERROR: %s: unknown response: %s\n"),
                hostp->hostname, line);
        remote_errors++;
        hostp->up = HOST_DONE;
@@ -1847,8 +1917,7 @@ handle_result(
         * The client does not support the features list, so give it an
         * empty one.
         */
-       dbprintf(("%s: no feature set from host %s\n",
-                 debug_prefix_time(NULL), hostp->hostname));
+       dbprintf(_("no feature set from host %s\n"), hostp->hostname);
        hostp->features = am_set_default_feature_set();
     }
     for(dp = hostp->disks; dp != NULL; dp = dp->hostnext) {
@@ -1859,4 +1928,7 @@ handle_result(
     start_host(hostp);
     if(hostp->up == HOST_DONE)
        security_close_connection(sech, hostp->hostname);
+    /* try to clean up any defunct processes, since Amanda doesn't wait() for
+       them explicitly */
+    while(waitpid(-1, NULL, WNOHANG)> 0);
 }