static struct dep_t *depend;
-static int autoclean, show_only, quiet, do_syslog, verbose;
+
+#define main_options "acdklnqrst:vVC:"
+#define INSERT_ALL 1 /* a */
+#define DUMP_CONF_EXIT 2 /* c */
+#define D_OPT_IGNORED 4 /* d */
+#define AUTOCLEAN_FLG 8 /* k */
+#define LIST_ALL 16 /* l */
+#define SHOW_ONLY 32 /* n */
+#define QUIET 64 /* q */
+#define REMOVE_OPT 128 /* r */
+#define DO_SYSLOG 256 /* s */
+#define RESTRICT_DIR 512 /* t */
+#define VERBOSE 1024 /* v */
+#define VERSION_ONLY 2048 /* V */
+#define CONFIG_FILE 4096 /* C */
+
+#define autoclean (main_opts & AUTOCLEAN_FLG)
+#define show_only (main_opts & SHOW_ONLY)
+#define quiet (main_opts & QUIET)
+#define remove_opt (main_opts & REMOVE_OPT)
+#define do_syslog (main_opts & DO_SYSLOG)
+#define verbose (main_opts & VERBOSE)
+
+static int main_opts;
static int parse_tag_value ( char *buffer, char **ptag, char **pvalue )
{
/*
* This function appends an option to a list
*/
-struct mod_opt_t *append_option( struct mod_opt_t *opt_list, char *opt )
+static struct mod_opt_t *append_option( struct mod_opt_t *opt_list, char *opt )
{
struct mod_opt_t *ol = opt_list;
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 ) );
+ *tmp_str++ = '\0';
+ *dst = xrealloc( *dst, (tmp_str - *dst ) );
return src;
}
#else
#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
+ * This function reads aliases and default module options from a configuration file
+ * (/etc/modprobe.conf syntax). It supports includes (only files, no directories).
+ */
+static void include_conf ( struct dep_t **first, struct dep_t **current, char *buffer, int buflen, int fd )
+{
+ int continuation_line = 0;
+
+ // alias parsing is not 100% correct (no correct handling of continuation lines within an alias) !
+
+ while ( reads ( fd, buffer, buflen)) {
+ int l;
+ char *p;
+
+ p = strchr ( buffer, '#' );
+ if ( p )
+ *p = 0;
+
+ l = strlen ( buffer );
+
+ while ( l && isspace ( buffer [l-1] )) {
+ buffer [l-1] = 0;
+ l--;
+ }
+
+ if ( l == 0 ) {
+ continuation_line = 0;
+ continue;
+ }
+
+ if ( !continuation_line ) {
+ if (( strncmp ( buffer, "alias", 5 ) == 0 ) && isspace ( buffer [5] )) {
+ char *alias, *mod;
+
+ if ( parse_tag_value ( buffer + 6, &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 ));
+ }
+ else {
+ (*current)-> m_next = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t ));
+ (*current) = (*current)-> m_next;
+ }
+ (*current)-> m_name = bb_xstrdup ( alias );
+ (*current)-> m_isalias = 1;
+
+ if (( strcmp ( mod, "off" ) == 0 ) || ( strcmp ( mod, "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] = bb_xstrdup ( mod );
+ }
+ (*current)-> m_next = 0;
+ }
+ }
+ 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_name, mod ) == 0 )
+ break;
+ }
+ if ( dt ) {
+ 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 );
+ }
+ }
+ }
+ }
+ else if (( strncmp ( buffer, "include", 7 ) == 0 ) && isspace ( buffer [7] )) {
+
+ int fdi; char *filename = buffer + 8;
+
+ while ( isspace ( *filename ))
+ filename++;
+
+ if (( fdi = open ( filename, O_RDONLY )) >= 0 ) {
+ include_conf(first, current, buffer, buflen, fdi);
+ close(fdi);
+ }
+ }
+ }
+ }
+}
+
+/*
+ * 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 )
struct dep_t *first = 0;
struct dep_t *current = 0;
char buffer[2048];
- char *filename = buffer;
+ char *filename;
int continuation_line = 0;
int k_version;
if ( uname ( &un ))
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 )) {
- return 0;
- }
if (un.release[0] == '2') {
k_version = un.release[2] - '0';
}
- strcpy ( filename, "/lib/modules/" );
- strcat ( filename, un.release );
- strcat ( filename, "/modules.dep" );
-
- if (( fd = open ( filename, O_RDONLY )) < 0 ) {
-
+ filename = bb_xasprintf("/lib/modules/%s/modules.dep", un.release );
+ fd = open ( filename, O_RDONLY );
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(filename);
+ if (fd < 0) {
/* Ok, that didn't work. Fall back to looking in /lib/modules */
if (( fd = open ( "/lib/modules/modules.dep", O_RDONLY )) < 0 ) {
return 0;
}
while ( reads ( fd, buffer, sizeof( buffer ))) {
- int l = bb_strlen ( buffer );
+ int l = strlen ( buffer );
char *p = 0;
- while ( isspace ( buffer [l-1] )) {
+ while ( l > 0 && isspace ( buffer [l-1] )) {
buffer [l-1] = 0;
l--;
}
}
close ( fd );
- // alias parsing is not 100% correct (no correct handling of continuation lines within an alias) !
-
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 ))) {
- int l;
- char *p;
-
- p = strchr ( buffer, '#' );
- if ( p )
- *p = 0;
-
- l = bb_strlen ( buffer );
-
- while ( l && isspace ( buffer [l-1] )) {
- buffer [l-1] = 0;
- l--;
- }
+ include_conf (&first, ¤t, buffer, sizeof(buffer), fd);
+ close(fd);
- if ( l == 0 ) {
- continuation_line = 0;
- continue;
- }
-
- if ( !continuation_line ) {
- if (( strncmp ( buffer, "alias", 5 ) == 0 ) && isspace ( buffer [5] )) {
- char *alias, *mod;
-
- if ( parse_tag_value ( buffer + 6, &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 ));
- }
- else {
- current-> m_next = (struct dep_t *) xcalloc ( 1, sizeof ( struct dep_t ));
- current = current-> m_next;
- }
- current-> m_name = bb_xstrdup ( alias );
- current-> m_isalias = 1;
-
- if (( strcmp ( mod, "off" ) == 0 ) || ( strcmp ( mod, "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] = bb_xstrdup ( mod );
- }
- current-> m_next = 0;
- }
- }
- 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_name, mod ) == 0 )
- break;
- }
- if ( dt ) {
- 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 );
- }
- }
- }
- }
+ filename = bb_xasprintf("/lib/modules/%s/modules.alias", un.release);
+ fd = open ( filename, O_RDONLY );
+ if (ENABLE_FEATURE_CLEAN_UP)
+ free(filename);
+ if (fd < 0) {
+ /* Ok, that didn't work. Fall back to looking in /lib/modules */
+ if (( fd = open ( "/lib/modules/modules.alias", O_RDONLY )) < 0 ) {
+ return first;
}
}
- close ( fd );
+
+ include_conf (&first, ¤t, buffer, sizeof(buffer), fd);
+ close(fd);
return first;
}
static int mod_remove ( char *mod )
{
int rc;
- static struct mod_list_t rm_a_dummy = { "-a", 0, 0 };
+ static struct mod_list_t rm_a_dummy = { "-a", NULL, NULL, NULL, NULL };
struct mod_list_t *head = 0;
struct mod_list_t *tail = 0;
}
-extern int modprobe_main(int argc, char** argv)
+int modprobe_main(int argc, char** argv)
{
- int opt;
int rc = EXIT_SUCCESS;
- int remove_opt = 0;
+ char *unused;
- autoclean = show_only = quiet = do_syslog = verbose = 0;
-
- while ((opt = getopt(argc, argv, "acdklnqrst:vVC:")) != -1) {
- switch(opt) {
- case 'c': // no config used
- case 'l': // no pattern matching
+ bb_opt_complementally = "?V-:q-v:v-q";
+ main_opts = bb_getopt_ulflags(argc, argv, "acdklnqrst:vVC:",
+ &unused, &unused);
+ if((main_opts & (DUMP_CONF_EXIT | LIST_ALL)))
return EXIT_SUCCESS;
- break;
- case 'C': // no config used
- case 't': // no pattern matching
+ if((main_opts & (RESTRICT_DIR | CONFIG_FILE)))
bb_error_msg_and_die("-t and -C not supported");
- case 'a': // ignore
- case 'd': // ignore
- break;
- case 'k':
- autoclean++;
- break;
- case 'n':
- show_only++;
- break;
- case 'q':
- quiet++; verbose=0;
- break;
- case 'r':
- remove_opt++;
- break;
- case 's':
- do_syslog++;
- break;
- case 'v':
- verbose++; quiet=0;
- break;
- case 'V':
- default:
- bb_show_usage();
- break;
- }
- }
-
depend = build_dep ( );
if ( !depend )
if (remove_opt) {
do {
if (mod_remove ( optind < argc ?
- bb_xstrdup (argv [optind]) : NULL )) {
+ argv [optind] : NULL )) {
bb_error_msg ("failed to remove module %s",
argv [optind] );
rc = EXIT_FAILURE;
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 ))
+ if ( mod_insert ( argv [optind], argc - optind - 1, argv + optind + 1 ))
bb_error_msg_and_die ( "failed to load module %s", argv [optind] );
}