devfs
[Top] [All Lists]

[PATCH] configuration for modprobe

To: devfs@xxxxxxxxxxx
Subject: [PATCH] configuration for modprobe
From: Yann Droneaud <ydroneaud@xxxxxxxxxxx>
Date: Sat, 17 Nov 2001 00:09:07 +0100
Sender: owner-devfs@xxxxxxxxxxx
Hi,
here is a quite big patch against devfsd v1.3.18.
This enable user to select which modprobe to use,
This also let the user specify arguments to pass to it.
 The config options could be put in devfsd.conf or on command line.
 Command line options have a higher priority.

Also some Makefile little tweaks

This work perfectly for me (with a patch against modprobe 
to make it use syslog(), the patch was sent to the modutils team).

Feel free to use it as is, or make any modification to my code.

--
Yann Droneaud <ydroneaud@xxxxxxxxxxx>

================ patch-devfsd-meuh-modprobe-arguments =========================
diff -ur devfsd-1.3.18/GNUmakefile devfsd-1.3.18-meuh/GNUmakefile
--- devfsd-1.3.18/GNUmakefile   Sat Aug 18 19:50:39 2001
+++ devfsd-1.3.18-meuh/GNUmakefile      Fri Nov 16 22:12:20 2001
@@ -16,14 +16,16 @@
 
 OBJECTS = devfsd.o expression.o compat_name.o
 
+CC = gcc
+CFLAGS = -g -O2 -W -Wall 
+CFLAGS += -I.
 ifdef KERNEL_DIR
-CFLAGS = -O2 -I. -I$(KERNEL_DIR)/include -Wall $(CEXTRAS) $(DEFINES)
-else
-CFLAGS = -O2 -I. -Wall $(CEXTRAS) $(DEFINES)
+CFLAGS += -I$(KERNEL_DIR)/include 
 endif
+CFLAGS += $(CEXTRAS) $(DEFINES)
 
 devfsd:        $(OBJECTS)
-       cc -O2 -o devfsd $(OBJECTS) $(LDFLAGS) -export-dynamic -ldl
+       $(CC) $(CFLAGS) -o devfsd $(OBJECTS) $(LDFLAGS) -export-dynamic -ldl
 
 install: devfsd
        @if fgrep -q "Generic section: do not change" /etc/modules.conf ; then\
diff -ur devfsd-1.3.18/devfsd.c devfsd-1.3.18-meuh/devfsd.c
--- devfsd-1.3.18/devfsd.c      Mon Aug 20 02:12:21 2001
+++ devfsd-1.3.18-meuh/devfsd.c Fri Nov 16 23:36:44 2001
@@ -206,11 +206,13 @@
     Updated by      Richard Gooch   18-AUG-2001: Dynamically load libnsl at
   run-time as needed, rather than linking. Based on patch from Adam J. Richter.
 
-    Last updated by Richard Gooch   19-AUG-2001: Switched to stat(2) in
+    Updated by      Richard Gooch   19-AUG-2001: Switched to stat(2) in
   <action_permissions> to avoid harmless false positives. Return 0 instead of
   exiting if passwd or group entry not found in database. Do not exit in
   <action_execute> if fork(2) fails.
 
+   Last updated by Yann Droneaud <ydroneaud@xxxxxxxxxxx> 16-NOV-2001: support 
for
+  modprobe configuration (which modprobe use and with what parameters)
 
 */
 #define _GNU_SOURCE
@@ -247,8 +249,10 @@
 #  define RTLD_DEFAULT RTLD_NEXT
 #endif
 
+#define MODPROBE    "/sbin/modprobe"
 #define CONFIG_FILE "/etc/devfsd.conf"
-#define MAX_ARGS (6 + 1)
+#define MAX_ARGS     (6 + 1)
+#define MAX_ARGV_ARGS 16 /* number of arguments passed to modprobe */
 #define MAX_SUBEXPR  10
 
 /*  Update only after changing code to reflect new protocol  */
