f80137263e7113ce14f64f53eeacce33b2efb846
[debian/amanda] / server-src / conffile.c
1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-2000 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: conffile.c,v 1.127 2006/03/15 16:26:13 martinea Exp $
29  *
30  * read configuration file
31  */
32 /*
33  *
34  * XXX - I'm not happy *at all* with this implementation, but I don't
35  * think YACC would be any easier.  A more table based implementation
36  * would be better.  Also clean up memory leaks.
37  */
38 #include "amanda.h"
39 #include "arglist.h"
40
41 #include "conffile.h"
42 #include "diskfile.h"
43 #include "driverio.h"
44 #include "clock.h"
45
46 #ifdef HAVE_LIMITS_H
47 #include <limits.h>
48 #endif
49
50 #ifndef INT_MAX
51 #define INT_MAX 2147483647
52 #endif
53
54 #define BIGINT  1000000000              /* 2 million yrs @ 1 per day */
55
56 /* internal types and variables */
57
58 typedef enum {
59     UNKNOWN, ANY, COMMA, LBRACE, RBRACE, NL, END,
60     IDENT, INT, LONG, AM64, BOOL, REAL, STRING, TIME,
61
62     /* config parameters */
63     INCLUDEFILE,
64     ORG, MAILTO, DUMPUSER,
65     TAPECYCLE, TAPEDEV, CHNGRDEV, CHNGRFILE, LABELSTR,
66     BUMPPERCENT, BUMPSIZE, BUMPDAYS, BUMPMULT, ETIMEOUT, DTIMEOUT, CTIMEOUT,
67     TAPEBUFS, TAPELIST, DISKFILE, INFOFILE, LOGDIR, LOGFILE,
68     DISKDIR, DISKSIZE, INDEXDIR, NETUSAGE, INPARALLEL, DUMPORDER, TIMEOUT,
69     TPCHANGER, RUNTAPES,
70     DEFINE, DUMPTYPE, TAPETYPE, INTERFACE,
71     PRINTER, AUTOFLUSH, RESERVE, MAXDUMPSIZE,
72     COLUMNSPEC, 
73     AMRECOVER_DO_FSF, AMRECOVER_CHECK_LABEL, AMRECOVER_CHANGER,
74     LABEL_NEW_TAPES,
75
76     TAPERALGO, FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST, LAST,
77     DISPLAYUNIT,
78
79     /* kerberos 5 */
80     KRB5KEYTAB, KRB5PRINCIPAL, 
81
82     /* holding disk */
83     COMMENT, DIRECTORY, USE, CHUNKSIZE,
84
85     /* dump type */
86     /*COMMENT,*/ PROGRAM, DUMPCYCLE, RUNSPERCYCLE, MAXCYCLE, MAXDUMPS,
87     OPTIONS, PRIORITY, FREQUENCY, INDEX, MAXPROMOTEDAY,
88     STARTTIME, COMPRESS, ENCRYPT, AUTH, STRATEGY, ESTIMATE,
89     SKIP_INCR, SKIP_FULL, RECORD, HOLDING,
90     EXCLUDE, INCLUDE, KENCRYPT, IGNORE, COMPRATE, TAPE_SPLITSIZE,
91     SPLIT_DISKBUFFER, FALLBACK_SPLITSIZE, SRVCOMPPROG, CLNTCOMPPROG,
92     SRV_ENCRYPT, CLNT_ENCRYPT, SRV_DECRYPT_OPT, CLNT_DECRYPT_OPT,
93
94     /* tape type */
95     /*COMMENT,*/ BLOCKSIZE, FILE_PAD, LBL_TEMPL, FILEMARK, LENGTH, SPEED,
96
97     /* network interface */
98     /*COMMENT, USE,*/
99
100     /* dump options (obsolete) */
101     EXCLUDE_FILE, EXCLUDE_LIST,
102
103     /* compress, estimate, encryption */
104     NONE, FAST, BEST, SERVER, CLIENT, CALCSIZE, CUSTOM,
105
106     /* priority */
107     LOW, MEDIUM, HIGH,
108
109     /* dump strategy */
110     SKIP, STANDARD, NOFULL, NOINC, HANOI, INCRONLY,
111
112     /* exclude list */
113     LIST, EFILE, APPEND, OPTIONAL,
114
115     /* numbers */
116     INFINITY, MULT1, MULT7, MULT1K, MULT1M, MULT1G,
117
118     /* boolean */
119     ATRUE, AFALSE,
120
121     RAWTAPEDEV
122 } tok_t;
123
124 typedef struct {        /* token table entry */
125     char *keyword;
126     tok_t token;
127 } keytab_t;
128
129 keytab_t *keytable;
130
131 typedef union {
132     int i;
133     long l;
134     am64_t am64;
135     double r;
136     char *s;
137 } val_t;
138
139 /* this corresponds to the normal output of amanda, but may
140  * be adapted to any spacing as you like.
141  */
142 ColumnInfo ColumnData[] = {
143     { "HostName",   0, 12, 12, 0, "%-*.*s", "HOSTNAME" },
144     { "Disk",       1, 11, 11, 0, "%-*.*s", "DISK" },
145     { "Level",      1, 1,  1,  0, "%*.*d",  "L" },
146     { "OrigKB",     1, 7,  0,  0, "%*.*f",  "ORIG-KB" },
147     { "OutKB",      1, 7,  0,  0, "%*.*f",  "OUT-KB" },
148     { "Compress",   1, 6,  1,  0, "%*.*f",  "COMP%" },
149     { "DumpTime",   1, 7,  7,  0, "%*.*s",  "MMM:SS" },
150     { "DumpRate",   1, 6,  1,  0, "%*.*f",  "KB/s" },
151     { "TapeTime",   1, 6,  6,  0, "%*.*s",  "MMM:SS" },
152     { "TapeRate",   1, 6,  1,  0, "%*.*f",  "KB/s" },
153     { NULL,         0, 0,  0,  0, NULL,     NULL }
154 };
155
156 char *config_name = NULL;
157 char *config_dir = NULL;
158
159 /* visible holding disk variables */
160
161 holdingdisk_t *holdingdisks;
162 int num_holdingdisks;
163
164 long int unit_divisor = 1;
165
166 /* configuration parameters */
167
168 /* strings */
169 static val_t conf_org;
170 static val_t conf_mailto;
171 static val_t conf_dumpuser;
172 static val_t conf_printer;
173 static val_t conf_tapedev;
174 static val_t conf_rawtapedev;
175 static val_t conf_tpchanger;
176 static val_t conf_chngrdev;
177 static val_t conf_chngrfile;
178 static val_t conf_labelstr;
179 static val_t conf_tapelist;
180 static val_t conf_infofile;
181 static val_t conf_logdir;
182 static val_t conf_diskfile;
183 static val_t conf_diskdir;
184 static val_t conf_tapetype;
185 static val_t conf_indexdir;
186 static val_t conf_columnspec;
187 static val_t conf_dumporder;
188 static val_t conf_amrecover_changer;
189
190 /* ints */
191 static val_t conf_dumpcycle;
192 static val_t conf_runspercycle;
193 static val_t conf_maxcycle;
194 static val_t conf_tapecycle;
195 static val_t conf_runtapes;
196 static val_t conf_disksize;
197 static val_t conf_netusage;
198 static val_t conf_inparallel;
199 static val_t conf_timeout;
200 static val_t conf_maxdumps;
201 static val_t conf_bumppercent;
202 static val_t conf_bumpsize;
203 static val_t conf_bumpdays;
204 static val_t conf_etimeout;
205 static val_t conf_dtimeout;
206 static val_t conf_ctimeout;
207 static val_t conf_tapebufs;
208 static val_t conf_autoflush;
209 static val_t conf_reserve;
210 static val_t conf_maxdumpsize;
211 static val_t conf_amrecover_do_fsf;
212 static val_t conf_amrecover_check_label;
213 static val_t conf_taperalgo;
214 static val_t conf_displayunit;
215 static val_t conf_krb5keytab;
216 static val_t conf_krb5principal;
217 static val_t conf_label_new_tapes;
218
219 /* reals */
220 static val_t conf_bumpmult;
221
222 /* other internal variables */
223 static holdingdisk_t hdcur;
224
225 static tapetype_t tpcur;
226
227 static dumptype_t dpcur;
228
229 static interface_t ifcur;
230
231 static int seen_org;
232 static int seen_mailto;
233 static int seen_dumpuser;
234 static int seen_rawtapedev;
235 static int seen_printer;
236 static int seen_tapedev;
237 static int seen_tpchanger;
238 static int seen_chngrdev;
239 static int seen_chngrfile;
240 static int seen_labelstr;
241 static int seen_runtapes;
242 static int seen_maxdumps;
243 static int seen_tapelist;
244 static int seen_infofile;
245 static int seen_diskfile;
246 static int seen_diskdir;
247 static int seen_logdir;
248 static int seen_bumppercent;
249 static int seen_bumpsize;
250 static int seen_bumpmult;
251 static int seen_bumpdays;
252 static int seen_tapetype;
253 static int seen_dumpcycle;
254 static int seen_runspercycle;
255 static int seen_maxcycle;
256 static int seen_tapecycle;
257 static int seen_disksize;
258 static int seen_netusage;
259 static int seen_inparallel;
260 static int seen_dumporder;
261 static int seen_timeout;
262 static int seen_indexdir;
263 static int seen_etimeout;
264 static int seen_dtimeout;
265 static int seen_ctimeout;
266 static int seen_tapebufs;
267 static int seen_autoflush;
268 static int seen_reserve;
269 static int seen_maxdumpsize;
270 static int seen_columnspec;
271 static int seen_amrecover_do_fsf;
272 static int seen_amrecover_check_label;
273 static int seen_amrecover_changer;
274 static int seen_taperalgo;
275 static int seen_displayunit;
276 static int seen_krb5keytab;
277 static int seen_krb5principal;
278 static int seen_label_new_tapes;
279
280 static int allow_overwrites;
281 static int token_pushed;
282
283 static tok_t tok, pushed_tok;
284 static val_t tokenval;
285
286 static int line_num, got_parserror;
287 static dumptype_t *dumplist = NULL;
288 static tapetype_t *tapelist = NULL;
289 static interface_t *interface_list = NULL;
290 static FILE *conf = (FILE *)NULL;
291 static char *confname = NULL;
292
293 /* predeclare local functions */
294
295 static void init_defaults P((void));
296 static void read_conffile_recursively P((char *filename));
297
298 static int read_confline P((void));
299 static void get_holdingdisk P((void));
300 static void init_holdingdisk_defaults P((void));
301 static void save_holdingdisk P((void));
302 static void get_dumptype P((void));
303 static void init_dumptype_defaults P((void));
304 static void save_dumptype P((void));
305 static void copy_dumptype P((void));
306 static void get_tapetype P((void));
307 static void init_tapetype_defaults P((void));
308 static void save_tapetype P((void));
309 static void copy_tapetype P((void));
310 static void get_interface P((void));
311 static void init_interface_defaults P((void));
312 static void save_interface P((void));
313 static void copy_interface P((void));
314 static void get_dumpopts P((void));
315 static void get_comprate P((void));
316 static void get_compress P((void));
317 static void get_encrypt P((void));
318 static void get_priority P((void));
319 static void get_strategy P((void));
320 static void get_estimate P((void));
321 static void get_exclude P((void));
322 static void get_include P((void));
323 static void get_taperalgo P((val_t *c_taperalgo, int *s_taperalgo));
324
325 static void get_simple P((val_t *var, int *seen, tok_t type));
326 static int get_time P((void));
327 static int get_int P((void));
328 static long get_long P((void));
329 static am64_t get_am64_t P((void));
330 static int get_bool P((void));
331 static void ckseen P((int *seen));
332 static void parserror P((char *format, ...))
333     __attribute__ ((format (printf, 1, 2)));
334 static tok_t lookup_keyword P((char *str));
335 static void unget_conftoken P((void));
336 static void get_conftoken P((tok_t exp));
337
338 /*
339 ** ------------------------
340 **  External entry points
341 ** ------------------------
342 */
343
344 int read_conffile(filename)
345 char *filename;
346 {
347     interface_t *ip;
348
349     init_defaults();
350
351     /* We assume that confname & conf are initialized to NULL above */
352     read_conffile_recursively(filename);
353
354     if(got_parserror != -1 ) {
355         if(lookup_tapetype(conf_tapetype.s) == NULL) {
356             char *save_confname = confname;
357
358             confname = filename;
359             if(!seen_tapetype)
360                 parserror("default tapetype %s not defined", conf_tapetype.s);
361             else {
362                 line_num = seen_tapetype;
363                 parserror("tapetype %s not defined", conf_tapetype.s);
364             }
365             confname = save_confname;
366         }
367     }
368
369     ip = alloc(sizeof(interface_t));
370     malloc_mark(ip);
371     ip->name = "";
372     ip->seen = seen_netusage;
373     ip->comment = "implicit from NETUSAGE";
374     ip->maxusage = conf_netusage.i;
375     ip->curusage = 0;
376     ip->next = interface_list;
377     interface_list = ip;
378
379     return got_parserror;
380 }
381
382 struct byname {
383     char *name;
384     confparm_t parm;
385     tok_t typ;
386 } byname_table [] = {
387     { "ORG", CNF_ORG, STRING },
388     { "MAILTO", CNF_MAILTO, STRING },
389     { "DUMPUSER", CNF_DUMPUSER, STRING },
390     { "PRINTER", CNF_PRINTER, STRING },
391     { "TAPEDEV", CNF_TAPEDEV, STRING },
392     { "TPCHANGER", CNF_TPCHANGER, STRING },
393     { "CHANGERDEV", CNF_CHNGRDEV, STRING },
394     { "CHANGERFILE", CNF_CHNGRFILE, STRING },
395     { "LABELSTR", CNF_LABELSTR, STRING },
396     { "TAPELIST", CNF_TAPELIST, STRING },
397     { "DISKFILE", CNF_DISKFILE, STRING },
398     { "INFOFILE", CNF_INFOFILE, STRING },
399     { "LOGDIR", CNF_LOGDIR, STRING },
400     /*{ "LOGFILE", CNF_LOGFILE, STRING },*/
401     /*{ "DISKDIR", CNF_DISKDIR, STRING },*/
402     { "INDEXDIR", CNF_INDEXDIR, STRING },
403     { "TAPETYPE", CNF_TAPETYPE, STRING },
404     { "DUMPCYCLE", CNF_DUMPCYCLE, INT },
405     { "RUNSPERCYCLE", CNF_RUNSPERCYCLE, INT },
406     { "MINCYCLE",  CNF_DUMPCYCLE, INT },
407     { "RUNTAPES",   CNF_RUNTAPES, INT },
408     { "TAPECYCLE", CNF_TAPECYCLE, INT },
409     /*{ "DISKSIZE", CNF_DISKSIZE, INT },*/
410     { "BUMPDAYS", CNF_BUMPDAYS, INT },
411     { "BUMPSIZE", CNF_BUMPSIZE, INT },
412     { "BUMPPERCENT", CNF_BUMPPERCENT, INT },
413     { "BUMPMULT", CNF_BUMPMULT, REAL },
414     { "NETUSAGE", CNF_NETUSAGE, INT },
415     { "INPARALLEL", CNF_INPARALLEL, INT },
416     { "DUMPORDER", CNF_DUMPORDER, STRING },
417     /*{ "TIMEOUT", CNF_TIMEOUT, INT },*/
418     { "MAXDUMPS", CNF_MAXDUMPS, INT },
419     { "ETIMEOUT", CNF_ETIMEOUT, INT },
420     { "DTIMEOUT", CNF_DTIMEOUT, INT },
421     { "CTIMEOUT", CNF_CTIMEOUT, INT },
422     { "TAPEBUFS", CNF_TAPEBUFS, INT },
423     { "RAWTAPEDEV", CNF_RAWTAPEDEV, STRING },
424     { "COLUMNSPEC", CNF_COLUMNSPEC, STRING },
425     { "AMRECOVER_DO_FSF", CNF_AMRECOVER_DO_FSF, BOOL },
426     { "AMRECOVER_CHECK_LABEL", CNF_AMRECOVER_CHECK_LABEL, BOOL },
427     { "AMRECOVER_CHANGER", CNF_AMRECOVER_CHANGER, STRING },
428     { "TAPERALGO", CNF_TAPERALGO, INT },
429     { "DISPLAYUNIT", CNF_DISPLAYUNIT, STRING },
430     { "AUTOFLUSH", CNF_AUTOFLUSH, BOOL },
431     { "RESERVE", CNF_RESERVE, INT },
432     { "MAXDUMPSIZE", CNF_MAXDUMPSIZE, AM64 },
433     { "KRB5KEYTAB", CNF_KRB5KEYTAB, STRING },
434     { "KRB5PRINCIPAL", CNF_KRB5PRINCIPAL, STRING },
435     { "LABEL_NEW_TAPES", CNF_LABEL_NEW_TAPES, STRING },
436     { NULL }
437 };
438
439 char *getconf_byname(str)
440 char *str;
441 {
442     static char *tmpstr;
443     char number[NUM_STR_SIZE];
444     struct byname *np;
445     char *s;
446     char ch;
447
448     tmpstr = stralloc(str);
449     s = tmpstr;
450     while((ch = *s++) != '\0') {
451         if(islower((int)ch)) s[-1] = toupper(ch);
452     }
453
454     for(np = byname_table; np->name != NULL; np++)
455         if(strcmp(np->name, tmpstr) == 0) break;
456
457     if(np->name == NULL) return NULL;
458
459     if(np->typ == INT) {
460         snprintf(number, sizeof(number), "%d", getconf_int(np->parm));
461         tmpstr = newstralloc(tmpstr, number);
462     } else if(np->typ == BOOL) {
463         if(getconf_int(np->parm) == 0) {
464             tmpstr = newstralloc(tmpstr, "off");
465         }
466         else {
467             tmpstr = newstralloc(tmpstr, "on");
468         }
469     } else if(np->typ == REAL) {
470         snprintf(number, sizeof(number), "%f", getconf_real(np->parm));
471         tmpstr = newstralloc(tmpstr, number);
472     } else {
473         tmpstr = newstralloc(tmpstr, getconf_str(np->parm));
474     }
475
476     return tmpstr;
477 }
478
479 int getconf_seen(parm)
480 confparm_t parm;
481 {
482     switch(parm) {
483     case CNF_ORG: return seen_org;
484     case CNF_MAILTO: return seen_mailto;
485     case CNF_DUMPUSER: return seen_dumpuser;
486     case CNF_PRINTER: return seen_printer;
487     case CNF_TAPEDEV: return seen_tapedev;
488     case CNF_TPCHANGER: return seen_tpchanger;
489     case CNF_CHNGRDEV: return seen_chngrdev;
490     case CNF_CHNGRFILE: return seen_chngrfile;
491     case CNF_LABELSTR: return seen_labelstr;
492     case CNF_RUNTAPES: return seen_runtapes;
493     case CNF_MAXDUMPS: return seen_maxdumps;
494     case CNF_TAPELIST: return seen_tapelist;
495     case CNF_INFOFILE: return seen_infofile;
496     case CNF_DISKFILE: return seen_diskfile;
497     /*case CNF_DISKDIR: return seen_diskdir;*/
498     case CNF_LOGDIR: return seen_logdir;
499     /*case CNF_LOGFILE: return seen_logfile;*/
500     case CNF_BUMPPERCENT: return seen_bumppercent;
501     case CNF_BUMPSIZE: return seen_bumpsize;
502     case CNF_BUMPMULT: return seen_bumpmult;
503     case CNF_BUMPDAYS: return seen_bumpdays;
504     case CNF_TAPETYPE: return seen_tapetype;
505     case CNF_DUMPCYCLE: return seen_dumpcycle;
506     case CNF_RUNSPERCYCLE: return seen_runspercycle;
507     /*case CNF_MAXCYCLE: return seen_maxcycle;*/
508     case CNF_TAPECYCLE: return seen_tapecycle;
509     /*case CNF_DISKSIZE: return seen_disksize;*/
510     case CNF_NETUSAGE: return seen_netusage;
511     case CNF_INPARALLEL: return seen_inparallel;
512     case CNF_DUMPORDER: return seen_dumporder;
513     /*case CNF_TIMEOUT: return seen_timeout;*/
514     case CNF_INDEXDIR: return seen_indexdir;
515     case CNF_ETIMEOUT: return seen_etimeout;
516     case CNF_DTIMEOUT: return seen_dtimeout;
517     case CNF_CTIMEOUT: return seen_ctimeout;
518     case CNF_TAPEBUFS: return seen_tapebufs;
519     case CNF_RAWTAPEDEV: return seen_rawtapedev;
520     case CNF_AUTOFLUSH: return seen_autoflush;
521     case CNF_RESERVE: return seen_reserve;
522     case CNF_MAXDUMPSIZE: return seen_maxdumpsize;
523     case CNF_AMRECOVER_DO_FSF: return seen_amrecover_do_fsf;
524     case CNF_AMRECOVER_CHECK_LABEL: return seen_amrecover_check_label;
525     case CNF_AMRECOVER_CHANGER: return seen_amrecover_changer;
526     case CNF_TAPERALGO: return seen_taperalgo;
527     case CNF_DISPLAYUNIT: return seen_displayunit;
528     case CNF_KRB5KEYTAB: return seen_krb5keytab;
529     case CNF_KRB5PRINCIPAL: return seen_krb5principal;
530     case CNF_LABEL_NEW_TAPES: return seen_label_new_tapes;
531     default: return 0;
532     }
533 }
534
535 int getconf_int(parm)
536 confparm_t parm;
537 {
538     int r = 0;
539
540     switch(parm) {
541
542     case CNF_DUMPCYCLE: r = conf_dumpcycle.i; break;
543     case CNF_RUNSPERCYCLE: r = conf_runspercycle.i; break;
544     case CNF_TAPECYCLE: r = conf_tapecycle.i; break;
545     case CNF_RUNTAPES: r = conf_runtapes.i; break;
546     /*case CNF_DISKSIZE: r = conf_disksize.i; break;*/
547     case CNF_BUMPPERCENT: r = conf_bumppercent.i; break;
548     case CNF_BUMPSIZE: r = conf_bumpsize.i; break;
549     case CNF_BUMPDAYS: r = conf_bumpdays.i; break;
550     case CNF_NETUSAGE: r = conf_netusage.i; break;
551     case CNF_INPARALLEL: r = conf_inparallel.i; break;
552     /*case CNF_TIMEOUT: r = conf_timeout.i; break;*/
553     case CNF_MAXDUMPS: r = conf_maxdumps.i; break;
554     case CNF_ETIMEOUT: r = conf_etimeout.i; break;
555     case CNF_DTIMEOUT: r = conf_dtimeout.i; break;
556     case CNF_CTIMEOUT: r = conf_ctimeout.i; break;
557     case CNF_TAPEBUFS: r = conf_tapebufs.i; break;
558     case CNF_AUTOFLUSH: r = conf_autoflush.i; break;
559     case CNF_RESERVE: r = conf_reserve.i; break;
560     case CNF_AMRECOVER_DO_FSF: r = conf_amrecover_do_fsf.i; break;
561     case CNF_AMRECOVER_CHECK_LABEL: r = conf_amrecover_check_label.i; break;
562     case CNF_TAPERALGO: r = conf_taperalgo.i; break;
563
564     default:
565         error("error [unknown getconf_int parm: %d]", parm);
566         /* NOTREACHED */
567     }
568     return r;
569 }
570
571 am64_t getconf_am64(parm)
572 confparm_t parm;
573 {
574     am64_t r = 0;
575
576     switch(parm) {
577     case CNF_MAXDUMPSIZE: r = conf_maxdumpsize.am64; break;
578
579     default:
580         error("error [unknown getconf_am64 parm: %d]", parm);
581         /* NOTREACHED */
582     }
583     return r;
584 }
585
586 double getconf_real(parm)
587 confparm_t parm;
588 {
589     double r = 0;
590
591     switch(parm) {
592
593     case CNF_BUMPMULT: r = conf_bumpmult.r; break;
594
595     default:
596         error("error [unknown getconf_real parm: %d]", parm);
597         /* NOTREACHED */
598     }
599     return r;
600 }
601
602 char *getconf_str(parm)
603 confparm_t parm;
604 {
605     char *r = 0;
606
607     switch(parm) {
608
609     case CNF_ORG: r = conf_org.s; break;
610     case CNF_MAILTO: r = conf_mailto.s; break;
611     case CNF_DUMPUSER: r = conf_dumpuser.s; break;
612     case CNF_PRINTER: r = conf_printer.s; break;
613     case CNF_TAPEDEV: r = conf_tapedev.s; break;
614     case CNF_TPCHANGER: r = conf_tpchanger.s; break;
615     case CNF_CHNGRDEV: r = conf_chngrdev.s; break;
616     case CNF_CHNGRFILE: r = conf_chngrfile.s; break;
617     case CNF_LABELSTR: r = conf_labelstr.s; break;
618     case CNF_TAPELIST: r = conf_tapelist.s; break;
619     case CNF_INFOFILE: r = conf_infofile.s; break;
620     case CNF_DUMPORDER: r = conf_dumporder.s; break;
621     case CNF_LOGDIR: r = conf_logdir.s; break;
622     /*case CNF_LOGFILE: r = conf_logfile.s; break;*/
623     case CNF_DISKFILE: r = conf_diskfile.s; break;
624     /*case CNF_DISKDIR: r = conf_diskdir.s; break;*/
625     case CNF_TAPETYPE: r = conf_tapetype.s; break;
626     case CNF_INDEXDIR: r = conf_indexdir.s; break;
627     case CNF_RAWTAPEDEV: r = conf_rawtapedev.s; break;
628     case CNF_COLUMNSPEC: r = conf_columnspec.s; break;
629     case CNF_AMRECOVER_CHANGER: r = conf_amrecover_changer.s; break;
630     case CNF_DISPLAYUNIT: r = conf_displayunit.s; break;
631     case CNF_KRB5PRINCIPAL: r = conf_krb5principal.s; break;
632     case CNF_KRB5KEYTAB: r = conf_krb5keytab.s; break;
633     case CNF_LABEL_NEW_TAPES: r = conf_label_new_tapes.s; break;
634
635     default:
636         error("error [unknown getconf_str parm: %d]", parm);
637         /* NOTREACHED */
638     }
639     return r;
640 }
641
642 holdingdisk_t *getconf_holdingdisks()
643 {
644     return holdingdisks;
645 }
646
647 dumptype_t *lookup_dumptype(str)
648 char *str;
649 {
650     dumptype_t *p;
651
652     for(p = dumplist; p != NULL; p = p->next) {
653         if(strcmp(p->name, str) == 0) return p;
654     }
655     return NULL;
656 }
657
658 tapetype_t *lookup_tapetype(str)
659 char *str;
660 {
661     tapetype_t *p;
662
663     for(p = tapelist; p != NULL; p = p->next) {
664         if(strcmp(p->name, str) == 0) return p;
665     }
666     return NULL;
667 }
668
669 interface_t *lookup_interface(str)
670 char *str;
671 {
672     interface_t *p;
673
674     if(str == NULL) return interface_list;
675     for(p = interface_list; p != NULL; p = p->next) {
676         if(strcmp(p->name, str) == 0) return p;
677     }
678     return NULL;
679 }
680
681
682 /*
683 ** ------------------------
684 **  Internal routines
685 ** ------------------------
686 */
687
688
689 static void init_defaults()
690 {
691     char *s;
692
693     /* defaults for exported variables */
694
695 #ifdef DEFAULT_CONFIG
696     s = DEFAULT_CONFIG;
697 #else
698     s = "YOUR ORG";
699 #endif
700     conf_org.s = stralloc(s);
701     malloc_mark(conf_org.s);
702     conf_mailto.s = stralloc("operators");
703     malloc_mark(conf_mailto.s);
704     conf_dumpuser.s = stralloc(CLIENT_LOGIN);
705     malloc_mark(conf_dumpuser.s);
706 #ifdef DEFAULT_TAPE_DEVICE
707     s = DEFAULT_TAPE_DEVICE;
708 #else
709     s = "/dev/rmt8";
710 #endif
711     conf_tapedev.s = stralloc(s);
712     malloc_mark(conf_tapedev.s);
713 #ifdef DEFAULT_RAW_TAPE_DEVICE
714     s = DEFAULT_RAW_TAPE_DEVICE;
715 #else
716     s = "/dev/rawft0";
717 #endif
718     conf_rawtapedev.s = stralloc(s);
719     malloc_mark(conf_rawtapedev.s);
720     conf_tpchanger.s = stralloc("");
721     malloc_mark(conf_tpchanger.s);
722 #ifdef DEFAULT_CHANGER_DEVICE
723     s = DEFAULT_CHANGER_DEVICE;
724 #else
725     s = "/dev/null";
726 #endif
727     conf_chngrdev.s = stralloc(s);
728     malloc_mark(conf_chngrdev.s);
729     conf_chngrfile.s = stralloc("/usr/adm/amanda/changer-status");
730     malloc_mark(conf_chngrfile.s);
731     conf_labelstr.s = stralloc(".*");
732     malloc_mark(conf_labelstr.s);
733     conf_tapelist.s = stralloc("tapelist");
734     malloc_mark(conf_tapelist.s);
735     conf_infofile.s = stralloc("/usr/adm/amanda/curinfo");
736     malloc_mark(conf_infofile.s);
737     conf_logdir.s = stralloc("/usr/adm/amanda");
738     malloc_mark(conf_logdir.s);
739     conf_diskfile.s = stralloc("disklist");
740     malloc_mark(conf_diskfile.s);
741     conf_diskdir.s  = stralloc("/dumps/amanda");
742     malloc_mark(conf_diskdir.s);
743     conf_tapetype.s = stralloc("EXABYTE");
744     malloc_mark(conf_tapetype.s);
745     conf_indexdir.s = stralloc("/usr/adm/amanda/index");
746     malloc_mark(conf_indexdir.s);
747     conf_columnspec.s = stralloc("");
748     malloc_mark(conf_columnspec.s);
749     conf_dumporder.s = stralloc("ttt");
750     malloc_mark(conf_dumporder.s);
751     conf_amrecover_changer.s = stralloc("");
752     conf_printer.s = stralloc("");
753     conf_displayunit.s = stralloc("k");
754     conf_label_new_tapes.s = stralloc("");
755
756     conf_krb5keytab.s = stralloc("/.amanda-v5-keytab");
757     conf_krb5principal.s = stralloc("service/amanda");
758
759     conf_dumpcycle.i    = 10;
760     conf_runspercycle.i = 0;
761     conf_tapecycle.i    = 15;
762     conf_runtapes.i     = 1;
763     conf_disksize.i     = 0;
764     conf_netusage.i     = 300;
765     conf_inparallel.i   = 10;
766     conf_maxdumps.i     = 1;
767     conf_timeout.i      = 2;
768     conf_bumppercent.i  = 0;
769     conf_bumpsize.i     = 10*1024;
770     conf_bumpdays.i     = 2;
771     conf_bumpmult.r     = 1.5;
772     conf_etimeout.i     = 300;
773     conf_dtimeout.i     = 1800;
774     conf_ctimeout.i     = 30;
775     conf_tapebufs.i     = 20;
776     conf_autoflush.i    = 0;
777     conf_reserve.i      = 100;
778     conf_maxdumpsize.am64       = -1;
779     conf_amrecover_do_fsf.i = 1;
780     conf_amrecover_check_label.i = 1;
781     conf_taperalgo.i = 0;
782
783     /* defaults for internal variables */
784
785     seen_org = 0;
786     seen_mailto = 0;
787     seen_dumpuser = 0;
788     seen_tapedev = 0;
789     seen_rawtapedev = 0;
790     seen_printer = 0;
791     seen_tpchanger = 0;
792     seen_chngrdev = 0;
793     seen_chngrfile = 0;
794     seen_labelstr = 0;
795     seen_runtapes = 0;
796     seen_maxdumps = 0;
797     seen_tapelist = 0;
798     seen_infofile = 0;
799     seen_diskfile = 0;
800     seen_diskdir = 0;
801     seen_logdir = 0;
802     seen_bumppercent = 0;
803     seen_bumpsize = 0;
804     seen_bumpmult = 0;
805     seen_bumpdays = 0;
806     seen_tapetype = 0;
807     seen_dumpcycle = 0;
808     seen_runspercycle = 0;
809     seen_maxcycle = 0;
810     seen_tapecycle = 0;
811     seen_disksize = 0;
812     seen_netusage = 0;
813     seen_inparallel = 0;
814     seen_dumporder = 0;
815     seen_timeout = 0;
816     seen_indexdir = 0;
817     seen_etimeout = 0;
818     seen_dtimeout = 0;
819     seen_ctimeout = 0;
820     seen_tapebufs = 0;
821     seen_autoflush = 0;
822     seen_reserve = 0;
823     seen_maxdumpsize = 0;
824     seen_columnspec = 0;
825     seen_amrecover_do_fsf = 0;
826     seen_amrecover_check_label = 0;
827     seen_amrecover_changer = 0;
828     seen_taperalgo = 0;
829     seen_displayunit = 0;
830     seen_krb5keytab = 0;
831     seen_krb5principal = 0;
832     seen_label_new_tapes = 0;
833
834     line_num = got_parserror = 0;
835     allow_overwrites = 0;
836     token_pushed = 0;
837
838     while(holdingdisks != NULL) {
839         holdingdisk_t *hp;
840
841         hp = holdingdisks;
842         holdingdisks = holdingdisks->next;
843         amfree(hp);
844     }
845     num_holdingdisks = 0;
846
847     /* free any previously declared dump, tape and interface types */
848
849     while(dumplist != NULL) {
850         dumptype_t *dp;
851
852         dp = dumplist;
853         dumplist = dumplist->next;
854         amfree(dp);
855     }
856     while(tapelist != NULL) {
857         tapetype_t *tp;
858
859         tp = tapelist;
860         tapelist = tapelist->next;
861         amfree(tp);
862     }
863     while(interface_list != NULL) {
864         interface_t *ip;
865
866         ip = interface_list;
867         interface_list = interface_list->next;
868         amfree(ip);
869     }
870
871     /* create some predefined dumptypes for backwards compatability */
872     init_dumptype_defaults();
873     dpcur.name = "NO-COMPRESS"; dpcur.seen = -1;
874     dpcur.compress = COMP_NONE; dpcur.s_compress = -1;
875     save_dumptype();
876
877     init_dumptype_defaults();
878     dpcur.name = "COMPRESS-FAST"; dpcur.seen = -1;
879     dpcur.compress = COMP_FAST; dpcur.s_compress = -1;
880     save_dumptype();
881
882     init_dumptype_defaults();
883     dpcur.name = "COMPRESS-BEST"; dpcur.seen = -1;
884     dpcur.compress = COMP_BEST; dpcur.s_compress = -1;
885     save_dumptype();
886
887     init_dumptype_defaults();
888     dpcur.name = "COMPRESS-CUST"; dpcur.seen = -1;
889     dpcur.compress = COMP_CUST; dpcur.s_compress = -1;
890     save_dumptype();
891
892     init_dumptype_defaults();
893     dpcur.name = "SRVCOMPRESS"; dpcur.seen = -1;
894     dpcur.compress = COMP_SERV_FAST; dpcur.s_compress = -1;
895     save_dumptype();
896
897     init_dumptype_defaults();
898     dpcur.name = "BSD-AUTH"; dpcur.seen = -1;
899     amfree(dpcur.security_driver);
900     dpcur.security_driver = stralloc("BSD"); dpcur.s_security_driver = -1;
901     save_dumptype();
902
903     init_dumptype_defaults();
904     dpcur.name = "KRB4-AUTH"; dpcur.seen = -1;
905     amfree(dpcur.security_driver);
906     dpcur.security_driver = stralloc("KRB4"); dpcur.s_security_driver = -1;
907     save_dumptype();
908
909     init_dumptype_defaults();
910     dpcur.name = "NO-RECORD"; dpcur.seen = -1;
911     dpcur.record = 0; dpcur.s_record = -1;
912     save_dumptype();
913
914     init_dumptype_defaults();
915     dpcur.name = "NO-HOLD"; dpcur.seen = -1;
916     dpcur.no_hold = 1; dpcur.s_no_hold = -1;
917     save_dumptype();
918
919     init_dumptype_defaults();
920     dpcur.name = "NO-FULL"; dpcur.seen = -1;
921     dpcur.strategy = DS_NOFULL; dpcur.s_strategy = -1;
922     save_dumptype();
923 }
924
925 static void read_conffile_recursively(filename)
926 char *filename;
927 {
928     extern int errno;
929
930     /* Save globals used in read_confline(), elsewhere. */
931     int  save_line_num  = line_num;
932     FILE *save_conf     = conf;
933     char *save_confname = confname;
934
935     if (*filename == '/' || config_dir == NULL) {
936         confname = stralloc(filename);
937     } else {
938         confname = stralloc2(config_dir, filename);
939     }
940
941     if((conf = fopen(confname, "r")) == NULL) {
942         fprintf(stderr, "could not open conf file \"%s\": %s\n", confname,
943                 strerror(errno));
944         amfree(confname);
945         got_parserror = -1;
946         return;
947     }
948
949     line_num = 0;
950
951     /* read_confline() can invoke us recursively via "includefile" */
952     while(read_confline());
953     afclose(conf);
954
955     amfree(confname);
956
957     /* Restore globals */
958     line_num = save_line_num;
959     conf     = save_conf;
960     confname = save_confname;
961 }
962
963
964 /* ------------------------ */
965
966
967 keytab_t main_keytable[] = {
968     { "BUMPDAYS", BUMPDAYS },
969     { "BUMPMULT", BUMPMULT },
970     { "BUMPSIZE", BUMPSIZE },
971     { "BUMPPERCENT", BUMPPERCENT },
972     { "DEFINE", DEFINE },
973     { "DISKDIR", DISKDIR },     /* XXX - historical */
974     { "DISKFILE", DISKFILE },
975     { "DISKSIZE", DISKSIZE },   /* XXX - historical */
976     { "DUMPCYCLE", DUMPCYCLE },
977     { "RUNSPERCYCLE", RUNSPERCYCLE },
978     { "DUMPTYPE", DUMPTYPE },
979     { "DUMPUSER", DUMPUSER },
980     { "PRINTER", PRINTER },
981     { "HOLDINGDISK", HOLDING },
982     { "INCLUDEFILE", INCLUDEFILE },
983     { "INDEXDIR", INDEXDIR },
984     { "INFOFILE", INFOFILE },
985     { "INPARALLEL", INPARALLEL },
986     { "DUMPORDER", DUMPORDER },
987     { "INTERFACE", INTERFACE },
988     { "LABELSTR", LABELSTR },
989     { "LOGDIR", LOGDIR },
990     { "LOGFILE", LOGFILE },     /* XXX - historical */
991     { "MAILTO", MAILTO },
992     { "MAXCYCLE", MAXCYCLE },   /* XXX - historical */
993     { "MAXDUMPS", MAXDUMPS },
994     { "MINCYCLE", DUMPCYCLE },  /* XXX - historical */
995     { "NETUSAGE", NETUSAGE },   /* XXX - historical */
996     { "ORG", ORG },
997     { "RUNTAPES", RUNTAPES },
998     { "TAPECYCLE", TAPECYCLE },
999     { "TAPEDEV", TAPEDEV },
1000     { "TAPELIST", TAPELIST },
1001     { "TAPETYPE", TAPETYPE },
1002     { "TIMEOUT", TIMEOUT },     /* XXX - historical */
1003     { "TPCHANGER", TPCHANGER },
1004     { "CHANGERDEV", CHNGRDEV },
1005     { "CHANGERFILE", CHNGRFILE },
1006     { "ETIMEOUT", ETIMEOUT },
1007     { "DTIMEOUT", DTIMEOUT },
1008     { "CTIMEOUT", CTIMEOUT },
1009     { "TAPEBUFS", TAPEBUFS },
1010     { "RAWTAPEDEV", RAWTAPEDEV },
1011     { "AUTOFLUSH", AUTOFLUSH },
1012     { "RESERVE", RESERVE },
1013     { "MAXDUMPSIZE", MAXDUMPSIZE },
1014     { "COLUMNSPEC", COLUMNSPEC },
1015     { "AMRECOVER_DO_FSF", AMRECOVER_DO_FSF },
1016     { "AMRECOVER_CHECK_LABEL", AMRECOVER_CHECK_LABEL },
1017     { "AMRECOVER_CHANGER", AMRECOVER_CHANGER },
1018     { "TAPERALGO", TAPERALGO },
1019     { "DISPLAYUNIT", DISPLAYUNIT },
1020     { "KRB5KEYTAB", KRB5KEYTAB },
1021     { "KRB5PRINCIPAL", KRB5PRINCIPAL },
1022     { "LABEL_NEW_TAPES", LABEL_NEW_TAPES },
1023     { NULL, IDENT }
1024 };
1025
1026 static int read_confline()
1027 {
1028     keytable = main_keytable;
1029
1030     line_num += 1;
1031     get_conftoken(ANY);
1032     switch(tok) {
1033     case INCLUDEFILE:
1034         {
1035             char *fn;
1036
1037             get_conftoken(STRING);
1038             fn = tokenval.s;
1039             read_conffile_recursively(fn);
1040         }
1041         break;
1042
1043     case ORG:       get_simple(&conf_org,       &seen_org,       STRING); break;
1044     case MAILTO:    get_simple(&conf_mailto,    &seen_mailto,    STRING); break;
1045     case DUMPUSER:  get_simple(&conf_dumpuser,  &seen_dumpuser,  STRING); break;
1046     case PRINTER:   get_simple(&conf_printer,   &seen_printer,   STRING); break;
1047     case DUMPCYCLE: get_simple(&conf_dumpcycle, &seen_dumpcycle, INT);
1048                     if(conf_dumpcycle.i < 0) {
1049                         parserror("dumpcycle must be positive");
1050                     }
1051                     break;
1052     case RUNSPERCYCLE: get_simple(&conf_runspercycle, &seen_runspercycle, INT);
1053                     if(conf_runspercycle.i < -1) {
1054                         parserror("runspercycle must be >= -1");
1055                     }
1056                     break;
1057     case MAXCYCLE:  get_simple(&conf_maxcycle,  &seen_maxcycle,  INT);    break;
1058     case TAPECYCLE: get_simple(&conf_tapecycle, &seen_tapecycle, INT);
1059                     if(conf_tapecycle.i < 1) {
1060                         parserror("tapecycle must be positive");
1061                     }
1062                     break;
1063     case RUNTAPES:  get_simple(&conf_runtapes,  &seen_runtapes,  INT);
1064                     if(conf_runtapes.i < 0) {
1065                         parserror("runtapes must be positive");
1066                     }
1067                     break;
1068     case TAPEDEV:   get_simple(&conf_tapedev,   &seen_tapedev,   STRING); break;
1069     case RAWTAPEDEV:get_simple(&conf_rawtapedev,&seen_rawtapedev,STRING); break;
1070     case TPCHANGER: get_simple(&conf_tpchanger, &seen_tpchanger, STRING); break;
1071     case CHNGRDEV:  get_simple(&conf_chngrdev,  &seen_chngrdev,  STRING); break;
1072     case CHNGRFILE: get_simple(&conf_chngrfile, &seen_chngrfile, STRING); break;
1073     case LABELSTR:  get_simple(&conf_labelstr,  &seen_labelstr,  STRING); break;
1074     case TAPELIST:  get_simple(&conf_tapelist,  &seen_tapelist,  STRING); break;
1075     case INFOFILE:  get_simple(&conf_infofile,  &seen_infofile,  STRING); break;
1076     case LOGDIR:    get_simple(&conf_logdir,    &seen_logdir,    STRING); break;
1077     case DISKFILE:  get_simple(&conf_diskfile,  &seen_diskfile,  STRING); break;
1078     case BUMPMULT:  get_simple(&conf_bumpmult,  &seen_bumpmult,  REAL);
1079                     if(conf_bumpmult.r < 0.999) {
1080                         parserror("bumpmult must be positive");
1081                     }
1082                     break;
1083     case BUMPPERCENT:  get_simple(&conf_bumppercent,  &seen_bumppercent,  INT);
1084                     if(conf_bumppercent.i < 0 || conf_bumppercent.i > 100) {
1085                         parserror("bumppercent must be between 0 and 100");
1086                     }
1087                     break;
1088     case BUMPSIZE:  get_simple(&conf_bumpsize,  &seen_bumpsize,  INT);
1089                     if(conf_bumpsize.i < 1) {
1090                         parserror("bumpsize must be positive");
1091                     }
1092                     break;
1093     case BUMPDAYS:  get_simple(&conf_bumpdays,  &seen_bumpdays,  INT);
1094                     if(conf_bumpdays.i < 1) {
1095                         parserror("bumpdays must be positive");
1096                     }
1097                     break;
1098     case NETUSAGE:  get_simple(&conf_netusage,  &seen_netusage,  INT);
1099                     if(conf_netusage.i < 1) {
1100                         parserror("netusage must be positive");
1101                     }
1102                     break;
1103     case INPARALLEL:get_simple(&conf_inparallel,&seen_inparallel,INT);
1104                     if(conf_inparallel.i < 1 || conf_inparallel.i >MAX_DUMPERS){
1105                         parserror(
1106                             "inparallel must be between 1 and MAX_DUMPERS (%d)",
1107                             MAX_DUMPERS);
1108                     }
1109                     break;
1110     case DUMPORDER: get_simple(&conf_dumporder, &seen_dumporder, STRING); break;
1111     case TIMEOUT:   get_simple(&conf_timeout,   &seen_timeout,   INT);    break;
1112     case MAXDUMPS:  get_simple(&conf_maxdumps,  &seen_maxdumps,  INT);
1113                     if(conf_maxdumps.i < 1) {
1114                         parserror("maxdumps must be positive");
1115                     }
1116                     break;
1117     case TAPETYPE:  get_simple(&conf_tapetype,  &seen_tapetype,  IDENT);  break;
1118     case INDEXDIR:  get_simple(&conf_indexdir,  &seen_indexdir,  STRING); break;
1119     case ETIMEOUT:  get_simple(&conf_etimeout,  &seen_etimeout,  INT);    break;
1120     case DTIMEOUT:  get_simple(&conf_dtimeout,  &seen_dtimeout,  INT);
1121                     if(conf_dtimeout.i < 1) {
1122                         parserror("dtimeout must be positive");
1123                     }
1124                     break;
1125     case CTIMEOUT:  get_simple(&conf_ctimeout,  &seen_ctimeout,  INT);
1126                     if(conf_ctimeout.i < 1) {
1127                         parserror("ctimeout must be positive");
1128                     }
1129                     break;
1130     case TAPEBUFS:  get_simple(&conf_tapebufs,  &seen_tapebufs,  INT);
1131                     if(conf_tapebufs.i < 1) {
1132                         parserror("tapebufs must be positive");
1133                     }
1134                     break;
1135     case AUTOFLUSH: get_simple(&conf_autoflush, &seen_autoflush, BOOL);   break;
1136     case RESERVE:   get_simple(&conf_reserve,   &seen_reserve,   INT);
1137                     if(conf_reserve.i < 0 || conf_reserve.i > 100) {
1138                         parserror("reserve must be between 0 and 100");
1139                     }
1140                     break;
1141     case MAXDUMPSIZE:get_simple(&conf_maxdumpsize,&seen_maxdumpsize,AM64); break;
1142     case COLUMNSPEC:get_simple(&conf_columnspec,&seen_columnspec,STRING); break;
1143
1144     case AMRECOVER_DO_FSF: get_simple(&conf_amrecover_do_fsf,&seen_amrecover_do_fsf, BOOL); break;
1145     case AMRECOVER_CHECK_LABEL: get_simple(&conf_amrecover_check_label,&seen_amrecover_check_label, BOOL); break;
1146     case AMRECOVER_CHANGER: get_simple(&conf_amrecover_changer,&seen_amrecover_changer, STRING); break;
1147
1148     case TAPERALGO: get_taperalgo(&conf_taperalgo,&seen_taperalgo); break;
1149     case DISPLAYUNIT: get_simple(&conf_displayunit,&seen_displayunit, STRING);
1150                       if(strcmp(conf_displayunit.s,"k") == 0 ||
1151                          strcmp(conf_displayunit.s,"K") == 0) {
1152                           conf_displayunit.s[0] = toupper(conf_displayunit.s[0]);
1153                           unit_divisor=1;
1154                       }
1155                       else if(strcmp(conf_displayunit.s,"m") == 0 ||
1156                          strcmp(conf_displayunit.s,"M") == 0) {
1157                           conf_displayunit.s[0] = toupper(conf_displayunit.s[0]);
1158                           unit_divisor=1024;
1159                       }
1160                       else if(strcmp(conf_displayunit.s,"g") == 0 ||
1161                          strcmp(conf_displayunit.s,"G") == 0) {
1162                           conf_displayunit.s[0] = toupper(conf_displayunit.s[0]);
1163                           unit_divisor=1024*1024;
1164                       }
1165                       else if(strcmp(conf_displayunit.s,"t") == 0 ||
1166                          strcmp(conf_displayunit.s,"T") == 0) {
1167                           conf_displayunit.s[0] = toupper(conf_displayunit.s[0]);
1168                           unit_divisor=1024*1024*1024;
1169                       }
1170                       else {
1171                           parserror("displayunit must be k,m,g or t.");
1172                       }
1173                       break;
1174
1175     /* kerberos 5 bits.  only useful when kerberos 5 built in... */
1176     case KRB5KEYTAB:    get_simple(&conf_krb5keytab,   &seen_krb5keytab,   STRING); break;
1177     case KRB5PRINCIPAL: get_simple(&conf_krb5principal,&seen_krb5principal,STRING); break;
1178
1179     case LOGFILE: /* XXX - historical */
1180         /* truncate the filename part and pretend he said "logdir" */
1181         {
1182             char *p;
1183
1184             get_simple(&conf_logdir, &seen_logdir, STRING);
1185
1186             p = strrchr(conf_logdir.s, '/');
1187             if (p != (char *)0) *p = '\0';
1188         }
1189         break;
1190
1191     case DISKDIR:
1192         {
1193             char *s;
1194
1195             get_conftoken(STRING);
1196             s = tokenval.s;
1197
1198             if(!seen_diskdir) {
1199                 conf_diskdir.s = newstralloc(conf_diskdir.s, s);
1200                 seen_diskdir = line_num;
1201             }
1202
1203             init_holdingdisk_defaults();
1204             hdcur.name = "default from DISKDIR";
1205             hdcur.seen = line_num;
1206             hdcur.diskdir = stralloc(s);
1207             hdcur.s_disk = line_num;
1208             hdcur.disksize = conf_disksize.i;
1209             hdcur.s_size = seen_disksize;
1210             save_holdingdisk();
1211         }
1212         break;
1213
1214     case DISKSIZE:
1215         {
1216             int i;
1217
1218             i = get_int();
1219             i = (i / DISK_BLOCK_KB) * DISK_BLOCK_KB;
1220
1221             if(!seen_disksize) {
1222                 conf_disksize.i = i;
1223                 seen_disksize = line_num;
1224             }
1225
1226             if(holdingdisks != NULL)
1227                 holdingdisks->disksize = i;
1228         }
1229
1230         break;
1231
1232     case HOLDING:
1233         get_holdingdisk();
1234         break;
1235
1236     case DEFINE:
1237         get_conftoken(ANY);
1238         if(tok == DUMPTYPE) get_dumptype();
1239         else if(tok == TAPETYPE) get_tapetype();
1240         else if(tok == INTERFACE) get_interface();
1241         else parserror("DUMPTYPE, INTERFACE or TAPETYPE expected");
1242         break;
1243     case LABEL_NEW_TAPES:
1244         get_simple(&conf_label_new_tapes, &seen_label_new_tapes, STRING);
1245         break;
1246
1247     case NL:    /* empty line */
1248         break;
1249     case END:   /* end of file */
1250         return 0;
1251     default:
1252         parserror("configuration keyword expected");
1253     }
1254     if(tok != NL) get_conftoken(NL);
1255     return 1;
1256 }
1257
1258 keytab_t holding_keytable[] = {
1259     { "DIRECTORY", DIRECTORY },
1260     { "COMMENT", COMMENT },
1261     { "USE", USE },
1262     { "CHUNKSIZE", CHUNKSIZE },
1263     { NULL, IDENT }
1264 };
1265
1266 static void get_holdingdisk()
1267 {
1268     int done;
1269     int save_overwrites;
1270     keytab_t *save_kt;
1271
1272     save_overwrites = allow_overwrites;
1273     allow_overwrites = 1;
1274
1275     save_kt = keytable;
1276     keytable = holding_keytable;
1277
1278     init_holdingdisk_defaults();
1279
1280     get_conftoken(IDENT);
1281     hdcur.name = stralloc(tokenval.s);
1282     malloc_mark(hdcur.name);
1283     hdcur.seen = line_num;
1284
1285     get_conftoken(LBRACE);
1286     get_conftoken(NL);
1287
1288     done = 0;
1289     do {
1290         line_num += 1;
1291         get_conftoken(ANY);
1292         switch(tok) {
1293
1294         case COMMENT:
1295             get_simple((val_t *)&hdcur.comment, &hdcur.s_comment, STRING);
1296             break;
1297         case DIRECTORY:
1298             get_simple((val_t *)&hdcur.diskdir, &hdcur.s_disk, STRING);
1299             break;
1300         case USE:
1301             get_simple((val_t *)&hdcur.disksize, &hdcur.s_size, LONG);
1302             hdcur.disksize = am_floor(hdcur.disksize, DISK_BLOCK_KB);
1303             break;
1304         case CHUNKSIZE:
1305             get_simple((val_t *)&hdcur.chunksize, &hdcur.s_csize, LONG);
1306             if(hdcur.chunksize == 0) {
1307                 hdcur.chunksize =  ((INT_MAX / 1024) - (2 * DISK_BLOCK_KB));
1308             } else if(hdcur.chunksize < 0) {
1309                 parserror("Negative chunksize (%ld) is no longer supported",
1310                           hdcur.chunksize);
1311             }
1312             hdcur.chunksize = am_floor(hdcur.chunksize, DISK_BLOCK_KB);
1313             break;
1314         case RBRACE:
1315             done = 1;
1316             break;
1317         case NL:        /* empty line */
1318             break;
1319         case END:       /* end of file */
1320             done = 1;
1321         default:
1322             parserror("holding disk parameter expected");
1323         }
1324         if(tok != NL && tok != END) get_conftoken(NL);
1325     } while(!done);
1326
1327     save_holdingdisk();
1328
1329     allow_overwrites = save_overwrites;
1330     keytable = save_kt;
1331 }
1332
1333 static void init_holdingdisk_defaults()
1334 {
1335     hdcur.comment = stralloc("");
1336     hdcur.diskdir = stralloc(conf_diskdir.s);
1337     malloc_mark(hdcur.diskdir);
1338     hdcur.disksize = 0;
1339     hdcur.chunksize = 1024*1024/**1024*/; /* 1 Gb = 1M counted in 1Kb blocks */
1340
1341     hdcur.s_comment = 0;
1342     hdcur.s_disk = 0;
1343     hdcur.s_size = 0;
1344     hdcur.s_csize = 0;
1345
1346     hdcur.up = (void *)0;
1347 }
1348
1349 static void save_holdingdisk()
1350 {
1351     holdingdisk_t *hp;
1352
1353     hp = alloc(sizeof(holdingdisk_t));
1354     malloc_mark(hp);
1355     *hp = hdcur;
1356     hp->next = holdingdisks;
1357     holdingdisks = hp;
1358
1359     num_holdingdisks++;
1360 }
1361
1362
1363 keytab_t dumptype_keytable[] = {
1364     { "AUTH", AUTH },
1365     { "BUMPDAYS", BUMPDAYS },
1366     { "BUMPMULT", BUMPMULT },
1367     { "BUMPSIZE", BUMPSIZE },
1368     { "BUMPPERCENT", BUMPPERCENT },
1369     { "COMMENT", COMMENT },
1370     { "COMPRATE", COMPRATE },
1371     { "COMPRESS", COMPRESS },
1372     { "ENCRYPT", ENCRYPT },
1373     { "SERVER_DECRYPT_OPTION", SRV_DECRYPT_OPT },
1374     { "CLIENT_DECRYPT_OPTION", CLNT_DECRYPT_OPT },
1375     { "DUMPCYCLE", DUMPCYCLE },
1376     { "EXCLUDE", EXCLUDE },
1377     { "FREQUENCY", FREQUENCY }, /* XXX - historical */
1378     { "HOLDINGDISK", HOLDING },
1379     { "IGNORE", IGNORE },
1380     { "INCLUDE", INCLUDE },
1381     { "INDEX", INDEX },
1382     { "KENCRYPT", KENCRYPT },
1383     { "MAXCYCLE", MAXCYCLE },   /* XXX - historical */
1384     { "MAXDUMPS", MAXDUMPS },
1385     { "MAXPROMOTEDAY", MAXPROMOTEDAY },
1386     { "OPTIONS", OPTIONS },     /* XXX - historical */
1387     { "PRIORITY", PRIORITY },
1388     { "PROGRAM", PROGRAM },
1389     { "RECORD", RECORD },
1390     { "SKIP-FULL", SKIP_FULL },
1391     { "SKIP-INCR", SKIP_INCR },
1392     { "STARTTIME", STARTTIME },
1393     { "STRATEGY", STRATEGY },
1394     { "TAPE_SPLITSIZE", TAPE_SPLITSIZE },
1395     { "SPLIT_DISKBUFFER", SPLIT_DISKBUFFER },
1396     { "FALLBACK_SPLITSIZE", FALLBACK_SPLITSIZE },
1397     { "ESTIMATE", ESTIMATE },
1398     { "SERVER_CUSTOM_COMPRESS", SRVCOMPPROG },
1399     { "CLIENT_CUSTOM_COMPRESS", CLNTCOMPPROG },
1400     { "SERVER_ENCRYPT", SRV_ENCRYPT },
1401     { "CLIENT_ENCRYPT", CLNT_ENCRYPT },
1402     { NULL, IDENT }
1403 };
1404
1405 dumptype_t *read_dumptype(name, from, fname, linenum)
1406      char *name;
1407      FILE *from;
1408      char *fname;
1409      int *linenum;
1410 {
1411     int done;
1412     int save_overwrites;
1413     keytab_t *save_kt;
1414     val_t tmpval;
1415     FILE *saved_conf = NULL;
1416     char *saved_fname = NULL;
1417
1418     if (from) {
1419         saved_conf = conf;
1420         conf = from;
1421     }
1422
1423     if (fname) {
1424         saved_fname = confname;
1425         confname = fname;
1426     }
1427
1428     if (linenum)
1429         line_num = *linenum;
1430
1431     save_overwrites = allow_overwrites;
1432     allow_overwrites = 1;
1433
1434     save_kt = keytable;
1435     keytable = dumptype_keytable;
1436
1437     init_dumptype_defaults();
1438
1439     if (name) {
1440         dpcur.name = name;
1441     } else {
1442         get_conftoken(IDENT);
1443         dpcur.name = stralloc(tokenval.s);
1444         malloc_mark(dpcur.name);
1445     }
1446
1447     dpcur.seen = line_num;
1448
1449     if (! name) {
1450         get_conftoken(LBRACE);
1451         get_conftoken(NL);
1452     }
1453
1454     done = 0;
1455     do {
1456         line_num += 1;
1457         get_conftoken(ANY);
1458         switch(tok) {
1459
1460         case AUTH:
1461             get_simple((val_t *)&dpcur.security_driver,
1462                 &dpcur.s_security_driver, STRING);
1463             break;
1464         case COMMENT:
1465             get_simple((val_t *)&dpcur.comment, &dpcur.s_comment, STRING);
1466             break;
1467         case COMPRATE:
1468             get_comprate();
1469             break;
1470         case COMPRESS:
1471             get_compress();
1472             break;
1473         case ENCRYPT:
1474             get_encrypt();
1475             break;
1476         case SRV_DECRYPT_OPT:
1477             get_simple((val_t *)&dpcur.srv_decrypt_opt, &dpcur.s_srv_decrypt_opt, STRING);
1478             break;
1479         case CLNT_DECRYPT_OPT:
1480             get_simple((val_t *)&dpcur.clnt_decrypt_opt, &dpcur.s_clnt_decrypt_opt, STRING);
1481             break;
1482         case DUMPCYCLE:
1483             get_simple((val_t *)&dpcur.dumpcycle, &dpcur.s_dumpcycle, INT);
1484             if(dpcur.dumpcycle < 0) {
1485                 parserror("dumpcycle must be positive");
1486             }
1487             break;
1488         case EXCLUDE:
1489             get_exclude();
1490             break;
1491         case FREQUENCY:
1492             get_simple((val_t *)&dpcur.frequency, &dpcur.s_frequency, INT);
1493             break;
1494         case HOLDING:
1495             get_simple(&tmpval, &dpcur.s_no_hold, BOOL);
1496             dpcur.no_hold = (tmpval.i == 0);
1497             break;
1498         case IGNORE:
1499             get_simple(&tmpval, &dpcur.s_ignore, BOOL);
1500             dpcur.ignore = (tmpval.i != 0);
1501             break;
1502         case INCLUDE:
1503             get_include();
1504             break;
1505         case INDEX:
1506             get_simple(&tmpval, &dpcur.s_index, BOOL);
1507             dpcur.index = (tmpval.i != 0);
1508             break;
1509         case KENCRYPT:
1510             get_simple(&tmpval, &dpcur.s_kencrypt, BOOL);
1511             dpcur.kencrypt = (tmpval.i != 0);
1512             break;
1513         case MAXCYCLE:
1514             get_simple((val_t *)&conf_maxcycle, &dpcur.s_maxcycle, INT);
1515             break;
1516         case MAXDUMPS:
1517             get_simple((val_t *)&dpcur.maxdumps, &dpcur.s_maxdumps, INT);
1518             if(dpcur.maxdumps < 1) {
1519                 parserror("maxdumps must be positive");
1520             }
1521             break;
1522         case MAXPROMOTEDAY:
1523             get_simple((val_t *)&dpcur.maxpromoteday, &dpcur.s_maxpromoteday, INT);
1524             if(dpcur.maxpromoteday < 0) {
1525                 parserror("dpcur.maxpromoteday must be >= 0");
1526             }
1527             break;
1528         case BUMPPERCENT:
1529             get_simple((val_t *)&dpcur.bumppercent,  &dpcur.s_bumppercent,  INT);
1530             if(dpcur.bumppercent < 0 || dpcur.bumppercent > 100) {
1531                 parserror("bumppercent must be between 0 and 100");
1532             }
1533             break;
1534         case BUMPSIZE:
1535             get_simple((val_t *)&dpcur.bumpsize,  &dpcur.s_bumpsize,  INT);
1536             if(dpcur.bumpsize < 1) {
1537                 parserror("bumpsize must be positive");
1538             }
1539             break;
1540         case BUMPDAYS:
1541             get_simple((val_t *)&dpcur.bumpdays,  &dpcur.s_bumpdays,  INT);
1542             if(dpcur.bumpdays < 1) {
1543                 parserror("bumpdays must be positive");
1544             }
1545             break;
1546         case BUMPMULT:
1547             get_simple((val_t *)&dpcur.bumpmult,  &dpcur.s_bumpmult,  REAL);
1548             if(dpcur.bumpmult < 0.999) {
1549                 parserror("bumpmult must be positive (%f)",dpcur.bumpmult);
1550             }
1551             break;
1552         case OPTIONS:
1553             get_dumpopts();
1554             break;
1555         case PRIORITY:
1556             get_priority();
1557             break;
1558         case PROGRAM:
1559             get_simple((val_t *)&dpcur.program, &dpcur.s_program, STRING);
1560             break;
1561         case RECORD:
1562             get_simple(&tmpval, &dpcur.s_record, BOOL);
1563             dpcur.record = (tmpval.i != 0);
1564             break;
1565         case SKIP_FULL:
1566             get_simple(&tmpval, &dpcur.s_skip_full, BOOL);
1567             dpcur.skip_full = (tmpval.i != 0);
1568             break;
1569         case SKIP_INCR:
1570             get_simple(&tmpval, &dpcur.s_skip_incr, BOOL);
1571             dpcur.skip_incr = (tmpval.i != 0);
1572             break;
1573         case STARTTIME:
1574             get_simple((val_t *)&dpcur.start_t, &dpcur.s_start_t, TIME);
1575             break;
1576         case STRATEGY:
1577             get_strategy();
1578             break;
1579         case ESTIMATE:
1580             get_estimate();
1581             break;
1582         case IDENT:
1583             copy_dumptype();
1584             break;
1585         case TAPE_SPLITSIZE:
1586             get_simple((val_t *)&dpcur.tape_splitsize,  &dpcur.s_tape_splitsize,  INT);
1587             if(dpcur.tape_splitsize < 0) {
1588               parserror("tape_splitsize must be >= 0");
1589             }
1590             break;
1591         case SPLIT_DISKBUFFER:
1592             get_simple((val_t *)&dpcur.split_diskbuffer, &dpcur.s_split_diskbuffer, STRING);
1593             break;
1594         case FALLBACK_SPLITSIZE:
1595             get_simple((val_t *)&dpcur.fallback_splitsize,  &dpcur.s_fallback_splitsize,  INT);
1596             if(dpcur.fallback_splitsize < 0) {
1597               parserror("fallback_splitsize must be >= 0");
1598             }
1599             break;
1600         case SRVCOMPPROG:
1601             get_simple((val_t *)&dpcur.srvcompprog, &dpcur.s_srvcompprog, STRING);
1602             break;
1603         case CLNTCOMPPROG:
1604             get_simple((val_t *)&dpcur.clntcompprog, &dpcur.s_clntcompprog, STRING);
1605             break;
1606         case SRV_ENCRYPT:
1607             get_simple((val_t *)&dpcur.srv_encrypt, &dpcur.s_srv_encrypt, STRING);
1608             break;
1609         case CLNT_ENCRYPT:
1610             get_simple((val_t *)&dpcur.clnt_encrypt, &dpcur.s_clnt_encrypt, STRING);
1611             break;
1612         case RBRACE:
1613             done = 1;
1614             break;
1615         case NL:        /* empty line */
1616             break;
1617         case END:       /* end of file */
1618             done = 1;
1619         default:
1620             parserror("dump type parameter expected");
1621         }
1622         if(tok != NL && tok != END &&
1623            /* When a name is specified, we shouldn't consume the NL
1624               after the RBRACE.  */
1625            (tok != RBRACE || name == 0))
1626             get_conftoken(NL);
1627     } while(!done);
1628
1629     /* XXX - there was a stupidity check in here for skip-incr and
1630     ** skip-full.  This check should probably be somewhere else. */
1631
1632     save_dumptype();
1633
1634     allow_overwrites = save_overwrites;
1635     keytable = save_kt;
1636
1637     if (linenum)
1638         *linenum = line_num;
1639
1640     if (fname)
1641         confname = saved_fname;
1642
1643     if (from)
1644         conf = saved_conf;
1645
1646     return lookup_dumptype(dpcur.name);
1647 }
1648
1649 static void get_dumptype()
1650 {
1651     read_dumptype(NULL, NULL, NULL, NULL);
1652 }
1653
1654 static void init_dumptype_defaults()
1655 {
1656     dpcur.comment = stralloc("");
1657     dpcur.program = stralloc("DUMP");
1658     dpcur.srvcompprog = stralloc("");
1659     dpcur.clntcompprog = stralloc("");
1660     dpcur.srv_encrypt = stralloc("");
1661     dpcur.clnt_encrypt = stralloc("");
1662     dpcur.exclude_file = NULL;
1663     dpcur.exclude_list = NULL;
1664     dpcur.include_file = NULL;
1665     dpcur.include_list = NULL;
1666     dpcur.priority = 1;
1667     dpcur.dumpcycle = conf_dumpcycle.i;
1668     dpcur.maxcycle = conf_maxcycle.i;
1669     dpcur.frequency = 1;
1670     dpcur.maxdumps = conf_maxdumps.i;
1671     dpcur.maxpromoteday = 10000;
1672     dpcur.bumppercent = conf_bumppercent.i;
1673     dpcur.bumpsize = conf_bumpsize.i;
1674     dpcur.bumpdays = conf_bumpdays.i;
1675     dpcur.bumpmult = conf_bumpmult.r;
1676     dpcur.start_t = 0;
1677     dpcur.security_driver = stralloc("BSD");
1678
1679     /* options */
1680     dpcur.record = 1;
1681     dpcur.strategy = DS_STANDARD;
1682     dpcur.estimate = ES_CLIENT;
1683     dpcur.compress = COMP_FAST;
1684     dpcur.encrypt = ENCRYPT_NONE;
1685     dpcur.srv_decrypt_opt = stralloc("-d");
1686     dpcur.clnt_decrypt_opt = stralloc("-d");
1687     dpcur.comprate[0] = dpcur.comprate[1] = 0.50;
1688     dpcur.skip_incr = dpcur.skip_full = 0;
1689     dpcur.no_hold = 0;
1690     dpcur.kencrypt = 0;
1691     dpcur.ignore = 0;
1692     dpcur.index = 0;
1693     dpcur.tape_splitsize = 0;
1694     dpcur.split_diskbuffer = NULL;
1695     dpcur.fallback_splitsize = 10 * 1024;
1696
1697     dpcur.s_comment = 0;
1698     dpcur.s_program = 0;
1699     dpcur.s_srvcompprog = 0;
1700     dpcur.s_clntcompprog = 0;
1701     dpcur.s_clnt_encrypt= 0;
1702     dpcur.s_srv_encrypt= 0;
1703
1704     dpcur.s_exclude_file = 0;
1705     dpcur.s_exclude_list = 0;
1706     dpcur.s_include_file = 0;
1707     dpcur.s_include_list = 0;
1708     dpcur.s_priority = 0;
1709     dpcur.s_dumpcycle = 0;
1710     dpcur.s_maxcycle = 0;
1711     dpcur.s_frequency = 0;
1712     dpcur.s_maxdumps = 0;
1713     dpcur.s_maxpromoteday = 0;
1714     dpcur.s_bumppercent = 0;
1715     dpcur.s_bumpsize = 0;
1716     dpcur.s_bumpdays = 0;
1717     dpcur.s_bumpmult = 0;
1718     dpcur.s_start_t = 0;
1719     dpcur.s_security_driver = 0;
1720     dpcur.s_record = 0;
1721     dpcur.s_strategy = 0;
1722     dpcur.s_estimate = 0;
1723     dpcur.s_compress = 0;
1724     dpcur.s_encrypt = 0;
1725     dpcur.s_srv_decrypt_opt = 0;
1726     dpcur.s_clnt_decrypt_opt = 0;
1727     dpcur.s_comprate = 0;
1728     dpcur.s_skip_incr = 0;
1729     dpcur.s_skip_full = 0;
1730     dpcur.s_no_hold = 0;
1731     dpcur.s_kencrypt = 0;
1732     dpcur.s_ignore = 0;
1733     dpcur.s_index = 0;
1734     dpcur.s_tape_splitsize = 0;
1735     dpcur.s_split_diskbuffer = 0;
1736     dpcur.s_fallback_splitsize = 0;
1737 }
1738
1739 static void save_dumptype()
1740 {
1741     dumptype_t *dp;
1742
1743     dp = lookup_dumptype(dpcur.name);
1744
1745     if(dp != (dumptype_t *)0) {
1746         parserror("dumptype %s already defined on line %d", dp->name, dp->seen);
1747         return;
1748     }
1749
1750     dp = alloc(sizeof(dumptype_t));
1751     malloc_mark(dp);
1752     *dp = dpcur;
1753     dp->next = dumplist;
1754     dumplist = dp;
1755 }
1756
1757 static void copy_dumptype()
1758 {
1759     dumptype_t *dt;
1760
1761     dt = lookup_dumptype(tokenval.s);
1762
1763     if(dt == NULL) {
1764         parserror("dump type parameter expected");
1765         return;
1766     }
1767
1768 #define dtcopy(v,s) if(dt->s) { dpcur.v = dt->v; dpcur.s = dt->s; }
1769
1770     if(dt->s_comment) {
1771         dpcur.comment = newstralloc(dpcur.comment, dt->comment);
1772         dpcur.s_comment = dt->s_comment;
1773     }
1774     if(dt->s_program) {
1775         dpcur.program = newstralloc(dpcur.program, dt->program);
1776         dpcur.s_program = dt->s_program;
1777     }
1778     if(dt->s_security_driver) {
1779         dpcur.security_driver = newstralloc(dpcur.security_driver,
1780                                             dt->security_driver);
1781         dpcur.s_security_driver = dt->s_security_driver;
1782     }
1783     if(dt->s_srvcompprog) {
1784         dpcur.srvcompprog = newstralloc(dpcur.srvcompprog, dt->srvcompprog);
1785         dpcur.s_srvcompprog = dt->s_srvcompprog;
1786     }
1787     if(dt->s_clntcompprog) {
1788         dpcur.clntcompprog = newstralloc(dpcur.clntcompprog, dt->clntcompprog);
1789         dpcur.s_clntcompprog = dt->s_clntcompprog;
1790     }
1791     if(dt->s_srv_encrypt) {
1792         dpcur.srv_encrypt = newstralloc(dpcur.srv_encrypt, dt->srv_encrypt);
1793         dpcur.s_srv_encrypt = dt->s_srv_encrypt;
1794     }
1795     if(dt->s_clnt_encrypt) {
1796         dpcur.clnt_encrypt = newstralloc(dpcur.clnt_encrypt, dt->clnt_encrypt);
1797         dpcur.s_clnt_encrypt = dt->s_clnt_encrypt;
1798     }
1799     if(dt->s_srv_decrypt_opt) {
1800         dpcur.srv_decrypt_opt = newstralloc(dpcur.srv_decrypt_opt, dt->srv_decrypt_opt);
1801         dpcur.s_srv_decrypt_opt = dt->s_srv_decrypt_opt;
1802     }
1803     if(dt->s_clnt_decrypt_opt) {
1804         dpcur.clnt_decrypt_opt = newstralloc(dpcur.clnt_decrypt_opt, dt->clnt_decrypt_opt);
1805         dpcur.s_clnt_decrypt_opt = dt->s_clnt_decrypt_opt;
1806     }
1807
1808     if(dt->s_exclude_file) {
1809         dpcur.exclude_file = duplicate_sl(dt->exclude_file);
1810         dpcur.s_exclude_file = dt->s_exclude_file;
1811     }
1812     if(dt->s_exclude_list) {
1813         dpcur.exclude_list = duplicate_sl(dt->exclude_list);
1814         dpcur.s_exclude_list = dt->s_exclude_list;
1815     }
1816     if(dt->s_include_file) {
1817         dpcur.include_file = duplicate_sl(dt->include_file);
1818         dpcur.s_include_file = dt->s_include_file;
1819     }
1820     if(dt->s_include_list) {
1821         dpcur.include_list = duplicate_sl(dt->include_list);
1822         dpcur.s_include_list = dt->s_include_list;
1823     }
1824     dtcopy(priority, s_priority);
1825     dtcopy(dumpcycle, s_dumpcycle);
1826     dtcopy(maxcycle, s_maxcycle);
1827     dtcopy(frequency, s_frequency);
1828     dtcopy(maxdumps, s_maxdumps);
1829     dtcopy(maxpromoteday, s_maxpromoteday);
1830     dtcopy(bumppercent, s_bumppercent);
1831     dtcopy(bumpsize, s_bumpsize);
1832     dtcopy(bumpdays, s_bumpdays);
1833     dtcopy(bumpmult, s_bumpmult);
1834     dtcopy(start_t, s_start_t);
1835     dtcopy(record, s_record);
1836     dtcopy(strategy, s_strategy);
1837     dtcopy(estimate, s_estimate);
1838     dtcopy(compress, s_compress);
1839     dtcopy(encrypt, s_encrypt);
1840     dtcopy(comprate[0], s_comprate);
1841     dtcopy(comprate[1], s_comprate);
1842     dtcopy(skip_incr, s_skip_incr);
1843     dtcopy(skip_full, s_skip_full);
1844     dtcopy(no_hold, s_no_hold);
1845     dtcopy(kencrypt, s_kencrypt);
1846     dtcopy(ignore, s_ignore);
1847     dtcopy(index, s_index);
1848     dtcopy(tape_splitsize, s_tape_splitsize);
1849     dtcopy(split_diskbuffer, s_split_diskbuffer);
1850     dtcopy(fallback_splitsize, s_fallback_splitsize);
1851 }
1852
1853 keytab_t tapetype_keytable[] = {
1854     { "COMMENT", COMMENT },
1855     { "LBL-TEMPL", LBL_TEMPL },
1856     { "BLOCKSIZE", BLOCKSIZE },
1857     { "FILE-PAD", FILE_PAD },
1858     { "FILEMARK", FILEMARK },
1859     { "LENGTH", LENGTH },
1860     { "SPEED", SPEED },
1861     { NULL, IDENT }
1862 };
1863
1864 static void get_tapetype()
1865 {
1866     int done;
1867     int save_overwrites;
1868     val_t value;
1869
1870     keytab_t *save_kt;
1871
1872     save_overwrites = allow_overwrites;
1873     allow_overwrites = 1;
1874
1875     save_kt = keytable;
1876     keytable = tapetype_keytable;
1877
1878     init_tapetype_defaults();
1879
1880     get_conftoken(IDENT);
1881     tpcur.name = stralloc(tokenval.s);
1882     malloc_mark(tpcur.name);
1883     tpcur.seen = line_num;
1884
1885     get_conftoken(LBRACE);
1886     get_conftoken(NL);
1887
1888     done = 0;
1889     do {
1890         line_num += 1;
1891         get_conftoken(ANY);
1892         switch(tok) {
1893
1894         case RBRACE:
1895             done = 1;
1896             break;
1897         case COMMENT:
1898             get_simple((val_t *)&tpcur.comment, &tpcur.s_comment, STRING);
1899             break;
1900         case LBL_TEMPL:
1901             get_simple((val_t *)&tpcur.lbl_templ, &tpcur.s_lbl_templ, STRING);
1902             break;
1903         case BLOCKSIZE:
1904             get_simple((val_t *)&tpcur.blocksize, &tpcur.s_blocksize, LONG);
1905             if(tpcur.blocksize < DISK_BLOCK_KB) {
1906                 parserror("Tape blocksize must be at least %d KBytes",
1907                           DISK_BLOCK_KB);
1908             } else if(tpcur.blocksize > MAX_TAPE_BLOCK_KB) {
1909                 parserror("Tape blocksize must not be larger than %d KBytes",
1910                           MAX_TAPE_BLOCK_KB);
1911             }
1912             break;
1913         case FILE_PAD:
1914             get_simple(&value, &tpcur.s_file_pad, BOOL);
1915             tpcur.file_pad = (value.i != 0);
1916             break;
1917         case LENGTH:
1918             get_simple(&value, &tpcur.s_length, LONG);
1919             if(value.l < 0) {
1920                 parserror("Tape length must be positive");
1921             }
1922             else {
1923                 tpcur.length = (unsigned long) value.l;
1924             }
1925             break;
1926         case FILEMARK:
1927             get_simple(&value, &tpcur.s_filemark, LONG);
1928             if(value.l < 0) {
1929                 parserror("Tape file mark size must be positive");
1930             }
1931             else {
1932                 tpcur.filemark = (unsigned long) value.l;
1933             }
1934             break;
1935         case SPEED:
1936             get_simple((val_t *)&tpcur.speed, &tpcur.s_speed, INT);
1937             if(tpcur.speed < 0) {
1938                 parserror("Speed must be positive");
1939             }
1940             break;
1941         case IDENT:
1942             copy_tapetype();
1943             break;
1944         case NL:        /* empty line */
1945             break;
1946         case END:       /* end of file */
1947             done = 1;
1948         default:
1949             parserror("tape type parameter expected");
1950         }
1951         if(tok != NL && tok != END) get_conftoken(NL);
1952     } while(!done);
1953
1954     save_tapetype();
1955
1956     allow_overwrites = save_overwrites;
1957     keytable = save_kt;
1958 }
1959
1960 static void init_tapetype_defaults()
1961 {
1962     tpcur.comment = stralloc("");
1963     tpcur.lbl_templ = stralloc("");
1964     tpcur.blocksize = (DISK_BLOCK_KB);
1965     tpcur.file_pad = 1;
1966     tpcur.length = 2000 * 1024;
1967     tpcur.filemark = 1000;
1968     tpcur.speed = 200;
1969
1970     tpcur.s_comment = 0;
1971     tpcur.s_lbl_templ = 0;
1972     tpcur.s_blocksize = 0;
1973     tpcur.s_file_pad = 0;
1974     tpcur.s_length = 0;
1975     tpcur.s_filemark = 0;
1976     tpcur.s_speed = 0;
1977 }
1978
1979 static void save_tapetype()
1980 {
1981     tapetype_t *tp;
1982
1983     tp = lookup_tapetype(tpcur.name);
1984
1985     if(tp != (tapetype_t *)0) {
1986         amfree(tpcur.name);
1987         parserror("tapetype %s already defined on line %d", tp->name, tp->seen);
1988         return;
1989     }
1990
1991     tp = alloc(sizeof(tapetype_t));
1992     malloc_mark(tp);
1993     *tp = tpcur;
1994     tp->next = tapelist;
1995     tapelist = tp;
1996 }
1997
1998 static void copy_tapetype()
1999 {
2000     tapetype_t *tp;
2001
2002     tp = lookup_tapetype(tokenval.s);
2003
2004     if(tp == NULL) {
2005         parserror("tape type parameter expected");
2006         return;
2007     }
2008
2009 #define ttcopy(v,s) if(tp->s) { tpcur.v = tp->v; tpcur.s = tp->s; }
2010
2011     if(tp->s_comment) {
2012         tpcur.comment = newstralloc(tpcur.comment, tp->comment);
2013         tpcur.s_comment = tp->s_comment;
2014     }
2015     if(tp->s_lbl_templ) {
2016         tpcur.lbl_templ = newstralloc(tpcur.lbl_templ, tp->lbl_templ);
2017         tpcur.s_lbl_templ = tp->s_lbl_templ;
2018     }
2019     ttcopy(blocksize, s_blocksize);
2020     ttcopy(file_pad, s_file_pad);
2021     ttcopy(length, s_length);
2022     ttcopy(filemark, s_filemark);
2023     ttcopy(speed, s_speed);
2024 }
2025
2026 keytab_t interface_keytable[] = {
2027     { "COMMENT", COMMENT },
2028     { "USE", USE },
2029     { NULL, IDENT }
2030 };
2031
2032 static void get_interface()
2033 {
2034     int done;
2035     int save_overwrites;
2036     keytab_t *save_kt;
2037
2038     save_overwrites = allow_overwrites;
2039     allow_overwrites = 1;
2040
2041     save_kt = keytable;
2042     keytable = interface_keytable;
2043
2044     init_interface_defaults();
2045
2046     get_conftoken(IDENT);
2047     ifcur.name = stralloc(tokenval.s);
2048     malloc_mark(ifcur.name);
2049     ifcur.seen = line_num;
2050
2051     get_conftoken(LBRACE);
2052     get_conftoken(NL);
2053
2054     done = 0;
2055     do {
2056         line_num += 1;
2057         get_conftoken(ANY);
2058         switch(tok) {
2059
2060         case RBRACE:
2061             done = 1;
2062             break;
2063         case COMMENT:
2064             get_simple((val_t *)&ifcur.comment, &ifcur.s_comment, STRING);
2065             break;
2066         case USE:
2067             get_simple((val_t *)&ifcur.maxusage, &ifcur.s_maxusage, INT);
2068             if(ifcur.maxusage <1) {
2069                 parserror("use must bbe positive");
2070             }
2071             break;
2072         case IDENT:
2073             copy_interface();
2074             break;
2075         case NL:        /* empty line */
2076             break;
2077         case END:       /* end of file */
2078             done = 1;
2079         default:
2080             parserror("interface parameter expected");
2081         }
2082         if(tok != NL && tok != END) get_conftoken(NL);
2083     } while(!done);
2084
2085     save_interface();
2086
2087     allow_overwrites = save_overwrites;
2088     keytable = save_kt;
2089
2090     return;
2091 }
2092
2093 static void init_interface_defaults()
2094 {
2095     ifcur.comment = stralloc("");
2096     ifcur.maxusage = 300;
2097
2098     ifcur.s_comment = 0;
2099     ifcur.s_maxusage = 0;
2100
2101     ifcur.curusage = 0;
2102 }
2103
2104 static void save_interface()
2105 {
2106     interface_t *ip;
2107
2108     ip = lookup_interface(ifcur.name);
2109
2110     if(ip != (interface_t *)0) {
2111         parserror("interface %s already defined on line %d", ip->name, ip->seen);
2112         return;
2113     }
2114
2115     ip = alloc(sizeof(interface_t));
2116     malloc_mark(ip);
2117     *ip = ifcur;
2118     ip->next = interface_list;
2119     interface_list = ip;
2120 }
2121
2122 static void copy_interface()
2123 {
2124     interface_t *ip;
2125
2126     ip = lookup_interface(tokenval.s);
2127
2128     if(ip == NULL) {
2129         parserror("interface parameter expected");
2130         return;
2131     }
2132
2133 #define ifcopy(v,s) if(ip->s) { ifcur.v = ip->v; ifcur.s = ip->s; }
2134
2135     if(ip->s_comment) {
2136         ifcur.comment = newstralloc(ifcur.comment, ip->comment);
2137         ifcur.s_comment = ip->s_comment;
2138     }
2139     ifcopy(maxusage, s_maxusage);
2140 }
2141
2142 keytab_t dumpopts_keytable[] = {
2143     { "COMPRESS", COMPRESS },
2144     { "ENCRYPT", ENCRYPT },
2145     { "INDEX", INDEX },
2146     { "EXCLUDE-FILE", EXCLUDE_FILE },
2147     { "EXCLUDE-LIST", EXCLUDE_LIST },
2148     { "KENCRYPT", KENCRYPT },
2149     { "SKIP-FULL", SKIP_FULL },
2150     { "SKIP-INCR", SKIP_INCR },
2151     { NULL, IDENT }
2152 };
2153
2154 static void get_dumpopts() /* XXX - for historical compatability */
2155 {
2156     int done;
2157     keytab_t *save_kt;
2158
2159     save_kt = keytable;
2160     keytable = dumpopts_keytable;
2161
2162     done = 0;
2163     do {
2164         get_conftoken(ANY);
2165         switch(tok) {
2166         case COMPRESS:   ckseen(&dpcur.s_compress);  dpcur.compress = COMP_FAST; break;
2167         case ENCRYPT:   ckseen(&dpcur.s_encrypt);  dpcur.encrypt = ENCRYPT_NONE; break;
2168         case EXCLUDE_FILE:
2169             ckseen(&dpcur.s_exclude_file);
2170             get_conftoken(STRING);
2171             dpcur.exclude_file = append_sl(dpcur.exclude_file, tokenval.s);
2172             break;
2173         case EXCLUDE_LIST:
2174             ckseen(&dpcur.s_exclude_list);
2175             get_conftoken(STRING);
2176             dpcur.exclude_list = append_sl(dpcur.exclude_list, tokenval.s);
2177             break;
2178         case KENCRYPT:   ckseen(&dpcur.s_kencrypt);  dpcur.kencrypt = 1; break;
2179         case SKIP_INCR:  ckseen(&dpcur.s_skip_incr); dpcur.skip_incr= 1; break;
2180         case SKIP_FULL:  ckseen(&dpcur.s_skip_full); dpcur.skip_full= 1; break;
2181         case INDEX:      ckseen(&dpcur.s_index);     dpcur.index    = 1; break;
2182         case IDENT:
2183             copy_dumptype();
2184             break;
2185         case NL: done = 1; break;
2186         case COMMA: break;
2187         case END:
2188             done = 1;
2189         default:
2190             parserror("dump option expected");
2191         }
2192     } while(!done);
2193
2194     keytable = save_kt;
2195 }
2196
2197 static void get_comprate()
2198 {
2199     val_t var;
2200
2201     get_simple(&var, &dpcur.s_comprate, REAL);
2202     dpcur.comprate[0] = dpcur.comprate[1] = var.r;
2203     if(dpcur.comprate[0] < 0) {
2204         parserror("full compression rate must be >= 0");
2205     }
2206
2207     get_conftoken(ANY);
2208     switch(tok) {
2209     case NL:
2210         return;
2211     case COMMA:
2212         break;
2213     default:
2214         unget_conftoken();
2215     }
2216
2217     get_conftoken(REAL);
2218     dpcur.comprate[1] = tokenval.r;
2219     if(dpcur.comprate[1] < 0) {
2220         parserror("incremental compression rate must be >= 0");
2221     }
2222 }
2223
2224 keytab_t compress_keytable[] = {
2225     { "BEST", BEST },
2226     { "CLIENT", CLIENT },
2227     { "FAST", FAST },
2228     { "NONE", NONE },
2229     { "SERVER", SERVER },
2230     { "CUSTOM", CUSTOM },
2231     { NULL, IDENT }
2232 };
2233
2234 static void get_compress()
2235 {
2236     keytab_t *save_kt;
2237     int serv, clie, none, fast, best, custom;
2238     int done;
2239     int comp;
2240
2241     save_kt = keytable;
2242     keytable = compress_keytable;
2243
2244     ckseen(&dpcur.s_compress);
2245
2246     serv = clie = none = fast = best = custom  = 0;
2247
2248     done = 0;
2249     do {
2250         get_conftoken(ANY);
2251         switch(tok) {
2252         case NONE:   none = 1; break;
2253         case FAST:   fast = 1; break;
2254         case BEST:   best = 1; break;
2255         case CLIENT: clie = 1; break;
2256         case SERVER: serv = 1; break;
2257         case CUSTOM: custom=1; break;
2258         case NL:     done = 1; break;
2259         default:
2260             done = 1;
2261             serv = clie = 1; /* force an error */
2262         }
2263     } while(!done);
2264
2265     if(serv + clie == 0) clie = 1;      /* default to client */
2266     if(none + fast + best + custom  == 0) fast = 1; /* default to fast */
2267
2268     comp = -1;
2269
2270     if(!serv && clie) {
2271         if(none && !fast && !best && !custom) comp = COMP_NONE;
2272         if(!none && fast && !best && !custom) comp = COMP_FAST;
2273         if(!none && !fast && best && !custom) comp = COMP_BEST;
2274         if(!none && !fast && !best && custom) comp = COMP_CUST;
2275     }
2276
2277     if(serv && !clie) {
2278         if(none && !fast && !best && !custom) comp = COMP_NONE;
2279         if(!none && fast && !best && !custom) comp = COMP_SERV_FAST;
2280         if(!none && !fast && best && !custom) comp = COMP_SERV_BEST;
2281         if(!none && !fast && !best && custom) comp = COMP_SERV_CUST;
2282     }
2283
2284     if(comp == -1) {
2285         parserror("NONE, CLIENT FAST, CLIENT BEST, CLIENT CUSTOM, SERVER FAST, SERVER BEST or SERVER CUSTOM expected");
2286         comp = COMP_NONE;
2287     }
2288
2289     dpcur.compress = comp;
2290
2291     keytable = save_kt;
2292 }
2293
2294 keytab_t encrypt_keytable[] = {
2295     { "NONE", NONE },
2296     { "CLIENT", CLIENT },
2297     { "SERVER", SERVER },
2298     { NULL, IDENT }
2299 };
2300
2301 static void get_encrypt()
2302 {
2303    keytab_t *save_kt;
2304    int encrypt;
2305
2306    save_kt = keytable;
2307    keytable = encrypt_keytable;
2308
2309    ckseen(&dpcur.s_encrypt);
2310
2311    get_conftoken(ANY);
2312    switch(tok) {
2313    case NONE:  
2314      encrypt = ENCRYPT_NONE; 
2315      break;
2316    case CLIENT:  
2317      encrypt = ENCRYPT_CUST;
2318      break;
2319    case SERVER: 
2320      encrypt = ENCRYPT_SERV_CUST;
2321      break;
2322    default:
2323      parserror("NONE, CLIENT or SERVER expected");
2324      encrypt = ENCRYPT_NONE;
2325    }
2326
2327    dpcur.encrypt = encrypt;
2328    keytable = save_kt;  
2329 }
2330
2331 keytab_t taperalgo_keytable[] = {
2332     { "FIRST", FIRST },
2333     { "FIRSTFIT", FIRSTFIT },
2334     { "LARGEST", LARGEST },
2335     { "LARGESTFIT", LARGESTFIT },
2336     { "SMALLEST", SMALLEST },
2337     { "LAST", LAST },
2338     { NULL, IDENT }
2339 };
2340
2341 static void get_taperalgo(c_taperalgo, s_taperalgo)
2342 val_t *c_taperalgo;
2343 int *s_taperalgo;
2344 {
2345     keytab_t *save_kt;
2346
2347     save_kt = keytable;
2348     keytable = taperalgo_keytable;
2349
2350     ckseen(s_taperalgo);
2351
2352     get_conftoken(ANY);
2353     switch(tok) {
2354     case FIRST:      c_taperalgo->i = ALGO_FIRST;      break;
2355     case FIRSTFIT:   c_taperalgo->i = ALGO_FIRSTFIT;   break;
2356     case LARGEST:    c_taperalgo->i = ALGO_LARGEST;    break;
2357     case LARGESTFIT: c_taperalgo->i = ALGO_LARGESTFIT; break;
2358     case SMALLEST:   c_taperalgo->i = ALGO_SMALLEST;   break;
2359     case LAST:       c_taperalgo->i = ALGO_LAST;       break;
2360     default:
2361         parserror("FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST or LAST expected");
2362     }
2363
2364     keytable = save_kt;
2365 }
2366
2367 keytab_t priority_keytable[] = {
2368     { "HIGH", HIGH },
2369     { "LOW", LOW },
2370     { "MEDIUM", MEDIUM },
2371     { NULL, IDENT }
2372 };
2373
2374 static void get_priority()
2375 {
2376     int pri;
2377     keytab_t *save_kt;
2378
2379     save_kt = keytable;
2380     keytable = priority_keytable;
2381
2382     ckseen(&dpcur.s_priority);
2383
2384     get_conftoken(ANY);
2385     switch(tok) {
2386     case LOW: pri = 0; break;
2387     case MEDIUM: pri = 1; break;
2388     case HIGH: pri = 2; break;
2389     case INT: pri = tokenval.i; break;
2390     default:
2391         parserror("LOW, MEDIUM, HIGH or integer expected");
2392         pri = 0;
2393     }
2394     dpcur.priority = pri;
2395
2396     keytable = save_kt;
2397 }
2398
2399 keytab_t strategy_keytable[] = {
2400     { "HANOI", HANOI },
2401     { "NOFULL", NOFULL },
2402     { "NOINC", NOINC },
2403     { "SKIP", SKIP },
2404     { "STANDARD", STANDARD },
2405     { "INCRONLY", INCRONLY },
2406     { NULL, IDENT }
2407 };
2408
2409 static void get_strategy()
2410 {
2411     int strat;
2412     keytab_t *save_kt;
2413
2414     save_kt = keytable;
2415     keytable = strategy_keytable;
2416
2417     ckseen(&dpcur.s_strategy);
2418
2419     get_conftoken(ANY);
2420     switch(tok) {
2421     case SKIP:
2422         strat = DS_SKIP;
2423         break;
2424     case STANDARD:
2425         strat = DS_STANDARD;
2426         break;
2427     case NOFULL:
2428         strat = DS_NOFULL;
2429         break;
2430     case NOINC:
2431         strat = DS_NOINC;
2432         break;
2433     case HANOI:
2434         strat = DS_HANOI;
2435         break;
2436     case INCRONLY:
2437         strat = DS_INCRONLY;
2438         break;
2439     default:
2440         parserror("STANDARD or NOFULL expected");
2441         strat = DS_STANDARD;
2442     }
2443     dpcur.strategy = strat;
2444
2445     keytable = save_kt;
2446 }
2447
2448 keytab_t estimate_keytable[] = {
2449     { "CLIENT", CLIENT },
2450     { "SERVER", SERVER },
2451     { "CALCSIZE", CALCSIZE }
2452 };
2453
2454 static void get_estimate()
2455 {
2456     int estime;
2457     keytab_t *save_kt;
2458
2459     save_kt = keytable;
2460     keytable = estimate_keytable;
2461
2462     ckseen(&dpcur.s_estimate);
2463
2464     get_conftoken(ANY);
2465     switch(tok) {
2466     case CLIENT:
2467         estime = ES_CLIENT;
2468         break;
2469     case SERVER:
2470         estime = ES_SERVER;
2471         break;
2472     case CALCSIZE:
2473         estime = ES_CALCSIZE;
2474         break;
2475     default:
2476         parserror("CLIENT, SERVER or CALCSIZE expected");
2477         estime = ES_CLIENT;
2478     }
2479     dpcur.estimate = estime;
2480
2481     keytable = save_kt;
2482 }
2483
2484 keytab_t exclude_keytable[] = {
2485     { "LIST", LIST },
2486     { "FILE", EFILE },
2487     { "APPEND", APPEND },
2488     { "OPTIONAL", OPTIONAL },
2489     { NULL, IDENT }
2490 };
2491
2492 static void get_exclude()
2493 {
2494     int list, got_one = 0;
2495     keytab_t *save_kt;
2496     sl_t *exclude;
2497     int optional = 0;
2498     int append = 0;
2499
2500     save_kt = keytable;
2501     keytable = exclude_keytable;
2502
2503     get_conftoken(ANY);
2504     if(tok == LIST) {
2505         list = 1;
2506         exclude = dpcur.exclude_list;
2507         ckseen(&dpcur.s_exclude_list);
2508         get_conftoken(ANY);
2509     }
2510     else {
2511         list = 0;
2512         exclude = dpcur.exclude_file;
2513         ckseen(&dpcur.s_exclude_file);
2514         if(tok == EFILE) get_conftoken(ANY);
2515     }
2516
2517     if(tok == OPTIONAL) {
2518         get_conftoken(ANY);
2519         optional = 1;
2520     }
2521
2522     if(tok == APPEND) {
2523         get_conftoken(ANY);
2524         append = 1;
2525     }
2526     else {
2527         free_sl(exclude);
2528         exclude = NULL;
2529         append = 0;
2530     }
2531
2532     while(tok == STRING) {
2533         exclude = append_sl(exclude, tokenval.s);
2534         got_one = 1;
2535         get_conftoken(ANY);
2536     }
2537     unget_conftoken();
2538
2539     if(got_one == 0) { free_sl(exclude); exclude = NULL; }
2540
2541     if(list == 0)
2542         dpcur.exclude_file = exclude;
2543     else {
2544         dpcur.exclude_list = exclude;
2545         if(!append || optional)
2546             dpcur.exclude_optional = optional;
2547     }
2548
2549     keytable = save_kt;
2550 }
2551
2552
2553 static void get_include()
2554 {
2555     int list, got_one = 0;
2556     keytab_t *save_kt;
2557     sl_t *include;
2558     int optional = 0;
2559     int append = 0;
2560
2561     save_kt = keytable;
2562     keytable = exclude_keytable;
2563
2564     get_conftoken(ANY);
2565     if(tok == LIST) {
2566         list = 1;
2567         include = dpcur.include_list;
2568         ckseen(&dpcur.s_include_list);
2569         get_conftoken(ANY);
2570     }
2571     else {
2572         list = 0;
2573         include = dpcur.include_file;
2574         ckseen(&dpcur.s_include_file);
2575         if(tok == EFILE) get_conftoken(ANY);
2576     }
2577
2578     if(tok == OPTIONAL) {
2579         get_conftoken(ANY);
2580         optional = 1;
2581     }
2582
2583     if(tok == APPEND) {
2584         get_conftoken(ANY);
2585         append = 1;
2586     }
2587     else {
2588         free_sl(include);
2589         include = NULL;
2590         append = 0;
2591     }
2592
2593     while(tok == STRING) {
2594         include = append_sl(include, tokenval.s);
2595         got_one = 1;
2596         get_conftoken(ANY);
2597     }
2598     unget_conftoken();
2599
2600     if(got_one == 0) { free_sl(include); include = NULL; }
2601
2602     if(list == 0)
2603         dpcur.include_file = include;
2604     else {
2605         dpcur.include_list = include;
2606         if(!append || optional)
2607             dpcur.include_optional = optional;
2608     }
2609
2610     keytable = save_kt;
2611 }
2612
2613
2614 /* ------------------------ */
2615
2616
2617 static void get_simple(var, seen, type)
2618 val_t *var;
2619 int *seen;
2620 tok_t type;
2621 {
2622     ckseen(seen);
2623
2624     switch(type) {
2625     case STRING:
2626     case IDENT:
2627         get_conftoken(type);
2628         var->s = newstralloc(var->s, tokenval.s);
2629         malloc_mark(var->s);
2630         break;
2631     case INT:
2632         var->i = get_int();
2633         break;
2634     case LONG:
2635         var->l = get_long();
2636         break;
2637     case AM64:
2638         var->am64 = get_am64_t();
2639         break;
2640     case BOOL:
2641         var->i = get_bool();
2642         break;
2643     case REAL:
2644         get_conftoken(REAL);
2645         var->r = tokenval.r;
2646         break;
2647     case TIME:
2648         var->i = get_time();
2649         break;
2650     default:
2651         error("error [unknown get_simple type: %d]", type);
2652         /* NOTREACHED */
2653     }
2654     return;
2655 }
2656
2657 static int get_time()
2658 {
2659     time_t st = start_time.r.tv_sec;
2660     struct tm *stm;
2661     int hhmm;
2662
2663     get_conftoken(INT);
2664     hhmm = tokenval.i;
2665
2666     stm = localtime(&st);
2667     st -= stm->tm_sec + 60 * (stm->tm_min + 60 * stm->tm_hour);
2668     st += ((hhmm/100*60) + hhmm%100)*60;
2669
2670     if (st-start_time.r.tv_sec<-43200)
2671         st += 86400;
2672
2673     return st;
2674 }
2675
2676 keytab_t numb_keytable[] = {
2677     { "B", MULT1 },
2678     { "BPS", MULT1 },
2679     { "BYTE", MULT1 },
2680     { "BYTES", MULT1 },
2681     { "DAY", MULT1 },
2682     { "DAYS", MULT1 },
2683     { "INF", INFINITY },
2684     { "K", MULT1K },
2685     { "KB", MULT1K },
2686     { "KBPS", MULT1K },
2687     { "KBYTE", MULT1K },
2688     { "KBYTES", MULT1K },
2689     { "KILOBYTE", MULT1K },
2690     { "KILOBYTES", MULT1K },
2691     { "KPS", MULT1K },
2692     { "M", MULT1M },
2693     { "MB", MULT1M },
2694     { "MBPS", MULT1M },
2695     { "MBYTE", MULT1M },
2696     { "MBYTES", MULT1M },
2697     { "MEG", MULT1M },
2698     { "MEGABYTE", MULT1M },
2699     { "MEGABYTES", MULT1M },
2700     { "G", MULT1G },
2701     { "GB", MULT1G },
2702     { "GBPS", MULT1G },
2703     { "GBYTE", MULT1G },
2704     { "GBYTES", MULT1G },
2705     { "GIG", MULT1G },
2706     { "GIGABYTE", MULT1G },
2707     { "GIGABYTES", MULT1G },
2708     { "MPS", MULT1M },
2709     { "TAPE", MULT1 },
2710     { "TAPES", MULT1 },
2711     { "WEEK", MULT7 },
2712     { "WEEKS", MULT7 },
2713     { NULL, IDENT }
2714 };
2715
2716 static int get_int()
2717 {
2718     int val;
2719     keytab_t *save_kt;
2720
2721     save_kt = keytable;
2722     keytable = numb_keytable;
2723
2724     get_conftoken(ANY);
2725
2726     switch(tok) {
2727     case AM64:
2728         if(abs(tokenval.am64) > INT_MAX)
2729             parserror("value too large");
2730         val = (int) tokenval.am64;
2731         break;
2732     case INFINITY:
2733         val = (int) BIGINT;
2734         break;
2735     default:
2736         parserror("an integer expected");
2737         val = 0;
2738     }
2739
2740     /* get multiplier, if any */
2741     get_conftoken(ANY);
2742
2743     switch(tok) {
2744     case NL:                    /* multiply by one */
2745     case MULT1:
2746     case MULT1K:
2747         break;
2748     case MULT7:
2749         if(abs(val) > INT_MAX/7)
2750             parserror("value too large");
2751         val *= 7;
2752         break;
2753     case MULT1M:
2754         if(abs(val) > INT_MAX/1024)
2755             parserror("value too large");
2756         val *= 1024;
2757         break;
2758     case MULT1G:
2759         if(abs(val) > INT_MAX/(1024*1024))
2760             parserror("value too large");
2761         val *= 1024*1024;
2762         break;
2763     default:    /* it was not a multiplier */
2764         unget_conftoken();
2765     }
2766
2767     keytable = save_kt;
2768
2769     return val;
2770 }
2771
2772 static long get_long()
2773 {
2774     long val;
2775     keytab_t *save_kt;
2776
2777     save_kt = keytable;
2778     keytable = numb_keytable;
2779
2780     get_conftoken(ANY);
2781
2782     switch(tok) {
2783     case AM64:
2784         if(tokenval.am64 > LONG_MAX || tokenval.am64 < LONG_MIN)
2785             parserror("value too large");
2786         val = (long) tokenval.am64;
2787         break;
2788     case INFINITY:
2789         val = (long) LONG_MAX;
2790         break;
2791     default:
2792         parserror("a long expected");
2793         val = 0;
2794     }
2795
2796     /* get multiplier, if any */
2797     get_conftoken(ANY);
2798
2799     switch(tok) {
2800     case NL:                    /* multiply by one */
2801     case MULT1:
2802     case MULT1K:
2803         break;
2804     case MULT7:
2805         if(val > LONG_MAX/7 || val < LONG_MIN/7)
2806             parserror("value too large");
2807         val *= 7;
2808         break;
2809     case MULT1M:
2810         if(val > LONG_MAX/1024 || val < LONG_MIN/7)
2811             parserror("value too large");
2812         val *= 1024;
2813         break;
2814     case MULT1G:
2815         if(val > LONG_MAX/(1024*1024) || val < LONG_MIN/(1024*1024))
2816             parserror("value too large");
2817         val *= 1024*1024;
2818         break;
2819     default:    /* it was not a multiplier */
2820         unget_conftoken();
2821     }
2822
2823     keytable = save_kt;
2824
2825     return val;
2826 }
2827
2828 static am64_t get_am64_t()
2829 {
2830     am64_t val;
2831     keytab_t *save_kt;
2832
2833     save_kt = keytable;
2834     keytable = numb_keytable;
2835
2836     get_conftoken(ANY);
2837
2838     switch(tok) {
2839     case AM64:
2840         val = tokenval.am64;
2841         break;
2842     case INFINITY:
2843         val = AM64_MAX;
2844         break;
2845     default:
2846         parserror("a am64 expected %d", tok);
2847         val = 0;
2848     }
2849
2850     /* get multiplier, if any */
2851     get_conftoken(ANY);
2852
2853     switch(tok) {
2854     case NL:                    /* multiply by one */
2855     case MULT1:
2856     case MULT1K:
2857         break;
2858     case MULT7:
2859         if(val > AM64_MAX/7 || val < AM64_MIN/7)
2860             parserror("value too large");
2861         val *= 7;
2862         break;
2863     case MULT1M:
2864         if(val > AM64_MAX/1024 || val < AM64_MIN/1024)
2865             parserror("value too large");
2866         val *= 1024;
2867         break;
2868     case MULT1G:
2869         if(val > AM64_MAX/(1024*1024) || val < AM64_MIN/(1024*1024))
2870             parserror("value too large");
2871         val *= 1024*1024;
2872         break;
2873     default:    /* it was not a multiplier */
2874         unget_conftoken();
2875     }
2876
2877     keytable = save_kt;
2878
2879     return val;
2880 }
2881
2882 keytab_t bool_keytable[] = {
2883     { "Y", ATRUE },
2884     { "YES", ATRUE },
2885     { "T", ATRUE },
2886     { "TRUE", ATRUE },
2887     { "ON", ATRUE },
2888     { "N", AFALSE },
2889     { "NO", AFALSE },
2890     { "F", AFALSE },
2891     { "FALSE", AFALSE },
2892     { "OFF", AFALSE },
2893     { NULL, IDENT }
2894 };
2895
2896 static int get_bool()
2897 {
2898     int val;
2899     keytab_t *save_kt;
2900
2901     save_kt = keytable;
2902     keytable = bool_keytable;
2903
2904     get_conftoken(ANY);
2905
2906     switch(tok) {
2907     case INT:
2908         val = tokenval.i ? 1 : 0;
2909         break;
2910     case ATRUE:
2911         val = 1;
2912         break;
2913     case AFALSE:
2914         val = 0;
2915         break;
2916     case NL:
2917     default:
2918         unget_conftoken();
2919         val = 2; /* no argument - most likely TRUE */
2920     }
2921
2922     keytable = save_kt;
2923
2924     return val;
2925 }
2926
2927 static void ckseen(seen)
2928 int *seen;
2929 {
2930     if(*seen && !allow_overwrites) {
2931         parserror("duplicate parameter, prev def on line %d", *seen);
2932     }
2933     *seen = line_num;
2934 }
2935
2936 printf_arglist_function(static void parserror, char *, format)
2937 {
2938     va_list argp;
2939
2940     /* print error message */
2941
2942     fprintf(stderr, "\"%s\", line %d: ", confname, line_num);
2943     arglist_start(argp, format);
2944     vfprintf(stderr, format, argp);
2945     arglist_end(argp);
2946     fputc('\n', stderr);
2947
2948     got_parserror = 1;
2949 }
2950
2951 static tok_t lookup_keyword(str)
2952 char *str;
2953 {
2954     keytab_t *kwp;
2955
2956     /* switch to binary search if performance warrants */
2957
2958     for(kwp = keytable; kwp->keyword != NULL; kwp++) {
2959         if(strcmp(kwp->keyword, str) == 0) break;
2960     }
2961     return kwp->token;
2962 }
2963
2964 static char tkbuf[4096];
2965
2966 /* push the last token back (can only unget ANY tokens) */
2967 static void unget_conftoken()
2968 {
2969     token_pushed = 1;
2970     pushed_tok = tok;
2971     tok = UNKNOWN;
2972     return;
2973 }
2974
2975 static void get_conftoken(exp)
2976 tok_t exp;
2977 {
2978     int ch, d;
2979     am64_t am64;
2980     char *buf;
2981     int token_overflow;
2982
2983     if(token_pushed) {
2984         token_pushed = 0;
2985         tok = pushed_tok;
2986
2987         /* If it looked like a key word before then look it
2988         ** up again in the current keyword table. */
2989         switch(tok) {
2990         case LONG:    case AM64:
2991         case INT:     case REAL:    case STRING:
2992         case LBRACE:  case RBRACE:  case COMMA:
2993         case NL:      case END:     case UNKNOWN:
2994             break;
2995         default:
2996             if(exp == IDENT) tok = IDENT;
2997             else tok = lookup_keyword(tokenval.s);
2998         }
2999     }
3000     else {
3001         ch = getc(conf);
3002
3003         while(ch != EOF && ch != '\n' && isspace(ch)) ch = getc(conf);
3004         if(ch == '#') {         /* comment - eat everything but eol/eof */
3005             while((ch = getc(conf)) != EOF && ch != '\n') {}
3006         }
3007
3008         if(isalpha(ch)) {               /* identifier */
3009             buf = tkbuf;
3010             token_overflow = 0;
3011             do {
3012                 if(islower(ch)) ch = toupper(ch);
3013                 if(buf < tkbuf+sizeof(tkbuf)-1) {
3014                     *buf++ = ch;
3015                 } else {
3016                     *buf = '\0';
3017                     if(!token_overflow) {
3018                         parserror("token too long: %.20s...", tkbuf);
3019                     }
3020                     token_overflow = 1;
3021                 }
3022                 ch = getc(conf);
3023             } while(isalnum(ch) || ch == '_' || ch == '-');
3024
3025             ungetc(ch, conf);
3026             *buf = '\0';
3027
3028             tokenval.s = tkbuf;
3029
3030             if(token_overflow) tok = UNKNOWN;
3031             else if(exp == IDENT) tok = IDENT;
3032             else tok = lookup_keyword(tokenval.s);
3033         }
3034         else if(isdigit(ch)) {  /* integer */
3035             int sign;
3036             if (1) {
3037                 sign = 1;
3038             } else {
3039             negative_number: /* look for goto negative_number below */
3040                 sign = -1;
3041             }
3042             tokenval.am64 = 0;
3043             do {
3044                 tokenval.am64 = tokenval.am64 * 10 + (ch - '0');
3045                 ch = getc(conf);
3046             } while(isdigit(ch));
3047             if(ch != '.') {
3048                 if(exp == INT) {
3049                     tok = INT;
3050                     tokenval.i *= sign;
3051                 }
3052                 else if(exp == LONG) {
3053                     tok = LONG;
3054                     tokenval.l *= sign;
3055                 }
3056                 else if(exp != REAL) {
3057                     tok = AM64;
3058                     tokenval.am64 *= sign;
3059                 } else {
3060                     /* automatically convert to real when expected */
3061                     am64 = tokenval.am64;
3062                     tokenval.r = sign * (double) am64;
3063                     tok = REAL;
3064                 }
3065             }
3066             else {
3067                 /* got a real number, not an int */
3068                 am64 = tokenval.am64;
3069                 tokenval.r = sign * (double) am64;
3070                 am64=0; d=1;
3071                 ch = getc(conf);
3072                 while(isdigit(ch)) {
3073                     am64 = am64 * 10 + (ch - '0');
3074                     d = d * 10;
3075                     ch = getc(conf);
3076                 }
3077                 tokenval.r += sign * ((double)am64)/d;
3078                 tok = REAL;
3079             }
3080             ungetc(ch,conf);
3081         }
3082         else switch(ch) {
3083
3084         case '"':                       /* string */
3085             buf = tkbuf;
3086             token_overflow = 0;
3087             ch = getc(conf);
3088             while(ch != '"' && ch != '\n' && ch != EOF) {
3089                 if(buf < tkbuf+sizeof(tkbuf)-1) {
3090                     *buf++ = ch;
3091                 } else {
3092                     *buf = '\0';
3093                     if(!token_overflow) {
3094                         parserror("string too long: %.20s...", tkbuf);
3095                     }
3096                     token_overflow = 1;
3097                 }
3098                 ch = getc(conf);
3099             }
3100             if(ch != '"') {
3101                 parserror("missing end quote");
3102                 ungetc(ch, conf);
3103             }
3104             *buf = '\0';
3105             tokenval.s = tkbuf;
3106             if(token_overflow) tok = UNKNOWN;
3107             else tok = STRING;
3108             break;
3109
3110         case '-':
3111             ch = getc(conf);
3112             if (isdigit(ch))
3113                 goto negative_number;
3114             else {
3115                 ungetc(ch, conf);
3116                 tok = UNKNOWN;
3117             }
3118             break;
3119         case ',':  tok = COMMA; break;
3120         case '{':  tok = LBRACE; break;
3121         case '}':  tok = RBRACE; break;
3122         case '\n': tok = NL; break;
3123         case EOF:  tok = END; break;
3124         default:   tok = UNKNOWN;
3125         }
3126     }
3127
3128     if(exp != ANY && tok != exp) {
3129         char *str;
3130         keytab_t *kwp;
3131
3132         switch(exp) {
3133         case LBRACE: str = "\"{\""; break;
3134         case RBRACE: str = "\"}\""; break;
3135         case COMMA:  str = "\",\""; break;
3136
3137         case NL: str = "end of line"; break;
3138         case END: str = "end of file"; break;
3139         case INT: str = "an integer"; break;
3140         case REAL: str = "a real number"; break;
3141         case STRING: str = "a quoted string"; break;
3142         case IDENT: str = "an identifier"; break;
3143         default:
3144             for(kwp = keytable; kwp->keyword != NULL; kwp++)
3145                 if(exp == kwp->token) break;
3146             if(kwp->keyword == NULL) str = "token not";
3147             else str = kwp->keyword;
3148         }
3149         parserror("%s expected", str);
3150         tok = exp;
3151         if(tok == INT) tokenval.i = 0;
3152         else tokenval.s = "";
3153     }
3154
3155     return;
3156 }
3157
3158 int ColumnDataCount()
3159 {
3160     return sizeof(ColumnData) / sizeof(ColumnData[0]);
3161 }
3162
3163 /* conversion from string to table index
3164  */
3165 int
3166 StringToColumn(s)
3167     char *s;
3168 {
3169     int cn;
3170
3171     for (cn=0; ColumnData[cn].Name != NULL; cn++) {
3172         if (strcasecmp(s, ColumnData[cn].Name) == 0) {
3173             break;
3174         }
3175     }
3176     return cn;
3177 }
3178
3179 char
3180 LastChar(s)
3181     char *s;
3182 {
3183     return s[strlen(s)-1];
3184 }
3185
3186 int
3187 SetColumDataFromString(ci, s, errstr)
3188     ColumnInfo* ci;
3189     char *s;
3190     char **errstr;
3191 {
3192     /* Convert from a Columspec string to our internal format
3193      * of columspec. The purpose is to provide this string
3194      * as configuration paramter in the amanda.conf file or
3195      * (maybe) as environment variable.
3196      * 
3197      * This text should go as comment into the sample amanda.conf
3198      *
3199      * The format for such a ColumnSpec string s is a ',' seperated
3200      * list of triples. Each triple consists of
3201      *   -the name of the column (as in ColumnData.Name)
3202      *   -prefix before the column
3203      *   -the width of the column
3204      *       if set to -1 it will be recalculated
3205      *   to the maximum length of a line to print.
3206      * Example:
3207      *  "Disk=1:17,HostName=1:10,OutKB=1:7"
3208      * or
3209      *  "Disk=1:-1,HostName=1:10,OutKB=1:7"
3210      *  
3211      * You need only specify those colums that should be changed from
3212      * the default. If nothing is specified in the configfile, the
3213      * above compiled in values will be in effect, resulting in an
3214      * output as it was all the time.
3215      *                                                  ElB, 1999-02-24.
3216      */
3217 #ifdef TEST
3218     char *myname= "SetColumDataFromString";
3219 #endif
3220
3221     while (s && *s) {
3222         int Space, Width;
3223         int cn;
3224         char *eon= strchr(s, '=');
3225
3226         if (eon == NULL) {
3227             *errstr = stralloc2("invalid columnspec: ", s);
3228 #ifdef TEST
3229             fprintf(stderr, "%s: %s\n", myname, *errstr);
3230 #endif
3231             return -1;
3232         }
3233         *eon= '\0';
3234         cn=StringToColumn(s);
3235         if (ColumnData[cn].Name == NULL) {
3236             *errstr = stralloc2("invalid column name: ", s);
3237 #ifdef TEST
3238             fprintf(stderr, "%s: %s\n", myname, *errstr);
3239 #endif
3240             return -1;
3241         }
3242         if (sscanf(eon+1, "%d:%d", &Space, &Width) != 2) {
3243             *errstr = stralloc2("invalid format: ", eon + 1);
3244 #ifdef TEST
3245             fprintf(stderr, "%s: %s\n", myname, *errstr);
3246 #endif
3247             return -1;
3248         }
3249         ColumnData[cn].Width= Width;
3250         ColumnData[cn].PrefixSpace= Space;
3251         if (LastChar(ColumnData[cn].Format) == 's') {
3252             if (Width < 0)
3253                 ColumnData[cn].MaxWidth= 1;
3254             else
3255                 if (Width > ColumnData[cn].Precision)
3256                     ColumnData[cn].Precision= Width;
3257         }
3258         else if (Width < ColumnData[cn].Precision)
3259             ColumnData[cn].Precision= Width;
3260         s= strchr(eon+1, ',');
3261         if (s != NULL)
3262             s++;
3263     }
3264     return 0;
3265 }
3266
3267
3268 char *taperalgo2str(taperalgo)
3269 int taperalgo;
3270 {
3271     if(taperalgo == ALGO_FIRST) return "FIRST";
3272     if(taperalgo == ALGO_FIRSTFIT) return "FIRSTFIT";
3273     if(taperalgo == ALGO_LARGEST) return "LARGEST";
3274     if(taperalgo == ALGO_LARGESTFIT) return "LARGESTFIT";
3275     if(taperalgo == ALGO_SMALLEST) return "SMALLEST";
3276     if(taperalgo == ALGO_LAST) return "LAST";
3277     return "UNKNOWN";
3278 }
3279
3280 long int getconf_unit_divisor()
3281 {
3282     return unit_divisor;
3283 }
3284
3285 /* ------------------------ */
3286
3287
3288 #ifdef TEST
3289
3290 void
3291 dump_configuration(filename)
3292     char *filename;
3293 {
3294     tapetype_t *tp;
3295     dumptype_t *dp;
3296     interface_t *ip;
3297     holdingdisk_t *hp;
3298     time_t st;
3299     struct tm *stm;
3300
3301     printf("AMANDA CONFIGURATION FROM FILE \"%s\":\n\n", filename);
3302
3303     printf("conf_org = \"%s\"\n", getconf_str(CNF_ORG));
3304     printf("conf_mailto = \"%s\"\n", getconf_str(CNF_MAILTO));
3305     printf("conf_dumpuser = \"%s\"\n", getconf_str(CNF_DUMPUSER));
3306     printf("conf_printer = \"%s\"\n", getconf_str(CNF_PRINTER));
3307     printf("conf_tapedev = \"%s\"\n", getconf_str(CNF_TAPEDEV));
3308     printf("conf_rawtapedev = \"%s\"\n", getconf_str(CNF_RAWTAPEDEV));
3309     printf("conf_tpchanger = \"%s\"\n", getconf_str(CNF_TPCHANGER));
3310     printf("conf_chngrdev = \"%s\"\n", getconf_str(CNF_CHNGRDEV));
3311     printf("conf_chngrfile = \"%s\"\n", getconf_str(CNF_CHNGRFILE));
3312     printf("conf_labelstr = \"%s\"\n", getconf_str(CNF_LABELSTR));
3313     printf("conf_tapelist = \"%s\"\n", getconf_str(CNF_TAPELIST));
3314     printf("conf_infofile = \"%s\"\n", getconf_str(CNF_INFOFILE));
3315     printf("conf_logdir = \"%s\"\n", getconf_str(CNF_LOGDIR));
3316     printf("conf_diskfile = \"%s\"\n", getconf_str(CNF_DISKFILE));
3317     printf("conf_tapetype = \"%s\"\n", getconf_str(CNF_TAPETYPE));
3318
3319     printf("conf_dumpcycle = %d\n", getconf_int(CNF_DUMPCYCLE));
3320     printf("conf_runspercycle = %d\n", getconf_int(CNF_RUNSPERCYCLE));
3321     printf("conf_runtapes = %d\n", getconf_int(CNF_RUNTAPES));
3322     printf("conf_tapecycle = %d\n", getconf_int(CNF_TAPECYCLE));
3323     printf("conf_bumppercent = %d\n", getconf_int(CNF_BUMPPERCENT));
3324     printf("conf_bumpsize = %d\n", getconf_int(CNF_BUMPSIZE));
3325     printf("conf_bumpdays = %d\n", getconf_int(CNF_BUMPDAYS));
3326     printf("conf_bumpmult = %f\n", getconf_real(CNF_BUMPMULT));
3327     printf("conf_netusage = %d\n", getconf_int(CNF_NETUSAGE));
3328     printf("conf_inparallel = %d\n", getconf_int(CNF_INPARALLEL));
3329     printf("conf_dumporder = \"%s\"\n", getconf_str(CNF_DUMPORDER));
3330     /*printf("conf_timeout = %d\n", getconf_int(CNF_TIMEOUT));*/
3331     printf("conf_maxdumps = %d\n", getconf_int(CNF_MAXDUMPS));
3332     printf("conf_etimeout = %d\n", getconf_int(CNF_ETIMEOUT));
3333     printf("conf_dtimeout = %d\n", getconf_int(CNF_DTIMEOUT));
3334     printf("conf_ctimeout = %d\n", getconf_int(CNF_CTIMEOUT));
3335     printf("conf_tapebufs = %d\n", getconf_int(CNF_TAPEBUFS));
3336     printf("conf_autoflush  = %d\n", getconf_int(CNF_AUTOFLUSH));
3337     printf("conf_reserve  = %d\n", getconf_int(CNF_RESERVE));
3338     printf("conf_maxdumpsize  = " AM64_FMT "\n", getconf_am64(CNF_MAXDUMPSIZE));
3339     printf("conf_amrecover_do_fsf  = %d\n", getconf_int(CNF_AMRECOVER_DO_FSF));
3340     printf("conf_amrecover_check_label  = %d\n", getconf_int(CNF_AMRECOVER_CHECK_LABEL));
3341     printf("conf_amrecover_changer = \"%s\"\n", getconf_str(CNF_AMRECOVER_CHANGER));
3342     printf("conf_taperalgo  = %s\n", taperalgo2str(getconf_int(CNF_TAPERALGO)));
3343     printf("conf_displayunit  = %s\n", getconf_str(CNF_DISPLAYUNIT));
3344
3345     /*printf("conf_diskdir = \"%s\"\n", getconf_str(CNF_DISKDIR));*/
3346     /*printf("conf_disksize = %d\n", getconf_int(CNF_DISKSIZE));*/
3347     printf("conf_columnspec = \"%s\"\n", getconf_str(CNF_COLUMNSPEC));
3348     printf("conf_indexdir = \"%s\"\n", getconf_str(CNF_INDEXDIR));
3349     printf("num_holdingdisks = %d\n", num_holdingdisks);
3350     printf("conf_krb5keytab = \"%s\"\n", getconf_str(CNF_KRB5KEYTAB));
3351     printf("conf_krb5principal = \"%s\"\n", getconf_str(CNF_KRB5PRINCIPAL));
3352     printf("conf_label_new_tapes  = \"%s\"\n", getconf_str(CNF_LABEL_NEW_TAPES));
3353     for(hp = holdingdisks; hp != NULL; hp = hp->next) {
3354         printf("\nHOLDINGDISK %s:\n", hp->name);
3355         printf("        COMMENT \"%s\"\n", hp->comment);
3356         printf("        DISKDIR \"%s\"\n", hp->diskdir);
3357         printf("        SIZE %ld\n", (long)hp->disksize);
3358         printf("        CHUNKSIZE %ld\n", (long)hp->chunksize);
3359     }
3360
3361     for(tp = tapelist; tp != NULL; tp = tp->next) {
3362         printf("\nTAPETYPE %s:\n", tp->name);
3363         printf("        COMMENT \"%s\"\n", tp->comment);
3364         printf("        LBL_TEMPL %s\n", tp->lbl_templ);
3365         printf("        BLOCKSIZE %ld\n", (long)tp->blocksize);
3366         printf("        FILE_PAD %s\n", (tp->file_pad) ? "YES" : "NO");
3367         printf("        LENGTH %lu\n", (unsigned long)tp->length);
3368         printf("        FILEMARK %lu\n", (unsigned long)tp->filemark);
3369         printf("        SPEED %ld\n", (long)tp->speed);
3370     }
3371
3372     for(dp = dumplist; dp != NULL; dp = dp->next) {
3373         printf("\nDUMPTYPE %s:\n", dp->name);
3374         printf("        COMMENT \"%s\"\n", dp->comment);
3375         printf("        PROGRAM \"%s\"\n", dp->program);
3376         printf("        SERVER_CUSTOM_COMPRESS \"%s\"\n", dp->srvcompprog);
3377         printf("        CLIENT_CUSTOM_COMPRESS \"%s\"\n", dp->clntcompprog);
3378         printf("        SERVER_ENCRYPT \"%s\"\n", dp->srv_encrypt);
3379         printf("        CLIENT_ENCRYPT \"%s\"\n", dp->clnt_encrypt);
3380         printf("        SERVER_DECRYPT_OPTION \"%s\"\n", dp->srv_decrypt_opt);
3381         printf("        CLIENT_DECRYPT_OPTION \"%s\"\n", dp->clnt_decrypt_opt);
3382         printf("        PRIORITY %ld\n", (long)dp->priority);
3383         printf("        DUMPCYCLE %ld\n", (long)dp->dumpcycle);
3384         st = dp->start_t;
3385         if(st) {
3386             stm = localtime(&st);
3387             printf("    STARTTIME %d:%02d:%02d\n",
3388               stm->tm_hour, stm->tm_min, stm->tm_sec);
3389         }
3390         if(dp->exclude_file) {
3391             sle_t *excl;
3392             printf("    EXCLUDE FILE");
3393             for(excl = dp->exclude_file->first; excl != NULL; excl =excl->next){
3394                 printf(" \"%s\"", excl->name);
3395             }
3396             printf("\n");
3397         }
3398         if(dp->exclude_list) {
3399             sle_t *excl;
3400             printf("    EXCLUDE LIST");
3401             for(excl = dp->exclude_list->first; excl != NULL; excl =excl->next){
3402                 printf(" \"%s\"", excl->name);
3403             }
3404             printf("\n");
3405         }
3406         if(dp->include_file) {
3407             sle_t *incl;
3408             printf("    INCLUDE FILE");
3409             for(incl = dp->include_file->first; incl != NULL; incl =incl->next){
3410                 printf(" \"%s\"", incl->name);
3411             }
3412             printf("\n");
3413         }
3414         if(dp->include_list) {
3415             sle_t *incl;
3416             printf("    INCLUDE LIST");
3417             for(incl = dp->include_list->first; incl != NULL; incl =incl->next){
3418                 printf(" \"%s\"", incl->name);
3419             }
3420             printf("\n");
3421         }
3422         printf("        FREQUENCY %ld\n", (long)dp->frequency);
3423         printf("        MAXDUMPS %d\n", dp->maxdumps);
3424         printf("        MAXPROMOTEDAY %d\n", dp->maxpromoteday);
3425         printf("        STRATEGY ");
3426         switch(dp->strategy) {
3427         case DS_SKIP:
3428             printf("SKIP");
3429             break;
3430         case DS_STANDARD:
3431             printf("STANDARD");
3432             break;
3433         case DS_NOFULL:
3434             printf("NOFULL");
3435             break;
3436         case DS_NOINC:
3437             printf("NOINC");
3438             break;
3439         case DS_HANOI:
3440             printf("HANOI");
3441             break;
3442         case DS_INCRONLY:
3443             printf("INCRONLY");
3444             break;
3445         }
3446         putchar('\n');
3447         printf("        ESTIMATE ");
3448         switch(dp->estimate) {
3449         case ES_CLIENT:
3450             printf("CLIENT");
3451             break;
3452         case ES_SERVER:
3453             printf("SERVER");
3454             break;
3455         case ES_CALCSIZE:
3456             printf("CALCSIZE");
3457             break;
3458         }
3459         putchar('\n');
3460         printf("        COMPRATE %f, %f\n", dp->comprate[0], dp->comprate[1]);
3461
3462         printf("        OPTIONS: ");
3463
3464         switch(dp->compress) {
3465         case COMP_NONE:
3466             printf("NO-COMPRESS ");
3467             break;
3468         case COMP_FAST:
3469             printf("COMPRESS-FAST ");
3470             break;
3471         case COMP_BEST:
3472             printf("COMPRESS-BEST ");
3473             break;
3474         case COMP_CUST:
3475             printf("COMPRESS-CUST ");
3476             break;
3477         case COMP_SERV_FAST:
3478             printf("SRVCOMP-FAST ");
3479             break;
3480         case COMP_SERV_BEST:
3481             printf("SRVCOMP-BEST ");
3482             break;
3483         case COMP_SERV_CUST:
3484             printf("SRVCOMP-CUST ");
3485             break;
3486         }
3487
3488         switch(dp->encrypt) {
3489         case ENCRYPT_NONE:
3490             printf("ENCRYPT-NONE ");
3491             break;
3492         case ENCRYPT_CUST:
3493             printf("ENCRYPT-CUST ");
3494             break;
3495         case ENCRYPT_SERV_CUST:
3496             printf("ENCRYPT-SERV-CUST ");
3497             break;
3498         }
3499
3500         if(!dp->record) printf("NO-");
3501         printf("RECORD");
3502         printf(" %s-AUTH", dp->security_driver);
3503         if(dp->skip_incr) printf(" SKIP-INCR");
3504         if(dp->skip_full) printf(" SKIP-FULL");
3505         if(dp->no_hold) printf(" NO-HOLD");
3506         if(dp->kencrypt) printf(" KENCRYPT");
3507         /* an ignored disk will never reach this point */
3508         assert(!dp->ignore);
3509         if(dp->index) printf(" INDEX");
3510         putchar('\n');
3511     }
3512
3513     for(ip = interface_list; ip != NULL; ip = ip->next) {
3514         printf("\nINTERFACE %s:\n", ip->name);
3515         printf("        COMMENT \"%s\"\n", ip->comment);
3516         printf("        USE %d\n", ip->maxusage);
3517     }
3518 }
3519
3520 int
3521 main(argc, argv)
3522     int argc;
3523     char *argv[];
3524 {
3525   char *conffile;
3526   char *diskfile;
3527   disklist_t lst;
3528   int result;
3529   unsigned long malloc_hist_1, malloc_size_1;
3530   unsigned long malloc_hist_2, malloc_size_2;
3531
3532   safe_fd(-1, 0);
3533
3534   set_pname("conffile");
3535
3536   /* Don't die when child closes pipe */
3537   signal(SIGPIPE, SIG_IGN);
3538
3539   malloc_size_1 = malloc_inuse(&malloc_hist_1);
3540
3541   startclock();
3542
3543   if (argc > 1) {
3544     if (argv[1][0] == '/') {
3545       config_dir = stralloc(argv[1]);
3546       config_name = strrchr(config_dir, '/') + 1;
3547       config_name[-1] = '\0';
3548       config_dir = newstralloc2(config_dir, config_dir, "/");
3549     } else {
3550       config_name = stralloc(argv[1]);
3551       config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
3552     }
3553   } else {
3554     char my_cwd[STR_SIZE];
3555
3556     if (getcwd(my_cwd, sizeof(my_cwd)) == NULL) {
3557       error("cannot determine current working directory");
3558     }
3559     config_dir = stralloc2(my_cwd, "/");
3560     if ((config_name = strrchr(my_cwd, '/')) != NULL) {
3561       config_name = stralloc(config_name + 1);
3562     }
3563   }
3564
3565   conffile = stralloc2(config_dir, CONFFILE_NAME);
3566   result = read_conffile(conffile);
3567   if (result == 0) {
3568       diskfile = getconf_str(CNF_DISKFILE);
3569       if (diskfile != NULL && access(diskfile, R_OK) == 0) {
3570           result = read_diskfile(diskfile, &lst);
3571       }
3572   }
3573   dump_configuration(CONFFILE_NAME);
3574   amfree(conffile);
3575
3576   malloc_size_2 = malloc_inuse(&malloc_hist_2);
3577
3578   if(malloc_size_1 != malloc_size_2) {
3579     malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
3580   }
3581
3582   return result;
3583 }
3584
3585 #endif /* TEST */
3586
3587 char *
3588 generic_get_security_conf(string, arg)
3589         char *string;
3590         void *arg;
3591 {
3592         if(!string || !*string)
3593                 return(NULL);
3594
3595         if(strcmp(string, "krb5principal")==0) {
3596                 return(getconf_str(CNF_KRB5PRINCIPAL));
3597         } else if(strcmp(string, "krb5keytab")==0) {
3598                 return(getconf_str(CNF_KRB5KEYTAB));
3599         }
3600         return(NULL);
3601 }