+ case CONF_NL: /* empty line */
+ break;
+
+ case CONF_END: /* end of file */
+ return 0;
+
+ /* These should never be at the begining of a line */
+ case CONF_LBRACE:
+ case CONF_RBRACE:
+ case CONF_IDENT:
+ case CONF_INT:
+ case CONF_INT64:
+ case CONF_BOOL:
+ case CONF_REAL:
+ case CONF_STRING:
+ case CONF_TIME:
+ case CONF_SIZE:
+ conf_parserror("error: not a keyword.");
+ break;
+
+ /* if it's not a known punctuation mark, then check the parse table and use the
+ * read_function we find there. */
+ default:
+ {
+ for(np = parsetable; np->token != CONF_UNKNOWN; np++)
+ if(np->token == tok) break;
+
+ if(np->token == CONF_UNKNOWN) {
+ handle_invalid_keyword(tokenval.v.s);
+ } else {
+ np->read_function(np, &conf_data[np->parm]);
+ if(np->validate_function)
+ np->validate_function(np, &conf_data[np->parm]);
+ }
+ }
+ }
+ if(tok != CONF_NL)
+ get_conftoken(CONF_NL);
+ return 1;
+}
+
+static void
+handle_deprecated_keyword(void)
+{
+ /* Procedure for deprecated keywords:
+ *
+ * 1) At time of deprecation, add to warning_deprecated below. Note the
+ * version in which deprecation will expire. The keyword will still be
+ * parsed, and can still be used from other parts of Amanda, during this
+ * time.
+ * 2) After it has expired, move the keyword (as a string) to
+ * error_deprecated below. Remove the token (CONF_XXX) and
+ * config parameter (CNF_XXX) from the rest of the module.
+ * Note the date of the move.
+ */
+
+ static struct { tok_t tok; gboolean warned; }
+ warning_deprecated[] = {
+ { CONF_LABEL_NEW_TAPES, 0 }, /* exp in Amanda-3.2 */
+ { CONF_AMRECOVER_DO_FSF, 0 }, /* exp in Amanda-3.3 */
+ { CONF_AMRECOVER_CHECK_LABEL, 0 }, /* exp in Amanda-3.3 */
+ { CONF_TAPE_SPLITSIZE, 0 }, /* exp. in Amanda-3.3 */
+ { CONF_SPLIT_DISKBUFFER, 0 }, /* exp. in Amanda-3.3 */
+ { CONF_FALLBACK_SPLITSIZE, 0 }, /* exp. in Amanda-3.3 */
+ { 0, 0 },
+ }, *dep;
+
+ for (dep = warning_deprecated; dep->tok; dep++) {
+ if (tok == dep->tok) {
+ if (!dep->warned)
+ conf_parswarn(_("warning: Keyword %s is deprecated."),
+ tokenval.v.s);
+ dep->warned = 1;
+ break;
+ }
+ }
+}
+
+static void
+handle_invalid_keyword(
+ const char * token)
+{
+ static const char * error_deprecated[] = {
+ "rawtapedev",
+ "tapebufs", /* deprecated: 2007-10-15; invalid: 2010-04-14 */
+ "file-pad", /* deprecated: 2008-07-01; invalid: 2010-04-14 */
+ NULL
+ };
+ const char ** s;
+ char *folded_token, *p;
+
+ /* convert '_' to '-' in TOKEN */
+ folded_token = g_strdup(token);
+ for (p = folded_token; *p; p++) {
+ if (*p == '_') *p = '-';
+ }
+
+ for (s = error_deprecated; *s != NULL; s ++) {
+ if (g_ascii_strcasecmp(*s, folded_token) == 0) {
+ conf_parserror(_("error: Keyword %s is deprecated."),
+ token);
+ g_free(folded_token);
+ return;
+ }
+ }
+ g_free(folded_token);
+
+ if (*s == NULL) {
+ conf_parserror(_("configuration keyword expected"));
+ }
+
+ for (;;) {
+ char c = conftoken_getc();
+ if (c == '\n' || c == -1) {
+ conftoken_ungetc(c);
+ return;
+ }
+ }
+
+ g_assert_not_reached();
+}
+
+static char *
+get_seen_filename(
+ char *filename)
+{
+ GSList *iter;
+ char *istr;
+
+ for (iter = seen_filenames; iter; iter = iter->next) {
+ istr = iter->data;
+ if (istr == filename || 0 == strcmp(istr, filename))
+ return istr;
+ }
+
+ istr = stralloc(filename);
+ seen_filenames = g_slist_prepend(seen_filenames, istr);
+ return istr;
+}
+
+static void
+read_block(
+ conf_var_t *read_var,
+ val_t *valarray,
+ char *errormsg,
+ int read_brace,
+ void (*copy_function)(void),
+ char *type,
+ char *name)
+{
+ conf_var_t *np;
+ int done;
+ char *key_ovr;
+ int i;
+
+ if(read_brace) {
+ get_conftoken(CONF_LBRACE);
+ get_conftoken(CONF_NL);
+ }
+
+ done = 0;
+ do {
+ current_line_num += 1;
+ get_conftoken(CONF_ANY);
+ handle_deprecated_keyword();
+
+ 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("%s", 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);
+
+ if (!config_overrides)
+ return;
+
+ key_ovr = vstralloc(type, ":", name, NULL);
+ for (i = 0; i < config_overrides->n_used; i++) {
+ config_override_t *co = &config_overrides->ovr[i];
+ char *key = co->key;
+ char *keyword;
+ char *value;
+ keytab_t *kt;
+
+ if (key_ovr && strncasecmp(key_ovr, key, strlen(key_ovr)) != 0)
+ continue;
+
+ if (strlen(key) <= strlen(key_ovr) + 1)
+ continue;
+
+ keyword = key + strlen(key_ovr) + 1;
+ value = co->value;
+
+ /* find the token in keytable */
+ for (kt = keytable; kt->token != CONF_UNKNOWN; kt++) {
+ if (kt->keyword && strcasecmp(kt->keyword, keyword) == 0)
+ break;
+ }
+ if (kt->token == CONF_UNKNOWN)
+ continue;
+
+ /* find the var in read_var */
+ for (np = read_var; np->token != CONF_UNKNOWN; np++)
+ if (np->token == kt->token) break;
+ if (np->token == CONF_UNKNOWN)
+ continue;
+
+ /* now set up a fake line and use the relevant read_function to
+ * parse it. This is sneaky! */
+ if (np->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->applied = TRUE;
+
+ np->read_function(np, &valarray[np->parm]);
+ if (np->validate_function)
+ np->validate_function(np, &valarray[np->parm]);
+
+ amfree(current_line);
+ current_char = NULL;
+ }
+ amfree(key_ovr);
+
+}
+
+static void
+read_holdingdisk(
+ conf_var_t *np G_GNUC_UNUSED,
+ val_t *val G_GNUC_UNUSED)
+{
+ assert (val == &conf_data[CNF_HOLDINGDISK]);
+ get_holdingdisk(0);
+}
+
+static void
+get_holdingdisk(
+ int is_define)
+{
+ int save_overwrites;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_holdingdisk_defaults();
+
+ get_conftoken(CONF_IDENT);
+ hdcur.name = stralloc(tokenval.v.s);
+ current_block = g_strconcat("holdingdisk ", hdcur.name, NULL);
+ hdcur.seen.block = current_block;
+ hdcur.seen.filename = current_filename;
+ hdcur.seen.linenum = current_line_num;
+
+ get_conftoken(CONF_ANY);
+ if (tok == CONF_LBRACE) {
+ holdingdisk_t *hd;
+ hd = lookup_holdingdisk(hdcur.name);
+ if (hd) {
+ conf_parserror(_("holding disk '%s' already defined"),
+ hdcur.name);
+ } else {
+ unget_conftoken();
+ read_block(holding_var, hdcur.value,
+ _("holding disk parameter expected"), 1, copy_holdingdisk,
+ "HOLDINGDISK", hdcur.name);
+ get_conftoken(CONF_NL);
+ save_holdingdisk();
+ if (!is_define) {
+ conf_data[CNF_HOLDINGDISK].v.identlist = g_slist_append(
+ conf_data[CNF_HOLDINGDISK].v.identlist,
+ stralloc(hdcur.name));
+ }
+ }
+ } else { /* use the already defined holding disk */
+ unget_conftoken();
+ if (is_define) {
+ conf_parserror(_("holdingdisk definition must specify holdingdisk parameters"));
+ }
+ do {
+ identlist_t il;
+
+ for (il = conf_data[CNF_HOLDINGDISK].v.identlist; il != NULL;
+ il = il->next) {
+ if (strcmp((char *)il->data, hdcur.name) == 0) {
+ break;
+ }
+ }
+ if (il) {
+ conf_parserror(_("holding disk '%s' already in use"),
+ hdcur.name);
+ } else {
+ conf_data[CNF_HOLDINGDISK].v.identlist = g_slist_append(
+ conf_data[CNF_HOLDINGDISK].v.identlist,
+ stralloc(hdcur.name));
+ }
+ amfree(hdcur.name);
+ get_conftoken(CONF_ANY);
+ if (tok == CONF_IDENT || tok == CONF_STRING) {
+ hdcur.name = stralloc(tokenval.v.s);
+ } else if (tok != CONF_NL) {
+ conf_parserror(_("IDENT or NL expected"));
+ }
+ } while (tok == CONF_IDENT || tok == CONF_STRING);
+ }
+
+ allow_overwrites = save_overwrites;
+}
+
+static void
+init_holdingdisk_defaults(
+ void)
+{
+ conf_init_str(&hdcur.value[HOLDING_COMMENT] , "");
+ conf_init_str(&hdcur.value[HOLDING_DISKDIR] , "");
+ conf_init_int64(&hdcur.value[HOLDING_DISKSIZE] , CONF_UNIT_K, (gint64)0);
+ /* 1 Gb = 1M counted in 1Kb blocks */
+ conf_init_int64(&hdcur.value[HOLDING_CHUNKSIZE], CONF_UNIT_K, (gint64)1024*1024);
+}
+
+static void
+save_holdingdisk(
+ void)
+{
+ holdingdisk_t *hp;
+
+ hp = alloc(sizeof(holdingdisk_t));
+ *hp = hdcur;
+ holdinglist = g_slist_append(holdinglist, hp);
+}
+
+static void
+copy_holdingdisk(
+ void)
+{
+ holdingdisk_t *hp;
+ int i;
+
+ hp = lookup_holdingdisk(tokenval.v.s);
+
+ if (hp == NULL) {
+ conf_parserror(_("holdingdisk parameter expected"));
+ return;
+ }
+
+ for(i=0; i < HOLDING_HOLDING; i++) {
+ if(hp->value[i].seen.linenum) {
+ merge_val_t(&hdcur.value[i], &hp->value[i]);
+ }
+ }
+
+}
+
+
+/* WARNING:
+ * This function is called both from this module and from diskfile.c. Modify
+ * with caution. */
+dumptype_t *
+read_dumptype(
+ char *name,
+ FILE *from,
+ char *fname,
+ int *linenum)
+{
+ int save_overwrites;
+ FILE *saved_conf = NULL;
+ char *saved_fname = NULL;
+
+ if (from) {
+ saved_conf = current_file;
+ current_file = from;
+ }
+
+ if (fname) {
+ saved_fname = current_filename;
+ current_filename = get_seen_filename(fname);
+ }
+
+ if (linenum)
+ current_line_num = *linenum;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_dumptype_defaults();
+ if (name) {
+ dpcur.name = name;
+ } else {
+ get_conftoken(CONF_IDENT);
+ dpcur.name = stralloc(tokenval.v.s);
+ }
+ current_block = g_strconcat("dumptype ", dpcur.name, NULL);
+ dpcur.seen.block = current_block;
+ dpcur.seen.filename = current_filename;
+ dpcur.seen.linenum = current_line_num;
+
+ read_block(dumptype_var, dpcur.value,
+ _("dumptype parameter expected"),
+ (name == NULL), copy_dumptype,
+ "DUMPTYPE", dpcur.name);
+
+ if(!name) /* !name => reading disklist, not conffile */
+ get_conftoken(CONF_NL);
+
+ /* XXX - there was a stupidity check in here for skip-incr and
+ ** skip-full. This check should probably be somewhere else. */
+
+ save_dumptype();
+
+ allow_overwrites = save_overwrites;
+
+ if (linenum)
+ *linenum = current_line_num;
+
+ if (fname)
+ current_filename = saved_fname;
+
+ if (from)
+ current_file = saved_conf;
+
+ return lookup_dumptype(dpcur.name);
+}
+
+static void
+get_dumptype(void)
+{
+ read_dumptype(NULL, NULL, NULL, NULL);
+}
+
+static void
+init_dumptype_defaults(void)
+{
+ dpcur.name = NULL;
+ 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] , "");
+ conf_init_str (&dpcur.value[DUMPTYPE_CLIENT_USERNAME] , "");
+ conf_init_str (&dpcur.value[DUMPTYPE_CLIENT_PORT] , "");
+ conf_init_str (&dpcur.value[DUMPTYPE_SSH_KEYS] , "");
+ conf_init_str (&dpcur.value[DUMPTYPE_AUTH] , "BSDTCP");
+ conf_init_exinclude(&dpcur.value[DUMPTYPE_EXCLUDE]);
+ conf_init_exinclude(&dpcur.value[DUMPTYPE_INCLUDE]);
+ conf_init_priority (&dpcur.value[DUMPTYPE_PRIORITY] , 1);
+ conf_init_int (&dpcur.value[DUMPTYPE_DUMPCYCLE] , CONF_UNIT_NONE, conf_data[CNF_DUMPCYCLE].v.i);
+ conf_init_int (&dpcur.value[DUMPTYPE_MAXDUMPS] , CONF_UNIT_NONE, conf_data[CNF_MAXDUMPS].v.i);
+ conf_init_int (&dpcur.value[DUMPTYPE_MAXPROMOTEDAY] , CONF_UNIT_NONE, 10000);
+ conf_init_int (&dpcur.value[DUMPTYPE_BUMPPERCENT] , CONF_UNIT_NONE, conf_data[CNF_BUMPPERCENT].v.i);
+ conf_init_int64 (&dpcur.value[DUMPTYPE_BUMPSIZE] , CONF_UNIT_K , conf_data[CNF_BUMPSIZE].v.int64);
+ conf_init_int (&dpcur.value[DUMPTYPE_BUMPDAYS] , CONF_UNIT_NONE, conf_data[CNF_BUMPDAYS].v.i);
+ conf_init_real (&dpcur.value[DUMPTYPE_BUMPMULT] , conf_data[CNF_BUMPMULT].v.r);
+ conf_init_time (&dpcur.value[DUMPTYPE_STARTTIME] , (time_t)0);
+ conf_init_strategy (&dpcur.value[DUMPTYPE_STRATEGY] , DS_STANDARD);
+ conf_init_estimatelist(&dpcur.value[DUMPTYPE_ESTIMATELIST] , ES_CLIENT);
+ conf_init_compress (&dpcur.value[DUMPTYPE_COMPRESS] , COMP_FAST);
+ conf_init_encrypt (&dpcur.value[DUMPTYPE_ENCRYPT] , ENCRYPT_NONE);
+ conf_init_data_path(&dpcur.value[DUMPTYPE_DATA_PATH] , DATA_PATH_AMANDA);
+ 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_int64 (&dpcur.value[DUMPTYPE_TAPE_SPLITSIZE] , CONF_UNIT_K, (gint64)0);
+ conf_init_int64 (&dpcur.value[DUMPTYPE_FALLBACK_SPLITSIZE], CONF_UNIT_K, (gint64)10 * 1024);
+ 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);
+ conf_init_holding (&dpcur.value[DUMPTYPE_HOLDINGDISK] , HOLD_AUTO);
+ conf_init_bool (&dpcur.value[DUMPTYPE_KENCRYPT] , 0);
+ conf_init_bool (&dpcur.value[DUMPTYPE_IGNORE] , 0);
+ conf_init_bool (&dpcur.value[DUMPTYPE_INDEX] , 1);
+ conf_init_application(&dpcur.value[DUMPTYPE_APPLICATION]);
+ conf_init_identlist(&dpcur.value[DUMPTYPE_SCRIPTLIST], NULL);
+ conf_init_proplist(&dpcur.value[DUMPTYPE_PROPERTY]);
+ conf_init_bool (&dpcur.value[DUMPTYPE_ALLOW_SPLIT] , 1);
+ conf_init_int (&dpcur.value[DUMPTYPE_MAX_WARNINGS] , CONF_UNIT_NONE, 20);
+ conf_init_host_limit(&dpcur.value[DUMPTYPE_RECOVERY_LIMIT]);
+ conf_init_host_limit_server(&dpcur.value[DUMPTYPE_DUMP_LIMIT]);
+}
+
+static void
+save_dumptype(void)
+{
+ dumptype_t *dp, *dp1;;
+
+ dp = lookup_dumptype(dpcur.name);
+
+ if(dp != (dumptype_t *)0) {
+ if (dp->seen.linenum == -1) {
+ conf_parserror(_("dumptype %s is defined by default and cannot be redefined"), dp->name);
+ } else {
+ conf_parserror(_("dumptype %s already defined at %s:%d"), dp->name,
+ dp->seen.filename, dp->seen.linenum);
+ }
+ return;
+ }
+
+ dp = alloc(sizeof(dumptype_t));
+ *dp = dpcur;
+ dp->next = NULL;
+ /* add at end of list */
+ if(!dumplist)
+ dumplist = dp;
+ else {
+ dp1 = dumplist;
+ while (dp1->next != NULL) {
+ dp1 = dp1->next;
+ }
+ dp1->next = dp;
+ }
+}
+
+static void
+copy_dumptype(void)
+{
+ dumptype_t *dt;
+ int i;
+
+ dt = lookup_dumptype(tokenval.v.s);
+
+ if(dt == NULL) {
+ conf_parserror(_("dumptype parameter expected"));
+ return;
+ }
+
+ for(i=0; i < DUMPTYPE_DUMPTYPE; i++) {
+ if(dt->value[i].seen.linenum) {
+ merge_val_t(&dpcur.value[i], &dt->value[i]);
+ if (i == DUMPTYPE_SCRIPTLIST) {
+ /* sort in 'order' */
+ dpcur.value[i].v.identlist = g_slist_sort(dpcur.value[i].v.identlist, &compare_pp_script_order);
+ }
+ }
+ }
+}
+
+static void
+get_tapetype(void)
+{
+ int save_overwrites;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_tapetype_defaults();
+
+ get_conftoken(CONF_IDENT);
+ tpcur.name = stralloc(tokenval.v.s);
+ current_block = g_strconcat("tapetype ", tpcur.name, NULL);
+ tpcur.seen.block = current_block;
+ tpcur.seen.filename = current_filename;
+ tpcur.seen.linenum = current_line_num;
+
+ read_block(tapetype_var, tpcur.value,
+ _("tapetype parameter expected"), 1, copy_tapetype,
+ "TAPETYPE", tpcur.name);
+ get_conftoken(CONF_NL);
+
+ if (tapetype_get_readblocksize(&tpcur) <
+ tapetype_get_blocksize(&tpcur)) {
+ conf_init_size(&tpcur.value[TAPETYPE_READBLOCKSIZE], CONF_UNIT_K,
+ tapetype_get_blocksize(&tpcur));
+ }
+ save_tapetype();
+
+ allow_overwrites = save_overwrites;
+}
+
+static void
+init_tapetype_defaults(void)
+{
+ conf_init_str(&tpcur.value[TAPETYPE_COMMENT] , "");
+ conf_init_str(&tpcur.value[TAPETYPE_LBL_TEMPL] , "");
+ conf_init_size (&tpcur.value[TAPETYPE_BLOCKSIZE] , CONF_UNIT_K, DISK_BLOCK_KB);
+ conf_init_size (&tpcur.value[TAPETYPE_READBLOCKSIZE], CONF_UNIT_K, DISK_BLOCK_KB);
+ conf_init_int64 (&tpcur.value[TAPETYPE_LENGTH] , CONF_UNIT_K, ((gint64)2000));
+ conf_init_int64 (&tpcur.value[TAPETYPE_FILEMARK] , CONF_UNIT_K, (gint64)1);
+ conf_init_int (&tpcur.value[TAPETYPE_SPEED] , CONF_UNIT_NONE, 200);
+ conf_init_int64(&tpcur.value[TAPETYPE_PART_SIZE], CONF_UNIT_K, 0);
+ conf_init_part_cache_type(&tpcur.value[TAPETYPE_PART_CACHE_TYPE], PART_CACHE_TYPE_NONE);
+ conf_init_str(&tpcur.value[TAPETYPE_PART_CACHE_DIR], "");
+ conf_init_int64(&tpcur.value[TAPETYPE_PART_CACHE_MAX_SIZE], CONF_UNIT_K, 0);
+}
+
+static void
+save_tapetype(void)
+{
+ tapetype_t *tp, *tp1;
+
+ tp = lookup_tapetype(tpcur.name);
+
+ if(tp != (tapetype_t *)0) {
+ amfree(tpcur.name);
+ conf_parserror(_("tapetype %s already defined at %s:%d"),
+ tp->name, tp->seen.filename, tp->seen.linenum);
+ return;
+ }
+
+ tp = alloc(sizeof(tapetype_t));
+ *tp = tpcur;
+
+ /* add at end of list */
+ if(!tapelist)
+ tapelist = tp;
+ else {
+ tp1 = tapelist;
+ while (tp1->next != NULL) {
+ tp1 = tp1->next;
+ }
+ tp1->next = tp;
+ }
+}
+
+static void
+copy_tapetype(void)
+{
+ tapetype_t *tp;
+ int i;
+
+ tp = lookup_tapetype(tokenval.v.s);
+
+ if(tp == NULL) {
+ conf_parserror(_("tape type parameter expected"));
+ return;
+ }
+
+ for(i=0; i < TAPETYPE_TAPETYPE; i++) {
+ if(tp->value[i].seen.linenum) {
+ merge_val_t(&tpcur.value[i], &tp->value[i]);
+ }
+ }
+}
+
+static void
+get_interface(void)
+{
+ int save_overwrites;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_interface_defaults();
+
+ get_conftoken(CONF_IDENT);
+ ifcur.name = stralloc(tokenval.v.s);
+ current_block = g_strconcat("interface ", ifcur.name, NULL);
+ ifcur.seen.block = current_block;
+ ifcur.seen.filename = current_filename;
+ ifcur.seen.linenum = current_line_num;
+
+ read_block(interface_var, ifcur.value,
+ _("interface parameter expected"), 1, copy_interface,
+ "INTERFACE", ifcur.name);
+ get_conftoken(CONF_NL);
+
+ save_interface();
+
+ allow_overwrites = save_overwrites;
+
+ return;
+}
+
+static void
+init_interface_defaults(void)
+{
+ conf_init_str(&ifcur.value[INTER_COMMENT] , "");
+ conf_init_int (&ifcur.value[INTER_MAXUSAGE], CONF_UNIT_K, 80000);
+}
+
+static void
+save_interface(void)
+{
+ interface_t *ip, *ip1;
+
+ ip = lookup_interface(ifcur.name);
+
+ if(ip != (interface_t *)0) {
+ conf_parserror(_("interface %s already defined at %s:%d"),
+ ip->name, ip->seen.filename, ip->seen.linenum);
+ return;
+ }
+
+ ip = alloc(sizeof(interface_t));
+ *ip = ifcur;
+ /* add at end of list */
+ if(!interface_list) {
+ interface_list = ip;
+ } else {
+ ip1 = interface_list;
+ while (ip1->next != NULL) {
+ ip1 = ip1->next;
+ }
+ ip1->next = ip;
+ }
+}
+
+static void
+copy_interface(void)
+{
+ interface_t *ip;
+ int i;
+
+ ip = lookup_interface(tokenval.v.s);
+
+ if(ip == NULL) {
+ conf_parserror(_("interface parameter expected"));
+ return;
+ }
+
+ for(i=0; i < INTER_INTER; i++) {
+ if(ip->value[i].seen.linenum) {
+ merge_val_t(&ifcur.value[i], &ip->value[i]);
+ }
+ }
+}
+
+
+static application_t *
+read_application(
+ char *name,
+ FILE *from,
+ char *fname,
+ int *linenum)
+{
+ int save_overwrites;
+ FILE *saved_conf = NULL;
+ char *saved_fname = NULL;
+
+ if (from) {
+ saved_conf = current_file;
+ current_file = from;
+ }
+
+ if (fname) {
+ saved_fname = current_filename;
+ current_filename = get_seen_filename(fname);
+ }
+
+ if (linenum)
+ current_line_num = *linenum;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_application_defaults();
+ if (name) {
+ apcur.name = name;
+ } else {
+ get_conftoken(CONF_IDENT);
+ apcur.name = stralloc(tokenval.v.s);
+ }
+ current_block = g_strconcat("application ", apcur.name, NULL);
+ apcur.seen.block = current_block;
+ apcur.seen.filename = current_filename;
+ apcur.seen.linenum = current_line_num;
+
+ read_block(application_var, apcur.value,
+ _("application parameter expected"),
+ (name == NULL), *copy_application,
+ "APPLICATION", apcur.name);
+ if(!name)
+ get_conftoken(CONF_NL);
+
+ save_application();
+
+ allow_overwrites = save_overwrites;
+
+ if (linenum)
+ *linenum = current_line_num;
+
+ if (fname)
+ current_filename = saved_fname;
+
+ if (from)
+ current_file = saved_conf;
+
+ return lookup_application(apcur.name);
+}
+
+static void
+get_application(
+ void)
+{
+ read_application(NULL, NULL, NULL, NULL);
+}
+
+static void
+init_application_defaults(
+ void)
+{
+ apcur.name = NULL;
+ conf_init_str(&apcur.value[APPLICATION_COMMENT] , "");
+ conf_init_str(&apcur.value[APPLICATION_PLUGIN] , "");
+ conf_init_proplist(&apcur.value[APPLICATION_PROPERTY]);
+ conf_init_str(&apcur.value[APPLICATION_CLIENT_NAME] , "");
+}
+
+static void
+save_application(
+ void)
+{
+ application_t *ap, *ap1;
+
+ ap = lookup_application(apcur.name);
+
+ if(ap != (application_t *)0) {
+ conf_parserror(_("application %s already defined at %s:%d"),
+ ap->name, ap->seen.filename, ap->seen.linenum);
+ return;
+ }
+
+ ap = alloc(sizeof(application_t));
+ *ap = apcur;
+ ap->next = NULL;
+ /* add at end of list */
+ if (!application_list)
+ application_list = ap;
+ else {
+ ap1 = application_list;
+ while (ap1->next != NULL) {
+ ap1 = ap1->next;
+ }
+ ap1->next = ap;
+ }
+}
+
+static void
+copy_application(void)
+{
+ application_t *ap;
+ int i;
+
+ ap = lookup_application(tokenval.v.s);
+
+ if(ap == NULL) {
+ conf_parserror(_("application parameter expected"));
+ return;
+ }
+
+ for(i=0; i < APPLICATION_APPLICATION; i++) {
+ if(ap->value[i].seen.linenum) {
+ merge_val_t(&apcur.value[i], &ap->value[i]);
+ }
+ }
+}
+
+static interactivity_t *
+read_interactivity(
+ char *name,
+ FILE *from,
+ char *fname,
+ int *linenum)
+{
+ int save_overwrites;
+ FILE *saved_conf = NULL;
+ char *saved_fname = NULL;
+
+ if (from) {
+ saved_conf = current_file;
+ current_file = from;
+ }
+
+ if (fname) {
+ saved_fname = current_filename;
+ current_filename = get_seen_filename(fname);
+ }
+
+ if (linenum)
+ current_line_num = *linenum;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_interactivity_defaults();
+ if (name) {
+ ivcur.name = name;
+ } else {
+ get_conftoken(CONF_IDENT);
+ ivcur.name = stralloc(tokenval.v.s);
+ }
+ current_block = g_strconcat("interactivity ", ivcur.name, NULL);
+ ivcur.seen.block = current_block;
+ ivcur.seen.filename = current_filename;
+ ivcur.seen.linenum = current_line_num;
+
+ read_block(interactivity_var, ivcur.value,
+ _("interactivity parameter expected"),
+ (name == NULL), *copy_interactivity,
+ "INTERACTIVITY", ivcur.name);
+ if(!name)
+ get_conftoken(CONF_NL);
+
+ save_interactivity();
+
+ allow_overwrites = save_overwrites;
+
+ if (linenum)
+ *linenum = current_line_num;
+
+ if (fname)
+ current_filename = saved_fname;
+
+ if (from)
+ current_file = saved_conf;
+
+ return lookup_interactivity(ivcur.name);
+}
+
+static void
+get_interactivity(
+ void)
+{
+ read_interactivity(NULL, NULL, NULL, NULL);
+}
+
+static void
+init_interactivity_defaults(
+ void)
+{
+ ivcur.name = NULL;
+ conf_init_str(&ivcur.value[INTERACTIVITY_COMMENT] , "");
+ conf_init_str(&ivcur.value[INTERACTIVITY_PLUGIN] , "");
+ conf_init_proplist(&ivcur.value[INTERACTIVITY_PROPERTY]);
+}
+
+static void
+save_interactivity(
+ void)
+{
+ interactivity_t *iv, *iv1;
+
+ iv = lookup_interactivity(ivcur.name);
+
+ if (iv != (interactivity_t *)0) {
+ conf_parserror(_("interactivity %s already defined at %s:%d"),
+ iv->name, iv->seen.filename, iv->seen.linenum);
+ return;
+ }
+
+ iv = alloc(sizeof(interactivity_t));
+ *iv = ivcur;
+ iv->next = NULL;
+ /* add at end of list */
+ if (!interactivity_list)
+ interactivity_list = iv;
+ else {
+ iv1 = interactivity_list;
+ while (iv1->next != NULL) {
+ iv1 = iv1->next;
+ }
+ iv1->next = iv;
+ }
+}
+
+static void
+copy_interactivity(void)
+{
+ interactivity_t *iv;
+ int i;
+
+ iv = lookup_interactivity(tokenval.v.s);
+
+ if (iv == NULL) {
+ conf_parserror(_("interactivity parameter expected"));
+ return;
+ }
+
+ for (i=0; i < INTERACTIVITY_INTERACTIVITY; i++) {
+ if(iv->value[i].seen.linenum) {
+ merge_val_t(&ivcur.value[i], &iv->value[i]);
+ }
+ }
+}
+
+static taperscan_t *
+read_taperscan(
+ char *name,
+ FILE *from,
+ char *fname,
+ int *linenum)
+{
+ int save_overwrites;
+ FILE *saved_conf = NULL;
+ char *saved_fname = NULL;
+
+ if (from) {
+ saved_conf = current_file;
+ current_file = from;
+ }
+
+ if (fname) {
+ saved_fname = current_filename;
+ current_filename = get_seen_filename(fname);
+ }
+
+ if (linenum)
+ current_line_num = *linenum;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_taperscan_defaults();
+ if (name) {
+ tscur.name = name;
+ } else {
+ get_conftoken(CONF_IDENT);
+ tscur.name = stralloc(tokenval.v.s);
+ }
+ current_block = g_strconcat("taperscan ", tscur.name, NULL);
+ tscur.seen.block = current_block;
+ tscur.seen.filename = current_filename;
+ tscur.seen.linenum = current_line_num;
+
+ read_block(taperscan_var, tscur.value,
+ _("taperscan parameter expected"),
+ (name == NULL), *copy_taperscan,
+ "TAPERSCAN", tscur.name);
+ if(!name)
+ get_conftoken(CONF_NL);
+
+ save_taperscan();
+
+ allow_overwrites = save_overwrites;
+
+ if (linenum)
+ *linenum = current_line_num;
+
+ if (fname)
+ current_filename = saved_fname;
+
+ if (from)
+ current_file = saved_conf;
+
+ return lookup_taperscan(tscur.name);
+}
+
+static void
+get_taperscan(
+ void)
+{
+ read_taperscan(NULL, NULL, NULL, NULL);
+}
+
+static void
+init_taperscan_defaults(
+ void)
+{
+ tscur.name = NULL;
+ conf_init_str(&tscur.value[TAPERSCAN_COMMENT] , "");
+ conf_init_str(&tscur.value[TAPERSCAN_PLUGIN] , "");
+ conf_init_proplist(&tscur.value[TAPERSCAN_PROPERTY]);
+}
+
+static void
+save_taperscan(
+ void)
+{
+ taperscan_t *ts, *ts1;
+
+ ts = lookup_taperscan(tscur.name);
+
+ if (ts != (taperscan_t *)0) {
+ conf_parserror(_("taperscan %s already defined at %s:%d"),
+ ts->name, ts->seen.filename, ts->seen.linenum);
+ return;
+ }
+
+ ts = alloc(sizeof(taperscan_t));
+ *ts = tscur;
+ ts->next = NULL;
+ /* add at end of list */
+ if (!taperscan_list)
+ taperscan_list = ts;
+ else {
+ ts1 = taperscan_list;
+ while (ts1->next != NULL) {
+ ts1 = ts1->next;
+ }
+ ts1->next = ts;
+ }
+}
+
+static void
+copy_taperscan(void)
+{
+ taperscan_t *ts;
+ int i;
+
+ ts = lookup_taperscan(tokenval.v.s);
+
+ if (ts == NULL) {
+ conf_parserror(_("taperscan parameter expected"));
+ return;
+ }
+
+ for (i=0; i < TAPERSCAN_TAPERSCAN; i++) {
+ if(ts->value[i].seen.linenum) {
+ merge_val_t(&tscur.value[i], &ts->value[i]);
+ }
+ }
+}
+
+static pp_script_t *
+read_pp_script(
+ char *name,
+ FILE *from,
+ char *fname,
+ int *linenum)
+{
+ int save_overwrites;
+ FILE *saved_conf = NULL;
+ char *saved_fname = NULL;
+
+ if (from) {
+ saved_conf = current_file;
+ current_file = from;
+ }
+
+ if (fname) {
+ saved_fname = current_filename;
+ current_filename = get_seen_filename(fname);
+ }
+
+ if (linenum)
+ current_line_num = *linenum;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_pp_script_defaults();
+ if (name) {
+ pscur.name = name;
+ } else {
+ get_conftoken(CONF_IDENT);
+ pscur.name = stralloc(tokenval.v.s);
+ }
+ current_block = g_strconcat("script ", pscur.name, NULL);
+ pscur.seen.block = current_block;
+ pscur.seen.filename = current_filename;
+ pscur.seen.linenum = current_line_num;
+
+ read_block(pp_script_var, pscur.value,
+ _("script parameter expected"),
+ (name == NULL), *copy_pp_script,
+ "SCRIPT", pscur.name);
+ if(!name)
+ get_conftoken(CONF_NL);
+
+ save_pp_script();
+
+ allow_overwrites = save_overwrites;
+
+ if (linenum)
+ *linenum = current_line_num;
+
+ if (fname)
+ current_filename = saved_fname;
+
+ if (from)
+ current_file = saved_conf;
+
+ return lookup_pp_script(pscur.name);
+}
+
+static void
+get_pp_script(
+ void)
+{
+ read_pp_script(NULL, NULL, NULL, NULL);
+}
+
+static void
+init_pp_script_defaults(
+ void)
+{
+ pscur.name = NULL;
+ conf_init_str(&pscur.value[PP_SCRIPT_COMMENT] , "");
+ conf_init_str(&pscur.value[PP_SCRIPT_PLUGIN] , "");
+ conf_init_proplist(&pscur.value[PP_SCRIPT_PROPERTY]);
+ conf_init_execute_on(&pscur.value[PP_SCRIPT_EXECUTE_ON], 0);
+ conf_init_execute_where(&pscur.value[PP_SCRIPT_EXECUTE_WHERE], ES_CLIENT);
+ conf_init_int(&pscur.value[PP_SCRIPT_ORDER], CONF_UNIT_NONE, 5000);
+ conf_init_bool(&pscur.value[PP_SCRIPT_SINGLE_EXECUTION], 0);
+ conf_init_str(&pscur.value[PP_SCRIPT_CLIENT_NAME], "");
+}
+
+static void
+save_pp_script(
+ void)
+{
+ pp_script_t *ps, *ps1;
+
+ ps = lookup_pp_script(pscur.name);
+
+ if(ps != (pp_script_t *)0) {
+ conf_parserror(_("script %s already defined at %s:%d"),
+ ps->name, ps->seen.filename, ps->seen.linenum);
+ return;
+ }
+
+ ps = alloc(sizeof(pp_script_t));
+ *ps = pscur;
+ ps->next = NULL;
+ /* add at end of list */
+ if (!pp_script_list)
+ pp_script_list = ps;
+ else {
+ ps1 = pp_script_list;
+ while (ps1->next != NULL) {
+ ps1 = ps1->next;
+ }
+ ps1->next = ps;
+ }
+}
+
+static void
+copy_pp_script(void)
+{
+ pp_script_t *ps;
+ int i;
+
+ ps = lookup_pp_script(tokenval.v.s);
+
+ if(ps == NULL) {
+ conf_parserror(_("script parameter expected"));
+ return;
+ }
+
+ for(i=0; i < PP_SCRIPT_PP_SCRIPT; i++) {
+ if(ps->value[i].seen.linenum) {
+ merge_val_t(&pscur.value[i], &ps->value[i]);
+ }
+ }
+}
+
+static device_config_t *
+read_device_config(
+ char *name,
+ FILE *from,
+ char *fname,
+ int *linenum)
+{
+ int save_overwrites;
+ FILE *saved_conf = NULL;
+ char *saved_fname = NULL;
+
+ if (from) {
+ saved_conf = current_file;
+ current_file = from;
+ }
+
+ if (fname) {
+ saved_fname = current_filename;
+ current_filename = get_seen_filename(fname);
+ }
+
+ if (linenum)
+ current_line_num = *linenum;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_device_config_defaults();
+ if (name) {
+ dccur.name = name;
+ } else {
+ get_conftoken(CONF_IDENT);
+ dccur.name = stralloc(tokenval.v.s);
+ }
+ current_block = g_strconcat("device ", dccur.name, NULL);
+ dccur.seen.block = current_block;
+ dccur.seen.filename = current_filename;
+ dccur.seen.linenum = current_line_num;
+
+ read_block(device_config_var, dccur.value,
+ _("device parameter expected"),
+ (name == NULL), *copy_device_config,
+ "DEVICE", dccur.name);
+ if(!name)
+ get_conftoken(CONF_NL);
+
+ save_device_config();
+
+ allow_overwrites = save_overwrites;
+
+ if (linenum)
+ *linenum = current_line_num;
+
+ if (fname)
+ current_filename = saved_fname;
+
+ if (from)
+ current_file = saved_conf;
+
+ return lookup_device_config(dccur.name);
+}
+
+static void
+get_device_config(
+ void)
+{
+ read_device_config(NULL, NULL, NULL, NULL);
+}
+
+static void
+init_device_config_defaults(
+ void)
+{
+ dccur.name = NULL;
+ conf_init_str(&dccur.value[DEVICE_CONFIG_COMMENT] , "");
+ conf_init_str(&dccur.value[DEVICE_CONFIG_TAPEDEV] , "");
+ conf_init_proplist(&dccur.value[DEVICE_CONFIG_DEVICE_PROPERTY]);
+}
+
+static void
+save_device_config(
+ void)
+{
+ device_config_t *dc, *dc1;
+
+ dc = lookup_device_config(dccur.name);
+
+ if(dc != (device_config_t *)0) {
+ conf_parserror(_("device %s already defined at %s:%d"),
+ dc->name, dc->seen.filename, dc->seen.linenum);
+ return;
+ }
+
+ dc = alloc(sizeof(device_config_t));
+ *dc = dccur;
+ dc->next = NULL;
+ /* add at end of list */
+ if (!device_config_list)
+ device_config_list = dc;
+ else {
+ dc1 = device_config_list;
+ while (dc1->next != NULL) {
+ dc1 = dc1->next;
+ }
+ dc1->next = dc;
+ }
+}
+
+static void
+copy_device_config(void)
+{
+ device_config_t *dc;
+ int i;
+
+ dc = lookup_device_config(tokenval.v.s);
+
+ if(dc == NULL) {
+ conf_parserror(_("device parameter expected"));
+ return;
+ }
+
+ for(i=0; i < DEVICE_CONFIG_DEVICE_CONFIG; i++) {
+ if(dc->value[i].seen.linenum) {
+ merge_val_t(&dccur.value[i], &dc->value[i]);
+ }
+ }
+}
+
+static changer_config_t *
+read_changer_config(
+ char *name,
+ FILE *from,
+ char *fname,
+ int *linenum)
+{
+ int save_overwrites;
+ FILE *saved_conf = NULL;
+ char *saved_fname = NULL;
+
+ if (from) {
+ saved_conf = current_file;
+ current_file = from;
+ }
+
+ if (fname) {
+ saved_fname = current_filename;
+ current_filename = fname;
+ }
+
+ if (linenum)
+ current_line_num = *linenum;
+
+ save_overwrites = allow_overwrites;
+ allow_overwrites = 1;
+
+ init_changer_config_defaults();
+ if (name) {
+ cccur.name = name;
+ } else {
+ get_conftoken(CONF_IDENT);
+ cccur.name = stralloc(tokenval.v.s);
+ }
+ current_block = g_strconcat("changer ", cccur.name, NULL);
+ cccur.seen.block = current_block;
+ cccur.seen.filename = current_filename;
+ cccur.seen.linenum = current_line_num;
+
+ read_block(changer_config_var, cccur.value,
+ _("changer parameter expected"),
+ (name == NULL), *copy_changer_config,
+ "CHANGER", cccur.name);
+ if(!name)
+ get_conftoken(CONF_NL);
+
+ save_changer_config();
+
+ allow_overwrites = save_overwrites;
+
+ if (linenum)
+ *linenum = current_line_num;