kmod_config: parse kernel command line for options and blacklist
authorLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 14 Dec 2011 19:19:19 +0000 (17:19 -0200)
committerLucas De Marchi <lucas.demarchi@profusion.mobi>
Wed, 14 Dec 2011 19:19:19 +0000 (17:19 -0200)
TODO
libkmod/libkmod-config.c
libkmod/libkmod-private.h

diff --git a/TODO b/TODO
index 28b4fcd..4d85327 100644 (file)
--- a/TODO
+++ b/TODO
@@ -25,8 +25,6 @@ Features:
 
 * Implement soft dependencies
 
-* Parse kernel command line (modname.opt=val)
-
 * provide 1:1 compatibility with module-init-tools's modprobe
    - show modversions (needs elf manipulation)
    - dump configuration
index 44fad72..d36f17f 100644 (file)
@@ -242,6 +242,67 @@ static void kmod_config_free_blacklist(struct kmod_config *config,
        config->blacklists = kmod_list_remove(l);
 }
 
+static void kcmdline_parse_result(struct kmod_config *config, char *modname,
+                                               char *param, char *value)
+{
+       if (modname == NULL || param == NULL || value == NULL)
+               return;
+
+       DBG(config->ctx, "%s %s\n", modname, param);
+
+       if (streq(modname, "modprobe") && !strncmp(param, "blacklist=", 10)) {
+               for (;;) {
+                       char *t = strsep(&value, ",");
+                       if (t == NULL)
+                               break;
+
+                       kmod_config_add_blacklist(config, t);
+               }
+       } else {
+               kmod_config_add_options(config,
+                               underscores(config->ctx, modname), param);
+       }
+}
+
+static int kmod_config_parse_kcmdline(struct kmod_config *config)
+{
+       char buf[KCMD_LINE_SIZE];
+       int fd, err;
+       char *p, *modname,  *param = NULL, *value = NULL;
+
+       fd = open("/proc/cmdline", O_RDONLY);
+       err = read_str_safe(fd, buf, sizeof(buf));
+       close(fd);
+       if (err < 0) {
+               ERR(config->ctx, "could not read from '/proc/cmdline': %s\n",
+                                                       strerror(-err));
+               return err;
+       }
+
+       for (p = buf, modname = buf; *p != '\0' && *p != '\n'; p++) {
+               switch (*p) {
+               case ' ':
+                       *p = '\0';
+                       kcmdline_parse_result(config, modname, param, value);
+                       param = value = NULL;
+                       modname = p + 1;
+                       break;
+               case '.':
+                       *p = '\0';
+                       param = p + 1;
+                       break;
+               case '=':
+                       value = p + 1;
+                       break;
+               }
+       }
+
+       *p = '\0';
+       kcmdline_parse_result(config, modname, param, value);
+
+       return 0;
+}
+
 /*
  * Take an fd and own it. It will be closed on return. filename is used only
  * for debug messages
@@ -513,5 +574,7 @@ int kmod_config_new(struct kmod_ctx *ctx, struct kmod_config **p_config,
                closedir(d);
        }
 
+       kmod_config_parse_kcmdline(config);
+
        return 0;
 }
index c22e805..6c6abca 100644 (file)
@@ -34,6 +34,8 @@ static __always_inline __printf_format(2, 3) void
 
 #define KMOD_EXPORT __attribute__ ((visibility("default")))
 
+#define KCMD_LINE_SIZE 4096
+
 void kmod_log(const struct kmod_ctx *ctx,
                int priority, const char *file, int line, const char *fn,
                const char *format, ...) __attribute__((format(printf, 6, 7))) __attribute__((nonnull(1, 3, 5)));