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 ©_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 ©_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