lintian doesn't like orphan packages with uploaders...
[debian/amanda] / recover-src / set_commands.c
index 65163a7450134b090bfacd3fa0ed5410c29d835e..6d4e96ad64da35d10dd40355f05de4c16280a648 100644 (file)
@@ -1,6 +1,7 @@
 /*
  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
  * Copyright (c) 1991-1998, 2000 University of Maryland at College Park
+ * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
  * All Rights Reserved.
  *
  * Permission to use, copy, modify, distribute, and sell this software and its
  * file named AUTHORS, in the root directory of this distribution.
  */
 /*
- * $Id: set_commands.c,v 1.23 2004/02/11 13:15:18 martinea Exp $
+ * $Id: set_commands.c,v 1.26 2006/07/05 13:14:58 martinea Exp $
  *
  * implements the "set" commands in amrecover
  */
 
 #include "amanda.h"
+#include "match.h"
+#include "util.h"
 #include "amrecover.h"
+#include "amxml.h"
 
-#ifdef SAMBA_CLIENT
 extern unsigned short samba_extract_method;
-#endif /* SAMBA_CLIENT */
 
 /* sets a date, mapping given date into standard form if needed */
-int set_date(date)
-char *date;
+int
+set_date(
+    char *     date)
 {
     char *cmd = NULL;
+    char *qdisk_path;
 
     clear_dir_list();
 
@@ -52,7 +56,9 @@ char *date;
        is still valid at the new date, and if not set directory to
        mount_point */
     if (disk_path != NULL) {
-       cmd = newstralloc2(cmd, "OISD ", disk_path);
+       qdisk_path = quote_string(disk_path);
+       cmd = newstralloc2(cmd, "OISD ", qdisk_path);
+       amfree(qdisk_path);
        if (exchange(cmd) == -1)
            exit(1);
        if (server_happy())
@@ -61,120 +67,173 @@ char *date;
        }
        else
        {
-           printf("No index records for cwd on new date\n");
-           printf("Setting cwd to mount point\n");
+           g_printf(_("No index records for cwd on new date\n"));
+           g_printf(_("Setting cwd to mount point\n"));
            disk_path = newstralloc(disk_path, "/");    /* fake it */
+           disk_tpath = newstralloc(disk_tpath, "/");  /* fake it */
            clear_dir_list();
        }
     }
     amfree(cmd);
-
     return 0;
 }
 
 