@@ -287,7 +291,7 @@
 
 struct execute_type
 {
-    char *argv[MAX_ARGS + 1];  /*  argv[0] must always be the programme  */
+    char *argv[MAX_ARGS + 1];  /*  argv[0] must always be the program  */
 };
 
 struct call_function_type
@@ -343,6 +347,21 @@
     struct shared_object *next;
 };
 
+struct modprobe
+{
+  flag verbose_option; /* on command line/devfsd.conf/env */
+  flag verbose_config;  
+
+  char path_option[STRING_LENGTH];
+  char path_config[STRING_LENGTH];
+  char path[STRING_LENGTH];
+
+  int argc;
+  char *argv[MAX_ARGV_ARGS + 1];
+  char extra_argv[MAX_ARGV_ARGS + 1][STRING_LENGTH]; /* for extra params in 
config file */
+
+  int (*func) (int argc, char **argv);
+};
 
 /*  External functions  */
 EXTERN_FUNCTION (flag st_expr_expand,
@@ -415,6 +434,21 @@
 
 
 /*  Private data  */
+static struct modprobe modprobe =
+{
+  verbose_option: -1,
+  verbose_config: -1,
+  path_option: "",
+  path_config: "",
+  path: "",
+
+  argc: 0,
+  argv: { NULL },
+  extra_argv: { "", "" },
+
+  func: NULL,
+};
+
 static struct config_entry_struct *first_config = NULL;
 static struct config_entry_struct *last_config = NULL;
 static struct shared_object *first_so = NULL;
@@ -452,7 +486,7 @@
     unsigned long event_mask = 0;
     struct sigaction new_action;
     struct stat statbuf;
-    static char usage[] = "devfsd mntpnt [-v] [-d] [-t num] [-D mask] [-fg] 
[-np]";
+    static char usage[] = "devfsd mntpnt [-v] [-d] [-t num] [-D mask] [-fg] 
[-np] [-m[nv|v] [modprobe]]";
 
     if (argc < 2)
     {
@@ -476,6 +510,22 @@
        }
        else if (strcmp (argv[count], "-fg") == 0) do_daemon = FALSE;
        else if (strcmp (argv[count], "-np") == 0) no_polling = TRUE;
+       else if (strcmp (argv[count], "-mnv") == 0) /* modprobe non verbose */
+       { 
+           modprobe.verbose_option = FALSE;
+           if ((count + 1) < argc && argv[count + 1][0] != '-')
+             strncpy(modprobe.path_option, argv[++count], STRING_LENGTH);
+       }
+       else if (strcmp (argv[count], "-mv") == 0) /* modprobe verbose */
+       { 
+           modprobe.verbose_option = TRUE;
+           if ((count + 1) < argc && argv[count + 1][0] != '-')
+             strncpy(modprobe.path_option, argv[++count], STRING_LENGTH);
+       }
+       else if ( (strcmp (argv[count], "-m") == 0) && (++count < argc) ) /* 
modprobe */
+       {
+            strncpy(modprobe.path_option, argv[count], STRING_LENGTH);
+        }
        else
        {
            fprintf (stderr, "Usage:\t%s\n", usage);
@@ -730,7 +780,7 @@
 {
     int err, num_args, count;
     struct config_entry_struct *new;
-    char p[MAX_ARGS][STRING_LENGTH];
+    char p[MAX_ARGS + 1][STRING_LENGTH];
     char when[STRING_LENGTH], what[STRING_LENGTH];
     char name[STRING_LENGTH], tmp[STRING_LENGTH];
 
@@ -759,6 +809,40 @@
                     event_mask);
        return;
     }
+    if (strcasecmp (when, "MODPROBE") == 0) /* set the modprobe path/and or 
option */
+    {
+        if (strcasecmp(name, "DEFAULT") == 0) 
+         modprobe.path_config[0] = '\0';  /* get modprobe from 
/proc/sys/kernel/modprobe */
+       else if ( (strcasecmp(name, "CURRENT") != 0) &&  /* if match CURRENT|.* 
use the current value, don't set it */
+                 (strcasecmp(name, ".*") != 0) )
+         strncpy(modprobe.path_config, name, STRING_LENGTH); /* else take the 
argument */
+
+       if (num_args > 2)
+         {
+           if (strcasecmp(what, "VERBOSE") == 0) /* be verbose */
+             modprobe.verbose_config = TRUE;
+           else if (strcasecmp(what, "NORMAL") == 0) /* don't be verbose */
+             modprobe.verbose_config = FALSE;
+           else if ( (strcasecmp(what, "ARGS") == 0) || 
+                     (strcasecmp(what, "ARGUMENTS") == 0) )
+             {
+               int i;
+
+               /* read all args and store them in the modprobe structure */
+               for(i = 0; i < num_args - 3; i++)
+                 strncpy(modprobe.extra_argv[i], p[i], STRING_LENGTH);
+
+               modprobe.extra_argv[i][0] = '\0';
+             }
+           else
+             {
+               SYSLOG (LOG_ERR, "bad config line: \"%s\"\n", line);
+               SYSLOG (LOG_ERR, "exiting\n");
+               exit (1);
+             }
+         }
+        return;
+    }
     if (num_args < 3)
     {
        SYSLOG (LOG_ERR, "bad config line: \"%s\"\n", line);
@@ -1123,6 +1207,37 @@
     }
 }   /*  End Function action_permissions  */
 
