From 1ab52b1a51cb828a5868bfcca555d6752136fb52 Mon Sep 17 00:00:00 2001 From: Robert Spalek Date: Sat, 22 Apr 2006 15:00:06 +0200 Subject: [PATCH] conf2: implemented a command-line parser and sections supporting unknown items --- lib/conf2.c | 53 +++++++++++++++++++++++++++++++++++++++++++++-------- lib/conf2.h | 28 +++++++++++++++++++++++++++- 2 files changed, 72 insertions(+), 9 deletions(-) diff --git a/lib/conf2.c b/lib/conf2.c index baceb2dc..cd1196be 100644 --- a/lib/conf2.c +++ b/lib/conf2.c @@ -20,6 +20,7 @@ #include #include #include +#include #define TRY(f) do { byte *_msg = f; if (_msg) return _msg; } while (0) @@ -147,7 +148,8 @@ journal_rollback_section(uns new_pool, struct journal_item *oldj) /* Initialization */ #define SEC_FLAG_DYNAMIC 0x80000000 // contains a dynamic attribute -#define SEC_FLAG_NUMBER 0x7fffffff // number of entries +#define SEC_FLAG_UNKNOWN 0x40000000 // ignore unknown entriies +#define SEC_FLAG_NUMBER 0x3fffffff // number of entries static struct cf_section sections; // root section @@ -179,7 +181,7 @@ inspect_section(struct cf_section *sec) } void -cf_declare_section(byte *name, struct cf_section *sec) +cf_declare_section(byte *name, struct cf_section *sec, uns allow_unknown) { if (!sections.cfg) { @@ -195,6 +197,8 @@ cf_declare_section(byte *name, struct cf_section *sec) ci->ptr = NULL; ci->u.sec = sec; inspect_section(sec); + if (allow_unknown) + sec->flags |= SEC_FLAG_UNKNOWN; ci++; if (ci - sections.cfg >= (int) sections.size) { @@ -225,6 +229,7 @@ global_init(void) static uns initialized = 0; if (initialized++) return; + sections.flags |= SEC_FLAG_UNKNOWN; for (struct cf_item *ci=sections.cfg; ci->cls; ci++) cf_init_section(ci->name, ci->u.sec, NULL); } @@ -245,7 +250,7 @@ find_item(struct cf_section *curr_sec, byte *name, byte **msg) struct cf_item *ci = find_subitem(curr_sec, name); if (!ci->cls) { - if (curr_sec != §ions) // ignore silently unknown top-level sections + if (!(curr_sec->flags & SEC_FLAG_UNKNOWN)) // ignore silently unknown top-level sections and unknown attributes in flagged sections *msg = cf_printf("Unknown item %s", name); return NULL; } @@ -1128,14 +1133,46 @@ load_file(byte *file) static int load_string(byte *string) { - if (cf_def_file) { - int err = load_file(cf_def_file); - if (err) - return err; - } init_stack(); struct fastbuf fb; fbbuf_init_read(&fb, string, strlen(string), 0); byte *msg = parse_fastbuf("memory string", &fb, 0); return !!msg || done_stack(); } + +/* Command-line parser */ + +static void +load_default(void) +{ + if (cf_def_file) + if (cf_load(cf_def_file)) + die("Cannot load default config %s", optarg); +} + +int +cf_get_opt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index) +{ + static int other_options = 0; + while (1) { + int res = getopt_long (argc, argv, short_opts, long_opts, long_index); + if (res == 'S' || res == 'C') + { + if (other_options) + die("The -S and -C options must precede all other arguments"); + if (res == 'S') { + load_default(); + if (cf_set(optarg)) + die("Cannot set %s", optarg); + } else { + if (cf_load(optarg)) + die("Cannot load %s", optarg); + } + } else { + /* unhandled option or end of options */ + load_default(); + other_options++; + return res; + } + } +} diff --git a/lib/conf2.h b/lib/conf2.h index 22431f26..0f49ec9c 100644 --- a/lib/conf2.h +++ b/lib/conf2.h @@ -113,7 +113,7 @@ extern uns cf_need_journal; void cf_journal_block(void *ptr, uns len); /* Declaration */ -void cf_declare_section(byte *name, struct cf_section *sec); +void cf_declare_section(byte *name, struct cf_section *sec, uns allow_unknown); void cf_init_section(byte *name, struct cf_section *sec, void *ptr); /* Safe reloading and loading of configuration files */ @@ -128,4 +128,30 @@ byte *cf_parse_u64(byte *str, u64 *ptr); byte *cf_parse_double(byte *str, double *ptr); byte *cf_parse_ip(byte *p, u32 *varp); +/* + * When using cf_get_opt(), you must prefix your own short/long options by the + * CF_(SHORT|LONG)_OPTS. + * + * cf_def_file contains the name of a configuration file that will be + * automatically loaded before the first --set option is executed. If no --set + * option occurs, it will be loaded after getopt() returns -1 (i.e. at the end + * of the configuration options). cf_def_file will be ignored if another + * configuration file has already been loaded using the --config option. The + * initial value of cf_def_file is DEFAULT_CONFIG from config.h, but you can + * override it manually before calling cf_get_opt(). + */ + +#define CF_SHORT_OPTS "S:C:" +#define CF_LONG_OPTS {"set", 1, 0, 'S'}, {"config", 1, 0, 'C'}, +#define CF_NO_LONG_OPTS (const struct option []) { CF_LONG_OPTS { NULL, 0, 0, 0 } } +#ifndef CF_USAGE_TAB +#define CF_USAGE_TAB "" +#endif +#define CF_USAGE \ +"-S, --set sec.item=val\t" CF_USAGE_TAB "Manual setting of a configuration item\n\ +-C, --config filename\t" CF_USAGE_TAB "Overwrite default configuration file\n" + +struct option; +int cf_get_opt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index); + #endif -- 2.39.2