X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=modutils%2Fmodprobe.c;h=844eb99c5ee3d36a95b3939ca9158fa62a2b4697;hb=3496fdc9a573a424e34141cbe04250cc8df15e32;hp=2b90eb0198180bc0712a9fac2b3b0cbef98ee4a9;hpb=ba05e79815df6d521c39ce7d2dd7e495ccb6ef48;p=oweals%2Fbusybox.git diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 2b90eb019..844eb99c5 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c @@ -4,24 +4,16 @@ * * Copyright (c) 2002 by Robert Griebl, griebl@gmx.de * Copyright (c) 2003 by Andrew Dennison, andrew.dennison@motec.com.au + * Copyright (c) 2005 by Jim Bauer, jfbauer@nfr.com * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Portions Copyright (c) 2005 by Yann E. MORIN, yann.morin.1998@anciens.enib.fr * + * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. */ #include +#include +#include #include #include #include @@ -31,24 +23,31 @@ #include #include "busybox.h" +struct mod_opt_t { /* one-way list of options to pass to a module */ + char * m_opt_val; + struct mod_opt_t * m_next; +}; +struct dep_t { /* one-way list of dependency rules */ + /* a dependency rule */ + char * m_name; /* the module name*/ + char * m_path; /* the module file path */ + struct mod_opt_t * m_options; /* the module options */ -struct dep_t { - char * m_module; - char * m_options; - - int m_isalias : 1; - int m_reserved : 15; + int m_isalias : 1; /* the module is an alias */ + int m_reserved : 15; /* stuffin' */ - int m_depcnt : 16; - char ** m_deparr; + int m_depcnt : 16; /* the number of dependable module(s) */ + char ** m_deparr; /* the list of dependable module(s) */ - struct dep_t * m_next; + struct dep_t * m_next; /* the next dependency rule */ }; -struct mod_list_t { - char * m_module; - char * m_options; +struct mod_list_t { /* two-way list of modules to process */ + /* a module description */ + char * m_name; + char * m_path; + struct mod_opt_t * m_options; struct mod_list_t * m_prev; struct mod_list_t * m_next; @@ -57,9 +56,8 @@ struct mod_list_t { static struct dep_t *depend; static int autoclean, show_only, quiet, do_syslog, verbose; -static int k_version; -int parse_tag_value ( char *buffer, char **ptag, char **pvalue ) +static int parse_tag_value ( char *buffer, char **ptag, char **pvalue ) { char *tag, *value; @@ -67,15 +65,17 @@ int parse_tag_value ( char *buffer, char **ptag, char **pvalue ) buffer++; tag = value = buffer; while ( !isspace ( *value )) - value++; + if (!*value) return 0; + else value++; *value++ = 0; while ( isspace ( *value )) value++; + if (!*value) return 0; *ptag = tag; *pvalue = value; - return bb_strlen( tag ) && bb_strlen( value ); + return 1; } /* Jump through hoops to simulate how fgets() grabs just one line at a @@ -107,19 +107,160 @@ static char *reads ( int fd, char *buffer, size_t len ) return 0; } +/* + * This function appends an option to a list + */ +struct mod_opt_t *append_option( struct mod_opt_t *opt_list, char *opt ) +{ + struct mod_opt_t *ol = opt_list; + + if( ol ) { + while( ol-> m_next ) { + ol = ol-> m_next; + } + ol-> m_next = xmalloc( sizeof( struct mod_opt_t ) ); + ol = ol-> m_next; + } else { + ol = opt_list = xmalloc( sizeof( struct mod_opt_t ) ); + } + + ol-> m_opt_val = bb_xstrdup( opt ); + ol-> m_next = NULL; + + return opt_list; +} + +#if ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS +/* static char* parse_command_string( char* src, char **dst ); + * src: pointer to string containing argument + * dst: pointer to where to store the parsed argument + * return value: the pointer to the first char after the parsed argument, + * NULL if there was no argument parsed (only trailing spaces). + * Note that memory is allocated with bb_xstrdup when a new argument was + * parsed. Don't forget to free it! + */ +#define ARG_EMPTY 0x00 +#define ARG_IN_DQUOTES 0x01 +#define ARG_IN_SQUOTES 0x02 +static char *parse_command_string( char *src, char **dst ) +{ + int opt_status = ARG_EMPTY; + char* tmp_str; + + /* Dumb you, I have nothing to do... */ + if( src == NULL ) return src; + + /* Skip leading spaces */ + while( *src == ' ' ) { + src++; + } + /* Is the end of string reached? */ + if( *src == '\0' ) { + return NULL; + } + /* Reached the start of an argument + * By the way, we duplicate a little too much + * here but what is too much is freed later. */ + *dst = tmp_str = bb_xstrdup( src ); + /* Get to the end of that argument */ + while( ( *tmp_str != '\0' ) + && ( ( *tmp_str != ' ' ) + || ( opt_status & ( ARG_IN_DQUOTES | ARG_IN_SQUOTES ) ) ) ) { + switch( *tmp_str ) { + case '\'': + if( opt_status & ARG_IN_DQUOTES ) { + /* Already in double quotes, keep current char as is */ + } else { + /* shift left 1 char, until end of string: get rid of the opening/closing quotes */ + memmove( tmp_str, tmp_str + 1, strlen( tmp_str ) ); + /* mark me: we enter or leave single quotes */ + opt_status ^= ARG_IN_SQUOTES; + /* Back one char, as we need to re-scan the new char there. */ + tmp_str--; + } + break; + case '"': + if( opt_status & ARG_IN_SQUOTES ) { + /* Already in single quotes, keep current char as is */ + } else { + /* shift left 1 char, until end of string: get rid of the opening/closing quotes */ + memmove( tmp_str, tmp_str + 1, strlen( tmp_str ) ); + /* mark me: we enter or leave double quotes */ + opt_status ^= ARG_IN_DQUOTES; + /* Back one char, as we need to re-scan the new char there. */ + tmp_str--; + } + break; + case '\\': + if( opt_status & ARG_IN_SQUOTES ) { + /* Between single quotes: keep as is. */ + } else { + switch( *(tmp_str+1) ) { + case 'a': + case 'b': + case 't': + case 'n': + case 'v': + case 'f': + case 'r': + case '0': + /* We escaped a special character. For now, keep + * both the back-slash and the following char. */ + tmp_str++; src++; + break; + default: + /* We escaped a space or a single or double quote, + * or a back-slash, or a non-escapable char. Remove + * the '\' and keep the new current char as is. */ + memmove( tmp_str, tmp_str + 1, strlen( tmp_str ) ); + break; + } + } + break; + /* Any other char that is special shall appear here. + * Example: $ starts a variable + case '$': + do_variable_expansion(); + break; + * */ + default: + /* any other char is kept as is. */ + break; + } + tmp_str++; /* Go to next char */ + src++; /* Go to next char to find the end of the argument. */ + } + /* End of string, but still no ending quote */ + if( opt_status & ( ARG_IN_DQUOTES | ARG_IN_SQUOTES ) ) { + bb_error_msg_and_die( "unterminated (single or double) quote in options list: %s", src ); + } + *tmp_str = '\0'; + *dst = xrealloc( *dst, strlen( *dst ) ); + return src; +} +#else +#define parse_command_string(src, dst) (0) +#endif /* ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS */ + +/* + * This function builds a list of dependency rules from /lib/modules/`uname -r\modules.dep. + * It then fills every modules and aliases with their default options, found by parsing + * modprobe.conf (or modules.conf, or conf.modules). + */ static struct dep_t *build_dep ( void ) { int fd; struct utsname un; struct dep_t *first = 0; struct dep_t *current = 0; - char buffer[256]; + char buffer[2048]; char *filename = buffer; int continuation_line = 0; + int k_version; k_version = 0; if ( uname ( &un )) - return 0; + bb_error_msg_and_die("can't determine kernel version"); // check for buffer overflow in following code if ( bb_strlen ( un.release ) > ( sizeof( buffer ) - 64 )) { @@ -155,33 +296,43 @@ static struct dep_t *build_dep ( void ) continue; } + /* Is this a new module dep description? */ if ( !continuation_line ) { + /* find the dep beginning */ char *col = strchr ( buffer, ':' ); + char *dot = col; if ( col ) { + /* This line is a dep description */ char *mods; + char *modpath; char *mod; - int ext = 0; + /* Find the beginning of the module file name */ *col = 0; mods = strrchr ( buffer, '/' ); if ( !mods ) - mods = buffer; + mods = buffer; /* no path for this module */ else - mods++; - -#if defined(CONFIG_FEATURE_2_6_MODULES) - if ((k_version > 4) && ( *(col-3) == '.' ) && - ( *(col-2) == 'k' ) && ( *(col-1) == 'o' )) - ext = 3; + mods++; /* there was a path for this module... */ + + /* find the path of the module */ + modpath = strchr ( buffer, '/' ); /* ... and this is the path */ + if ( !modpath ) + modpath = buffer; /* module with no path */ + /* find the end of the module name in the file name */ + if ( ENABLE_FEATURE_2_6_MODULES && + (k_version > 4) && ( *(col-3) == '.' ) && + ( *(col-2) == 'k' ) && ( *(col-1) == 'o' ) ) + dot = col - 3; else -#endif if (( *(col-2) == '.' ) && ( *(col-1) == 'o' )) - ext = 2; + dot = col - 2; - mod = bb_xstrndup ( mods, col - mods - ext ); + mod = bb_xstrndup ( mods, dot - mods ); + /* enqueue new module */ if ( !current ) { first = current = (struct dep_t *) xmalloc ( sizeof ( struct dep_t )); } @@ -189,25 +340,28 @@ static struct dep_t *build_dep ( void ) current-> m_next = (struct dep_t *) xmalloc ( sizeof ( struct dep_t )); current = current-> m_next; } - current-> m_module = mod; - current-> m_options = 0; + current-> m_name = mod; + current-> m_path = bb_xstrdup(modpath); + current-> m_options = NULL; current-> m_isalias = 0; current-> m_depcnt = 0; current-> m_deparr = 0; current-> m_next = 0; - //printf ( "%s:\n", mod ); p = col + 1; } else + /* this line is not a dep description */ p = 0; } else + /* It's a dep description continuation */ p = buffer; while ( p && *p && isblank(*p)) p++; + /* p points to the first dependable module; if NULL, no dependable module */ if ( p && *p ) { char *end = &buffer [l-1]; char *deps; @@ -220,6 +374,7 @@ static struct dep_t *build_dep ( void ) do { + /* search the end of the dependency */ next = strchr (p, ' ' ); if (next) { @@ -229,6 +384,7 @@ static struct dep_t *build_dep ( void ) else next = end; + /* find the beginning of the module file name */ deps = strrchr ( p, '/' ); if ( !deps || ( deps < p )) { @@ -240,12 +396,12 @@ static struct dep_t *build_dep ( void ) else deps++; -#if defined(CONFIG_FEATURE_2_6_MODULES) - if ((k_version > 4) && ( *(next-2) == '.' ) && *(next-1) == 'k' && - ( *next == 'o' )) + /* find the end of the module name in the file name */ + if ( ENABLE_FEATURE_2_6_MODULES && + (k_version > 4) && ( *(next-2) == '.' ) && + ( *(next-1) == 'k' ) && ( *next == 'o' ) ) ext = 3; else -#endif if (( *(next-1) == '.' ) && ( *next == 'o' )) ext = 2; @@ -254,16 +410,17 @@ static struct dep_t *build_dep ( void ) continue; dep = bb_xstrndup ( deps, next - deps - ext + 1 ); + /* Add the new dependable module name */ current-> m_depcnt++; current-> m_deparr = (char **) xrealloc ( current-> m_deparr, sizeof ( char *) * current-> m_depcnt ); current-> m_deparr [current-> m_depcnt - 1] = dep; - //printf ( " %d) %s\n", current-> m_depcnt, current-> m_deparr [current-> m_depcnt -1] ); p = next + 2; } while (next < end); } + /* is there other dependable module(s) ? */ if ( buffer [l-1] == '\\' ) continuation_line = 1; else @@ -273,9 +430,11 @@ static struct dep_t *build_dep ( void ) // alias parsing is not 100% correct (no correct handling of continuation lines within an alias) ! - if (( fd = open ( "/etc/modules.conf", O_RDONLY )) < 0 ) - if (( fd = open ( "/etc/conf.modules", O_RDONLY )) < 0 ) - return first; + if (!ENABLE_FEATURE_2_6_MODULES + || ( fd = open ( "/etc/modprobe.conf", O_RDONLY )) < 0 ) + if (( fd = open ( "/etc/modules.conf", O_RDONLY )) < 0 ) + if (( fd = open ( "/etc/conf.modules", O_RDONLY )) < 0 ) + return first; continuation_line = 0; while ( reads ( fd, buffer, sizeof( buffer ))) { @@ -303,8 +462,7 @@ static struct dep_t *build_dep ( void ) char *alias, *mod; if ( parse_tag_value ( buffer + 6, &alias, &mod )) { - // fprintf ( stderr, "ALIAS: '%s' -> '%s'\n", alias, mod ); - + /* handle alias as a module dependent on the aliased module */ if ( !current ) { first = current = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t )); } @@ -312,10 +470,10 @@ static struct dep_t *build_dep ( void ) current-> m_next = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t )); current = current-> m_next; } - current-> m_module = bb_xstrdup ( alias ); + current-> m_name = bb_xstrdup ( alias ); current-> m_isalias = 1; - if (( strcmp ( alias, "off" ) == 0 ) || ( strcmp ( alias, "null" ) == 0 )) { + if (( strcmp ( mod, "off" ) == 0 ) || ( strcmp ( mod, "null" ) == 0 )) { current-> m_depcnt = 0; current-> m_deparr = 0; } @@ -330,18 +488,24 @@ static struct dep_t *build_dep ( void ) else if (( strncmp ( buffer, "options", 7 ) == 0 ) && isspace ( buffer [7] )) { char *mod, *opt; + /* split the line in the module/alias name, and options */ if ( parse_tag_value ( buffer + 8, &mod, &opt )) { struct dep_t *dt; + /* find the corresponding module */ for ( dt = first; dt; dt = dt-> m_next ) { - if ( strcmp ( dt-> m_module, mod ) == 0 ) + if ( strcmp ( dt-> m_name, mod ) == 0 ) break; } if ( dt ) { - dt-> m_options = xrealloc ( dt-> m_options, bb_strlen( opt ) + 1 ); - strcpy ( dt-> m_options, opt ); - - // fprintf ( stderr, "OPTION: '%s' -> '%s'\n", dt-> m_module, dt-> m_options ); + if ( ENABLE_FEATURE_MODPROBE_MULTIPLE_OPTIONS ) { + char* new_opt = NULL; + while( ( opt = parse_command_string( opt, &new_opt ) ) ) { + dt-> m_options = append_option( dt-> m_options, new_opt ); + } + } else { + dt-> m_options = append_option( dt-> m_options, opt ); + } } } } @@ -356,7 +520,7 @@ static struct dep_t *build_dep ( void ) static int already_loaded (const char *name) { int fd; - char buffer[256]; + char buffer[4096]; fd = open ("/proc/modules", O_RDONLY); if (fd < 0) @@ -368,6 +532,9 @@ static int already_loaded (const char *name) p = strchr (buffer, ' '); if (p) { *p = 0; + for( p = buffer; ENABLE_FEATURE_2_6_MODULES && *p; p++ ) { + *p = ((*p)=='-')?'_':*p; + } if (strcmp (name, buffer) == 0) { close (fd); return 1; @@ -381,88 +548,174 @@ static int already_loaded (const char *name) static int mod_process ( struct mod_list_t *list, int do_insert ) { - char lcmd [256]; - int rc = 1; + int rc = 0; + char **argv = NULL; + struct mod_opt_t *opts; + int argc_malloc; /* never used when CONFIG_FEATURE_CLEAN_UP not defined */ + int argc; while ( list ) { - *lcmd = '\0'; + argc = 0; + if( ENABLE_FEATURE_CLEAN_UP ) + argc_malloc = 0; + /* If CONFIG_FEATURE_CLEAN_UP is not defined, then we leak memory + * each time we allocate memory for argv. + * But it is (quite) small amounts of memory that leak each + * time a module is loaded, and it is reclaimed when modprobe + * exits anyway (even when standalone shell?). + * This could become a problem when loading a module with LOTS of + * dependencies, with LOTS of options for each dependencies, with + * very little memory on the target... But in that case, the module + * would not load because there is no more memory, so there's no + * problem. */ + /* enough for minimal insmod (5 args + NULL) or rmmod (3 args + NULL) */ + argv = (char**) malloc( 6 * sizeof( char* ) ); if ( do_insert ) { - if (already_loaded (list->m_module) != 1) - snprintf ( lcmd, sizeof( lcmd ) - 1, "insmod %s %s %s %s %s", - do_syslog ? "-s" : "", autoclean ? "-k" : "", - quiet ? "-q" : "", list-> m_module, list-> m_options ? - list-> m_options : "" ); + if (already_loaded (list->m_name) != 1) { + argv[argc++] = "insmod"; + if (do_syslog) + argv[argc++] = "-s"; + if (autoclean) + argv[argc++] = "-k"; + if (quiet) + argv[argc++] = "-q"; + else if(verbose) /* verbose and quiet are mutually exclusive */ + argv[argc++] = "-v"; + argv[argc++] = list-> m_path; + if( ENABLE_FEATURE_CLEAN_UP ) + argc_malloc = argc; + opts = list-> m_options; + while( opts ) { + /* Add one more option */ + argc++; + argv = (char**) xrealloc( argv, ( argc + 1 ) * sizeof( char* ) ); + argv[argc-1] = opts-> m_opt_val; + opts = opts-> m_next; + } + } } else { - if (already_loaded (list->m_module) != 0) - snprintf ( lcmd, sizeof( lcmd ) - 1, "rmmod %s %s", - do_syslog ? "-s" : "", list-> m_module ); + /* modutils uses short name for removal */ + if (already_loaded (list->m_name) != 0) { + argv[argc++] = "rmmod"; + if (do_syslog) + argv[argc++] = "-s"; + argv[argc++] = list->m_name; + if( ENABLE_FEATURE_CLEAN_UP ) + argc_malloc = argc; + } } + argv[argc] = NULL; - if ( verbose ) - printf ( "%s\n", lcmd ); - if ( !show_only && *lcmd) { - int rc2 = system ( lcmd ); - if (do_insert) rc = rc2; /* only last module matters */ - else if (!rc2) rc = 0; /* success if remove any mod */ + if (argc) { + if (verbose) { + printf("%s module %s\n", do_insert?"Loading":"Unloading", list-> m_name ); + } + if (!show_only) { + int rc2 = 0; + int status; + switch (fork()) { + case -1: + rc2 = 1; + break; + case 0: //child + execvp(argv[0], argv); + bb_perror_msg_and_die("exec of %s", argv[0]); + /* NOTREACHED */ + default: + if (wait(&status) == -1) { + rc2 = 1; + break; + } + if (WIFEXITED(status)) + rc2 = WEXITSTATUS(status); + if (WIFSIGNALED(status)) + rc2 = WTERMSIG(status); + break; + } + if (do_insert) { + rc = rc2; /* only last module matters */ + } + else if (!rc2) { + rc = 0; /* success if remove any mod */ + } + } + if( ENABLE_FEATURE_CLEAN_UP ) + /* the last value in the array has index == argc, but + * it is the terminating NULL, so we must not free it. */ + while( argc_malloc < argc ) { + free( argv[argc_malloc++] ); + } + } + if( ENABLE_FEATURE_CLEAN_UP ) { + free( argv ); + argv = NULL; } - list = do_insert ? list-> m_prev : list-> m_next; } return (show_only) ? 0 : rc; } +/* + * Builds the dependency list (aka stack) of a module. + * head: the highest module in the stack (last to insmod, first to rmmod) + * tail: the lowest module in the stack (first to insmod, last to rmmod) + */ static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t **tail ) { struct mod_list_t *find; struct dep_t *dt; - char *opt = 0; - int lm; - - // remove .o extension - lm = bb_strlen ( mod ); - -#if defined(CONFIG_FEATURE_2_6_MODULES) - if ((k_version > 4) && ( mod [lm-3] == '.' ) && - ( mod [lm-2] == 'k' ) && ( mod [lm-1] == 'o' )) - mod [lm-3] = 0; - else -#endif - if (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' )) - mod [lm-2] = 0; + struct mod_opt_t *opt = 0; + char *path = 0; // check dependencies for ( dt = depend; dt; dt = dt-> m_next ) { - if ( strcmp ( dt-> m_module, mod ) == 0 ) { - opt = dt-> m_options; + if ( strcmp ( dt-> m_name, mod ) == 0) { break; } } + if( !dt ) { + bb_error_msg ("module %s not found.", mod); + return; + } + // resolve alias names - while ( dt && dt-> m_isalias ) { + while ( 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 ( strcmp ( adt-> m_name, dt-> m_deparr [0] ) == 0 ) break; } if ( adt ) { + /* This is the module we are aliased to */ + struct mod_opt_t *opts = dt-> m_options; + /* Option of the alias are appended to the options of the module */ + while( opts ) { + adt-> m_options = append_option( adt-> m_options, opts-> m_opt_val ); + opts = opts-> m_next; + } dt = adt; - mod = dt-> m_module; - if ( !opt ) - opt = dt-> m_options; } - else + else { + bb_error_msg ("module %s not found.", mod); return; + } } - else + else { + bb_error_msg ("Bad alias %s", dt-> m_name); return; + } } + mod = dt-> m_name; + path = dt-> m_path; + opt = dt-> m_options; + // search for duplicates for ( find = *head; find; find = find-> m_next ) { - if ( !strcmp ( mod, find-> m_module )) { + if ( !strcmp ( mod, find-> m_name )) { // found -> dequeue it if ( find-> m_prev ) @@ -481,7 +734,8 @@ 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_name = mod; + find-> m_path = path; find-> m_options = opt; } @@ -498,13 +752,12 @@ static void check_dep ( char *mod, struct mod_list_t **head, struct mod_list_t * if ( dt ) { int i; + /* Add all dependable module for that new module */ for ( i = 0; i < dt-> m_depcnt; i++ ) check_dep ( dt-> m_deparr [i], head, tail ); } } - - static int mod_insert ( char *mod, int argc, char **argv ) { struct mod_list_t *tail = 0; @@ -515,21 +768,11 @@ static int mod_insert ( char *mod, int argc, char **argv ) check_dep ( mod, &head, &tail ); if ( head && tail ) { - if ( argc ) { + if( argc ) { int i; - int l = 0; - // append module args for ( i = 0; i < argc; i++ ) - l += ( bb_strlen ( argv [i] ) + 1 ); - - head-> m_options = xrealloc ( head-> m_options, l + 1 ); - head-> m_options [0] = 0; - - for ( i = 0; i < argc; i++ ) { - strcat ( head-> m_options, argv [i] ); - strcat ( head-> m_options, " " ); - } + head->m_options = append_option( head->m_options, argv[i] ); } // process tail ---> head @@ -562,11 +805,10 @@ static int mod_remove ( char *mod ) } - - extern int modprobe_main(int argc, char** argv) { int opt; + int rc = EXIT_SUCCESS; int remove_opt = 0; autoclean = show_only = quiet = do_syslog = verbose = 0; @@ -591,7 +833,7 @@ extern int modprobe_main(int argc, char** argv) show_only++; break; case 'q': - quiet++; + quiet++; verbose=0; break; case 'r': remove_opt++; @@ -600,7 +842,7 @@ extern int modprobe_main(int argc, char** argv) do_syslog++; break; case 'v': - verbose++; + verbose++; quiet=0; break; case 'V': default: @@ -615,7 +857,6 @@ extern int modprobe_main(int argc, char** argv) bb_error_msg_and_die ( "could not parse modules.dep\n" ); if (remove_opt) { - int rc = EXIT_SUCCESS; do { if (mod_remove ( optind < argc ? bb_xstrdup (argv [optind]) : NULL )) { @@ -624,17 +865,15 @@ extern int modprobe_main(int argc, char** argv) rc = EXIT_FAILURE; } } while ( ++optind < argc ); + } else { + if (optind >= argc) + bb_error_msg_and_die ( "No module or pattern provided\n" ); - return rc; + if ( mod_insert ( bb_xstrdup ( argv [optind] ), argc - optind - 1, argv + optind + 1 )) + bb_error_msg_and_die ( "failed to load module %s", argv [optind] ); } - if (optind >= argc) - bb_error_msg_and_die ( "No module or pattern provided\n" ); - - if ( mod_insert ( bb_xstrdup ( argv [optind] ), argc - optind - 1, argv + optind + 1 )) - bb_error_msg_and_die ( "failed to load module %s", argv [optind] ); + /* Here would be a good place to free up memory allocated during the dependencies build. */ - return EXIT_SUCCESS; + return rc; } - -