+static char * modprobe_find(void)
+{
+  FILE *file;
+  int num;
+
+  /* modprobe path must be configurable at runtime
+     o default /sbin/modprobe
+     o from /proc/sys/kernel/modprobe
+     o parameter on command line 
+     o from devfsd.conf
+  */
+
+  if (modprobe.path_option[0] != '\0')
+    return modprobe.path_option; /* use the one provided on the command line */
+
+  if (modprobe.path_config[0] != '\0')
+    return modprobe.path_config; /* use the one found in config file */
+  
+  file = fopen("/proc/sys/kernel/modprobe", "r");
+  if (file != NULL)
+    {
+      num = fscanf(file, "%s", modprobe.path);
+      fclose(file);
+
+      if (num == 1)
+       return modprobe.path;
+    }
+
+  return MODPROBE; /* use the default path */
+}
+
 static void action_modload (const struct devfsd_notify_struct *info,
                            const struct config_entry_struct *entry)
 /*  [SUMMARY] Load a module.
@@ -1131,38 +1246,60 @@
     [RETURNS] Nothing.
 */
 {
-    char *argv[6];
     char device[STRING_LENGTH];
-    static int (*modprobe) (int argc, char **argv) = NULL;
-    static flag first_time = TRUE;
-
-    if (first_time)
-    {
-       void *lib;
+    void *lib;
+    int i;
+ 
+    /* can't compute args only one time, must be resetup when devfsd.conf is 
reread (SIGHUP) */
+    
+    modprobe.argc = 0;
+    modprobe.argv[modprobe.argc ++] = NULL; /* place for modprobe path */
+    if ( (modprobe.verbose_option == TRUE) ||
+        (modprobe.verbose_option == -1 && modprobe.verbose_config == TRUE) )
+      {
+       modprobe.argv[modprobe.argc ++] = "-s"; /* use syslog */
+       modprobe.argv[modprobe.argc ++] = "-v"; /* be verbose */
+      }
+    
+    /* add extra args */
+    for(i = 0; modprobe.extra_argv[i][0] != '\0' ; i++)
+      modprobe.argv[modprobe.argc ++] = modprobe.extra_argv[i]; 
+    
+    modprobe.argv[modprobe.argc ++] = "-k"; /* Auto unload this module if 
unused */
+    modprobe.argv[modprobe.argc ++] = "-C"; /* use this config file : */
+    modprobe.argv[modprobe.argc ++] = "/etc/modules.devfs"; 
+    
+    modprobe.argv[modprobe.argc ++] = NULL; /* place for the device name */
+    modprobe.argv[modprobe.argc] = NULL;
 
-       first_time = FALSE;
-       if ( ( lib = dlopen ("/lib/modutils.so", RTLD_NOW) ) != NULL )
-           modprobe = dlsym (lib, "modprobe");
-    }
-    argv[0] = "/sbin/modprobe";
-    argv[1] = "-k";
-    argv[2] = "-C";
-    argv[3] = "/etc/modules.devfs";
-    argv[4] = device;
-    argv[5] = NULL;
+    /* compute really dynamic parameter (those that don't depend of us 
directly) */
+    modprobe.argv[0] = modprobe_find();
     snprintf (device, sizeof (device), "/dev/%s", info->devname);
+    modprobe.argv[modprobe.argc - 1] = device;
+
+    /* always try to open this */
+    lib = dlopen ("/lib/modutils.so", RTLD_NOW);
+    if ( lib != NULL )
+      modprobe.func = dlsym (lib, "modprobe");
+    else
+      modprobe.func = NULL;
+
     if (trace_level > 1)
        fprintf (stderr, "Calling modprobe with name: \"%s\"\n", device);
-    if (modprobe != NULL)
+    if (modprobe.func != NULL)
     {
-       (*modprobe) (5, argv);
+        /* use the function from the library */
+       (*modprobe.func) (modprobe.argc, modprobe.argv);
        return;
     }
     switch ( fork () )
     {
       case 0:
        /*  Child  */
-       break;
+       execvp (modprobe.argv[0], modprobe.argv);
+       SYSLOG (LOG_ERR, "error execing: \"%s\"\t%s\n", modprobe.argv[0], 
ERRSTRING);
+       _exit (1);
+       /* break; */
       case -1:
        /*  Error  */
        SYSLOG (LOG_ERR, "error forking\t%s\n", ERRSTRING);
@@ -1174,15 +1311,12 @@
        return;
        /*break;*/
     }
-    execvp (argv[0], argv);
-    SYSLOG (LOG_ERR, "error execing: \"%s\"\t%s\n", argv[0], ERRSTRING);
-    _exit (1);
 }   /*  End Function action_modload  */
 
 static void action_execute (const struct devfsd_notify_struct *info,
                            const struct config_entry_struct *entry,
                            const regmatch_t *regexpr, unsigned int numexpr)
