Imported Upstream version 2.5.2p1
[debian/amanda] / common-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 "clock.h"
38
39 #ifdef HAVE_LIMITS_H
40 #include <limits.h>
41 #endif
42
43 #ifndef AMANDATES_FILE
44 #define AMANDATES_FILE "/etc/amandates"
45 #endif
46
47 #ifndef INT_MAX
48 #define INT_MAX 2147483647
49 #endif
50
51 /* this corresponds to the normal output of amanda, but may
52  * be adapted to any spacing as you like.
53  */
54 ColumnInfo ColumnData[] = {
55     { "HostName",   0, 12, 12, 0, "%-*.*s", "HOSTNAME" },
56     { "Disk",       1, 11, 11, 0, "%-*.*s", "DISK" },
57     { "Level",      1, 1,  1,  0, "%*.*d",  "L" },
58     { "OrigKB",     1, 7,  0,  0, "%*.*lf", "ORIG-KB" },
59     { "OutKB",      1, 7,  0,  0, "%*.*lf", "OUT-KB" },
60     { "Compress",   1, 6,  1,  0, "%*.*lf", "COMP%" },
61     { "DumpTime",   1, 7,  7,  0, "%*.*s",  "MMM:SS" },
62     { "DumpRate",   1, 6,  1,  0, "%*.*lf", "KB/s" },
63     { "TapeTime",   1, 6,  6,  0, "%*.*s",  "MMM:SS" },
64     { "TapeRate",   1, 6,  1,  0, "%*.*lf", "KB/s" },
65     { NULL,         0, 0,  0,  0, NULL,     NULL }
66 };
67
68 char *config_name = NULL;
69 char *config_dir = NULL;
70
71 int debug_amandad    = 0;
72 int debug_amidxtaped = 0;
73 int debug_amindexd   = 0;
74 int debug_amrecover  = 0;
75 int debug_auth       = 0;
76 int debug_event      = 0;
77 int debug_holding    = 0;
78 int debug_protocol   = 0;
79 int debug_planner    = 0;
80 int debug_driver     = 0;
81 int debug_dumper     = 0;
82 int debug_chunker    = 0;
83 int debug_taper      = 0;
84 int debug_selfcheck  = 0;
85 int debug_sendsize   = 0;
86 int debug_sendbackup = 0;
87
88 /* visible holding disk variables */
89
90 holdingdisk_t *holdingdisks;
91 int num_holdingdisks;
92
93 long int unit_divisor = 1;
94
95 /* configuration parameters */
96
97 val_t conf_data[CNF_CNF];
98 int conffile_init = 0;
99
100 command_option_t *program_options      = NULL;
101 int               program_options_size = 0;
102
103 /* other internal variables */
104 static holdingdisk_t hdcur;
105
106 static tapetype_t tpcur;
107
108 static dumptype_t dpcur;
109
110 static interface_t ifcur;
111
112 static dumptype_t *dumplist = NULL;
113 static tapetype_t *tapelist = NULL;
114 static interface_t *interface_list = NULL;
115
116 static int allow_overwrites;
117 static int token_pushed;
118 static tok_t tok, pushed_tok;
119 static val_t tokenval;
120
121 static int conf_line_num;
122 static int got_parserror;
123 static FILE *conf_conf = (FILE *)NULL;
124 static char *conf_confname = NULL;
125 static char *conf_line = NULL;
126 static char *conf_char = NULL;
127 static keytab_t *keytable = NULL;
128
129 /* predeclare local functions */
130
131 char *get_token_name(tok_t);
132
133
134 static void validate_positive0            (t_conf_var *, val_t *);
135 static void validate_positive1            (t_conf_var *, val_t *);
136 static void validate_runspercycle         (t_conf_var *, val_t *);
137 static void validate_bumppercent          (t_conf_var *, val_t *);
138 static void validate_bumpmult             (t_conf_var *, val_t *);
139 static void validate_inparallel           (t_conf_var *, val_t *);
140 static void validate_displayunit          (t_conf_var *, val_t *);
141 static void validate_reserve              (t_conf_var *, val_t *);
142 static void validate_use                  (t_conf_var *, val_t *);
143 static void validate_chunksize            (t_conf_var *, val_t *);
144 static void validate_blocksize            (t_conf_var *, val_t *);
145 static void validate_debug                (t_conf_var *, val_t *);
146 static void validate_reserved_port_range  (t_conf_var *, val_t *);
147 static void validate_unreserved_port_range(t_conf_var *, val_t *);
148
149 /*static t_conf_var  *get_np(t_conf_var *get_var, int parm);*/
150 static int     get_int(void);
151 /*static long    get_long(void);*/
152 static time_t  get_time(void);
153 static ssize_t get_size(void);
154 static off_t   get_am64_t(void);
155 static int     get_bool(void);
156 static void    ckseen(int *seen);
157 static void    conf_parserror(const char *format, ...)
158                 __attribute__ ((format (printf, 1, 2)));
159 static tok_t   lookup_keyword(char *str);
160
161 static void read_string(t_conf_var *, val_t *);
162 static void read_ident(t_conf_var *, val_t *);
163 static void read_int(t_conf_var *, val_t *);
164 /*static void read_long(t_conf_var *, val_t *);*/
165 static void read_size(t_conf_var *, val_t *);
166 static void read_am64(t_conf_var *, val_t *);
167 static void read_bool(t_conf_var *, val_t *);
168 static void read_real(t_conf_var *, val_t *);
169 static void read_time(t_conf_var *, val_t *);
170 static void read_intrange(t_conf_var *, val_t *);
171 static void conf_init_string(val_t *, char *);
172 static void conf_init_ident(val_t *, char *);
173 static void conf_init_int(val_t *, int);
174 static void conf_init_bool(val_t *, int);
175 static void conf_init_strategy(val_t *, int);
176 static void conf_init_estimate(val_t *, int);
177 static void conf_init_taperalgo(val_t *, int);
178 static void conf_init_priority(val_t *, int);
179 static void conf_init_strategy(val_t *, int);
180 static void conf_init_compress(val_t *, comp_t);
181 static void conf_init_encrypt(val_t *, encrypt_t);
182 static void conf_init_holding(val_t *, dump_holdingdisk_t);
183 /*static void conf_init_long(val_t *, long);*/
184 static void conf_init_size(val_t *, ssize_t);
185 static void conf_init_am64(val_t *, off_t);
186 static void conf_init_real(val_t *, double);
187 static void conf_init_rate(val_t *, double, double);
188 static void conf_init_intrange(val_t *, int, int);
189 static void conf_init_time(val_t *, time_t);
190 /*static void conf_init_sl(val_t *, sl_t *);*/
191 static void conf_init_exinclude(val_t *);
192 static void conf_set_string(val_t *, char *);
193 /*static void conf_set_int(val_t *, int);*/
194 static void conf_set_bool(val_t *, int);
195 static void conf_set_compress(val_t *, comp_t);
196 /*static void conf_set_encrypt(val_t *, encrypt_t);*/
197 static void conf_set_holding(val_t *, dump_holdingdisk_t);
198 static void conf_set_strategy(val_t *, int);
199
200 static void init_defaults(void);
201 static void read_conffile_recursively(char *filename);
202 static void read_client_conffile_recursively(char *filename);
203
204 static int read_confline(void);
205 static int read_client_confline(void);
206
207 static void read_block(command_option_t *command_options, t_conf_var *read_var,
208                        keytab_t *keytab, val_t *valarray, char *prefix,
209                        char *errormsg, int read_brace,
210                        void (*copy_function)(void));
211
212 static void copy_val_t(val_t *, val_t *);
213 static void free_val_t(val_t *);
214 static char *conf_print(val_t *, int, char *);
215 static void conf_print_exinclude(val_t *, int, int, char *prefix, char **buf, int *free_space);
216
217 static void get_holdingdisk(void);
218 static void init_holdingdisk_defaults(void);
219 static void save_holdingdisk(void);
220 static void get_dumptype(void);
221 static void init_dumptype_defaults(void);
222 static void save_dumptype(void);
223 static void copy_dumptype(void);
224 static void get_tapetype(void);
225 static void init_tapetype_defaults(void);
226 static void save_tapetype(void);
227 static void copy_tapetype(void);
228 static void get_interface(void);
229 static void init_interface_defaults(void);
230 static void save_interface(void);
231 static void copy_interface(void);
232 static void get_comprate(t_conf_var *, val_t *);
233 static void get_compress(t_conf_var *, val_t *);
234 static void get_encrypt (t_conf_var *, val_t *);
235 static void get_holding (t_conf_var *, val_t *);
236 static void get_priority(t_conf_var *, val_t *);
237 static void get_strategy(t_conf_var *, val_t *);
238 static void get_estimate(t_conf_var *, val_t *);
239 static void get_exclude (t_conf_var *, val_t *);
240 /*static void get_include(t_conf_var *, val_t *);*/
241 static void get_taperalgo(t_conf_var *, val_t *);
242
243 static int  conftoken_getc(void);
244 static int  conftoken_ungetc(int c);
245 static void unget_conftoken(void);
246 static void get_conftoken(tok_t exp);
247
248 keytab_t   *my_keytab = NULL;
249 t_conf_var *my_var = NULL;
250
251 keytab_t client_keytab[] = {
252     { "CONF", CONF_CONF },
253     { "INDEX_SERVER", CONF_INDEX_SERVER },
254     { "TAPE_SERVER", CONF_TAPE_SERVER },
255     { "TAPEDEV", CONF_TAPEDEV },
256     { "AUTH", CONF_AUTH },
257     { "SSH_KEYS", CONF_SSH_KEYS },
258     { "AMANDAD_PATH", CONF_AMANDAD_PATH },
259     { "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
260     { "GNUTAR_LIST_DIR", CONF_GNUTAR_LIST_DIR },
261     { "AMANDATES", CONF_AMANDATES },
262     { "KRB5KEYTAB", CONF_KRB5KEYTAB },
263     { "KRB5PRINCIPAL", CONF_KRB5PRINCIPAL },
264     { "INCLUDEFILE", CONF_INCLUDEFILE },
265     { "CONNECT_TRIES", CONF_CONNECT_TRIES },
266     { "REP_TRIES", CONF_REP_TRIES },
267     { "REQ_TRIES", CONF_REQ_TRIES },
268     { "DEBUG_AMANDAD", CONF_DEBUG_AMANDAD },
269     { "DEBUG_AMIDXTAPED", CONF_DEBUG_AMIDXTAPED },
270     { "DEBUG_AMINDEXD", CONF_DEBUG_AMINDEXD },
271     { "DEBUG_AMRECOVER", CONF_DEBUG_AMRECOVER },
272     { "DEBUG_AUTH", CONF_DEBUG_AUTH },
273     { "DEBUG_EVENT", CONF_DEBUG_EVENT },
274     { "DEBUG_HOLDING", CONF_DEBUG_HOLDING },
275     { "DEBUG_PROTOCOL", CONF_DEBUG_PROTOCOL },
276     { "DEBUG_PLANNER", CONF_DEBUG_PLANNER },
277     { "DEBUG_DRIVER", CONF_DEBUG_DRIVER },
278     { "DEBUG_DUMPER", CONF_DEBUG_DUMPER },
279     { "DEBUG_CHUNKER", CONF_DEBUG_CHUNKER },
280     { "DEBUG_TAPER", CONF_DEBUG_TAPER },
281     { "DEBUG_SELFCHECK", CONF_DEBUG_SELFCHECK },
282     { "DEBUG_SENDSIZE", CONF_DEBUG_SENDSIZE },
283     { "DEBUG_SENDBACKUP", CONF_DEBUG_SENDBACKUP },
284     { "UNRESERVED-TCP-PORT", CONF_UNRESERVED_TCP_PORT },
285     { NULL, CONF_UNKNOWN },
286 };
287
288 t_conf_var client_var [] = {
289    { CONF_CONF               , CONFTYPE_STRING  , read_string  , CNF_CONF               , NULL },
290    { CONF_INDEX_SERVER       , CONFTYPE_STRING  , read_string  , CNF_INDEX_SERVER       , NULL },
291    { CONF_TAPE_SERVER        , CONFTYPE_STRING  , read_string  , CNF_TAPE_SERVER        , NULL },
292    { CONF_TAPEDEV            , CONFTYPE_STRING  , read_string  , CNF_TAPEDEV            , NULL },
293    { CONF_AUTH               , CONFTYPE_STRING  , read_string  , CNF_AUTH               , NULL },
294    { CONF_SSH_KEYS           , CONFTYPE_STRING  , read_string  , CNF_SSH_KEYS           , NULL },
295    { CONF_AMANDAD_PATH       , CONFTYPE_STRING  , read_string  , CNF_AMANDAD_PATH       , NULL },
296    { CONF_CLIENT_USERNAME    , CONFTYPE_STRING  , read_string  , CNF_CLIENT_USERNAME    , NULL },
297    { CONF_GNUTAR_LIST_DIR    , CONFTYPE_STRING  , read_string  , CNF_GNUTAR_LIST_DIR    , NULL },
298    { CONF_AMANDATES          , CONFTYPE_STRING  , read_string  , CNF_AMANDATES          , NULL },
299    { CONF_KRB5KEYTAB         , CONFTYPE_STRING  , read_string  , CNF_KRB5KEYTAB         , NULL },
300    { CONF_KRB5PRINCIPAL      , CONFTYPE_STRING  , read_string  , CNF_KRB5PRINCIPAL      , NULL },
301    { CONF_CONNECT_TRIES      , CONFTYPE_INT     , read_int     , CNF_CONNECT_TRIES      , validate_positive1 },
302    { CONF_REP_TRIES          , CONFTYPE_INT     , read_int     , CNF_REP_TRIES          , validate_positive1 },
303    { CONF_REQ_TRIES          , CONFTYPE_INT     , read_int     , CNF_REQ_TRIES          , validate_positive1 },
304    { CONF_DEBUG_AMANDAD      , CONFTYPE_INT     , read_int     , CNF_DEBUG_AMANDAD      , validate_debug },
305    { CONF_DEBUG_AMIDXTAPED   , CONFTYPE_INT     , read_int     , CNF_DEBUG_AMIDXTAPED   , validate_debug },
306    { CONF_DEBUG_AMINDEXD     , CONFTYPE_INT     , read_int     , CNF_DEBUG_AMINDEXD     , validate_debug },
307    { CONF_DEBUG_AMRECOVER    , CONFTYPE_INT     , read_int     , CNF_DEBUG_AMRECOVER    , validate_debug },
308    { CONF_DEBUG_AUTH         , CONFTYPE_INT     , read_int     , CNF_DEBUG_AUTH         , validate_debug },
309    { CONF_DEBUG_EVENT        , CONFTYPE_INT     , read_int     , CNF_DEBUG_EVENT        , validate_debug },
310    { CONF_DEBUG_HOLDING      , CONFTYPE_INT     , read_int     , CNF_DEBUG_HOLDING      , validate_debug },
311    { CONF_DEBUG_PROTOCOL     , CONFTYPE_INT     , read_int     , CNF_DEBUG_PROTOCOL     , validate_debug },
312    { CONF_DEBUG_PLANNER      , CONFTYPE_INT     , read_int     , CNF_DEBUG_PLANNER      , validate_debug },
313    { CONF_DEBUG_DRIVER       , CONFTYPE_INT     , read_int     , CNF_DEBUG_DRIVER       , validate_debug },
314    { CONF_DEBUG_DUMPER       , CONFTYPE_INT     , read_int     , CNF_DEBUG_DUMPER       , validate_debug },
315    { CONF_DEBUG_CHUNKER      , CONFTYPE_INT     , read_int     , CNF_DEBUG_CHUNKER      , validate_debug },
316    { CONF_DEBUG_TAPER        , CONFTYPE_INT     , read_int     , CNF_DEBUG_TAPER        , validate_debug },
317    { CONF_DEBUG_SELFCHECK    , CONFTYPE_INT     , read_int     , CNF_DEBUG_SELFCHECK    , validate_debug },
318    { CONF_DEBUG_SENDSIZE     , CONFTYPE_INT     , read_int     , CNF_DEBUG_SENDSIZE     , validate_debug },
319    { CONF_DEBUG_SENDBACKUP   , CONFTYPE_INT     , read_int     , CNF_DEBUG_SENDBACKUP   , validate_debug },
320    { CONF_UNRESERVED_TCP_PORT, CONFTYPE_INTRANGE, read_intrange, CNF_UNRESERVED_TCP_PORT, validate_unreserved_port_range },
321    { CONF_UNKNOWN            , CONFTYPE_INT     , NULL         , CNF_CNF                , NULL }
322 };
323
324 keytab_t server_keytab[] = {
325     { "AMANDAD_PATH", CONF_AMANDAD_PATH },
326     { "AMRECOVER_CHANGER", CONF_AMRECOVER_CHANGER },
327     { "AMRECOVER_CHECK_LABEL", CONF_AMRECOVER_CHECK_LABEL },
328     { "AMRECOVER_DO_FSF", CONF_AMRECOVER_DO_FSF },
329     { "APPEND", CONF_APPEND },
330     { "AUTH", CONF_AUTH },
331     { "AUTO", CONF_AUTO },
332     { "AUTOFLUSH", CONF_AUTOFLUSH },
333     { "BEST", CONF_BEST },
334     { "BLOCKSIZE", CONF_BLOCKSIZE },
335     { "BUMPDAYS", CONF_BUMPDAYS },
336     { "BUMPMULT", CONF_BUMPMULT },
337     { "BUMPPERCENT", CONF_BUMPPERCENT },
338     { "BUMPSIZE", CONF_BUMPSIZE },
339     { "CALCSIZE", CONF_CALCSIZE },
340     { "CHANGERDEV", CONF_CHNGRDEV },
341     { "CHANGERFILE", CONF_CHNGRFILE },
342     { "CHUNKSIZE", CONF_CHUNKSIZE },
343     { "CLIENT", CONF_CLIENT },
344     { "CLIENT_CUSTOM_COMPRESS", CONF_CLNTCOMPPROG },
345     { "CLIENT_DECRYPT_OPTION", CONF_CLNT_DECRYPT_OPT },
346     { "CLIENT_ENCRYPT", CONF_CLNT_ENCRYPT },
347     { "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
348     { "COLUMNSPEC", CONF_COLUMNSPEC },
349     { "COMMENT", CONF_COMMENT },
350     { "COMPRATE", CONF_COMPRATE },
351     { "COMPRESS", CONF_COMPRESS },
352     { "CONNECT_TRIES", CONF_CONNECT_TRIES },
353     { "CTIMEOUT", CONF_CTIMEOUT },
354     { "CUSTOM", CONF_CUSTOM },
355     { "DEBUG_AMANDAD"    , CONF_DEBUG_AMANDAD },
356     { "DEBUG_AMIDXTAPED" , CONF_DEBUG_AMIDXTAPED },
357     { "DEBUG_AMINDEXD"   , CONF_DEBUG_AMINDEXD },
358     { "DEBUG_AMRECOVER"  , CONF_DEBUG_AMRECOVER },
359     { "DEBUG_AUTH"       , CONF_DEBUG_AUTH },
360     { "DEBUG_EVENT"      , CONF_DEBUG_EVENT },
361     { "DEBUG_HOLDING"    , CONF_DEBUG_HOLDING },
362     { "DEBUG_PROTOCOL"   , CONF_DEBUG_PROTOCOL },
363     { "DEBUG_PLANNER"    , CONF_DEBUG_PLANNER },
364     { "DEBUG_DRIVER"     , CONF_DEBUG_DRIVER },
365     { "DEBUG_DUMPER"     , CONF_DEBUG_DUMPER },
366     { "DEBUG_CHUNKER"    , CONF_DEBUG_CHUNKER },
367     { "DEBUG_TAPER"      , CONF_DEBUG_TAPER },
368     { "DEBUG_SELFCHECK"  , CONF_DEBUG_SELFCHECK },
369     { "DEBUG_SENDSIZE"   , CONF_DEBUG_SENDSIZE },
370     { "DEBUG_SENDBACKUP" , CONF_DEBUG_SENDBACKUP },
371     { "DEFINE", CONF_DEFINE },
372     { "DIRECTORY", CONF_DIRECTORY },
373     { "DISKFILE", CONF_DISKFILE },
374     { "DISPLAYUNIT", CONF_DISPLAYUNIT },
375     { "DTIMEOUT", CONF_DTIMEOUT },
376     { "DUMPCYCLE", CONF_DUMPCYCLE },
377     { "DUMPORDER", CONF_DUMPORDER },
378     { "DUMPTYPE", CONF_DUMPTYPE },
379     { "DUMPUSER", CONF_DUMPUSER },
380     { "ENCRYPT", CONF_ENCRYPT },
381     { "ESTIMATE", CONF_ESTIMATE },
382     { "ETIMEOUT", CONF_ETIMEOUT },
383     { "EXCLUDE", CONF_EXCLUDE },
384     { "EXCLUDE-FILE", CONF_EXCLUDE_FILE },
385     { "EXCLUDE-LIST", CONF_EXCLUDE_LIST },
386     { "FALLBACK_SPLITSIZE", CONF_FALLBACK_SPLITSIZE },
387     { "FAST", CONF_FAST },
388     { "FILE", CONF_EFILE },
389     { "FILE-PAD", CONF_FILE_PAD },
390     { "FILEMARK", CONF_FILEMARK },
391     { "FIRST", CONF_FIRST },
392     { "FIRSTFIT", CONF_FIRSTFIT },
393     { "HANOI", CONF_HANOI },
394     { "HIGH", CONF_HIGH },
395     { "HOLDINGDISK", CONF_HOLDING },
396     { "IGNORE", CONF_IGNORE },
397     { "INCLUDE", CONF_INCLUDE },
398     { "INCLUDEFILE", CONF_INCLUDEFILE },
399     { "INCRONLY", CONF_INCRONLY },
400     { "INDEX", CONF_INDEX },
401     { "INDEXDIR", CONF_INDEXDIR },
402     { "INFOFILE", CONF_INFOFILE },
403     { "INPARALLEL", CONF_INPARALLEL },
404     { "INTERFACE", CONF_INTERFACE },
405     { "KENCRYPT", CONF_KENCRYPT },
406     { "KRB5KEYTAB", CONF_KRB5KEYTAB },
407     { "KRB5PRINCIPAL", CONF_KRB5PRINCIPAL },
408     { "LABELSTR", CONF_LABELSTR },
409     { "LABEL_NEW_TAPES", CONF_LABEL_NEW_TAPES },
410     { "LARGEST", CONF_LARGEST },
411     { "LARGESTFIT", CONF_LARGESTFIT },
412     { "LAST", CONF_LAST },
413     { "LBL-TEMPL", CONF_LBL_TEMPL },
414     { "LENGTH", CONF_LENGTH },
415     { "LIST", CONF_LIST },
416     { "LOGDIR", CONF_LOGDIR },
417     { "LOW", CONF_LOW },
418     { "MAILTO", CONF_MAILTO },
419     { "READBLOCKSIZE", CONF_READBLOCKSIZE },
420     { "MAXDUMPS", CONF_MAXDUMPS },
421     { "MAXDUMPSIZE", CONF_MAXDUMPSIZE },
422     { "MAXPROMOTEDAY", CONF_MAXPROMOTEDAY },
423     { "MEDIUM", CONF_MEDIUM },
424     { "NETUSAGE", CONF_NETUSAGE },      /* XXX - historical */
425     { "NEVER", CONF_NEVER },
426     { "NOFULL", CONF_NOFULL },
427     { "NOINC", CONF_NOINC },
428     { "NONE", CONF_NONE },
429     { "OPTIONAL", CONF_OPTIONAL },
430     { "ORG", CONF_ORG },
431     { "PRINTER", CONF_PRINTER },
432     { "PRIORITY", CONF_PRIORITY },
433     { "PROGRAM", CONF_PROGRAM },
434     { "RAWTAPEDEV", CONF_RAWTAPEDEV },
435     { "RECORD", CONF_RECORD },
436     { "REP_TRIES", CONF_REP_TRIES },
437     { "REQ_TRIES", CONF_REQ_TRIES },
438     { "REQUIRED", CONF_REQUIRED },
439     { "RESERVE", CONF_RESERVE },
440     { "RESERVED-UDP-PORT", CONF_RESERVED_UDP_PORT },
441     { "RESERVED-TCP-PORT", CONF_RESERVED_TCP_PORT },
442     { "RUNSPERCYCLE", CONF_RUNSPERCYCLE },
443     { "RUNTAPES", CONF_RUNTAPES },
444     { "SERVER", CONF_SERVER },
445     { "SERVER_CUSTOM_COMPRESS", CONF_SRVCOMPPROG },
446     { "SERVER_DECRYPT_OPTION", CONF_SRV_DECRYPT_OPT },
447     { "SERVER_ENCRYPT", CONF_SRV_ENCRYPT },
448     { "SKIP", CONF_SKIP },
449     { "SKIP-FULL", CONF_SKIP_FULL },
450     { "SKIP-INCR", CONF_SKIP_INCR },
451     { "SMALLEST", CONF_SMALLEST },
452     { "SPEED", CONF_SPEED },
453     { "SPLIT_DISKBUFFER", CONF_SPLIT_DISKBUFFER },
454     { "SSH_KEYS", CONF_SSH_KEYS },
455     { "STANDARD", CONF_STANDARD },
456     { "STARTTIME", CONF_STARTTIME },
457     { "STRATEGY", CONF_STRATEGY },
458     { "TAPEBUFS", CONF_TAPEBUFS },
459     { "TAPECYCLE", CONF_TAPECYCLE },
460     { "TAPEDEV", CONF_TAPEDEV },
461     { "TAPELIST", CONF_TAPELIST },
462     { "TAPERALGO", CONF_TAPERALGO },
463     { "TAPETYPE", CONF_TAPETYPE },
464     { "TAPE_SPLITSIZE", CONF_TAPE_SPLITSIZE },
465     { "TPCHANGER", CONF_TPCHANGER },
466     { "UNRESERVED-TCP-PORT", CONF_UNRESERVED_TCP_PORT },
467     { "USE", CONF_USE },
468     { "USETIMESTAMPS", CONF_USETIMESTAMPS },
469     { NULL, CONF_IDENT },
470     { NULL, CONF_UNKNOWN }
471 };
472
473 t_conf_var server_var [] = {
474    { CONF_ORG                  , CONFTYPE_STRING   , read_string  , CNF_ORG                  , NULL },
475    { CONF_MAILTO               , CONFTYPE_STRING   , read_string  , CNF_MAILTO               , NULL },
476    { CONF_DUMPUSER             , CONFTYPE_STRING   , read_string  , CNF_DUMPUSER             , NULL },
477    { CONF_PRINTER              , CONFTYPE_STRING   , read_string  , CNF_PRINTER              , NULL },
478    { CONF_TAPEDEV              , CONFTYPE_STRING   , read_string  , CNF_TAPEDEV              , NULL },
479    { CONF_TPCHANGER            , CONFTYPE_STRING   , read_string  , CNF_TPCHANGER            , NULL },
480    { CONF_CHNGRDEV             , CONFTYPE_STRING   , read_string  , CNF_CHNGRDEV             , NULL },
481    { CONF_CHNGRFILE            , CONFTYPE_STRING   , read_string  , CNF_CHNGRFILE            , NULL },
482    { CONF_LABELSTR             , CONFTYPE_STRING   , read_string  , CNF_LABELSTR             , NULL },
483    { CONF_TAPELIST             , CONFTYPE_STRING   , read_string  , CNF_TAPELIST             , NULL },
484    { CONF_DISKFILE             , CONFTYPE_STRING   , read_string  , CNF_DISKFILE             , NULL },
485    { CONF_INFOFILE             , CONFTYPE_STRING   , read_string  , CNF_INFOFILE             , NULL },
486    { CONF_LOGDIR               , CONFTYPE_STRING   , read_string  , CNF_LOGDIR               , NULL },
487    { CONF_INDEXDIR             , CONFTYPE_STRING   , read_string  , CNF_INDEXDIR             , NULL },
488    { CONF_TAPETYPE             , CONFTYPE_IDENT    , read_ident   , CNF_TAPETYPE             , NULL },
489    { CONF_DUMPCYCLE            , CONFTYPE_INT      , read_int     , CNF_DUMPCYCLE            , validate_positive0 },
490    { CONF_RUNSPERCYCLE         , CONFTYPE_INT      , read_int     , CNF_RUNSPERCYCLE         , validate_runspercycle },
491    { CONF_RUNTAPES             , CONFTYPE_INT      , read_int     , CNF_RUNTAPES             , validate_positive0 },
492    { CONF_TAPECYCLE            , CONFTYPE_INT      , read_int     , CNF_TAPECYCLE            , validate_positive1 },
493    { CONF_BUMPDAYS             , CONFTYPE_INT      , read_int     , CNF_BUMPDAYS             , validate_positive1 },
494    { CONF_BUMPSIZE             , CONFTYPE_AM64     , read_am64    , CNF_BUMPSIZE             , validate_positive1 },
495    { CONF_BUMPPERCENT          , CONFTYPE_INT      , read_int     , CNF_BUMPPERCENT          , validate_bumppercent },
496    { CONF_BUMPMULT             , CONFTYPE_REAL     , read_real    , CNF_BUMPMULT             , validate_bumpmult },
497    { CONF_NETUSAGE             , CONFTYPE_INT      , read_int     , CNF_NETUSAGE             , validate_positive1 },
498    { CONF_INPARALLEL           , CONFTYPE_INT      , read_int     , CNF_INPARALLEL           , validate_inparallel },
499    { CONF_DUMPORDER            , CONFTYPE_STRING   , read_string  , CNF_DUMPORDER            , NULL },
500    { CONF_MAXDUMPS             , CONFTYPE_INT      , read_int     , CNF_MAXDUMPS             , validate_positive1 },
501    { CONF_ETIMEOUT             , CONFTYPE_INT      , read_int     , CNF_ETIMEOUT             , NULL },
502    { CONF_DTIMEOUT             , CONFTYPE_INT      , read_int     , CNF_DTIMEOUT             , validate_positive1 },
503    { CONF_CTIMEOUT             , CONFTYPE_INT      , read_int     , CNF_CTIMEOUT             , validate_positive1 },
504    { CONF_TAPEBUFS             , CONFTYPE_INT      , read_int     , CNF_TAPEBUFS             , validate_positive1 },
505    { CONF_RAWTAPEDEV           , CONFTYPE_STRING   , read_string  , CNF_RAWTAPEDEV           , NULL },
506    { CONF_COLUMNSPEC           , CONFTYPE_STRING   , read_string  , CNF_COLUMNSPEC           , NULL },
507    { CONF_TAPERALGO            , CONFTYPE_TAPERALGO, get_taperalgo, CNF_TAPERALGO            , NULL },
508    { CONF_DISPLAYUNIT          , CONFTYPE_STRING   , read_string  , CNF_DISPLAYUNIT          , validate_displayunit },
509    { CONF_AUTOFLUSH            , CONFTYPE_BOOL     , read_bool    , CNF_AUTOFLUSH            , NULL },
510    { CONF_RESERVE              , CONFTYPE_INT      , read_int     , CNF_RESERVE              , validate_reserve },
511    { CONF_MAXDUMPSIZE          , CONFTYPE_AM64     , read_am64    , CNF_MAXDUMPSIZE          , NULL },
512    { CONF_KRB5KEYTAB           , CONFTYPE_STRING   , read_string  , CNF_KRB5KEYTAB           , NULL },
513    { CONF_KRB5PRINCIPAL        , CONFTYPE_STRING   , read_string  , CNF_KRB5PRINCIPAL        , NULL },
514    { CONF_LABEL_NEW_TAPES      , CONFTYPE_STRING   , read_string  , CNF_LABEL_NEW_TAPES      , NULL },
515    { CONF_USETIMESTAMPS        , CONFTYPE_BOOL     , read_bool    , CNF_USETIMESTAMPS        , NULL },
516    { CONF_AMRECOVER_DO_FSF     , CONFTYPE_BOOL     , read_bool    , CNF_AMRECOVER_DO_FSF     , NULL },
517    { CONF_AMRECOVER_CHANGER    , CONFTYPE_STRING   , read_string  , CNF_AMRECOVER_CHANGER    , NULL },
518    { CONF_AMRECOVER_CHECK_LABEL, CONFTYPE_BOOL     , read_bool    , CNF_AMRECOVER_CHECK_LABEL, NULL },
519    { CONF_CONNECT_TRIES        , CONFTYPE_INT      , read_int     , CNF_CONNECT_TRIES        , validate_positive1 },
520    { CONF_REP_TRIES            , CONFTYPE_INT      , read_int     , CNF_REP_TRIES            , validate_positive1 },
521    { CONF_REQ_TRIES            , CONFTYPE_INT      , read_int     , CNF_REQ_TRIES            , validate_positive1 },
522    { CONF_DEBUG_AMANDAD        , CONFTYPE_INT      , read_int     , CNF_DEBUG_AMANDAD        , validate_debug },
523    { CONF_DEBUG_AMIDXTAPED     , CONFTYPE_INT      , read_int     , CNF_DEBUG_AMIDXTAPED     , validate_debug },
524    { CONF_DEBUG_AMINDEXD       , CONFTYPE_INT      , read_int     , CNF_DEBUG_AMINDEXD       , validate_debug },
525    { CONF_DEBUG_AMRECOVER      , CONFTYPE_INT      , read_int     , CNF_DEBUG_AMRECOVER      , validate_debug },
526    { CONF_DEBUG_AUTH           , CONFTYPE_INT      , read_int     , CNF_DEBUG_AUTH           , validate_debug },
527    { CONF_DEBUG_EVENT          , CONFTYPE_INT      , read_int     , CNF_DEBUG_EVENT          , validate_debug },
528    { CONF_DEBUG_HOLDING        , CONFTYPE_INT      , read_int     , CNF_DEBUG_HOLDING        , validate_debug },
529    { CONF_DEBUG_PROTOCOL       , CONFTYPE_INT      , read_int     , CNF_DEBUG_PROTOCOL       , validate_debug },
530    { CONF_DEBUG_PLANNER        , CONFTYPE_INT      , read_int     , CNF_DEBUG_PLANNER        , validate_debug },
531    { CONF_DEBUG_DRIVER         , CONFTYPE_INT      , read_int     , CNF_DEBUG_DRIVER         , validate_debug },
532    { CONF_DEBUG_DUMPER         , CONFTYPE_INT      , read_int     , CNF_DEBUG_DUMPER         , validate_debug },
533    { CONF_DEBUG_CHUNKER        , CONFTYPE_INT      , read_int     , CNF_DEBUG_CHUNKER        , validate_debug },
534    { CONF_DEBUG_TAPER          , CONFTYPE_INT      , read_int     , CNF_DEBUG_TAPER          , validate_debug },
535    { CONF_DEBUG_SELFCHECK      , CONFTYPE_INT      , read_int     , CNF_DEBUG_SELFCHECK      , validate_debug },
536    { CONF_DEBUG_SENDSIZE       , CONFTYPE_INT      , read_int     , CNF_DEBUG_SENDSIZE       , validate_debug },
537    { CONF_DEBUG_SENDBACKUP     , CONFTYPE_INT      , read_int     , CNF_DEBUG_SENDBACKUP     , validate_debug },
538    { CONF_RESERVED_UDP_PORT    , CONFTYPE_INTRANGE , read_intrange, CNF_RESERVED_UDP_PORT    , validate_reserved_port_range },
539    { CONF_RESERVED_TCP_PORT    , CONFTYPE_INTRANGE , read_intrange, CNF_RESERVED_TCP_PORT    , validate_reserved_port_range },
540    { CONF_UNRESERVED_TCP_PORT  , CONFTYPE_INTRANGE , read_intrange, CNF_UNRESERVED_TCP_PORT  , validate_unreserved_port_range },
541    { CONF_UNKNOWN              , CONFTYPE_INT      , NULL         , CNF_CNF                  , NULL }
542 };
543
544 t_conf_var tapetype_var [] = {
545    { CONF_COMMENT     , CONFTYPE_STRING, read_string, TAPETYPE_COMMENT      , NULL },
546    { CONF_LBL_TEMPL   , CONFTYPE_STRING, read_string, TAPETYPE_LBL_TEMPL    , NULL },
547    { CONF_BLOCKSIZE   , CONFTYPE_SIZE  , read_size  , TAPETYPE_BLOCKSIZE    , validate_blocksize },
548    { CONF_READBLOCKSIZE, CONFTYPE_SIZE  , read_size , TAPETYPE_READBLOCKSIZE, validate_blocksize },
549    { CONF_LENGTH      , CONFTYPE_AM64  , read_am64  , TAPETYPE_LENGTH       , validate_positive0 },
550    { CONF_FILEMARK    , CONFTYPE_AM64  , read_am64  , TAPETYPE_FILEMARK     , NULL },
551    { CONF_SPEED       , CONFTYPE_INT   , read_int   , TAPETYPE_SPEED        , validate_positive0 },
552    { CONF_FILE_PAD    , CONFTYPE_BOOL  , read_bool  , TAPETYPE_FILE_PAD     , NULL },
553    { CONF_UNKNOWN     , CONFTYPE_INT   , NULL       , TAPETYPE_TAPETYPE     , NULL }
554 };
555
556 t_conf_var dumptype_var [] = {
557    { CONF_COMMENT           , CONFTYPE_STRING   , read_string , DUMPTYPE_COMMENT           , NULL },
558    { CONF_AUTH              , CONFTYPE_STRING   , read_string , DUMPTYPE_SECURITY_DRIVER   , NULL },
559    { CONF_BUMPDAYS          , CONFTYPE_INT      , read_int    , DUMPTYPE_BUMPDAYS          , NULL },
560    { CONF_BUMPMULT          , CONFTYPE_REAL     , read_real   , DUMPTYPE_BUMPMULT          , NULL },
561    { CONF_BUMPSIZE          , CONFTYPE_AM64     , read_am64   , DUMPTYPE_BUMPSIZE          , NULL },
562    { CONF_BUMPPERCENT       , CONFTYPE_INT      , read_int    , DUMPTYPE_BUMPPERCENT       , NULL },
563    { CONF_COMPRATE          , CONFTYPE_REAL     , get_comprate, DUMPTYPE_COMPRATE          , NULL },
564    { CONF_COMPRESS          , CONFTYPE_INT      , get_compress, DUMPTYPE_COMPRESS          , NULL },
565    { CONF_ENCRYPT           , CONFTYPE_INT      , get_encrypt , DUMPTYPE_ENCRYPT           , NULL },
566    { CONF_DUMPCYCLE         , CONFTYPE_INT      , read_int    , DUMPTYPE_DUMPCYCLE         , validate_positive0 },
567    { CONF_EXCLUDE           , CONFTYPE_EXINCLUDE, get_exclude , DUMPTYPE_EXCLUDE           , NULL },
568    { CONF_INCLUDE           , CONFTYPE_EXINCLUDE, get_exclude , DUMPTYPE_INCLUDE           , NULL },
569    { CONF_IGNORE            , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_IGNORE            , NULL },
570    { CONF_HOLDING           , CONFTYPE_HOLDING  , get_holding , DUMPTYPE_HOLDINGDISK       , NULL },
571    { CONF_INDEX             , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_INDEX             , NULL },
572    { CONF_KENCRYPT          , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_KENCRYPT          , NULL },
573    { CONF_MAXDUMPS          , CONFTYPE_INT      , read_int    , DUMPTYPE_MAXDUMPS          , validate_positive1 },
574    { CONF_MAXPROMOTEDAY     , CONFTYPE_INT      , read_int    , DUMPTYPE_MAXPROMOTEDAY     , validate_positive0 },
575    { CONF_PRIORITY          , CONFTYPE_PRIORITY , get_priority, DUMPTYPE_PRIORITY          , NULL },
576    { CONF_PROGRAM           , CONFTYPE_STRING   , read_string , DUMPTYPE_PROGRAM           , NULL },
577    { CONF_RECORD            , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_RECORD            , NULL },
578    { CONF_SKIP_FULL         , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_SKIP_FULL         , NULL },
579    { CONF_SKIP_INCR         , CONFTYPE_BOOL     , read_bool   , DUMPTYPE_SKIP_INCR         , NULL },
580    { CONF_STARTTIME         , CONFTYPE_TIME     , read_time   , DUMPTYPE_STARTTIME         , NULL },
581    { CONF_STRATEGY          , CONFTYPE_INT      , get_strategy, DUMPTYPE_STRATEGY          , NULL },
582    { CONF_TAPE_SPLITSIZE    , CONFTYPE_AM64     , read_am64   , DUMPTYPE_TAPE_SPLITSIZE    , validate_positive0 },
583    { CONF_SPLIT_DISKBUFFER  , CONFTYPE_STRING   , read_string , DUMPTYPE_SPLIT_DISKBUFFER  , NULL },
584    { CONF_ESTIMATE          , CONFTYPE_INT      , get_estimate, DUMPTYPE_ESTIMATE          , NULL },
585    { CONF_SRV_ENCRYPT       , CONFTYPE_STRING   , read_string , DUMPTYPE_SRV_ENCRYPT       , NULL },
586    { CONF_CLNT_ENCRYPT      , CONFTYPE_STRING   , read_string , DUMPTYPE_CLNT_ENCRYPT      , NULL },
587    { CONF_AMANDAD_PATH      , CONFTYPE_STRING   , read_string , DUMPTYPE_AMANDAD_PATH      , NULL },
588    { CONF_CLIENT_USERNAME   , CONFTYPE_STRING   , read_string , DUMPTYPE_CLIENT_USERNAME   , NULL },
589    { CONF_SSH_KEYS          , CONFTYPE_STRING   , read_string , DUMPTYPE_SSH_KEYS          , NULL },
590    { CONF_SRVCOMPPROG       , CONFTYPE_STRING   , read_string , DUMPTYPE_SRVCOMPPROG       , NULL },
591    { CONF_CLNTCOMPPROG      , CONFTYPE_STRING   , read_string , DUMPTYPE_CLNTCOMPPROG      , NULL },
592    { CONF_FALLBACK_SPLITSIZE, CONFTYPE_AM64     , read_am64   , DUMPTYPE_FALLBACK_SPLITSIZE, NULL },
593    { CONF_SRV_DECRYPT_OPT   , CONFTYPE_STRING   , read_string , DUMPTYPE_SRV_DECRYPT_OPT   , NULL },
594    { CONF_CLNT_DECRYPT_OPT  , CONFTYPE_STRING   , read_string , DUMPTYPE_CLNT_DECRYPT_OPT  , NULL },
595    { CONF_UNKNOWN           , CONFTYPE_INT      , NULL        , DUMPTYPE_DUMPTYPE          , NULL }
596 };
597
598 t_conf_var holding_var [] = {
599    { CONF_DIRECTORY, CONFTYPE_STRING, read_string, HOLDING_DISKDIR  , NULL },
600    { CONF_COMMENT  , CONFTYPE_STRING, read_string, HOLDING_COMMENT  , NULL },
601    { CONF_USE      , CONFTYPE_AM64  , read_am64  , HOLDING_DISKSIZE , validate_use },
602    { CONF_CHUNKSIZE, CONFTYPE_AM64  , read_am64  , HOLDING_CHUNKSIZE, validate_chunksize },
603    { CONF_UNKNOWN  , CONFTYPE_INT   , NULL       , HOLDING_HOLDING  , NULL }
604 };
605
606 /*
607 ** ------------------------
608 **  External entry points
609 ** ------------------------
610 */
611
612 int
613 read_conffile(
614     char *filename)
615 {
616     interface_t *ip;
617
618     my_keytab = server_keytab;
619     my_var = server_var;
620     init_defaults();
621
622     /* We assume that conf_confname & conf are initialized to NULL above */
623     read_conffile_recursively(filename);
624
625     /* overwrite with command line option */
626     command_overwrite(program_options, my_var, my_keytab, conf_data,
627                       "");
628
629     if(got_parserror != -1 ) {
630         if(lookup_tapetype(conf_data[CNF_TAPETYPE].v.s) == NULL) {
631             char *save_confname = conf_confname;
632
633             conf_confname = filename;
634             if(!conf_data[CNF_TAPETYPE].seen)
635                 conf_parserror("default tapetype %s not defined", conf_data[CNF_TAPETYPE].v.s);
636             else {
637                 conf_line_num = conf_data[CNF_TAPETYPE].seen;
638                 conf_parserror("tapetype %s not defined", conf_data[CNF_TAPETYPE].v.s);
639             }
640             conf_confname = save_confname;
641         }
642     }
643
644     ip = alloc(SIZEOF(interface_t));
645     ip->name = stralloc("default");
646     ip->seen = conf_data[CNF_NETUSAGE].seen;
647     conf_init_string(&ip->value[INTER_COMMENT], "implicit from NETUSAGE");
648     conf_init_int(&ip->value[INTER_MAXUSAGE], conf_data[CNF_NETUSAGE].v.i);
649     ip->curusage = 0;
650     ip->next = interface_list;
651     interface_list = ip;
652
653     debug_amandad    = getconf_int(CNF_DEBUG_AMANDAD);
654     debug_amidxtaped = getconf_int(CNF_DEBUG_AMIDXTAPED);
655     debug_amindexd   = getconf_int(CNF_DEBUG_AMINDEXD);
656     debug_amrecover  = getconf_int(CNF_DEBUG_AMRECOVER);
657     debug_auth       = getconf_int(CNF_DEBUG_AUTH);
658     debug_event      = getconf_int(CNF_DEBUG_EVENT);
659     debug_holding    = getconf_int(CNF_DEBUG_HOLDING);
660     debug_protocol   = getconf_int(CNF_DEBUG_PROTOCOL);
661     debug_planner    = getconf_int(CNF_DEBUG_PLANNER);
662     debug_driver     = getconf_int(CNF_DEBUG_DRIVER);
663     debug_dumper     = getconf_int(CNF_DEBUG_DUMPER);
664     debug_chunker    = getconf_int(CNF_DEBUG_CHUNKER);
665     debug_taper      = getconf_int(CNF_DEBUG_TAPER);
666     debug_selfcheck  = getconf_int(CNF_DEBUG_SELFCHECK);
667     debug_sendsize   = getconf_int(CNF_DEBUG_SENDSIZE);
668     debug_sendbackup = getconf_int(CNF_DEBUG_SENDBACKUP);
669
670     return got_parserror;
671 }
672
673 static void
674 validate_positive0(
675     struct s_conf_var *np,
676     val_t        *val)
677 {
678     switch(val->type) {
679     case CONFTYPE_INT:
680         if(val->v.i < 0)
681             conf_parserror("%s must be positive", get_token_name(np->token));
682         break;
683     case CONFTYPE_LONG:
684         if(val->v.l < 0)
685             conf_parserror("%s must be positive", get_token_name(np->token));
686         break;
687     case CONFTYPE_AM64:
688         if(val->v.am64 < 0)
689             conf_parserror("%s must be positive", get_token_name(np->token));
690         break;
691     default:
692         conf_parserror("validate_positive0 invalid type %d\n", val->type);
693     }
694 }
695
696 static void
697 validate_positive1(
698     struct s_conf_var *np,
699     val_t        *val)
700 {
701     switch(val->type) {
702     case CONFTYPE_INT:
703         if(val->v.i < 1)
704             conf_parserror("%s must be positive", get_token_name(np->token));
705         break;
706     case CONFTYPE_LONG:
707         if(val->v.l < 1)
708             conf_parserror("%s must be positive", get_token_name(np->token));
709         break;
710     case CONFTYPE_AM64:
711         if(val->v.am64 < 1)
712             conf_parserror("%s must be positive", get_token_name(np->token));
713         break;
714     case CONFTYPE_TIME:
715         if(val->v.t < 1)
716             conf_parserror("%s must be positive", get_token_name(np->token));
717         break;
718     default:
719         conf_parserror("validate_positive1 invalid type %d\n", val->type);
720     }
721 }
722
723 static void
724 validate_runspercycle(
725     struct s_conf_var *np,
726     val_t        *val)
727 {
728     np = np;
729     if(val->v.i < -1)
730         conf_parserror("runspercycle must be >= -1");
731 }
732
733 static void
734 validate_bumppercent(
735     struct s_conf_var *np,
736     val_t        *val)
737 {
738     np = np;
739     if(val->v.i < 0 || val->v.i > 100)
740         conf_parserror("bumppercent must be between 0 and 100");
741 }
742
743 static void
744 validate_inparallel(
745     struct s_conf_var *np,
746     val_t        *val)
747 {
748     np = np;
749     if(val->v.i < 1 || val->v.i >MAX_DUMPERS)
750         conf_parserror("inparallel must be between 1 and MAX_DUMPERS (%d)",
751                        MAX_DUMPERS);
752 }
753
754 static void
755 validate_bumpmult(
756     struct s_conf_var *np,
757     val_t        *val)
758 {
759     np = np;
760     if(val->v.r < 0.999) {
761         conf_parserror("bumpmult must be positive");
762     }
763 }
764
765 static void
766 validate_displayunit(
767     struct s_conf_var *np,
768     val_t        *val)
769 {
770     np = np;
771     if(strcmp(val->v.s, "k") == 0 ||
772        strcmp(val->v.s, "K") == 0) {
773         val->v.s[0] = (char)toupper(val->v.s[0]);
774         unit_divisor=1;
775     }
776     else if(strcmp(val->v.s, "m") == 0 ||
777        strcmp(val->v.s, "M") == 0) {
778         val->v.s[0] = (char)toupper(val->v.s[0]);
779         unit_divisor=1024;
780     }
781     else if(strcmp(val->v.s, "g") == 0 ||
782        strcmp(val->v.s, "G") == 0) {
783         val->v.s[0] = (char)toupper(val->v.s[0]);
784         unit_divisor=1024*1024;
785     }
786     else if(strcmp(val->v.s, "t") == 0 ||
787        strcmp(val->v.s, "T") == 0) {
788         val->v.s[0] = (char)toupper(val->v.s[0]);
789         unit_divisor=1024*1024*1024;
790     }
791     else {
792         conf_parserror("displayunit must be k,m,g or t.");
793     }
794 }
795
796 static void
797 validate_reserve(
798     struct s_conf_var *np,
799     val_t        *val)
800 {
801     np = np;
802     if(val->v.i < 0 || val->v.i > 100)
803         conf_parserror("reserve must be between 0 and 100");
804 }
805
806 static void
807 validate_use(
808     struct s_conf_var *np,
809     val_t        *val)
810 {
811     np = np;
812     val->v.am64 = am_floor(val->v.am64, DISK_BLOCK_KB);
813 }
814
815 static void
816 validate_chunksize(
817     struct s_conf_var *np,
818     val_t        *val)
819 {
820     np = np;
821     if(val->v.am64 == 0) {
822         val->v.am64 = ((AM64_MAX / 1024) - (2 * DISK_BLOCK_KB));
823     }
824     else if(val->v.am64 < 0) {
825         conf_parserror("Negative chunksize (" OFF_T_FMT
826                        ") is no longer supported", val->v.am64);
827     }
828     val->v.am64 = am_floor(val->v.am64, (off_t)DISK_BLOCK_KB);
829     if (val->v.am64 < 2*DISK_BLOCK_KB) {
830         conf_parserror("chunksize must be at least %dkb", 2*DISK_BLOCK_KB);
831     }
832 }
833
834 static void
835 validate_blocksize(
836     struct s_conf_var *np,
837     val_t        *val)
838 {
839     np = np;
840     if(val->v.l < DISK_BLOCK_KB) {
841         conf_parserror("Tape blocksize must be at least %d KBytes",
842                   DISK_BLOCK_KB);
843     } else if(val->v.l > MAX_TAPE_BLOCK_KB) {
844         conf_parserror("Tape blocksize must not be larger than %d KBytes",
845                   MAX_TAPE_BLOCK_KB);
846     }
847 }
848
849 static void
850 validate_debug(
851     struct s_conf_var *np,
852     val_t        *val)
853 {
854     np = np;
855     if(val->v.i < 0 || val->v.i > 9) {
856         conf_parserror("Debug must be between 0 and 9");
857     }
858 }
859
860 static void
861 validate_reserved_port_range(
862     struct s_conf_var *np,
863     val_t        *val)
864 {
865     np = np;
866     if(val->v.intrange[0] < 1 || val->v.intrange[0] > IPPORT_RESERVED-1) {
867         conf_parserror("portrange must be between 1 and %d", IPPORT_RESERVED-1);
868     } else if(val->v.intrange[1] < 1 || val->v.intrange[1] > IPPORT_RESERVED-1) {
869         conf_parserror("portrange must be between 1 and IPPORT_RESERVED-1");
870     }
871 }
872
873 static void
874 validate_unreserved_port_range(
875     struct s_conf_var *np,
876     val_t        *val)
877 {
878     np = np;
879     if(val->v.intrange[0] < IPPORT_RESERVED+1 || val->v.intrange[0] > 65536) {
880         conf_parserror("portrange must be between %d and 65536", IPPORT_RESERVED+1);
881     } else if(val->v.intrange[1] < IPPORT_RESERVED+1 || val->v.intrange[1] > 65536) {
882         conf_parserror("portrange must be between %d and 65536", IPPORT_RESERVED+1);
883     }
884 }
885
886 char *
887 getconf_byname(
888     char *str)
889 {
890     static char *tmpstr;
891     t_conf_var *np;
892     keytab_t *kt;
893     char *s;
894     char ch;
895     char *first_delim;
896     char *second_delim;
897     tapetype_t *tp;
898     dumptype_t *dp;
899     interface_t *ip;
900     holdingdisk_t *hp;
901
902     tmpstr = stralloc(str);
903     s = tmpstr;
904     while((ch = *s++) != '\0') {
905         if(islower((int)ch))
906             s[-1] = (char)toupper(ch);
907     }
908
909     first_delim = strchr(tmpstr, ':');
910     if (first_delim) {
911         *first_delim = '\0';
912         first_delim++;
913         second_delim = strchr(first_delim,':');
914         if(!second_delim) {
915             amfree(tmpstr);
916             return(NULL);
917         }
918         *second_delim = '\0';
919         second_delim++;
920
921         for(kt = my_keytab; kt->token != CONF_UNKNOWN; kt++) {
922             if(kt->keyword && strcmp(kt->keyword, second_delim) == 0)
923                 break;
924         }
925
926         if(kt->token == CONF_UNKNOWN)
927             return NULL;
928
929         if (strcmp(tmpstr, "TAPETYPE") == 0) {
930             tp = lookup_tapetype(first_delim);
931             if (!tp) {
932                 amfree(tmpstr);
933                 return(NULL);
934             }
935             for(np = tapetype_var; np->token != CONF_UNKNOWN; np++) {
936                 if(np->token == kt->token)
937                    break;
938             }
939             if (np->token == CONF_UNKNOWN) return NULL;
940             tmpstr = stralloc(conf_print(&tp->value[np->parm], 0, ""));
941         } else if (strcmp(tmpstr, "DUMPTYPE") == 0) {
942             dp = lookup_dumptype(first_delim);
943             if (!dp) {
944                 amfree(tmpstr);
945                 return(NULL);
946             }
947             for(np = dumptype_var; np->token != CONF_UNKNOWN; np++) {
948                 if(np->token == kt->token)
949                    break;
950             }
951             if (np->token == CONF_UNKNOWN) return NULL;
952             tmpstr = stralloc(conf_print(&dp->value[np->parm], 0, ""));
953         } else if (strcmp(tmpstr, "HOLDINGDISK") == 0) {
954             hp = lookup_holdingdisk(first_delim);
955             if (!hp) {
956                 amfree(tmpstr);
957                 return(NULL);
958             }
959             for(np = holding_var; np->token != CONF_UNKNOWN; np++) {
960                 if(np->token == kt->token)
961                    break;
962             }
963             if (np->token == CONF_UNKNOWN) return NULL;
964             tmpstr = stralloc(conf_print(&hp->value[np->parm], 0, ""));
965         } else if (strcmp(tmpstr, "INTERFACE") == 0) {
966             ip = lookup_interface(first_delim);
967             if (!ip) {
968                 amfree(tmpstr);
969                 return(NULL);
970             }
971             for(np = holding_var; np->token != CONF_UNKNOWN; np++) {
972                 if(np->token == kt->token)
973                    break;
974             }
975             if (np->token == CONF_UNKNOWN) return NULL;
976             tmpstr = stralloc(conf_print(&ip->value[np->parm], 0, ""));
977         } else {
978             amfree(tmpstr);
979             return(NULL);
980         }
981     } else {
982         for(kt = my_keytab; kt->token != CONF_UNKNOWN; kt++) {
983             if(kt->keyword && strcmp(kt->keyword, tmpstr) == 0)
984                 break;
985         }
986
987         if(kt->token == CONF_UNKNOWN)
988             return NULL;
989
990         for(np = my_var; np->token != CONF_UNKNOWN; np++) {
991             if(np->token == kt->token)
992                 break;
993         }
994
995         if(np->token == CONF_UNKNOWN) return NULL;
996
997         tmpstr = stralloc(conf_print(&conf_data[np->parm], 0, ""));
998     }
999
1000     return tmpstr;
1001 }
1002
1003
1004 char *
1005 getconf_list(
1006     char *listname)
1007 {
1008     char *result = NULL;
1009     tapetype_t *tp;
1010     dumptype_t *dp;
1011     interface_t *ip;
1012     holdingdisk_t *hp;
1013
1014     if (strcasecmp(listname,"tapetype") == 0) {
1015         result = stralloc("");
1016         for(tp = tapelist; tp != NULL; tp=tp->next) {
1017             result = vstrextend(&result, tp->name, "\n", NULL);
1018         }
1019     } else if (strcasecmp(listname,"dumptype") == 0) {
1020         result = stralloc("");
1021         for(dp = dumplist; dp != NULL; dp=dp->next) {
1022             result = vstrextend(&result, dp->name, "\n", NULL);
1023         }
1024     } else if (strcasecmp(listname,"holdingdisk") == 0) {
1025         result = stralloc("");
1026         for(hp = holdingdisks; hp != NULL; hp=hp->next) {
1027             result = vstrextend(&result, hp->name, "\n", NULL);
1028         }
1029     } else if (strcasecmp(listname,"interface") == 0) {
1030         result = stralloc("");
1031         for(ip = interface_list; ip != NULL; ip=ip->next) {
1032             result = vstrextend(&result, ip->name, "\n", NULL);
1033         }
1034     }
1035     return result;
1036 }
1037
1038
1039 int
1040 getconf_seen(
1041     confparm_t parm)
1042 {
1043     return(conf_data[parm].seen);
1044 }
1045
1046 int
1047 getconf_boolean(
1048     confparm_t parm)
1049 {
1050     if (conf_data[parm].type != CONFTYPE_BOOL) {
1051         error("getconf_boolean: parm is not a CONFTYPE_BOOL");
1052         /*NOTREACHED*/
1053     }
1054     return(conf_data[parm].v.i != 0);
1055 }
1056
1057 int
1058 getconf_int(
1059     confparm_t parm)
1060 {
1061     if (conf_data[parm].type != CONFTYPE_INT) {
1062         error("getconf_int: parm is not a CONFTYPE_INT");
1063         /*NOTREACHED*/
1064     }
1065     return(conf_data[parm].v.i);
1066 }
1067
1068 long
1069 getconf_long(
1070     confparm_t parm)
1071 {
1072     if (conf_data[parm].type != CONFTYPE_LONG) {
1073         error("getconf_long: parm is not a CONFTYPE_LONG");
1074         /*NOTREACHED*/
1075     }
1076     return(conf_data[parm].v.l);
1077 }
1078
1079 time_t
1080 getconf_time(
1081     confparm_t parm)
1082 {
1083     if (conf_data[parm].type != CONFTYPE_TIME) {
1084         error("getconf_time: parm is not a CONFTYPE_TIME");
1085         /*NOTREACHED*/
1086     }
1087     return(conf_data[parm].v.t);
1088 }
1089
1090 ssize_t
1091 getconf_size(
1092     confparm_t parm)
1093 {
1094     if (conf_data[parm].type != CONFTYPE_SIZE) {
1095         error("getconf_size: parm is not a CONFTYPE_SIZE");
1096         /*NOTREACHED*/
1097     }
1098     return(conf_data[parm].v.size);
1099 }
1100
1101 off_t
1102 getconf_am64(
1103     confparm_t parm)
1104 {
1105     if (conf_data[parm].type != CONFTYPE_AM64) {
1106         error("getconf_am64: parm is not a CONFTYPE_AM64");
1107         /*NOTREACHED*/
1108     }
1109     return(conf_data[parm].v.am64);
1110 }
1111
1112 double
1113 getconf_real(
1114     confparm_t parm)
1115 {
1116     if (conf_data[parm].type != CONFTYPE_REAL) {
1117         error("getconf_real: parm is not a CONFTYPE_REAL");
1118         /*NOTREACHED*/
1119     }
1120     return(conf_data[parm].v.r);
1121 }
1122
1123 char *
1124 getconf_str(
1125     confparm_t parm)
1126 {
1127     if (conf_data[parm].type != CONFTYPE_STRING &&
1128         conf_data[parm].type != CONFTYPE_IDENT) {
1129         error("getconf_str: parm is not a CONFTYPE_STRING|CONFTYPE_IDENT: %d", parm);
1130         /*NOTREACHED*/
1131     }
1132     return(conf_data[parm].v.s);
1133 }
1134
1135 int
1136 getconf_taperalgo(
1137     confparm_t parm)
1138 {
1139     if (conf_data[parm].type != CONFTYPE_TAPERALGO) {
1140         error("getconf_taperalgo: parm is not a CONFTYPE_TAPERALGO");
1141         /*NOTREACHED*/
1142     }
1143     return(conf_data[parm].v.i);
1144 }
1145
1146 int*
1147 getconf_intrange(
1148     confparm_t parm)
1149 {
1150     if (conf_data[parm].type != CONFTYPE_INTRANGE) {
1151         error("getconf_intrange: parm is not a CONFTYPE_INTRANGE");
1152         /*NOTREACHED*/
1153     }
1154     return(conf_data[parm].v.intrange);
1155 }
1156
1157 holdingdisk_t *
1158 getconf_holdingdisks(
1159     void)
1160 {
1161     return holdingdisks;
1162 }
1163
1164 dumptype_t *
1165 lookup_dumptype(
1166     char *str)
1167 {
1168     dumptype_t *p;
1169
1170     for(p = dumplist; p != NULL; p = p->next) {
1171         if(strcasecmp(p->name, str) == 0) return p;
1172     }
1173     return NULL;
1174 }
1175
1176 tapetype_t *
1177 lookup_tapetype(
1178     char *str)
1179 {
1180     tapetype_t *p;
1181
1182     for(p = tapelist; p != NULL; p = p->next) {
1183         if(strcasecmp(p->name, str) == 0) return p;
1184     }
1185     return NULL;
1186 }
1187
1188 holdingdisk_t *
1189 lookup_holdingdisk(
1190     char *str)
1191 {
1192     holdingdisk_t *p;
1193
1194     for(p = holdingdisks; p != NULL; p = p->next) {
1195         if(strcasecmp(p->name, str) == 0) return p;
1196     }
1197     return NULL;
1198 }
1199
1200 interface_t *
1201 lookup_interface(
1202     char *str)
1203 {
1204 #ifndef __lint
1205     interface_t *p;
1206 #endif
1207
1208     if (str == NULL)
1209         return interface_list;
1210
1211 #ifndef __lint
1212     for (p = interface_list; p != NULL; p = p->next) {
1213         if (strcasecmp(p->name, str) == 0)
1214             return p;
1215     }
1216 #endif
1217     return NULL;
1218 }
1219
1220
1221 /*
1222 ** ------------------------
1223 **  Internal routines
1224 ** ------------------------
1225 */
1226
1227
1228 static void
1229 init_defaults(
1230     void)
1231 {
1232     char *s;
1233
1234     /* defaults for exported variables */
1235
1236 #ifdef DEFAULT_CONFIG
1237     s = DEFAULT_CONFIG;
1238 #else
1239     s = "YOUR ORG";
1240 #endif
1241 #ifdef DEFAULT_CONFIG
1242     s = DEFAULT_CONFIG;
1243 #else
1244     s = "";
1245 #endif
1246     conf_init_string(&conf_data[CNF_CONF], s);
1247 #ifdef DEFAULT_SERVER
1248     s = DEFAULT_SERVER;
1249 #else
1250     s = "";
1251 #endif
1252     conf_init_string(&conf_data[CNF_INDEX_SERVER], s);
1253
1254
1255 #ifdef DEFAULT_TAPE_SERVER
1256     s = DEFAULT_TAPE_SERVER;
1257 #else
1258 #ifdef DEFAULT_SERVER
1259     s = DEFAULT_SERVER;
1260 #else
1261     s = "";
1262 #endif
1263 #endif
1264     conf_init_string(&conf_data[CNF_TAPE_SERVER], s);
1265     conf_init_string(&conf_data[CNF_AUTH], "bsd");
1266     conf_init_string(&conf_data[CNF_SSH_KEYS], "");
1267     conf_init_string(&conf_data[CNF_AMANDAD_PATH], "");
1268     conf_init_string(&conf_data[CNF_CLIENT_USERNAME], "");
1269 #ifdef GNUTAR_LISTED_INCREMENTAL_DIR
1270     conf_init_string(&conf_data[CNF_GNUTAR_LIST_DIR],
1271                      GNUTAR_LISTED_INCREMENTAL_DIR);
1272 #else
1273     conf_init_string(&conf_data[CNF_GNUTAR_LIST_DIR], NULL);
1274 #endif
1275     conf_init_string(&conf_data[CNF_AMANDATES], AMANDATES_FILE);
1276     conf_init_string(&conf_data[CNF_KRB5KEYTAB], "/.amanda-v5-keytab");
1277     conf_init_string(&conf_data[CNF_KRB5PRINCIPAL], "service/amanda");
1278
1279     conf_init_string(&conf_data[CNF_ORG], s);
1280     conf_init_string(&conf_data[CNF_MAILTO], "operators");
1281     conf_init_string(&conf_data[CNF_DUMPUSER], CLIENT_LOGIN);
1282 #ifdef DEFAULT_TAPE_DEVICE
1283     s = DEFAULT_TAPE_DEVICE;
1284 #else
1285     s = NULL;
1286 #endif
1287     conf_init_string(&conf_data[CNF_TAPEDEV], s);
1288 #ifdef DEFAULT_CHANGER_DEVICE
1289     s = DEFAULT_CHANGER_DEVICE;
1290 #else
1291     s = "/dev/null";
1292 #endif
1293     conf_init_string(&conf_data[CNF_CHNGRDEV], s);
1294     conf_init_string(&conf_data[CNF_CHNGRFILE], "/usr/adm/amanda/changer-status");
1295 #ifdef DEFAULT_RAW_TAPE_DEVICE
1296     s = DEFAULT_RAW_TAPE_DEVICE;
1297 #else
1298     s = "/dev/rawft0";
1299 #endif
1300     conf_init_string   (&conf_data[CNF_LABELSTR]             , ".*");
1301     conf_init_string   (&conf_data[CNF_TAPELIST]             , "tapelist");
1302     conf_init_string   (&conf_data[CNF_DISKFILE]             , "disklist");
1303     conf_init_string   (&conf_data[CNF_INFOFILE]             , "/usr/adm/amanda/curinfo");
1304     conf_init_string   (&conf_data[CNF_LOGDIR]               , "/usr/adm/amanda");
1305     conf_init_string   (&conf_data[CNF_INDEXDIR]             , "/usr/adm/amanda/index");
1306     conf_init_ident    (&conf_data[CNF_TAPETYPE]             , "EXABYTE");
1307     conf_init_int      (&conf_data[CNF_DUMPCYCLE]            , 10);
1308     conf_init_int      (&conf_data[CNF_RUNSPERCYCLE]         , 0);
1309     conf_init_int      (&conf_data[CNF_TAPECYCLE]            , 15);
1310     conf_init_int      (&conf_data[CNF_NETUSAGE]             , 300);
1311     conf_init_int      (&conf_data[CNF_INPARALLEL]           , 10);
1312     conf_init_string   (&conf_data[CNF_DUMPORDER]            , "ttt");
1313     conf_init_int      (&conf_data[CNF_BUMPPERCENT]          , 0);
1314     conf_init_am64     (&conf_data[CNF_BUMPSIZE]             , (off_t)10*1024);
1315     conf_init_real     (&conf_data[CNF_BUMPMULT]             , 1.5);
1316     conf_init_int      (&conf_data[CNF_BUMPDAYS]             , 2);
1317     conf_init_string   (&conf_data[CNF_TPCHANGER]            , "");
1318     conf_init_int      (&conf_data[CNF_RUNTAPES]             , 1);
1319     conf_init_int      (&conf_data[CNF_MAXDUMPS]             , 1);
1320     conf_init_int      (&conf_data[CNF_ETIMEOUT]             , 300);
1321     conf_init_int      (&conf_data[CNF_DTIMEOUT]             , 1800);
1322     conf_init_int      (&conf_data[CNF_CTIMEOUT]             , 30);
1323     conf_init_int      (&conf_data[CNF_TAPEBUFS]             , 20);
1324     conf_init_string   (&conf_data[CNF_RAWTAPEDEV]           , s);
1325     conf_init_string   (&conf_data[CNF_PRINTER]              , "");
1326     conf_init_bool     (&conf_data[CNF_AUTOFLUSH]            , 0);
1327     conf_init_int      (&conf_data[CNF_RESERVE]              , 100);
1328     conf_init_am64     (&conf_data[CNF_MAXDUMPSIZE]          , (off_t)-1);
1329     conf_init_string   (&conf_data[CNF_COLUMNSPEC]           , "");
1330     conf_init_bool     (&conf_data[CNF_AMRECOVER_DO_FSF]     , 1);
1331     conf_init_string   (&conf_data[CNF_AMRECOVER_CHANGER]    , "");
1332     conf_init_bool     (&conf_data[CNF_AMRECOVER_CHECK_LABEL], 1);
1333     conf_init_taperalgo(&conf_data[CNF_TAPERALGO]            , 0);
1334     conf_init_string   (&conf_data[CNF_DISPLAYUNIT]          , "k");
1335     conf_init_string   (&conf_data[CNF_KRB5KEYTAB]           , "/.amanda-v5-keytab");
1336     conf_init_string   (&conf_data[CNF_KRB5PRINCIPAL]        , "service/amanda");
1337     conf_init_string   (&conf_data[CNF_LABEL_NEW_TAPES]      , "");
1338     conf_init_bool     (&conf_data[CNF_USETIMESTAMPS]        , 0);
1339     conf_init_int      (&conf_data[CNF_CONNECT_TRIES]        , 3);
1340     conf_init_int      (&conf_data[CNF_REP_TRIES]            , 5);
1341     conf_init_int      (&conf_data[CNF_REQ_TRIES]            , 3);
1342     conf_init_int      (&conf_data[CNF_DEBUG_AMANDAD]        , 0);
1343     conf_init_int      (&conf_data[CNF_DEBUG_AMIDXTAPED]     , 0);
1344     conf_init_int      (&conf_data[CNF_DEBUG_AMINDEXD]       , 0);
1345     conf_init_int      (&conf_data[CNF_DEBUG_AMRECOVER]      , 0);
1346     conf_init_int      (&conf_data[CNF_DEBUG_AUTH]           , 0);
1347     conf_init_int      (&conf_data[CNF_DEBUG_EVENT]          , 0);
1348     conf_init_int      (&conf_data[CNF_DEBUG_HOLDING]        , 0);
1349     conf_init_int      (&conf_data[CNF_DEBUG_PROTOCOL]       , 0);
1350     conf_init_int      (&conf_data[CNF_DEBUG_PLANNER]        , 0);
1351     conf_init_int      (&conf_data[CNF_DEBUG_DRIVER]         , 0);
1352     conf_init_int      (&conf_data[CNF_DEBUG_DUMPER]         , 0);
1353     conf_init_int      (&conf_data[CNF_DEBUG_CHUNKER]        , 0);
1354     conf_init_int      (&conf_data[CNF_DEBUG_TAPER]          , 0);
1355     conf_init_int      (&conf_data[CNF_DEBUG_SELFCHECK]      , 0);
1356     conf_init_int      (&conf_data[CNF_DEBUG_SENDSIZE]       , 0);
1357     conf_init_int      (&conf_data[CNF_DEBUG_SENDBACKUP]     , 0);
1358 #ifdef UDPPORTRANGE
1359     conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT]    , UDPPORTRANGE);
1360 #else
1361     conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT]    , 512, 1023);
1362 #endif
1363 #ifdef LOW_TCPPORTRANGE
1364     conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT]    , LOW_TCPPORTRANGE);
1365 #else
1366     conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT]    , 512, 1023);
1367 #endif
1368 #ifdef TCPPORTRANGE
1369     conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT]  , TCPPORTRANGE);
1370 #else
1371     conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT]  , 0, 0);
1372 #endif
1373
1374     /* defaults for internal variables */
1375
1376     conf_line_num = got_parserror = 0;
1377     allow_overwrites = 0;
1378     token_pushed = 0;
1379
1380     while(holdingdisks != NULL) {
1381         holdingdisk_t *hp;
1382
1383         hp = holdingdisks;
1384         holdingdisks = holdingdisks->next;
1385         amfree(hp);
1386     }
1387     num_holdingdisks = 0;
1388
1389     /* free any previously declared dump, tape and interface types */
1390
1391     while(dumplist != NULL) {
1392         dumptype_t *dp;
1393
1394         dp = dumplist;
1395         dumplist = dumplist->next;
1396         amfree(dp);
1397     }
1398     while(tapelist != NULL) {
1399         tapetype_t *tp;
1400
1401         tp = tapelist;
1402         tapelist = tapelist->next;
1403         amfree(tp);
1404     }
1405     while(interface_list != NULL) {
1406         interface_t *ip;
1407
1408         ip = interface_list;
1409         interface_list = interface_list->next;
1410         amfree(ip);
1411     }
1412
1413     /* create some predefined dumptypes for backwards compatability */
1414     init_dumptype_defaults();
1415     dpcur.name = stralloc("NO-COMPRESS");
1416     dpcur.seen = -1;
1417     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_NONE);
1418     save_dumptype();
1419
1420     init_dumptype_defaults();
1421     dpcur.name = stralloc("COMPRESS-FAST");
1422     dpcur.seen = -1;
1423     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_FAST);
1424     save_dumptype();
1425
1426     init_dumptype_defaults();
1427     dpcur.name = stralloc("COMPRESS-BEST");
1428     dpcur.seen = -1;
1429     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_BEST);
1430     save_dumptype();
1431
1432     init_dumptype_defaults();
1433     dpcur.name = stralloc("COMPRESS-CUST");
1434     dpcur.seen = -1;
1435     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_CUST);
1436     save_dumptype();
1437
1438     init_dumptype_defaults();
1439     dpcur.name = stralloc("SRVCOMPRESS");
1440     dpcur.seen = -1;
1441     conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_SERVER_FAST);
1442     save_dumptype();
1443
1444     init_dumptype_defaults();
1445     dpcur.name = stralloc("BSD-AUTH");
1446     dpcur.seen = -1;
1447     conf_set_string(&dpcur.value[DUMPTYPE_SECURITY_DRIVER], "BSD");
1448     save_dumptype();
1449
1450     init_dumptype_defaults();
1451     dpcur.name = stralloc("KRB4-AUTH");
1452     dpcur.seen = -1;
1453     conf_set_string(&dpcur.value[DUMPTYPE_SECURITY_DRIVER], "KRB4");
1454     save_dumptype();
1455
1456     init_dumptype_defaults();
1457     dpcur.name = stralloc("NO-RECORD");
1458     dpcur.seen = -1;
1459     conf_set_bool(&dpcur.value[DUMPTYPE_RECORD], 0);
1460     save_dumptype();
1461
1462     init_dumptype_defaults();
1463     dpcur.name = stralloc("NO-HOLD");
1464     dpcur.seen = -1;
1465     conf_set_holding(&dpcur.value[DUMPTYPE_HOLDINGDISK], HOLD_NEVER);
1466     save_dumptype();
1467
1468     init_dumptype_defaults();
1469     dpcur.name = stralloc("NO-FULL");
1470     dpcur.seen = -1;
1471     conf_set_strategy(&dpcur.value[DUMPTYPE_STRATEGY], DS_NOFULL);
1472     save_dumptype();
1473     conffile_init = 1;
1474 }
1475
1476 static void
1477 read_conffile_recursively(
1478     char *filename)
1479 {
1480     /* Save globals used in read_confline(), elsewhere. */
1481     int  save_line_num  = conf_line_num;
1482     FILE *save_conf     = conf_conf;
1483     char *save_confname = conf_confname;
1484     int rc;
1485
1486     if (*filename == '/' || config_dir == NULL) {
1487         conf_confname = stralloc(filename);
1488     } else {
1489         conf_confname = stralloc2(config_dir, filename);
1490     }
1491
1492     if((conf_conf = fopen(conf_confname, "r")) == NULL) {
1493         fprintf(stderr, "could not open conf file \"%s\": %s\n", conf_confname,
1494                 strerror(errno));
1495         amfree(conf_confname);
1496         got_parserror = -1;
1497         return;
1498     }
1499
1500     conf_line_num = 0;
1501
1502     /* read_confline() can invoke us recursively via "includefile" */
1503     do {
1504         rc = read_confline();
1505     } while (rc != 0);
1506     afclose(conf_conf);
1507
1508     amfree(conf_confname);
1509
1510     /* Restore servers */
1511     conf_line_num = save_line_num;
1512     conf_conf     = save_conf;
1513     conf_confname = save_confname;
1514 }
1515
1516
1517 /* ------------------------ */
1518
1519
1520 static int
1521 read_confline(
1522     void)
1523 {
1524     t_conf_var *np;
1525
1526     keytable = server_keytab;
1527
1528     conf_line_num += 1;
1529     get_conftoken(CONF_ANY);
1530     switch(tok) {
1531     case CONF_INCLUDEFILE:
1532         {
1533             char *fn;
1534             char *cname;
1535
1536             get_conftoken(CONF_STRING);
1537             fn = tokenval.v.s;
1538             if (*fn == '/' || config_dir == NULL) {
1539                 cname = stralloc(fn);
1540             } else {
1541                 cname = stralloc2(config_dir, fn);
1542             }
1543             if ( cname != NULL &&  (access(cname, R_OK) == 0)) {
1544                 read_conffile_recursively(cname);
1545                 amfree(cname);
1546             } else {
1547                 conf_parserror("cannot open %s: %s\n", fn, strerror(errno));
1548             }
1549             amfree(cname);
1550             
1551         }
1552         break;
1553
1554     case CONF_HOLDING:
1555         get_holdingdisk();
1556         break;
1557
1558     case CONF_DEFINE:
1559         get_conftoken(CONF_ANY);
1560         if(tok == CONF_DUMPTYPE) get_dumptype();
1561         else if(tok == CONF_TAPETYPE) get_tapetype();
1562         else if(tok == CONF_INTERFACE) get_interface();
1563         else conf_parserror("DUMPTYPE, INTERFACE or TAPETYPE expected");
1564         break;
1565
1566     case CONF_NL:       /* empty line */
1567         break;
1568
1569     case CONF_END:      /* end of file */
1570         return 0;
1571
1572     default:
1573         {
1574             for(np = server_var; np->token != CONF_UNKNOWN; np++) 
1575                 if(np->token == tok) break;
1576
1577             if(np->token == CONF_UNKNOWN) {
1578                 conf_parserror("configuration keyword expected");
1579             } else {
1580                 np->read_function(np, &conf_data[np->parm]);
1581                 if(np->validate)
1582                     np->validate(np, &conf_data[np->parm]);
1583             }
1584         }
1585     }
1586     if(tok != CONF_NL)
1587         get_conftoken(CONF_NL);
1588     return 1;
1589 }
1590
1591 static void
1592 get_holdingdisk(
1593     void)
1594 {
1595     char *prefix;
1596     int save_overwrites;
1597
1598     save_overwrites = allow_overwrites;
1599     allow_overwrites = 1;
1600
1601     init_holdingdisk_defaults();
1602
1603     get_conftoken(CONF_IDENT);
1604     hdcur.name = stralloc(tokenval.v.s);
1605     hdcur.seen = conf_line_num;
1606
1607     prefix = vstralloc( "HOLDINGDISK:", hdcur.name, ":", NULL);
1608     read_block(program_options, holding_var, server_keytab, hdcur.value, prefix,
1609                "holding disk parameter expected", 1, NULL);
1610     amfree(prefix);
1611     get_conftoken(CONF_NL);
1612
1613     hdcur.disksize = holdingdisk_get_disksize(&hdcur);
1614     save_holdingdisk();
1615
1616     allow_overwrites = save_overwrites;
1617 }
1618
1619 static void
1620 init_holdingdisk_defaults(
1621     void)
1622 {
1623     conf_init_string(&hdcur.value[HOLDING_COMMENT]  , "");
1624     conf_init_string(&hdcur.value[HOLDING_DISKDIR]  , "");
1625     conf_init_am64(&hdcur.value[HOLDING_DISKSIZE] , (off_t)0);
1626                     /* 1 Gb = 1M counted in 1Kb blocks */
1627     conf_init_am64(&hdcur.value[HOLDING_CHUNKSIZE], (off_t)1024*1024);
1628
1629     hdcur.up = (void *)0;
1630     hdcur.disksize = 0LL;
1631 }
1632
1633 static void
1634 save_holdingdisk(
1635     void)
1636 {
1637     holdingdisk_t *hp;
1638
1639     hp = alloc(sizeof(holdingdisk_t));
1640     *hp = hdcur;
1641     hp->next = holdingdisks;
1642     holdingdisks = hp;
1643
1644     num_holdingdisks++;
1645 }
1646
1647
1648 dumptype_t *
1649 read_dumptype(
1650     char *name,
1651     FILE *from,
1652     char *fname,
1653     int *linenum)
1654 {
1655     int save_overwrites;
1656     FILE *saved_conf = NULL;
1657     char *saved_fname = NULL;
1658     char *prefix;
1659
1660     if (from) {
1661         saved_conf = conf_conf;
1662         conf_conf = from;
1663     }
1664
1665     if (fname) {
1666         saved_fname = conf_confname;
1667         conf_confname = fname;
1668     }
1669
1670     if (linenum)
1671         conf_line_num = *linenum;
1672
1673     save_overwrites = allow_overwrites;
1674     allow_overwrites = 1;
1675
1676     init_dumptype_defaults();
1677     if (name) {
1678         dpcur.name = name;
1679     } else {
1680         get_conftoken(CONF_IDENT);
1681         dpcur.name = stralloc(tokenval.v.s);
1682     }
1683     dpcur.seen = conf_line_num;
1684
1685     prefix = vstralloc( "DUMPTYPE:", dpcur.name, ":", NULL);
1686     read_block(program_options, dumptype_var, server_keytab, dpcur.value,
1687                prefix, "dumptype parameter expected",
1688                (name == NULL), *copy_dumptype);
1689     amfree(prefix);
1690     if(!name)
1691         get_conftoken(CONF_NL);
1692
1693     /* XXX - there was a stupidity check in here for skip-incr and
1694     ** skip-full.  This check should probably be somewhere else. */
1695
1696     save_dumptype();
1697
1698     allow_overwrites = save_overwrites;
1699
1700     if (linenum)
1701         *linenum = conf_line_num;
1702
1703     if (fname)
1704         conf_confname = saved_fname;
1705
1706     if (from)
1707         conf_conf = saved_conf;
1708
1709     return lookup_dumptype(dpcur.name);
1710 }
1711
1712 static void
1713 get_dumptype(void)
1714 {
1715     read_dumptype(NULL, NULL, NULL, NULL);
1716 }
1717
1718 static void
1719 init_dumptype_defaults(void)
1720 {
1721     dpcur.name = NULL;
1722     conf_init_string   (&dpcur.value[DUMPTYPE_COMMENT]           , "");
1723     conf_init_string   (&dpcur.value[DUMPTYPE_PROGRAM]           , "DUMP");
1724     conf_init_string   (&dpcur.value[DUMPTYPE_SRVCOMPPROG]       , "");
1725     conf_init_string   (&dpcur.value[DUMPTYPE_CLNTCOMPPROG]      , "");
1726     conf_init_string   (&dpcur.value[DUMPTYPE_SRV_ENCRYPT]       , "");
1727     conf_init_string   (&dpcur.value[DUMPTYPE_CLNT_ENCRYPT]      , "");
1728     conf_init_string   (&dpcur.value[DUMPTYPE_AMANDAD_PATH]      , "X");
1729     conf_init_string   (&dpcur.value[DUMPTYPE_CLIENT_USERNAME]   , "X");
1730     conf_init_string   (&dpcur.value[DUMPTYPE_SSH_KEYS]          , "X");
1731     conf_init_string   (&dpcur.value[DUMPTYPE_SECURITY_DRIVER]   , "BSD");
1732     conf_init_exinclude(&dpcur.value[DUMPTYPE_EXCLUDE]);
1733     conf_init_exinclude(&dpcur.value[DUMPTYPE_INCLUDE]);
1734     conf_init_priority (&dpcur.value[DUMPTYPE_PRIORITY]          , 1);
1735     conf_init_int      (&dpcur.value[DUMPTYPE_DUMPCYCLE]         , conf_data[CNF_DUMPCYCLE].v.i);
1736     conf_init_int      (&dpcur.value[DUMPTYPE_MAXDUMPS]          , conf_data[CNF_MAXDUMPS].v.i);
1737     conf_init_int      (&dpcur.value[DUMPTYPE_MAXPROMOTEDAY]     , 10000);
1738     conf_init_int      (&dpcur.value[DUMPTYPE_BUMPPERCENT]       , conf_data[CNF_BUMPPERCENT].v.i);
1739     conf_init_am64     (&dpcur.value[DUMPTYPE_BUMPSIZE]          , conf_data[CNF_BUMPSIZE].v.am64);
1740     conf_init_int      (&dpcur.value[DUMPTYPE_BUMPDAYS]          , conf_data[CNF_BUMPDAYS].v.i);
1741     conf_init_real     (&dpcur.value[DUMPTYPE_BUMPMULT]          , conf_data[CNF_BUMPMULT].v.r);
1742     conf_init_time     (&dpcur.value[DUMPTYPE_STARTTIME]         , (time_t)0);
1743     conf_init_strategy (&dpcur.value[DUMPTYPE_STRATEGY]          , DS_STANDARD);
1744     conf_init_estimate (&dpcur.value[DUMPTYPE_ESTIMATE]          , ES_CLIENT);
1745     conf_init_compress (&dpcur.value[DUMPTYPE_COMPRESS]          , COMP_FAST);
1746     conf_init_encrypt  (&dpcur.value[DUMPTYPE_ENCRYPT]           , ENCRYPT_NONE);
1747     conf_init_string   (&dpcur.value[DUMPTYPE_SRV_DECRYPT_OPT]   , "-d");
1748     conf_init_string   (&dpcur.value[DUMPTYPE_CLNT_DECRYPT_OPT]  , "-d");
1749     conf_init_rate     (&dpcur.value[DUMPTYPE_COMPRATE]          , 0.50, 0.50);
1750     conf_init_am64     (&dpcur.value[DUMPTYPE_TAPE_SPLITSIZE]    , (off_t)0);
1751     conf_init_am64     (&dpcur.value[DUMPTYPE_FALLBACK_SPLITSIZE], (off_t)10 * 1024);
1752     conf_init_string   (&dpcur.value[DUMPTYPE_SPLIT_DISKBUFFER]  , NULL);
1753     conf_init_bool     (&dpcur.value[DUMPTYPE_RECORD]            , 1);
1754     conf_init_bool     (&dpcur.value[DUMPTYPE_SKIP_INCR]         , 0);
1755     conf_init_bool     (&dpcur.value[DUMPTYPE_SKIP_FULL]         , 0);
1756     conf_init_holding  (&dpcur.value[DUMPTYPE_HOLDINGDISK]       , HOLD_AUTO);
1757     conf_init_bool     (&dpcur.value[DUMPTYPE_KENCRYPT]          , 0);
1758     conf_init_bool     (&dpcur.value[DUMPTYPE_IGNORE]            , 0);
1759     conf_init_bool     (&dpcur.value[DUMPTYPE_INDEX]             , 1);
1760 }
1761
1762 static void
1763 save_dumptype(void)
1764 {
1765     dumptype_t *dp, *dp1;;
1766
1767     dp = lookup_dumptype(dpcur.name);
1768
1769     if(dp != (dumptype_t *)0) {
1770         conf_parserror("dumptype %s already defined on line %d", dp->name, dp->seen);
1771         return;
1772     }
1773
1774     dp = alloc(sizeof(dumptype_t));
1775     *dp = dpcur;
1776     dp->next = NULL;
1777     /* add at end of list */
1778     if(!dumplist)
1779         dumplist = dp;
1780     else {
1781         dp1 = dumplist;
1782         while (dp1->next != NULL) {
1783              dp1 = dp1->next;
1784         }
1785         dp1->next = dp;
1786     }
1787 }
1788
1789 static void
1790 copy_dumptype(void)
1791 {
1792     dumptype_t *dt;
1793     int i;
1794
1795     dt = lookup_dumptype(tokenval.v.s);
1796
1797     if(dt == NULL) {
1798         conf_parserror("dumptype parameter expected");
1799         return;
1800     }
1801
1802     for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
1803         if(dt->value[i].seen) {
1804             free_val_t(&dpcur.value[i]);
1805             copy_val_t(&dpcur.value[i], &dt->value[i]);
1806         }
1807     }
1808 }
1809
1810 static void
1811 get_tapetype(void)
1812 {
1813     int save_overwrites;
1814     char *prefix;
1815
1816     save_overwrites = allow_overwrites;
1817     allow_overwrites = 1;
1818
1819     init_tapetype_defaults();
1820
1821     get_conftoken(CONF_IDENT);
1822     tpcur.name = stralloc(tokenval.v.s);
1823     tpcur.seen = conf_line_num;
1824
1825     prefix = vstralloc( "TAPETYPE:", tpcur.name, ":", NULL);
1826     read_block(program_options, tapetype_var, server_keytab, tpcur.value,
1827                prefix, "tapetype parameter expected", 1, &copy_tapetype);
1828     amfree(prefix);
1829     get_conftoken(CONF_NL);
1830
1831     save_tapetype();
1832
1833     allow_overwrites = save_overwrites;
1834 }
1835
1836 static void
1837 init_tapetype_defaults(void)
1838 {
1839     conf_init_string(&tpcur.value[TAPETYPE_COMMENT]      , "");
1840     conf_init_string(&tpcur.value[TAPETYPE_LBL_TEMPL]    , "");
1841     conf_init_size  (&tpcur.value[TAPETYPE_BLOCKSIZE]    , DISK_BLOCK_KB);
1842     conf_init_size  (&tpcur.value[TAPETYPE_READBLOCKSIZE], MAX_TAPE_BLOCK_KB);
1843     conf_init_am64  (&tpcur.value[TAPETYPE_LENGTH]       , (off_t)2000);
1844     conf_init_am64  (&tpcur.value[TAPETYPE_FILEMARK]     , (off_t)1);
1845     conf_init_int   (&tpcur.value[TAPETYPE_SPEED]        , 200);
1846     conf_init_bool  (&tpcur.value[TAPETYPE_FILE_PAD]     , 1);
1847 }
1848
1849 static void
1850 save_tapetype(void)
1851 {
1852     tapetype_t *tp, *tp1;
1853
1854     tp = lookup_tapetype(tpcur.name);
1855
1856     if(tp != (tapetype_t *)0) {
1857         amfree(tpcur.name);
1858         conf_parserror("tapetype %s already defined on line %d", tp->name, tp->seen);
1859         return;
1860     }
1861
1862     tp = alloc(sizeof(tapetype_t));
1863     *tp = tpcur;
1864     /* add at end of list */
1865     if(!tapelist)
1866         tapelist = tp;
1867     else {
1868         tp1 = tapelist;
1869         while (tp1->next != NULL) {
1870             tp1 = tp1->next;
1871         }
1872         tp1->next = tp;
1873     }
1874 }
1875
1876 static void
1877 copy_tapetype(void)
1878 {
1879     tapetype_t *tp;
1880     int i;
1881
1882     tp = lookup_tapetype(tokenval.v.s);
1883
1884     if(tp == NULL) {
1885         conf_parserror("tape type parameter expected");
1886         return;
1887     }
1888
1889     for(i=0; i < TAPETYPE_TAPETYPE; i++) {
1890         if(tp->value[i].seen) {
1891             free_val_t(&tpcur.value[i]);
1892             copy_val_t(&tpcur.value[i], &tp->value[i]);
1893         }
1894     }
1895 }
1896
1897 t_conf_var interface_var [] = {
1898    { CONF_COMMENT, CONFTYPE_STRING, read_string, INTER_COMMENT , NULL },
1899    { CONF_USE    , CONFTYPE_INT   , read_int   , INTER_MAXUSAGE, validate_positive1 },
1900    { CONF_UNKNOWN, CONFTYPE_INT   , NULL       , INTER_INTER   , NULL }
1901 };
1902
1903 static void
1904 get_interface(void)
1905 {
1906     int save_overwrites;
1907     char *prefix;
1908
1909     save_overwrites = allow_overwrites;
1910     allow_overwrites = 1;
1911
1912     init_interface_defaults();
1913
1914     get_conftoken(CONF_IDENT);
1915     ifcur.name = stralloc(tokenval.v.s);
1916     ifcur.seen = conf_line_num;
1917
1918     prefix = vstralloc( "INTERFACE:", ifcur.name, ":", NULL);
1919     read_block(program_options, interface_var, server_keytab, ifcur.value,
1920                prefix, "interface parameter expected", 1, &copy_interface);
1921     amfree(prefix);
1922     get_conftoken(CONF_NL);
1923
1924     save_interface();
1925
1926     allow_overwrites = save_overwrites;
1927
1928     return;
1929 }
1930
1931 static void
1932 init_interface_defaults(void)
1933 {
1934     conf_init_string(&ifcur.value[INTER_COMMENT] , "");
1935     conf_init_int   (&ifcur.value[INTER_MAXUSAGE], 300);
1936
1937     ifcur.curusage = 0;
1938 }
1939
1940 static void
1941 save_interface(void)
1942 {
1943     interface_t *ip, *ip1;
1944
1945     ip = lookup_interface(ifcur.name);
1946
1947     if(ip != (interface_t *)0) {
1948         conf_parserror("interface %s already defined on line %d", ip->name,
1949                        ip->seen);
1950         return;
1951     }
1952
1953     ip = alloc(sizeof(interface_t));
1954     *ip = ifcur;
1955     /* add at end of list */
1956     if(!interface_list) {
1957         interface_list = ip;
1958     } else {
1959         ip1 = interface_list;
1960         while (ip1->next != NULL) {
1961             ip1 = ip1->next;
1962         }
1963         ip1->next = ip;
1964     }
1965 }
1966
1967 static void
1968 copy_interface(void)
1969 {
1970 /*
1971     int i;
1972     t_xxx *np;
1973     keytab_t *kt;
1974     
1975     val_t val;
1976 */
1977     interface_t *ip;
1978     int i;
1979
1980     ip = lookup_interface(tokenval.v.s);
1981
1982     if(ip == NULL) {
1983         conf_parserror("interface parameter expected");
1984         return;
1985     }
1986
1987     for(i=0; i < INTER_INTER; i++) {
1988         if(ip->value[i].seen) {
1989             free_val_t(&ifcur.value[i]);
1990             copy_val_t(&ifcur.value[i], &ip->value[i]);
1991         }
1992     }
1993 }
1994
1995 static void
1996 get_comprate(
1997     t_conf_var *np,
1998     val_t *val)
1999 {
2000     np = np;
2001     get_conftoken(CONF_REAL);
2002     val->v.rate[0] = tokenval.v.r;
2003     val->v.rate[1] = tokenval.v.r;
2004     val->seen = tokenval.seen;
2005     if(tokenval.v.r < 0) {
2006         conf_parserror("full compression rate must be >= 0");
2007     }
2008
2009     get_conftoken(CONF_ANY);
2010     switch(tok) {
2011     case CONF_NL:
2012         return;
2013
2014     case CONF_END:
2015         return;
2016
2017     case CONF_COMMA:
2018         break;
2019
2020     default:
2021         unget_conftoken();
2022     }
2023
2024     get_conftoken(CONF_REAL);
2025     val->v.rate[1] = tokenval.v.r;
2026     if(tokenval.v.r < 0) {
2027         conf_parserror("incremental compression rate must be >= 0");
2028     }
2029 }
2030
2031 static void
2032 read_intrange(
2033     t_conf_var *np,
2034     val_t *val)
2035 {
2036     np = np;
2037     get_conftoken(CONF_INT);
2038     val->v.intrange[0] = tokenval.v.i;
2039     val->v.intrange[1] = tokenval.v.i;
2040     val->seen = tokenval.seen;
2041
2042     get_conftoken(CONF_ANY);
2043     switch(tok) {
2044     case CONF_NL:
2045         return;
2046
2047     case CONF_END:
2048         return;
2049
2050     case CONF_COMMA:
2051         break;
2052
2053     default:
2054         unget_conftoken();
2055     }
2056
2057     get_conftoken(CONF_INT);
2058     val->v.intrange[1] = tokenval.v.i;
2059 }
2060
2061 static void
2062 get_compress(
2063     t_conf_var *np,
2064     val_t *val)
2065 {
2066     int serv, clie, none, fast, best, custom;
2067     int done;
2068     comp_t comp;
2069
2070     np = np;
2071     ckseen(&val->seen);
2072
2073     serv = clie = none = fast = best = custom  = 0;
2074
2075     done = 0;
2076     do {
2077         get_conftoken(CONF_ANY);
2078         switch(tok) {
2079         case CONF_NONE:   none = 1; break;
2080         case CONF_FAST:   fast = 1; break;
2081         case CONF_BEST:   best = 1; break;
2082         case CONF_CLIENT: clie = 1; break;
2083         case CONF_SERVER: serv = 1; break;
2084         case CONF_CUSTOM: custom=1; break;
2085         case CONF_NL:     done = 1; break;
2086         case CONF_END:    done = 1; break;
2087         default:
2088             done = 1;
2089             serv = clie = 1; /* force an error */
2090         }
2091     } while(!done);
2092
2093     if(serv + clie == 0) clie = 1;      /* default to client */
2094     if(none + fast + best + custom  == 0) fast = 1; /* default to fast */
2095
2096     comp = -1;
2097
2098     if(!serv && clie) {
2099         if(none && !fast && !best && !custom) comp = COMP_NONE;
2100         if(!none && fast && !best && !custom) comp = COMP_FAST;
2101         if(!none && !fast && best && !custom) comp = COMP_BEST;
2102         if(!none && !fast && !best && custom) comp = COMP_CUST;
2103     }
2104
2105     if(serv && !clie) {
2106         if(none && !fast && !best && !custom) comp = COMP_NONE;
2107         if(!none && fast && !best && !custom) comp = COMP_SERVER_FAST;
2108         if(!none && !fast && best && !custom) comp = COMP_SERVER_BEST;
2109         if(!none && !fast && !best && custom) comp = COMP_SERVER_CUST;
2110     }
2111
2112     if((int)comp == -1) {
2113         conf_parserror("NONE, CLIENT FAST, CLIENT BEST, CLIENT CUSTOM, SERVER FAST, SERVER BEST or SERVER CUSTOM expected");
2114         comp = COMP_NONE;
2115     }
2116
2117     val->v.i = (int)comp;
2118 }
2119
2120 static void
2121 get_encrypt(
2122     t_conf_var *np,
2123     val_t *val)
2124 {
2125    encrypt_t encrypt;
2126
2127    np = np;
2128    ckseen(&val->seen);
2129
2130    get_conftoken(CONF_ANY);
2131    switch(tok) {
2132    case CONF_NONE:  
2133      encrypt = ENCRYPT_NONE; 
2134      break;
2135
2136    case CONF_CLIENT:  
2137      encrypt = ENCRYPT_CUST;
2138      break;
2139
2140    case CONF_SERVER: 
2141      encrypt = ENCRYPT_SERV_CUST;
2142      break;
2143
2144    default:
2145      conf_parserror("NONE, CLIENT or SERVER expected");
2146      encrypt = ENCRYPT_NONE;
2147      break;
2148    }
2149
2150    val->v.i = (int)encrypt;
2151 }
2152
2153 static void
2154 get_holding(
2155     t_conf_var *np,
2156     val_t *val)
2157 {
2158    dump_holdingdisk_t holding;
2159
2160    np = np;
2161    ckseen(&val->seen);
2162
2163    get_conftoken(CONF_ANY);
2164    switch(tok) {
2165    case CONF_NEVER:  
2166      holding = HOLD_NEVER; 
2167      break;
2168
2169    case CONF_AUTO:  
2170      holding = HOLD_AUTO;
2171      break;
2172
2173    case CONF_REQUIRED: 
2174      holding = HOLD_REQUIRED;
2175      break;
2176
2177    default: /* can be a BOOLEAN */
2178      unget_conftoken();
2179      holding =  (dump_holdingdisk_t)get_bool();
2180      if (holding == 0)
2181         holding = HOLD_NEVER;
2182      else if (holding == 1 || holding == 2)
2183         holding = HOLD_AUTO;
2184      else
2185         conf_parserror("NEVER, AUTO or REQUIRED expected");
2186      break;
2187    }
2188
2189    val->v.i = (int)holding;
2190 }
2191
2192 static void
2193 get_taperalgo(
2194     t_conf_var *np,
2195     val_t *val)
2196 {
2197     np = np;
2198     ckseen(&val->seen);
2199
2200     get_conftoken(CONF_ANY);
2201     switch(tok) {
2202     case CONF_FIRST:      val->v.i = ALGO_FIRST;      break;
2203     case CONF_FIRSTFIT:   val->v.i = ALGO_FIRSTFIT;   break;
2204     case CONF_LARGEST:    val->v.i = ALGO_LARGEST;    break;
2205     case CONF_LARGESTFIT: val->v.i = ALGO_LARGESTFIT; break;
2206     case CONF_SMALLEST:   val->v.i = ALGO_SMALLEST;   break;
2207     case CONF_LAST:       val->v.i = ALGO_LAST;       break;
2208     default:
2209         conf_parserror("FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST or LAST expected");
2210     }
2211 }
2212
2213 static void
2214 get_priority(
2215     t_conf_var *np,
2216     val_t *val)
2217 {
2218     int pri;
2219
2220     np = np;
2221     ckseen(&val->seen);
2222
2223     get_conftoken(CONF_ANY);
2224     switch(tok) {
2225     case CONF_LOW: pri = 0; break;
2226     case CONF_MEDIUM: pri = 1; break;
2227     case CONF_HIGH: pri = 2; break;
2228     case CONF_INT: pri = tokenval.v.i; break;
2229     default:
2230         conf_parserror("LOW, MEDIUM, HIGH or integer expected");
2231         pri = 0;
2232     }
2233     val->v.i = pri;
2234 }
2235
2236 static void
2237 get_strategy(
2238     t_conf_var *np,
2239     val_t *val)
2240 {
2241     int strat;
2242
2243     np = np;
2244     ckseen(&val->seen);
2245
2246     get_conftoken(CONF_ANY);
2247     switch(tok) {
2248     case CONF_SKIP:
2249         strat = DS_SKIP;
2250         break;
2251     case CONF_STANDARD:
2252         strat = DS_STANDARD;
2253         break;
2254     case CONF_NOFULL:
2255         strat = DS_NOFULL;
2256         break;
2257     case CONF_NOINC:
2258         strat = DS_NOINC;
2259         break;
2260     case CONF_HANOI:
2261         strat = DS_HANOI;
2262         break;
2263     case CONF_INCRONLY:
2264         strat = DS_INCRONLY;
2265         break;
2266     default:
2267         conf_parserror("STANDARD or NOFULL expected");
2268         strat = DS_STANDARD;
2269     }
2270     val->v.i = strat;
2271 }
2272
2273 static void
2274 get_estimate(
2275     t_conf_var *np,
2276     val_t *val)
2277 {
2278     int estime;
2279
2280     np = np;
2281     ckseen(&val->seen);
2282
2283     get_conftoken(CONF_ANY);
2284     switch(tok) {
2285     case CONF_CLIENT:
2286         estime = ES_CLIENT;
2287         break;
2288     case CONF_SERVER:
2289         estime = ES_SERVER;
2290         break;
2291     case CONF_CALCSIZE:
2292         estime = ES_CALCSIZE;
2293         break;
2294     default:
2295         conf_parserror("CLIENT, SERVER or CALCSIZE expected");
2296         estime = ES_CLIENT;
2297     }
2298     val->v.i = estime;
2299 }
2300
2301 static void
2302 get_exclude(
2303     t_conf_var *np,
2304     val_t *val)
2305 {
2306     int file, got_one = 0;
2307     sl_t *exclude;
2308     int optional = 0;
2309
2310     np = np;
2311     get_conftoken(CONF_ANY);
2312     if(tok == CONF_LIST) {
2313         file = 0;
2314         get_conftoken(CONF_ANY);
2315         exclude = val->v.exinclude.sl_list;
2316     }
2317     else {
2318         file = 1;
2319         if(tok == CONF_EFILE) get_conftoken(CONF_ANY);
2320         exclude = val->v.exinclude.sl_file;
2321     }
2322     ckseen(&val->seen);
2323
2324     if(tok == CONF_OPTIONAL) {
2325         get_conftoken(CONF_ANY);
2326         optional = 1;
2327     }
2328
2329     if(tok == CONF_APPEND) {
2330         get_conftoken(CONF_ANY);
2331     }
2332     else {
2333         free_sl(exclude);
2334         exclude = NULL;
2335     }
2336
2337     while(tok == CONF_STRING) {
2338         exclude = append_sl(exclude, tokenval.v.s);
2339         got_one = 1;
2340         get_conftoken(CONF_ANY);
2341     }
2342     unget_conftoken();
2343
2344     if(got_one == 0) { free_sl(exclude); exclude = NULL; }
2345
2346     if (file == 0)
2347         val->v.exinclude.sl_list = exclude;
2348     else
2349         val->v.exinclude.sl_file = exclude;
2350     val->v.exinclude.optional = optional;
2351 }
2352
2353 /*
2354 static void get_include(np, val)
2355     t_conf_var *np;
2356     val_t *val;
2357 {
2358     int list, got_one = 0;
2359     sl_t *include;
2360     int optional = 0;
2361     int append = 0;
2362
2363     get_conftoken(CONF_ANY);
2364     if(tok == CONF_LIST) {
2365         list = 1;
2366         include = dpcur.value[DUMPTYPE_INCLUDE_LIST].v.sl;
2367         ckseen(&dpcur.value[DUMPTYPE_INCLUDE_LIST].seen);
2368         get_conftoken(CONF_ANY);
2369     }
2370     else {
2371         list = 0;
2372         include = dpcur.value[DUMPTYPE_INCLUDE_FILE].v.sl;
2373         ckseen(&dpcur.value[DUMPTYPE_INCLUDE_FILE].seen);
2374         if(tok == CONF_EFILE) get_conftoken(CONF_ANY);
2375     }
2376
2377     if(tok == CONF_OPTIONAL) {
2378         get_conftoken(CONF_ANY);
2379         optional = 1;
2380     }
2381
2382     if(tok == CONF_APPEND) {
2383         get_conftoken(CONF_ANY);
2384         append = 1;
2385     }
2386     else {
2387         free_sl(include);
2388         include = NULL;
2389         append = 0;
2390     }
2391
2392     while(tok == CONF_STRING) {
2393         include = append_sl(include, tokenval.v.s);
2394         got_one = 1;
2395         get_conftoken(CONF_ANY);
2396     }
2397     unget_conftoken();
2398
2399     if(got_one == 0) { free_sl(include); include = NULL; }
2400
2401     if(list == 0)
2402         dpcur.value[DUMPTYPE_INCLUDE_FILE].v.sl = include;
2403     else {
2404         dpcur.value[DUMPTYPE_INCLUDE_LIST].v.sl = include;
2405         if(!append || optional)
2406             dpcur.value[DUMPTYPE_INCLUDE_OPTIONAL].v.i = optional;
2407     }
2408 }
2409 */
2410
2411 /* ------------------------ */
2412
2413 int
2414 ColumnDataCount(void )
2415 {
2416     return (int)(SIZEOF(ColumnData) / SIZEOF(ColumnData[0]));
2417 }
2418
2419 /* conversion from string to table index
2420  */
2421 int
2422 StringToColumn(
2423     char *s)
2424 {
2425     int cn;
2426
2427     for (cn=0; ColumnData[cn].Name != NULL; cn++) {
2428         if (strcasecmp(s, ColumnData[cn].Name) == 0) {
2429             break;
2430         }
2431     }
2432     return cn;
2433 }
2434
2435 char
2436 LastChar(
2437     char *s)
2438 {
2439     return s[strlen(s)-1];
2440 }
2441
2442 int
2443 SetColumDataFromString(
2444     ColumnInfo* ci,
2445     char *s,
2446     char **errstr)
2447 {
2448 #ifdef TEST
2449     char *myname= "SetColumDataFromString";
2450 #endif
2451     ci = ci;
2452
2453     /* Convert from a Columspec string to our internal format
2454      * of columspec. The purpose is to provide this string
2455      * as configuration paramter in the amanda.conf file or
2456      * (maybe) as environment variable.
2457      * 
2458      * This text should go as comment into the sample amanda.conf
2459      *
2460      * The format for such a ColumnSpec string s is a ',' seperated
2461      * list of triples. Each triple consists of
2462      *   -the name of the column (as in ColumnData.Name)
2463      *   -prefix before the column
2464      *   -the width of the column
2465      *       if set to -1 it will be recalculated
2466      *   to the maximum length of a line to print.
2467      * Example:
2468      *  "Disk=1:17,HostName=1:10,OutKB=1:7"
2469      * or
2470      *  "Disk=1:-1,HostName=1:10,OutKB=1:7"
2471      *  
2472      * You need only specify those colums that should be changed from
2473      * the default. If nothing is specified in the configfile, the
2474      * above compiled in values will be in effect, resulting in an
2475      * output as it was all the time.
2476      *                                                  ElB, 1999-02-24.
2477      */
2478
2479     while (s && *s) {
2480         int Space, Width;
2481         int cn;
2482         char *eon= strchr(s, '=');
2483
2484         if (eon == NULL) {
2485             *errstr = stralloc2("invalid columnspec: ", s);
2486 #ifdef TEST
2487             fprintf(stderr, "%s: %s\n", myname, *errstr);
2488 #endif
2489             return -1;
2490         }
2491         *eon= '\0';
2492         cn=StringToColumn(s);
2493         if (ColumnData[cn].Name == NULL) {
2494             *errstr = stralloc2("invalid column name: ", s);
2495 #ifdef TEST
2496             fprintf(stderr, "%s: %s\n", myname, *errstr);
2497 #endif
2498             return -1;
2499         }
2500         if (sscanf(eon+1, "%d:%d", &Space, &Width) != 2) {
2501             *errstr = stralloc2("invalid format: ", eon + 1);
2502 #ifdef TEST
2503             fprintf(stderr, "%s: %s\n", myname, *errstr);
2504 #endif
2505             return -1;
2506         }
2507         ColumnData[cn].Width= Width;
2508         ColumnData[cn].PrefixSpace = Space;
2509         if (LastChar(ColumnData[cn].Format) == 's') {
2510             if (Width < 0)
2511                 ColumnData[cn].MaxWidth= 1;
2512             else
2513                 if (Width > ColumnData[cn].Precision)
2514                     ColumnData[cn].Precision= Width;
2515         }
2516         else if (Width < ColumnData[cn].Precision)
2517             ColumnData[cn].Precision = Width;
2518         s= strchr(eon+1, ',');
2519         if (s != NULL)
2520             s++;
2521     }
2522     return 0;
2523 }
2524
2525
2526 long int
2527 getconf_unit_divisor(void)
2528 {
2529     return unit_divisor;
2530 }
2531
2532 /* ------------------------ */
2533
2534
2535 void
2536 dump_configuration(
2537     char *filename)
2538 {
2539     tapetype_t *tp;
2540     dumptype_t *dp;
2541     interface_t *ip;
2542     holdingdisk_t *hp;
2543     int i;
2544     t_conf_var *np;
2545     keytab_t *kt;
2546     char *prefix;
2547     char kt_prefix[100];
2548
2549     printf("AMANDA CONFIGURATION FROM FILE \"%s\":\n\n", filename);
2550
2551     for(np=server_var; np->token != CONF_UNKNOWN; np++) {
2552         for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) 
2553             if (np->token == kt->token) break;
2554
2555         if(kt->token == CONF_UNKNOWN)
2556             error("server bad token");
2557
2558         if (kt->token != CONF_IDENT)
2559             snprintf(kt_prefix, 100, "%-21s ", kt->keyword);
2560             printf("%s\n",
2561                    conf_print(&conf_data[np->parm], 1, kt_prefix));
2562     }
2563
2564     for(hp = holdingdisks; hp != NULL; hp = hp->next) {
2565         printf("\nHOLDINGDISK %s {\n", hp->name);
2566         for(i=0; i < HOLDING_HOLDING; i++) {
2567             for(np=holding_var; np->token != CONF_UNKNOWN; np++) {
2568                 if(np->parm == i)
2569                         break;
2570             }
2571             if(np->token == CONF_UNKNOWN)
2572                 error("holding bad value");
2573
2574             for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) {
2575                 if(kt->token == np->token)
2576                     break;
2577             }
2578             if(kt->token == CONF_UNKNOWN)
2579                 error("holding bad token");
2580
2581             snprintf(kt_prefix, 100, "      %-9s ", kt->keyword);
2582             printf("%s\n", conf_print(&hp->value[i], 1, kt_prefix));
2583         }
2584         printf("}\n");
2585     }
2586
2587     for(tp = tapelist; tp != NULL; tp = tp->next) {
2588         printf("\nDEFINE TAPETYPE %s {\n", tp->name);
2589         for(i=0; i < TAPETYPE_TAPETYPE; i++) {
2590             for(np=tapetype_var; np->token != CONF_UNKNOWN; np++)
2591                 if(np->parm == i) break;
2592             if(np->token == CONF_UNKNOWN)
2593                 error("tapetype bad value");
2594
2595             for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
2596                 if(kt->token == np->token) break;
2597             if(kt->token == CONF_UNKNOWN)
2598                 error("tapetype bad token");
2599
2600             snprintf(kt_prefix, 100, "      %-9s ", kt->keyword);
2601             printf("%s\n", conf_print(&tp->value[i], 1, kt_prefix));
2602         }
2603         printf("}\n");
2604     }
2605
2606     for(dp = dumplist; dp != NULL; dp = dp->next) {
2607         if (strncmp(dp->name, "custom(", 7) != 0) {
2608             if(dp->seen == -1)
2609                 prefix = "#";
2610             else
2611                 prefix = "";
2612             printf("\n%sDEFINE DUMPTYPE %s {\n", prefix, dp->name);
2613             for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
2614                 for(np=dumptype_var; np->token != CONF_UNKNOWN; np++)
2615                     if(np->parm == i) break;
2616                 if(np->token == CONF_UNKNOWN)
2617                     error("dumptype bad value");
2618
2619                 for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
2620                     if(kt->token == np->token) break;
2621                 if(kt->token == CONF_UNKNOWN)
2622                     error("dumptype bad token");
2623
2624                 snprintf(kt_prefix, 100, "%s      %-19s ", prefix,kt->keyword);
2625                 printf("%s\n", conf_print(&dp->value[i], 1, kt_prefix));
2626             }
2627             printf("%s}\n", prefix);
2628         }
2629     }
2630
2631     for(ip = interface_list; ip != NULL; ip = ip->next) {
2632         if(strcmp(ip->name,"default") == 0)
2633             prefix = "#";
2634         else
2635             prefix = "";
2636         printf("\n%sDEFINE INTERFACE %s {\n", prefix, ip->name);
2637         for(i=0; i < INTER_INTER; i++) {
2638             for(np=interface_var; np->token != CONF_UNKNOWN; np++)
2639                 if(np->parm == i) break;
2640             if(np->token == CONF_UNKNOWN)
2641                 error("interface bad value");
2642
2643             for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
2644                 if(kt->token == np->token) break;
2645             if(kt->token == CONF_UNKNOWN)
2646                 error("interface bad token");
2647
2648             snprintf(kt_prefix, 100, "%s      %-19s ", prefix, kt->keyword);
2649             printf("%s\n", conf_print(&ip->value[i], 1, kt_prefix));
2650         }
2651         printf("%s}\n",prefix);
2652     }
2653
2654 }
2655
2656 char *
2657 generic_get_security_conf(
2658         char *string,
2659         void *arg)
2660 {
2661         arg = arg;
2662         if(!string || !*string)
2663                 return(NULL);
2664
2665         if(strcmp(string, "krb5principal")==0) {
2666                 return(getconf_str(CNF_KRB5PRINCIPAL));
2667         } else if(strcmp(string, "krb5keytab")==0) {
2668                 return(getconf_str(CNF_KRB5KEYTAB));
2669         }
2670         return(NULL);
2671 }
2672
2673 char *
2674 get_token_name(
2675     tok_t token)
2676 {
2677     keytab_t *kt;
2678
2679     if (my_keytab == NULL) {
2680         error("my_keytab == NULL");
2681         /*NOTREACHED*/
2682     }
2683
2684     for(kt = my_keytab; kt->token != CONF_UNKNOWN; kt++)
2685         if(kt->token == token) break;
2686
2687     if(kt->token == CONF_UNKNOWN)
2688         return("");
2689     return(kt->keyword);
2690 }
2691
2692 void
2693 parse_conf(
2694     int parse_argc,
2695     char **parse_argv,
2696     int *new_argc,
2697     char ***new_argv)
2698 {
2699     int i;
2700     char **my_argv;
2701     char *myarg, *value;
2702     command_option_t *program_option;
2703
2704     program_options = alloc((size_t)(parse_argc+1) * SIZEOF(*program_options));
2705     program_options_size = parse_argc+1;
2706     program_option = program_options;
2707     program_option->name = NULL;
2708
2709     my_argv = alloc((size_t)parse_argc * SIZEOF(char *));
2710     *new_argv = my_argv;
2711     *new_argc = 0;
2712     i=0;
2713     while(i<parse_argc) {
2714         if(strncmp(parse_argv[i],"-o",2) == 0) {
2715             if(strlen(parse_argv[i]) > 2)
2716                 myarg = &parse_argv[i][2];
2717             else {
2718                 i++;
2719                 if(i >= parse_argc)
2720                     error("expect something after -o");
2721                 myarg = parse_argv[i];
2722             }
2723             value = index(myarg,'=');
2724             if (value == NULL) {
2725                 conf_parserror("Must specify a value for %s.\n", myarg);
2726             } else {
2727                 *value = '\0';
2728                 value++;
2729                 program_option->used = 0;
2730                 program_option->name = stralloc(myarg);
2731                 program_option->value = stralloc(value);
2732                 program_option++;
2733                 program_option->name = NULL;
2734             }
2735         }
2736         else {
2737             my_argv[*new_argc] = stralloc(parse_argv[i]);
2738             *new_argc += 1;
2739         }
2740         i++;
2741     }
2742 }
2743
2744 char **
2745 get_config_options(
2746     int first)
2747 {
2748     char             **config_options;
2749     char             **config_option;
2750     command_option_t  *command_options;
2751
2752     config_options = alloc((first+program_options_size+1)*SIZEOF(char *));
2753     for(command_options = program_options,
2754         config_option = config_options + first;
2755         command_options->name != NULL; command_options++) {
2756         *config_option = vstralloc("-o", command_options->name, "=",
2757                                    command_options->value, NULL);
2758         config_option++;
2759     }
2760     *config_option = NULL;
2761     return(config_options);
2762 }
2763
2764 void
2765 report_bad_conf_arg(void)
2766 {
2767     command_option_t *command_option;
2768
2769     for(command_option = program_options; command_option->name != NULL;
2770                                                         command_option++) {
2771         if(command_option->used == 0) {
2772             fprintf(stderr,"argument -o%s=%s not used\n",
2773                     command_option->name, command_option->value);
2774         }
2775     }
2776 }
2777
2778 void
2779 free_server_config(void)
2780 {
2781     holdingdisk_t    *hp, *hpnext;
2782     dumptype_t       *dp, *dpnext;
2783     tapetype_t       *tp, *tpnext;
2784     interface_t      *ip, *ipnext;
2785     command_option_t *server_option;
2786     int               i;
2787
2788     for(hp=holdingdisks; hp != NULL; hp = hpnext) {
2789         amfree(hp->name);
2790         for(i=0; i<HOLDING_HOLDING-1; i++) {
2791            free_val_t(&hp->value[i]);
2792         }
2793         hpnext = hp->next;
2794         amfree(hp);
2795     }
2796
2797     for(dp=dumplist; dp != NULL; dp = dpnext) {
2798         amfree(dp->name);
2799         for(i=0; i<DUMPTYPE_DUMPTYPE-1; i++) {
2800            free_val_t(&dp->value[i]);
2801         }
2802         dpnext = dp->next;
2803         amfree(dp);
2804     }
2805
2806     for(tp=tapelist; tp != NULL; tp = tpnext) {
2807         amfree(tp->name);
2808         for(i=0; i<TAPETYPE_TAPETYPE-1; i++) {
2809            free_val_t(&tp->value[i]);
2810         }
2811         tpnext = tp->next;
2812         amfree(tp);
2813     }
2814
2815     for(ip=interface_list; ip != NULL; ip = ipnext) {
2816         amfree(ip->name);
2817         for(i=0; i<INTER_INTER-1; i++) {
2818            free_val_t(&ip->value[i]);
2819         }
2820         ipnext = ip->next;
2821         amfree(ip);
2822     }
2823
2824     if(program_options) {
2825         for(server_option = program_options; server_option->name != NULL;
2826                                                 server_option++) {
2827             amfree(server_option->name);
2828             amfree(server_option->value);
2829         }
2830         amfree(program_options);
2831     }
2832
2833     for(i=0; i<CNF_CNF-1; i++)
2834         free_val_t(&conf_data[i]);
2835 }
2836
2837
2838
2839 /* configuration parameters */
2840 static char *cln_config_dir = NULL;
2841
2842 /* predeclare local functions */
2843
2844 static void read_client_conffile_recursively(char *filename);
2845 static int read_client_confline(void);
2846
2847 static int first_file = 1;
2848
2849 /*
2850 ** ------------------------
2851 **  External entry points
2852 ** ------------------------
2853 */
2854
2855 /* return  0 on success        */
2856 /* return  1 on error          */
2857 /* return -1 if file not found */
2858
2859 int read_clientconf(
2860     char *filename)
2861 {
2862     my_keytab = server_keytab;
2863     my_var = client_var;
2864
2865     if(first_file == 1) {
2866         init_defaults();
2867         first_file = 0;
2868     } else {
2869         allow_overwrites = 1;
2870     }
2871
2872     /* We assume that conf_confname & conf are initialized to NULL above */
2873     read_client_conffile_recursively(filename);
2874
2875     command_overwrite(program_options, client_var, client_keytab, conf_data,
2876                       "");
2877
2878     debug_amandad    = getconf_int(CNF_DEBUG_AMANDAD);
2879     debug_amidxtaped = getconf_int(CNF_DEBUG_AMIDXTAPED);
2880     debug_amindexd   = getconf_int(CNF_DEBUG_AMINDEXD);
2881     debug_amrecover  = getconf_int(CNF_DEBUG_AMRECOVER);
2882     debug_auth       = getconf_int(CNF_DEBUG_AUTH);
2883     debug_event      = getconf_int(CNF_DEBUG_EVENT);
2884     debug_holding    = getconf_int(CNF_DEBUG_HOLDING);
2885     debug_protocol   = getconf_int(CNF_DEBUG_PROTOCOL);
2886     debug_planner    = getconf_int(CNF_DEBUG_PLANNER);
2887     debug_driver     = getconf_int(CNF_DEBUG_DRIVER);
2888     debug_dumper     = getconf_int(CNF_DEBUG_DUMPER);
2889     debug_chunker    = getconf_int(CNF_DEBUG_CHUNKER);
2890     debug_taper      = getconf_int(CNF_DEBUG_TAPER);
2891     debug_selfcheck  = getconf_int(CNF_DEBUG_SELFCHECK);
2892     debug_sendsize   = getconf_int(CNF_DEBUG_SENDSIZE);
2893     debug_sendbackup = getconf_int(CNF_DEBUG_SENDBACKUP);
2894
2895     return got_parserror;
2896 }
2897
2898
2899 /*
2900 ** ------------------------
2901 **  Internal routines
2902 ** ------------------------
2903 */
2904
2905
2906 static void
2907 read_client_conffile_recursively(
2908     char *      filename)
2909 {
2910     /* Save globals used in read_client_confline(), elsewhere. */
2911     int  save_line_num  = conf_line_num;
2912     FILE *save_conf     = conf_conf;
2913     char *save_confname = conf_confname;
2914     int rc;
2915
2916     if (*filename == '/' || cln_config_dir == NULL) {
2917         conf_confname = stralloc(filename);
2918     } else {
2919         conf_confname = stralloc2(cln_config_dir, filename);
2920     }
2921
2922     if((conf_conf = fopen(conf_confname, "r")) == NULL) {
2923         dbprintf(("Could not open conf file \"%s\": %s\n", conf_confname,
2924                   strerror(errno)));
2925         amfree(conf_confname);
2926         got_parserror = -1;
2927         return;
2928     }
2929     dbprintf(("Reading conf file \"%s\".\n", conf_confname));
2930
2931     conf_line_num = 0;
2932
2933     /* read_client_confline() can invoke us recursively via "includefile" */
2934     do {
2935         rc = read_client_confline();
2936     } while (rc != 0);
2937     afclose(conf_conf);
2938
2939     amfree(conf_confname);
2940
2941     /* Restore globals */
2942     conf_line_num = save_line_num;
2943     conf_conf     = save_conf;
2944     conf_confname = save_confname;
2945 }
2946
2947
2948 /* ------------------------ */
2949
2950
2951 static int
2952 read_client_confline(void)
2953 {
2954     t_conf_var *np;
2955
2956     keytable = client_keytab;
2957
2958     conf_line_num += 1;
2959     get_conftoken(CONF_ANY);
2960     switch(tok) {
2961     case CONF_INCLUDEFILE:
2962         {
2963             char *fn;
2964
2965             get_conftoken(CONF_STRING);
2966             fn = tokenval.v.s;
2967             read_client_conffile_recursively(fn);
2968         }
2969         break;
2970
2971     case CONF_NL:       /* empty line */
2972         break;
2973
2974     case CONF_END:      /* end of file */
2975         return 0;
2976
2977     default:
2978         {
2979             for(np = client_var; np->token != CONF_UNKNOWN; np++)
2980                 if(np->token == tok) break;
2981
2982             if(np->token == CONF_UNKNOWN) {
2983                 conf_parserror("configuration keyword expected");
2984             } else {
2985                 np->read_function(np, &conf_data[np->parm]);
2986                 if(np->validate)
2987                     np->validate(np, &conf_data[np->parm]);
2988             }
2989         }
2990     }
2991     if(tok != CONF_NL)
2992         get_conftoken(CONF_NL);
2993     return 1;
2994 }
2995
2996
2997 char *
2998 generic_client_get_security_conf(
2999     char *      string,
3000     void *      arg)
3001 {
3002         (void)arg;      /* Quiet unused parameter warning */
3003
3004         if(!string || !*string)
3005                 return(NULL);
3006
3007         if(strcmp(string, "conf")==0) {
3008                 return(getconf_str(CNF_CONF));
3009         } else if(strcmp(string, "index_server")==0) {
3010                 return(getconf_str(CNF_INDEX_SERVER));
3011         } else if(strcmp(string, "tape_server")==0) {
3012                 return(getconf_str(CNF_TAPE_SERVER));
3013         } else if(strcmp(string, "tapedev")==0) {
3014                 return(getconf_str(CNF_TAPEDEV));
3015         } else if(strcmp(string, "auth")==0) {
3016                 return(getconf_str(CNF_AUTH));
3017         } else if(strcmp(string, "ssh_keys")==0) {
3018                 return(getconf_str(CNF_SSH_KEYS));
3019         } else if(strcmp(string, "amandad_path")==0) {
3020                 return(getconf_str(CNF_AMANDAD_PATH));
3021         } else if(strcmp(string, "client_username")==0) {
3022                 return(getconf_str(CNF_CLIENT_USERNAME));
3023         } else if(strcmp(string, "gnutar_list_dir")==0) {
3024                 return(getconf_str(CNF_GNUTAR_LIST_DIR));
3025         } else if(strcmp(string, "amandates")==0) {
3026                 return(getconf_str(CNF_AMANDATES));
3027         } else if(strcmp(string, "krb5principal")==0) {
3028                 return(getconf_str(CNF_KRB5PRINCIPAL));
3029         } else if(strcmp(string, "krb5keytab")==0) {
3030                 return(getconf_str(CNF_KRB5KEYTAB));
3031         }
3032         return(NULL);
3033 }
3034
3035
3036 /* return  0 on success             */
3037 /* return -1 if it is already there */
3038 /* return -2 if other failure       */
3039 int
3040 add_client_conf(
3041     confparm_t parm,
3042     char *value)
3043 {
3044     t_conf_var *np;
3045     keytab_t *kt;
3046     command_option_t *command_option;
3047     int nb_option;
3048
3049     for(np = client_var; np->token != CONF_UNKNOWN; np++)
3050         if(np->parm == (int)parm) break;
3051
3052     if(np->token == CONF_UNKNOWN) return -2;
3053
3054     for(kt = client_keytab; kt->token != CONF_UNKNOWN; kt++)
3055         if(kt->token == np->token) break;
3056
3057     if(kt->token == CONF_UNKNOWN) return -2;
3058
3059     /* Try to find it */
3060     nb_option = 0;
3061     for(command_option = program_options; command_option->name != NULL;
3062                                                         command_option++) {
3063         nb_option++;
3064     }
3065
3066     /* Increase size of program_options if needed */
3067     if(nb_option >= program_options_size-1) {
3068         program_options_size *= 2;
3069         program_options = realloc(program_options,
3070                                 program_options_size * SIZEOF(*program_options));
3071         if (program_options == NULL) {
3072             error("Can't realloc program_options: %s\n", strerror(errno));
3073             /*NOTREACHED*/
3074         }
3075         for(command_option = program_options; command_option->name != NULL;
3076                                                         command_option++) {
3077         }
3078     }
3079
3080     /* add it */
3081     command_option->used = 0;
3082     command_option->name = stralloc(kt->keyword);
3083     command_option->value = stralloc(value);
3084     command_option++;
3085     command_option->name = NULL;
3086     return 0;
3087 }
3088
3089 /*
3090 static t_conf_var *
3091 get_np(
3092     t_conf_var  *get_var,
3093     int         parm)
3094 {
3095     t_conf_var *np;
3096
3097     for(np = get_var; np->token != CONF_UNKNOWN; np++) {
3098         if(np->parm == parm)
3099             break;
3100     }
3101
3102     if(np->token == CONF_UNKNOWN) {
3103         error("error [unknown get_np parm: %d]", parm);
3104         NOTREACHED
3105     }
3106     return np;
3107 }
3108 */
3109
3110 static time_t
3111 get_time(void)
3112 {
3113     time_t hhmm;
3114
3115     get_conftoken(CONF_ANY);
3116     switch(tok) {
3117     case CONF_INT:
3118 #if SIZEOF_TIME_T < SIZEOF_INT
3119         if ((off_t)tokenval.v.i >= (off_t)TIME_MAX)
3120             conf_parserror("value too large");
3121 #endif
3122         hhmm = (time_t)tokenval.v.i;
3123         break;
3124
3125     case CONF_LONG:
3126 #if SIZEOF_TIME_T < SIZEOF_LONG
3127         if ((off_t)tokenval.v.l >= (off_t)TIME_MAX)
3128             conf_parserror("value too large");
3129 #endif
3130         hhmm = (time_t)tokenval.v.l;
3131         break;
3132
3133     case CONF_SIZE:
3134 #if SIZEOF_TIME_T < SIZEOF_SSIZE_T
3135         if ((off_t)tokenval.v.size >= (off_t)TIME_MAX)
3136             conf_parserror("value too large");
3137 #endif
3138         hhmm = (time_t)tokenval.v.size;
3139         break;
3140
3141     case CONF_AM64:
3142 #if SIZEOF_TIME_T < SIZEOF_LONG_LONG
3143         if ((off_t)tokenval.v.am64 >= (off_t)TIME_MAX)
3144             conf_parserror("value too large");
3145 #endif
3146         hhmm = (time_t)tokenval.v.am64;
3147         break;
3148
3149     case CONF_AMINFINITY:
3150         hhmm = TIME_MAX;
3151         break;
3152
3153     default:
3154         conf_parserror("a time is expected");
3155         hhmm = 0;
3156         break;
3157     }
3158     return hhmm;
3159 }
3160
3161 keytab_t numb_keytable[] = {
3162     { "B", CONF_MULT1 },
3163     { "BPS", CONF_MULT1 },
3164     { "BYTE", CONF_MULT1 },
3165     { "BYTES", CONF_MULT1 },
3166     { "DAY", CONF_MULT1 },
3167     { "DAYS", CONF_MULT1 },
3168     { "INF", CONF_AMINFINITY },
3169     { "K", CONF_MULT1K },
3170     { "KB", CONF_MULT1K },
3171     { "KBPS", CONF_MULT1K },
3172     { "KBYTE", CONF_MULT1K },
3173     { "KBYTES", CONF_MULT1K },
3174     { "KILOBYTE", CONF_MULT1K },
3175     { "KILOBYTES", CONF_MULT1K },
3176     { "KPS", CONF_MULT1K },
3177     { "M", CONF_MULT1M },
3178     { "MB", CONF_MULT1M },
3179     { "MBPS", CONF_MULT1M },
3180     { "MBYTE", CONF_MULT1M },
3181     { "MBYTES", CONF_MULT1M },
3182     { "MEG", CONF_MULT1M },
3183     { "MEGABYTE", CONF_MULT1M },
3184     { "MEGABYTES", CONF_MULT1M },
3185     { "G", CONF_MULT1G },
3186     { "GB", CONF_MULT1G },
3187     { "GBPS", CONF_MULT1G },
3188     { "GBYTE", CONF_MULT1G },
3189     { "GBYTES", CONF_MULT1G },
3190     { "GIG", CONF_MULT1G },
3191     { "GIGABYTE", CONF_MULT1G },
3192     { "GIGABYTES", CONF_MULT1G },
3193     { "MPS", CONF_MULT1M },
3194     { "TAPE", CONF_MULT1 },
3195     { "TAPES", CONF_MULT1 },
3196     { "WEEK", CONF_MULT7 },
3197     { "WEEKS", CONF_MULT7 },
3198     { NULL, CONF_IDENT }
3199 };
3200
3201 static int
3202 get_int(void)
3203 {
3204     int val;
3205     keytab_t *save_kt;
3206
3207     save_kt = keytable;
3208     keytable = numb_keytable;
3209
3210     get_conftoken(CONF_ANY);
3211     switch(tok) {
3212     case CONF_INT:
3213         val = tokenval.v.i;
3214         break;
3215
3216     case CONF_LONG:
3217 #if SIZEOF_INT < SIZEOF_LONG
3218         if ((off_t)tokenval.v.l > (off_t)INT_MAX)
3219             conf_parserror("value too large");
3220         if ((off_t)tokenval.v.l < (off_t)INT_MIN)
3221             conf_parserror("value too small");
3222 #endif
3223         val = (int)tokenval.v.l;
3224         break;
3225
3226     case CONF_SIZE:
3227 #if SIZEOF_INT < SIZEOF_SSIZE_T
3228         if ((off_t)tokenval.v.size > (off_t)INT_MAX)
3229             conf_parserror("value too large");
3230         if ((off_t)tokenval.v.size < (off_t)INT_MIN)
3231             conf_parserror("value too small");
3232 #endif
3233         val = (int)tokenval.v.size;
3234         break;
3235
3236     case CONF_AM64:
3237 #if SIZEOF_INT < SIZEOF_LONG_LONG
3238         if (tokenval.v.am64 > (off_t)INT_MAX)
3239             conf_parserror("value too large");
3240         if (tokenval.v.am64 < (off_t)INT_MIN)
3241             conf_parserror("value too small");
3242 #endif
3243         val = (int)tokenval.v.am64;
3244         break;
3245
3246     case CONF_AMINFINITY:
3247         val = INT_MAX;
3248         break;
3249
3250     default:
3251         conf_parserror("an integer is expected");
3252         val = 0;
3253         break;
3254     }
3255
3256     /* get multiplier, if any */
3257     get_conftoken(CONF_ANY);
3258     switch(tok) {
3259     case CONF_NL:                       /* multiply by one */
3260     case CONF_END:
3261     case CONF_MULT1:
3262     case CONF_MULT1K:
3263         break;
3264
3265     case CONF_MULT7:
3266         if (val > (INT_MAX / 7))
3267             conf_parserror("value too large");
3268         if (val < (INT_MIN / 7))
3269             conf_parserror("value too small");
3270         val *= 7;
3271         break;
3272
3273     case CONF_MULT1M:
3274         if (val > (INT_MAX / 1024))
3275             conf_parserror("value too large");
3276         if (val < (INT_MIN / 1024))
3277             conf_parserror("value too small");
3278         val *= 1024;
3279         break;
3280
3281     case CONF_MULT1G:
3282         if (val > (INT_MAX / (1024 * 1024)))
3283             conf_parserror("value too large");
3284         if (val < (INT_MIN / (1024 * 1024)))
3285             conf_parserror("value too small");
3286         val *= 1024 * 1024;
3287         break;
3288
3289     default:    /* it was not a multiplier */
3290         unget_conftoken();
3291         break;
3292     }
3293
3294     keytable = save_kt;
3295     return val;
3296 }
3297
3298 /*
3299 static long
3300 get_long(void)
3301 {
3302     long val;
3303     keytab_t *save_kt;
3304
3305     save_kt = keytable;
3306     keytable = numb_keytable;
3307
3308     get_conftoken(CONF_ANY);
3309
3310     switch(tok) {
3311     case CONF_LONG:
3312         val = tokenval.v.l;
3313         break;
3314
3315     case CONF_INT:
3316 #if SIZEOF_LONG < SIZEOF_INT
3317         if ((off_t)tokenval.v.i > (off_t)LONG_MAX)
3318             conf_parserror("value too large");
3319         if ((off_t)tokenval.v.i < (off_t)LONG_MIN)
3320             conf_parserror("value too small");
3321 #endif
3322         val = (long)tokenval.v.i;
3323         break;
3324
3325     case CONF_SIZE:
3326 #if SIZEOF_LONG < SIZEOF_SSIZE_T
3327         if ((off_t)tokenval.v.size > (off_t)LONG_MAX)
3328             conf_parserror("value too large");
3329         if ((off_t)tokenval.v.size < (off_t)LONG_MIN)
3330             conf_parserror("value too small");
3331 #endif
3332         val = (long)tokenval.v.size;
3333         break;
3334
3335     case CONF_AM64:
3336 #if SIZEOF_LONG < SIZEOF_LONG_LONG
3337         if (tokenval.v.am64 > (off_t)LONG_MAX)
3338             conf_parserror("value too large");
3339         if (tokenval.v.am64 < (off_t)LONG_MIN)
3340             conf_parserror("value too small");
3341 #endif
3342         val = (long)tokenval.v.am64;
3343         break;
3344
3345     case CONF_AMINFINITY:
3346         val = (long)LONG_MAX;
3347         break;
3348
3349     default:
3350         conf_parserror("an integer is expected");
3351         val = 0;
3352         break;
3353     }
3354
3355     get_conftoken(CONF_ANY);
3356
3357     switch(tok) {
3358     case CONF_NL:
3359     case CONF_MULT1:
3360     case CONF_MULT1K:
3361         break;
3362
3363     case CONF_MULT7:
3364         if (val > (LONG_MAX / 7L))
3365             conf_parserror("value too large");
3366         if (val < (LONG_MIN / 7L))
3367             conf_parserror("value too small");
3368         val *= 7L;
3369         break;
3370
3371     case CONF_MULT1M:
3372         if (val > (LONG_MAX / 1024L))
3373             conf_parserror("value too large");
3374         if (val < (LONG_MIN / 1024L))
3375             conf_parserror("value too small");
3376         val *= 1024L;
3377         break;
3378
3379     case CONF_MULT1G:
3380         if (val > (LONG_MAX / (1024L * 1024L)))
3381             conf_parserror("value too large");
3382         if (val < (LONG_MIN / (1024L * 1024L)))
3383             conf_parserror("value too small");
3384         val *= 1024L * 1024L;
3385         break;
3386
3387     default:
3388         unget_conftoken();
3389         break;
3390     }
3391
3392     keytable = save_kt;
3393     return val;
3394 }
3395 */
3396
3397 static ssize_t
3398 get_size(void)
3399 {
3400     ssize_t val;
3401     keytab_t *save_kt;
3402
3403     save_kt = keytable;
3404     keytable = numb_keytable;
3405
3406     get_conftoken(CONF_ANY);
3407
3408     switch(tok) {
3409     case CONF_SIZE:
3410         val = tokenval.v.size;
3411         break;
3412
3413     case CONF_INT:
3414 #if SIZEOF_SIZE_T < SIZEOF_INT
3415         if ((off_t)tokenval.v.i > (off_t)SSIZE_MAX)
3416             conf_parserror("value too large");
3417         if ((off_t)tokenval.v.i < (off_t)SSIZE_MIN)
3418             conf_parserror("value too small");
3419 #endif
3420         val = (ssize_t)tokenval.v.i;
3421         break;
3422
3423     case CONF_LONG:
3424 #if SIZEOF_SIZE_T < SIZEOF_LONG
3425         if ((off_t)tokenval.v.l > (off_t)SSIZE_MAX)
3426             conf_parserror("value too large");
3427         if ((off_t)tokenval.v.l < (off_t)SSIZE_MIN)
3428             conf_parserror("value too small");
3429 #endif
3430         val = (ssize_t)tokenval.v.l;
3431         break;
3432
3433     case CONF_AM64:
3434 #if SIZEOF_SIZE_T < SIZEOF_LONG_LONG
3435         if (tokenval.v.am64 > (off_t)SSIZE_MAX)
3436             conf_parserror("value too large");
3437         if (tokenval.v.am64 < (off_t)SSIZE_MIN)
3438             conf_parserror("value too small");
3439 #endif
3440         val = (ssize_t)tokenval.v.am64;
3441         break;
3442
3443     case CONF_AMINFINITY:
3444         val = (ssize_t)SSIZE_MAX;
3445         break;
3446
3447     default:
3448         conf_parserror("an integer is expected");
3449         val = 0;
3450         break;
3451     }
3452
3453     /* get multiplier, if any */
3454     get_conftoken(CONF_ANY);
3455
3456     switch(tok) {
3457     case CONF_NL:                       /* multiply by one */
3458     case CONF_MULT1:
3459     case CONF_MULT1K:
3460         break;
3461
3462     case CONF_MULT7:
3463         if (val > (ssize_t)(SSIZE_MAX / 7))
3464             conf_parserror("value too large");
3465         if (val < (ssize_t)(SSIZE_MIN / 7))
3466             conf_parserror("value too small");
3467         val *= (ssize_t)7;
3468         break;
3469
3470     case CONF_MULT1M:
3471         if (val > (ssize_t)(SSIZE_MAX / (ssize_t)1024))
3472             conf_parserror("value too large");
3473         if (val < (ssize_t)(SSIZE_MIN / (ssize_t)1024))
3474             conf_parserror("value too small");
3475         val *= (ssize_t)1024;
3476         break;
3477
3478     case CONF_MULT1G:
3479         if (val > (ssize_t)(SSIZE_MAX / (1024 * 1024)))
3480             conf_parserror("value too large");
3481         if (val < (ssize_t)(SSIZE_MIN / (1024 * 1024)))
3482             conf_parserror("value too small");
3483         val *= (ssize_t)(1024 * 1024);
3484         break;
3485
3486     default:    /* it was not a multiplier */
3487         unget_conftoken();
3488         break;
3489     }
3490
3491     keytable = save_kt;
3492     return val;
3493 }
3494
3495 static off_t
3496 get_am64_t(void)
3497 {
3498     off_t val;
3499     keytab_t *save_kt;
3500
3501     save_kt = keytable;
3502     keytable = numb_keytable;
3503
3504     get_conftoken(CONF_ANY);
3505
3506     switch(tok) {
3507     case CONF_INT:
3508         val = (off_t)tokenval.v.i;
3509         break;
3510
3511     case CONF_LONG:
3512         val = (off_t)tokenval.v.l;
3513         break;
3514
3515     case CONF_SIZE:
3516         val = (off_t)tokenval.v.size;
3517         break;
3518
3519     case CONF_AM64:
3520         val = tokenval.v.am64;
3521         break;
3522
3523     case CONF_AMINFINITY:
3524         val = AM64_MAX;
3525         break;
3526
3527     default:
3528         conf_parserror("an integer is expected");
3529         val = 0;
3530         break;
3531     }
3532
3533     /* get multiplier, if any */
3534     get_conftoken(CONF_ANY);
3535
3536     switch(tok) {
3537     case CONF_NL:                       /* multiply by one */
3538     case CONF_MULT1:
3539     case CONF_MULT1K:
3540         break;
3541
3542     case CONF_MULT7:
3543         if (val > AM64_MAX/7 || val < AM64_MIN/7)
3544             conf_parserror("value too large");
3545         val *= 7;
3546         break;
3547
3548     case CONF_MULT1M:
3549         if (val > AM64_MAX/1024 || val < AM64_MIN/1024)
3550             conf_parserror("value too large");
3551         val *= 1024;
3552         break;
3553
3554     case CONF_MULT1G:
3555         if (val > AM64_MAX/(1024*1024) || val < AM64_MIN/(1024*1024))
3556             conf_parserror("value too large");
3557         val *= 1024*1024;
3558         break;
3559
3560     default:    /* it was not a multiplier */
3561         unget_conftoken();
3562         break;
3563     }
3564
3565     keytable = save_kt;
3566
3567     return val;
3568 }
3569
3570 keytab_t bool_keytable[] = {
3571     { "Y", CONF_ATRUE },
3572     { "YES", CONF_ATRUE },
3573     { "T", CONF_ATRUE },
3574     { "TRUE", CONF_ATRUE },
3575     { "ON", CONF_ATRUE },
3576     { "N", CONF_AFALSE },
3577     { "NO", CONF_AFALSE },
3578     { "F", CONF_AFALSE },
3579     { "FALSE", CONF_AFALSE },
3580     { "OFF", CONF_AFALSE },
3581     { NULL, CONF_IDENT }
3582 };
3583
3584 static int
3585 get_bool(void)
3586 {
3587     int val;
3588     keytab_t *save_kt;
3589
3590     save_kt = keytable;
3591     keytable = bool_keytable;
3592
3593     get_conftoken(CONF_ANY);
3594
3595     switch(tok) {
3596     case CONF_INT:
3597         if (tokenval.v.i != 0)
3598             val = 1;
3599         else
3600             val = 0;
3601         break;
3602
3603     case CONF_LONG:
3604         if (tokenval.v.l != 0L)
3605             val = 1;
3606         else
3607             val = 0;
3608         break;
3609
3610     case CONF_SIZE:
3611         if (tokenval.v.size != (size_t)0)
3612             val = 1;
3613         else
3614             val = 0;
3615         break;
3616
3617     case CONF_AM64:
3618         if (tokenval.v.am64 != (off_t)0)
3619             val = 1;
3620         else
3621             val = 0;
3622         break;
3623
3624     case CONF_ATRUE:
3625         val = 1;
3626         break;
3627
3628     case CONF_AFALSE:
3629         val = 0;
3630         break;
3631
3632     case CONF_NL:
3633         unget_conftoken();
3634         val = 2; /* no argument - most likely TRUE */
3635         break;
3636     default:
3637         unget_conftoken();
3638         val = 3; /* a bad argument - most likely TRUE */
3639         conf_parserror("YES, NO, TRUE, FALSE, ON, OFF expected");
3640         break;
3641     }
3642
3643     keytable = save_kt;
3644     return val;
3645 }
3646
3647 void
3648 ckseen(
3649     int *seen)
3650 {
3651     if (*seen && !allow_overwrites && conf_line_num != -2) {
3652         conf_parserror("duplicate parameter, prev def on line %d", *seen);
3653     }
3654     *seen = conf_line_num;
3655 }
3656
3657 printf_arglist_function(void conf_parserror, const char *, format)
3658 {
3659     va_list argp;
3660
3661     /* print error message */
3662
3663     if(conf_line)
3664         fprintf(stderr, "argument \"%s\": ", conf_line);
3665     else
3666         fprintf(stderr, "\"%s\", line %d: ", conf_confname, conf_line_num);
3667     arglist_start(argp, format);
3668     vfprintf(stderr, format, argp);
3669     arglist_end(argp);
3670     fputc('\n', stderr);
3671
3672     got_parserror = 1;
3673 }
3674
3675 tok_t
3676 lookup_keyword(
3677     char *      str)
3678 {
3679     keytab_t *kwp;
3680
3681     /* switch to binary search if performance warrants */
3682
3683     for(kwp = keytable; kwp->keyword != NULL; kwp++) {
3684         if (strcasecmp(kwp->keyword, str) == 0) break;
3685     }
3686     return kwp->token;
3687 }
3688
3689 char tkbuf[4096];
3690
3691 /* push the last token back (can only unget ANY tokens) */
3692 static void
3693 unget_conftoken(void)
3694 {
3695     token_pushed = 1;
3696     pushed_tok = tok;
3697     tok = CONF_UNKNOWN;
3698     return;
3699 }
3700
3701 static int
3702 conftoken_getc(void)
3703 {
3704     if(conf_line == NULL)
3705         return getc(conf_conf);
3706     if(*conf_char == '\0')
3707         return -1;
3708     return(*conf_char++);
3709 }
3710
3711 static int
3712 conftoken_ungetc(
3713     int c)
3714 {
3715     if(conf_line == NULL)
3716         return ungetc(c, conf_conf);
3717     else if(conf_char > conf_line) {
3718         if(c == -1)
3719             return c;
3720         conf_char--;
3721         if(*conf_char != c) {
3722             error("*conf_char != c   : %c %c", *conf_char, c);
3723             /* NOTREACHED */
3724         }
3725     } else {
3726         error("conf_char == conf_line");
3727         /* NOTREACHED */
3728     }
3729     return c;
3730 }
3731
3732 static void
3733 get_conftoken(
3734     tok_t       exp)
3735 {
3736     int ch, d;
3737     off_t am64;
3738     char *buf;
3739     char *tmps;
3740     int token_overflow;
3741     int inquote = 0;
3742     int escape = 0;
3743     int sign;
3744
3745     if (token_pushed) {
3746         token_pushed = 0;
3747         tok = pushed_tok;
3748
3749         /*
3750         ** If it looked like a key word before then look it
3751         ** up again in the current keyword table.
3752         */
3753         switch(tok) {
3754         case CONF_LONG:    case CONF_AM64:    case CONF_SIZE:
3755         case CONF_INT:     case CONF_REAL:    case CONF_STRING:
3756         case CONF_LBRACE:  case CONF_RBRACE:  case CONF_COMMA:
3757         case CONF_NL:      case CONF_END:     case CONF_UNKNOWN:
3758         case CONF_TIME:
3759             break;
3760
3761         default:
3762             if (exp == CONF_IDENT)
3763                 tok = CONF_IDENT;
3764             else
3765                 tok = lookup_keyword(tokenval.v.s);
3766             break;
3767         }
3768     }
3769     else {
3770         ch = conftoken_getc();
3771
3772         while(ch != EOF && ch != '\n' && isspace(ch))
3773             ch = conftoken_getc();
3774         if (ch == '#') {        /* comment - eat everything but eol/eof */
3775             while((ch = conftoken_getc()) != EOF && ch != '\n') {
3776                 (void)ch; /* Quiet empty loop complaints */     
3777             }
3778         }
3779
3780         if (isalpha(ch)) {              /* identifier */
3781             buf = tkbuf;
3782             token_overflow = 0;
3783             do {
3784                 if (buf < tkbuf+sizeof(tkbuf)-1) {
3785                     *buf++ = (char)ch;
3786                 } else {
3787                     *buf = '\0';
3788                     if (!token_overflow) {
3789                         conf_parserror("token too long: %.20s...", tkbuf);
3790                     }
3791                     token_overflow = 1;
3792                 }
3793                 ch = conftoken_getc();
3794             } while(isalnum(ch) || ch == '_' || ch == '-');
3795
3796             if (ch != EOF && conftoken_ungetc(ch) == EOF) {
3797                 if (ferror(conf_conf)) {
3798                     conf_parserror("Pushback of '%c' failed: %s",
3799                                    ch, strerror(ferror(conf_conf)));
3800                 } else {
3801                     conf_parserror("Pushback of '%c' failed: EOF", ch);
3802                 }
3803             }
3804             *buf = '\0';
3805
3806             tokenval.v.s = tkbuf;
3807
3808             if (token_overflow) tok = CONF_UNKNOWN;
3809             else if (exp == CONF_IDENT) tok = CONF_IDENT;
3810             else tok = lookup_keyword(tokenval.v.s);
3811         }
3812         else if (isdigit(ch)) { /* integer */
3813             sign = 1;
3814
3815 negative_number: /* look for goto negative_number below sign is set there */
3816             am64 = 0;
3817             do {
3818                 am64 = am64 * 10 + (ch - '0');
3819                 ch = conftoken_getc();
3820             } while (isdigit(ch));
3821
3822             if (ch != '.') {
3823                 if (exp == CONF_INT) {
3824                     tok = CONF_INT;
3825                     tokenval.v.i = sign * (int)am64;
3826                 } else if (exp == CONF_LONG) {
3827                     tok = CONF_LONG;
3828                     tokenval.v.l = (long)sign * (long)am64;
3829                 } else if (exp != CONF_REAL) {
3830                     tok = CONF_AM64;
3831                     tokenval.v.am64 = (off_t)sign * am64;
3832                 } else {
3833                     /* automatically convert to real when expected */
3834                     tokenval.v.r = (double)sign * (double)am64;
3835                     tok = CONF_REAL;
3836                 }
3837             } else {
3838                 /* got a real number, not an int */
3839                 tokenval.v.r = sign * (double) am64;
3840                 am64 = 0;
3841                 d = 1;
3842                 ch = conftoken_getc();
3843                 while (isdigit(ch)) {
3844                     am64 = am64 * 10 + (ch - '0');
3845                     d = d * 10;
3846                     ch = conftoken_getc();
3847                 }
3848                 tokenval.v.r += sign * ((double)am64) / d;
3849                 tok = CONF_REAL;
3850             }
3851
3852             if (ch != EOF &&  conftoken_ungetc(ch) == EOF) {
3853                 if (ferror(conf_conf)) {
3854                     conf_parserror("Pushback of '%c' failed: %s",
3855                                    ch, strerror(ferror(conf_conf)));
3856                 } else {
3857                     conf_parserror("Pushback of '%c' failed: EOF", ch);
3858                 }
3859             }
3860         } else switch(ch) {
3861         case '"':                       /* string */
3862             buf = tkbuf;
3863             token_overflow = 0;
3864             inquote = 1;
3865             *buf++ = (char)ch;
3866             while (inquote && ((ch = conftoken_getc()) != EOF)) {
3867                 if (ch == '\n') {
3868                     if (!escape)
3869                         break;
3870                     escape = 0;
3871                     buf--; /* Consume escape in buffer */
3872                 } else if (ch == '\\') {
3873                     escape = 1;
3874                 } else {
3875                     if (ch == '"') {
3876                         if (!escape)
3877                             inquote = 0;
3878                     }
3879                     escape = 0;
3880                 }
3881
3882                 if(buf >= &tkbuf[sizeof(tkbuf) - 1]) {
3883                     if (!token_overflow) {
3884                         conf_parserror("string too long: %.20s...", tkbuf);
3885                     }
3886                     token_overflow = 1;
3887                     break;
3888                 }
3889                 *buf++ = (char)ch;
3890             }
3891             *buf = '\0';
3892
3893             /*
3894              * A little manuver to leave a fully unquoted, unallocated  string
3895              * in tokenval.v.s
3896              */
3897             tmps = unquote_string(tkbuf);
3898             strncpy(tkbuf, tmps, sizeof(tkbuf));
3899             amfree(tmps);
3900             tokenval.v.s = tkbuf;
3901
3902             tok = (token_overflow) ? CONF_UNKNOWN :
3903                         (exp == CONF_IDENT) ? CONF_IDENT : CONF_STRING;
3904             break;
3905
3906         case '-':
3907             ch = conftoken_getc();
3908             if (isdigit(ch)) {
3909                 sign = -1;
3910                 goto negative_number;
3911             }
3912             else {
3913                 if (ch != EOF && conftoken_ungetc(ch) == EOF) {
3914                     if (ferror(conf_conf)) {
3915                         conf_parserror("Pushback of '%c' failed: %s",
3916                                        ch, strerror(ferror(conf_conf)));
3917                     } else {
3918                         conf_parserror("Pushback of '%c' failed: EOF", ch);
3919                     }
3920                 }
3921                 tok = CONF_UNKNOWN;
3922             }
3923             break;
3924
3925         case ',':
3926             tok = CONF_COMMA;
3927             break;
3928
3929         case '{':
3930             tok = CONF_LBRACE;
3931             break;
3932
3933         case '}':
3934             tok = CONF_RBRACE;
3935             break;
3936
3937         case '\n':
3938             tok = CONF_NL;
3939             break;
3940
3941         case EOF:
3942             tok = CONF_END;
3943             break;
3944
3945         default:
3946             tok = CONF_UNKNOWN;
3947             break;
3948         }
3949     }
3950
3951     if (exp != CONF_ANY && tok != exp) {
3952         char *str;
3953         keytab_t *kwp;
3954
3955         switch(exp) {
3956         case CONF_LBRACE:
3957             str = "\"{\"";
3958             break;
3959
3960         case CONF_RBRACE:
3961             str = "\"}\"";
3962             break;
3963
3964         case CONF_COMMA:
3965             str = "\",\"";
3966             break;
3967
3968         case CONF_NL:
3969             str = "end of line";
3970             break;
3971
3972         case CONF_END:
3973             str = "end of file";
3974             break;
3975
3976         case CONF_INT:
3977             str = "an integer";
3978             break;
3979
3980         case CONF_REAL:
3981             str = "a real number";
3982             break;
3983
3984         case CONF_STRING:
3985             str = "a quoted string";
3986             break;
3987
3988         case CONF_IDENT:
3989             str = "an identifier";
3990             break;
3991
3992         default:
3993             for(kwp = keytable; kwp->keyword != NULL; kwp++) {
3994                 if (exp == kwp->token)
3995                     break;
3996             }
3997             if (kwp->keyword == NULL)
3998                 str = "token not";
3999             else
4000                 str = kwp->keyword;
4001             break;
4002         }
4003         conf_parserror("%s is expected", str);
4004         tok = exp;
4005         if (tok == CONF_INT)
4006             tokenval.v.i = 0;
4007         else
4008             tokenval.v.s = "";
4009     }
4010 }
4011
4012
4013 static void
4014 read_string(
4015     t_conf_var *np,
4016     val_t *val)
4017 {
4018     np = np;
4019     ckseen(&val->seen);
4020     get_conftoken(CONF_STRING);
4021     val->v.s = newstralloc(val->v.s, tokenval.v.s);
4022 }
4023
4024 static void
4025 read_ident(
4026     t_conf_var *np,
4027     val_t *val)
4028 {
4029     np = np;
4030     ckseen(&val->seen);
4031     get_conftoken(CONF_IDENT);
4032     val->v.s = newstralloc(val->v.s, tokenval.v.s);
4033 }
4034
4035 static void
4036 read_int(
4037     t_conf_var *np,
4038     val_t *val)
4039 {
4040     np = np;
4041     ckseen(&val->seen);
4042     val->v.i = get_int();
4043 }
4044
4045 /*
4046 static void
4047 read_long(
4048     t_conf_var *np,
4049     val_t *val)
4050 {
4051     np = np;
4052     ckseen(&val->seen);
4053     val->v.l = get_long();
4054 }
4055 */
4056
4057 static void
4058 read_size(
4059     t_conf_var *np,
4060     val_t *val)
4061 {
4062     np = np;
4063     ckseen(&val->seen);
4064     val->v.size = get_size();
4065 }
4066
4067 static void
4068 read_am64(
4069     t_conf_var *np,
4070     val_t *val)
4071 {
4072     np = np;
4073     ckseen(&val->seen);
4074     val->v.am64 = get_am64_t();
4075 }
4076
4077 static void
4078 read_bool(
4079     t_conf_var *np,
4080     val_t *val)
4081 {
4082     np = np;
4083     ckseen(&val->seen);
4084     val->v.i = get_bool();
4085 }
4086
4087 static void
4088 read_real(
4089     t_conf_var *np,
4090     val_t *val)
4091 {
4092     np = np;
4093     ckseen(&val->seen);
4094     get_conftoken(CONF_REAL);
4095     val->v.r = tokenval.v.r;
4096 }
4097
4098 static void
4099 read_time(
4100     t_conf_var *np,
4101     val_t *val)
4102 {
4103     np = np;
4104     ckseen(&val->seen);
4105     val->v.t = get_time();
4106 }
4107
4108 static void
4109 copy_val_t(
4110     val_t *valdst,
4111     val_t *valsrc)
4112 {
4113     if(valsrc->seen) {
4114         valdst->type = valsrc->type;
4115         valdst->seen = valsrc->seen;
4116         switch(valsrc->type) {
4117         case CONFTYPE_INT:
4118         case CONFTYPE_BOOL:
4119         case CONFTYPE_COMPRESS:
4120         case CONFTYPE_ENCRYPT:
4121         case CONFTYPE_HOLDING:
4122         case CONFTYPE_ESTIMATE:
4123         case CONFTYPE_STRATEGY:
4124         case CONFTYPE_TAPERALGO:
4125         case CONFTYPE_PRIORITY:
4126             valdst->v.i = valsrc->v.i;
4127             break;
4128
4129         case CONFTYPE_LONG:
4130             valdst->v.l = valsrc->v.l;
4131             break;
4132
4133         case CONFTYPE_SIZE:
4134             valdst->v.size = valsrc->v.size;
4135             break;
4136
4137         case CONFTYPE_AM64:
4138             valdst->v.am64 = valsrc->v.am64;
4139             break;
4140
4141         case CONFTYPE_REAL:
4142             valdst->v.r = valsrc->v.r;
4143             break;
4144
4145         case CONFTYPE_RATE:
4146             valdst->v.rate[0] = valsrc->v.rate[0];
4147             valdst->v.rate[1] = valsrc->v.rate[1];
4148             break;
4149
4150         case CONFTYPE_IDENT:
4151         case CONFTYPE_STRING:
4152             valdst->v.s = stralloc(valsrc->v.s);
4153             break;
4154
4155         case CONFTYPE_TIME:
4156             valdst->v.t = valsrc->v.t;
4157             break;
4158
4159         case CONFTYPE_SL:
4160             valdst->v.sl = duplicate_sl(valsrc->v.sl);
4161             break;
4162
4163         case CONFTYPE_EXINCLUDE:
4164             valdst->v.exinclude.optional = valsrc->v.exinclude.optional;
4165             valdst->v.exinclude.sl_list = duplicate_sl(valsrc->v.exinclude.sl_list);
4166             valdst->v.exinclude.sl_file = duplicate_sl(valsrc->v.exinclude.sl_file);
4167             break;
4168
4169         case CONFTYPE_INTRANGE:
4170             valdst->v.intrange[0] = valsrc->v.intrange[0];
4171             valdst->v.intrange[1] = valsrc->v.intrange[1];
4172             break;
4173
4174         }
4175     }
4176 }
4177
4178 static void
4179 free_val_t(
4180     val_t *val)
4181 {
4182     switch(val->type) {
4183         case CONFTYPE_INT:
4184         case CONFTYPE_BOOL:
4185         case CONFTYPE_COMPRESS:
4186         case CONFTYPE_ENCRYPT:
4187         case CONFTYPE_HOLDING:
4188         case CONFTYPE_ESTIMATE:
4189         case CONFTYPE_STRATEGY:
4190         case CONFTYPE_SIZE:
4191         case CONFTYPE_TAPERALGO:
4192         case CONFTYPE_PRIORITY:
4193         case CONFTYPE_LONG:
4194         case CONFTYPE_AM64:
4195         case CONFTYPE_REAL:
4196         case CONFTYPE_RATE:
4197         case CONFTYPE_INTRANGE:
4198             break;
4199
4200         case CONFTYPE_IDENT:
4201         case CONFTYPE_STRING:
4202             amfree(val->v.s);
4203             break;
4204
4205         case CONFTYPE_TIME:
4206             break;
4207
4208         case CONFTYPE_SL:
4209             free_sl(val->v.sl);
4210             break;
4211
4212         case CONFTYPE_EXINCLUDE:
4213             free_sl(val->v.exinclude.sl_list);
4214             free_sl(val->v.exinclude.sl_file);
4215             break;
4216     }
4217     val->seen = 0;
4218 }
4219
4220 char *
4221 taperalgo2str(
4222     int taperalgo)
4223 {
4224     if(taperalgo == ALGO_FIRST) return "FIRST";
4225     if(taperalgo == ALGO_FIRSTFIT) return "FIRSTFIT";
4226     if(taperalgo == ALGO_LARGEST) return "LARGEST";
4227     if(taperalgo == ALGO_LARGESTFIT) return "LARGESTFIT";
4228     if(taperalgo == ALGO_SMALLEST) return "SMALLEST";
4229     if(taperalgo == ALGO_LAST) return "LAST";
4230     return "UNKNOWN";
4231 }
4232
4233 static char buffer_conf_print[2049];
4234
4235 static char *
4236 conf_print(
4237     val_t *val,
4238     int    str_need_quote,
4239     char  *prefix)
4240 {
4241     char *buf;
4242     int   free_space;
4243
4244     buffer_conf_print[0] = '\0';
4245     snprintf(buffer_conf_print, SIZEOF(buffer_conf_print), prefix);
4246     free_space = SIZEOF(buffer_conf_print) - strlen(buffer_conf_print);
4247     buf = buffer_conf_print + strlen(buffer_conf_print);
4248     switch(val->type) {
4249     case CONFTYPE_INT:
4250         snprintf(buf, free_space, "%d", val->v.i);
4251         break;
4252
4253     case CONFTYPE_LONG:
4254         snprintf(buf, free_space, "%ld", val->v.l);
4255         break;
4256
4257     case CONFTYPE_SIZE:
4258         snprintf(buf, free_space, SSIZE_T_FMT, (SSIZE_T_FMT_TYPE)val->v.size);
4259         break;
4260
4261     case CONFTYPE_AM64:
4262         snprintf(buf, free_space, OFF_T_FMT, (OFF_T_FMT_TYPE)val->v.am64);
4263         break;
4264
4265     case CONFTYPE_REAL:
4266         snprintf(buf, free_space, "%0.5f" , val->v.r);
4267         break;
4268
4269     case CONFTYPE_RATE:
4270         snprintf(buf, free_space, "%0.5f %0.5f",
4271                  val->v.rate[0], val->v.rate[1]);
4272         break;
4273
4274     case CONFTYPE_INTRANGE:
4275         snprintf(buf, free_space, "%d,%d",
4276                  val->v.intrange[0], val->v.intrange[1]);
4277         break;
4278
4279     case CONFTYPE_IDENT:
4280         if(val->v.s) {
4281             strncpy(buf, val->v.s, free_space);
4282         }
4283         break;
4284
4285     case CONFTYPE_STRING:
4286         if(str_need_quote) {
4287             *buf++ = '"';
4288             free_space++;
4289             if(val->v.s) {
4290                 strncpy(buf, val->v.s, free_space);
4291                 buffer_conf_print[SIZEOF(buffer_conf_print) - 2] = '\0';
4292                 buffer_conf_print[strlen(buffer_conf_print)] = '"';
4293                 buffer_conf_print[strlen(buffer_conf_print) + 1] = '\0';
4294             } else {
4295                 *buf++ = '"';
4296                 *buf++ = '\0';
4297                 free_space -= 2;
4298             }
4299         } else {
4300             if(val->v.s) {
4301                 strncpy(buf, val->v.s, free_space);
4302             }
4303         }
4304         break;
4305
4306     case CONFTYPE_TIME:
4307         snprintf(buf, free_space, "%2d%02d",
4308                  (int)val->v.t/100, (int)val->v.t % 100);
4309         break;
4310
4311     case CONFTYPE_SL:
4312         break;
4313
4314     case CONFTYPE_EXINCLUDE:
4315         buf = buffer_conf_print;
4316         free_space = SIZEOF(buffer_conf_print);
4317
4318         conf_print_exinclude(val, 1, 0, prefix, &buf ,&free_space);
4319         *buf++ = '\n';
4320         free_space -= 1;
4321
4322         conf_print_exinclude(val, 1, 1, prefix, &buf, &free_space);
4323         break;
4324
4325     case CONFTYPE_BOOL:
4326         if(val->v.i)
4327             strncpy(buf, "yes", free_space);
4328         else
4329             strncpy(buf, "no", free_space);
4330         break;
4331
4332     case CONFTYPE_STRATEGY:
4333         switch(val->v.i) {
4334         case DS_SKIP:
4335             strncpy(buf, "SKIP", free_space);
4336             break;
4337
4338         case DS_STANDARD:
4339             strncpy(buf, "STANDARD", free_space);
4340             break;
4341
4342         case DS_NOFULL:
4343             strncpy(buf, "NOFULL", free_space);
4344             break;
4345
4346         case DS_NOINC:
4347             strncpy(buf, "NOINC", free_space);
4348             break;
4349
4350         case DS_HANOI:
4351             strncpy(buf, "HANOI", free_space);
4352             break;
4353
4354         case DS_INCRONLY:
4355             strncpy(buf, "INCRONLY", free_space);
4356             break;
4357         }
4358         break;
4359
4360     case CONFTYPE_COMPRESS:
4361         switch(val->v.i) {
4362         case COMP_NONE:
4363             strncpy(buf, "NONE", free_space);
4364             break;
4365
4366         case COMP_FAST:
4367             strncpy(buf, "CLIENT FAST", free_space);
4368             break;
4369
4370         case COMP_BEST:
4371             strncpy(buf, "CLIENT BEST", free_space);
4372             break;
4373
4374         case COMP_CUST:
4375             strncpy(buf, "CLIENT CUSTOM", free_space);
4376             break;
4377
4378         case COMP_SERVER_FAST:
4379             strncpy(buf, "SERVER FAST", free_space);
4380             break;
4381
4382         case COMP_SERVER_BEST:
4383             strncpy(buf, "SERVER FAST", free_space);
4384             break;
4385
4386         case COMP_SERVER_CUST:
4387             strncpy(buf, "SERVER CUSTOM", free_space);
4388             break;
4389         }
4390         break;
4391
4392     case CONFTYPE_ESTIMATE:
4393         switch(val->v.i) {
4394         case ES_CLIENT:
4395             strncpy(buf, "CLIENT", free_space);
4396             break;
4397
4398         case ES_SERVER:
4399             strncpy(buf, "SERVER", free_space);
4400             break;
4401
4402         case ES_CALCSIZE:
4403             strncpy(buf, "CALCSIZE", free_space);
4404             break;
4405         }
4406         break;
4407
4408      case CONFTYPE_ENCRYPT:
4409         switch(val->v.i) {
4410         case ENCRYPT_NONE:
4411             strncpy(buf, "NONE", free_space);
4412             break;
4413
4414         case ENCRYPT_CUST:
4415             strncpy(buf, "CLIENT", free_space);
4416             break;
4417
4418         case ENCRYPT_SERV_CUST:
4419             strncpy(buf, "SERVER", free_space);
4420             break;
4421         }
4422         break;
4423
4424      case CONFTYPE_HOLDING:
4425         switch(val->v.i) {
4426         case HOLD_NEVER:
4427             strncpy(buf, "NEVER", free_space);
4428             break;
4429
4430         case HOLD_AUTO:
4431             strncpy(buf, "AUTO", free_space);
4432             break;
4433
4434         case HOLD_REQUIRED:
4435             strncpy(buf, "REQUIRED", free_space);
4436             break;
4437         }
4438         break;
4439
4440      case CONFTYPE_TAPERALGO:
4441         strncpy(buf, taperalgo2str(val->v.i), free_space);
4442         break;
4443
4444      case CONFTYPE_PRIORITY:
4445         switch(val->v.i) {
4446         case 0:
4447             strncpy(buf, "LOW", free_space);
4448             break;
4449
4450         case 1:
4451             strncpy(buf, "MEDIUM", free_space);
4452             break;
4453
4454         case 2:
4455             strncpy(buf, "HIGH", free_space);
4456             break;
4457         }
4458         break;
4459     }
4460     buffer_conf_print[SIZEOF(buffer_conf_print) - 1] = '\0';
4461     return buffer_conf_print;
4462 }
4463
4464 void  conf_print_exinclude(
4465     val_t *val,
4466     int    str_need_quote,
4467     int    file,
4468     char  *prefix,
4469     char **buf,
4470     int   *free_space)
4471 {
4472     sl_t  *sl;
4473     sle_t *excl;
4474
4475     (void)str_need_quote;
4476
4477     snprintf(*buf, *free_space, prefix);
4478     *free_space -= strlen(prefix);
4479     *buf += strlen(prefix);
4480
4481     if (val->type != CONFTYPE_EXINCLUDE) {
4482         strcpy(*buf,
4483           "ERROR: conf_print_exinclude called for type != CONFTYPE_EXINCLUDE");
4484         return;
4485     }
4486
4487     if (file == 0) {
4488         sl = val->v.exinclude.sl_list;
4489         strncpy(*buf, "LIST ", *free_space);
4490         *buf += 5;
4491         *free_space -= 5;
4492     } else {
4493         sl = val->v.exinclude.sl_file;
4494         strncpy(*buf, "FILE ", *free_space);
4495         *buf += 5;
4496         *free_space -= 5;
4497     }
4498
4499     if (val->v.exinclude.optional == 1) {
4500         strncpy(*buf, "OPTIONAL ", *free_space);
4501         *buf += 9;
4502         *free_space -= 9;
4503     }
4504
4505     if (sl != NULL) {
4506         for(excl = sl->first; excl != NULL; excl = excl->next) {
4507             if (3 + (int)strlen(excl->name) < *free_space) {
4508                 *(*buf)++ = ' ';
4509                 *(*buf)++ = '"';
4510                 strcpy(*buf, excl->name);
4511                 *buf += strlen(excl->name);
4512                 *(*buf)++ = '"';
4513                 *free_space -= 3 + strlen(excl->name);
4514             }
4515         }
4516     }
4517
4518     return;
4519 }
4520
4521 static void
4522 conf_init_string(
4523     val_t *val,
4524     char  *s)
4525 {
4526     val->seen = 0;
4527     val->type = CONFTYPE_STRING;
4528     if(s)
4529         val->v.s = stralloc(s);
4530     else
4531         val->v.s = NULL;
4532 }
4533
4534 static void
4535 conf_init_ident(
4536     val_t *val,
4537     char  *s)
4538 {
4539     val->seen = 0;
4540     val->type = CONFTYPE_IDENT;
4541     if(s)
4542         val->v.s = stralloc(s);
4543     else
4544         val->v.s = NULL;
4545 }
4546
4547 static void
4548 conf_init_int(
4549     val_t *val,
4550     int    i)
4551 {
4552     val->seen = 0;
4553     val->type = CONFTYPE_INT;
4554     val->v.i = i;
4555 }
4556
4557 static void
4558 conf_init_bool(
4559     val_t *val,
4560     int    i)
4561 {
4562     val->seen = 0;
4563     val->type = CONFTYPE_BOOL;
4564     val->v.i = i;
4565 }
4566
4567 static void
4568 conf_init_strategy(
4569     val_t *val,
4570     int    i)
4571 {
4572     val->seen = 0;
4573     val->type = CONFTYPE_STRATEGY;
4574     val->v.i = i;
4575 }
4576
4577 static void
4578 conf_init_estimate(
4579     val_t *val,
4580     int    i)
4581 {
4582     val->seen = 0;
4583     val->type = CONFTYPE_ESTIMATE;
4584     val->v.i = i;
4585 }
4586
4587 static void
4588 conf_init_taperalgo(
4589     val_t *val,
4590     int    i)
4591 {
4592     val->seen = 0;
4593     val->type = CONFTYPE_TAPERALGO;
4594     val->v.i = i;
4595 }
4596
4597 static void
4598 conf_init_priority(
4599     val_t *val,
4600     int    i)
4601 {
4602     val->seen = 0;
4603     val->type = CONFTYPE_PRIORITY;
4604     val->v.i = i;
4605 }
4606
4607 static void
4608 conf_init_compress(
4609     val_t *val,
4610     comp_t    i)
4611 {
4612     val->seen = 0;
4613     val->type = CONFTYPE_COMPRESS;
4614     val->v.i = (int)i;
4615 }
4616
4617 static void
4618 conf_init_encrypt(
4619     val_t *val,
4620     encrypt_t    i)
4621 {
4622     val->seen = 0;
4623     val->type = CONFTYPE_ENCRYPT;
4624     val->v.i = (int)i;
4625 }
4626
4627 static void
4628 conf_init_holding(
4629     val_t              *val,
4630     dump_holdingdisk_t  i)
4631 {
4632     val->seen = 0;
4633     val->type = CONFTYPE_HOLDING;
4634     val->v.i = (int)i;
4635 }
4636
4637 /*
4638 static void
4639 conf_init_long(
4640     val_t *val,
4641     long   l)
4642 {
4643     val->seen = 0;
4644     val->type = CONFTYPE_LONG;
4645     val->v.l = l;
4646 }
4647 */
4648
4649 static void
4650 conf_init_size(
4651     val_t *val,
4652     ssize_t   sz)
4653 {
4654     val->seen = 0;
4655     val->type = CONFTYPE_SIZE;
4656     val->v.size = sz;
4657 }
4658
4659 static void
4660 conf_init_am64(
4661     val_t *val,
4662     off_t   l)
4663 {
4664     val->seen = 0;
4665     val->type = CONFTYPE_AM64;
4666     val->v.am64 = l;
4667 }
4668
4669 static void
4670 conf_init_real(
4671     val_t  *val,
4672     double r)
4673 {
4674     val->seen = 0;
4675     val->type = CONFTYPE_REAL;
4676     val->v.r = r;
4677 }
4678
4679 static void
4680 conf_init_rate(
4681     val_t  *val,
4682     double r1,
4683     double r2)
4684 {
4685     val->seen = 0;
4686     val->type = CONFTYPE_RATE;
4687     val->v.rate[0] = r1;
4688     val->v.rate[1] = r2;
4689 }
4690
4691 static void
4692 conf_init_intrange(
4693     val_t *val,
4694     int    i1,
4695     int    i2)
4696 {
4697     val->seen = 0;
4698     val->type = CONFTYPE_INTRANGE;
4699     val->v.intrange[0] = i1;
4700     val->v.intrange[1] = i2;
4701 }
4702
4703 static void
4704 conf_init_time(
4705     val_t *val,
4706     time_t   t)
4707 {
4708     val->seen = 0;
4709     val->type = CONFTYPE_TIME;
4710     val->v.t = t;
4711 }
4712
4713 /*
4714 static void
4715 conf_init_sl(
4716     val_t *val,
4717     sl_t  *sl)
4718 {
4719     val->seen = 0;
4720     val->type = CONFTYPE_AM64;
4721     val->v.sl = sl;
4722 }
4723 */
4724
4725 static void
4726 conf_init_exinclude(
4727     val_t *val)
4728 {
4729     val->seen = 0;
4730     val->type = CONFTYPE_EXINCLUDE;
4731     val->v.exinclude.optional = 0;
4732     val->v.exinclude.sl_list = NULL;
4733     val->v.exinclude.sl_file = NULL;
4734 }
4735
4736 static void
4737 conf_set_string(
4738     val_t *val,
4739     char *s)
4740 {
4741     val->seen = -1;
4742     val->type = CONFTYPE_STRING;
4743     amfree(val->v.s);
4744     val->v.s = stralloc(s);
4745 }
4746
4747 /*
4748 static void
4749 conf_set_int(
4750     val_t *val,
4751     int    i)
4752 {
4753     val->seen = -1;
4754     val->type = CONFTYPE_INT;
4755     val->v.i = i;
4756 }
4757 */
4758
4759 static void
4760 conf_set_bool(
4761     val_t *val,
4762     int    i)
4763 {
4764     val->seen = -1;
4765     val->type = CONFTYPE_BOOL;
4766     val->v.i = i;
4767 }
4768
4769 static void
4770 conf_set_compress(
4771     val_t *val,
4772     comp_t    i)
4773 {
4774     val->seen = -1;
4775     val->type = CONFTYPE_COMPRESS;
4776     val->v.i = (int)i;
4777 }
4778
4779 /*
4780 static void
4781 conf_set_encrypt(
4782     val_t *val,
4783     encrypt_t    i)
4784 {
4785     val->seen = -1;
4786     val->type = CONFTYPE_COMPRESS;
4787     val->v.i = (int)i;
4788 }
4789 */
4790
4791 static void
4792 conf_set_holding(
4793     val_t              *val,
4794     dump_holdingdisk_t  i)
4795 {
4796     val->seen = -1;
4797     val->type = CONFTYPE_HOLDING;
4798     val->v.i = (int)i;
4799 }
4800
4801 static void
4802 conf_set_strategy(
4803     val_t *val,
4804     int    i)
4805 {
4806     val->seen = -1;
4807     val->type = CONFTYPE_STRATEGY;
4808     val->v.i = i;
4809 }
4810
4811
4812 int
4813 get_conftype_int(
4814     val_t *val)
4815 {
4816     if (val->type != CONFTYPE_INT) {
4817         error("get_conftype_int: val.type is not CONFTYPE_INT");
4818         /*NOTREACHED*/
4819     }
4820     return val->v.i;
4821 }
4822
4823 long
4824 get_conftype_long(
4825     val_t *val)
4826 {
4827     if (val->type != CONFTYPE_LONG) {
4828         error("get_conftype_long: val.type is not CONFTYPE_LONG");
4829         /*NOTREACHED*/
4830     }
4831     return val->v.l;
4832 }
4833
4834 off_t
4835 get_conftype_am64(
4836     val_t *val)
4837 {
4838     if (val->type != CONFTYPE_AM64) {
4839         error("get_conftype_am64: val.type is not CONFTYPE_AM64");
4840         /*NOTREACHED*/
4841     }
4842     return val->v.am64;
4843 }
4844
4845 double
4846 get_conftype_real(
4847     val_t *val)
4848 {
4849     if (val->type != CONFTYPE_REAL) {
4850         error("get_conftype_real: val.type is not CONFTYPE_REAL");
4851         /*NOTREACHED*/
4852     }
4853     return val->v.r;
4854 }
4855
4856 char *
4857 get_conftype_string(
4858     val_t *val)
4859 {
4860     if (val->type != CONFTYPE_STRING) {
4861         error("get_conftype_string: val.type is not CONFTYPE_STRING");
4862         /*NOTREACHED*/
4863     }
4864     return val->v.s;
4865 }
4866
4867 char *
4868 get_conftype_ident(
4869     val_t *val)
4870 {
4871     if (val->type != CONFTYPE_IDENT) {
4872         error("get_conftype_ident: val.type is not CONFTYPE_IDENT");
4873         /*NOTREACHED*/
4874     }
4875     return val->v.s;
4876 }
4877
4878 time_t
4879 get_conftype_time(
4880     val_t *val)
4881 {
4882     if (val->type != CONFTYPE_TIME) {
4883         error("get_conftype_time: val.type is not CONFTYPE_TIME");
4884         /*NOTREACHED*/
4885     }
4886     return val->v.t;
4887 }
4888
4889 ssize_t
4890 get_conftype_size(
4891     val_t *val)
4892 {
4893     if (val->type != CONFTYPE_SIZE) {
4894         error("get_conftype_size: val.type is not CONFTYPE_SIZE");
4895         /*NOTREACHED*/
4896     }
4897     return val->v.size;
4898 }
4899
4900 sl_t *
4901 get_conftype_sl(
4902     val_t *val)
4903 {
4904     if (val->type != CONFTYPE_SL) {
4905         error("get_conftype_size: val.type is not CONFTYPE_SL");
4906         /*NOTREACHED*/
4907     }
4908     return val->v.sl;
4909 }
4910
4911 int
4912 get_conftype_bool(
4913     val_t *val)
4914 {
4915     if (val->type != CONFTYPE_BOOL) {
4916         error("get_conftype_bool: val.type is not CONFTYPE_BOOL");
4917         /*NOTREACHED*/
4918     }
4919     return val->v.i;
4920 }
4921
4922 int
4923 get_conftype_hold(
4924     val_t *val)
4925 {
4926     if (val->type != CONFTYPE_HOLDING) {
4927         error("get_conftype_hold: val.type is not CONFTYPE_HOLDING");
4928         /*NOTREACHED*/
4929     }
4930     return val->v.i;
4931 }
4932
4933 int
4934 get_conftype_compress(
4935     val_t *val)
4936 {
4937     if (val->type != CONFTYPE_COMPRESS) {
4938         error("get_conftype_compress: val.type is not CONFTYPE_COMPRESS");
4939         /*NOTREACHED*/
4940     }
4941     return val->v.i;
4942 }
4943
4944 int
4945 get_conftype_encrypt(
4946     val_t *val)
4947 {
4948     if (val->type != CONFTYPE_ENCRYPT) {
4949         error("get_conftype_encrypt: val.type is not CONFTYPE_ENCRYPT");
4950         /*NOTREACHED*/
4951     }
4952     return val->v.i;
4953 }
4954
4955 int
4956 get_conftype_estimate(
4957     val_t *val)
4958 {
4959     if (val->type != CONFTYPE_ESTIMATE) {
4960         error("get_conftype_extimate: val.type is not CONFTYPE_ESTIMATE");
4961         /*NOTREACHED*/
4962     }
4963     return val->v.i;
4964 }
4965
4966 int
4967 get_conftype_strategy(
4968     val_t *val)
4969 {
4970     if (val->type != CONFTYPE_STRATEGY) {
4971         error("get_conftype_strategy: val.type is not CONFTYPE_STRATEGY");
4972         /*NOTREACHED*/
4973     }
4974     return val->v.i;
4975 }
4976
4977 int
4978 get_conftype_taperalgo(
4979     val_t *val)
4980 {
4981     if (val->type != CONFTYPE_TAPERALGO) {
4982         error("get_conftype_taperalgo: val.type is not CONFTYPE_TAPERALGO");
4983         /*NOTREACHED*/
4984     }
4985     return val->v.i;
4986 }
4987
4988 int
4989 get_conftype_priority(
4990     val_t *val)
4991 {
4992     if (val->type != CONFTYPE_PRIORITY) {
4993         error("get_conftype_priority: val.type is not CONFTYPE_PRIORITY");
4994         /*NOTREACHED*/
4995     }
4996     return val->v.i;
4997 }
4998
4999 exinclude_t
5000 get_conftype_exinclude(
5001     val_t *val)
5002 {
5003     if (val->type != CONFTYPE_EXINCLUDE) {
5004         error("get_conftype_exinclude: val.type is not CONFTYPE_EXINCLUDE");
5005         /*NOTREACHED*/
5006     }
5007     return val->v.exinclude;
5008 }
5009
5010
5011 static void
5012 read_block(
5013     command_option_t *command_options,
5014     t_conf_var    *read_var,
5015     keytab_t *keytab,
5016     val_t    *valarray,
5017     char     *prefix,
5018     char     *errormsg,
5019     int       read_brace,
5020     void      (*copy_function)(void))
5021 {
5022     t_conf_var *np;
5023     int    saved_conf_line_num;
5024     int    done;
5025
5026     if(read_brace) {
5027         get_conftoken(CONF_LBRACE);
5028         get_conftoken(CONF_NL);
5029     }
5030
5031     done = 0;
5032     do {
5033         conf_line_num += 1;
5034         get_conftoken(CONF_ANY);
5035         switch(tok) {
5036         case CONF_RBRACE:
5037             done = 1;
5038             break;
5039         case CONF_NL:   /* empty line */
5040             break;
5041         case CONF_END:  /* end of file */
5042             done = 1;
5043             break;
5044         case CONF_IDENT:
5045         case CONF_STRING:
5046             if(copy_function) 
5047                 copy_function();
5048             else
5049                 conf_parserror("ident not expected");
5050             break;
5051         default:
5052             {
5053                 for(np = read_var; np->token != CONF_UNKNOWN; np++)
5054                     if(np->token == tok) break;
5055
5056                 if(np->token == CONF_UNKNOWN)
5057                     conf_parserror(errormsg);
5058                 else {
5059                     np->read_function(np, &valarray[np->parm]);
5060                     if(np->validate)
5061                         np->validate(np, &valarray[np->parm]);
5062                 }
5063             }
5064         }
5065         if(tok != CONF_NL && tok != CONF_END && tok != CONF_RBRACE)
5066             get_conftoken(CONF_NL);
5067     } while(!done);
5068
5069     /* overwrite with command line option */
5070     saved_conf_line_num = conf_line_num;
5071     command_overwrite(command_options, read_var, keytab, valarray, prefix);
5072     conf_line_num = saved_conf_line_num;
5073 }
5074
5075 void
5076 command_overwrite(
5077     command_option_t *command_options,
5078     t_conf_var    *overwrite_var,
5079     keytab_t *keytab,
5080     val_t    *valarray,
5081     char     *prefix)
5082 {
5083     t_conf_var       *np;
5084     keytab_t         *kt;
5085     char             *myprefix;
5086     command_option_t *command_option;
5087     int               duplicate;
5088
5089     if(!command_options) return;
5090
5091     for(np = overwrite_var; np->token != CONF_UNKNOWN; np++) {
5092         for(kt = keytab; kt->token != CONF_UNKNOWN; kt++)
5093             if(kt->token == np->token) break;
5094
5095         if(kt->token == CONF_UNKNOWN) {
5096             error("command_overwrite: invalid token");
5097             /* NOTREACHED */
5098         }
5099
5100         for(command_option = command_options; command_option->name != NULL;
5101                                                             command_option++) {
5102             myprefix = stralloc2(prefix, kt->keyword);
5103             if(strcasecmp(myprefix, command_option->name) == 0) {
5104                 duplicate = 0;
5105                 if (command_option->used == 0 &&
5106                     valarray[np->parm].seen == -2) {
5107                     duplicate = 1;
5108                 }
5109                 command_option->used = 1;
5110                 valarray[np->parm].seen = -2;
5111                 if(np->type == CONFTYPE_STRING &&
5112                    command_option->value[0] != '"') {
5113                     conf_line = vstralloc("\"", command_option->value, "\"",
5114                                           NULL);
5115                 }
5116                 else {
5117                     conf_line = stralloc(command_option->value);
5118                 }
5119                 conf_char = conf_line;
5120                 token_pushed = 0;
5121                 conf_line_num = -2;
5122                 np->read_function(np, &valarray[np->parm]);
5123                 amfree(conf_line);
5124                 conf_line = conf_char = NULL;
5125
5126                 if (np->validate)
5127                     np->validate(np, &valarray[np->parm]);
5128                 if (duplicate == 1) {
5129                     fprintf(stderr,"Duplicate %s option, using %s\n",
5130                             command_option->name, command_option->value);
5131                 }
5132             }
5133             amfree(myprefix);
5134         }
5135     }
5136 }
5137
5138 void
5139 free_new_argv(
5140     int new_argc,
5141     char **new_argv)
5142 {
5143     int i;
5144     for(i=0; i<new_argc; i++)
5145         amfree(new_argv[i]);
5146     amfree(new_argv);
5147 }
5148
5149 ssize_t
5150 getconf_readblocksize(void)
5151 {
5152     tapetype_t *tape;
5153     char       *conf_tapetype;
5154
5155     if (conffile_init == 1) {
5156         conf_tapetype = getconf_str(CNF_TAPETYPE);
5157
5158         if (!conf_tapetype || strlen(conf_tapetype) == 0)
5159             return MAX_TAPE_BLOCK_KB;
5160
5161         tape = lookup_tapetype(conf_tapetype);
5162         if (!tape)
5163             return MAX_TAPE_BLOCK_KB;
5164         return tapetype_get_readblocksize(tape);
5165     }
5166
5167     return MAX_TAPE_BLOCK_KB;
5168 }