+ assert(devconf != NULL);
+ assert(key < CHANGER_CONFIG_CHANGER_CONFIG);
+ return &devconf->value[key];
+}
+
+char *
+changer_config_name(
+ changer_config_t *devconf)
+{
+ assert(devconf != NULL);
+ return devconf->name;
+}
+
+long int
+getconf_unit_divisor(void)
+{
+ return unit_divisor;
+}
+
+/*
+ * Command-line Handling Implementation
+ */
+
+config_overrides_t *
+new_config_overrides(
+ int size_estimate)
+{
+ config_overrides_t *co;
+
+ if (size_estimate <= 0)
+ size_estimate = 10;
+
+ 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_overrides(
+ config_overrides_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_override(
+ config_overrides_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 */
+ }
+ }
+
+ co->ovr[co->n_used].key = stralloc(key);
+ co->ovr[co->n_used].value = stralloc(value);
+ co->n_used++;
+}
+
+void
+add_config_override_opt(
+ config_overrides_t *co,
+ char *optarg)
+{
+ char *value;
+ assert(optarg != NULL);
+
+ value = strchr(optarg, '=');
+ if (value == NULL) {
+ error(_("Must specify a value for %s."), optarg);
+ /* NOTREACHED */
+ }
+
+ *value = '\0';
+ add_config_override(co, optarg, value+1);
+ *value = '=';
+}
+
+config_overrides_t *
+extract_commandline_config_overrides(
+ int *argc,
+ char ***argv)
+{
+ int i, j, moveup;
+ config_overrides_t *co = new_config_overrides(*argc/2);
+
+ i = 0;
+ while (i<*argc) {
+ if(strncmp((*argv)[i],"-o",2) == 0) {
+ if(strlen((*argv)[i]) > 2) {
+ add_config_override_opt(co, (*argv)[i]+2);
+ moveup = 1;
+ }
+ else {
+ if (i+1 >= *argc) error(_("expect something after -o"));
+ add_config_override_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++;
+ }
+ }
+
+ return co;
+}
+
+void
+set_config_overrides(
+ config_overrides_t *co)
+{
+ int i;
+
+ config_overrides = co;
+
+ for (i = 0; i < co->n_used; i++) {
+ g_debug("config_overrides: %s %s", co->ovr[i].key, co->ovr[i].value);
+ }
+
+ return;
+}
+
+static cfgerr_level_t
+apply_config_overrides(
+ config_overrides_t *co,
+ char *key_ovr)
+{
+ int i;
+
+ if(!co) return cfgerr_level;
+ assert(keytable != NULL);
+ assert(parsetable != NULL);
+
+ 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;
+
+ if (key_ovr && strncasecmp(key_ovr, key, strlen(key_ovr)) != 0) {
+ continue;
+ }
+
+ if (!parm_key_info(key, &key_parm, &key_val)) {
+ /* not an error, only default config is loaded */
+ continue;
+ }
+
+ /* now set up a fake line and use the relevant read_function to
+ * parse it. This is sneaky! */
+ if (key_parm->type == CONFTYPE_STR) {
+ current_line = quote_string_always(value);
+ } else {
+ current_line = stralloc(value);
+ }
+
+ current_char = current_line;
+ token_pushed = 0;
+ current_line_num = -2;
+ allow_overwrites = 1;
+ co->ovr[i].applied = TRUE;
+
+ key_parm->read_function(key_parm, key_val);
+ if ((key_parm)->validate_function)
+ key_parm->validate_function(key_parm, key_val);
+
+ amfree(current_line);
+ current_char = NULL;
+ }
+
+ return cfgerr_level;
+}
+
+/*
+ * val_t Management Implementation
+ */
+
+int
+val_t_to_int(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_INT) {
+ error(_("val_t_to_int: val.type is not CONFTYPE_INT"));
+ /*NOTREACHED*/
+ }
+ return val_t__int(val);
+}
+
+gint64
+val_t_to_int64(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_INT64) {
+ error(_("val_t_to_int64: val.type is not CONFTYPE_INT64"));
+ /*NOTREACHED*/
+ }
+ return val_t__int64(val);
+}
+
+float
+val_t_to_real(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_REAL) {
+ error(_("val_t_to_real: val.type is not CONFTYPE_REAL"));
+ /*NOTREACHED*/
+ }
+ return val_t__real(val);
+}
+
+char *
+val_t_to_str(
+ val_t *val)
+{
+ assert(config_initialized);
+ /* 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);
+}
+
+char *
+val_t_to_ident(
+ val_t *val)
+{
+ assert(config_initialized);
+ /* 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);
+}
+
+identlist_t
+val_t_to_identlist(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_IDENTLIST) {
+ error(_("val_t_to_ident: val.type is not CONFTYPE_IDENTLIST"));
+ /*NOTREACHED*/
+ }
+ return val_t__identlist(val);
+}
+
+time_t
+val_t_to_time(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_TIME) {
+ error(_("val_t_to_time: val.type is not CONFTYPE_TIME"));
+ /*NOTREACHED*/
+ }
+ return val_t__time(val);
+}
+
+ssize_t
+val_t_to_size(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_SIZE) {
+ error(_("val_t_to_size: val.type is not CONFTYPE_SIZE"));
+ /*NOTREACHED*/
+ }
+ return val_t__size(val);
+}
+
+int
+val_t_to_boolean(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_BOOLEAN) {
+ error(_("val_t_to_bool: val.type is not CONFTYPE_BOOLEAN"));
+ /*NOTREACHED*/
+ }
+ return val_t__boolean(val);
+}
+
+comp_t
+val_t_to_compress(
+ val_t *val)
+{
+ assert(config_initialized);
+ 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)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_ENCRYPT) {
+ error(_("val_t_to_encrypt: val.type is not CONFTYPE_ENCRYPT"));
+ /*NOTREACHED*/
+ }
+ return val_t__encrypt(val);
+}
+
+part_cache_type_t
+val_t_to_part_cache_type(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_PART_CACHE_TYPE) {
+ error(_("val_t_to_part_cache_type: val.type is not CONFTYPE_PART_CACHE_TYPE"));
+ /*NOTREACHED*/
+ }
+ return val_t__part_cache_type(val);
+}
+
+recovery_limit_t *
+val_t_to_recovery_limit(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_RECOVERY_LIMIT) {
+ error(_("val_t_to_recovery_limit: val.type is not CONFTYPE_RECOVERY_LIMIT"));
+ /*NOTREACHED*/
+ }
+ return &val_t__recovery_limit(val);
+}
+
+dump_holdingdisk_t
+val_t_to_holding(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_HOLDING) {
+ error(_("val_t_to_hold: val.type is not CONFTYPE_HOLDING"));
+ /*NOTREACHED*/
+ }
+ return val_t__holding(val);
+}
+
+estimatelist_t
+val_t_to_estimatelist(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_ESTIMATELIST) {
+ error(_("val_t_to_estimatelist: val.type is not CONFTYPE_ESTIMATELIST"));
+ /*NOTREACHED*/
+ }
+ return val_t__estimatelist(val);
+}
+
+strategy_t
+val_t_to_strategy(
+ val_t *val)
+{
+ assert(config_initialized);
+ 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)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_TAPERALGO) {
+ error(_("val_t_to_taperalgo: val.type is not CONFTYPE_TAPERALGO"));
+ /*NOTREACHED*/
+ }
+ return val_t__taperalgo(val);
+}
+
+send_amreport_t
+val_t_to_send_amreport(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_SEND_AMREPORT_ON) {
+ error(_("val_t_to_send_amreport: val.type is not CONFTYPE_SEND_AMREPORT_ON"));
+ /*NOTREACHED*/
+ }
+ return val_t__send_amreport(val);
+}
+
+data_path_t
+val_t_to_data_path(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_DATA_PATH) {
+ error(_("val_t_to_data_path: val.type is not CONFTYPE_DATA_PATH"));
+ /*NOTREACHED*/
+ }
+ return val_t__data_path(val);
+}
+
+int
+val_t_to_priority(
+ val_t *val)
+{
+ assert(config_initialized);
+ 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)
+{
+ assert(config_initialized);
+ 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)
+{
+ assert(config_initialized);
+ 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)
+{
+ assert(config_initialized);
+ 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)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_PROPLIST) {
+ error(_("val_t_to_proplist: val.type is not CONFTYPE_PROPLIST"));
+ /*NOTREACHED*/
+ }
+ return val_t__proplist(val);
+}
+
+autolabel_t
+val_t_to_autolabel(
+ val_t *val)
+{
+ assert(config_initialized);
+ if (val->type != CONFTYPE_AUTOLABEL) {
+ error(_("val_t_to_autolabel: val.type is not CONFTYPE_AUTOLABEL"));
+ /*NOTREACHED*/
+ }
+ return val_t__autolabel(val);
+}
+
+static void
+merge_val_t(
+ val_t *valdst,
+ val_t *valsrc)
+{
+ if (valsrc->type == CONFTYPE_PROPLIST) {
+ if (valsrc->v.proplist) {
+ if (valdst->v.proplist == NULL) {
+ valdst->v.proplist = g_hash_table_new_full(g_str_amanda_hash,
+ g_str_amanda_equal,
+ &g_free,
+ &free_property_t);
+ g_hash_table_foreach(valsrc->v.proplist,
+ ©_proplist_foreach_fn,
+ valdst->v.proplist);
+ } else {
+ g_hash_table_foreach(valsrc->v.proplist,
+ &merge_proplist_foreach_fn,
+ valdst->v.proplist);
+ }
+ }
+ } else if (valsrc->type == CONFTYPE_IDENTLIST) {
+ if (valsrc->v.identlist) {
+ identlist_t il;
+ for (il = valsrc->v.identlist; il != NULL; il = il->next) {
+ valdst->v.identlist = g_slist_append(valdst->v.identlist,
+ stralloc((char *)il->data));
+ }
+ }
+ } else {
+ free_val_t(valdst);
+ copy_val_t(valdst, valsrc);
+ }
+}
+
+static void
+copy_val_t(
+ val_t *valdst,
+ val_t *valsrc)
+{
+ GSList *ia;
+
+ if(valsrc->seen.linenum) {
+ valdst->type = valsrc->type;
+ valdst->seen = valsrc->seen;
+ switch(valsrc->type) {
+ case CONFTYPE_INT:
+ case CONFTYPE_BOOLEAN:
+ case CONFTYPE_COMPRESS:
+ case CONFTYPE_ENCRYPT:
+ case CONFTYPE_HOLDING:
+ case CONFTYPE_EXECUTE_ON:
+ case CONFTYPE_EXECUTE_WHERE:
+ case CONFTYPE_SEND_AMREPORT_ON:
+ case CONFTYPE_DATA_PATH:
+ case CONFTYPE_STRATEGY:
+ case CONFTYPE_TAPERALGO:
+ case CONFTYPE_PRIORITY:
+ case CONFTYPE_PART_CACHE_TYPE:
+ valdst->v.i = valsrc->v.i;
+ break;
+
+ case CONFTYPE_SIZE:
+ valdst->v.size = valsrc->v.size;
+ break;
+
+ case CONFTYPE_INT64:
+ valdst->v.int64 = valsrc->v.int64;
+ break;
+
+ case CONFTYPE_REAL:
+ valdst->v.r = valsrc->v.r;
+ break;
+
+ case CONFTYPE_RATE:
+ valdst->v.rate[0] = valsrc->v.rate[0];
+ valdst->v.rate[1] = valsrc->v.rate[1];
+ break;
+
+ case CONFTYPE_IDENT:
+ case CONFTYPE_STR:
+ valdst->v.s = stralloc(valsrc->v.s);
+ break;
+
+ case CONFTYPE_IDENTLIST:
+ valdst->v.identlist = NULL;
+ for (ia = valsrc->v.identlist; ia != NULL; ia = ia->next) {
+ valdst->v.identlist = g_slist_append(valdst->v.identlist,
+ stralloc(ia->data));
+ }
+ break;
+
+ case CONFTYPE_RECOVERY_LIMIT:
+ valdst->v.recovery_limit = valsrc->v.recovery_limit;
+ valdst->v.recovery_limit.match_pats = NULL;
+ for (ia = valsrc->v.recovery_limit.match_pats; ia != NULL; ia = ia->next) {
+ valdst->v.recovery_limit.match_pats =
+ g_slist_append(valdst->v.recovery_limit.match_pats, g_strdup(ia->data));
+ }
+ break;
+
+ case CONFTYPE_TIME:
+ valdst->v.t = valsrc->v.t;
+ break;
+
+ case CONFTYPE_ESTIMATELIST: {
+ estimatelist_t estimates = valsrc->v.estimatelist;
+ estimatelist_t dst_estimates = NULL;
+ while (estimates != NULL) {
+ dst_estimates = g_slist_append(dst_estimates, estimates->data);
+ estimates = estimates->next;
+ }
+ valdst->v.estimatelist = dst_estimates;
+ break;
+ }
+
+ case CONFTYPE_EXINCLUDE:
+ valdst->v.exinclude.optional = valsrc->v.exinclude.optional;
+ valdst->v.exinclude.sl_list = duplicate_sl(valsrc->v.exinclude.sl_list);
+ valdst->v.exinclude.sl_file = duplicate_sl(valsrc->v.exinclude.sl_file);
+ break;
+
+ case CONFTYPE_INTRANGE:
+ valdst->v.intrange[0] = valsrc->v.intrange[0];
+ valdst->v.intrange[1] = valsrc->v.intrange[1];
+ break;
+
+ case CONFTYPE_PROPLIST:
+ if (valsrc->v.proplist) {
+ valdst->v.proplist = g_hash_table_new_full(g_str_amanda_hash,
+ g_str_amanda_equal,
+ &g_free,
+ &free_property_t);
+
+ g_hash_table_foreach(valsrc->v.proplist,
+ ©_proplist_foreach_fn,
+ valdst->v.proplist);
+ } else {
+ valdst->v.proplist = NULL;
+ }
+ break;
+
+ case CONFTYPE_APPLICATION:
+ valdst->v.s = stralloc(valsrc->v.s);
+ break;
+
+ case CONFTYPE_AUTOLABEL:
+ valdst->v.autolabel.template = stralloc(valsrc->v.autolabel.template);
+ valdst->v.autolabel.autolabel = valsrc->v.autolabel.autolabel;
+ break;
+ }
+ }
+}
+
+static void
+merge_proplist_foreach_fn(
+ gpointer key_p,
+ gpointer value_p,
+ gpointer user_data_p)
+{
+ char *property_s = key_p;
+ property_t *property = value_p;
+ proplist_t proplist = user_data_p;
+ GSList *elem = NULL;
+ int new_prop = 0;
+ property_t *new_property = g_hash_table_lookup(proplist, property_s);
+ if (new_property && !property->append) {
+ g_hash_table_remove(proplist, property_s);
+ new_property = NULL;
+ }
+ if (!new_property) {
+ new_property = malloc(sizeof(property_t));
+ new_property->append = property->append;
+ new_property->priority = property->priority;
+ new_property->values = NULL;
+ new_prop = 1;
+ }
+
+ for(elem = property->values;elem != NULL; elem=elem->next) {
+ new_property->values = g_slist_append(new_property->values,
+ stralloc(elem->data));
+ }
+ if (new_prop)
+ g_hash_table_insert(proplist, stralloc(property_s), new_property);
+}
+
+static void
+copy_proplist_foreach_fn(
+ gpointer key_p,
+ gpointer value_p,
+ gpointer user_data_p)
+{
+ char *property_s = key_p;
+ property_t *property = value_p;
+ proplist_t proplist = user_data_p;
+ GSList *elem = NULL;
+ property_t *new_property = malloc(sizeof(property_t));
+ new_property->append = property->append;
+ new_property->priority = property->priority;
+ new_property->values = NULL;
+
+ for(elem = property->values;elem != NULL; elem=elem->next) {
+ new_property->values = g_slist_append(new_property->values,
+ stralloc(elem->data));
+ }
+ g_hash_table_insert(proplist, stralloc(property_s), new_property);
+}
+
+static void
+free_val_t(
+ val_t *val)
+{
+ switch(val->type) {
+ case CONFTYPE_INT:
+ case CONFTYPE_BOOLEAN:
+ case CONFTYPE_COMPRESS:
+ case CONFTYPE_ENCRYPT:
+ case CONFTYPE_HOLDING:
+ case CONFTYPE_EXECUTE_WHERE:
+ case CONFTYPE_EXECUTE_ON:
+ case CONFTYPE_SEND_AMREPORT_ON:
+ case CONFTYPE_DATA_PATH:
+ case CONFTYPE_STRATEGY:
+ case CONFTYPE_SIZE:
+ case CONFTYPE_TAPERALGO:
+ case CONFTYPE_PRIORITY:
+ case CONFTYPE_INT64:
+ case CONFTYPE_REAL:
+ case CONFTYPE_RATE:
+ case CONFTYPE_INTRANGE:
+ case CONFTYPE_PART_CACHE_TYPE:
+ break;
+
+ case CONFTYPE_IDENT:
+ case CONFTYPE_STR:
+ case CONFTYPE_APPLICATION:
+ amfree(val->v.s);
+ break;
+
+ case CONFTYPE_IDENTLIST:
+ g_slist_free_full(val->v.identlist);
+ break;
+
+ case CONFTYPE_RECOVERY_LIMIT:
+ g_slist_free_full(val->v.recovery_limit.match_pats);
+ break;
+
+ case CONFTYPE_TIME:
+ break;
+
+ case CONFTYPE_ESTIMATELIST:
+ g_slist_free(val->v.estimatelist);
+ break;
+
+ case CONFTYPE_EXINCLUDE:
+ 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;
+
+ case CONFTYPE_AUTOLABEL:
+ amfree(val->v.autolabel.template);
+ break;
+ }
+ val->seen.linenum = 0;
+ val->seen.filename = NULL;
+}
+
+/*
+ * Utilities Implementation
+ */
+
+char *
+generic_get_security_conf(
+ char *string,
+ void *arg)
+{
+ 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);
+}
+
+char *
+generic_client_get_security_conf(
+ char * string,
+ void * arg)
+{
+ (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, "client_port")==0) {
+ return(getconf_str(CNF_CLIENT_PORT));
+ } 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 *hd;
+ GSList *hp;
+ application_t *ap;
+ pp_script_t *ps;
+ device_config_t *dc;
+ changer_config_t *cc;
+ 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) {
+ hd = hp->data;
+ g_printf("\nDEFINE HOLDINGDISK %s {\n", hd->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, &hd->value[i]);
+ }
+ g_printf("}\n");
+ }
+
+ for(tp = tapelist; tp != NULL; tp = tp->next) {
+ if(tp->seen.linenum == -1)
+ prefix = "#";
+ else
+ prefix = "";
+ g_printf("\n%sDEFINE TAPETYPE %s {\n", prefix, 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, prefix, " %-9s ", kt, &tp->value[i]);
+ }
+ g_printf("%s}\n", prefix);
+ }
+
+ for(dp = dumplist; dp != NULL; dp = dp->next) {
+ if (strncmp_const(dp->name, "custom(") != 0) { /* don't dump disklist-derived dumptypes */
+ if(dp->seen.linenum == -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) {
+ seen_t *netusage_seen = &val_t__seen(getconf(CNF_NETUSAGE));
+ if (ip->seen.linenum == netusage_seen->linenum &&
+ ip->seen.filename && netusage_seen->filename &&
+ 0 == strcmp(ip->seen.filename, netusage_seen->filename))
+ 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);
+ }
+
+ for(ap = application_list; ap != NULL; ap = ap->next) {
+ if(strcmp(ap->name,"default") == 0)
+ prefix = "#";
+ else
+ prefix = "";
+ g_printf("\n%sDEFINE APPLICATION %s {\n", prefix, ap->name);
+ for(i=0; i < APPLICATION_APPLICATION; i++) {
+ for(np=application_var; np->token != CONF_UNKNOWN; np++)
+ if(np->parm == i) break;
+ if(np->token == CONF_UNKNOWN)
+ error(_("application bad value"));
+
+ for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
+ if(kt->token == np->token) break;
+ if(kt->token == CONF_UNKNOWN)
+ error(_("application bad token"));
+
+ val_t_print_token(stdout, prefix, " %-19s ", kt, &ap->value[i]);
+ }
+ g_printf("%s}\n",prefix);
+ }
+
+ for(ps = pp_script_list; ps != NULL; ps = ps->next) {
+ if(strcmp(ps->name,"default") == 0)
+ prefix = "#";
+ else
+ prefix = "";
+ g_printf("\n%sDEFINE SCRIPT %s {\n", prefix, ps->name);
+ for(i=0; i < PP_SCRIPT_PP_SCRIPT; i++) {
+ for(np=pp_script_var; np->token != CONF_UNKNOWN; np++)
+ if(np->parm == i) break;
+ if(np->token == CONF_UNKNOWN)
+ error(_("script bad value"));
+
+ for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
+ if(kt->token == np->token) break;
+ if(kt->token == CONF_UNKNOWN)
+ error(_("script bad token"));
+
+ val_t_print_token(stdout, prefix, " %-19s ", kt, &ps->value[i]);
+ }
+ g_printf("%s}\n",prefix);
+ }
+
+ for(dc = device_config_list; dc != NULL; dc = dc->next) {
+ prefix = "";
+ g_printf("\n%sDEFINE DEVICE %s {\n", prefix, dc->name);
+ for(i=0; i < DEVICE_CONFIG_DEVICE_CONFIG; i++) {
+ for(np=device_config_var; np->token != CONF_UNKNOWN; np++)
+ if(np->parm == i) break;
+ if(np->token == CONF_UNKNOWN)
+ error(_("device bad value"));
+
+ for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
+ if(kt->token == np->token) break;
+ if(kt->token == CONF_UNKNOWN)
+ error(_("device bad token"));
+
+ val_t_print_token(stdout, prefix, " %-19s ", kt, &dc->value[i]);
+ }
+ g_printf("%s}\n",prefix);
+ }
+
+ for(cc = changer_config_list; cc != NULL; cc = cc->next) {
+ prefix = "";
+ g_printf("\n%sDEFINE CHANGER %s {\n", prefix, cc->name);
+ for(i=0; i < CHANGER_CONFIG_CHANGER_CONFIG; i++) {
+ for(np=changer_config_var; np->token != CONF_UNKNOWN; np++)
+ if(np->parm == i) break;
+ if(np->token == CONF_UNKNOWN)
+ error(_("changer bad value"));
+
+ for(kt = server_keytab; kt->token != CONF_UNKNOWN; kt++)
+ if(kt->token == np->token) break;
+ if(kt->token == CONF_UNKNOWN)
+ error(_("changer bad token"));
+
+ val_t_print_token(stdout, prefix, " %-19s ", kt, &cc->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 **buf;
+ buf = malloc(3*SIZEOF(char *));
+ buf[0] = NULL;
+ buf[1] = NULL;
+ buf[2] = NULL;
+
+ switch(val->type) {
+ case CONFTYPE_INT:
+ buf[0] = vstrallocf("%d", val_t__int(val));
+ break;
+
+ case CONFTYPE_SIZE:
+ buf[0] = vstrallocf("%zd", (ssize_t)val_t__size(val));
+ break;
+
+ case CONFTYPE_INT64:
+ buf[0] = vstrallocf("%lld", (long long)val_t__int64(val));
+ break;
+
+ case CONFTYPE_REAL:
+ buf[0] = vstrallocf("%0.5f", val_t__real(val));
+ break;
+
+ case CONFTYPE_RATE:
+ buf[0] = vstrallocf("%0.5f %0.5f", val_t__rate(val)[0], val_t__rate(val)[1]);
+ break;
+
+ case CONFTYPE_INTRANGE:
+ buf[0] = vstrallocf("%d,%d", val_t__intrange(val)[0], val_t__intrange(val)[1]);
+ break;
+
+ case CONFTYPE_IDENT:
+ if(val->v.s) {
+ buf[0] = stralloc(val->v.s);
+ } else {
+ buf[0] = stralloc("");
+ }
+ break;
+
+ case CONFTYPE_IDENTLIST:
+ {
+ GSList *ia;
+ int first = 1;
+
+ buf[0] = NULL;
+ for (ia = val->v.identlist; ia != NULL; ia = ia->next) {
+ if (first) {
+ buf[0] = stralloc(ia->data);
+ first = 0;
+ } else {
+ strappend(buf[0], " ");
+ strappend(buf[0], ia->data);
+ }
+ }
+ }
+ break;
+
+ case CONFTYPE_STR:
+ if(str_need_quote) {
+ if(val->v.s) {
+ buf[0] = quote_string_always(val->v.s);
+ } else {
+ buf[0] = stralloc("\"\"");
+ }
+ } else {
+ if(val->v.s) {
+ buf[0] = stralloc(val->v.s);
+ } else {
+ buf[0] = stralloc("");
+ }
+ }
+ break;
+
+ case CONFTYPE_AUTOLABEL:
+ {
+ buf[0] = quote_string_always(val->v.autolabel.template);
+ if (val->v.autolabel.autolabel & AL_OTHER_CONFIG) {
+ buf[0] = vstrextend(&buf[0], " OTHER-CONFIG", NULL);
+ }
+ if (val->v.autolabel.autolabel & AL_NON_AMANDA) {
+ buf[0] = vstrextend(&buf[0], " NON-AMANDA", NULL);
+ }
+ if (val->v.autolabel.autolabel & AL_VOLUME_ERROR) {
+ buf[0] = vstrextend(&buf[0], " VOLUME-ERROR", NULL);
+ }
+ if (val->v.autolabel.autolabel & AL_EMPTY) {
+ buf[0] = vstrextend(&buf[0], " EMPTY", NULL);
+ }
+ }
+ break;
+
+ case CONFTYPE_TIME:
+ buf[0] = vstrallocf("%2d%02d",
+ (int)val_t__time(val)/100, (int)val_t__time(val) % 100);
+ break;
+
+ case CONFTYPE_EXINCLUDE: {
+ buf[0] = exinclude_display_str(val, 0);
+ buf[1] = exinclude_display_str(val, 1);
+ break;
+ }
+
+ case CONFTYPE_BOOLEAN:
+ if(val_t__boolean(val))
+ buf[0] = stralloc("yes");
+ else
+ buf[0] = stralloc("no");
+ break;
+
+ case CONFTYPE_STRATEGY:
+ switch(val_t__strategy(val)) {
+ case DS_SKIP:
+ buf[0] = vstrallocf("SKIP");
+ break;
+
+ case DS_STANDARD:
+ buf[0] = vstrallocf("STANDARD");
+ break;
+
+ case DS_NOFULL:
+ buf[0] = vstrallocf("NOFULL");
+ break;
+
+ case DS_NOINC:
+ buf[0] = vstrallocf("NOINC");
+ break;
+
+ case DS_HANOI:
+ buf[0] = vstrallocf("HANOI");
+ break;
+
+ case DS_INCRONLY:
+ buf[0] = vstrallocf("INCRONLY");
+ break;
+ }
+ break;
+
+ case CONFTYPE_COMPRESS:
+ switch(val_t__compress(val)) {
+ case COMP_NONE:
+ buf[0] = vstrallocf("NONE");
+ break;
+
+ case COMP_FAST:
+ buf[0] = vstrallocf("CLIENT FAST");
+ break;
+
+ case COMP_BEST:
+ buf[0] = vstrallocf("CLIENT BEST");
+ break;
+
+ case COMP_CUST:
+ buf[0] = vstrallocf("CLIENT CUSTOM");
+ break;
+
+ case COMP_SERVER_FAST:
+ buf[0] = vstrallocf("SERVER FAST");
+ break;
+
+ case COMP_SERVER_BEST:
+ buf[0] = vstrallocf("SERVER BEST");
+ break;
+
+ case COMP_SERVER_CUST:
+ buf[0] = vstrallocf("SERVER CUSTOM");
+ break;
+ }
+ break;
+
+ case CONFTYPE_ESTIMATELIST: {
+ estimatelist_t es = val_t__estimatelist(val);
+ buf[0] = stralloc("");
+ while (es) {
+ switch((estimate_t)GPOINTER_TO_INT(es->data)) {
+ case ES_CLIENT:
+ strappend(buf[0], "CLIENT");
+ break;
+
+ case ES_SERVER:
+ strappend(buf[0], "SERVER");
+ break;
+
+ case ES_CALCSIZE:
+ strappend(buf[0], "CALCSIZE");
+ break;
+
+ case ES_ES:
+ break;
+ }
+ es = es->next;
+ if (es)
+ strappend(buf[0], " ");
+ }
+ break;
+ }
+
+ case CONFTYPE_EXECUTE_WHERE:
+ switch(val->v.i) {
+ case ES_CLIENT:
+ buf[0] = vstrallocf("CLIENT");
+ break;
+
+ case ES_SERVER:
+ buf[0] = vstrallocf("SERVER");
+ break;
+ }
+ break;
+
+ case CONFTYPE_SEND_AMREPORT_ON:
+ switch(val->v.i) {
+ case SEND_AMREPORT_ALL:
+ buf[0] = vstrallocf("ALL");
+ break;
+ case SEND_AMREPORT_STRANGE:
+ buf[0] = vstrallocf("STRANGE");
+ break;
+ case SEND_AMREPORT_ERROR:
+ buf[0] = vstrallocf("ERROR");
+ break;
+ case SEND_AMREPORT_NEVER:
+ buf[0] = vstrallocf("NEVER");
+ break;
+ }
+ break;
+
+ case CONFTYPE_DATA_PATH:
+ buf[0] = g_strdup(data_path_to_string(val->v.i));
+ break;
+
+ case CONFTYPE_ENCRYPT:
+ switch(val_t__encrypt(val)) {
+ case ENCRYPT_NONE:
+ buf[0] = vstrallocf("NONE");
+ break;
+
+ case ENCRYPT_CUST:
+ buf[0] = vstrallocf("CLIENT");
+ break;
+
+ case ENCRYPT_SERV_CUST:
+ buf[0] = vstrallocf("SERVER");
+ break;
+ }
+ break;
+
+ case CONFTYPE_PART_CACHE_TYPE:
+ switch(val_t__part_cache_type(val)) {
+ case PART_CACHE_TYPE_NONE:
+ buf[0] = vstrallocf("NONE");
+ break;
+
+ case PART_CACHE_TYPE_DISK:
+ buf[0] = vstrallocf("DISK");
+ break;
+
+ case PART_CACHE_TYPE_MEMORY:
+ buf[0] = vstrallocf("MEMORY");
+ break;
+ }
+ break;
+
+ case CONFTYPE_RECOVERY_LIMIT: {
+ GSList *iter = val_t__recovery_limit(val).match_pats;
+
+ if(val_t__recovery_limit(val).same_host)
+ buf[0] = stralloc("SAME-HOST ");
+ else
+ buf[0] = stralloc("");
+
+ while (iter) {
+ strappend(buf[0], (char *)iter->data);
+ strappend(buf[0], " ");
+ iter = iter->next;
+ }
+ break;
+ }
+
+ case CONFTYPE_HOLDING:
+ switch(val_t__holding(val)) {
+ case HOLD_NEVER:
+ buf[0] = vstrallocf("NEVER");
+ break;
+
+ case HOLD_AUTO:
+ buf[0] = vstrallocf("AUTO");
+ break;
+
+ case HOLD_REQUIRED:
+ buf[0] = vstrallocf("REQUIRED");
+ break;
+ }
+ break;
+
+ case CONFTYPE_TAPERALGO:
+ buf[0] = vstrallocf("%s", taperalgo2str(val_t__taperalgo(val)));
+ break;
+
+ case CONFTYPE_PRIORITY:
+ switch(val_t__priority(val)) {
+ case 0:
+ buf[0] = vstrallocf("LOW");
+ break;
+
+ case 1:
+ buf[0] = vstrallocf("MEDIUM");
+ break;
+
+ case 2:
+ buf[0] = vstrallocf("HIGH");
+ break;
+ }
+ break;
+
+ case CONFTYPE_PROPLIST: {
+ int nb_property;
+ char **mybuf;
+
+ 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;
+ }
+
+ case CONFTYPE_APPLICATION: {
+ if (val->v.s) {
+ buf[0] = quote_string_always(val->v.s);
+ } else {
+ buf[0] = stralloc("");
+ }
+ break;
+ }
+
+ case CONFTYPE_EXECUTE_ON:
+ buf[0] = stralloc("");
+ if (val->v.i != 0) {
+ char *sep = "";
+ if (val->v.i & EXECUTE_ON_PRE_DLE_AMCHECK) {
+ buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-AMCHECK", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_PRE_HOST_AMCHECK) {
+ buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-AMCHECK", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_POST_DLE_AMCHECK) {
+ buf[0] = vstrextend(&buf[0], sep, "POST-DLE-AMCHECK", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_POST_HOST_AMCHECK) {
+ buf[0] = vstrextend(&buf[0], sep, "POST-HOST-AMCHECK", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_PRE_DLE_ESTIMATE) {
+ buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-ESTIMATE", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_PRE_HOST_ESTIMATE) {
+ buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-ESTIMATE", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_POST_DLE_ESTIMATE) {
+ buf[0] = vstrextend(&buf[0], sep, "POST-DLE-ESTIMATE", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_POST_HOST_ESTIMATE) {
+ buf[0] = vstrextend(&buf[0], sep, "POST-HOST-ESTIMATE", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_PRE_DLE_BACKUP) {
+ buf[0] = vstrextend(&buf[0], sep, "PRE-DLE-BACKUP", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_PRE_HOST_BACKUP) {
+ buf[0] = vstrextend(&buf[0], sep, "PRE-HOST-BACKUP", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_POST_DLE_BACKUP) {
+ buf[0] = vstrextend(&buf[0], sep, "POST-DLE-BACKUP", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_POST_HOST_BACKUP) {
+ buf[0] = vstrextend(&buf[0], sep, "POST-HOST-BACKUP", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_PRE_RECOVER) {
+ buf[0] = vstrextend(&buf[0], sep, "PRE-RECOVER", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_POST_RECOVER) {
+ buf[0] = vstrextend(&buf[0], sep, "POST-RECOVER", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_PRE_LEVEL_RECOVER) {
+ buf[0] = vstrextend(&buf[0], sep, "PRE-LEVEL-RECOVER", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_POST_LEVEL_RECOVER) {
+ buf[0] = vstrextend(&buf[0], sep, "POST-LEVEL-RECOVER", NULL);
+ sep = ", ";
+ }
+ if (val->v.i & EXECUTE_ON_INTER_LEVEL_RECOVER) {
+ buf[0] = vstrextend(&buf[0], sep, "INTER-LEVEL-RECOVER", NULL);
+ sep = ", ";
+ }
+ }
+ break;
+