<ucw/getopt.h> now contains only cf_getopt() and related settings.
All high-level configuration functions have been moved to <ucw/conf.h>.
partmap hashfunc \
slists simple-lists bitsig \
log log-stream log-file log-syslog log-conf tbf \
- conf-context conf-alloc conf-dump conf-input conf-intr conf-journal conf-parse conf-section \
+ conf-context conf-alloc conf-dump conf-input conf-intr conf-journal conf-parse conf-section conf-getopt \
ipaccess \
fastbuf ff-binary ff-string ff-printf ff-unicode ff-stkstring \
fb-file fb-mem fb-temp tempfile fb-mmap fb-limfd fb-buffer fb-grow fb-pool fb-atomic fb-param fb-socket \
--- /dev/null
+/*
+ * UCW Library -- Configuration files: getopt wrapper
+ *
+ * (c) 2001--2006 Robert Spalek <robert@ucw.cz>
+ * (c) 2003--2012 Martin Mares <mj@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
+ */
+
+#include <ucw/lib.h>
+#include <ucw/conf.h>
+#include <ucw/conf-internal.h>
+#include <ucw/getopt.h>
+#include <ucw/fastbuf.h>
+
+#include <stdlib.h>
+
+#ifndef CONFIG_UCW_DEFAULT_CONFIG
+#define CONFIG_UCW_DEFAULT_CONFIG NULL
+#endif
+char *cf_def_file = CONFIG_UCW_DEFAULT_CONFIG;
+
+#ifndef CONFIG_UCW_ENV_VAR_CONFIG
+#define CONFIG_UCW_ENV_VAR_CONFIG NULL
+#endif
+char *cf_env_file = CONFIG_UCW_ENV_VAR_CONFIG;
+
+static void
+load_default(struct cf_context *cc)
+{
+ if (cc->config_loaded++)
+ return;
+ if (cf_def_file)
+ {
+ char *env;
+ if (cf_env_file && (env = getenv(cf_env_file)))
+ {
+ if (cf_load(env))
+ die("Cannot load config file %s", env);
+ }
+ else if (cf_load(cf_def_file))
+ die("Cannot load default config %s", cf_def_file);
+ }
+ else
+ {
+ // We need to create an empty pool and initialize all configuration items
+ struct cf_journal_item *oldj = cf_journal_new_transaction(1);
+ cf_init_stack(cc);
+ cf_done_stack(cc);
+ cf_journal_commit_transaction(1, oldj);
+ }
+}
+
+static void
+final_commit(struct cf_context *cc)
+{
+ if (cc->postpone_commit)
+ {
+ cc->postpone_commit = 0;
+ if (cf_done_stack(cc))
+ die("Cannot commit after the initialization");
+ }
+}
+
+int
+cf_getopt(int argc, char *const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
+{
+ struct cf_context *cc = cf_get_context();
+ cc->postpone_commit = 1;
+
+ while (1)
+ {
+ int res = getopt_long(argc, argv, short_opts, long_opts, long_index);
+ if (res == 'S' || res == 'C' || res == 0x64436667)
+ {
+ if (cc->other_options)
+ die("The -S and -C options must precede all other arguments");
+ if (res == 'S')
+ {
+ load_default(cc);
+ if (cf_set(optarg))
+ die("Cannot set %s", optarg);
+ }
+ else if (res == 'C')
+ {
+ if (cf_load(optarg))
+ die("Cannot load config file %s", optarg);
+ }
+#ifdef CONFIG_UCW_DEBUG
+ else
+ { /* --dumpconfig */
+ load_default(cc);
+ final_commit(cc);
+ struct fastbuf *b = bfdopen(1, 4096);
+ cf_dump_sections(b);
+ bclose(b);
+ exit(0);
+ }
+#endif
+ }
+ else
+ {
+ /* unhandled option or end of options */
+ if (res != ':' && res != '?')
+ {
+ load_default(cc);
+ final_commit(cc);
+ }
+ cc->other_options++;
+ return res;
+ }
+ }
+}
#include <ucw/lib.h>
#include <ucw/conf.h>
-#include <ucw/getopt.h>
#include <ucw/conf-internal.h>
#include <ucw/clists.h>
#include <ucw/mempool.h>
return "included from here";
}
-static int
-done_stack(struct cf_context *cc)
-{
- if (cf_check_stack(cc))
- return 1;
- if (cf_commit_all(cc->postpone_commit ? CF_NO_COMMIT : cc->everything_committed ? CF_COMMIT : CF_COMMIT_ALL))
- return 1;
- if (!cc->postpone_commit)
- cc->everything_committed = 1;
- return 0;
-}
-
static int
load_file(struct cf_context *cc, const char *file)
{
}
char *err_msg = parse_fastbuf(cc, file, fb, 0);
bclose(fb);
- return !!err_msg || done_stack(cc);
+ return !!err_msg || cf_done_stack(cc);
}
static int
struct fastbuf fb;
fbbuf_init_read(&fb, (byte *)string, strlen(string), 0);
char *msg = parse_fastbuf(cc, NULL, &fb, 0);
- return !!msg || done_stack(cc);
+ return !!msg || cf_done_stack(cc);
}
/* Safe loading and reloading */
cc->postpone_commit = 0;
if (!err)
- err |= done_stack(cc);
+ err |= cf_done_stack(cc);
if (!err) {
cf_journal_delete();
if (!err) {
cf_journal_commit_transaction(1, oldj);
cf_remember_entry(cc, CE_FILE, file);
- cc->def_loaded = 1;
+ cc->config_loaded = 1;
} else
cf_journal_rollback_transaction(1, oldj);
return err;
cf_journal_rollback_transaction(0, oldj);
return err;
}
-
-/* Command-line parser */
-
-#ifndef CONFIG_UCW_DEFAULT_CONFIG
-#define CONFIG_UCW_DEFAULT_CONFIG NULL
-#endif
-char *cf_def_file = CONFIG_UCW_DEFAULT_CONFIG;
-
-#ifndef CONFIG_UCW_ENV_VAR_CONFIG
-#define CONFIG_UCW_ENV_VAR_CONFIG NULL
-#endif
-char *cf_env_file = CONFIG_UCW_ENV_VAR_CONFIG;
-
-static void
-load_default(struct cf_context *cc)
-{
- if (cc->def_loaded++)
- return;
- if (cf_def_file)
- {
- char *env;
- if (cf_env_file && (env = getenv(cf_env_file)))
- {
- if (cf_load(env))
- die("Cannot load config file %s", env);
- }
- else if (cf_load(cf_def_file))
- die("Cannot load default config %s", cf_def_file);
- }
- else
- {
- // We need to create an empty pool and initialize all configuration items
- struct cf_journal_item *oldj = cf_journal_new_transaction(1);
- cf_init_stack(cc);
- done_stack(cc);
- cf_journal_commit_transaction(1, oldj);
- }
-}
-
-static void
-final_commit(struct cf_context *cc)
-{
- if (cc->postpone_commit) {
- cc->postpone_commit = 0;
- if (done_stack(cc))
- die("Cannot commit after the initialization");
- }
-}
-
-int
-cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index)
-{
- struct cf_context *cc = cf_get_context();
- cc->postpone_commit = 1;
-
- while (1) {
- int res = getopt_long (argc, argv, short_opts, long_opts, long_index);
- if (res == 'S' || res == 'C' || res == 0x64436667)
- {
- if (cc->other_options)
- die("The -S and -C options must precede all other arguments");
- if (res == 'S') {
- load_default(cc);
- if (cf_set(optarg))
- die("Cannot set %s", optarg);
- } else if (res == 'C') {
- if (cf_load(optarg))
- die("Cannot load config file %s", optarg);
- }
-#ifdef CONFIG_UCW_DEBUG
- else { /* --dumpconfig */
- load_default(cc);
- final_commit(cc);
- struct fastbuf *b = bfdopen(1, 4096);
- cf_dump_sections(b);
- bclose(b);
- exit(0);
- }
-#endif
- } else {
- /* unhandled option or end of options */
- if (res != ':' && res != '?') {
- load_default(cc);
- final_commit(cc);
- }
- cc->other_options++;
- return res;
- }
- }
-}
struct cf_context {
struct mempool *pool;
int is_active;
- int def_loaded;
+ int config_loaded; // at least one config file was loaded
struct cf_parser_state *parser;
uns everything_committed; // after the 1st load, this flag is set on
uns postpone_commit; // used internally by cf_getopt()
uns cf_type_size(enum cf_type type, struct cf_user_type *utype);
char *cf_interpret_line(struct cf_context *cc, char *name, enum cf_operation op, int number, char **pars);
void cf_init_stack(struct cf_context *cc);
-int cf_check_stack(struct cf_context *cc);
+int cf_done_stack(struct cf_context *cc);
/* conf-journal.c */
void cf_journal_swap(void);
}
int
-cf_check_stack(struct cf_context *cc)
+cf_done_stack(struct cf_context *cc)
{
if (cc->stack_level > 0) {
msg(L_ERROR, "Unterminated block");
return 1;
}
+ if (cf_commit_all(cc->postpone_commit ? CF_NO_COMMIT : cc->everything_committed ? CF_COMMIT : CF_COMMIT_ALL))
+ return 1;
+ if (!cc->postpone_commit)
+ cc->everything_committed = 1;
return 0;
}
**/
struct cf_context *cf_switch_context(struct cf_context *cc);
+/***
+ * [[conf_load]]
+ * Safe configuration loading
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * These functions can be used to to safely load or reload configuration.
+ */
+
+int cf_reload(const char *file); /** Reload configuration from @file, replace the old one. **/
+int cf_load(const char *file); /** Load configuration from @file. If @file is NULL, reload all loaded configuration files. **/
+/**
+ * Parse some part of configuration passed in @string.
+ * The syntax is the same as in the <<config:,configuration file>>.
+ **/
+int cf_set(const char *string);
+
/*** === Data types [[conf_types]] ***/
enum cf_class { /** Class of the configuration item. **/
* Undo journal
* ~~~~~~~~~~~~
*
- * For error recovery when <<reload,reloading configuration>>.
+ * The configuration system uses journaling to safely reload
+ * configuration. It begins a transaction and tries to load the
+ * configuration. If it fails, it restores the original state.
+ *
+ * The behaviour of journal is described in <<reload,reloading configuration>>.
***/
/**
* By default, the configuration mechanism remembers all changes in a journal,
void cf_journal_block(void *ptr, uns len);
#define CF_JOURNAL_VAR(var) cf_journal_block(&(var), sizeof(var)) // Store single value into journal.
+struct cf_journal_item; /** Opaque identifier of the journal state. **/
+/**
+ * Starts a new transaction. It returns the current state so you can
+ * get back to it. The @new_pool parameter tells if a new memory pool
+ * should be created and used from now.
+ **/
+struct cf_journal_item *cf_journal_new_transaction(uns new_pool);
+/**
+ * Marks current state as a complete transaction. The @new_pool
+ * parameter tells if the transaction was created with new memory pool
+ * (the parameter must be the same as the one with
+ * @cf_journal_new_transaction() was called with). The @oldj parameter
+ * is the journal state returned from last
+ * @cf_journal_new_transaction() call.
+ **/
+void cf_journal_commit_transaction(uns new_pool, struct cf_journal_item *oldj);
+/**
+ * Returns to an old journal state, reverting anything the current
+ * transaction did. The @new_pool parameter must be the same as the
+ * one you used when you created the transaction. The @oldj parameter
+ * is the journal state you got from @cf_journal_new_transaction() --
+ * it is the state to return to.
+ **/
+void cf_journal_rollback_transaction(uns new_pool, struct cf_journal_item *oldj);
+
/***
* [[declare]]
* Section declaration
char *cf_parse_double(const char *str, double *ptr); /** Parser for doubles. **/
char *cf_parse_ip(const char *p, u32 *varp); /** Parser for IP addresses. **/
+/***
+ * [[conf_direct]]
+ * Direct access
+ * ~~~~~~~~~~~~~
+ *
+ * Direct access to configuration items.
+ * You probably should not need this.
+ ***/
+
+/**
+ * List of operations used on items.
+ * This macro is used to generate internal source code,
+ * but you may be interested in the list of operations it creates.
+ *
+ * Each operation corresponds to the same-named operation
+ * described in <<config:operations,configuration syntax>>.
+ **/
+#define CF_OPERATIONS T(CLOSE) T(SET) T(CLEAR) T(ALL) \
+ T(APPEND) T(PREPEND) T(REMOVE) T(EDIT) T(AFTER) T(BEFORE) T(COPY) T(RESET)
+ /* Closing brace finishes previous block.
+ * Basic attributes (static, dynamic, parsed) can be used with SET.
+ * Dynamic arrays can be used with SET, APPEND, PREPEND.
+ * Sections can be used with SET.
+ * Lists can be used with everything. */
+#define T(x) OP_##x,
+enum cf_operation { CF_OPERATIONS }; /** Allowed operations on items. See <<def_CF_OPERATIONS,`CF_OPERATIONS`>> for list (they have an `OP_` prefix -- it means you use `OP_SET` instead of just `SET`). **/
+#undef T
+
+/**
+ * Searches for a configuration item called @name.
+ * If it is found, it is copied into @item and NULL is returned.
+ * Otherwise, an error is returned and @item is zeroed.
+ **/
+char *cf_find_item(const char *name, struct cf_item *item);
+/**
+ * Performs a single operation on a given item.
+ **/
+char *cf_modify_item(struct cf_item *item, enum cf_operation op, int number, char **pars);
+
+/***
+ * [[conf_dump]]
+ * Debug dumping
+ * ~~~~~~~~~~~~~
+ ***/
+
+struct fastbuf;
+/**
+ * Take everything and write it into @fb.
+ **/
+void cf_dump_sections(struct fastbuf *fb);
+
#endif
* UCW Library -- Parsing of configuration and command-line options
*
* (c) 2001--2006 Robert Spalek <robert@ucw.cz>
- * (c) 2003--2006 Martin Mares <mj@ucw.cz>
+ * (c) 2003--2012 Martin Mares <mj@ucw.cz>
*
* This software may be freely distributed and used according to the terms
* of the GNU Lesser General Public License.
#include <getopt.h>
#endif
-void reset_getopt(void); /** If you want to start parsing of the arguments from the first one again. **/
-
/***
- * [[conf_load]]
- * Safe configuration loading
- * ~~~~~~~~~~~~~~~~~~~~~~~~~~
- *
- * These functions can be used to to safely load or reload configuration.
- */
+ * [[conf_getopt]]
+ * Loading by @cf_getopt()
+ * ~~~~~~~~~~~~~~~~~~~~~~~
+ ***/
/**
* The default config (as set by `CONFIG_UCW_DEFAULT_CONFIG`) or NULL if already loaded.
* Defaults to `CONFIG_UCW_ENV_VAR_CONFIG`.
**/
extern char *cf_env_file;
-int cf_reload(const char *file); /** Reload configuration from @file, replace the old one. **/
-int cf_load(const char *file); /** Load configuration from @file. If @file is NULL, reload all loaded configuration files. **/
-/**
- * Parse some part of configuration passed in @string.
- * The syntax is the same as in the <<config:,configuration file>>.
- **/
-int cf_set(const char *string);
-
-/***
- * [[conf_direct]]
- * Direct access
- * ~~~~~~~~~~~~~
- *
- * Direct access to configuration items.
- * You probably should not need this.
- ***/
-
-/**
- * List of operations used on items.
- * This macro is used to generate internal source code,
- * but you may be interested in the list of operations it creates.
- *
- * Each operation corresponds to the same-named operation
- * described in <<config:operations,configuration syntax>>.
- **/
-#define CF_OPERATIONS T(CLOSE) T(SET) T(CLEAR) T(ALL) \
- T(APPEND) T(PREPEND) T(REMOVE) T(EDIT) T(AFTER) T(BEFORE) T(COPY) T(RESET)
- /* Closing brace finishes previous block.
- * Basic attributes (static, dynamic, parsed) can be used with SET.
- * Dynamic arrays can be used with SET, APPEND, PREPEND.
- * Sections can be used with SET.
- * Lists can be used with everything. */
-#define T(x) OP_##x,
-enum cf_operation { CF_OPERATIONS }; /** Allowed operations on items. See <<def_CF_OPERATIONS,`CF_OPERATIONS`>> for list (they have an `OP_` prefix -- it means you use `OP_SET` instead of just `SET`). **/
-#undef T
-
-struct cf_item;
-/**
- * Searches for a configuration item called @name.
- * If it is found, it is copied into @item and NULL is returned.
- * Otherwise, an error is returned and @item is zeroed.
- **/
-char *cf_find_item(const char *name, struct cf_item *item);
-/**
- * Performs a single operation on a given item.
- **/
-char *cf_modify_item(struct cf_item *item, enum cf_operation op, int number, char **pars);
-
-/***
- * [[conf_dump]]
- * Debug dumping
- * ~~~~~~~~~~~~~
- ***/
-
-struct fastbuf;
-/**
- * Take everything and write it into @fb.
- **/
-void cf_dump_sections(struct fastbuf *fb);
-
-/***
- * [[conf_journal]]
- * Journaling control
- * ~~~~~~~~~~~~~~~~~~
- *
- * The configuration system uses journaling to safely reload
- * configuration. It begins a transaction and tries to load the
- * configuration. If it fails, it restores the original state.
- *
- * The behaviour of journal is described in <<reload,reloading configuration>>.
- ***/
-
-struct cf_journal_item; /** Opaque identifier of the journal state. **/
-/**
- * Starts a new transaction. It returns the current state so you can
- * get back to it. The @new_pool parameter tells if a new memory pool
- * should be created and used from now.
- **/
-struct cf_journal_item *cf_journal_new_transaction(uns new_pool);
-/**
- * Marks current state as a complete transaction. The @new_pool
- * parameter tells if the transaction was created with new memory pool
- * (the parameter must be the same as the one with
- * @cf_journal_new_transaction() was called with). The @oldj parameter
- * is the journal state returned from last
- * @cf_journal_new_transaction() call.
- **/
-void cf_journal_commit_transaction(uns new_pool, struct cf_journal_item *oldj);
-/**
- * Returns to an old journal state, reverting anything the current
- * transaction did. The @new_pool parameter must be the same as the
- * one you used when you created the transaction. The @oldj parameter
- * is the journal state you got from @cf_journal_new_transaction() --
- * it is the state to return to.
- **/
-void cf_journal_rollback_transaction(uns new_pool, struct cf_journal_item *oldj);
-
-/***
- * [[conf_getopt]]
- * Loading by @cf_getopt()
- * ~~~~~~~~~~~~~~~~~~~~~~~
- ***/
-
/**
* Short options for loading configuration by @cf_getopt().
* Prepend to your own options.
**/
int cf_getopt(int argc, char * const argv[], const char *short_opts, const struct option *long_opts, int *long_index);
+void reset_getopt(void); /** If you want to start parsing of the arguments from the first one again. **/
+
#endif