42fa544ea4cdea37c7c336a4c76f07c5430f81d8
[debian/amanda] / server-src / diskfile.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-1998 University of Maryland at College Park
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify, distribute, and sell this software and its
7  * documentation for any purpose is hereby granted without fee, provided that
8  * the above copyright notice appear in all copies and that both that
9  * copyright notice and this permission notice appear in supporting
10  * documentation, and that the name of U.M. not be used in advertising or
11  * publicity pertaining to distribution of the software without specific,
12  * written prior permission.  U.M. makes no representations about the
13  * suitability of this software for any purpose.  It is provided "as is"
14  * without express or implied warranty.
15  *
16  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
18  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
20  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
21  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22  *
23  * Author: James da Silva, Systems Design and Analysis Group
24  *                         Computer Science Department
25  *                         University of Maryland at College Park
26  */
27 /*
28  * $Id: diskfile.c,v 1.95 2006/07/26 15:17:37 martinea Exp $
29  *
30  * read disklist file
31  */
32 #include "amanda.h"
33 #include "arglist.h"
34 #include "conffile.h"
35 #include "diskfile.h"
36 #include "util.h"
37 #include "amxml.h"
38
39 static am_host_t *hostlist;
40 static netif_t *all_netifs;
41
42 /* local functions */
43 static char *upcase(char *st);
44 static int parse_diskline(disklist_t *, const char *, FILE *, int *, char **);
45 static void disk_parserror(const char *, int, const char *, ...)
46                             G_GNUC_PRINTF(3, 4);
47
48
49 cfgerr_level_t
50 read_diskfile(
51     const char *filename,
52     disklist_t *lst)
53 {
54     FILE *diskf;
55     int line_num;
56     char *line = NULL;
57
58     /* initialize */
59     hostlist = NULL;
60     lst->head = lst->tail = NULL;
61     line_num = 0;
62
63     /* if we already have config errors, then don't bother */
64     if (config_errors(NULL) >= CFGERR_ERRORS) {
65         return config_errors(NULL);
66     }
67
68     if ((diskf = fopen(filename, "r")) == NULL) {
69         config_add_error(CFGERR_ERRORS,
70             vstrallocf(_("Could not open '%s': %s"), filename, strerror(errno)));
71         goto end;
72         /*NOTREACHED*/
73     }
74
75     while ((line = agets(diskf)) != NULL) {
76         line_num++;
77         if (line[0] != '\0') {
78             if (parse_diskline(lst, filename, diskf, &line_num, &line) < 0) {
79                 goto end;
80             }
81         }
82         amfree(line);
83     }
84
85 end:
86     amfree(line);
87     afclose(diskf);
88     return config_errors(NULL);
89 }
90
91 am_host_t *
92 lookup_host(
93     const char *hostname)
94 {
95     am_host_t *p;
96
97     for (p = hostlist; p != NULL; p = p->next) {
98         if(strcasecmp(p->hostname, hostname) == 0) return p;
99     }
100     return (NULL);
101 }
102
103 disk_t *
104 lookup_disk(
105     const char *hostname,
106     const char *diskname)
107 {
108     am_host_t *host;
109     disk_t *disk;
110
111     host = lookup_host(hostname);
112     if (host == NULL)
113         return (NULL);
114
115     for (disk = host->disks; disk != NULL; disk = disk->hostnext) {
116         if (strcmp(disk->name, diskname) == 0)
117             return (disk);
118     }
119     return (NULL);
120 }
121
122
123 /*
124  * put disk on end of queue
125  */
126
127 void
128 enqueue_disk(
129     disklist_t *list,
130     disk_t *    disk)
131 {
132     if(list->tail == NULL) list->head = disk;
133     else list->tail->next = disk;
134     disk->prev = list->tail;
135
136     list->tail = disk;
137     disk->next = NULL;
138 }
139
140
141 /*
142  * put disk on head of queue
143  */
144
145 void
146 headqueue_disk(
147     disklist_t *list,
148     disk_t *    disk)
149 {
150     if(list->head == NULL) list->tail = disk;
151     else list->head->prev = disk;
152     disk->next = list->head;
153
154     list->head = disk;
155     disk->prev = NULL;
156 }
157
158
159 /*
160  * insert in sorted order
161  */
162
163 void
164 insert_disk(
165     disklist_t *list,
166     disk_t *    disk,
167     int         (*cmp)(disk_t *a, disk_t *b))
168 {
169     disk_t *prev, *ptr;
170
171     prev = NULL;
172     ptr = list->head;
173
174     while(ptr != NULL) {
175         if(cmp(disk, ptr) < 0) break;
176         prev = ptr;
177         ptr = ptr->next;
178     }
179     disk->next = ptr;
180     disk->prev = prev;
181
182     if(prev == NULL) list->head = disk;
183     else prev->next = disk;
184     if(ptr == NULL) list->tail = disk;
185     else ptr->prev = disk;
186 }
187
188 disk_t *
189 add_disk(
190     disklist_t *list,
191     char *      hostname,
192     char *      diskname)
193 {
194     disk_t *disk;
195     am_host_t *host;
196
197     disk = alloc(SIZEOF(disk_t));
198     bzero(disk, SIZEOF(disk_t));
199     disk->line = 0;
200     disk->tape_splitsize = (off_t)0;
201     disk->split_diskbuffer = NULL;
202     disk->fallback_splitsize = (off_t)0;
203     disk->hostname = stralloc(hostname);
204     disk->name = stralloc(diskname);
205     disk->device = stralloc(diskname);
206     disk->spindle = -1;
207     disk->up = NULL;
208     disk->compress = COMP_NONE;
209     disk->encrypt  = ENCRYPT_NONE;
210     disk->start_t = 0;
211     disk->todo = 1;
212     disk->index = 1;
213     disk->exclude_list = NULL;
214     disk->exclude_file = NULL;
215     disk->include_list = NULL;
216     disk->include_file = NULL;
217     disk->application = NULL;
218     disk->pp_scriptlist = NULL;
219
220     host = lookup_host(hostname);
221     if(host == NULL) {
222         host = alloc(SIZEOF(am_host_t));
223         host->next = hostlist;
224         hostlist = host;
225
226         host->hostname = stralloc(hostname);
227         host->disks = NULL;
228         host->inprogress = 0;
229         host->maxdumps = 1;
230         host->netif = NULL;
231         host->start_t = 0;
232         host->up = NULL;
233         host->features = NULL;
234         host->pre_script = 0;
235         host->post_script = 0;
236     }
237     enqueue_disk(list, disk);
238
239     disk->host = host;
240     disk->hostnext = host->disks;
241     host->disks = disk;
242
243     return disk;
244 }
245
246
247 /*
248  * check if disk is present in list. Return true if so, false otherwise.
249  */
250
251 int
252 find_disk(
253     disklist_t *list,
254     disk_t *    disk)
255 {
256     disk_t *t;
257
258     t = list->head;
259     while ((t != NULL) && (t != disk)) {
260         t = t->next;
261     }
262     return (t == disk);
263 }
264
265
266 /*
267  * sort a whole queue
268  */
269
270 void
271 sort_disk(
272     disklist_t *in,
273     disklist_t *out,
274     int         (*cmp)(disk_t *a, disk_t *b))
275 {
276     disklist_t *tmp;
277     disk_t *disk;
278
279     tmp = in;           /* just in case in == out */
280
281     out->head = (disk_t *)0;
282     out->tail = (disk_t *)0;
283
284     while((disk = dequeue_disk(tmp)))
285         insert_disk(out, disk, cmp);
286 }
287
288
289 /*
290  * remove disk from front of queue
291  */
292
293 disk_t *
294 dequeue_disk(
295     disklist_t *list)
296 {
297     disk_t *disk;
298
299     if(list->head == NULL) return NULL;
300
301     disk = list->head;
302     list->head = disk->next;
303
304     if(list->head == NULL) list->tail = NULL;
305     else list->head->prev = NULL;
306
307     disk->prev = disk->next = NULL;     /* for debugging */
308     return disk;
309 }
310
311 void
312 remove_disk(
313     disklist_t *list,
314     disk_t *    disk)
315 {
316     if(disk->prev == NULL) list->head = disk->next;
317     else disk->prev->next = disk->next;
318
319     if(disk->next == NULL) list->tail = disk->prev;
320     else disk->next->prev = disk->prev;
321
322     disk->prev = disk->next = NULL;
323 }
324
325 void
326 free_disklist(
327     disklist_t* dl)
328 {
329     disk_t    *dp;
330     am_host_t *host, *hostnext;
331
332     while (dl->head != NULL) {
333         dp = dequeue_disk(dl);
334         amfree(dp->name);
335         amfree(dp->hostname);
336         amfree(dp->device);
337         free_sl(dp->exclude_file);
338         free_sl(dp->exclude_list);
339         free_sl(dp->include_file);
340         free_sl(dp->include_list);
341         free(dp);
342     }
343
344     for(host=hostlist; host != NULL; host = hostnext) {
345         amfree(host->hostname);
346         am_release_feature_set(host->features);
347         host->features = NULL;
348         hostnext = host->next;
349         amfree(host);
350     }
351     hostlist=NULL;
352 }
353
354 static char *
355 upcase(
356     char *st)
357 {
358     char *s = st;
359
360     while(*s) {
361         if(islower((int)*s)) *s = (char)toupper((int)*s);
362         s++;
363     }
364     return st;
365 }
366
367
368 /* return  0 on success */
369 /* return -1 on error   */
370 static int
371 parse_diskline(
372     disklist_t *lst,
373     const char *filename,
374     FILE *      diskf,
375     int *       line_num_p,
376     /*@keep@*/ char **  line_p)
377 {
378     am_host_t *host;
379     disk_t *disk;
380     dumptype_t *dtype;
381     netif_t *netif = NULL;
382     interface_t *cfg_if = NULL;
383     char *hostname = NULL;
384     char *diskname, *diskdevice;
385     char *dumptype;
386     char *s, *fp;
387     int ch, dup = 0;
388     char *line = *line_p;
389     int line_num = *line_num_p;
390     struct tm *stm;
391     time_t st;
392     char *shost, *sdisk;
393     am_host_t *p;
394     disk_t *dp;
395
396     assert(filename != NULL);
397     assert(line_num > 0);
398     assert(line != NULL);
399
400     s = line;
401     ch = *s++;
402     skip_whitespace(s, ch);
403     if(ch == '\0' || ch == '#')
404         return (0);
405
406     fp = s - 1;
407     skip_non_whitespace(s, ch);
408     s[-1] = '\0';
409     host = lookup_host(fp);
410     if (host == NULL) {
411         hostname = stralloc(fp);
412     } else {
413         hostname = stralloc(host->hostname);
414         if (strcmp(host->hostname, fp) != 0) {
415             disk_parserror(filename, line_num, "Same host with different case: \"%s\" and \"%s\".", host->hostname, fp);
416             return -1;
417         }
418     }
419
420     shost = sanitise_filename(hostname);
421     for (p = hostlist; p != NULL; p = p->next) {
422         char *shostp = sanitise_filename(p->hostname);
423         if (strcmp(hostname, p->hostname) &&
424             !strcmp(shost, shostp)) {
425             disk_parserror(filename, line_num, "Two hosts are mapping to the same name: \"%s\" and \"%s\"", p->hostname, hostname);
426             return(-1);
427         }
428         else if (strcasecmp(hostname, p->hostname) &&
429                  match_host(hostname, p->hostname) &&
430                  match_host(p->hostname, hostname)) {
431             disk_parserror(filename, line_num, _("Duplicate host name: \"%s\" and \"%s\""), p->hostname, hostname);
432             return(-1);
433         }
434         amfree(shostp);
435     }
436     amfree(shost);
437
438     skip_whitespace(s, ch);
439     if(ch == '\0' || ch == '#') {
440         disk_parserror(filename, line_num, _("disk device name expected"));
441         amfree(hostname);
442         return (-1);
443     }
444
445     fp = s - 1;
446     skip_quoted_string(s, ch);
447     s[-1] = '\0';
448     diskname = unquote_string(fp);
449     if (strlen(diskname) == 0) {
450         disk_parserror(filename, line_num, _("invalid empty diskname"));
451         amfree(hostname);
452         return (-1);
453     }
454     skip_whitespace(s, ch);
455     if(ch == '\0' || ch == '#') {
456         disk_parserror(filename, line_num, _("disk dumptype expected"));
457         amfree(hostname);
458         amfree(diskname);
459         return (-1);
460     }
461     fp = s - 1;
462     skip_quoted_string(s, ch);
463     s[-1] = '\0';
464
465     /* diskdevice */
466     dumptype = NULL;
467     diskdevice = NULL;
468     if(fp[0] != '{') {
469         dumptype = unquote_string(fp);
470         if (strlen(dumptype) == 0) {
471             disk_parserror(filename, line_num, _("invalid empty diskdevice"));
472             amfree(hostname);
473             return (-1);
474         }
475         if ((dtype = lookup_dumptype(dumptype)) == NULL) {
476             diskdevice = dumptype;
477             skip_whitespace(s, ch);
478             if(ch == '\0' || ch == '#') {
479                 disk_parserror(filename, line_num,
480                         _("disk dumptype '%s' not found"), dumptype);
481                 amfree(hostname);
482                 amfree(diskdevice);
483                 amfree(diskname);
484                 return (-1);
485             }
486
487             fp = s - 1;
488             skip_quoted_string(s, ch);
489             s[-1] = '\0';
490             if (fp[0] != '{') {
491                 dumptype = unquote_string(fp);
492             }
493         }
494     }
495
496     /* check for duplicate disk */
497     disk = NULL;
498     if (host) {
499         if ((disk = lookup_disk(hostname, diskname)) != NULL) {
500             dup = 1;
501         } else {
502             disk = host->disks;
503             do {
504                 char *a1, *a2;
505                 a1 = clean_regex(diskname);
506                 a2 = clean_regex(disk->name);
507
508                 if (match_disk(a1, disk->name) && match_disk(a2, diskname)) {
509                     dup = 1;
510                 } else {
511                     disk = disk->hostnext;
512                 }
513                 amfree(a1);
514                 amfree(a2);
515             }
516             while (dup == 0 && disk != NULL);
517         }
518         if (dup == 1) {
519             disk_parserror(filename, line_num,
520                            _("duplicate disk record, previous on line %d"),
521                            disk->line);
522         }
523     }
524     if (!disk) {
525         disk = alloc(SIZEOF(disk_t));
526         disk->line = line_num;
527         disk->hostname = stralloc(hostname);
528         disk->name = diskname;
529         disk->device = diskdevice;
530         disk->spindle = -1;
531         disk->up = NULL;
532         disk->inprogress = 0;
533         disk->application = NULL;
534         disk->pp_scriptlist = NULL;
535     }
536
537     if (host) {
538         sdisk = sanitise_filename(diskname);
539         for (dp = host->disks; dp != NULL; dp = dp->hostnext) {
540             char *sdiskp = sanitise_filename(dp->name);
541             if (strcmp(diskname, dp->name) != 0 &&
542                  strcmp(sdisk, sdiskp) == 0) {
543                 disk_parserror(filename, line_num,
544                  _("Two disks are mapping to the same name: \"%s\" and \"%s\"; you must use different diskname"),
545                  dp->name, diskname);
546             return(-1);
547             }
548             amfree(sdiskp);
549         }
550         amfree(sdisk);
551     }
552
553     if (fp[0] == '{') {
554         s[-1] = (char)ch;
555         s = fp+2;
556         skip_whitespace(s, ch);
557         if (ch != '\0' && ch != '#') {
558             disk_parserror(filename, line_num,
559                       _("expected line break after `{\', ignoring rest of line"));
560         }
561
562         if (strchr(s-1, '}') &&
563             (strchr(s-1, '#') == NULL ||
564              strchr(s-1, '}') < strchr(s-1, '#'))) {
565             disk_parserror(filename, line_num,_("'}' on same line than '{'"));
566             amfree(hostname);
567             if(!dup) {
568                 amfree(disk->device);
569                 amfree(disk->name);
570                 amfree(disk);
571             } else {
572                 amfree(diskdevice);
573                 amfree(diskname);
574             }
575             return (-1);
576         }
577         dtype = read_dumptype(vstralloc("custom(", hostname,
578                                         ":", disk->name, ")",
579                                         ".", anonymous_value(), NULL),
580                               diskf, (char*)filename, line_num_p);
581         if (dtype == NULL || dup) {
582             disk_parserror(filename, line_num,
583                            _("read of custom dumptype failed"));
584             amfree(hostname);
585             if(!dup) {
586                 amfree(disk->device);
587                 amfree(disk->name);
588                 amfree(disk);
589             } else {
590                 amfree(diskdevice);
591                 amfree(diskname);
592             }
593             return (-1);
594         }
595         amfree(line);
596
597         *line_p = line = agets(diskf);
598         line_num = *line_num_p; /* no incr, read_dumptype did it already */
599
600         if (line == NULL)
601             *line_p = line = stralloc("");
602         s = line;
603         ch = *s++;
604     } else {
605         if((dtype = lookup_dumptype(dumptype)) == NULL) {
606             char *qdt = quote_string(dumptype);
607
608             disk_parserror(filename, line_num, _("undefined dumptype `%s'"), qdt);
609             amfree(qdt);
610             amfree(dumptype);
611             amfree(hostname);
612             if (!dup) {
613                 amfree(disk->device);
614                 amfree(disk->name);
615                 amfree(disk);
616             } else {
617                 amfree(diskdevice);
618                 amfree(diskname);
619             }
620             return (-1);
621         }
622     }
623
624     if (dup) {
625         /* disk_parserror already called, above */
626         g_assert(config_errors(NULL) != CFGERR_OK);
627         amfree(hostname);
628         amfree(diskdevice);
629         amfree(diskname);
630         return (-1);
631     }
632
633     disk->dtype_name         = dumptype_name(dtype);
634     disk->program            = dumptype_get_program(dtype);
635     disk->exclude_list     = duplicate_sl(dumptype_get_exclude(dtype).sl_list);
636     disk->exclude_file     = duplicate_sl(dumptype_get_exclude(dtype).sl_file);
637     disk->exclude_optional   = dumptype_get_exclude(dtype).optional;
638     disk->include_list     = duplicate_sl(dumptype_get_include(dtype).sl_list);
639     disk->include_file     = duplicate_sl(dumptype_get_include(dtype).sl_file);
640     disk->include_optional   = dumptype_get_include(dtype).optional;
641     disk->priority           = dumptype_get_priority(dtype);
642     disk->dumpcycle          = dumptype_get_dumpcycle(dtype);
643 /*    disk->frequency        = dumptype_get_frequency(dtype);*/
644     disk->security_driver    = dumptype_get_security_driver(dtype);
645     disk->maxdumps           = dumptype_get_maxdumps(dtype);
646     disk->tape_splitsize     = dumptype_get_tape_splitsize(dtype);
647     disk->split_diskbuffer   = dumptype_get_split_diskbuffer(dtype);
648     disk->fallback_splitsize = dumptype_get_fallback_splitsize(dtype);
649     disk->maxpromoteday      = dumptype_get_maxpromoteday(dtype);
650     disk->bumppercent        = dumptype_get_bumppercent(dtype);
651     disk->bumpsize           = dumptype_get_bumpsize(dtype);
652     disk->bumpdays           = dumptype_get_bumpdays(dtype);
653     disk->bumpmult           = dumptype_get_bumpmult(dtype);
654     disk->starttime          = dumptype_get_starttime(dtype);
655     disk->application        = dumptype_get_application(dtype);
656     disk->pp_scriptlist      = dumptype_get_pp_scriptlist(dtype);
657     disk->start_t = 0;
658     if (disk->starttime > 0) {
659         st = time(NULL);
660         disk->start_t = st;
661         stm = localtime(&st);
662         disk->start_t -= stm->tm_sec + 60 * stm->tm_min + 3600 * stm->tm_hour;
663         disk->start_t += disk->starttime / 100 * 3600 +
664                          disk->starttime % 100 * 60;
665         if ((disk->start_t - st) < -43200)
666             disk->start_t += 86400;
667     }
668     disk->strategy           = dumptype_get_strategy(dtype);
669     disk->ignore             = dumptype_get_ignore(dtype);
670     disk->estimate           = dumptype_get_estimate(dtype);
671     disk->compress           = dumptype_get_compress(dtype);
672     disk->srvcompprog        = dumptype_get_srvcompprog(dtype);
673     disk->clntcompprog       = dumptype_get_clntcompprog(dtype);
674     disk->encrypt            = dumptype_get_encrypt(dtype);
675     disk->srv_decrypt_opt    = dumptype_get_srv_decrypt_opt(dtype);
676     disk->clnt_decrypt_opt   = dumptype_get_clnt_decrypt_opt(dtype);
677     disk->srv_encrypt        = dumptype_get_srv_encrypt(dtype);
678     disk->clnt_encrypt       = dumptype_get_clnt_encrypt(dtype);
679     disk->amandad_path       = dumptype_get_amandad_path(dtype);
680     disk->client_username    = dumptype_get_client_username(dtype);
681     disk->ssh_keys           = dumptype_get_ssh_keys(dtype);
682     disk->comprate[0]        = dumptype_get_comprate(dtype)[0];
683     disk->comprate[1]        = dumptype_get_comprate(dtype)[1];
684
685     /*
686      * Boolean parameters with no value (Appears here as value 2) defaults
687      * to TRUE for backward compatibility and for logical consistency.
688      */
689     disk->record             = dumptype_get_record(dtype) != 0;
690     disk->skip_incr          = dumptype_get_skip_incr(dtype) != 0;
691     disk->skip_full          = dumptype_get_skip_full(dtype) != 0;
692     disk->to_holdingdisk     = dumptype_get_to_holdingdisk(dtype);
693     disk->kencrypt           = dumptype_get_kencrypt(dtype) != 0;
694     disk->index              = dumptype_get_index(dtype) != 0; 
695
696     disk->todo               = 1;
697
698     skip_whitespace(s, ch);
699     fp = s - 1;
700     if(ch && ch != '#') {               /* get optional spindle number */
701         char *fp1;
702         int is_digit=1;
703
704         skip_non_whitespace(s, ch);
705         s[-1] = '\0';
706         fp1=fp;
707         if (*fp1 == '-') fp1++;
708         for(;*fp1!='\0';fp1++) {
709             if(!isdigit((int)*fp1)) {
710                 is_digit = 0;
711             }
712         }
713         if(is_digit == 0) {
714             disk_parserror(filename, line_num, _("non-integer spindle `%s'"), fp);
715             amfree(hostname);
716             amfree(disk->name);
717             amfree(disk);
718             return (-1);
719         }
720         disk->spindle = atoi(fp);
721         skip_integer(s, ch);
722     }
723
724     skip_whitespace(s, ch);
725     fp = s - 1;
726     if(ch && ch != '#') {               /* get optional network interface */
727         skip_non_whitespace(s, ch);
728         s[-1] = '\0';
729         if((cfg_if = lookup_interface(upcase(fp))) == NULL) {
730             disk_parserror(filename, line_num,
731                 _("undefined network interface `%s'"), fp);
732             amfree(hostname);
733             amfree(disk->name);
734             amfree(disk);
735             return (-1);
736         }
737     } else {
738         cfg_if = lookup_interface("default");
739     }
740
741     /* see if we already have a netif_t for this interface */
742     for (netif = all_netifs; netif != NULL; netif = netif->next) {
743         if (netif->config == cfg_if)
744             break;
745     }
746
747     /* nope; make up a new one */
748     if (!netif) {
749         netif = alloc(sizeof(*netif));
750         netif->next = all_netifs;
751         all_netifs = netif;
752         netif->config = cfg_if;
753         netif->curusage = 0;
754     }
755
756     skip_whitespace(s, ch);
757     if(ch && ch != '#') {               /* now we have garbage, ignore it */
758         disk_parserror(filename, line_num, _("end of line expected"));
759     }
760
761     if (disk->program && disk->application &&
762         strcmp(disk->program,"APPLICATION")) {
763         disk_parserror(filename, line_num,
764                        _("Both program and application set"));
765     }
766
767     if (disk->program && strcmp(disk->program,"APPLICATION")==0 &&
768         !disk->application) {
769         disk_parserror(filename, line_num,
770                        _("program set to APPLICATION but no application set"));
771     }
772
773     if(dumptype_get_ignore(dtype) || dumptype_get_strategy(dtype) == DS_SKIP) {
774         disk->todo = 0;
775     }
776
777     /* success, add disk to lists */
778
779     if(host == NULL) {                  /* new host */
780         host = alloc(SIZEOF(am_host_t));
781         host->next = hostlist;
782         hostlist = host;
783
784         host->hostname = hostname;
785         hostname = NULL;
786         host->disks = NULL;
787         host->inprogress = 0;
788         host->maxdumps = 1;             /* will be overwritten */
789         host->netif = NULL;
790         host->start_t = 0;
791         host->up = NULL;
792         host->features = NULL;
793         host->pre_script = 0;
794         host->post_script = 0;
795     } else {
796         amfree(hostname);
797     }
798
799     host->netif = netif;
800
801     enqueue_disk(lst, disk);
802
803     disk->host = host;
804     disk->hostnext = host->disks;
805     host->disks = disk;
806     host->maxdumps = disk->maxdumps;
807
808     return (0);
809 }
810
811
812 printf_arglist_function2(void disk_parserror, const char *, filename,
813     int, line_num, const char *, format)
814 {
815     va_list argp;
816     char * msg;
817     char * errstr;
818
819     /* format the error message and hand it off to conffile */
820
821     arglist_start(argp, format);
822     msg = g_strdup_vprintf(format, argp);
823     errstr = g_strdup_printf("\"%s\", line %d: %s", filename, line_num, msg);
824     amfree(msg);
825     arglist_end(argp);
826
827     config_add_error(CFGERR_ERRORS, errstr);
828 }
829
830
831 void
832 dump_queue(
833     char *      st,
834     disklist_t  q,
835     int         npr,    /* we print first npr disks on queue, plus last two */
836     FILE *      f)
837 {
838     disk_t *d,*p;
839     int pos;
840     char *qname;
841
842     if(empty(q)) {
843         g_fprintf(f, _("%s QUEUE: empty\n"), st);
844         return;
845     }
846     g_fprintf(f, _("%s QUEUE:\n"), st);
847     for(pos = 0, d = q.head, p = NULL; d != NULL; p = d, d = d->next, pos++) {
848         qname = quote_string(d->name);
849         if(pos < npr) g_fprintf(f, "%3d: %-10s %-4s\n",
850                               pos, d->host->hostname, qname);
851         amfree(qname);
852     }
853     if(pos > npr) {
854         if(pos > npr+2) g_fprintf(f, "  ...\n");
855         if(pos > npr+1) {
856             d = p->prev;
857             g_fprintf(f, "%3d: %-10s %-4s\n", pos-2, d->host->hostname, d->name);
858         }
859         d = p;
860         g_fprintf(f, "%3d: %-10s %-4s\n", pos-1, d->host->hostname, d->name);
861     }
862 }
863
864 char *
865 optionstr(
866     disk_t *            dp,
867     am_feature_t *      their_features,
868     FILE *              fdout)
869 {
870     char *auth_opt = NULL;
871     char *kencrypt_opt = "";
872     char *compress_opt = "";
873     char *encrypt_opt = stralloc("");
874     char *decrypt_opt = stralloc("");
875     char *record_opt = "";
876     char *index_opt = "";
877     char *exclude_file = NULL;
878     char *exclude_list = NULL;
879     char *include_file = NULL;
880     char *include_list = NULL;
881     char *excl_opt = "";
882     char *incl_opt = "";
883     char *exc = NULL;
884     char *result = NULL;
885     sle_t *excl;
886     int nb_exclude_file;
887     int nb_include_file;
888     char *qdpname;
889     char *qname;
890     int err=0;
891
892     assert(dp != NULL);
893     assert(dp->host != NULL);
894
895     qdpname = quote_string(dp->name);
896     if(am_has_feature(dp->host->features, fe_options_auth)) {
897         auth_opt = vstralloc("auth=", dp->security_driver, ";", NULL);
898     } else if(strcasecmp(dp->security_driver, "bsd") == 0) {
899         if(am_has_feature(dp->host->features, fe_options_bsd_auth))
900             auth_opt = stralloc("bsd-auth;");
901         else if(fdout) {
902             g_fprintf(fdout,
903                     _("WARNING: %s:%s does not support auth or bsd-auth\n"),
904                     dp->host->hostname, qdpname);
905         }
906     } else if(strcasecmp(dp->security_driver, "krb4") == 0) {
907         if(am_has_feature(dp->host->features, fe_options_krb4_auth))
908             auth_opt = stralloc("krb4-auth;");
909         else if(fdout) {
910             g_fprintf(fdout,
911                     _("WARNING: %s:%s does not support auth or krb4-auth\n"),
912                     dp->host->hostname, qdpname);
913         }
914         if(dp->kencrypt) {
915             if(am_has_feature(dp->host->features, fe_options_kencrypt)) {
916                 kencrypt_opt = "kencrypt;";
917             }
918             else if(fdout) {
919             g_fprintf(fdout,
920                     _("WARNING: %s:%s does not support kencrypt\n"),
921                     dp->host->hostname, qdpname);
922             }
923         }
924     }
925
926     switch(dp->compress) {
927     case COMP_FAST:
928         if(am_has_feature(their_features, fe_options_compress_fast)) {
929             compress_opt = "compress-fast;";
930         }
931         else if(fdout) {
932             g_fprintf(fdout,
933                     _("WARNING: %s:%s does not support fast compression\n"),
934                     dp->host->hostname, qdpname);
935         }
936         break;
937     case COMP_BEST:
938         if(am_has_feature(their_features, fe_options_compress_best)) {
939             compress_opt = "compress-best;";
940         }
941         else if(fdout) {
942             g_fprintf(fdout,
943                     _("WARNING: %s:%s does not support best compression\n"),
944                     dp->host->hostname, qdpname);
945         }
946         break;
947     case COMP_CUST:
948         if(am_has_feature(their_features, fe_options_compress_cust)) {
949           compress_opt = vstralloc("comp-cust=", dp->clntcompprog, ";", NULL);
950           if (BSTRNCMP(compress_opt, "comp-cust=;") == 0){
951             if(fdout) {
952               g_fprintf(fdout,
953                       _("ERROR: %s:%s client custom compression with no compression program specified\n"),
954                       dp->host->hostname, qdpname);
955             }
956             err++;
957           }
958         }
959         else if(fdout) {
960             g_fprintf(fdout,
961                     _("WARNING: %s:%s does not support client custom compression\n"),
962                     dp->host->hostname, qdpname);
963         }
964         break;
965     case COMP_SERVER_FAST:
966         if(am_has_feature(their_features, fe_options_srvcomp_fast)) {
967             compress_opt = "srvcomp-fast;";
968         }
969         break;
970     case COMP_SERVER_BEST:
971         if(am_has_feature(their_features, fe_options_srvcomp_best)) {
972             compress_opt = "srvcomp-best;";
973         }
974         break;
975     case COMP_SERVER_CUST:
976         if(am_has_feature(their_features, fe_options_srvcomp_cust)) {
977           compress_opt = vstralloc("srvcomp-cust=", dp->srvcompprog, ";", NULL);
978           if (BSTRNCMP(compress_opt, "srvcomp-cust=;") == 0){
979             if(fdout) {
980               g_fprintf(fdout,
981                       _("ERROR: %s:%s server custom compression with no compression program specified\n"),
982                       dp->host->hostname, qdpname);
983             }
984             err++;
985           }
986         }
987         else if(fdout) {
988           g_fprintf(fdout,
989                   _("WARNING: %s:%s does not support server custom compression\n"),
990                   dp->host->hostname, qdpname);
991         }
992         break;
993     }
994
995     switch(dp->encrypt) {
996     case ENCRYPT_CUST:
997       if(am_has_feature(their_features, fe_options_encrypt_cust)) {
998          encrypt_opt = newvstralloc(encrypt_opt, "encrypt-cust=",
999                                     dp->clnt_encrypt, ";", NULL);
1000          if (BSTRNCMP(encrypt_opt, "encrypt-cust=;") == 0) {
1001             if(fdout) {
1002               g_fprintf(fdout,
1003                       _("ERROR: %s:%s encrypt client with no encryption program specified\n"),
1004                       dp->host->hostname, qdpname);
1005             }
1006             err++;
1007           }
1008          if ( dp->compress == COMP_SERVER_FAST || 
1009               dp->compress == COMP_SERVER_BEST ||
1010               dp->compress == COMP_SERVER_CUST ) {
1011            if(fdout) {
1012               g_fprintf(fdout,
1013                       _("ERROR: %s:Client encryption with server compression is "
1014                         "not supported. See amanda.conf(5) for detail.\n"), 
1015                         dp->host->hostname);
1016             }
1017             err++;
1018           }
1019          if(dp->clnt_decrypt_opt) {
1020            if(am_has_feature(their_features, fe_options_client_decrypt_option)) {
1021              decrypt_opt = newvstralloc(decrypt_opt, "client-decrypt-option=",
1022                                         dp->clnt_decrypt_opt, ";", NULL);
1023            }
1024            else if(fdout) {
1025             g_fprintf(fdout,
1026                     _("WARNING: %s:%s does not support client decrypt option\n"),
1027                     dp->host->hostname, qdpname);
1028            }
1029          }
1030       }
1031       else if(fdout) {
1032             g_fprintf(fdout,
1033                     _("WARNING: %s:%s does not support client data encryption\n"),
1034                     dp->host->hostname, qdpname);
1035      }
1036          break;
1037     case ENCRYPT_SERV_CUST:
1038       if(am_has_feature(their_features, fe_options_encrypt_serv_cust)) {
1039          encrypt_opt = newvstralloc(encrypt_opt, "encrypt-serv-cust=",
1040                                     dp->srv_encrypt, ";", NULL);
1041          if (BSTRNCMP(encrypt_opt, "encrypt-serv-cust=;") == 0){
1042             if(fdout) {
1043               g_fprintf(fdout,
1044                       _("ERROR: %s:%s No encryption program specified in dumptypes\n"),
1045                       dp->host->hostname, qdpname);
1046               g_fprintf(fdout, _("Change the dumptype in the disklist or mention "
1047                                "the ecnryption program to use in the dumptypes file\n"));
1048
1049             }
1050             err++;
1051           }
1052          if(dp->srv_decrypt_opt) {
1053            if(am_has_feature(their_features, fe_options_server_decrypt_option)) {
1054              decrypt_opt = newvstralloc(decrypt_opt, "server-decrypt-option=",
1055                                         dp->srv_decrypt_opt, ";", NULL);
1056            }
1057            else if(fdout) {
1058             g_fprintf(fdout,
1059                     _("WARNING: %s:%s client version does not support server data decryption\n"),
1060                     dp->host->hostname, qdpname);
1061            }
1062          }
1063       }
1064       else if(fdout) {
1065             g_fprintf(fdout,
1066                     _("WARNING: %s:%s client version does not support server data encryption\n"),
1067                     dp->host->hostname, qdpname);
1068       }
1069          break;
1070     }
1071     
1072     if(!dp->record) {
1073         if(am_has_feature(their_features, fe_options_no_record)) {
1074             record_opt = "no-record;";
1075         }
1076         else if(fdout) {
1077             g_fprintf(fdout, _("WARNING: %s:%s does not support no record\n"),
1078                     dp->host->hostname, qdpname);
1079         }
1080     }
1081
1082     if(dp->index) {
1083         if(am_has_feature(their_features, fe_options_index)) {
1084             index_opt = "index;";
1085         }
1086         else if(fdout) {
1087             g_fprintf(fdout, _("WARNING: %s:%s does not support index\n"),
1088                     dp->host->hostname, qdpname);
1089         }
1090     }
1091
1092     if(dp->kencrypt) kencrypt_opt = "kencrypt;";
1093
1094
1095     exclude_file = stralloc("");
1096     nb_exclude_file = 0;
1097     if(dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
1098         nb_exclude_file = dp->exclude_file->nb_element;
1099         if(am_has_feature(their_features, fe_options_exclude_file)) {
1100             if(am_has_feature(their_features, fe_options_multiple_exclude) ||
1101                dp->exclude_file->nb_element == 1) {
1102                 for(excl = dp->exclude_file->first; excl != NULL;
1103                                                     excl = excl->next) {
1104                     qname = quote_string(excl->name);
1105                     exc = newvstralloc( exc, "exclude-file=", qname, ";", NULL);
1106                     strappend(exclude_file, exc);
1107                     amfree(qname);
1108                 }
1109             } else {
1110                 qname = quote_string(dp->exclude_file->last->name);
1111                 exc = newvstralloc(exc, "exclude-file=", qname, ";", NULL);
1112                 strappend(exclude_file, exc);
1113                 if(fdout) {
1114                     g_fprintf(fdout,
1115                        _("WARNING: %s:%s does not support multiple exclude\n"),
1116                        dp->host->hostname, qdpname);
1117                 }
1118                 amfree(qname);
1119             }
1120         } else if(fdout) {
1121             g_fprintf(fdout, _("WARNING: %s:%s does not support exclude file\n"),
1122                     dp->host->hostname, qdpname);
1123         }
1124     }
1125     exclude_list = stralloc("");
1126     if(dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) {
1127         if(am_has_feature(their_features, fe_options_exclude_list)) {
1128             if(am_has_feature(their_features, fe_options_multiple_exclude) ||
1129                (dp->exclude_list->nb_element == 1 && nb_exclude_file == 0)) {
1130                 for(excl = dp->exclude_list->first; excl != NULL;
1131                                                     excl = excl->next) {
1132                     qname = quote_string(excl->name);
1133                     exc = newvstralloc( exc, "exclude-list=", qname, ";", NULL);
1134                     strappend(exclude_list, exc);
1135                     amfree(qname);
1136                 }
1137             } else {
1138                 qname = quote_string(dp->exclude_list->last->name);
1139                 exc = newvstralloc(exc, "exclude-list=", qname, ";", NULL);
1140                 strappend(exclude_list, exc);
1141                 if(fdout) {
1142                         g_fprintf(fdout,
1143                          _("WARNING: %s:%s does not support multiple exclude\n"),
1144                          dp->host->hostname, qdpname);
1145                 }
1146                 amfree(qname);
1147             }
1148         } else if(fdout) {
1149             g_fprintf(fdout, _("WARNING: %s:%s does not support exclude list\n"),
1150                     dp->host->hostname, qdpname);
1151         }
1152     }
1153
1154     include_file = stralloc("");
1155     nb_include_file = 0;
1156     if(dp->include_file != NULL && dp->include_file->nb_element > 0) {
1157         nb_include_file = dp->include_file->nb_element;
1158         if(am_has_feature(their_features, fe_options_include_file)) {
1159             if(am_has_feature(their_features, fe_options_multiple_include) ||
1160                dp->include_file->nb_element == 1) {
1161                 for(excl = dp->include_file->first; excl != NULL;
1162                                                     excl = excl->next) {
1163                     qname = quote_string(excl->name);
1164                     exc = newvstralloc(exc, "include-file=", qname, ";", NULL);
1165                     strappend(include_file, exc);
1166                     amfree(qname);
1167                 }
1168             } else {
1169                 qname = quote_string(dp->include_file->last->name);
1170                 exc = newvstralloc(exc, "include-file=", qname, ";", NULL);
1171                 strappend(include_file, exc);
1172                 if(fdout) {
1173                     g_fprintf(fdout,
1174                          _("WARNING: %s:%s does not support multiple include\n"),
1175                          dp->host->hostname, qdpname);
1176                 }
1177                 amfree(qname);
1178             }
1179         } else if(fdout) {
1180             g_fprintf(fdout, _("WARNING: %s:%s does not support include file\n"),
1181                     dp->host->hostname, qdpname);
1182         }
1183     }
1184     include_list = stralloc("");
1185     if(dp->include_list != NULL && dp->include_list->nb_element > 0) {
1186         if(am_has_feature(their_features, fe_options_include_list)) {
1187             if(am_has_feature(their_features, fe_options_multiple_include) ||
1188                (dp->include_list->nb_element == 1 && nb_include_file == 0)) {
1189                 for(excl = dp->include_list->first; excl != NULL;
1190                                                     excl = excl->next) {
1191                     qname = quote_string(excl->name);
1192                     exc = newvstralloc(exc, "include-list=", qname, ";", NULL);
1193                     strappend(include_list, exc);
1194                     amfree(qname);
1195                 }
1196             } else {
1197                 qname = quote_string(dp->include_list->last->name);
1198                 exc = newvstralloc(exc, "include-list=", qname, ";", NULL);
1199                 strappend(include_list, exc);
1200                 if(fdout) {
1201                         g_fprintf(fdout,
1202                          _("WARNING: %s:%s does not support multiple include\n"),
1203                          dp->host->hostname, qdpname);
1204                 }
1205                 amfree(qname);
1206             }
1207         } else if(fdout) {
1208             g_fprintf(fdout, _("WARNING: %s:%s does not support include list\n"),
1209                     dp->host->hostname, qdpname);
1210         }
1211     }
1212
1213     if(dp->exclude_optional) {
1214         if(am_has_feature(their_features, fe_options_optional_exclude)) {
1215             excl_opt = "exclude-optional;";
1216         }
1217         else if(fdout) {
1218             g_fprintf(fdout,
1219                     _("WARNING: %s:%s does not support optional exclude\n"),
1220                     dp->host->hostname, qdpname);
1221         }
1222     }
1223     if(dp->include_optional) {
1224         if(am_has_feature(their_features, fe_options_optional_include)) {
1225            incl_opt = "include-optional;";
1226         }
1227         else if(fdout) {
1228             g_fprintf(fdout,
1229                     _("WARNING: %s:%s does not support optional include\n"),
1230                     dp->host->hostname, qdpname);
1231         }
1232     }
1233
1234     result = vstralloc(";",
1235                        auth_opt,
1236                        kencrypt_opt,
1237                        compress_opt,
1238                        encrypt_opt,
1239                        decrypt_opt,
1240                        record_opt,
1241                        index_opt,
1242                        exclude_file,
1243                        exclude_list,
1244                        include_file,
1245                        include_list,
1246                        excl_opt,
1247                        incl_opt,
1248                        NULL);
1249     amfree(qdpname);
1250     amfree(auth_opt);
1251     amfree(exclude_list);
1252     amfree(exclude_file);
1253     amfree(include_file);
1254     amfree(include_list);
1255     amfree(exc);
1256     amfree(decrypt_opt);
1257     amfree(encrypt_opt);
1258
1259     /* result contains at least 'auth=...' */
1260     if ( err ) {
1261         amfree(result);
1262         return NULL;
1263     } else {
1264         return result;
1265     }
1266 }
1267
1268  
1269 char *
1270 xml_optionstr(
1271     disk_t *            dp,
1272     am_feature_t *      their_features,
1273     FILE *              fdout,
1274     int                 to_server)
1275 {
1276     char *auth_opt = stralloc("");
1277     char *kencrypt_opt = stralloc("");
1278     char *compress_opt = stralloc("");
1279     char *encrypt_opt = stralloc("");
1280     char *decrypt_opt = stralloc("");
1281     char *record_opt = stralloc("");
1282     char *index_opt = stralloc("");
1283     char *exclude = stralloc("");
1284     char *exclude_file = NULL;
1285     char *exclude_list = NULL;
1286     char *include = stralloc("");
1287     char *include_file = NULL;
1288     char *include_list = NULL;
1289     char *excl_opt = "";
1290     char *incl_opt = "";
1291     char *exc = NULL;
1292     char *script_opt;
1293     char *result = NULL;
1294     sle_t *excl;
1295     int nb_exclude_file;
1296     int nb_include_file;
1297     char *qdpname;
1298     char *q64name;
1299     int err=0;
1300
1301     assert(dp != NULL);
1302     assert(dp->host != NULL);
1303
1304     qdpname = quote_string(dp->name);
1305     if(am_has_feature(dp->host->features, fe_options_auth)) {
1306         auth_opt = vstralloc("  <auth>", dp->security_driver, "</auth>\n", NULL);
1307     } else if(fdout) {
1308         fprintf(fdout,
1309                 _("WARNING: %s:%s does not support auth\n"),
1310                 dp->host->hostname, qdpname);
1311     }
1312
1313     switch(dp->compress) {
1314     case COMP_FAST:
1315         if(am_has_feature(their_features, fe_options_compress_fast)) {
1316             compress_opt = "  <compress>FAST</compress>\n";
1317         }
1318         else if(fdout) {
1319             fprintf(fdout,
1320                     _("WARNING: %s:%s does not support fast compression\n"),
1321                     dp->host->hostname, qdpname);
1322         }
1323         break;
1324     case COMP_BEST:
1325         if(am_has_feature(their_features, fe_options_compress_best)) {
1326             compress_opt = "  <compress>BEST</compress>\n";
1327         }
1328         else if(fdout) {
1329             fprintf(fdout,
1330                     _("WARNING: %s:%s does not support best compression\n"),
1331                     dp->host->hostname, qdpname);
1332         }
1333         break;
1334     case COMP_CUST:
1335         if(am_has_feature(their_features, fe_options_compress_cust)) {
1336             if (dp->clntcompprog == NULL) {
1337                 if(fdout) {
1338                     fprintf(fdout,
1339                             _("ERROR: %s:%s client custom compression with no compression program specified\n"),
1340                             dp->host->hostname, qdpname);
1341                     }
1342                 err++;
1343             } else {
1344
1345                 compress_opt = vstralloc("  <compress>CUSTOM"
1346                                          "<custom-compress-program>",
1347                                          dp->clntcompprog,
1348                                          "</custom-compress-program>\n"
1349                                          "  </compress>\n", NULL);
1350             }
1351         }
1352         else if(fdout) {
1353             fprintf(fdout,
1354                     _("WARNING: %s:%s does not support client custom compression\n"),
1355                     dp->host->hostname, qdpname);
1356         }
1357         break;
1358     case COMP_SERVER_FAST:
1359         compress_opt = "  <compress>SERVER-FAST</compress>\n";
1360         break;
1361     case COMP_SERVER_BEST:
1362         compress_opt = "  <compress>SERVER-BEST</compress>\n";
1363         break;
1364     case COMP_SERVER_CUST:
1365         compress_opt = "  <compress>SERVER-CUSTOM</compress>\n";
1366         if (dp->srvcompprog == NULL) {
1367             if(fdout) {
1368                 fprintf(fdout,
1369                         _("ERROR: %s:%s server custom compression with no compression program specified\n"),
1370                         dp->host->hostname, qdpname);
1371             }
1372             err++;
1373         } else {
1374             compress_opt = vstralloc("  <compress>SERVER-CUSTOM"
1375                                      "<custom-compress-program>",
1376                                      dp->srvcompprog,
1377                                      "</custom-compress-program>\n"
1378                                      "  </compress>\n", NULL);
1379         }
1380         break;
1381     }
1382
1383     switch(dp->encrypt) {
1384     case ENCRYPT_CUST:
1385         if(am_has_feature(their_features, fe_options_encrypt_cust)) {
1386             if(dp->clnt_decrypt_opt) {
1387                 if(am_has_feature(their_features, fe_options_client_decrypt_option)) {
1388                     decrypt_opt = newvstralloc(decrypt_opt,
1389                                                "    <decrypt-option>",
1390                                                dp->clnt_decrypt_opt,
1391                                                "</decrypt-option>\n", NULL);
1392                 } else if(fdout) {
1393                     fprintf(fdout,
1394                             _("WARNING: %s:%s does not support client decrypt option\n"),
1395                             dp->host->hostname, qdpname);
1396                 }
1397             }
1398             if (dp->clnt_encrypt == NULL) {
1399                 if(fdout) {
1400                     fprintf(fdout,
1401                             _("ERROR: %s:%s encrypt client with no encryption program specified\n"),
1402                             dp->host->hostname, qdpname);
1403                 }
1404                 err++;
1405             } else if (decrypt_opt) {
1406                  encrypt_opt = newvstralloc(encrypt_opt,
1407                                             "  <encrypt>CUSTOM"
1408                                             "<custom-encrypt-program>",
1409                                             dp->clnt_encrypt,
1410                                             "</custom-encrypt-program>\n",
1411                                             decrypt_opt,
1412                                             "  </encrypt>\n", NULL);
1413             }
1414             if (dp->compress == COMP_SERVER_FAST || 
1415                 dp->compress == COMP_SERVER_BEST ||
1416                 dp->compress == COMP_SERVER_CUST ) {
1417                 if(fdout) {
1418                     fprintf(fdout,
1419                             _("ERROR: %s:Client encryption with server compression is "
1420                             "not supported. See amanda.conf(5) for detail.\n"),
1421                             dp->host->hostname);
1422                 }
1423                 err++;
1424             }
1425         } else if(fdout) {
1426             fprintf(fdout,
1427                     _("WARNING: %s:%s does not support client data encryption\n"),
1428                     dp->host->hostname, qdpname);
1429         }
1430         break;
1431     case ENCRYPT_SERV_CUST:
1432         if (dp->srv_encrypt != NULL && to_server) {
1433             decrypt_opt =  newvstralloc(decrypt_opt,
1434                                         "    <decrypt-option>",
1435                                         dp->srv_decrypt_opt, 
1436                                         "</decrypt-option>\n", NULL);
1437             encrypt_opt = newvstralloc(encrypt_opt,
1438                                        "  <encrypt>SERVER-CUSTOM"
1439                                        "<custom-encrypt-program>",
1440                                        dp->srv_encrypt,
1441                                        "</custom-encrypt-program>\n",
1442                                        decrypt_opt,
1443                                        "  </encrypt>\n", NULL);
1444         } else if (dp->srv_encrypt == NULL) {
1445             if(fdout) {
1446                 fprintf(fdout,
1447                         _("ERROR: %s:%s No encryption program specified in dumptypes\n"),
1448                         dp->host->hostname, qdpname);
1449                 fprintf(fdout,
1450                          _("Change the dumptype in the disklist or mention "
1451                         "the encryption program to use in the dumptypes file\n"));
1452             }
1453             err++;
1454         }
1455         break;
1456     }
1457     
1458     if(!dp->record) {
1459         if(am_has_feature(their_features, fe_options_no_record)) {
1460             record_opt = "  <record>NO</record>\n";
1461         }
1462         else if(fdout) {
1463             fprintf(fdout, _("WARNING: %s:%s does not support no record\n"),
1464                     dp->host->hostname, qdpname);
1465         }
1466     } else {
1467         record_opt = "  <record>YES</record>\n";
1468     }
1469
1470     if(dp->index) {
1471         if(am_has_feature(their_features, fe_options_index)) {
1472             index_opt = "  <index>YES</index>\n";
1473         }
1474         else if(fdout) {
1475             fprintf(fdout, _("WARNING: %s:%s does not support index\n"),
1476                     dp->host->hostname, qdpname);
1477         }
1478     }
1479
1480     if(dp->kencrypt) {
1481         if(am_has_feature(their_features, fe_options_kencrypt)) {
1482             kencrypt_opt = "  <kencrypt>YES</kencrypt>\n";
1483         }
1484         else if(fdout) {
1485             fprintf(fdout, _("WARNING: %s:%s does not support kencrypt\n"),
1486                     dp->host->hostname, qdpname);
1487         }
1488     }
1489
1490     exclude_file = stralloc("");
1491     nb_exclude_file = 0;
1492     if(dp->exclude_file != NULL && dp->exclude_file->nb_element > 0) {
1493         nb_exclude_file = dp->exclude_file->nb_element;
1494         if(am_has_feature(their_features, fe_options_exclude_file)) {
1495             if(am_has_feature(their_features, fe_options_multiple_exclude) ||
1496                dp->exclude_file->nb_element == 1) {
1497                 for(excl = dp->exclude_file->first; excl != NULL;
1498                                                     excl = excl->next) {
1499                     q64name = amxml_format_tag("file", excl->name);
1500                     exc = newvstralloc( exc, "    ", q64name, "\n", NULL);
1501                     strappend(exclude_file, exc);
1502                     amfree(q64name);
1503                 }
1504             } else {
1505                 q64name = amxml_format_tag("file", dp->exclude_file->last->name);
1506                 exc = newvstralloc(exc, "    ", q64name, "\n", NULL);
1507                 strappend(exclude_file, exc);
1508                 if(fdout) {
1509                     fprintf(fdout,
1510                        _("WARNING: %s:%s does not support multiple exclude\n"),
1511                        dp->host->hostname, qdpname);
1512                 }
1513                 amfree(q64name);
1514             }
1515         } else if(fdout) {
1516             fprintf(fdout, _("WARNING: %s:%s does not support exclude file\n"),
1517                     dp->host->hostname, qdpname);
1518         }
1519     }
1520     exclude_list = stralloc("");
1521     if(dp->exclude_list != NULL && dp->exclude_list->nb_element > 0) {
1522         if(am_has_feature(their_features, fe_options_exclude_list)) {
1523             if(am_has_feature(their_features, fe_options_multiple_exclude) ||
1524                (dp->exclude_list->nb_element == 1 && nb_exclude_file == 0)) {
1525                 for(excl = dp->exclude_list->first; excl != NULL;
1526                                                     excl = excl->next) {
1527                     q64name = amxml_format_tag("list", excl->name);
1528                     exc = newvstralloc(exc, "    ", q64name, "\n", NULL);
1529                     strappend(exclude_list, exc);
1530                     amfree(q64name);
1531                 }
1532             } else {
1533                 q64name = amxml_format_tag("list", dp->exclude_list->last->name);
1534                 exc = newvstralloc(exc, "    ", q64name, "\n", NULL);
1535                 strappend(exclude_list, exc);
1536                 if(fdout) {
1537                         fprintf(fdout,
1538                          _("WARNING: %s:%s does not support multiple exclude\n"),
1539                          dp->host->hostname, qdpname);
1540                 }
1541                 amfree(q64name);
1542             }
1543         } else if(fdout) {
1544             fprintf(fdout, _("WARNING: %s:%s does not support exclude list\n"),
1545                     dp->host->hostname, qdpname);
1546         }
1547     }
1548
1549     include_file = stralloc("");
1550     nb_include_file = 0;
1551     if(dp->include_file != NULL && dp->include_file->nb_element > 0) {
1552         nb_include_file = dp->include_file->nb_element;
1553         if(am_has_feature(their_features, fe_options_include_file)) {
1554             if(am_has_feature(their_features, fe_options_multiple_include) ||
1555                dp->include_file->nb_element == 1) {
1556                 for(excl = dp->include_file->first; excl != NULL;
1557                                                     excl = excl->next) {
1558                     q64name = amxml_format_tag("file", excl->name);
1559                     exc = newvstralloc( exc, "    ", q64name, "\n", NULL);
1560                     strappend(include_file, exc);
1561                     amfree(q64name);
1562                 }
1563             } else {
1564                 q64name = amxml_format_tag("file", dp->include_file->last->name);
1565                 exc = newvstralloc(exc, "    ", q64name, "\n", NULL);
1566                 strappend(include_file, exc);
1567                 if(fdout) {
1568                     fprintf(fdout,
1569                          _("WARNING: %s:%s does not support multiple include\n"),
1570                          dp->host->hostname, qdpname);
1571                 }
1572                 amfree(q64name);
1573             }
1574         } else if(fdout) {
1575             fprintf(fdout, _("WARNING: %s:%s does not support include file\n"),
1576                     dp->host->hostname, qdpname);
1577         }
1578     }
1579     include_list = stralloc("");
1580     if(dp->include_list != NULL && dp->include_list->nb_element > 0) {
1581         if(am_has_feature(their_features, fe_options_include_list)) {
1582             if(am_has_feature(their_features, fe_options_multiple_include) ||
1583                (dp->include_list->nb_element == 1 && nb_include_file == 0)) {
1584                 for(excl = dp->include_list->first; excl != NULL;
1585                                                     excl = excl->next) {
1586                     q64name = amxml_format_tag("list", excl->name);
1587                     exc = newvstralloc( exc, "    ", q64name, "\n", NULL);
1588                     strappend(include_list, exc);
1589                     amfree(q64name);
1590                 }
1591             } else {
1592                 q64name = amxml_format_tag("list", dp->include_list->last->name);
1593                 exc = newvstralloc(exc, "    ", q64name, "\n", NULL);
1594                 strappend(include_list, exc);
1595                 if(fdout) {
1596                         fprintf(fdout,
1597                          _("WARNING: %s:%s does not support multiple include\n"),
1598                          dp->host->hostname, qdpname);
1599                 }
1600                 amfree(q64name);
1601             }
1602         } else if(fdout) {
1603             fprintf(fdout, _("WARNING: %s:%s does not support include list\n"),
1604                     dp->host->hostname, qdpname);
1605         }
1606     }
1607
1608     if(dp->exclude_optional) {
1609         if(am_has_feature(their_features, fe_options_optional_exclude)) {
1610             excl_opt = "    <optional>YES</optional>\n";
1611         }
1612         else if(fdout) {
1613             fprintf(fdout,
1614                     _("WARNING: %s:%s does not support optional exclude\n"),
1615                     dp->host->hostname, qdpname);
1616         }
1617     }
1618     if(dp->include_optional) {
1619         if(am_has_feature(their_features, fe_options_optional_include)) {
1620             incl_opt = "    <optional>YES</optional>\n";
1621         }
1622         else if(fdout) {
1623             fprintf(fdout,
1624                     _("WARNING: %s:%s does not support optional include\n"),
1625                     dp->host->hostname, qdpname);
1626         }
1627     }
1628
1629     if (dp->exclude_file || dp->exclude_list)
1630         exclude = newvstralloc(exclude,
1631                                "  <exclude>\n",
1632                                exclude_file,
1633                                exclude_list,
1634                                excl_opt,
1635                                "  </exclude>\n", NULL);
1636     if (dp->include_file || dp->include_list)
1637         include = newvstralloc(include,
1638                                "  <include>\n",
1639                                include_file,
1640                                include_list,
1641                                incl_opt,
1642                                "  </include>\n", NULL);
1643     script_opt = xml_scripts(dp->pp_scriptlist, their_features);
1644     result = vstralloc(auth_opt,
1645                        kencrypt_opt,
1646                        compress_opt,
1647                        encrypt_opt,
1648                        record_opt,
1649                        index_opt,
1650                        exclude,
1651                        include,
1652                        script_opt,
1653                        NULL);
1654
1655     amfree(qdpname);
1656     amfree(auth_opt);
1657     amfree(exclude);
1658     amfree(exclude_list);
1659     amfree(exclude_file);
1660     amfree(include);
1661     amfree(include_file);
1662     amfree(include_list);
1663     amfree(exc);
1664     amfree(decrypt_opt);
1665     amfree(encrypt_opt);
1666
1667     /* result contains at least 'auth=...' */
1668     if ( err ) {
1669         amfree(result);
1670         return NULL;
1671     } else {
1672         return result;
1673     }
1674 }
1675
1676 char *
1677 clean_dle_str_for_client(
1678     char *dle_str)
1679 {
1680     char *rval_dle_str;
1681     char *hack1, *hack2;
1682
1683     if (!dle_str)
1684         return NULL;
1685
1686     rval_dle_str = stralloc(dle_str);
1687
1688     /* Remove everything between "  <encrypt>SERVER-CUSTOM" and "</encrypt>\n"
1689      */
1690 #define SC "</encrypt>\n"
1691 #define SC_LEN strlen(SC)
1692     hack1 = strstr(rval_dle_str, "  <encrypt>SERVER-CUSTOM");
1693     if (hack1) {
1694         hack2 = strstr(hack1, SC);
1695         /* +1 is to also move the trailing '\0' */
1696         memmove(hack1, hack2 + SC_LEN, strlen(hack2 + SC_LEN) + 1);
1697     }
1698 #undef SC
1699 #undef SC_LEN
1700
1701     return rval_dle_str;
1702 }
1703
1704 typedef struct {
1705     am_feature_t  *features;
1706     char          *result;
1707 } xml_app_t;
1708
1709 /* A GHFunc (callback for g_hash_table_foreach) */
1710 static void xml_property(
1711     gpointer key_p,
1712     gpointer value_p,
1713     gpointer user_data_p)
1714 {
1715     char       *property_s = key_p;
1716     char       *b64property;
1717     property_t *property = value_p;
1718     char       *b64value_data;
1719     xml_app_t  *xml_app = user_data_p;
1720     GSList     *value;
1721
1722     b64property = amxml_format_tag("name", property_s);
1723     vstrextend(&xml_app->result, "    <property>\n",
1724                                 "      ", b64property, "\n", NULL);
1725     // TODO if client have fe_xml_property_priority
1726     if (property->priority &&
1727         am_has_feature(xml_app->features, fe_xml_property_priority)) {
1728         vstrextend(&xml_app->result, "      <priority>yes</priority>\n", NULL);
1729     }
1730     for(value = property->values; value != NULL; value = value->next) {
1731         b64value_data = amxml_format_tag("value", value->data);
1732         vstrextend(&xml_app->result, "      ", b64value_data, "\n", NULL);
1733         amfree(b64value_data);
1734     }
1735     vstrextend(&xml_app->result, "    </property>\n", NULL);
1736
1737     amfree(b64property);
1738 }
1739
1740 char *
1741 xml_application(
1742     application_t *application,
1743     am_feature_t  *their_features)
1744 {
1745     char       *plugin;
1746     char       *b64plugin;
1747     xml_app_t   xml_app;
1748     proplist_t  proplist;
1749
1750     xml_app.features = their_features;
1751     xml_app.result   = NULL;
1752     plugin = application_get_plugin(application);
1753     b64plugin = amxml_format_tag("plugin", plugin);
1754     xml_app.result = vstralloc("  <backup-program>\n",
1755                         "    ", b64plugin, "\n",
1756                         NULL);
1757     proplist = application_get_property(application);
1758     g_hash_table_foreach(proplist, xml_property, &xml_app);
1759     vstrextend(&xml_app.result, "  </backup-program>\n", NULL);
1760
1761     amfree(b64plugin);
1762
1763     return xml_app.result;
1764 }
1765
1766  
1767 char *
1768 xml_scripts(
1769     pp_scriptlist_t pp_scriptlist,
1770     am_feature_t  *their_features)
1771 {
1772     char       *plugin;
1773     char       *b64plugin;
1774     char       *xml_scr;
1775     char       *xml_scr1;
1776     char       *str = "";
1777     char       *sep;
1778     char       *eo_str;
1779     execute_on_t execute_on;
1780     int          execute_where;
1781     proplist_t  proplist;
1782     pp_scriptlist_t pp_scriptlist1;
1783     pp_script_t *pp_script;
1784     xml_app_t   xml_app;
1785
1786     xml_app.features = their_features;
1787
1788     xml_scr = stralloc("");
1789     for (pp_scriptlist1=pp_scriptlist; pp_scriptlist1 != NULL;
1790          pp_scriptlist1 = pp_scriptlist1->next) {
1791         pp_script = pp_scriptlist1->data;
1792         plugin = pp_script_get_plugin(pp_script);
1793         b64plugin = amxml_format_tag("plugin", plugin);
1794         xml_scr1 = vstralloc("  <script>\n",
1795                              "    ", b64plugin, "\n",
1796                              NULL);
1797
1798         execute_where = pp_script_get_execute_where(pp_script);
1799         switch (execute_where) {
1800             case ES_CLIENT: str = "CLIENT"; break;
1801             case ES_SERVER: str = "SERVER"; break;
1802         }
1803         xml_scr1 = vstrextend(&xml_scr1, "    <execute_where>",
1804                               str, "</execute_where>\n", NULL);
1805
1806         execute_on = pp_script_get_execute_on(pp_script);
1807         sep = "";
1808         eo_str = NULL;
1809         if (execute_on & EXECUTE_ON_PRE_DLE_AMCHECK) {
1810             eo_str = vstrextend(&eo_str, sep, "PRE-DLE-AMCHECK", NULL);
1811             sep = ",";
1812         }
1813         if (execute_on & EXECUTE_ON_PRE_HOST_AMCHECK) {
1814             eo_str = vstrextend(&eo_str, sep, "PRE-HOST-AMCHECK", NULL);
1815             sep = ",";
1816         }
1817         if (execute_on & EXECUTE_ON_POST_DLE_AMCHECK) {
1818             eo_str = vstrextend(&eo_str, sep, "POST-DLE-AMCHECK", NULL);
1819             sep = ",";
1820         }
1821         if (execute_on & EXECUTE_ON_POST_HOST_AMCHECK) {
1822             eo_str = vstrextend(&eo_str, sep, "POST-HOST-AMCHECK", NULL);
1823             sep = ",";
1824         }
1825         if (execute_on & EXECUTE_ON_PRE_DLE_ESTIMATE) {
1826             eo_str = vstrextend(&eo_str, sep, "PRE-DLE-ESTIMATE", NULL);
1827             sep = ",";
1828         }
1829         if (execute_on & EXECUTE_ON_PRE_HOST_ESTIMATE) {
1830             eo_str = vstrextend(&eo_str, sep, "PRE-HOST-ESTIMATE", NULL);
1831             sep = ",";
1832         }
1833         if (execute_on & EXECUTE_ON_POST_DLE_ESTIMATE) {
1834             eo_str = vstrextend(&eo_str, sep, "POST-DLE-ESTIMATE", NULL);
1835             sep = ",";
1836         }
1837         if (execute_on & EXECUTE_ON_POST_HOST_ESTIMATE) {
1838             eo_str = vstrextend(&eo_str, sep, "POST-HOST-ESTIMATE", NULL);
1839             sep = ",";
1840         }
1841         if (execute_on & EXECUTE_ON_PRE_DLE_BACKUP) {
1842             eo_str = vstrextend(&eo_str, sep, "PRE-DLE-BACKUP", NULL);
1843             sep = ",";
1844         }
1845         if (execute_on & EXECUTE_ON_PRE_HOST_BACKUP) {
1846             eo_str = vstrextend(&eo_str, sep, "PRE-HOST-BACKUP", NULL);
1847             sep = ",";
1848         }
1849         if (execute_on & EXECUTE_ON_POST_DLE_BACKUP) {
1850             eo_str = vstrextend(&eo_str, sep, "POST-DLE-BACKUP", NULL);
1851             sep = ",";
1852         }
1853         if (execute_on & EXECUTE_ON_POST_HOST_BACKUP) {
1854             eo_str = vstrextend(&eo_str, sep, "POST-HOST-BACKUP", NULL);
1855             sep = ",";
1856         }
1857         if (execute_on & EXECUTE_ON_PRE_RECOVER) {
1858             eo_str = vstrextend(&eo_str, sep, "PRE-RECOVER", NULL);
1859             sep = ",";
1860         }
1861         if (execute_on & EXECUTE_ON_POST_RECOVER) {
1862             eo_str = vstrextend(&eo_str, sep, "POST-RECOVER", NULL);
1863             sep = ",";
1864         }
1865         if (execute_on & EXECUTE_ON_PRE_LEVEL_RECOVER) {
1866             eo_str = vstrextend(&eo_str, sep, "PRE-LEVEL-RECOVER", NULL);
1867             sep = ",";
1868         }
1869         if (execute_on & EXECUTE_ON_POST_LEVEL_RECOVER) {
1870             eo_str = vstrextend(&eo_str, sep, "POST-LEVEL-RECOVER", NULL);
1871             sep = ",";
1872         }
1873         if (execute_on & EXECUTE_ON_INTER_LEVEL_RECOVER) {
1874             eo_str = vstrextend(&eo_str, sep, "INTER-LEVEL-RECOVER", NULL);
1875             sep = ",";
1876         }
1877         if (execute_on != 0)
1878             xml_scr1 = vstrextend(&xml_scr1,
1879                                   "    <execute_on>", eo_str,
1880                                   "</execute_on>\n", NULL);
1881         amfree(eo_str);
1882         proplist = pp_script_get_property(pp_script);
1883         xml_app.result   = stralloc("");
1884         g_hash_table_foreach(proplist, xml_property, &xml_app);
1885         xml_scr = vstrextend(&xml_scr, xml_scr1, xml_app.result, "  </script>\n", NULL);
1886         amfree(b64plugin);
1887         amfree(xml_app.result);
1888     }
1889     return xml_scr;
1890 }
1891
1892  
1893 char *
1894 match_disklist(
1895     disklist_t *origqp,
1896     int         sargc,
1897     char **     sargv)
1898 {
1899     char *prevhost = NULL;
1900     char *errstr = NULL;
1901     int i;
1902     int match_a_host;
1903     int match_a_disk;
1904     int prev_match;
1905     disk_t *dp;
1906
1907     if(sargc <= 0)
1908         return NULL;
1909
1910     for(dp = origqp->head; dp != NULL; dp = dp->next) {
1911         if(dp->todo == 1)
1912             dp->todo = -1;
1913     }
1914
1915     prev_match = 0;
1916     for(i=0;i<sargc;i++) {
1917         match_a_host = 0;
1918         for(dp = origqp->head; dp != NULL; dp = dp->next) {
1919             if(match_host(sargv[i], dp->host->hostname))
1920                 match_a_host = 1;
1921         }
1922         match_a_disk = 0;
1923         for(dp = origqp->head; dp != NULL; dp = dp->next) {
1924             if(prevhost != NULL &&
1925                match_host(prevhost, dp->host->hostname) &&
1926                (match_disk(sargv[i], dp->name) ||
1927                 (dp->device && match_disk(sargv[i], dp->device)))) {
1928                 if(match_a_host) {
1929                     error(_("Argument %s cannot be both a host and a disk"),sargv[i]);
1930                     /*NOTREACHED*/
1931                 }
1932                 else {
1933                     if(dp->todo == -1) {
1934                         dp->todo = 1;
1935                         match_a_disk = 1;
1936                         prev_match = 0;
1937                     }
1938                 }
1939             }
1940         }
1941         if(!match_a_disk) {
1942             if(match_a_host == 1) {
1943                 if(prev_match == 1) { /* all disk of the previous host */
1944                     for(dp = origqp->head; dp != NULL; dp = dp->next) {
1945                         if(match_host(prevhost,dp->host->hostname))
1946                             if(dp->todo == -1)
1947                                 dp->todo = 1;
1948                     }
1949                 }
1950                 prevhost = sargv[i];
1951                 prev_match = 1;
1952             }
1953             else {
1954                 char *errstr1 = vstrallocf(_("Argument '%s' matches neither a host nor a disk.\n"), sargv[i]);
1955                 vstrextend(&errstr, errstr1, NULL);
1956                 prev_match = 0;
1957             }
1958         }
1959     }
1960
1961     if(prev_match == 1) { /* all disk of the previous host */
1962         for(dp = origqp->head; dp != NULL; dp = dp->next) {
1963             if(match_host(prevhost,dp->host->hostname))
1964                 if(dp->todo == -1)
1965                     dp->todo = 1;
1966         }
1967     }
1968
1969     for(dp = origqp->head; dp != NULL; dp = dp->next) {
1970         if(dp->todo == -1)
1971             dp->todo = 0;
1972     }
1973
1974     return errstr;
1975 }
1976
1977 netif_t *
1978 disklist_netifs(void)
1979 {
1980     return all_netifs;
1981 }
1982
1983 #ifdef TEST
1984
1985 static void dump_disk(const disk_t *);
1986 static void dump_disklist(const disklist_t *);
1987 int main(int, char *[]);
1988
1989 static void
1990 dump_disk(
1991     const disk_t *      dp)
1992 {
1993     g_printf(_("  DISK %s (HOST %s, LINE %d) TYPE %s NAME %s SPINDLE %d\n"),
1994            dp->name, dp->host->hostname, dp->line, dp->dtype_name,
1995            dp->name == NULL? "(null)": dp->name,
1996            dp->spindle);
1997 }
1998
1999 static void
2000 dump_disklist(
2001     const disklist_t *  lst)
2002 {
2003     const disk_t *dp, *prev;
2004     const am_host_t *hp;
2005
2006     if(hostlist == NULL) {
2007         g_printf(_("DISKLIST not read in\n"));
2008         return;
2009     }
2010
2011     g_printf(_("DISKLIST BY HOSTNAME:\n"));
2012
2013     for(hp = hostlist; hp != NULL; hp = hp->next) {
2014         char *if_name = NULL;
2015         if (hp->netif && hp->netif->config)
2016             if_name = interface_name(hp->netif->config);
2017
2018         g_printf(_("HOST %s INTERFACE %s\n"),
2019                hp->hostname,
2020                if_name ? _("(null)") : if_name);
2021         for(dp = hp->disks; dp != NULL; dp = dp->hostnext)
2022             dump_disk(dp);
2023         putchar('\n');
2024     }
2025
2026
2027     g_printf(_("DISKLIST IN FILE ORDER:\n"));
2028
2029     prev = NULL;
2030     for(dp = lst->head; dp != NULL; prev = dp, dp = dp->next) {
2031         dump_disk(dp);
2032         /* check pointers */
2033         if(dp->prev != prev) g_printf(_("*** prev pointer mismatch!\n"));
2034         if(dp->next == NULL && lst->tail != dp) g_printf(_("tail mismatch!\n"));
2035     }
2036 }
2037
2038 int
2039 main(
2040     int         argc,
2041     char **     argv)
2042 {
2043   char *conffile;
2044   char *conf_diskfile;
2045   disklist_t lst;
2046   int result;
2047
2048   /*
2049    * Configure program for internationalization:
2050    *   1) Only set the message locale for now.
2051    *   2) Set textdomain for all amanda related programs to "amanda"
2052    *      We don't want to be forced to support dozens of message catalogs.
2053    */  
2054   setlocale(LC_MESSAGES, "C");
2055   textdomain("amanda"); 
2056
2057   safe_fd(-1, 0);
2058
2059   set_pname("diskfile");
2060
2061   dbopen(DBG_SUBDIR_SERVER);
2062
2063   /* Don't die when child closes pipe */
2064   signal(SIGPIPE, SIG_IGN);
2065
2066   if (argc>1) {
2067     config_init(CONFIG_INIT_EXPLICIT_NAME, argv[1]);
2068   } else {
2069     config_init(CONFIG_INIT_USE_CWD, NULL)
2070   }
2071
2072   if (config_errors(NULL) >= CFGERR_WARNINGS) {
2073     config_print_errors();
2074     if (config_errors(NULL) >= CFGERR_ERRORS) {
2075       g_critical(_("errors processing config file"));
2076     }
2077   }
2078
2079   conf_diskfile = config_dir_relative(getconf_str(CNF_DISKFILE));
2080   result = read_diskfile(conf_diskfile, &lst);
2081   if(result == CFGERR_OK) {
2082     dump_disklist(&lst);
2083   } else {
2084     config_print_errors();
2085   }
2086   amfree(conf_diskfile);
2087   amfree(conffile);
2088   amfree(config_dir);
2089
2090   return result;
2091 }
2092 #endif /* TEST */