lintian doesn't like orphan packages with uploaders...
[debian/amanda] / recover-src / set_commands.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998, 2000 University of Maryland at College Park
4  * Copyright (c) 2007-2012 Zmanda, Inc.  All Rights Reserved.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of U.M. not be used in advertising or
12  * publicity pertaining to distribution of the software without specific,
13  * written prior permission.  U.M. makes no representations about the
14  * suitability of this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  *
17  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Authors: the Amanda Development Team.  Its members are listed in a
25  * file named AUTHORS, in the root directory of this distribution.
26  */
27 /*
28  * $Id: set_commands.c,v 1.26 2006/07/05 13:14:58 martinea Exp $
29  *
30  * implements the "set" commands in amrecover
31  */
32
33 #include "amanda.h"
34 #include "match.h"
35 #include "util.h"
36 #include "amrecover.h"
37 #include "amxml.h"
38
39 extern unsigned short samba_extract_method;
40
41 /* sets a date, mapping given date into standard form if needed */
42 int
43 set_date(
44     char *      date)
45 {
46     char *cmd = NULL;
47     char *qdisk_path;
48
49     clear_dir_list();
50
51     cmd = stralloc2("DATE ", date);
52     if (converse(cmd) == -1)
53         exit(1);
54
55     /* if a host/disk/directory is set, then check if that directory
56        is still valid at the new date, and if not set directory to
57        mount_point */
58     if (disk_path != NULL) {
59         qdisk_path = quote_string(disk_path);
60         cmd = newstralloc2(cmd, "OISD ", qdisk_path);
61         amfree(qdisk_path);
62         if (exchange(cmd) == -1)
63             exit(1);
64         if (server_happy())
65         {
66             suck_dir_list_from_server();
67         }
68         else
69         {
70             g_printf(_("No index records for cwd on new date\n"));
71             g_printf(_("Setting cwd to mount point\n"));
72             disk_path = newstralloc(disk_path, "/");    /* fake it */
73             disk_tpath = newstralloc(disk_tpath, "/");  /* fake it */
74             clear_dir_list();
75         }
76     }
77     amfree(cmd);
78     return 0;
79 }
80
81
82 void
83 set_host(
84     const char *host)
85 {
86     char *cmd = NULL;
87     struct hostent *hp = NULL;
88     char **hostp;
89     int found_host = 0;
90     char *uqhost = unquote_string(host);
91
92     if (is_extract_list_nonempty())
93     {
94         g_printf(_("Must clear extract list before changing host\n"));
95         amfree(uqhost);
96         return;
97     }
98
99     /*
100      * The idea here is to try as many permutations of the hostname
101      * as we can imagine.  The server will reject anything it doesn't
102      * recognize.
103      */
104
105     cmd = stralloc2("HOST ", uqhost);
106     if (converse(cmd) == -1)
107         exit(1);
108     if (server_happy())
109         found_host = 1;
110
111     /*
112      * Try converting the given host to a fully qualified, canonical
113      * name.
114      */
115     if (!found_host) {
116         if ((hp = gethostbyname(uqhost)) != NULL) {
117             host = hp->h_name;
118             g_printf(_("Trying host %s ...\n"), host);
119             cmd = newstralloc2(cmd, "HOST ", host);
120             if (converse(cmd) == -1)
121                 exit(1);
122             if(server_happy())
123                 found_host = 1;
124         }
125     }
126
127     /*
128      * Since we have them, try any CNAMEs that were traversed from uqhost
129      * to the canonical name (this assumes gethostbyname was called above)
130      */
131     if (!found_host) {
132         if (hp) {
133             for (hostp = hp->h_aliases; (host = *hostp) != NULL; hostp++)
134             {
135                 g_printf(_("Trying host %s ...\n"), host);
136                 cmd = newstralloc2(cmd, "HOST ", host);
137                 if (converse(cmd) == -1)
138                     exit(1);
139                 if(server_happy())
140                 {
141                     found_host = 1;
142                     break;
143                 }
144             }
145         }
146     }
147
148     /* Try looking up the canonical name of the host */
149     if (!found_host) {
150         char *canonname;
151         int result;
152
153         result = resolve_hostname(uqhost, 0, NULL, &canonname);
154         if (result == 0 && canonname) {
155             host = canonname;
156             g_printf(_("Trying host %s ...\n"), host);
157             cmd = newstralloc2(cmd, "HOST ", host);
158             if (converse(cmd) == -1)
159                 exit(1);
160             if(server_happy())
161                 found_host = 1;
162         }
163     }
164
165     if(found_host) {
166         dump_hostname = newstralloc(dump_hostname, host);
167         amfree(disk_name);
168         amfree(mount_point);
169         amfree(disk_path);
170         amfree(disk_tpath);
171         clear_dir_list();
172     }
173     amfree(cmd);
174     amfree(uqhost);
175 }
176
177 void
178 list_host(void)
179 {
180     char *cmd = NULL;
181
182     cmd = stralloc("LISTHOST");
183     if (converse(cmd) == -1)
184         exit(1);
185     amfree(cmd);
186 }
187
188 void
189 set_disk(
190     char *      dsk,
191     char *      mtpt)
192 {
193     char *cmd = NULL;
194     char *qdsk;
195     char *uqdsk;
196     char *uqmtpt = NULL;
197
198     if (is_extract_list_nonempty())
199     {
200         g_printf(_("Must clear extract list before changing disk\n"));
201         return;
202     }
203
204     /* if mount point specified, check it is valid */
205     if (mtpt != NULL) {
206         uqmtpt = unquote_string(mtpt);
207         if (*mtpt != '/') {
208             g_printf(_("Mount point \"%s\" invalid - must start with /\n"), uqmtpt);
209             amfree(uqmtpt);
210             return;
211         }
212     }
213
214     clear_dir_list();
215     uqdsk = unquote_string(dsk);
216     qdsk = quote_string(uqdsk);
217     cmd = stralloc2("DISK ", qdsk);
218     amfree(qdsk);
219     if (converse(cmd) == -1)
220         exit(1);
221     amfree(cmd);
222
223     if (!server_happy()) {
224         amfree(uqmtpt);
225         amfree(uqdsk);
226         return;
227     }
228
229     disk_name = newstralloc(disk_name, uqdsk);
230     if (mtpt == NULL)
231     {
232         /* mount point not specified */
233         if (*uqdsk == '/')
234         {
235             /* disk specified by mount point, hence use it */
236             mount_point = newstralloc(mount_point, uqdsk);
237         }
238         else
239         {
240             /* device name given, use '/' because nothing better */
241             mount_point = newstralloc(mount_point, "/");
242         }
243     }
244     else
245     {
246         /* mount point specified */
247         mount_point = newstralloc(mount_point, uqmtpt);
248     }
249
250     /* set the working directory to the mount point */
251     /* there is the possibility that there are no index records for the
252        disk for the given date, hence setting the directory to the
253        mount point will fail. Preempt this by checking first so we can write
254        a more informative message. */
255     if (exchange("OISD /") == -1)
256         exit(1);
257     if (server_happy())
258     {
259         disk_path = newstralloc(disk_path, "/");
260         disk_tpath = newstralloc(disk_tpath, "/");
261         suck_dir_list_from_server();    /* get list of directory contents */
262     }
263     else
264     {
265         g_printf(_("No index records for disk for specified date\n"));
266         g_printf(_("If date correct, notify system administrator\n"));
267         disk_path = newstralloc(disk_path, "/");        /* fake it */
268         disk_tpath = newstralloc(disk_tpath, "/");      /* fake it */
269         clear_dir_list();
270     }
271     amfree(uqmtpt);
272     amfree(uqdsk);
273
274     if (am_has_feature(indexsrv_features, fe_amindexd_DLE)) {
275         char *dle_str;
276         char *errmsg = NULL;
277
278         cmd = stralloc("DLE");
279         if (exchange(cmd) == -1)
280             exit(1);
281         amfree(cmd);
282
283         if (!server_happy())
284             return;
285
286         dle_str = reply_line();
287         if (BSTRNCMP(dle_str+4, "NODLE") == 0) {
288             dump_dle = NULL;
289         } else {
290             dle_str = unquote_string(dle_str+4);
291             dump_dle = amxml_parse_node_CHAR(dle_str, &errmsg);
292             amfree(dle_str);
293         }
294     }
295 }
296
297 void
298 list_disk(
299     char *      amdevice)
300 {
301     char *cmd = NULL;
302     char *qamdevice, *uqamdevice;
303
304     if(amdevice) {
305         uqamdevice = unquote_string(amdevice);
306         qamdevice = quote_string(uqamdevice);
307         cmd = stralloc2("LISTDISK ", qamdevice);
308         amfree(uqamdevice);
309         amfree(qamdevice);
310         if (converse(cmd) == -1)
311             exit(1);
312         amfree(cmd);
313     }
314     else {
315         cmd = stralloc("LISTDISK");
316         if (converse(cmd) == -1)
317             exit(1);
318         amfree(cmd);
319     }
320 }
321
322 static GSList *prop_values = NULL;
323
324 void
325 set_property_name(
326     char *name,
327     int   append)
328 {
329     property_t *prop;
330     char       *property_name, *pn;
331
332     pn = unquote_string(name);
333     property_name = amandaify_property_name(pn);
334     amfree(pn);
335
336     if (!append) {
337         g_hash_table_remove(proplist, property_name);
338         prop = NULL;
339     } else {
340         prop = g_hash_table_lookup(proplist, property_name);
341     }
342     
343     if (!prop) {
344         prop = malloc(sizeof(property_t));
345         prop->append = 0;
346         prop->priority = 1;
347         prop->values = NULL;
348         g_hash_table_insert(proplist, stralloc(property_name), prop);
349     }
350
351     /* add prop_values to prop->values */
352     if (!prop->values) {
353         prop->values = prop_values;
354         prop_values = NULL;
355     } else {
356         GSList *pv;
357
358         for(pv = prop_values; pv != NULL; pv = pv->next) {
359             prop->values = g_slist_append(prop->values, pv->data);
360         }
361         g_slist_free(prop_values);
362         prop_values = NULL;
363     }
364     amfree(property_name);
365 }
366
367 void
368 add_property_value(
369     char *value)
370 {
371     if (value) {
372         prop_values = g_slist_prepend(prop_values, unquote_string(value));
373     }
374 }
375
376 /* A GHFunc (callback for g_hash_table_foreach) */
377 static void list_one_property(
378     gpointer key_p,
379     gpointer value_p,
380     gpointer user_data_p G_GNUC_UNUSED)
381 {
382     char       *property_s = key_p;
383     char       *qproperty;
384     property_t *property = value_p;
385     GSList     *value;
386     char       *qvalue;
387
388     qproperty = quote_string_always(property_s);
389     printf("property %s", qproperty);
390     amfree(qproperty);
391     for (value = property->values; value != NULL; value = value->next) {
392         qvalue = quote_string_always((char*)value->data);
393         printf(" %s", qvalue);
394         amfree(qvalue);
395     }
396     printf("\n");
397 }
398
399 void
400 list_property(void)
401 {
402     if (proplist) {
403         g_hash_table_foreach(proplist, list_one_property, NULL);
404     } else {
405         printf("No property set\n");
406     }
407 }
408
409 void
410 local_cd(
411     char *dir)
412 {
413     char *uqdir = unquote_string(dir);
414     if (chdir(uqdir) == -1) {
415         perror(uqdir);
416     }
417     amfree(uqdir);
418 }
419
420 int
421 cd_glob(
422     char *      glob,
423     int         verbose)
424 {
425     char *regex;
426     char *regex_path;
427     char *s;
428     char *uqglob;
429     int   result;
430
431     char *tpath_on_disk = NULL;
432
433     if (disk_name == NULL) {
434         g_printf(_("Must select disk before changing directory\n"));
435         return 0;
436     }
437
438     uqglob = unquote_string(glob);
439     regex = glob_to_regex(uqglob);
440     dbprintf(_("cd_glob (%s) -> %s\n"), uqglob, regex);
441     if ((s = validate_regexp(regex)) != NULL) {
442         g_printf(_("\"%s\" is not a valid shell wildcard pattern: "), glob);
443         puts(s);
444         amfree(regex);
445         amfree(uqglob);
446         return 0;
447     }
448     /*
449      * glob_to_regex() anchors the beginning of the pattern with ^,
450      * but we will be tacking it onto the end of the current directory
451      * in add_file, so strip that off.  Also, it anchors the end with
452      * $, but we need to match a trailing /, add it if it is not there
453      */
454     regex_path = stralloc(regex + 1);
455     amfree(regex);
456     if(regex_path[strlen(regex_path) - 2] != '/' ) {
457         regex_path[strlen(regex_path) - 1] = '\0';
458         strappend(regex_path, "/$");
459     }
460
461     /* convert path (assumed in cwd) to one on disk */
462     if (strcmp(disk_path, "/") == 0)
463         tpath_on_disk = stralloc2("/", regex_path);
464     else {
465         char *clean_disk_tpath = clean_regex(disk_tpath, 0);
466         tpath_on_disk = vstralloc(clean_disk_tpath, "/", regex_path, NULL);
467         amfree(clean_disk_tpath);
468     }
469
470     result = cd_dir(tpath_on_disk, uqglob, verbose);
471
472     amfree(regex_path);
473     amfree(tpath_on_disk);
474     amfree(uqglob);
475
476     return result;
477 }
478
479 int
480 cd_regex(
481     char *      regex,
482     int         verbose)
483 {
484     char *s;
485     char *uq_orig_regex;
486     char *uqregex;
487     int  len_uqregex;
488     int  result;
489
490     char *tpath_on_disk = NULL;
491
492     if (disk_name == NULL) {
493         g_printf(_("Must select disk before changing directory\n"));
494         return 0;
495     }
496
497     uq_orig_regex = unquote_string(regex);
498     uqregex = stralloc(uq_orig_regex);
499
500     /* Add a terminating '/' if it is not there, maybe before a '$' */
501     len_uqregex = strlen(uqregex);
502     if (uqregex[len_uqregex-1] == '$') {
503         if (uqregex[len_uqregex-2] != '/') {
504             uqregex[len_uqregex-1] = '\0';
505             strappend(uqregex, "/$");
506         }
507     } else if (uqregex[len_uqregex-1] != '/') {
508         //uqregex[len_uqregex-1] = '\0';
509         strappend(uqregex, "/");
510     }
511     if ((s = validate_regexp(uqregex)) != NULL) {
512         g_printf(_("\"%s\" is not a valid regular expression: "), uq_orig_regex);
513         amfree(uqregex);
514         amfree(uq_orig_regex);
515         puts(s);
516         return 0;
517     }
518
519     /* convert path (assumed in cwd) to one on disk */
520     if (strcmp(disk_path, "/") == 0)
521         tpath_on_disk = stralloc2("/", uqregex);
522     else {
523         char *clean_disk_tpath = clean_regex(disk_tpath, 0);
524         tpath_on_disk = vstralloc(clean_disk_tpath, "/", regex, NULL);
525         amfree(clean_disk_tpath);
526     }
527
528     result = cd_dir(tpath_on_disk, uq_orig_regex, verbose);
529
530     amfree(tpath_on_disk);
531     amfree(uqregex);
532     amfree(uq_orig_regex);
533
534     return result;
535 }
536
537 int
538 cd_dir(
539     char *tpath_on_disk,
540     char *default_dir,
541     int   verbose)
542 {
543     char *dir = NULL;
544     int nb_found;
545     int result;
546     size_t i;
547
548     DIR_ITEM *ditem;
549
550     if (validate_regexp(tpath_on_disk) != NULL) {
551         result = set_directory(default_dir, verbose);
552         return result;
553     }
554
555     nb_found = 0;
556
557     for (ditem=get_dir_list(); ditem!=NULL && nb_found <= 1; 
558                                ditem=get_next_dir_item(ditem))
559     {
560         if (match(tpath_on_disk, ditem->tpath))
561         {
562             i = strlen(ditem->tpath);
563             if((i > 0 && ditem->tpath[i-1] == '/')
564                || (i > 1 && ditem->tpath[i-2] == '/' && ditem->tpath[i-1] == '.'))
565             {   /* It is a directory */
566                 char *dir1, *dir2;
567                 nb_found++;
568                 dir = newstralloc(dir,ditem->path);
569                 if(dir[strlen(dir)-1] == '/')
570                     dir[strlen(dir)-1] = '\0'; /* remove last / */
571                 /* remove everything before the last / */
572                 dir1 = strrchr(dir,'/');
573                 if (dir1) {
574                     dir1++;
575                     dir2 = stralloc(dir1);
576                     amfree(dir);
577                     dir = dir2;
578                 }
579             }
580         }
581     }
582
583     if(nb_found==0) {
584         result = set_directory(default_dir, verbose);
585     }
586     else if(nb_found==1) {
587         result = set_directory(dir, verbose);
588     }
589     else {
590         g_printf(_("Too many directories matching '%s'\n"), default_dir);
591         result = 0;
592     }
593     amfree(dir);
594     return result;
595 }
596
597 /* dir is relative to dir_path or absolute with mount_point */
598 int
599 set_directory(
600     char *      dir,
601     int         verbose)
602 {
603     char *cmd = NULL;
604     char *new_dir = NULL;
605     char *qnew_dir;
606     char *dp, *de;
607     char *ldir = NULL;
608     int   result;
609
610     /* do nothing if "." */
611     if(strcmp(dir,".")==0) {
612         show_directory();               /* say where we are */
613         return 1;
614         /*NOTREACHED*/
615     }
616
617     if (disk_name == NULL) {
618         g_printf(_("Must select disk before setting directory\n"));
619         return 0;
620         /*NOTREACHED*/
621     }
622
623     ldir = stralloc(dir);
624     clean_pathname(ldir);
625
626     /* convert directory into absolute path relative to disk mount point */
627     if (ldir[0] == '/')
628     {
629         /* absolute path specified, must start with mount point */
630         if (strcmp(mount_point, "/") == 0)
631         {
632             new_dir = stralloc(ldir);
633         }
634         else
635         {
636             if (strncmp(mount_point, ldir, strlen(mount_point)) != 0)
637             {
638                 g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
639                        mount_point);
640                 amfree(ldir);
641                 return 0;
642                 /*NOTREACHED*/
643             }
644             new_dir = stralloc(ldir+strlen(mount_point));
645             if (strlen(new_dir) == 0) {
646                 new_dir = newstralloc(new_dir, "/");
647                                         /* i.e. ldir == mount_point */
648             }
649         }
650     }
651     else
652     {
653         new_dir = stralloc(disk_path);
654         dp = ldir;
655         /* strip any leading ..s */
656         while (strncmp(dp, "../", 3) == 0)
657         {
658             de = strrchr(new_dir, '/'); /* always at least 1 */
659             if (de == new_dir)
660             {
661                 /* at top of disk */
662                 *(de + 1) = '\0';
663                 dp = dp + 3;
664             }
665             else
666             {
667                 *de = '\0';
668                 dp = dp + 3;
669             }
670         }
671         if (strcmp(dp, "..") == 0) {
672             if (strcmp(new_dir, "/") == 0) {
673                 /* at top of disk */
674                 g_printf(_("Invalid directory - Can't cd outside mount point \"%s\"\n"),
675                        mount_point);
676                 /*@ignore@*/
677                 amfree(new_dir);
678                 /*@end@*/
679                 amfree(ldir);
680                 return 0;
681                 /*NOTREACHED*/
682             }
683             de = strrchr(new_dir, '/'); /* always at least 1 */
684             if (de == new_dir)
685             {
686                 /* at top of disk */
687                 *(de+1) = '\0';
688             }
689             else
690             {
691                 *de = '\0';
692             }
693         } else {
694             /*@ignore@*/
695             if (strcmp(new_dir, "/") != 0) {
696                 strappend(new_dir, "/");
697             }
698             strappend(new_dir, ldir);
699             /*@end@*/
700         }
701     }
702
703     qnew_dir = quote_string(new_dir);
704     cmd = stralloc2("OISD ", qnew_dir);
705     amfree(qnew_dir);
706     if (exchange(cmd) == -1) {
707         exit(1);
708         /*NOTREACHED*/
709     }
710     amfree(cmd);
711
712     if (server_happy())
713     {
714         disk_path = newstralloc(disk_path, new_dir);
715         g_free(disk_tpath);
716         disk_tpath = translate_octal(g_strdup(disk_path));
717         suck_dir_list_from_server();    /* get list of directory contents */
718         if (verbose)
719             show_directory();           /* say where we moved to */
720         result = 1;
721     }
722     else
723     {
724         g_printf(_("Invalid directory - %s\n"), dir);
725         result = 0;
726     }
727
728     /*@ignore@*/
729     amfree(new_dir);
730     amfree(ldir);
731     /*@end@*/
732
733     return result;
734 }
735
736
737 /* prints the current working directory */
738 void
739 show_directory(void)
740 {
741     if (mount_point == NULL || disk_path == NULL)
742         g_printf(_("Must select disk first\n"));
743     else if (strcmp(mount_point, "/") == 0)
744         g_printf("%s\n", disk_tpath);
745     else if (strcmp(disk_path, "/") == 0)
746         g_printf("%s\n", mount_point);
747     else
748         g_printf("%s%s\n", mount_point, disk_tpath);
749 }
750
751
752 /* set the tape server and device (deprecated version) */
753 void
754 set_tape(
755     char *      tape)
756 {
757     char *uqtape = unquote_string(tape);
758     char *tapedev = strchr(uqtape, ':');
759     char *host = NULL;
760
761     g_printf(_("NOTE: 'settape' is deprecated; use setdevice instead.\n"));
762
763     if (tapedev)
764     {
765         /* This command is deprecated because this parsing is going to fall 
766          * behind the list of available device names at some point, or to shadow
767          * an interesting hostname (wouldn't 'tape' be a good name for a 
768          * tape server?) */
769         if (tapedev != uqtape) {
770             if((strchr(tapedev+1, ':') == NULL) &&
771                (strncmp_const(uqtape, "null:") == 0 ||
772                 strncmp_const(uqtape, "rait:") == 0 ||
773                 strncmp_const(uqtape, "file:") == 0 ||
774                 strncmp_const(uqtape, "s3:") == 0 ||
775                 strncmp_const(uqtape, "tape:") == 0)) {
776                 tapedev = uqtape;
777             }
778             else {
779                 *tapedev = '\0';
780                 host = stralloc(uqtape);
781                 ++tapedev;
782             }
783         } else {
784             ++tapedev;
785         }
786     } else
787         tapedev = uqtape;
788     
789     if (tapedev[0])
790     {
791         if (strcmp(tapedev, "default") == 0)
792             tapedev = NULL;
793     }
794
795     /* call out to the new version */
796     set_device(host, tapedev);
797
798     amfree(host);
799     amfree(uqtape);
800 }
801
802 /* set the tape server and device, for real */
803 void
804 set_device(
805     char *      host,
806     char *      device)
807 {
808     if (host)
809         tape_server_name = newstralloc(tape_server_name, host);
810     else
811         amfree(tape_server_name);
812
813     if (device)
814         tape_device_name = newstralloc(tape_device_name, device);
815     else
816         amfree(tape_device_name);
817
818     /* print the current status */
819     if (tape_device_name)
820         g_printf (_("Using tape \"%s\""), tape_device_name);
821     else
822         g_printf (_("Using default tape"));
823
824     if (tape_server_name)
825         g_printf (_(" from server %s.\n"), tape_server_name);
826     else
827         g_printf (_(".\nTape server unspecified, assumed to be %s.\n"),
828                 server_name);
829 }
830
831 void
832 set_translate(
833     char *translate)
834 {
835
836     if (translate == NULL) {
837         translate_mode = TRUE;
838     } else if (strcasecmp(translate, "yes") == 0 ||
839                strcasecmp(translate, "true") == 0 ||
840                strcasecmp(translate, "on") == 0) {
841         translate_mode = TRUE;
842     } else {
843         translate_mode = FALSE;
844     }
845     suck_dir_list_from_server();        /* get list of directory contents */
846 }
847
848 void
849 set_mode(
850     int         mode)
851 {
852   if (mode == SAMBA_SMBCLIENT) {
853     g_printf (_("SAMBA dumps will be extracted using smbclient\n"));
854     samba_extract_method = SAMBA_SMBCLIENT;
855   } else {
856     if (mode == SAMBA_TAR) {
857       g_printf (_("SAMBA dumps will be extracted as TAR dumps\n"));
858       samba_extract_method = SAMBA_TAR;
859     }
860   }
861 }
862
863 void
864 show_mode(void) 
865 {
866 #ifdef SAMBA_CLIENT
867   g_printf (_("SAMBA dumps are extracted "));
868
869   if (samba_extract_method == SAMBA_TAR) {
870     g_printf (_(" as TAR dumps\n"));
871   } else {
872     g_printf (_("using smbclient\n"));
873   }
874 #endif /* SAMBA_CLIENT */
875 }