Imported Upstream version 2.5.1
[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.156 2006/07/26 15:17:37 martinea Exp $
29  *
30  * read configuration file
31  */
32
33 #include "amanda.h"
34 #include "arglist.h"
35 #include "util.h"
36 #include "conffile.h"
37 #include "diskfile.h"
38 #include "driverio.h"
39 #include "clock.h"
40
41 #ifdef HAVE_LIMITS_H
42 #include <limits.h>
43 #endif
44
45 #ifndef INT_MAX
46 #define INT_MAX 2147483647
47 #endif
48
49 /* this corresponds to the normal output of amanda, but may
50  * be adapted to any spacing as you like.
51  */
52 ColumnInfo ColumnData[] = {
53     { "HostName",   0, 12, 12, 0, "%-*.*s", "HOSTNAME" },
54     { "Disk",       1, 11, 11, 0, "%-*.*s", "DISK" },
55     { "Level",      1, 1,  1,  0, "%*.*d",  "L" },
56     { "OrigKB",     1, 7,  0,  0, "%*.*lf", "ORIG-KB" },
57     { "OutKB",      1, 7,  0,  0, "%*.*lf", "OUT-KB" },
58     { "Compress",   1, 6,  1,  0, "%*.*lf", "COMP%" },
59     { "DumpTime",   1, 7,  7,  0, "%*.*s",  "MMM:SS" },
60     { "DumpRate",   1, 6,  1,  0, "%*.*lf", "KB/s" },
61     { "TapeTime",   1, 6,  6,  0, "%*.*s",  "MMM:SS" },
62     { "TapeRate",   1, 6,  1,  0, "%*.*lf", "KB/s" },
63     { NULL,         0, 0,  0,  0, NULL,     NULL }
64 };
65
66 char *config_name = NULL;
67 char *config_dir = NULL;
68
69 /* visible holding disk variables */
70
71 holdingdisk_t *holdingdisks;
72 int num_holdingdisks;
73
74 long int unit_divisor = 1;
75
76 /* configuration parameters */
77
78 val_t server_conf[CNF_CNF];
79
80 command_option_t *server_options = NULL;
81
82 /* other internal variables */
83 static holdingdisk_t hdcur;
84
85 static tapetype_t tpcur;
86
87 static dumptype_t dpcur;
88
89 static interface_t ifcur;
90
91 static dumptype_t *dumplist = NULL;
92 static tapetype_t *tapelist = NULL;
93 static interface_t *interface_list = NULL;
94
95 /* predeclare local functions */
96
97 char *get_token_name(tok_t);
98
99
100 void validate_positive0   (t_conf_var *, val_t *);
101 void validate_positive1   (t_conf_var *, val_t *);
102 void validate_runspercycle(t_conf_var *, val_t *);
103 void validate_bumppercent (t_conf_var *, val_t *);
104 void validate_bumpmult    (t_conf_var *, val_t *);
105 void validate_inparallel  (t_conf_var *, val_t *);
106 void validate_displayunit (t_conf_var *, val_t *);
107 void validate_reserve     (t_conf_var *, val_t *);
108 void validate_use         (t_conf_var *, val_t *);
109 void validate_chunksize   (t_conf_var *, val_t *);
110 void validate_blocksize   (t_conf_var *, val_t *);
111
112 static void init_defaults(void);
113 static void read_conffile_recursively(char *filename);
114
115 static int read_confline(void);
116 static void get_holdingdisk(void);
117 static void init_holdingdisk_defaults(void);
118 static void save_holdingdisk(void);
119 static void get_dumptype(void);
120 static void init_dumptype_defaults(void);
121 static void save_dumptype(void);
122 static void copy_dumptype(void);
123 static void get_tapetype(void);
124 static void init_tapetype_defaults(void);
125 static void save_tapetype(void);
126 static void copy_tapetype(void);
127 static void get_interface(void);
128 static void init_interface_defaults(void);
129 static void save_interface(void);
130 static void copy_interface(void);
131 static void get_comprate(t_conf_var *, val_t *);
132 static void get_compress(t_conf_var *, val_t *);
133 static void get_encrypt (t_conf_var *, val_t *);
134 static void get_holding (t_conf_var *, val_t *);
135 static void get_priority(t_conf_var *, val_t *);
136 static void get_strategy(t_conf_var *, val_t *);
137 static void get_estimate(t_conf_var *, val_t *);
138 static void get_exclude (t_conf_var *, val_t *);
139 /*static void get_include(t_conf_var *, val_t *);*/
140 static void get_taperalgo(t_conf_var *, val_t *);
141
142 keytab_t server_keytab[] = {
143     { "AMANDAD_PATH", CONF_AMANDAD_PATH },
144     { "AMRECOVER_CHANGER", CONF_AMRECOVER_CHANGER },
145     { "AMRECOVER_CHECK_LABEL", CONF_AMRECOVER_CHECK_LABEL },
146     { "AMRECOVER_DO_FSF", CONF_AMRECOVER_DO_FSF },
147     { "APPEND", CONF_APPEND },
148     { "AUTH", CONF_AUTH },
149     { "AUTO", CONF_AUTO },
150     { "AUTOFLUSH", CONF_AUTOFLUSH },
151     { "BEST", CONF_BEST },
152     { "BLOCKSIZE", CONF_BLOCKSIZE },
153     { "BUMPDAYS", CONF_BUMPDAYS },
154     { "BUMPMULT", CONF_BUMPMULT },
155     { "BUMPPERCENT", CONF_BUMPPERCENT },
156     { "BUMPSIZE", CONF_BUMPSIZE },
157     { "CALCSIZE", CONF_CALCSIZE },
158     { "CHANGERDEV", CONF_CHNGRDEV },
159     { "CHANGERFILE", CONF_CHNGRFILE },
160     { "CHUNKSIZE", CONF_CHUNKSIZE },
161     { "CLIENT", CONF_CLIENT },
162     { "CLIENT_CUSTOM_COMPRESS", CONF_CLNTCOMPPROG },
163     { "CLIENT_DECRYPT_OPTION", CONF_CLNT_DECRYPT_OPT },
164     { "CLIENT_ENCRYPT", CONF_CLNT_ENCRYPT },
165     { "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
166     { "COLUMNSPEC", CONF_COLUMNSPEC },
167     { "COMMENT", CONF_COMMENT },
168     { "COMPRATE", CONF_COMPRATE },
169     { "COMPRESS", CONF_COMPRESS },
170     { "CTIMEOUT", CONF_CTIMEOUT },
171     { "CUSTOM", CONF_CUSTOM },
172     { "DEFINE", CONF_DEFINE },
173     { "DIRECTORY", CONF_DIRECTORY },
174     { "DISKFILE", CONF_DISKFILE },
175     { "DISPLAYUNIT", CONF_DISPLAYUNIT },
176     { "DTIMEOUT", CONF_DTIMEOUT },
177     { "DUMPCYCLE", CONF_DUMPCYCLE },
178     { "DUMPORDER", CONF_DUMPORDER },
179     { "DUMPTYPE", CONF_DUMPTYPE },
180     { "DUMPUSER", CONF_DUMPUSER },
181     { "ENCRYPT", CONF_ENCRYPT },
182     { "ESTIMATE", CONF_ESTIMATE },
183     { "ETIMEOUT", CONF_ETIMEOUT },
184     { "EXCLUDE", CONF_EXCLUDE },
185     { "EXCLUDE-FILE", CONF_EXCLUDE_FILE },
186     { "EXCLUDE-LIST", CONF_EXCLUDE_LIST },
187     { "FALLBACK_SPLITSIZE", CONF_FALLBACK_SPLITSIZE },
188     { "FAST", CONF_FAST },
189     { "FILE", CONF_EFILE },
190     { "FILE-PAD", CONF_FILE_PAD },
191     { "FILEMARK", CONF_FILEMARK },
192     { "FIRST", CONF_FIRST },
193     { "FIRSTFIT", CONF_FIRSTFIT },
194     { "HANOI", CONF_HANOI },
195     { "HIGH", CONF_HIGH },
196     { "HOLDINGDISK", CONF_HOLDING },
197     { "IGNORE", CONF_IGNORE },
198     { "INCLUDE", CONF_INCLUDE },
199     { "INCLUDEFILE", CONF_INCLUDEFILE },
200     { "INCRONLY", CONF_INCRONLY },
201     { "INDEX", CONF_INDEX },
202     { "INDEXDIR", CONF_INDEXDIR },
203     { "INFOFILE", CONF_INFOFILE },
204     { "INPARALLEL", CONF_INPARALLEL },
205     { "INTERFACE", CONF_INTERFACE },
206     { "KENCRYPT", CONF_KENCRYPT },
207     { "KRB5KEYTAB", CONF_KRB5KEYTAB },
208     { "KRB5PRINCIPAL", CONF_KRB5PRINCIPAL },
209     { "LABELSTR", CONF_LABELSTR },
210     { "LABEL_NEW_TAPES", CONF_LABEL_NEW_TAPES },
211     { "LARGEST", CONF_LARGEST },
212     { "LARGESTFIT", CONF_LARGESTFIT },
213     { "LAST", CONF_LAST },
214     { "LBL-TEMPL", CONF_LBL_TEMPL },
215     { "LENGTH", CONF_LENGTH },
216     { "LIST", CONF_LIST },
217     { "LOGDIR", CONF_LOGDIR },
218     { "LOW", CONF_LOW },
219     { "MAILTO", CONF_MAILTO },
220     { "MAXDUMPS", CONF_MAXDUMPS },
221     { "MAXDUMPSIZE", CONF_MAXDUMPSIZE },
222     { "MAXPROMOTEDAY", CONF_MAXPROMOTEDAY },
223     { "MEDIUM", CONF_MEDIUM },
224     { "NETUSAGE", CONF_NETUSAGE },      /* XXX - historical */
225     { "NEVER", CONF_NEVER },
226     { "NOFULL", CONF_NOFULL },
227     { "NOINC", CONF_NOINC },
228     { "NONE", CONF_NONE },
229     { "OPTIONAL", CONF_OPTIONAL },
230     { "ORG", CONF_ORG },
231     { "PRINTER", CONF_PRINTER },
232     { "PRIORITY", CONF_PRIORITY },
233     { "PROGRAM", CONF_PROGRAM },
234     { "RAWTAPEDEV", CONF_RAWTAPEDEV },
235     { "RECORD", CONF_RECORD },
236     { "REQUIRED", CONF_REQUIRED },
237     { "RESERVE", CONF_RESERVE },
238     { "RUNSPERCYCLE", CONF_RUNSPERCYCLE },
239     { "RUNTAPES", CONF_RUNTAPES },
240     { "SERVER", CONF_SERVER },
241     { "SERVER_CUSTOM_COMPRESS", CONF_SRVCOMPPROG },
242     { "SERVER_DECRYPT_OPTION", CONF_SRV_DECRYPT_OPT },
243     { "SERVER_ENCRYPT", CONF_SRV_ENCRYPT },
244     { "SKIP", CONF_SKIP },
245     { "SKIP-FULL", CONF_SKIP_FULL },
246     { "SKIP-INCR", CONF_SKIP_INCR },
247     { "SMALLEST", CONF_SMALLEST },
248     { "SPEED", CONF_SPEED },
249     { "SPLIT_DISKBUFFER", CONF_SPLIT_DISKBUFFER },
250     { "SSH_KEYS", CONF_SSH_KEYS },
251     { "STANDARD", CONF_STANDARD },
252     { "STARTTIME", CONF_STARTTIME },
253     { "STRATEGY", CONF_STRATEGY },
254     { "TAPEBUFS", CONF_TAPEBUFS },
255     { "TAPECYCLE", CONF_TAPECYCLE },
256     { "TAPEDEV", CONF_TAPEDEV },
257     { "TAPELIST", CONF_TAPELIST },
258     { "TAPERALGO", CONF_TAPERALGO },
259     { "TAPETYPE", CONF_TAPETYPE },
260     { "TAPE_SPLITSIZE", CONF_TAPE_SPLITSIZE },
261     { "TPCHANGER", CONF_TPCHANGER },
262     { "USE", CONF_USE },
263     { "USETIMESTAMPS", CONF_USETIMESTAMPS },
264     { NULL, CONF_IDENT },
265     { NULL, CONF_UNKNOWN }
266 };
267
268 t_conf_var server_var [] = {
269    { CONF_ORG                  , CONFTYPE_STRING   , read_string  , CNF_ORG                  , NULL },
270    { CONF_MAILTO               , CONFTYPE_STRING   , read_string  , CNF_MAILTO               , NULL },
271    { CONF_DUMPUSER             , CONFTYPE_STRING   , read_string  , CNF_DUMPUSER             , NULL },
272    { CONF_PRINTER              , CONFTYPE_STRING   , read_string  , CNF_PRINTER              , NULL },
273    { CONF_TAPEDEV              , CONFTYPE_STRING   , read_string  , CNF_TAPEDEV              , NULL },
274    { CONF_TPCHANGER            , CONFTYPE_STRING   , read_string  , CNF_TPCHANGER            , NULL },
275    { CONF_CHNGRDEV             , CONFTYPE_STRING   , read_string  , CNF_CHNGRDEV             , NULL },
276    { CONF_CHNGRFILE            , CONFTYPE_STRING   , read_string  , CNF_CHNGRFILE            , NULL },
277    { CONF_LABELSTR             , CONFTYPE_STRING   , read_string  , CNF_LABELSTR             , NULL },
278    { CONF_TAPELIST             , CONFTYPE_STRING   , read_string  , CNF_TAPELIST             , NULL },
279    { CONF_DISKFILE             , CONFTYPE_STRING   , read_string  , CNF_DISKFILE             , NULL },
280    { CONF_INFOFILE             , CONFTYPE_STRING   , read_string  , CNF_INFOFILE             , NULL },
281    { CONF_LOGDIR               , CONFTYPE_STRING   , read_string  , CNF_LOGDIR               , NULL },
282    { CONF_INDEXDIR             , CONFTYPE_STRING   , read_string  , CNF_INDEXDIR             , NULL },
283    { CONF_TAPETYPE             , CONFTYPE_IDENT    , read_ident   , CNF_TAPETYPE             , NULL },
284    { CONF_DUMPCYCLE            , CONFTYPE_INT      , read_int     , CNF_DUMPCYCLE            , validate_positive0 },
285    { CONF_RUNSPERCYCLE         , CONFTYPE_INT      , read_int     , CNF_RUNSPERCYCLE         , validate_runspercycle },
286    { CONF_RUNTAPES             , CONFTYPE_INT      , read_int     , CNF_RUNTAPES             , validate_positive0 },
287    { CONF_TAPECYCLE            , CONFTYPE_INT      , read_int     , CNF_TAPECYCLE            , validate_positive1 },
288    { CONF_BUMPDAYS             , CONFTYPE_INT      , read_int     , CNF_BUMPDAYS             , validate_positive1 },
289    { CONF_BUMPSIZE             , CONFTYPE_AM64     , read_am64    , CNF_BUMPSIZE             , validate_positive1 },
290    { CONF_BUMPPERCENT          , CONFTYPE_INT      , read_int     , CNF_BUMPPERCENT          , validate_bumppercent },
291    { CONF_BUMPMULT             , CONFTYPE_REAL     , read_real    , CNF_BUMPMULT             , validate_bumpmult },
292    { CONF_NETUSAGE             , CONFTYPE_INT      , read_int     , CNF_NETUSAGE             , validate_positive1 },
293    { CONF_INPARALLEL           , CONFTYPE_INT      , read_int     , CNF_INPARALLEL           , validate_inparallel },
294    { CONF_DUMPORDER            , CONFTYPE_STRING   , read_string  , CNF_DUMPORDER            , NULL },
295    { CONF_MAXDUMPS             , CONFTYPE_INT      , read_int     , CNF_MAXDUMPS             , validate_positive1 },
296    { CONF_ETIMEOUT             , CONFTYPE_TIME     , read_time    , CNF_ETIMEOUT             , NULL },
297    { CONF_DTIMEOUT             , CONFTYPE_TIME     , read_time    , CNF_DTIMEOUT             , validate_positive1 },
298    { CONF_CTIMEOUT             , CONFTYPE_TIME     , read_time    , CNF_CTIMEOUT             , validate_positive1 },
299    { CONF_TAPEBUFS             , CONFTYPE_INT      , read_int     , CNF_TAPEBUFS             , validate_positive1 },
300    { CONF_RAWTAPEDEV           , CONFTYPE_STRING   , read_string  , CNF_RAWTAPEDEV           , NULL },
301    { CONF_COLUMNSPEC           , CONFTYPE_STRING   , read_string  , CNF_COLUMNSPEC           , NULL },
302    { CONF_TAPERALGO            , CONFTYPE_TAPERALGO, get_taperalgo, CNF_TAPERALGO            , NULL },
303    { CONF_DISPLAYUNIT          , CONFTYPE_STRING   , read_string  , CNF_DISPLAYUNIT          , validate_displayunit },
304    { CONF_AUTOFLUSH            , CONFTYPE_BOOL     , read_bool    , CNF_AUTOFLUSH            , NULL },
305    { CONF_RESERVE              , CONFTYPE_INT      , read_int     , CNF_RESERVE              , validate_reserve },
306    { CONF_MAXDUMPSIZE          , CONFTYPE_AM64     , read_am64    , CNF_MAXDUMPSIZE          , NULL },
307    { CONF_KRB5KEYTAB           , CONFTYPE_STRING   , read_string  , CNF_KRB5KEYTAB           , NULL },
308    { CONF_KRB5PRINCIPAL        , CONFTYPE_STRING   , read_string  , CNF_KRB5PRINCIPAL        , NULL },
309    { CONF_LABEL_NEW_TAPES      , CONFTYPE_STRING   , read_string  , CNF_LABEL_NEW_TAPES      , NULL },
310    { CONF_USETIMESTAMPS        , CONFTYPE_BOOL     , read_bool    , CNF_USETIMESTAMPS        , NULL },
311    { CONF_AMRECOVER_DO_FSF     , CONFTYPE_BOOL     , read_bool    , CNF_AMRECOVER_DO_FSF     , NULL },
312    { CONF_AMRECOVER_CHANGER    , CONFTYPE_STRING   , read_string  , CNF_AMRECOVER_CHANGER    , NULL },
313    { CONF_AMRECOVER_CHECK_LABEL, CONFTYPE_BOOL     , read_bool    , CNF_AMRECOVER_CHECK_LABEL, NULL },
314    { CONF_UNKNOWN              , CONFTYPE_INT      , NULL         , CNF_CNF                  , NULL }
315 };
316 /*
317 ** ------------------------
318 **  External entry points
319 ** ------------------------
320 */
321
322 int
323 read_conffile(
324     char *filename)
325 {
326     interface_t *ip;
327
328     init_defaults();
329
330     /* We assume that conf_confname & conf are initialized to NULL above */
331     read_conffile_recursively(filename);
332
333     /* overwrite with command line option */
334     command_overwrite(server_options, server_var, server_keytab, server_conf,
335                       "");
336
337     if(got_parserror != -1 ) {
338         if(lookup_tapetype(server_conf[CNF_TAPETYPE].v.s) == NULL) {
339             char *save_confname = conf_confname;
340
341             conf_confname = filename;
342             if(!server_conf[CNF_TAPETYPE].seen)
343                 conf_parserror("default tapetype %s not defined", server_conf[CNF_TAPETYPE].v.s);
344             else {
345                 conf_line_num = server_conf[CNF_TAPETYPE].seen;
346                 conf_parserror("tapetype %s not defined", server_conf[CNF_TAPETYPE].v.s);
347             }
348             conf_confname = save_confname;
349         }
350     }
351
352     ip = alloc(SIZEOF(interface_t));
353     ip->name = stralloc("default");
354     ip->seen = server_conf[CNF_NETUSAGE].seen;
355     conf_init_string(&ip->value[INTER_COMMENT], "implicit from NETUSAGE");
356     conf_init_int(&ip->value[INTER_MAXUSAGE], server_conf[CNF_NETUSAGE].v.i);
357     ip->curusage = 0;
358     ip->next = interface_list;
359     interface_list = ip;
360
361     return got_parserror;
362 }
363
364 void
365 validate_positive0(
366     struct s_conf_var *np,
367     val_t        *val)
368 {
369     switch(val->type) {
370     case CONFTYPE_INT:
371         if(val->v.i < 0)
372             conf_parserror("%s must be positive", get_token_name(np->token));
373         break;
374     case CONFTYPE_LONG:
375         if(val->v.l < 0)
376             conf_parserror("%s must be positive", get_token_name(np->token));
377         break;
378     case CONFTYPE_AM64:
379         if(val->v.am64 < 0)
380             conf_parserror("%s must be positive", get_token_name(np->token));
381         break;
382     default:
383         conf_parserror("validate_positive0 invalid type %d\n", val->type);
384     }
385 }
386
387 void
388 validate_positive1(
389     struct s_conf_var *np,
390     val_t        *val)
391 {
392     switch(val->type) {
393     case CONFTYPE_INT:
394         if(val->v.i < 1)
395             conf_parserror("%s must be positive", get_token_name(np->token));
396         break;
397     case CONFTYPE_LONG:
398         if(val->v.l < 1)
399             conf_parserror("%s must be positive", get_token_name(np->token));
400         break;
401     case CONFTYPE_AM64:
402         if(val->v.am64 < 1)
403             conf_parserror("%s must be positive", get_token_name(np->token));
404         break;
405     case CONFTYPE_TIME:
406         if(val->v.t < 1)
407             conf_parserror("%s must be positive", get_token_name(np->token));
408         break;
409     default:
410         conf_parserror("validate_positive1 invalid type %d\n", val->type);
411     }
412 }
413
414 void
415 validate_runspercycle(
416     struct s_conf_var *np,
417     val_t        *val)
418 {
419     np = np;
420     if(val->v.i < -1)
421         conf_parserror("runspercycle must be >= -1");
422 }
423
424 void
425 validate_bumppercent(
426     struct s_conf_var *np,
427     val_t        *val)
428 {
429     np = np;
430     if(val->v.i < 0 || val->v.i > 100)
431         conf_parserror("bumppercent must be between 0 and 100");
432 }
433
434 void
435 validate_inparallel(
436     struct s_conf_var *np,
437     val_t        *val)
438 {
439     np = np;
440     if(val->v.i < 1 || val->v.i >MAX_DUMPERS)
441         conf_parserror("inparallel must be between 1 and MAX_DUMPERS (%d)",
442                        MAX_DUMPERS);
443 }
444
445 void
446 validate_bumpmult(
447     struct s_conf_var *np,
448     val_t        *val)
449 {
450     np = np;
451     if(val->v.r < 0.999) {
452         conf_parserror("bumpmult must be positive");
453     }
454 }
455
456 void
457 validate_displayunit(
458     struct s_conf_var *np,
459     val_t        *val)
460 {
461     np = np;
462     if(strcmp(val->v.s, "k") == 0 ||
463        strcmp(val->v.s, "K") == 0) {
464         val->v.s[0] = (char)toupper(val->v.s[0]);
465         unit_divisor=1;
466     }
467     else if(strcmp(val->v.s, "m") == 0 ||
468        strcmp(val->v.s, "M") == 0) {
469         val->v.s[0] = (char)toupper(val->v.s[0]);
470         unit_divisor=1024;
471     }
472     else if(strcmp(val->v.s, "g") == 0 ||
473        strcmp(val->v.s, "G") == 0) {
474         val->v.s[0] = (char)toupper(val->v.s[0]);
475         unit_divisor=1024*1024;
476     }
477     else if(strcmp(val->v.s, "t") == 0 ||
478        strcmp(val->v.s, "T") == 0) {
479         val->v.s[0] = (char)toupper(val->v.s[0]);
480         unit_divisor=1024*1024*1024;
481     }
482     else {
483         conf_parserror("displayunit must be k,m,g or t.");
484     }
485 }
486
487 void
488 validate_reserve(
489     struct s_conf_var *np,
490     val_t        *val)
491 {
492     np = np;
493     if(val->v.i < 0 || val->v.i > 100)
494         conf_parserror("reserve must be between 0 and 100");
495 }
496
497 void
498 validate_use(
499     struct s_conf_var *np,
500     val_t        *val)
501 {
502     np = np;
503     val->v.am64 = am_floor(val->v.am64, DISK_BLOCK_KB);
504 }
505
506 void
507 validate_chunksize(
508     struct s_conf_var *np,
509     val_t        *val)
510 {
511     np = np;
512     if(val->v.am64 == 0) {
513         val->v.am64 = ((AM64_MAX / 1024) - (2 * DISK_BLOCK_KB));
514     }
515     else if(val->v.am64 < 0) {
516         conf_parserror("Negative chunksize (%lld) is no longer supported", val->v.am64);
517     }
518     val->v.am64 = am_floor(val->v.am64, (off_t)DISK_BLOCK_KB);
519 }
520
521 void
522 validate_blocksize(
523     struct s_conf_var *np,
524     val_t        *val)
525 {
526     np = np;
527     if(val->v.l < DISK_BLOCK_KB) {
528         conf_parserror("Tape blocksize must be at least %d KBytes",
529                   DISK_BLOCK_KB);
530     } else if(val->v.l > MAX_TAPE_BLOCK_KB) {
531         conf_parserror("Tape blocksize must not be larger than %d KBytes",
532                   MAX_TAPE_BLOCK_KB);
533     }
534 }
535
536 char *
537 getconf_byname(
538     char *str)
539 {
540     static char *tmpstr;
541     char number[NUM_STR_SIZE];
542     t_conf_var *np;
543     keytab_t *kt;
544     char *s;
545     char ch;
546
547     tmpstr = stralloc(str);
548     s = tmpstr;
549     while((ch = *s++) != '\0') {
550         if(islower((int)ch))
551             s[-1] = (char)toupper(ch);
552     }
553     for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) {
554         if(kt->keyword && strcmp(kt->keyword, tmpstr) == 0)
555             break;
556     }
557
558     if(kt->token == CONF_UNKNOWN)
559         return NULL;
560
561     for(np = server_var; np->token != CONF_UNKNOWN; np++) {
562         if(np->token == kt->token)
563             break;
564     }
565
566     if(np->token == CONF_UNKNOWN) return NULL;
567
568     if(np->type == CONFTYPE_INT) {
569         snprintf(number, sizeof(number), "%d", server_conf[np->parm].v.i);
570         tmpstr = newstralloc(tmpstr, number);
571     } else if(np->type == CONFTYPE_BOOL) {
572         if(getconf_boolean(np->parm) == 0) {
573             tmpstr = newstralloc(tmpstr, "off");
574         } else {
575             tmpstr = newstralloc(tmpstr, "on");
576         }
577     } else if(np->type == CONFTYPE_REAL) {
578         snprintf(number, sizeof(number), "%lf", server_conf[np->parm].v.r);
579         tmpstr = newstralloc(tmpstr, number);
580     } else if(np->type == CONFTYPE_AM64){
581         snprintf(number, sizeof(number), OFF_T_FMT, 
582                  (OFF_T_FMT_TYPE)server_conf[np->parm].v.am64);
583         tmpstr = newstralloc(tmpstr, number);
584     } else {
585         tmpstr = newstralloc(tmpstr, getconf_str(np->parm));
586     }
587
588     return tmpstr;
589 }
590
591 int
592 getconf_seen(
593     confparm_t parm)
594 {
595     t_conf_var *np;
596     np = get_np(server_var, parm);
597     return(server_conf[np->parm].seen);
598 }
599
600 int
601 getconf_boolean(
602     confparm_t parm)
603 {
604     t_conf_var *np;
605     np = get_np(server_var, parm);
606     if (np->type != CONFTYPE_BOOL) {
607         error("getconf_boolean: np is not a CONFTYPE_BOOL");
608         /*NOTREACHED*/
609     }
610     return(server_conf[np->parm].v.i != 0);
611 }
612
613 int
614 getconf_int(
615     confparm_t parm)
616 {
617     t_conf_var *np;
618     np = get_np(server_var, parm);
619     if (np->type != CONFTYPE_INT) {
620         error("getconf_int: np is not a CONFTYPE_INT");
621         /*NOTREACHED*/
622     }
623     return(server_conf[np->parm].v.i);
624 }
625
626 long
627 getconf_long(
628     confparm_t parm)
629 {
630     t_conf_var *np;
631     np = get_np(server_var, parm);
632     if (np->type != CONFTYPE_LONG) {
633         error("getconf_long: np is not a CONFTYPE_LONG");
634         /*NOTREACHED*/
635     }
636     return(server_conf[np->parm].v.l);
637 }
638
639 time_t
640 getconf_time(
641     confparm_t parm)
642 {
643     t_conf_var *np;
644     np = get_np(server_var, parm);
645     if (np->type != CONFTYPE_TIME) {
646         error("getconf_time: np is not a CONFTYPE_TIME");
647         /*NOTREACHED*/
648     }
649     return(server_conf[np->parm].v.t);
650 }
651
652 ssize_t
653 getconf_size(
654     confparm_t parm)
655 {
656     t_conf_var *np;
657     np = get_np(server_var, parm);
658     if (np->type != CONFTYPE_SIZE) {
659         error("getconf_size: np is not a CONFTYPE_SIZE");
660         /*NOTREACHED*/
661     }
662     return(server_conf[np->parm].v.size);
663 }
664
665 off_t
666 getconf_am64(
667     confparm_t parm)
668 {
669     t_conf_var *np;
670     np = get_np(server_var, parm);
671     if (np->type != CONFTYPE_AM64) {
672         error("getconf_am64: np is not a CONFTYPE_AM64");
673         /*NOTREACHED*/
674     }
675     return(server_conf[np->parm].v.am64);
676 }
677
678 double
679 getconf_real(
680     confparm_t parm)
681 {
682     t_conf_var *np;
683     np = get_np(server_var, parm);
684     if (np->type != CONFTYPE_REAL) {
685         error("getconf_real: np is not a CONFTYPE_REAL");
686         /*NOTREACHED*/
687     }
688     return(server_conf[np->parm].v.r);
689 }
690
691 char *
692 getconf_str(
693     confparm_t parm)
694 {
695     t_conf_var *np;
696     np = get_np(server_var, parm);
697     if (np->type != CONFTYPE_STRING && np->type != CONFTYPE_IDENT) {
698         error("getconf_str: np is not a CONFTYPE_STRING|CONFTYPE_IDENT: %d", parm);
699         /*NOTREACHED*/
700     }
701     return(server_conf[np->parm].v.s);
702 }
703
704 int
705 getconf_taperalgo(
706     confparm_t parm)
707 {
708     t_conf_var *np;
709     np = get_np(server_var, parm);
710     if (np->type != CONFTYPE_TAPERALGO) {
711         error("getconf_taperalgo: np is not a CONFTYPE_TAPERALGO");
712         /*NOTREACHED*/
713     }
714     return(server_conf[np->parm].v.i);
715 }
716
717 holdingdisk_t *
718 getconf_holdingdisks(
719     void)
720 {
721     return holdingdisks;
722 }
723
724 dumptype_t *
725 lookup_dumptype(
726     char *str)
727 {
728     dumptype_t *p;
729
730     for(p = dumplist; p != NULL; p = p->next) {
731         if(strcasecmp(p->name, str) == 0) return p;
732     }
733     return NULL;
734 }
735
736 tapetype_t *
737 lookup_tapetype(
738     char *str)
739 {
740     tapetype_t *p;
741
742     for(p = tapelist; p != NULL; p = p->next) {
743         if(strcasecmp(p->name, str) == 0) return p;
744     }
745     return NULL;
746 }
747
748 interface_t *
749 lookup_interface(
750     char *str)
751 {
752 #ifndef __lint
753     interface_t *p;
754 #endif
755
756     if (str == NULL)
757         return interface_list;
758
759 #ifndef __lint
760     for (p = interface_list; p != NULL; p = p->next) {
761         if (strcasecmp(p->name, str) == 0)
762             return p;
763     }
764 #endif
765     return NULL;
766 }
767
768
769 /*
770 ** ------------------------
771 **  Internal routines
772 ** ------------------------
773 */
774
775
776 static void
777 init_defaults(
778     void)
779 {
780     char *s;
781
782     /* defaults for exported variables */
783
784 #ifdef DEFAULT_CONFIG
785     s = DEFAULT_CONFIG;
786 #else
787     s = "YOUR ORG";
788 #endif
789     conf_init_string(&server_conf[CNF_ORG], s);
790     conf_init_string(&server_conf[CNF_MAILTO], "operators");
791     conf_init_string(&server_conf[CNF_DUMPUSER], CLIENT_LOGIN);
792 #ifdef DEFAULT_TAPE_DEVICE
793     s = DEFAULT_TAPE_DEVICE;
794 #else
795     s = "/dev/rmt8";
796 #endif
797     conf_init_string(&server_conf[CNF_TAPEDEV], s);
798 #ifdef DEFAULT_CHANGER_DEVICE
799     s = DEFAULT_CHANGER_DEVICE;
800 #else
801     s = "/dev/null";
802 #endif
803     conf_init_string(&server_conf[CNF_CHNGRDEV], s);
804     conf_init_string(&server_conf[CNF_CHNGRFILE], "/usr/adm/amanda/changer-status");
805 #ifdef DEFAULT_RAW_TAPE_DEVICE
806     s = DEFAULT_RAW_TAPE_DEVICE;
807 #else
808     s = "/dev/rawft0";
809 #endif
810     conf_init_string   (&server_conf[CNF_LABELSTR]             , ".*");
811     conf_init_string   (&server_conf[CNF_TAPELIST]             , "tapelist");
812     conf_init_string   (&server_conf[CNF_DISKFILE]             , "disklist");
813     conf_init_string   (&server_conf[CNF_INFOFILE]             , "/usr/adm/amanda/curinfo");
814     conf_init_string   (&server_conf[CNF_LOGDIR]               , "/usr/adm/amanda");
815     conf_init_string   (&server_conf[CNF_INDEXDIR]             , "/usr/adm/amanda/index");
816     conf_init_ident    (&server_conf[CNF_TAPETYPE]             , "EXABYTE");
817     conf_init_int      (&server_conf[CNF_DUMPCYCLE]            , 10);
818     conf_init_int      (&server_conf[CNF_RUNSPERCYCLE]         , 0);
819     conf_init_int      (&server_conf[CNF_TAPECYCLE]            , 15);
820     conf_init_int      (&server_conf[CNF_NETUSAGE]             , 300);
821     conf_init_int      (&server_conf[CNF_INPARALLEL]           , 10);
822     conf_init_string   (&server_conf[CNF_DUMPORDER]            , "ttt");
823     conf_init_int      (&server_conf[CNF_BUMPPERCENT]          , 0);
824     conf_init_am64     (&server_conf[CNF_BUMPSIZE]             , (off_t)10*1024);
825     conf_init_real     (&server_conf[CNF_BUMPMULT]             , 1.5);
826     conf_init_int      (&server_conf[CNF_BUMPDAYS]             , 2);
827     conf_init_string   (&server_conf[CNF_TPCHANGER]            , "");
828     conf_init_int      (&server_conf[CNF_RUNTAPES]             , 1);
829     conf_init_int      (&server_conf[CNF_MAXDUMPS]             , 1);
830     conf_init_time     (&server_conf[CNF_ETIMEOUT]             , (time_t)300);
831     conf_init_time     (&server_conf[CNF_DTIMEOUT]             , (time_t)1800);
832     conf_init_time     (&server_conf[CNF_CTIMEOUT]             , (time_t)30);
833     conf_init_int      (&server_conf[CNF_TAPEBUFS]             , 20);
834     conf_init_string   (&server_conf[CNF_RAWTAPEDEV]           , s);
835     conf_init_string   (&server_conf[CNF_PRINTER]              , "");
836     conf_init_bool     (&server_conf[CNF_AUTOFLUSH]            , 0);
837     conf_init_int      (&server_conf[CNF_RESERVE]              , 100);
838     conf_init_am64     (&server_conf[CNF_MAXDUMPSIZE]          , (off_t)-1);
839     conf_init_string   (&server_conf[CNF_COLUMNSPEC]           , "");
840     conf_init_bool     (&server_conf[CNF_AMRECOVER_DO_FSF]     , 1);
841     conf_init_string   (&server_conf[CNF_AMRECOVER_CHANGER]    , "");
842     conf_init_bool     (&server_conf[CNF_AMRECOVER_CHECK_LABEL], 1);
843     conf_init_taperalgo(&server_conf[CNF_TAPERALGO]            , 0);
844     conf_init_string   (&server_conf[CNF_DISPLAYUNIT]          , "k");
845     conf_init_string   (&server_conf[CNF_KRB5KEYTAB]           , "/.amanda-v5-keytab");
846     conf_init_string   (&server_conf[CNF_KRB5PRINCIPAL]        , "service/amanda");
847     conf_init_string   (&server_conf[CNF_LABEL_NEW_TAPES]      , "");
848     conf_init_bool     (&server_conf[CNF_USETIMESTAMPS]        , 0);
849
850     /* defaults for internal variables */
851
852     conf_line_num = got_parserror = 0;
853     allow_overwrites = 0;
854     token_pushed = 0;
855
856     while(holdingdisks != NULL) {
857         holdingdisk_t *hp;
858
859         hp = holdingdisks;
860         holdingdisks = holdingdisks->next;
861         amfree(hp);
862     }
863     num_holdingdisks = 0;
864
865     /* free any previously declared dump, tape and interface types */
866
867     while(dumplist != NULL) {
868         dumptype_t *dp;
869
870         dp = dumplist;
871         dumplist = dumplist->next;
872         amfree(dp);
873     }
874     while(tapelist != NULL) {
875         tapetype_t *tp;
876
877         tp = tapelist;
878         tapelist = tapelist->next;
879         amfree(tp);
880     }
881     while(interface_list != NULL) {
882         interface_t *ip;
883
884         ip = interface_list;
885         interface_list = interface_list->next;
886         amfree(ip);
887     }
888
889     /* create some predefined dumptypes for backwards compatability */
890     init_dumptype_defaults();
891     dpcur.name = stralloc("NO-COMPRESS");
892     dpcur.seen = -1;
893     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_NONE);
894     save_dumptype();
895
896     init_dumptype_defaults();
897     dpcur.name = stralloc("COMPRESS-FAST");
898     dpcur.seen = -1;
899     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_FAST);
900     save_dumptype();
901
902     init_dumptype_defaults();
903     dpcur.name = stralloc("COMPRESS-BEST");
904     dpcur.seen = -1;
905     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_BEST);
906     save_dumptype();
907
908     init_dumptype_defaults();
909     dpcur.name = stralloc("COMPRESS-CUST");
910     dpcur.seen = -1;
911     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_CUST);
912     save_dumptype();
913
914     init_dumptype_defaults();
915     dpcur.name = stralloc("SRVCOMPRESS");
916     dpcur.seen = -1;
917     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_SERV_FAST);
918     save_dumptype();
919
920     init_dumptype_defaults();
921     dpcur.name = stralloc("BSD-AUTH");
922     dpcur.seen = -1;
923     conf_set_string(&dpcur.value[DUMPTYPE_SECURITY_DRIVER], "BSD");
924     save_dumptype();
925
926     init_dumptype_defaults();
927     dpcur.name = stralloc("KRB4-AUTH");
928     dpcur.seen = -1;
929     conf_set_string(&dpcur.value[DUMPTYPE_SECURITY_DRIVER], "KRB4");
930     save_dumptype();
931
932     init_dumptype_defaults();
933     dpcur.name = stralloc("NO-RECORD");
934     dpcur.seen = -1;
935     conf_set_bool(&dpcur.value[DUMPTYPE_RECORD], 0);
936     save_dumptype();
937
938     init_dumptype_defaults();
939     dpcur.name = stralloc("NO-HOLD");
940     dpcur.seen = -1;
941     conf_set_holding(&dpcur.value[DUMPTYPE_HOLDINGDISK], HOLD_NEVER);
942     save_dumptype();
943
944     init_dumptype_defaults();
945     dpcur.name = stralloc("NO-FULL");
946     dpcur.seen = -1;
947     conf_set_strategy(&dpcur.value[DUMPTYPE_STRATEGY], DS_NOFULL);
948     save_dumptype();
949 }
950
951 static void
952 read_conffile_recursively(
953     char *filename)
954 {
955     /* Save globals used in read_confline(), elsewhere. */
956     int  save_line_num  = conf_line_num;
957     FILE *save_conf     = conf_conf;
958     char *save_confname = conf_confname;
959     int rc;
960
961     if (*filename == '/' || config_dir == NULL) {
962         conf_confname = stralloc(filename);
963     } else {
964         conf_confname = stralloc2(config_dir, filename);
965     }
966
967     if((conf_conf = fopen(conf_confname, "r")) == NULL) {
968         fprintf(stderr, "could not open conf file \"%s\": %s\n", conf_confname,
969                 strerror(errno));
970         amfree(conf_confname);
971         got_parserror = -1;
972         return;
973     }
974
975     conf_line_num = 0;
976
977     /* read_confline() can invoke us recursively via "includefile" */
978     do {
979         rc = read_confline();
980     } while (rc != 0);
981     afclose(conf_conf);
982
983     amfree(conf_confname);
984
985     /* Restore servers */
986     conf_line_num = save_line_num;
987     conf_conf     = save_conf;
988     conf_confname = save_confname;
989 }
990
991
992 /* ------------------------ */
993
994
995 static int
996 read_confline(
997     void)
998 {
999     t_conf_var *np;
1000
1001     keytable = server_keytab;
1002
1003     conf_line_num += 1;
1004     get_conftoken(CONF_ANY);
1005     switch(tok) {
1006     case CONF_INCLUDEFILE:
1007         {
1008             char *fn;
1009             char *cname;
1010
1011             get_conftoken(CONF_STRING);
1012             fn = tokenval.v.s;
1013             if (*fn == '/' || config_dir == NULL) {
1014                 cname = stralloc(fn);
1015             } else {
1016                 cname = stralloc2(config_dir, fn);
1017             }
1018             if ( cname != NULL &&  (access(cname, R_OK) == 0)) {
1019                 read_conffile_recursively(cname);
1020                 amfree(cname);
1021             } else {
1022                 conf_parserror("cannot open %s: %s\n", fn, strerror(errno));
1023             }
1024             amfree(cname);
1025             
1026         }
1027         break;
1028
1029     case CONF_HOLDING:
1030         get_holdingdisk();
1031         break;
1032
1033     case CONF_DEFINE:
1034         get_conftoken(CONF_ANY);
1035         if(tok == CONF_DUMPTYPE) get_dumptype();
1036         else if(tok == CONF_TAPETYPE) get_tapetype();
1037         else if(tok == CONF_INTERFACE) get_interface();
1038         else conf_parserror("DUMPTYPE, INTERFACE or TAPETYPE expected");
1039         break;
1040
1041     case CONF_NL:       /* empty line */
1042         break;
1043
1044     case CONF_END:      /* end of file */
1045         return 0;
1046
1047     default:
1048         {
1049             for(np = server_var; np->token != CONF_UNKNOWN; np++) 
1050                 if(np->token == tok) break;
1051
1052             if(np->token == CONF_UNKNOWN) {
1053                 conf_parserror("configuration keyword expected");
1054             } else {
1055                 np->read_function(np, &server_conf[np->parm]);
1056                 if(np->validate)
1057                     np->validate(np, &server_conf[np->parm]);
1058             }
1059         }
1060     }
1061     if(tok != CONF_NL)
1062         get_conftoken(CONF_NL);
1063     return 1;
1064 }
1065
1066 t_conf_var holding_var [] = {
1067    { CONF_DIRECTORY, CONFTYPE_STRING, read_string, HOLDING_DISKDIR  , NULL },
1068    { CONF_COMMENT  , CONFTYPE_STRING, read_string, HOLDING_COMMENT  , NULL },
1069    { CONF_USE      , CONFTYPE_AM64  , read_am64  , HOLDING_DISKSIZE , validate_use },
1070    { CONF_CHUNKSIZE, CONFTYPE_AM64  , read_am64  , HOLDING_CHUNKSIZE, validate_chunksize },
1071    { CONF_UNKNOWN  , CONFTYPE_INT   , NULL       , HOLDING_HOLDING  , NULL }
1072 };
1073
1074 static void
1075 get_holdingdisk(
1076     void)
1077 {
1078     char *prefix;
1079     int save_overwrites;
1080
1081     save_overwrites = allow_overwrites;
1082     allow_overwrites = 1;
1083
1084     init_holdingdisk_defaults();
1085
1086     get_conftoken(CONF_IDENT);
1087     hdcur.name = stralloc(tokenval.v.s);
1088     hdcur.seen = conf_line_num;
1089
1090     prefix = vstralloc( "HOLDINGDISK:", hdcur.name, ":", NULL);
1091     read_block(server_options, holding_var, server_keytab, hdcur.value, prefix,
1092                "holding disk parameter expected", 1, NULL);
1093     amfree(prefix);
1094     get_conftoken(CONF_NL);
1095
1096     hdcur.disksize = holdingdisk_get_disksize(&hdcur);
1097     save_holdingdisk();
1098
1099     allow_overwrites = save_overwrites;
1100 }
1101
1102 static void
1103 init_holdingdisk_defaults(
1104     void)
1105 {
1106     conf_init_string(&hdcur.value[HOLDING_COMMENT]  , "");
1107     conf_init_string(&hdcur.value[HOLDING_DISKDIR]  , "");
1108     conf_init_am64(&hdcur.value[HOLDING_DISKSIZE] , (off_t)0);
1109                     /* 1 Gb = 1M counted in 1Kb blocks */
1110     conf_init_am64(&hdcur.value[HOLDING_CHUNKSIZE], (off_t)1024*1024);
1111
1112     hdcur.up = (void *)0;
1113     hdcur.disksize = 0LL;
1114 }
1115
1116 static void
1117 save_holdingdisk(
1118     void)
1119 {
1120     holdingdisk_t *hp;
1121
1122     hp = alloc(sizeof(holdingdisk_t));
1123     *hp = hdcur;
1124     hp->next = holdingdisks;
1125     holdingdisks = hp;
1126
1127     num_holdingdisks++;
1128 }
1129
1130
1131 t_conf_var dumptype_var [] = {
1132    { CONF_COMMENT           , CONFTYPE_STRING   , read_string , DUMPTYPE_COMMENT           , NULL },
1133    { CONF_AUTH              , CONFTYPE_STRING   , read_string , DUMPTYPE_SECURITY_DRIVER   , NULL },
1134    { CONF_BUMPDAYS          , CONFTYPE_INT      , read_int    , DUMPTYPE_BUMPDAYS          , NULL },
1135    { CONF_BUMPMULT          , CONFTYPE_REAL     , read_real   , DUMPTYPE_BUMPMULT          , NULL },
1136    { CONF_BUMPSIZE          , CONFTYPE_AM64     , read_am64   , DUMPTYPE_BUMPSIZE          , NULL },
1137    { CONF_BUMPPERCENT       , CONFTYPE_INT      , read_int    , DUMPTYPE_BUMPPERCENT       , NULL },
1138    { CONF_COMPRATE          , CONFTYPE_REAL     , get_comprate, DUMPTYPE_COMPRATE          , NULL },
1139    { CONF_COMPRESS          , CONFTYPE_INT      , get_compress, DUMPTYPE_COMPRESS          , NULL },
1140    { CONF_ENCRYPT           , CONFTYPE_INT      , get_encrypt , DUMPTYPE_ENCRYPT           , NULL },
1141    { CONF_DUMPCYCLE         , CONFTYPE_INT      , read_int    , DUMPTYPE_DUMPCYCLE         , validate_positive0 },
1142    { CONF_EXCLUDE           , CONFTYPE_EXINCLUDE, get_exclude , DUMPTYPE_EXCLUDE           , NULL },
1143    { CONF_INCLUDE           , CONFTYPE_EXINCLUDE, get_exclude , DUMPTYPE_INCLUDE           , NULL },
1144    { CONF_IGNORE            , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_IGNORE            , NULL },
1145    { CONF_HOLDING           , CONFTYPE_HOLDING  , get_holding , DUMPTYPE_HOLDINGDISK       , NULL },
1146    { CONF_INDEX             , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_INDEX             , NULL },
1147    { CONF_KENCRYPT          , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_KENCRYPT          , NULL },
1148    { CONF_MAXDUMPS          , CONFTYPE_INT      , read_int    , DUMPTYPE_MAXDUMPS          , validate_positive1 },
1149    { CONF_MAXPROMOTEDAY     , CONFTYPE_INT      , read_int    , DUMPTYPE_MAXPROMOTEDAY     , validate_positive0 },
1150    { CONF_PRIORITY          , CONFTYPE_PRIORITY , get_priority, DUMPTYPE_PRIORITY          , NULL },
1151    { CONF_PROGRAM           , CONFTYPE_STRING   , read_string , DUMPTYPE_PROGRAM           , NULL },
1152    { CONF_RECORD            , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_RECORD            , NULL },
1153    { CONF_SKIP_FULL         , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_SKIP_FULL         , NULL },
1154    { CONF_SKIP_INCR         , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_SKIP_INCR         , NULL },
1155    { CONF_STARTTIME         , CONFTYPE_TIME     , read_time   , DUMPTYPE_START_T           , NULL },
1156    { CONF_STRATEGY          , CONFTYPE_INT      , get_strategy, DUMPTYPE_STRATEGY          , NULL },
1157    { CONF_TAPE_SPLITSIZE    , CONFTYPE_AM64     , read_am64   , DUMPTYPE_TAPE_SPLITSIZE    , validate_positive0 },
1158    { CONF_SPLIT_DISKBUFFER  , CONFTYPE_STRING   , read_string , DUMPTYPE_SPLIT_DISKBUFFER  , NULL },
1159    { CONF_ESTIMATE          , CONFTYPE_INT      , get_estimate, DUMPTYPE_ESTIMATE          , NULL },
1160    { CONF_SRV_ENCRYPT       , CONFTYPE_STRING   , read_string , DUMPTYPE_SRV_ENCRYPT       , NULL },
1161    { CONF_CLNT_ENCRYPT      , CONFTYPE_STRING   , read_string , DUMPTYPE_CLNT_ENCRYPT      , NULL },
1162    { CONF_AMANDAD_PATH      , CONFTYPE_STRING   , read_string , DUMPTYPE_AMANDAD_PATH      , NULL },
1163    { CONF_CLIENT_USERNAME   , CONFTYPE_STRING   , read_string , DUMPTYPE_CLIENT_USERNAME   , NULL },
1164    { CONF_SSH_KEYS          , CONFTYPE_STRING   , read_string , DUMPTYPE_SSH_KEYS          , NULL },
1165    { CONF_SRVCOMPPROG       , CONFTYPE_STRING   , read_string , DUMPTYPE_SRVCOMPPROG       , NULL },
1166    { CONF_CLNTCOMPPROG      , CONFTYPE_STRING   , read_string , DUMPTYPE_CLNTCOMPPROG      , NULL },
1167    { CONF_FALLBACK_SPLITSIZE, CONFTYPE_AM64     , read_am64   , DUMPTYPE_FALLBACK_SPLITSIZE, NULL },
1168    { CONF_SRV_DECRYPT_OPT   , CONFTYPE_STRING   , read_string , DUMPTYPE_SRV_DECRYPT_OPT   , NULL },
1169    { CONF_CLNT_DECRYPT_OPT  , CONFTYPE_STRING   , read_string , DUMPTYPE_CLNT_DECRYPT_OPT  , NULL },
1170    { CONF_UNKNOWN           , CONFTYPE_INT      , NULL        , DUMPTYPE_DUMPTYPE          , NULL }
1171 };
1172
1173 dumptype_t *
1174 read_dumptype(
1175     char *name,
1176     FILE *from,
1177     char *fname,
1178     int *linenum)
1179 {
1180     int save_overwrites;
1181     FILE *saved_conf = NULL;
1182     char *saved_fname = NULL;
1183     char *prefix;
1184
1185     if (from) {
1186         saved_conf = conf_conf;
1187         conf_conf = from;
1188     }
1189
1190     if (fname) {
1191         saved_fname = conf_confname;
1192         conf_confname = fname;
1193     }
1194
1195     if (linenum)
1196         conf_line_num = *linenum;
1197
1198     save_overwrites = allow_overwrites;
1199     allow_overwrites = 1;
1200
1201     init_dumptype_defaults();
1202     if (name) {
1203         dpcur.name = name;
1204     } else {
1205         get_conftoken(CONF_IDENT);
1206         dpcur.name = stralloc(tokenval.v.s);
1207     }
1208     dpcur.seen = conf_line_num;
1209
1210     prefix = vstralloc( "DUMPTYPE:", dpcur.name, ":", NULL);
1211     read_block(server_options, dumptype_var, server_keytab, dpcur.value,
1212                prefix, "dumptype parameter expected",
1213                (name == NULL), *copy_dumptype);
1214     amfree(prefix);
1215     if(!name)
1216         get_conftoken(CONF_NL);
1217
1218     /* XXX - there was a stupidity check in here for skip-incr and
1219     ** skip-full.  This check should probably be somewhere else. */
1220
1221     save_dumptype();
1222
1223     allow_overwrites = save_overwrites;
1224
1225     if (linenum)
1226         *linenum = conf_line_num;
1227
1228     if (fname)
1229         conf_confname = saved_fname;
1230
1231     if (from)
1232         conf_conf = saved_conf;
1233
1234     return lookup_dumptype(dpcur.name);
1235 }
1236
1237 static void
1238 get_dumptype(void)
1239 {
1240     read_dumptype(NULL, NULL, NULL, NULL);
1241 }
1242
1243 static void
1244 init_dumptype_defaults(void)
1245 {
1246     dpcur.name = NULL;
1247     conf_init_string   (&dpcur.value[DUMPTYPE_COMMENT]           , "");
1248     conf_init_string   (&dpcur.value[DUMPTYPE_PROGRAM]           , "DUMP");
1249     conf_init_string   (&dpcur.value[DUMPTYPE_SRVCOMPPROG]       , "");
1250     conf_init_string   (&dpcur.value[DUMPTYPE_CLNTCOMPPROG]      , "");
1251     conf_init_string   (&dpcur.value[DUMPTYPE_SRV_ENCRYPT]       , "");
1252     conf_init_string   (&dpcur.value[DUMPTYPE_CLNT_ENCRYPT]      , "");
1253     conf_init_string   (&dpcur.value[DUMPTYPE_AMANDAD_PATH]      , "X");
1254     conf_init_string   (&dpcur.value[DUMPTYPE_CLIENT_USERNAME]   , "X");
1255     conf_init_string   (&dpcur.value[DUMPTYPE_SSH_KEYS]          , "X");
1256     conf_init_string   (&dpcur.value[DUMPTYPE_SECURITY_DRIVER]   , "BSD");
1257     conf_init_exinclude(&dpcur.value[DUMPTYPE_EXCLUDE]);
1258     conf_init_exinclude(&dpcur.value[DUMPTYPE_INCLUDE]);
1259     conf_init_priority (&dpcur.value[DUMPTYPE_PRIORITY]          , 1);
1260     conf_init_int      (&dpcur.value[DUMPTYPE_DUMPCYCLE]         , server_conf[CNF_DUMPCYCLE].v.i);
1261     conf_init_int      (&dpcur.value[DUMPTYPE_MAXDUMPS]          , server_conf[CNF_MAXDUMPS].v.i);
1262     conf_init_int      (&dpcur.value[DUMPTYPE_MAXPROMOTEDAY]     , 10000);
1263     conf_init_int      (&dpcur.value[DUMPTYPE_BUMPPERCENT]       , server_conf[CNF_BUMPPERCENT].v.i);
1264     conf_init_am64     (&dpcur.value[DUMPTYPE_BUMPSIZE]          , server_conf[CNF_BUMPSIZE].v.am64);
1265     conf_init_int      (&dpcur.value[DUMPTYPE_BUMPDAYS]          , server_conf[CNF_BUMPDAYS].v.i);
1266     conf_init_real     (&dpcur.value[DUMPTYPE_BUMPMULT]          , server_conf[CNF_BUMPMULT].v.r);
1267     conf_init_time     (&dpcur.value[DUMPTYPE_START_T]           , (time_t)0);
1268     conf_init_strategy (&dpcur.value[DUMPTYPE_STRATEGY]          , DS_STANDARD);
1269     conf_init_estimate (&dpcur.value[DUMPTYPE_ESTIMATE]          , ES_CLIENT);
1270     conf_init_compress (&dpcur.value[DUMPTYPE_COMPRESS]          , COMP_FAST);
1271     conf_init_encrypt  (&dpcur.value[DUMPTYPE_ENCRYPT]           , ENCRYPT_NONE);
1272     conf_init_string   (&dpcur.value[DUMPTYPE_SRV_DECRYPT_OPT]   , "-d");
1273     conf_init_string   (&dpcur.value[DUMPTYPE_CLNT_DECRYPT_OPT]  , "-d");
1274     conf_init_rate     (&dpcur.value[DUMPTYPE_COMPRATE]          , 0.50, 0.50);
1275     conf_init_am64     (&dpcur.value[DUMPTYPE_TAPE_SPLITSIZE]    , (off_t)0);
1276     conf_init_am64     (&dpcur.value[DUMPTYPE_FALLBACK_SPLITSIZE], (off_t)10 * 1024);
1277     conf_init_string   (&dpcur.value[DUMPTYPE_SPLIT_DISKBUFFER]  , NULL);
1278     conf_init_bool     (&dpcur.value[DUMPTYPE_RECORD]            , 1);
1279     conf_init_bool     (&dpcur.value[DUMPTYPE_SKIP_INCR]         , 0);
1280     conf_init_bool     (&dpcur.value[DUMPTYPE_SKIP_FULL]         , 0);
1281     conf_init_holding  (&dpcur.value[DUMPTYPE_HOLDINGDISK]       , HOLD_AUTO);
1282     conf_init_bool     (&dpcur.value[DUMPTYPE_KENCRYPT]          , 0);
1283     conf_init_bool     (&dpcur.value[DUMPTYPE_IGNORE]            , 0);
1284     conf_init_bool     (&dpcur.value[DUMPTYPE_INDEX]             , 1);
1285 }
1286
1287 static void
1288 save_dumptype(void)
1289 {
1290     dumptype_t *dp, *dp1;;
1291
1292     dp = lookup_dumptype(dpcur.name);
1293
1294     if(dp != (dumptype_t *)0) {
1295         conf_parserror("dumptype %s already defined on line %d", dp->name, dp->seen);
1296         return;
1297     }
1298
1299     dp = alloc(sizeof(dumptype_t));
1300     *dp = dpcur;
1301     dp->next = NULL;
1302     /* add at end of list */
1303     if(!dumplist)
1304         dumplist = dp;
1305     else {
1306         dp1 = dumplist;
1307         while (dp1->next != NULL) {
1308              dp1 = dp1->next;
1309         }
1310         dp1->next = dp;
1311     }
1312 }
1313
1314 static void
1315 copy_dumptype(void)
1316 {
1317     dumptype_t *dt;
1318     int i;
1319
1320     dt = lookup_dumptype(tokenval.v.s);
1321
1322     if(dt == NULL) {
1323         conf_parserror("dumptype parameter expected");
1324         return;
1325     }
1326
1327     for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
1328         if(dt->value[i].seen) {
1329             free_val_t(&dpcur.value[i]);
1330             copy_val_t(&dpcur.value[i], &dt->value[i]);
1331         }
1332     }
1333 }
1334
1335 t_conf_var tapetype_var [] = {
1336    { CONF_COMMENT  , CONFTYPE_STRING, read_string, TAPETYPE_COMMENT  , NULL },
1337    { CONF_LBL_TEMPL, CONFTYPE_STRING, read_string, TAPETYPE_LBL_TEMPL, NULL },
1338    { CONF_BLOCKSIZE, CONFTYPE_SIZE  , read_size  , TAPETYPE_BLOCKSIZE, validate_blocksize },
1339    { CONF_LENGTH   , CONFTYPE_AM64  , read_am64  , TAPETYPE_LENGTH   , validate_positive0 },
1340    { CONF_FILEMARK , CONFTYPE_AM64  , read_am64  , TAPETYPE_FILEMARK , NULL },
1341    { CONF_SPEED    , CONFTYPE_INT   , read_int   , TAPETYPE_SPEED    , validate_positive0 },
1342    { CONF_FILE_PAD , CONFTYPE_BOOL  , read_bool  , TAPETYPE_FILE_PAD , NULL },
1343    { CONF_UNKNOWN  , CONFTYPE_INT   , NULL       , TAPETYPE_TAPETYPE , NULL }
1344 };
1345
1346 static void
1347 get_tapetype(void)
1348 {
1349     int save_overwrites;
1350     char *prefix;
1351
1352     save_overwrites = allow_overwrites;
1353     allow_overwrites = 1;
1354
1355     init_tapetype_defaults();
1356
1357     get_conftoken(CONF_IDENT);
1358     tpcur.name = stralloc(tokenval.v.s);
1359     tpcur.seen = conf_line_num;
1360
1361     prefix = vstralloc( "TAPETYPE:", tpcur.name, ":", NULL);
1362     read_block(server_options, tapetype_var, server_keytab, tpcur.value,
1363                prefix, "tapetype parameter expected", 1, &copy_tapetype);
1364     amfree(prefix);
1365     get_conftoken(CONF_NL);
1366
1367     save_tapetype();
1368
1369     allow_overwrites = save_overwrites;
1370 }
1371
1372 static void
1373 init_tapetype_defaults(void)
1374 {
1375     conf_init_string(&tpcur.value[TAPETYPE_COMMENT]  , "");
1376     conf_init_string(&tpcur.value[TAPETYPE_LBL_TEMPL], "");
1377     conf_init_size  (&tpcur.value[TAPETYPE_BLOCKSIZE], DISK_BLOCK_KB);
1378     conf_init_am64  (&tpcur.value[TAPETYPE_LENGTH]   , (off_t)2000 * 1024);
1379     conf_init_am64  (&tpcur.value[TAPETYPE_FILEMARK] , (off_t)1000);
1380     conf_init_int   (&tpcur.value[TAPETYPE_SPEED]    , 200);
1381     conf_init_bool  (&tpcur.value[TAPETYPE_FILE_PAD] , 1);
1382 }
1383
1384 static void
1385 save_tapetype(void)
1386 {
1387     tapetype_t *tp, *tp1;
1388
1389     tp = lookup_tapetype(tpcur.name);
1390
1391     if(tp != (tapetype_t *)0) {
1392         amfree(tpcur.name);
1393         conf_parserror("tapetype %s already defined on line %d", tp->name, tp->seen);
1394         return;
1395     }
1396
1397     tp = alloc(sizeof(tapetype_t));
1398     *tp = tpcur;
1399     /* add at end of list */
1400     if(!tapelist)
1401         tapelist = tp;
1402     else {
1403         tp1 = tapelist;
1404         while (tp1->next != NULL) {
1405             tp1 = tp1->next;
1406         }
1407         tp1->next = tp;
1408     }
1409 }
1410
1411 static void
1412 copy_tapetype(void)
1413 {
1414     tapetype_t *tp;
1415     int i;
1416
1417     tp = lookup_tapetype(tokenval.v.s);
1418
1419     if(tp == NULL) {
1420         conf_parserror("tape type parameter expected");
1421         return;
1422     }
1423
1424     for(i=0; i < TAPETYPE_TAPETYPE; i++) {
1425         if(tp->value[i].seen) {
1426             free_val_t(&tpcur.value[i]);
1427             copy_val_t(&tpcur.value[i], &tp->value[i]);
1428         }
1429     }
1430 }
1431
1432 t_conf_var interface_var [] = {
1433    { CONF_COMMENT, CONFTYPE_STRING, read_string, INTER_COMMENT , NULL },
1434    { CONF_USE    , CONFTYPE_INT   , read_int   , INTER_MAXUSAGE, validate_positive1 },
1435    { CONF_UNKNOWN, CONFTYPE_INT   , NULL       , INTER_INTER   , NULL }
1436 };
1437
1438 static void
1439 get_interface(void)
1440 {
1441     int save_overwrites;
1442     char *prefix;
1443
1444     save_overwrites = allow_overwrites;
1445     allow_overwrites = 1;
1446
1447     init_interface_defaults();
1448
1449     get_conftoken(CONF_IDENT);
1450     ifcur.name = stralloc(tokenval.v.s);
1451     ifcur.seen = conf_line_num;
1452
1453     prefix = vstralloc( "INTERFACE:", ifcur.name, ":", NULL);
1454     read_block(server_options, interface_var, server_keytab, ifcur.value,
1455                prefix, "interface parameter expected", 1, &copy_interface);
1456     amfree(prefix);
1457     get_conftoken(CONF_NL);
1458
1459     save_interface();
1460
1461     allow_overwrites = save_overwrites;
1462
1463     return;
1464 }
1465
1466 static void
1467 init_interface_defaults(void)
1468 {
1469     conf_init_string(&ifcur.value[INTER_COMMENT] , "");
1470     conf_init_int   (&ifcur.value[INTER_MAXUSAGE], 300);
1471
1472     ifcur.curusage = 0;
1473 }
1474
1475 static void
1476 save_interface(void)
1477 {
1478     interface_t *ip, *ip1;
1479
1480     ip = lookup_interface(ifcur.name);
1481
1482     if(ip != (interface_t *)0) {
1483         conf_parserror("interface %s already defined on line %d", ip->name,
1484                        ip->seen);
1485         return;
1486     }
1487
1488     ip = alloc(sizeof(interface_t));
1489     *ip = ifcur;
1490     /* add at end of list */
1491     if(!interface_list) {
1492         interface_list = ip;
1493     } else {
1494         ip1 = interface_list;
1495         while (ip1->next != NULL) {
1496             ip1 = ip1->next;
1497         }
1498         ip1->next = ip;
1499     }
1500 }
1501
1502 static void
1503 copy_interface(void)
1504 {
1505 /*
1506     int i;
1507     t_xxx *np;
1508     keytab_t *kt;
1509     
1510     val_t val;
1511 */
1512     interface_t *ip;
1513     int i;
1514
1515     ip = lookup_interface(tokenval.v.s);
1516
1517     if(ip == NULL) {
1518         conf_parserror("interface parameter expected");
1519         return;
1520     }
1521
1522     for(i=0; i < INTER_INTER; i++) {
1523         if(ip->value[i].seen) {
1524             free_val_t(&ifcur.value[i]);
1525             copy_val_t(&ifcur.value[i], &ip->value[i]);
1526         }
1527     }
1528 }
1529
1530 static void
1531 get_comprate(
1532     t_conf_var *np,
1533     val_t *val)
1534 {
1535     np = np;
1536     get_conftoken(CONF_REAL);
1537     val->v.rate[0] = tokenval.v.r;
1538     val->v.rate[1] = tokenval.v.r;
1539     val->seen = tokenval.seen;
1540     if(tokenval.v.r < 0) {
1541         conf_parserror("full compression rate must be >= 0");
1542     }
1543
1544     get_conftoken(CONF_ANY);
1545     switch(tok) {
1546     case CONF_NL:
1547         return;
1548
1549     case CONF_END:
1550         return;
1551
1552     case CONF_COMMA:
1553         break;
1554
1555     default:
1556         unget_conftoken();
1557     }
1558
1559     get_conftoken(CONF_REAL);
1560     val->v.rate[1] = tokenval.v.r;
1561     if(tokenval.v.r < 0) {
1562         conf_parserror("incremental compression rate must be >= 0");
1563     }
1564 }
1565
1566 static void
1567 get_compress(
1568     t_conf_var *np,
1569     val_t *val)
1570 {
1571     int serv, clie, none, fast, best, custom;
1572     int done;
1573     comp_t comp;
1574
1575     np = np;
1576     ckseen(&val->seen);
1577
1578     serv = clie = none = fast = best = custom  = 0;
1579
1580     done = 0;
1581     do {
1582         get_conftoken(CONF_ANY);
1583         switch(tok) {
1584         case CONF_NONE:   none = 1; break;
1585         case CONF_FAST:   fast = 1; break;
1586         case CONF_BEST:   best = 1; break;
1587         case CONF_CLIENT: clie = 1; break;
1588         case CONF_SERVER: serv = 1; break;
1589         case CONF_CUSTOM: custom=1; break;
1590         case CONF_NL:     done = 1; break;
1591         case CONF_END:    done = 1; break;
1592         default:
1593             done = 1;
1594             serv = clie = 1; /* force an error */
1595         }
1596     } while(!done);
1597
1598     if(serv + clie == 0) clie = 1;      /* default to client */
1599     if(none + fast + best + custom  == 0) fast = 1; /* default to fast */
1600
1601     comp = -1;
1602
1603     if(!serv && clie) {
1604         if(none && !fast && !best && !custom) comp = COMP_NONE;
1605         if(!none && fast && !best && !custom) comp = COMP_FAST;
1606         if(!none && !fast && best && !custom) comp = COMP_BEST;
1607         if(!none && !fast && !best && custom) comp = COMP_CUST;
1608     }
1609
1610     if(serv && !clie) {
1611         if(none && !fast && !best && !custom) comp = COMP_NONE;
1612         if(!none && fast && !best && !custom) comp = COMP_SERV_FAST;
1613         if(!none && !fast && best && !custom) comp = COMP_SERV_BEST;
1614         if(!none && !fast && !best && custom) comp = COMP_SERV_CUST;
1615     }
1616
1617     if((int)comp == -1) {
1618         conf_parserror("NONE, CLIENT FAST, CLIENT BEST, CLIENT CUSTOM, SERVER FAST, SERVER BEST or SERVER CUSTOM expected");
1619         comp = COMP_NONE;
1620     }
1621
1622     val->v.i = (int)comp;
1623 }
1624
1625 static void
1626 get_encrypt(
1627     t_conf_var *np,
1628     val_t *val)
1629 {
1630    encrypt_t encrypt;
1631
1632    np = np;
1633    ckseen(&val->seen);
1634
1635    get_conftoken(CONF_ANY);
1636    switch(tok) {
1637    case CONF_NONE:  
1638      encrypt = ENCRYPT_NONE; 
1639      break;
1640
1641    case CONF_CLIENT:  
1642      encrypt = ENCRYPT_CUST;
1643      break;
1644
1645    case CONF_SERVER: 
1646      encrypt = ENCRYPT_SERV_CUST;
1647      break;
1648
1649    default:
1650      conf_parserror("NONE, CLIENT or SERVER expected");
1651      encrypt = ENCRYPT_NONE;
1652      break;
1653    }
1654
1655    val->v.i = (int)encrypt;
1656 }
1657
1658 static void
1659 get_holding(
1660     t_conf_var *np,
1661     val_t *val)
1662 {
1663    dump_holdingdisk_t holding;
1664
1665    np = np;
1666    ckseen(&val->seen);
1667
1668    get_conftoken(CONF_ANY);
1669    switch(tok) {
1670    case CONF_NEVER:  
1671      holding = HOLD_NEVER; 
1672      break;
1673
1674    case CONF_AUTO:  
1675      holding = HOLD_AUTO;
1676      break;
1677
1678    case CONF_REQUIRED: 
1679      holding = HOLD_REQUIRED;
1680      break;
1681
1682    default: /* can be a BOOLEAN */
1683      unget_conftoken();
1684      holding =  (dump_holdingdisk_t)get_bool();
1685      if (holding == 0)
1686         holding = HOLD_NEVER;
1687      else if (holding == 1 || holding == 2)
1688         holding = HOLD_AUTO;
1689      else
1690         conf_parserror("NEVER, AUTO or REQUIRED expected");
1691      break;
1692    }
1693
1694    val->v.i = (int)holding;
1695 }
1696
1697 static void
1698 get_taperalgo(
1699     t_conf_var *np,
1700     val_t *val)
1701 {
1702     np = np;
1703     ckseen(&val->seen);
1704
1705     get_conftoken(CONF_ANY);
1706     switch(tok) {
1707     case CONF_FIRST:      val->v.i = ALGO_FIRST;      break;
1708     case CONF_FIRSTFIT:   val->v.i = ALGO_FIRSTFIT;   break;
1709     case CONF_LARGEST:    val->v.i = ALGO_LARGEST;    break;
1710     case CONF_LARGESTFIT: val->v.i = ALGO_LARGESTFIT; break;
1711     case CONF_SMALLEST:   val->v.i = ALGO_SMALLEST;   break;
1712     case CONF_LAST:       val->v.i = ALGO_LAST;       break;
1713     default:
1714         conf_parserror("FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST or LAST expected");
1715     }
1716 }
1717
1718 static void
1719 get_priority(
1720     t_conf_var *np,
1721     val_t *val)
1722 {
1723     int pri;
1724
1725     np = np;
1726     ckseen(&val->seen);
1727
1728     get_conftoken(CONF_ANY);
1729     switch(tok) {
1730     case CONF_LOW: pri = 0; break;
1731     case CONF_MEDIUM: pri = 1; break;
1732     case CONF_HIGH: pri = 2; break;
1733     case CONF_INT: pri = tokenval.v.i; break;
1734     default:
1735         conf_parserror("LOW, MEDIUM, HIGH or integer expected");
1736         pri = 0;
1737     }
1738     val->v.i = pri;
1739 }
1740
1741 static void
1742 get_strategy(
1743     t_conf_var *np,
1744     val_t *val)
1745 {
1746     int strat;
1747
1748     np = np;
1749     ckseen(&val->seen);
1750
1751     get_conftoken(CONF_ANY);
1752     switch(tok) {
1753     case CONF_SKIP:
1754         strat = DS_SKIP;
1755         break;
1756     case CONF_STANDARD:
1757         strat = DS_STANDARD;
1758         break;
1759     case CONF_NOFULL:
1760         strat = DS_NOFULL;
1761         break;
1762     case CONF_NOINC:
1763         strat = DS_NOINC;
1764         break;
1765     case CONF_HANOI:
1766         strat = DS_HANOI;
1767         break;
1768     case CONF_INCRONLY:
1769         strat = DS_INCRONLY;
1770         break;
1771     default:
1772         conf_parserror("STANDARD or NOFULL expected");
1773         strat = DS_STANDARD;
1774     }
1775     val->v.i = strat;
1776 }
1777
1778 static void
1779 get_estimate(
1780     t_conf_var *np,
1781     val_t *val)
1782 {
1783     int estime;
1784
1785     np = np;
1786     ckseen(&val->seen);
1787
1788     get_conftoken(CONF_ANY);
1789     switch(tok) {
1790     case CONF_CLIENT:
1791         estime = ES_CLIENT;
1792         break;
1793     case CONF_SERVER:
1794         estime = ES_SERVER;
1795         break;
1796     case CONF_CALCSIZE:
1797         estime = ES_CALCSIZE;
1798         break;
1799     default:
1800         conf_parserror("CLIENT, SERVER or CALCSIZE expected");
1801         estime = ES_CLIENT;
1802     }
1803     val->v.i = estime;
1804 }
1805
1806 static void
1807 get_exclude(
1808     t_conf_var *np,
1809     val_t *val)
1810 {
1811     int file, got_one = 0;
1812     sl_t *exclude;
1813     int optional = 0;
1814
1815     np = np;
1816     get_conftoken(CONF_ANY);
1817     if(tok == CONF_LIST) {
1818         file = 0;
1819         get_conftoken(CONF_ANY);
1820     }
1821     else {
1822         file = 1;
1823         if(tok == CONF_EFILE) get_conftoken(CONF_ANY);
1824     }
1825     val->v.exinclude.type = file;
1826     exclude = val->v.exinclude.sl;
1827     ckseen(&val->seen);
1828
1829     if(tok == CONF_OPTIONAL) {
1830         get_conftoken(CONF_ANY);
1831         optional = 1;
1832     }
1833
1834     if(tok == CONF_APPEND) {
1835         get_conftoken(CONF_ANY);
1836     }
1837     else {
1838         free_sl(exclude);
1839         exclude = NULL;
1840     }
1841
1842     while(tok == CONF_STRING) {
1843         exclude = append_sl(exclude, tokenval.v.s);
1844         got_one = 1;
1845         get_conftoken(CONF_ANY);
1846     }
1847     unget_conftoken();
1848
1849     if(got_one == 0) { free_sl(exclude); exclude = NULL; }
1850
1851     val->v.exinclude.sl = exclude;
1852     val->v.exinclude.optional = optional;
1853 }
1854
1855 /*
1856 static void get_include(np, val)
1857     t_conf_var *np;
1858     val_t *val;
1859 {
1860     int list, got_one = 0;
1861     sl_t *include;
1862     int optional = 0;
1863     int append = 0;
1864
1865     get_conftoken(CONF_ANY);
1866     if(tok == CONF_LIST) {
1867         list = 1;
1868         include = dpcur.value[DUMPTYPE_INCLUDE_LIST].v.sl;
1869         ckseen(&dpcur.value[DUMPTYPE_INCLUDE_LIST].seen);
1870         get_conftoken(CONF_ANY);
1871     }
1872     else {
1873         list = 0;
1874         include = dpcur.value[DUMPTYPE_INCLUDE_FILE].v.sl;
1875         ckseen(&dpcur.value[DUMPTYPE_INCLUDE_FILE].seen);
1876         if(tok == CONF_EFILE) get_conftoken(CONF_ANY);
1877     }
1878
1879     if(tok == CONF_OPTIONAL) {
1880         get_conftoken(CONF_ANY);
1881         optional = 1;
1882     }
1883
1884     if(tok == CONF_APPEND) {
1885         get_conftoken(CONF_ANY);
1886         append = 1;
1887     }
1888     else {
1889         free_sl(include);
1890         include = NULL;
1891         append = 0;
1892     }
1893
1894     while(tok == CONF_STRING) {
1895         include = append_sl(include, tokenval.v.s);
1896         got_one = 1;
1897         get_conftoken(CONF_ANY);
1898     }
1899     unget_conftoken();
1900
1901     if(got_one == 0) { free_sl(include); include = NULL; }
1902
1903     if(list == 0)
1904         dpcur.value[DUMPTYPE_INCLUDE_FILE].v.sl = include;
1905     else {
1906         dpcur.value[DUMPTYPE_INCLUDE_LIST].v.sl = include;
1907         if(!append || optional)
1908             dpcur.value[DUMPTYPE_INCLUDE_OPTIONAL].v.i = optional;
1909     }
1910 }
1911 */
1912
1913 /* ------------------------ */
1914
1915 int
1916 ColumnDataCount(void )
1917 {
1918     return (int)(SIZEOF(ColumnData) / SIZEOF(ColumnData[0]));
1919 }
1920
1921 /* conversion from string to table index
1922  */
1923 int
1924 StringToColumn(
1925     char *s)
1926 {
1927     int cn;
1928
1929     for (cn=0; ColumnData[cn].Name != NULL; cn++) {
1930         if (strcasecmp(s, ColumnData[cn].Name) == 0) {
1931             break;
1932         }
1933     }
1934     return cn;
1935 }
1936
1937 char
1938 LastChar(
1939     char *s)
1940 {
1941     return s[strlen(s)-1];
1942 }
1943
1944 int
1945 SetColumDataFromString(
1946     ColumnInfo* ci,
1947     char *s,
1948     char **errstr)
1949 {
1950 #ifdef TEST
1951     char *myname= "SetColumDataFromString";
1952 #endif
1953     ci = ci;
1954
1955     /* Convert from a Columspec string to our internal format
1956      * of columspec. The purpose is to provide this string
1957      * as configuration paramter in the amanda.conf file or
1958      * (maybe) as environment variable.
1959      * 
1960      * This text should go as comment into the sample amanda.conf
1961      *
1962      * The format for such a ColumnSpec string s is a ',' seperated
1963      * list of triples. Each triple consists of
1964      *   -the name of the column (as in ColumnData.Name)
1965      *   -prefix before the column
1966      *   -the width of the column
1967      *       if set to -1 it will be recalculated
1968      *   to the maximum length of a line to print.
1969      * Example:
1970      *  "Disk=1:17,HostName=1:10,OutKB=1:7"
1971      * or
1972      *  "Disk=1:-1,HostName=1:10,OutKB=1:7"
1973      *  
1974      * You need only specify those colums that should be changed from
1975      * the default. If nothing is specified in the configfile, the
1976      * above compiled in values will be in effect, resulting in an
1977      * output as it was all the time.
1978      *                                                  ElB, 1999-02-24.
1979      */
1980
1981     while (s && *s) {
1982         int Space, Width;
1983         int cn;
1984         char *eon= strchr(s, '=');
1985
1986         if (eon == NULL) {
1987             *errstr = stralloc2("invalid columnspec: ", s);
1988 #ifdef TEST
1989             fprintf(stderr, "%s: %s\n", myname, *errstr);
1990 #endif
1991             return -1;
1992         }
1993         *eon= '\0';
1994         cn=StringToColumn(s);
1995         if (ColumnData[cn].Name == NULL) {
1996             *errstr = stralloc2("invalid column name: ", s);
1997 #ifdef TEST
1998             fprintf(stderr, "%s: %s\n", myname, *errstr);
1999 #endif
2000             return -1;
2001         }
2002         if (sscanf(eon+1, "%d:%d", &Space, &Width) != 2) {
2003             *errstr = stralloc2("invalid format: ", eon + 1);
2004 #ifdef TEST
2005             fprintf(stderr, "%s: %s\n", myname, *errstr);
2006 #endif
2007             return -1;
2008         }
2009         ColumnData[cn].Width= Width;
2010         ColumnData[cn].PrefixSpace = Space;
2011         if (LastChar(ColumnData[cn].Format) == 's') {
2012             if (Width < 0)
2013                 ColumnData[cn].MaxWidth= 1;
2014             else
2015                 if (Width > ColumnData[cn].Precision)
2016                     ColumnData[cn].Precision= Width;
2017         }
2018         else if (Width < ColumnData[cn].Precision)
2019             ColumnData[cn].Precision = Width;
2020         s= strchr(eon+1, ',');
2021         if (s != NULL)
2022             s++;
2023     }
2024     return 0;
2025 }
2026
2027
2028 long int
2029 getconf_unit_divisor(void)
2030 {
2031     return unit_divisor;
2032 }
2033
2034 /* ------------------------ */
2035
2036
2037 void
2038 dump_configuration(
2039     char *filename)
2040 {
2041     tapetype_t *tp;
2042     dumptype_t *dp;
2043     interface_t *ip;
2044     holdingdisk_t *hp;
2045     int i;
2046     t_conf_var *np;
2047     keytab_t *kt;
2048     char *prefix;
2049
2050     printf("AMANDA CONFIGURATION FROM FILE \"%s\":\n\n", filename);
2051
2052     for(i=0; i < CNF_CNF; i++) {
2053         for(np=server_var; np->token != CONF_UNKNOWN; np++) {
2054             if(np->parm == i)
2055                 break;
2056         }
2057         if(np->token == CONF_UNKNOWN)
2058             error("server bad value");
2059
2060         for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
2061             if(kt->token == np->token) break;
2062         if(kt->token == CONF_UNKNOWN)
2063             error("server bad token");
2064
2065         printf("%-21s %s\n", kt->keyword, conf_print(&server_conf[i]));
2066     }
2067
2068     for(hp = holdingdisks; hp != NULL; hp = hp->next) {
2069         printf("\nHOLDINGDISK %s {\n", hp->name);
2070         for(i=0; i < HOLDING_HOLDING; i++) {
2071             for(np=holding_var; np->token != CONF_UNKNOWN; np++) {
2072                 if(np->parm == i)
2073                         break;
2074             }
2075             if(np->token == CONF_UNKNOWN)
2076                 error("holding bad value");
2077
2078             for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) {
2079                 if(kt->token == np->token)
2080                     break;
2081             }
2082             if(kt->token == CONF_UNKNOWN)
2083                 error("holding bad token");
2084
2085             printf("      %-9s %s\n", kt->keyword, conf_print(&hp->value[i]));
2086         }
2087         printf("}\n");
2088     }
2089
2090     for(tp = tapelist; tp != NULL; tp = tp->next) {
2091         printf("\nDEFINE TAPETYPE %s {\n", tp->name);
2092         for(i=0; i < TAPETYPE_TAPETYPE; i++) {
2093             for(np=tapetype_var; np->token != CONF_UNKNOWN; np++)
2094                 if(np->parm == i) break;
2095             if(np->token == CONF_UNKNOWN)
2096                 error("tapetype bad value");
2097
2098             for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
2099                 if(kt->token == np->token) break;
2100             if(kt->token == CONF_UNKNOWN)
2101                 error("tapetype bad token");
2102
2103             printf("      %-9s %s\n", kt->keyword, conf_print(&tp->value[i]));
2104         }
2105         printf("}\n");
2106     }
2107
2108     for(dp = dumplist; dp != NULL; dp = dp->next) {
2109         if(dp->seen == -1)
2110             prefix = "#";
2111         else
2112             prefix = "";
2113         printf("\n%sDEFINE DUMPTYPE %s {\n", prefix, dp->name);
2114         for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
2115             for(np=dumptype_var; np->token != CONF_UNKNOWN; np++)
2116                 if(np->parm == i) break;
2117             if(np->token == CONF_UNKNOWN)
2118                 error("dumptype bad value");
2119
2120             for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
2121                 if(kt->token == np->token) break;
2122             if(kt->token == CONF_UNKNOWN)
2123                 error("dumptype bad token");
2124
2125             printf("%s      %-19s %s\n", prefix, kt->keyword, conf_print(&dp->value[i]));
2126         }
2127         printf("%s}\n", prefix);
2128     }
2129
2130     for(ip = interface_list; ip != NULL; ip = ip->next) {
2131         if(strcmp(ip->name,"default") == 0)
2132             prefix = "#";
2133         else
2134             prefix = "";
2135         printf("\n%sDEFINE INTERFACE %s {\n", prefix, ip->name);
2136         for(i=0; i < INTER_INTER; i++) {
2137             for(np=interface_var; np->token != CONF_UNKNOWN; np++)
2138                 if(np->parm == i) break;
2139             if(np->token == CONF_UNKNOWN)
2140                 error("interface bad value");
2141
2142             for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
2143                 if(kt->token == np->token) break;
2144             if(kt->token == CONF_UNKNOWN)
2145                 error("interface bad token");
2146
2147             printf("%s      %-9s %s\n", prefix, kt->keyword, conf_print(&ip->value[i]));
2148         }
2149         printf("%s}\n",prefix);
2150     }
2151
2152 }
2153
2154 #ifdef TEST
2155
2156 int
2157 main(
2158     int argc,
2159     char *argv[])
2160 {
2161   char *conffile;
2162   char *diskfile;
2163   disklist_t lst;
2164   int result;
2165   unsigned long malloc_hist_1, malloc_size_1;
2166   unsigned long malloc_hist_2, malloc_size_2;
2167
2168   safe_fd(-1, 0);
2169
2170   set_pname("conffile");
2171
2172   /* Don't die when child closes pipe */
2173   signal(SIGPIPE, SIG_IGN);
2174
2175   malloc_size_1 = malloc_inuse(&malloc_hist_1);
2176
2177   startclock();
2178
2179   if (argc > 1) {
2180     if (argv[1][0] == '/') {
2181       config_dir = stralloc(argv[1]);
2182       config_name = strrchr(config_dir, '/') + 1;
2183       config_name[-1] = '\0';
2184       config_dir = newstralloc2(config_dir, config_dir, "/");
2185     } else {
2186       config_name = stralloc(argv[1]);
2187       config_dir = vstralloc(CONFIG_DIR, "/", config_name, "/", NULL);
2188     }
2189   } else {
2190     char my_cwd[STR_SIZE];
2191
2192     if (getcwd(my_cwd, sizeof(my_cwd)) == NULL) {
2193       error("cannot determine current working directory");
2194     }
2195     config_dir = stralloc2(my_cwd, "/");
2196     if ((config_name = strrchr(my_cwd, '/')) != NULL) {
2197       config_name = stralloc(config_name + 1);
2198     }
2199   }
2200
2201   conffile = stralloc2(config_dir, CONFFILE_NAME);
2202   result = read_conffile(conffile);
2203   if (result == 0) {
2204       diskfile = getconf_str(CNF_DISKFILE);
2205       if (diskfile != NULL && access(diskfile, R_OK) == 0) {
2206           result = read_diskfile(diskfile, &lst);
2207       }
2208   }
2209   dump_configuration(CONFFILE_NAME);
2210   amfree(conffile);
2211
2212   malloc_size_2 = malloc_inuse(&malloc_hist_2);
2213
2214   if(malloc_size_1 != malloc_size_2) {
2215     malloc_list(fileno(stderr), malloc_hist_1, malloc_hist_2);
2216   }
2217
2218   return result;
2219 }
2220
2221 #endif /* TEST */
2222
2223 char *
2224 generic_get_security_conf(
2225         char *string,
2226         void *arg)
2227 {
2228         arg = arg;
2229         if(!string || !*string)
2230                 return(NULL);
2231
2232         if(strcmp(string, "krb5principal")==0) {
2233                 return(getconf_str(CNF_KRB5PRINCIPAL));
2234         } else if(strcmp(string, "krb5keytab")==0) {
2235                 return(getconf_str(CNF_KRB5KEYTAB));
2236         }
2237         return(NULL);
2238 }
2239
2240 char *
2241 get_token_name(
2242     tok_t token)
2243 {
2244     keytab_t *kt;
2245
2246     for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
2247         if(kt->token == token) break;
2248
2249     if(kt->token == CONF_UNKNOWN)
2250         return("");
2251     return(kt->keyword);
2252 }
2253
2254 void
2255 parse_server_conf(
2256     int parse_argc,
2257     char **parse_argv,
2258     int *new_argc,
2259     char ***new_argv)
2260 {
2261     int i;
2262     char **my_argv;
2263     char *myarg, *value;
2264     command_option_t *server_option;
2265
2266     server_options = alloc((size_t)(parse_argc+1) * SIZEOF(*server_options));
2267     server_option = server_options;
2268     server_option->name = NULL;
2269
2270     my_argv = alloc((size_t)parse_argc * SIZEOF(char *));
2271     *new_argv = my_argv;
2272     *new_argc = 0;
2273     i=0;
2274     while(i<parse_argc) {
2275         if(strncmp(parse_argv[i],"-o",2) == 0) {
2276             if(strlen(parse_argv[i]) > 2)
2277                 myarg = &parse_argv[i][2];
2278             else {
2279                 i++;
2280                 if(i >= parse_argc)
2281                     error("expect something after -o");
2282                 myarg = parse_argv[i];
2283             }
2284             value = index(myarg,'=');
2285             if (value == NULL) {
2286                 conf_parserror("Must specify a value for %s.\n", myarg);
2287             } else {
2288                 *value = '\0';
2289                 value++;
2290                 server_option->used = 0;
2291                 server_option->name = stralloc(myarg);
2292                 server_option->value = stralloc(value);
2293                 server_option++;
2294                 server_option->name = NULL;
2295             }
2296         }
2297         else {
2298             my_argv[*new_argc] = stralloc(parse_argv[i]);
2299             *new_argc += 1;
2300         }
2301         i++;
2302     }
2303 }
2304
2305 void
2306 report_bad_conf_arg(void)
2307 {
2308     command_option_t *command_option;
2309
2310     for(command_option = server_options; command_option->name != NULL;
2311                                                         command_option++) {
2312         if(command_option->used == 0) {
2313             fprintf(stderr,"argument -o%s=%s not used\n",
2314                     command_option->name, command_option->value);
2315         }
2316     }
2317 }
2318
2319 void
2320 free_server_config(void)
2321 {
2322     holdingdisk_t    *hp, *hpnext;
2323     dumptype_t       *dp, *dpnext;
2324     tapetype_t       *tp, *tpnext;
2325     interface_t      *ip, *ipnext;
2326     command_option_t *server_option;
2327     int               i;
2328
2329     for(hp=holdingdisks; hp != NULL; hp = hpnext) {
2330         amfree(hp->name);
2331         for(i=0; i<HOLDING_HOLDING-1; i++) {
2332            free_val_t(&hp->value[i]);
2333         }
2334         hpnext = hp->next;
2335         amfree(hp);
2336     }
2337
2338     for(dp=dumplist; dp != NULL; dp = dpnext) {
2339         amfree(dp->name);
2340         for(i=0; i<DUMPTYPE_DUMPTYPE-1; i++) {
2341            free_val_t(&dp->value[i]);
2342         }
2343         dpnext = dp->next;
2344         amfree(dp);
2345     }
2346
2347     for(tp=tapelist; tp != NULL; tp = tpnext) {
2348         amfree(tp->name);
2349         for(i=0; i<TAPETYPE_TAPETYPE-1; i++) {
2350            free_val_t(&tp->value[i]);
2351         }
2352         tpnext = tp->next;
2353         amfree(tp);
2354     }
2355
2356     for(ip=interface_list; ip != NULL; ip = ipnext) {
2357         amfree(ip->name);
2358         for(i=0; i<INTER_INTER-1; i++) {
2359            free_val_t(&ip->value[i]);
2360         }
2361         ipnext = ip->next;
2362         amfree(ip);
2363     }
2364
2365     if(server_options) {
2366         for(server_option = server_options; server_option->name != NULL;
2367                                                 server_option++) {
2368             amfree(server_option->name);
2369             amfree(server_option->value);
2370         }
2371         amfree(server_options);
2372     }
2373
2374     for(i=0; i<CNF_CNF-1; i++)
2375         free_val_t(&server_conf[i]);
2376 }