X-Git-Url: https://git.gag.com/?a=blobdiff_plain;f=common-src%2Fconffile.c;h=2cc9cba4af08b9f56fd59bea8f0c5def55f48b60;hb=94a044f90357edefa6f4ae9f0b1d5885b0e34aee;hp=986d9b46bbdbdf43b7a4b50d1abb64b80bfe0ace;hpb=d3b2175e084f88c8736ad7073eacbf4670147aec;p=debian%2Famanda diff --git a/common-src/conffile.c b/common-src/conffile.c index 986d9b4..2cc9cba 100644 --- a/common-src/conffile.c +++ b/common-src/conffile.c @@ -36,223 +36,553 @@ #include "conffile.h" #include "clock.h" -#ifdef HAVE_LIMITS_H -#include -#endif - -#ifndef AMANDATES_FILE -#define AMANDATES_FILE "/etc/amandates" -#endif +/* + * Lexical analysis + */ -#ifndef INT_MAX -#define INT_MAX 2147483647 -#endif +/* This module implements its own quixotic lexer and parser, present for historical + * reasons. If this were written from scratch, it would use flex/bison. */ -/* this corresponds to the normal output of amanda, but may - * be adapted to any spacing as you like. +/* An enumeration of the various tokens that might appear in a configuration file. + * + * - CONF_UNKNOWN has special meaning as an unrecognized token. + * - CONF_ANY can be used to request any token, rather than requiring a specific + * token. */ -ColumnInfo ColumnData[] = { - { "HostName", 0, 12, 12, 0, "%-*.*s", "HOSTNAME" }, - { "Disk", 1, 11, 11, 0, "%-*.*s", "DISK" }, - { "Level", 1, 1, 1, 0, "%*.*d", "L" }, - { "OrigKB", 1, 7, 0, 0, "%*.*lf", "ORIG-KB" }, - { "OutKB", 1, 7, 0, 0, "%*.*lf", "OUT-KB" }, - { "Compress", 1, 6, 1, 0, "%*.*lf", "COMP%" }, - { "DumpTime", 1, 7, 7, 0, "%*.*s", "MMM:SS" }, - { "DumpRate", 1, 6, 1, 0, "%*.*lf", "KB/s" }, - { "TapeTime", 1, 6, 6, 0, "%*.*s", "MMM:SS" }, - { "TapeRate", 1, 6, 1, 0, "%*.*lf", "KB/s" }, - { NULL, 0, 0, 0, 0, NULL, NULL } -}; +typedef enum { + CONF_UNKNOWN, CONF_ANY, CONF_COMMA, + CONF_LBRACE, CONF_RBRACE, CONF_NL, + CONF_END, CONF_IDENT, CONF_INT, + CONF_AM64, CONF_BOOL, CONF_REAL, + CONF_STRING, CONF_TIME, CONF_SIZE, + + /* config parameters */ + CONF_INCLUDEFILE, CONF_ORG, CONF_MAILTO, + CONF_DUMPUSER, CONF_TAPECYCLE, CONF_TAPEDEV, + CONF_CHANGERDEV, CONF_CHANGERFILE, CONF_LABELSTR, + CONF_BUMPPERCENT, CONF_BUMPSIZE, CONF_BUMPDAYS, + CONF_BUMPMULT, CONF_ETIMEOUT, CONF_DTIMEOUT, + CONF_CTIMEOUT, CONF_TAPEBUFS, CONF_TAPELIST, + CONF_DEVICE_OUTPUT_BUFFER_SIZE, + CONF_DISKFILE, CONF_INFOFILE, CONF_LOGDIR, + CONF_LOGFILE, CONF_DISKDIR, CONF_DISKSIZE, + CONF_INDEXDIR, CONF_NETUSAGE, CONF_INPARALLEL, + CONF_DUMPORDER, CONF_TIMEOUT, CONF_TPCHANGER, + CONF_RUNTAPES, CONF_DEFINE, CONF_DUMPTYPE, + CONF_TAPETYPE, CONF_INTERFACE, CONF_PRINTER, + CONF_AUTOFLUSH, CONF_RESERVE, CONF_MAXDUMPSIZE, + CONF_COLUMNSPEC, CONF_AMRECOVER_DO_FSF, CONF_AMRECOVER_CHECK_LABEL, + CONF_AMRECOVER_CHANGER, CONF_LABEL_NEW_TAPES, CONF_USETIMESTAMPS, + + CONF_TAPERALGO, CONF_FIRST, CONF_FIRSTFIT, + CONF_LARGEST, CONF_LARGESTFIT, CONF_SMALLEST, + CONF_LAST, CONF_DISPLAYUNIT, CONF_RESERVED_UDP_PORT, + CONF_RESERVED_TCP_PORT, CONF_UNRESERVED_TCP_PORT, + CONF_TAPERFLUSH, + CONF_FLUSH_THRESHOLD_DUMPED, + CONF_FLUSH_THRESHOLD_SCHEDULED, + CONF_DEVICE_PROPERTY, + + /* kerberos 5 */ + CONF_KRB5KEYTAB, CONF_KRB5PRINCIPAL, + + /* holding disk */ + CONF_COMMENT, CONF_DIRECTORY, CONF_USE, + CONF_CHUNKSIZE, + + /* dump type */ + /*COMMENT,*/ CONF_PROGRAM, CONF_DUMPCYCLE, + CONF_RUNSPERCYCLE, CONF_MAXCYCLE, CONF_MAXDUMPS, + CONF_OPTIONS, CONF_PRIORITY, CONF_FREQUENCY, + CONF_INDEX, CONF_MAXPROMOTEDAY, CONF_STARTTIME, + CONF_COMPRESS, CONF_ENCRYPT, CONF_AUTH, + CONF_STRATEGY, CONF_ESTIMATE, CONF_SKIP_INCR, + CONF_SKIP_FULL, CONF_RECORD, CONF_HOLDING, + CONF_EXCLUDE, CONF_INCLUDE, CONF_KENCRYPT, + CONF_IGNORE, CONF_COMPRATE, CONF_TAPE_SPLITSIZE, + CONF_SPLIT_DISKBUFFER, CONF_FALLBACK_SPLITSIZE,CONF_SRVCOMPPROG, + CONF_CLNTCOMPPROG, CONF_SRV_ENCRYPT, CONF_CLNT_ENCRYPT, + CONF_SRV_DECRYPT_OPT, CONF_CLNT_DECRYPT_OPT, CONF_AMANDAD_PATH, + CONF_CLIENT_USERNAME, + + /* tape type */ + /*COMMENT,*/ CONF_BLOCKSIZE, CONF_FILE_PAD, + CONF_LBL_TEMPL, CONF_FILEMARK, CONF_LENGTH, + CONF_SPEED, CONF_READBLOCKSIZE, + + /* client conf */ + CONF_CONF, CONF_INDEX_SERVER, CONF_TAPE_SERVER, + CONF_SSH_KEYS, CONF_GNUTAR_LIST_DIR, CONF_AMANDATES, + + /* protocol config */ + CONF_REP_TRIES, CONF_CONNECT_TRIES, CONF_REQ_TRIES, + + /* debug config */ + CONF_DEBUG_AMANDAD, CONF_DEBUG_AMIDXTAPED, CONF_DEBUG_AMINDEXD, + CONF_DEBUG_AMRECOVER, CONF_DEBUG_AUTH, CONF_DEBUG_EVENT, + CONF_DEBUG_HOLDING, CONF_DEBUG_PROTOCOL, CONF_DEBUG_PLANNER, + CONF_DEBUG_DRIVER, CONF_DEBUG_DUMPER, CONF_DEBUG_CHUNKER, + CONF_DEBUG_TAPER, CONF_DEBUG_SELFCHECK, CONF_DEBUG_SENDSIZE, + CONF_DEBUG_SENDBACKUP, + + /* network interface */ + /* COMMENT, */ /* USE, */ + + /* dump options (obsolete) */ + CONF_EXCLUDE_FILE, CONF_EXCLUDE_LIST, + + /* compress, estimate, encryption */ + CONF_NONE, CONF_FAST, CONF_BEST, + CONF_SERVER, CONF_CLIENT, CONF_CALCSIZE, + CONF_CUSTOM, + + /* holdingdisk */ + CONF_NEVER, CONF_AUTO, CONF_REQUIRED, + + /* priority */ + CONF_LOW, CONF_MEDIUM, CONF_HIGH, + + /* dump strategy */ + CONF_SKIP, CONF_STANDARD, CONF_NOFULL, + CONF_NOINC, CONF_HANOI, CONF_INCRONLY, + + /* exclude list */ + CONF_LIST, CONF_EFILE, CONF_APPEND, + CONF_OPTIONAL, + + /* numbers */ + CONF_AMINFINITY, CONF_MULT1, CONF_MULT7, + CONF_MULT1K, CONF_MULT1M, CONF_MULT1G, + + /* boolean */ + CONF_ATRUE, CONF_AFALSE +} tok_t; + +/* A keyword table entry, mapping the given keyword to the given token. + * Note that punctuation, integers, and quoted strings are handled + * internally to the lexer, so they do not appear here. */ +typedef struct { + char *keyword; + tok_t token; +} keytab_t; + +/* The current keyword table, used by all token-related functions */ +static keytab_t *keytable = NULL; -char *config_name = NULL; -char *config_dir = NULL; +/* Has a token been "ungotten", and if so, what was it? */ +static int token_pushed; +static tok_t pushed_tok; -int debug_amandad = 0; -int debug_amidxtaped = 0; -int debug_amindexd = 0; -int debug_amrecover = 0; -int debug_auth = 0; -int debug_event = 0; -int debug_holding = 0; -int debug_protocol = 0; -int debug_planner = 0; -int debug_driver = 0; -int debug_dumper = 0; -int debug_chunker = 0; -int debug_taper = 0; -int debug_selfcheck = 0; -int debug_sendsize = 0; -int debug_sendbackup = 0; +/* The current token and its value. Note that, unlike most other val_t*, + * tokenval's v.s points to statically allocated memory which cannot be + * free()'d. */ +static tok_t tok; +static val_t tokenval; -/* visible holding disk variables */ +/* The current input information: file, filename, line, and character + * (which points somewhere within current_line) */ +static FILE *current_file = NULL; +static char *current_filename = NULL; +static char *current_line = NULL; +static char *current_char = NULL; +static int current_line_num = 0; /* (technically, managed by the parser) */ -holdingdisk_t *holdingdisks; -int num_holdingdisks; +/* A static buffer for storing tokens while they are being scanned. */ +static char tkbuf[4096]; -long int unit_divisor = 1; +/* Look up the name of the given token in the current keytable */ +static char *get_token_name(tok_t); -/* configuration parameters */ +/* Look up a token in keytable, given a string, returning CONF_UNKNOWN + * for unrecognized strings. Search is case-insensitive. */ +static tok_t lookup_keyword(char *str); -val_t conf_data[CNF_CNF]; -int conffile_init = 0; +/* Get the next token. If exp is anything but CONF_ANY, and the next token + * does not match, then a parse error is flagged. This function reads from the + * current_* static variables, recognizes keywords against the keytable static + * variable, and places its result in tok and tokenval. */ +static void get_conftoken(tok_t exp); -command_option_t *program_options = NULL; -int program_options_size = 0; +/* "Unget" the current token; this supports a 1-token lookahead. */ +static void unget_conftoken(void); -/* other internal variables */ -static holdingdisk_t hdcur; +/* Tokenizer character-by-character access. */ +static int conftoken_getc(void); +static int conftoken_ungetc(int c); -static tapetype_t tpcur; +/* + * Parser + */ -static dumptype_t dpcur; +/* A parser table entry. Read as " introduces parameter , + * the data for which will be read by and validated by + * (if not NULL). is only used in formatting + * config overwrites. */ +typedef struct conf_var_s { + tok_t token; + conftype_t type; + void (*read_function) (struct conf_var_s *, val_t*); + int parm; + void (*validate_function) (struct conf_var_s *, val_t *); +} conf_var_t; + +/* If allow_overwrites is true, the a parameter which has already been + * seen will simply overwrite the old value, rather than triggering an + * error. Note that this does not apply to all parameters, e.g., + * device_property */ +static int allow_overwrites; -static interface_t ifcur; +/* subsection structs + * + * The 'seen' fields in these structs are useless outside this module; + * they are only used to generate error messages for multiply defined + * subsections. + */ +struct tapetype_s { + struct tapetype_s *next; + int seen; + char *name; -static dumptype_t *dumplist = NULL; -static tapetype_t *tapelist = NULL; -static interface_t *interface_list = NULL; + val_t value[TAPETYPE_TAPETYPE]; +}; -static int allow_overwrites; -static int token_pushed; -static tok_t tok, pushed_tok; -static val_t tokenval; +struct dumptype_s { + struct dumptype_s *next; + int seen; + char *name; -static int conf_line_num; -static int got_parserror; -static FILE *conf_conf = (FILE *)NULL; -static char *conf_confname = NULL; -static char *conf_line = NULL; -static char *conf_char = NULL; -static keytab_t *keytable = NULL; + val_t value[DUMPTYPE_DUMPTYPE]; +}; -/* predeclare local functions */ +struct interface_s { + struct interface_s *next; + int seen; + char *name; -char *get_token_name(tok_t); + val_t value[INTER_INTER]; +}; +struct holdingdisk_s { + struct holdingdisk_s *next; + int seen; + char *name; -static void validate_positive0 (t_conf_var *, val_t *); -static void validate_positive1 (t_conf_var *, val_t *); -static void validate_runspercycle (t_conf_var *, val_t *); -static void validate_bumppercent (t_conf_var *, val_t *); -static void validate_bumpmult (t_conf_var *, val_t *); -static void validate_inparallel (t_conf_var *, val_t *); -static void validate_displayunit (t_conf_var *, val_t *); -static void validate_reserve (t_conf_var *, val_t *); -static void validate_use (t_conf_var *, val_t *); -static void validate_chunksize (t_conf_var *, val_t *); -static void validate_blocksize (t_conf_var *, val_t *); -static void validate_debug (t_conf_var *, val_t *); -static void validate_reserved_port_range (t_conf_var *, val_t *); -static void validate_unreserved_port_range(t_conf_var *, val_t *); + val_t value[HOLDING_HOLDING]; +}; -/*static t_conf_var *get_np(t_conf_var *get_var, int parm);*/ -static int get_int(void); -/*static long get_long(void);*/ -static time_t get_time(void); -static ssize_t get_size(void); -static off_t get_am64_t(void); -static int get_bool(void); -static void ckseen(int *seen); -static void conf_parserror(const char *format, ...) - __attribute__ ((format (printf, 1, 2))); -static tok_t lookup_keyword(char *str); - -static void read_string(t_conf_var *, val_t *); -static void read_ident(t_conf_var *, val_t *); -static void read_int(t_conf_var *, val_t *); -/*static void read_long(t_conf_var *, val_t *);*/ -static void read_size(t_conf_var *, val_t *); -static void read_am64(t_conf_var *, val_t *); -static void read_bool(t_conf_var *, val_t *); -static void read_real(t_conf_var *, val_t *); -static void read_time(t_conf_var *, val_t *); -static void read_intrange(t_conf_var *, val_t *); -static void conf_init_string(val_t *, char *); -static void conf_init_ident(val_t *, char *); -static void conf_init_int(val_t *, int); -static void conf_init_bool(val_t *, int); -static void conf_init_strategy(val_t *, int); -static void conf_init_estimate(val_t *, int); -static void conf_init_taperalgo(val_t *, int); -static void conf_init_priority(val_t *, int); -static void conf_init_strategy(val_t *, int); -static void conf_init_compress(val_t *, comp_t); -static void conf_init_encrypt(val_t *, encrypt_t); -static void conf_init_holding(val_t *, dump_holdingdisk_t); -/*static void conf_init_long(val_t *, long);*/ -static void conf_init_size(val_t *, ssize_t); -static void conf_init_am64(val_t *, off_t); -static void conf_init_real(val_t *, double); -static void conf_init_rate(val_t *, double, double); -static void conf_init_intrange(val_t *, int, int); -static void conf_init_time(val_t *, time_t); -/*static void conf_init_sl(val_t *, sl_t *);*/ -static void conf_init_exinclude(val_t *); -static void conf_set_string(val_t *, char *); -/*static void conf_set_int(val_t *, int);*/ -static void conf_set_bool(val_t *, int); -static void conf_set_compress(val_t *, comp_t); -/*static void conf_set_encrypt(val_t *, encrypt_t);*/ -static void conf_set_holding(val_t *, dump_holdingdisk_t); -static void conf_set_strategy(val_t *, int); +/* The current parser table */ +static conf_var_t *parsetable = NULL; -static void init_defaults(void); -static void read_conffile_recursively(char *filename); -static void read_client_conffile_recursively(char *filename); +/* Read and parse a configuration file, recursively reading any included + * files. This function sets the keytable and parsetable appropriately + * according to is_client. + * + * @param filename: configuration file to read + * @param is_client: true if this is a client + * @returns: false if an error occurred + */ +static gboolean read_conffile(char *filename, + gboolean is_client); + +/* Read and process a line of input from the current file, using the + * current keytable and parsetable. For blocks, this recursively + * reads the entire block. + * + * @param is_client: true if this is a client + * @returns: true on success, false on EOF or error + */ +static gboolean read_confline(gboolean is_client); -static int read_confline(void); -static int read_client_confline(void); +/* Handle an invalid token, by issuing a warning or an error, depending + * on how long the token has been deprecated. + * + * @param token: the identifier + */ +static void handle_invalid_keyword(const char * token); -static void read_block(command_option_t *command_options, t_conf_var *read_var, - keytab_t *keytab, val_t *valarray, char *prefix, +/* Read a brace-delimited block using the given parse table. This + * function is used to read brace-delimited subsections in the config + * files and also (via read_dumptype) to read dumptypes from + * the disklist. + * + * This function implements "inheritance" as follows: if a bare + * identifier occurs within the braces, it calls copy_function (if + * not NULL), which looks up an existing subsection using the + * identifier from tokenval and copies any values not already seen + * into valarray. + * + * @param read_var: the parse table to use + * @param valarray: the (pre-initialized) val_t array to fill in + * @param errormsg: error message to display for unrecognized keywords + * @param read_brace: if true, read the opening brace + * @param copy_function: function to copy configuration from + * another subsection into this one. + */ +static void read_block(conf_var_t *read_var, val_t *valarray, char *errormsg, int read_brace, void (*copy_function)(void)); -static void copy_val_t(val_t *, val_t *); -static void free_val_t(val_t *); -static char *conf_print(val_t *, int, char *); -static void conf_print_exinclude(val_t *, int, int, char *prefix, char **buf, int *free_space); - +/* For each subsection type, we have a global and four functions: + * - foocur is a temporary struct used to assemble new subsections + * - get_foo is called after reading "DEFINE FOO", and + * is responsible for reading the entire block, using + * read_block() + * - init_foo_defaults initializes a new subsection struct + * to its default values + * - save_foo copies foocur to a newly allocated struct and + * inserts that into the relevant list. + * - copy_foo implements inheritance as described in read_block() + */ +static holdingdisk_t hdcur; static void get_holdingdisk(void); static void init_holdingdisk_defaults(void); static void save_holdingdisk(void); +/* (holdingdisks don't support inheritance) */ + +static dumptype_t dpcur; static void get_dumptype(void); static void init_dumptype_defaults(void); static void save_dumptype(void); static void copy_dumptype(void); + +static tapetype_t tpcur; static void get_tapetype(void); static void init_tapetype_defaults(void); static void save_tapetype(void); static void copy_tapetype(void); + +static interface_t ifcur; static void get_interface(void); static void init_interface_defaults(void); static void save_interface(void); static void copy_interface(void); -static void get_comprate(t_conf_var *, val_t *); -static void get_compress(t_conf_var *, val_t *); -static void get_encrypt (t_conf_var *, val_t *); -static void get_holding (t_conf_var *, val_t *); -static void get_priority(t_conf_var *, val_t *); -static void get_strategy(t_conf_var *, val_t *); -static void get_estimate(t_conf_var *, val_t *); -static void get_exclude (t_conf_var *, val_t *); -/*static void get_include(t_conf_var *, val_t *);*/ -static void get_taperalgo(t_conf_var *, val_t *); -static int conftoken_getc(void); -static int conftoken_ungetc(int c); -static void unget_conftoken(void); -static void get_conftoken(tok_t exp); +/* read_functions -- these fit into the read_function slot in a parser + * table entry, and are responsible for calling getconf_token as necessary + * to consume their arguments, and setting their second argument with the + * result. The first argument is a copy of the parser table entry, if + * needed. */ +static void read_int(conf_var_t *, val_t *); +static void read_am64(conf_var_t *, val_t *); +static void read_real(conf_var_t *, val_t *); +static void read_str(conf_var_t *, val_t *); +static void read_ident(conf_var_t *, val_t *); +static void read_time(conf_var_t *, val_t *); +static void read_size(conf_var_t *, val_t *); +static void read_bool(conf_var_t *, val_t *); +static void read_compress(conf_var_t *, val_t *); +static void read_encrypt(conf_var_t *, val_t *); +static void read_holding(conf_var_t *, val_t *); +static void read_estimate(conf_var_t *, val_t *); +static void read_strategy(conf_var_t *, val_t *); +static void read_taperalgo(conf_var_t *, val_t *); +static void read_priority(conf_var_t *, val_t *); +static void read_rate(conf_var_t *, val_t *); +static void read_exinclude(conf_var_t *, val_t *); +static void read_intrange(conf_var_t *, val_t *); +static void read_property(conf_var_t *, val_t *); + +/* Functions to get various types of values. These are called by + * read_functions to take care of any variations in the way that these + * values can be written: integers can have units, boolean values can be + * specified with a number of names, etc. They form utility functions + * for the read_functions, below. */ +static time_t get_time(void); +static int get_int(void); +static ssize_t get_size(void); +static off_t get_am64_t(void); +static int get_bool(void); + +/* Check the given 'seen', flagging an error if this value has already + * been seen and allow_overwrites is false. Also marks the value as + * seen on the current line. + * + * @param seen: (in/out) seen value to adjust + */ +static void ckseen(int *seen); + +/* validate_functions -- these fit into the validate_function solt in + * a parser table entry. They call conf_parserror if the value in their + * second argument is invalid. */ +static void validate_nonnegative(conf_var_t *, val_t *); +static void validate_positive(conf_var_t *, val_t *); +static void validate_runspercycle(conf_var_t *, val_t *); +static void validate_bumppercent(conf_var_t *, val_t *); +static void validate_bumpmult(conf_var_t *, val_t *); +static void validate_inparallel(conf_var_t *, val_t *); +static void validate_displayunit(conf_var_t *, val_t *); +static void validate_reserve(conf_var_t *, val_t *); +static void validate_use(conf_var_t *, val_t *); +static void validate_chunksize(conf_var_t *, val_t *); +static void validate_blocksize(conf_var_t *, val_t *); +static void validate_debug(conf_var_t *, val_t *); +static void validate_port_range(val_t *, int, int); +static void validate_reserved_port_range(conf_var_t *, val_t *); +static void validate_unreserved_port_range(conf_var_t *, val_t *); + +/* + * Initialization + */ + +/* Name of the current configuration (part of API) */ +char *config_name = NULL; + +/* Current configuration directory (part of API) */ +char *config_dir = NULL; + +/* Current toplevel configuration file (part of API) */ +char *config_filename = NULL; + +/* Has the config been initialized? */ +static gboolean config_initialized = FALSE; + +/* Are we running a client? (true if last init was + * with CONFIG_INIT_CLIENT) */ +static gboolean config_client = FALSE; + +/* What config overwrites are applied? */ +static config_overwrites_t *applied_config_overwrites = NULL; + +/* All global parameters */ +static val_t conf_data[CNF_CNF]; + +/* Linked list of holding disks */ +static holdingdisk_t *holdinglist = NULL; +static dumptype_t *dumplist = NULL; +static tapetype_t *tapelist = NULL; +static interface_t *interface_list = NULL; + +/* storage for derived values */ +static long int unit_divisor = 1; + +int debug_amandad = 0; +int debug_amidxtaped = 0; +int debug_amindexd = 0; +int debug_amrecover = 0; +int debug_auth = 0; +int debug_event = 0; +int debug_holding = 0; +int debug_protocol = 0; +int debug_planner = 0; +int debug_driver = 0; +int debug_dumper = 0; +int debug_chunker = 0; +int debug_taper = 0; +int debug_selfcheck = 0; +int debug_sendsize = 0; +int debug_sendbackup = 0; -keytab_t *my_keytab = NULL; -t_conf_var *my_var = NULL; +/* Reset all configuration values to their defaults (which, in many + * cases, come from --with-foo options at build time) */ +static void init_defaults(void); + +/* Update all dervied values based on the current configuration. This + * function can be called multiple times, once after each adjustment + * to the current configuration. + * + * @param is_client: are we running a client? + */ +static void update_derived_values(gboolean is_client); + +/* per-type conf_init functions, used as utilities for init_defaults + * and for each subsection's init_foo_defaults. + * + * These set the value's type and seen flags, as well as copying + * the relevant value into the 'v' field. + */ +static void conf_init_int(val_t *val, int i); +static void conf_init_am64(val_t *val, off_t l); +static void conf_init_real(val_t *val, float r); +static void conf_init_str(val_t *val, char *s); +static void conf_init_ident(val_t *val, char *s); +static void conf_init_time(val_t *val, time_t t); +static void conf_init_size(val_t *val, ssize_t sz); +static void conf_init_bool(val_t *val, int i); +static void conf_init_compress(val_t *val, comp_t i); +static void conf_init_encrypt(val_t *val, encrypt_t i); +static void conf_init_holding(val_t *val, dump_holdingdisk_t i); +static void conf_init_estimate(val_t *val, estimate_t i); +static void conf_init_strategy(val_t *val, strategy_t); +static void conf_init_taperalgo(val_t *val, taperalgo_t i); +static void conf_init_priority(val_t *val, int i); +static void conf_init_rate(val_t *val, float r1, float r2); +static void conf_init_exinclude(val_t *val); /* to empty list */ +static void conf_init_intrange(val_t *val, int i1, int i2); +static void conf_init_proplist(val_t *val); /* to empty list */ + +/* + * Command-line Handling + */ + +typedef struct config_overwrite_s { + char *key; + char *value; +} config_overwrite_t; + +struct config_overwrites_s { + int n_allocated; + int n_used; + config_overwrite_t *ovr; +}; + +/* + * val_t Management + */ + +static void copy_val_t(val_t *, val_t *); +static void free_val_t(val_t *); + +/* + * Utilities + */ + + +/* Utility functions/structs for val_t_display_strs */ +static char *exinclude_display_str(val_t *val, int file); +static void proplist_display_str_foreach_fn(gpointer key_p, gpointer value_p, gpointer user_data_p); +static void val_t_print_token(FILE *output, char *prefix, char *format, keytab_t *kt, val_t *val); + +/* Given a key name as used in config overwrites, return a pointer to the corresponding + * conf_var_t in the current parsetable, and the val_t representing that value. This + * function will access subsections if key has the form TYPE:SUBSEC:KEYWORD. Returns + * false if the value does not exist. + * + * Assumes keytable and parsetable are set correctly, which is generally OK after + * config_init has been called. + * + * @param key: the key to look up + * @param parm: (result) the parse table entry + * @param val: (result) the parameter value + * @returns: true on success + */ +static int parm_key_info(char *key, conf_var_t **parm, val_t **val); + +/* + * Error handling + */ + +/* Have we seen a parse error yet? Parsing continues after an error, so this + * flag is checked after the parse is complete. + */ +static gboolean got_parserror; + +static void conf_parserror(const char *format, ...) + __attribute__ ((format (printf, 1, 2))); + +static void conf_parswarn(const char *format, ...) + __attribute__ ((format (printf, 1, 2))); + +/* + * Tables + */ +/* First, the keyword tables for client and server */ keytab_t client_keytab[] = { { "CONF", CONF_CONF }, { "INDEX_SERVER", CONF_INDEX_SERVER }, { "TAPE_SERVER", CONF_TAPE_SERVER }, { "TAPEDEV", CONF_TAPEDEV }, + { "DEVICE-PROPERTY", CONF_DEVICE_PROPERTY }, { "AUTH", CONF_AUTH }, { "SSH_KEYS", CONF_SSH_KEYS }, { "AMANDAD_PATH", CONF_AMANDAD_PATH }, @@ -281,46 +611,12 @@ keytab_t client_keytab[] = { { "DEBUG_SELFCHECK", CONF_DEBUG_SELFCHECK }, { "DEBUG_SENDSIZE", CONF_DEBUG_SENDSIZE }, { "DEBUG_SENDBACKUP", CONF_DEBUG_SENDBACKUP }, + { "RESERVED-UDP-PORT", CONF_RESERVED_UDP_PORT }, + { "RESERVED-TCP-PORT", CONF_RESERVED_TCP_PORT }, { "UNRESERVED-TCP-PORT", CONF_UNRESERVED_TCP_PORT }, { NULL, CONF_UNKNOWN }, }; -t_conf_var client_var [] = { - { CONF_CONF , CONFTYPE_STRING , read_string , CNF_CONF , NULL }, - { CONF_INDEX_SERVER , CONFTYPE_STRING , read_string , CNF_INDEX_SERVER , NULL }, - { CONF_TAPE_SERVER , CONFTYPE_STRING , read_string , CNF_TAPE_SERVER , NULL }, - { CONF_TAPEDEV , CONFTYPE_STRING , read_string , CNF_TAPEDEV , NULL }, - { CONF_AUTH , CONFTYPE_STRING , read_string , CNF_AUTH , NULL }, - { CONF_SSH_KEYS , CONFTYPE_STRING , read_string , CNF_SSH_KEYS , NULL }, - { CONF_AMANDAD_PATH , CONFTYPE_STRING , read_string , CNF_AMANDAD_PATH , NULL }, - { CONF_CLIENT_USERNAME , CONFTYPE_STRING , read_string , CNF_CLIENT_USERNAME , NULL }, - { CONF_GNUTAR_LIST_DIR , CONFTYPE_STRING , read_string , CNF_GNUTAR_LIST_DIR , NULL }, - { CONF_AMANDATES , CONFTYPE_STRING , read_string , CNF_AMANDATES , NULL }, - { CONF_KRB5KEYTAB , CONFTYPE_STRING , read_string , CNF_KRB5KEYTAB , NULL }, - { CONF_KRB5PRINCIPAL , CONFTYPE_STRING , read_string , CNF_KRB5PRINCIPAL , NULL }, - { CONF_CONNECT_TRIES , CONFTYPE_INT , read_int , CNF_CONNECT_TRIES , validate_positive1 }, - { CONF_REP_TRIES , CONFTYPE_INT , read_int , CNF_REP_TRIES , validate_positive1 }, - { CONF_REQ_TRIES , CONFTYPE_INT , read_int , CNF_REQ_TRIES , validate_positive1 }, - { CONF_DEBUG_AMANDAD , CONFTYPE_INT , read_int , CNF_DEBUG_AMANDAD , validate_debug }, - { CONF_DEBUG_AMIDXTAPED , CONFTYPE_INT , read_int , CNF_DEBUG_AMIDXTAPED , validate_debug }, - { CONF_DEBUG_AMINDEXD , CONFTYPE_INT , read_int , CNF_DEBUG_AMINDEXD , validate_debug }, - { CONF_DEBUG_AMRECOVER , CONFTYPE_INT , read_int , CNF_DEBUG_AMRECOVER , validate_debug }, - { CONF_DEBUG_AUTH , CONFTYPE_INT , read_int , CNF_DEBUG_AUTH , validate_debug }, - { CONF_DEBUG_EVENT , CONFTYPE_INT , read_int , CNF_DEBUG_EVENT , validate_debug }, - { CONF_DEBUG_HOLDING , CONFTYPE_INT , read_int , CNF_DEBUG_HOLDING , validate_debug }, - { CONF_DEBUG_PROTOCOL , CONFTYPE_INT , read_int , CNF_DEBUG_PROTOCOL , validate_debug }, - { CONF_DEBUG_PLANNER , CONFTYPE_INT , read_int , CNF_DEBUG_PLANNER , validate_debug }, - { CONF_DEBUG_DRIVER , CONFTYPE_INT , read_int , CNF_DEBUG_DRIVER , validate_debug }, - { CONF_DEBUG_DUMPER , CONFTYPE_INT , read_int , CNF_DEBUG_DUMPER , validate_debug }, - { CONF_DEBUG_CHUNKER , CONFTYPE_INT , read_int , CNF_DEBUG_CHUNKER , validate_debug }, - { CONF_DEBUG_TAPER , CONFTYPE_INT , read_int , CNF_DEBUG_TAPER , validate_debug }, - { CONF_DEBUG_SELFCHECK , CONFTYPE_INT , read_int , CNF_DEBUG_SELFCHECK , validate_debug }, - { CONF_DEBUG_SENDSIZE , CONFTYPE_INT , read_int , CNF_DEBUG_SENDSIZE , validate_debug }, - { CONF_DEBUG_SENDBACKUP , CONFTYPE_INT , read_int , CNF_DEBUG_SENDBACKUP , validate_debug }, - { CONF_UNRESERVED_TCP_PORT, CONFTYPE_INTRANGE, read_intrange, CNF_UNRESERVED_TCP_PORT, validate_unreserved_port_range }, - { CONF_UNKNOWN , CONFTYPE_INT , NULL , CNF_CNF , NULL } -}; - keytab_t server_keytab[] = { { "AMANDAD_PATH", CONF_AMANDAD_PATH }, { "AMRECOVER_CHANGER", CONF_AMRECOVER_CHANGER }, @@ -337,8 +633,8 @@ keytab_t server_keytab[] = { { "BUMPPERCENT", CONF_BUMPPERCENT }, { "BUMPSIZE", CONF_BUMPSIZE }, { "CALCSIZE", CONF_CALCSIZE }, - { "CHANGERDEV", CONF_CHNGRDEV }, - { "CHANGERFILE", CONF_CHNGRFILE }, + { "CHANGERDEV", CONF_CHANGERDEV }, + { "CHANGERFILE", CONF_CHANGERFILE }, { "CHUNKSIZE", CONF_CHUNKSIZE }, { "CLIENT", CONF_CLIENT }, { "CLIENT_CUSTOM_COMPRESS", CONF_CLNTCOMPPROG }, @@ -369,6 +665,7 @@ keytab_t server_keytab[] = { { "DEBUG_SENDSIZE" , CONF_DEBUG_SENDSIZE }, { "DEBUG_SENDBACKUP" , CONF_DEBUG_SENDBACKUP }, { "DEFINE", CONF_DEFINE }, + { "DEVICE_PROPERTY", CONF_DEVICE_PROPERTY }, { "DIRECTORY", CONF_DIRECTORY }, { "DISKFILE", CONF_DISKFILE }, { "DISPLAYUNIT", CONF_DISPLAYUNIT }, @@ -421,7 +718,7 @@ keytab_t server_keytab[] = { { "MAXDUMPSIZE", CONF_MAXDUMPSIZE }, { "MAXPROMOTEDAY", CONF_MAXPROMOTEDAY }, { "MEDIUM", CONF_MEDIUM }, - { "NETUSAGE", CONF_NETUSAGE }, /* XXX - historical */ + { "NETUSAGE", CONF_NETUSAGE }, { "NEVER", CONF_NEVER }, { "NOFULL", CONF_NOFULL }, { "NOINC", CONF_NOINC }, @@ -431,7 +728,6 @@ keytab_t server_keytab[] = { { "PRINTER", CONF_PRINTER }, { "PRIORITY", CONF_PRIORITY }, { "PROGRAM", CONF_PROGRAM }, - { "RAWTAPEDEV", CONF_RAWTAPEDEV }, { "RECORD", CONF_RECORD }, { "REP_TRIES", CONF_REP_TRIES }, { "REQ_TRIES", CONF_REQ_TRIES }, @@ -456,10 +752,14 @@ keytab_t server_keytab[] = { { "STARTTIME", CONF_STARTTIME }, { "STRATEGY", CONF_STRATEGY }, { "TAPEBUFS", CONF_TAPEBUFS }, + { "DEVICE_OUTPUT_BUFFER_SIZE", CONF_DEVICE_OUTPUT_BUFFER_SIZE }, { "TAPECYCLE", CONF_TAPECYCLE }, { "TAPEDEV", CONF_TAPEDEV }, { "TAPELIST", CONF_TAPELIST }, { "TAPERALGO", CONF_TAPERALGO }, + { "FLUSH-THRESHOLD-DUMPED", CONF_FLUSH_THRESHOLD_DUMPED }, + { "FLUSH-THRESHOLD-SCHEDULED", CONF_FLUSH_THRESHOLD_SCHEDULED }, + { "TAPERFLUSH", CONF_TAPERFLUSH }, { "TAPETYPE", CONF_TAPETYPE }, { "TAPE_SPLITSIZE", CONF_TAPE_SPLITSIZE }, { "TPCHANGER", CONF_TPCHANGER }, @@ -470,1097 +770,683 @@ keytab_t server_keytab[] = { { NULL, CONF_UNKNOWN } }; -t_conf_var server_var [] = { - { CONF_ORG , CONFTYPE_STRING , read_string , CNF_ORG , NULL }, - { CONF_MAILTO , CONFTYPE_STRING , read_string , CNF_MAILTO , NULL }, - { CONF_DUMPUSER , CONFTYPE_STRING , read_string , CNF_DUMPUSER , NULL }, - { CONF_PRINTER , CONFTYPE_STRING , read_string , CNF_PRINTER , NULL }, - { CONF_TAPEDEV , CONFTYPE_STRING , read_string , CNF_TAPEDEV , NULL }, - { CONF_TPCHANGER , CONFTYPE_STRING , read_string , CNF_TPCHANGER , NULL }, - { CONF_CHNGRDEV , CONFTYPE_STRING , read_string , CNF_CHNGRDEV , NULL }, - { CONF_CHNGRFILE , CONFTYPE_STRING , read_string , CNF_CHNGRFILE , NULL }, - { CONF_LABELSTR , CONFTYPE_STRING , read_string , CNF_LABELSTR , NULL }, - { CONF_TAPELIST , CONFTYPE_STRING , read_string , CNF_TAPELIST , NULL }, - { CONF_DISKFILE , CONFTYPE_STRING , read_string , CNF_DISKFILE , NULL }, - { CONF_INFOFILE , CONFTYPE_STRING , read_string , CNF_INFOFILE , NULL }, - { CONF_LOGDIR , CONFTYPE_STRING , read_string , CNF_LOGDIR , NULL }, - { CONF_INDEXDIR , CONFTYPE_STRING , read_string , CNF_INDEXDIR , NULL }, - { CONF_TAPETYPE , CONFTYPE_IDENT , read_ident , CNF_TAPETYPE , NULL }, - { CONF_DUMPCYCLE , CONFTYPE_INT , read_int , CNF_DUMPCYCLE , validate_positive0 }, - { CONF_RUNSPERCYCLE , CONFTYPE_INT , read_int , CNF_RUNSPERCYCLE , validate_runspercycle }, - { CONF_RUNTAPES , CONFTYPE_INT , read_int , CNF_RUNTAPES , validate_positive0 }, - { CONF_TAPECYCLE , CONFTYPE_INT , read_int , CNF_TAPECYCLE , validate_positive1 }, - { CONF_BUMPDAYS , CONFTYPE_INT , read_int , CNF_BUMPDAYS , validate_positive1 }, - { CONF_BUMPSIZE , CONFTYPE_AM64 , read_am64 , CNF_BUMPSIZE , validate_positive1 }, - { CONF_BUMPPERCENT , CONFTYPE_INT , read_int , CNF_BUMPPERCENT , validate_bumppercent }, - { CONF_BUMPMULT , CONFTYPE_REAL , read_real , CNF_BUMPMULT , validate_bumpmult }, - { CONF_NETUSAGE , CONFTYPE_INT , read_int , CNF_NETUSAGE , validate_positive1 }, - { CONF_INPARALLEL , CONFTYPE_INT , read_int , CNF_INPARALLEL , validate_inparallel }, - { CONF_DUMPORDER , CONFTYPE_STRING , read_string , CNF_DUMPORDER , NULL }, - { CONF_MAXDUMPS , CONFTYPE_INT , read_int , CNF_MAXDUMPS , validate_positive1 }, - { CONF_ETIMEOUT , CONFTYPE_INT , read_int , CNF_ETIMEOUT , NULL }, - { CONF_DTIMEOUT , CONFTYPE_INT , read_int , CNF_DTIMEOUT , validate_positive1 }, - { CONF_CTIMEOUT , CONFTYPE_INT , read_int , CNF_CTIMEOUT , validate_positive1 }, - { CONF_TAPEBUFS , CONFTYPE_INT , read_int , CNF_TAPEBUFS , validate_positive1 }, - { CONF_RAWTAPEDEV , CONFTYPE_STRING , read_string , CNF_RAWTAPEDEV , NULL }, - { CONF_COLUMNSPEC , CONFTYPE_STRING , read_string , CNF_COLUMNSPEC , NULL }, - { CONF_TAPERALGO , CONFTYPE_TAPERALGO, get_taperalgo, CNF_TAPERALGO , NULL }, - { CONF_DISPLAYUNIT , CONFTYPE_STRING , read_string , CNF_DISPLAYUNIT , validate_displayunit }, - { CONF_AUTOFLUSH , CONFTYPE_BOOL , read_bool , CNF_AUTOFLUSH , NULL }, - { CONF_RESERVE , CONFTYPE_INT , read_int , CNF_RESERVE , validate_reserve }, - { CONF_MAXDUMPSIZE , CONFTYPE_AM64 , read_am64 , CNF_MAXDUMPSIZE , NULL }, - { CONF_KRB5KEYTAB , CONFTYPE_STRING , read_string , CNF_KRB5KEYTAB , NULL }, - { CONF_KRB5PRINCIPAL , CONFTYPE_STRING , read_string , CNF_KRB5PRINCIPAL , NULL }, - { CONF_LABEL_NEW_TAPES , CONFTYPE_STRING , read_string , CNF_LABEL_NEW_TAPES , NULL }, - { CONF_USETIMESTAMPS , CONFTYPE_BOOL , read_bool , CNF_USETIMESTAMPS , NULL }, - { CONF_AMRECOVER_DO_FSF , CONFTYPE_BOOL , read_bool , CNF_AMRECOVER_DO_FSF , NULL }, - { CONF_AMRECOVER_CHANGER , CONFTYPE_STRING , read_string , CNF_AMRECOVER_CHANGER , NULL }, - { CONF_AMRECOVER_CHECK_LABEL, CONFTYPE_BOOL , read_bool , CNF_AMRECOVER_CHECK_LABEL, NULL }, - { CONF_CONNECT_TRIES , CONFTYPE_INT , read_int , CNF_CONNECT_TRIES , validate_positive1 }, - { CONF_REP_TRIES , CONFTYPE_INT , read_int , CNF_REP_TRIES , validate_positive1 }, - { CONF_REQ_TRIES , CONFTYPE_INT , read_int , CNF_REQ_TRIES , validate_positive1 }, - { CONF_DEBUG_AMANDAD , CONFTYPE_INT , read_int , CNF_DEBUG_AMANDAD , validate_debug }, - { CONF_DEBUG_AMIDXTAPED , CONFTYPE_INT , read_int , CNF_DEBUG_AMIDXTAPED , validate_debug }, - { CONF_DEBUG_AMINDEXD , CONFTYPE_INT , read_int , CNF_DEBUG_AMINDEXD , validate_debug }, - { CONF_DEBUG_AMRECOVER , CONFTYPE_INT , read_int , CNF_DEBUG_AMRECOVER , validate_debug }, - { CONF_DEBUG_AUTH , CONFTYPE_INT , read_int , CNF_DEBUG_AUTH , validate_debug }, - { CONF_DEBUG_EVENT , CONFTYPE_INT , read_int , CNF_DEBUG_EVENT , validate_debug }, - { CONF_DEBUG_HOLDING , CONFTYPE_INT , read_int , CNF_DEBUG_HOLDING , validate_debug }, - { CONF_DEBUG_PROTOCOL , CONFTYPE_INT , read_int , CNF_DEBUG_PROTOCOL , validate_debug }, - { CONF_DEBUG_PLANNER , CONFTYPE_INT , read_int , CNF_DEBUG_PLANNER , validate_debug }, - { CONF_DEBUG_DRIVER , CONFTYPE_INT , read_int , CNF_DEBUG_DRIVER , validate_debug }, - { CONF_DEBUG_DUMPER , CONFTYPE_INT , read_int , CNF_DEBUG_DUMPER , validate_debug }, - { CONF_DEBUG_CHUNKER , CONFTYPE_INT , read_int , CNF_DEBUG_CHUNKER , validate_debug }, - { CONF_DEBUG_TAPER , CONFTYPE_INT , read_int , CNF_DEBUG_TAPER , validate_debug }, - { CONF_DEBUG_SELFCHECK , CONFTYPE_INT , read_int , CNF_DEBUG_SELFCHECK , validate_debug }, - { CONF_DEBUG_SENDSIZE , CONFTYPE_INT , read_int , CNF_DEBUG_SENDSIZE , validate_debug }, - { CONF_DEBUG_SENDBACKUP , CONFTYPE_INT , read_int , CNF_DEBUG_SENDBACKUP , validate_debug }, - { CONF_RESERVED_UDP_PORT , CONFTYPE_INTRANGE , read_intrange, CNF_RESERVED_UDP_PORT , validate_reserved_port_range }, - { CONF_RESERVED_TCP_PORT , CONFTYPE_INTRANGE , read_intrange, CNF_RESERVED_TCP_PORT , validate_reserved_port_range }, - { CONF_UNRESERVED_TCP_PORT , CONFTYPE_INTRANGE , read_intrange, CNF_UNRESERVED_TCP_PORT , validate_unreserved_port_range }, - { CONF_UNKNOWN , CONFTYPE_INT , NULL , CNF_CNF , NULL } -}; - -t_conf_var tapetype_var [] = { - { CONF_COMMENT , CONFTYPE_STRING, read_string, TAPETYPE_COMMENT , NULL }, - { CONF_LBL_TEMPL , CONFTYPE_STRING, read_string, TAPETYPE_LBL_TEMPL , NULL }, - { CONF_BLOCKSIZE , CONFTYPE_SIZE , read_size , TAPETYPE_BLOCKSIZE , validate_blocksize }, - { CONF_READBLOCKSIZE, CONFTYPE_SIZE , read_size , TAPETYPE_READBLOCKSIZE, validate_blocksize }, - { CONF_LENGTH , CONFTYPE_AM64 , read_am64 , TAPETYPE_LENGTH , validate_positive0 }, - { CONF_FILEMARK , CONFTYPE_AM64 , read_am64 , TAPETYPE_FILEMARK , NULL }, - { CONF_SPEED , CONFTYPE_INT , read_int , TAPETYPE_SPEED , validate_positive0 }, - { CONF_FILE_PAD , CONFTYPE_BOOL , read_bool , TAPETYPE_FILE_PAD , NULL }, - { CONF_UNKNOWN , CONFTYPE_INT , NULL , TAPETYPE_TAPETYPE , NULL } -}; - -t_conf_var dumptype_var [] = { - { CONF_COMMENT , CONFTYPE_STRING , read_string , DUMPTYPE_COMMENT , NULL }, - { CONF_AUTH , CONFTYPE_STRING , read_string , DUMPTYPE_SECURITY_DRIVER , NULL }, - { CONF_BUMPDAYS , CONFTYPE_INT , read_int , DUMPTYPE_BUMPDAYS , NULL }, - { CONF_BUMPMULT , CONFTYPE_REAL , read_real , DUMPTYPE_BUMPMULT , NULL }, - { CONF_BUMPSIZE , CONFTYPE_AM64 , read_am64 , DUMPTYPE_BUMPSIZE , NULL }, - { CONF_BUMPPERCENT , CONFTYPE_INT , read_int , DUMPTYPE_BUMPPERCENT , NULL }, - { CONF_COMPRATE , CONFTYPE_REAL , get_comprate, DUMPTYPE_COMPRATE , NULL }, - { CONF_COMPRESS , CONFTYPE_INT , get_compress, DUMPTYPE_COMPRESS , NULL }, - { CONF_ENCRYPT , CONFTYPE_INT , get_encrypt , DUMPTYPE_ENCRYPT , NULL }, - { CONF_DUMPCYCLE , CONFTYPE_INT , read_int , DUMPTYPE_DUMPCYCLE , validate_positive0 }, - { CONF_EXCLUDE , CONFTYPE_EXINCLUDE, get_exclude , DUMPTYPE_EXCLUDE , NULL }, - { CONF_INCLUDE , CONFTYPE_EXINCLUDE, get_exclude , DUMPTYPE_INCLUDE , NULL }, - { CONF_IGNORE , CONFTYPE_BOOL , read_bool , DUMPTYPE_IGNORE , NULL }, - { CONF_HOLDING , CONFTYPE_HOLDING , get_holding , DUMPTYPE_HOLDINGDISK , NULL }, - { CONF_INDEX , CONFTYPE_BOOL , read_bool , DUMPTYPE_INDEX , NULL }, - { CONF_KENCRYPT , CONFTYPE_BOOL , read_bool , DUMPTYPE_KENCRYPT , NULL }, - { CONF_MAXDUMPS , CONFTYPE_INT , read_int , DUMPTYPE_MAXDUMPS , validate_positive1 }, - { CONF_MAXPROMOTEDAY , CONFTYPE_INT , read_int , DUMPTYPE_MAXPROMOTEDAY , validate_positive0 }, - { CONF_PRIORITY , CONFTYPE_PRIORITY , get_priority, DUMPTYPE_PRIORITY , NULL }, - { CONF_PROGRAM , CONFTYPE_STRING , read_string , DUMPTYPE_PROGRAM , NULL }, - { CONF_RECORD , CONFTYPE_BOOL , read_bool , DUMPTYPE_RECORD , NULL }, - { CONF_SKIP_FULL , CONFTYPE_BOOL , read_bool , DUMPTYPE_SKIP_FULL , NULL }, - { CONF_SKIP_INCR , CONFTYPE_BOOL , read_bool , DUMPTYPE_SKIP_INCR , NULL }, - { CONF_STARTTIME , CONFTYPE_TIME , read_time , DUMPTYPE_STARTTIME , NULL }, - { CONF_STRATEGY , CONFTYPE_INT , get_strategy, DUMPTYPE_STRATEGY , NULL }, - { CONF_TAPE_SPLITSIZE , CONFTYPE_AM64 , read_am64 , DUMPTYPE_TAPE_SPLITSIZE , validate_positive0 }, - { CONF_SPLIT_DISKBUFFER , CONFTYPE_STRING , read_string , DUMPTYPE_SPLIT_DISKBUFFER , NULL }, - { CONF_ESTIMATE , CONFTYPE_INT , get_estimate, DUMPTYPE_ESTIMATE , NULL }, - { CONF_SRV_ENCRYPT , CONFTYPE_STRING , read_string , DUMPTYPE_SRV_ENCRYPT , NULL }, - { CONF_CLNT_ENCRYPT , CONFTYPE_STRING , read_string , DUMPTYPE_CLNT_ENCRYPT , NULL }, - { CONF_AMANDAD_PATH , CONFTYPE_STRING , read_string , DUMPTYPE_AMANDAD_PATH , NULL }, - { CONF_CLIENT_USERNAME , CONFTYPE_STRING , read_string , DUMPTYPE_CLIENT_USERNAME , NULL }, - { CONF_SSH_KEYS , CONFTYPE_STRING , read_string , DUMPTYPE_SSH_KEYS , NULL }, - { CONF_SRVCOMPPROG , CONFTYPE_STRING , read_string , DUMPTYPE_SRVCOMPPROG , NULL }, - { CONF_CLNTCOMPPROG , CONFTYPE_STRING , read_string , DUMPTYPE_CLNTCOMPPROG , NULL }, - { CONF_FALLBACK_SPLITSIZE, CONFTYPE_AM64 , read_am64 , DUMPTYPE_FALLBACK_SPLITSIZE, NULL }, - { CONF_SRV_DECRYPT_OPT , CONFTYPE_STRING , read_string , DUMPTYPE_SRV_DECRYPT_OPT , NULL }, - { CONF_CLNT_DECRYPT_OPT , CONFTYPE_STRING , read_string , DUMPTYPE_CLNT_DECRYPT_OPT , NULL }, - { CONF_UNKNOWN , CONFTYPE_INT , NULL , DUMPTYPE_DUMPTYPE , NULL } +/* A keyword table for recognizing unit suffixes. No distinction is made for kinds + * of suffixes: 1024 weeks = 7 k. */ +keytab_t numb_keytable[] = { + { "B", CONF_MULT1 }, + { "BPS", CONF_MULT1 }, + { "BYTE", CONF_MULT1 }, + { "BYTES", CONF_MULT1 }, + { "DAY", CONF_MULT1 }, + { "DAYS", CONF_MULT1 }, + { "INF", CONF_AMINFINITY }, + { "K", CONF_MULT1K }, + { "KB", CONF_MULT1K }, + { "KBPS", CONF_MULT1K }, + { "KBYTE", CONF_MULT1K }, + { "KBYTES", CONF_MULT1K }, + { "KILOBYTE", CONF_MULT1K }, + { "KILOBYTES", CONF_MULT1K }, + { "KPS", CONF_MULT1K }, + { "M", CONF_MULT1M }, + { "MB", CONF_MULT1M }, + { "MBPS", CONF_MULT1M }, + { "MBYTE", CONF_MULT1M }, + { "MBYTES", CONF_MULT1M }, + { "MEG", CONF_MULT1M }, + { "MEGABYTE", CONF_MULT1M }, + { "MEGABYTES", CONF_MULT1M }, + { "G", CONF_MULT1G }, + { "GB", CONF_MULT1G }, + { "GBPS", CONF_MULT1G }, + { "GBYTE", CONF_MULT1G }, + { "GBYTES", CONF_MULT1G }, + { "GIG", CONF_MULT1G }, + { "GIGABYTE", CONF_MULT1G }, + { "GIGABYTES", CONF_MULT1G }, + { "MPS", CONF_MULT1M }, + { "TAPE", CONF_MULT1 }, + { "TAPES", CONF_MULT1 }, + { "WEEK", CONF_MULT7 }, + { "WEEKS", CONF_MULT7 }, + { NULL, CONF_IDENT } }; -t_conf_var holding_var [] = { - { CONF_DIRECTORY, CONFTYPE_STRING, read_string, HOLDING_DISKDIR , NULL }, - { CONF_COMMENT , CONFTYPE_STRING, read_string, HOLDING_COMMENT , NULL }, - { CONF_USE , CONFTYPE_AM64 , read_am64 , HOLDING_DISKSIZE , validate_use }, - { CONF_CHUNKSIZE, CONFTYPE_AM64 , read_am64 , HOLDING_CHUNKSIZE, validate_chunksize }, - { CONF_UNKNOWN , CONFTYPE_INT , NULL , HOLDING_HOLDING , NULL } +/* Boolean keywords -- all the ways to say "true" and "false" in amanda.conf */ +keytab_t bool_keytable[] = { + { "Y", CONF_ATRUE }, + { "YES", CONF_ATRUE }, + { "T", CONF_ATRUE }, + { "TRUE", CONF_ATRUE }, + { "ON", CONF_ATRUE }, + { "N", CONF_AFALSE }, + { "NO", CONF_AFALSE }, + { "F", CONF_AFALSE }, + { "FALSE", CONF_AFALSE }, + { "OFF", CONF_AFALSE }, + { NULL, CONF_IDENT } }; -/* -** ------------------------ -** External entry points -** ------------------------ -*/ - -int -read_conffile( - char *filename) -{ - interface_t *ip; - - my_keytab = server_keytab; - my_var = server_var; - init_defaults(); +/* Now, the parser tables for client and server global parameters, and for + * each of the server subsections */ +conf_var_t client_var [] = { + { CONF_CONF , CONFTYPE_STR , read_str , CNF_CONF , NULL }, + { CONF_INDEX_SERVER , CONFTYPE_STR , read_str , CNF_INDEX_SERVER , NULL }, + { CONF_TAPE_SERVER , CONFTYPE_STR , read_str , CNF_TAPE_SERVER , NULL }, + { CONF_TAPEDEV , CONFTYPE_STR , read_str , CNF_TAPEDEV , NULL }, + { CONF_AUTH , CONFTYPE_STR , read_str , CNF_AUTH , NULL }, + { CONF_SSH_KEYS , CONFTYPE_STR , read_str , CNF_SSH_KEYS , NULL }, + { CONF_AMANDAD_PATH , CONFTYPE_STR , read_str , CNF_AMANDAD_PATH , NULL }, + { CONF_CLIENT_USERNAME , CONFTYPE_STR , read_str , CNF_CLIENT_USERNAME , NULL }, + { CONF_GNUTAR_LIST_DIR , CONFTYPE_STR , read_str , CNF_GNUTAR_LIST_DIR , NULL }, + { CONF_AMANDATES , CONFTYPE_STR , read_str , CNF_AMANDATES , NULL }, + { CONF_KRB5KEYTAB , CONFTYPE_STR , read_str , CNF_KRB5KEYTAB , NULL }, + { CONF_KRB5PRINCIPAL , CONFTYPE_STR , read_str , CNF_KRB5PRINCIPAL , NULL }, + { CONF_CONNECT_TRIES , CONFTYPE_INT , read_int , CNF_CONNECT_TRIES , validate_positive }, + { CONF_REP_TRIES , CONFTYPE_INT , read_int , CNF_REP_TRIES , validate_positive }, + { CONF_REQ_TRIES , CONFTYPE_INT , read_int , CNF_REQ_TRIES , validate_positive }, + { CONF_DEBUG_AMANDAD , CONFTYPE_INT , read_int , CNF_DEBUG_AMANDAD , validate_debug }, + { CONF_DEBUG_AMIDXTAPED , CONFTYPE_INT , read_int , CNF_DEBUG_AMIDXTAPED , validate_debug }, + { CONF_DEBUG_AMINDEXD , CONFTYPE_INT , read_int , CNF_DEBUG_AMINDEXD , validate_debug }, + { CONF_DEBUG_AMRECOVER , CONFTYPE_INT , read_int , CNF_DEBUG_AMRECOVER , validate_debug }, + { CONF_DEBUG_AUTH , CONFTYPE_INT , read_int , CNF_DEBUG_AUTH , validate_debug }, + { CONF_DEBUG_EVENT , CONFTYPE_INT , read_int , CNF_DEBUG_EVENT , validate_debug }, + { CONF_DEBUG_HOLDING , CONFTYPE_INT , read_int , CNF_DEBUG_HOLDING , validate_debug }, + { CONF_DEBUG_PROTOCOL , CONFTYPE_INT , read_int , CNF_DEBUG_PROTOCOL , validate_debug }, + { CONF_DEBUG_PLANNER , CONFTYPE_INT , read_int , CNF_DEBUG_PLANNER , validate_debug }, + { CONF_DEBUG_DRIVER , CONFTYPE_INT , read_int , CNF_DEBUG_DRIVER , validate_debug }, + { CONF_DEBUG_DUMPER , CONFTYPE_INT , read_int , CNF_DEBUG_DUMPER , validate_debug }, + { CONF_DEBUG_CHUNKER , CONFTYPE_INT , read_int , CNF_DEBUG_CHUNKER , validate_debug }, + { CONF_DEBUG_TAPER , CONFTYPE_INT , read_int , CNF_DEBUG_TAPER , validate_debug }, + { CONF_DEBUG_SELFCHECK , CONFTYPE_INT , read_int , CNF_DEBUG_SELFCHECK , validate_debug }, + { CONF_DEBUG_SENDSIZE , CONFTYPE_INT , read_int , CNF_DEBUG_SENDSIZE , validate_debug }, + { CONF_DEBUG_SENDBACKUP , CONFTYPE_INT , read_int , CNF_DEBUG_SENDBACKUP , validate_debug }, + { CONF_RESERVED_UDP_PORT , CONFTYPE_INTRANGE, read_intrange, CNF_RESERVED_UDP_PORT , validate_reserved_port_range }, + { CONF_RESERVED_TCP_PORT , CONFTYPE_INTRANGE, read_intrange, CNF_RESERVED_TCP_PORT , validate_reserved_port_range }, + { CONF_UNRESERVED_TCP_PORT, CONFTYPE_INTRANGE, read_intrange, CNF_UNRESERVED_TCP_PORT, validate_unreserved_port_range }, + { CONF_UNKNOWN , CONFTYPE_INT , NULL , CNF_CNF , NULL } +}; - /* We assume that conf_confname & conf are initialized to NULL above */ - read_conffile_recursively(filename); +conf_var_t server_var [] = { + { CONF_ORG , CONFTYPE_STR , read_str , CNF_ORG , NULL }, + { CONF_MAILTO , CONFTYPE_STR , read_str , CNF_MAILTO , NULL }, + { CONF_DUMPUSER , CONFTYPE_STR , read_str , CNF_DUMPUSER , NULL }, + { CONF_PRINTER , CONFTYPE_STR , read_str , CNF_PRINTER , NULL }, + { CONF_TAPEDEV , CONFTYPE_STR , read_str , CNF_TAPEDEV , NULL }, + { CONF_DEVICE_PROPERTY , CONFTYPE_PROPLIST , read_property , CNF_DEVICE_PROPERTY , NULL }, + { CONF_TPCHANGER , CONFTYPE_STR , read_str , CNF_TPCHANGER , NULL }, + { CONF_CHANGERDEV , CONFTYPE_STR , read_str , CNF_CHANGERDEV , NULL }, + { CONF_CHANGERFILE , CONFTYPE_STR , read_str , CNF_CHANGERFILE , NULL }, + { CONF_LABELSTR , CONFTYPE_STR , read_str , CNF_LABELSTR , NULL }, + { CONF_TAPELIST , CONFTYPE_STR , read_str , CNF_TAPELIST , NULL }, + { CONF_DISKFILE , CONFTYPE_STR , read_str , CNF_DISKFILE , NULL }, + { CONF_INFOFILE , CONFTYPE_STR , read_str , CNF_INFOFILE , NULL }, + { CONF_LOGDIR , CONFTYPE_STR , read_str , CNF_LOGDIR , NULL }, + { CONF_INDEXDIR , CONFTYPE_STR , read_str , CNF_INDEXDIR , NULL }, + { CONF_TAPETYPE , CONFTYPE_IDENT , read_ident , CNF_TAPETYPE , NULL }, + { CONF_DUMPCYCLE , CONFTYPE_INT , read_int , CNF_DUMPCYCLE , validate_nonnegative }, + { CONF_RUNSPERCYCLE , CONFTYPE_INT , read_int , CNF_RUNSPERCYCLE , validate_runspercycle }, + { CONF_RUNTAPES , CONFTYPE_INT , read_int , CNF_RUNTAPES , validate_nonnegative }, + { CONF_TAPECYCLE , CONFTYPE_INT , read_int , CNF_TAPECYCLE , validate_positive }, + { CONF_BUMPDAYS , CONFTYPE_INT , read_int , CNF_BUMPDAYS , validate_positive }, + { CONF_BUMPSIZE , CONFTYPE_AM64 , read_am64 , CNF_BUMPSIZE , validate_positive }, + { CONF_BUMPPERCENT , CONFTYPE_INT , read_int , CNF_BUMPPERCENT , validate_bumppercent }, + { CONF_BUMPMULT , CONFTYPE_REAL , read_real , CNF_BUMPMULT , validate_bumpmult }, + { CONF_NETUSAGE , CONFTYPE_INT , read_int , CNF_NETUSAGE , validate_positive }, + { CONF_INPARALLEL , CONFTYPE_INT , read_int , CNF_INPARALLEL , validate_inparallel }, + { CONF_DUMPORDER , CONFTYPE_STR , read_str , CNF_DUMPORDER , NULL }, + { CONF_MAXDUMPS , CONFTYPE_INT , read_int , CNF_MAXDUMPS , validate_positive }, + { CONF_ETIMEOUT , CONFTYPE_INT , read_int , CNF_ETIMEOUT , NULL }, + { CONF_DTIMEOUT , CONFTYPE_INT , read_int , CNF_DTIMEOUT , validate_positive }, + { CONF_CTIMEOUT , CONFTYPE_INT , read_int , CNF_CTIMEOUT , validate_positive }, + { CONF_TAPEBUFS , CONFTYPE_INT , read_int , CNF_TAPEBUFS , validate_positive }, + { CONF_DEVICE_OUTPUT_BUFFER_SIZE, CONFTYPE_SIZE , read_size , CNF_DEVICE_OUTPUT_BUFFER_SIZE, validate_positive }, + { CONF_COLUMNSPEC , CONFTYPE_STR , read_str , CNF_COLUMNSPEC , NULL }, + { CONF_TAPERALGO , CONFTYPE_TAPERALGO, read_taperalgo , CNF_TAPERALGO , NULL }, + { CONF_FLUSH_THRESHOLD_DUMPED, CONFTYPE_INT , read_int , CNF_FLUSH_THRESHOLD_DUMPED, validate_nonnegative }, + { CONF_FLUSH_THRESHOLD_SCHEDULED, CONFTYPE_INT , read_int , CNF_FLUSH_THRESHOLD_SCHEDULED, validate_nonnegative }, + { CONF_TAPERFLUSH , CONFTYPE_INT , read_int , CNF_TAPERFLUSH , validate_nonnegative }, + { CONF_DISPLAYUNIT , CONFTYPE_STR , read_str , CNF_DISPLAYUNIT , validate_displayunit }, + { CONF_AUTOFLUSH , CONFTYPE_BOOLEAN , read_bool , CNF_AUTOFLUSH , NULL }, + { CONF_RESERVE , CONFTYPE_INT , read_int , CNF_RESERVE , validate_reserve }, + { CONF_MAXDUMPSIZE , CONFTYPE_AM64 , read_am64 , CNF_MAXDUMPSIZE , NULL }, + { CONF_KRB5KEYTAB , CONFTYPE_STR , read_str , CNF_KRB5KEYTAB , NULL }, + { CONF_KRB5PRINCIPAL , CONFTYPE_STR , read_str , CNF_KRB5PRINCIPAL , NULL }, + { CONF_LABEL_NEW_TAPES , CONFTYPE_STR , read_str , CNF_LABEL_NEW_TAPES , NULL }, + { CONF_USETIMESTAMPS , CONFTYPE_BOOLEAN , read_bool , CNF_USETIMESTAMPS , NULL }, + { CONF_AMRECOVER_DO_FSF , CONFTYPE_BOOLEAN , read_bool , CNF_AMRECOVER_DO_FSF , NULL }, + { CONF_AMRECOVER_CHANGER , CONFTYPE_STR , read_str , CNF_AMRECOVER_CHANGER , NULL }, + { CONF_AMRECOVER_CHECK_LABEL, CONFTYPE_BOOLEAN , read_bool , CNF_AMRECOVER_CHECK_LABEL, NULL }, + { CONF_CONNECT_TRIES , CONFTYPE_INT , read_int , CNF_CONNECT_TRIES , validate_positive }, + { CONF_REP_TRIES , CONFTYPE_INT , read_int , CNF_REP_TRIES , validate_positive }, + { CONF_REQ_TRIES , CONFTYPE_INT , read_int , CNF_REQ_TRIES , validate_positive }, + { CONF_DEBUG_AMANDAD , CONFTYPE_INT , read_int , CNF_DEBUG_AMANDAD , validate_debug }, + { CONF_DEBUG_AMIDXTAPED , CONFTYPE_INT , read_int , CNF_DEBUG_AMIDXTAPED , validate_debug }, + { CONF_DEBUG_AMINDEXD , CONFTYPE_INT , read_int , CNF_DEBUG_AMINDEXD , validate_debug }, + { CONF_DEBUG_AMRECOVER , CONFTYPE_INT , read_int , CNF_DEBUG_AMRECOVER , validate_debug }, + { CONF_DEBUG_AUTH , CONFTYPE_INT , read_int , CNF_DEBUG_AUTH , validate_debug }, + { CONF_DEBUG_EVENT , CONFTYPE_INT , read_int , CNF_DEBUG_EVENT , validate_debug }, + { CONF_DEBUG_HOLDING , CONFTYPE_INT , read_int , CNF_DEBUG_HOLDING , validate_debug }, + { CONF_DEBUG_PROTOCOL , CONFTYPE_INT , read_int , CNF_DEBUG_PROTOCOL , validate_debug }, + { CONF_DEBUG_PLANNER , CONFTYPE_INT , read_int , CNF_DEBUG_PLANNER , validate_debug }, + { CONF_DEBUG_DRIVER , CONFTYPE_INT , read_int , CNF_DEBUG_DRIVER , validate_debug }, + { CONF_DEBUG_DUMPER , CONFTYPE_INT , read_int , CNF_DEBUG_DUMPER , validate_debug }, + { CONF_DEBUG_CHUNKER , CONFTYPE_INT , read_int , CNF_DEBUG_CHUNKER , validate_debug }, + { CONF_DEBUG_TAPER , CONFTYPE_INT , read_int , CNF_DEBUG_TAPER , validate_debug }, + { CONF_DEBUG_SELFCHECK , CONFTYPE_INT , read_int , CNF_DEBUG_SELFCHECK , validate_debug }, + { CONF_DEBUG_SENDSIZE , CONFTYPE_INT , read_int , CNF_DEBUG_SENDSIZE , validate_debug }, + { CONF_DEBUG_SENDBACKUP , CONFTYPE_INT , read_int , CNF_DEBUG_SENDBACKUP , validate_debug }, + { CONF_RESERVED_UDP_PORT , CONFTYPE_INTRANGE , read_intrange , CNF_RESERVED_UDP_PORT , validate_reserved_port_range }, + { CONF_RESERVED_TCP_PORT , CONFTYPE_INTRANGE , read_intrange , CNF_RESERVED_TCP_PORT , validate_reserved_port_range }, + { CONF_UNRESERVED_TCP_PORT , CONFTYPE_INTRANGE , read_intrange , CNF_UNRESERVED_TCP_PORT , validate_unreserved_port_range }, + { CONF_UNKNOWN , CONFTYPE_INT , NULL , CNF_CNF , NULL } +}; - /* overwrite with command line option */ - command_overwrite(program_options, my_var, my_keytab, conf_data, - ""); +conf_var_t tapetype_var [] = { + { CONF_COMMENT , CONFTYPE_STR , read_str , TAPETYPE_COMMENT , NULL }, + { CONF_LBL_TEMPL , CONFTYPE_STR , read_str , TAPETYPE_LBL_TEMPL , NULL }, + { CONF_BLOCKSIZE , CONFTYPE_SIZE , read_size , TAPETYPE_BLOCKSIZE , validate_blocksize }, + { CONF_READBLOCKSIZE , CONFTYPE_SIZE , read_size , TAPETYPE_READBLOCKSIZE, validate_blocksize }, + { CONF_LENGTH , CONFTYPE_AM64 , read_am64 , TAPETYPE_LENGTH , validate_nonnegative }, + { CONF_FILEMARK , CONFTYPE_AM64 , read_am64 , TAPETYPE_FILEMARK , NULL }, + { CONF_SPEED , CONFTYPE_INT , read_int , TAPETYPE_SPEED , validate_nonnegative }, + { CONF_FILE_PAD , CONFTYPE_BOOLEAN , read_bool , TAPETYPE_FILE_PAD , NULL }, + { CONF_UNKNOWN , CONFTYPE_INT , NULL , TAPETYPE_TAPETYPE , NULL } +}; - if(got_parserror != -1 ) { - if(lookup_tapetype(conf_data[CNF_TAPETYPE].v.s) == NULL) { - char *save_confname = conf_confname; +conf_var_t dumptype_var [] = { + { CONF_COMMENT , CONFTYPE_STR , read_str , DUMPTYPE_COMMENT , NULL }, + { CONF_AUTH , CONFTYPE_STR , read_str , DUMPTYPE_SECURITY_DRIVER , NULL }, + { CONF_BUMPDAYS , CONFTYPE_INT , read_int , DUMPTYPE_BUMPDAYS , NULL }, + { CONF_BUMPMULT , CONFTYPE_REAL , read_real , DUMPTYPE_BUMPMULT , NULL }, + { CONF_BUMPSIZE , CONFTYPE_AM64 , read_am64 , DUMPTYPE_BUMPSIZE , NULL }, + { CONF_BUMPPERCENT , CONFTYPE_INT , read_int , DUMPTYPE_BUMPPERCENT , NULL }, + { CONF_COMPRATE , CONFTYPE_REAL , read_rate , DUMPTYPE_COMPRATE , NULL }, + { CONF_COMPRESS , CONFTYPE_INT , read_compress , DUMPTYPE_COMPRESS , NULL }, + { CONF_ENCRYPT , CONFTYPE_INT , read_encrypt , DUMPTYPE_ENCRYPT , NULL }, + { CONF_DUMPCYCLE , CONFTYPE_INT , read_int , DUMPTYPE_DUMPCYCLE , validate_nonnegative }, + { CONF_EXCLUDE , CONFTYPE_EXINCLUDE, read_exinclude, DUMPTYPE_EXCLUDE , NULL }, + { CONF_INCLUDE , CONFTYPE_EXINCLUDE, read_exinclude, DUMPTYPE_INCLUDE , NULL }, + { CONF_IGNORE , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_IGNORE , NULL }, + { CONF_HOLDING , CONFTYPE_HOLDING , read_holding , DUMPTYPE_HOLDINGDISK , NULL }, + { CONF_INDEX , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_INDEX , NULL }, + { CONF_KENCRYPT , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_KENCRYPT , NULL }, + { CONF_MAXDUMPS , CONFTYPE_INT , read_int , DUMPTYPE_MAXDUMPS , validate_positive }, + { CONF_MAXPROMOTEDAY , CONFTYPE_INT , read_int , DUMPTYPE_MAXPROMOTEDAY , validate_nonnegative }, + { CONF_PRIORITY , CONFTYPE_PRIORITY , read_priority , DUMPTYPE_PRIORITY , NULL }, + { CONF_PROGRAM , CONFTYPE_STR , read_str , DUMPTYPE_PROGRAM , NULL }, + { CONF_RECORD , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_RECORD , NULL }, + { CONF_SKIP_FULL , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_SKIP_FULL , NULL }, + { CONF_SKIP_INCR , CONFTYPE_BOOLEAN , read_bool , DUMPTYPE_SKIP_INCR , NULL }, + { CONF_STARTTIME , CONFTYPE_TIME , read_time , DUMPTYPE_STARTTIME , NULL }, + { CONF_STRATEGY , CONFTYPE_INT , read_strategy , DUMPTYPE_STRATEGY , NULL }, + { CONF_TAPE_SPLITSIZE , CONFTYPE_AM64 , read_am64 , DUMPTYPE_TAPE_SPLITSIZE , validate_nonnegative }, + { CONF_SPLIT_DISKBUFFER , CONFTYPE_STR , read_str , DUMPTYPE_SPLIT_DISKBUFFER , NULL }, + { CONF_ESTIMATE , CONFTYPE_INT , read_estimate , DUMPTYPE_ESTIMATE , NULL }, + { CONF_SRV_ENCRYPT , CONFTYPE_STR , read_str , DUMPTYPE_SRV_ENCRYPT , NULL }, + { CONF_CLNT_ENCRYPT , CONFTYPE_STR , read_str , DUMPTYPE_CLNT_ENCRYPT , NULL }, + { CONF_AMANDAD_PATH , CONFTYPE_STR , read_str , DUMPTYPE_AMANDAD_PATH , NULL }, + { CONF_CLIENT_USERNAME , CONFTYPE_STR , read_str , DUMPTYPE_CLIENT_USERNAME , NULL }, + { CONF_SSH_KEYS , CONFTYPE_STR , read_str , DUMPTYPE_SSH_KEYS , NULL }, + { CONF_SRVCOMPPROG , CONFTYPE_STR , read_str , DUMPTYPE_SRVCOMPPROG , NULL }, + { CONF_CLNTCOMPPROG , CONFTYPE_STR , read_str , DUMPTYPE_CLNTCOMPPROG , NULL }, + { CONF_FALLBACK_SPLITSIZE, CONFTYPE_AM64 , read_am64 , DUMPTYPE_FALLBACK_SPLITSIZE, NULL }, + { CONF_SRV_DECRYPT_OPT , CONFTYPE_STR , read_str , DUMPTYPE_SRV_DECRYPT_OPT , NULL }, + { CONF_CLNT_DECRYPT_OPT , CONFTYPE_STR , read_str , DUMPTYPE_CLNT_DECRYPT_OPT , NULL }, + { CONF_UNKNOWN , CONFTYPE_INT , NULL , DUMPTYPE_DUMPTYPE , NULL } +}; - conf_confname = filename; - if(!conf_data[CNF_TAPETYPE].seen) - conf_parserror("default tapetype %s not defined", conf_data[CNF_TAPETYPE].v.s); - else { - conf_line_num = conf_data[CNF_TAPETYPE].seen; - conf_parserror("tapetype %s not defined", conf_data[CNF_TAPETYPE].v.s); - } - conf_confname = save_confname; - } - } +conf_var_t holding_var [] = { + { CONF_DIRECTORY, CONFTYPE_STR , read_str , HOLDING_DISKDIR , NULL }, + { CONF_COMMENT , CONFTYPE_STR , read_str , HOLDING_COMMENT , NULL }, + { CONF_USE , CONFTYPE_AM64 , read_am64 , HOLDING_DISKSIZE , validate_use }, + { CONF_CHUNKSIZE, CONFTYPE_AM64 , read_am64 , HOLDING_CHUNKSIZE, validate_chunksize }, + { CONF_UNKNOWN , CONFTYPE_INT , NULL , HOLDING_HOLDING , NULL } +}; - ip = alloc(SIZEOF(interface_t)); - ip->name = stralloc("default"); - ip->seen = conf_data[CNF_NETUSAGE].seen; - conf_init_string(&ip->value[INTER_COMMENT], "implicit from NETUSAGE"); - conf_init_int(&ip->value[INTER_MAXUSAGE], conf_data[CNF_NETUSAGE].v.i); - ip->curusage = 0; - ip->next = interface_list; - interface_list = ip; +conf_var_t interface_var [] = { + { CONF_COMMENT, CONFTYPE_STR , read_str , INTER_COMMENT , NULL }, + { CONF_USE , CONFTYPE_INT , read_int , INTER_MAXUSAGE, validate_positive }, + { CONF_UNKNOWN, CONFTYPE_INT , NULL , INTER_INTER , NULL } +}; - debug_amandad = getconf_int(CNF_DEBUG_AMANDAD); - debug_amidxtaped = getconf_int(CNF_DEBUG_AMIDXTAPED); - debug_amindexd = getconf_int(CNF_DEBUG_AMINDEXD); - debug_amrecover = getconf_int(CNF_DEBUG_AMRECOVER); - debug_auth = getconf_int(CNF_DEBUG_AUTH); - debug_event = getconf_int(CNF_DEBUG_EVENT); - debug_holding = getconf_int(CNF_DEBUG_HOLDING); - debug_protocol = getconf_int(CNF_DEBUG_PROTOCOL); - debug_planner = getconf_int(CNF_DEBUG_PLANNER); - debug_driver = getconf_int(CNF_DEBUG_DRIVER); - debug_dumper = getconf_int(CNF_DEBUG_DUMPER); - debug_chunker = getconf_int(CNF_DEBUG_CHUNKER); - debug_taper = getconf_int(CNF_DEBUG_TAPER); - debug_selfcheck = getconf_int(CNF_DEBUG_SELFCHECK); - debug_sendsize = getconf_int(CNF_DEBUG_SENDSIZE); - debug_sendbackup = getconf_int(CNF_DEBUG_SENDBACKUP); - return got_parserror; -} +/* + * Lexical Analysis Implementation + */ -static void -validate_positive0( - struct s_conf_var *np, - val_t *val) +static char * +get_token_name( + tok_t token) { - switch(val->type) { - case CONFTYPE_INT: - if(val->v.i < 0) - conf_parserror("%s must be positive", get_token_name(np->token)); - break; - case CONFTYPE_LONG: - if(val->v.l < 0) - conf_parserror("%s must be positive", get_token_name(np->token)); - break; - case CONFTYPE_AM64: - if(val->v.am64 < 0) - conf_parserror("%s must be positive", get_token_name(np->token)); - break; - default: - conf_parserror("validate_positive0 invalid type %d\n", val->type); - } -} + keytab_t *kt; -static void -validate_positive1( - struct s_conf_var *np, - val_t *val) -{ - switch(val->type) { - case CONFTYPE_INT: - if(val->v.i < 1) - conf_parserror("%s must be positive", get_token_name(np->token)); - break; - case CONFTYPE_LONG: - if(val->v.l < 1) - conf_parserror("%s must be positive", get_token_name(np->token)); - break; - case CONFTYPE_AM64: - if(val->v.am64 < 1) - conf_parserror("%s must be positive", get_token_name(np->token)); - break; - case CONFTYPE_TIME: - if(val->v.t < 1) - conf_parserror("%s must be positive", get_token_name(np->token)); - break; - default: - conf_parserror("validate_positive1 invalid type %d\n", val->type); + if (keytable == NULL) { + error(_("keytable == NULL")); + /*NOTREACHED*/ } -} -static void -validate_runspercycle( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(val->v.i < -1) - conf_parserror("runspercycle must be >= -1"); -} - -static void -validate_bumppercent( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(val->v.i < 0 || val->v.i > 100) - conf_parserror("bumppercent must be between 0 and 100"); -} + for(kt = keytable; kt->token != CONF_UNKNOWN; kt++) + if(kt->token == token) break; -static void -validate_inparallel( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(val->v.i < 1 || val->v.i >MAX_DUMPERS) - conf_parserror("inparallel must be between 1 and MAX_DUMPERS (%d)", - MAX_DUMPERS); + if(kt->token == CONF_UNKNOWN) + return(""); + return(kt->keyword); } -static void -validate_bumpmult( - struct s_conf_var *np, - val_t *val) +static tok_t +lookup_keyword( + char * str) { - np = np; - if(val->v.r < 0.999) { - conf_parserror("bumpmult must be positive"); - } -} + keytab_t *kwp; -static void -validate_displayunit( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(strcmp(val->v.s, "k") == 0 || - strcmp(val->v.s, "K") == 0) { - val->v.s[0] = (char)toupper(val->v.s[0]); - unit_divisor=1; - } - else if(strcmp(val->v.s, "m") == 0 || - strcmp(val->v.s, "M") == 0) { - val->v.s[0] = (char)toupper(val->v.s[0]); - unit_divisor=1024; - } - else if(strcmp(val->v.s, "g") == 0 || - strcmp(val->v.s, "G") == 0) { - val->v.s[0] = (char)toupper(val->v.s[0]); - unit_divisor=1024*1024; - } - else if(strcmp(val->v.s, "t") == 0 || - strcmp(val->v.s, "T") == 0) { - val->v.s[0] = (char)toupper(val->v.s[0]); - unit_divisor=1024*1024*1024; - } - else { - conf_parserror("displayunit must be k,m,g or t."); + for(kwp = keytable; kwp->keyword != NULL; kwp++) { + if (strcasecmp(kwp->keyword, str) == 0) break; } + return kwp->token; } static void -validate_reserve( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(val->v.i < 0 || val->v.i > 100) - conf_parserror("reserve must be between 0 and 100"); -} - -static void -validate_use( - struct s_conf_var *np, - val_t *val) -{ - np = np; - val->v.am64 = am_floor(val->v.am64, DISK_BLOCK_KB); -} - -static void -validate_chunksize( - struct s_conf_var *np, - val_t *val) +get_conftoken( + tok_t exp) { - np = np; - if(val->v.am64 == 0) { - val->v.am64 = ((AM64_MAX / 1024) - (2 * DISK_BLOCK_KB)); - } - else if(val->v.am64 < 0) { - conf_parserror("Negative chunksize (" OFF_T_FMT - ") is no longer supported", val->v.am64); - } - val->v.am64 = am_floor(val->v.am64, (off_t)DISK_BLOCK_KB); - if (val->v.am64 < 2*DISK_BLOCK_KB) { - conf_parserror("chunksize must be at least %dkb", 2*DISK_BLOCK_KB); - } -} + int ch, d; + off_t am64; + char *buf; + char *tmps; + int token_overflow; + int inquote = 0; + int escape = 0; + int sign; -static void -validate_blocksize( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(val->v.l < DISK_BLOCK_KB) { - conf_parserror("Tape blocksize must be at least %d KBytes", - DISK_BLOCK_KB); - } else if(val->v.l > MAX_TAPE_BLOCK_KB) { - conf_parserror("Tape blocksize must not be larger than %d KBytes", - MAX_TAPE_BLOCK_KB); - } -} + if (token_pushed) { + token_pushed = 0; + tok = pushed_tok; -static void -validate_debug( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(val->v.i < 0 || val->v.i > 9) { - conf_parserror("Debug must be between 0 and 9"); - } -} + /* + ** If it looked like a keyword before then look it + ** up again in the current keyword table. + */ + switch(tok) { + case CONF_AM64: case CONF_SIZE: + case CONF_INT: case CONF_REAL: case CONF_STRING: + case CONF_LBRACE: case CONF_RBRACE: case CONF_COMMA: + case CONF_NL: case CONF_END: case CONF_UNKNOWN: + case CONF_TIME: + break; /* not a keyword */ -static void -validate_reserved_port_range( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(val->v.intrange[0] < 1 || val->v.intrange[0] > IPPORT_RESERVED-1) { - conf_parserror("portrange must be between 1 and %d", IPPORT_RESERVED-1); - } else if(val->v.intrange[1] < 1 || val->v.intrange[1] > IPPORT_RESERVED-1) { - conf_parserror("portrange must be between 1 and IPPORT_RESERVED-1"); + default: + if (exp == CONF_IDENT) + tok = CONF_IDENT; + else + tok = lookup_keyword(tokenval.v.s); + break; + } } -} + else { + ch = conftoken_getc(); -static void -validate_unreserved_port_range( - struct s_conf_var *np, - val_t *val) -{ - np = np; - if(val->v.intrange[0] < IPPORT_RESERVED+1 || val->v.intrange[0] > 65536) { - conf_parserror("portrange must be between %d and 65536", IPPORT_RESERVED+1); - } else if(val->v.intrange[1] < IPPORT_RESERVED+1 || val->v.intrange[1] > 65536) { - conf_parserror("portrange must be between %d and 65536", IPPORT_RESERVED+1); - } -} + while(ch != EOF && ch != '\n' && isspace(ch)) + ch = conftoken_getc(); + if (ch == '#') { /* comment - eat everything but eol/eof */ + while((ch = conftoken_getc()) != EOF && ch != '\n') { + (void)ch; /* Quiet empty loop complaints */ + } + } -char * -getconf_byname( - char *str) -{ - static char *tmpstr; - t_conf_var *np; - keytab_t *kt; - char *s; - char ch; - char *first_delim; - char *second_delim; - tapetype_t *tp; - dumptype_t *dp; - interface_t *ip; - holdingdisk_t *hp; + if (isalpha(ch)) { /* identifier */ + buf = tkbuf; + token_overflow = 0; + do { + if (buf < tkbuf+sizeof(tkbuf)-1) { + *buf++ = (char)ch; + } else { + *buf = '\0'; + if (!token_overflow) { + conf_parserror(_("token too long: %.20s..."), tkbuf); + } + token_overflow = 1; + } + ch = conftoken_getc(); + } while(isalnum(ch) || ch == '_' || ch == '-'); - tmpstr = stralloc(str); - s = tmpstr; - while((ch = *s++) != '\0') { - if(islower((int)ch)) - s[-1] = (char)toupper(ch); - } + if (ch != EOF && conftoken_ungetc(ch) == EOF) { + if (ferror(current_file)) { + conf_parserror(_("Pushback of '%c' failed: %s"), + ch, strerror(ferror(current_file))); + } else { + conf_parserror(_("Pushback of '%c' failed: EOF"), ch); + } + } + *buf = '\0'; - first_delim = strchr(tmpstr, ':'); - if (first_delim) { - *first_delim = '\0'; - first_delim++; - second_delim = strchr(first_delim,':'); - if(!second_delim) { - amfree(tmpstr); - return(NULL); - } - *second_delim = '\0'; - second_delim++; + tokenval.v.s = tkbuf; - for(kt = my_keytab; kt->token != CONF_UNKNOWN; kt++) { - if(kt->keyword && strcmp(kt->keyword, second_delim) == 0) - break; + if (token_overflow) tok = CONF_UNKNOWN; + else if (exp == CONF_IDENT) tok = CONF_IDENT; + else tok = lookup_keyword(tokenval.v.s); } + else if (isdigit(ch)) { /* integer */ + sign = 1; - if(kt->token == CONF_UNKNOWN) - return NULL; +negative_number: /* look for goto negative_number below sign is set there */ + am64 = 0; + do { + am64 = am64 * 10 + (ch - '0'); + ch = conftoken_getc(); + } while (isdigit(ch)); - if (strcmp(tmpstr, "TAPETYPE") == 0) { - tp = lookup_tapetype(first_delim); - if (!tp) { - amfree(tmpstr); - return(NULL); - } - for(np = tapetype_var; np->token != CONF_UNKNOWN; np++) { - if(np->token == kt->token) - break; - } - if (np->token == CONF_UNKNOWN) return NULL; - tmpstr = stralloc(conf_print(&tp->value[np->parm], 0, "")); - } else if (strcmp(tmpstr, "DUMPTYPE") == 0) { - dp = lookup_dumptype(first_delim); - if (!dp) { - amfree(tmpstr); - return(NULL); - } - for(np = dumptype_var; np->token != CONF_UNKNOWN; np++) { - if(np->token == kt->token) - break; + if (ch != '.') { + if (exp == CONF_INT) { + tok = CONF_INT; + tokenval.v.i = sign * (int)am64; + } else if (exp != CONF_REAL) { + tok = CONF_AM64; + tokenval.v.am64 = (off_t)sign * am64; + } else { + /* automatically convert to real when expected */ + tokenval.v.r = (double)sign * (double)am64; + tok = CONF_REAL; + } + } else { + /* got a real number, not an int */ + tokenval.v.r = sign * (double) am64; + am64 = 0; + d = 1; + ch = conftoken_getc(); + while (isdigit(ch)) { + am64 = am64 * 10 + (ch - '0'); + d = d * 10; + ch = conftoken_getc(); + } + tokenval.v.r += sign * ((double)am64) / d; + tok = CONF_REAL; } - if (np->token == CONF_UNKNOWN) return NULL; - tmpstr = stralloc(conf_print(&dp->value[np->parm], 0, "")); - } else if (strcmp(tmpstr, "HOLDINGDISK") == 0) { - hp = lookup_holdingdisk(first_delim); - if (!hp) { - amfree(tmpstr); - return(NULL); + + if (ch != EOF && conftoken_ungetc(ch) == EOF) { + if (ferror(current_file)) { + conf_parserror(_("Pushback of '%c' failed: %s"), + ch, strerror(ferror(current_file))); + } else { + conf_parserror(_("Pushback of '%c' failed: EOF"), ch); + } } - for(np = holding_var; np->token != CONF_UNKNOWN; np++) { - if(np->token == kt->token) - break; + } else switch(ch) { + case '"': /* string */ + buf = tkbuf; + token_overflow = 0; + inquote = 1; + *buf++ = (char)ch; + while (inquote && ((ch = conftoken_getc()) != EOF)) { + if (ch == '\n') { + if (!escape) + break; + escape = 0; + buf--; /* Consume escape in buffer */ + } else if (ch == '\\') { + escape = 1; + } else { + if (ch == '"') { + if (!escape) + inquote = 0; + } + escape = 0; + } + + if(buf >= &tkbuf[sizeof(tkbuf) - 1]) { + if (!token_overflow) { + conf_parserror(_("string too long: %.20s..."), tkbuf); + } + token_overflow = 1; + break; + } + *buf++ = (char)ch; } - if (np->token == CONF_UNKNOWN) return NULL; - tmpstr = stralloc(conf_print(&hp->value[np->parm], 0, "")); - } else if (strcmp(tmpstr, "INTERFACE") == 0) { - ip = lookup_interface(first_delim); - if (!ip) { - amfree(tmpstr); - return(NULL); + *buf = '\0'; + + /* + * A little manuver to leave a fully unquoted, unallocated string + * in tokenval.v.s + */ + tmps = unquote_string(tkbuf); + strncpy(tkbuf, tmps, sizeof(tkbuf)); + amfree(tmps); + tokenval.v.s = tkbuf; + + tok = (token_overflow) ? CONF_UNKNOWN : + (exp == CONF_IDENT) ? CONF_IDENT : CONF_STRING; + break; + + case '-': + ch = conftoken_getc(); + if (isdigit(ch)) { + sign = -1; + goto negative_number; } - for(np = holding_var; np->token != CONF_UNKNOWN; np++) { - if(np->token == kt->token) - break; + else { + if (ch != EOF && conftoken_ungetc(ch) == EOF) { + if (ferror(current_file)) { + conf_parserror(_("Pushback of '%c' failed: %s"), + ch, strerror(ferror(current_file))); + } else { + conf_parserror(_("Pushback of '%c' failed: EOF"), ch); + } + } + tok = CONF_UNKNOWN; } - if (np->token == CONF_UNKNOWN) return NULL; - tmpstr = stralloc(conf_print(&ip->value[np->parm], 0, "")); - } else { - amfree(tmpstr); - return(NULL); - } - } else { - for(kt = my_keytab; kt->token != CONF_UNKNOWN; kt++) { - if(kt->keyword && strcmp(kt->keyword, tmpstr) == 0) - break; - } + break; - if(kt->token == CONF_UNKNOWN) - return NULL; + case ',': + tok = CONF_COMMA; + break; - for(np = my_var; np->token != CONF_UNKNOWN; np++) { - if(np->token == kt->token) - break; - } + case '{': + tok = CONF_LBRACE; + break; + + case '}': + tok = CONF_RBRACE; + break; + + case '\n': + tok = CONF_NL; + break; - if(np->token == CONF_UNKNOWN) return NULL; + case EOF: + tok = CONF_END; + break; - tmpstr = stralloc(conf_print(&conf_data[np->parm], 0, "")); + default: + tok = CONF_UNKNOWN; + break; + } } - return tmpstr; -} + if (exp != CONF_ANY && tok != exp) { + char *str; + keytab_t *kwp; + switch(exp) { + case CONF_LBRACE: + str = "\"{\""; + break; -char * -getconf_list( - char *listname) -{ - char *result = NULL; - tapetype_t *tp; - dumptype_t *dp; - interface_t *ip; - holdingdisk_t *hp; + case CONF_RBRACE: + str = "\"}\""; + break; - if (strcasecmp(listname,"tapetype") == 0) { - result = stralloc(""); - for(tp = tapelist; tp != NULL; tp=tp->next) { - result = vstrextend(&result, tp->name, "\n", NULL); - } - } else if (strcasecmp(listname,"dumptype") == 0) { - result = stralloc(""); - for(dp = dumplist; dp != NULL; dp=dp->next) { - result = vstrextend(&result, dp->name, "\n", NULL); - } - } else if (strcasecmp(listname,"holdingdisk") == 0) { - result = stralloc(""); - for(hp = holdingdisks; hp != NULL; hp=hp->next) { - result = vstrextend(&result, hp->name, "\n", NULL); - } - } else if (strcasecmp(listname,"interface") == 0) { - result = stralloc(""); - for(ip = interface_list; ip != NULL; ip=ip->next) { - result = vstrextend(&result, ip->name, "\n", NULL); - } - } - return result; -} + case CONF_COMMA: + str = "\",\""; + break; + case CONF_NL: + str = _("end of line"); + break; -int -getconf_seen( - confparm_t parm) -{ - return(conf_data[parm].seen); -} + case CONF_END: + str = _("end of file"); + break; -int -getconf_boolean( - confparm_t parm) -{ - if (conf_data[parm].type != CONFTYPE_BOOL) { - error("getconf_boolean: parm is not a CONFTYPE_BOOL"); - /*NOTREACHED*/ - } - return(conf_data[parm].v.i != 0); -} + case CONF_INT: + str = _("an integer"); + break; -int -getconf_int( - confparm_t parm) -{ - if (conf_data[parm].type != CONFTYPE_INT) { - error("getconf_int: parm is not a CONFTYPE_INT"); - /*NOTREACHED*/ - } - return(conf_data[parm].v.i); -} + case CONF_REAL: + str = _("a real number"); + break; -long -getconf_long( - confparm_t parm) -{ - if (conf_data[parm].type != CONFTYPE_LONG) { - error("getconf_long: parm is not a CONFTYPE_LONG"); - /*NOTREACHED*/ - } - return(conf_data[parm].v.l); -} + case CONF_STRING: + str = _("a quoted string"); + break; -time_t -getconf_time( - confparm_t parm) -{ - if (conf_data[parm].type != CONFTYPE_TIME) { - error("getconf_time: parm is not a CONFTYPE_TIME"); - /*NOTREACHED*/ - } - return(conf_data[parm].v.t); -} + case CONF_IDENT: + str = _("an identifier"); + break; -ssize_t -getconf_size( - confparm_t parm) -{ - if (conf_data[parm].type != CONFTYPE_SIZE) { - error("getconf_size: parm is not a CONFTYPE_SIZE"); - /*NOTREACHED*/ + default: + for(kwp = keytable; kwp->keyword != NULL; kwp++) { + if (exp == kwp->token) + break; + } + if (kwp->keyword == NULL) + str = _("token not"); + else + str = kwp->keyword; + break; + } + conf_parserror(_("%s is expected"), str); + tok = exp; + if (tok == CONF_INT) + tokenval.v.i = 0; + else + tokenval.v.s = ""; } - return(conf_data[parm].v.size); } -off_t -getconf_am64( - confparm_t parm) +static void +unget_conftoken(void) { - if (conf_data[parm].type != CONFTYPE_AM64) { - error("getconf_am64: parm is not a CONFTYPE_AM64"); - /*NOTREACHED*/ - } - return(conf_data[parm].v.am64); + assert(!token_pushed); + token_pushed = 1; + pushed_tok = tok; + tok = CONF_UNKNOWN; } -double -getconf_real( - confparm_t parm) +static int +conftoken_getc(void) { - if (conf_data[parm].type != CONFTYPE_REAL) { - error("getconf_real: parm is not a CONFTYPE_REAL"); - /*NOTREACHED*/ - } - return(conf_data[parm].v.r); + if(current_line == NULL) + return getc(current_file); + if(*current_char == '\0') + return -1; + return(*current_char++); } -char * -getconf_str( - confparm_t parm) +static int +conftoken_ungetc( + int c) { - if (conf_data[parm].type != CONFTYPE_STRING && - conf_data[parm].type != CONFTYPE_IDENT) { - error("getconf_str: parm is not a CONFTYPE_STRING|CONFTYPE_IDENT: %d", parm); - /*NOTREACHED*/ + if(current_line == NULL) + return ungetc(c, current_file); + else if(current_char > current_line) { + if(c == -1) + return c; + current_char--; + if(*current_char != c) { + error(_("*current_char != c : %c %c"), *current_char, c); + /* NOTREACHED */ + } + } else { + error(_("current_char == current_line")); + /* NOTREACHED */ } - return(conf_data[parm].v.s); + return c; } -int -getconf_taperalgo( - confparm_t parm) +/* + * Parser Implementation + */ + +static gboolean +read_conffile( + char *filename, + gboolean is_client) { - if (conf_data[parm].type != CONFTYPE_TAPERALGO) { - error("getconf_taperalgo: parm is not a CONFTYPE_TAPERALGO"); - /*NOTREACHED*/ + /* Save global locations. */ + FILE *save_file = current_file; + char *save_filename = current_filename; + int save_line_num = current_line_num; + int rc; + + if (is_client) { + keytable = client_keytab; + parsetable = client_var; + } else { + keytable = server_keytab; + parsetable = server_var; } - return(conf_data[parm].v.i); -} + current_filename = config_dir_relative(filename); -int* -getconf_intrange( - confparm_t parm) -{ - if (conf_data[parm].type != CONFTYPE_INTRANGE) { - error("getconf_intrange: parm is not a CONFTYPE_INTRANGE"); - /*NOTREACHED*/ + if ((current_file = fopen(current_filename, "r")) == NULL) { + g_fprintf(stderr, _("could not open conf file \"%s\": %s\n"), current_filename, + strerror(errno)); + got_parserror = TRUE; + goto finish; } - return(conf_data[parm].v.intrange); -} -holdingdisk_t * -getconf_holdingdisks( - void) -{ - return holdingdisks; -} - -dumptype_t * -lookup_dumptype( - char *str) -{ - dumptype_t *p; - - for(p = dumplist; p != NULL; p = p->next) { - if(strcasecmp(p->name, str) == 0) return p; - } - return NULL; -} - -tapetype_t * -lookup_tapetype( - char *str) -{ - tapetype_t *p; - - for(p = tapelist; p != NULL; p = p->next) { - if(strcasecmp(p->name, str) == 0) return p; - } - return NULL; -} - -holdingdisk_t * -lookup_holdingdisk( - char *str) -{ - holdingdisk_t *p; - - for(p = holdingdisks; p != NULL; p = p->next) { - if(strcasecmp(p->name, str) == 0) return p; - } - return NULL; -} - -interface_t * -lookup_interface( - char *str) -{ -#ifndef __lint - interface_t *p; -#endif - - if (str == NULL) - return interface_list; - -#ifndef __lint - for (p = interface_list; p != NULL; p = p->next) { - if (strcasecmp(p->name, str) == 0) - return p; - } -#endif - return NULL; -} - - -/* -** ------------------------ -** Internal routines -** ------------------------ -*/ - - -static void -init_defaults( - void) -{ - char *s; - - /* defaults for exported variables */ - -#ifdef DEFAULT_CONFIG - s = DEFAULT_CONFIG; -#else - s = "YOUR ORG"; -#endif -#ifdef DEFAULT_CONFIG - s = DEFAULT_CONFIG; -#else - s = ""; -#endif - conf_init_string(&conf_data[CNF_CONF], s); -#ifdef DEFAULT_SERVER - s = DEFAULT_SERVER; -#else - s = ""; -#endif - conf_init_string(&conf_data[CNF_INDEX_SERVER], s); - - -#ifdef DEFAULT_TAPE_SERVER - s = DEFAULT_TAPE_SERVER; -#else -#ifdef DEFAULT_SERVER - s = DEFAULT_SERVER; -#else - s = ""; -#endif -#endif - conf_init_string(&conf_data[CNF_TAPE_SERVER], s); - conf_init_string(&conf_data[CNF_AUTH], "bsd"); - conf_init_string(&conf_data[CNF_SSH_KEYS], ""); - conf_init_string(&conf_data[CNF_AMANDAD_PATH], ""); - conf_init_string(&conf_data[CNF_CLIENT_USERNAME], ""); -#ifdef GNUTAR_LISTED_INCREMENTAL_DIR - conf_init_string(&conf_data[CNF_GNUTAR_LIST_DIR], - GNUTAR_LISTED_INCREMENTAL_DIR); -#else - conf_init_string(&conf_data[CNF_GNUTAR_LIST_DIR], NULL); -#endif - conf_init_string(&conf_data[CNF_AMANDATES], AMANDATES_FILE); - conf_init_string(&conf_data[CNF_KRB5KEYTAB], "/.amanda-v5-keytab"); - conf_init_string(&conf_data[CNF_KRB5PRINCIPAL], "service/amanda"); - - conf_init_string(&conf_data[CNF_ORG], s); - conf_init_string(&conf_data[CNF_MAILTO], "operators"); - conf_init_string(&conf_data[CNF_DUMPUSER], CLIENT_LOGIN); -#ifdef DEFAULT_TAPE_DEVICE - s = DEFAULT_TAPE_DEVICE; -#else - s = NULL; -#endif - conf_init_string(&conf_data[CNF_TAPEDEV], s); -#ifdef DEFAULT_CHANGER_DEVICE - s = DEFAULT_CHANGER_DEVICE; -#else - s = "/dev/null"; -#endif - conf_init_string(&conf_data[CNF_CHNGRDEV], s); - conf_init_string(&conf_data[CNF_CHNGRFILE], "/usr/adm/amanda/changer-status"); -#ifdef DEFAULT_RAW_TAPE_DEVICE - s = DEFAULT_RAW_TAPE_DEVICE; -#else - s = "/dev/rawft0"; -#endif - conf_init_string (&conf_data[CNF_LABELSTR] , ".*"); - conf_init_string (&conf_data[CNF_TAPELIST] , "tapelist"); - conf_init_string (&conf_data[CNF_DISKFILE] , "disklist"); - conf_init_string (&conf_data[CNF_INFOFILE] , "/usr/adm/amanda/curinfo"); - conf_init_string (&conf_data[CNF_LOGDIR] , "/usr/adm/amanda"); - conf_init_string (&conf_data[CNF_INDEXDIR] , "/usr/adm/amanda/index"); - conf_init_ident (&conf_data[CNF_TAPETYPE] , "EXABYTE"); - conf_init_int (&conf_data[CNF_DUMPCYCLE] , 10); - conf_init_int (&conf_data[CNF_RUNSPERCYCLE] , 0); - conf_init_int (&conf_data[CNF_TAPECYCLE] , 15); - conf_init_int (&conf_data[CNF_NETUSAGE] , 300); - conf_init_int (&conf_data[CNF_INPARALLEL] , 10); - conf_init_string (&conf_data[CNF_DUMPORDER] , "ttt"); - conf_init_int (&conf_data[CNF_BUMPPERCENT] , 0); - conf_init_am64 (&conf_data[CNF_BUMPSIZE] , (off_t)10*1024); - conf_init_real (&conf_data[CNF_BUMPMULT] , 1.5); - conf_init_int (&conf_data[CNF_BUMPDAYS] , 2); - conf_init_string (&conf_data[CNF_TPCHANGER] , ""); - conf_init_int (&conf_data[CNF_RUNTAPES] , 1); - conf_init_int (&conf_data[CNF_MAXDUMPS] , 1); - conf_init_int (&conf_data[CNF_ETIMEOUT] , 300); - conf_init_int (&conf_data[CNF_DTIMEOUT] , 1800); - conf_init_int (&conf_data[CNF_CTIMEOUT] , 30); - conf_init_int (&conf_data[CNF_TAPEBUFS] , 20); - conf_init_string (&conf_data[CNF_RAWTAPEDEV] , s); - conf_init_string (&conf_data[CNF_PRINTER] , ""); - conf_init_bool (&conf_data[CNF_AUTOFLUSH] , 0); - conf_init_int (&conf_data[CNF_RESERVE] , 100); - conf_init_am64 (&conf_data[CNF_MAXDUMPSIZE] , (off_t)-1); - conf_init_string (&conf_data[CNF_COLUMNSPEC] , ""); - conf_init_bool (&conf_data[CNF_AMRECOVER_DO_FSF] , 1); - conf_init_string (&conf_data[CNF_AMRECOVER_CHANGER] , ""); - conf_init_bool (&conf_data[CNF_AMRECOVER_CHECK_LABEL], 1); - conf_init_taperalgo(&conf_data[CNF_TAPERALGO] , 0); - conf_init_string (&conf_data[CNF_DISPLAYUNIT] , "k"); - conf_init_string (&conf_data[CNF_KRB5KEYTAB] , "/.amanda-v5-keytab"); - conf_init_string (&conf_data[CNF_KRB5PRINCIPAL] , "service/amanda"); - conf_init_string (&conf_data[CNF_LABEL_NEW_TAPES] , ""); - conf_init_bool (&conf_data[CNF_USETIMESTAMPS] , 0); - conf_init_int (&conf_data[CNF_CONNECT_TRIES] , 3); - conf_init_int (&conf_data[CNF_REP_TRIES] , 5); - conf_init_int (&conf_data[CNF_REQ_TRIES] , 3); - conf_init_int (&conf_data[CNF_DEBUG_AMANDAD] , 0); - conf_init_int (&conf_data[CNF_DEBUG_AMIDXTAPED] , 0); - conf_init_int (&conf_data[CNF_DEBUG_AMINDEXD] , 0); - conf_init_int (&conf_data[CNF_DEBUG_AMRECOVER] , 0); - conf_init_int (&conf_data[CNF_DEBUG_AUTH] , 0); - conf_init_int (&conf_data[CNF_DEBUG_EVENT] , 0); - conf_init_int (&conf_data[CNF_DEBUG_HOLDING] , 0); - conf_init_int (&conf_data[CNF_DEBUG_PROTOCOL] , 0); - conf_init_int (&conf_data[CNF_DEBUG_PLANNER] , 0); - conf_init_int (&conf_data[CNF_DEBUG_DRIVER] , 0); - conf_init_int (&conf_data[CNF_DEBUG_DUMPER] , 0); - conf_init_int (&conf_data[CNF_DEBUG_CHUNKER] , 0); - conf_init_int (&conf_data[CNF_DEBUG_TAPER] , 0); - conf_init_int (&conf_data[CNF_DEBUG_SELFCHECK] , 0); - conf_init_int (&conf_data[CNF_DEBUG_SENDSIZE] , 0); - conf_init_int (&conf_data[CNF_DEBUG_SENDBACKUP] , 0); -#ifdef UDPPORTRANGE - conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT] , UDPPORTRANGE); -#else - conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT] , 512, 1023); -#endif -#ifdef LOW_TCPPORTRANGE - conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT] , LOW_TCPPORTRANGE); -#else - conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT] , 512, 1023); -#endif -#ifdef TCPPORTRANGE - conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT] , TCPPORTRANGE); -#else - conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT] , 0, 0); -#endif - - /* defaults for internal variables */ - - conf_line_num = got_parserror = 0; - allow_overwrites = 0; - token_pushed = 0; - - while(holdingdisks != NULL) { - holdingdisk_t *hp; - - hp = holdingdisks; - holdingdisks = holdingdisks->next; - amfree(hp); - } - num_holdingdisks = 0; - - /* free any previously declared dump, tape and interface types */ - - while(dumplist != NULL) { - dumptype_t *dp; - - dp = dumplist; - dumplist = dumplist->next; - amfree(dp); - } - while(tapelist != NULL) { - tapetype_t *tp; - - tp = tapelist; - tapelist = tapelist->next; - amfree(tp); - } - while(interface_list != NULL) { - interface_t *ip; - - ip = interface_list; - interface_list = interface_list->next; - amfree(ip); - } - - /* create some predefined dumptypes for backwards compatability */ - init_dumptype_defaults(); - dpcur.name = stralloc("NO-COMPRESS"); - dpcur.seen = -1; - conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_NONE); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("COMPRESS-FAST"); - dpcur.seen = -1; - conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_FAST); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("COMPRESS-BEST"); - dpcur.seen = -1; - conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_BEST); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("COMPRESS-CUST"); - dpcur.seen = -1; - conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_CUST); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("SRVCOMPRESS"); - dpcur.seen = -1; - conf_set_compress(&dpcur.value[DUMPTYPE_COMPRESS], COMP_SERVER_FAST); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("BSD-AUTH"); - dpcur.seen = -1; - conf_set_string(&dpcur.value[DUMPTYPE_SECURITY_DRIVER], "BSD"); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("KRB4-AUTH"); - dpcur.seen = -1; - conf_set_string(&dpcur.value[DUMPTYPE_SECURITY_DRIVER], "KRB4"); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("NO-RECORD"); - dpcur.seen = -1; - conf_set_bool(&dpcur.value[DUMPTYPE_RECORD], 0); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("NO-HOLD"); - dpcur.seen = -1; - conf_set_holding(&dpcur.value[DUMPTYPE_HOLDINGDISK], HOLD_NEVER); - save_dumptype(); - - init_dumptype_defaults(); - dpcur.name = stralloc("NO-FULL"); - dpcur.seen = -1; - conf_set_strategy(&dpcur.value[DUMPTYPE_STRATEGY], DS_NOFULL); - save_dumptype(); - conffile_init = 1; -} - -static void -read_conffile_recursively( - char *filename) -{ - /* Save globals used in read_confline(), elsewhere. */ - int save_line_num = conf_line_num; - FILE *save_conf = conf_conf; - char *save_confname = conf_confname; - int rc; - - if (*filename == '/' || config_dir == NULL) { - conf_confname = stralloc(filename); - } else { - conf_confname = stralloc2(config_dir, filename); - } - - if((conf_conf = fopen(conf_confname, "r")) == NULL) { - fprintf(stderr, "could not open conf file \"%s\": %s\n", conf_confname, - strerror(errno)); - amfree(conf_confname); - got_parserror = -1; - return; - } + current_line_num = 0; - conf_line_num = 0; - - /* read_confline() can invoke us recursively via "includefile" */ do { - rc = read_confline(); + /* read_confline() can invoke us recursively via "includefile" */ + rc = read_confline(is_client); } while (rc != 0); - afclose(conf_conf); - - amfree(conf_confname); - /* Restore servers */ - conf_line_num = save_line_num; - conf_conf = save_conf; - conf_confname = save_confname; -} + afclose(current_file); +finish: + amfree(current_filename); -/* ------------------------ */ + /* Restore servers */ + current_line_num = save_line_num; + current_file = save_file; + current_filename = save_filename; + return !got_parserror; +} -static int +static gboolean read_confline( - void) + gboolean is_client) { - t_conf_var *np; + conf_var_t *np; - keytable = server_keytab; - - conf_line_num += 1; + current_line_num += 1; get_conftoken(CONF_ANY); switch(tok) { case CONF_INCLUDEFILE: - { - char *fn; - char *cname; - - get_conftoken(CONF_STRING); - fn = tokenval.v.s; - if (*fn == '/' || config_dir == NULL) { - cname = stralloc(fn); - } else { - cname = stralloc2(config_dir, fn); - } - if ( cname != NULL && (access(cname, R_OK) == 0)) { - read_conffile_recursively(cname); - amfree(cname); - } else { - conf_parserror("cannot open %s: %s\n", fn, strerror(errno)); - } - amfree(cname); - - } + get_conftoken(CONF_STRING); + if (!read_conffile(tokenval.v.s, is_client)) + return 0; break; case CONF_HOLDING: - get_holdingdisk(); + if (is_client) { + handle_invalid_keyword(tokenval.v.s); + } else { + get_holdingdisk(); + } break; case CONF_DEFINE: - get_conftoken(CONF_ANY); - if(tok == CONF_DUMPTYPE) get_dumptype(); - else if(tok == CONF_TAPETYPE) get_tapetype(); - else if(tok == CONF_INTERFACE) get_interface(); - else conf_parserror("DUMPTYPE, INTERFACE or TAPETYPE expected"); + if (is_client) { + handle_invalid_keyword(tokenval.v.s); + } else { + get_conftoken(CONF_ANY); + if(tok == CONF_DUMPTYPE) get_dumptype(); + else if(tok == CONF_TAPETYPE) get_tapetype(); + else if(tok == CONF_INTERFACE) get_interface(); + else conf_parserror(_("DUMPTYPE, INTERFACE or TAPETYPE expected")); + } break; case CONF_NL: /* empty line */ @@ -1569,17 +1455,19 @@ read_confline( case CONF_END: /* end of file */ return 0; + /* if it's not a known punctuation mark, then check the parse table and use the + * read_function we find there. */ default: { - for(np = server_var; np->token != CONF_UNKNOWN; np++) + for(np = parsetable; np->token != CONF_UNKNOWN; np++) if(np->token == tok) break; if(np->token == CONF_UNKNOWN) { - conf_parserror("configuration keyword expected"); + handle_invalid_keyword(tokenval.v.s); } else { np->read_function(np, &conf_data[np->parm]); - if(np->validate) - np->validate(np, &conf_data[np->parm]); + if(np->validate_function) + np->validate_function(np, &conf_data[np->parm]); } } } @@ -1589,28 +1477,133 @@ read_confline( } static void -get_holdingdisk( - void) -{ - char *prefix; - int save_overwrites; +handle_invalid_keyword( + const char * token) +{ + /* Procedure for deprecated keywords: + * 1) At time of deprecation, add to warning_deprecated below. + * Note the date of deprecation. + * 2) After two years, move the keyword to error_deprecated below. + * Note the date of the move. + * 3) After two more years, drop the token entirely. */ + + static const char * warning_deprecated[] = { + "rawtapedev", /* 2007-01-23 */ + "tapebufs", /* 2007-10-15 */ + "netusage", /* historical since 1997-08-11, deprecated 2007-10-23 */ + NULL + }; + static const char * error_deprecated[] = { + NULL + }; + const char ** s; + + for (s = warning_deprecated; *s != NULL; s ++) { + if (strcmp(*s, token) == 0) { + conf_parswarn(_("warning: Keyword %s is deprecated."), + token); + break; + } + } + if (*s == NULL) { + for (s = error_deprecated; *s != NULL; s ++) { + if (strcmp(*s, token) == 0) { + conf_parserror(_("error: Keyword %s is deprecated."), + token); + return; + } + } + } + if (*s == NULL) { + conf_parserror(_("configuration keyword expected")); + } - save_overwrites = allow_overwrites; - allow_overwrites = 1; + for (;;) { + char c = conftoken_getc(); + if (c == '\n' || c == -1) { + conftoken_ungetc(c); + return; + } + } - init_holdingdisk_defaults(); + g_assert_not_reached(); +} + +static void +read_block( + conf_var_t *read_var, + val_t *valarray, + char *errormsg, + int read_brace, + void (*copy_function)(void)) +{ + conf_var_t *np; + int done; + + if(read_brace) { + get_conftoken(CONF_LBRACE); + get_conftoken(CONF_NL); + } + + done = 0; + do { + current_line_num += 1; + get_conftoken(CONF_ANY); + switch(tok) { + case CONF_RBRACE: + done = 1; + break; + case CONF_NL: /* empty line */ + break; + case CONF_END: /* end of file */ + done = 1; + break; + + /* inherit from a "parent" */ + case CONF_IDENT: + case CONF_STRING: + if(copy_function) + copy_function(); + else + conf_parserror(_("ident not expected")); + break; + default: + { + for(np = read_var; np->token != CONF_UNKNOWN; np++) + if(np->token == tok) break; + + if(np->token == CONF_UNKNOWN) + conf_parserror(errormsg); + else { + np->read_function(np, &valarray[np->parm]); + if(np->validate_function) + np->validate_function(np, &valarray[np->parm]); + } + } + } + if(tok != CONF_NL && tok != CONF_END && tok != CONF_RBRACE) + get_conftoken(CONF_NL); + } while(!done); +} + +static void +get_holdingdisk( + void) +{ + int save_overwrites; + + save_overwrites = allow_overwrites; + allow_overwrites = 1; + + init_holdingdisk_defaults(); get_conftoken(CONF_IDENT); hdcur.name = stralloc(tokenval.v.s); - hdcur.seen = conf_line_num; + hdcur.seen = current_line_num; - prefix = vstralloc( "HOLDINGDISK:", hdcur.name, ":", NULL); - read_block(program_options, holding_var, server_keytab, hdcur.value, prefix, - "holding disk parameter expected", 1, NULL); - amfree(prefix); + read_block(holding_var, hdcur.value, + _("holding disk parameter expected"), 1, NULL); get_conftoken(CONF_NL); - - hdcur.disksize = holdingdisk_get_disksize(&hdcur); save_holdingdisk(); allow_overwrites = save_overwrites; @@ -1620,14 +1613,11 @@ static void init_holdingdisk_defaults( void) { - conf_init_string(&hdcur.value[HOLDING_COMMENT] , ""); - conf_init_string(&hdcur.value[HOLDING_DISKDIR] , ""); + conf_init_str(&hdcur.value[HOLDING_COMMENT] , ""); + conf_init_str(&hdcur.value[HOLDING_DISKDIR] , ""); conf_init_am64(&hdcur.value[HOLDING_DISKSIZE] , (off_t)0); /* 1 Gb = 1M counted in 1Kb blocks */ conf_init_am64(&hdcur.value[HOLDING_CHUNKSIZE], (off_t)1024*1024); - - hdcur.up = (void *)0; - hdcur.disksize = 0LL; } static void @@ -1638,13 +1628,14 @@ save_holdingdisk( hp = alloc(sizeof(holdingdisk_t)); *hp = hdcur; - hp->next = holdingdisks; - holdingdisks = hp; - - num_holdingdisks++; + hp->next = holdinglist; + holdinglist = hp; } +/* WARNING: + * This function is called both from this module and from diskfile.c. Modify + * with caution. */ dumptype_t * read_dumptype( char *name, @@ -1655,20 +1646,19 @@ read_dumptype( int save_overwrites; FILE *saved_conf = NULL; char *saved_fname = NULL; - char *prefix; if (from) { - saved_conf = conf_conf; - conf_conf = from; + saved_conf = current_file; + current_file = from; } if (fname) { - saved_fname = conf_confname; - conf_confname = fname; + saved_fname = current_filename; + current_filename = fname; } if (linenum) - conf_line_num = *linenum; + current_line_num = *linenum; save_overwrites = allow_overwrites; allow_overwrites = 1; @@ -1680,14 +1670,13 @@ read_dumptype( get_conftoken(CONF_IDENT); dpcur.name = stralloc(tokenval.v.s); } - dpcur.seen = conf_line_num; - - prefix = vstralloc( "DUMPTYPE:", dpcur.name, ":", NULL); - read_block(program_options, dumptype_var, server_keytab, dpcur.value, - prefix, "dumptype parameter expected", - (name == NULL), *copy_dumptype); - amfree(prefix); - if(!name) + dpcur.seen = current_line_num; + + read_block(dumptype_var, dpcur.value, + _("dumptype parameter expected"), + (name == NULL), copy_dumptype); + + if(!name) /* !name => reading disklist, not conffile */ get_conftoken(CONF_NL); /* XXX - there was a stupidity check in here for skip-incr and @@ -1698,13 +1687,13 @@ read_dumptype( allow_overwrites = save_overwrites; if (linenum) - *linenum = conf_line_num; + *linenum = current_line_num; if (fname) - conf_confname = saved_fname; + current_filename = saved_fname; if (from) - conf_conf = saved_conf; + current_file = saved_conf; return lookup_dumptype(dpcur.name); } @@ -1719,16 +1708,16 @@ static void init_dumptype_defaults(void) { dpcur.name = NULL; - conf_init_string (&dpcur.value[DUMPTYPE_COMMENT] , ""); - conf_init_string (&dpcur.value[DUMPTYPE_PROGRAM] , "DUMP"); - conf_init_string (&dpcur.value[DUMPTYPE_SRVCOMPPROG] , ""); - conf_init_string (&dpcur.value[DUMPTYPE_CLNTCOMPPROG] , ""); - conf_init_string (&dpcur.value[DUMPTYPE_SRV_ENCRYPT] , ""); - conf_init_string (&dpcur.value[DUMPTYPE_CLNT_ENCRYPT] , ""); - conf_init_string (&dpcur.value[DUMPTYPE_AMANDAD_PATH] , "X"); - conf_init_string (&dpcur.value[DUMPTYPE_CLIENT_USERNAME] , "X"); - conf_init_string (&dpcur.value[DUMPTYPE_SSH_KEYS] , "X"); - conf_init_string (&dpcur.value[DUMPTYPE_SECURITY_DRIVER] , "BSD"); + conf_init_str (&dpcur.value[DUMPTYPE_COMMENT] , ""); + conf_init_str (&dpcur.value[DUMPTYPE_PROGRAM] , "DUMP"); + conf_init_str (&dpcur.value[DUMPTYPE_SRVCOMPPROG] , ""); + conf_init_str (&dpcur.value[DUMPTYPE_CLNTCOMPPROG] , ""); + conf_init_str (&dpcur.value[DUMPTYPE_SRV_ENCRYPT] , ""); + conf_init_str (&dpcur.value[DUMPTYPE_CLNT_ENCRYPT] , ""); + conf_init_str (&dpcur.value[DUMPTYPE_AMANDAD_PATH] , "X"); + conf_init_str (&dpcur.value[DUMPTYPE_CLIENT_USERNAME] , "X"); + conf_init_str (&dpcur.value[DUMPTYPE_SSH_KEYS] , "X"); + conf_init_str (&dpcur.value[DUMPTYPE_SECURITY_DRIVER] , "BSD"); conf_init_exinclude(&dpcur.value[DUMPTYPE_EXCLUDE]); conf_init_exinclude(&dpcur.value[DUMPTYPE_INCLUDE]); conf_init_priority (&dpcur.value[DUMPTYPE_PRIORITY] , 1); @@ -1744,12 +1733,12 @@ init_dumptype_defaults(void) conf_init_estimate (&dpcur.value[DUMPTYPE_ESTIMATE] , ES_CLIENT); conf_init_compress (&dpcur.value[DUMPTYPE_COMPRESS] , COMP_FAST); conf_init_encrypt (&dpcur.value[DUMPTYPE_ENCRYPT] , ENCRYPT_NONE); - conf_init_string (&dpcur.value[DUMPTYPE_SRV_DECRYPT_OPT] , "-d"); - conf_init_string (&dpcur.value[DUMPTYPE_CLNT_DECRYPT_OPT] , "-d"); + conf_init_str (&dpcur.value[DUMPTYPE_SRV_DECRYPT_OPT] , "-d"); + conf_init_str (&dpcur.value[DUMPTYPE_CLNT_DECRYPT_OPT] , "-d"); conf_init_rate (&dpcur.value[DUMPTYPE_COMPRATE] , 0.50, 0.50); conf_init_am64 (&dpcur.value[DUMPTYPE_TAPE_SPLITSIZE] , (off_t)0); conf_init_am64 (&dpcur.value[DUMPTYPE_FALLBACK_SPLITSIZE], (off_t)10 * 1024); - conf_init_string (&dpcur.value[DUMPTYPE_SPLIT_DISKBUFFER] , NULL); + conf_init_str (&dpcur.value[DUMPTYPE_SPLIT_DISKBUFFER] , NULL); conf_init_bool (&dpcur.value[DUMPTYPE_RECORD] , 1); conf_init_bool (&dpcur.value[DUMPTYPE_SKIP_INCR] , 0); conf_init_bool (&dpcur.value[DUMPTYPE_SKIP_FULL] , 0); @@ -1767,7 +1756,7 @@ save_dumptype(void) dp = lookup_dumptype(dpcur.name); if(dp != (dumptype_t *)0) { - conf_parserror("dumptype %s already defined on line %d", dp->name, dp->seen); + conf_parserror(_("dumptype %s already defined on line %d"), dp->name, dp->seen); return; } @@ -1795,7 +1784,7 @@ copy_dumptype(void) dt = lookup_dumptype(tokenval.v.s); if(dt == NULL) { - conf_parserror("dumptype parameter expected"); + conf_parserror(_("dumptype parameter expected")); return; } @@ -1811,7 +1800,6 @@ static void get_tapetype(void) { int save_overwrites; - char *prefix; save_overwrites = allow_overwrites; allow_overwrites = 1; @@ -1820,12 +1808,10 @@ get_tapetype(void) get_conftoken(CONF_IDENT); tpcur.name = stralloc(tokenval.v.s); - tpcur.seen = conf_line_num; + tpcur.seen = current_line_num; - prefix = vstralloc( "TAPETYPE:", tpcur.name, ":", NULL); - read_block(program_options, tapetype_var, server_keytab, tpcur.value, - prefix, "tapetype parameter expected", 1, ©_tapetype); - amfree(prefix); + read_block(tapetype_var, tpcur.value, + _("tapetype parameter expected"), 1, copy_tapetype); get_conftoken(CONF_NL); save_tapetype(); @@ -1836,12 +1822,12 @@ get_tapetype(void) static void init_tapetype_defaults(void) { - conf_init_string(&tpcur.value[TAPETYPE_COMMENT] , ""); - conf_init_string(&tpcur.value[TAPETYPE_LBL_TEMPL] , ""); + conf_init_str(&tpcur.value[TAPETYPE_COMMENT] , ""); + conf_init_str(&tpcur.value[TAPETYPE_LBL_TEMPL] , ""); conf_init_size (&tpcur.value[TAPETYPE_BLOCKSIZE] , DISK_BLOCK_KB); conf_init_size (&tpcur.value[TAPETYPE_READBLOCKSIZE], MAX_TAPE_BLOCK_KB); - conf_init_am64 (&tpcur.value[TAPETYPE_LENGTH] , (off_t)2000); - conf_init_am64 (&tpcur.value[TAPETYPE_FILEMARK] , (off_t)1); + conf_init_am64 (&tpcur.value[TAPETYPE_LENGTH] , ((off_t)2000 * 1024)); + conf_init_am64 (&tpcur.value[TAPETYPE_FILEMARK] , (off_t)1000); conf_init_int (&tpcur.value[TAPETYPE_SPEED] , 200); conf_init_bool (&tpcur.value[TAPETYPE_FILE_PAD] , 1); } @@ -1855,7 +1841,7 @@ save_tapetype(void) if(tp != (tapetype_t *)0) { amfree(tpcur.name); - conf_parserror("tapetype %s already defined on line %d", tp->name, tp->seen); + conf_parserror(_("tapetype %s already defined on line %d"), tp->name, tp->seen); return; } @@ -1882,7 +1868,7 @@ copy_tapetype(void) tp = lookup_tapetype(tokenval.v.s); if(tp == NULL) { - conf_parserror("tape type parameter expected"); + conf_parserror(_("tape type parameter expected")); return; } @@ -1894,17 +1880,10 @@ copy_tapetype(void) } } -t_conf_var interface_var [] = { - { CONF_COMMENT, CONFTYPE_STRING, read_string, INTER_COMMENT , NULL }, - { CONF_USE , CONFTYPE_INT , read_int , INTER_MAXUSAGE, validate_positive1 }, - { CONF_UNKNOWN, CONFTYPE_INT , NULL , INTER_INTER , NULL } -}; - static void get_interface(void) { int save_overwrites; - char *prefix; save_overwrites = allow_overwrites; allow_overwrites = 1; @@ -1913,12 +1892,10 @@ get_interface(void) get_conftoken(CONF_IDENT); ifcur.name = stralloc(tokenval.v.s); - ifcur.seen = conf_line_num; + ifcur.seen = current_line_num; - prefix = vstralloc( "INTERFACE:", ifcur.name, ":", NULL); - read_block(program_options, interface_var, server_keytab, ifcur.value, - prefix, "interface parameter expected", 1, ©_interface); - amfree(prefix); + read_block(interface_var, ifcur.value, + _("interface parameter expected"), 1, copy_interface); get_conftoken(CONF_NL); save_interface(); @@ -1931,10 +1908,8 @@ get_interface(void) static void init_interface_defaults(void) { - conf_init_string(&ifcur.value[INTER_COMMENT] , ""); - conf_init_int (&ifcur.value[INTER_MAXUSAGE], 300); - - ifcur.curusage = 0; + conf_init_str(&ifcur.value[INTER_COMMENT] , ""); + conf_init_int (&ifcur.value[INTER_MAXUSAGE], 8000); } static void @@ -1945,7 +1920,7 @@ save_interface(void) ip = lookup_interface(ifcur.name); if(ip != (interface_t *)0) { - conf_parserror("interface %s already defined on line %d", ip->name, + conf_parserror(_("interface %s already defined on line %d"), ip->name, ip->seen); return; } @@ -1967,20 +1942,13 @@ save_interface(void) static void copy_interface(void) { -/* - int i; - t_xxx *np; - keytab_t *kt; - - val_t val; -*/ interface_t *ip; int i; ip = lookup_interface(tokenval.v.s); if(ip == NULL) { - conf_parserror("interface parameter expected"); + conf_parserror(_("interface parameter expected")); return; } @@ -1992,82 +1960,92 @@ copy_interface(void) } } +/* Read functions */ + static void -get_comprate( - t_conf_var *np, +read_int( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { - np = np; - get_conftoken(CONF_REAL); - val->v.rate[0] = tokenval.v.r; - val->v.rate[1] = tokenval.v.r; - val->seen = tokenval.seen; - if(tokenval.v.r < 0) { - conf_parserror("full compression rate must be >= 0"); - } - - get_conftoken(CONF_ANY); - switch(tok) { - case CONF_NL: - return; - - case CONF_END: - return; - - case CONF_COMMA: - break; + ckseen(&val->seen); + val_t__int(val) = get_int(); +} - default: - unget_conftoken(); - } +static void +read_am64( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); + val_t__am64(val) = get_am64_t(); +} +static void +read_real( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); get_conftoken(CONF_REAL); - val->v.rate[1] = tokenval.v.r; - if(tokenval.v.r < 0) { - conf_parserror("incremental compression rate must be >= 0"); - } + val_t__real(val) = tokenval.v.r; } static void -read_intrange( - t_conf_var *np, +read_str( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { - np = np; - get_conftoken(CONF_INT); - val->v.intrange[0] = tokenval.v.i; - val->v.intrange[1] = tokenval.v.i; - val->seen = tokenval.seen; - - get_conftoken(CONF_ANY); - switch(tok) { - case CONF_NL: - return; + ckseen(&val->seen); + get_conftoken(CONF_STRING); + val->v.s = newstralloc(val->v.s, tokenval.v.s); +} - case CONF_END: - return; +static void +read_ident( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); + get_conftoken(CONF_IDENT); + val->v.s = newstralloc(val->v.s, tokenval.v.s); +} - case CONF_COMMA: - break; +static void +read_time( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); + val_t__time(val) = get_time(); +} - default: - unget_conftoken(); - } +static void +read_size( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); + val_t__size(val) = get_size(); +} - get_conftoken(CONF_INT); - val->v.intrange[1] = tokenval.v.i; +static void +read_bool( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + ckseen(&val->seen); + val_t__boolean(val) = get_bool(); } static void -get_compress( - t_conf_var *np, +read_compress( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { int serv, clie, none, fast, best, custom; int done; comp_t comp; - np = np; ckseen(&val->seen); serv = clie = none = fast = best = custom = 0; @@ -2110,21 +2088,20 @@ get_compress( } if((int)comp == -1) { - conf_parserror("NONE, CLIENT FAST, CLIENT BEST, CLIENT CUSTOM, SERVER FAST, SERVER BEST or SERVER CUSTOM expected"); + conf_parserror(_("NONE, CLIENT FAST, CLIENT BEST, CLIENT CUSTOM, SERVER FAST, SERVER BEST or SERVER CUSTOM expected")); comp = COMP_NONE; } - val->v.i = (int)comp; + val_t__compress(val) = (int)comp; } static void -get_encrypt( - t_conf_var *np, +read_encrypt( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { encrypt_t encrypt; - np = np; ckseen(&val->seen); get_conftoken(CONF_ANY); @@ -2142,22 +2119,21 @@ get_encrypt( break; default: - conf_parserror("NONE, CLIENT or SERVER expected"); + conf_parserror(_("NONE, CLIENT or SERVER expected")); encrypt = ENCRYPT_NONE; break; } - val->v.i = (int)encrypt; + val_t__encrypt(val) = (int)encrypt; } static void -get_holding( - t_conf_var *np, +read_holding( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { dump_holdingdisk_t holding; - np = np; ckseen(&val->seen); get_conftoken(CONF_ANY); @@ -2182,65 +2158,47 @@ get_holding( else if (holding == 1 || holding == 2) holding = HOLD_AUTO; else - conf_parserror("NEVER, AUTO or REQUIRED expected"); + conf_parserror(_("NEVER, AUTO or REQUIRED expected")); break; } - val->v.i = (int)holding; -} - -static void -get_taperalgo( - t_conf_var *np, - val_t *val) -{ - np = np; - ckseen(&val->seen); - - get_conftoken(CONF_ANY); - switch(tok) { - case CONF_FIRST: val->v.i = ALGO_FIRST; break; - case CONF_FIRSTFIT: val->v.i = ALGO_FIRSTFIT; break; - case CONF_LARGEST: val->v.i = ALGO_LARGEST; break; - case CONF_LARGESTFIT: val->v.i = ALGO_LARGESTFIT; break; - case CONF_SMALLEST: val->v.i = ALGO_SMALLEST; break; - case CONF_LAST: val->v.i = ALGO_LAST; break; - default: - conf_parserror("FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST or LAST expected"); - } + val_t__holding(val) = (int)holding; } static void -get_priority( - t_conf_var *np, +read_estimate( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { - int pri; + int estime; - np = np; ckseen(&val->seen); get_conftoken(CONF_ANY); switch(tok) { - case CONF_LOW: pri = 0; break; - case CONF_MEDIUM: pri = 1; break; - case CONF_HIGH: pri = 2; break; - case CONF_INT: pri = tokenval.v.i; break; + case CONF_CLIENT: + estime = ES_CLIENT; + break; + case CONF_SERVER: + estime = ES_SERVER; + break; + case CONF_CALCSIZE: + estime = ES_CALCSIZE; + break; default: - conf_parserror("LOW, MEDIUM, HIGH or integer expected"); - pri = 0; + conf_parserror(_("CLIENT, SERVER or CALCSIZE expected")); + estime = ES_CLIENT; } - val->v.i = pri; + val_t__estimate(val) = estime; } static void -get_strategy( - t_conf_var *np, +read_strategy( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { int strat; - np = np; ckseen(&val->seen); get_conftoken(CONF_ANY); @@ -2264,60 +2222,108 @@ get_strategy( strat = DS_INCRONLY; break; default: - conf_parserror("STANDARD or NOFULL expected"); + conf_parserror(_("dump strategy expected")); strat = DS_STANDARD; } - val->v.i = strat; + val_t__strategy(val) = strat; } static void -get_estimate( - t_conf_var *np, +read_taperalgo( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { - int estime; + ckseen(&val->seen); + + get_conftoken(CONF_ANY); + switch(tok) { + case CONF_FIRST: val_t__taperalgo(val) = ALGO_FIRST; break; + case CONF_FIRSTFIT: val_t__taperalgo(val) = ALGO_FIRSTFIT; break; + case CONF_LARGEST: val_t__taperalgo(val) = ALGO_LARGEST; break; + case CONF_LARGESTFIT: val_t__taperalgo(val) = ALGO_LARGESTFIT; break; + case CONF_SMALLEST: val_t__taperalgo(val) = ALGO_SMALLEST; break; + case CONF_LAST: val_t__taperalgo(val) = ALGO_LAST; break; + default: + conf_parserror(_("FIRST, FIRSTFIT, LARGEST, LARGESTFIT, SMALLEST or LAST expected")); + } +} + +static void +read_priority( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + int pri; - np = np; ckseen(&val->seen); get_conftoken(CONF_ANY); switch(tok) { - case CONF_CLIENT: - estime = ES_CLIENT; - break; - case CONF_SERVER: - estime = ES_SERVER; - break; - case CONF_CALCSIZE: - estime = ES_CALCSIZE; + case CONF_LOW: pri = 0; break; + case CONF_MEDIUM: pri = 1; break; + case CONF_HIGH: pri = 2; break; + case CONF_INT: pri = tokenval.v.i; break; + default: + conf_parserror(_("LOW, MEDIUM, HIGH or integer expected")); + pri = 0; + } + val_t__priority(val) = pri; +} + +static void +read_rate( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) +{ + get_conftoken(CONF_REAL); + val_t__rate(val)[0] = tokenval.v.r; + val_t__rate(val)[1] = tokenval.v.r; + val->seen = tokenval.seen; + if(tokenval.v.r < 0) { + conf_parserror(_("full compression rate must be >= 0")); + } + + get_conftoken(CONF_ANY); + switch(tok) { + case CONF_NL: + return; + + case CONF_END: + return; + + case CONF_COMMA: break; + default: - conf_parserror("CLIENT, SERVER or CALCSIZE expected"); - estime = ES_CLIENT; + unget_conftoken(); + } + + get_conftoken(CONF_REAL); + val_t__rate(val)[1] = tokenval.v.r; + if(tokenval.v.r < 0) { + conf_parserror(_("incremental compression rate must be >= 0")); } - val->v.i = estime; } static void -get_exclude( - t_conf_var *np, +read_exinclude( + conf_var_t *np G_GNUC_UNUSED, val_t *val) { int file, got_one = 0; sl_t *exclude; int optional = 0; - np = np; get_conftoken(CONF_ANY); if(tok == CONF_LIST) { file = 0; get_conftoken(CONF_ANY); - exclude = val->v.exinclude.sl_list; + exclude = val_t__exinclude(val).sl_list; } else { file = 1; if(tok == CONF_EFILE) get_conftoken(CONF_ANY); - exclude = val->v.exinclude.sl_file; + exclude = val_t__exinclude(val).sl_file; } ckseen(&val->seen); @@ -2344,1765 +2350,1852 @@ get_exclude( if(got_one == 0) { free_sl(exclude); exclude = NULL; } if (file == 0) - val->v.exinclude.sl_list = exclude; + val_t__exinclude(val).sl_list = exclude; else - val->v.exinclude.sl_file = exclude; - val->v.exinclude.optional = optional; + val_t__exinclude(val).sl_file = exclude; + val_t__exinclude(val).optional = optional; } -/* -static void get_include(np, val) - t_conf_var *np; - val_t *val; +static void +read_intrange( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) { - int list, got_one = 0; - sl_t *include; - int optional = 0; - int append = 0; + get_conftoken(CONF_INT); + val_t__intrange(val)[0] = tokenval.v.i; + val_t__intrange(val)[1] = tokenval.v.i; + val->seen = tokenval.seen; get_conftoken(CONF_ANY); - if(tok == CONF_LIST) { - list = 1; - include = dpcur.value[DUMPTYPE_INCLUDE_LIST].v.sl; - ckseen(&dpcur.value[DUMPTYPE_INCLUDE_LIST].seen); - get_conftoken(CONF_ANY); - } - else { - list = 0; - include = dpcur.value[DUMPTYPE_INCLUDE_FILE].v.sl; - ckseen(&dpcur.value[DUMPTYPE_INCLUDE_FILE].seen); - if(tok == CONF_EFILE) get_conftoken(CONF_ANY); - } + switch(tok) { + case CONF_NL: + return; - if(tok == CONF_OPTIONAL) { - get_conftoken(CONF_ANY); - optional = 1; - } - - if(tok == CONF_APPEND) { - get_conftoken(CONF_ANY); - append = 1; - } - else { - free_sl(include); - include = NULL; - append = 0; - } - - while(tok == CONF_STRING) { - include = append_sl(include, tokenval.v.s); - got_one = 1; - get_conftoken(CONF_ANY); - } - unget_conftoken(); + case CONF_END: + return; - if(got_one == 0) { free_sl(include); include = NULL; } + case CONF_COMMA: + break; - if(list == 0) - dpcur.value[DUMPTYPE_INCLUDE_FILE].v.sl = include; - else { - dpcur.value[DUMPTYPE_INCLUDE_LIST].v.sl = include; - if(!append || optional) - dpcur.value[DUMPTYPE_INCLUDE_OPTIONAL].v.i = optional; + default: + unget_conftoken(); } -} -*/ - -/* ------------------------ */ -int -ColumnDataCount(void ) -{ - return (int)(SIZEOF(ColumnData) / SIZEOF(ColumnData[0])); + get_conftoken(CONF_INT); + val_t__intrange(val)[1] = tokenval.v.i; } -/* conversion from string to table index - */ -int -StringToColumn( - char *s) +static void +read_property( + conf_var_t *np G_GNUC_UNUSED, + val_t *val) { - int cn; + char *key, *value; + get_conftoken(CONF_STRING); + key = strdup(tokenval.v.s); + get_conftoken(CONF_STRING); + value = strdup(tokenval.v.s); - for (cn=0; ColumnData[cn].Name != NULL; cn++) { - if (strcasecmp(s, ColumnData[cn].Name) == 0) { - break; - } - } - return cn; + g_hash_table_insert(val_t__proplist(val), key, value); } -char -LastChar( - char *s) -{ - return s[strlen(s)-1]; -} +/* get_* functions */ -int -SetColumDataFromString( - ColumnInfo* ci, - char *s, - char **errstr) +static time_t +get_time(void) { -#ifdef TEST - char *myname= "SetColumDataFromString"; -#endif - ci = ci; - - /* Convert from a Columspec string to our internal format - * of columspec. The purpose is to provide this string - * as configuration paramter in the amanda.conf file or - * (maybe) as environment variable. - * - * This text should go as comment into the sample amanda.conf - * - * The format for such a ColumnSpec string s is a ',' seperated - * list of triples. Each triple consists of - * -the name of the column (as in ColumnData.Name) - * -prefix before the column - * -the width of the column - * if set to -1 it will be recalculated - * to the maximum length of a line to print. - * Example: - * "Disk=1:17,HostName=1:10,OutKB=1:7" - * or - * "Disk=1:-1,HostName=1:10,OutKB=1:7" - * - * You need only specify those colums that should be changed from - * the default. If nothing is specified in the configfile, the - * above compiled in values will be in effect, resulting in an - * output as it was all the time. - * ElB, 1999-02-24. - */ - - while (s && *s) { - int Space, Width; - int cn; - char *eon= strchr(s, '='); + time_t hhmm; - if (eon == NULL) { - *errstr = stralloc2("invalid columnspec: ", s); -#ifdef TEST - fprintf(stderr, "%s: %s\n", myname, *errstr); + get_conftoken(CONF_ANY); + switch(tok) { + case CONF_INT: +#if SIZEOF_TIME_T < SIZEOF_INT + if ((off_t)tokenval.v.i >= (off_t)TIME_MAX) + conf_parserror(_("value too large")); #endif - return -1; - } - *eon= '\0'; - cn=StringToColumn(s); - if (ColumnData[cn].Name == NULL) { - *errstr = stralloc2("invalid column name: ", s); -#ifdef TEST - fprintf(stderr, "%s: %s\n", myname, *errstr); + hhmm = (time_t)tokenval.v.i; + break; + + case CONF_SIZE: +#if SIZEOF_TIME_T < SIZEOF_SSIZE_T + if ((off_t)tokenval.v.size >= (off_t)TIME_MAX) + conf_parserror(_("value too large")); #endif - return -1; - } - if (sscanf(eon+1, "%d:%d", &Space, &Width) != 2) { - *errstr = stralloc2("invalid format: ", eon + 1); -#ifdef TEST - fprintf(stderr, "%s: %s\n", myname, *errstr); + hhmm = (time_t)tokenval.v.size; + break; + + case CONF_AM64: +#if SIZEOF_TIME_T < SIZEOF_LONG_LONG + if ((off_t)tokenval.v.am64 >= (off_t)TIME_MAX) + conf_parserror(_("value too large")); #endif - return -1; - } - ColumnData[cn].Width= Width; - ColumnData[cn].PrefixSpace = Space; - if (LastChar(ColumnData[cn].Format) == 's') { - if (Width < 0) - ColumnData[cn].MaxWidth= 1; - else - if (Width > ColumnData[cn].Precision) - ColumnData[cn].Precision= Width; - } - else if (Width < ColumnData[cn].Precision) - ColumnData[cn].Precision = Width; - s= strchr(eon+1, ','); - if (s != NULL) - s++; - } - return 0; -} + hhmm = (time_t)tokenval.v.am64; + break; + case CONF_AMINFINITY: + hhmm = TIME_MAX; + break; -long int -getconf_unit_divisor(void) -{ - return unit_divisor; + default: + conf_parserror(_("a time is expected")); + hhmm = 0; + break; + } + return hhmm; } -/* ------------------------ */ - - -void -dump_configuration( - char *filename) +static int +get_int(void) { - tapetype_t *tp; - dumptype_t *dp; - interface_t *ip; - holdingdisk_t *hp; - int i; - t_conf_var *np; - keytab_t *kt; - char *prefix; - char kt_prefix[100]; - - printf("AMANDA CONFIGURATION FROM FILE \"%s\":\n\n", filename); - - for(np=server_var; np->token != CONF_UNKNOWN; np++) { - for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) - if (np->token == kt->token) break; - - if(kt->token == CONF_UNKNOWN) - error("server bad token"); - - if (kt->token != CONF_IDENT) - snprintf(kt_prefix, 100, "%-21s ", kt->keyword); - printf("%s\n", - conf_print(&conf_data[np->parm], 1, kt_prefix)); - } + int val; + keytab_t *save_kt; - for(hp = holdingdisks; hp != NULL; hp = hp->next) { - printf("\nHOLDINGDISK %s {\n", hp->name); - for(i=0; i < HOLDING_HOLDING; i++) { - for(np=holding_var; np->token != CONF_UNKNOWN; np++) { - if(np->parm == i) - break; - } - if(np->token == CONF_UNKNOWN) - error("holding bad value"); + save_kt = keytable; + keytable = numb_keytable; - for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) { - if(kt->token == np->token) - break; - } - if(kt->token == CONF_UNKNOWN) - error("holding bad token"); + get_conftoken(CONF_ANY); + switch(tok) { + case CONF_INT: + val = tokenval.v.i; + break; - snprintf(kt_prefix, 100, " %-9s ", kt->keyword); - printf("%s\n", conf_print(&hp->value[i], 1, kt_prefix)); - } - printf("}\n"); - } + case CONF_SIZE: +#if SIZEOF_INT < SIZEOF_SSIZE_T + if ((off_t)tokenval.v.size > (off_t)INT_MAX) + conf_parserror(_("value too large")); + if ((off_t)tokenval.v.size < (off_t)INT_MIN) + conf_parserror(_("value too small")); +#endif + val = (int)tokenval.v.size; + break; - for(tp = tapelist; tp != NULL; tp = tp->next) { - printf("\nDEFINE TAPETYPE %s {\n", tp->name); - for(i=0; i < TAPETYPE_TAPETYPE; i++) { - for(np=tapetype_var; np->token != CONF_UNKNOWN; np++) - if(np->parm == i) break; - if(np->token == CONF_UNKNOWN) - error("tapetype bad value"); + case CONF_AM64: +#if SIZEOF_INT < SIZEOF_LONG_LONG + if (tokenval.v.am64 > (off_t)INT_MAX) + conf_parserror(_("value too large")); + if (tokenval.v.am64 < (off_t)INT_MIN) + conf_parserror(_("value too small")); +#endif + val = (int)tokenval.v.am64; + break; - for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) - if(kt->token == np->token) break; - if(kt->token == CONF_UNKNOWN) - error("tapetype bad token"); + case CONF_AMINFINITY: + val = INT_MAX; + break; - snprintf(kt_prefix, 100, " %-9s ", kt->keyword); - printf("%s\n", conf_print(&tp->value[i], 1, kt_prefix)); - } - printf("}\n"); + default: + conf_parserror(_("an integer is expected")); + val = 0; + break; } - for(dp = dumplist; dp != NULL; dp = dp->next) { - if (strncmp(dp->name, "custom(", 7) != 0) { - if(dp->seen == -1) - prefix = "#"; - else - prefix = ""; - printf("\n%sDEFINE DUMPTYPE %s {\n", prefix, dp->name); - for(i=0; i < DUMPTYPE_DUMPTYPE; i++) { - for(np=dumptype_var; np->token != CONF_UNKNOWN; np++) - if(np->parm == i) break; - if(np->token == CONF_UNKNOWN) - error("dumptype bad value"); - - for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) - if(kt->token == np->token) break; - if(kt->token == CONF_UNKNOWN) - error("dumptype bad token"); + /* get multiplier, if any */ + get_conftoken(CONF_ANY); + switch(tok) { + case CONF_NL: /* multiply by one */ + case CONF_END: + case CONF_MULT1: + case CONF_MULT1K: + break; - snprintf(kt_prefix, 100, "%s %-19s ", prefix,kt->keyword); - printf("%s\n", conf_print(&dp->value[i], 1, kt_prefix)); - } - printf("%s}\n", prefix); - } - } + case CONF_MULT7: + if (val > (INT_MAX / 7)) + conf_parserror(_("value too large")); + if (val < (INT_MIN / 7)) + conf_parserror(_("value too small")); + val *= 7; + break; - for(ip = interface_list; ip != NULL; ip = ip->next) { - if(strcmp(ip->name,"default") == 0) - prefix = "#"; - else - prefix = ""; - printf("\n%sDEFINE INTERFACE %s {\n", prefix, ip->name); - for(i=0; i < INTER_INTER; i++) { - for(np=interface_var; np->token != CONF_UNKNOWN; np++) - if(np->parm == i) break; - if(np->token == CONF_UNKNOWN) - error("interface bad value"); + case CONF_MULT1M: + if (val > (INT_MAX / 1024)) + conf_parserror(_("value too large")); + if (val < (INT_MIN / 1024)) + conf_parserror(_("value too small")); + val *= 1024; + break; - for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) - if(kt->token == np->token) break; - if(kt->token == CONF_UNKNOWN) - error("interface bad token"); + case CONF_MULT1G: + if (val > (INT_MAX / (1024 * 1024))) + conf_parserror(_("value too large")); + if (val < (INT_MIN / (1024 * 1024))) + conf_parserror(_("value too small")); + val *= 1024 * 1024; + break; - snprintf(kt_prefix, 100, "%s %-19s ", prefix, kt->keyword); - printf("%s\n", conf_print(&ip->value[i], 1, kt_prefix)); - } - printf("%s}\n",prefix); + default: /* it was not a multiplier */ + unget_conftoken(); + break; } + keytable = save_kt; + return val; } -char * -generic_get_security_conf( - char *string, - void *arg) +static ssize_t +get_size(void) { - arg = arg; - if(!string || !*string) - return(NULL); + ssize_t val; + keytab_t *save_kt; - if(strcmp(string, "krb5principal")==0) { - return(getconf_str(CNF_KRB5PRINCIPAL)); - } else if(strcmp(string, "krb5keytab")==0) { - return(getconf_str(CNF_KRB5KEYTAB)); - } - return(NULL); -} + save_kt = keytable; + keytable = numb_keytable; -char * -get_token_name( - tok_t token) -{ - keytab_t *kt; + get_conftoken(CONF_ANY); - if (my_keytab == NULL) { - error("my_keytab == NULL"); - /*NOTREACHED*/ - } + switch(tok) { + case CONF_SIZE: + val = tokenval.v.size; + break; - for(kt = my_keytab; kt->token != CONF_UNKNOWN; kt++) - if(kt->token == token) break; + case CONF_INT: +#if SIZEOF_SIZE_T < SIZEOF_INT + if ((off_t)tokenval.v.i > (off_t)SSIZE_MAX) + conf_parserror(_("value too large")); + if ((off_t)tokenval.v.i < (off_t)SSIZE_MIN) + conf_parserror(_("value too small")); +#endif + val = (ssize_t)tokenval.v.i; + break; - if(kt->token == CONF_UNKNOWN) - return(""); - return(kt->keyword); -} - -void -parse_conf( - int parse_argc, - char **parse_argv, - int *new_argc, - char ***new_argv) -{ - int i; - char **my_argv; - char *myarg, *value; - command_option_t *program_option; - - program_options = alloc((size_t)(parse_argc+1) * SIZEOF(*program_options)); - program_options_size = parse_argc+1; - program_option = program_options; - program_option->name = NULL; - - my_argv = alloc((size_t)parse_argc * SIZEOF(char *)); - *new_argv = my_argv; - *new_argc = 0; - i=0; - while(i 2) - myarg = &parse_argv[i][2]; - else { - i++; - if(i >= parse_argc) - error("expect something after -o"); - myarg = parse_argv[i]; - } - value = index(myarg,'='); - if (value == NULL) { - conf_parserror("Must specify a value for %s.\n", myarg); - } else { - *value = '\0'; - value++; - program_option->used = 0; - program_option->name = stralloc(myarg); - program_option->value = stralloc(value); - program_option++; - program_option->name = NULL; - } - } - else { - my_argv[*new_argc] = stralloc(parse_argv[i]); - *new_argc += 1; - } - i++; - } -} - -char ** -get_config_options( - int first) -{ - char **config_options; - char **config_option; - command_option_t *command_options; - - config_options = alloc((first+program_options_size+1)*SIZEOF(char *)); - for(command_options = program_options, - config_option = config_options + first; - command_options->name != NULL; command_options++) { - *config_option = vstralloc("-o", command_options->name, "=", - command_options->value, NULL); - config_option++; - } - *config_option = NULL; - return(config_options); -} + case CONF_AM64: +#if SIZEOF_SIZE_T < SIZEOF_LONG_LONG + if (tokenval.v.am64 > (off_t)SSIZE_MAX) + conf_parserror(_("value too large")); + if (tokenval.v.am64 < (off_t)SSIZE_MIN) + conf_parserror(_("value too small")); +#endif + val = (ssize_t)tokenval.v.am64; + break; -void -report_bad_conf_arg(void) -{ - command_option_t *command_option; + case CONF_AMINFINITY: + val = (ssize_t)SSIZE_MAX; + break; - for(command_option = program_options; command_option->name != NULL; - command_option++) { - if(command_option->used == 0) { - fprintf(stderr,"argument -o%s=%s not used\n", - command_option->name, command_option->value); - } + default: + conf_parserror(_("an integer is expected")); + val = 0; + break; } -} -void -free_server_config(void) -{ - holdingdisk_t *hp, *hpnext; - dumptype_t *dp, *dpnext; - tapetype_t *tp, *tpnext; - interface_t *ip, *ipnext; - command_option_t *server_option; - int i; + /* get multiplier, if any */ + get_conftoken(CONF_ANY); - for(hp=holdingdisks; hp != NULL; hp = hpnext) { - amfree(hp->name); - for(i=0; ivalue[i]); - } - hpnext = hp->next; - amfree(hp); - } + switch(tok) { + case CONF_NL: /* multiply by one */ + case CONF_MULT1: + case CONF_MULT1K: + break; - for(dp=dumplist; dp != NULL; dp = dpnext) { - amfree(dp->name); - for(i=0; ivalue[i]); - } - dpnext = dp->next; - amfree(dp); - } + case CONF_MULT7: + if (val > (ssize_t)(SSIZE_MAX / 7)) + conf_parserror(_("value too large")); + if (val < (ssize_t)(SSIZE_MIN / 7)) + conf_parserror(_("value too small")); + val *= (ssize_t)7; + break; - for(tp=tapelist; tp != NULL; tp = tpnext) { - amfree(tp->name); - for(i=0; ivalue[i]); - } - tpnext = tp->next; - amfree(tp); - } + case CONF_MULT1M: + if (val > (ssize_t)(SSIZE_MAX / (ssize_t)1024)) + conf_parserror(_("value too large")); + if (val < (ssize_t)(SSIZE_MIN / (ssize_t)1024)) + conf_parserror(_("value too small")); + val *= (ssize_t)1024; + break; - for(ip=interface_list; ip != NULL; ip = ipnext) { - amfree(ip->name); - for(i=0; ivalue[i]); - } - ipnext = ip->next; - amfree(ip); - } + case CONF_MULT1G: + if (val > (ssize_t)(SSIZE_MAX / (1024 * 1024))) + conf_parserror(_("value too large")); + if (val < (ssize_t)(SSIZE_MIN / (1024 * 1024))) + conf_parserror(_("value too small")); + val *= (ssize_t)(1024 * 1024); + break; - if(program_options) { - for(server_option = program_options; server_option->name != NULL; - server_option++) { - amfree(server_option->name); - amfree(server_option->value); - } - amfree(program_options); + default: /* it was not a multiplier */ + unget_conftoken(); + break; } - for(i=0; i AM64_MAX/7 || val < AM64_MIN/7) + conf_parserror(_("value too large")); + val *= 7; + break; -static void -read_client_conffile_recursively( - char * filename) -{ - /* Save globals used in read_client_confline(), elsewhere. */ - int save_line_num = conf_line_num; - FILE *save_conf = conf_conf; - char *save_confname = conf_confname; - int rc; + case CONF_MULT1M: + if (val > AM64_MAX/1024 || val < AM64_MIN/1024) + conf_parserror(_("value too large")); + val *= 1024; + break; - if (*filename == '/' || cln_config_dir == NULL) { - conf_confname = stralloc(filename); - } else { - conf_confname = stralloc2(cln_config_dir, filename); - } + case CONF_MULT1G: + if (val > AM64_MAX/(1024*1024) || val < AM64_MIN/(1024*1024)) + conf_parserror(_("value too large")); + val *= 1024*1024; + break; - if((conf_conf = fopen(conf_confname, "r")) == NULL) { - dbprintf(("Could not open conf file \"%s\": %s\n", conf_confname, - strerror(errno))); - amfree(conf_confname); - got_parserror = -1; - return; + default: /* it was not a multiplier */ + unget_conftoken(); + break; } - dbprintf(("Reading conf file \"%s\".\n", conf_confname)); - - conf_line_num = 0; - /* read_client_confline() can invoke us recursively via "includefile" */ - do { - rc = read_client_confline(); - } while (rc != 0); - afclose(conf_conf); - - amfree(conf_confname); + keytable = save_kt; - /* Restore globals */ - conf_line_num = save_line_num; - conf_conf = save_conf; - conf_confname = save_confname; + return val; } - -/* ------------------------ */ - - static int -read_client_confline(void) +get_bool(void) { - t_conf_var *np; + int val; + keytab_t *save_kt; - keytable = client_keytab; + save_kt = keytable; + keytable = bool_keytable; - conf_line_num += 1; get_conftoken(CONF_ANY); + switch(tok) { - case CONF_INCLUDEFILE: - { - char *fn; + case CONF_INT: + if (tokenval.v.i != 0) + val = 1; + else + val = 0; + break; - get_conftoken(CONF_STRING); - fn = tokenval.v.s; - read_client_conffile_recursively(fn); - } + case CONF_SIZE: + if (tokenval.v.size != (size_t)0) + val = 1; + else + val = 0; break; - case CONF_NL: /* empty line */ + case CONF_AM64: + if (tokenval.v.am64 != (off_t)0) + val = 1; + else + val = 0; break; - case CONF_END: /* end of file */ - return 0; + case CONF_ATRUE: + val = 1; + break; - default: - { - for(np = client_var; np->token != CONF_UNKNOWN; np++) - if(np->token == tok) break; + case CONF_AFALSE: + val = 0; + break; - if(np->token == CONF_UNKNOWN) { - conf_parserror("configuration keyword expected"); - } else { - np->read_function(np, &conf_data[np->parm]); - if(np->validate) - np->validate(np, &conf_data[np->parm]); - } - } + case CONF_NL: + unget_conftoken(); + val = 2; /* no argument - most likely TRUE */ + break; + default: + unget_conftoken(); + val = 3; /* a bad argument - most likely TRUE */ + conf_parserror(_("YES, NO, TRUE, FALSE, ON, OFF expected")); + break; } - if(tok != CONF_NL) - get_conftoken(CONF_NL); - return 1; + + keytable = save_kt; + return val; } - -char * -generic_client_get_security_conf( - char * string, - void * arg) +void +ckseen( + int *seen) { - (void)arg; /* Quiet unused parameter warning */ - - if(!string || !*string) - return(NULL); - - if(strcmp(string, "conf")==0) { - return(getconf_str(CNF_CONF)); - } else if(strcmp(string, "index_server")==0) { - return(getconf_str(CNF_INDEX_SERVER)); - } else if(strcmp(string, "tape_server")==0) { - return(getconf_str(CNF_TAPE_SERVER)); - } else if(strcmp(string, "tapedev")==0) { - return(getconf_str(CNF_TAPEDEV)); - } else if(strcmp(string, "auth")==0) { - return(getconf_str(CNF_AUTH)); - } else if(strcmp(string, "ssh_keys")==0) { - return(getconf_str(CNF_SSH_KEYS)); - } else if(strcmp(string, "amandad_path")==0) { - return(getconf_str(CNF_AMANDAD_PATH)); - } else if(strcmp(string, "client_username")==0) { - return(getconf_str(CNF_CLIENT_USERNAME)); - } else if(strcmp(string, "gnutar_list_dir")==0) { - return(getconf_str(CNF_GNUTAR_LIST_DIR)); - } else if(strcmp(string, "amandates")==0) { - return(getconf_str(CNF_AMANDATES)); - } else if(strcmp(string, "krb5principal")==0) { - return(getconf_str(CNF_KRB5PRINCIPAL)); - } else if(strcmp(string, "krb5keytab")==0) { - return(getconf_str(CNF_KRB5KEYTAB)); - } - return(NULL); + if (*seen && !allow_overwrites && current_line_num != -2) { + conf_parserror(_("duplicate parameter, prev def on line %d"), *seen); + } + *seen = current_line_num; } +/* Validation functions */ -/* return 0 on success */ -/* return -1 if it is already there */ -/* return -2 if other failure */ -int -add_client_conf( - confparm_t parm, - char *value) +static void +validate_nonnegative( + struct conf_var_s *np, + val_t *val) { - t_conf_var *np; - keytab_t *kt; - command_option_t *command_option; - int nb_option; + switch(val->type) { + case CONFTYPE_INT: + if(val_t__int(val) < 0) + conf_parserror(_("%s must be nonnegative"), get_token_name(np->token)); + break; + case CONFTYPE_AM64: + if(val_t__am64(val) < 0) + conf_parserror(_("%s must be nonnegative"), get_token_name(np->token)); + break; + case CONFTYPE_SIZE: + if(val_t__size(val) < 0) + conf_parserror(_("%s must be positive"), get_token_name(np->token)); + break; + default: + conf_parserror(_("validate_nonnegative invalid type %d\n"), val->type); + } +} - for(np = client_var; np->token != CONF_UNKNOWN; np++) - if(np->parm == (int)parm) break; +static void +validate_positive( + struct conf_var_s *np, + val_t *val) +{ + switch(val->type) { + case CONFTYPE_INT: + if(val_t__int(val) < 1) + conf_parserror(_("%s must be positive"), get_token_name(np->token)); + break; + case CONFTYPE_AM64: + if(val_t__am64(val) < 1) + conf_parserror(_("%s must be positive"), get_token_name(np->token)); + break; + case CONFTYPE_TIME: + if(val_t__time(val) < 1) + conf_parserror(_("%s must be positive"), get_token_name(np->token)); + break; + case CONFTYPE_SIZE: + if(val_t__size(val) < 1) + conf_parserror(_("%s must be positive"), get_token_name(np->token)); + break; + default: + conf_parserror(_("validate_positive invalid type %d\n"), val->type); + } +} - if(np->token == CONF_UNKNOWN) return -2; +static void +validate_runspercycle( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + if(val_t__int(val) < -1) + conf_parserror(_("runspercycle must be >= -1")); +} - for(kt = client_keytab; kt->token != CONF_UNKNOWN; kt++) - if(kt->token == np->token) break; +static void +validate_bumppercent( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + if(val_t__int(val) < 0 || val_t__int(val) > 100) + conf_parserror(_("bumppercent must be between 0 and 100")); +} - if(kt->token == CONF_UNKNOWN) return -2; +static void +validate_inparallel( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + if(val_t__int(val) < 1 || val_t__int(val) >MAX_DUMPERS) + conf_parserror(_("inparallel must be between 1 and MAX_DUMPERS (%d)"), + MAX_DUMPERS); +} - /* Try to find it */ - nb_option = 0; - for(command_option = program_options; command_option->name != NULL; - command_option++) { - nb_option++; +static void +validate_bumpmult( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + if(val_t__real(val) < 0.999) { + conf_parserror(_("bumpmult must one or more")); } +} - /* Increase size of program_options if needed */ - if(nb_option >= program_options_size-1) { - program_options_size *= 2; - program_options = realloc(program_options, - program_options_size * SIZEOF(*program_options)); - if (program_options == NULL) { - error("Can't realloc program_options: %s\n", strerror(errno)); - /*NOTREACHED*/ - } - for(command_option = program_options; command_option->name != NULL; - command_option++) { +static void +validate_displayunit( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val G_GNUC_UNUSED) +{ + char *s = val_t__str(val); + if (strlen(s) == 1) { + switch (s[0]) { + case 'K': + case 'M': + case 'G': + case 'T': + return; /* all good */ + + /* lower-case values should get folded to upper case */ + case 'k': + case 'm': + case 'g': + case 't': + s[0] = toupper(s[0]); + return; + + default: /* bad */ + break; } } + conf_parserror(_("displayunit must be k,m,g or t.")); +} - /* add it */ - command_option->used = 0; - command_option->name = stralloc(kt->keyword); - command_option->value = stralloc(value); - command_option++; - command_option->name = NULL; - return 0; +static void +validate_reserve( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + if(val_t__int(val) < 0 || val_t__int(val) > 100) + conf_parserror(_("reserve must be between 0 and 100")); } -/* -static t_conf_var * -get_np( - t_conf_var *get_var, - int parm) +static void +validate_use( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) { - t_conf_var *np; + val_t__am64(val) = am_floor(val_t__am64(val), DISK_BLOCK_KB); +} - for(np = get_var; np->token != CONF_UNKNOWN; np++) { - if(np->parm == parm) - break; +static void +validate_chunksize( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + /* NOTE: this function modifies the target value (rounding) */ + if(val_t__am64(val) == 0) { + val_t__am64(val) = ((AM64_MAX / 1024) - (2 * DISK_BLOCK_KB)); } - - if(np->token == CONF_UNKNOWN) { - error("error [unknown get_np parm: %d]", parm); - NOTREACHED + else if(val_t__am64(val) < 0) { + conf_parserror(_("Negative chunksize (%lld) is no longer supported"), (long long)val_t__am64(val)); + } + val_t__am64(val) = am_floor(val_t__am64(val), (off_t)DISK_BLOCK_KB); + if (val_t__am64(val) < 2*DISK_BLOCK_KB) { + conf_parserror("chunksize must be at least %dkb", 2*DISK_BLOCK_KB); } - return np; } -*/ -static time_t -get_time(void) +static void +validate_blocksize( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) { - time_t hhmm; - - get_conftoken(CONF_ANY); - switch(tok) { - case CONF_INT: -#if SIZEOF_TIME_T < SIZEOF_INT - if ((off_t)tokenval.v.i >= (off_t)TIME_MAX) - conf_parserror("value too large"); -#endif - hhmm = (time_t)tokenval.v.i; - break; + if(val_t__size(val) < DISK_BLOCK_KB) { + conf_parserror(_("Tape blocksize must be at least %d KBytes"), + DISK_BLOCK_KB); + } else if(val_t__size(val) > MAX_TAPE_BLOCK_KB) { + conf_parserror(_("Tape blocksize must not be larger than %d KBytes"), + MAX_TAPE_BLOCK_KB); + } +} - case CONF_LONG: -#if SIZEOF_TIME_T < SIZEOF_LONG - if ((off_t)tokenval.v.l >= (off_t)TIME_MAX) - conf_parserror("value too large"); -#endif - hhmm = (time_t)tokenval.v.l; - break; +static void +validate_debug( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + if(val_t__int(val) < 0 || val_t__int(val) > 9) { + conf_parserror(_("Debug must be between 0 and 9")); + } +} - case CONF_SIZE: -#if SIZEOF_TIME_T < SIZEOF_SSIZE_T - if ((off_t)tokenval.v.size >= (off_t)TIME_MAX) - conf_parserror("value too large"); -#endif - hhmm = (time_t)tokenval.v.size; - break; +static void +validate_port_range( + val_t *val, + int smallest, + int largest) +{ + int i; + /* check both values are in range */ + for (i = 0; i < 2; i++) { + if(val_t__intrange(val)[0] < smallest || val_t__intrange(val)[0] > largest) { + conf_parserror(_("portrange must be in the range %d to %d, inclusive"), smallest, largest); + } + } - case CONF_AM64: -#if SIZEOF_TIME_T < SIZEOF_LONG_LONG - if ((off_t)tokenval.v.am64 >= (off_t)TIME_MAX) - conf_parserror("value too large"); -#endif - hhmm = (time_t)tokenval.v.am64; - break; + /* and check they're in the right order and not equal */ + if (val_t__intrange(val)[0] > val_t__intrange(val)[1]) { + conf_parserror(_("portranges must be in order from low to high")); + } +} - case CONF_AMINFINITY: - hhmm = TIME_MAX; - break; +static void +validate_reserved_port_range( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + validate_port_range(val, 1, IPPORT_RESERVED-1); +} - default: - conf_parserror("a time is expected"); - hhmm = 0; - break; - } - return hhmm; +static void +validate_unreserved_port_range( + struct conf_var_s *np G_GNUC_UNUSED, + val_t *val) +{ + validate_port_range(val, IPPORT_RESERVED, 65535); } -keytab_t numb_keytable[] = { - { "B", CONF_MULT1 }, - { "BPS", CONF_MULT1 }, - { "BYTE", CONF_MULT1 }, - { "BYTES", CONF_MULT1 }, - { "DAY", CONF_MULT1 }, - { "DAYS", CONF_MULT1 }, - { "INF", CONF_AMINFINITY }, - { "K", CONF_MULT1K }, - { "KB", CONF_MULT1K }, - { "KBPS", CONF_MULT1K }, - { "KBYTE", CONF_MULT1K }, - { "KBYTES", CONF_MULT1K }, - { "KILOBYTE", CONF_MULT1K }, - { "KILOBYTES", CONF_MULT1K }, - { "KPS", CONF_MULT1K }, - { "M", CONF_MULT1M }, - { "MB", CONF_MULT1M }, - { "MBPS", CONF_MULT1M }, - { "MBYTE", CONF_MULT1M }, - { "MBYTES", CONF_MULT1M }, - { "MEG", CONF_MULT1M }, - { "MEGABYTE", CONF_MULT1M }, - { "MEGABYTES", CONF_MULT1M }, - { "G", CONF_MULT1G }, - { "GB", CONF_MULT1G }, - { "GBPS", CONF_MULT1G }, - { "GBYTE", CONF_MULT1G }, - { "GBYTES", CONF_MULT1G }, - { "GIG", CONF_MULT1G }, - { "GIGABYTE", CONF_MULT1G }, - { "GIGABYTES", CONF_MULT1G }, - { "MPS", CONF_MULT1M }, - { "TAPE", CONF_MULT1 }, - { "TAPES", CONF_MULT1 }, - { "WEEK", CONF_MULT7 }, - { "WEEKS", CONF_MULT7 }, - { NULL, CONF_IDENT } -}; +/* + * Initialization Implementation + */ -static int -get_int(void) +gboolean +config_init( + config_init_flags flags, + char *arg_config_name) { - int val; - keytab_t *save_kt; + if (!(flags & CONFIG_INIT_OVERLAY)) { + /* Clear out anything that's already in there */ + config_uninit(); - save_kt = keytable; - keytable = numb_keytable; + /* and set everything to default values */ + init_defaults(); - get_conftoken(CONF_ANY); - switch(tok) { - case CONF_INT: - val = tokenval.v.i; - break; + allow_overwrites = FALSE; + } else { + if (!config_initialized) { + error(_("Attempt to overlay configuration with no existing configuration")); + /* NOTREACHED */ + } - case CONF_LONG: -#if SIZEOF_INT < SIZEOF_LONG - if ((off_t)tokenval.v.l > (off_t)INT_MAX) - conf_parserror("value too large"); - if ((off_t)tokenval.v.l < (off_t)INT_MIN) - conf_parserror("value too small"); -#endif - val = (int)tokenval.v.l; - break; + allow_overwrites = TRUE; + } - case CONF_SIZE: -#if SIZEOF_INT < SIZEOF_SSIZE_T - if ((off_t)tokenval.v.size > (off_t)INT_MAX) - conf_parserror("value too large"); - if ((off_t)tokenval.v.size < (off_t)INT_MIN) - conf_parserror("value too small"); -#endif - val = (int)tokenval.v.size; - break; + /* store away our client-ness for later reference */ + config_client = flags & CONFIG_INIT_CLIENT; - case CONF_AM64: -#if SIZEOF_INT < SIZEOF_LONG_LONG - if (tokenval.v.am64 > (off_t)INT_MAX) - conf_parserror("value too large"); - if (tokenval.v.am64 < (off_t)INT_MIN) - conf_parserror("value too small"); -#endif - val = (int)tokenval.v.am64; - break; + if ((flags & CONFIG_INIT_EXPLICIT_NAME) && arg_config_name) { + config_name = newstralloc(config_name, arg_config_name); + config_dir = newvstralloc(config_dir, CONFIG_DIR, "/", arg_config_name, NULL); + } else if (flags & CONFIG_INIT_USE_CWD) { + char * cwd; + + cwd = get_original_cwd(); + if (!cwd) { + /* (this isn't a config error, so it's always fatal) */ + error(_("Cannot determine current working directory")); + /* NOTREACHED */ + } - case CONF_AMINFINITY: - val = INT_MAX; - break; + config_dir = stralloc2(cwd, "/"); + if ((config_name = strrchr(cwd, '/')) != NULL) { + config_name = stralloc(config_name + 1); + } - default: - conf_parserror("an integer is expected"); - val = 0; - break; + amfree(cwd); + } else if (flags & CONFIG_INIT_CLIENT) { + amfree(config_name); + config_dir = newstralloc(config_dir, CONFIG_DIR); + } else { + /* ok, then, we won't read anything (for e.g., amrestore) */ + amfree(config_name); + amfree(config_dir); } - /* get multiplier, if any */ - get_conftoken(CONF_ANY); - switch(tok) { - case CONF_NL: /* multiply by one */ - case CONF_END: - case CONF_MULT1: - case CONF_MULT1K: - break; + /* If we have a config_dir, we can try reading something */ + if (config_dir) { + if (flags & CONFIG_INIT_CLIENT) { + config_filename = newvstralloc(config_filename, config_dir, "/amanda-client.conf", NULL); + } else { + config_filename = newvstralloc(config_filename, config_dir, "/amanda.conf", NULL); + } - case CONF_MULT7: - if (val > (INT_MAX / 7)) - conf_parserror("value too large"); - if (val < (INT_MIN / 7)) - conf_parserror("value too small"); - val *= 7; - break; + /* try to read the file, and handle parse errors */ + if (!read_conffile(config_filename, flags & CONFIG_INIT_CLIENT)) { + if (flags & CONFIG_INIT_FATAL) { + error(_("errors processing config file \"%s\""), config_filename); + /* NOTREACHED */ + } else { + g_warning(_("errors processing config file \"%s\" (non-fatal)"), config_filename); + return FALSE; + } + } + } else { + amfree(config_filename); + } - case CONF_MULT1M: - if (val > (INT_MAX / 1024)) - conf_parserror("value too large"); - if (val < (INT_MIN / 1024)) - conf_parserror("value too small"); - val *= 1024; - break; + update_derived_values(flags & CONFIG_INIT_CLIENT); - case CONF_MULT1G: - if (val > (INT_MAX / (1024 * 1024))) - conf_parserror("value too large"); - if (val < (INT_MIN / (1024 * 1024))) - conf_parserror("value too small"); - val *= 1024 * 1024; - break; + return TRUE; +} - default: /* it was not a multiplier */ - unget_conftoken(); - break; +void +config_uninit(void) +{ + holdingdisk_t *hp, *hpnext; + dumptype_t *dp, *dpnext; + tapetype_t *tp, *tpnext; + interface_t *ip, *ipnext; + int i; + + if (!config_initialized) return; + + for(hp=holdinglist; hp != NULL; hp = hpnext) { + amfree(hp->name); + for(i=0; ivalue[i]); + } + hpnext = hp->next; + amfree(hp); } + holdinglist = NULL; - keytable = save_kt; - return val; -} + for(dp=dumplist; dp != NULL; dp = dpnext) { + amfree(dp->name); + for(i=0; ivalue[i]); + } + dpnext = dp->next; + amfree(dp); + } + dumplist = NULL; -/* -static long -get_long(void) -{ - long val; - keytab_t *save_kt; + for(tp=tapelist; tp != NULL; tp = tpnext) { + amfree(tp->name); + for(i=0; ivalue[i]); + } + tpnext = tp->next; + amfree(tp); + } + tapelist = NULL; - save_kt = keytable; - keytable = numb_keytable; + for(ip=interface_list; ip != NULL; ip = ipnext) { + amfree(ip->name); + for(i=0; ivalue[i]); + } + ipnext = ip->next; + amfree(ip); + } + interface_list = NULL; - get_conftoken(CONF_ANY); + for(i=0; i (off_t)LONG_MAX) - conf_parserror("value too large"); - if ((off_t)tokenval.v.i < (off_t)LONG_MIN) - conf_parserror("value too small"); -#endif - val = (long)tokenval.v.i; - break; + amfree(config_name); + amfree(config_dir); - case CONF_SIZE: -#if SIZEOF_LONG < SIZEOF_SSIZE_T - if ((off_t)tokenval.v.size > (off_t)LONG_MAX) - conf_parserror("value too large"); - if ((off_t)tokenval.v.size < (off_t)LONG_MIN) - conf_parserror("value too small"); -#endif - val = (long)tokenval.v.size; - break; + config_client = FALSE; - case CONF_AM64: -#if SIZEOF_LONG < SIZEOF_LONG_LONG - if (tokenval.v.am64 > (off_t)LONG_MAX) - conf_parserror("value too large"); - if (tokenval.v.am64 < (off_t)LONG_MIN) - conf_parserror("value too small"); + config_initialized = FALSE; +} + +static void +init_defaults( + void) +{ + assert(!config_initialized); + + /* defaults for exported variables */ + conf_init_str(&conf_data[CNF_ORG], DEFAULT_CONFIG); + conf_init_str(&conf_data[CNF_CONF], DEFAULT_CONFIG); + conf_init_str(&conf_data[CNF_INDEX_SERVER], DEFAULT_SERVER); + conf_init_str(&conf_data[CNF_TAPE_SERVER], DEFAULT_TAPE_SERVER); + conf_init_str(&conf_data[CNF_AUTH], "bsd"); + conf_init_str(&conf_data[CNF_SSH_KEYS], ""); + conf_init_str(&conf_data[CNF_AMANDAD_PATH], ""); + conf_init_str(&conf_data[CNF_CLIENT_USERNAME], ""); + conf_init_str(&conf_data[CNF_GNUTAR_LIST_DIR], GNUTAR_LISTED_INCREMENTAL_DIR); + conf_init_str(&conf_data[CNF_AMANDATES], DEFAULT_AMANDATES_FILE); + conf_init_str(&conf_data[CNF_MAILTO], "operators"); + conf_init_str(&conf_data[CNF_DUMPUSER], CLIENT_LOGIN); + conf_init_str(&conf_data[CNF_TAPEDEV], DEFAULT_TAPE_DEVICE); + conf_init_proplist(&conf_data[CNF_DEVICE_PROPERTY]); + conf_init_str(&conf_data[CNF_CHANGERDEV], DEFAULT_CHANGER_DEVICE); + conf_init_str(&conf_data[CNF_CHANGERFILE], "/usr/adm/amanda/changer-status"); + conf_init_str (&conf_data[CNF_LABELSTR] , ".*"); + conf_init_str (&conf_data[CNF_TAPELIST] , "tapelist"); + conf_init_str (&conf_data[CNF_DISKFILE] , "disklist"); + conf_init_str (&conf_data[CNF_INFOFILE] , "/usr/adm/amanda/curinfo"); + conf_init_str (&conf_data[CNF_LOGDIR] , "/usr/adm/amanda"); + conf_init_str (&conf_data[CNF_INDEXDIR] , "/usr/adm/amanda/index"); + conf_init_ident (&conf_data[CNF_TAPETYPE] , "EXABYTE"); + conf_init_int (&conf_data[CNF_DUMPCYCLE] , 10); + conf_init_int (&conf_data[CNF_RUNSPERCYCLE] , 0); + conf_init_int (&conf_data[CNF_TAPECYCLE] , 15); + conf_init_int (&conf_data[CNF_NETUSAGE] , 8000); + conf_init_int (&conf_data[CNF_INPARALLEL] , 10); + conf_init_str (&conf_data[CNF_DUMPORDER] , "ttt"); + conf_init_int (&conf_data[CNF_BUMPPERCENT] , 0); + conf_init_am64 (&conf_data[CNF_BUMPSIZE] , (off_t)10*1024); + conf_init_real (&conf_data[CNF_BUMPMULT] , 1.5); + conf_init_int (&conf_data[CNF_BUMPDAYS] , 2); + conf_init_str (&conf_data[CNF_TPCHANGER] , ""); + conf_init_int (&conf_data[CNF_RUNTAPES] , 1); + conf_init_int (&conf_data[CNF_MAXDUMPS] , 1); + conf_init_int (&conf_data[CNF_ETIMEOUT] , 300); + conf_init_int (&conf_data[CNF_DTIMEOUT] , 1800); + conf_init_int (&conf_data[CNF_CTIMEOUT] , 30); + conf_init_int (&conf_data[CNF_TAPEBUFS] , 20); + conf_init_size (&conf_data[CNF_DEVICE_OUTPUT_BUFFER_SIZE], 40*32768); + conf_init_str (&conf_data[CNF_PRINTER] , ""); + conf_init_bool (&conf_data[CNF_AUTOFLUSH] , 0); + conf_init_int (&conf_data[CNF_RESERVE] , 100); + conf_init_am64 (&conf_data[CNF_MAXDUMPSIZE] , (off_t)-1); + conf_init_str (&conf_data[CNF_COLUMNSPEC] , ""); + conf_init_bool (&conf_data[CNF_AMRECOVER_DO_FSF] , 1); + conf_init_str (&conf_data[CNF_AMRECOVER_CHANGER] , ""); + conf_init_bool (&conf_data[CNF_AMRECOVER_CHECK_LABEL], 1); + conf_init_taperalgo(&conf_data[CNF_TAPERALGO] , 0); + conf_init_int (&conf_data[CNF_FLUSH_THRESHOLD_DUMPED] , 0); + conf_init_int (&conf_data[CNF_FLUSH_THRESHOLD_SCHEDULED], 0); + conf_init_int (&conf_data[CNF_TAPERFLUSH] , 0); + conf_init_str (&conf_data[CNF_DISPLAYUNIT] , "k"); + conf_init_str (&conf_data[CNF_KRB5KEYTAB] , "/.amanda-v5-keytab"); + conf_init_str (&conf_data[CNF_KRB5PRINCIPAL] , "service/amanda"); + conf_init_str (&conf_data[CNF_LABEL_NEW_TAPES] , ""); + conf_init_bool (&conf_data[CNF_USETIMESTAMPS] , 1); + conf_init_int (&conf_data[CNF_CONNECT_TRIES] , 3); + conf_init_int (&conf_data[CNF_REP_TRIES] , 5); + conf_init_int (&conf_data[CNF_REQ_TRIES] , 3); + conf_init_int (&conf_data[CNF_DEBUG_AMANDAD] , 0); + conf_init_int (&conf_data[CNF_DEBUG_AMIDXTAPED] , 0); + conf_init_int (&conf_data[CNF_DEBUG_AMINDEXD] , 0); + conf_init_int (&conf_data[CNF_DEBUG_AMRECOVER] , 0); + conf_init_int (&conf_data[CNF_DEBUG_AUTH] , 0); + conf_init_int (&conf_data[CNF_DEBUG_EVENT] , 0); + conf_init_int (&conf_data[CNF_DEBUG_HOLDING] , 0); + conf_init_int (&conf_data[CNF_DEBUG_PROTOCOL] , 0); + conf_init_int (&conf_data[CNF_DEBUG_PLANNER] , 0); + conf_init_int (&conf_data[CNF_DEBUG_DRIVER] , 0); + conf_init_int (&conf_data[CNF_DEBUG_DUMPER] , 0); + conf_init_int (&conf_data[CNF_DEBUG_CHUNKER] , 0); + conf_init_int (&conf_data[CNF_DEBUG_TAPER] , 0); + conf_init_int (&conf_data[CNF_DEBUG_SELFCHECK] , 0); + conf_init_int (&conf_data[CNF_DEBUG_SENDSIZE] , 0); + conf_init_int (&conf_data[CNF_DEBUG_SENDBACKUP] , 0); +#ifdef UDPPORTRANGE + conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT] , UDPPORTRANGE); +#else + conf_init_intrange (&conf_data[CNF_RESERVED_UDP_PORT] , 512, IPPORT_RESERVED-1); +#endif +#ifdef LOW_TCPPORTRANGE + conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT] , LOW_TCPPORTRANGE); +#else + conf_init_intrange (&conf_data[CNF_RESERVED_TCP_PORT] , 512, IPPORT_RESERVED-1); +#endif +#ifdef TCPPORTRANGE + conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT] , TCPPORTRANGE); +#else + conf_init_intrange (&conf_data[CNF_UNRESERVED_TCP_PORT] , IPPORT_RESERVED, 65535); #endif - val = (long)tokenval.v.am64; - break; - case CONF_AMINFINITY: - val = (long)LONG_MAX; - break; + /* reset internal variables */ + got_parserror = FALSE; + allow_overwrites = 0; + token_pushed = 0; - default: - conf_parserror("an integer is expected"); - val = 0; - break; - } + /* create some predefined dumptypes for backwards compatability */ + init_dumptype_defaults(); + dpcur.name = stralloc("NO-COMPRESS"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]); + val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_NONE; + val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]) = -1; + save_dumptype(); - get_conftoken(CONF_ANY); + init_dumptype_defaults(); + dpcur.name = stralloc("COMPRESS-FAST"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]); + val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_FAST; + val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]) = -1; + save_dumptype(); - switch(tok) { - case CONF_NL: - case CONF_MULT1: - case CONF_MULT1K: - break; + init_dumptype_defaults(); + dpcur.name = stralloc("COMPRESS-BEST"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]); + val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_BEST; + val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]) = -1; + save_dumptype(); - case CONF_MULT7: - if (val > (LONG_MAX / 7L)) - conf_parserror("value too large"); - if (val < (LONG_MIN / 7L)) - conf_parserror("value too small"); - val *= 7L; - break; + init_dumptype_defaults(); + dpcur.name = stralloc("COMPRESS-CUST"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]); + val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_CUST; + val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]) = -1; + save_dumptype(); - case CONF_MULT1M: - if (val > (LONG_MAX / 1024L)) - conf_parserror("value too large"); - if (val < (LONG_MIN / 1024L)) - conf_parserror("value too small"); - val *= 1024L; - break; + init_dumptype_defaults(); + dpcur.name = stralloc("SRVCOMPRESS"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_COMPRESS]); + val_t__compress(&dpcur.value[DUMPTYPE_COMPRESS]) = COMP_SERVER_FAST; + val_t__seen(&dpcur.value[DUMPTYPE_COMPRESS]) = -1; + save_dumptype(); - case CONF_MULT1G: - if (val > (LONG_MAX / (1024L * 1024L))) - conf_parserror("value too large"); - if (val < (LONG_MIN / (1024L * 1024L))) - conf_parserror("value too small"); - val *= 1024L * 1024L; - break; + init_dumptype_defaults(); + dpcur.name = stralloc("BSD-AUTH"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_SECURITY_DRIVER]); + val_t__str(&dpcur.value[DUMPTYPE_SECURITY_DRIVER]) = stralloc("BSD"); + val_t__seen(&dpcur.value[DUMPTYPE_SECURITY_DRIVER]) = -1; + save_dumptype(); - default: - unget_conftoken(); - break; - } + init_dumptype_defaults(); + dpcur.name = stralloc("KRB4-AUTH"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_SECURITY_DRIVER]); + val_t__str(&dpcur.value[DUMPTYPE_SECURITY_DRIVER]) = stralloc("KRB4"); + val_t__seen(&dpcur.value[DUMPTYPE_SECURITY_DRIVER]) = -1; + save_dumptype(); - keytable = save_kt; - return val; + init_dumptype_defaults(); + dpcur.name = stralloc("NO-RECORD"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_RECORD]); + val_t__int(&dpcur.value[DUMPTYPE_RECORD]) = 0; + val_t__seen(&dpcur.value[DUMPTYPE_RECORD]) = -1; + save_dumptype(); + + init_dumptype_defaults(); + dpcur.name = stralloc("NO-HOLD"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_HOLDINGDISK]); + val_t__holding(&dpcur.value[DUMPTYPE_HOLDINGDISK]) = HOLD_NEVER; + val_t__seen(&dpcur.value[DUMPTYPE_HOLDINGDISK]) = -1; + save_dumptype(); + + init_dumptype_defaults(); + dpcur.name = stralloc("NO-FULL"); + dpcur.seen = -1; + free_val_t(&dpcur.value[DUMPTYPE_STRATEGY]); + val_t__strategy(&dpcur.value[DUMPTYPE_STRATEGY]) = DS_NOFULL; + val_t__seen(&dpcur.value[DUMPTYPE_STRATEGY]) = -1; + save_dumptype(); + + /* And we're initialized! */ + config_initialized = 1; } -*/ -static ssize_t -get_size(void) +char ** +get_config_options( + int first) { - ssize_t val; - keytab_t *save_kt; + char **config_options; + char **config_option; + int n_applied_config_overwrites = 0; + int i; - save_kt = keytable; - keytable = numb_keytable; + if (applied_config_overwrites) + n_applied_config_overwrites = applied_config_overwrites->n_used; - get_conftoken(CONF_ANY); + config_options = alloc((first+n_applied_config_overwrites+1)*SIZEOF(char *)); + config_option = config_options + first; - switch(tok) { - case CONF_SIZE: - val = tokenval.v.size; - break; + for (i = 0; i < n_applied_config_overwrites; i++) { + char *key = applied_config_overwrites->ovr[i].key; + char *value = applied_config_overwrites->ovr[i].value; + *config_option = vstralloc("-o", key, "=", value, NULL); + config_option++; + } - case CONF_INT: -#if SIZEOF_SIZE_T < SIZEOF_INT - if ((off_t)tokenval.v.i > (off_t)SSIZE_MAX) - conf_parserror("value too large"); - if ((off_t)tokenval.v.i < (off_t)SSIZE_MIN) - conf_parserror("value too small"); -#endif - val = (ssize_t)tokenval.v.i; - break; + *config_option = NULL; /* add terminating sentinel */ - case CONF_LONG: -#if SIZEOF_SIZE_T < SIZEOF_LONG - if ((off_t)tokenval.v.l > (off_t)SSIZE_MAX) - conf_parserror("value too large"); - if ((off_t)tokenval.v.l < (off_t)SSIZE_MIN) - conf_parserror("value too small"); -#endif - val = (ssize_t)tokenval.v.l; - break; + return config_options; +} - case CONF_AM64: -#if SIZEOF_SIZE_T < SIZEOF_LONG_LONG - if (tokenval.v.am64 > (off_t)SSIZE_MAX) - conf_parserror("value too large"); - if (tokenval.v.am64 < (off_t)SSIZE_MIN) - conf_parserror("value too small"); -#endif - val = (ssize_t)tokenval.v.am64; - break; +static void +update_derived_values( + gboolean is_client) +{ + interface_t *ip; - case CONF_AMINFINITY: - val = (ssize_t)SSIZE_MAX; - break; + if (!is_client) { + /* Add a 'default' interface if one doesn't already exist */ + if (!(ip = lookup_interface("default"))) { + init_interface_defaults(); + ifcur.name = stralloc("default"); + ifcur.seen = getconf_seen(CNF_NETUSAGE); + save_interface(); - default: - conf_parserror("an integer is expected"); - val = 0; - break; + ip = lookup_interface("default"); + } + + /* .. and set its maxusage from 'netusage' */ + if (!interface_seen(ip, INTER_MAXUSAGE)) { + val_t *v; + + v = interface_getconf(ip, INTER_COMMENT); + free_val_t(v); + val_t__str(v) = stralloc(_("implicit from NETUSAGE")); + val_t__seen(v) = getconf_seen(CNF_NETUSAGE); + + v = interface_getconf(ip, INTER_MAXUSAGE); + free_val_t(v); + val_t__int(v) = getconf_int(CNF_NETUSAGE); + val_t__seen(v) = getconf_seen(CNF_NETUSAGE); + } } - /* get multiplier, if any */ - get_conftoken(CONF_ANY); + /* fill in the debug_* values */ + debug_amandad = getconf_int(CNF_DEBUG_AMANDAD); + debug_amidxtaped = getconf_int(CNF_DEBUG_AMIDXTAPED); + debug_amindexd = getconf_int(CNF_DEBUG_AMINDEXD); + debug_amrecover = getconf_int(CNF_DEBUG_AMRECOVER); + debug_auth = getconf_int(CNF_DEBUG_AUTH); + debug_event = getconf_int(CNF_DEBUG_EVENT); + debug_holding = getconf_int(CNF_DEBUG_HOLDING); + debug_protocol = getconf_int(CNF_DEBUG_PROTOCOL); + debug_planner = getconf_int(CNF_DEBUG_PLANNER); + debug_driver = getconf_int(CNF_DEBUG_DRIVER); + debug_dumper = getconf_int(CNF_DEBUG_DUMPER); + debug_chunker = getconf_int(CNF_DEBUG_CHUNKER); + debug_taper = getconf_int(CNF_DEBUG_TAPER); + debug_selfcheck = getconf_int(CNF_DEBUG_SELFCHECK); + debug_sendsize = getconf_int(CNF_DEBUG_SENDSIZE); + debug_sendbackup = getconf_int(CNF_DEBUG_SENDBACKUP); - switch(tok) { - case CONF_NL: /* multiply by one */ - case CONF_MULT1: - case CONF_MULT1K: - break; + /* And finally, display unit */ + switch (getconf_str(CNF_DISPLAYUNIT)[0]) { + case 'k': + case 'K': + unit_divisor = 1; + break; - case CONF_MULT7: - if (val > (ssize_t)(SSIZE_MAX / 7)) - conf_parserror("value too large"); - if (val < (ssize_t)(SSIZE_MIN / 7)) - conf_parserror("value too small"); - val *= (ssize_t)7; - break; + case 'm': + case 'M': + unit_divisor = 1024; + break; - case CONF_MULT1M: - if (val > (ssize_t)(SSIZE_MAX / (ssize_t)1024)) - conf_parserror("value too large"); - if (val < (ssize_t)(SSIZE_MIN / (ssize_t)1024)) - conf_parserror("value too small"); - val *= (ssize_t)1024; - break; + case 'g': + case 'G': + unit_divisor = 1024*1024; + break; - case CONF_MULT1G: - if (val > (ssize_t)(SSIZE_MAX / (1024 * 1024))) - conf_parserror("value too large"); - if (val < (ssize_t)(SSIZE_MIN / (1024 * 1024))) - conf_parserror("value too small"); - val *= (ssize_t)(1024 * 1024); - break; + case 't': + case 'T': + unit_divisor = 1024*1024*1024; + break; - default: /* it was not a multiplier */ - unget_conftoken(); - break; + default: + error(_("Invalid displayunit missed by validate_displayunit")); + /* NOTREACHED */ } - - keytable = save_kt; - return val; } -static off_t -get_am64_t(void) +static void +conf_init_int( + val_t *val, + int i) { - off_t val; - keytab_t *save_kt; + val->seen = 0; + val->type = CONFTYPE_INT; + val_t__int(val) = i; +} - save_kt = keytable; - keytable = numb_keytable; +static void +conf_init_am64( + val_t *val, + off_t l) +{ + val->seen = 0; + val->type = CONFTYPE_AM64; + val_t__am64(val) = l; +} - get_conftoken(CONF_ANY); +static void +conf_init_real( + val_t *val, + float r) +{ + val->seen = 0; + val->type = CONFTYPE_REAL; + val_t__real(val) = r; +} - switch(tok) { - case CONF_INT: - val = (off_t)tokenval.v.i; - break; +static void +conf_init_str( + val_t *val, + char *s) +{ + val->seen = 0; + val->type = CONFTYPE_STR; + if(s) + val->v.s = stralloc(s); + else + val->v.s = NULL; +} - case CONF_LONG: - val = (off_t)tokenval.v.l; - break; +static void +conf_init_ident( + val_t *val, + char *s) +{ + val->seen = 0; + val->type = CONFTYPE_IDENT; + if(s) + val->v.s = stralloc(s); + else + val->v.s = NULL; +} - case CONF_SIZE: - val = (off_t)tokenval.v.size; - break; +static void +conf_init_time( + val_t *val, + time_t t) +{ + val->seen = 0; + val->type = CONFTYPE_TIME; + val_t__time(val) = t; +} - case CONF_AM64: - val = tokenval.v.am64; - break; +static void +conf_init_size( + val_t *val, + ssize_t sz) +{ + val->seen = 0; + val->type = CONFTYPE_SIZE; + val_t__size(val) = sz; +} - case CONF_AMINFINITY: - val = AM64_MAX; - break; +static void +conf_init_bool( + val_t *val, + int i) +{ + val->seen = 0; + val->type = CONFTYPE_BOOLEAN; + val_t__boolean(val) = i; +} - default: - conf_parserror("an integer is expected"); - val = 0; - break; - } +static void +conf_init_compress( + val_t *val, + comp_t i) +{ + val->seen = 0; + val->type = CONFTYPE_COMPRESS; + val_t__compress(val) = (int)i; +} - /* get multiplier, if any */ - get_conftoken(CONF_ANY); +static void +conf_init_encrypt( + val_t *val, + encrypt_t i) +{ + val->seen = 0; + val->type = CONFTYPE_ENCRYPT; + val_t__encrypt(val) = (int)i; +} - switch(tok) { - case CONF_NL: /* multiply by one */ - case CONF_MULT1: - case CONF_MULT1K: - break; +static void +conf_init_holding( + val_t *val, + dump_holdingdisk_t i) +{ + val->seen = 0; + val->type = CONFTYPE_HOLDING; + val_t__holding(val) = (int)i; +} - case CONF_MULT7: - if (val > AM64_MAX/7 || val < AM64_MIN/7) - conf_parserror("value too large"); - val *= 7; - break; +static void +conf_init_estimate( + val_t *val, + estimate_t i) +{ + val->seen = 0; + val->type = CONFTYPE_ESTIMATE; + val_t__estimate(val) = i; +} - case CONF_MULT1M: - if (val > AM64_MAX/1024 || val < AM64_MIN/1024) - conf_parserror("value too large"); - val *= 1024; - break; +static void +conf_init_strategy( + val_t *val, + strategy_t i) +{ + val->seen = 0; + val->type = CONFTYPE_STRATEGY; + val_t__strategy(val) = i; +} - case CONF_MULT1G: - if (val > AM64_MAX/(1024*1024) || val < AM64_MIN/(1024*1024)) - conf_parserror("value too large"); - val *= 1024*1024; - break; +static void +conf_init_taperalgo( + val_t *val, + taperalgo_t i) +{ + val->seen = 0; + val->type = CONFTYPE_TAPERALGO; + val_t__taperalgo(val) = i; +} - default: /* it was not a multiplier */ - unget_conftoken(); - break; - } +static void +conf_init_priority( + val_t *val, + int i) +{ + val->seen = 0; + val->type = CONFTYPE_PRIORITY; + val_t__priority(val) = i; +} - keytable = save_kt; +static void +conf_init_rate( + val_t *val, + float r1, + float r2) +{ + val->seen = 0; + val->type = CONFTYPE_RATE; + val_t__rate(val)[0] = r1; + val_t__rate(val)[1] = r2; +} - return val; +static void +conf_init_exinclude( + val_t *val) +{ + val->seen = 0; + val->type = CONFTYPE_EXINCLUDE; + val_t__exinclude(val).optional = 0; + val_t__exinclude(val).sl_list = NULL; + val_t__exinclude(val).sl_file = NULL; } -keytab_t bool_keytable[] = { - { "Y", CONF_ATRUE }, - { "YES", CONF_ATRUE }, - { "T", CONF_ATRUE }, - { "TRUE", CONF_ATRUE }, - { "ON", CONF_ATRUE }, - { "N", CONF_AFALSE }, - { "NO", CONF_AFALSE }, - { "F", CONF_AFALSE }, - { "FALSE", CONF_AFALSE }, - { "OFF", CONF_AFALSE }, - { NULL, CONF_IDENT } -}; +static void +conf_init_intrange( + val_t *val, + int i1, + int i2) +{ + val->seen = 0; + val->type = CONFTYPE_INTRANGE; + val_t__intrange(val)[0] = i1; + val_t__intrange(val)[1] = i2; +} -static int -get_bool(void) +static void +conf_init_proplist( + val_t *val) { - int val; - keytab_t *save_kt; + val->seen = 0; + val->type = CONFTYPE_PROPLIST; + val_t__proplist(val) = + g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); +} - save_kt = keytable; - keytable = bool_keytable; +/* + * Config access implementation + */ - get_conftoken(CONF_ANY); +val_t * +getconf(confparm_key key) +{ + assert(key < CNF_CNF); + return &conf_data[key]; +} - switch(tok) { - case CONF_INT: - if (tokenval.v.i != 0) - val = 1; - else - val = 0; - break; +GSList * +getconf_list( + char *listname) +{ + tapetype_t *tp; + dumptype_t *dp; + interface_t *ip; + holdingdisk_t *hp; + GSList *rv = NULL; - case CONF_LONG: - if (tokenval.v.l != 0L) - val = 1; - else - val = 0; - break; + if (strcasecmp(listname,"tapetype") == 0) { + for(tp = tapelist; tp != NULL; tp=tp->next) { + rv = g_slist_append(rv, tp->name); + } + } else if (strcasecmp(listname,"dumptype") == 0) { + for(dp = dumplist; dp != NULL; dp=dp->next) { + rv = g_slist_append(rv, dp->name); + } + } else if (strcasecmp(listname,"holdingdisk") == 0) { + for(hp = holdinglist; hp != NULL; hp=hp->next) { + rv = g_slist_append(rv, hp->name); + } + } else if (strcasecmp(listname,"interface") == 0) { + for(ip = interface_list; ip != NULL; ip=ip->next) { + rv = g_slist_append(rv, ip->name); + } + } + return rv; +} - case CONF_SIZE: - if (tokenval.v.size != (size_t)0) - val = 1; - else - val = 0; - break; +val_t * +getconf_byname( + char *key) +{ + val_t *rv = NULL; - case CONF_AM64: - if (tokenval.v.am64 != (off_t)0) - val = 1; - else - val = 0; - break; + if (!parm_key_info(key, NULL, &rv)) + return NULL; - case CONF_ATRUE: - val = 1; - break; + return rv; +} - case CONF_AFALSE: - val = 0; - break; +tapetype_t * +lookup_tapetype( + char *str) +{ + tapetype_t *p; - case CONF_NL: - unget_conftoken(); - val = 2; /* no argument - most likely TRUE */ - break; - default: - unget_conftoken(); - val = 3; /* a bad argument - most likely TRUE */ - conf_parserror("YES, NO, TRUE, FALSE, ON, OFF expected"); - break; + for(p = tapelist; p != NULL; p = p->next) { + if(strcasecmp(p->name, str) == 0) return p; } + return NULL; +} - keytable = save_kt; - return val; +val_t * +tapetype_getconf( + tapetype_t *ttyp, + tapetype_key key) +{ + assert(ttyp != NULL); + assert(key < TAPETYPE_TAPETYPE); + return &ttyp->value[key]; } -void -ckseen( - int *seen) +char * +tapetype_name( + tapetype_t *ttyp) +{ + assert(ttyp != NULL); + return ttyp->name; +} + +dumptype_t * +lookup_dumptype( + char *str) { - if (*seen && !allow_overwrites && conf_line_num != -2) { - conf_parserror("duplicate parameter, prev def on line %d", *seen); + dumptype_t *p; + + for(p = dumplist; p != NULL; p = p->next) { + if(strcasecmp(p->name, str) == 0) return p; } - *seen = conf_line_num; + return NULL; } -printf_arglist_function(void conf_parserror, const char *, format) +val_t * +dumptype_getconf( + dumptype_t *dtyp, + dumptype_key key) { - va_list argp; + assert(dtyp != NULL); + assert(key < DUMPTYPE_DUMPTYPE); + return &dtyp->value[key]; +} - /* print error message */ +char * +dumptype_name( + dumptype_t *dtyp) +{ + assert(dtyp != NULL); + return dtyp->name; +} - if(conf_line) - fprintf(stderr, "argument \"%s\": ", conf_line); - else - fprintf(stderr, "\"%s\", line %d: ", conf_confname, conf_line_num); - arglist_start(argp, format); - vfprintf(stderr, format, argp); - arglist_end(argp); - fputc('\n', stderr); +interface_t * +lookup_interface( + char *str) +{ + interface_t *p; - got_parserror = 1; + for(p = interface_list; p != NULL; p = p->next) { + if(strcasecmp(p->name, str) == 0) return p; + } + return NULL; } -tok_t -lookup_keyword( - char * str) +val_t * +interface_getconf( + interface_t *iface, + interface_key key) { - keytab_t *kwp; + assert(iface != NULL); + assert(key < INTER_INTER); + return &iface->value[key]; +} + +char * +interface_name( + interface_t *iface) +{ + assert(iface != NULL); + return iface->name; +} - /* switch to binary search if performance warrants */ +holdingdisk_t * +lookup_holdingdisk( + char *str) +{ + holdingdisk_t *p; - for(kwp = keytable; kwp->keyword != NULL; kwp++) { - if (strcasecmp(kwp->keyword, str) == 0) break; + for(p = holdinglist; p != NULL; p = p->next) { + if(strcasecmp(p->name, str) == 0) return p; } - return kwp->token; + return NULL; +} + +holdingdisk_t * +getconf_holdingdisks( + void) +{ + return holdinglist; } -char tkbuf[4096]; +holdingdisk_t * +holdingdisk_next( + holdingdisk_t *hdisk) +{ + if (hdisk) return hdisk->next; + return NULL; +} -/* push the last token back (can only unget ANY tokens) */ -static void -unget_conftoken(void) +val_t * +holdingdisk_getconf( + holdingdisk_t *hdisk, + holdingdisk_key key) { - token_pushed = 1; - pushed_tok = tok; - tok = CONF_UNKNOWN; - return; + assert(hdisk != NULL); + assert(key < HOLDING_HOLDING); + return &hdisk->value[key]; } -static int -conftoken_getc(void) +char * +holdingdisk_name( + holdingdisk_t *hdisk) { - if(conf_line == NULL) - return getc(conf_conf); - if(*conf_char == '\0') - return -1; - return(*conf_char++); + assert(hdisk != NULL); + return hdisk->name; } -static int -conftoken_ungetc( - int c) +long int +getconf_unit_divisor(void) { - if(conf_line == NULL) - return ungetc(c, conf_conf); - else if(conf_char > conf_line) { - if(c == -1) - return c; - conf_char--; - if(*conf_char != c) { - error("*conf_char != c : %c %c", *conf_char, c); + return unit_divisor; +} + +/* + * Command-line Handling Implementation + */ + +config_overwrites_t * +new_config_overwrites( + int size_estimate) +{ + config_overwrites_t *co; + + co = alloc(sizeof(*co)); + co->ovr = alloc(sizeof(*co->ovr) * size_estimate); + co->n_allocated = size_estimate; + co->n_used = 0; + + return co; +} + +void +free_config_overwrites( + config_overwrites_t *co) +{ + int i; + + if (!co) return; + for (i = 0; i < co->n_used; i++) { + amfree(co->ovr[i].key); + amfree(co->ovr[i].value); + } + amfree(co->ovr); + amfree(co); +} + +void add_config_overwrite( + config_overwrites_t *co, + char *key, + char *value) +{ + /* reallocate if necessary */ + if (co->n_used == co->n_allocated) { + co->n_allocated *= 2; + co->ovr = realloc(co->ovr, co->n_allocated * sizeof(*co->ovr)); + if (!co->ovr) { + error(_("Cannot realloc; out of memory")); /* NOTREACHED */ } - } else { - error("conf_char == conf_line"); - /* NOTREACHED */ } - return c; + + co->ovr[co->n_used].key = stralloc(key); + co->ovr[co->n_used].value = stralloc(value); + co->n_used++; } -static void -get_conftoken( - tok_t exp) +void +add_config_overwrite_opt( + config_overwrites_t *co, + char *optarg) { - int ch, d; - off_t am64; - char *buf; - char *tmps; - int token_overflow; - int inquote = 0; - int escape = 0; - int sign; + char *value; + assert(optarg != NULL); - if (token_pushed) { - token_pushed = 0; - tok = pushed_tok; + value = index(optarg, '='); + if (value == NULL) { + error(_("Must specify a value for %s."), optarg); + /* NOTREACHED */ + } - /* - ** If it looked like a key word before then look it - ** up again in the current keyword table. - */ - switch(tok) { - case CONF_LONG: case CONF_AM64: case CONF_SIZE: - case CONF_INT: case CONF_REAL: case CONF_STRING: - case CONF_LBRACE: case CONF_RBRACE: case CONF_COMMA: - case CONF_NL: case CONF_END: case CONF_UNKNOWN: - case CONF_TIME: - break; + *value = '\0'; + add_config_overwrite(co, optarg, value+1); + *value = '='; +} - default: - if (exp == CONF_IDENT) - tok = CONF_IDENT; - else - tok = lookup_keyword(tokenval.v.s); - break; - } - } - else { - ch = conftoken_getc(); +config_overwrites_t * +extract_commandline_config_overwrites( + int *argc, + char ***argv) +{ + int i, j, moveup; + config_overwrites_t *co = new_config_overwrites(*argc/2); - while(ch != EOF && ch != '\n' && isspace(ch)) - ch = conftoken_getc(); - if (ch == '#') { /* comment - eat everything but eol/eof */ - while((ch = conftoken_getc()) != EOF && ch != '\n') { - (void)ch; /* Quiet empty loop complaints */ + i = 0; + while (i<*argc) { + if(strncmp((*argv)[i],"-o",2) == 0) { + if(strlen((*argv)[i]) > 2) { + add_config_overwrite_opt(co, (*argv)[i]+2); + moveup = 1; + } + else { + if (i+1 >= *argc) error(_("expect something after -o")); + add_config_overwrite_opt(co, (*argv)[i+1]); + moveup = 2; } + + /* move up remaining argment array */ + for (j = i; j+moveup<*argc; j++) { + (*argv)[j] = (*argv)[j+moveup]; + } + *argc -= moveup; + } else { + i++; } + } - if (isalpha(ch)) { /* identifier */ - buf = tkbuf; - token_overflow = 0; - do { - if (buf < tkbuf+sizeof(tkbuf)-1) { - *buf++ = (char)ch; - } else { - *buf = '\0'; - if (!token_overflow) { - conf_parserror("token too long: %.20s...", tkbuf); - } - token_overflow = 1; - } - ch = conftoken_getc(); - } while(isalnum(ch) || ch == '_' || ch == '-'); - - if (ch != EOF && conftoken_ungetc(ch) == EOF) { - if (ferror(conf_conf)) { - conf_parserror("Pushback of '%c' failed: %s", - ch, strerror(ferror(conf_conf))); - } else { - conf_parserror("Pushback of '%c' failed: EOF", ch); - } - } - *buf = '\0'; - - tokenval.v.s = tkbuf; - - if (token_overflow) tok = CONF_UNKNOWN; - else if (exp == CONF_IDENT) tok = CONF_IDENT; - else tok = lookup_keyword(tokenval.v.s); - } - else if (isdigit(ch)) { /* integer */ - sign = 1; - -negative_number: /* look for goto negative_number below sign is set there */ - am64 = 0; - do { - am64 = am64 * 10 + (ch - '0'); - ch = conftoken_getc(); - } while (isdigit(ch)); - - if (ch != '.') { - if (exp == CONF_INT) { - tok = CONF_INT; - tokenval.v.i = sign * (int)am64; - } else if (exp == CONF_LONG) { - tok = CONF_LONG; - tokenval.v.l = (long)sign * (long)am64; - } else if (exp != CONF_REAL) { - tok = CONF_AM64; - tokenval.v.am64 = (off_t)sign * am64; - } else { - /* automatically convert to real when expected */ - tokenval.v.r = (double)sign * (double)am64; - tok = CONF_REAL; - } - } else { - /* got a real number, not an int */ - tokenval.v.r = sign * (double) am64; - am64 = 0; - d = 1; - ch = conftoken_getc(); - while (isdigit(ch)) { - am64 = am64 * 10 + (ch - '0'); - d = d * 10; - ch = conftoken_getc(); - } - tokenval.v.r += sign * ((double)am64) / d; - tok = CONF_REAL; - } - - if (ch != EOF && conftoken_ungetc(ch) == EOF) { - if (ferror(conf_conf)) { - conf_parserror("Pushback of '%c' failed: %s", - ch, strerror(ferror(conf_conf))); - } else { - conf_parserror("Pushback of '%c' failed: EOF", ch); - } - } - } else switch(ch) { - case '"': /* string */ - buf = tkbuf; - token_overflow = 0; - inquote = 1; - *buf++ = (char)ch; - while (inquote && ((ch = conftoken_getc()) != EOF)) { - if (ch == '\n') { - if (!escape) - break; - escape = 0; - buf--; /* Consume escape in buffer */ - } else if (ch == '\\') { - escape = 1; - } else { - if (ch == '"') { - if (!escape) - inquote = 0; - } - escape = 0; - } + return co; +} - if(buf >= &tkbuf[sizeof(tkbuf) - 1]) { - if (!token_overflow) { - conf_parserror("string too long: %.20s...", tkbuf); - } - token_overflow = 1; - break; - } - *buf++ = (char)ch; - } - *buf = '\0'; +void +apply_config_overwrites( + config_overwrites_t *co) +{ + int i; - /* - * A little manuver to leave a fully unquoted, unallocated string - * in tokenval.v.s - */ - tmps = unquote_string(tkbuf); - strncpy(tkbuf, tmps, sizeof(tkbuf)); - amfree(tmps); - tokenval.v.s = tkbuf; + if(!co) return; + assert(keytable != NULL); + assert(parsetable != NULL); - tok = (token_overflow) ? CONF_UNKNOWN : - (exp == CONF_IDENT) ? CONF_IDENT : CONF_STRING; - break; + for (i = 0; i < co->n_used; i++) { + char *key = co->ovr[i].key; + char *value = co->ovr[i].value; + val_t *key_val; + conf_var_t *key_parm; - case '-': - ch = conftoken_getc(); - if (isdigit(ch)) { - sign = -1; - goto negative_number; - } - else { - if (ch != EOF && conftoken_ungetc(ch) == EOF) { - if (ferror(conf_conf)) { - conf_parserror("Pushback of '%c' failed: %s", - ch, strerror(ferror(conf_conf))); - } else { - conf_parserror("Pushback of '%c' failed: EOF", ch); - } - } - tok = CONF_UNKNOWN; - } - break; + if (!parm_key_info(key, &key_parm, &key_val)) { + error(_("unknown parameter '%s'"), key); + } - case ',': - tok = CONF_COMMA; - break; + /* now set up a fake line and use the relevant read_function to + * parse it. This is sneaky! */ - case '{': - tok = CONF_LBRACE; - break; + if (key_parm->type == CONFTYPE_STR) { + current_line = vstralloc("\"", value, "\"", NULL); + } else { + current_line = stralloc(""); + } - case '}': - tok = CONF_RBRACE; - break; + current_char = current_line; + token_pushed = 0; + current_line_num = -2; + allow_overwrites = 1; + got_parserror = 0; - case '\n': - tok = CONF_NL; - break; + key_parm->read_function(key_parm, key_val); + if ((key_parm)->validate_function) + key_parm->validate_function(key_parm, key_val); - case EOF: - tok = CONF_END; - break; + amfree(current_line); + current_char = NULL; - default: - tok = CONF_UNKNOWN; - break; + if (got_parserror) { + error(_("parse error in configuration overwrites")); + /* NOTREACHED */ } } - if (exp != CONF_ANY && tok != exp) { - char *str; - keytab_t *kwp; - - switch(exp) { - case CONF_LBRACE: - str = "\"{\""; - break; - - case CONF_RBRACE: - str = "\"}\""; - break; - - case CONF_COMMA: - str = "\",\""; - break; - - case CONF_NL: - str = "end of line"; - break; - - case CONF_END: - str = "end of file"; - break; - - case CONF_INT: - str = "an integer"; - break; + /* merge these overwrites with previous overwrites, if necessary */ + if (applied_config_overwrites) { + for (i = 0; i < co->n_used; i++) { + char *key = co->ovr[i].key; + char *value = co->ovr[i].value; - case CONF_REAL: - str = "a real number"; - break; - - case CONF_STRING: - str = "a quoted string"; - break; - - case CONF_IDENT: - str = "an identifier"; - break; - - default: - for(kwp = keytable; kwp->keyword != NULL; kwp++) { - if (exp == kwp->token) - break; - } - if (kwp->keyword == NULL) - str = "token not"; - else - str = kwp->keyword; - break; + add_config_overwrite(applied_config_overwrites, key, value); } - conf_parserror("%s is expected", str); - tok = exp; - if (tok == CONF_INT) - tokenval.v.i = 0; - else - tokenval.v.s = ""; + free_config_overwrites(co); + } else { + applied_config_overwrites = co; } + + update_derived_values(config_client); } +/* + * val_t Management Implementation + */ -static void -read_string( - t_conf_var *np, +int +val_t_to_int( val_t *val) { - np = np; - ckseen(&val->seen); - get_conftoken(CONF_STRING); - val->v.s = newstralloc(val->v.s, tokenval.v.s); + if (val->type != CONFTYPE_INT) { + error(_("val_t_to_int: val.type is not CONFTYPE_INT")); + /*NOTREACHED*/ + } + return val_t__int(val); } -static void -read_ident( - t_conf_var *np, +off_t +val_t_to_am64( val_t *val) { - np = np; - ckseen(&val->seen); - get_conftoken(CONF_IDENT); - val->v.s = newstralloc(val->v.s, tokenval.v.s); + if (val->type != CONFTYPE_AM64) { + error(_("val_t_to_am64: val.type is not CONFTYPE_AM64")); + /*NOTREACHED*/ + } + return val_t__am64(val); } -static void -read_int( - t_conf_var *np, +float +val_t_to_real( val_t *val) { - np = np; - ckseen(&val->seen); - val->v.i = get_int(); + if (val->type != CONFTYPE_REAL) { + error(_("val_t_to_real: val.type is not CONFTYPE_REAL")); + /*NOTREACHED*/ + } + return val_t__real(val); } -/* -static void -read_long( - t_conf_var *np, +char * +val_t_to_str( val_t *val) { - np = np; - ckseen(&val->seen); - val->v.l = get_long(); + /* support CONFTYPE_IDENT, too */ + if (val->type != CONFTYPE_STR && val->type != CONFTYPE_IDENT) { + error(_("val_t_to_str: val.type is not CONFTYPE_STR nor CONFTYPE_IDENT")); + /*NOTREACHED*/ + } + return val_t__str(val); } -*/ -static void -read_size( - t_conf_var *np, +char * +val_t_to_ident( val_t *val) { - np = np; - ckseen(&val->seen); - val->v.size = get_size(); + /* support CONFTYPE_STR, too */ + if (val->type != CONFTYPE_STR && val->type != CONFTYPE_IDENT) { + error(_("val_t_to_ident: val.type is not CONFTYPE_IDENT nor CONFTYPE_STR")); + /*NOTREACHED*/ + } + return val_t__str(val); } -static void -read_am64( - t_conf_var *np, +time_t +val_t_to_time( val_t *val) { - np = np; - ckseen(&val->seen); - val->v.am64 = get_am64_t(); + if (val->type != CONFTYPE_TIME) { + error(_("val_t_to_time: val.type is not CONFTYPE_TIME")); + /*NOTREACHED*/ + } + return val_t__time(val); } -static void -read_bool( - t_conf_var *np, +ssize_t +val_t_to_size( val_t *val) { - np = np; - ckseen(&val->seen); - val->v.i = get_bool(); + if (val->type != CONFTYPE_SIZE) { + error(_("val_t_to_size: val.type is not CONFTYPE_SIZE")); + /*NOTREACHED*/ + } + return val_t__size(val); } -static void -read_real( - t_conf_var *np, +int +val_t_to_boolean( val_t *val) { - np = np; - ckseen(&val->seen); - get_conftoken(CONF_REAL); - val->v.r = tokenval.v.r; + if (val->type != CONFTYPE_BOOLEAN) { + error(_("val_t_to_bool: val.type is not CONFTYPE_BOOLEAN")); + /*NOTREACHED*/ + } + return val_t__boolean(val); } -static void -read_time( - t_conf_var *np, +comp_t +val_t_to_compress( val_t *val) { - np = np; - ckseen(&val->seen); - val->v.t = get_time(); + if (val->type != CONFTYPE_COMPRESS) { + error(_("val_t_to_compress: val.type is not CONFTYPE_COMPRESS")); + /*NOTREACHED*/ + } + return val_t__compress(val); +} + +encrypt_t +val_t_to_encrypt( + val_t *val) +{ + if (val->type != CONFTYPE_ENCRYPT) { + error(_("val_t_to_encrypt: val.type is not CONFTYPE_ENCRYPT")); + /*NOTREACHED*/ + } + return val_t__encrypt(val); +} + +dump_holdingdisk_t +val_t_to_holding( + val_t *val) +{ + if (val->type != CONFTYPE_HOLDING) { + error(_("val_t_to_hold: val.type is not CONFTYPE_HOLDING")); + /*NOTREACHED*/ + } + return val_t__holding(val); +} + +estimate_t +val_t_to_estimate( + val_t *val) +{ + if (val->type != CONFTYPE_ESTIMATE) { + error(_("val_t_to_extimate: val.type is not CONFTYPE_ESTIMATE")); + /*NOTREACHED*/ + } + return val_t__estimate(val); +} + +strategy_t +val_t_to_strategy( + val_t *val) +{ + if (val->type != CONFTYPE_STRATEGY) { + error(_("val_t_to_strategy: val.type is not CONFTYPE_STRATEGY")); + /*NOTREACHED*/ + } + return val_t__strategy(val); +} + +taperalgo_t +val_t_to_taperalgo( + val_t *val) +{ + if (val->type != CONFTYPE_TAPERALGO) { + error(_("val_t_to_taperalgo: val.type is not CONFTYPE_TAPERALGO")); + /*NOTREACHED*/ + } + return val_t__taperalgo(val); +} + +int +val_t_to_priority( + val_t *val) +{ + if (val->type != CONFTYPE_PRIORITY) { + error(_("val_t_to_priority: val.type is not CONFTYPE_PRIORITY")); + /*NOTREACHED*/ + } + return val_t__priority(val); +} + +float * +val_t_to_rate( + val_t *val) +{ + if (val->type != CONFTYPE_RATE) { + error(_("val_t_to_rate: val.type is not CONFTYPE_RATE")); + /*NOTREACHED*/ + } + return val_t__rate(val); +} + +exinclude_t +val_t_to_exinclude( + val_t *val) +{ + if (val->type != CONFTYPE_EXINCLUDE) { + error(_("val_t_to_exinclude: val.type is not CONFTYPE_EXINCLUDE")); + /*NOTREACHED*/ + } + return val_t__exinclude(val); +} + + +int * +val_t_to_intrange( + val_t *val) +{ + if (val->type != CONFTYPE_INTRANGE) { + error(_("val_t_to_intrange: val.type is not CONFTYPE_INTRANGE")); + /*NOTREACHED*/ + } + return val_t__intrange(val); +} + +proplist_t +val_t_to_proplist( + val_t *val) +{ + if (val->type != CONFTYPE_PROPLIST) { + error(_("val_t_to_proplist: val.type is not CONFTYPE_PROPLIST")); + /*NOTREACHED*/ + } + return val_t__proplist(val); } static void @@ -4115,7 +4208,7 @@ copy_val_t( valdst->seen = valsrc->seen; switch(valsrc->type) { case CONFTYPE_INT: - case CONFTYPE_BOOL: + case CONFTYPE_BOOLEAN: case CONFTYPE_COMPRESS: case CONFTYPE_ENCRYPT: case CONFTYPE_HOLDING: @@ -4126,10 +4219,6 @@ copy_val_t( valdst->v.i = valsrc->v.i; break; - case CONFTYPE_LONG: - valdst->v.l = valsrc->v.l; - break; - case CONFTYPE_SIZE: valdst->v.size = valsrc->v.size; break; @@ -4148,7 +4237,7 @@ copy_val_t( break; case CONFTYPE_IDENT: - case CONFTYPE_STRING: + case CONFTYPE_STR: valdst->v.s = stralloc(valsrc->v.s); break; @@ -4156,10 +4245,6 @@ copy_val_t( valdst->v.t = valsrc->v.t; break; - case CONFTYPE_SL: - valdst->v.sl = duplicate_sl(valsrc->v.sl); - break; - case CONFTYPE_EXINCLUDE: valdst->v.exinclude.optional = valsrc->v.exinclude.optional; valdst->v.exinclude.sl_list = duplicate_sl(valsrc->v.exinclude.sl_list); @@ -4171,6 +4256,9 @@ copy_val_t( valdst->v.intrange[1] = valsrc->v.intrange[1]; break; + case CONFTYPE_PROPLIST: + g_assert_not_reached(); + break; } } } @@ -4181,7 +4269,7 @@ free_val_t( { switch(val->type) { case CONFTYPE_INT: - case CONFTYPE_BOOL: + case CONFTYPE_BOOLEAN: case CONFTYPE_COMPRESS: case CONFTYPE_ENCRYPT: case CONFTYPE_HOLDING: @@ -4190,7 +4278,6 @@ free_val_t( case CONFTYPE_SIZE: case CONFTYPE_TAPERALGO: case CONFTYPE_PRIORITY: - case CONFTYPE_LONG: case CONFTYPE_AM64: case CONFTYPE_REAL: case CONFTYPE_RATE: @@ -4198,971 +4285,743 @@ free_val_t( break; case CONFTYPE_IDENT: - case CONFTYPE_STRING: + case CONFTYPE_STR: amfree(val->v.s); break; case CONFTYPE_TIME: break; - case CONFTYPE_SL: - free_sl(val->v.sl); - break; - case CONFTYPE_EXINCLUDE: - free_sl(val->v.exinclude.sl_list); - free_sl(val->v.exinclude.sl_file); + free_sl(val_t__exinclude(val).sl_list); + free_sl(val_t__exinclude(val).sl_file); break; + + case CONFTYPE_PROPLIST: + g_hash_table_destroy(val_t__proplist(val)); + break; } val->seen = 0; } +/* + * Utilities Implementation + */ + char * -taperalgo2str( - int taperalgo) +generic_get_security_conf( + char *string, + void *arg) { - if(taperalgo == ALGO_FIRST) return "FIRST"; - if(taperalgo == ALGO_FIRSTFIT) return "FIRSTFIT"; - if(taperalgo == ALGO_LARGEST) return "LARGEST"; - if(taperalgo == ALGO_LARGESTFIT) return "LARGESTFIT"; - if(taperalgo == ALGO_SMALLEST) return "SMALLEST"; - if(taperalgo == ALGO_LAST) return "LAST"; - return "UNKNOWN"; + arg = arg; + if(!string || !*string) + return(NULL); + + if(strcmp(string, "krb5principal")==0) { + return(getconf_str(CNF_KRB5PRINCIPAL)); + } else if(strcmp(string, "krb5keytab")==0) { + return(getconf_str(CNF_KRB5KEYTAB)); + } + return(NULL); } -static char buffer_conf_print[2049]; +char * +generic_client_get_security_conf( + char * string, + void * arg) +{ + (void)arg; /* Quiet unused parameter warning */ + + if(!string || !*string) + return(NULL); -static char * -conf_print( + if(strcmp(string, "conf")==0) { + return(getconf_str(CNF_CONF)); + } else if(strcmp(string, "index_server")==0) { + return(getconf_str(CNF_INDEX_SERVER)); + } else if(strcmp(string, "tape_server")==0) { + return(getconf_str(CNF_TAPE_SERVER)); + } else if(strcmp(string, "tapedev")==0) { + return(getconf_str(CNF_TAPEDEV)); + } else if(strcmp(string, "auth")==0) { + return(getconf_str(CNF_AUTH)); + } else if(strcmp(string, "ssh_keys")==0) { + return(getconf_str(CNF_SSH_KEYS)); + } else if(strcmp(string, "amandad_path")==0) { + return(getconf_str(CNF_AMANDAD_PATH)); + } else if(strcmp(string, "client_username")==0) { + return(getconf_str(CNF_CLIENT_USERNAME)); + } else if(strcmp(string, "gnutar_list_dir")==0) { + return(getconf_str(CNF_GNUTAR_LIST_DIR)); + } else if(strcmp(string, "amandates")==0) { + return(getconf_str(CNF_AMANDATES)); + } else if(strcmp(string, "krb5principal")==0) { + return(getconf_str(CNF_KRB5PRINCIPAL)); + } else if(strcmp(string, "krb5keytab")==0) { + return(getconf_str(CNF_KRB5KEYTAB)); + } + return(NULL); +} + +void +dump_configuration(void) +{ + tapetype_t *tp; + dumptype_t *dp; + interface_t *ip; + holdingdisk_t *hp; + int i; + conf_var_t *np; + keytab_t *kt; + char *prefix; + + if (config_client) { + error(_("Don't know how to dump client configurations.")); + /* NOTREACHED */ + } + + g_printf(_("# AMANDA CONFIGURATION FROM FILE \"%s\":\n\n"), config_filename); + + for(np=server_var; np->token != CONF_UNKNOWN; np++) { + for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) + if (np->token == kt->token) break; + + if(kt->token == CONF_UNKNOWN) + error(_("server bad token")); + + val_t_print_token(stdout, NULL, "%-21s ", kt, &conf_data[np->parm]); + } + + for(hp = holdinglist; hp != NULL; hp = hp->next) { + g_printf("\nHOLDINGDISK %s {\n", hp->name); + for(i=0; i < HOLDING_HOLDING; i++) { + for(np=holding_var; np->token != CONF_UNKNOWN; np++) { + if(np->parm == i) + break; + } + if(np->token == CONF_UNKNOWN) + error(_("holding bad value")); + + for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) { + if(kt->token == np->token) + break; + } + if(kt->token == CONF_UNKNOWN) + error(_("holding bad token")); + + val_t_print_token(stdout, NULL, " %-9s ", kt, &hp->value[i]); + } + g_printf("}\n"); + } + + for(tp = tapelist; tp != NULL; tp = tp->next) { + g_printf("\nDEFINE TAPETYPE %s {\n", tp->name); + for(i=0; i < TAPETYPE_TAPETYPE; i++) { + for(np=tapetype_var; np->token != CONF_UNKNOWN; np++) + if(np->parm == i) break; + if(np->token == CONF_UNKNOWN) + error(_("tapetype bad value")); + + for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) + if(kt->token == np->token) break; + if(kt->token == CONF_UNKNOWN) + error(_("tapetype bad token")); + + val_t_print_token(stdout, NULL, " %-9s ", kt, &tp->value[i]); + } + g_printf("}\n"); + } + + for(dp = dumplist; dp != NULL; dp = dp->next) { + if (strncmp_const(dp->name, "custom(") != 0) { /* don't dump disklist-derived dumptypes */ + if(dp->seen == -1) + prefix = "#"; + else + prefix = ""; + g_printf("\n%sDEFINE DUMPTYPE %s {\n", prefix, dp->name); + for(i=0; i < DUMPTYPE_DUMPTYPE; i++) { + for(np=dumptype_var; np->token != CONF_UNKNOWN; np++) + if(np->parm == i) break; + if(np->token == CONF_UNKNOWN) + error(_("dumptype bad value")); + + for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) + if(kt->token == np->token) break; + if(kt->token == CONF_UNKNOWN) + error(_("dumptype bad token")); + + val_t_print_token(stdout, prefix, " %-19s ", kt, &dp->value[i]); + } + g_printf("%s}\n", prefix); + } + } + + for(ip = interface_list; ip != NULL; ip = ip->next) { + if(strcmp(ip->name,"default") == 0) + prefix = "#"; + else + prefix = ""; + g_printf("\n%sDEFINE INTERFACE %s {\n", prefix, ip->name); + for(i=0; i < INTER_INTER; i++) { + for(np=interface_var; np->token != CONF_UNKNOWN; np++) + if(np->parm == i) break; + if(np->token == CONF_UNKNOWN) + error(_("interface bad value")); + + for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++) + if(kt->token == np->token) break; + if(kt->token == CONF_UNKNOWN) + error(_("interface bad token")); + + val_t_print_token(stdout, prefix, " %-19s ", kt, &ip->value[i]); + } + g_printf("%s}\n",prefix); + } + +} + +static void +val_t_print_token( + FILE *output, + char *prefix, + char *format, + keytab_t *kt, + val_t *val) +{ + char **dispstrs, **dispstr; + dispstrs = val_t_display_strs(val, 1); + + /* For most configuration types, this outputs + * PREFIX KEYWORD DISPSTR + * for each of the display strings. For identifiers, however, it + * simply prints the first line of the display string. + */ + + /* Print the keyword for anything that is not itself an identifier */ + if (kt->token != CONF_IDENT) { + for(dispstr=dispstrs; *dispstr!=NULL; dispstr++) { + if (prefix) + g_fprintf(output, "%s", prefix); + g_fprintf(output, format, kt->keyword); + g_fprintf(output, "%s\n", *dispstr); + } + } else { + /* for identifiers, assume there's at most one display string */ + assert(g_strv_length(dispstrs) <= 1); + if (*dispstrs) { + g_fprintf(output, "%s\n", *dispstrs); + } + } + + g_strfreev(dispstrs); +} + +char ** +val_t_display_strs( val_t *val, - int str_need_quote, - char *prefix) + int str_need_quote) { - char *buf; - int free_space; + char **buf; + buf = malloc(3*SIZEOF(char *)); + buf[0] = NULL; + buf[1] = NULL; + buf[2] = NULL; - buffer_conf_print[0] = '\0'; - snprintf(buffer_conf_print, SIZEOF(buffer_conf_print), prefix); - free_space = SIZEOF(buffer_conf_print) - strlen(buffer_conf_print); - buf = buffer_conf_print + strlen(buffer_conf_print); switch(val->type) { case CONFTYPE_INT: - snprintf(buf, free_space, "%d", val->v.i); - break; - - case CONFTYPE_LONG: - snprintf(buf, free_space, "%ld", val->v.l); + buf[0] = vstrallocf("%d", val_t__int(val)); break; case CONFTYPE_SIZE: - snprintf(buf, free_space, SSIZE_T_FMT, (SSIZE_T_FMT_TYPE)val->v.size); + buf[0] = vstrallocf("%zd", (ssize_t)val_t__size(val)); break; case CONFTYPE_AM64: - snprintf(buf, free_space, OFF_T_FMT, (OFF_T_FMT_TYPE)val->v.am64); + buf[0] = vstrallocf("%lld", (long long)val_t__am64(val)); break; case CONFTYPE_REAL: - snprintf(buf, free_space, "%0.5f" , val->v.r); + buf[0] = vstrallocf("%0.5f", val_t__real(val)); break; case CONFTYPE_RATE: - snprintf(buf, free_space, "%0.5f %0.5f", - val->v.rate[0], val->v.rate[1]); + buf[0] = vstrallocf("%0.5f %0.5f", val_t__rate(val)[0], val_t__rate(val)[1]); break; case CONFTYPE_INTRANGE: - snprintf(buf, free_space, "%d,%d", - val->v.intrange[0], val->v.intrange[1]); + buf[0] = vstrallocf("%d,%d", val_t__intrange(val)[0], val_t__intrange(val)[1]); break; case CONFTYPE_IDENT: if(val->v.s) { - strncpy(buf, val->v.s, free_space); + buf[0] = stralloc(val->v.s); + } else { + buf[0] = stralloc(""); } break; - case CONFTYPE_STRING: + case CONFTYPE_STR: if(str_need_quote) { - *buf++ = '"'; - free_space++; if(val->v.s) { - strncpy(buf, val->v.s, free_space); - buffer_conf_print[SIZEOF(buffer_conf_print) - 2] = '\0'; - buffer_conf_print[strlen(buffer_conf_print)] = '"'; - buffer_conf_print[strlen(buffer_conf_print) + 1] = '\0'; + buf[0] = vstrallocf("\"%s\"", val->v.s); } else { - *buf++ = '"'; - *buf++ = '\0'; - free_space -= 2; + buf[0] = stralloc("\"\""); } } else { if(val->v.s) { - strncpy(buf, val->v.s, free_space); - } + buf[0] = stralloc(val->v.s); + } else { + buf[0] = stralloc(""); + } } break; case CONFTYPE_TIME: - snprintf(buf, free_space, "%2d%02d", - (int)val->v.t/100, (int)val->v.t % 100); + buf[0] = vstrallocf("%2d%02d", + (int)val_t__time(val)/100, (int)val_t__time(val) % 100); break; - case CONFTYPE_SL: + case CONFTYPE_EXINCLUDE: { + buf[0] = exinclude_display_str(val, 0); + buf[1] = exinclude_display_str(val, 1); break; + } - case CONFTYPE_EXINCLUDE: - buf = buffer_conf_print; - free_space = SIZEOF(buffer_conf_print); - - conf_print_exinclude(val, 1, 0, prefix, &buf ,&free_space); - *buf++ = '\n'; - free_space -= 1; - - conf_print_exinclude(val, 1, 1, prefix, &buf, &free_space); - break; - - case CONFTYPE_BOOL: - if(val->v.i) - strncpy(buf, "yes", free_space); + case CONFTYPE_BOOLEAN: + if(val_t__boolean(val)) + buf[0] = stralloc("yes"); else - strncpy(buf, "no", free_space); + buf[0] = stralloc("no"); break; case CONFTYPE_STRATEGY: - switch(val->v.i) { + switch(val_t__strategy(val)) { case DS_SKIP: - strncpy(buf, "SKIP", free_space); + buf[0] = vstrallocf("SKIP"); break; case DS_STANDARD: - strncpy(buf, "STANDARD", free_space); + buf[0] = vstrallocf("STANDARD"); break; case DS_NOFULL: - strncpy(buf, "NOFULL", free_space); + buf[0] = vstrallocf("NOFULL"); break; case DS_NOINC: - strncpy(buf, "NOINC", free_space); + buf[0] = vstrallocf("NOINC"); break; case DS_HANOI: - strncpy(buf, "HANOI", free_space); + buf[0] = vstrallocf("HANOI"); break; case DS_INCRONLY: - strncpy(buf, "INCRONLY", free_space); + buf[0] = vstrallocf("INCRONLY"); break; } break; case CONFTYPE_COMPRESS: - switch(val->v.i) { + switch(val_t__compress(val)) { case COMP_NONE: - strncpy(buf, "NONE", free_space); + buf[0] = vstrallocf("NONE"); break; case COMP_FAST: - strncpy(buf, "CLIENT FAST", free_space); + buf[0] = vstrallocf("CLIENT FAST"); break; case COMP_BEST: - strncpy(buf, "CLIENT BEST", free_space); + buf[0] = vstrallocf("CLIENT BEST"); break; case COMP_CUST: - strncpy(buf, "CLIENT CUSTOM", free_space); + buf[0] = vstrallocf("CLIENT CUSTOM"); break; case COMP_SERVER_FAST: - strncpy(buf, "SERVER FAST", free_space); + buf[0] = vstrallocf("SERVER FAST"); break; case COMP_SERVER_BEST: - strncpy(buf, "SERVER FAST", free_space); + buf[0] = vstrallocf("SERVER BEST"); break; case COMP_SERVER_CUST: - strncpy(buf, "SERVER CUSTOM", free_space); + buf[0] = vstrallocf("SERVER CUSTOM"); break; } break; case CONFTYPE_ESTIMATE: - switch(val->v.i) { + switch(val_t__estimate(val)) { case ES_CLIENT: - strncpy(buf, "CLIENT", free_space); + buf[0] = vstrallocf("CLIENT"); break; case ES_SERVER: - strncpy(buf, "SERVER", free_space); + buf[0] = vstrallocf("SERVER"); break; case ES_CALCSIZE: - strncpy(buf, "CALCSIZE", free_space); + buf[0] = vstrallocf("CALCSIZE"); break; } break; case CONFTYPE_ENCRYPT: - switch(val->v.i) { + switch(val_t__encrypt(val)) { case ENCRYPT_NONE: - strncpy(buf, "NONE", free_space); + buf[0] = vstrallocf("NONE"); break; case ENCRYPT_CUST: - strncpy(buf, "CLIENT", free_space); + buf[0] = vstrallocf("CLIENT"); break; case ENCRYPT_SERV_CUST: - strncpy(buf, "SERVER", free_space); + buf[0] = vstrallocf("SERVER"); break; } break; case CONFTYPE_HOLDING: - switch(val->v.i) { + switch(val_t__holding(val)) { case HOLD_NEVER: - strncpy(buf, "NEVER", free_space); + buf[0] = vstrallocf("NEVER"); break; case HOLD_AUTO: - strncpy(buf, "AUTO", free_space); + buf[0] = vstrallocf("AUTO"); break; case HOLD_REQUIRED: - strncpy(buf, "REQUIRED", free_space); + buf[0] = vstrallocf("REQUIRED"); break; } break; case CONFTYPE_TAPERALGO: - strncpy(buf, taperalgo2str(val->v.i), free_space); - break; - - case CONFTYPE_PRIORITY: - switch(val->v.i) { - case 0: - strncpy(buf, "LOW", free_space); - break; - - case 1: - strncpy(buf, "MEDIUM", free_space); - break; - - case 2: - strncpy(buf, "HIGH", free_space); - break; - } + buf[0] = vstrallocf("%s", taperalgo2str(val_t__taperalgo(val))); break; - } - buffer_conf_print[SIZEOF(buffer_conf_print) - 1] = '\0'; - return buffer_conf_print; -} - -void conf_print_exinclude( - val_t *val, - int str_need_quote, - int file, - char *prefix, - char **buf, - int *free_space) -{ - sl_t *sl; - sle_t *excl; - - (void)str_need_quote; - - snprintf(*buf, *free_space, prefix); - *free_space -= strlen(prefix); - *buf += strlen(prefix); - - if (val->type != CONFTYPE_EXINCLUDE) { - strcpy(*buf, - "ERROR: conf_print_exinclude called for type != CONFTYPE_EXINCLUDE"); - return; - } - - if (file == 0) { - sl = val->v.exinclude.sl_list; - strncpy(*buf, "LIST ", *free_space); - *buf += 5; - *free_space -= 5; - } else { - sl = val->v.exinclude.sl_file; - strncpy(*buf, "FILE ", *free_space); - *buf += 5; - *free_space -= 5; - } - - if (val->v.exinclude.optional == 1) { - strncpy(*buf, "OPTIONAL ", *free_space); - *buf += 9; - *free_space -= 9; - } - - if (sl != NULL) { - for(excl = sl->first; excl != NULL; excl = excl->next) { - if (3 + (int)strlen(excl->name) < *free_space) { - *(*buf)++ = ' '; - *(*buf)++ = '"'; - strcpy(*buf, excl->name); - *buf += strlen(excl->name); - *(*buf)++ = '"'; - *free_space -= 3 + strlen(excl->name); - } - } - } - - return; -} - -static void -conf_init_string( - val_t *val, - char *s) -{ - val->seen = 0; - val->type = CONFTYPE_STRING; - if(s) - val->v.s = stralloc(s); - else - val->v.s = NULL; -} - -static void -conf_init_ident( - val_t *val, - char *s) -{ - val->seen = 0; - val->type = CONFTYPE_IDENT; - if(s) - val->v.s = stralloc(s); - else - val->v.s = NULL; -} - -static void -conf_init_int( - val_t *val, - int i) -{ - val->seen = 0; - val->type = CONFTYPE_INT; - val->v.i = i; -} - -static void -conf_init_bool( - val_t *val, - int i) -{ - val->seen = 0; - val->type = CONFTYPE_BOOL; - val->v.i = i; -} - -static void -conf_init_strategy( - val_t *val, - int i) -{ - val->seen = 0; - val->type = CONFTYPE_STRATEGY; - val->v.i = i; -} - -static void -conf_init_estimate( - val_t *val, - int i) -{ - val->seen = 0; - val->type = CONFTYPE_ESTIMATE; - val->v.i = i; -} - -static void -conf_init_taperalgo( - val_t *val, - int i) -{ - val->seen = 0; - val->type = CONFTYPE_TAPERALGO; - val->v.i = i; -} - -static void -conf_init_priority( - val_t *val, - int i) -{ - val->seen = 0; - val->type = CONFTYPE_PRIORITY; - val->v.i = i; -} - -static void -conf_init_compress( - val_t *val, - comp_t i) -{ - val->seen = 0; - val->type = CONFTYPE_COMPRESS; - val->v.i = (int)i; -} - -static void -conf_init_encrypt( - val_t *val, - encrypt_t i) -{ - val->seen = 0; - val->type = CONFTYPE_ENCRYPT; - val->v.i = (int)i; -} - -static void -conf_init_holding( - val_t *val, - dump_holdingdisk_t i) -{ - val->seen = 0; - val->type = CONFTYPE_HOLDING; - val->v.i = (int)i; -} - -/* -static void -conf_init_long( - val_t *val, - long l) -{ - val->seen = 0; - val->type = CONFTYPE_LONG; - val->v.l = l; -} -*/ - -static void -conf_init_size( - val_t *val, - ssize_t sz) -{ - val->seen = 0; - val->type = CONFTYPE_SIZE; - val->v.size = sz; -} - -static void -conf_init_am64( - val_t *val, - off_t l) -{ - val->seen = 0; - val->type = CONFTYPE_AM64; - val->v.am64 = l; -} - -static void -conf_init_real( - val_t *val, - double r) -{ - val->seen = 0; - val->type = CONFTYPE_REAL; - val->v.r = r; -} - -static void -conf_init_rate( - val_t *val, - double r1, - double r2) -{ - val->seen = 0; - val->type = CONFTYPE_RATE; - val->v.rate[0] = r1; - val->v.rate[1] = r2; -} - -static void -conf_init_intrange( - val_t *val, - int i1, - int i2) -{ - val->seen = 0; - val->type = CONFTYPE_INTRANGE; - val->v.intrange[0] = i1; - val->v.intrange[1] = i2; -} - -static void -conf_init_time( - val_t *val, - time_t t) -{ - val->seen = 0; - val->type = CONFTYPE_TIME; - val->v.t = t; -} - -/* -static void -conf_init_sl( - val_t *val, - sl_t *sl) -{ - val->seen = 0; - val->type = CONFTYPE_AM64; - val->v.sl = sl; -} -*/ - -static void -conf_init_exinclude( - val_t *val) -{ - val->seen = 0; - val->type = CONFTYPE_EXINCLUDE; - val->v.exinclude.optional = 0; - val->v.exinclude.sl_list = NULL; - val->v.exinclude.sl_file = NULL; -} - -static void -conf_set_string( - val_t *val, - char *s) -{ - val->seen = -1; - val->type = CONFTYPE_STRING; - amfree(val->v.s); - val->v.s = stralloc(s); -} - -/* -static void -conf_set_int( - val_t *val, - int i) -{ - val->seen = -1; - val->type = CONFTYPE_INT; - val->v.i = i; -} -*/ - -static void -conf_set_bool( - val_t *val, - int i) -{ - val->seen = -1; - val->type = CONFTYPE_BOOL; - val->v.i = i; -} - -static void -conf_set_compress( - val_t *val, - comp_t i) -{ - val->seen = -1; - val->type = CONFTYPE_COMPRESS; - val->v.i = (int)i; -} - -/* -static void -conf_set_encrypt( - val_t *val, - encrypt_t i) -{ - val->seen = -1; - val->type = CONFTYPE_COMPRESS; - val->v.i = (int)i; -} -*/ - -static void -conf_set_holding( - val_t *val, - dump_holdingdisk_t i) -{ - val->seen = -1; - val->type = CONFTYPE_HOLDING; - val->v.i = (int)i; -} - -static void -conf_set_strategy( - val_t *val, - int i) -{ - val->seen = -1; - val->type = CONFTYPE_STRATEGY; - val->v.i = i; -} - -int -get_conftype_int( - val_t *val) -{ - if (val->type != CONFTYPE_INT) { - error("get_conftype_int: val.type is not CONFTYPE_INT"); - /*NOTREACHED*/ - } - return val->v.i; -} + case CONFTYPE_PRIORITY: + switch(val_t__priority(val)) { + case 0: + buf[0] = vstrallocf("LOW"); + break; -long -get_conftype_long( - val_t *val) -{ - if (val->type != CONFTYPE_LONG) { - error("get_conftype_long: val.type is not CONFTYPE_LONG"); - /*NOTREACHED*/ - } - return val->v.l; -} + case 1: + buf[0] = vstrallocf("MEDIUM"); + break; -off_t -get_conftype_am64( - val_t *val) -{ - if (val->type != CONFTYPE_AM64) { - error("get_conftype_am64: val.type is not CONFTYPE_AM64"); - /*NOTREACHED*/ - } - return val->v.am64; -} + case 2: + buf[0] = vstrallocf("HIGH"); + break; + } + break; -double -get_conftype_real( - val_t *val) -{ - if (val->type != CONFTYPE_REAL) { - error("get_conftype_real: val.type is not CONFTYPE_REAL"); - /*NOTREACHED*/ - } - return val->v.r; -} + case CONFTYPE_PROPLIST: { + int nb_property; + char **mybuf; -char * -get_conftype_string( - val_t *val) -{ - if (val->type != CONFTYPE_STRING) { - error("get_conftype_string: val.type is not CONFTYPE_STRING"); - /*NOTREACHED*/ + nb_property = g_hash_table_size(val_t__proplist(val)); + amfree(buf); + buf = malloc((nb_property+1)*SIZEOF(char*)); + buf[nb_property] = NULL; + mybuf = buf; + g_hash_table_foreach(val_t__proplist(val), proplist_display_str_foreach_fn, &mybuf); + break; } - return val->v.s; -} - -char * -get_conftype_ident( - val_t *val) -{ - if (val->type != CONFTYPE_IDENT) { - error("get_conftype_ident: val.type is not CONFTYPE_IDENT"); - /*NOTREACHED*/ } - return val->v.s; + return buf; } -time_t -get_conftype_time( - val_t *val) +static void +proplist_display_str_foreach_fn( + gpointer key_p, + gpointer value_p, + gpointer user_data_p) { - if (val->type != CONFTYPE_TIME) { - error("get_conftype_time: val.type is not CONFTYPE_TIME"); - /*NOTREACHED*/ - } - return val->v.t; -} + char *property_s = key_p; + char *value_s = value_p; + char ***msg = (char ***)user_data_p; -ssize_t -get_conftype_size( - val_t *val) -{ - if (val->type != CONFTYPE_SIZE) { - error("get_conftype_size: val.type is not CONFTYPE_SIZE"); - /*NOTREACHED*/ - } - return val->v.size; + **msg = vstralloc("\"", property_s, "\" \"", value_s, "\"", NULL); + (*msg)++; } -sl_t * -get_conftype_sl( - val_t *val) +static char * +exinclude_display_str( + val_t *val, + int file) { - if (val->type != CONFTYPE_SL) { - error("get_conftype_size: val.type is not CONFTYPE_SL"); - /*NOTREACHED*/ - } - return val->v.sl; -} + sl_t *sl; + sle_t *excl; + char *rval; -int -get_conftype_bool( - val_t *val) -{ - if (val->type != CONFTYPE_BOOL) { - error("get_conftype_bool: val.type is not CONFTYPE_BOOL"); - /*NOTREACHED*/ - } - return val->v.i; -} + assert(val->type == CONFTYPE_EXINCLUDE); -int -get_conftype_hold( - val_t *val) -{ - if (val->type != CONFTYPE_HOLDING) { - error("get_conftype_hold: val.type is not CONFTYPE_HOLDING"); - /*NOTREACHED*/ - } - return val->v.i; -} + rval = stralloc(""); -int -get_conftype_compress( - val_t *val) -{ - if (val->type != CONFTYPE_COMPRESS) { - error("get_conftype_compress: val.type is not CONFTYPE_COMPRESS"); - /*NOTREACHED*/ + if (file == 0) { + sl = val_t__exinclude(val).sl_list; + strappend(rval, "LIST"); + } else { + sl = val_t__exinclude(val).sl_file; + strappend(rval, "FILE"); } - return val->v.i; -} -int -get_conftype_encrypt( - val_t *val) -{ - if (val->type != CONFTYPE_ENCRYPT) { - error("get_conftype_encrypt: val.type is not CONFTYPE_ENCRYPT"); - /*NOTREACHED*/ + if (val_t__exinclude(val).optional == 1) { + strappend(rval, " OPTIONAL"); } - return val->v.i; -} -int -get_conftype_estimate( - val_t *val) -{ - if (val->type != CONFTYPE_ESTIMATE) { - error("get_conftype_extimate: val.type is not CONFTYPE_ESTIMATE"); - /*NOTREACHED*/ + if (sl != NULL) { + for(excl = sl->first; excl != NULL; excl = excl->next) { + vstrextend(&rval, " \"", excl->name, "\"", NULL); + } } - return val->v.i; -} -int -get_conftype_strategy( - val_t *val) -{ - if (val->type != CONFTYPE_STRATEGY) { - error("get_conftype_strategy: val.type is not CONFTYPE_STRATEGY"); - /*NOTREACHED*/ - } - return val->v.i; + return rval; } -int -get_conftype_taperalgo( - val_t *val) +char * +taperalgo2str( + taperalgo_t taperalgo) { - if (val->type != CONFTYPE_TAPERALGO) { - error("get_conftype_taperalgo: val.type is not CONFTYPE_TAPERALGO"); - /*NOTREACHED*/ - } - return val->v.i; + if(taperalgo == ALGO_FIRST) return "FIRST"; + if(taperalgo == ALGO_FIRSTFIT) return "FIRSTFIT"; + if(taperalgo == ALGO_LARGEST) return "LARGEST"; + if(taperalgo == ALGO_LARGESTFIT) return "LARGESTFIT"; + if(taperalgo == ALGO_SMALLEST) return "SMALLEST"; + if(taperalgo == ALGO_LAST) return "LAST"; + return "UNKNOWN"; } -int -get_conftype_priority( - val_t *val) +char * +config_dir_relative( + char *filename) { - if (val->type != CONFTYPE_PRIORITY) { - error("get_conftype_priority: val.type is not CONFTYPE_PRIORITY"); - /*NOTREACHED*/ + if (*filename == '/' || config_dir == NULL) { + return stralloc(filename); + } else { + if (config_dir[strlen(config_dir)-1] == '/') { + return vstralloc(config_dir, filename, NULL); + } else { + return vstralloc(config_dir, "/", filename, NULL); + } } - return val->v.i; } -exinclude_t -get_conftype_exinclude( - val_t *val) +static int +parm_key_info( + char *key, + conf_var_t **parm, + val_t **val) { - if (val->type != CONFTYPE_EXINCLUDE) { - error("get_conftype_exinclude: val.type is not CONFTYPE_EXINCLUDE"); - /*NOTREACHED*/ - } - return val->v.exinclude; -} + conf_var_t *np; + keytab_t *kt; + char *s; + char ch; + char *subsec_type; + char *subsec_name; + char *subsec_key; + tapetype_t *tp; + dumptype_t *dp; + interface_t *ip; + holdingdisk_t *hp; + int success = FALSE; + /* WARNING: assumes globals keytable and parsetable are set correctly. */ + assert(keytable != NULL); + assert(parsetable != NULL); -static void -read_block( - command_option_t *command_options, - t_conf_var *read_var, - keytab_t *keytab, - val_t *valarray, - char *prefix, - char *errormsg, - int read_brace, - void (*copy_function)(void)) -{ - t_conf_var *np; - int saved_conf_line_num; - int done; + /* make a copy we can stomp on */ + key = stralloc(key); - if(read_brace) { - get_conftoken(CONF_LBRACE); - get_conftoken(CONF_NL); + /* uppercase the key */ + s = key; + for (s = key; (ch = *s) != 0; s++) { + if(islower((int)ch)) + *s = (char)toupper(ch); } - done = 0; - do { - conf_line_num += 1; - get_conftoken(CONF_ANY); - switch(tok) { - case CONF_RBRACE: - done = 1; - break; - case CONF_NL: /* empty line */ - break; - case CONF_END: /* end of file */ - done = 1; - break; - case CONF_IDENT: - case CONF_STRING: - if(copy_function) - copy_function(); - else - conf_parserror("ident not expected"); - break; - default: - { - for(np = read_var; np->token != CONF_UNKNOWN; np++) - if(np->token == tok) break; + subsec_name = strchr(key, ':'); + if (subsec_name) { + subsec_type = key; - if(np->token == CONF_UNKNOWN) - conf_parserror(errormsg); - else { - np->read_function(np, &valarray[np->parm]); - if(np->validate) - np->validate(np, &valarray[np->parm]); - } - } - } - if(tok != CONF_NL && tok != CONF_END && tok != CONF_RBRACE) - get_conftoken(CONF_NL); - } while(!done); + *subsec_name = '\0'; + subsec_name++; - /* overwrite with command line option */ - saved_conf_line_num = conf_line_num; - command_overwrite(command_options, read_var, keytab, valarray, prefix); - conf_line_num = saved_conf_line_num; -} + subsec_key = strchr(subsec_name,':'); + if(!subsec_key) goto out; /* failure */ -void -command_overwrite( - command_option_t *command_options, - t_conf_var *overwrite_var, - keytab_t *keytab, - val_t *valarray, - char *prefix) -{ - t_conf_var *np; - keytab_t *kt; - char *myprefix; - command_option_t *command_option; - int duplicate; + *subsec_key = '\0'; + subsec_key++; + + /* If the keyword doesn't exist, there's no need to look up the + * subsection -- we know it's invalid */ + for(kt = keytable; kt->token != CONF_UNKNOWN; kt++) { + if(kt->keyword && strcmp(kt->keyword, subsec_key) == 0) + break; + } + if(kt->token == CONF_UNKNOWN) goto out; - if(!command_options) return; + /* Otherwise, figure out which kind of subsection we're dealing with, + * and parse against that. */ + if (strcmp(subsec_type, "TAPETYPE") == 0) { + tp = lookup_tapetype(subsec_name); + if (!tp) goto out; + for(np = tapetype_var; np->token != CONF_UNKNOWN; np++) { + if(np->token == kt->token) + break; + } + if (np->token == CONF_UNKNOWN) goto out; + + if (val) *val = &tp->value[np->parm]; + if (parm) *parm = np; + success = TRUE; + } else if (strcmp(subsec_type, "DUMPTYPE") == 0) { + dp = lookup_dumptype(subsec_name); + if (!dp) goto out; + for(np = dumptype_var; np->token != CONF_UNKNOWN; np++) { + if(np->token == kt->token) + break; + } + if (np->token == CONF_UNKNOWN) goto out; + + if (val) *val = &dp->value[np->parm]; + if (parm) *parm = np; + success = TRUE; + } else if (strcmp(subsec_type, "HOLDINGDISK") == 0) { + hp = lookup_holdingdisk(subsec_name); + if (!hp) goto out; + for(np = holding_var; np->token != CONF_UNKNOWN; np++) { + if(np->token == kt->token) + break; + } + if (np->token == CONF_UNKNOWN) goto out; + + if (val) *val = &hp->value[np->parm]; + if (parm) *parm = np; + success = TRUE; + } else if (strcmp(subsec_type, "INTERFACE") == 0) { + ip = lookup_interface(subsec_name); + if (!ip) goto out; + for(np = interface_var; np->token != CONF_UNKNOWN; np++) { + if(np->token == kt->token) + break; + } + if (np->token == CONF_UNKNOWN) goto out; - for(np = overwrite_var; np->token != CONF_UNKNOWN; np++) { - for(kt = keytab; kt->token != CONF_UNKNOWN; kt++) - if(kt->token == np->token) break; + if (val) *val = &ip->value[np->parm]; + if (parm) *parm = np; + success = TRUE; + } - if(kt->token == CONF_UNKNOWN) { - error("command_overwrite: invalid token"); - /* NOTREACHED */ + /* No delimiters -- we're referencing a global config parameter */ + } else { + /* look up the keyword */ + for(kt = keytable; kt->token != CONF_UNKNOWN; kt++) { + if(kt->keyword && strcmp(kt->keyword, key) == 0) + break; } + if(kt->token == CONF_UNKNOWN) goto out; - for(command_option = command_options; command_option->name != NULL; - command_option++) { - myprefix = stralloc2(prefix, kt->keyword); - if(strcasecmp(myprefix, command_option->name) == 0) { - duplicate = 0; - if (command_option->used == 0 && - valarray[np->parm].seen == -2) { - duplicate = 1; - } - command_option->used = 1; - valarray[np->parm].seen = -2; - if(np->type == CONFTYPE_STRING && - command_option->value[0] != '"') { - conf_line = vstralloc("\"", command_option->value, "\"", - NULL); - } - else { - conf_line = stralloc(command_option->value); - } - conf_char = conf_line; - token_pushed = 0; - conf_line_num = -2; - np->read_function(np, &valarray[np->parm]); - amfree(conf_line); - conf_line = conf_char = NULL; - - if (np->validate) - np->validate(np, &valarray[np->parm]); - if (duplicate == 1) { - fprintf(stderr,"Duplicate %s option, using %s\n", - command_option->name, command_option->value); - } - } - amfree(myprefix); + /* and then look that up in the parse table */ + for(np = parsetable; np->token != CONF_UNKNOWN; np++) { + if(np->token == kt->token) + break; } + if(np->token == CONF_UNKNOWN) goto out; + + if (val) *val = &conf_data[np->parm]; + if (parm) *parm = np; + success = TRUE; } + +out: + amfree(key); + return success; } -void -free_new_argv( - int new_argc, - char **new_argv) +gint64 +find_multiplier( + char * casestr) { - int i; - for(i=0; ikeyword != NULL; + table_entry ++) { + if (strcmp(casestr, table_entry->keyword) == 0) { + g_free(str); + switch (table_entry->token) { + case CONF_MULT1K: + return 1024; + case CONF_MULT1M: + return 1024*1024; + case CONF_MULT1G: + return 1024*1024*1024; + case CONF_MULT7: + return 7; + case CONF_AMINFINITY: + return G_MAXINT64; + case CONF_MULT1: + case CONF_IDENT: + return 1; + default: + /* Should not happen. */ + return 0; + } + } + } + + /* None found; this is an error. */ + g_free(str); + return 0; } -ssize_t -getconf_readblocksize(void) -{ - tapetype_t *tape; - char *conf_tapetype; +/* + * Error Handling Implementaiton + */ + +static void print_parse_problem(const char * format, va_list argp) { + const char *xlated_fmt = gettext(format); - if (conffile_init == 1) { - conf_tapetype = getconf_str(CNF_TAPETYPE); + if(current_line) + g_fprintf(stderr, _("argument \"%s\": "), current_line); + else if (current_filename && current_line_num > 0) + g_fprintf(stderr, "\"%s\", line %d: ", current_filename, current_line_num); + else + g_fprintf(stderr, _("parse error: ")); + + g_vfprintf(stderr, xlated_fmt, argp); + fputc('\n', stderr); +} - if (!conf_tapetype || strlen(conf_tapetype) == 0) - return MAX_TAPE_BLOCK_KB; +printf_arglist_function(void conf_parserror, const char *, format) +{ + va_list argp; + + arglist_start(argp, format); + print_parse_problem(format, argp); + arglist_end(argp); - tape = lookup_tapetype(conf_tapetype); - if (!tape) - return MAX_TAPE_BLOCK_KB; - return tapetype_get_readblocksize(tape); - } + got_parserror = TRUE; +} - return MAX_TAPE_BLOCK_KB; +printf_arglist_function(void conf_parswarn, const char *, format) { + va_list argp; + + arglist_start(argp, format); + print_parse_problem(format, argp); + arglist_end(argp); }