aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--modutils/modprobe.c154
1 files changed, 99 insertions, 55 deletions
diff --git a/modutils/modprobe.c b/modutils/modprobe.c
index b05158ac0..36d2aa211 100644
--- a/modutils/modprobe.c
+++ b/modutils/modprobe.c
@@ -1,9 +1,6 @@
/* vi: set sw=4 ts=4: */
/*
- * really dumb modprobe implementation for busybox
- * Copyright (C) 2001 Lineo, davidm@lineo.com
- *
- * dependency specific stuff completly rewritten and
+ * Modprobe written from scratch for BusyBox
* copyright (c) 2002 by Robert Griebl, griebl@gmx.de
*
*/
@@ -22,6 +19,7 @@
struct dep_t {
char * m_module;
+ char * m_options;
int m_isalias : 1;
int m_reserved : 15;
@@ -34,6 +32,7 @@ struct dep_t {
struct mod_list_t {
char * m_module;
+ char * m_options;
struct mod_list_t * m_prev;
struct mod_list_t * m_next;
@@ -43,6 +42,24 @@ struct mod_list_t {
static struct dep_t *depend;
static int autoclean, show_only, quiet, do_syslog, verbose;
+int parse_tag_value ( char *buffer, char **ptag, char **pvalue )
+{
+ char *tag, *value;
+
+ while ( isspace ( *buffer ))
+ buffer++;
+ tag = value = buffer;
+ while ( !isspace ( *value ))
+ value++;
+ *value++ = 0;
+ while ( isspace ( *value ))
+ value++;
+
+ *ptag = tag;
+ *pvalue = value;
+
+ return xstrlen( tag ) && xstrlen( value );
+}
/* Jump through hoops to simulate how fgets() grabs just one line at a
* time... Don't use any stdio since modprobe gets called from a kernel
@@ -141,6 +158,7 @@ static struct dep_t *build_dep ( void )
current = current-> m_next;
}
current-> m_module = mod;
+ current-> m_options = 0;
current-> m_isalias = 0;
current-> m_depcnt = 0;
current-> m_deparr = 0;
@@ -230,41 +248,49 @@ static struct dep_t *build_dep ( void )
if (( strncmp ( buffer, "alias", 5 ) == 0 ) && isspace ( buffer [5] )) {
char *alias, *mod;
- alias = buffer + 6;
-
- while ( isspace ( *alias ))
- alias++;
- mod = alias;
- while ( !isspace ( *mod ))
- mod++;
- *mod = 0;
- mod++;
- while ( isspace ( *mod ))
- mod++;
-
-// fprintf ( stderr, "ALIAS: '%s' -> '%s'\n", alias, mod );
+ if ( parse_tag_value ( buffer + 6, &alias, &mod )) {
+ // fprintf ( stderr, "ALIAS: '%s' -> '%s'\n", alias, mod );
- if ( !current ) {
- first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
- }
- else {
- current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
- current = current-> m_next;
+ if ( !current ) {
+ first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
+ }
+ else {
+ current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t ));
+ current = current-> m_next;
+ }
+ current-> m_module = xstrdup ( alias );
+ current-> m_isalias = 1;
+
+ if (( strcmp ( alias, "off" ) == 0 ) || ( strcmp ( alias, "null" ) == 0 )) {
+ current-> m_depcnt = 0;
+ current-> m_deparr = 0;
+ }
+ else {
+ current-> m_depcnt = 1;
+ current-> m_deparr = xmalloc ( 1 * sizeof( char * ));
+ current-> m_deparr[0] = xstrdup ( mod );
+ }
+ current-> m_next = 0;
}
- current-> m_module = xstrdup ( alias );
- current-> m_isalias = 1;
+ }
+ else if (( strncmp ( buffer, "options", 7 ) == 0 ) && isspace ( buffer [7] )) {
+ char *mod, *opt;
- if (( strcmp ( alias, "off" ) == 0 ) || ( strcmp ( alias, "null" ) == 0 )) {
- current-> m_depcnt = 0;
- current-> m_deparr = 0;
- }
- else {
- current-> m_depcnt = 1;
- current-> m_deparr = xmalloc ( 1 * sizeof( char * ));
- current-> m_deparr[0] = xstrdup ( mod );
+ if ( parse_tag_value ( buffer + 8, &mod, &opt )) {
+ struct dep_t *dt;
+
+ for ( dt = first; dt; dt = dt-> m_next ) {
+ if ( strcmp ( dt-> m_module, mod ) == 0 )
+ break;
+ }
+ if ( dt ) {
+ dt-> m_options = xrealloc ( dt-> m_options, xstrlen( opt ) + 1 );
+ strcpy ( dt-> m_options, opt );
+
+ // fprintf ( stderr, "OPTION: '%s' -> '%s'\n", dt-> m_module, dt-> m_options );
+ }
}
- current-> m_next = 0;
- }
+ }
}
}
close ( fd );
@@ -283,7 +309,7 @@ static int mod_process ( struct mod_list_t *list, int do_insert )
while ( list ) {
if ( do_insert )
- snprintf ( lcmd, sizeof( lcmd ) - 1, "insmod %s %s %s %s 2>/dev/null", do_syslog ? "-s" : "", autoclean ? "-k" : "", quiet ? "-q" : "", list-> m_module );
+ snprintf ( lcmd, sizeof( lcmd ) - 1, "insmod %s %s %s %s %s 2>/dev/null", do_syslog ? "-s" : "", autoclean ? "-k" : "", quiet ? "-q" : "", list-> m_module, list-> m_options ? list-> m_options : "" );
else
snprintf ( lcmd, sizeof( lcmd ) - 1, "rmmod %s %s 2>/dev/null", do_syslog ? "-s" : "", list-> m_module );
@@ -301,7 +327,7 @@ static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t *
{
struct mod_list_t *find;
struct dep_t *dt;
-
+ char *opt = 0;
int lm;
// remove .o extension
@@ -311,16 +337,31 @@ static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t *
// check dependencies
for ( dt = depend; dt; dt = dt-> m_next ) {
- if ( strcmp ( dt-> m_module, mod ) == 0 )
+ if ( strcmp ( dt-> m_module, mod ) == 0 ) {
+ opt = dt-> m_options;
break;
+ }
}
+
// resolve alias names
- if ( dt && dt-> m_isalias ) {
- if ( dt-> m_depcnt == 1 )
- check_dep ( dt-> m_deparr [0], head, tail );
- printf ( "Got alias: %s -> %s\n", mod, dt-> m_deparr [0] );
-
- return;
+ while ( dt && dt-> m_isalias ) {
+ if ( dt-> m_depcnt == 1 ) {
+ struct dep_t *adt;
+
+ for ( adt = depend; adt; adt = adt-> m_next ) {
+ if ( strcmp ( adt-> m_module, dt-> m_deparr [0] ) == 0 ) {
+ if ( !opt )
+ opt = adt-> m_options;
+ break;
+ }
+ }
+ if ( !adt )
+ return;
+ else
+ dt = adt;
+ }
+ else
+ return;
}
// search for duplicates
@@ -345,6 +386,7 @@ static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t *
if ( !find ) { // did not find a duplicate
find = (struct mod_list_t *) xmalloc ( sizeof(struct mod_list_t));
find-> m_module = mod;
+ find-> m_options = opt;
}
// enqueue at tail
@@ -377,21 +419,23 @@ static int mod_insert ( char *mod, int argc, char **argv )
check_dep ( mod, &head, &tail );
if ( head && tail ) {
- int i;
- int l = 0;
+ if ( argc ) {
+ int i;
+ int l = 0;
- // append module args
- l = xstrlen ( head-> m_module );
- for ( i = 0; i < argc; i++ )
- l += ( xstrlen ( argv [i] ) + 1 );
+ // append module args
+ for ( i = 0; i < argc; i++ )
+ l += ( xstrlen ( argv [i] ) + 1 );
- head-> m_module = xrealloc ( head-> m_module, l + 1 );
+ head-> m_options = xrealloc ( head-> m_options, l + 1 );
+ head-> m_options [0] = 0;
- for ( i = 0; i < argc; i++ ) {
- strcat ( head-> m_module, " " );
- strcat ( head-> m_module, argv [i] );
+ for ( i = 0; i < argc; i++ ) {
+ strcat ( head-> m_options, argv [i] );
+ strcat ( head-> m_options, " " );
+ }
}
-
+
// process tail ---> head
rc |= mod_process ( tail, 1 );
}