1 /*
2  * Amanda, The Advanced Maryland Automatic Network Disk Archiver
3  * Copyright (c) 1991-2000 University of Maryland at College Park
4  * Copyright (c) 2007-2013 Zmanda, Inc.  All Rights Reserved.
5  * All Rights Reserved.
6  *
7  * Permission to use, copy, modify, distribute, and sell this software and its
8  * documentation for any purpose is hereby granted without fee, provided that
9  * the above copyright notice appear in all copies and that both that
10  * copyright notice and this permission notice appear in supporting
11  * documentation, and that the name of U.M. not be used in advertising or
12  * publicity pertaining to distribution of the software without specific,
13  * written prior permission.  U.M. makes no representations about the
14  * suitability of this software for any purpose.  It is provided "as is"
15  * without express or implied warranty.
16  *
17  * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M.
19  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
21  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
22  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23  *
24  * Author: James da Silva, Systems Design and Analysis Group
25  *			   Computer Science Department
26  *			   University of Maryland at College Park
27  */
28 /*
29  * $Id: conffile.c,v 1.156 2006/07/26 15:17:37 martinea Exp $
30  *
31  * read configuration file
32  */
33 
34 #include "amanda.h"
35 #include "arglist.h"
36 #include "util.h"
37 #include "conffile.h"
38 #include "clock.h"
39 #include <glib.h>
40 
41 /*
42  * Lexical analysis
43  */
44 
45 /* This module implements its own quixotic lexer and parser, present for historical
46  * reasons.  If this were written from scratch, it would use flex/bison. */
47 
48 /* An enumeration of the various tokens that might appear in a configuration file.
49  *
50  * - CONF_UNKNOWN has special meaning as an unrecognized token.
51  * - CONF_ANY can be used to request any token, rather than requiring a specific
52  *   token.
53  */
54 typedef enum {
55     CONF_UNKNOWN,		CONF_ANY,		CONF_COMMA,
56     CONF_LBRACE,		CONF_RBRACE,		CONF_NL,
57     CONF_END,			CONF_IDENT,		CONF_INT,
58     CONF_INT64,			CONF_BOOL,		CONF_REAL,
59     CONF_STRING,		CONF_TIME,		CONF_SIZE,
60 
61     /* config parameters */
62     CONF_INCLUDEFILE,		CONF_ORG,		CONF_MAILTO,
63     CONF_DUMPUSER,		CONF_TAPECYCLE,		CONF_TAPEDEV,
64     CONF_CHANGERDEV,		CONF_CHANGERFILE,	CONF_LABELSTR,
65     CONF_BUMPPERCENT,		CONF_BUMPSIZE,		CONF_BUMPDAYS,
66     CONF_BUMPMULT,		CONF_ETIMEOUT,		CONF_DTIMEOUT,
67     CONF_CTIMEOUT,		CONF_TAPELIST,
68     CONF_DEVICE_OUTPUT_BUFFER_SIZE,
69     CONF_DISKFILE,		CONF_INFOFILE,		CONF_LOGDIR,
70     CONF_LOGFILE,		CONF_DISKDIR,		CONF_DISKSIZE,
71     CONF_INDEXDIR,		CONF_NETUSAGE,		CONF_INPARALLEL,
72     CONF_DUMPORDER,		CONF_TIMEOUT,		CONF_TPCHANGER,
73     CONF_RUNTAPES,		CONF_DEFINE,		CONF_DUMPTYPE,
74     CONF_TAPETYPE,		CONF_INTERFACE,		CONF_PRINTER,
75     CONF_MAILER,
76     CONF_AUTOFLUSH,		CONF_RESERVE,		CONF_MAXDUMPSIZE,
77     CONF_COLUMNSPEC,		CONF_AMRECOVER_DO_FSF,	CONF_AMRECOVER_CHECK_LABEL,
78     CONF_AMRECOVER_CHANGER,	CONF_LABEL_NEW_TAPES,	CONF_USETIMESTAMPS,
79     CONF_CHANGER,
80 
81     CONF_TAPERALGO,		CONF_FIRST,		CONF_FIRSTFIT,
82     CONF_LARGEST,		CONF_LARGESTFIT,	CONF_SMALLEST,
83     CONF_LAST,			CONF_DISPLAYUNIT,	CONF_RESERVED_UDP_PORT,
84     CONF_RESERVED_TCP_PORT,	CONF_UNRESERVED_TCP_PORT,
85     CONF_TAPERFLUSH,
86     CONF_FLUSH_THRESHOLD_DUMPED,
87     CONF_FLUSH_THRESHOLD_SCHEDULED,
88     CONF_DEVICE_PROPERTY,      CONF_PROPERTY,		CONF_PLUGIN,
89     CONF_APPLICATION,          CONF_APPLICATION_TOOL,
90     CONF_SCRIPT,               CONF_SCRIPT_TOOL,
91     CONF_EXECUTE_ON,           CONF_EXECUTE_WHERE,	CONF_SEND_AMREPORT_ON,
92     CONF_DEVICE,               CONF_ORDER,		CONF_SINGLE_EXECUTION,
93     CONF_DATA_PATH,            CONF_AMANDA,		CONF_DIRECTTCP,
94     CONF_TAPER_PARALLEL_WRITE, CONF_INTERACTIVITY,	CONF_TAPERSCAN,
95     CONF_MAX_DLE_BY_VOLUME,    CONF_EJECT_VOLUME,	CONF_TMPDIR,
96     CONF_REPORT_USE_MEDIA,     CONF_REPORT_NEXT_MEDIA,  CONF_REPORT_FORMAT,
97 
98     /* execute on */
99     CONF_PRE_AMCHECK,          CONF_POST_AMCHECK,
100     CONF_PRE_DLE_AMCHECK,      CONF_PRE_HOST_AMCHECK,
101     CONF_POST_DLE_AMCHECK,     CONF_POST_HOST_AMCHECK,
102     CONF_PRE_ESTIMATE,         CONF_POST_ESTIMATE,
103     CONF_PRE_DLE_ESTIMATE,     CONF_PRE_HOST_ESTIMATE,
104     CONF_POST_DLE_ESTIMATE,    CONF_POST_HOST_ESTIMATE,
105     CONF_PRE_BACKUP,           CONF_POST_BACKUP,
106     CONF_PRE_DLE_BACKUP,       CONF_PRE_HOST_BACKUP,
107     CONF_POST_DLE_BACKUP,      CONF_POST_HOST_BACKUP,
108     CONF_PRE_RECOVER,	       CONF_POST_RECOVER,
109     CONF_PRE_LEVEL_RECOVER,    CONF_POST_LEVEL_RECOVER,
110     CONF_INTER_LEVEL_RECOVER,
111 
112     /* kerberos 5 */
113     CONF_KRB5KEYTAB,		CONF_KRB5PRINCIPAL,
114 
115     /* holding disk */
116     CONF_COMMENT,		CONF_DIRECTORY,		CONF_USE,
117     CONF_CHUNKSIZE,
118 
119     /* dump type */
120     /*COMMENT,*/		CONF_PROGRAM,		CONF_DUMPCYCLE,
121     CONF_RUNSPERCYCLE,		CONF_MAXCYCLE,		CONF_MAXDUMPS,
122     CONF_OPTIONS,		CONF_PRIORITY,		CONF_FREQUENCY,
123     CONF_INDEX,			CONF_MAXPROMOTEDAY,	CONF_STARTTIME,
124     CONF_COMPRESS,		CONF_ENCRYPT,		CONF_AUTH,
125     CONF_STRATEGY,		CONF_ESTIMATE,		CONF_SKIP_INCR,
126     CONF_SKIP_FULL,		CONF_RECORD,		CONF_HOLDING,
127     CONF_EXCLUDE,		CONF_INCLUDE,		CONF_KENCRYPT,
128     CONF_IGNORE,		CONF_COMPRATE,		CONF_TAPE_SPLITSIZE,
129     CONF_SPLIT_DISKBUFFER,	CONF_FALLBACK_SPLITSIZE,CONF_SRVCOMPPROG,
130     CONF_CLNTCOMPPROG,		CONF_SRV_ENCRYPT,	CONF_CLNT_ENCRYPT,
131     CONF_SRV_DECRYPT_OPT,	CONF_CLNT_DECRYPT_OPT,	CONF_AMANDAD_PATH,
132     CONF_CLIENT_USERNAME,	CONF_CLIENT_PORT,	CONF_ALLOW_SPLIT,
133     CONF_MAX_WARNINGS,
134 
135     /* tape type */
136     /*COMMENT,*/		CONF_BLOCKSIZE,
137     CONF_LBL_TEMPL,		CONF_FILEMARK,		CONF_LENGTH,
138     CONF_SPEED,			CONF_READBLOCKSIZE,
139 
140     /* client conf */
141     CONF_CONF,			CONF_INDEX_SERVER,	CONF_TAPE_SERVER,
142     CONF_SSH_KEYS,		CONF_GNUTAR_LIST_DIR,	CONF_AMANDATES,
143     CONF_AMDUMP_SERVER,
144 
145     /* protocol config */
146     CONF_REP_TRIES,		CONF_CONNECT_TRIES,	CONF_REQ_TRIES,
147 
148     /* debug config */
149     CONF_DEBUG_DAYS,
150     CONF_DEBUG_AMANDAD,		CONF_DEBUG_AMIDXTAPED,	CONF_DEBUG_AMINDEXD,
151     CONF_DEBUG_AMRECOVER,	CONF_DEBUG_AUTH,	CONF_DEBUG_EVENT,
152     CONF_DEBUG_HOLDING,		CONF_DEBUG_PROTOCOL,	CONF_DEBUG_PLANNER,
153     CONF_DEBUG_DRIVER,		CONF_DEBUG_DUMPER,	CONF_DEBUG_CHUNKER,
154     CONF_DEBUG_TAPER,		CONF_DEBUG_SELFCHECK,	CONF_DEBUG_SENDSIZE,
155     CONF_DEBUG_SENDBACKUP,	CONF_DEBUG_RECOVERY,
156 
157     /* network interface */
158     /* COMMENT, */		/* USE, */
159 
160     /* dump options (obsolete) */
161     CONF_EXCLUDE_FILE,		CONF_EXCLUDE_LIST,
162 
163     /* compress, estimate, encryption */
164     CONF_NONE,			CONF_FAST,		CONF_BEST,
165     CONF_SERVER,		CONF_CLIENT,		CONF_CALCSIZE,
166     CONF_CUSTOM,
167 
168     /* autolabel */
169     CONF_AUTOLABEL,		CONF_ANY_VOLUME,	CONF_OTHER_CONFIG,
170     CONF_NON_AMANDA,		CONF_VOLUME_ERROR,	CONF_EMPTY,
171     CONF_META_AUTOLABEL,
172 
173     /* part_cache_type */
174     CONF_PART_SIZE,		CONF_PART_CACHE_TYPE,	CONF_PART_CACHE_DIR,
175     CONF_PART_CACHE_MAX_SIZE,	CONF_DISK,		CONF_MEMORY,
176 
177     /* host-limit */
178     CONF_RECOVERY_LIMIT,	CONF_SAME_HOST,		CONF_DUMP_LIMIT,
179 
180     /* holdingdisk */
181     CONF_NEVER,			CONF_AUTO,		CONF_REQUIRED,
182 
183     /* send_amreport */
184     CONF_ALL,			CONF_STRANGE,		CONF_ERROR,
185 
186     /* priority */
187     CONF_LOW,			CONF_MEDIUM,		CONF_HIGH,
188 
189     /* dump strategy */
190     CONF_SKIP,			CONF_STANDARD,		CONF_NOFULL,
191     CONF_NOINC,			CONF_HANOI,		CONF_INCRONLY,
192 
193     /* exclude list */
194     CONF_LIST,			CONF_EFILE,		CONF_APPEND,
195     CONF_OPTIONAL,
196 
197     /* numbers */
198     CONF_AMINFINITY,		CONF_MULT1,		CONF_MULT7,
199     CONF_MULT1K,		CONF_MULT1M,		CONF_MULT1G,
200     CONF_MULT1T,
201 
202     /* boolean */
203     CONF_ATRUE,			CONF_AFALSE,
204 
205     CONF_CLIENT_NAME,
206 } tok_t;
207 
208 /* A keyword table entry, mapping the given keyword to the given token.
209  * Note that punctuation, integers, and quoted strings are handled
210  * internally to the lexer, so they do not appear here. */
211 typedef struct {
212     char *keyword;
213     tok_t token;
214 } keytab_t;
215 
216 /* The current keyword table, used by all token-related functions */
217 static keytab_t *keytable = NULL;
218 
219 /* Has a token been "ungotten", and if so, what was it? */
220 static int token_pushed;
221 static tok_t pushed_tok;
222 
223 /* The current token and its value.  Note that, unlike most other val_t*,
224  * tokenval's v.s points to statically allocated memory which cannot be
225  * free()'d. */
226 static tok_t tok;
227 static val_t tokenval;
228 
229 /* The current input information: file, filename, line, and character
230  * (which points somewhere within current_line) */
231 static FILE *current_file = NULL;
232 static char *current_filename = NULL;
233 static char *current_line = NULL;
234 static char *current_char = NULL;
235 static char *current_block = NULL;
236 static int current_line_num = 0; /* (technically, managed by the parser) */
237 
238 /* A static buffer for storing tokens while they are being scanned. */
239 static char tkbuf[4096];
240 
241 /* Return a token formated for output */
242 static char *str_keyword(keytab_t *kt);
243 
244 static char *str_keyword(keytab_t *kt);
245 /* Look up the name of the given token in the current keytable */
246 static char *get_token_name(tok_t);
247 
248 /* Look up a token in keytable, given a string, returning CONF_UNKNOWN
249  * for unrecognized strings.  Search is case-insensitive. */
250 static tok_t lookup_keyword(char *str);
251 
252 /* Get the next token.  If exp is anything but CONF_ANY, and the next token
253  * does not match, then a parse error is flagged.  This function reads from the
254  * current_* static variables, recognizes keywords against the keytable static
255  * variable, and places its result in tok and tokenval. */
256 static void get_conftoken(tok_t exp);
257 
258 /* "Unget" the current token; this supports a 1-token lookahead. */
259 static void unget_conftoken(void);
260 
261 /* Tokenizer character-by-character access. */
262 static int  conftoken_getc(void);
263 static int  conftoken_ungetc(int c);
264 
265 static void merge_proplist_foreach_fn(gpointer key_p,
266                                       gpointer value_p,
267                                       gpointer user_data_p);
268 static void copy_proplist_foreach_fn(gpointer key_p,
269                                      gpointer value_p,
270                                      gpointer user_data_p);
271 
272 /*
273  * Parser
274  */
275 
276 /* A parser table entry.  Read as "<token> introduces parameter <parm>,
277  * the data for which will be read by <read_function> and validated by
278  * <validate_function> (if not NULL).  <type> is only used in formatting
279  * config overwrites. */
280 typedef struct conf_var_s {
281     tok_t	token;
282     conftype_t	type;
283     void	(*read_function) (struct conf_var_s *, val_t*);
284     int		parm;
285     void	(*validate_function) (struct conf_var_s *, val_t *);
286 } conf_var_t;
287 
288 /* This is a list of filenames that are used in 'seen_t' structs. */
289 static GSList *seen_filenames = NULL;
290 
291 /* get a copy of filename that's stored in seen_filenames so that it won't go
292  * away until config_uninit. */
293 static char *get_seen_filename(char *filename);
294 
295 /* If allow_overwrites is true, the a parameter which has already been
296  * seen will simply overwrite the old value, rather than triggering an
297  * error.  Note that this does not apply to all parameters, e.g.,
298  * device_property */
299 static int allow_overwrites;
300 
301 /* subsection structs
302  *
303  * The 'seen' fields in these structs are useless outside this module;
304  * they are only used to generate error messages for multiply defined
305  * subsections.
306  */
307 struct tapetype_s {
308     struct tapetype_s *next;
309     seen_t seen;
310     char *name;
311 
312     val_t value[TAPETYPE_TAPETYPE];
313 };
314 
315 struct dumptype_s {
316     struct dumptype_s *next;
317     seen_t seen;
318     char *name;
319 
320     val_t value[DUMPTYPE_DUMPTYPE];
321 };
322 
323 struct interface_s {
324     struct interface_s *next;
325     seen_t seen;
326     char *name;
327 
328     val_t value[INTER_INTER];
329 };
330 
331 struct holdingdisk_s {
332     seen_t seen;
333     char *name;
334 
335     val_t value[HOLDING_HOLDING];
336 };
337 
338 struct application_s {
339     struct application_s *next;
340     seen_t seen;
341     char *name;
342 
343     val_t value[APPLICATION_APPLICATION];
344 };
345 
346 struct pp_script_s {
347     struct pp_script_s *next;
348     seen_t seen;
349     char *name;
350 
351     val_t value[PP_SCRIPT_PP_SCRIPT];
352 };
353 
354 struct device_config_s {
355     struct device_config_s *next;
356     seen_t seen;
357     char *name;
358 
359     val_t value[DEVICE_CONFIG_DEVICE_CONFIG];
360 };
361 
362 struct changer_config_s {
363     struct changer_config_s *next;
364     seen_t seen;
365     char *name;
366 
367     val_t value[CHANGER_CONFIG_CHANGER_CONFIG];
368 };
369 
370 struct interactivity_s {
371     struct interactivity_s *next;
372     seen_t seen;
373     char *name;
374 
375     val_t value[INTERACTIVITY_INTERACTIVITY];
376 };
377 
378 struct taperscan_s {
379     struct taperscan_s *next;
380     seen_t seen;
381     char *name;
382 
383     val_t value[TAPERSCAN_TAPERSCAN];
384 };
385 
386 /* The current parser table */
387 static conf_var_t *parsetable = NULL;
388 
389 /* Read and parse a configuration file, recursively reading any included
390  * files.  This function sets the keytable and parsetable appropriately
391  * according to is_client.
392  *
393  * @param filename: configuration file to read
394  * @param is_client: true if this is a client
395  * @param missing_ok: is it OK if the file is missing?
396  */
397 static void read_conffile(char *filename,
398 			  gboolean is_client,
399 			  gboolean missing_ok);
400 
401 /* Read and process a line of input from the current file, using the
402  * current keytable and parsetable.  For blocks, this recursively
403  * reads the entire block.
404  *
405  * @param is_client: true if this is a client
406  * @returns: true on success, false on EOF
407  */
408 static gboolean read_confline(gboolean is_client);
409 
410 /* Handle an invalid token, recognizing deprecated tokens as such,
411  * and producing an appropriate error message.
412  *
413  * @param token: the identifier
414  */
415 static void handle_invalid_keyword(const char * token);
416 
417 /* Check whether token is deprecated, and issue a warning if it
418  * is.  This consults the global variables 'tok' and 'tokenval'
419  */
420 static void handle_deprecated_keyword(void);
421 
422 /* Read a brace-delimited block using the given parse table.  This
423  * function is used to read brace-delimited subsections in the config
424  * files and also (via read_dumptype) to read dumptypes from
425  * the disklist.
426  *
427  * This function implements "inheritance" as follows: if a bare
428  * identifier occurs within the braces, it calls copy_function (if
429  * not NULL), which looks up an existing subsection using the
430  * identifier from tokenval and copies any values not already seen
431  * into valarray.
432  *
433  * @param read_var: the parse table to use
434  * @param valarray: the (pre-initialized) val_t array to fill in
435  * @param errormsg: error message to display for unrecognized keywords
436  * @param read_brace: if true, read the opening brace
437  * @param copy_function: function to copy configuration from
438  *     another subsection into this one.
439  */
440 static void read_block(conf_var_t *read_var, val_t *valarray,
441 		       char *errormsg, int read_brace,
442 		       void (*copy_function)(void),
443 		       char *type, char *name);
444 
445 /* For each subsection type, we have a global and  four functions:
446  *  - foocur is a temporary struct used to assemble new subsections
447  *  - get_foo is called after reading "DEFINE FOO", and
448  *    is responsible for reading the entire block, using
449  *    read_block()
450  *  - init_foo_defaults initializes a new subsection struct
451  *    to its default values
452  *  - save_foo copies foocur to a newly allocated struct and
453  *    inserts that into the relevant list.
454  *  - copy_foo implements inheritance as described in read_block()
455  */
456 static holdingdisk_t hdcur;
457 static void get_holdingdisk(int is_define);
458 static void init_holdingdisk_defaults(void);
459 static void save_holdingdisk(void);
460 static void copy_holdingdisk(void);
461 
462 static dumptype_t dpcur;
463 static void get_dumptype(void);
464 static void init_dumptype_defaults(void);
465 static void save_dumptype(void);
466 static void copy_dumptype(void);
467 
468 static tapetype_t tpcur;
469 static void get_tapetype(void);
470 static void init_tapetype_defaults(void);
471 static void save_tapetype(void);
472 static void copy_tapetype(void);
473 
474 static interface_t ifcur;
475 static void get_interface(void);
476 static void init_interface_defaults(void);
477 static void save_interface(void);
478 static void copy_interface(void);
479 
480 static application_t apcur;
481 static void get_application(void);
482 static void init_application_defaults(void);
483 static void save_application(void);
484 static void copy_application(void);
485 
486 static pp_script_t pscur;
487 static void get_pp_script(void);
488 static void init_pp_script_defaults(void);
489 static void save_pp_script(void);
490 static void copy_pp_script(void);
491 
492 static device_config_t dccur;
493 static void get_device_config(void);
494 static void init_device_config_defaults(void);
495 static void save_device_config(void);
496 static void copy_device_config(void);
497 
498 static changer_config_t cccur;
499 static void get_changer_config(void);
500 static void init_changer_config_defaults(void);
501 static void save_changer_config(void);
502 static void copy_changer_config(void);
503 
504 static interactivity_t ivcur;
505 static void get_interactivity(void);
506 static void init_interactivity_defaults(void);
507 static void save_interactivity(void);
508 static void copy_interactivity(void);
509 
510 static taperscan_t tscur;
511 static void get_taperscan(void);
512 static void init_taperscan_defaults(void);
513 static void save_taperscan(void);
514 static void copy_taperscan(void);
515 
516 /* read_functions -- these fit into the read_function slot in a parser
517  * table entry, and are responsible for calling getconf_token as necessary
518  * to consume their arguments, and setting their second argument with the
519  * result.  The first argument is a copy of the parser table entry, if
520  * needed. */
521 static void read_int(conf_var_t *, val_t *);
522 static void read_int64(conf_var_t *, val_t *);
523 static void read_real(conf_var_t *, val_t *);
524 static void read_str(conf_var_t *, val_t *);
525 static void read_str_list(conf_var_t *, val_t *);
526 static void read_ident(conf_var_t *, val_t *);
527 static void read_time(conf_var_t *, val_t *);
528 static void read_size(conf_var_t *, val_t *);
529 static void read_bool(conf_var_t *, val_t *);
530 static void read_no_yes_all(conf_var_t *, val_t *);
531 static void read_compress(conf_var_t *, val_t *);
532 static void read_encrypt(conf_var_t *, val_t *);
533 static void read_holding(conf_var_t *, val_t *);
534 static void read_estimatelist(conf_var_t *, val_t *);
535 static void read_strategy(conf_var_t *, val_t *);
536 static void read_taperalgo(conf_var_t *, val_t *);
537 static void read_send_amreport_on(conf_var_t *, val_t *);
538 static void read_data_path(conf_var_t *, val_t *);
539 static void read_priority(conf_var_t *, val_t *);
540 static void read_rate(conf_var_t *, val_t *);
541 static void read_exinclude(conf_var_t *, val_t *);
542 static void read_intrange(conf_var_t *, val_t *);
543 static void read_dapplication(conf_var_t *, val_t *);
544 static void read_dinteractivity(conf_var_t *, val_t *);
545 static void read_dtaperscan(conf_var_t *, val_t *);
546 static void read_dpp_script(conf_var_t *, val_t *);
547 static void read_property(conf_var_t *, val_t *);
548 static void read_execute_on(conf_var_t *, val_t *);
549 static void read_execute_where(conf_var_t *, val_t *);
550 static void read_holdingdisk(conf_var_t *, val_t *);
551 static void read_int_or_str(conf_var_t *, val_t *);
552 static void read_autolabel(conf_var_t *, val_t *);
553 static void read_part_cache_type(conf_var_t *, val_t *);
554 static void read_host_limit(conf_var_t *, val_t *);
555 
556 static application_t *read_application(char *name, FILE *from, char *fname,
557 				       int *linenum);
558 static pp_script_t *read_pp_script(char *name, FILE *from, char *fname,
559 				   int *linenum);
560 static device_config_t *read_device_config(char *name, FILE *from, char *fname,
561 					   int *linenum);
562 static changer_config_t *read_changer_config(char *name, FILE *from,
563 					     char *fname, int *linenum);
564 static interactivity_t *read_interactivity(char *name, FILE *from,
565 					   char *fname, int *linenum);
566 static taperscan_t *read_taperscan(char *name, FILE *from, char *fname,
567 				   int *linenum);
568 /* Functions to get various types of values.  These are called by
569  * read_functions to take care of any variations in the way that these
570  * values can be written: integers can have units, boolean values can be
571  * specified with a number of names, etc.  They form utility functions
572  * for the read_functions, below. */
573 static gint64 get_multiplier(gint64 val, confunit_t unit);
574 static time_t  get_time(void);
575 static int     get_int(confunit_t unit);
576 static ssize_t get_size(confunit_t unit);
577 static gint64  get_int64(confunit_t unit);
578 static int     get_bool(void);
579 static int     get_no_yes_all(void);
580 
581 /* Check the given 'seen', flagging an error if this value has already
582  * been seen and allow_overwrites is false.  Also marks the value as
583  * seen on the current line.
584  *
585  * @param seen: (in/out) seen value to adjust
586  */
587 static void ckseen(seen_t *seen);
588 
589 /* validate_functions -- these fit into the validate_function solt in
590  * a parser table entry.  They call conf_parserror if the value in their
591  * second argument is invalid.  */
592 static void validate_nonnegative(conf_var_t *, val_t *);
593 static void validate_non_zero(conf_var_t *, val_t *);
594 static void validate_positive(conf_var_t *, val_t *);
595 static void validate_runspercycle(conf_var_t *, val_t *);
596 static void validate_bumppercent(conf_var_t *, val_t *);
597 static void validate_bumpmult(conf_var_t *, val_t *);
598 static void validate_inparallel(conf_var_t *, val_t *);
599 static void validate_displayunit(conf_var_t *, val_t *);
600 static void validate_reserve(conf_var_t *, val_t *);
601 static void validate_use(conf_var_t *, val_t *);
602 static void validate_chunksize(conf_var_t *, val_t *);
603 static void validate_blocksize(conf_var_t *, val_t *);
604 static void validate_debug(conf_var_t *, val_t *);
605 static void validate_port_range(val_t *, int, int);
606 static void validate_reserved_port_range(conf_var_t *, val_t *);
607 static void validate_unreserved_port_range(conf_var_t *, val_t *);
608 static void validate_program(conf_var_t *, val_t *);
609 static void validate_dump_limit(conf_var_t *, val_t *);
610 static void validate_tmpdir(conf_var_t *, val_t *);
611 
612 gint compare_pp_script_order(gconstpointer a, gconstpointer b);
613 
614 /*
615  * Initialization
616  */
617 
618 /* The name of the configuration under which this application is running.
619  * This variable is initialized by config_init.
620  */
621 static char *config_name = NULL;
622 
623 /* The directory containing the configuration for this application.  This
624  * variable is initialized by config_init
625  */
626 static char *config_dir = NULL;
627 
628 /* The most recently read top-level configuration file.  This variable is
629  * initialized by config_init
630  */
631 static char *config_filename = NULL;
632 
633 /* Has the config been initialized? */
634 static gboolean config_initialized = FALSE;
635 
636 /* Are we running a client? (true if last init was
637  * with CONFIG_INIT_CLIENT) */
638 static gboolean config_client = FALSE;
639 
640 /* What config overwrites to use? */
641 static config_overrides_t *config_overrides = NULL;
642 
643 /* All global parameters */
644 static val_t conf_data[CNF_CNF];
645 
646 /* Linked list of holding disks */
647 static GSList *holdinglist = NULL;
648 static dumptype_t *dumplist = NULL;
649 static tapetype_t *tapelist = NULL;
650 static interface_t *interface_list = NULL;
651 static application_t *application_list = NULL;
652 static pp_script_t *pp_script_list = NULL;
653 static device_config_t *device_config_list = NULL;
654 static changer_config_t *changer_config_list = NULL;
655 static interactivity_t *interactivity_list = NULL;
656 static taperscan_t *taperscan_list = NULL;
657 
658 /* storage for derived values */
659 static long int unit_divisor = 1;
660 
661 int debug_amandad    = 0;
662 int debug_recovery   = 0;
663 int debug_amidxtaped = 0;
664 int debug_amindexd   = 0;
665 int debug_amrecover  = 0;
666 int debug_auth       = 0;
667 int debug_event      = 0;
668 int debug_holding    = 0;
669 int debug_protocol   = 0;
670 int debug_planner    = 0;
671 int debug_driver     = 0;
672 int debug_dumper     = 0;
673 int debug_chunker    = 0;
674 int debug_taper      = 0;
675 int debug_selfcheck  = 0;
676 int debug_sendsize   = 0;
677 int debug_sendbackup = 0;
678 
679 /* Reset all configuration values to their defaults (which, in many
680  * cases, come from --with-foo options at build time) */
681 static void init_defaults(void);
682 
683 /* Update all dervied values based on the current configuration.  This
684  * function can be called multiple times, once after each adjustment
685  * to the current configuration.
686  *
687  * @param is_client: are we running a client?
688  */
689 static void update_derived_values(gboolean is_client);
690 
691 static cfgerr_level_t apply_config_overrides(config_overrides_t *co,
692 					     char *key_ovr);
693 
694 /* per-type conf_init functions, used as utilities for init_defaults
695  * and for each subsection's init_foo_defaults.
696  *
697  * These set the value's type and seen flags, as well as copying
698  * the relevant value into the 'v' field.
699  */
700 static void conf_init_int(val_t *val, confunit_t unit, int i);
701 static void conf_init_int64(val_t *val, confunit_t unit, gint64 l);
702 static void conf_init_real(val_t *val, float r);
703 static void conf_init_str(val_t *val, char *s);
704 static void conf_init_ident(val_t *val, char *s);
705 static void conf_init_identlist(val_t *val, char *s);
706 static void conf_init_str_list(val_t *val, char *s);
707 static void conf_init_time(val_t *val, time_t t);
708 static void conf_init_size(val_t *val, confunit_t unit, ssize_t sz);
709 static void conf_init_bool(val_t *val, int i);
710 static void conf_init_no_yes_all(val_t *val, int i);
711 static void conf_init_compress(val_t *val, comp_t i);
712 static void conf_init_encrypt(val_t *val, encrypt_t i);
713 static void conf_init_data_path(val_t *val, data_path_t i);
714 static void conf_init_holding(val_t *val, dump_holdingdisk_t i);
715 static void conf_init_estimatelist(val_t *val, estimate_t i);
716 static void conf_init_execute_on(val_t *, int);
717 static void conf_init_execute_where(val_t *, int);
718 static void conf_init_send_amreport(val_t *val, send_amreport_t i);
719 static void conf_init_strategy(val_t *val, strategy_t);
720 static void conf_init_taperalgo(val_t *val, taperalgo_t i);
721 static void conf_init_priority(val_t *val, int i);
722 static void conf_init_rate(val_t *val, float r1, float r2);
723 static void conf_init_exinclude(val_t *val); /* to empty list */
724 static void conf_init_intrange(val_t *val, int i1, int i2);
725 static void conf_init_proplist(val_t *val); /* to empty list */
726 static void conf_init_application(val_t *val);
727 static void conf_init_autolabel(val_t *val);
728 static void conf_init_part_cache_type(val_t *val, part_cache_type_t i);
729 static void conf_init_host_limit(val_t *val);
730 static void conf_init_host_limit_server(val_t *val);
731 
732 /*
733  * Command-line Handling
734  */
735 
736 typedef struct config_override_s {
737     char     *key;
738     char     *value;
739     gboolean  applied;
740 } config_override_t;
741 
742 struct config_overrides_s {
743     int n_allocated;
744     int n_used;
745     config_override_t *ovr;
746 };
747 
748 /*
749  * val_t Management
750  */
751 
752 static void merge_val_t(val_t *, val_t *);
753 static void copy_val_t(val_t *, val_t *);
754 static void free_val_t(val_t *);
755 
756 /*
757  * Utilities
758  */
759 
760 /* memory handling */
761 void free_property_t(gpointer p);
762 
763 /* Utility functions/structs for val_t_display_strs */
764 static char *exinclude_display_str(val_t *val, int file);
765 static void proplist_display_str_foreach_fn(gpointer key_p, gpointer value_p, gpointer user_data_p);
766 static void val_t_print_token(gboolean print_default, gboolean print_source, FILE *output, char *prefix, char *format, keytab_t *kt, val_t *val);
767 
768 /* Given a key name as used in config overwrites, return a pointer to the corresponding
769  * conf_var_t in the current parsetable, and the val_t representing that value.  This
770  * function will access subsections if key has the form  TYPE:SUBSEC:KEYWORD.  Returns
771  * false if the value does not exist.
772  *
773  * Assumes keytable and parsetable are set correctly, which is generally OK after
774  * config_init has been called.
775  *
776  * @param key: the key to look up
777  * @param parm: (result) the parse table entry
778  * @param val: (result) the parameter value
779  * @returns: true on success
780  */
781 static int parm_key_info(char *key, conf_var_t **parm, val_t **val);
782 
783 /*
784  * Error handling
785  */
786 
787 /* Have we seen a parse error yet?  Parsing continues after an error, so this
788  * flag is checked after the parse is complete.
789  */
790 static cfgerr_level_t cfgerr_level;
791 static GSList *cfgerr_errors = NULL;
792 
793 static void conf_error_common(cfgerr_level_t level, const char * format, va_list argp);
794 static void    conf_parserror(const char *format, ...)
795                 __attribute__ ((format (printf, 1, 2)));
796 
797 static void    conf_parswarn(const char *format, ...)
798                 __attribute__ ((format (printf, 1, 2)));
799 
800 /*
801  * Tables
802  */
803 
804 /* First, the keyword tables for client and server */
805 keytab_t client_keytab[] = {
806     { "CONF", CONF_CONF },
807     { "AMDUMP_SERVER", CONF_AMDUMP_SERVER },
808     { "INDEX_SERVER", CONF_INDEX_SERVER },
809     { "TAPE_SERVER", CONF_TAPE_SERVER },
810     { "TAPEDEV", CONF_TAPEDEV },
811     { "AUTH", CONF_AUTH },
812     { "SSH_KEYS", CONF_SSH_KEYS },
813     { "AMANDAD_PATH", CONF_AMANDAD_PATH },
814     { "CLIENT_NAME", CONF_CLIENT_NAME },
815     { "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
816     { "CLIENT_PORT", CONF_CLIENT_PORT },
817     { "GNUTAR_LIST_DIR", CONF_GNUTAR_LIST_DIR },
818     { "AMANDATES", CONF_AMANDATES },
819     { "KRB5KEYTAB", CONF_KRB5KEYTAB },
820     { "KRB5PRINCIPAL", CONF_KRB5PRINCIPAL },
821     { "INCLUDEFILE", CONF_INCLUDEFILE },
822     { "CONNECT_TRIES", CONF_CONNECT_TRIES },
823     { "REP_TRIES", CONF_REP_TRIES },
824     { "REQ_TRIES", CONF_REQ_TRIES },
825     { "CLIENT", CONF_CLIENT },
826     { "DEBUG_DAYS", CONF_DEBUG_DAYS },
827     { "DEBUG_AMANDAD", CONF_DEBUG_AMANDAD },
828     { "DEBUG_RECOVERY", CONF_DEBUG_RECOVERY },
829     { "DEBUG_AMIDXTAPED", CONF_DEBUG_AMIDXTAPED },
830     { "DEBUG_AMINDEXD", CONF_DEBUG_AMINDEXD },
831     { "DEBUG_AMRECOVER", CONF_DEBUG_AMRECOVER },
832     { "DEBUG_AUTH", CONF_DEBUG_AUTH },
833     { "DEBUG_EVENT", CONF_DEBUG_EVENT },
834     { "DEBUG_HOLDING", CONF_DEBUG_HOLDING },
835     { "DEBUG_PROTOCOL", CONF_DEBUG_PROTOCOL },
836     { "DEBUG_PLANNER", CONF_DEBUG_PLANNER },
837     { "DEBUG_DRIVER", CONF_DEBUG_DRIVER },
838     { "DEBUG_DUMPER", CONF_DEBUG_DUMPER },
839     { "DEBUG_CHUNKER", CONF_DEBUG_CHUNKER },
840     { "DEBUG_TAPER", CONF_DEBUG_TAPER },
841     { "DEBUG_SELFCHECK", CONF_DEBUG_SELFCHECK },
842     { "DEBUG_SENDSIZE", CONF_DEBUG_SENDSIZE },
843     { "DEBUG_SENDBACKUP", CONF_DEBUG_SENDBACKUP },
844     { "EXECUTE_ON", CONF_EXECUTE_ON },
845     { "EXECUTE_WHERE", CONF_EXECUTE_WHERE },
846     { "RESERVED_UDP_PORT", CONF_RESERVED_UDP_PORT },
847     { "RESERVED_TCP_PORT", CONF_RESERVED_TCP_PORT },
848     { "UNRESERVED_TCP_PORT", CONF_UNRESERVED_TCP_PORT },
849     { "DEFINE", CONF_DEFINE },
850     { "COMMENT", CONF_COMMENT },
851     { "MAILER", CONF_MAILER },
852     { "ORDER", CONF_ORDER },
853     { "SCRIPT", CONF_SCRIPT },
854     { "SCRIPT_TOOL", CONF_SCRIPT_TOOL },
855     { "PLUGIN", CONF_PLUGIN },
856     { "PRE_AMCHECK", CONF_PRE_AMCHECK },
857     { "PRE_DLE_AMCHECK", CONF_PRE_DLE_AMCHECK },
858     { "PRE_HOST_AMCHECK", CONF_PRE_HOST_AMCHECK },
859     { "POST_AMCHECK", CONF_POST_AMCHECK },
860     { "POST_DLE_AMCHECK", CONF_POST_DLE_AMCHECK },
861     { "POST_HOST_AMCHECK", CONF_POST_HOST_AMCHECK },
862     { "PRE_ESTIMATE", CONF_PRE_ESTIMATE },
863     { "PRE_DLE_ESTIMATE", CONF_PRE_DLE_ESTIMATE },
864     { "PRE_HOST_ESTIMATE", CONF_PRE_HOST_ESTIMATE },
865     { "POST_ESTIMATE", CONF_POST_ESTIMATE },
866     { "POST_DLE_ESTIMATE", CONF_POST_DLE_ESTIMATE },
867     { "POST_HOST_ESTIMATE", CONF_POST_HOST_ESTIMATE },
868     { "POST_BACKUP", CONF_POST_BACKUP },
869     { "POST_DLE_BACKUP", CONF_POST_DLE_BACKUP },
870     { "POST_HOST_BACKUP", CONF_POST_HOST_BACKUP },
871     { "PRE_BACKUP", CONF_PRE_BACKUP },
872     { "PRE_DLE_BACKUP", CONF_PRE_DLE_BACKUP },
873     { "PRE_HOST_BACKUP", CONF_PRE_HOST_BACKUP },
874     { "PRE_RECOVER", CONF_PRE_RECOVER },
875     { "POST_RECOVER", CONF_POST_RECOVER },
876     { "PRE_LEVEL_RECOVER", CONF_PRE_LEVEL_RECOVER },
877     { "POST_LEVEL_RECOVER", CONF_POST_LEVEL_RECOVER },
878     { "INTER_LEVEL_RECOVER", CONF_INTER_LEVEL_RECOVER },
879     { "PRIORITY", CONF_PRIORITY },
880     { "PROPERTY", CONF_PROPERTY },
881     { "APPLICATION", CONF_APPLICATION },
882     { "APPLICATION_TOOL", CONF_APPLICATION_TOOL },
883     { "SERVER", CONF_SERVER },
884     { "APPEND", CONF_APPEND },
885     { NULL, CONF_IDENT },
886     { NULL, CONF_UNKNOWN }
887 };
888 
889 keytab_t server_keytab[] = {
890     { "ALL", CONF_ALL },
891     { "ALLOW_SPLIT", CONF_ALLOW_SPLIT },
892     { "AMANDA", CONF_AMANDA },
893     { "AMANDAD_PATH", CONF_AMANDAD_PATH },
894     { "AMRECOVER_CHANGER", CONF_AMRECOVER_CHANGER },
895     { "AMRECOVER_CHECK_LABEL", CONF_AMRECOVER_CHECK_LABEL },
896     { "AMRECOVER_DO_FSF", CONF_AMRECOVER_DO_FSF },
897     { "ANY", CONF_ANY_VOLUME },
898     { "APPEND", CONF_APPEND },
899     { "AUTH", CONF_AUTH },
900     { "AUTO", CONF_AUTO },
901     { "AUTOFLUSH", CONF_AUTOFLUSH },
902     { "AUTOLABEL", CONF_AUTOLABEL },
903     { "APPLICATION", CONF_APPLICATION },
904     { "APPLICATION_TOOL", CONF_APPLICATION_TOOL },
905     { "BEST", CONF_BEST },
906     { "BLOCKSIZE", CONF_BLOCKSIZE },
907     { "BUMPDAYS", CONF_BUMPDAYS },
908     { "BUMPMULT", CONF_BUMPMULT },
909     { "BUMPPERCENT", CONF_BUMPPERCENT },
910     { "BUMPSIZE", CONF_BUMPSIZE },
911     { "CALCSIZE", CONF_CALCSIZE },
912     { "CHANGER", CONF_CHANGER },
913     { "CHANGERDEV", CONF_CHANGERDEV },
914     { "CHANGERFILE", CONF_CHANGERFILE },
915     { "CHUNKSIZE", CONF_CHUNKSIZE },
916     { "CLIENT", CONF_CLIENT },
917     { "CLIENT_CUSTOM_COMPRESS", CONF_CLNTCOMPPROG },
918     { "CLIENT_DECRYPT_OPTION", CONF_CLNT_DECRYPT_OPT },
919     { "CLIENT_ENCRYPT", CONF_CLNT_ENCRYPT },
920     { "CLIENT_NAME", CONF_CLIENT_NAME },
921     { "CLIENT_USERNAME", CONF_CLIENT_USERNAME },
922     { "COLUMNSPEC", CONF_COLUMNSPEC },
923     { "COMMENT", CONF_COMMENT },
924     { "COMPRATE", CONF_COMPRATE },
925     { "COMPRESS", CONF_COMPRESS },
926     { "CONNECT_TRIES", CONF_CONNECT_TRIES },
927     { "CTIMEOUT", CONF_CTIMEOUT },
928     { "CUSTOM", CONF_CUSTOM },
929     { "DATA_PATH", CONF_DATA_PATH },
930     { "DEBUG_DAYS"       , CONF_DEBUG_DAYS },
931     { "DEBUG_AMANDAD"    , CONF_DEBUG_AMANDAD },
932     { "DEBUG_RECOVERY"   , CONF_DEBUG_RECOVERY },
933     { "DEBUG_AMIDXTAPED" , CONF_DEBUG_AMIDXTAPED },
934     { "DEBUG_AMINDEXD"   , CONF_DEBUG_AMINDEXD },
935     { "DEBUG_AMRECOVER"  , CONF_DEBUG_AMRECOVER },
936     { "DEBUG_AUTH"       , CONF_DEBUG_AUTH },
937     { "DEBUG_EVENT"      , CONF_DEBUG_EVENT },
938     { "DEBUG_HOLDING"    , CONF_DEBUG_HOLDING },
939     { "DEBUG_PROTOCOL"   , CONF_DEBUG_PROTOCOL },
940     { "DEBUG_PLANNER"    , CONF_DEBUG_PLANNER },
941     { "DEBUG_DRIVER"     , CONF_DEBUG_DRIVER },
942     { "DEBUG_DUMPER"     , CONF_DEBUG_DUMPER },
943     { "DEBUG_CHUNKER"    , CONF_DEBUG_CHUNKER },
944     { "DEBUG_TAPER"      , CONF_DEBUG_TAPER },
945     { "DEBUG_SELFCHECK"  , CONF_DEBUG_SELFCHECK },
946     { "DEBUG_SENDSIZE"   , CONF_DEBUG_SENDSIZE },
947     { "DEBUG_SENDBACKUP" , CONF_DEBUG_SENDBACKUP },
948     { "DEFINE", CONF_DEFINE },
949     { "DEVICE", CONF_DEVICE },
950     { "DEVICE_PROPERTY", CONF_DEVICE_PROPERTY },
951     { "DIRECTORY", CONF_DIRECTORY },
952     { "DIRECTTCP", CONF_DIRECTTCP },
953     { "DISK", CONF_DISK },
954     { "DISKFILE", CONF_DISKFILE },
955     { "DISPLAYUNIT", CONF_DISPLAYUNIT },
956     { "DTIMEOUT", CONF_DTIMEOUT },
957     { "DUMPCYCLE", CONF_DUMPCYCLE },
958     { "DUMPORDER", CONF_DUMPORDER },
959     { "DUMPTYPE", CONF_DUMPTYPE },
960     { "DUMPUSER", CONF_DUMPUSER },
961     { "DUMP_LIMIT", CONF_DUMP_LIMIT },
962     { "EJECT_VOLUME", CONF_EJECT_VOLUME },
963     { "EMPTY", CONF_EMPTY },
964     { "ENCRYPT", CONF_ENCRYPT },
965     { "ERROR", CONF_ERROR },
966     { "ESTIMATE", CONF_ESTIMATE },
967     { "ETIMEOUT", CONF_ETIMEOUT },
968     { "EXCLUDE", CONF_EXCLUDE },
969     { "EXCLUDE_FILE", CONF_EXCLUDE_FILE },
970     { "EXCLUDE_LIST", CONF_EXCLUDE_LIST },
971     { "EXECUTE_ON", CONF_EXECUTE_ON },
972     { "EXECUTE_WHERE", CONF_EXECUTE_WHERE },
973     { "FALLBACK_SPLITSIZE", CONF_FALLBACK_SPLITSIZE },
974     { "FAST", CONF_FAST },
975     { "FILE", CONF_EFILE },
976     { "FILEMARK", CONF_FILEMARK },
977     { "FIRST", CONF_FIRST },
978     { "FIRSTFIT", CONF_FIRSTFIT },
979     { "HANOI", CONF_HANOI },
980     { "HIGH", CONF_HIGH },
981     { "HOLDINGDISK", CONF_HOLDING },
982     { "IGNORE", CONF_IGNORE },
983     { "INCLUDE", CONF_INCLUDE },
984     { "INCLUDEFILE", CONF_INCLUDEFILE },
985     { "INCRONLY", CONF_INCRONLY },
986     { "INDEX", CONF_INDEX },
987     { "INDEXDIR", CONF_INDEXDIR },
988     { "INFOFILE", CONF_INFOFILE },
989     { "INPARALLEL", CONF_INPARALLEL },
990     { "INTERACTIVITY", CONF_INTERACTIVITY },
991     { "INTERFACE", CONF_INTERFACE },
992     { "KENCRYPT", CONF_KENCRYPT },
993     { "KRB5KEYTAB", CONF_KRB5KEYTAB },
994     { "KRB5PRINCIPAL", CONF_KRB5PRINCIPAL },
995     { "LABELSTR", CONF_LABELSTR },
996     { "LABEL_NEW_TAPES", CONF_LABEL_NEW_TAPES },
997     { "LARGEST", CONF_LARGEST },
998     { "LARGESTFIT", CONF_LARGESTFIT },
999     { "LAST", CONF_LAST },
1000     { "LBL_TEMPL", CONF_LBL_TEMPL },
1001     { "LENGTH", CONF_LENGTH },
1002     { "LIST", CONF_LIST },
1003     { "LOGDIR", CONF_LOGDIR },
1004     { "LOW", CONF_LOW },
1005     { "MAILER", CONF_MAILER },
1006     { "MAILTO", CONF_MAILTO },
1007     { "READBLOCKSIZE", CONF_READBLOCKSIZE },
1008     { "MAX_DLE_BY_VOLUME", CONF_MAX_DLE_BY_VOLUME },
1009     { "MAXDUMPS", CONF_MAXDUMPS },
1010     { "MAXDUMPSIZE", CONF_MAXDUMPSIZE },
1011     { "MAXPROMOTEDAY", CONF_MAXPROMOTEDAY },
1012     { "MAX_WARNINGS", CONF_MAX_WARNINGS },
1013     { "MEMORY", CONF_MEMORY },
1014     { "MEDIUM", CONF_MEDIUM },
1015     { "META_AUTOLABEL", CONF_META_AUTOLABEL },
1016     { "NETUSAGE", CONF_NETUSAGE },
1017     { "NEVER", CONF_NEVER },
1018     { "NOFULL", CONF_NOFULL },
1019     { "NOINC", CONF_NOINC },
1020     { "NONE", CONF_NONE },
1021     { "NON_AMANDA", CONF_NON_AMANDA },
1022     { "OPTIONAL", CONF_OPTIONAL },
1023     { "ORDER", CONF_ORDER },
1024     { "ORG", CONF_ORG },
1025     { "OTHER_CONFIG", CONF_OTHER_CONFIG },
1026     { "PART_CACHE_DIR", CONF_PART_CACHE_DIR },
1027     { "PART_CACHE_MAX_SIZE", CONF_PART_CACHE_MAX_SIZE },
1028     { "PART_CACHE_TYPE", CONF_PART_CACHE_TYPE },
1029     { "PART_SIZE", CONF_PART_SIZE },
1030     { "PLUGIN", CONF_PLUGIN },
1031     { "PRE_AMCHECK", CONF_PRE_AMCHECK },
1032     { "PRE_DLE_AMCHECK", CONF_PRE_DLE_AMCHECK },
1033     { "PRE_HOST_AMCHECK", CONF_PRE_HOST_AMCHECK },
1034     { "POST_AMCHECK", CONF_POST_AMCHECK },
1035     { "POST_DLE_AMCHECK", CONF_POST_DLE_AMCHECK },
1036     { "POST_HOST_AMCHECK", CONF_POST_HOST_AMCHECK },
1037     { "PRE_ESTIMATE", CONF_PRE_ESTIMATE },
1038     { "PRE_DLE_ESTIMATE", CONF_PRE_DLE_ESTIMATE },
1039     { "PRE_HOST_ESTIMATE", CONF_PRE_HOST_ESTIMATE },
1040     { "POST_ESTIMATE", CONF_POST_ESTIMATE },
1041     { "POST_DLE_ESTIMATE", CONF_POST_DLE_ESTIMATE },
1042     { "POST_HOST_ESTIMATE", CONF_POST_HOST_ESTIMATE },
1043     { "POST_BACKUP", CONF_POST_BACKUP },
1044     { "POST_DLE_BACKUP", CONF_POST_DLE_BACKUP },
1045     { "POST_HOST_BACKUP", CONF_POST_HOST_BACKUP },
1046     { "PRE_BACKUP", CONF_PRE_BACKUP },
1047     { "PRE_DLE_BACKUP", CONF_PRE_DLE_BACKUP },
1048     { "PRE_HOST_BACKUP", CONF_PRE_HOST_BACKUP },
1049     { "PRE_RECOVER", CONF_PRE_RECOVER },
1050     { "POST_RECOVER", CONF_POST_RECOVER },
1051     { "PRE_LEVEL_RECOVER", CONF_PRE_LEVEL_RECOVER },
1052     { "POST_LEVEL_RECOVER", CONF_POST_LEVEL_RECOVER },
1053     { "INTER_LEVEL_RECOVER", CONF_INTER_LEVEL_RECOVER },
1054     { "PRINTER", CONF_PRINTER },
1055     { "PRIORITY", CONF_PRIORITY },
1056     { "PROGRAM", CONF_PROGRAM },
1057     { "PROPERTY", CONF_PROPERTY },
1058     { "RECORD", CONF_RECORD },
1059     { "RECOVERY_LIMIT", CONF_RECOVERY_LIMIT },
1060     { "REP_TRIES", CONF_REP_TRIES },
1061     { "REPORT_FORMAT", CONF_REPORT_FORMAT },
1062     { "REPORT_NEXT_MEDIA", CONF_REPORT_NEXT_MEDIA },
1063     { "REPORT_USE_MEDIA", CONF_REPORT_USE_MEDIA },
1064     { "REQ_TRIES", CONF_REQ_TRIES },
1065     { "REQUIRED", CONF_REQUIRED },
1066     { "RESERVE", CONF_RESERVE },
1067     { "RESERVED_UDP_PORT", CONF_RESERVED_UDP_PORT },
1068     { "RESERVED_TCP_PORT", CONF_RESERVED_TCP_PORT },
1069     { "RUNSPERCYCLE", CONF_RUNSPERCYCLE },
1070     { "RUNTAPES", CONF_RUNTAPES },
1071     { "SAME_HOST", CONF_SAME_HOST },
1072     { "SCRIPT", CONF_SCRIPT },
1073     { "SCRIPT_TOOL", CONF_SCRIPT_TOOL },
1074     { "SEND_AMREPORT_ON", CONF_SEND_AMREPORT_ON },
1075     { "CLIENT_PORT", CONF_CLIENT_PORT },
1076     { "SERVER", CONF_SERVER },
1077     { "SERVER_CUSTOM_COMPRESS", CONF_SRVCOMPPROG },
1078     { "SERVER_DECRYPT_OPTION", CONF_SRV_DECRYPT_OPT },
1079     { "SERVER_ENCRYPT", CONF_SRV_ENCRYPT },
1080     { "SKIP", CONF_SKIP },
1081     { "SKIP_FULL", CONF_SKIP_FULL },
1082     { "SKIP_INCR", CONF_SKIP_INCR },
1083     { "SINGLE_EXECUTION", CONF_SINGLE_EXECUTION },
1084     { "SMALLEST", CONF_SMALLEST },
1085     { "SPEED", CONF_SPEED },
1086     { "SPLIT_DISKBUFFER", CONF_SPLIT_DISKBUFFER },
1087     { "SSH_KEYS", CONF_SSH_KEYS },
1088     { "STANDARD", CONF_STANDARD },
1089     { "STARTTIME", CONF_STARTTIME },
1090     { "STRANGE", CONF_STRANGE },
1091     { "STRATEGY", CONF_STRATEGY },
1092     { "DEVICE_OUTPUT_BUFFER_SIZE", CONF_DEVICE_OUTPUT_BUFFER_SIZE },
1093     { "TAPECYCLE", CONF_TAPECYCLE },
1094     { "TAPEDEV", CONF_TAPEDEV },
1095     { "TAPELIST", CONF_TAPELIST },
1096     { "TAPERALGO", CONF_TAPERALGO },
1097     { "TAPERSCAN", CONF_TAPERSCAN },
1098     { "TAPER_PARALLEL_WRITE", CONF_TAPER_PARALLEL_WRITE },
1099     { "FLUSH_THRESHOLD_DUMPED", CONF_FLUSH_THRESHOLD_DUMPED },
1100     { "FLUSH_THRESHOLD_SCHEDULED", CONF_FLUSH_THRESHOLD_SCHEDULED },
1101     { "TAPERFLUSH", CONF_TAPERFLUSH },
1102     { "TAPETYPE", CONF_TAPETYPE },
1103     { "TAPE_SPLITSIZE", CONF_TAPE_SPLITSIZE },
1104     { "TMPDIR", CONF_TMPDIR },
1105     { "TPCHANGER", CONF_TPCHANGER },
1106     { "UNRESERVED_TCP_PORT", CONF_UNRESERVED_TCP_PORT },
1107     { "USE", CONF_USE },
1108     { "USETIMESTAMPS", CONF_USETIMESTAMPS },
1109     { "VOLUME_ERROR", CONF_VOLUME_ERROR },
1110     { NULL, CONF_IDENT },
1111     { NULL, CONF_UNKNOWN }
1112 };
1113 
1114 /* A keyword table for recognizing unit suffixes.  No distinction is made for kinds
1115  * of suffixes: 1024 weeks = 7 k. */
1116 keytab_t numb_keytable[] = {
1117     { "B", CONF_MULT1 },
1118     { "BPS", CONF_MULT1 },
1119     { "BYTE", CONF_MULT1 },
1120     { "BYTES", CONF_MULT1 },
1121     { "DAY", CONF_MULT1 },
1122     { "DAYS", CONF_MULT1 },
1123     { "INF", CONF_AMINFINITY },
1124     { "K", CONF_MULT1K },
1125     { "KB", CONF_MULT1K },
1126     { "KBPS", CONF_MULT1K },
1127     { "KBYTE", CONF_MULT1K },
1128     { "KBYTES", CONF_MULT1K },
1129     { "KILOBYTE", CONF_MULT1K },
1130     { "KILOBYTES", CONF_MULT1K },
1131     { "KPS", CONF_MULT1K },
1132     { "M", CONF_MULT1M },
1133     { "MB", CONF_MULT1M },
1134     { "MBPS", CONF_MULT1M },
1135     { "MBYTE", CONF_MULT1M },
1136     { "MBYTES", CONF_MULT1M },
1137     { "MEG", CONF_MULT1M },
1138     { "MEGABYTE", CONF_MULT1M },
1139     { "MEGABYTES", CONF_MULT1M },
1140     { "G", CONF_MULT1G },
1141     { "GB", CONF_MULT1G },
1142     { "GBPS", CONF_MULT1G },
1143     { "GBYTE", CONF_MULT1G },
1144     { "GBYTES", CONF_MULT1G },
1145     { "GIG", CONF_MULT1G },
1146     { "GIGABYTE", CONF_MULT1G },
1147     { "GIGABYTES", CONF_MULT1G },
1148     { "T", CONF_MULT1T },
1149     { "TB", CONF_MULT1T },
1150     { "TBPS", CONF_MULT1T },
1151     { "TBYTE", CONF_MULT1T },
1152     { "TBYTES", CONF_MULT1T },
1153     { "TERA", CONF_MULT1T },
1154     { "TERABYTE", CONF_MULT1T },
1155     { "TERABYTES", CONF_MULT1T },
1156     { "MPS", CONF_MULT1M },
1157     { "TAPE", CONF_MULT1 },
1158     { "TAPES", CONF_MULT1 },
1159     { "WEEK", CONF_MULT7 },
1160     { "WEEKS", CONF_MULT7 },
1161     { NULL, CONF_IDENT }
1162 };
1163 
1164 /* Boolean keywords -- all the ways to say "true" and "false" in amanda.conf */
1165 keytab_t bool_keytable[] = {
1166     { "Y", CONF_ATRUE },
1167     { "YES", CONF_ATRUE },
1168     { "T", CONF_ATRUE },
1169     { "TRUE", CONF_ATRUE },
1170     { "ON", CONF_ATRUE },
1171     { "N", CONF_AFALSE },
1172     { "NO", CONF_AFALSE },
1173     { "F", CONF_AFALSE },
1174     { "FALSE", CONF_AFALSE },
1175     { "OFF", CONF_AFALSE },
1176     { NULL, CONF_IDENT }
1177 };
1178 
1179 /* no_yes_all keywords -- all the ways to say "true" and "false" in amanda.conf */
1180 keytab_t no_yes_all_keytable[] = {
1181     { "Y", CONF_ATRUE },
1182     { "YES", CONF_ATRUE },
1183     { "T", CONF_ATRUE },
1184     { "TRUE", CONF_ATRUE },
1185     { "ON", CONF_ATRUE },
1186     { "N", CONF_AFALSE },
1187     { "NO", CONF_AFALSE },
1188     { "F", CONF_AFALSE },
1189     { "FALSE", CONF_AFALSE },
1190     { "OFF", CONF_AFALSE },
1191     { "ALL", CONF_ALL },
1192     { NULL, CONF_IDENT }
1193 };
1194 
1195 /* Now, the parser tables for client and server global parameters, and for
1196  * each of the server subsections */
1197 conf_var_t client_var [] = {
1198    { CONF_CONF               , CONFTYPE_STR     , read_str     , CNF_CONF               , NULL },
1199    { CONF_AMDUMP_SERVER      , CONFTYPE_STR     , read_str     , CNF_AMDUMP_SERVER      , NULL },
1200    { CONF_INDEX_SERVER       , CONFTYPE_STR     , read_str     , CNF_INDEX_SERVER       , NULL },
1201    { CONF_TAPE_SERVER        , CONFTYPE_STR     , read_str     , CNF_TAPE_SERVER        , NULL },
1202    { CONF_TAPEDEV            , CONFTYPE_STR     , read_str     , CNF_TAPEDEV            , NULL },
1203    { CONF_AUTH               , CONFTYPE_STR     , read_str     , CNF_AUTH               , NULL },
1204    { CONF_SSH_KEYS           , CONFTYPE_STR     , read_str     , CNF_SSH_KEYS           , NULL },
1205    { CONF_AMANDAD_PATH       , CONFTYPE_STR     , read_str     , CNF_AMANDAD_PATH       , NULL },
1206    { CONF_CLIENT_USERNAME    , CONFTYPE_STR     , read_str     , CNF_CLIENT_USERNAME    , NULL },
1207    { CONF_CLIENT_PORT        , CONFTYPE_STR     , read_int_or_str, CNF_CLIENT_PORT      , NULL },
1208    { CONF_GNUTAR_LIST_DIR    , CONFTYPE_STR     , read_str     , CNF_GNUTAR_LIST_DIR    , NULL },
1209    { CONF_AMANDATES          , CONFTYPE_STR     , read_str     , CNF_AMANDATES          , NULL },
1210    { CONF_MAILER             , CONFTYPE_STR     , read_str     , CNF_MAILER             , NULL },
1211    { CONF_KRB5KEYTAB         , CONFTYPE_STR     , read_str     , CNF_KRB5KEYTAB         , NULL },
1212    { CONF_KRB5PRINCIPAL      , CONFTYPE_STR     , read_str     , CNF_KRB5PRINCIPAL      , NULL },
1213    { CONF_CONNECT_TRIES      , CONFTYPE_INT     , read_int     , CNF_CONNECT_TRIES      , validate_positive },
1214    { CONF_REP_TRIES          , CONFTYPE_INT     , read_int     , CNF_REP_TRIES          , validate_positive },
1215    { CONF_REQ_TRIES          , CONFTYPE_INT     , read_int     , CNF_REQ_TRIES          , validate_positive },
1216    { CONF_DEBUG_DAYS         , CONFTYPE_INT     , read_int     , CNF_DEBUG_DAYS         , NULL },
1217    { CONF_DEBUG_AMANDAD      , CONFTYPE_INT     , read_int     , CNF_DEBUG_AMANDAD      , validate_debug },
1218    { CONF_DEBUG_RECOVERY     , CONFTYPE_INT     , read_int     , CNF_DEBUG_RECOVERY     , validate_debug },
1219    { CONF_DEBUG_AMIDXTAPED   , CONFTYPE_INT     , read_int     , CNF_DEBUG_AMIDXTAPED   , validate_debug },
1220    { CONF_DEBUG_AMINDEXD     , CONFTYPE_INT     , read_int     , CNF_DEBUG_AMINDEXD     , validate_debug },
1221    { CONF_DEBUG_AMRECOVER    , CONFTYPE_INT     , read_int     , CNF_DEBUG_AMRECOVER    , validate_debug },
1222    { CONF_DEBUG_AUTH         , CONFTYPE_INT     , read_int     , CNF_DEBUG_AUTH         , validate_debug },
1223    { CONF_DEBUG_EVENT        , CONFTYPE_INT     , read_int     , CNF_DEBUG_EVENT        , validate_debug },
1224    { CONF_DEBUG_HOLDING      , CONFTYPE_INT     , read_int     , CNF_DEBUG_HOLDING      , validate_debug },
1225    { CONF_DEBUG_PROTOCOL     , CONFTYPE_INT     , read_int     , CNF_DEBUG_PROTOCOL     , validate_debug },
1226    { CONF_DEBUG_PLANNER      , CONFTYPE_INT     , read_int     , CNF_DEBUG_PLANNER      , validate_debug },
1227    { CONF_DEBUG_DRIVER       , CONFTYPE_INT     , read_int     , CNF_DEBUG_DRIVER       , validate_debug },
1228    { CONF_DEBUG_DUMPER       , CONFTYPE_INT     , read_int     , CNF_DEBUG_DUMPER       , validate_debug },
1229    { CONF_DEBUG_CHUNKER      , CONFTYPE_INT     , read_int     , CNF_DEBUG_CHUNKER      , validate_debug },
1230    { CONF_DEBUG_TAPER        , CONFTYPE_INT     , read_int     , CNF_DEBUG_TAPER        , validate_debug },
1231    { CONF_DEBUG_SELFCHECK    , CONFTYPE_INT     , read_int     , CNF_DEBUG_SELFCHECK    , validate_debug },
1232    { CONF_DEBUG_SENDSIZE     , CONFTYPE_INT     , read_int     , CNF_DEBUG_SENDSIZE     , validate_debug },
1233    { CONF_DEBUG_SENDBACKUP   , CONFTYPE_INT     , read_int     , CNF_DEBUG_SENDBACKUP   , validate_debug },
1234    { CONF_RESERVED_UDP_PORT  , CONFTYPE_INTRANGE, read_intrange, CNF_RESERVED_UDP_PORT  , validate_reserved_port_range },
1235    { CONF_RESERVED_TCP_PORT  , CONFTYPE_INTRANGE, read_intrange, CNF_RESERVED_TCP_PORT  , validate_reserved_port_range },
1236    { CONF_UNRESERVED_TCP_PORT, CONFTYPE_INTRANGE, read_intrange, CNF_UNRESERVED_TCP_PORT, validate_unreserved_port_range },
1237    { CONF_PROPERTY           , CONFTYPE_PROPLIST, read_property, CNF_PROPERTY           , NULL },
1238    { CONF_APPLICATION        , CONFTYPE_STR     , read_dapplication, DUMPTYPE_APPLICATION, NULL },
1239    { CONF_SCRIPT             , CONFTYPE_STR     , read_dpp_script, DUMPTYPE_SCRIPTLIST, NULL },
1240    { CONF_UNKNOWN            , CONFTYPE_INT     , NULL         , CNF_CNF                , NULL }
1241 };
1242 
1243 conf_var_t server_var [] = {
1244    { CONF_ORG                  , CONFTYPE_STR      , read_str         , CNF_ORG                  , NULL },
1245    { CONF_MAILTO               , CONFTYPE_STR      , read_str         , CNF_MAILTO               , NULL },
1246    { CONF_DUMPUSER             , CONFTYPE_STR      , read_str         , CNF_DUMPUSER             , NULL },
1247    { CONF_PRINTER              , CONFTYPE_STR      , read_str         , CNF_PRINTER              , NULL },
1248    { CONF_MAILER               , CONFTYPE_STR      , read_str         , CNF_MAILER               , NULL },
1249    { CONF_TAPEDEV              , CONFTYPE_STR      , read_str         , CNF_TAPEDEV              , NULL },
1250    { CONF_DEVICE_PROPERTY      , CONFTYPE_PROPLIST , read_property    , CNF_DEVICE_PROPERTY      , NULL },
1251    { CONF_PROPERTY             , CONFTYPE_PROPLIST , read_property    , CNF_PROPERTY             , NULL },
1252    { CONF_TPCHANGER            , CONFTYPE_STR      , read_str         , CNF_TPCHANGER            , NULL },
1253    { CONF_CHANGERDEV           , CONFTYPE_STR      , read_str         , CNF_CHANGERDEV           , NULL },
1254    { CONF_CHANGERFILE          , CONFTYPE_STR      , read_str         , CNF_CHANGERFILE          , NULL },
1255    { CONF_LABELSTR             , CONFTYPE_STR      , read_str         , CNF_LABELSTR             , NULL },
1256    { CONF_TAPELIST             , CONFTYPE_STR      , read_str         , CNF_TAPELIST             , NULL },
1257    { CONF_DISKFILE             , CONFTYPE_STR      , read_str         , CNF_DISKFILE             , NULL },
1258    { CONF_INFOFILE             , CONFTYPE_STR      , read_str         , CNF_INFOFILE             , NULL },
1259    { CONF_LOGDIR               , CONFTYPE_STR      , read_str         , CNF_LOGDIR               , NULL },
1260    { CONF_INDEXDIR             , CONFTYPE_STR      , read_str         , CNF_INDEXDIR             , NULL },
1261    { CONF_TAPETYPE             , CONFTYPE_IDENT    , read_ident       , CNF_TAPETYPE             , NULL },
1262    { CONF_HOLDING              , CONFTYPE_IDENTLIST, read_holdingdisk , CNF_HOLDINGDISK          , NULL },
1263    { CONF_DUMPCYCLE            , CONFTYPE_INT      , read_int         , CNF_DUMPCYCLE            , validate_nonnegative },
1264    { CONF_RUNSPERCYCLE         , CONFTYPE_INT      , read_int         , CNF_RUNSPERCYCLE         , validate_runspercycle },
1265    { CONF_RUNTAPES             , CONFTYPE_INT      , read_int         , CNF_RUNTAPES             , validate_nonnegative },
1266    { CONF_TAPECYCLE            , CONFTYPE_INT      , read_int         , CNF_TAPECYCLE            , validate_positive },
1267    { CONF_BUMPDAYS             , CONFTYPE_INT      , read_int         , CNF_BUMPDAYS             , validate_nonnegative },
1268    { CONF_BUMPSIZE             , CONFTYPE_INT64    , read_int64       , CNF_BUMPSIZE             , validate_positive },
1269    { CONF_BUMPPERCENT          , CONFTYPE_INT      , read_int         , CNF_BUMPPERCENT          , validate_bumppercent },
1270    { CONF_BUMPMULT             , CONFTYPE_REAL     , read_real        , CNF_BUMPMULT             , validate_bumpmult },
1271    { CONF_NETUSAGE             , CONFTYPE_INT      , read_int         , CNF_NETUSAGE             , validate_positive },
1272    { CONF_INPARALLEL           , CONFTYPE_INT      , read_int         , CNF_INPARALLEL           , validate_inparallel },
1273    { CONF_DUMPORDER            , CONFTYPE_STR      , read_str         , CNF_DUMPORDER            , NULL },
1274    { CONF_MAXDUMPS             , CONFTYPE_INT      , read_int         , CNF_MAXDUMPS             , validate_positive },
1275    { CONF_MAX_DLE_BY_VOLUME    , CONFTYPE_INT      , read_int         , CNF_MAX_DLE_BY_VOLUME    , validate_positive },
1276    { CONF_ETIMEOUT             , CONFTYPE_INT      , read_int         , CNF_ETIMEOUT             , validate_non_zero },
1277    { CONF_DTIMEOUT             , CONFTYPE_INT      , read_int         , CNF_DTIMEOUT             , validate_positive },
1278    { CONF_CTIMEOUT             , CONFTYPE_INT      , read_int         , CNF_CTIMEOUT             , validate_positive },
1279    { CONF_DEVICE_OUTPUT_BUFFER_SIZE, CONFTYPE_SIZE , read_size        , CNF_DEVICE_OUTPUT_BUFFER_SIZE, NULL },
1280    { CONF_COLUMNSPEC           , CONFTYPE_STR      , read_str         , CNF_COLUMNSPEC           , NULL },
1281    { CONF_TAPERALGO            , CONFTYPE_TAPERALGO, read_taperalgo   , CNF_TAPERALGO            , NULL },
1282    { CONF_TAPER_PARALLEL_WRITE , CONFTYPE_INT      , read_int         , CNF_TAPER_PARALLEL_WRITE , NULL },
1283    { CONF_SEND_AMREPORT_ON     , CONFTYPE_SEND_AMREPORT_ON, read_send_amreport_on, CNF_SEND_AMREPORT_ON       , NULL },
1284    { CONF_FLUSH_THRESHOLD_DUMPED, CONFTYPE_INT     , read_int         , CNF_FLUSH_THRESHOLD_DUMPED, validate_nonnegative },
1285    { CONF_FLUSH_THRESHOLD_SCHEDULED, CONFTYPE_INT  , read_int         , CNF_FLUSH_THRESHOLD_SCHEDULED, validate_nonnegative },
1286    { CONF_TAPERFLUSH           , CONFTYPE_INT      , read_int         , CNF_TAPERFLUSH           , validate_nonnegative },
1287    { CONF_DISPLAYUNIT          , CONFTYPE_STR      , read_str         , CNF_DISPLAYUNIT          , validate_displayunit },
1288    { CONF_AUTOFLUSH            , CONFTYPE_NO_YES_ALL,read_no_yes_all  , CNF_AUTOFLUSH            , NULL },
1289    { CONF_RESERVE              , CONFTYPE_INT      , read_int         , CNF_RESERVE              , validate_reserve },
1290    { CONF_MAXDUMPSIZE          , CONFTYPE_INT64    , read_int64       , CNF_MAXDUMPSIZE          , NULL },
1291    { CONF_KRB5KEYTAB           , CONFTYPE_STR      , read_str         , CNF_KRB5KEYTAB           , NULL },
1292    { CONF_KRB5PRINCIPAL        , CONFTYPE_STR      , read_str         , CNF_KRB5PRINCIPAL        , NULL },
1293    { CONF_LABEL_NEW_TAPES      , CONFTYPE_STR      , read_str         , CNF_LABEL_NEW_TAPES      , NULL },
1294    { CONF_AUTOLABEL            , CONFTYPE_AUTOLABEL, read_autolabel   , CNF_AUTOLABEL            , NULL },
1295    { CONF_META_AUTOLABEL       , CONFTYPE_STR      , read_str         , CNF_META_AUTOLABEL       , NULL },
1296    { CONF_EJECT_VOLUME         , CONFTYPE_BOOLEAN  , read_bool        , CNF_EJECT_VOLUME         , NULL },
1297    { CONF_TMPDIR               , CONFTYPE_STR      , read_str         , CNF_TMPDIR               , validate_tmpdir },
1298    { CONF_USETIMESTAMPS        , CONFTYPE_BOOLEAN  , read_bool        , CNF_USETIMESTAMPS        , NULL },
1299    { CONF_AMRECOVER_DO_FSF     , CONFTYPE_BOOLEAN  , read_bool        , CNF_AMRECOVER_DO_FSF     , NULL },
1300    { CONF_AMRECOVER_CHANGER    , CONFTYPE_STR      , read_str         , CNF_AMRECOVER_CHANGER    , NULL },
1301    { CONF_AMRECOVER_CHECK_LABEL, CONFTYPE_BOOLEAN  , read_bool        , CNF_AMRECOVER_CHECK_LABEL, NULL },
1302    { CONF_CONNECT_TRIES        , CONFTYPE_INT      , read_int         , CNF_CONNECT_TRIES        , validate_positive },
1303    { CONF_REP_TRIES            , CONFTYPE_INT      , read_int         , CNF_REP_TRIES            , validate_positive },
1304    { CONF_REQ_TRIES            , CONFTYPE_INT      , read_int         , CNF_REQ_TRIES            , validate_positive },
1305    { CONF_DEBUG_DAYS           , CONFTYPE_INT      , read_int         , CNF_DEBUG_DAYS           , NULL },
1306    { CONF_DEBUG_AMANDAD        , CONFTYPE_INT      , read_int         , CNF_DEBUG_AMANDAD        , validate_debug },
1307    { CONF_DEBUG_RECOVERY       , CONFTYPE_INT      , read_int         , CNF_DEBUG_RECOVERY       , validate_debug },
1308    { CONF_DEBUG_AMIDXTAPED     , CONFTYPE_INT      , read_int         , CNF_DEBUG_AMIDXTAPED     , validate_debug },
1309    { CONF_DEBUG_AMINDEXD       , CONFTYPE_INT      , read_int         , CNF_DEBUG_AMINDEXD       , validate_debug },
1310    { CONF_DEBUG_AMRECOVER      , CONFTYPE_INT      , read_int         , CNF_DEBUG_AMRECOVER      , validate_debug },
1311    { CONF_DEBUG_AUTH           , CONFTYPE_INT      , read_int         , CNF_DEBUG_AUTH           , validate_debug },
1312    { CONF_DEBUG_EVENT          , CONFTYPE_INT      , read_int         , CNF_DEBUG_EVENT          , validate_debug },
1313    { CONF_DEBUG_HOLDING        , CONFTYPE_INT      , read_int         , CNF_DEBUG_HOLDING        , validate_debug },
1314    { CONF_DEBUG_PROTOCOL       , CONFTYPE_INT      , read_int         , CNF_DEBUG_PROTOCOL       , validate_debug },
1315    { CONF_DEBUG_PLANNER        , CONFTYPE_INT      , read_int         , CNF_DEBUG_PLANNER        , validate_debug },
1316    { CONF_DEBUG_DRIVER         , CONFTYPE_INT      , read_int         , CNF_DEBUG_DRIVER         , validate_debug },
1317    { CONF_DEBUG_DUMPER         , CONFTYPE_INT      , read_int         , CNF_DEBUG_DUMPER         , validate_debug },
1318    { CONF_DEBUG_CHUNKER        , CONFTYPE_INT      , read_int         , CNF_DEBUG_CHUNKER        , validate_debug },
1319    { CONF_DEBUG_TAPER          , CONFTYPE_INT      , read_int         , CNF_DEBUG_TAPER          , validate_debug },
1320    { CONF_DEBUG_SELFCHECK      , CONFTYPE_INT      , read_int         , CNF_DEBUG_SELFCHECK      , validate_debug },
1321    { CONF_DEBUG_SENDSIZE       , CONFTYPE_INT      , read_int         , CNF_DEBUG_SENDSIZE       , validate_debug },
1322    { CONF_DEBUG_SENDBACKUP     , CONFTYPE_INT      , read_int         , CNF_DEBUG_SENDBACKUP     , validate_debug },
1323    { CONF_RESERVED_UDP_PORT    , CONFTYPE_INTRANGE , read_intrange    , CNF_RESERVED_UDP_PORT    , validate_reserved_port_range },
1324    { CONF_RESERVED_TCP_PORT    , CONFTYPE_INTRANGE , read_intrange    , CNF_RESERVED_TCP_PORT    , validate_reserved_port_range },
1325    { CONF_UNRESERVED_TCP_PORT  , CONFTYPE_INTRANGE , read_intrange    , CNF_UNRESERVED_TCP_PORT  , validate_unreserved_port_range },
1326    { CONF_RECOVERY_LIMIT       , CONFTYPE_HOST_LIMIT, read_host_limit , CNF_RECOVERY_LIMIT       , NULL },
1327    { CONF_INTERACTIVITY        , CONFTYPE_STR      , read_dinteractivity, CNF_INTERACTIVITY      , NULL },
1328    { CONF_TAPERSCAN            , CONFTYPE_STR      , read_dtaperscan  , CNF_TAPERSCAN            , NULL },
1329    { CONF_REPORT_USE_MEDIA     , CONFTYPE_BOOLEAN  , read_bool        , CNF_REPORT_USE_MEDIA     , NULL },
1330    { CONF_REPORT_NEXT_MEDIA    , CONFTYPE_BOOLEAN  , read_bool        , CNF_REPORT_NEXT_MEDIA    , NULL },
1331    { CONF_REPORT_FORMAT        , CONFTYPE_STR_LIST , read_str_list    , CNF_REPORT_FORMAT        , NULL },
1332    { CONF_UNKNOWN              , CONFTYPE_INT      , NULL             , CNF_CNF                  , NULL }
1333 };
1334 
1335 conf_var_t tapetype_var [] = {
1336    { CONF_COMMENT              , CONFTYPE_STR     , read_str          , TAPETYPE_COMMENT         , NULL },
1337    { CONF_LBL_TEMPL            , CONFTYPE_STR     , read_str          , TAPETYPE_LBL_TEMPL       , NULL },
1338    { CONF_BLOCKSIZE            , CONFTYPE_SIZE    , read_size         , TAPETYPE_BLOCKSIZE       , validate_blocksize },
1339    { CONF_READBLOCKSIZE        , CONFTYPE_SIZE    , read_size         , TAPETYPE_READBLOCKSIZE   , validate_blocksize },
1340    { CONF_LENGTH               , CONFTYPE_INT64   , read_int64        , TAPETYPE_LENGTH          , validate_nonnegative },
1341    { CONF_FILEMARK             , CONFTYPE_INT64   , read_int64        , TAPETYPE_FILEMARK        , NULL },
1342    { CONF_SPEED                , CONFTYPE_INT     , read_int          , TAPETYPE_SPEED           , validate_nonnegative },
1343    { CONF_PART_SIZE            , CONFTYPE_INT64    , read_int64       , TAPETYPE_PART_SIZE       , validate_nonnegative },
1344    { CONF_PART_CACHE_TYPE      , CONFTYPE_PART_CACHE_TYPE, read_part_cache_type, TAPETYPE_PART_CACHE_TYPE, NULL },
1345    { CONF_PART_CACHE_DIR       , CONFTYPE_STR      , read_str         , TAPETYPE_PART_CACHE_DIR	 , NULL },
1346    { CONF_PART_CACHE_MAX_SIZE  , CONFTYPE_INT64    , read_int64       , TAPETYPE_PART_CACHE_MAX_SIZE, validate_nonnegative },
1347    { CONF_UNKNOWN              , CONFTYPE_INT     , NULL              , TAPETYPE_TAPETYPE        , NULL }
1348 };
1349 
1350 conf_var_t dumptype_var [] = {
1351    { CONF_COMMENT           , CONFTYPE_STR      , read_str      , DUMPTYPE_COMMENT           , NULL },
1352    { CONF_AUTH              , CONFTYPE_STR      , read_str      , DUMPTYPE_AUTH              , NULL },
1353    { CONF_BUMPDAYS          , CONFTYPE_INT      , read_int      , DUMPTYPE_BUMPDAYS          , validate_nonnegative },
1354    { CONF_BUMPMULT          , CONFTYPE_REAL     , read_real     , DUMPTYPE_BUMPMULT          , validate_bumpmult },
1355    { CONF_BUMPSIZE          , CONFTYPE_INT64    , read_int64    , DUMPTYPE_BUMPSIZE          , validate_positive },
1356    { CONF_BUMPPERCENT       , CONFTYPE_INT      , read_int      , DUMPTYPE_BUMPPERCENT       , validate_bumppercent },
1357    { CONF_COMPRATE          , CONFTYPE_REAL     , read_rate     , DUMPTYPE_COMPRATE          , NULL },
1358    { CONF_COMPRESS          , CONFTYPE_INT      , read_compress , DUMPTYPE_COMPRESS          , NULL },
1359    { CONF_ENCRYPT           , CONFTYPE_INT      , read_encrypt  , DUMPTYPE_ENCRYPT           , NULL },
1360    { CONF_DUMPCYCLE         , CONFTYPE_INT      , read_int      , DUMPTYPE_DUMPCYCLE         , validate_nonnegative },
1361    { CONF_EXCLUDE           , CONFTYPE_EXINCLUDE, read_exinclude, DUMPTYPE_EXCLUDE           , NULL },
1362    { CONF_INCLUDE           , CONFTYPE_EXINCLUDE, read_exinclude, DUMPTYPE_INCLUDE           , NULL },
1363    { CONF_IGNORE            , CONFTYPE_BOOLEAN  , read_bool     , DUMPTYPE_IGNORE            , NULL },
1364    { CONF_HOLDING           , CONFTYPE_HOLDING  , read_holding  , DUMPTYPE_HOLDINGDISK       , NULL },
1365    { CONF_INDEX             , CONFTYPE_BOOLEAN  , read_bool     , DUMPTYPE_INDEX             , NULL },
1366    { CONF_KENCRYPT          , CONFTYPE_BOOLEAN  , read_bool     , DUMPTYPE_KENCRYPT          , NULL },
1367    { CONF_MAXDUMPS          , CONFTYPE_INT      , read_int      , DUMPTYPE_MAXDUMPS          , validate_positive },
1368    { CONF_MAXPROMOTEDAY     , CONFTYPE_INT      , read_int      , DUMPTYPE_MAXPROMOTEDAY     , validate_nonnegative },
1369    { CONF_PRIORITY          , CONFTYPE_PRIORITY , read_priority , DUMPTYPE_PRIORITY          , NULL },
1370    { CONF_PROGRAM           , CONFTYPE_STR      , read_str      , DUMPTYPE_PROGRAM           , validate_program },
1371    { CONF_PROPERTY          , CONFTYPE_PROPLIST , read_property , DUMPTYPE_PROPERTY          , NULL },
1372    { CONF_RECORD            , CONFTYPE_BOOLEAN  , read_bool     , DUMPTYPE_RECORD            , NULL },
1373    { CONF_SKIP_FULL         , CONFTYPE_BOOLEAN  , read_bool     , DUMPTYPE_SKIP_FULL         , NULL },
1374    { CONF_SKIP_INCR         , CONFTYPE_BOOLEAN  , read_bool     , DUMPTYPE_SKIP_INCR         , NULL },
1375    { CONF_STARTTIME         , CONFTYPE_TIME     , read_time     , DUMPTYPE_STARTTIME         , NULL },
1376    { CONF_STRATEGY          , CONFTYPE_INT      , read_strategy , DUMPTYPE_STRATEGY          , NULL },
1377    { CONF_TAPE_SPLITSIZE    , CONFTYPE_INT64    , read_int64    , DUMPTYPE_TAPE_SPLITSIZE    , validate_nonnegative },
1378    { CONF_SPLIT_DISKBUFFER  , CONFTYPE_STR      , read_str      , DUMPTYPE_SPLIT_DISKBUFFER  , NULL },
1379    { CONF_ESTIMATE          , CONFTYPE_ESTIMATELIST, read_estimatelist , DUMPTYPE_ESTIMATELIST  , NULL },
1380    { CONF_SRV_ENCRYPT       , CONFTYPE_STR      , read_str      , DUMPTYPE_SRV_ENCRYPT       , NULL },
1381    { CONF_CLNT_ENCRYPT      , CONFTYPE_STR      , read_str      , DUMPTYPE_CLNT_ENCRYPT      , NULL },
1382    { CONF_AMANDAD_PATH      , CONFTYPE_STR      , read_str      , DUMPTYPE_AMANDAD_PATH      , NULL },
1383    { CONF_CLIENT_USERNAME   , CONFTYPE_STR      , read_str      , DUMPTYPE_CLIENT_USERNAME   , NULL },
1384    { CONF_CLIENT_PORT       , CONFTYPE_STR      , read_int_or_str, DUMPTYPE_CLIENT_PORT      , NULL },
1385    { CONF_SSH_KEYS          , CONFTYPE_STR      , read_str      , DUMPTYPE_SSH_KEYS          , NULL },
1386    { CONF_SRVCOMPPROG       , CONFTYPE_STR      , read_str      , DUMPTYPE_SRVCOMPPROG       , NULL },
1387    { CONF_CLNTCOMPPROG      , CONFTYPE_STR      , read_str      , DUMPTYPE_CLNTCOMPPROG      , NULL },
1388    { CONF_FALLBACK_SPLITSIZE, CONFTYPE_INT64    , read_int64    , DUMPTYPE_FALLBACK_SPLITSIZE, NULL },
1389    { CONF_SRV_DECRYPT_OPT   , CONFTYPE_STR      , read_str      , DUMPTYPE_SRV_DECRYPT_OPT   , NULL },
1390    { CONF_CLNT_DECRYPT_OPT  , CONFTYPE_STR      , read_str      , DUMPTYPE_CLNT_DECRYPT_OPT  , NULL },
1391    { CONF_APPLICATION       , CONFTYPE_STR      , read_dapplication, DUMPTYPE_APPLICATION    , NULL },
1392    { CONF_SCRIPT            , CONFTYPE_STR      , read_dpp_script, DUMPTYPE_SCRIPTLIST       , NULL },
1393    { CONF_DATA_PATH         , CONFTYPE_DATA_PATH, read_data_path, DUMPTYPE_DATA_PATH         , NULL },
1394    { CONF_ALLOW_SPLIT       , CONFTYPE_BOOLEAN  , read_bool    , DUMPTYPE_ALLOW_SPLIT        , NULL },
1395    { CONF_MAX_WARNINGS      , CONFTYPE_INT      , read_int     , DUMPTYPE_MAX_WARNINGS       , validate_nonnegative },
1396    { CONF_RECOVERY_LIMIT    , CONFTYPE_HOST_LIMIT, read_host_limit, DUMPTYPE_RECOVERY_LIMIT  , NULL },
1397    { CONF_DUMP_LIMIT        , CONFTYPE_HOST_LIMIT, read_host_limit, DUMPTYPE_DUMP_LIMIT      , validate_dump_limit },
1398    { CONF_UNKNOWN           , CONFTYPE_INT      , NULL          , DUMPTYPE_DUMPTYPE          , NULL }
1399 };
1400 
1401 conf_var_t holding_var [] = {
1402    { CONF_DIRECTORY, CONFTYPE_STR   , read_str   , HOLDING_DISKDIR  , NULL },
1403    { CONF_COMMENT  , CONFTYPE_STR   , read_str   , HOLDING_COMMENT  , NULL },
1404    { CONF_USE      , CONFTYPE_INT64 , read_int64 , HOLDING_DISKSIZE , validate_use },
1405    { CONF_CHUNKSIZE, CONFTYPE_INT64 , read_int64 , HOLDING_CHUNKSIZE, validate_chunksize },
1406    { CONF_UNKNOWN  , CONFTYPE_INT   , NULL       , HOLDING_HOLDING  , NULL }
1407 };
1408 
1409 conf_var_t interface_var [] = {
1410    { CONF_COMMENT, CONFTYPE_STR   , read_str   , INTER_COMMENT , NULL },
1411    { CONF_USE    , CONFTYPE_INT   , read_int   , INTER_MAXUSAGE, validate_positive },
1412    { CONF_UNKNOWN, CONFTYPE_INT   , NULL       , INTER_INTER   , NULL }
1413 };
1414 
1415 
1416 conf_var_t application_var [] = {
1417    { CONF_COMMENT  , CONFTYPE_STR     , read_str     , APPLICATION_COMMENT    , NULL },
1418    { CONF_PLUGIN   , CONFTYPE_STR     , read_str     , APPLICATION_PLUGIN     , NULL },
1419    { CONF_PROPERTY , CONFTYPE_PROPLIST, read_property, APPLICATION_PROPERTY   , NULL },
1420    { CONF_CLIENT_NAME, CONFTYPE_STR   , read_str     , APPLICATION_CLIENT_NAME, NULL },
1421    { CONF_UNKNOWN  , CONFTYPE_INT     , NULL         , APPLICATION_APPLICATION, NULL }
1422 };
1423 
1424 conf_var_t pp_script_var [] = {
1425    { CONF_COMMENT      , CONFTYPE_STR     , read_str     , PP_SCRIPT_COMMENT      , NULL },
1426    { CONF_PLUGIN       , CONFTYPE_STR     , read_str     , PP_SCRIPT_PLUGIN       , NULL },
1427    { CONF_PROPERTY     , CONFTYPE_PROPLIST, read_property, PP_SCRIPT_PROPERTY     , NULL },
1428    { CONF_EXECUTE_ON   , CONFTYPE_EXECUTE_ON  , read_execute_on  , PP_SCRIPT_EXECUTE_ON   , NULL },
1429    { CONF_EXECUTE_WHERE, CONFTYPE_EXECUTE_WHERE  , read_execute_where  , PP_SCRIPT_EXECUTE_WHERE, NULL },
1430    { CONF_ORDER        , CONFTYPE_INT     , read_int     , PP_SCRIPT_ORDER        , NULL },
1431    { CONF_SINGLE_EXECUTION, CONFTYPE_BOOLEAN, read_bool    , PP_SCRIPT_SINGLE_EXECUTION, NULL },
1432    { CONF_CLIENT_NAME  , CONFTYPE_STR     , read_str     , PP_SCRIPT_CLIENT_NAME  , NULL },
1433    { CONF_UNKNOWN      , CONFTYPE_INT     , NULL         , PP_SCRIPT_PP_SCRIPT    , NULL }
1434 };
1435 
1436 conf_var_t device_config_var [] = {
1437    { CONF_COMMENT         , CONFTYPE_STR      , read_str      , DEVICE_CONFIG_COMMENT        , NULL },
1438    { CONF_DEVICE_PROPERTY , CONFTYPE_PROPLIST , read_property , DEVICE_CONFIG_DEVICE_PROPERTY, NULL },
1439    { CONF_TAPEDEV         , CONFTYPE_STR      , read_str      , DEVICE_CONFIG_TAPEDEV        , NULL },
1440    { CONF_UNKNOWN         , CONFTYPE_INT      , NULL          , DEVICE_CONFIG_DEVICE_CONFIG  , NULL }
1441 };
1442 
1443 conf_var_t changer_config_var [] = {
1444    { CONF_COMMENT         , CONFTYPE_STR      , read_str      , CHANGER_CONFIG_COMMENT        , NULL },
1445    { CONF_TAPEDEV         , CONFTYPE_STR      , read_str      , CHANGER_CONFIG_TAPEDEV        , NULL },
1446    { CONF_TPCHANGER       , CONFTYPE_STR      , read_str      , CHANGER_CONFIG_TPCHANGER      , NULL },
1447    { CONF_CHANGERDEV      , CONFTYPE_STR      , read_str      , CHANGER_CONFIG_CHANGERDEV     , NULL },
1448    { CONF_CHANGERFILE     , CONFTYPE_STR      , read_str      , CHANGER_CONFIG_CHANGERFILE    , NULL },
1449    { CONF_PROPERTY        , CONFTYPE_PROPLIST , read_property , CHANGER_CONFIG_PROPERTY       , NULL },
1450    { CONF_DEVICE_PROPERTY , CONFTYPE_PROPLIST , read_property , CHANGER_CONFIG_DEVICE_PROPERTY, NULL },
1451    { CONF_UNKNOWN         , CONFTYPE_INT      , NULL          , CHANGER_CONFIG_CHANGER_CONFIG , NULL }
1452 };
1453 
1454 conf_var_t interactivity_var [] = {
1455    { CONF_COMMENT         , CONFTYPE_STR      , read_str      , INTERACTIVITY_COMMENT        , NULL },
1456    { CONF_PLUGIN          , CONFTYPE_STR      , read_str      , INTERACTIVITY_PLUGIN         , NULL },
1457    { CONF_PROPERTY        , CONFTYPE_PROPLIST , read_property , INTERACTIVITY_PROPERTY       , NULL },
1458    { CONF_UNKNOWN         , CONFTYPE_INT      , NULL          , INTERACTIVITY_INTERACTIVITY  , NULL }
1459 };
1460 
1461 conf_var_t taperscan_var [] = {
1462    { CONF_COMMENT         , CONFTYPE_STR      , read_str      , TAPERSCAN_COMMENT        , NULL },
1463    { CONF_PLUGIN          , CONFTYPE_STR      , read_str      , TAPERSCAN_PLUGIN         , NULL },
1464    { CONF_PROPERTY        , CONFTYPE_PROPLIST , read_property , TAPERSCAN_PROPERTY       , NULL },
1465    { CONF_UNKNOWN         , CONFTYPE_INT      , NULL          , TAPERSCAN_TAPERSCAN      , NULL }
1466 };
1467 
1468 /*
1469  * Lexical Analysis Implementation
1470  */
1471 
1472 static char *
get_token_name(tok_t token)1473 get_token_name(
1474     tok_t token)
1475 {
1476     keytab_t *kt;
1477 
1478     if (keytable == NULL) {
1479 	error(_("keytable == NULL"));
1480 	/*NOTREACHED*/
1481     }
1482 
1483     for(kt = keytable; kt->token != CONF_UNKNOWN; kt++)
1484 	if(kt->token == token) break;
1485 
1486     if(kt->token == CONF_UNKNOWN)
1487 	return("");
1488     return(kt->keyword);
1489 }
1490 
1491 static tok_t
lookup_keyword(char * str)1492 lookup_keyword(
1493     char *	str)
1494 {
1495     keytab_t *kwp;
1496     char *str1 = stralloc(str);
1497     char *p = str1;
1498 
1499     /* Fold '-' to '_' in the token.  Note that this modifies str1
1500      * in place. */
1501     while (*p) {
1502 	if (*p == '-') *p = '_';
1503 	p++;
1504     }
1505 
1506     for(kwp = keytable; kwp->keyword != NULL; kwp++) {
1507 	if (strcasecmp(kwp->keyword, str1) == 0) break;
1508     }
1509 
1510     amfree(str1);
1511     return kwp->token;
1512 }
1513 
1514 static void
get_conftoken(tok_t exp)1515 get_conftoken(
1516     tok_t	exp)
1517 {
1518     int ch, d;
1519     gint64 int64;
1520     char *buf;
1521     char *tmps;
1522     int token_overflow;
1523     int inquote = 0;
1524     int escape = 0;
1525     int sign;
1526 
1527     if (token_pushed) {
1528 	token_pushed = 0;
1529 	tok = pushed_tok;
1530 
1531 	/*
1532 	** If it looked like a keyword before then look it
1533 	** up again in the current keyword table.
1534 	*/
1535 	switch(tok) {
1536 	case CONF_INT64:   case CONF_SIZE:
1537 	case CONF_INT:     case CONF_REAL:    case CONF_STRING:
1538 	case CONF_LBRACE:  case CONF_RBRACE:  case CONF_COMMA:
1539 	case CONF_NL:      case CONF_END:     case CONF_UNKNOWN:
1540 	case CONF_TIME:
1541 	    break; /* not a keyword */
1542 
1543 	default:
1544 	    if (exp == CONF_IDENT)
1545 		tok = CONF_IDENT;
1546 	    else
1547 		tok = lookup_keyword(tokenval.v.s);
1548 	    break;
1549 	}
1550     }
1551     else {
1552 	ch = conftoken_getc();
1553 
1554 	/* note that we're explicitly assuming this file is ASCII.  Someday
1555 	 * maybe we'll support UTF-8? */
1556 	while(ch != EOF && ch != '\n' && g_ascii_isspace(ch))
1557 	    ch = conftoken_getc();
1558 	if (ch == '#') {	/* comment - eat everything but eol/eof */
1559 	    while((ch = conftoken_getc()) != EOF && ch != '\n') {
1560 		(void)ch; /* Quiet empty loop complaints */
1561 	    }
1562 	}
1563 
1564 	if (isalpha(ch)) {		/* identifier */
1565 	    buf = tkbuf;
1566 	    token_overflow = 0;
1567 	    do {
1568 		if (buf < tkbuf+sizeof(tkbuf)-1) {
1569 		    *buf++ = (char)ch;
1570 		} else {
1571 		    *buf = '\0';
1572 		    if (!token_overflow) {
1573 			conf_parserror(_("token too long: %.20s..."), tkbuf);
1574 		    }
1575 		    token_overflow = 1;
1576 		}
1577 		ch = conftoken_getc();
1578 	    } while(isalnum(ch) || ch == '_' || ch == '-');
1579 
1580 	    if (ch != EOF && conftoken_ungetc(ch) == EOF) {
1581 		if (ferror(current_file)) {
1582 		    conf_parserror(_("Pushback of '%c' failed: %s"),
1583 				   ch, strerror(ferror(current_file)));
1584 		} else {
1585 		    conf_parserror(_("Pushback of '%c' failed: EOF"), ch);
1586 		}
1587 	    }
1588 	    *buf = '\0';
1589 
1590 	    tokenval.v.s = tkbuf;
1591 
1592 	    if (token_overflow) tok = CONF_UNKNOWN;
1593 	    else if (exp == CONF_IDENT) tok = CONF_IDENT;
1594 	    else tok = lookup_keyword(tokenval.v.s);
1595 	}
1596 	else if (isdigit(ch)) {	/* integer */
1597 	    sign = 1;
1598 
1599 negative_number: /* look for goto negative_number below sign is set there */
1600 	    int64 = 0;
1601 	    do {
1602 		int64 = int64 * 10 + (ch - '0');
1603 		ch = conftoken_getc();
1604 	    } while (isdigit(ch));
1605 
1606 	    if (ch != '.') {
1607 		if (exp == CONF_INT) {
1608 		    tok = CONF_INT;
1609 		    tokenval.v.i = sign * (int)int64;
1610 		} else if (exp != CONF_REAL) {
1611 		    tok = CONF_INT64;
1612 		    tokenval.v.int64 = (gint64)sign * int64;
1613 		} else {
1614 		    /* automatically convert to real when expected */
1615 		    tokenval.v.r = (double)sign * (double)int64;
1616 		    tok = CONF_REAL;
1617 		}
1618 	    } else {
1619 		/* got a real number, not an int */
1620 		tokenval.v.r = sign * (double) int64;
1621 		int64 = 0;
1622 		d = 1;
1623 		ch = conftoken_getc();
1624 		while (isdigit(ch)) {
1625 		    int64 = int64 * 10 + (ch - '0');
1626 		    d = d * 10;
1627 		    ch = conftoken_getc();
1628 		}
1629 		tokenval.v.r += sign * ((double)int64) / d;
1630 		tok = CONF_REAL;
1631 	    }
1632 
1633 	    if (ch != EOF &&  conftoken_ungetc(ch) == EOF) {
1634 		if (ferror(current_file)) {
1635 		    conf_parserror(_("Pushback of '%c' failed: %s"),
1636 				   ch, strerror(ferror(current_file)));
1637 		} else {
1638 		    conf_parserror(_("Pushback of '%c' failed: EOF"), ch);
1639 		}
1640 	    }
1641 	} else switch(ch) {
1642 	case '"':			/* string */
1643 	    buf = tkbuf;
1644 	    token_overflow = 0;
1645 	    inquote = 1;
1646 	    *buf++ = (char)ch;
1647 	    while (inquote && ((ch = conftoken_getc()) != EOF)) {
1648 		if (ch == '\n') {
1649 		    if (!escape) {
1650 			conf_parserror(_("string not terminated"));
1651 			conftoken_ungetc(ch);
1652 			break;
1653 		    }
1654 		    escape = 0;
1655 		    buf--; /* Consume escape in buffer */
1656 		} else if (ch == '\\' && !escape) {
1657 		    escape = 1;
1658 		} else {
1659 		    if (ch == '"') {
1660 			if (!escape)
1661 			    inquote = 0;
1662 		    }
1663 		    escape = 0;
1664 		}
1665 
1666 		if(buf >= &tkbuf[sizeof(tkbuf) - 1]) {
1667 		    if (!token_overflow) {
1668 			conf_parserror(_("string too long: %.20s..."), tkbuf);
1669 		    }
1670 		    token_overflow = 1;
1671 		    break;
1672 		}
1673 		*buf++ = (char)ch;
1674 	    }
1675 	    *buf = '\0';
1676 
1677 	    /*
1678 	     * A little manuver to leave a fully unquoted, unallocated  string
1679 	     * in tokenval.v.s
1680 	     */
1681 	    tmps = unquote_string(tkbuf);
1682 	    strncpy(tkbuf, tmps, sizeof(tkbuf));
1683 	    amfree(tmps);
1684 	    tokenval.v.s = tkbuf;
1685 
1686 	    tok = (token_overflow) ? CONF_UNKNOWN :
1687 			(exp == CONF_IDENT) ? CONF_IDENT : CONF_STRING;
1688 	    break;
1689 
1690 	case '-':
1691 	    ch = conftoken_getc();
1692 	    if (isdigit(ch)) {
1693 		sign = -1;
1694 		goto negative_number;
1695 	    }
1696 	    else {
1697 		if (ch != EOF && conftoken_ungetc(ch) == EOF) {
1698 		    if (ferror(current_file)) {
1699 			conf_parserror(_("Pushback of '%c' failed: %s"),
1700 				       ch, strerror(ferror(current_file)));
1701 		    } else {
1702 			conf_parserror(_("Pushback of '%c' failed: EOF"), ch);
1703 		    }
1704 		}
1705 		tok = CONF_UNKNOWN;
1706 	    }
1707 	    break;
1708 
1709 	case ',':
1710 	    tok = CONF_COMMA;
1711 	    break;
1712 
1713 	case '{':
1714 	    tok = CONF_LBRACE;
1715 	    break;
1716 
1717 	case '}':
1718 	    tok = CONF_RBRACE;
1719 	    break;
1720 
1721 	case '\n':
1722 	    tok = CONF_NL;
1723 	    break;
1724 
1725 	case EOF:
1726 	    tok = CONF_END;
1727 	    break;
1728 
1729 	default:
1730 	    tok = CONF_UNKNOWN;
1731 	    break;
1732 	}
1733     }
1734 
1735     if (exp != CONF_ANY && tok != exp) {
1736 	char *str;
1737 	keytab_t *kwp;
1738 
1739 	switch(exp) {
1740 	case CONF_LBRACE:
1741 	    str = "\"{\"";
1742 	    break;
1743 
1744 	case CONF_RBRACE:
1745 	    str = "\"}\"";
1746 	    break;
1747 
1748 	case CONF_COMMA:
1749 	    str = "\",\"";
1750 	    break;
1751 
1752 	case CONF_NL:
1753 	    str = _("end of line");
1754 	    break;
1755 
1756 	case CONF_END:
1757 	    str = _("end of file");
1758 	    break;
1759 
1760 	case CONF_INT:
1761 	    str = _("an integer");
1762 	    break;
1763 
1764 	case CONF_REAL:
1765 	    str = _("a real number");
1766 	    break;
1767 
1768 	case CONF_STRING:
1769 	    str = _("a quoted string");
1770 	    break;
1771 
1772 	case CONF_IDENT:
1773 	    str = _("an identifier");
1774 	    break;
1775 
1776 	default:
1777 	    for(kwp = keytable; kwp->keyword != NULL; kwp++) {
1778 		if (exp == kwp->token)
1779 		    break;
1780 	    }
1781 	    if (kwp->keyword == NULL)
1782 		str = _("token not");
1783 	    else
1784 		str = str_keyword(kwp);
1785 	    break;
1786 	}
1787 	conf_parserror(_("%s is expected"), str);
1788 	tok = exp;
1789 	if (tok == CONF_INT)
1790 	    tokenval.v.i = 0;
1791 	else
1792 	    tokenval.v.s = "";
1793     }
1794 }
1795 
1796 static void
unget_conftoken(void)1797 unget_conftoken(void)
1798 {
1799     assert(!token_pushed);
1800     token_pushed = 1;
1801     pushed_tok = tok;
1802     tok = CONF_UNKNOWN;
1803 }
1804 
1805 static int
conftoken_getc(void)1806 conftoken_getc(void)
1807 {
1808     if(current_line == NULL)
1809 	return getc(current_file);
1810     if(*current_char == '\0')
1811 	return -1;
1812     return(*current_char++);
1813 }
1814 
1815 static int
conftoken_ungetc(int c)1816 conftoken_ungetc(
1817     int c)
1818 {
1819     if(current_line == NULL)
1820 	return ungetc(c, current_file);
1821     else if(current_char > current_line) {
1822 	if(c == -1)
1823 	    return c;
1824 	current_char--;
1825 	if(*current_char != c) {
1826 	    error(_("*current_char != c   : %c %c"), *current_char, c);
1827 	    /* NOTREACHED */
1828 	}
1829     } else {
1830 	error(_("current_char == current_line"));
1831 	/* NOTREACHED */
1832     }
1833     return c;
1834 }
1835 
1836 /*
1837  * Parser Implementation
1838  */
1839 
1840 static void
read_conffile(char * filename,gboolean is_client,gboolean missing_ok)1841 read_conffile(
1842     char *filename,
1843     gboolean is_client,
1844     gboolean missing_ok)
1845 {
1846     /* Save global locations. */
1847     FILE *save_file     = current_file;
1848     char *save_filename = current_filename;
1849     int  save_line_num  = current_line_num;
1850     int	rc;
1851 
1852     if (is_client) {
1853 	keytable = client_keytab;
1854 	parsetable = client_var;
1855     } else {
1856 	keytable = server_keytab;
1857 	parsetable = server_var;
1858     }
1859     filename = config_dir_relative(filename);
1860     current_filename = get_seen_filename(filename);
1861     amfree(filename);
1862 
1863     if ((current_file = fopen(current_filename, "r")) == NULL) {
1864 	if (!missing_ok || errno != ENOENT)
1865 	    conf_parserror(_("could not open conf file \"%s\": %s"),
1866 		    current_filename, strerror(errno));
1867 	goto finish;
1868     }
1869 
1870     current_line_num = 0;
1871 
1872     do {
1873 	/* read_confline() can invoke us recursively via "includefile" */
1874 	rc = read_confline(is_client);
1875     } while (rc != 0);
1876 
1877     afclose(current_file);
1878 
1879 finish:
1880 
1881     /* Restore servers */
1882     current_line_num = save_line_num;
1883     current_file     = save_file;
1884     current_filename = save_filename;
1885 }
1886 
1887 static gboolean
read_confline(gboolean is_client)1888 read_confline(
1889     gboolean is_client)
1890 {
1891     conf_var_t *np;
1892 
1893     current_line_num += 1;
1894     get_conftoken(CONF_ANY);
1895     handle_deprecated_keyword();
1896 
1897     switch(tok) {
1898     case CONF_INCLUDEFILE:
1899 	get_conftoken(CONF_STRING);
1900 	read_conffile(tokenval.v.s, is_client, FALSE);
1901 	break;
1902 
1903     case CONF_DEFINE:
1904 	if (is_client) {
1905 	    get_conftoken(CONF_ANY);
1906 	    /* accept application-tool here, too, for backward compatibility */
1907 	    if(tok == CONF_APPLICATION_TOOL || tok == CONF_APPLICATION) get_application();
1908 	    else if(tok == CONF_SCRIPT_TOOL || tok == CONF_SCRIPT) get_pp_script();
1909 	    else conf_parserror(_("APPLICATION-TOOL or SCRIPT-TOOL expected"));
1910 	} else {
1911 	    get_conftoken(CONF_ANY);
1912 	    if(tok == CONF_DUMPTYPE) get_dumptype();
1913 	    else if(tok == CONF_TAPETYPE) get_tapetype();
1914 	    else if(tok == CONF_INTERFACE) get_interface();
1915 	    else if(tok == CONF_APPLICATION_TOOL || tok == CONF_APPLICATION) get_application();
1916 	    else if(tok == CONF_SCRIPT_TOOL || tok == CONF_SCRIPT) get_pp_script();
1917 	    else if(tok == CONF_DEVICE) get_device_config();
1918 	    else if(tok == CONF_CHANGER) get_changer_config();
1919 	    else if(tok == CONF_HOLDING) get_holdingdisk(1);
1920 	    else if(tok == CONF_INTERACTIVITY) get_interactivity();
1921 	    else if(tok == CONF_TAPERSCAN) get_taperscan();
1922 	    else conf_parserror(_("DUMPTYPE, INTERFACE, TAPETYPE, HOLDINGDISK, APPLICATION, SCRIPT, DEVICE, CHANGER, INTERACTIVITY or TAPERSCAN expected"));
1923 	    current_block = NULL;
1924 	}
1925 	break;
1926 
1927     case CONF_NL:	/* empty line */
1928 	break;
1929 
1930     case CONF_END:	/* end of file */
1931 	return 0;
1932 
1933     /* These should never be at the begining of a line */
1934     case CONF_LBRACE:
1935     case CONF_RBRACE:
1936     case CONF_IDENT:
1937     case CONF_INT:
1938     case CONF_INT64:
1939     case CONF_BOOL:
1940     case CONF_REAL:
1941     case CONF_STRING:
1942     case CONF_TIME:
1943     case CONF_SIZE:
1944 	conf_parserror("error: not a keyword.");
1945 	break;
1946 
1947     /* if it's not a known punctuation mark, then check the parse table and use the
1948      * read_function we find there. */
1949     default:
1950 	{
1951 	    for(np = parsetable; np->token != CONF_UNKNOWN; np++)
1952 		if(np->token == tok) break;
1953 
1954 	    if(np->token == CONF_UNKNOWN) {
1955                 handle_invalid_keyword(tokenval.v.s);
1956 	    } else {
1957 		np->read_function(np, &conf_data[np->parm]);
1958 		if(np->validate_function)
1959 		    np->validate_function(np, &conf_data[np->parm]);
1960 	    }
1961 	}
1962     }
1963     if(tok != CONF_NL)
1964 	get_conftoken(CONF_NL);
1965     return 1;
1966 }
1967 
1968 static void
handle_deprecated_keyword(void)1969 handle_deprecated_keyword(void)
1970 {
1971     /* Procedure for deprecated keywords:
1972      *
1973      * 1) At time of deprecation, add to warning_deprecated below.  Note the
1974      *    version in which deprecation will expire.  The keyword will still be
1975      *    parsed, and can still be used from other parts of Amanda, during this
1976      *    time.
1977      * 2) After it has expired, move the keyword (as a string) to
1978      *    error_deprecated below. Remove the token (CONF_XXX) and
1979      *    config parameter (CNF_XXX) from the rest of the module.
1980      *    Note the date of the move.
1981      */
1982 
1983     static struct { tok_t tok; gboolean warned; }
1984     warning_deprecated[] = {
1985 	{ CONF_LABEL_NEW_TAPES, 0 },	/* exp in Amanda-3.2 */
1986 	{ CONF_AMRECOVER_DO_FSF, 0 },	/* exp in Amanda-3.3 */
1987 	{ CONF_AMRECOVER_CHECK_LABEL, 0 }, /* exp in Amanda-3.3 */
1988 	{ CONF_TAPE_SPLITSIZE, 0 },	/* exp. in Amanda-3.3 */
1989 	{ CONF_SPLIT_DISKBUFFER, 0 },	/* exp. in Amanda-3.3 */
1990 	{ CONF_FALLBACK_SPLITSIZE, 0 }, /* exp. in Amanda-3.3 */
1991 	{ 0, 0 },
1992     }, *dep;
1993 
1994     for (dep = warning_deprecated; dep->tok; dep++) {
1995 	if (tok == dep->tok) {
1996 	    if (!dep->warned)
1997 		conf_parswarn(_("warning: Keyword %s is deprecated."),
1998 			       tokenval.v.s);
1999 	    dep->warned = 1;
2000 	    break;
2001 	}
2002     }
2003 }
2004 
2005 static void
handle_invalid_keyword(const char * token)2006 handle_invalid_keyword(
2007     const char * token)
2008 {
2009     static const char * error_deprecated[] = {
2010 	"rawtapedev",
2011 	"tapebufs", /* deprecated: 2007-10-15; invalid: 2010-04-14 */
2012 	"file-pad", /* deprecated: 2008-07-01; invalid: 2010-04-14 */
2013         NULL
2014     };
2015     const char ** s;
2016     char *folded_token, *p;
2017 
2018     /* convert '_' to '-' in TOKEN */
2019     folded_token = g_strdup(token);
2020     for (p = folded_token; *p; p++) {
2021 	if (*p == '_') *p = '-';
2022     }
2023 
2024     for (s = error_deprecated; *s != NULL; s ++) {
2025 	if (g_ascii_strcasecmp(*s, folded_token) == 0) {
2026 	    conf_parserror(_("error: Keyword %s is deprecated."),
2027 			   token);
2028 	    g_free(folded_token);
2029 	    return;
2030 	}
2031     }
2032     g_free(folded_token);
2033 
2034     if (*s == NULL) {
2035         conf_parserror(_("configuration keyword expected"));
2036     }
2037 
2038     for (;;) {
2039         int c = conftoken_getc();
2040         if (c == '\n' || c == -1) {
2041             conftoken_ungetc(c);
2042             return;
2043         }
2044     }
2045 
2046     g_assert_not_reached();
2047 }
2048 
2049 static char *
get_seen_filename(char * filename)2050 get_seen_filename(
2051     char *filename)
2052 {
2053     GSList *iter;
2054     char *istr;
2055 
2056     for (iter = seen_filenames; iter; iter = iter->next) {
2057 	istr = iter->data;
2058 	if (istr == filename || 0 == strcmp(istr, filename))
2059 	    return istr;
2060     }
2061 
2062     istr = stralloc(filename);
2063     seen_filenames = g_slist_prepend(seen_filenames, istr);
2064     return istr;
2065 }
2066 
2067 static void
read_block(conf_var_t * read_var,val_t * valarray,char * errormsg,int read_brace,void (* copy_function)(void),char * type,char * name)2068 read_block(
2069     conf_var_t    *read_var,
2070     val_t    *valarray,
2071     char     *errormsg,
2072     int       read_brace,
2073     void      (*copy_function)(void),
2074     char     *type,
2075     char     *name)
2076 {
2077     conf_var_t *np;
2078     int         done;
2079     char       *key_ovr;
2080     int         i;
2081 
2082     if(read_brace) {
2083 	get_conftoken(CONF_LBRACE);
2084 	get_conftoken(CONF_NL);
2085     }
2086 
2087     done = 0;
2088     do {
2089 	current_line_num += 1;
2090 	get_conftoken(CONF_ANY);
2091 	handle_deprecated_keyword();
2092 
2093 	switch(tok) {
2094 	case CONF_RBRACE:
2095 	    done = 1;
2096 	    break;
2097 	case CONF_NL:	/* empty line */
2098 	    break;
2099 	case CONF_END:	/* end of file */
2100 	    done = 1;
2101 	    break;
2102 
2103 	/* inherit from a "parent" */
2104         case CONF_IDENT:
2105         case CONF_STRING:
2106 	    if(copy_function)
2107 		copy_function();
2108 	    else
2109 		conf_parserror(_("ident not expected"));
2110 	    break;
2111 	default:
2112 	    {
2113 		for(np = read_var; np->token != CONF_UNKNOWN; np++)
2114 		    if(np->token == tok) break;
2115 
2116 		if(np->token == CONF_UNKNOWN)
2117 		    conf_parserror("%s", errormsg);
2118 		else {
2119 		    np->read_function(np, &valarray[np->parm]);
2120 		    if(np->validate_function)
2121 			np->validate_function(np, &valarray[np->parm]);
2122 		}
2123 	    }
2124 	}
2125 	if(tok != CONF_NL && tok != CONF_END && tok != CONF_RBRACE)
2126 	    get_conftoken(CONF_NL);
2127     } while(!done);
2128 
2129     if (!config_overrides)
2130 	return;
2131 
2132     key_ovr = vstralloc(type, ":", name, NULL);
2133     for (i = 0; i < config_overrides->n_used; i++) {
2134 	config_override_t *co = &config_overrides->ovr[i];
2135 	char              *key = co->key;
2136 	char              *keyword;
2137 	char              *value;
2138 
2139 	if (key_ovr && strncasecmp(key_ovr, key, strlen(key_ovr)) != 0)
2140 	    continue;
2141 
2142 	if (strlen(key) <= strlen(key_ovr) + 1)
2143 	    continue;
2144 
2145 	keyword = key + strlen(key_ovr) + 1;
2146 	value = co->value;
2147 
2148 	tok = lookup_keyword(keyword);
2149 	if (tok == CONF_UNKNOWN)
2150 	     continue;
2151 
2152 	/* find the var in read_var */
2153 	for (np = read_var; np->token != CONF_UNKNOWN; np++)
2154 	    if (np->token == tok) break;
2155 	if (np->token == CONF_UNKNOWN)
2156 	    continue;
2157 
2158 	/* now set up a fake line and use the relevant read_function to
2159 	 * parse it.  This is sneaky! */
2160 	if (np->type == CONFTYPE_STR) {
2161 	    current_line = quote_string_always(value);
2162 	} else {
2163 	    current_line = stralloc(value);
2164 	}
2165 
2166 	current_char = current_line;
2167 	token_pushed = 0;
2168 	current_line_num = -2;
2169 	allow_overwrites = 1;
2170 	co->applied = TRUE;
2171 
2172 	np->read_function(np, &valarray[np->parm]);
2173 	if (np->validate_function)
2174 	    np->validate_function(np, &valarray[np->parm]);
2175 
2176 	amfree(current_line);
2177 	current_char = NULL;
2178     }
2179     token_pushed = 0;
2180     amfree(key_ovr);
2181 
2182 }
2183 
2184 static void
read_holdingdisk(conf_var_t * np G_GNUC_UNUSED,val_t * val G_GNUC_UNUSED)2185 read_holdingdisk(
2186     conf_var_t *np  G_GNUC_UNUSED,
2187     val_t      *val G_GNUC_UNUSED)
2188 {
2189     assert (val == &conf_data[CNF_HOLDINGDISK]);
2190     get_holdingdisk(0);
2191 }
2192 
2193 static void
get_holdingdisk(int is_define)2194 get_holdingdisk(
2195     int is_define)
2196 {
2197     int save_overwrites;
2198     char *saved_block;
2199 
2200     saved_block = current_block;
2201     save_overwrites = allow_overwrites;
2202     allow_overwrites = 1;
2203 
2204     init_holdingdisk_defaults();
2205 
2206     get_conftoken(CONF_IDENT);
2207     hdcur.name = stralloc(tokenval.v.s);
2208     current_block = g_strconcat("holdingdisk ", hdcur.name, NULL);
2209     hdcur.seen.block = current_block;
2210     hdcur.seen.filename = current_filename;
2211     hdcur.seen.linenum = current_line_num;
2212 
2213     get_conftoken(CONF_ANY);
2214     if (tok == CONF_LBRACE) {
2215 	holdingdisk_t *hd;
2216 	hd = lookup_holdingdisk(hdcur.name);
2217 	if (hd) {
2218 	    conf_parserror(_("holding disk '%s' already defined"),
2219 			       hdcur.name);
2220 	} else {
2221 	    unget_conftoken();
2222 	    read_block(holding_var, hdcur.value,
2223 		     _("holding disk parameter expected"), 1, copy_holdingdisk,
2224 		     "HOLDINGDISK", hdcur.name);
2225 	    get_conftoken(CONF_NL);
2226             save_holdingdisk();
2227 	    if (!is_define) {
2228 		conf_data[CNF_HOLDINGDISK].v.identlist = g_slist_append(
2229 				conf_data[CNF_HOLDINGDISK].v.identlist,
2230 				stralloc(hdcur.name));
2231 	    }
2232 	}
2233     } else { /* use the already defined holding disk */
2234 	unget_conftoken();
2235 	if (is_define) {
2236 	    conf_parserror(_("holdingdisk definition must specify holdingdisk parameters"));
2237 	}
2238 	do {
2239 	    identlist_t il;
2240 
2241 	    for (il = conf_data[CNF_HOLDINGDISK].v.identlist; il != NULL;
2242 							      il = il->next) {
2243 		if (strcmp((char *)il->data, hdcur.name) == 0) {
2244 		    break;
2245 		}
2246 	    }
2247 	    if (il) {
2248 		conf_parserror(_("holding disk '%s' already in use"),
2249 			       hdcur.name);
2250 	    } else {
2251 		conf_data[CNF_HOLDINGDISK].v.identlist = g_slist_append(
2252 				conf_data[CNF_HOLDINGDISK].v.identlist,
2253 				stralloc(hdcur.name));
2254 	    }
2255 	    amfree(hdcur.name);
2256 	    get_conftoken(CONF_ANY);
2257 	    if (tok == CONF_IDENT || tok == CONF_STRING) {
2258 		hdcur.name = stralloc(tokenval.v.s);
2259 	    } else if (tok != CONF_NL) {
2260 		conf_parserror(_("IDENT or NL expected"));
2261 	    }
2262 	} while (tok == CONF_IDENT || tok == CONF_STRING);
2263     }
2264 
2265     allow_overwrites = save_overwrites;
2266 
2267     current_block = saved_block;
2268 }
2269 
2270 static void
init_holdingdisk_defaults(void)2271 init_holdingdisk_defaults(
2272     void)
2273 {
2274     conf_init_str(&hdcur.value[HOLDING_COMMENT]  , "");
2275     conf_init_str(&hdcur.value[HOLDING_DISKDIR]  , "");
2276     conf_init_int64(&hdcur.value[HOLDING_DISKSIZE] , CONF_UNIT_K, (gint64)0);
2277                     /* 1 Gb = 1M counted in 1Kb blocks */
2278     conf_init_int64(&hdcur.value[HOLDING_CHUNKSIZE], CONF_UNIT_K, (gint64)1024*1024);
2279 }
2280 
2281 static void
save_holdingdisk(void)2282 save_holdingdisk(
2283     void)
2284 {
2285     holdingdisk_t *hp;
2286 
2287     hp = alloc(sizeof(holdingdisk_t));
2288     *hp = hdcur;
2289     holdinglist = g_slist_append(holdinglist, hp);
2290 }
2291 
2292 static void
copy_holdingdisk(void)2293 copy_holdingdisk(
2294     void)
2295 {
2296     holdingdisk_t *hp;
2297     int i;
2298 
2299     hp = lookup_holdingdisk(tokenval.v.s);
2300 
2301     if (hp == NULL) {
2302         conf_parserror(_("holdingdisk parameter expected"));
2303         return;
2304     }
2305 
2306     for(i=0; i < HOLDING_HOLDING; i++) {
2307         if(hp->value[i].seen.linenum) {
2308             merge_val_t(&hdcur.value[i], &hp->value[i]);
2309         }
2310     }
2311 
2312 }
2313 
2314 
2315 /* WARNING:
2316  * This function is called both from this module and from diskfile.c. Modify
2317  * with caution. */
2318 dumptype_t *
read_dumptype(char * name,FILE * from,char * fname,int * linenum)2319 read_dumptype(
2320     char *name,
2321     FILE *from,
2322     char *fname,
2323     int *linenum)
2324 {
2325     int save_overwrites;
2326     FILE *saved_conf = NULL;
2327     char *saved_fname = NULL;
2328     char *saved_block;
2329 
2330     if (from) {
2331 	saved_conf = current_file;
2332 	current_file = from;
2333     }
2334 
2335     if (fname) {
2336 	saved_fname = current_filename;
2337 	current_filename = get_seen_filename(fname);
2338     }
2339 
2340     if (linenum)
2341 	current_line_num = *linenum;
2342 
2343     saved_block = current_block;
2344     save_overwrites = allow_overwrites;
2345     allow_overwrites = 1;
2346 
2347     init_dumptype_defaults();
2348     if (name) {
2349 	dpcur.name = name;
2350     } else {
2351 	get_conftoken(CONF_IDENT);
2352 	dpcur.name = stralloc(tokenval.v.s);
2353     }
2354     current_block = g_strconcat("dumptype ", dpcur.name, NULL);
2355     dpcur.seen.block = current_block;
2356     dpcur.seen.filename = current_filename;
2357     dpcur.seen.linenum = current_line_num;
2358 
2359     read_block(dumptype_var, dpcur.value,
2360 	       _("dumptype parameter expected"),
2361 	       (name == NULL), copy_dumptype,
2362 	       "DUMPTYPE", dpcur.name);
2363 
2364     if(!name) /* !name => reading disklist, not conffile */
2365 	get_conftoken(CONF_NL);
2366 
2367     /* XXX - there was a stupidity check in here for skip-incr and
2368     ** skip-full.  This check should probably be somewhere else. */
2369 
2370     save_dumptype();
2371 
2372     allow_overwrites = save_overwrites;
2373 
2374     current_block = saved_block;
2375 
2376     if (linenum)
2377 	*linenum = current_line_num;
2378 
2379     if (fname)
2380 	current_filename = saved_fname;
2381 
2382     if (from)
2383 	current_file = saved_conf;
2384 
2385     return lookup_dumptype(dpcur.name);
2386 }
2387 
2388 static void
get_dumptype(void)2389 get_dumptype(void)
2390 {
2391     read_dumptype(NULL, NULL, NULL, NULL);
2392 }
2393 
2394 static void
init_dumptype_defaults(void)2395 init_dumptype_defaults(void)
2396 {
2397     dpcur.name = NULL;
2398     conf_init_str   (&dpcur.value[DUMPTYPE_COMMENT]           , "");
2399     conf_init_str   (&dpcur.value[DUMPTYPE_PROGRAM]           , "DUMP");
2400     conf_init_str   (&dpcur.value[DUMPTYPE_SRVCOMPPROG]       , "");
2401     conf_init_str   (&dpcur.value[DUMPTYPE_CLNTCOMPPROG]      , "");
2402     conf_init_str   (&dpcur.value[DUMPTYPE_SRV_ENCRYPT]       , "");
2403     conf_init_str   (&dpcur.value[DUMPTYPE_CLNT_ENCRYPT]      , "");
2404     conf_init_str   (&dpcur.value[DUMPTYPE_AMANDAD_PATH]      , "");
2405     conf_init_str   (&dpcur.value[DUMPTYPE_CLIENT_USERNAME]   , "");
2406     conf_init_str   (&dpcur.value[DUMPTYPE_CLIENT_PORT]       , "");
2407     conf_init_str   (&dpcur.value[DUMPTYPE_SSH_KEYS]          , "");
2408     conf_init_str   (&dpcur.value[DUMPTYPE_AUTH]   , "BSDTCP");
2409     conf_init_exinclude(&dpcur.value[DUMPTYPE_EXCLUDE]);
2410     conf_init_exinclude(&dpcur.value[DUMPTYPE_INCLUDE]);
2411     conf_init_priority (&dpcur.value[DUMPTYPE_PRIORITY]          , 1);
2412     conf_init_int      (&dpcur.value[DUMPTYPE_DUMPCYCLE]         , CONF_UNIT_NONE, conf_data[CNF_DUMPCYCLE].v.i);
2413     conf_init_int      (&dpcur.value[DUMPTYPE_MAXDUMPS]          , CONF_UNIT_NONE, conf_data[CNF_MAXDUMPS].v.i);
2414     conf_init_int      (&dpcur.value[DUMPTYPE_MAXPROMOTEDAY]     , CONF_UNIT_NONE, 10000);
2415     conf_init_int      (&dpcur.value[DUMPTYPE_BUMPPERCENT]       , CONF_UNIT_NONE, conf_data[CNF_BUMPPERCENT].v.i);
2416     conf_init_int64    (&dpcur.value[DUMPTYPE_BUMPSIZE]          , CONF_UNIT_K   , conf_data[CNF_BUMPSIZE].v.int64);
2417     conf_init_int      (&dpcur.value[DUMPTYPE_BUMPDAYS]          , CONF_UNIT_NONE, conf_data[CNF_BUMPDAYS].v.i);
2418     conf_init_real     (&dpcur.value[DUMPTYPE_BUMPMULT]          , conf_data[CNF_BUMPMULT].v.r);
2419     conf_init_time     (&dpcur.value[DUMPTYPE_STARTTIME]         , (time_t)0);
2420     conf_init_strategy (&dpcur.value[DUMPTYPE_STRATEGY]          , DS_STANDARD);
2421     conf_init_estimatelist(&dpcur.value[DUMPTYPE_ESTIMATELIST]   , ES_CLIENT);
2422     conf_init_compress (&dpcur.value[DUMPTYPE_COMPRESS]          , COMP_FAST);
2423     conf_init_encrypt  (&dpcur.value[DUMPTYPE_ENCRYPT]           , ENCRYPT_NONE);
2424     conf_init_data_path(&dpcur.value[DUMPTYPE_DATA_PATH]         , DATA_PATH_AMANDA);
2425     conf_init_str   (&dpcur.value[DUMPTYPE_SRV_DECRYPT_OPT]   , "-d");
2426     conf_init_str   (&dpcur.value[DUMPTYPE_CLNT_DECRYPT_OPT]  , "-d");
2427     conf_init_rate     (&dpcur.value[DUMPTYPE_COMPRATE]          , 0.50, 0.50);
2428     conf_init_int64    (&dpcur.value[DUMPTYPE_TAPE_SPLITSIZE]    , CONF_UNIT_K, (gint64)0);
2429     conf_init_int64    (&dpcur.value[DUMPTYPE_FALLBACK_SPLITSIZE], CONF_UNIT_K, (gint64)10 * 1024);
2430     conf_init_str   (&dpcur.value[DUMPTYPE_SPLIT_DISKBUFFER]  , NULL);
2431     conf_init_bool     (&dpcur.value[DUMPTYPE_RECORD]            , 1);
2432     conf_init_bool     (&dpcur.value[DUMPTYPE_SKIP_INCR]         , 0);
2433     conf_init_bool     (&dpcur.value[DUMPTYPE_SKIP_FULL]         , 0);
2434     conf_init_holding  (&dpcur.value[DUMPTYPE_HOLDINGDISK]       , HOLD_AUTO);
2435     conf_init_bool     (&dpcur.value[DUMPTYPE_KENCRYPT]          , 0);
2436     conf_init_bool     (&dpcur.value[DUMPTYPE_IGNORE]            , 0);
2437     conf_init_bool     (&dpcur.value[DUMPTYPE_INDEX]             , 1);
2438     conf_init_application(&dpcur.value[DUMPTYPE_APPLICATION]);
2439     conf_init_identlist(&dpcur.value[DUMPTYPE_SCRIPTLIST], NULL);
2440     conf_init_proplist(&dpcur.value[DUMPTYPE_PROPERTY]);
2441     conf_init_bool     (&dpcur.value[DUMPTYPE_ALLOW_SPLIT]       , 1);
2442     conf_init_int      (&dpcur.value[DUMPTYPE_MAX_WARNINGS]      , CONF_UNIT_NONE, 20);
2443     conf_init_host_limit(&dpcur.value[DUMPTYPE_RECOVERY_LIMIT]);
2444     conf_init_host_limit_server(&dpcur.value[DUMPTYPE_DUMP_LIMIT]);
2445 }
2446 
2447 static void
save_dumptype(void)2448 save_dumptype(void)
2449 {
2450     dumptype_t *dp, *dp1;;
2451 
2452     dp = lookup_dumptype(dpcur.name);
2453 
2454     if(dp != (dumptype_t *)0) {
2455 	if (dp->seen.linenum == -1) {
2456 	    conf_parserror(_("dumptype %s is defined by default and cannot be redefined"), dp->name);
2457 	} else {
2458 	    conf_parserror(_("dumptype %s already defined at %s:%d"), dp->name,
2459 			   dp->seen.filename, dp->seen.linenum);
2460 	}
2461 	return;
2462     }
2463 
2464     dp = alloc(sizeof(dumptype_t));
2465     *dp = dpcur;
2466     dp->next = NULL;
2467     /* add at end of list */
2468     if(!dumplist)
2469 	dumplist = dp;
2470     else {
2471 	dp1 = dumplist;
2472 	while (dp1->next != NULL) {
2473 	     dp1 = dp1->next;
2474 	}
2475 	dp1->next = dp;
2476     }
2477 }
2478 
2479 static void
copy_dumptype(void)2480 copy_dumptype(void)
2481 {
2482     dumptype_t *dt;
2483     int i;
2484 
2485     dt = lookup_dumptype(tokenval.v.s);
2486 
2487     if(dt == NULL) {
2488 	conf_parserror(_("dumptype parameter expected"));
2489 	return;
2490     }
2491 
2492     for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
2493 	if(dt->value[i].seen.linenum) {
2494 	    merge_val_t(&dpcur.value[i], &dt->value[i]);
2495 	    if (i == DUMPTYPE_SCRIPTLIST) {
2496 		/* sort in 'order' */
2497 		dpcur.value[i].v.identlist = g_slist_sort(dpcur.value[i].v.identlist, &compare_pp_script_order);
2498 	    }
2499 	}
2500     }
2501 }
2502 
2503 static void
get_tapetype(void)2504 get_tapetype(void)
2505 {
2506     int save_overwrites;
2507     char *saved_block;
2508 
2509     saved_block = current_block;
2510     save_overwrites = allow_overwrites;
2511     allow_overwrites = 1;
2512 
2513     init_tapetype_defaults();
2514 
2515     get_conftoken(CONF_IDENT);
2516     tpcur.name = stralloc(tokenval.v.s);
2517     current_block = g_strconcat("tapetype ", tpcur.name, NULL);
2518     tpcur.seen.block = current_block;
2519     tpcur.seen.filename = current_filename;
2520     tpcur.seen.linenum = current_line_num;
2521 
2522     read_block(tapetype_var, tpcur.value,
2523 	       _("tapetype parameter expected"), 1, copy_tapetype,
2524 	       "TAPETYPE", tpcur.name);
2525     get_conftoken(CONF_NL);
2526 
2527     if (tapetype_get_readblocksize(&tpcur) <
2528 	tapetype_get_blocksize(&tpcur)) {
2529 	conf_init_size(&tpcur.value[TAPETYPE_READBLOCKSIZE], CONF_UNIT_K,
2530 		       tapetype_get_blocksize(&tpcur));
2531     }
2532     save_tapetype();
2533 
2534     allow_overwrites = save_overwrites;
2535 
2536     current_block = saved_block;
2537 }
2538 
2539 static void
init_tapetype_defaults(void)2540 init_tapetype_defaults(void)
2541 {
2542     conf_init_str(&tpcur.value[TAPETYPE_COMMENT]      , "");
2543     conf_init_str(&tpcur.value[TAPETYPE_LBL_TEMPL]    , "");
2544     conf_init_size  (&tpcur.value[TAPETYPE_BLOCKSIZE]    , CONF_UNIT_K, DISK_BLOCK_KB);
2545     conf_init_size  (&tpcur.value[TAPETYPE_READBLOCKSIZE], CONF_UNIT_K, DISK_BLOCK_KB);
2546     conf_init_int64 (&tpcur.value[TAPETYPE_LENGTH]       , CONF_UNIT_K, ((gint64)2000));
2547     conf_init_int64 (&tpcur.value[TAPETYPE_FILEMARK]     , CONF_UNIT_K, (gint64)1);
2548     conf_init_int   (&tpcur.value[TAPETYPE_SPEED]        , CONF_UNIT_NONE, 200);
2549     conf_init_int64(&tpcur.value[TAPETYPE_PART_SIZE], CONF_UNIT_K, 0);
2550     conf_init_part_cache_type(&tpcur.value[TAPETYPE_PART_CACHE_TYPE], PART_CACHE_TYPE_NONE);
2551     conf_init_str(&tpcur.value[TAPETYPE_PART_CACHE_DIR], "");
2552     conf_init_int64(&tpcur.value[TAPETYPE_PART_CACHE_MAX_SIZE], CONF_UNIT_K, 0);
2553 }
2554 
2555 static void
save_tapetype(void)2556 save_tapetype(void)
2557 {
2558     tapetype_t *tp, *tp1;
2559 
2560     tp = lookup_tapetype(tpcur.name);
2561 
2562     if(tp != (tapetype_t *)0) {
2563 	amfree(tpcur.name);
2564 	conf_parserror(_("tapetype %s already defined at %s:%d"),
2565 		tp->name, tp->seen.filename, tp->seen.linenum);
2566 	return;
2567     }
2568 
2569     tp = alloc(sizeof(tapetype_t));
2570     *tp = tpcur;
2571 
2572     /* add at end of list */
2573     if(!tapelist)
2574 	tapelist = tp;
2575     else {
2576 	tp1 = tapelist;
2577 	while (tp1->next != NULL) {
2578 	    tp1 = tp1->next;
2579 	}
2580 	tp1->next = tp;
2581     }
2582 }
2583 
2584 static void
copy_tapetype(void)2585 copy_tapetype(void)
2586 {
2587     tapetype_t *tp;
2588     int i;
2589 
2590     tp = lookup_tapetype(tokenval.v.s);
2591 
2592     if(tp == NULL) {
2593 	conf_parserror(_("tape type parameter expected"));
2594 	return;
2595     }
2596 
2597     for(i=0; i < TAPETYPE_TAPETYPE; i++) {
2598 	if(tp->value[i].seen.linenum) {
2599 	    merge_val_t(&tpcur.value[i], &tp->value[i]);
2600 	}
2601     }
2602 }
2603 
2604 static void
get_interface(void)2605 get_interface(void)
2606 {
2607     int save_overwrites;
2608     char *saved_block;
2609 
2610     saved_block = current_block;
2611     save_overwrites = allow_overwrites;
2612     allow_overwrites = 1;
2613 
2614     init_interface_defaults();
2615 
2616     get_conftoken(CONF_IDENT);
2617     ifcur.name = stralloc(tokenval.v.s);
2618     current_block = g_strconcat("interface ", ifcur.name, NULL);
2619     ifcur.seen.block = current_block;
2620     ifcur.seen.filename = current_filename;
2621     ifcur.seen.linenum = current_line_num;
2622 
2623     read_block(interface_var, ifcur.value,
2624 	       _("interface parameter expected"), 1, copy_interface,
2625 	       "INTERFACE", ifcur.name);
2626     get_conftoken(CONF_NL);
2627 
2628     save_interface();
2629 
2630     allow_overwrites = save_overwrites;
2631 
2632     current_block = saved_block;
2633 
2634     return;
2635 }
2636 
2637 static void
init_interface_defaults(void)2638 init_interface_defaults(void)
2639 {
2640     conf_init_str(&ifcur.value[INTER_COMMENT] , "");
2641     conf_init_int   (&ifcur.value[INTER_MAXUSAGE], CONF_UNIT_K, 80000);
2642 }
2643 
2644 static void
save_interface(void)2645 save_interface(void)
2646 {
2647     interface_t *ip, *ip1;
2648 
2649     ip = lookup_interface(ifcur.name);
2650 
2651     if(ip != (interface_t *)0) {
2652 	conf_parserror(_("interface %s already defined at %s:%d"),
2653 		ip->name, ip->seen.filename, ip->seen.linenum);
2654 	return;
2655     }
2656 
2657     ip = alloc(sizeof(interface_t));
2658     *ip = ifcur;
2659     /* add at end of list */
2660     if(!interface_list) {
2661 	interface_list = ip;
2662     } else {
2663 	ip1 = interface_list;
2664 	while (ip1->next != NULL) {
2665 	    ip1 = ip1->next;
2666 	}
2667 	ip1->next = ip;
2668     }
2669 }
2670 
2671 static void
copy_interface(void)2672 copy_interface(void)
2673 {
2674     interface_t *ip;
2675     int i;
2676 
2677     ip = lookup_interface(tokenval.v.s);
2678 
2679     if(ip == NULL) {
2680 	conf_parserror(_("interface parameter expected"));
2681 	return;
2682     }
2683 
2684     for(i=0; i < INTER_INTER; i++) {
2685 	if(ip->value[i].seen.linenum) {
2686 	    merge_val_t(&ifcur.value[i], &ip->value[i]);
2687 	}
2688     }
2689 }
2690 
2691 
2692 static application_t *
read_application(char * name,FILE * from,char * fname,int * linenum)2693 read_application(
2694     char *name,
2695     FILE *from,
2696     char *fname,
2697     int *linenum)
2698 {
2699     int save_overwrites;
2700     FILE *saved_conf = NULL;
2701     char *saved_fname = NULL;
2702     char *saved_block;
2703 
2704     if (from) {
2705 	saved_conf = current_file;
2706 	current_file = from;
2707     }
2708 
2709     if (fname) {
2710 	saved_fname = current_filename;
2711 	current_filename = get_seen_filename(fname);
2712     }
2713 
2714     if (linenum)
2715 	current_line_num = *linenum;
2716 
2717     saved_block = current_block;
2718     save_overwrites = allow_overwrites;
2719     allow_overwrites = 1;
2720 
2721     init_application_defaults();
2722     if (name) {
2723 	apcur.name = name;
2724     } else {
2725 	get_conftoken(CONF_IDENT);
2726 	apcur.name = stralloc(tokenval.v.s);
2727     }
2728     current_block = g_strconcat("application ", apcur.name, NULL);
2729     apcur.seen.block = current_block;
2730     apcur.seen.filename = current_filename;
2731     apcur.seen.linenum = current_line_num;
2732 
2733     read_block(application_var, apcur.value,
2734 	       _("application parameter expected"),
2735 	       (name == NULL), *copy_application,
2736 	       "APPLICATION", apcur.name);
2737     if(!name)
2738 	get_conftoken(CONF_NL);
2739 
2740     save_application();
2741 
2742     allow_overwrites = save_overwrites;
2743 
2744     current_block = saved_block;
2745     if (linenum)
2746 	*linenum = current_line_num;
2747 
2748     if (fname)
2749 	current_filename = saved_fname;
2750 
2751     if (from)
2752 	current_file = saved_conf;
2753 
2754     return lookup_application(apcur.name);
2755 }
2756 
2757 static void
get_application(void)2758 get_application(
2759     void)
2760 {
2761     read_application(NULL, NULL, NULL, NULL);
2762 }
2763 
2764 static void
init_application_defaults(void)2765 init_application_defaults(
2766     void)
2767 {
2768     apcur.name = NULL;
2769     conf_init_str(&apcur.value[APPLICATION_COMMENT] , "");
2770     conf_init_str(&apcur.value[APPLICATION_PLUGIN]  , "");
2771     conf_init_proplist(&apcur.value[APPLICATION_PROPERTY]);
2772     conf_init_str(&apcur.value[APPLICATION_CLIENT_NAME] , "");
2773 }
2774 
2775 static void
save_application(void)2776 save_application(
2777     void)
2778 {
2779     application_t *ap, *ap1;
2780 
2781     ap = lookup_application(apcur.name);
2782 
2783     if(ap != (application_t *)0) {
2784 	conf_parserror(_("application %s already defined at %s:%d"),
2785 		       ap->name, ap->seen.filename, ap->seen.linenum);
2786 	return;
2787     }
2788 
2789     ap = alloc(sizeof(application_t));
2790     *ap = apcur;
2791     ap->next = NULL;
2792     /* add at end of list */
2793     if (!application_list)
2794 	application_list = ap;
2795     else {
2796 	ap1 = application_list;
2797 	while (ap1->next != NULL) {
2798 	    ap1 = ap1->next;
2799 	}
2800 	ap1->next = ap;
2801     }
2802 }
2803 
2804 static void
copy_application(void)2805 copy_application(void)
2806 {
2807     application_t *ap;
2808     int i;
2809 
2810     ap = lookup_application(tokenval.v.s);
2811 
2812     if(ap == NULL) {
2813 	conf_parserror(_("application parameter expected"));
2814 	return;
2815     }
2816 
2817     for(i=0; i < APPLICATION_APPLICATION; i++) {
2818 	if(ap->value[i].seen.linenum) {
2819 	    merge_val_t(&apcur.value[i], &ap->value[i]);
2820 	}
2821     }
2822 }
2823 
2824 static interactivity_t *
read_interactivity(char * name,FILE * from,char * fname,int * linenum)2825 read_interactivity(
2826     char *name,
2827     FILE *from,
2828     char *fname,
2829     int *linenum)
2830 {
2831     int save_overwrites;
2832     FILE *saved_conf = NULL;
2833     char *saved_fname = NULL;
2834     char *saved_block;
2835 
2836     if (from) {
2837 	saved_conf = current_file;
2838 	current_file = from;
2839     }
2840 
2841     if (fname) {
2842 	saved_fname = current_filename;
2843 	current_filename = get_seen_filename(fname);
2844     }
2845 
2846     if (linenum)
2847 	current_line_num = *linenum;
2848 
2849     saved_block = current_block;
2850     save_overwrites = allow_overwrites;
2851     allow_overwrites = 1;
2852 
2853     init_interactivity_defaults();
2854     if (name) {
2855 	ivcur.name = name;
2856     } else {
2857 	get_conftoken(CONF_IDENT);
2858 	ivcur.name = stralloc(tokenval.v.s);
2859     }
2860     current_block = g_strconcat("interactivity ", ivcur.name, NULL);
2861     ivcur.seen.block = current_block;
2862     ivcur.seen.filename = current_filename;
2863     ivcur.seen.linenum = current_line_num;
2864 
2865     read_block(interactivity_var, ivcur.value,
2866 	       _("interactivity parameter expected"),
2867 	       (name == NULL), *copy_interactivity,
2868 	       "INTERACTIVITY", ivcur.name);
2869     if(!name)
2870 	get_conftoken(CONF_NL);
2871 
2872     save_interactivity();
2873 
2874     allow_overwrites = save_overwrites;
2875 
2876     current_block = saved_block;
2877     if (linenum)
2878 	*linenum = current_line_num;
2879 
2880     if (fname)
2881 	current_filename = saved_fname;
2882 
2883     if (from)
2884 	current_file = saved_conf;
2885 
2886     return lookup_interactivity(ivcur.name);
2887 }
2888 
2889 static void
get_interactivity(void)2890 get_interactivity(
2891     void)
2892 {
2893     read_interactivity(NULL, NULL, NULL, NULL);
2894 }
2895 
2896 static void
init_interactivity_defaults(void)2897 init_interactivity_defaults(
2898     void)
2899 {
2900     ivcur.name = NULL;
2901     conf_init_str(&ivcur.value[INTERACTIVITY_COMMENT] , "");
2902     conf_init_str(&ivcur.value[INTERACTIVITY_PLUGIN]  , "");
2903     conf_init_proplist(&ivcur.value[INTERACTIVITY_PROPERTY]);
2904 }
2905 
2906 static void
save_interactivity(void)2907 save_interactivity(
2908     void)
2909 {
2910     interactivity_t *iv, *iv1;
2911 
2912     iv = lookup_interactivity(ivcur.name);
2913 
2914     if (iv != (interactivity_t *)0) {
2915 	conf_parserror(_("interactivity %s already defined at %s:%d"),
2916 		       iv->name, iv->seen.filename, iv->seen.linenum);
2917 	return;
2918     }
2919 
2920     iv = alloc(sizeof(interactivity_t));
2921     *iv = ivcur;
2922     iv->next = NULL;
2923     /* add at end of list */
2924     if (!interactivity_list)
2925 	interactivity_list = iv;
2926     else {
2927 	iv1 = interactivity_list;
2928 	while (iv1->next != NULL) {
2929 	    iv1 = iv1->next;
2930 	}
2931 	iv1->next = iv;
2932     }
2933 }
2934 
2935 static void
copy_interactivity(void)2936 copy_interactivity(void)
2937 {
2938     interactivity_t *iv;
2939     int i;
2940 
2941     iv = lookup_interactivity(tokenval.v.s);
2942 
2943     if (iv == NULL) {
2944 	conf_parserror(_("interactivity parameter expected"));
2945 	return;
2946     }
2947 
2948     for (i=0; i < INTERACTIVITY_INTERACTIVITY; i++) {
2949 	if(iv->value[i].seen.linenum) {
2950 	    merge_val_t(&ivcur.value[i], &iv->value[i]);
2951 	}
2952     }
2953 }
2954 
2955 static taperscan_t *
read_taperscan(char * name,FILE * from,char * fname,int * linenum)2956 read_taperscan(
2957     char *name,
2958     FILE *from,
2959     char *fname,
2960     int *linenum)
2961 {
2962     int save_overwrites;
2963     FILE *saved_conf = NULL;
2964     char *saved_fname = NULL;
2965     char *saved_block;
2966 
2967     if (from) {
2968 	saved_conf = current_file;
2969 	current_file = from;
2970     }
2971 
2972     if (fname) {
2973 	saved_fname = current_filename;
2974 	current_filename = get_seen_filename(fname);
2975     }
2976 
2977     if (linenum)
2978 	current_line_num = *linenum;
2979 
2980     saved_block = current_block;
2981     save_overwrites = allow_overwrites;
2982     allow_overwrites = 1;
2983 
2984     init_taperscan_defaults();
2985     if (name) {
2986 	tscur.name = name;
2987     } else {
2988 	get_conftoken(CONF_IDENT);
2989 	tscur.name = stralloc(tokenval.v.s);
2990     }
2991     current_block = g_strconcat("taperscan ", tscur.name, NULL);
2992     tscur.seen.block = current_block;
2993     tscur.seen.filename = current_filename;
2994     tscur.seen.linenum = current_line_num;
2995 
2996     read_block(taperscan_var, tscur.value,
2997 	       _("taperscan parameter expected"),
2998 	       (name == NULL), *copy_taperscan,
2999 	       "TAPERSCAN", tscur.name);
3000     if(!name)
3001 	get_conftoken(CONF_NL);
3002 
3003     save_taperscan();
3004 
3005     allow_overwrites = save_overwrites;
3006 
3007     current_block = saved_block;
3008     if (linenum)
3009 	*linenum = current_line_num;
3010 
3011     if (fname)
3012 	current_filename = saved_fname;
3013 
3014     if (from)
3015 	current_file = saved_conf;
3016 
3017     return lookup_taperscan(tscur.name);
3018 }
3019 
3020 static void
get_taperscan(void)3021 get_taperscan(
3022     void)
3023 {
3024     read_taperscan(NULL, NULL, NULL, NULL);
3025 }
3026 
3027 static void
init_taperscan_defaults(void)3028 init_taperscan_defaults(
3029     void)
3030 {
3031     tscur.name = NULL;
3032     conf_init_str(&tscur.value[TAPERSCAN_COMMENT] , "");
3033     conf_init_str(&tscur.value[TAPERSCAN_PLUGIN]  , "");
3034     conf_init_proplist(&tscur.value[TAPERSCAN_PROPERTY]);
3035 }
3036 
3037 static void
save_taperscan(void)3038 save_taperscan(
3039     void)
3040 {
3041     taperscan_t *ts, *ts1;
3042 
3043     ts = lookup_taperscan(tscur.name);
3044 
3045     if (ts != (taperscan_t *)0) {
3046 	conf_parserror(_("taperscan %s already defined at %s:%d"),
3047 		       ts->name, ts->seen.filename, ts->seen.linenum);
3048 	return;
3049     }
3050 
3051     ts = alloc(sizeof(taperscan_t));
3052     *ts = tscur;
3053     ts->next = NULL;
3054     /* add at end of list */
3055     if (!taperscan_list)
3056 	taperscan_list = ts;
3057     else {
3058 	ts1 = taperscan_list;
3059 	while (ts1->next != NULL) {
3060 	    ts1 = ts1->next;
3061 	}
3062 	ts1->next = ts;
3063     }
3064 }
3065 
3066 static void
copy_taperscan(void)3067 copy_taperscan(void)
3068 {
3069     taperscan_t *ts;
3070     int i;
3071 
3072     ts = lookup_taperscan(tokenval.v.s);
3073 
3074     if (ts == NULL) {
3075 	conf_parserror(_("taperscan parameter expected"));
3076 	return;
3077     }
3078 
3079     for (i=0; i < TAPERSCAN_TAPERSCAN; i++) {
3080 	if(ts->value[i].seen.linenum) {
3081 	    merge_val_t(&tscur.value[i], &ts->value[i]);
3082 	}
3083     }
3084 }
3085 
3086 static pp_script_t *
read_pp_script(char * name,FILE * from,char * fname,int * linenum)3087 read_pp_script(
3088     char *name,
3089     FILE *from,
3090     char *fname,
3091     int *linenum)
3092 {
3093     int save_overwrites;
3094     FILE *saved_conf = NULL;
3095     char *saved_fname = NULL;
3096     char *saved_block;
3097 
3098     if (from) {
3099 	saved_conf = current_file;
3100 	current_file = from;
3101     }
3102 
3103     if (fname) {
3104 	saved_fname = current_filename;
3105 	current_filename = get_seen_filename(fname);
3106     }
3107 
3108     if (linenum)
3109 	current_line_num = *linenum;
3110 
3111     saved_block = current_block;
3112     save_overwrites = allow_overwrites;
3113     allow_overwrites = 1;
3114 
3115     init_pp_script_defaults();
3116     if (name) {
3117 	pscur.name = name;
3118     } else {
3119 	get_conftoken(CONF_IDENT);
3120 	pscur.name = stralloc(tokenval.v.s);
3121     }
3122     current_block = g_strconcat("script ", pscur.name, NULL);
3123     pscur.seen.block = current_block;
3124     pscur.seen.filename = current_filename;
3125     pscur.seen.linenum = current_line_num;
3126 
3127     read_block(pp_script_var, pscur.value,
3128 	       _("script parameter expected"),
3129 	       (name == NULL), *copy_pp_script,
3130 	       "SCRIPT", pscur.name);
3131     if(!name)
3132 	get_conftoken(CONF_NL);
3133 
3134     save_pp_script();
3135 
3136     allow_overwrites = save_overwrites;
3137 
3138     current_block = saved_block;
3139     if (linenum)
3140 	*linenum = current_line_num;
3141 
3142     if (fname)
3143 	current_filename = saved_fname;
3144 
3145     if (from)
3146 	current_file = saved_conf;
3147 
3148     return lookup_pp_script(pscur.name);
3149 }
3150 
3151 static void
get_pp_script(void)3152 get_pp_script(
3153     void)
3154 {
3155     read_pp_script(NULL, NULL, NULL, NULL);
3156 }
3157 
3158 static void
init_pp_script_defaults(void)3159 init_pp_script_defaults(
3160     void)
3161 {
3162     pscur.name = NULL;
3163     conf_init_str(&pscur.value[PP_SCRIPT_COMMENT] , "");
3164     conf_init_str(&pscur.value[PP_SCRIPT_PLUGIN]  , "");
3165     conf_init_proplist(&pscur.value[PP_SCRIPT_PROPERTY]);
3166     conf_init_execute_on(&pscur.value[PP_SCRIPT_EXECUTE_ON], 0);
3167     conf_init_execute_where(&pscur.value[PP_SCRIPT_EXECUTE_WHERE], ES_CLIENT);
3168     conf_init_int(&pscur.value[PP_SCRIPT_ORDER], CONF_UNIT_NONE, 5000);
3169     conf_init_bool(&pscur.value[PP_SCRIPT_SINGLE_EXECUTION], 0);
3170     conf_init_str(&pscur.value[PP_SCRIPT_CLIENT_NAME], "");
3171 }
3172 
3173 static void
save_pp_script(void)3174 save_pp_script(
3175     void)
3176 {
3177     pp_script_t *ps, *ps1;
3178 
3179     ps = lookup_pp_script(pscur.name);
3180 
3181     if(ps != (pp_script_t *)0) {
3182 	conf_parserror(_("script %s already defined at %s:%d"),
3183 		       ps->name, ps->seen.filename, ps->seen.linenum);
3184 	return;
3185     }
3186 
3187     ps = alloc(sizeof(pp_script_t));
3188     *ps = pscur;
3189     ps->next = NULL;
3190     /* add at end of list */
3191     if (!pp_script_list)
3192 	pp_script_list = ps;
3193     else {
3194 	ps1 = pp_script_list;
3195 	while (ps1->next != NULL) {
3196 	    ps1 = ps1->next;
3197 	}
3198 	ps1->next = ps;
3199     }
3200 }
3201 
3202 static void
copy_pp_script(void)3203 copy_pp_script(void)
3204 {
3205     pp_script_t *ps;
3206     int i;
3207 
3208     ps = lookup_pp_script(tokenval.v.s);
3209 
3210     if(ps == NULL) {
3211 	conf_parserror(_("script parameter expected"));
3212 	return;
3213     }
3214 
3215     for(i=0; i < PP_SCRIPT_PP_SCRIPT; i++) {
3216 	if(ps->value[i].seen.linenum) {
3217 	    merge_val_t(&pscur.value[i], &ps->value[i]);
3218 	}
3219     }
3220 }
3221 
3222 static device_config_t *
read_device_config(char * name,FILE * from,char * fname,int * linenum)3223 read_device_config(
3224     char *name,
3225     FILE *from,
3226     char *fname,
3227     int *linenum)
3228 {
3229     int save_overwrites;
3230     FILE *saved_conf = NULL;
3231     char *saved_fname = NULL;
3232     char *saved_block;
3233 
3234     if (from) {
3235 	saved_conf = current_file;
3236 	current_file = from;
3237     }
3238 
3239     if (fname) {
3240 	saved_fname = current_filename;
3241 	current_filename = get_seen_filename(fname);
3242     }
3243 
3244     if (linenum)
3245 	current_line_num = *linenum;
3246 
3247     saved_block = current_block;
3248     save_overwrites = allow_overwrites;
3249     allow_overwrites = 1;
3250 
3251     init_device_config_defaults();
3252     if (name) {
3253 	dccur.name = name;
3254     } else {
3255 	get_conftoken(CONF_IDENT);
3256 	dccur.name = stralloc(tokenval.v.s);
3257     }
3258     current_block = g_strconcat("device ", dccur.name, NULL);
3259     dccur.seen.block = current_block;
3260     dccur.seen.filename = current_filename;
3261     dccur.seen.linenum = current_line_num;
3262 
3263     read_block(device_config_var, dccur.value,
3264 	       _("device parameter expected"),
3265 	       (name == NULL), *copy_device_config,
3266 	       "DEVICE", dccur.name);
3267     if(!name)
3268 	get_conftoken(CONF_NL);
3269 
3270     save_device_config();
3271 
3272     allow_overwrites = save_overwrites;
3273 
3274     current_block = saved_block;
3275     if (linenum)
3276 	*linenum = current_line_num;
3277 
3278     if (fname)
3279 	current_filename = saved_fname;
3280 
3281     if (from)
3282 	current_file = saved_conf;
3283 
3284     return lookup_device_config(dccur.name);
3285 }
3286 
3287 static void
get_device_config(void)3288 get_device_config(
3289     void)
3290 {
3291     read_device_config(NULL, NULL, NULL, NULL);
3292 }
3293 
3294 static void
init_device_config_defaults(void)3295 init_device_config_defaults(
3296     void)
3297 {
3298     dccur.name = NULL;
3299     conf_init_str(&dccur.value[DEVICE_CONFIG_COMMENT] , "");
3300     conf_init_str(&dccur.value[DEVICE_CONFIG_TAPEDEV]  , "");
3301     conf_init_proplist(&dccur.value[DEVICE_CONFIG_DEVICE_PROPERTY]);
3302 }
3303 
3304 static void
save_device_config(void)3305 save_device_config(
3306     void)
3307 {
3308     device_config_t *dc, *dc1;
3309 
3310     dc = lookup_device_config(dccur.name);
3311 
3312     if(dc != (device_config_t *)0) {
3313 	conf_parserror(_("device %s already defined at %s:%d"),
3314 		       dc->name, dc->seen.filename, dc->seen.linenum);
3315 	return;
3316     }
3317 
3318     dc = alloc(sizeof(device_config_t));
3319     *dc = dccur;
3320     dc->next = NULL;
3321     /* add at end of list */
3322     if (!device_config_list)
3323 	device_config_list = dc;
3324     else {
3325 	dc1 = device_config_list;
3326 	while (dc1->next != NULL) {
3327 	    dc1 = dc1->next;
3328 	}
3329 	dc1->next = dc;
3330     }
3331 }
3332 
3333 static void
copy_device_config(void)3334 copy_device_config(void)
3335 {
3336     device_config_t *dc;
3337     int i;
3338 
3339     dc = lookup_device_config(tokenval.v.s);
3340 
3341     if(dc == NULL) {
3342 	conf_parserror(_("device parameter expected"));
3343 	return;
3344     }
3345 
3346     for(i=0; i < DEVICE_CONFIG_DEVICE_CONFIG; i++) {
3347 	if(dc->value[i].seen.linenum) {
3348 	    merge_val_t(&dccur.value[i], &dc->value[i]);
3349 	}
3350     }
3351 }
3352 
3353 static changer_config_t *
read_changer_config(char * name,FILE * from,char * fname,int * linenum)3354 read_changer_config(
3355     char *name,
3356     FILE *from,
3357     char *fname,
3358     int *linenum)
3359 {
3360     int save_overwrites;
3361     FILE *saved_conf = NULL;
3362     char *saved_fname = NULL;
3363     char *saved_block;
3364 
3365     if (from) {
3366 	saved_conf = current_file;
3367 	current_file = from;
3368     }
3369 
3370     if (fname) {
3371 	saved_fname = current_filename;
3372 	current_filename = fname;
3373     }
3374 
3375     if (linenum)
3376 	current_line_num = *linenum;
3377 
3378     saved_block = current_block;
3379     save_overwrites = allow_overwrites;
3380     allow_overwrites = 1;
3381 
3382     init_changer_config_defaults();
3383     if (name) {
3384 	cccur.name = name;
3385     } else {
3386 	get_conftoken(CONF_IDENT);
3387 	cccur.name = stralloc(tokenval.v.s);
3388     }
3389     current_block = g_strconcat("changer ", cccur.name, NULL);
3390     cccur.seen.block = current_block;
3391     cccur.seen.filename = current_filename;
3392     cccur.seen.linenum = current_line_num;
3393 
3394     read_block(changer_config_var, cccur.value,
3395 	       _("changer parameter expected"),
3396 	       (name == NULL), *copy_changer_config,
3397 	       "CHANGER", cccur.name);
3398     if(!name)
3399 	get_conftoken(CONF_NL);
3400 
3401     save_changer_config();
3402 
3403     allow_overwrites = save_overwrites;
3404 
3405     current_block = saved_block;
3406     if (linenum)
3407 	*linenum = current_line_num;
3408 
3409     if (fname)
3410 	current_filename = saved_fname;
3411 
3412     if (from)
3413 	current_file = saved_conf;
3414 
3415     return lookup_changer_config(cccur.name);
3416 }
3417 
3418 static void
get_changer_config(void)3419 get_changer_config(
3420     void)
3421 {
3422     read_changer_config(NULL, NULL, NULL, NULL);
3423 }
3424 
3425 static void
init_changer_config_defaults(void)3426 init_changer_config_defaults(
3427     void)
3428 {
3429     cccur.name = NULL;
3430     conf_init_str(&cccur.value[CHANGER_CONFIG_COMMENT] , "");
3431     conf_init_str(&cccur.value[CHANGER_CONFIG_TAPEDEV]  , "");
3432     conf_init_str(&cccur.value[CHANGER_CONFIG_TPCHANGER]  , "");
3433     conf_init_str(&cccur.value[CHANGER_CONFIG_CHANGERDEV]  , "");
3434     conf_init_str(&cccur.value[CHANGER_CONFIG_CHANGERFILE]  , "");
3435     conf_init_proplist(&cccur.value[CHANGER_CONFIG_PROPERTY]);
3436     conf_init_proplist(&cccur.value[CHANGER_CONFIG_DEVICE_PROPERTY]);
3437 }
3438 
3439 static void
save_changer_config(void)3440 save_changer_config(
3441     void)
3442 {
3443     changer_config_t *dc, *dc1;
3444 
3445     dc = lookup_changer_config(cccur.name);
3446 
3447     if(dc != (changer_config_t *)0) {
3448 	conf_parserror(_("changer %s already defined at %s:%d"),
3449 		       dc->name, dc->seen.filename, dc->seen.linenum);
3450 	return;
3451     }
3452 
3453     dc = alloc(sizeof(changer_config_t));
3454     *dc = cccur;
3455     dc->next = NULL;
3456     /* add at end of list */
3457     if (!changer_config_list)
3458 	changer_config_list = dc;
3459     else {
3460 	dc1 = changer_config_list;
3461 	while (dc1->next != NULL) {
3462 	    dc1 = dc1->next;
3463 	}
3464 	dc1->next = dc;
3465     }
3466 }
3467 
3468 static void
copy_changer_config(void)3469 copy_changer_config(void)
3470 {
3471     changer_config_t *dc;
3472     int i;
3473 
3474     dc = lookup_changer_config(tokenval.v.s);
3475 
3476     if(dc == NULL) {
3477 	conf_parserror(_("changer parameter expected"));
3478 	return;
3479     }
3480 
3481     for(i=0; i < CHANGER_CONFIG_CHANGER_CONFIG; i++) {
3482 	if(dc->value[i].seen.linenum) {
3483 	    merge_val_t(&cccur.value[i], &dc->value[i]);
3484 	}
3485     }
3486 }
3487 
3488 /* Read functions */
3489 
3490 static void
read_int(conf_var_t * np G_GNUC_UNUSED,val_t * val)3491 read_int(
3492     conf_var_t *np G_GNUC_UNUSED,
3493     val_t *val)
3494 {
3495     ckseen(&val->seen);
3496     val_t__int(val) = get_int(val->unit);
3497 }
3498 
3499 static void
read_int64(conf_var_t * np G_GNUC_UNUSED,val_t * val)3500 read_int64(
3501     conf_var_t *np G_GNUC_UNUSED,
3502     val_t *val)
3503 {
3504     ckseen(&val->seen);
3505     val_t__int64(val) = get_int64(val->unit);
3506 }
3507 
3508 static void
read_real(conf_var_t * np G_GNUC_UNUSED,val_t * val)3509 read_real(
3510     conf_var_t *np G_GNUC_UNUSED,
3511     val_t *val)
3512 {
3513     ckseen(&val->seen);
3514     get_conftoken(CONF_REAL);
3515     val_t__real(val) = tokenval.v.r;
3516 }
3517 
3518 static void
read_str(conf_var_t * np G_GNUC_UNUSED,val_t * val)3519 read_str(
3520     conf_var_t *np G_GNUC_UNUSED,
3521     val_t *val)
3522 {
3523     ckseen(&val->seen);
3524     get_conftoken(CONF_STRING);
3525     val->v.s = newstralloc(val->v.s, tokenval.v.s);
3526 }
3527 
3528 static void
read_str_list(conf_var_t * np G_GNUC_UNUSED,val_t * val)3529 read_str_list(
3530     conf_var_t *np G_GNUC_UNUSED,
3531     val_t *val)
3532 {
3533     ckseen(&val->seen);
3534 
3535     get_conftoken(CONF_ANY);
3536     while (tok == CONF_STRING) {
3537 	val->v.identlist = g_slist_append(val->v.identlist,
3538 					  g_strdup(tokenval.v.s));
3539 	get_conftoken(CONF_ANY);
3540     }
3541     if (tok != CONF_NL && tok != CONF_END) {
3542 	conf_parserror(_("string expected"));
3543 	unget_conftoken();
3544     }
3545 }
3546 
3547 static void
read_ident(conf_var_t * np G_GNUC_UNUSED,val_t * val)3548 read_ident(
3549     conf_var_t *np G_GNUC_UNUSED,
3550     val_t *val)
3551 {
3552     ckseen(&val->seen);
3553     get_conftoken(CONF_IDENT);
3554     val->v.s = newstralloc(val->v.s, tokenval.v.s);
3555 }
3556 
3557 static void
read_time(conf_var_t * np G_GNUC_UNUSED,val_t * val)3558 read_time(
3559     conf_var_t *np G_GNUC_UNUSED,
3560     val_t *val)
3561 {
3562     ckseen(&val->seen);
3563     val_t__time(val) = get_time();
3564 }
3565 
3566 static void
read_size(conf_var_t * np G_GNUC_UNUSED,val_t * val)3567 read_size(
3568     conf_var_t *np G_GNUC_UNUSED,
3569     val_t *val)
3570 {
3571     ckseen(&val->seen);
3572     val_t__size(val) = get_size(val->unit);
3573 }
3574 
3575 static void
read_bool(conf_var_t * np G_GNUC_UNUSED,val_t * val)3576 read_bool(
3577     conf_var_t *np G_GNUC_UNUSED,
3578     val_t *val)
3579 {
3580     ckseen(&val->seen);
3581     val_t__boolean(val) = get_bool();
3582 }
3583 
3584 static void
read_no_yes_all(conf_var_t * np G_GNUC_UNUSED,val_t * val)3585 read_no_yes_all(
3586     conf_var_t *np G_GNUC_UNUSED,
3587     val_t *val)
3588 {
3589     ckseen(&val->seen);
3590     val_t__int(val) = get_no_yes_all();
3591 }
3592 
3593 static void
read_compress(conf_var_t * np G_GNUC_UNUSED,val_t * val)3594 read_compress(
3595     conf_var_t *np G_GNUC_UNUSED,
3596     val_t *val)
3597 {
3598     int serv, clie, none, fast, best, custom;
3599     int done;
3600     comp_t comp;
3601 
3602     ckseen(&val->seen);
3603 
3604     serv = clie = none = fast = best = custom  = 0;
3605 
3606     done = 0;
3607     do {
3608 	get_conftoken(CONF_ANY);
3609 	switch(tok) {
3610 	case CONF_NONE:   none = 1; break;
3611 	case CONF_FAST:   fast = 1; break;
3612 	case CONF_BEST:   best = 1; break;
3613 	case CONF_CLIENT: clie = 1; break;
3614 	case CONF_SERVER: serv = 1; break;
3615 	case CONF_CUSTOM: custom=1; break;
3616 	case CONF_NL:     done = 1; break;
3617 	case CONF_END:    done = 1; break;
3618 	default:
3619 	    done = 1;
3620 	    serv = clie = 1; /* force an error */
3621 	}
3622     } while(!done);
3623 
3624     if(serv + clie == 0) clie = 1;	/* default to client */
3625     if(none + fast + best + custom  == 0) fast = 1; /* default to fast */
3626 
3627     comp = -1;
3628 
3629     if(!serv && clie) {
3630 	if(none && !fast && !best && !custom) comp = COMP_NONE;
3631 	if(!none && fast && !best && !custom) comp = COMP_FAST;
3632 	if(!none && !fast && best && !custom) comp = COMP_BEST;
3633 	if(!none && !fast && !best && custom) comp = COMP_CUST;
3634     }
3635 
3636     if(serv && !clie) {
3637 	if(none && !fast && !best && !custom) comp = COMP_NONE;
3638 	if(!none && fast && !best && !custom) comp = COMP_SERVER_FAST;
3639 	if(!none && !fast && best && !custom) comp = COMP_SERVER_BEST;
3640 	if(!none && !fast && !best && custom) comp = COMP_SERVER_CUST;
3641     }
3642 
3643     if((int)comp == -1) {
3644 	conf_parserror(_("NONE, CLIENT FAST, CLIENT BEST, CLIENT CUSTOM, SERVER FAST, SERVER BEST or SERVER CUSTOM expected"));
3645 	comp = COMP_NONE;
3646     }
3647 
3648     val_t__compress(val) = (int)comp;
3649 }
3650 
3651 static void
read_encrypt(conf_var_t * np G_GNUC_UNUSED,val_t * val)3652 read_encrypt(
3653     conf_var_t *np G_GNUC_UNUSED,
3654     val_t *val)
3655 {
3656    encrypt_t encrypt;
3657 
3658    ckseen(&val->seen);
3659 
3660    get_conftoken(CONF_ANY);
3661    switch(tok) {
3662    case CONF_NONE:
3663      encrypt = ENCRYPT_NONE;
3664      break;
3665 
3666    case CONF_CLIENT:
3667      encrypt = ENCRYPT_CUST;
3668      break;
3669 
3670    case CONF_SERVER:
3671      encrypt = ENCRYPT_SERV_CUST;
3672      break;
3673 
3674    default:
3675      conf_parserror(_("NONE, CLIENT or SERVER expected"));
3676      encrypt = ENCRYPT_NONE;
3677      break;
3678    }
3679 
3680    val_t__encrypt(val) = (int)encrypt;
3681 }
3682 
3683 static void
read_holding(conf_var_t * np G_GNUC_UNUSED,val_t * val)3684 read_holding(
3685     conf_var_t *np G_GNUC_UNUSED,
3686     val_t *val)
3687 {
3688    dump_holdingdisk_t holding;
3689 
3690    ckseen(&val->seen);
3691 
3692    get_conftoken(CONF_ANY);
3693    switch(tok) {
3694    case CONF_NEVER:
3695      holding = HOLD_NEVER;
3696      break;
3697 
3698    case CONF_AUTO:
3699      holding = HOLD_AUTO;
3700      break;
3701 
3702    case CONF_REQUIRED:
3703      holding = HOLD_REQUIRED;
3704      break;
3705 
3706    default: /* can be a BOOLEAN */
3707      unget_conftoken();
3708      holding =  (dump_holdingdisk_t)get_bool();
3709      if (holding == 0)
3710 	holding = HOLD_NEVER;
3711      else if (holding == 1 || holding == 2)
3712 	holding = HOLD_AUTO;
3713      else
3714 	conf_parserror(_("NEVER, AUTO or REQUIRED expected"));
3715      break;
3716    }
3717 
3718    val_t__holding(val) = (int)holding;
3719 }
3720 
3721 static void
read_estimatelist(conf_var_t * np G_GNUC_UNUSED,val_t * val)3722 read_estimatelist(
3723     conf_var_t *np G_GNUC_UNUSED,
3724     val_t *val)
3725 {
3726     estimatelist_t estimates = NULL;
3727 
3728     ckseen(&val->seen);
3729 
3730     get_conftoken(CONF_ANY);
3731     do {
3732 	switch(tok) {
3733 	case CONF_CLIENT:
3734 	    estimates = g_slist_append(estimates, GINT_TO_POINTER(ES_CLIENT));
3735 	    break;
3736 	case CONF_SERVER:
3737 	    estimates = g_slist_append(estimates, GINT_TO_POINTER(ES_SERVER));
3738 	    break;
3739 	case CONF_CALCSIZE:
3740 	    estimates = g_slist_append(estimates, GINT_TO_POINTER(ES_CALCSIZE));
3741 	    break;
3742 	default:
3743 	    conf_parserror(_("CLIENT, SERVER or CALCSIZE expected"));
3744 	}
3745 	get_conftoken(CONF_ANY);
3746 	if (tok == CONF_NL)
3747 	    break;
3748     } while (1);
3749     val_t__estimatelist(val) = estimates;
3750 }
3751 
3752 static void
read_strategy(conf_var_t * np G_GNUC_UNUSED,val_t * val)3753 read_strategy(
3754     conf_var_t *np G_GNUC_UNUSED,
3755     val_t *val)
3756 {
3757     int strat;
3758 
3759     ckseen(&val->seen);
3760 
3761     get_conftoken(CONF_ANY);
3762     switch(tok) {
3763     case CONF_SKIP:
3764 	strat = DS_SKIP;
3765 	break;
3766     case CONF_STANDARD:
3767 	strat = DS_STANDARD;
3768 	break;
3769     case CONF_NOFULL:
3770 	strat = DS_NOFULL;
3771 	break;
3772     case CONF_NOINC:
3773 	strat = DS_NOINC;
3774 	break;
3775     case CONF_HANOI:
3776 	strat = DS_HANOI;
3777 	break;
3778     case CONF_INCRONLY:
3779 	strat = DS_INCRONLY;
3780 	break;
3781     default:
3782 	conf_parserror(_("dump strategy expected"));
3783 	strat = DS_STANDARD;
3784     }
3785     val_t__strategy(val) = strat;
3786 }
3787 
3788 static void
read_taperalgo(conf_var_t * np G_GNUC_UNUSED,val_t * val)3789 read_taperalgo(
3790     conf_var_t *np G_GNUC_UNUSED,
3791     val_t *val)
3792 {
3793     ckseen(&val->seen);
3794 
3795     get_conftoken(CONF_ANY);
3796     switch(tok) {
3797     case CONF_FIRST:      val_t__taperalgo(val) = ALGO_FIRST;      break;
3798     case CONF_FIRSTFIT:   val_t__taperalgo(val) = ALGO_FIRSTFIT;   break;
3799     case CONF_LARGEST:    val_t__taperalgo(val) = ALGO_LARGEST;    break;
3800     case CONF_LARGESTFIT: val_t__taperalgo(val) = ALGO_LARGESTFIT; break;
3801     case CONF_SMALLEST:   val_t__taperalgo(val) = ALGO_SMALLEST;   break;
3802     case CONF_LAST:       val_t__taperalgo(val) = ALGO_LAST;       break;
3803     default:
3804 	conf_parserror(_("FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST or LAST expected"));
3805     }
3806 }
3807 
3808 static void
read_send_amreport_on(conf_var_t * np G_GNUC_UNUSED,val_t * val)3809 read_send_amreport_on(
3810     conf_var_t *np G_GNUC_UNUSED,
3811     val_t *val)
3812 {
3813     ckseen(&val->seen);
3814 
3815     get_conftoken(CONF_ANY);
3816     switch(tok) {
3817     case CONF_ALL:     val_t__send_amreport(val) = SEND_AMREPORT_ALL;     break;
3818     case CONF_STRANGE: val_t__send_amreport(val) = SEND_AMREPORT_STRANGE; break;
3819     case CONF_ERROR:   val_t__send_amreport(val) = SEND_AMREPORT_ERROR;   break;
3820     case CONF_NEVER:   val_t__send_amreport(val) = SEND_AMREPORT_NEVER;   break;
3821     default:
3822 	conf_parserror(_("ALL, STRANGE, ERROR or NEVER expected"));
3823     }
3824 }
3825 
3826 static void
read_data_path(conf_var_t * np G_GNUC_UNUSED,val_t * val)3827 read_data_path(
3828     conf_var_t *np G_GNUC_UNUSED,
3829     val_t *val)
3830 {
3831     ckseen(&val->seen);
3832 
3833     get_conftoken(CONF_ANY);
3834     switch(tok) {
3835     case CONF_AMANDA   : val_t__data_path(val) = DATA_PATH_AMANDA   ; break;
3836     case CONF_DIRECTTCP: val_t__data_path(val) = DATA_PATH_DIRECTTCP; break;
3837     default:
3838 	conf_parserror(_("AMANDA or DIRECTTCP expected"));
3839     }
3840 }
3841 
3842 static void
read_priority(conf_var_t * np G_GNUC_UNUSED,val_t * val)3843 read_priority(
3844     conf_var_t *np G_GNUC_UNUSED,
3845     val_t *val)
3846 {
3847     int pri;
3848 
3849     ckseen(&val->seen);
3850 
3851     get_conftoken(CONF_ANY);
3852     switch(tok) {
3853     case CONF_LOW: pri = 0; break;
3854     case CONF_MEDIUM: pri = 1; break;
3855     case CONF_HIGH: pri = 2; break;
3856     case CONF_INT: pri = tokenval.v.i; break;
3857     default:
3858 	conf_parserror(_("LOW, MEDIUM, HIGH or integer expected"));
3859 	pri = 0;
3860     }
3861     val_t__priority(val) = pri;
3862 }
3863 
3864 static void
read_rate(conf_var_t * np G_GNUC_UNUSED,val_t * val)3865 read_rate(
3866     conf_var_t *np G_GNUC_UNUSED,
3867     val_t *val)
3868 {
3869     get_conftoken(CONF_REAL);
3870     val_t__rate(val)[0] = tokenval.v.r;
3871     val_t__rate(val)[1] = tokenval.v.r;
3872     val->seen = tokenval.seen;
3873     if(tokenval.v.r < 0) {
3874 	conf_parserror(_("full compression rate must be >= 0"));
3875     }
3876 
3877     get_conftoken(CONF_ANY);
3878     switch(tok) {
3879     case CONF_NL:
3880 	return;
3881 
3882     case CONF_END:
3883 	return;
3884 
3885     case CONF_COMMA:
3886 	break;
3887 
3888     default:
3889 	unget_conftoken();
3890     }
3891 
3892     get_conftoken(CONF_REAL);
3893     val_t__rate(val)[1] = tokenval.v.r;
3894     if(tokenval.v.r < 0) {
3895 	conf_parserror(_("incremental compression rate must be >= 0"));
3896     }
3897 }
3898 
3899 static void
read_exinclude(conf_var_t * np G_GNUC_UNUSED,val_t * val)3900 read_exinclude(
3901     conf_var_t *np G_GNUC_UNUSED,
3902     val_t *val)
3903 {
3904     int file, got_one = 0;
3905     am_sl_t *exclude;
3906     int optional = 0;
3907 
3908     get_conftoken(CONF_ANY);
3909     if(tok == CONF_LIST) {
3910 	file = 0;
3911 	get_conftoken(CONF_ANY);
3912 	exclude = val_t__exinclude(val).sl_list;
3913     }
3914     else {
3915 	file = 1;
3916 	if(tok == CONF_EFILE) get_conftoken(CONF_ANY);
3917 	exclude = val_t__exinclude(val).sl_file;
3918     }
3919     ckseen(&val->seen);
3920 
3921     if(tok == CONF_OPTIONAL) {
3922 	get_conftoken(CONF_ANY);
3923 	optional = 1;
3924     }
3925 
3926     if(tok == CONF_APPEND) {
3927 	get_conftoken(CONF_ANY);
3928     }
3929     else {
3930 	free_sl(exclude);
3931 	exclude = NULL;
3932     }
3933 
3934     while(tok == CONF_STRING) {
3935 	exclude = append_sl(exclude, tokenval.v.s);
3936 	got_one = 1;
3937 	get_conftoken(CONF_ANY);
3938     }
3939     unget_conftoken();
3940 
3941     if(got_one == 0) { free_sl(exclude); exclude = NULL; }
3942 
3943     if (file == 0)
3944 	val_t__exinclude(val).sl_list = exclude;
3945     else
3946 	val_t__exinclude(val).sl_file = exclude;
3947     val_t__exinclude(val).optional = optional;
3948 }
3949 
3950 static void
read_intrange(conf_var_t * np G_GNUC_UNUSED,val_t * val)3951 read_intrange(
3952     conf_var_t *np G_GNUC_UNUSED,
3953     val_t *val)
3954 {
3955     get_conftoken(CONF_INT);
3956     val_t__intrange(val)[0] = tokenval.v.i;
3957     val_t__intrange(val)[1] = tokenval.v.i;
3958     val->seen = tokenval.seen;
3959 
3960     get_conftoken(CONF_ANY);
3961     switch(tok) {
3962     case CONF_NL:
3963 	return;
3964 
3965     case CONF_END:
3966 	return;
3967 
3968     case CONF_COMMA:
3969 	break;
3970 
3971     default:
3972 	unget_conftoken();
3973     }
3974 
3975     get_conftoken(CONF_INT);
3976     val_t__intrange(val)[1] = tokenval.v.i;
3977 }
3978 
3979 static void
read_property(conf_var_t * np G_GNUC_UNUSED,val_t * val)3980 read_property(
3981     conf_var_t *np G_GNUC_UNUSED,
3982     val_t      *val)
3983 {
3984     char *key;
3985     gboolean set_seen = TRUE;
3986     property_t *property = malloc(sizeof(property_t));
3987     property_t *old_property;
3988     property->append = 0;
3989     property->priority = 0;
3990     property->values = NULL;
3991 
3992     get_conftoken(CONF_ANY);
3993     if (tok == CONF_PRIORITY) {
3994 	property->priority = 1;
3995 	get_conftoken(CONF_ANY);
3996     }
3997     if (tok == CONF_APPEND) {
3998 	property->append = 1;
3999 	get_conftoken(CONF_ANY);
4000     }
4001     if (tok != CONF_STRING) {
4002 	conf_parserror(_("key expected"));
4003 	return;
4004     }
4005     key = amandaify_property_name(tokenval.v.s);
4006 
4007     get_conftoken(CONF_ANY);
4008     if (tok == CONF_NL ||  tok == CONF_END) {
4009 	g_hash_table_remove(val->v.proplist, key);
4010 	unget_conftoken();
4011 	return;
4012     }
4013     if (tok != CONF_STRING) {
4014 	conf_parserror(_("value expected"));
4015 	return;
4016     }
4017 
4018     if(val->seen.linenum == 0) {
4019 	ckseen(&val->seen); // first property
4020     }
4021 
4022     old_property = g_hash_table_lookup(val->v.proplist, key);
4023     if (property->append) {
4024 	/* old_property will be freed by g_hash_table_insert, so
4025 	 * steal its values */
4026 	if (old_property) {
4027 	    if (old_property->priority)
4028 		property->priority = 1;
4029 	    property->values = old_property->values;
4030 	    old_property->values = NULL;
4031 	    set_seen = FALSE;
4032 	}
4033     }
4034     while(tok == CONF_STRING) {
4035 	property->values = g_slist_append(property->values,
4036 					  strdup(tokenval.v.s));
4037 	get_conftoken(CONF_ANY);
4038     }
4039     unget_conftoken();
4040     g_hash_table_insert(val->v.proplist, key, property);
4041     if (set_seen) {
4042 	property->seen.linenum = 0;
4043 	property->seen.filename = NULL;
4044 	property->seen.block = NULL;
4045 	ckseen(&property->seen);
4046     }
4047 }
4048 
4049 
4050 static void
read_dapplication(conf_var_t * np G_GNUC_UNUSED,val_t * val)4051 read_dapplication(
4052     conf_var_t *np G_GNUC_UNUSED,
4053     val_t      *val)
4054 {
4055     application_t *application;
4056 
4057     get_conftoken(CONF_ANY);
4058     if (tok == CONF_LBRACE) {
4059 	current_line_num -= 1;
4060 	application = read_application(vstralloc("custom(DUMPTYPE:",
4061 						 dpcur.name, ")", ".",
4062 						 anonymous_value(),NULL),
4063 				       NULL, NULL, NULL);
4064 	current_line_num -= 1;
4065     } else if (tok == CONF_STRING) {
4066 	application = lookup_application(tokenval.v.s);
4067 	if (application == NULL) {
4068 	    conf_parserror(_("Unknown application named: %s"), tokenval.v.s);
4069 	    return;
4070 	}
4071     } else {
4072 	conf_parserror(_("application name expected: %d %d"), tok, CONF_STRING);
4073 	return;
4074     }
4075     amfree(val->v.s);
4076     val->v.s = stralloc(application->name);
4077     ckseen(&val->seen);
4078 }
4079 
4080 static void
read_dinteractivity(conf_var_t * np G_GNUC_UNUSED,val_t * val)4081 read_dinteractivity(
4082     conf_var_t *np G_GNUC_UNUSED,
4083     val_t      *val)
4084 {
4085     interactivity_t *interactivity;
4086 
4087     get_conftoken(CONF_ANY);
4088     if (tok == CONF_LBRACE) {
4089 	current_line_num -= 1;
4090 	interactivity = read_interactivity(vstralloc("custom(iv)", ".",
4091 						     anonymous_value(),NULL),
4092 				       NULL, NULL, NULL);
4093 	current_line_num -= 1;
4094     } else if (tok == CONF_STRING) {
4095 	interactivity = lookup_interactivity(tokenval.v.s);
4096 	if (interactivity == NULL) {
4097 	    conf_parserror(_("Unknown interactivity named: %s"), tokenval.v.s);
4098 	    return;
4099 	}
4100     } else {
4101 	conf_parserror(_("interactivity name expected: %d %d"), tok, CONF_STRING);
4102 	return;
4103     }
4104     amfree(val->v.s);
4105     val->v.s = stralloc(interactivity->name);
4106     ckseen(&val->seen);
4107 }
4108 
4109 static void
read_dtaperscan(conf_var_t * np G_GNUC_UNUSED,val_t * val)4110 read_dtaperscan(
4111     conf_var_t *np G_GNUC_UNUSED,
4112     val_t      *val)
4113 {
4114     taperscan_t *taperscan;
4115 
4116     get_conftoken(CONF_ANY);
4117     if (tok == CONF_LBRACE) {
4118 	current_line_num -= 1;
4119 	taperscan = read_taperscan(vstralloc("custom(ts)", ".",
4120 				   anonymous_value(),NULL),
4121 				   NULL, NULL, NULL);
4122 	current_line_num -= 1;
4123     } else if (tok == CONF_STRING) {
4124 	taperscan = lookup_taperscan(tokenval.v.s);
4125 	if (taperscan == NULL) {
4126 	    conf_parserror(_("Unknown taperscan named: %s"), tokenval.v.s);
4127 	    return;
4128 	}
4129     } else {
4130 	conf_parserror(_("taperscan name expected: %d %d"), tok, CONF_STRING);
4131 	return;
4132     }
4133     amfree(val->v.s);
4134     val->v.s = stralloc(taperscan->name);
4135     ckseen(&val->seen);
4136 }
4137 
4138 static void
read_dpp_script(conf_var_t * np G_GNUC_UNUSED,val_t * val)4139 read_dpp_script(
4140     conf_var_t *np G_GNUC_UNUSED,
4141     val_t      *val)
4142 {
4143     pp_script_t *pp_script;
4144     get_conftoken(CONF_ANY);
4145     if (tok == CONF_LBRACE) {
4146 	current_line_num -= 1;
4147 	pp_script = read_pp_script(vstralloc("custom(DUMPTYPE:", dpcur.name,
4148 					     ")", ".", anonymous_value(),NULL),
4149 				   NULL, NULL, NULL);
4150 	current_line_num -= 1;
4151 	val->v.identlist = g_slist_insert_sorted(val->v.identlist,
4152 			stralloc(pp_script->name), &compare_pp_script_order);
4153     } else if (tok == CONF_STRING || tok == CONF_IDENT) {
4154 	while (tok == CONF_STRING || tok == CONF_IDENT) {
4155 	    pp_script = lookup_pp_script(tokenval.v.s);
4156 	    if (pp_script == NULL) {
4157 		conf_parserror(_("Unknown pp_script named: %s"), tokenval.v.s);
4158 		return;
4159 	    }
4160     	    val->v.identlist = g_slist_insert_sorted(val->v.identlist,
4161 			 stralloc(pp_script->name), &compare_pp_script_order);
4162 	    get_conftoken(CONF_ANY);
4163 	}
4164 	unget_conftoken();
4165     } else {
4166 	conf_parserror(_("pp_script name expected: %d %d"), tok, CONF_STRING);
4167 	return;
4168     }
4169     ckseen(&val->seen);
4170 }
4171 static void
read_execute_on(conf_var_t * np G_GNUC_UNUSED,val_t * val)4172 read_execute_on(
4173     conf_var_t *np G_GNUC_UNUSED,
4174     val_t *val)
4175 {
4176     ckseen(&val->seen);
4177 
4178     get_conftoken(CONF_ANY);
4179     val->v.i = 0;
4180     do {
4181 	switch(tok) {
4182 	case CONF_PRE_AMCHECK:         val->v.i |= EXECUTE_ON_PRE_AMCHECK;          break;
4183 	case CONF_PRE_DLE_AMCHECK:     val->v.i |= EXECUTE_ON_PRE_DLE_AMCHECK;     break;
4184 	case CONF_PRE_HOST_AMCHECK:    val->v.i |= EXECUTE_ON_PRE_HOST_AMCHECK;    break;
4185 	case CONF_POST_DLE_AMCHECK:    val->v.i |= EXECUTE_ON_POST_DLE_AMCHECK;    break;
4186 	case CONF_POST_HOST_AMCHECK:   val->v.i |= EXECUTE_ON_POST_HOST_AMCHECK;   break;
4187 	case CONF_POST_AMCHECK:        val->v.i |= EXECUTE_ON_POST_AMCHECK;          break;
4188 	case CONF_PRE_ESTIMATE:        val->v.i |= EXECUTE_ON_PRE_ESTIMATE;          break;
4189 	case CONF_PRE_DLE_ESTIMATE:    val->v.i |= EXECUTE_ON_PRE_DLE_ESTIMATE;    break;
4190 	case CONF_PRE_HOST_ESTIMATE:   val->v.i |= EXECUTE_ON_PRE_HOST_ESTIMATE;   break;
4191 	case CONF_POST_DLE_ESTIMATE:   val->v.i |= EXECUTE_ON_POST_DLE_ESTIMATE;   break;
4192 	case CONF_POST_HOST_ESTIMATE:  val->v.i |= EXECUTE_ON_POST_HOST_ESTIMATE;  break;
4193 	case CONF_POST_ESTIMATE:       val->v.i |= EXECUTE_ON_POST_ESTIMATE;          break;
4194 	case CONF_PRE_BACKUP:          val->v.i |= EXECUTE_ON_PRE_BACKUP;          break;
4195 	case CONF_PRE_DLE_BACKUP:      val->v.i |= EXECUTE_ON_PRE_DLE_BACKUP;      break;
4196 	case CONF_PRE_HOST_BACKUP:     val->v.i |= EXECUTE_ON_PRE_HOST_BACKUP;     break;
4197 	case CONF_POST_BACKUP:         val->v.i |= EXECUTE_ON_POST_BACKUP;         break;
4198 	case CONF_POST_DLE_BACKUP:     val->v.i |= EXECUTE_ON_POST_DLE_BACKUP;     break;
4199 	case CONF_POST_HOST_BACKUP:    val->v.i |= EXECUTE_ON_POST_HOST_BACKUP;    break;
4200 	case CONF_PRE_RECOVER:         val->v.i |= EXECUTE_ON_PRE_RECOVER;         break;
4201 	case CONF_POST_RECOVER:        val->v.i |= EXECUTE_ON_POST_RECOVER;        break;
4202 	case CONF_PRE_LEVEL_RECOVER:   val->v.i |= EXECUTE_ON_PRE_LEVEL_RECOVER;   break;
4203 	case CONF_POST_LEVEL_RECOVER:  val->v.i |= EXECUTE_ON_POST_LEVEL_RECOVER;  break;
4204 	case CONF_INTER_LEVEL_RECOVER: val->v.i |= EXECUTE_ON_INTER_LEVEL_RECOVER; break;
4205 	default:
4206 	conf_parserror(_("Execute-on expected"));
4207 	}
4208 	get_conftoken(CONF_ANY);
4209 	if (tok != CONF_COMMA) {
4210 	    unget_conftoken();
4211 	    break;
4212 	}
4213 	get_conftoken(CONF_ANY);
4214     } while (1);
4215 }
4216 
4217 static void
read_execute_where(conf_var_t * np G_GNUC_UNUSED,val_t * val)4218 read_execute_where(
4219     conf_var_t *np G_GNUC_UNUSED,
4220     val_t *val)
4221 {
4222     ckseen(&val->seen);
4223 
4224     get_conftoken(CONF_ANY);
4225     switch(tok) {
4226     case CONF_CLIENT:      val->v.i = ES_CLIENT;   break;
4227     case CONF_SERVER:      val->v.i = ES_SERVER;   break;
4228     default:
4229 	conf_parserror(_("CLIENT or SERVER expected"));
4230     }
4231 }
4232 
4233 static void
read_int_or_str(conf_var_t * np G_GNUC_UNUSED,val_t * val)4234 read_int_or_str(
4235     conf_var_t *np G_GNUC_UNUSED,
4236     val_t *val)
4237 {
4238     ckseen(&val->seen);
4239 
4240     get_conftoken(CONF_ANY);
4241     switch(tok) {
4242     case CONF_INT:
4243 	amfree(val->v.s);
4244 	val->v.s = g_strdup_printf("%d", tokenval.v.i);
4245 	break;
4246 
4247     case CONF_SIZE:
4248 	amfree(val->v.s);
4249 	val->v.s = g_strdup_printf("%zu", tokenval.v.size);
4250 	break;
4251 
4252     case CONF_INT64:
4253 	amfree(val->v.s);
4254 	val->v.s = g_strdup_printf("%jd", (intmax_t)tokenval.v.int64);
4255 	break;
4256 
4257     case CONF_STRING:
4258 	val->v.s = newstralloc(val->v.s, tokenval.v.s);
4259 	break;
4260     default:
4261 	conf_parserror(_("an integer or a quoted string is expected"));
4262     }
4263 }
4264 
4265 static void
read_autolabel(conf_var_t * np G_GNUC_UNUSED,val_t * val)4266 read_autolabel(
4267     conf_var_t *np G_GNUC_UNUSED,
4268     val_t *val)
4269 {
4270     int data = 0;
4271     ckseen(&val->seen);
4272 
4273     get_conftoken(CONF_ANY);
4274     if (tok == CONF_STRING) {
4275 	data++;
4276 	val->v.autolabel.template = newstralloc(val->v.autolabel.template,
4277 						tokenval.v.s);
4278 	get_conftoken(CONF_ANY);
4279     }
4280     val->v.autolabel.autolabel = 0;
4281     while (tok != CONF_NL && tok != CONF_END) {
4282 	data++;
4283 	if (tok == CONF_ANY_VOLUME)
4284 	    val->v.autolabel.autolabel |= AL_OTHER_CONFIG | AL_NON_AMANDA |
4285 					  AL_VOLUME_ERROR | AL_EMPTY;
4286 	else if (tok == CONF_OTHER_CONFIG)
4287 	    val->v.autolabel.autolabel |= AL_OTHER_CONFIG;
4288 	else if (tok == CONF_NON_AMANDA)
4289 	    val->v.autolabel.autolabel |= AL_NON_AMANDA;
4290 	else if (tok == CONF_VOLUME_ERROR)
4291 	    val->v.autolabel.autolabel |= AL_VOLUME_ERROR;
4292 	else if (tok == CONF_EMPTY)
4293 	    val->v.autolabel.autolabel |= AL_EMPTY;
4294 	else {
4295 	    conf_parserror(_("ANY, NEW-VOLUME, OTHER-CONFIG, NON-AMANDA, VOLUME-ERROR or EMPTY is expected"));
4296 	}
4297 	get_conftoken(CONF_ANY);
4298     }
4299     if (data == 0) {
4300 	amfree(val->v.autolabel.template);
4301 	val->v.autolabel.autolabel = 0;
4302     } else if (val->v.autolabel.autolabel == 0) {
4303 	val->v.autolabel.autolabel = AL_VOLUME_ERROR | AL_EMPTY;
4304     }
4305 }
4306 
4307 static void
read_part_cache_type(conf_var_t * np G_GNUC_UNUSED,val_t * val)4308 read_part_cache_type(
4309     conf_var_t *np G_GNUC_UNUSED,
4310     val_t *val)
4311 {
4312    part_cache_type_t part_cache_type;
4313 
4314    ckseen(&val->seen);
4315 
4316    get_conftoken(CONF_ANY);
4317    switch(tok) {
4318    case CONF_NONE:
4319      part_cache_type = PART_CACHE_TYPE_NONE;
4320      break;
4321 
4322    case CONF_DISK:
4323      part_cache_type = PART_CACHE_TYPE_DISK;
4324      break;
4325 
4326    case CONF_MEMORY:
4327      part_cache_type = PART_CACHE_TYPE_MEMORY;
4328      break;
4329 
4330    default:
4331      conf_parserror(_("NONE, DISK or MEMORY expected"));
4332      part_cache_type = PART_CACHE_TYPE_NONE;
4333      break;
4334    }
4335 
4336    val_t__part_cache_type(val) = (int)part_cache_type;
4337 }
4338 
4339 static void
read_host_limit(conf_var_t * np G_GNUC_UNUSED,val_t * val)4340 read_host_limit(
4341     conf_var_t *np G_GNUC_UNUSED,
4342     val_t *val)
4343 {
4344     host_limit_t *rl = &val_t__host_limit(val);
4345     ckseen(&val->seen);
4346 
4347     rl->match_pats = NULL;
4348     rl->same_host  = FALSE;
4349     rl->server     = FALSE;
4350 
4351     while (1) {
4352 	get_conftoken(CONF_ANY);
4353 	switch(tok) {
4354 	case CONF_STRING:
4355 	    rl->match_pats = g_slist_append(rl->match_pats, g_strdup(tokenval.v.s));
4356 	    break;
4357 	case CONF_SAME_HOST:
4358 	    rl->same_host = TRUE;
4359 	    break;
4360 
4361 	case CONF_SERVER:
4362 	    rl->server = TRUE;
4363 	    break;
4364 
4365 	case CONF_NL:
4366 	case CONF_END:
4367 	    return;
4368 
4369         default:
4370 	    conf_parserror("SAME-HOST or a string expected");
4371 	    break;
4372 	}
4373     }
4374 }
4375 
4376 /* get_* functions */
4377 
4378 /* these functions use precompiler conditionals to skip useless size checks
4379  * when casting from one type to another.  SIZEOF_GINT64 is pretty simple to
4380  * calculate; the others are calculated by configure. */
4381 
4382 #define SIZEOF_GINT64 8
4383 
4384 static time_t
get_time(void)4385 get_time(void)
4386 {
4387     time_t hhmm;
4388 
4389     get_conftoken(CONF_ANY);
4390     switch(tok) {
4391     case CONF_INT:
4392 #if SIZEOF_TIME_T < SIZEOF_INT
4393 	if ((gint64)tokenval.v.i >= (gint64)TIME_MAX)
4394 	    conf_parserror(_("value too large"));
4395 #endif
4396 	hhmm = (time_t)tokenval.v.i;
4397 	break;
4398 
4399     case CONF_SIZE:
4400 #if SIZEOF_TIME_T < SIZEOF_SSIZE_T
4401 	if ((gint64)tokenval.v.size >= (gint64)TIME_MAX)
4402 	    conf_parserror(_("value too large"));
4403 #endif
4404 	hhmm = (time_t)tokenval.v.size;
4405 	break;
4406 
4407     case CONF_INT64:
4408 #if SIZEOF_TIME_T < SIZEOF_GINT64
4409 	if ((gint64)tokenval.v.int64 >= (gint64)TIME_MAX)
4410 	    conf_parserror(_("value too large"));
4411 #endif
4412 	hhmm = (time_t)tokenval.v.int64;
4413 	break;
4414 
4415     case CONF_AMINFINITY:
4416 	hhmm = TIME_MAX;
4417 	break;
4418 
4419     default:
4420 	conf_parserror(_("a time is expected"));
4421 	hhmm = 0;
4422 	break;
4423     }
4424     return hhmm;
4425 }
4426 
4427 static int
get_int(confunit_t unit)4428 get_int(
4429     confunit_t unit)
4430 {
4431     int val;
4432     keytab_t *save_kt;
4433 
4434     save_kt = keytable;
4435     keytable = numb_keytable;
4436 
4437     get_conftoken(CONF_ANY);
4438     switch(tok) {
4439     case CONF_INT:
4440 	val = tokenval.v.i;
4441 	break;
4442 
4443     case CONF_SIZE:
4444 #if SIZEOF_INT < SIZEOF_SSIZE_T
4445 	if ((gint64)tokenval.v.size > (gint64)INT_MAX)
4446 	    conf_parserror(_("value too large"));
4447 	if ((gint64)tokenval.v.size < (gint64)INT_MIN)
4448 	    conf_parserror(_("value too small"));
4449 #endif
4450 	val = (int)tokenval.v.size;
4451 	break;
4452 
4453     case CONF_INT64:
4454 #if SIZEOF_INT < SIZEOF_GINT64
4455 	if (tokenval.v.int64 > (gint64)INT_MAX)
4456 	    conf_parserror(_("value too large"));
4457 	if (tokenval.v.int64 < (gint64)INT_MIN)
4458 	    conf_parserror(_("value too small"));
4459 #endif
4460 	val = (int)tokenval.v.int64;
4461 	break;
4462 
4463     case CONF_AMINFINITY:
4464 	val = INT_MAX;
4465 	break;
4466 
4467     default:
4468 	conf_parserror(_("an integer is expected"));
4469 	val = 0;
4470 	break;
4471     }
4472 
4473     /* get multiplier, if any */
4474     val = get_multiplier(val, unit);
4475 
4476     keytable = save_kt;
4477     return val;
4478 }
4479 
4480 static ssize_t
get_size(confunit_t unit)4481 get_size(
4482     confunit_t unit)
4483 {
4484     ssize_t val;
4485     keytab_t *save_kt;
4486 
4487     save_kt = keytable;
4488     keytable = numb_keytable;
4489 
4490     get_conftoken(CONF_ANY);
4491 
4492     switch(tok) {
4493     case CONF_SIZE:
4494 	val = tokenval.v.size;
4495 	break;
4496 
4497     case CONF_INT:
4498 #if SIZEOF_SIZE_T < SIZEOF_INT
4499 	if ((gint64)tokenval.v.i > (gint64)SSIZE_MAX)
4500 	    conf_parserror(_("value too large"));
4501 	if ((gint64)tokenval.v.i < (gint64)SSIZE_MIN)
4502 	    conf_parserror(_("value too small"));
4503 #endif
4504 	val = (ssize_t)tokenval.v.i;
4505 	break;
4506 
4507     case CONF_INT64:
4508 #if SIZEOF_SIZE_T < SIZEOF_GINT64
4509 	if (tokenval.v.int64 > (gint64)SSIZE_MAX)
4510 	    conf_parserror(_("value too large"));
4511 	if (tokenval.v.int64 < (gint64)SSIZE_MIN)
4512 	    conf_parserror(_("value too small"));
4513 #endif
4514 	val = (ssize_t)tokenval.v.int64;
4515 	break;
4516 
4517     case CONF_AMINFINITY:
4518 	val = (ssize_t)SSIZE_MAX;
4519 	break;
4520 
4521     default:
4522 	conf_parserror(_("an integer is expected"));
4523 	val = 0;
4524 	break;
4525     }
4526 
4527     /* get multiplier, if any */
4528     val = get_multiplier(val, unit);
4529 
4530     keytable = save_kt;
4531     return val;
4532 }
4533 
4534 static gint64
get_int64(confunit_t unit)4535 get_int64(
4536     confunit_t unit)
4537 {
4538     gint64 val;
4539     keytab_t *save_kt;
4540 
4541     save_kt = keytable;
4542     keytable = numb_keytable;
4543 
4544     get_conftoken(CONF_ANY);
4545 
4546     switch(tok) {
4547     case CONF_INT:
4548 	val = (gint64)tokenval.v.i;
4549 	break;
4550 
4551     case CONF_SIZE:
4552 	val = (gint64)tokenval.v.size;
4553 	break;
4554 
4555     case CONF_INT64:
4556 	val = tokenval.v.int64;
4557 	break;
4558 
4559     case CONF_AMINFINITY:
4560 	val = G_MAXINT64;
4561 	break;
4562 
4563     default:
4564 	conf_parserror(_("an integer is expected"));
4565 	val = 0;
4566 	break;
4567     }
4568 
4569     /* get multiplier, if any */
4570     val = get_multiplier(val, unit);
4571 
4572     keytable = save_kt;
4573 
4574     return val;
4575 }
4576 
4577 gint64
get_multiplier(gint64 val,confunit_t unit)4578 get_multiplier(
4579     gint64 val,
4580     confunit_t unit)
4581 {
4582     /* get multiplier, if any */
4583     get_conftoken(CONF_ANY);
4584 
4585     if (tok == CONF_NL || tok == CONF_END) { /* no multiplier */
4586 	val = val;
4587     } else if (tok == CONF_MULT1 && unit == CONF_UNIT_K) {
4588 	val /= 1024;
4589     } else if (tok == CONF_MULT1 ||
4590 	(tok == CONF_MULT1K && unit == CONF_UNIT_K)) {
4591 	val *= 1;	/* multiply by one */
4592     } else if (tok == CONF_MULT7) {
4593 	if (val > G_MAXINT64/7 || val < ((gint64)G_MININT64)/7)
4594 	    conf_parserror(_("value too large"));
4595 	val *= 7;
4596     } else if (tok == CONF_MULT1K ||
4597 	       (tok == CONF_MULT1M && unit == CONF_UNIT_K)) {
4598 	if (val > G_MAXINT64/1024 || val < ((gint64)G_MININT64)/1024)
4599 	    conf_parserror(_("value too large"));
4600 	val *= 1024;
4601     } else if (tok == CONF_MULT1M ||
4602 	       (tok == CONF_MULT1G && unit == CONF_UNIT_K)) {
4603 	if (val > G_MAXINT64/(1024*1024) || val < ((gint64)G_MININT64)/(1024*1024))
4604 	    conf_parserror(_("value too large"));
4605 	val *= 1024*1024;
4606     } else if (tok == CONF_MULT1G ||
4607 	       (tok == CONF_MULT1T && unit == CONF_UNIT_K)) {
4608 	if (val > G_MAXINT64/(1024*1024*1024) || val < ((gint64)G_MININT64)/(1024*1024*1024))
4609 	    conf_parserror(_("value too large"));
4610 	val *= 1024*1024*1024;
4611     } else if (tok == CONF_MULT1T) {
4612 	if (val > G_MAXINT64/(1024*1024*1024*1024LL) || val < ((gint64)G_MININT64)/(1024*1024*1024*1024LL))
4613 	    conf_parserror(_("value too large"));
4614 	val *= 1024*1024*1024*1024LL;
4615     } else {
4616 	val *= 1;
4617 	unget_conftoken();
4618     }
4619 
4620     return val;
4621 }
4622 
4623 static int
get_bool(void)4624 get_bool(void)
4625 {
4626     int val;
4627     keytab_t *save_kt;
4628 
4629     save_kt = keytable;
4630     keytable = bool_keytable;
4631 
4632     get_conftoken(CONF_ANY);
4633 
4634     switch(tok) {
4635     case CONF_INT:
4636 	if (tokenval.v.i != 0)
4637 	    val = 1;
4638 	else
4639 	    val = 0;
4640 	break;
4641 
4642     case CONF_SIZE:
4643 	if (tokenval.v.size != (size_t)0)
4644 	    val = 1;
4645 	else
4646 	    val = 0;
4647 	break;
4648 
4649     case CONF_INT64:
4650 	if (tokenval.v.int64 != (gint64)0)
4651 	    val = 1;
4652 	else
4653 	    val = 0;
4654 	break;
4655 
4656     case CONF_ATRUE:
4657 	val = 1;
4658 	break;
4659 
4660     case CONF_AFALSE:
4661 	val = 0;
4662 	break;
4663 
4664     case CONF_NL:
4665 	unget_conftoken();
4666 	val = 2; /* no argument - most likely TRUE */
4667 	break;
4668     default:
4669 	unget_conftoken();
4670 	val = 3; /* a bad argument - most likely TRUE */
4671 	conf_parserror(_("YES, NO, TRUE, FALSE, ON, OFF, 0, 1 expected"));
4672 	break;
4673     }
4674 
4675     keytable = save_kt;
4676     return val;
4677 }
4678 
4679 static int
get_no_yes_all(void)4680 get_no_yes_all(void)
4681 {
4682     int val;
4683     keytab_t *save_kt;
4684 
4685     save_kt = keytable;
4686     keytable = no_yes_all_keytable;
4687 
4688     get_conftoken(CONF_ANY);
4689 
4690     switch(tok) {
4691     case CONF_INT:
4692 	val = tokenval.v.i;
4693 	break;
4694 
4695     case CONF_SIZE:
4696 	val = tokenval.v.size;
4697 	break;
4698 
4699     case CONF_INT64:
4700 	val = tokenval.v.int64;
4701 	break;
4702 
4703     case CONF_ALL:
4704 	val = 2;
4705 	break;
4706 
4707     case CONF_ATRUE:
4708 	val = 1;
4709 	break;
4710 
4711     case CONF_AFALSE:
4712 	val = 0;
4713 	break;
4714 
4715     case CONF_NL:
4716 	unget_conftoken();
4717 	val = 3; /* no argument - most likely TRUE */
4718 	break;
4719     default:
4720 	unget_conftoken();
4721 	val = 3; /* a bad argument - most likely TRUE */
4722 	conf_parserror(_("%d: YES, NO, ALL, TRUE, FALSE, ON, OFF, 0, 1, 2 expected"), tok);
4723 	break;
4724     }
4725 
4726     if (val > 2 || val < 0)
4727 	val = 1;
4728     keytable = save_kt;
4729     return val;
4730 }
4731 
4732 void
ckseen(seen_t * seen)4733 ckseen(
4734     seen_t *seen)
4735 {
4736     if (seen->linenum && !allow_overwrites && current_line_num != -2) {
4737 	conf_parserror(_("duplicate parameter; previous definition %s:%d"),
4738 		seen->filename, seen->linenum);
4739     }
4740     seen->block = current_block;
4741     seen->filename = current_filename;
4742     seen->linenum = current_line_num;
4743 }
4744 
4745 /* Validation functions */
4746 
4747 static void
validate_nonnegative(struct conf_var_s * np,val_t * val)4748 validate_nonnegative(
4749     struct conf_var_s *np,
4750     val_t        *val)
4751 {
4752     switch(val->type) {
4753     case CONFTYPE_INT:
4754 	if(val_t__int(val) < 0)
4755 	    conf_parserror(_("%s must be nonnegative"), get_token_name(np->token));
4756 	break;
4757     case CONFTYPE_INT64:
4758 	if(val_t__int64(val) < 0)
4759 	    conf_parserror(_("%s must be nonnegative"), get_token_name(np->token));
4760 	break;
4761     case CONFTYPE_SIZE:
4762 	// Can't be negative
4763 	//if(val_t__size(val) < 0)
4764 	//    conf_parserror(_("%s must be positive"), get_token_name(np->token));
4765 	break;
4766     default:
4767 	conf_parserror(_("validate_nonnegative invalid type %d\n"), val->type);
4768     }
4769 }
4770 
4771 static void
validate_non_zero(struct conf_var_s * np,val_t * val)4772 validate_non_zero(
4773     struct conf_var_s *np,
4774     val_t        *val)
4775 {
4776     switch(val->type) {
4777     case CONFTYPE_INT:
4778 	if(val_t__int(val) == 0)
4779 	    conf_parserror(_("%s must not be 0"), get_token_name(np->token));
4780 	break;
4781     case CONFTYPE_INT64:
4782 	if(val_t__int64(val) == 0)
4783 	    conf_parserror(_("%s must not be 0"), get_token_name(np->token));
4784 	break;
4785     case CONFTYPE_TIME:
4786 	if(val_t__time(val) == 0)
4787 	    conf_parserror(_("%s must not be 0"), get_token_name(np->token));
4788 	break;
4789     case CONFTYPE_SIZE:
4790 	if(val_t__size(val) == 0)
4791 	    conf_parserror(_("%s must not be 0"), get_token_name(np->token));
4792 	break;
4793     default:
4794 	conf_parserror(_("validate_non_zero invalid type %d\n"), val->type);
4795     }
4796 }
4797 
4798 static void
validate_positive(struct conf_var_s * np,val_t * val)4799 validate_positive(
4800     struct conf_var_s *np,
4801     val_t        *val)
4802 {
4803     switch(val->type) {
4804     case CONFTYPE_INT:
4805 	if(val_t__int(val) < 1)
4806 	    conf_parserror(_("%s must be positive"), get_token_name(np->token));
4807 	break;
4808     case CONFTYPE_INT64:
4809 	if(val_t__int64(val) < 1)
4810 	    conf_parserror(_("%s must be positive"), get_token_name(np->token));
4811 	break;
4812     case CONFTYPE_TIME:
4813 	if(val_t__time(val) < 1)
4814 	    conf_parserror(_("%s must be positive"), get_token_name(np->token));
4815 	break;
4816     case CONFTYPE_SIZE:
4817 	if(val_t__size(val) < 1)
4818 	    conf_parserror(_("%s must be positive"), get_token_name(np->token));
4819 	break;
4820     default:
4821 	conf_parserror(_("validate_positive invalid type %d\n"), val->type);
4822     }
4823 }
4824 
4825 static void
validate_runspercycle(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4826 validate_runspercycle(
4827     struct conf_var_s *np G_GNUC_UNUSED,
4828     val_t        *val)
4829 {
4830     if(val_t__int(val) < -1)
4831 	conf_parserror(_("runspercycle must be >= -1"));
4832 }
4833 
4834 static void
validate_bumppercent(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4835 validate_bumppercent(
4836     struct conf_var_s *np G_GNUC_UNUSED,
4837     val_t        *val)
4838 {
4839     if(val_t__int(val) < 0 || val_t__int(val) > 100)
4840 	conf_parserror(_("bumppercent must be between 0 and 100"));
4841 }
4842 
4843 static void
validate_inparallel(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4844 validate_inparallel(
4845     struct conf_var_s *np G_GNUC_UNUSED,
4846     val_t        *val)
4847 {
4848     if(val_t__int(val) < 1 || val_t__int(val) >MAX_DUMPERS)
4849 	conf_parserror(_("inparallel must be between 1 and MAX_DUMPERS (%d)"),
4850 		       MAX_DUMPERS);
4851 }
4852 
4853 static void
validate_bumpmult(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4854 validate_bumpmult(
4855     struct conf_var_s *np G_GNUC_UNUSED,
4856     val_t        *val)
4857 {
4858     if(val_t__real(val) < 0.999) {
4859 	conf_parserror(_("bumpmult must one or more"));
4860     }
4861 }
4862 
4863 static void
validate_displayunit(struct conf_var_s * np G_GNUC_UNUSED,val_t * val G_GNUC_UNUSED)4864 validate_displayunit(
4865     struct conf_var_s *np G_GNUC_UNUSED,
4866     val_t        *val G_GNUC_UNUSED)
4867 {
4868     char *s = val_t__str(val);
4869     if (strlen(s) == 1) {
4870 	switch (s[0]) {
4871 	    case 'K':
4872 	    case 'M':
4873 	    case 'G':
4874 	    case 'T':
4875 		return; /* all good */
4876 
4877 	    /* lower-case values should get folded to upper case */
4878 	    case 'k':
4879 	    case 'm':
4880 	    case 'g':
4881 	    case 't':
4882 		s[0] = toupper(s[0]);
4883 		return;
4884 
4885 	    default:	/* bad */
4886 		break;
4887 	}
4888     }
4889     conf_parserror(_("displayunit must be k,m,g or t."));
4890 }
4891 
4892 static void
validate_reserve(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4893 validate_reserve(
4894     struct conf_var_s *np G_GNUC_UNUSED,
4895     val_t        *val)
4896 {
4897     if(val_t__int(val) < 0 || val_t__int(val) > 100)
4898 	conf_parserror(_("reserve must be between 0 and 100"));
4899 }
4900 
4901 static void
validate_use(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4902 validate_use(
4903     struct conf_var_s *np G_GNUC_UNUSED,
4904     val_t        *val)
4905 {
4906     val_t__int64(val) = am_floor(val_t__int64(val), DISK_BLOCK_KB);
4907 }
4908 
4909 static void
validate_chunksize(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4910 validate_chunksize(
4911     struct conf_var_s *np G_GNUC_UNUSED,
4912     val_t        *val)
4913 {
4914     /* NOTE: this function modifies the target value (rounding) */
4915     if(val_t__int64(val) == 0) {
4916 	val_t__int64(val) = ((G_MAXINT64 / 1024) - (2 * DISK_BLOCK_KB));
4917     }
4918     else if(val_t__int64(val) < 0) {
4919 	conf_parserror(_("Negative chunksize (%lld) is no longer supported"), (long long)val_t__int64(val));
4920     }
4921     val_t__int64(val) = am_floor(val_t__int64(val), (gint64)DISK_BLOCK_KB);
4922     if (val_t__int64(val) < 2*DISK_BLOCK_KB) {
4923 	conf_parserror("chunksize must be at least %dkb", 2*DISK_BLOCK_KB);
4924     }
4925 }
4926 
4927 static void
validate_blocksize(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4928 validate_blocksize(
4929     struct conf_var_s *np G_GNUC_UNUSED,
4930     val_t        *val)
4931 {
4932     if(val_t__size(val) < DISK_BLOCK_KB) {
4933 	conf_parserror(_("Tape blocksize must be at least %d KBytes"),
4934 		  DISK_BLOCK_KB);
4935     }
4936 }
4937 
4938 static void
validate_debug(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4939 validate_debug(
4940     struct conf_var_s *np G_GNUC_UNUSED,
4941     val_t        *val)
4942 {
4943     if(val_t__int(val) < 0 || val_t__int(val) > 9) {
4944 	conf_parserror(_("Debug must be between 0 and 9"));
4945     }
4946 }
4947 
4948 static void
validate_port_range(val_t * val,int smallest,int largest)4949 validate_port_range(
4950     val_t        *val,
4951     int		 smallest,
4952     int		 largest)
4953 {
4954     int i;
4955     /* check both values are in range */
4956     for (i = 0; i < 2; i++) {
4957         if(val_t__intrange(val)[0] < smallest || val_t__intrange(val)[0] > largest) {
4958 	    conf_parserror(_("portrange must be in the range %d to %d, inclusive"), smallest, largest);
4959 	}
4960      }
4961 
4962     /* and check they're in the right order and not equal */
4963     if (val_t__intrange(val)[0] > val_t__intrange(val)[1]) {
4964 	conf_parserror(_("portranges must be in order from low to high"));
4965     }
4966 }
4967 
4968 static void
validate_reserved_port_range(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4969 validate_reserved_port_range(
4970     struct conf_var_s *np G_GNUC_UNUSED,
4971     val_t        *val)
4972 {
4973     validate_port_range(val, 1, IPPORT_RESERVED-1);
4974 }
4975 
4976 static void
validate_unreserved_port_range(struct conf_var_s * np G_GNUC_UNUSED,val_t * val)4977 validate_unreserved_port_range(
4978     struct conf_var_s *np G_GNUC_UNUSED,
4979     val_t        *val)
4980 {
4981     validate_port_range(val, IPPORT_RESERVED, 65535);
4982 }
4983 
4984 /*
4985  * Validate tmpdir, the directory must exist and be writable by the user.
4986  */
4987 
validate_tmpdir(conf_var_t * var G_GNUC_UNUSED,val_t * value)4988 static void validate_tmpdir(conf_var_t *var G_GNUC_UNUSED, val_t *value)
4989 {
4990     struct stat stat_buf;
4991     gchar *tmpdir = val_t_to_str(value);
4992 
4993     if (stat(tmpdir, &stat_buf)) {
4994 	conf_parserror(_("invalid TMPDIR: directory '%s': %s."),
4995 		      tmpdir, strerror(errno));
4996     } else if (!S_ISDIR(stat_buf.st_mode)) {
4997 	conf_parserror(_("invalid TMPDIR: '%s' is not a directory."),
4998 		      tmpdir);
4999     } else {
5000 	gchar *dir = g_strconcat(tmpdir, "/.", NULL);
5001 	if (access(dir, R_OK|W_OK) == -1) {
5002 	    conf_parserror(_("invalid TMPDIR: '%s': can not read/write: %s."),
5003 			   tmpdir, strerror(errno));
5004 	}
5005 	g_free(dir);
5006     }
5007 }
5008 
5009 gboolean
config_is_initialized(void)5010 config_is_initialized(void)
5011 {
5012     return config_initialized;
5013 }
5014 
5015 /*
5016  * Initialization Implementation
5017  */
5018 
5019 cfgerr_level_t
config_init(config_init_flags flags,char * arg_config_name)5020 config_init(
5021     config_init_flags flags,
5022     char *arg_config_name)
5023 {
5024     if (!(flags & CONFIG_INIT_OVERLAY)) {
5025 	/* Clear out anything that's already in there */
5026 	config_uninit();
5027 
5028 	/* and set everything to default values */
5029 	init_defaults();
5030 
5031 	allow_overwrites = FALSE;
5032     } else {
5033 	if (!config_initialized) {
5034 	    error(_("Attempt to overlay configuration with no existing configuration"));
5035 	    /* NOTREACHED */
5036 	}
5037 
5038 	allow_overwrites = TRUE;
5039     }
5040 
5041     /* store away our client-ness for later reference */
5042     config_client = flags & CONFIG_INIT_CLIENT;
5043 
5044     /* if we're using an explicit name, but the name is '.', then we're using the
5045      * current directory */
5046     if ((flags & CONFIG_INIT_EXPLICIT_NAME) && arg_config_name) {
5047 	if (0 == strcmp(arg_config_name, "."))
5048 	    flags = (flags & (~CONFIG_INIT_EXPLICIT_NAME)) | CONFIG_INIT_USE_CWD;
5049     }
5050 
5051     if ((flags & CONFIG_INIT_EXPLICIT_NAME) && arg_config_name) {
5052 	config_name = newstralloc(config_name, arg_config_name);
5053 	config_dir = newvstralloc(config_dir, CONFIG_DIR, "/", arg_config_name, NULL);
5054     } else if (flags & CONFIG_INIT_USE_CWD) {
5055         char * cwd;
5056 
5057         cwd = get_original_cwd();
5058 	if (!cwd) {
5059 	    /* (this isn't a config error, so it's always fatal) */
5060 	    error(_("Cannot determine current working directory"));
5061 	    /* NOTREACHED */
5062 	}
5063 
5064 	config_dir = stralloc2(cwd, "/");
5065 	if ((config_name = strrchr(cwd, '/')) != NULL) {
5066 	    config_name = stralloc(config_name + 1);
5067 	}
5068 
5069     } else if (flags & CONFIG_INIT_CLIENT) {
5070 	amfree(config_name);
5071 	config_dir = newstralloc(config_dir, CONFIG_DIR);
5072     } else {
5073 	/* ok, then, we won't read anything (for e.g., amrestore) */
5074 	amfree(config_name);
5075 	amfree(config_dir);
5076     }
5077 
5078     /* setup for apply_config_overrides */
5079     if (flags & CONFIG_INIT_CLIENT) {
5080 	keytable = client_keytab;
5081 	parsetable = client_var;
5082     } else {
5083 	keytable = server_keytab;
5084 	parsetable = server_var;
5085     }
5086 
5087     if (config_overrides) {
5088 	int i;
5089 	for (i = 0; i < config_overrides->n_used; i++) {
5090 	    config_overrides->ovr[i].applied = FALSE;
5091 	}
5092     }
5093 
5094     /* apply config overrides to default setting */
5095     apply_config_overrides(config_overrides, NULL);
5096 
5097     /* If we have a config_dir, we can try reading something */
5098     if (config_dir) {
5099 	if (flags & CONFIG_INIT_CLIENT) {
5100 	    config_filename = newvstralloc(config_filename, config_dir, "/amanda-client.conf", NULL);
5101 	} else {
5102 	    config_filename = newvstralloc(config_filename, config_dir, "/amanda.conf", NULL);
5103 	}
5104 
5105 	read_conffile(config_filename,
5106 		flags & CONFIG_INIT_CLIENT,
5107 		flags & CONFIG_INIT_CLIENT);
5108     } else {
5109 	amfree(config_filename);
5110     }
5111 
5112     /* apply config overrides to default setting */
5113     apply_config_overrides(config_overrides, NULL);
5114 
5115     if (config_overrides) {
5116 	int i;
5117 	for (i = 0; i < config_overrides->n_used; i++) {
5118 	    if (config_overrides->ovr[i].applied == FALSE) {
5119 		conf_parserror(_("unknown parameter '%s'"),
5120 			       config_overrides->ovr[i].key);
5121 	    }
5122 	}
5123     }
5124 
5125     update_derived_values(flags & CONFIG_INIT_CLIENT);
5126 
5127     return cfgerr_level;
5128 }
5129 
5130 void
config_uninit(void)5131 config_uninit(void)
5132 {
5133     GSList           *hp;
5134     holdingdisk_t    *hd;
5135     dumptype_t       *dp, *dpnext;
5136     tapetype_t       *tp, *tpnext;
5137     interface_t      *ip, *ipnext;
5138     application_t *ap, *apnext;
5139     pp_script_t   *pp, *ppnext;
5140     device_config_t *dc, *dcnext;
5141     changer_config_t *cc, *ccnext;
5142     interactivity_t  *iv, *ivnext;
5143     taperscan_t      *ts, *tsnext;
5144     int               i;
5145 
5146     if (!config_initialized) return;
5147 
5148     for(hp=holdinglist; hp != NULL; hp = hp->next) {
5149 	hd = hp->data;
5150 	amfree(hd->name);
5151 	for(i=0; i<HOLDING_HOLDING; i++) {
5152 	   free_val_t(&hd->value[i]);
5153 	}
5154     }
5155     slist_free_full(holdinglist, g_free);
5156     holdinglist = NULL;
5157 
5158     for(dp=dumplist; dp != NULL; dp = dpnext) {
5159 	amfree(dp->name);
5160 	for(i=0; i<DUMPTYPE_DUMPTYPE; i++) {
5161 	   free_val_t(&dp->value[i]);
5162 	}
5163 	dpnext = dp->next;
5164 	amfree(dp);
5165     }
5166     dumplist = NULL;
5167 
5168     for(tp=tapelist; tp != NULL; tp = tpnext) {
5169 	amfree(tp->name);
5170 	for(i=0; i<TAPETYPE_TAPETYPE; i++) {
5171 	   free_val_t(&tp->value[i]);
5172 	}
5173 	tpnext = tp->next;
5174 	amfree(tp);
5175     }
5176     tapelist = NULL;
5177 
5178     for(ip=interface_list; ip != NULL; ip = ipnext) {
5179 	amfree(ip->name);
5180 	for(i=0; i<INTER_INTER; i++) {
5181 	   free_val_t(&ip->value[i]);
5182 	}
5183 	ipnext = ip->next;
5184 	amfree(ip);
5185     }
5186     interface_list = NULL;
5187 
5188     for(ap=application_list; ap != NULL; ap = apnext) {
5189 	amfree(ap->name);
5190 	for(i=0; i<APPLICATION_APPLICATION; i++) {
5191 	   free_val_t(&ap->value[i]);
5192 	}
5193 	apnext = ap->next;
5194 	amfree(ap);
5195     }
5196     application_list = NULL;
5197 
5198     for(pp=pp_script_list; pp != NULL; pp = ppnext) {
5199 	amfree(pp->name);
5200 	for(i=0; i<PP_SCRIPT_PP_SCRIPT; i++) {
5201 	   free_val_t(&pp->value[i]);
5202 	}
5203 	ppnext = pp->next;
5204 	amfree(pp);
5205     }
5206     pp_script_list = NULL;
5207 
5208     for(dc=device_config_list; dc != NULL; dc = dcnext) {
5209 	amfree(dc->name);
5210 	for(i=0; i<DEVICE_CONFIG_DEVICE_CONFIG; i++) {
5211 	   free_val_t(&dc->value[i]);
5212 	}
5213 	dcnext = dc->next;
5214 	amfree(dc);
5215     }
5216     device_config_list = NULL;
5217 
5218     for(cc=changer_config_list; cc != NULL; cc = ccnext) {
5219 	amfree(cc->name);
5220 	for(i=0; i<CHANGER_CONFIG_CHANGER_CONFIG; i++) {
5221 	   free_val_t(&cc->value[i]);
5222 	}
5223 	ccnext = cc->next;
5224 	amfree(cc);
5225     }
5226     changer_config_list = NULL;
5227 
5228     for(iv=interactivity_list; iv != NULL; iv = ivnext) {
5229 	amfree(iv->name);
5230 	for(i=0; i<INTERACTIVITY_INTERACTIVITY; i++) {
5231 	   free_val_t(&iv->value[i]);
5232 	}
5233 	ivnext = iv->next;
5234 	amfree(iv);
5235     }
5236     interactivity_list = NULL;
5237 
5238     for(ts=taperscan_list; ts != NULL; ts = tsnext) {
5239 	amfree(ts->name);
5240 	for(i=0; i<TAPERSCAN_TAPERSCAN; i++) {
5241 	   free_val_t(&ts->value[i]);
5242 	}
5243 	tsnext = ts->next;
5244 	amfree(ts);
5245     }
5246     taperscan_list = NULL;
5247 
5248     for(i=0; i<CNF_CNF; i++)
5249 	free_val_t(&conf_data[i]);
5250 
5251     if (config_overrides) {
5252 	free_config_overrides(config_overrides);
5253 	config_overrides = NULL;
5254     }
5255 
5256     amfree(config_name);
5257     amfree(config_dir);
5258     amfree(config_filename);
5259 
5260     slist_free_full(seen_filenames, g_free);
5261     seen_filenames = NULL;
5262 
5263     config_client = FALSE;
5264 
5265     config_clear_errors();
5266     config_initialized = FALSE;
5267 }
5268 
5269 static void
init_defaults(void)5270 init_defaults(
5271     void)
5272 {
5273     assert(!config_initialized);
5274 
5275     /* defaults for exported variables */
5276     conf_init_str(&conf_data[CNF_ORG], DEFAULT_CONFIG);
5277     conf_init_str(&conf_data[CNF_CONF], DEFAULT_CONFIG);
5278     conf_init_str(&conf_data[CNF_AMDUMP_SERVER], DEFAULT_SERVER);
5279     conf_init_str(&conf_data[CNF_INDEX_SERVER], DEFAULT_SERVER);
5280     conf_init_str(&conf_data[CNF_TAPE_SERVER], DEFAULT_TAPE_SERVER);
5281     conf_init_str(&conf_data[CNF_AUTH], "bsdtcp");
5282     conf_init_str(&conf_data[CNF_SSH_KEYS], "");
5283     conf_init_str(&conf_data[CNF_AMANDAD_PATH], "");
5284     conf_init_str(&conf_data[CNF_CLIENT_USERNAME], "");
5285     conf_init_str(&conf_data[CNF_CLIENT_PORT], "");
5286     conf_init_str(&conf_data[CNF_GNUTAR_LIST_DIR], GNUTAR_LISTED_INCREMENTAL_DIR);
5287     conf_init_str(&conf_data[CNF_AMANDATES], DEFAULT_AMANDATES_FILE);
5288     conf_init_str(&conf_data[CNF_MAILTO], "");
5289     conf_init_str(&conf_data[CNF_DUMPUSER], CLIENT_LOGIN);
5290     conf_init_str(&conf_data[CNF_TAPEDEV], DEFAULT_TAPE_DEVICE);
5291     conf_init_proplist(&conf_data[CNF_DEVICE_PROPERTY]);
5292     conf_init_proplist(&conf_data[CNF_PROPERTY]);
5293     conf_init_str(&conf_data[CNF_CHANGERDEV], NULL);
5294     conf_init_str(&conf_data[CNF_CHANGERFILE]             , "changer");
5295     conf_init_str   (&conf_data[CNF_LABELSTR]             , ".*");
5296     conf_init_str   (&conf_data[CNF_TAPELIST]             , "tapelist");
5297     conf_init_str   (&conf_data[CNF_DISKFILE]             , "disklist");
5298     conf_init_str   (&conf_data[CNF_INFOFILE]             , "/usr/adm/amanda/curinfo");
5299     conf_init_str   (&conf_data[CNF_LOGDIR]               , "/usr/adm/amanda");
5300     conf_init_str   (&conf_data[CNF_INDEXDIR]             , "/usr/adm/amanda/index");
5301     conf_init_ident    (&conf_data[CNF_TAPETYPE]             , "DEFAULT_TAPE");
5302     conf_init_identlist(&conf_data[CNF_HOLDINGDISK]          , NULL);
5303     conf_init_int      (&conf_data[CNF_DUMPCYCLE]            , CONF_UNIT_NONE, 10);
5304     conf_init_int      (&conf_data[CNF_RUNSPERCYCLE]         , CONF_UNIT_NONE, 0);
5305     conf_init_int      (&conf_data[CNF_TAPECYCLE]            , CONF_UNIT_NONE, 15);
5306     conf_init_int      (&conf_data[CNF_NETUSAGE]             , CONF_UNIT_K   , 80000);
5307     conf_init_int      (&conf_data[CNF_INPARALLEL]           , CONF_UNIT_NONE, 10);
5308     conf_init_str   (&conf_data[CNF_DUMPORDER]            , "ttt");
5309     conf_init_int      (&conf_data[CNF_BUMPPERCENT]          , CONF_UNIT_NONE, 0);
5310     conf_init_int64    (&conf_data[CNF_BUMPSIZE]             , CONF_UNIT_K   , (gint64)10*1024);
5311     conf_init_real     (&conf_data[CNF_BUMPMULT]             , 1.5);
5312     conf_init_int      (&conf_data[CNF_BUMPDAYS]             , CONF_UNIT_NONE, 2);
5313     conf_init_str   (&conf_data[CNF_TPCHANGER]            , "");
5314     conf_init_int      (&conf_data[CNF_RUNTAPES]             , CONF_UNIT_NONE, 1);
5315     conf_init_int      (&conf_data[CNF_MAXDUMPS]             , CONF_UNIT_NONE, 1);
5316     conf_init_int      (&conf_data[CNF_MAX_DLE_BY_VOLUME]    , CONF_UNIT_NONE, 1000000000);
5317     conf_init_int      (&conf_data[CNF_ETIMEOUT]             , CONF_UNIT_NONE, 300);
5318     conf_init_int      (&conf_data[CNF_DTIMEOUT]             , CONF_UNIT_NONE, 1800);
5319     conf_init_int      (&conf_data[CNF_CTIMEOUT]             , CONF_UNIT_NONE, 30);
5320     conf_init_size     (&conf_data[CNF_DEVICE_OUTPUT_BUFFER_SIZE], CONF_UNIT_NONE, 40*32768);
5321     conf_init_str   (&conf_data[CNF_PRINTER]              , "");
5322     conf_init_str   (&conf_data[CNF_MAILER]               , DEFAULT_MAILER);
5323     conf_init_no_yes_all(&conf_data[CNF_AUTOFLUSH]            , 0);
5324     conf_init_int      (&conf_data[CNF_RESERVE]              , CONF_UNIT_NONE, 100);
5325     conf_init_int64    (&conf_data[CNF_MAXDUMPSIZE]          , CONF_UNIT_K   , (gint64)-1);
5326     conf_init_str   (&conf_data[CNF_COLUMNSPEC]           , "");
5327     conf_init_bool     (&conf_data[CNF_AMRECOVER_DO_FSF]     , 1);
5328     conf_init_str   (&conf_data[CNF_AMRECOVER_CHANGER]    , "");
5329     conf_init_bool     (&conf_data[CNF_AMRECOVER_CHECK_LABEL], 1);
5330     conf_init_taperalgo(&conf_data[CNF_TAPERALGO]            , 0);
5331     conf_init_int      (&conf_data[CNF_TAPER_PARALLEL_WRITE]     , CONF_UNIT_NONE, 1);
5332     conf_init_int      (&conf_data[CNF_FLUSH_THRESHOLD_DUMPED]   , CONF_UNIT_NONE, 0);
5333     conf_init_int      (&conf_data[CNF_FLUSH_THRESHOLD_SCHEDULED], CONF_UNIT_NONE, 0);
5334     conf_init_int      (&conf_data[CNF_TAPERFLUSH]               , CONF_UNIT_NONE, 0);
5335     conf_init_str   (&conf_data[CNF_DISPLAYUNIT]          , "k");
5336     conf_init_str   (&conf_data[CNF_KRB5KEYTAB]           , "/.amanda-v5-keytab");
5337     conf_init_str   (&conf_data[CNF_KRB5PRINCIPAL]        , "service/amanda");
5338     conf_init_str   (&conf_data[CNF_LABEL_NEW_TAPES]      , "");
5339     conf_init_bool     (&conf_data[CNF_EJECT_VOLUME]         , 0);
5340     conf_init_bool     (&conf_data[CNF_REPORT_USE_MEDIA]     , TRUE);
5341     conf_init_bool     (&conf_data[CNF_REPORT_NEXT_MEDIA]    , TRUE);
5342     conf_init_str_list (&conf_data[CNF_REPORT_FORMAT]        , NULL);
5343     conf_init_str      (&conf_data[CNF_TMPDIR]               , "");
5344     conf_init_bool     (&conf_data[CNF_USETIMESTAMPS]        , 1);
5345     conf_init_int      (&conf_data[CNF_CONNECT_TRIES]        , CONF_UNIT_NONE, 3);
5346     conf_init_int      (&conf_data[CNF_REP_TRIES]            , CONF_UNIT_NONE, 5);
5347     conf_init_int      (&conf_data[CNF_REQ_TRIES]            , CONF_UNIT_NONE, 3);
5348     conf_init_int      (&conf_data[CNF_DEBUG_DAYS]           , CONF_UNIT_NONE, AMANDA_DEBUG_DAYS);
5349     conf_init_int      (&conf_data[CNF_DEBUG_AMANDAD]        , CONF_UNIT_NONE, 0);
5350     conf_init_int      (&conf_data[CNF_DEBUG_RECOVERY]       , CONF_UNIT_NONE, 1);
5351     conf_init_int      (&conf_data[CNF_DEBUG_AMIDXTAPED]     , CONF_UNIT_NONE, 0);
5352     conf_init_int      (&conf_data[CNF_DEBUG_AMINDEXD]       , CONF_UNIT_NONE, 0);
5353     conf_init_int      (&conf_data[CNF_DEBUG_AMRECOVER]      , CONF_UNIT_NONE, 0);
5354     conf_init_int      (&conf_data[CNF_DEBUG_AUTH]           , CONF_UNIT_NONE, 0);
5355     conf_init_int      (&conf_data[CNF_DEBUG_EVENT]          , CONF_UNIT_NONE, 0);
5356     conf_init_int      (&conf_data[CNF_DEBUG_HOLDING]        , CONF_UNIT_NONE, 0);
5357     conf_init_int      (&conf_data[CNF_DEBUG_PROTOCOL]       , CONF_UNIT_NONE, 0);
5358     conf_init_int      (&conf_data[CNF_DEBUG_PLANNER]        , CONF_UNIT_NONE, 0);
5359     conf_init_int      (&conf_data[CNF_DEBUG_DRIVER]         , CONF_UNIT_NONE, 0);
5360     conf_init_int      (&conf_data[CNF_DEBUG_DUMPER]         , CONF_UNIT_NONE, 0);
5361     conf_init_int      (&conf_data[CNF_DEBUG_CHUNKER]        , CONF_UNIT_NONE, 0);
5362     conf_init_int      (&conf_data[CNF_DEBUG_TAPER]          , CONF_UNIT_NONE, 0);
5363     conf_init_int      (&conf_data[CNF_DEBUG_SELFCHECK]      , CONF_UNIT_NONE, 0);
5364     conf_init_int      (&conf_data[CNF_DEBUG_SENDSIZE]       , CONF_UNIT_NONE, 0);
5365     conf_init_int      (&conf_data[CNF_DEBUG_SENDBACKUP]     , CONF_UNIT_NONE, 0);
5366 #ifdef UDPPORTRANGE
5367     conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT]    , UDPPORTRANGE);
5368 #else
5369     conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT]    , 512, IPPORT_RESERVED-1);
5370 #endif
5371 #ifdef LOW_TCPPORTRANGE
5372     conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT]    , LOW_TCPPORTRANGE);
5373 #else
5374     conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT]    , 512, IPPORT_RESERVED-1);
5375 #endif
5376 #ifdef TCPPORTRANGE
5377     conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT]  , TCPPORTRANGE);
5378 #else
5379     conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT]  , IPPORT_RESERVED, 65535);
5380 #endif
5381     conf_init_send_amreport (&conf_data[CNF_SEND_AMREPORT_ON], SEND_AMREPORT_ALL);
5382     conf_init_autolabel(&conf_data[CNF_AUTOLABEL]);
5383     conf_init_str(&conf_data[CNF_META_AUTOLABEL], NULL);
5384     conf_init_host_limit(&conf_data[CNF_RECOVERY_LIMIT]);
5385     conf_init_str(&conf_data[CNF_INTERACTIVITY], NULL);
5386     conf_init_str(&conf_data[CNF_TAPERSCAN], NULL);
5387 
5388     /* reset internal variables */
5389     config_clear_errors();
5390     cfgerr_level = CFGERR_OK;
5391     allow_overwrites = 0;
5392     token_pushed = 0;
5393 
5394     /* create some predefined dumptypes for backwards compatability */
5395     init_dumptype_defaults();
5396     dpcur.name = stralloc("NO-COMPRESS");
5397     dpcur.seen.linenum = -1;
5398     free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
5399     val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_NONE;
5400     val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
5401     save_dumptype();
5402 
5403     init_dumptype_defaults();
5404     dpcur.name = stralloc("COMPRESS-FAST");
5405     dpcur.seen.linenum = -1;
5406     free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
5407     val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_FAST;
5408     val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
5409     save_dumptype();
5410 
5411     init_dumptype_defaults();
5412     dpcur.name = stralloc("COMPRESS-BEST");
5413     dpcur.seen.linenum = -1;
5414     free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
5415     val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_BEST;
5416     val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
5417     save_dumptype();
5418 
5419     init_dumptype_defaults();
5420     dpcur.name = stralloc("COMPRESS-CUST");
5421     dpcur.seen.linenum = -1;
5422     free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
5423     val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_CUST;
5424     val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
5425     save_dumptype();
5426 
5427     init_dumptype_defaults();
5428     dpcur.name = stralloc("SRVCOMPRESS");
5429     dpcur.seen.linenum = -1;
5430     free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]);
5431     val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_SERVER_FAST;
5432     val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]).linenum = -1;
5433     save_dumptype();
5434 
5435     init_dumptype_defaults();
5436     dpcur.name = stralloc("BSD-AUTH");
5437     dpcur.seen.linenum = -1;
5438     free_val_t(&dpcur.value[DUMPTYPE_AUTH]);
5439     val_t__str(&dpcur.value[DUMPTYPE_AUTH]) = stralloc("BSD");
5440     val_t__seen(&dpcur.value[DUMPTYPE_AUTH]).linenum = -1;
5441     save_dumptype();
5442 
5443     init_dumptype_defaults();
5444     dpcur.name = stralloc("BSDTCP-AUTH");
5445     dpcur.seen.linenum = -1;
5446     free_val_t(&dpcur.value[DUMPTYPE_AUTH]);
5447     val_t__str(&dpcur.value[DUMPTYPE_AUTH]) = stralloc("BSDTCP");
5448     val_t__seen(&dpcur.value[DUMPTYPE_AUTH]).linenum = -1;
5449     save_dumptype();
5450 
5451     init_dumptype_defaults();
5452     dpcur.name = stralloc("NO-RECORD");
5453     dpcur.seen.linenum = -1;
5454     free_val_t(&dpcur.value[DUMPTYPE_RECORD]);
5455     val_t__int(&dpcur.value[DUMPTYPE_RECORD]) = 0;
5456     val_t__seen(&dpcur.value[DUMPTYPE_RECORD]).linenum = -1;
5457     save_dumptype();
5458 
5459     init_dumptype_defaults();
5460     dpcur.name = stralloc("NO-HOLD");
5461     dpcur.seen.linenum = -1;
5462     free_val_t(&dpcur.value[DUMPTYPE_HOLDINGDISK]);
5463     val_t__holding(&dpcur.value[DUMPTYPE_HOLDINGDISK]) = HOLD_NEVER;
5464     val_t__seen(&dpcur.value[DUMPTYPE_HOLDINGDISK]).linenum = -1;
5465     save_dumptype();
5466 
5467     init_dumptype_defaults();
5468     dpcur.name = stralloc("NO-FULL");
5469     dpcur.seen.linenum = -1;
5470     free_val_t(&dpcur.value[DUMPTYPE_STRATEGY]);
5471     val_t__strategy(&dpcur.value[DUMPTYPE_STRATEGY]) = DS_NOFULL;
5472     val_t__seen(&dpcur.value[DUMPTYPE_STRATEGY]).linenum = -1;
5473     save_dumptype();
5474 
5475     /* And we're initialized! */
5476     config_initialized = 1;
5477 }
5478 
5479 char **
get_config_options(int first)5480 get_config_options(
5481     int first)
5482 {
5483     char             **config_options;
5484     char	     **config_option;
5485     int		     n_config_overrides = 0;
5486     int		     i;
5487 
5488     if (config_overrides)
5489 	n_config_overrides = config_overrides->n_used;
5490 
5491     config_options = alloc((first+n_config_overrides+1)*SIZEOF(char *));
5492     config_option = config_options + first;
5493 
5494     for (i = 0; i < n_config_overrides; i++) {
5495 	char *key = config_overrides->ovr[i].key;
5496 	char *value = config_overrides->ovr[i].value;
5497 	*config_option = vstralloc("-o", key, "=", value, NULL);
5498 	config_option++;
5499     }
5500 
5501     *config_option = NULL; /* add terminating sentinel */
5502 
5503     return config_options;
5504 }
5505 
5506 static void
update_derived_values(gboolean is_client)5507 update_derived_values(
5508     gboolean is_client)
5509 {
5510     interface_t   *ip;
5511     identlist_t    il;
5512     holdingdisk_t *hd;
5513 
5514     if (!is_client) {
5515 	/* Add a 'default' interface if one doesn't already exist */
5516 	if (!(ip = lookup_interface("default"))) {
5517 	    init_interface_defaults();
5518 	    ifcur.name = stralloc("default");
5519 	    ifcur.seen = val_t__seen(getconf(CNF_NETUSAGE));
5520 	    save_interface();
5521 
5522 	    ip = lookup_interface("default");
5523 	}
5524 
5525 	/* .. and set its maxusage from 'netusage' */
5526 	if (!interface_seen(ip, INTER_MAXUSAGE)) {
5527 	    val_t *v;
5528 
5529 	    v = interface_getconf(ip, INTER_COMMENT);
5530 	    free_val_t(v);
5531 	    val_t__str(v) = stralloc(_("implicit from NETUSAGE"));
5532 	    val_t__seen(v) = val_t__seen(getconf(CNF_NETUSAGE));
5533 
5534 	    v = interface_getconf(ip, INTER_MAXUSAGE);
5535 	    free_val_t(v);
5536 	    val_t__int(v) = getconf_int(CNF_NETUSAGE);
5537 	    val_t__seen(v) = val_t__seen(getconf(CNF_NETUSAGE));
5538 	}
5539 
5540 	/* Check the tapetype is defined */
5541 	if (lookup_tapetype(getconf_str(CNF_TAPETYPE)) == NULL) {
5542 	    /* Create a default tapetype so that other code has
5543 	     * something to refer to, but don't pretend it's real */
5544 	    if (!getconf_seen(CNF_TAPETYPE) &&
5545 		strcmp(getconf_str(CNF_TAPETYPE), "DEFAULT_TAPE") == 0 &&
5546 		!lookup_tapetype("DEFAULT_TAPE")) {
5547 		init_tapetype_defaults();
5548 		tpcur.name = stralloc("DEFAULT_TAPE");
5549 		tpcur.seen = val_t__seen(getconf(CNF_TAPETYPE));
5550 		save_tapetype();
5551 	    } else {
5552 		conf_parserror(_("tapetype %s is not defined"),
5553 			       getconf_str(CNF_TAPETYPE));
5554 	    }
5555 	}
5556 
5557 	/* Check the holdingdisk are defined */
5558 	for (il = getconf_identlist(CNF_HOLDINGDISK);
5559 		 il != NULL; il = il->next) {
5560 	    hd = lookup_holdingdisk(il->data);
5561 	    if (!hd) {
5562 		conf_parserror(_("holdingdisk %s is not defined"),
5563 			       (char *)il->data);
5564 	    }
5565 	}
5566 
5567 	if ((getconf_seen(CNF_LABEL_NEW_TAPES) > 0 &&
5568 	     getconf_seen(CNF_AUTOLABEL) > 0)  ||
5569 	    (getconf_seen(CNF_LABEL_NEW_TAPES) < 0 &&
5570 	     getconf_seen(CNF_AUTOLABEL) < 0)) {
5571 		conf_parserror(_("Can't specify both label-new-tapes and autolabel"));
5572 	}
5573 	if ((getconf_seen(CNF_LABEL_NEW_TAPES) != 0 &&
5574 	     getconf_seen(CNF_AUTOLABEL) == 0) ||
5575 	    (getconf_seen(CNF_LABEL_NEW_TAPES) < 0 &&
5576 	     getconf_seen(CNF_AUTOLABEL) >= 0)) {
5577 	    autolabel_t *autolabel = &(conf_data[CNF_AUTOLABEL].v.autolabel);
5578 	    autolabel->template = g_strdup(getconf_str(CNF_LABEL_NEW_TAPES));
5579 	    if (!autolabel->template || autolabel->template == '\0') {
5580 		autolabel->template = NULL;
5581 		autolabel->autolabel = 0;
5582 	    } else {
5583 		autolabel->autolabel = AL_VOLUME_ERROR | AL_EMPTY;
5584 	    }
5585 	}
5586 
5587 	if (!getconf_seen(CNF_REPORT_USE_MEDIA) &&
5588 	    getconf_seen(CNF_MAX_DLE_BY_VOLUME)) {
5589 	    conf_init_bool(&conf_data[CNF_REPORT_USE_MEDIA], FALSE);
5590 	}
5591 	if (!getconf_seen(CNF_REPORT_NEXT_MEDIA) &&
5592 	    getconf_seen(CNF_MAX_DLE_BY_VOLUME)) {
5593 	    conf_init_bool(&conf_data[CNF_REPORT_NEXT_MEDIA], FALSE);
5594 	}
5595     }
5596 
5597     /* fill in the debug_* values */
5598     debug_amandad    = getconf_int(CNF_DEBUG_AMANDAD);
5599     debug_recovery   = getconf_int(CNF_DEBUG_RECOVERY);
5600     debug_amidxtaped = getconf_int(CNF_DEBUG_AMIDXTAPED);
5601     debug_amindexd   = getconf_int(CNF_DEBUG_AMINDEXD);
5602     debug_amrecover  = getconf_int(CNF_DEBUG_AMRECOVER);
5603     debug_auth       = getconf_int(CNF_DEBUG_AUTH);
5604     debug_event      = getconf_int(CNF_DEBUG_EVENT);
5605     debug_holding    = getconf_int(CNF_DEBUG_HOLDING);
5606     debug_protocol   = getconf_int(CNF_DEBUG_PROTOCOL);
5607     debug_planner    = getconf_int(CNF_DEBUG_PLANNER);
5608     debug_driver     = getconf_int(CNF_DEBUG_DRIVER);
5609     debug_dumper     = getconf_int(CNF_DEBUG_DUMPER);
5610     debug_chunker    = getconf_int(CNF_DEBUG_CHUNKER);
5611     debug_taper      = getconf_int(CNF_DEBUG_TAPER);
5612     debug_selfcheck  = getconf_int(CNF_DEBUG_SELFCHECK);
5613     debug_sendsize   = getconf_int(CNF_DEBUG_SENDSIZE);
5614     debug_sendbackup = getconf_int(CNF_DEBUG_SENDBACKUP);
5615 
5616     /* And finally, display unit */
5617     switch (getconf_str(CNF_DISPLAYUNIT)[0]) {
5618 	case 'k':
5619 	case 'K':
5620 	    unit_divisor = 1;
5621 	    break;
5622 
5623 	case 'm':
5624 	case 'M':
5625 	    unit_divisor = 1024;
5626 	    break;
5627 
5628 	case 'g':
5629 	case 'G':
5630 	    unit_divisor = 1024*1024;
5631 	    break;
5632 
5633 	case 't':
5634 	case 'T':
5635 	    unit_divisor = 1024*1024*1024;
5636 	    break;
5637 
5638 	default:
5639 	    error(_("Invalid displayunit missed by validate_displayunit"));
5640 	    /* NOTREACHED */
5641     }
5642 }
5643 
5644 static void
conf_init_int(val_t * val,confunit_t unit,int i)5645 conf_init_int(
5646     val_t *val,
5647     confunit_t unit,
5648     int    i)
5649 {
5650     val->seen.linenum = 0;
5651     val->seen.filename = NULL;
5652     val->seen.block = NULL;
5653     val->type = CONFTYPE_INT;
5654     val->unit = unit;
5655     val_t__int(val) = i;
5656 }
5657 
5658 static void
conf_init_int64(val_t * val,confunit_t unit,gint64 l)5659 conf_init_int64(
5660     val_t *val,
5661     confunit_t unit,
5662     gint64   l)
5663 {
5664     val->seen.linenum = 0;
5665     val->seen.filename = NULL;
5666     val->seen.block = NULL;
5667     val->type = CONFTYPE_INT64;
5668     val->unit = unit;
5669     val_t__int64(val) = l;
5670 }
5671 
5672 static void
conf_init_real(val_t * val,float r)5673 conf_init_real(
5674     val_t  *val,
5675     float r)
5676 {
5677     val->seen.linenum = 0;
5678     val->seen.filename = NULL;
5679     val->seen.block = NULL;
5680     val->type = CONFTYPE_REAL;
5681     val->unit = CONF_UNIT_NONE;
5682     val_t__real(val) = r;
5683 }
5684 
5685 static void
conf_init_str(val_t * val,char * s)5686 conf_init_str(
5687     val_t *val,
5688     char  *s)
5689 {
5690     val->seen.linenum = 0;
5691     val->seen.filename = NULL;
5692     val->seen.block = NULL;
5693     val->type = CONFTYPE_STR;
5694     val->unit = CONF_UNIT_NONE;
5695     if(s)
5696 	val->v.s = stralloc(s);
5697     else
5698 	val->v.s = NULL;
5699 }
5700 
5701 static void
conf_init_ident(val_t * val,char * s)5702 conf_init_ident(
5703     val_t *val,
5704     char  *s)
5705 {
5706     val->seen.linenum = 0;
5707     val->seen.filename = NULL;
5708     val->seen.block = NULL;
5709     val->type = CONFTYPE_IDENT;
5710     val->unit = CONF_UNIT_NONE;
5711     if(s)
5712 	val->v.s = stralloc(s);
5713     else
5714 	val->v.s = NULL;
5715 }
5716 
5717 static void
conf_init_identlist(val_t * val,char * s)5718 conf_init_identlist(
5719     val_t *val,
5720     char  *s)
5721 {
5722     val->seen.linenum = 0;
5723     val->seen.filename = NULL;
5724     val->seen.block = NULL;
5725     val->type = CONFTYPE_IDENTLIST;
5726     val->unit = CONF_UNIT_NONE;
5727     val->v.identlist = NULL;
5728     if (s)
5729 	val->v.identlist = g_slist_append(val->v.identlist, stralloc(s));
5730 }
5731 
5732 static void
conf_init_str_list(val_t * val,char * s)5733 conf_init_str_list(
5734     val_t *val,
5735     char  *s)
5736 {
5737     val->seen.linenum = 0;
5738     val->seen.filename = NULL;
5739     val->seen.block = NULL;
5740     val->type = CONFTYPE_STR_LIST;
5741     val->unit = CONF_UNIT_NONE;
5742     val->v.identlist = NULL;
5743     if (s)
5744 	val->v.identlist = g_slist_append(val->v.identlist, g_strdup(s));
5745 }
5746 
5747 static void
conf_init_time(val_t * val,time_t t)5748 conf_init_time(
5749     val_t *val,
5750     time_t   t)
5751 {
5752     val->seen.linenum = 0;
5753     val->seen.filename = NULL;
5754     val->seen.block = NULL;
5755     val->type = CONFTYPE_TIME;
5756     val->unit = CONF_UNIT_NONE;
5757     val_t__time(val) = t;
5758 }
5759 
5760 static void
conf_init_size(val_t * val,confunit_t unit,ssize_t sz)5761 conf_init_size(
5762     val_t *val,
5763     confunit_t unit,
5764     ssize_t   sz)
5765 {
5766     val->seen.linenum = 0;
5767     val->seen.filename = NULL;
5768     val->seen.block = NULL;
5769     val->type = CONFTYPE_SIZE;
5770     val->unit = unit;
5771     val_t__size(val) = sz;
5772 }
5773 
5774 static void
conf_init_bool(val_t * val,int i)5775 conf_init_bool(
5776     val_t *val,
5777     int    i)
5778 {
5779     val->seen.linenum = 0;
5780     val->seen.filename = NULL;
5781     val->seen.block = NULL;
5782     val->type = CONFTYPE_BOOLEAN;
5783     val->unit = CONF_UNIT_NONE;
5784     val_t__boolean(val) = i;
5785 }
5786 
5787 static void
conf_init_no_yes_all(val_t * val,int i)5788 conf_init_no_yes_all(
5789     val_t *val,
5790     int    i)
5791 {
5792     val->seen.linenum = 0;
5793     val->seen.filename = NULL;
5794     val->seen.block = NULL;
5795     val->type = CONFTYPE_NO_YES_ALL;
5796     val->unit = CONF_UNIT_NONE;
5797     val_t__int(val) = i;
5798 }
5799 
5800 static void
conf_init_compress(val_t * val,comp_t i)5801 conf_init_compress(
5802     val_t *val,
5803     comp_t    i)
5804 {
5805     val->seen.linenum = 0;
5806     val->seen.filename = NULL;
5807     val->seen.block = NULL;
5808     val->type = CONFTYPE_COMPRESS;
5809     val->unit = CONF_UNIT_NONE;
5810     val_t__compress(val) = (int)i;
5811 }
5812 
5813 static void
conf_init_encrypt(val_t * val,encrypt_t i)5814 conf_init_encrypt(
5815     val_t *val,
5816     encrypt_t    i)
5817 {
5818     val->seen.linenum = 0;
5819     val->seen.filename = NULL;
5820     val->seen.block = NULL;
5821     val->type = CONFTYPE_ENCRYPT;
5822     val->unit = CONF_UNIT_NONE;
5823     val_t__encrypt(val) = (int)i;
5824 }
5825 
5826 static void
conf_init_part_cache_type(val_t * val,part_cache_type_t i)5827 conf_init_part_cache_type(
5828     val_t *val,
5829     part_cache_type_t    i)
5830 {
5831     val->seen.linenum = 0;
5832     val->seen.filename = NULL;
5833     val->seen.block = NULL;
5834     val->type = CONFTYPE_PART_CACHE_TYPE;
5835     val->unit = CONF_UNIT_NONE;
5836     val_t__part_cache_type(val) = (int)i;
5837 }
5838 
5839 static void
conf_init_host_limit(val_t * val)5840 conf_init_host_limit(
5841     val_t *val)
5842 {
5843     val->seen.linenum = 0;
5844     val->seen.filename = NULL;
5845     val->seen.block = NULL;
5846     val->type = CONFTYPE_HOST_LIMIT;
5847     val->unit = CONF_UNIT_NONE;
5848     val_t__host_limit(val).match_pats = NULL;
5849     val_t__host_limit(val).same_host  = FALSE;
5850     val_t__host_limit(val).server     = FALSE;
5851 }
5852 
5853 static void
conf_init_host_limit_server(val_t * val)5854 conf_init_host_limit_server(
5855     val_t *val)
5856 {
5857     conf_init_host_limit(val);
5858     val_t__host_limit(val).server = TRUE;
5859 }
5860 
5861 static void
conf_init_data_path(val_t * val,data_path_t i)5862 conf_init_data_path(
5863     val_t *val,
5864     data_path_t    i)
5865 {
5866     val->seen.linenum = 0;
5867     val->seen.filename = NULL;
5868     val->seen.block = NULL;
5869     val->type = CONFTYPE_DATA_PATH;
5870     val->unit = CONF_UNIT_NONE;
5871     val_t__data_path(val) = (int)i;
5872 }
5873 
5874 static void
conf_init_holding(val_t * val,dump_holdingdisk_t i)5875 conf_init_holding(
5876     val_t              *val,
5877     dump_holdingdisk_t  i)
5878 {
5879     val->seen.linenum = 0;
5880     val->seen.filename = NULL;
5881     val->seen.block = NULL;
5882     val->type = CONFTYPE_HOLDING;
5883     val->unit = CONF_UNIT_NONE;
5884     val_t__holding(val) = (int)i;
5885 }
5886 
5887 static void
conf_init_estimatelist(val_t * val,estimate_t i)5888 conf_init_estimatelist(
5889     val_t *val,
5890     estimate_t    i)
5891 {
5892     GSList *estimates = NULL;
5893     val->seen.linenum = 0;
5894     val->seen.filename = NULL;
5895     val->seen.block = NULL;
5896     val->type = CONFTYPE_ESTIMATELIST;
5897     val->unit = CONF_UNIT_NONE;
5898     estimates = g_slist_append(estimates, GINT_TO_POINTER(i));
5899     val_t__estimatelist(val) = estimates;
5900 }
5901 
5902 static void
conf_init_strategy(val_t * val,strategy_t i)5903 conf_init_strategy(
5904     val_t *val,
5905     strategy_t    i)
5906 {
5907     val->seen.linenum = 0;
5908     val->seen.filename = NULL;
5909     val->seen.block = NULL;
5910     val->unit = CONF_UNIT_NONE;
5911     val->type = CONFTYPE_STRATEGY;
5912     val_t__strategy(val) = i;
5913 }
5914 
5915 static void
conf_init_taperalgo(val_t * val,taperalgo_t i)5916 conf_init_taperalgo(
5917     val_t *val,
5918     taperalgo_t    i)
5919 {
5920     val->seen.linenum = 0;
5921     val->seen.filename = NULL;
5922     val->seen.block = NULL;
5923     val->type = CONFTYPE_TAPERALGO;
5924     val->unit = CONF_UNIT_NONE;
5925     val_t__taperalgo(val) = i;
5926 }
5927 
5928 static void
conf_init_priority(val_t * val,int i)5929 conf_init_priority(
5930     val_t *val,
5931     int    i)
5932 {
5933     val->seen.linenum = 0;
5934     val->seen.filename = NULL;
5935     val->seen.block = NULL;
5936     val->type = CONFTYPE_PRIORITY;
5937     val->unit = CONF_UNIT_NONE;
5938     val_t__priority(val) = i;
5939 }
5940 
5941 static void
conf_init_rate(val_t * val,float r1,float r2)5942 conf_init_rate(
5943     val_t  *val,
5944     float r1,
5945     float r2)
5946 {
5947     val->seen.linenum = 0;
5948     val->seen.filename = NULL;
5949     val->seen.block = NULL;
5950     val->type = CONFTYPE_RATE;
5951     val->unit = CONF_UNIT_NONE;
5952     val_t__rate(val)[0] = r1;
5953     val_t__rate(val)[1] = r2;
5954 }
5955 
5956 static void
conf_init_exinclude(val_t * val)5957 conf_init_exinclude(
5958     val_t *val)
5959 {
5960     val->seen.linenum = 0;
5961     val->seen.filename = NULL;
5962     val->seen.block = NULL;
5963     val->type = CONFTYPE_EXINCLUDE;
5964     val->unit = CONF_UNIT_NONE;
5965     val_t__exinclude(val).optional = 0;
5966     val_t__exinclude(val).sl_list = NULL;
5967     val_t__exinclude(val).sl_file = NULL;
5968 }
5969 
5970 static void
conf_init_intrange(val_t * val,int i1,int i2)5971 conf_init_intrange(
5972     val_t *val,
5973     int    i1,
5974     int    i2)
5975 {
5976     val->seen.linenum = 0;
5977     val->seen.filename = NULL;
5978     val->seen.block = NULL;
5979     val->type = CONFTYPE_INTRANGE;
5980     val->unit = CONF_UNIT_NONE;
5981     val_t__intrange(val)[0] = i1;
5982     val_t__intrange(val)[1] = i2;
5983 }
5984 
5985 static void
conf_init_autolabel(val_t * val)5986 conf_init_autolabel(
5987     val_t *val) {
5988     val->seen.linenum = 0;
5989     val->seen.filename = NULL;
5990     val->seen.block = NULL;
5991     val->type = CONFTYPE_AUTOLABEL;
5992     val->unit = CONF_UNIT_NONE;
5993     val->v.autolabel.template = NULL;
5994     val->v.autolabel.autolabel = 0;
5995 }
5996 
5997 void
free_property_t(gpointer p)5998 free_property_t(
5999     gpointer p)
6000 {
6001     property_t *propery = (property_t *)p;
6002     slist_free_full(propery->values, g_free);
6003     amfree(propery);
6004 }
6005 
6006 static void
conf_init_proplist(val_t * val)6007 conf_init_proplist(
6008     val_t *val)
6009 {
6010     val->seen.linenum = 0;
6011     val->seen.filename = NULL;
6012     val->seen.block = NULL;
6013     val->type = CONFTYPE_PROPLIST;
6014     val->unit = CONF_UNIT_NONE;
6015     val_t__proplist(val) =
6016         g_hash_table_new_full(g_str_amanda_hash, g_str_amanda_equal,
6017 			      &g_free, &free_property_t);
6018 }
6019 
6020 static void
conf_init_execute_on(val_t * val,int i)6021 conf_init_execute_on(
6022     val_t *val,
6023     int    i)
6024 {
6025     val->seen.linenum = 0;
6026     val->seen.filename = NULL;
6027     val->seen.block = NULL;
6028     val->type = CONFTYPE_EXECUTE_ON;
6029     val->unit = CONF_UNIT_NONE;
6030     val->v.i = i;
6031 }
6032 
6033 static void
conf_init_execute_where(val_t * val,int i)6034 conf_init_execute_where(
6035     val_t *val,
6036     int    i)
6037 {
6038     val->seen.linenum = 0;
6039     val->seen.filename = NULL;
6040     val->seen.block = NULL;
6041     val->type = CONFTYPE_EXECUTE_WHERE;
6042     val->unit = CONF_UNIT_NONE;
6043     val->v.i = i;
6044 }
6045 
6046 static void
conf_init_send_amreport(val_t * val,send_amreport_t i)6047 conf_init_send_amreport(
6048     val_t *val,
6049     send_amreport_t i)
6050 {
6051     val->seen.linenum = 0;
6052     val->seen.filename = NULL;
6053     val->seen.block = NULL;
6054     val->type = CONFTYPE_SEND_AMREPORT_ON;
6055     val->unit = CONF_UNIT_NONE;
6056     val->v.i = i;
6057 }
6058 
conf_init_application(val_t * val)6059 static void conf_init_application(val_t *val) {
6060     val->seen.linenum = 0;
6061     val->seen.filename = NULL;
6062     val->seen.block = NULL;
6063     val->type = CONFTYPE_APPLICATION;
6064     val->unit = CONF_UNIT_NONE;
6065     val->v.s = NULL;
6066 }
6067 
6068 
6069 /*
6070  * Config access implementation
6071  */
6072 
6073 val_t *
getconf(confparm_key key)6074 getconf(confparm_key key)
6075 {
6076     assert(key < CNF_CNF);
6077     return &conf_data[key];
6078 }
6079 
6080 GSList *
getconf_list(char * listname)6081 getconf_list(
6082     char *listname)
6083 {
6084     tapetype_t *tp;
6085     dumptype_t *dp;
6086     interface_t *ip;
6087     holdingdisk_t *hd;
6088     GSList        *hp;
6089     application_t *ap;
6090     pp_script_t   *pp;
6091     device_config_t *dc;
6092     changer_config_t *cc;
6093     interactivity_t  *iv;
6094     taperscan_t      *ts;
6095     GSList *rv = NULL;
6096 
6097     if (strcasecmp(listname,"tapetype") == 0) {
6098 	for(tp = tapelist; tp != NULL; tp=tp->next) {
6099 	    rv = g_slist_append(rv, tp->name);
6100 	}
6101     } else if (strcasecmp(listname,"dumptype") == 0) {
6102 	for(dp = dumplist; dp != NULL; dp=dp->next) {
6103 	    rv = g_slist_append(rv, dp->name);
6104 	}
6105     } else if (strcasecmp(listname,"holdingdisk") == 0) {
6106 	for(hp = holdinglist; hp != NULL; hp=hp->next) {
6107 	    hd = hp->data;
6108 	    rv = g_slist_append(rv, hd->name);
6109 	}
6110     } else if (strcasecmp(listname,"interface") == 0) {
6111 	for(ip = interface_list; ip != NULL; ip=ip->next) {
6112 	    rv = g_slist_append(rv, ip->name);
6113 	}
6114     } else if (strcasecmp(listname,"application_tool") == 0
6115 	    || strcasecmp(listname,"application-tool") == 0
6116 	    || strcasecmp(listname,"application") == 0) {
6117 	for(ap = application_list; ap != NULL; ap=ap->next) {
6118 	    rv = g_slist_append(rv, ap->name);
6119 	}
6120     } else if (strcasecmp(listname,"script_tool") == 0
6121 	    || strcasecmp(listname,"script-tool") == 0
6122 	    || strcasecmp(listname,"script") == 0) {
6123 	for(pp = pp_script_list; pp != NULL; pp=pp->next) {
6124 	    rv = g_slist_append(rv, pp->name);
6125 	}
6126     } else if (strcasecmp(listname,"device") == 0) {
6127 	for(dc = device_config_list; dc != NULL; dc=dc->next) {
6128 	    rv = g_slist_append(rv, dc->name);
6129 	}
6130     } else if (strcasecmp(listname,"changer") == 0) {
6131 	for(cc = changer_config_list; cc != NULL; cc=cc->next) {
6132 	    rv = g_slist_append(rv, cc->name);
6133 	}
6134     } else if (strcasecmp(listname,"interactivity") == 0) {
6135 	for(iv = interactivity_list; iv != NULL; iv=iv->next) {
6136 	    rv = g_slist_append(rv, iv->name);
6137 	}
6138     } else if (strcasecmp(listname,"taperscan") == 0) {
6139 	for(ts = taperscan_list; ts != NULL; ts=ts->next) {
6140 	    rv = g_slist_append(rv, ts->name);
6141 	}
6142     }
6143     return rv;
6144 }
6145 
6146 val_t *
getconf_byname(char * key)6147 getconf_byname(
6148     char *key)
6149 {
6150     val_t *rv = NULL;
6151 
6152     if (!parm_key_info(key, NULL, &rv))
6153 	return NULL;
6154 
6155     return rv;
6156 }
6157 
6158 tapetype_t *
lookup_tapetype(char * str)6159 lookup_tapetype(
6160     char *str)
6161 {
6162     tapetype_t *p;
6163 
6164     for(p = tapelist; p != NULL; p = p->next) {
6165 	if(strcasecmp(p->name, str) == 0) return p;
6166     }
6167     return NULL;
6168 }
6169 
6170 val_t *
tapetype_getconf(tapetype_t * ttyp,tapetype_key key)6171 tapetype_getconf(
6172     tapetype_t *ttyp,
6173     tapetype_key key)
6174 {
6175     assert(ttyp != NULL);
6176     assert(key < TAPETYPE_TAPETYPE);
6177     return &ttyp->value[key];
6178 }
6179 
6180 static void
validate_program(conf_var_t * np G_GNUC_UNUSED,val_t * val)6181 validate_program(
6182     conf_var_t *np G_GNUC_UNUSED,
6183     val_t        *val)
6184 {
6185     if (strcmp(val->v.s, "DUMP") != 0 &&
6186     	strcmp(val->v.s, "GNUTAR") != 0 &&
6187     	strcmp(val->v.s, "STAR") != 0 &&
6188     	strcmp(val->v.s, "APPLICATION") != 0)
6189        conf_parserror("program must be \"DUMP\", \"GNUTAR\", \"STAR\" or \"APPLICATION\"");
6190 }
6191 
6192 static void
validate_dump_limit(conf_var_t * np G_GNUC_UNUSED,val_t * val)6193 validate_dump_limit(
6194     conf_var_t *np G_GNUC_UNUSED,
6195     val_t        *val)
6196 {
6197     if (val->v.host_limit.match_pats) {
6198 	conf_parserror("dump-limit can't specify hostname");
6199     }
6200 }
6201 
6202 char *
tapetype_name(tapetype_t * ttyp)6203 tapetype_name(
6204     tapetype_t *ttyp)
6205 {
6206     assert(ttyp != NULL);
6207     return ttyp->name;
6208 }
6209 
6210 dumptype_t *
lookup_dumptype(char * str)6211 lookup_dumptype(
6212     char *str)
6213 {
6214     dumptype_t *p;
6215 
6216     for(p = dumplist; p != NULL; p = p->next) {
6217 	if(strcasecmp(p->name, str) == 0) return p;
6218     }
6219     return NULL;
6220 }
6221 
6222 val_t *
dumptype_getconf(dumptype_t * dtyp,dumptype_key key)6223 dumptype_getconf(
6224     dumptype_t *dtyp,
6225     dumptype_key key)
6226 {
6227     assert(dtyp != NULL);
6228     assert(key < DUMPTYPE_DUMPTYPE);
6229     return &dtyp->value[key];
6230 }
6231 
6232 char *
dumptype_name(dumptype_t * dtyp)6233 dumptype_name(
6234     dumptype_t *dtyp)
6235 {
6236     assert(dtyp != NULL);
6237     return dtyp->name;
6238 }
6239 
6240 interface_t *
lookup_interface(char * str)6241 lookup_interface(
6242     char *str)
6243 {
6244     interface_t *p;
6245 
6246     for(p = interface_list; p != NULL; p = p->next) {
6247 	if(strcasecmp(p->name, str) == 0) return p;
6248     }
6249     return NULL;
6250 }
6251 
6252 val_t *
interface_getconf(interface_t * iface,interface_key key)6253 interface_getconf(
6254     interface_t *iface,
6255     interface_key key)
6256 {
6257     assert(iface != NULL);
6258     assert(key < INTER_INTER);
6259     return &iface->value[key];
6260 }
6261 
6262 char *
interface_name(interface_t * iface)6263 interface_name(
6264     interface_t *iface)
6265 {
6266     assert(iface != NULL);
6267     return iface->name;
6268 }
6269 
6270 holdingdisk_t *
lookup_holdingdisk(char * str)6271 lookup_holdingdisk(
6272     char *str)
6273 {
6274     GSList        *hp;
6275     holdingdisk_t *hd;
6276 
6277     for (hp = holdinglist; hp != NULL; hp = hp->next) {
6278 	hd = hp->data;
6279 	if (strcasecmp(hd->name, str) == 0) return hd;
6280     }
6281     return NULL;
6282 }
6283 
6284 GSList *
getconf_holdingdisks(void)6285 getconf_holdingdisks(
6286     void)
6287 {
6288     return holdinglist;
6289 }
6290 
6291 val_t *
holdingdisk_getconf(holdingdisk_t * hdisk,holdingdisk_key key)6292 holdingdisk_getconf(
6293     holdingdisk_t *hdisk,
6294     holdingdisk_key key)
6295 {
6296     assert(hdisk != NULL);
6297     assert(key < HOLDING_HOLDING);
6298     return &hdisk->value[key];
6299 }
6300 
6301 char *
holdingdisk_name(holdingdisk_t * hdisk)6302 holdingdisk_name(
6303     holdingdisk_t *hdisk)
6304 {
6305     assert(hdisk != NULL);
6306     return hdisk->name;
6307 }
6308 
6309 application_t *
lookup_application(char * str)6310 lookup_application(
6311     char *str)
6312 {
6313     application_t *p;
6314 
6315     for(p = application_list; p != NULL; p = p->next) {
6316 	if(strcasecmp(p->name, str) == 0) return p;
6317     }
6318     return NULL;
6319 }
6320 
6321 val_t *
application_getconf(application_t * ap,application_key key)6322 application_getconf(
6323     application_t *ap,
6324     application_key key)
6325 {
6326     assert(ap != NULL);
6327     assert(key < APPLICATION_APPLICATION);
6328     return &ap->value[key];
6329 }
6330 
6331 char *
application_name(application_t * ap)6332 application_name(
6333     application_t *ap)
6334 {
6335     assert(ap != NULL);
6336     return ap->name;
6337 }
6338 
6339 interactivity_t *
lookup_interactivity(char * str)6340 lookup_interactivity(
6341     char *str)
6342 {
6343     interactivity_t *p;
6344 
6345     for(p = interactivity_list; p != NULL; p = p->next) {
6346 	if(strcasecmp(p->name, str) == 0) return p;
6347     }
6348     return NULL;
6349 }
6350 
6351 val_t *
interactivity_getconf(interactivity_t * iv,interactivity_key key)6352 interactivity_getconf(
6353     interactivity_t *iv,
6354     interactivity_key key)
6355 {
6356     assert(iv != NULL);
6357     assert(key < INTERACTIVITY_INTERACTIVITY);
6358     return &iv->value[key];
6359 }
6360 
6361 char *
interactivity_name(interactivity_t * iv)6362 interactivity_name(
6363     interactivity_t *iv)
6364 {
6365     assert(iv != NULL);
6366     return iv->name;
6367 }
6368 
6369 taperscan_t *
lookup_taperscan(char * str)6370 lookup_taperscan(
6371     char *str)
6372 {
6373     taperscan_t *p;
6374 
6375     for(p = taperscan_list; p != NULL; p = p->next) {
6376 	if(strcasecmp(p->name, str) == 0) return p;
6377     }
6378     return NULL;
6379 }
6380 
6381 val_t *
taperscan_getconf(taperscan_t * ts,taperscan_key key)6382 taperscan_getconf(
6383     taperscan_t *ts,
6384     taperscan_key key)
6385 {
6386     assert(ts != NULL);
6387     assert(key < TAPERSCAN_TAPERSCAN);
6388     return &ts->value[key];
6389 }
6390 
6391 char *
taperscan_name(taperscan_t * ts)6392 taperscan_name(
6393     taperscan_t *ts)
6394 {
6395     assert(ts != NULL);
6396     return ts->name;
6397 }
6398 
6399 pp_script_t *
lookup_pp_script(char * str)6400 lookup_pp_script(
6401     char *str)
6402 {
6403     pp_script_t *pps;
6404 
6405     for(pps = pp_script_list; pps != NULL; pps = pps->next) {
6406 	if(strcasecmp(pps->name, str) == 0) return pps;
6407     }
6408     return NULL;
6409 }
6410 
6411 val_t *
pp_script_getconf(pp_script_t * pps,pp_script_key key)6412 pp_script_getconf(
6413     pp_script_t *pps,
6414     pp_script_key key)
6415 {
6416     assert(pps != NULL);
6417     assert(key < PP_SCRIPT_PP_SCRIPT);
6418     return &pps->value[key];
6419 }
6420 
6421 char *
pp_script_name(pp_script_t * pps)6422 pp_script_name(
6423     pp_script_t *pps)
6424 {
6425     assert(pps != NULL);
6426     return pps->name;
6427 }
6428 
6429 device_config_t *
lookup_device_config(char * str)6430 lookup_device_config(
6431     char *str)
6432 {
6433     device_config_t *devconf;
6434 
6435     for(devconf = device_config_list; devconf != NULL; devconf = devconf->next) {
6436 	if(strcasecmp(devconf->name, str) == 0) return devconf;
6437     }
6438     return NULL;
6439 }
6440 
6441 val_t *
device_config_getconf(device_config_t * devconf,device_config_key key)6442 device_config_getconf(
6443     device_config_t *devconf,
6444     device_config_key key)
6445 {
6446     assert(devconf != NULL);
6447     assert(key < DEVICE_CONFIG_DEVICE_CONFIG);
6448     return &devconf->value[key];
6449 }
6450 
6451 char *
device_config_name(device_config_t * devconf)6452 device_config_name(
6453     device_config_t *devconf)
6454 {
6455     assert(devconf != NULL);
6456     return devconf->name;
6457 }
6458 
6459 changer_config_t *
lookup_changer_config(char * str)6460 lookup_changer_config(
6461     char *str)
6462 {
6463     changer_config_t *devconf;
6464 
6465     for(devconf = changer_config_list; devconf != NULL; devconf = devconf->next) {
6466 	if(strcasecmp(devconf->name, str) == 0) return devconf;
6467     }
6468     return NULL;
6469 }
6470 
6471 val_t *
changer_config_getconf(changer_config_t * devconf,changer_config_key key)6472 changer_config_getconf(
6473     changer_config_t *devconf,
6474     changer_config_key key)
6475 {
6476     assert(devconf != NULL);
6477     assert(key < CHANGER_CONFIG_CHANGER_CONFIG);
6478     return &devconf->value[key];
6479 }
6480 
6481 char *
changer_config_name(changer_config_t * devconf)6482 changer_config_name(
6483     changer_config_t *devconf)
6484 {
6485     assert(devconf != NULL);
6486     return devconf->name;
6487 }
6488 
6489 long int
getconf_unit_divisor(void)6490 getconf_unit_divisor(void)
6491 {
6492     return unit_divisor;
6493 }
6494 
6495 /*
6496  * Command-line Handling Implementation
6497  */
6498 
6499 config_overrides_t *
new_config_overrides(int size_estimate)6500 new_config_overrides(
6501     int size_estimate)
6502 {
6503     config_overrides_t *co;
6504 
6505     if (size_estimate <= 0)
6506 	size_estimate = 10;
6507 
6508     co = alloc(sizeof(*co));
6509     co->ovr = alloc(sizeof(*co->ovr) * size_estimate);
6510     co->n_allocated = size_estimate;
6511     co->n_used = 0;
6512 
6513     return co;
6514 }
6515 
6516 void
free_config_overrides(config_overrides_t * co)6517 free_config_overrides(
6518     config_overrides_t *co)
6519 {
6520     int i;
6521 
6522     if (!co) return;
6523     for (i = 0; i < co->n_used; i++) {
6524 	amfree(co->ovr[i].key);
6525 	amfree(co->ovr[i].value);
6526     }
6527     amfree(co->ovr);
6528     amfree(co);
6529 }
6530 
add_config_override(config_overrides_t * co,char * key,char * value)6531 void add_config_override(
6532     config_overrides_t *co,
6533     char *key,
6534     char *value)
6535 {
6536     /* reallocate if necessary */
6537     if (co->n_used == co->n_allocated) {
6538 	co->n_allocated *= 2;
6539 	co->ovr = realloc(co->ovr, co->n_allocated * sizeof(*co->ovr));
6540 	if (!co->ovr) {
6541 	    error(_("Cannot realloc; out of memory"));
6542 	    /* NOTREACHED */
6543 	}
6544     }
6545 
6546     co->ovr[co->n_used].key = stralloc(key);
6547     co->ovr[co->n_used].value = stralloc(value);
6548     co->n_used++;
6549 }
6550 
6551 void
add_config_override_opt(config_overrides_t * co,char * optarg)6552 add_config_override_opt(
6553     config_overrides_t *co,
6554     char *optarg)
6555 {
6556     char *value;
6557     assert(optarg != NULL);
6558 
6559     value = strchr(optarg, '=');
6560     if (value == NULL) {
6561 	error(_("Must specify a value for %s."), optarg);
6562 	/* NOTREACHED */
6563     }
6564 
6565     *value = '\0';
6566     add_config_override(co, optarg, value+1);
6567     *value = '=';
6568 }
6569 
6570 config_overrides_t *
extract_commandline_config_overrides(int * argc,char *** argv)6571 extract_commandline_config_overrides(
6572     int *argc,
6573     char ***argv)
6574 {
6575     int i, j, moveup;
6576     config_overrides_t *co = new_config_overrides(*argc/2);
6577 
6578     i = 0;
6579     while (i<*argc) {
6580 	if(strncmp((*argv)[i],"-o",2) == 0) {
6581 	    if(strlen((*argv)[i]) > 2) {
6582 		add_config_override_opt(co, (*argv)[i]+2);
6583 		moveup = 1;
6584 	    }
6585 	    else {
6586 		if (i+1 >= *argc) error(_("expect something after -o"));
6587 		add_config_override_opt(co, (*argv)[i+1]);
6588 		moveup = 2;
6589 	    }
6590 
6591 	    /* move up remaining argment array */
6592 	    for (j = i; j+moveup<*argc; j++) {
6593 		(*argv)[j] = (*argv)[j+moveup];
6594 	    }
6595 	    *argc -= moveup;
6596 	} else {
6597 	    i++;
6598 	}
6599     }
6600 
6601     return co;
6602 }
6603 
6604 void
set_config_overrides(config_overrides_t * co)6605 set_config_overrides(
6606     config_overrides_t *co)
6607 {
6608     int i;
6609 
6610     config_overrides = co;
6611 
6612     for (i = 0; i < co->n_used; i++) {
6613 	g_debug("config_overrides: %s %s", co->ovr[i].key, co->ovr[i].value);
6614     }
6615 
6616     return;
6617 }
6618 
6619 static cfgerr_level_t
apply_config_overrides(config_overrides_t * co,char * key_ovr)6620 apply_config_overrides(
6621     config_overrides_t *co,
6622     char *key_ovr)
6623 {
6624     int i;
6625 
6626     if(!co) return cfgerr_level;
6627     assert(keytable != NULL);
6628     assert(parsetable != NULL);
6629 
6630     for (i = 0; i < co->n_used; i++) {
6631 	char *key = co->ovr[i].key;
6632 	char *value = co->ovr[i].value;
6633 	val_t *key_val;
6634 	conf_var_t *key_parm;
6635 
6636 	if (key_ovr && strncasecmp(key_ovr, key, strlen(key_ovr)) != 0) {
6637 	    continue;
6638 	}
6639 
6640 	if (!parm_key_info(key, &key_parm, &key_val)) {
6641 	    /* not an error, only default config is loaded */
6642 	    continue;
6643 	}
6644 
6645 	/* now set up a fake line and use the relevant read_function to
6646 	 * parse it.  This is sneaky! */
6647 	if (key_parm->type == CONFTYPE_STR) {
6648 	    current_line = quote_string_always(value);
6649 	} else {
6650 	    current_line = stralloc(value);
6651 	}
6652 
6653 	current_char = current_line;
6654 	token_pushed = 0;
6655 	current_line_num = -2;
6656 	allow_overwrites = 1;
6657         co->ovr[i].applied = TRUE;
6658 
6659 	key_parm->read_function(key_parm, key_val);
6660 	if ((key_parm)->validate_function)
6661 	    key_parm->validate_function(key_parm, key_val);
6662 
6663 	amfree(current_line);
6664 	current_char = NULL;
6665 	token_pushed = 0;
6666     }
6667 
6668     return cfgerr_level;
6669 }
6670 
6671 /*
6672  * val_t Management Implementation
6673  */
6674 
6675 int
val_t_to_int(val_t * val)6676 val_t_to_int(
6677     val_t *val)
6678 {
6679     assert(config_initialized);
6680     if (val->type != CONFTYPE_INT) {
6681 	error(_("val_t_to_int: val.type is not CONFTYPE_INT"));
6682 	/*NOTREACHED*/
6683     }
6684     return val_t__int(val);
6685 }
6686 
6687 gint64
val_t_to_int64(val_t * val)6688 val_t_to_int64(
6689     val_t *val)
6690 {
6691     assert(config_initialized);
6692     if (val->type != CONFTYPE_INT64) {
6693 	error(_("val_t_to_int64: val.type is not CONFTYPE_INT64"));
6694 	/*NOTREACHED*/
6695     }
6696     return val_t__int64(val);
6697 }
6698 
6699 float
val_t_to_real(val_t * val)6700 val_t_to_real(
6701     val_t *val)
6702 {
6703     assert(config_initialized);
6704     if (val->type != CONFTYPE_REAL) {
6705 	error(_("val_t_to_real: val.type is not CONFTYPE_REAL"));
6706 	/*NOTREACHED*/
6707     }
6708     return val_t__real(val);
6709 }
6710 
6711 char *
val_t_to_str(val_t * val)6712 val_t_to_str(
6713     val_t *val)
6714 {
6715     assert(config_initialized);
6716     /* support CONFTYPE_IDENT, too */
6717     if (val->type != CONFTYPE_STR && val->type != CONFTYPE_IDENT) {
6718 	error(_("val_t_to_str: val.type is not CONFTYPE_STR nor CONFTYPE_IDENT"));
6719 	/*NOTREACHED*/
6720     }
6721     return val_t__str(val);
6722 }
6723 
6724 char *
val_t_to_ident(val_t * val)6725 val_t_to_ident(
6726     val_t *val)
6727 {
6728     assert(config_initialized);
6729     /* support CONFTYPE_STR, too */
6730     if (val->type != CONFTYPE_STR && val->type != CONFTYPE_IDENT) {
6731 	error(_("val_t_to_ident: val.type is not CONFTYPE_IDENT nor CONFTYPE_STR"));
6732 	/*NOTREACHED*/
6733     }
6734     return val_t__str(val);
6735 }
6736 
6737 identlist_t
val_t_to_identlist(val_t * val)6738 val_t_to_identlist(
6739     val_t *val)
6740 {
6741     assert(config_initialized);
6742     if (val->type != CONFTYPE_IDENTLIST) {
6743 	error(_("val_t_to_ident: val.type is not CONFTYPE_IDENTLIST"));
6744 	/*NOTREACHED*/
6745     }
6746     return val_t__identlist(val);
6747 }
6748 
6749 identlist_t
val_t_to_str_list(val_t * val)6750 val_t_to_str_list(
6751     val_t *val)
6752 {
6753     assert(config_initialized);
6754     if (val->type != CONFTYPE_STR_LIST) {
6755 	error(_("val_t_to_ident: val.type is not CONFTYPE_STR_LIST"));
6756 	/*NOTREACHED*/
6757     }
6758     return val_t__identlist(val);
6759 }
6760 
6761 time_t
val_t_to_time(val_t * val)6762 val_t_to_time(
6763     val_t *val)
6764 {
6765     assert(config_initialized);
6766     if (val->type != CONFTYPE_TIME) {
6767 	error(_("val_t_to_time: val.type is not CONFTYPE_TIME"));
6768 	/*NOTREACHED*/
6769     }
6770     return val_t__time(val);
6771 }
6772 
6773 ssize_t
val_t_to_size(val_t * val)6774 val_t_to_size(
6775     val_t *val)
6776 {
6777     assert(config_initialized);
6778     if (val->type != CONFTYPE_SIZE) {
6779 	error(_("val_t_to_size: val.type is not CONFTYPE_SIZE"));
6780 	/*NOTREACHED*/
6781     }
6782     return val_t__size(val);
6783 }
6784 
6785 int
val_t_to_boolean(val_t * val)6786 val_t_to_boolean(
6787     val_t *val)
6788 {
6789     assert(config_initialized);
6790     if (val->type != CONFTYPE_BOOLEAN) {
6791 	error(_("val_t_to_bool: val.type is not CONFTYPE_BOOLEAN"));
6792 	/*NOTREACHED*/
6793     }
6794     return val_t__boolean(val);
6795 }
6796 
6797 int
val_t_to_no_yes_all(val_t * val)6798 val_t_to_no_yes_all(
6799     val_t *val)
6800 {
6801     assert(config_initialized);
6802     if (val->type != CONFTYPE_NO_YES_ALL) {
6803 	error(_("val_t_to_no_yes_all: val.type is not CONFTYPE_NO_YES_ALL"));
6804 	/*NOTREACHED*/
6805     }
6806     return val_t__no_yes_all(val);
6807 }
6808 
6809 comp_t
val_t_to_compress(val_t * val)6810 val_t_to_compress(
6811     val_t *val)
6812 {
6813     assert(config_initialized);
6814     if (val->type != CONFTYPE_COMPRESS) {
6815 	error(_("val_t_to_compress: val.type is not CONFTYPE_COMPRESS"));
6816 	/*NOTREACHED*/
6817     }
6818     return val_t__compress(val);
6819 }
6820 
6821 encrypt_t
val_t_to_encrypt(val_t * val)6822 val_t_to_encrypt(
6823     val_t *val)
6824 {
6825     assert(config_initialized);
6826     if (val->type != CONFTYPE_ENCRYPT) {
6827 	error(_("val_t_to_encrypt: val.type is not CONFTYPE_ENCRYPT"));
6828 	/*NOTREACHED*/
6829     }
6830     return val_t__encrypt(val);
6831 }
6832 
6833 part_cache_type_t
val_t_to_part_cache_type(val_t * val)6834 val_t_to_part_cache_type(
6835     val_t *val)
6836 {
6837     assert(config_initialized);
6838     if (val->type != CONFTYPE_PART_CACHE_TYPE) {
6839 	error(_("val_t_to_part_cache_type: val.type is not CONFTYPE_PART_CACHE_TYPE"));
6840 	/*NOTREACHED*/
6841     }
6842     return val_t__part_cache_type(val);
6843 }
6844 
6845 host_limit_t *
val_t_to_host_limit(val_t * val)6846 val_t_to_host_limit(
6847     val_t *val)
6848 {
6849     assert(config_initialized);
6850     if (val->type != CONFTYPE_HOST_LIMIT) {
6851 	error(_("val_t_to_host_limit: val.type is not CONFTYPE_HOST_LIMIT"));
6852 	/*NOTREACHED*/
6853     }
6854     return &val_t__host_limit(val);
6855 }
6856 
6857 dump_holdingdisk_t
val_t_to_holding(val_t * val)6858 val_t_to_holding(
6859     val_t *val)
6860 {
6861     assert(config_initialized);
6862     if (val->type != CONFTYPE_HOLDING) {
6863 	error(_("val_t_to_hold: val.type is not CONFTYPE_HOLDING"));
6864 	/*NOTREACHED*/
6865     }
6866     return val_t__holding(val);
6867 }
6868 
6869 estimatelist_t
val_t_to_estimatelist(val_t * val)6870 val_t_to_estimatelist(
6871     val_t *val)
6872 {
6873     assert(config_initialized);
6874     if (val->type != CONFTYPE_ESTIMATELIST) {
6875 	error(_("val_t_to_estimatelist: val.type is not CONFTYPE_ESTIMATELIST"));
6876 	/*NOTREACHED*/
6877     }
6878     return val_t__estimatelist(val);
6879 }
6880 
6881 strategy_t
val_t_to_strategy(val_t * val)6882 val_t_to_strategy(
6883     val_t *val)
6884 {
6885     assert(config_initialized);
6886     if (val->type != CONFTYPE_STRATEGY) {
6887 	error(_("val_t_to_strategy: val.type is not CONFTYPE_STRATEGY"));
6888 	/*NOTREACHED*/
6889     }
6890     return val_t__strategy(val);
6891 }
6892 
6893 taperalgo_t
val_t_to_taperalgo(val_t * val)6894 val_t_to_taperalgo(
6895     val_t *val)
6896 {
6897     assert(config_initialized);
6898     if (val->type != CONFTYPE_TAPERALGO) {
6899 	error(_("val_t_to_taperalgo: val.type is not CONFTYPE_TAPERALGO"));
6900 	/*NOTREACHED*/
6901     }
6902     return val_t__taperalgo(val);
6903 }
6904 
6905 send_amreport_t
val_t_to_send_amreport(val_t * val)6906 val_t_to_send_amreport(
6907     val_t *val)
6908 {
6909     assert(config_initialized);
6910     if (val->type != CONFTYPE_SEND_AMREPORT_ON) {
6911 	error(_("val_t_to_send_amreport: val.type is not CONFTYPE_SEND_AMREPORT_ON"));
6912 	/*NOTREACHED*/
6913     }
6914     return val_t__send_amreport(val);
6915 }
6916 
6917 data_path_t
val_t_to_data_path(val_t * val)6918 val_t_to_data_path(
6919     val_t *val)
6920 {
6921     assert(config_initialized);
6922     if (val->type != CONFTYPE_DATA_PATH) {
6923 	error(_("val_t_to_data_path: val.type is not CONFTYPE_DATA_PATH"));
6924 	/*NOTREACHED*/
6925     }
6926     return val_t__data_path(val);
6927 }
6928 
6929 int
val_t_to_priority(val_t * val)6930 val_t_to_priority(
6931     val_t *val)
6932 {
6933     assert(config_initialized);
6934     if (val->type != CONFTYPE_PRIORITY) {
6935 	error(_("val_t_to_priority: val.type is not CONFTYPE_PRIORITY"));
6936 	/*NOTREACHED*/
6937     }
6938     return val_t__priority(val);
6939 }
6940 
6941 float *
val_t_to_rate(val_t * val)6942 val_t_to_rate(
6943     val_t *val)
6944 {
6945     assert(config_initialized);
6946     if (val->type != CONFTYPE_RATE) {
6947 	error(_("val_t_to_rate: val.type is not CONFTYPE_RATE"));
6948 	/*NOTREACHED*/
6949     }
6950     return val_t__rate(val);
6951 }
6952 
6953 exinclude_t
val_t_to_exinclude(val_t * val)6954 val_t_to_exinclude(
6955     val_t *val)
6956 {
6957     assert(config_initialized);
6958     if (val->type != CONFTYPE_EXINCLUDE) {
6959 	error(_("val_t_to_exinclude: val.type is not CONFTYPE_EXINCLUDE"));
6960 	/*NOTREACHED*/
6961     }
6962     return val_t__exinclude(val);
6963 }
6964 
6965 
6966 int *
val_t_to_intrange(val_t * val)6967 val_t_to_intrange(
6968     val_t *val)
6969 {
6970     assert(config_initialized);
6971     if (val->type != CONFTYPE_INTRANGE) {
6972 	error(_("val_t_to_intrange: val.type is not CONFTYPE_INTRANGE"));
6973 	/*NOTREACHED*/
6974     }
6975     return val_t__intrange(val);
6976 }
6977 
6978 proplist_t
val_t_to_proplist(val_t * val)6979 val_t_to_proplist(
6980     val_t *val)
6981 {
6982     assert(config_initialized);
6983     if (val->type != CONFTYPE_PROPLIST) {
6984 	error(_("val_t_to_proplist: val.type is not CONFTYPE_PROPLIST"));
6985 	/*NOTREACHED*/
6986     }
6987     return val_t__proplist(val);
6988 }
6989 
6990 autolabel_t
val_t_to_autolabel(val_t * val)6991 val_t_to_autolabel(
6992     val_t *val)
6993 {
6994     assert(config_initialized);
6995     if (val->type != CONFTYPE_AUTOLABEL) {
6996 	error(_("val_t_to_autolabel: val.type is not CONFTYPE_AUTOLABEL"));
6997 	/*NOTREACHED*/
6998     }
6999     return val_t__autolabel(val);
7000 }
7001 
7002 static void
merge_val_t(val_t * valdst,val_t * valsrc)7003 merge_val_t(
7004     val_t *valdst,
7005     val_t *valsrc)
7006 {
7007     if (valsrc->type == CONFTYPE_PROPLIST) {
7008 	if (valsrc->v.proplist) {
7009 	    if (valdst->v.proplist == NULL ||
7010 		g_hash_table_size(valdst->v.proplist) == 0) {
7011 		valdst->seen.block = current_block;
7012 		valdst->seen.filename = current_filename;
7013 		valdst->seen.linenum = current_line_num;
7014 	    }
7015 	    if (valdst->v.proplist == NULL) {
7016 	        valdst->v.proplist = g_hash_table_new_full(g_str_amanda_hash,
7017 							   g_str_amanda_equal,
7018 							   &g_free,
7019 							   &free_property_t);
7020 	        g_hash_table_foreach(valsrc->v.proplist,
7021 				     &copy_proplist_foreach_fn,
7022 				     valdst->v.proplist);
7023 	    } else {
7024 		g_hash_table_foreach(valsrc->v.proplist,
7025 				     &merge_proplist_foreach_fn,
7026 				     valdst->v.proplist);
7027 	    }
7028 	}
7029     } else if (valsrc->type == CONFTYPE_IDENTLIST ||
7030 	       valsrc->type == CONFTYPE_STR_LIST) {
7031 	if (valsrc->v.identlist) {
7032 	    identlist_t il;
7033 	    for (il = valsrc->v.identlist; il != NULL; il = il->next) {
7034 		 valdst->v.identlist = g_slist_append(valdst->v.identlist,
7035 						   stralloc((char *)il->data));
7036 	    }
7037 	}
7038     } else {
7039 	free_val_t(valdst);
7040 	copy_val_t(valdst, valsrc);
7041     }
7042 }
7043 
7044 static void
copy_val_t(val_t * valdst,val_t * valsrc)7045 copy_val_t(
7046     val_t *valdst,
7047     val_t *valsrc)
7048 {
7049     GSList *ia;
7050 
7051     if(valsrc->seen.linenum) {
7052 	valdst->type = valsrc->type;
7053 	valdst->seen = valsrc->seen;
7054 	switch(valsrc->type) {
7055 	case CONFTYPE_INT:
7056 	case CONFTYPE_BOOLEAN:
7057 	case CONFTYPE_NO_YES_ALL:
7058 	case CONFTYPE_COMPRESS:
7059 	case CONFTYPE_ENCRYPT:
7060 	case CONFTYPE_HOLDING:
7061 	case CONFTYPE_EXECUTE_ON:
7062 	case CONFTYPE_EXECUTE_WHERE:
7063 	case CONFTYPE_SEND_AMREPORT_ON:
7064 	case CONFTYPE_DATA_PATH:
7065 	case CONFTYPE_STRATEGY:
7066 	case CONFTYPE_TAPERALGO:
7067 	case CONFTYPE_PRIORITY:
7068 	case CONFTYPE_PART_CACHE_TYPE:
7069 	    valdst->v.i = valsrc->v.i;
7070 	    break;
7071 
7072 	case CONFTYPE_SIZE:
7073 	    valdst->v.size = valsrc->v.size;
7074 	    break;
7075 
7076 	case CONFTYPE_INT64:
7077 	    valdst->v.int64 = valsrc->v.int64;
7078 	    break;
7079 
7080 	case CONFTYPE_REAL:
7081 	    valdst->v.r = valsrc->v.r;
7082 	    break;
7083 
7084 	case CONFTYPE_RATE:
7085 	    valdst->v.rate[0] = valsrc->v.rate[0];
7086 	    valdst->v.rate[1] = valsrc->v.rate[1];
7087 	    break;
7088 
7089 	case CONFTYPE_IDENT:
7090 	case CONFTYPE_STR:
7091 	    valdst->v.s = stralloc(valsrc->v.s);
7092 	    break;
7093 
7094 	case CONFTYPE_IDENTLIST:
7095 	case CONFTYPE_STR_LIST:
7096 	    valdst->v.identlist = NULL;
7097 	    for (ia = valsrc->v.identlist; ia != NULL; ia = ia->next) {
7098 		valdst->v.identlist = g_slist_append(valdst->v.identlist,
7099 						     stralloc(ia->data));
7100 	    }
7101 	    break;
7102 
7103 	case CONFTYPE_HOST_LIMIT:
7104 	    valdst->v.host_limit = valsrc->v.host_limit;
7105 	    valdst->v.host_limit.match_pats = NULL;
7106 	    for (ia = valsrc->v.host_limit.match_pats; ia != NULL; ia = ia->next) {
7107 		valdst->v.host_limit.match_pats =
7108 		    g_slist_append(valdst->v.host_limit.match_pats, g_strdup(ia->data));
7109 	    }
7110 	    break;
7111 
7112 	case CONFTYPE_TIME:
7113 	    valdst->v.t = valsrc->v.t;
7114 	    break;
7115 
7116 	case CONFTYPE_ESTIMATELIST: {
7117 	    estimatelist_t estimates = valsrc->v.estimatelist;
7118 	    estimatelist_t dst_estimates = NULL;
7119 	    while (estimates != NULL) {
7120 		dst_estimates = g_slist_append(dst_estimates, estimates->data);
7121 		estimates = estimates->next;
7122 	    }
7123 	    valdst->v.estimatelist = dst_estimates;
7124 	    break;
7125 	}
7126 
7127 	case CONFTYPE_EXINCLUDE:
7128 	    valdst->v.exinclude.optional = valsrc->v.exinclude.optional;
7129 	    valdst->v.exinclude.sl_list = duplicate_sl(valsrc->v.exinclude.sl_list);
7130 	    valdst->v.exinclude.sl_file = duplicate_sl(valsrc->v.exinclude.sl_file);
7131 	    break;
7132 
7133 	case CONFTYPE_INTRANGE:
7134 	    valdst->v.intrange[0] = valsrc->v.intrange[0];
7135 	    valdst->v.intrange[1] = valsrc->v.intrange[1];
7136 	    break;
7137 
7138         case CONFTYPE_PROPLIST:
7139 	    if (valsrc->v.proplist) {
7140 		valdst->v.proplist = g_hash_table_new_full(g_str_amanda_hash,
7141 							   g_str_amanda_equal,
7142 							   &g_free,
7143 							   &free_property_t);
7144 
7145 		g_hash_table_foreach(valsrc->v.proplist,
7146 				     &copy_proplist_foreach_fn,
7147 				     valdst->v.proplist);
7148 	    } else {
7149 		valdst->v.proplist = NULL;
7150 	    }
7151 	    break;
7152 
7153 	case CONFTYPE_APPLICATION:
7154 	    valdst->v.s = stralloc(valsrc->v.s);
7155 	    break;
7156 
7157 	case CONFTYPE_AUTOLABEL:
7158 	    valdst->v.autolabel.template = stralloc(valsrc->v.autolabel.template);
7159 	    valdst->v.autolabel.autolabel = valsrc->v.autolabel.autolabel;
7160 	    break;
7161 	}
7162     }
7163 }
7164 
7165 static void
merge_proplist_foreach_fn(gpointer key_p,gpointer value_p,gpointer user_data_p)7166 merge_proplist_foreach_fn(
7167     gpointer key_p,
7168     gpointer value_p,
7169     gpointer user_data_p)
7170 {
7171     char *property_s = key_p;
7172     property_t *property = value_p;
7173     proplist_t proplist = user_data_p;
7174     GSList *elem = NULL;
7175     int new_prop = 0;
7176     property_t *new_property = g_hash_table_lookup(proplist, property_s);
7177     if (new_property && !property->append) {
7178 	g_hash_table_remove(proplist, property_s);
7179 	new_property = NULL;
7180     }
7181     if (!new_property) {
7182         new_property = malloc(sizeof(property_t));
7183 	new_property->seen = property->seen;
7184 	new_property->append = property->append;
7185 	new_property->priority = property->priority;
7186 	new_property->values = NULL;
7187 	new_prop = 1;
7188     }
7189 
7190     for(elem = property->values;elem != NULL; elem=elem->next) {
7191 	new_property->values = g_slist_append(new_property->values,
7192 					      stralloc(elem->data));
7193     }
7194     if (new_prop)
7195 	g_hash_table_insert(proplist, stralloc(property_s), new_property);
7196 }
7197 
7198 static void
copy_proplist_foreach_fn(gpointer key_p,gpointer value_p,gpointer user_data_p)7199 copy_proplist_foreach_fn(
7200     gpointer key_p,
7201     gpointer value_p,
7202     gpointer user_data_p)
7203 {
7204     char *property_s = key_p;
7205     property_t *property = value_p;
7206     proplist_t proplist = user_data_p;
7207     GSList *elem = NULL;
7208     property_t *new_property = malloc(sizeof(property_t));
7209     new_property->append = property->append;
7210     new_property->priority = property->priority;
7211     new_property->seen = property->seen;
7212     new_property->values = NULL;
7213 
7214     for(elem = property->values;elem != NULL; elem=elem->next) {
7215 	new_property->values = g_slist_append(new_property->values,
7216 					      stralloc(elem->data));
7217     }
7218     g_hash_table_insert(proplist, stralloc(property_s), new_property);
7219 }
7220 
7221 static void
free_val_t(val_t * val)7222 free_val_t(
7223     val_t *val)
7224 {
7225     switch(val->type) {
7226 	case CONFTYPE_INT:
7227 	case CONFTYPE_BOOLEAN:
7228 	case CONFTYPE_NO_YES_ALL:
7229 	case CONFTYPE_COMPRESS:
7230 	case CONFTYPE_ENCRYPT:
7231 	case CONFTYPE_HOLDING:
7232 	case CONFTYPE_EXECUTE_WHERE:
7233 	case CONFTYPE_EXECUTE_ON:
7234 	case CONFTYPE_SEND_AMREPORT_ON:
7235 	case CONFTYPE_DATA_PATH:
7236 	case CONFTYPE_STRATEGY:
7237 	case CONFTYPE_SIZE:
7238 	case CONFTYPE_TAPERALGO:
7239 	case CONFTYPE_PRIORITY:
7240 	case CONFTYPE_INT64:
7241 	case CONFTYPE_REAL:
7242 	case CONFTYPE_RATE:
7243 	case CONFTYPE_INTRANGE:
7244 	case CONFTYPE_PART_CACHE_TYPE:
7245 	    break;
7246 
7247 	case CONFTYPE_IDENT:
7248 	case CONFTYPE_STR:
7249 	case CONFTYPE_APPLICATION:
7250 	    amfree(val->v.s);
7251 	    break;
7252 
7253 	case CONFTYPE_IDENTLIST:
7254 	case CONFTYPE_STR_LIST:
7255 	    slist_free_full(val->v.identlist, g_free);
7256 	    break;
7257 
7258 	case CONFTYPE_HOST_LIMIT:
7259 	    slist_free_full(val->v.host_limit.match_pats, g_free);
7260 	    break;
7261 
7262 	case CONFTYPE_TIME:
7263 	    break;
7264 
7265 	case CONFTYPE_ESTIMATELIST:
7266 	    g_slist_free(val->v.estimatelist);
7267 	    break;
7268 
7269 	case CONFTYPE_EXINCLUDE:
7270 	    free_sl(val_t__exinclude(val).sl_list);
7271 	    free_sl(val_t__exinclude(val).sl_file);
7272 	    break;
7273 
7274         case CONFTYPE_PROPLIST:
7275             g_hash_table_destroy(val_t__proplist(val));
7276             break;
7277 
7278 	case CONFTYPE_AUTOLABEL:
7279 	    amfree(val->v.autolabel.template);
7280 	    break;
7281     }
7282     val->seen.linenum = 0;
7283     val->seen.filename = NULL;
7284     val->seen.block = NULL;
7285 }
7286 
7287 /*
7288  * Utilities Implementation
7289  */
7290 
7291 char *
generic_get_security_conf(char * string,void * arg)7292 generic_get_security_conf(
7293 	char *string,
7294 	void *arg)
7295 {
7296 	arg = arg;
7297 	if(!string || !*string)
7298 		return(NULL);
7299 
7300 	if(strcmp(string, "krb5principal")==0) {
7301 		return(getconf_str(CNF_KRB5PRINCIPAL));
7302 	} else if(strcmp(string, "krb5keytab")==0) {
7303 		return(getconf_str(CNF_KRB5KEYTAB));
7304 	}
7305 	return(NULL);
7306 }
7307 
7308 char *
generic_client_get_security_conf(char * string,void * arg)7309 generic_client_get_security_conf(
7310     char *	string,
7311     void *	arg)
7312 {
7313 	(void)arg;	/* Quiet unused parameter warning */
7314 
7315 	if(!string || !*string)
7316 		return(NULL);
7317 
7318 	if(strcmp(string, "conf")==0) {
7319 		return(getconf_str(CNF_CONF));
7320 	} else if(strcmp(string, "amdump_server")==0) {
7321 		return(getconf_str(CNF_AMDUMP_SERVER));
7322 	} else if(strcmp(string, "index_server")==0) {
7323 		return(getconf_str(CNF_INDEX_SERVER));
7324 	} else if(strcmp(string, "tape_server")==0) {
7325 		return(getconf_str(CNF_TAPE_SERVER));
7326 	} else if(strcmp(string, "tapedev")==0) {
7327 		return(getconf_str(CNF_TAPEDEV));
7328         } else if(strcmp(string, "auth")==0) {
7329 		return(getconf_str(CNF_AUTH));
7330 	} else if(strcmp(string, "ssh_keys")==0) {
7331 		return(getconf_str(CNF_SSH_KEYS));
7332 	} else if(strcmp(string, "amandad_path")==0) {
7333 		return(getconf_str(CNF_AMANDAD_PATH));
7334 	} else if(strcmp(string, "client_username")==0) {
7335 		return(getconf_str(CNF_CLIENT_USERNAME));
7336 	} else if(strcmp(string, "client_port")==0) {
7337 		return(getconf_str(CNF_CLIENT_PORT));
7338 	} else if(strcmp(string, "gnutar_list_dir")==0) {
7339 		return(getconf_str(CNF_GNUTAR_LIST_DIR));
7340 	} else if(strcmp(string, "amandates")==0) {
7341 		return(getconf_str(CNF_AMANDATES));
7342 	} else if(strcmp(string, "krb5principal")==0) {
7343 		return(getconf_str(CNF_KRB5PRINCIPAL));
7344 	} else if(strcmp(string, "krb5keytab")==0) {
7345 		return(getconf_str(CNF_KRB5KEYTAB));
7346 	}
7347 	return(NULL);
7348 }
7349 
7350 void
dump_configuration(gboolean print_default,gboolean print_source)7351 dump_configuration(
7352     gboolean print_default,
7353     gboolean print_source)
7354 {
7355     tapetype_t *tp;
7356     dumptype_t *dp;
7357     interface_t *ip;
7358     holdingdisk_t *hd;
7359     GSList        *hp;
7360     application_t *ap;
7361     pp_script_t *ps;
7362     device_config_t *dc;
7363     changer_config_t *cc;
7364     interactivity_t  *iv;
7365     taperscan_t      *ts;
7366     int i;
7367     conf_var_t *np;
7368     keytab_t *kt;
7369     char *prefix;
7370 
7371     if (config_client) {
7372 	error(_("Don't know how to dump client configurations."));
7373 	/* NOTREACHED */
7374     }
7375 
7376     g_printf(_("# AMANDA CONFIGURATION FROM FILE \"%s\":\n\n"), config_filename);
7377 
7378     for(np=server_var; np->token != CONF_UNKNOWN; np++) {
7379 	for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7380 	    if (np->token == kt->token) break;
7381 
7382 	if(kt->token == CONF_UNKNOWN)
7383 	    error(_("server bad token"));
7384 
7385         val_t_print_token(print_default, print_source, stdout, NULL, "%-21s ", kt, &conf_data[np->parm]);
7386     }
7387 
7388     for(hp = holdinglist; hp != NULL; hp = hp->next) {
7389 	hd = hp->data;
7390 	g_printf("\nDEFINE HOLDINGDISK %s {\n", hd->name);
7391 	for(i=0; i < HOLDING_HOLDING; i++) {
7392 	    for(np=holding_var; np->token != CONF_UNKNOWN; np++) {
7393 		if(np->parm == i)
7394 			break;
7395 	    }
7396 	    if(np->token == CONF_UNKNOWN)
7397 		error(_("holding bad value"));
7398 
7399 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) {
7400 		if(kt->token == np->token)
7401 		    break;
7402 	    }
7403 	    if(kt->token == CONF_UNKNOWN)
7404 		error(_("holding bad token"));
7405 
7406             val_t_print_token(print_default, print_source, stdout, NULL, "      %-9s ", kt, &hd->value[i]);
7407 	}
7408 	g_printf("}\n");
7409     }
7410 
7411     for(tp = tapelist; tp != NULL; tp = tp->next) {
7412 	if(tp->seen.linenum == -1)
7413 	    prefix = "#";
7414 	else
7415 	    prefix = "";
7416 	g_printf("\n%sDEFINE TAPETYPE %s {\n", prefix, tp->name);
7417 	for(i=0; i < TAPETYPE_TAPETYPE; i++) {
7418 	    for(np=tapetype_var; np->token != CONF_UNKNOWN; np++)
7419 		if(np->parm == i) break;
7420 	    if(np->token == CONF_UNKNOWN)
7421 		error(_("tapetype bad value"));
7422 
7423 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7424 		if(kt->token == np->token) break;
7425 	    if(kt->token == CONF_UNKNOWN)
7426 		error(_("tapetype bad token"));
7427 
7428             val_t_print_token(print_default, print_source, stdout, prefix, "      %-9s ", kt, &tp->value[i]);
7429 	}
7430 	g_printf("%s}\n", prefix);
7431     }
7432 
7433     for(dp = dumplist; dp != NULL; dp = dp->next) {
7434 	if (strncmp_const(dp->name, "custom(") != 0) { /* don't dump disklist-derived dumptypes */
7435 	    if(dp->seen.linenum == -1)
7436 		prefix = "#";
7437 	    else
7438 		prefix = "";
7439 	    g_printf("\n%sDEFINE DUMPTYPE %s {\n", prefix, dp->name);
7440 	    for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
7441 		for(np=dumptype_var; np->token != CONF_UNKNOWN; np++)
7442 		    if(np->parm == i) break;
7443 		if(np->token == CONF_UNKNOWN)
7444 		    error(_("dumptype bad value"));
7445 
7446 		for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7447 		    if(kt->token == np->token) break;
7448 		if(kt->token == CONF_UNKNOWN)
7449 		    error(_("dumptype bad token"));
7450 
7451 		val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &dp->value[i]);
7452 	    }
7453 	    g_printf("%s}\n", prefix);
7454 	}
7455     }
7456 
7457     for(ip = interface_list; ip != NULL; ip = ip->next) {
7458 	seen_t *netusage_seen = &val_t__seen(getconf(CNF_NETUSAGE));
7459 	if (ip->seen.linenum == netusage_seen->linenum &&
7460 	    ip->seen.filename && netusage_seen->filename &&
7461 	    0 == strcmp(ip->seen.filename, netusage_seen->filename))
7462 	    prefix = "#";
7463 	else
7464 	    prefix = "";
7465 	g_printf("\n%sDEFINE INTERFACE %s {\n", prefix, ip->name);
7466 	for(i=0; i < INTER_INTER; i++) {
7467 	    for(np=interface_var; np->token != CONF_UNKNOWN; np++)
7468 		if(np->parm == i) break;
7469 	    if(np->token == CONF_UNKNOWN)
7470 		error(_("interface bad value"));
7471 
7472 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7473 		if(kt->token == np->token) break;
7474 	    if(kt->token == CONF_UNKNOWN)
7475 		error(_("interface bad token"));
7476 
7477 	    val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &ip->value[i]);
7478 	}
7479 	g_printf("%s}\n",prefix);
7480     }
7481 
7482     for(ap = application_list; ap != NULL; ap = ap->next) {
7483 	if(strcmp(ap->name,"default") == 0)
7484 	    prefix = "#";
7485 	else
7486 	    prefix = "";
7487 	g_printf("\n%sDEFINE APPLICATION %s {\n", prefix, ap->name);
7488 	for(i=0; i < APPLICATION_APPLICATION; i++) {
7489 	    for(np=application_var; np->token != CONF_UNKNOWN; np++)
7490 		if(np->parm == i) break;
7491 	    if(np->token == CONF_UNKNOWN)
7492 		error(_("application bad value"));
7493 
7494 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7495 		if(kt->token == np->token) break;
7496 	    if(kt->token == CONF_UNKNOWN)
7497 		error(_("application bad token"));
7498 
7499 	    val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &ap->value[i]);
7500 	}
7501 	g_printf("%s}\n",prefix);
7502     }
7503 
7504     for(ps = pp_script_list; ps != NULL; ps = ps->next) {
7505 	if(strcmp(ps->name,"default") == 0)
7506 	    prefix = "#";
7507 	else
7508 	    prefix = "";
7509 	g_printf("\n%sDEFINE SCRIPT %s {\n", prefix, ps->name);
7510 	for(i=0; i < PP_SCRIPT_PP_SCRIPT; i++) {
7511 	    for(np=pp_script_var; np->token != CONF_UNKNOWN; np++)
7512 		if(np->parm == i) break;
7513 	    if(np->token == CONF_UNKNOWN)
7514 		error(_("script bad value"));
7515 
7516 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7517 		if(kt->token == np->token) break;
7518 	    if(kt->token == CONF_UNKNOWN)
7519 		error(_("script bad token"));
7520 
7521 	    val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &ps->value[i]);
7522 	}
7523 	g_printf("%s}\n",prefix);
7524     }
7525 
7526     for(dc = device_config_list; dc != NULL; dc = dc->next) {
7527 	prefix = "";
7528 	g_printf("\n%sDEFINE DEVICE %s {\n", prefix, dc->name);
7529 	for(i=0; i < DEVICE_CONFIG_DEVICE_CONFIG; i++) {
7530 	    for(np=device_config_var; np->token != CONF_UNKNOWN; np++)
7531 		if(np->parm == i) break;
7532 	    if(np->token == CONF_UNKNOWN)
7533 		error(_("device bad value"));
7534 
7535 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7536 		if(kt->token == np->token) break;
7537 	    if(kt->token == CONF_UNKNOWN)
7538 		error(_("device bad token"));
7539 
7540 	    val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &dc->value[i]);
7541 	}
7542 	g_printf("%s}\n",prefix);
7543     }
7544 
7545     for(cc = changer_config_list; cc != NULL; cc = cc->next) {
7546 	prefix = "";
7547 	g_printf("\n%sDEFINE CHANGER %s {\n", prefix, cc->name);
7548 	for(i=0; i < CHANGER_CONFIG_CHANGER_CONFIG; i++) {
7549 	    for(np=changer_config_var; np->token != CONF_UNKNOWN; np++)
7550 		if(np->parm == i) break;
7551 	    if(np->token == CONF_UNKNOWN)
7552 		error(_("changer bad value"));
7553 
7554 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7555 		if(kt->token == np->token) break;
7556 	    if(kt->token == CONF_UNKNOWN)
7557 		error(_("changer bad token"));
7558 
7559 	    val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &cc->value[i]);
7560 	}
7561 	g_printf("%s}\n",prefix);
7562     }
7563 
7564     for(iv = interactivity_list; iv != NULL; iv = iv->next) {
7565 	prefix = "";
7566 	g_printf("\n%sDEFINE INTERACTIVITY %s {\n", prefix, iv->name);
7567 	for(i=0; i < INTERACTIVITY_INTERACTIVITY; i++) {
7568 	    for(np=interactivity_var; np->token != CONF_UNKNOWN; np++)
7569 		if(np->parm == i) break;
7570 	    if(np->token == CONF_UNKNOWN)
7571 		error(_("interactivity bad value"));
7572 
7573 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7574 		if(kt->token == np->token) break;
7575 	    if(kt->token == CONF_UNKNOWN)
7576 		error(_("interactivity bad token"));
7577 
7578 	    val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &iv->value[i]);
7579 	}
7580 	g_printf("%s}\n",prefix);
7581     }
7582 
7583     for(ts = taperscan_list; ts != NULL; ts = ts->next) {
7584 	prefix = "";
7585 	g_printf("\n%sDEFINE TAPERSCAN %s {\n", prefix, ts->name);
7586 	for(i=0; i < TAPERSCAN_TAPERSCAN; i++) {
7587 	    for(np=taperscan_var; np->token != CONF_UNKNOWN; np++)
7588 		if(np->parm == i) break;
7589 	    if(np->token == CONF_UNKNOWN)
7590 		error(_("taperscan bad value"));
7591 
7592 	    for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7593 		if(kt->token == np->token) break;
7594 	    if(kt->token == CONF_UNKNOWN)
7595 		error(_("taperscan bad token"));
7596 
7597 	    val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &ts->value[i]);
7598 	}
7599 	g_printf("%s}\n",prefix);
7600     }
7601 }
7602 
dump_dumptype(dumptype_t * dp,char * prefix,gboolean print_default,gboolean print_source)7603 void dump_dumptype(
7604     dumptype_t *dp,
7605     char       *prefix,
7606     gboolean    print_default,
7607     gboolean    print_source)
7608 {
7609     int i;
7610     conf_var_t *np;
7611     keytab_t *kt;
7612 
7613     for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
7614 	for(np=dumptype_var; np->token != CONF_UNKNOWN; np++)
7615 	    if(np->parm == i) break;
7616 	if(np->token == CONF_UNKNOWN)
7617 	    error(_("dumptype bad value"));
7618 
7619 	for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
7620 	    if(kt->token == np->token) break;
7621 	if(kt->token == CONF_UNKNOWN)
7622 	    error(_("dumptype bad token"));
7623 
7624 	val_t_print_token(print_default, print_source, stdout, prefix, "      %-19s ", kt, &dp->value[i]);
7625     }
7626 }
7627 
7628 static void
val_t_print_token(gboolean print_default,gboolean print_source,FILE * output,char * prefix,char * format,keytab_t * kt,val_t * val)7629 val_t_print_token(
7630     gboolean  print_default,
7631     gboolean  print_source,
7632     FILE     *output,
7633     char     *prefix,
7634     char     *format,
7635     keytab_t *kt,
7636     val_t    *val)
7637 {
7638     char       **dispstrs, **dispstr;
7639 
7640     if (print_default == 0 && !val_t_seen(val)) {
7641 	return;
7642     }
7643 
7644     dispstrs = val_t_display_strs(val, 1, print_source, TRUE);
7645 
7646     /* For most configuration types, this outputs
7647      *   PREFIX KEYWORD DISPSTR
7648      * for each of the display strings.  For identifiers, however, it
7649      * simply prints the first line of the display string.
7650      */
7651 
7652     /* Print the keyword for anything that is not itself an identifier */
7653     if (kt->token != CONF_IDENT) {
7654         for(dispstr=dispstrs; *dispstr!=NULL; dispstr++) {
7655 	    if (prefix)
7656 		g_fprintf(output, "%s", prefix);
7657 	    g_fprintf(output, format, str_keyword(kt));
7658 	    g_fprintf(output, "%s\n", *dispstr);
7659 	}
7660     } else {
7661 	/* for identifiers, assume there's at most one display string */
7662 	assert(g_strv_length(dispstrs) <= 1);
7663 	if (*dispstrs) {
7664 	    g_fprintf(output, "%s\n", *dispstrs);
7665 	}
7666     }
7667 
7668     g_strfreev(dispstrs);
7669 }
7670 
7671 typedef struct proplist_display_str_foreach_user_data {
7672     char     **msg;
7673     gboolean   print_source;
7674 } proplist_display_str_foreach_user_data;
7675 
7676 char *source_string(seen_t *seen);
source_string(seen_t * seen)7677 char *source_string(
7678     seen_t *seen)
7679 {
7680     char *buf;
7681 
7682     if (seen->linenum) {
7683 	if (seen->block) {
7684 	    buf = g_strdup_printf("     (%s file %s line %d)",
7685 			seen->block, seen->filename, seen->linenum);
7686 	} else {
7687 	    buf = g_strdup_printf("     (file %s line %d)",
7688 			seen->filename, seen->linenum);
7689 	}
7690     } else {
7691 	buf = g_strdup("     (default)");
7692     }
7693     return buf;
7694 }
7695 
7696 char **
val_t_display_strs(val_t * val,int str_need_quote,gboolean print_source,gboolean print_unit)7697 val_t_display_strs(
7698     val_t *val,
7699     int    str_need_quote,
7700     gboolean print_source,
7701     gboolean print_unit)
7702 {
7703     gboolean add_source = TRUE;
7704     int    i;
7705     char **buf;
7706     buf = malloc(3*SIZEOF(char *));
7707     buf[0] = NULL;
7708     buf[1] = NULL;
7709     buf[2] = NULL;
7710 
7711     switch(val->type) {
7712     case CONFTYPE_INT:
7713 	buf[0] = vstrallocf("%d ", val_t__int(val));
7714 	i = strlen(buf[0]) - 1;
7715 	if (print_unit && val->unit == CONF_UNIT_K) {
7716 	    buf[0][i] = 'K';
7717 	} else {
7718 	    buf[0][i] = '\0';
7719 	}
7720 	break;
7721 
7722     case CONFTYPE_SIZE:
7723 	buf[0] = vstrallocf("%zu ", (ssize_t)val_t__size(val));
7724 	i = strlen(buf[0]) - 1;
7725 	if (print_unit && val->unit == CONF_UNIT_K) {
7726 	    buf[0][i] = 'K';
7727 	} else {
7728 	    buf[0][i] = '\0';
7729 	}
7730 	break;
7731 
7732     case CONFTYPE_INT64:
7733 	buf[0] = vstrallocf("%lld ", (long long)val_t__int64(val));
7734 	i = strlen(buf[0]) - 1;
7735 	if (print_unit && val->unit == CONF_UNIT_K) {
7736 	    buf[0][i] = 'K';
7737 	} else {
7738 	    buf[0][i] = '\0';
7739 	}
7740 	break;
7741 
7742     case CONFTYPE_REAL:
7743 	buf[0] = vstrallocf("%0.5f", val_t__real(val));
7744 	break;
7745 
7746     case CONFTYPE_RATE:
7747 	buf[0] = vstrallocf("%0.5f %0.5f", val_t__rate(val)[0], val_t__rate(val)[1]);
7748 	break;
7749 
7750     case CONFTYPE_INTRANGE:
7751 	buf[0] = vstrallocf("%d,%d", val_t__intrange(val)[0], val_t__intrange(val)[1]);
7752 	break;
7753 
7754     case CONFTYPE_IDENT:
7755 	if(val->v.s) {
7756 	    buf[0] = stralloc(val->v.s);
7757         } else {
7758 	    buf[0] = stralloc("");
7759 	}
7760 	break;
7761 
7762     case CONFTYPE_IDENTLIST:
7763 	{
7764 	    GSList *ia;
7765 	    int     first = 1;
7766 
7767 	    buf[0] = NULL;
7768 	    for (ia = val->v.identlist; ia != NULL; ia = ia->next) {
7769 		if (first) {
7770 		    buf[0] = stralloc(ia->data);
7771 		    first = 0;
7772 		} else {
7773 		    strappend(buf[0], " ");
7774 		    strappend(buf[0],  ia->data);
7775 		}
7776 	    }
7777 	}
7778 	break;
7779 
7780     case CONFTYPE_STR_LIST:
7781 	{
7782 	    GSList *ia;
7783 	    int     first = 1;
7784 
7785 	    buf[0] = NULL;
7786 	    for (ia = val->v.identlist; ia != NULL; ia = ia->next) {
7787 		if (first) {
7788 		    buf[0] = quote_string_always(ia->data);
7789 		    first = 0;
7790 		} else {
7791 		    char *qdata = quote_string_always(ia->data);
7792 		    strappend(buf[0], " ");
7793 		    strappend(buf[0],  qdata);
7794 		    g_free(qdata);
7795 		}
7796 	    }
7797 	}
7798 	break;
7799 
7800     case CONFTYPE_STR:
7801 	if(str_need_quote) {
7802             if(val->v.s) {
7803 		buf[0] = quote_string_always(val->v.s);
7804             } else {
7805 		buf[0] = stralloc("\"\"");
7806             }
7807 	} else {
7808 	    if(val->v.s) {
7809 		buf[0] = stralloc(val->v.s);
7810             } else {
7811 		buf[0] = stralloc("");
7812             }
7813 	}
7814 	break;
7815 
7816     case CONFTYPE_AUTOLABEL:
7817 	{
7818 	    buf[0] = quote_string_always(val->v.autolabel.template);
7819 	    if (val->v.autolabel.autolabel & AL_OTHER_CONFIG) {
7820 		buf[0] = vstrextend(&buf[0], " OTHER-CONFIG", NULL);
7821 	    }
7822 	    if (val->v.autolabel.autolabel & AL_NON_AMANDA) {
7823 		buf[0] = vstrextend(&buf[0], " NON-AMANDA", NULL);
7824 	    }
7825 	    if (val->v.autolabel.autolabel & AL_VOLUME_ERROR) {
7826 		buf[0] = vstrextend(&buf[0], " VOLUME-ERROR", NULL);
7827 	    }
7828 	    if (val->v.autolabel.autolabel & AL_EMPTY) {
7829 		buf[0] = vstrextend(&buf[0], " EMPTY", NULL);
7830 	    }
7831 	}
7832 	break;
7833 
7834     case CONFTYPE_TIME:
7835 	buf[0] = vstrallocf("%2d%02d",
7836 			 (int)val_t__time(val)/100, (int)val_t__time(val) % 100);
7837 	break;
7838 
7839     case CONFTYPE_EXINCLUDE: {
7840         buf[0] = exinclude_display_str(val, 0);
7841         buf[1] = exinclude_display_str(val, 1);
7842 	break;
7843     }
7844 
7845     case CONFTYPE_BOOLEAN:
7846 	if(val_t__boolean(val))
7847 	    buf[0] = stralloc("yes");
7848 	else
7849 	    buf[0] = stralloc("no");
7850 	break;
7851 
7852     case CONFTYPE_NO_YES_ALL:
7853 	switch(val_t__no_yes_all(val)) {
7854 	case 0:
7855 	    buf[0] = stralloc("no");
7856 	    break;
7857 	case 1:
7858 	    buf[0] = stralloc("yes");
7859 	    break;
7860 	case 2:
7861 	    buf[0] = stralloc("all");
7862 	    break;
7863 	}
7864 	break;
7865 
7866     case CONFTYPE_STRATEGY:
7867 	switch(val_t__strategy(val)) {
7868 	case DS_SKIP:
7869 	    buf[0] = vstrallocf("SKIP");
7870 	    break;
7871 
7872 	case DS_STANDARD:
7873 	    buf[0] = vstrallocf("STANDARD");
7874 	    break;
7875 
7876 	case DS_NOFULL:
7877 	    buf[0] = vstrallocf("NOFULL");
7878 	    break;
7879 
7880 	case DS_NOINC:
7881 	    buf[0] = vstrallocf("NOINC");
7882 	    break;
7883 
7884 	case DS_HANOI:
7885 	    buf[0] = vstrallocf("HANOI");
7886 	    break;
7887 
7888 	case DS_INCRONLY:
7889 	    buf[0] = vstrallocf("INCRONLY");
7890 	    break;
7891 	}
7892 	break;
7893 
7894     case CONFTYPE_COMPRESS:
7895 	switch(val_t__compress(val)) {
7896 	case COMP_NONE:
7897 	    buf[0] = vstrallocf("NONE");
7898 	    break;
7899 
7900 	case COMP_FAST:
7901 	    buf[0] = vstrallocf("CLIENT FAST");
7902 	    break;
7903 
7904 	case COMP_BEST:
7905 	    buf[0] = vstrallocf("CLIENT BEST");
7906 	    break;
7907 
7908 	case COMP_CUST:
7909 	    buf[0] = vstrallocf("CLIENT CUSTOM");
7910 	    break;
7911 
7912 	case COMP_SERVER_FAST:
7913 	    buf[0] = vstrallocf("SERVER FAST");
7914 	    break;
7915 
7916 	case COMP_SERVER_BEST:
7917 	    buf[0] = vstrallocf("SERVER BEST");
7918 	    break;
7919 
7920 	case COMP_SERVER_CUST:
7921 	    buf[0] = vstrallocf("SERVER CUSTOM");
7922 	    break;
7923 	}
7924 	break;
7925 
7926     case CONFTYPE_ESTIMATELIST: {
7927 	estimatelist_t es = val_t__estimatelist(val);
7928 	buf[0] = stralloc("");
7929 	while (es) {
7930 	    switch((estimate_t)GPOINTER_TO_INT(es->data)) {
7931 	    case ES_CLIENT:
7932 		strappend(buf[0], "CLIENT");
7933 		break;
7934 
7935 	    case ES_SERVER:
7936 		strappend(buf[0], "SERVER");
7937 		break;
7938 
7939 	    case ES_CALCSIZE:
7940 		strappend(buf[0], "CALCSIZE");
7941 		break;
7942 
7943 	    case ES_ES:
7944 		break;
7945 	    }
7946 	    es = es->next;
7947 	    if (es)
7948 		strappend(buf[0], " ");
7949 	}
7950 	break;
7951     }
7952 
7953     case CONFTYPE_EXECUTE_WHERE:
7954 	switch(val->v.i) {
7955 	case ES_CLIENT:
7956 	    buf[0] = vstrallocf("CLIENT");
7957 	    break;
7958 
7959 	case ES_SERVER:
7960 	    buf[0] = vstrallocf("SERVER");
7961 	    break;
7962 	}
7963 	break;
7964 
7965     case CONFTYPE_SEND_AMREPORT_ON:
7966 	switch(val->v.i) {
7967 	case SEND_AMREPORT_ALL:
7968 	    buf[0] = vstrallocf("ALL");
7969 	    break;
7970 	case SEND_AMREPORT_STRANGE:
7971 	    buf[0] = vstrallocf("STRANGE");
7972 	    break;
7973 	case SEND_AMREPORT_ERROR:
7974 	    buf[0] = vstrallocf("ERROR");
7975 	    break;
7976 	case SEND_AMREPORT_NEVER:
7977 	    buf[0] = vstrallocf("NEVER");
7978 	    break;
7979 	}
7980 	break;
7981 
7982     case CONFTYPE_DATA_PATH:
7983 	buf[0] = g_strdup(data_path_to_string(val->v.i));
7984 	break;
7985 
7986      case CONFTYPE_ENCRYPT:
7987 	switch(val_t__encrypt(val)) {
7988 	case ENCRYPT_NONE:
7989 	    buf[0] = vstrallocf("NONE");
7990 	    break;
7991 
7992 	case ENCRYPT_CUST:
7993 	    buf[0] = vstrallocf("CLIENT");
7994 	    break;
7995 
7996 	case ENCRYPT_SERV_CUST:
7997 	    buf[0] = vstrallocf("SERVER");
7998 	    break;
7999 	}
8000 	break;
8001 
8002      case CONFTYPE_PART_CACHE_TYPE:
8003 	switch(val_t__part_cache_type(val)) {
8004 	case PART_CACHE_TYPE_NONE:
8005 	    buf[0] = vstrallocf("NONE");
8006 	    break;
8007 
8008 	case PART_CACHE_TYPE_DISK:
8009 	    buf[0] = vstrallocf("DISK");
8010 	    break;
8011 
8012 	case PART_CACHE_TYPE_MEMORY:
8013 	    buf[0] = vstrallocf("MEMORY");
8014 	    break;
8015 	}
8016 	break;
8017 
8018      case CONFTYPE_HOST_LIMIT: {
8019 	GSList *iter = val_t__host_limit(val).match_pats;
8020 
8021 	if (val_t__host_limit(val).same_host)
8022 	    buf[0] = stralloc("SAME-HOST ");
8023 	else
8024 	    buf[0] = stralloc("");
8025 
8026 	if (val_t__host_limit(val).server)
8027 	    strappend(buf[0], "SERVER ");
8028 
8029 	while (iter) {
8030 	    strappend(buf[0], quote_string_always((char *)iter->data));
8031 	    strappend(buf[0], " ");
8032 	    iter = iter->next;
8033 	}
8034 	break;
8035      }
8036 
8037      case CONFTYPE_HOLDING:
8038 	switch(val_t__holding(val)) {
8039 	case HOLD_NEVER:
8040 	    buf[0] = vstrallocf("NEVER");
8041 	    break;
8042 
8043 	case HOLD_AUTO:
8044 	    buf[0] = vstrallocf("AUTO");
8045 	    break;
8046 
8047 	case HOLD_REQUIRED:
8048 	    buf[0] = vstrallocf("REQUIRED");
8049 	    break;
8050 	}
8051 	break;
8052 
8053      case CONFTYPE_TAPERALGO:
8054 	buf[0] = vstrallocf("%s", taperalgo2str(val_t__taperalgo(val)));
8055 	break;
8056 
8057      case CONFTYPE_PRIORITY:
8058 	switch(val_t__priority(val)) {
8059 	case 0:
8060 	    buf[0] = vstrallocf("LOW");
8061 	    break;
8062 
8063 	case 1:
8064 	    buf[0] = vstrallocf("MEDIUM");
8065 	    break;
8066 
8067 	case 2:
8068 	    buf[0] = vstrallocf("HIGH");
8069 	    break;
8070 	}
8071 	break;
8072 
8073     case CONFTYPE_PROPLIST: {
8074 	int    nb_property;
8075 	proplist_display_str_foreach_user_data user_data;
8076 
8077 	nb_property = g_hash_table_size(val_t__proplist(val));
8078 	g_free(buf);
8079 	buf = g_new0(char *, nb_property+1);
8080 	user_data.msg = buf;
8081 	user_data.print_source = print_source;
8082 	g_hash_table_foreach(val_t__proplist(val),
8083 			     proplist_display_str_foreach_fn,
8084 			     &user_data);
8085 	add_source = FALSE;
8086         break;
8087     }
8088 
8089     case CONFTYPE_APPLICATION: {
8090 	if (val->v.s) {
8091 	    buf[0] = quote_string_always(val->v.s);
8092 	} else {
8093 	    buf[0] = stralloc("");
8094 	}
8095 	break;
8096     }
8097 
8098     case CONFTYPE_EXECUTE_ON:
8099 	buf[0] = stralloc("");
8100 	if (val->v.i != 0) {
8101 	    char *sep = "";
8102 	    if (val->v.i & EXECUTE_ON_PRE_AMCHECK) {
8103 		buf[0] = vstrextend(&buf[0], sep, "PRE-AMCHECK", NULL);
8104 		sep = ", ";
8105 	    }
8106 	    if (val->v.i & EXECUTE_ON_PRE_DLE_AMCHECK) {
8107 		buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-AMCHECK", NULL);
8108 		sep = ", ";
8109 	    }
8110 	    if (val->v.i & EXECUTE_ON_PRE_HOST_AMCHECK) {
8111 		buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-AMCHECK", NULL);
8112 		sep = ", ";
8113 	    }
8114 	    if (val->v.i & EXECUTE_ON_POST_DLE_AMCHECK) {
8115 		buf[0] = vstrextend(&buf[0], sep, "POST-DLE-AMCHECK", NULL);
8116 		sep = ", ";
8117 	    }
8118 	    if (val->v.i & EXECUTE_ON_POST_HOST_AMCHECK) {
8119 		buf[0] = vstrextend(&buf[0], sep, "POST-HOST-AMCHECK", NULL);
8120 		sep = ", ";
8121 	    }
8122 	    if (val->v.i & EXECUTE_ON_POST_AMCHECK) {
8123 		buf[0] = vstrextend(&buf[0], sep, "POST-AMCHECK", NULL);
8124 		sep = ", ";
8125 	    }
8126 	    if (val->v.i & EXECUTE_ON_PRE_ESTIMATE) {
8127 		buf[0] = vstrextend(&buf[0], sep, "PRE-ESTIMATE", NULL);
8128 		sep = ", ";
8129 	    }
8130 	    if (val->v.i & EXECUTE_ON_PRE_DLE_ESTIMATE) {
8131 		buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-ESTIMATE", NULL);
8132 		sep = ", ";
8133 	    }
8134 	    if (val->v.i & EXECUTE_ON_PRE_HOST_ESTIMATE) {
8135 		buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-ESTIMATE", NULL);
8136 		sep = ", ";
8137 	    }
8138 	    if (val->v.i & EXECUTE_ON_POST_DLE_ESTIMATE) {
8139 		buf[0] = vstrextend(&buf[0], sep, "POST-DLE-ESTIMATE", NULL);
8140 		sep = ", ";
8141 	    }
8142 	    if (val->v.i & EXECUTE_ON_POST_HOST_ESTIMATE) {
8143 		buf[0] = vstrextend(&buf[0], sep, "POST-HOST-ESTIMATE", NULL);
8144 		sep = ", ";
8145 	    }
8146 	    if (val->v.i & EXECUTE_ON_POST_ESTIMATE) {
8147 		buf[0] = vstrextend(&buf[0], sep, "POST-ESTIMATE", NULL);
8148 		sep = ", ";
8149 	    }
8150 	    if (val->v.i & EXECUTE_ON_PRE_BACKUP) {
8151 		buf[0] = vstrextend(&buf[0], sep, "PRE-BACKUP", NULL);
8152 		sep = ", ";
8153 	    }
8154 	    if (val->v.i & EXECUTE_ON_PRE_DLE_BACKUP) {
8155 		buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-BACKUP", NULL);
8156 		sep = ", ";
8157 	    }
8158 	    if (val->v.i & EXECUTE_ON_PRE_HOST_BACKUP) {
8159 		buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-BACKUP", NULL);
8160 		sep = ", ";
8161 	    }
8162 	    if (val->v.i & EXECUTE_ON_POST_BACKUP) {
8163 		buf[0] = vstrextend(&buf[0], sep, "POST-BACKUP", NULL);
8164 		sep = ", ";
8165 	    }
8166 	    if (val->v.i & EXECUTE_ON_POST_DLE_BACKUP) {
8167 		buf[0] = vstrextend(&buf[0], sep, "POST-DLE-BACKUP", NULL);
8168 		sep = ", ";
8169 	    }
8170 	    if (val->v.i & EXECUTE_ON_POST_HOST_BACKUP) {
8171 		buf[0] = vstrextend(&buf[0], sep, "POST-HOST-BACKUP", NULL);
8172 		sep = ", ";
8173 	    }
8174 	    if (val->v.i & EXECUTE_ON_PRE_RECOVER) {
8175 		buf[0] = vstrextend(&buf[0], sep, "PRE-RECOVER", NULL);
8176 		sep = ", ";
8177 	    }
8178 	    if (val->v.i & EXECUTE_ON_POST_RECOVER) {
8179 		buf[0] = vstrextend(&buf[0], sep, "POST-RECOVER", NULL);
8180 		sep = ", ";
8181 	    }
8182 	    if (val->v.i & EXECUTE_ON_PRE_LEVEL_RECOVER) {
8183 		buf[0] = vstrextend(&buf[0], sep, "PRE-LEVEL-RECOVER", NULL);
8184 		sep = ", ";
8185 	    }
8186 	    if (val->v.i & EXECUTE_ON_POST_LEVEL_RECOVER) {
8187 		buf[0] = vstrextend(&buf[0], sep, "POST-LEVEL-RECOVER", NULL);
8188 		sep = ", ";
8189 	    }
8190 	    if (val->v.i & EXECUTE_ON_INTER_LEVEL_RECOVER) {
8191 		buf[0] = vstrextend(&buf[0], sep, "INTER-LEVEL-RECOVER", NULL);
8192 		sep = ", ";
8193 	    }
8194 	}
8195         break;
8196 
8197     }
8198 
8199     /* add source */
8200     if (print_source && add_source) {
8201 	char **buf1;
8202 	for (buf1 = buf; *buf1 != NULL; buf1++) {
8203 	    char *ss = source_string(&val->seen);
8204 	    char *buf2 = g_strjoin("", *buf1, ss, NULL);
8205 	    g_free(*buf1);
8206 	    g_free(ss);
8207 	    *buf1 = buf2;
8208 	}
8209     }
8210     return buf;
8211 }
8212 
8213 int
val_t_to_execute_on(val_t * val)8214 val_t_to_execute_on(
8215     val_t *val)
8216 {
8217     if (val->type != CONFTYPE_EXECUTE_ON) {
8218 	error(_("get_conftype_execute_on: val.type is not CONFTYPE_EXECUTE_ON"));
8219 	/*NOTREACHED*/
8220     }
8221     return val_t__execute_on(val);
8222 }
8223 
8224 int
val_t_to_execute_where(val_t * val)8225 val_t_to_execute_where(
8226     val_t *val)
8227 {
8228     if (val->type != CONFTYPE_EXECUTE_WHERE) {
8229 	error(_("get_conftype_execute_where: val.type is not CONFTYPE_EXECUTE_WHERE"));
8230 	/*NOTREACHED*/
8231     }
8232     return val->v.i;
8233 }
8234 
8235 char *
val_t_to_application(val_t * val)8236 val_t_to_application(
8237     val_t *val)
8238 {
8239     if (val->type != CONFTYPE_APPLICATION) {
8240 	error(_("get_conftype_applicaiton: val.type is not CONFTYPE_APPLICATION"));
8241 	/*NOTREACHED*/
8242     }
8243     return val->v.s;
8244 }
8245 
8246 
8247 static void
proplist_display_str_foreach_fn(gpointer key_p,gpointer value_p,gpointer user_data_p)8248 proplist_display_str_foreach_fn(
8249     gpointer key_p,
8250     gpointer value_p,
8251     gpointer user_data_p)
8252 {
8253     char         *property_s = quote_string_always(key_p);
8254     property_t   *property   = value_p;
8255     GSList       *value;
8256     proplist_display_str_foreach_user_data *user_data = user_data_p;
8257     char       ***msg        = (char ***)&user_data->msg;
8258 
8259     /* What to do with property->append? it should be printed only on client */
8260     if (property->priority) {
8261 	**msg = vstralloc("priority ", property_s, NULL);
8262 	amfree(property_s);
8263     } else {
8264 	**msg = property_s;
8265 	property_s = NULL;
8266     }
8267     for(value=property->values; value != NULL; value = value->next) {
8268 	char *qstr = quote_string_always((char *)value->data);
8269 	**msg = vstrextend(*msg, " ", qstr, NULL);
8270 	amfree(qstr);
8271     }
8272     if (user_data->print_source) {
8273 	**msg = vstrextend(*msg, source_string(&property->seen), NULL);
8274     }
8275     (*msg)++;
8276 }
8277 
8278 static char *
exinclude_display_str(val_t * val,int file)8279 exinclude_display_str(
8280     val_t *val,
8281     int    file)
8282 {
8283     am_sl_t  *sl;
8284     sle_t *excl;
8285     char *rval;
8286 
8287     assert(val->type == CONFTYPE_EXINCLUDE);
8288 
8289     rval = stralloc("");
8290 
8291     if (file == 0) {
8292 	sl = val_t__exinclude(val).sl_list;
8293         strappend(rval, "LIST");
8294     } else {
8295 	sl = val_t__exinclude(val).sl_file;
8296         strappend(rval, "FILE");
8297     }
8298 
8299     if (val_t__exinclude(val).optional == 1) {
8300         strappend(rval, " OPTIONAL");
8301     }
8302 
8303     if (sl != NULL) {
8304 	for(excl = sl->first; excl != NULL; excl = excl->next) {
8305 	    char *qstr = quote_string_always(excl->name);
8306             vstrextend(&rval, " ", qstr, NULL);
8307 	    amfree(qstr);
8308 	}
8309     }
8310 
8311     return rval;
8312 }
8313 
8314 char *
taperalgo2str(taperalgo_t taperalgo)8315 taperalgo2str(
8316     taperalgo_t taperalgo)
8317 {
8318     if(taperalgo == ALGO_FIRST) return "FIRST";
8319     if(taperalgo == ALGO_FIRSTFIT) return "FIRSTFIT";
8320     if(taperalgo == ALGO_LARGEST) return "LARGEST";
8321     if(taperalgo == ALGO_LARGESTFIT) return "LARGESTFIT";
8322     if(taperalgo == ALGO_SMALLEST) return "SMALLEST";
8323     if(taperalgo == ALGO_LAST) return "LAST";
8324     return "UNKNOWN";
8325 }
8326 
8327 char *
config_dir_relative(char * filename)8328 config_dir_relative(
8329     char *filename)
8330 {
8331     if (*filename == '/' || config_dir == NULL) {
8332 	return stralloc(filename);
8333     } else {
8334 	if (config_dir[strlen(config_dir)-1] == '/') {
8335 	    return vstralloc(config_dir, filename, NULL);
8336 	} else {
8337 	    return vstralloc(config_dir, "/", filename, NULL);
8338 	}
8339     }
8340 }
8341 
8342 static int
parm_key_info(char * key,conf_var_t ** parm,val_t ** val)8343 parm_key_info(
8344     char *key,
8345     conf_var_t **parm,
8346     val_t **val)
8347 {
8348     conf_var_t *np;
8349     keytab_t *kt;
8350     char *s;
8351     char ch;
8352     char *subsec_type;
8353     char *subsec_name;
8354     char *subsec_key;
8355     tapetype_t *tp;
8356     dumptype_t *dp;
8357     interface_t *ip;
8358     holdingdisk_t *hp;
8359     application_t *ap;
8360     pp_script_t   *pp;
8361     device_config_t   *dc;
8362     changer_config_t   *cc;
8363     taperscan_t        *ts;
8364     interactivity_t    *iv;
8365     int success = FALSE;
8366 
8367     /* WARNING: assumes globals keytable and parsetable are set correctly. */
8368     assert(keytable != NULL);
8369     assert(parsetable != NULL);
8370 
8371     /* make a copy we can stomp on */
8372     key = stralloc(key);
8373 
8374     /* uppercase the key */
8375     for (s = key; (ch = *s) != 0; s++) {
8376 	if (islower((int)ch))
8377 	    *s = (char)toupper(ch);
8378     }
8379 
8380     subsec_name = strchr(key, ':');
8381     if (subsec_name) {
8382 	subsec_type = key;
8383 
8384 	*subsec_name = '\0';
8385 	subsec_name++;
8386 
8387 	/* convert subsec_type '-' to '_' */
8388 	for (s = subsec_type; (ch = *s) != 0; s++) {
8389 	    if (*s == '-') *s = '_';
8390 	}
8391 
8392 	subsec_key = strrchr(subsec_name,':');
8393 	if(!subsec_key) goto out; /* failure */
8394 
8395 	*subsec_key = '\0';
8396 	subsec_key++;
8397 
8398 	/* convert subsec_key '-' to '_' */
8399 	for (s = subsec_key; (ch = *s) != 0; s++) {
8400 	    if (*s == '-') *s = '_';
8401 	}
8402 
8403 	/* If the keyword doesn't exist, there's no need to look up the
8404 	 * subsection -- we know it's invalid */
8405 	for(kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
8406 	    if(kt->keyword && strcmp(kt->keyword, subsec_key) == 0)
8407 		break;
8408 	}
8409 	if(kt->token == CONF_UNKNOWN) goto out;
8410 
8411 	/* Otherwise, figure out which kind of subsection we're dealing with,
8412 	 * and parse against that. */
8413 	if (strcmp(subsec_type, "TAPETYPE") == 0) {
8414 	    tp = lookup_tapetype(subsec_name);
8415 	    if (!tp) goto out;
8416 	    for(np = tapetype_var; np->token != CONF_UNKNOWN; np++) {
8417 		if(np->token == kt->token)
8418 		   break;
8419 	    }
8420 	    if (np->token == CONF_UNKNOWN) goto out;
8421 
8422 	    if (val) *val = &tp->value[np->parm];
8423 	    if (parm) *parm = np;
8424 	    success = TRUE;
8425 	} else if (strcmp(subsec_type, "DUMPTYPE") == 0) {
8426 	    dp = lookup_dumptype(subsec_name);
8427 	    if (!dp) goto out;
8428 	    for(np = dumptype_var; np->token != CONF_UNKNOWN; np++) {
8429 		if(np->token == kt->token)
8430 		   break;
8431 	    }
8432 	    if (np->token == CONF_UNKNOWN) goto out;
8433 
8434 	    if (val) *val = &dp->value[np->parm];
8435 	    if (parm) *parm = np;
8436 	    success = TRUE;
8437 	} else if (strcmp(subsec_type, "HOLDINGDISK") == 0) {
8438 	    hp = lookup_holdingdisk(subsec_name);
8439 	    if (!hp) goto out;
8440 	    for(np = holding_var; np->token != CONF_UNKNOWN; np++) {
8441 		if(np->token == kt->token)
8442 		   break;
8443 	    }
8444 	    if (np->token == CONF_UNKNOWN) goto out;
8445 
8446 	    if (val) *val = &hp->value[np->parm];
8447 	    if (parm) *parm = np;
8448 	    success = TRUE;
8449 	} else if (strcmp(subsec_type, "INTERFACE") == 0) {
8450 	    ip = lookup_interface(subsec_name);
8451 	    if (!ip) goto out;
8452 	    for(np = interface_var; np->token != CONF_UNKNOWN; np++) {
8453 		if(np->token == kt->token)
8454 		   break;
8455 	    }
8456 	    if (np->token == CONF_UNKNOWN) goto out;
8457 
8458 	    if (val) *val = &ip->value[np->parm];
8459 	    if (parm) *parm = np;
8460 	    success = TRUE;
8461 	/* accept the old name here, too */
8462 	} else if (strcmp(subsec_type, "APPLICATION_TOOL") == 0
8463 		|| strcmp(subsec_type, "APPLICATION") == 0) {
8464 	    ap = lookup_application(subsec_name);
8465 	    if (!ap) goto out;
8466 	    for(np = application_var; np->token != CONF_UNKNOWN; np++) {
8467 		if(np->token == kt->token)
8468 		   break;
8469 	    }
8470 	    if (np->token == CONF_UNKNOWN) goto out;
8471 
8472 	    if (val) *val = &ap->value[np->parm];
8473 	    if (parm) *parm = np;
8474 	    success = TRUE;
8475 	/* accept the old name here, too */
8476 	} else if (strcmp(subsec_type, "SCRIPT_TOOL") == 0
8477 		|| strcmp(subsec_type, "SCRIPT") == 0) {
8478 	    pp = lookup_pp_script(subsec_name);
8479 	    if (!pp) goto out;
8480 	    for(np = pp_script_var; np->token != CONF_UNKNOWN; np++) {
8481 		if(np->token == kt->token)
8482 		   break;
8483 	    }
8484 	    if (np->token == CONF_UNKNOWN) goto out;
8485 
8486 	    if (val) *val = &pp->value[np->parm];
8487 	    if (parm) *parm = np;
8488 	    success = TRUE;
8489 	} else if (strcmp(subsec_type, "DEVICE") == 0) {
8490 	    dc = lookup_device_config(subsec_name);
8491 	    if (!dc) goto out;
8492 	    for(np = device_config_var; np->token != CONF_UNKNOWN; np++) {
8493 		if(np->token == kt->token)
8494 		   break;
8495 	    }
8496 	    if (np->token == CONF_UNKNOWN) goto out;
8497 
8498 	    if (val) *val = &dc->value[np->parm];
8499 	    if (parm) *parm = np;
8500 	    success = TRUE;
8501 	} else if (strcmp(subsec_type, "CHANGER") == 0) {
8502 	    cc = lookup_changer_config(subsec_name);
8503 	    if (!cc) goto out;
8504 	    for(np = changer_config_var; np->token != CONF_UNKNOWN; np++) {
8505 		if(np->token == kt->token)
8506 		   break;
8507 	    }
8508 	    if (np->token == CONF_UNKNOWN) goto out;
8509 
8510 	    if (val) *val = &cc->value[np->parm];
8511 	    if (parm) *parm = np;
8512 	    success = TRUE;
8513 	} else if (g_str_equal(subsec_type, "INTERACTIVITY")) {
8514 	    iv = lookup_interactivity(subsec_name);
8515 	    if (!iv) goto out;
8516 	    for(np = interactivity_var; np->token != CONF_UNKNOWN; np++) {
8517 		if(np->token == kt->token)
8518 		   break;
8519 	    }
8520 	    if (np->token == CONF_UNKNOWN) goto out;
8521 
8522 	    if (val) *val = &iv->value[np->parm];
8523 	    if (parm) *parm = np;
8524 	    success = TRUE;
8525 	} else if (g_str_equal(subsec_type, "TAPERSCAN")) {
8526 	    ts = lookup_taperscan(subsec_name);
8527 	    if (!ts) goto out;
8528 	    for(np = taperscan_var; np->token != CONF_UNKNOWN; np++) {
8529 		if(np->token == kt->token)
8530 		   break;
8531 	    }
8532 	    if (np->token == CONF_UNKNOWN) goto out;
8533 
8534 	    if (val) *val = &ts->value[np->parm];
8535 	    if (parm) *parm = np;
8536 	    success = TRUE;
8537 	}
8538 
8539     /* No delimiters -- we're referencing a global config parameter */
8540     } else {
8541 	/* convert key '-' to '_' */
8542 	for (s = key; (ch = *s) != 0; s++) {
8543 	    if (*s == '-') *s = '_';
8544 	}
8545 
8546 	/* look up the keyword */
8547 	for(kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
8548 	    if(kt->keyword && strcmp(kt->keyword, key) == 0)
8549 		break;
8550 	}
8551 	if(kt->token == CONF_UNKNOWN) goto out;
8552 
8553 	/* and then look that up in the parse table */
8554 	for(np = parsetable; np->token != CONF_UNKNOWN; np++) {
8555 	    if(np->token == kt->token)
8556 		break;
8557 	}
8558 	if(np->token == CONF_UNKNOWN) goto out;
8559 
8560 	if (val) *val = &conf_data[np->parm];
8561 	if (parm) *parm = np;
8562 	success = TRUE;
8563     }
8564 
8565 out:
8566     amfree(key);
8567     return success;
8568 }
8569 
8570 gint64
find_multiplier(char * str)8571 find_multiplier(
8572     char * str)
8573 {
8574     keytab_t * table_entry;
8575 
8576     str = g_strdup(str);
8577     g_strstrip(str);
8578 
8579     if (*str == '\0') {
8580         g_free(str);
8581         return 1;
8582     }
8583 
8584     for (table_entry = numb_keytable; table_entry->keyword != NULL;
8585          table_entry ++) {
8586         if (strcasecmp(str, table_entry->keyword) == 0) {
8587             g_free(str);
8588             switch (table_entry->token) {
8589             case CONF_MULT1K:
8590                 return 1024;
8591             case CONF_MULT1M:
8592                 return 1024*1024;
8593             case CONF_MULT1G:
8594                 return 1024*1024*1024;
8595             case CONF_MULT1T:
8596                 return (gint64)1024*1024*1024*1024;
8597             case CONF_MULT7:
8598                 return 7;
8599             case CONF_AMINFINITY:
8600                 return G_MAXINT64;
8601             case CONF_MULT1:
8602             case CONF_IDENT:
8603                 return 1;
8604             default:
8605                 /* Should not happen. */
8606                 return 0;
8607             }
8608         }
8609     }
8610 
8611     /* None found; this is an error. */
8612     g_free(str);
8613     return 0;
8614 }
8615 
8616 int
string_to_boolean(const char * str)8617 string_to_boolean(
8618     const char *str)
8619 {
8620     keytab_t * table_entry;
8621 
8622     if (str == NULL || *str == '\0') {
8623         return -1;
8624     }
8625 
8626     /* 0 and 1 are not in the table, as they are parsed as ints */
8627     if (0 == strcmp(str, "0"))
8628 	return 0;
8629     if (0 == strcmp(str, "1"))
8630 	return 1;
8631 
8632     for (table_entry = bool_keytable; table_entry->keyword != NULL;
8633          table_entry ++) {
8634         if (strcasecmp(str, table_entry->keyword) == 0) {
8635             switch (table_entry->token) {
8636             case CONF_ATRUE:
8637                 return 1;
8638             case CONF_AFALSE:
8639                 return 0;
8640             default:
8641                 return -1;
8642             }
8643         }
8644     }
8645 
8646     return -1;
8647 }
8648 
8649 /*
8650  * Error Handling Implementaiton
8651  */
8652 
config_add_error(cfgerr_level_t level,char * errmsg)8653 void config_add_error(
8654     cfgerr_level_t level,
8655     char * errmsg)
8656 {
8657     cfgerr_level = max(cfgerr_level, level);
8658 
8659     g_debug("%s", errmsg);
8660     cfgerr_errors = g_slist_append(cfgerr_errors, errmsg);
8661 }
8662 
conf_error_common(cfgerr_level_t level,const char * format,va_list argp)8663 static void conf_error_common(
8664     cfgerr_level_t level,
8665     const char * format,
8666     va_list argp)
8667 {
8668     char *msg = g_strdup_vprintf(format, argp);
8669     char *errstr = NULL;
8670 
8671     if(current_line)
8672 	errstr = g_strdup_printf(_("argument \"%s\": %s"),
8673 		    current_line, msg);
8674     else if (current_filename && current_line_num > 0)
8675 	errstr = g_strdup_printf(_("\"%s\", line %d: %s"),
8676 		    current_filename, current_line_num, msg);
8677     else
8678 	errstr = g_strdup_printf(_("parse error: %s"), msg);
8679     amfree(msg);
8680 
8681     config_add_error(level, errstr);
8682 }
8683 
printf_arglist_function(void conf_parserror,const char *,format)8684 printf_arglist_function(void conf_parserror, const char *, format)
8685 {
8686     va_list argp;
8687 
8688     arglist_start(argp, format);
8689     conf_error_common(CFGERR_ERRORS, format, argp);
8690     arglist_end(argp);
8691 }
8692 
printf_arglist_function(void conf_parswarn,const char *,format)8693 printf_arglist_function(void conf_parswarn, const char *, format) {
8694     va_list argp;
8695 
8696     arglist_start(argp, format);
8697     conf_error_common(CFGERR_WARNINGS, format, argp);
8698     arglist_end(argp);
8699 }
8700 
8701 cfgerr_level_t
config_errors(GSList ** errstr)8702 config_errors(GSList **errstr)
8703 {
8704     if (errstr)
8705 	*errstr = cfgerr_errors;
8706     return cfgerr_level;
8707 }
8708 
8709 void
config_clear_errors(void)8710 config_clear_errors(void)
8711 {
8712     slist_free_full(cfgerr_errors, g_free);
8713 
8714     cfgerr_errors = NULL;
8715     cfgerr_level = CFGERR_OK;
8716 }
8717 
8718 void
config_print_errors(void)8719 config_print_errors(void)
8720 {
8721     GSList *iter;
8722 
8723     for (iter = cfgerr_errors; iter; iter = g_slist_next(iter)) {
8724 	g_fprintf(stderr, "%s\n", (char *)iter->data);
8725     }
8726 }
8727 
8728 /* Get the config name */
get_config_name(void)8729 char *get_config_name(void)
8730 {
8731     return config_name;
8732 }
8733 
8734 /* Get the config directory */
get_config_dir(void)8735 char *get_config_dir(void)
8736 {
8737     return config_dir;
8738 }
8739 
8740 /* Get the config filename */
get_config_filename(void)8741 char *get_config_filename(void)
8742 {
8743     return config_filename;
8744 }
8745 
8746 char *
anonymous_value(void)8747 anonymous_value(void)
8748 {
8749     static char number[NUM_STR_SIZE];
8750     static int value=1;
8751 
8752     g_snprintf(number, sizeof(number), "%d", value);
8753 
8754     value++;
8755     return number;
8756 }
8757 
compare_pp_script_order(gconstpointer a,gconstpointer b)8758 gint compare_pp_script_order(
8759     gconstpointer a,
8760     gconstpointer b)
8761 {
8762     return pp_script_get_order(lookup_pp_script((char *)a)) > pp_script_get_order(lookup_pp_script((char *)b));
8763 }
8764 
8765 char *
data_path_to_string(data_path_t data_path)8766 data_path_to_string(
8767     data_path_t data_path)
8768 {
8769     switch (data_path) {
8770 	case DATA_PATH_AMANDA   : return "AMANDA";
8771 	case DATA_PATH_DIRECTTCP: return "DIRECTTCP";
8772     }
8773     error(_("datapath is not DATA_PATH_AMANDA or DATA_PATH_DIRECTTCP"));
8774     /* NOTREACHED */
8775 }
8776 
8777 data_path_t
data_path_from_string(char * data)8778 data_path_from_string(
8779     char *data)
8780 {
8781     if (strcmp(data, "AMANDA") == 0)
8782 	return DATA_PATH_AMANDA;
8783     if (strcmp(data, "DIRECTTCP") == 0)
8784 	return DATA_PATH_DIRECTTCP;
8785     error(_("datapath is not AMANDA or DIRECTTCP :%s:"), data);
8786     /* NOTREACHED */
8787 }
8788 
8789 gchar *
amandaify_property_name(const gchar * name)8790 amandaify_property_name(
8791     const gchar *name)
8792 {
8793     gchar *ret, *cur_r;
8794     const gchar *cur_o;
8795     if (!name) return NULL;
8796 
8797     ret = g_malloc0(strlen(name)+1);
8798     cur_r = ret;
8799     for (cur_o = name; *cur_o; cur_o++) {
8800 	if ('_' == *cur_o)
8801 	    *cur_r = '-';
8802 	else
8803 	    *cur_r = g_ascii_tolower(*cur_o);
8804 
8805 	cur_r++;
8806     }
8807 
8808     return ret;
8809 }
8810 
8811 static char keyword_str[1024];
8812 
8813 static char *
str_keyword(keytab_t * kt)8814 str_keyword(
8815     keytab_t *kt)
8816 {
8817     char *p = kt->keyword;
8818     char *s = keyword_str;
8819 
8820     while(*p != '\0') {
8821 	if (*p == '_') {
8822 	    *s = '-';
8823 	} else {
8824 	    *s = *p;
8825 	}
8826 	p++;
8827 	s++;
8828     }
8829     *s = '\0';
8830 
8831     return keyword_str;
8832 }
8833