From 39be24697a20fb48ad1607c2ae667d427249af27 Mon Sep 17 00:00:00 2001 From: David Herrmann Date: Sat, 11 Aug 2012 21:50:41 +0200 Subject: [PATCH] conf: make config functions take conf-options as arguments This replaces the global conf-options array with a parameter so we can use the config parsers with different argument-lists. Signed-off-by: David Herrmann --- src/conf.c | 226 ++++++++++++----------------------------------------- src/conf.h | 9 ++- src/main.c | 140 +++++++++++++++++++++++++++++++-- 3 files changed, 189 insertions(+), 186 deletions(-) diff --git a/src/conf.c b/src/conf.c index e527c42..f0dd48c 100644 --- a/src/conf.c +++ b/src/conf.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include @@ -43,70 +42,6 @@ #define LOG_SUBSYSTEM "config" struct conf_obj conf_global; -static char *def_argv[] = { NULL, "-i", NULL }; - -static void print_help() -{ - /* - * Usage/Help information - * This should be scaled to a maximum of 80 characters per line: - * - * 80 char line: - * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | - * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" - * 80 char line starting with tab: - * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 | - * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n" - */ - fprintf(stderr, - "Usage:\n" - "\t%1$s [options]\n" - "\t%1$s -h [options]\n" - "\t%1$s -l [options] -- /bin/sh [sh-arguments]\n" - "\n" - "You can prefix boolean options with \"no-\" to negate it. If an argument is\n" - "given multiple times, only the last argument matters if not otherwise stated.\n" - "\n" - "General Options:\n" - "\t-h, --help [off] Print this help and exit\n" - "\t-v, --verbose [off] Print verbose messages\n" - "\t --debug [off] Enable debug mode\n" - "\t --silent [off] Suppress notices and warnings\n" - "\t-s, --switchvt [off] Automatically switch to VT\n" - "\t --seat [seat0] Select seat; default: seat0\n" - "\n" - "Terminal Options:\n" - "\t-l, --login [/bin/sh]\n" - "\t Start the given login process instead\n" - "\t of the default process; all arguments\n" - "\t following '--' will be be parsed as\n" - "\t argv to this process. No more options\n" - "\t after '--' will be parsed so use it at\n" - "\t the end of the argument string\n" - "\t-t, --term [vt220]\n" - "\t Value of the TERM environment variable\n" - "\t for the child process\n" - "\n" - "Video Options:\n" - "\t --fbdev [off] Use fbdev instead of DRM\n" - "\n" - "Input Device Options:\n" - "\t --xkb-layout [us] Set XkbLayout for input devices\n" - "\t --xkb-variant [-] Set XkbVariant for input devices\n" - "\t --xkb-options [-] Set XkbOptions for input devices\n" - "\n" - "Font Options:\n" - "\t --font-engine [pango] Font engine\n", - "kmscon"); - /* - * 80 char line: - * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | - * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" - * 80 char line starting with tab: - * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 | - * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n" - */ -} void conf_free_value(struct conf_option *opt) { @@ -155,79 +90,15 @@ const struct conf_type conf_string = { .set_default = conf_default_string, }; -static int aftercheck_debug(struct conf_option *opt, int argc, char **argv, - int idx) -{ - /* --debug implies --verbose */ - if (conf_global.debug) - conf_global.verbose = 1; - - return 0; -} - -static int aftercheck_help(struct conf_option *opt, int argc, char **argv, - int idx) -{ - /* exit after printing --help information */ - if (conf_global.help) { - print_help(); - conf_global.exit = true; - } - - return 0; -} - -static int aftercheck_login(struct conf_option *opt, int argc, char **argv, - int idx) -{ - int ret; - - /* parse "--login [...] -- args" arguments */ - if (conf_global.login) { - if (idx >= argc) { - fprintf(stderr, "Arguments for --login missing\n"); - return -EFAULT; - } - - conf_global.argv = &argv[idx]; - ret = argc - idx; - } else { - def_argv[0] = getenv("SHELL") ? : _PATH_BSHELL; - conf_global.argv = def_argv; - ret = 0; - } - - return ret; -} - -struct conf_option options[] = { - CONF_OPTION_BOOL('h', "help", aftercheck_help, &conf_global.help, false), - CONF_OPTION_BOOL('v', "verbose", NULL, &conf_global.verbose, false), - CONF_OPTION_BOOL(0, "debug", aftercheck_debug, &conf_global.debug, false), - CONF_OPTION_BOOL(0, "silent", NULL, &conf_global.silent, false), - CONF_OPTION_BOOL(0, "fbdev", NULL, &conf_global.use_fbdev, false), - CONF_OPTION_BOOL('s', "switchvt", NULL, &conf_global.switchvt, false), - CONF_OPTION_BOOL('l', "login", aftercheck_login, &conf_global.login, false), - CONF_OPTION_STRING('t', "term", NULL, &conf_global.term, "vt220"), - CONF_OPTION_STRING(0, "xkb-layout", NULL, &conf_global.xkb_layout, "us"), - CONF_OPTION_STRING(0, "xkb-variant", NULL, &conf_global.xkb_variant, ""), - CONF_OPTION_STRING(0, "xkb-options", NULL, &conf_global.xkb_options, ""), - CONF_OPTION_STRING(0, "seat", NULL, &conf_global.seat, "seat0"), - CONF_OPTION_STRING(0, "font-engine", NULL, &conf_global.font_engine, "pango"), -}; - /* free all memory that we allocated and reset to initial state */ -void conf_free(void) +void conf_free(struct conf_option *opts, size_t len) { - unsigned int i, num; + unsigned int i; - num = sizeof(options) / sizeof(*options); - for (i = 0; i < num; ++i) { - if (options[i].type->free) - options[i].type->free(&options[i]); + for (i = 0; i < len; ++i) { + if (opts[i].type->free) + opts[i].type->free(&opts[i]); } - - memset(&conf_global, 0, sizeof(conf_global)); } /* @@ -236,19 +107,18 @@ void conf_free(void) * can use the getopt_long() library call. It locks all arguments after they * have been set so command-line options will always overwrite config-options. */ -int conf_parse_argv(int argc, char **argv) +int conf_parse_argv(struct conf_option *opts, size_t len, + int argc, char **argv) { char *short_options; struct option *long_options; struct option *opt; - size_t len, i, pos; + size_t i, pos; int c, ret; if (!argv || argc < 1) return -EINVAL; - len = sizeof(options) / sizeof(*options); - short_options = malloc(sizeof(char) * (len + 1) * 2); if (!short_options) { log_error("cannot allocate enough memory to parse command line arguments (%d): %m"); @@ -266,23 +136,23 @@ int conf_parse_argv(int argc, char **argv) short_options[pos++] = ':'; opt = long_options; for (i = 0; i < len; ++i) { - if (options[i].short_name) { - short_options[pos++] = options[i].short_name; - if (options[i].type->flags & CONF_HAS_ARG) + if (opts[i].short_name) { + short_options[pos++] = opts[i].short_name; + if (opts[i].type->flags & CONF_HAS_ARG) short_options[pos++] = ':'; } - if (options[i].long_name) { + if (opts[i].long_name) { /* skip the "no-" prefix */ - opt->name = &options[i].long_name[3]; - opt->has_arg = !!(options[i].type->flags & CONF_HAS_ARG); + opt->name = &opts[i].long_name[3]; + opt->has_arg = !!(opts[i].type->flags & CONF_HAS_ARG); opt->flag = NULL; opt->val = 100000 + i; ++opt; /* boolean args are also added with "no-" prefix */ - if (!(options[i].type->flags & CONF_HAS_ARG)) { - opt->name = options[i].long_name; + if (!(opts[i].type->flags & CONF_HAS_ARG)) { + opt->name = opts[i].long_name; opt->has_arg = 0; opt->flag = NULL; opt->val = 200000 + i; @@ -315,31 +185,31 @@ int conf_parse_argv(int argc, char **argv) return -EFAULT; } else if (c < 100000) { for (i = 0; i < len; ++i) { - if (options[i].short_name == c) { - ret = options[i].type->parse(&options[i], - true, - optarg); + if (opts[i].short_name == c) { + ret = opts[i].type->parse(&opts[i], + true, + optarg); if (ret) return ret; - options[i].flags |= CONF_LOCKED; - options[i].flags |= CONF_DONE; + opts[i].flags |= CONF_LOCKED; + opts[i].flags |= CONF_DONE; break; } } } else if (c < 200000) { i = c - 100000; - ret = options[i].type->parse(&options[i], true, optarg); + ret = opts[i].type->parse(&opts[i], true, optarg); if (ret) return ret; - options[i].flags |= CONF_LOCKED; - options[i].flags |= CONF_DONE; + opts[i].flags |= CONF_LOCKED; + opts[i].flags |= CONF_DONE; } else { i = c - 200000; - ret = options[i].type->parse(&options[i], false, NULL); + ret = opts[i].type->parse(&opts[i], false, NULL); if (ret) return ret; - options[i].flags |= CONF_LOCKED; - options[i].flags |= CONF_DONE; + opts[i].flags |= CONF_LOCKED; + opts[i].flags |= CONF_DONE; } } @@ -348,9 +218,9 @@ int conf_parse_argv(int argc, char **argv) /* set default values if not configured */ for (i = 0; i < len; ++i) { - if (!(options[i].flags & CONF_DONE) && - options[i].type->set_default) { - options[i].type->set_default(&options[i]); + if (!(opts[i].flags & CONF_DONE) && + opts[i].type->set_default) { + opts[i].type->set_default(&opts[i]); } } @@ -365,8 +235,8 @@ int conf_parse_argv(int argc, char **argv) * arguments passed in. If not all arguments are consumed, then this * function will report an error to the caller. */ for (i = 0; i < len; ++i) { - if (options[i].aftercheck) { - ret = options[i].aftercheck(&options[i], argc, argv, optind); + if (opts[i].aftercheck) { + ret = opts[i].aftercheck(&opts[i], argc, argv, optind); if (ret < 0) return ret; optind += ret; @@ -382,16 +252,16 @@ int conf_parse_argv(int argc, char **argv) return 0; } -static int parse_kv_pair(const char *key, const char *value) +static int parse_kv_pair(struct conf_option *opts, size_t len, + const char *key, const char *value) { - unsigned int i, num; + unsigned int i; int ret; bool set; struct conf_option *opt; - num = sizeof(options) / sizeof(*options); - for (i = 0; i < num; ++i) { - opt = &options[i]; + for (i = 0; i < len; ++i) { + opt = &opts[i]; if (!opt->long_name) continue; @@ -446,7 +316,8 @@ static void strip_spaces(char **buf) *tail-- = 0; } -static int parse_line(char **buf, size_t *size) +static int parse_line(struct conf_option *opts, size_t olen, + char **buf, size_t *size) { char *key; char *value = NULL; @@ -527,7 +398,7 @@ done: if (value) strip_spaces(&value); - ret = parse_kv_pair(key, value); + ret = parse_kv_pair(opts, olen, key, value); if (ret) return ret; } @@ -543,12 +414,13 @@ done: return 0; } -static int parse_buffer(char *buf, size_t size) +static int parse_buffer(struct conf_option *opts, size_t len, + char *buf, size_t size) { int ret = 0; while (!ret && size > 0) - ret = parse_line(&buf, &size); + ret = parse_line(opts, len, &buf, &size); return ret; } @@ -558,7 +430,7 @@ static int parse_buffer(char *buf, size_t size) /* This reads the file at \path in memory and parses it as if it was given as * command line options. */ -int conf_parse_file(const char *path) +int conf_parse_file(struct conf_option *opts, size_t len, const char *path) { int fd, ret; size_t size, pos; @@ -602,7 +474,7 @@ int conf_parse_file(const char *path) } while (ret > 0); buf[pos] = 0; - ret = parse_buffer(buf, pos); + ret = parse_buffer(opts, len, buf, pos); out_free: free(buf); @@ -610,7 +482,7 @@ out_free: return ret; } -int conf_parse_all_files(void) +int conf_parse_all_files(struct conf_option *opts, size_t len) { int ret; const char *file, *home; @@ -624,7 +496,7 @@ int conf_parse_all_files(void) log_warning("config file %s exists but read access was denied", file); else - ret = conf_parse_file(file); + ret = conf_parse_file(opts, len, file); } if (ret) @@ -643,7 +515,7 @@ int conf_parse_all_files(void) log_warning("config file %s exists but read access was denied", path); else - ret = conf_parse_file(path); + ret = conf_parse_file(opts, len, path); } free(path); } diff --git a/src/conf.h b/src/conf.h index 38dc68a..64b320b 100644 --- a/src/conf.h +++ b/src/conf.h @@ -138,9 +138,10 @@ void conf_default_string(struct conf_option *opt); extern const struct conf_type conf_bool; extern const struct conf_type conf_string; -void conf_free(void); -int conf_parse_argv(int argc, char **argv); -int conf_parse_file(const char *path); -int conf_parse_all_files(void); +void conf_free(struct conf_option *opts, size_t len); +int conf_parse_argv(struct conf_option *opts, size_t len, + int argc, char **argv); +int conf_parse_file(struct conf_option *opts, size_t len, const char *path); +int conf_parse_all_files(struct conf_option *opts, size_t len); #endif /* CONFIG_CONFIG_H */ diff --git a/src/main.c b/src/main.c index ffb90e1..05ea650 100644 --- a/src/main.c +++ b/src/main.c @@ -24,8 +24,10 @@ */ #include +#include #include #include +#include #include #include #include @@ -350,17 +352,145 @@ err_app: return ret; } +static void print_help() +{ + /* + * Usage/Help information + * This should be scaled to a maximum of 80 characters per line: + * + * 80 char line: + * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | + * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" + * 80 char line starting with tab: + * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 | + * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n" + */ + fprintf(stderr, + "Usage:\n" + "\t%1$s [options]\n" + "\t%1$s -h [options]\n" + "\t%1$s -l [options] -- /bin/sh [sh-arguments]\n" + "\n" + "You can prefix boolean options with \"no-\" to negate it. If an argument is\n" + "given multiple times, only the last argument matters if not otherwise stated.\n" + "\n" + "General Options:\n" + "\t-h, --help [off] Print this help and exit\n" + "\t-v, --verbose [off] Print verbose messages\n" + "\t --debug [off] Enable debug mode\n" + "\t --silent [off] Suppress notices and warnings\n" + "\t-s, --switchvt [off] Automatically switch to VT\n" + "\t --seat [seat0] Select seat; default: seat0\n" + "\n" + "Terminal Options:\n" + "\t-l, --login [/bin/sh]\n" + "\t Start the given login process instead\n" + "\t of the default process; all arguments\n" + "\t following '--' will be be parsed as\n" + "\t argv to this process. No more options\n" + "\t after '--' will be parsed so use it at\n" + "\t the end of the argument string\n" + "\t-t, --term [vt220]\n" + "\t Value of the TERM environment variable\n" + "\t for the child process\n" + "\n" + "Video Options:\n" + "\t --fbdev [off] Use fbdev instead of DRM\n" + "\n" + "Input Device Options:\n" + "\t --xkb-layout [us] Set XkbLayout for input devices\n" + "\t --xkb-variant [-] Set XkbVariant for input devices\n" + "\t --xkb-options [-] Set XkbOptions for input devices\n" + "\n" + "Font Options:\n" + "\t --font-engine [pango] Font engine\n", + "kmscon"); + /* + * 80 char line: + * | 10 | 20 | 30 | 40 | 50 | 60 | 70 | 80 | + * "12345678901234567890123456789012345678901234567890123456789012345678901234567890\n" + * 80 char line starting with tab: + * |10| 20 | 30 | 40 | 50 | 60 | 70 | 80 | + * "\t901234567890123456789012345678901234567890123456789012345678901234567890\n" + */ +} + +static int aftercheck_debug(struct conf_option *opt, int argc, char **argv, + int idx) +{ + /* --debug implies --verbose */ + if (conf_global.debug) + conf_global.verbose = 1; + + return 0; +} + +static int aftercheck_help(struct conf_option *opt, int argc, char **argv, + int idx) +{ + /* exit after printing --help information */ + if (conf_global.help) { + print_help(); + conf_global.exit = true; + } + + return 0; +} + +static char *def_argv[] = { NULL, "-i", NULL }; + +static int aftercheck_login(struct conf_option *opt, int argc, char **argv, + int idx) +{ + int ret; + + /* parse "--login [...] -- args" arguments */ + if (conf_global.login) { + if (idx >= argc) { + fprintf(stderr, "Arguments for --login missing\n"); + return -EFAULT; + } + + conf_global.argv = &argv[idx]; + ret = argc - idx; + } else { + def_argv[0] = getenv("SHELL") ? : _PATH_BSHELL; + conf_global.argv = def_argv; + ret = 0; + } + + return ret; +} + +struct conf_option options[] = { + CONF_OPTION_BOOL('h', "help", aftercheck_help, &conf_global.help, false), + CONF_OPTION_BOOL('v', "verbose", NULL, &conf_global.verbose, false), + CONF_OPTION_BOOL(0, "debug", aftercheck_debug, &conf_global.debug, false), + CONF_OPTION_BOOL(0, "silent", NULL, &conf_global.silent, false), + CONF_OPTION_BOOL(0, "fbdev", NULL, &conf_global.use_fbdev, false), + CONF_OPTION_BOOL('s', "switchvt", NULL, &conf_global.switchvt, false), + CONF_OPTION_BOOL('l', "login", aftercheck_login, &conf_global.login, false), + CONF_OPTION_STRING('t', "term", NULL, &conf_global.term, "vt220"), + CONF_OPTION_STRING(0, "xkb-layout", NULL, &conf_global.xkb_layout, "us"), + CONF_OPTION_STRING(0, "xkb-variant", NULL, &conf_global.xkb_variant, ""), + CONF_OPTION_STRING(0, "xkb-options", NULL, &conf_global.xkb_options, ""), + CONF_OPTION_STRING(0, "seat", NULL, &conf_global.seat, "seat0"), + CONF_OPTION_STRING(0, "font-engine", NULL, &conf_global.font_engine, "pango"), +}; + int main(int argc, char **argv) { int ret; struct kmscon_app app; + size_t onum; - ret = conf_parse_argv(argc, argv); + onum = sizeof(options) / sizeof(*options); + ret = conf_parse_argv(options, onum, argc, argv); if (ret) goto err_out; if (conf_global.exit) { - conf_free(); + conf_free(options, onum); return EXIT_SUCCESS; } @@ -372,7 +502,7 @@ int main(int argc, char **argv) log_print_init("kmscon"); - ret = conf_parse_all_files(); + ret = conf_parse_all_files(options, onum); if (ret) goto err_out; @@ -415,7 +545,7 @@ int main(int argc, char **argv) kmscon_font_freetype2_unload(); kmscon_font_pango_unload(); kmscon_font_8x16_unload(); - conf_free(); + conf_free(options, onum); log_info("exiting"); return EXIT_SUCCESS; @@ -427,7 +557,7 @@ err_unload: kmscon_font_pango_unload(); kmscon_font_8x16_unload(); err_out: - conf_free(); + conf_free(options, onum); log_err("cannot initialize kmscon, errno %d: %s", ret, strerror(-ret)); return -ret; }