conf: make config functions take conf-options as arguments
authorDavid Herrmann <dh.herrmann@googlemail.com>
Sat, 11 Aug 2012 19:50:41 +0000 (21:50 +0200)
committerDavid Herrmann <dh.herrmann@googlemail.com>
Sat, 11 Aug 2012 19:50:41 +0000 (21:50 +0200)
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 <dh.herrmann@googlemail.com>
src/conf.c
src/conf.h
src/main.c

index e527c42..f0dd48c 100644 (file)
@@ -31,7 +31,6 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <getopt.h>
-#include <paths.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
 #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 <seat-name>      [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 <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 <layout>   [us]    Set XkbLayout for input devices\n"
-               "\t    --xkb-variant <variant> [-]     Set XkbVariant for input devices\n"
-               "\t    --xkb-options <options> [-]     Set XkbOptions for input devices\n"
-               "\n"
-               "Font Options:\n"
-               "\t    --font-engine <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);
                }
index 38dc68a..64b320b 100644 (file)
@@ -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 */
index ffb90e1..05ea650 100644 (file)
  */
 
 #include <errno.h>
+#include <paths.h>
 #include <signal.h>
 #include <stdbool.h>
+#include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include <sys/signalfd.h>
@@ -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 <seat-name>      [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 <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 <layout>   [us]    Set XkbLayout for input devices\n"
+               "\t    --xkb-variant <variant> [-]     Set XkbVariant for input devices\n"
+               "\t    --xkb-options <options> [-]     Set XkbOptions for input devices\n"
+               "\n"
+               "Font Options:\n"
+               "\t    --font-engine <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;
 }