-void set_host(host)
-char *host;
+void
+set_host(
+    const char *host)
 {
     char *cmd = NULL;
-    struct hostent *hp;
+    struct hostent *hp = NULL;
     char **hostp;
     int found_host = 0;
+    char *uqhost = unquote_string(host);
 
     if (is_extract_list_nonempty())
     {
-       printf("Must clear extract list before changing host\n");
+       g_printf(_("Must clear extract list before changing host\n"));
+       amfree(uqhost);
        return;
     }
 
-    cmd = stralloc2("HOST ", host);
+    /*
+     * The idea here is to try as many permutations of the hostname
+     * as we can imagine.  The server will reject anything it doesn't
+     * recognize.
+     */
+
+    cmd = stralloc2("HOST ", uqhost);
     if (converse(cmd) == -1)
        exit(1);
     if (server_happy())
-    {
        found_host = 1;
-    }
-    else
-    {
-       /*
-        * Try converting the given host to a fully qualified name
-        * and then try each of the aliases.
-        */
-       if ((hp = gethostbyname(host)) != NULL) {
+
+    /*
+     * Try converting the given host to a fully qualified, canonical
+     * name.
+     */
+    if (!found_host) {
+       if ((hp = gethostbyname(uqhost)) != NULL) {
            host = hp->h_name;
-           printf("Trying host %s ...\n", host);
+           g_printf(_("Trying host %s ...\n"), host);
            cmd = newstralloc2(cmd, "HOST ", host);
            if (converse(cmd) == -1)
                exit(1);
            if(server_happy())
-           {
                found_host = 1;
-           }
-           else
+       }
+    }
+
+    /*
+     * Since we have them, try any CNAMEs that were traversed from uqhost
+     * to the canonical name (this assumes gethostbyname was called above)
+     */
+    if (!found_host) {
+       if (hp) {
+           for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
            {
-               for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
-               {
-                   printf("Trying host %s ...\n", host);
-                   cmd = newstralloc2(cmd, "HOST ", host);
-                   if (converse(cmd) == -1)
-                       exit(1);
-                   if(server_happy())
-                   {
-                       found_host = 1;
-                       break;
-                   }
+               g_printf(_("Trying host %s ...\n"), host);
+               cmd = newstralloc2(cmd, "HOST ", host);
+               if (converse(cmd) == -1)
+                   exit(1);
+               if(server_happy())
+               {
+                   found_host = 1;
+                   break;
                }
            }
        }
     }
-    if(found_host)
-    {
+
+    /* Try looking up the canonical name of the host */
+    if (!found_host) {
+       char *canonname;
+       int result;
+
+       result = resolve_hostname(uqhost, 0, NULL, &canonname);
+       if (result == 0 && canonname) {
+           host = canonname;
+           g_printf(_("Trying host %s ...\n"), host);
+           cmd = newstralloc2(cmd, "HOST ", host);
+           if (converse(cmd) == -1)
+               exit(1);
+           if(server_happy())
+               found_host = 1;
+       }
+    }
+
+    if(found_host) {
        dump_hostname = newstralloc(dump_hostname, host);
        amfree(disk_name);
        amfree(mount_point);
        amfree(disk_path);
+       amfree(disk_tpath);
        clear_dir_list();
     }
     amfree(cmd);
+    amfree(uqhost);
 }
 
+void
+list_host(void)
+{
+    char *cmd = NULL;
+
+    cmd = stralloc("LISTHOST");
+    if (converse(cmd) == -1)
+        exit(1);
+    amfree(cmd);
+}
 
-void set_disk(dsk, mtpt)
-char *dsk;
-char *mtpt;
+void
+set_disk(
+    char *     dsk,
+    char *     mtpt)
 {
     char *cmd = NULL;
+    char *qdsk;
+    char *uqdsk;
+    char *uqmtpt = NULL;
 
     if (is_extract_list_nonempty())
     {
-       printf("Must clear extract list before changing disk\n");
+       g_printf(_("Must clear extract list before changing disk\n"));
        return;
     }
 
     /* if mount point specified, check it is valid */
-    if ((mtpt != NULL) && (*mtpt != '/'))
-    {
-       printf("Mount point \"%s\" invalid - must start with /\n", mtpt);
-       return;
+    if (mtpt != NULL) {
+       uqmtpt = unquote_string(mtpt);
+       if (*mtpt != '/') {
+           g_printf(_("Mount point \"%s\" invalid - must start with /\n"), uqmtpt);
+           amfree(uqmtpt);
+           return;
+       }
     }
 
     clear_dir_list();
-    cmd = stralloc2("DISK ", dsk);
+    uqdsk = unquote_string(dsk);
+    qdsk = quote_string(uqdsk);
+    cmd = stralloc2("DISK ", qdsk);
+    amfree(qdsk);
     if (converse(cmd) == -1)
        exit(1);
     amfree(cmd);
 
-    if (!server_happy())
+    if (!server_happy()) {
+       amfree(uqmtpt);
+       amfree(uqdsk);
        return;
+    }
 
-    disk_name = newstralloc(disk_name, dsk);
+    disk_name = newstralloc(disk_name, uqdsk);
     if (mtpt == NULL)
     {
        /* mount point not specified */
-       if (*dsk == '/')
+       if (*uqdsk == '/')
        {
            /* disk specified by mount point, hence use it */
-           mount_point = newstralloc(mount_point, dsk);
+           mount_point = newstralloc(mount_point, uqdsk);
        }
        else
        {
@@ -185,7 +244,7 @@ char *mtpt;
     else
     {
        /* mount point specified */
-       mount_point = newstralloc(mount_point, mtpt);
+       mount_point = newstralloc(mount_point, uqmtpt);
     }
 
     /* set the working directory to the mount point */
@@ -198,24 +257,56 @@ char *mtpt;
     if (server_happy())
     {
        disk_path = newstralloc(disk_path, "/");
+       disk_tpath = newstralloc(disk_tpath, "/");
        suck_dir_list_from_server();    /* get list of directory contents */
     }
     else
     {
-       printf("No index records for disk for specified date\n");
-       printf("If date correct, notify system administrator\n");
+       g_printf(_("No index records for disk for specified date\n"));
+       g_printf(_("If date correct, notify system administrator\n"));
        disk_path = newstralloc(disk_path, "/");        /* fake it */
+       disk_tpath = newstralloc(disk_tpath, "/");      /* fake it */
        clear_dir_list();
     }
+    amfree(uqmtpt);
+    amfree(uqdsk);
+
+    if (am_has_feature(indexsrv_features, fe_amindexd_DLE)) {
+       char *dle_str;
+       char *errmsg = NULL;
+
+       cmd = stralloc("DLE");
+       if (exchange(cmd) == -1)
+           exit(1);
+       amfree(cmd);
+
+       if (!server_happy())
+           return;
+
+       dle_str = reply_line();
+       if (BSTRNCMP(dle_str+4, "NODLE") == 0) {
+           dump_dle = NULL;
+       } else {
+           dle_str = unquote_string(dle_str+4);
+           dump_dle = amxml_parse_node_CHAR(dle_str, &errmsg);
+           amfree(dle_str);
+       }
+    }
 }
 
-void list_disk(amdevice)
-char *amdevice;
+void
+list_disk(
+    char *     amdevice)
 {
     char *cmd = NULL;
+    char *qamdevice, *uqamdevice;
 
     if(amdevice) {
-       cmd = stralloc2("LISTDISK ", amdevice);
+       uqamdevice = unquote_string(amdevice);
+       qamdevice = quote_string(uqamdevice);
+       cmd = stralloc2("LISTDISK ", qamdevice);
+       amfree(uqamdevice);
+       amfree(qamdevice);
        if (converse(cmd) == -1)
            exit(1);
        amfree(cmd);
@@ -228,27 +319,131 @@ char *amdevice;
     }
 }
 
-void cd_glob(glob)
-char *glob;
+static GSList *prop_values = NULL;
+
+void
+set_property_name(
+    char *name,
+    int   append)
+{
+    property_t *prop;
+    char       *property_name, *pn;
+
+    pn = unquote_string(name);
+    property_name = amandaify_property_name(pn);
+    amfree(pn);
+
+    if (!append) {
+       g_hash_table_remove(proplist, property_name);
+       prop = NULL;
+    } else {
+       prop = g_hash_table_lookup(proplist, property_name);
+    }
+    
+    if (!prop) {
+       prop = malloc(sizeof(property_t));
+       prop->append = 0;
+       prop->priority = 1;
+       prop->values = NULL;
+       g_hash_table_insert(proplist, stralloc(property_name), prop);
+    }
+
+    /* add prop_values to prop->values */
+    if (!prop->values) {
+       prop->values = prop_values;
+       prop_values = NULL;
+    } else {
+       GSList *pv;
+
+       for(pv = prop_values; pv != NULL; pv = pv->next) {
+           prop->values = g_slist_append(prop->values, pv->data);
+       }
+       g_slist_free(prop_values);
+       prop_values = NULL;
+    }
+    amfree(property_name);
+}
+
+void
+add_property_value(
+    char *value)
+{
+    if (value) {
+       prop_values = g_slist_prepend(prop_values, unquote_string(value));
+    }
+}
+
+/* A GHFunc (callback for g_hash_table_foreach) */
+static void list_one_property(
+    gpointer key_p,
+    gpointer value_p,
+    gpointer user_data_p G_GNUC_UNUSED)
+{
+    char       *property_s = key_p;
+    char       *qproperty;
+    property_t *property = value_p;
+    GSList     *value;
+    char       *qvalue;
+
+    qproperty = quote_string_always(property_s);
+    printf("property %s", qproperty);
+    amfree(qproperty);
+    for (value = property->values; value != NULL; value = value->next) {
+       qvalue = quote_string_always((char*)value->data);
+       printf(" %s", qvalue);
+       amfree(qvalue);
+    }
+    printf("\n");
+}
+
+void
+list_property(void)
+{
+    if (proplist) {
+       g_hash_table_foreach(proplist, list_one_property, NULL);
+    } else {
+       printf("No property set\n");
+    }
+}
+
+void
+local_cd(
+    char *dir)
+{
+    char *uqdir = unquote_string(dir);
+    if (chdir(uqdir) == -1) {
+       perror(uqdir);
+    }
+    amfree(uqdir);
+}
+
+int
+cd_glob(
+    char *     glob,
+    int                verbose)
 {
     char *regex;
     char *regex_path;
     char *s;
+    char *uqglob;
+    int   result;
 
-    char *path_on_disk = NULL;
+    char *tpath_on_disk = NULL;
 
     if (disk_name == NULL) {
-       printf("Must select disk before changing directory\n");
-       return;
+       g_printf(_("Must select disk before changing directory\n"));
+       return 0;
     }
 
-    regex = glob_to_regex(glob);
-    dbprintf(("cd_glob (%s) -> %s\n", glob, regex));
+    uqglob = unquote_string(glob);
+    regex = glob_to_regex(uqglob);
+    dbprintf(_("cd_glob (%s) -> %s\n"), uqglob, regex);
     if ((s = validate_regexp(regex)) != NULL) {
-        printf("\"%s\" is not a valid shell wildcard pattern: ", glob);
+        g_printf(_("\"%s\" is not a valid shell wildcard pattern: "), glob);
         puts(s);
        amfree(regex);
-        return;
+       amfree(uqglob);
+        return 0;
     }
     /*
      * glob_to_regex() anchors the beginning of the pattern with ^,
@@ -265,76 +460,108 @@ char *glob;
 
     /* convert path (assumed in cwd) to one on disk */
     if (strcmp(disk_path, "/") == 0)
-        path_on_disk = stralloc2("/", regex_path);
+        tpath_on_disk = stralloc2("/", regex_path);
     else {
-        char *clean_disk_path = clean_regex(disk_path);
-        path_on_disk = vstralloc(clean_disk_path, "/", regex_path, NULL);
-        amfree(clean_disk_path);
+        char *clean_disk_tpath = clean_regex(disk_tpath, 0);
+        tpath_on_disk = vstralloc(clean_disk_tpath, "/", regex_path, NULL);
+        amfree(clean_disk_tpath);
     }
 
-    cd_dir(path_on_disk, glob);
+    result = cd_dir(tpath_on_disk, uqglob, verbose);
 
     amfree(regex_path);
-    amfree(path_on_disk);
+    amfree(tpath_on_disk);
+    amfree(uqglob);
+
+    return result;
 }
 
-void cd_regex(regex)
-char *regex;
+int
+cd_regex(
+    char *     regex,
+    int                verbose)
 {
     char *s;
+    char *uq_orig_regex;
+    char *uqregex;
+    int  len_uqregex;
+    int  result;
 
-    char *path_on_disk = NULL;
+    char *tpath_on_disk = NULL;
 
     if (disk_name == NULL) {
-       printf("Must select disk before changing directory\n");
-       return;
+       g_printf(_("Must select disk before changing directory\n"));
+       return 0;
     }
 
-    if ((s = validate_regexp(regex)) != NULL) {
-       printf("\"%s\" is not a valid regular expression: ", regex);
+    uq_orig_regex = unquote_string(regex);
+    uqregex = stralloc(uq_orig_regex);
+
+    /* Add a terminating '/' if it is not there, maybe before a '$' */
+    len_uqregex = strlen(uqregex);
+    if (uqregex[len_uqregex-1] == '$') {
+       if (uqregex[len_uqregex-2] != '/') {
+           uqregex[len_uqregex-1] = '\0';
+           strappend(uqregex, "/$");
+       }
+    } else if (uqregex[len_uqregex-1] != '/') {
+       //uqregex[len_uqregex-1] = '\0';
+       strappend(uqregex, "/");
+    }
+    if ((s = validate_regexp(uqregex)) != NULL) {
+       g_printf(_("\"%s\" is not a valid regular expression: "), uq_orig_regex);
+       amfree(uqregex);
+       amfree(uq_orig_regex);
        puts(s);
-       return;
+       return 0;
     }
 
     /* convert path (assumed in cwd) to one on disk */
     if (strcmp(disk_path, "/") == 0)
-        path_on_disk = stralloc2("/", regex);
+        tpath_on_disk = stralloc2("/", uqregex);
     else {
-        char *clean_disk_path = clean_regex(disk_path);
-        path_on_disk = vstralloc(clean_disk_path, "/", regex, NULL);
-        amfree(clean_disk_path);
+        char *clean_disk_tpath = clean_regex(disk_tpath, 0);
+        tpath_on_disk = vstralloc(clean_disk_tpath, "/", regex, NULL);
+        amfree(clean_disk_tpath);
     }
 
-    cd_dir(path_on_disk, regex);
+    result = cd_dir(tpath_on_disk, uq_orig_regex, verbose);
 
-    amfree(path_on_disk);
+    amfree(tpath_on_disk);
+    amfree(uqregex);
+    amfree(uq_orig_regex);
+
+    return result;
 }
 
-void cd_dir(path_on_disk, default_dir)
-char *path_on_disk;
-char *default_dir;
+int
+cd_dir(
+    char *tpath_on_disk,
+    char *default_dir,
+    int          verbose)
 {
-    char *path_on_disk_slash = NULL;
     char *dir = NULL;
-
     int nb_found;
+    int result;
     size_t i;
 
     DIR_ITEM *ditem;
 
-    path_on_disk_slash = stralloc2(path_on_disk, "/");
+    if (validate_regexp(tpath_on_disk) != NULL) {
+       result = set_directory(default_dir, verbose);
+       return result;
+    }
 
     nb_found = 0;
 
     for (ditem=get_dir_list(); ditem!=NULL && nb_found <= 1; 
                               ditem=get_next_dir_item(ditem))
     {
-       if (match(path_on_disk, ditem->path)
-           || match(path_on_disk_slash, ditem->path))
+       if (match(tpath_on_disk, ditem->tpath))
        {
-           i = strlen(ditem->path);
-           if((i > 0 && ditem->path[i-1] == '/')
-               || (i > 1 && ditem->path[i-2] == '/' && ditem->path[i-1] == '.'))
+           i = strlen(ditem->tpath);
+           if((i > 0 && ditem->tpath[i-1] == '/')
+               || (i > 1 && ditem->tpath[i-2] == '/' && ditem->tpath[i-1] == '.'))
             {   /* It is a directory */
                char *dir1, *dir2;
                nb_found++;
@@ -342,45 +569,55 @@ char *default_dir;
                if(dir[strlen(dir)-1] == '/')
                    dir[strlen(dir)-1] = '\0'; /* remove last / */
                /* remove everything before the last / */
-               dir1 = rindex(dir,'/');
-               dir1++;
-               dir2 = stralloc(dir1);
-               amfree(dir);
-               dir = dir2;
+               dir1 = strrchr(dir,'/');
+               if (dir1) {
+                   dir1++;
+                   dir2 = stralloc(dir1);
+                   amfree(dir);
+                   dir = dir2;
+               }
            }
        }
     }
-    amfree(path_on_disk_slash);
 
     if(nb_found==0) {
-       set_directory(default_dir);
+       result = set_directory(default_dir, verbose);
     }
     else if(nb_found==1) {
-       set_directory(dir);
+       result = set_directory(dir, verbose);
     }
     else {
-       printf("Too many directory\n");
+       g_printf(_("Too many directories matching '%s'\n"), default_dir);
+       result = 0;
     }
     amfree(dir);
+    return result;
 }
 
-void set_directory(dir)
-char *dir;
+/* dir is relative to dir_path or absolute with mount_point */
+int
+set_directory(
+    char *     dir,
+    int                verbose)
 {
     char *cmd = NULL;
     char *new_dir = NULL;
+    char *qnew_dir;
     char *dp, *de;
     char *ldir = NULL;
+    int   result;
 
     /* do nothing if "." */
     if(strcmp(dir,".")==0) {
        show_directory();               /* say where we are */
-       return;
+       return 1;
+       /*NOTREACHED*/
     }
 
     if (disk_name == NULL) {
-       printf("Must select disk before setting directory\n");
-       return;
+       g_printf(_("Must select disk before setting directory\n"));
+       return 0;
+       /*NOTREACHED*/
     }
 
     ldir = stralloc(dir);
@@ -398,10 +635,11 @@ char *dir;
        {
            if (strncmp(mount_point, ldir, strlen(mount_point)) != 0)
            {
-               printf("Invalid directory - Can't cd outside mount point \"%s\"\n",
+               g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
                       mount_point);
                amfree(ldir);
-               return;
+               return 0;
+               /*NOTREACHED*/
            }
            new_dir = stralloc(ldir+strlen(mount_point));
            if (strlen(new_dir) == 0) {
@@ -433,11 +671,14 @@ char *dir;
        if (strcmp(dp, "..") == 0) {
            if (strcmp(new_dir, "/") == 0) {
                /* at top of disk */
-               printf("Invalid directory - Can't cd outside mount point \"%s\"\n",
+               g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
                       mount_point);
+               /*@ignore@*/
                amfree(new_dir);
+               /*@end@*/
                amfree(ldir);
-               return;
+               return 0;
+               /*NOTREACHED*/
            }
            de = strrchr(new_dir, '/'); /* always at least 1 */
            if (de == new_dir)
@@ -450,120 +691,185 @@ char *dir;
                *de = '\0';
            }
        } else {
+           /*@ignore@*/
            if (strcmp(new_dir, "/") != 0) {
                strappend(new_dir, "/");
            }
            strappend(new_dir, ldir);
+           /*@end@*/
        }
     }
 
-    cmd = stralloc2("OISD ", new_dir);
-    if (exchange(cmd) == -1)
+    qnew_dir = quote_string(new_dir);
+    cmd = stralloc2("OISD ", qnew_dir);
+    amfree(qnew_dir);
+    if (exchange(cmd) == -1) {
        exit(1);
+       /*NOTREACHED*/
+    }
     amfree(cmd);
+
     if (server_happy())
     {
        disk_path = newstralloc(disk_path, new_dir);
+       g_free(disk_tpath);
+       disk_tpath = translate_octal(g_strdup(disk_path));
        suck_dir_list_from_server();    /* get list of directory contents */
-       show_directory();               /* say where we moved to */
+       if (verbose)
+           show_directory();           /* say where we moved to */
+       result = 1;
     }
     else
     {
-       printf("Invalid directory - %s\n", dir);
+       g_printf(_("Invalid directory - %s\n"), dir);
+       result = 0;
     }
 
+    /*@ignore@*/
     amfree(new_dir);
     amfree(ldir);
+    /*@end@*/
+
+    return result;
 }
 
 
 /* prints the current working directory */
-void show_directory P((void))
+void
+show_directory(void)
 {
     if (mount_point == NULL || disk_path == NULL)
-        printf("Must select disk first\n");
+        g_printf(_("Must select disk first\n"));
     else if (strcmp(mount_point, "/") == 0)
-       printf("%s\n", disk_path);
+       g_printf("%s\n", disk_tpath);
     else if (strcmp(disk_path, "/") == 0)
-       printf("%s\n", mount_point);
+       g_printf("%s\n", mount_point);
     else
-       printf("%s%s\n", mount_point, disk_path);
+       g_printf("%s%s\n", mount_point, disk_tpath);
 }
 
 
-/* set the tape server and device */
-void set_tape (tape)
-    char *tape;
+/* set the tape server and device (deprecated version) */
+void
+set_tape(
+    char *     tape)
 {
-    char *tapedev = strchr(tape, ':');
+    char *uqtape = unquote_string(tape);
+    char *tapedev = strchr(uqtape, ':');
+    char *host = NULL;
+
+    g_printf(_("NOTE: 'settape' is deprecated; use setdevice instead.\n"));
 
     if (tapedev)
     {
-       if (tapedev != tape) {
+       /* This command is deprecated because this parsing is going to fall 
+        * behind the list of available device names at some point, or to shadow
+        * an interesting hostname (wouldn't 'tape' be a good name for a 
+        * tape server?) */
+       if (tapedev != uqtape) {
            if((strchr(tapedev+1, ':') == NULL) &&
-              (strncmp(tape, "null:", 5) == 0 ||
-               strncmp(tape, "rait:", 5) == 0 ||
-               strncmp(tape, "file:", 5) == 0 ||
-               strncmp(tape, "tape:", 5) == 0)) {
-               tapedev = tape;
+              (strncmp_const(uqtape, "null:") == 0 ||
+               strncmp_const(uqtape, "rait:") == 0 ||
+               strncmp_const(uqtape, "file:") == 0 ||
+               strncmp_const(uqtape, "s3:") == 0 ||
+               strncmp_const(uqtape, "tape:") == 0)) {
+               tapedev = uqtape;
            }
            else {
                *tapedev = '\0';
-               tape_server_name = newstralloc(tape_server_name, tape);
+               host = stralloc(uqtape);
                ++tapedev;
            }
-       } else { /* reset server_name if start with : */
-           amfree(tape_server_name);
+       } else {
            ++tapedev;
        }
     } else
-       tapedev = tape;
+       tapedev = uqtape;
     
     if (tapedev[0])
     {
        if (strcmp(tapedev, "default") == 0)
-           amfree(tape_device_name);
-       else
-           tape_device_name = newstralloc(tape_device_name, tapedev);
+           tapedev = NULL;
     }
 
+    /* call out to the new version */
+    set_device(host, tapedev);
+
+    amfree(host);
+    amfree(uqtape);
+}
+
+/* set the tape server and device, for real */
+void
+set_device(
+    char *     host,
+    char *     device)
+{
+    if (host)
+       tape_server_name = newstralloc(tape_server_name, host);
+    else
+       amfree(tape_server_name);
+
+    if (device)
+       tape_device_name = newstralloc(tape_device_name, device);
+    else
+       amfree(tape_device_name);
+
+    /* print the current status */
     if (tape_device_name)
-       printf ("Using tape \"%s\"", tape_device_name);
+       g_printf (_("Using tape \"%s\""), tape_device_name);
     else
-       printf ("Using default tape");
+       g_printf (_("Using default tape"));
 
     if (tape_server_name)
-       printf (" from server %s.\n", tape_server_name);
+       g_printf (_(" from server %s.\n"), tape_server_name);
     else
-       printf (".\nTape server unspecified, assumed to be %s.\n",
+       g_printf (_(".\nTape server unspecified, assumed to be %s.\n"),
                server_name);
 }
 
-void set_mode (mode)
-int mode;
+void
+set_translate(
+    char *translate)
+{
+
+    if (translate == NULL) {
+       translate_mode = TRUE;
+    } else if (strcasecmp(translate, "yes") == 0 ||
+              strcasecmp(translate, "true") == 0 ||
+              strcasecmp(translate, "on") == 0) {
+       translate_mode = TRUE;
+    } else {
+       translate_mode = FALSE;
+    }
+    suck_dir_list_from_server();       /* get list of directory contents */
+}
+
+void
+set_mode(
+    int                mode)
 {
-#ifdef SAMBA_CLIENT
   if (mode == SAMBA_SMBCLIENT) {
-    printf ("SAMBA dumps will be extracted using smbclient\n");
+    g_printf (_("SAMBA dumps will be extracted using smbclient\n"));
     samba_extract_method = SAMBA_SMBCLIENT;
   } else {
     if (mode == SAMBA_TAR) {
-      printf ("SAMBA dumps will be extracted as TAR dumps\n");
+      g_printf (_("SAMBA dumps will be extracted as TAR dumps\n"));
       samba_extract_method = SAMBA_TAR;
     }
   }
-#endif /* SAMBA_CLIENT */
 }
 
-void show_mode (void) 
+void
+show_mode(void) 
 {
 #ifdef SAMBA_CLIENT
-  printf ("SAMBA dumps are extracted ");
+  g_printf (_("SAMBA dumps are extracted "));
 
   if (samba_extract_method == SAMBA_TAR) {
-    printf (" as TAR dumps\n");
+    g_printf (_(" as TAR dumps\n"));
   } else {
-    printf ("using smbclient\n");
+    g_printf (_("using smbclient\n"));
   }
 #endif /* SAMBA_CLIENT */
 }