-/*  [SUMMARY] Execute a programme.
+/*  [SUMMARY] Execute a program.
     <info> The devfs change.
     <entry> The config file entry.
     <regexpr> The number of subexpression (start, end) offsets within the
@@ -1222,7 +1356,7 @@
        break;
       case -1:
        /*  Error  */
-       SYSLOG (LOG_ERR, "error forking for programme: %s\t%s\n",
+       SYSLOG (LOG_ERR, "error forking for program: %s\t%s\n",
                argv[0], ERRSTRING);
        return;
        /*break;*/
diff -ur devfsd-1.3.18/devfsd.conf devfsd-1.3.18-meuh/devfsd.conf
--- devfsd-1.3.18/devfsd.conf   Thu Mar 29 22:05:37 2001
+++ devfsd-1.3.18-meuh/devfsd.conf      Fri Nov 16 23:39:20 2001
@@ -1,6 +1,16 @@
 # Sample /etc/devfsd.conf configuration file.
 # Richard Gooch  <rgooch@xxxxxxxxxxxxx>                3-JUL-2000
 #
+# Some configuration tricks for modprobe
+# use this modprobe
+#MODPROBE      /sbin/modprobe
+# make modprobe verbose (pass -s -v flags)
+#MODPROBE      .*              VERBOSE
+# add some flags to the modprobe command line
+#MODPROBE      current         ARGS    -a -d
+# use the default modprobe (from /proc/sys/kernel/modprobe or "/sbin/modprobe")
+#MODPROBE      default
+
 # Enable full compatibility mode for old device names. You may comment these
 # out if you don't use the old device names. Make sure you know what you're
 # doing!

========== patch-devfsd-meuh-modprobe-arguments ======================

<Prev in Thread] Current Thread [Next in Thread>