diff options
Diffstat (limited to 'modutils')
-rw-r--r-- | modutils/insmod.c | 2 | ||||
-rw-r--r-- | modutils/modprobe-small.c | 204 | ||||
-rw-r--r-- | modutils/modprobe.c | 2 |
3 files changed, 135 insertions, 73 deletions
diff --git a/modutils/insmod.c b/modutils/insmod.c index 887d9f2a3..9c3c992a5 100644 --- a/modutils/insmod.c +++ b/modutils/insmod.c | |||
@@ -21,7 +21,7 @@ | |||
21 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") | 21 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") |
22 | //usage: "[SYMBOL=VALUE]..." | 22 | //usage: "[SYMBOL=VALUE]..." |
23 | //usage:#define insmod_full_usage "\n\n" | 23 | //usage:#define insmod_full_usage "\n\n" |
24 | //usage: "Load the specified kernel modules into the kernel" | 24 | //usage: "Load kernel module" |
25 | //usage: IF_FEATURE_2_4_MODULES( "\n" | 25 | //usage: IF_FEATURE_2_4_MODULES( "\n" |
26 | //usage: "\n -f Force module to load into the wrong kernel version" | 26 | //usage: "\n -f Force module to load into the wrong kernel version" |
27 | //usage: "\n -k Make module autoclean-able" | 27 | //usage: "\n -k Make module autoclean-able" |
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index 5b7836344..91e0c1380 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
@@ -9,10 +9,10 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | //applet:IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP)) | 11 | //applet:IF_MODPROBE_SMALL(APPLET(modprobe, BB_DIR_SBIN, BB_SUID_DROP)) |
12 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe)) | 12 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(depmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, depmod)) |
13 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe)) | 13 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(insmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, insmod)) |
14 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe)) | 14 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(lsmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, lsmod)) |
15 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, modprobe)) | 15 | //applet:IF_MODPROBE_SMALL(APPLET_ODDNAME(rmmod, modprobe, BB_DIR_SBIN, BB_SUID_DROP, rmmod)) |
16 | 16 | ||
17 | #include "libbb.h" | 17 | #include "libbb.h" |
18 | /* After libbb.h, since it needs sys/types.h on some systems */ | 18 | /* After libbb.h, since it needs sys/types.h on some systems */ |
@@ -22,6 +22,9 @@ | |||
22 | extern int init_module(void *module, unsigned long len, const char *options); | 22 | extern int init_module(void *module, unsigned long len, const char *options); |
23 | extern int delete_module(const char *module, unsigned flags); | 23 | extern int delete_module(const char *module, unsigned flags); |
24 | extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); | 24 | extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret); |
25 | /* linux/include/linux/module.h has limit of 64 chars on module names */ | ||
26 | #undef MODULE_NAME_LEN | ||
27 | #define MODULE_NAME_LEN 64 | ||
25 | 28 | ||
26 | 29 | ||
27 | #if 1 | 30 | #if 1 |
@@ -143,6 +146,19 @@ static void replace(char *s, char what, char with) | |||
143 | } | 146 | } |
144 | } | 147 | } |
145 | 148 | ||
149 | static char *filename2modname(const char *filename, char *modname) | ||
150 | { | ||
151 | int i; | ||
152 | char *from; | ||
153 | |||
154 | from = bb_get_last_path_component_nostrip(filename); | ||
155 | for (i = 0; i < (MODULE_NAME_LEN-1) && from[i] != '\0' && from[i] != '.'; i++) | ||
156 | modname[i] = (from[i] == '-') ? '_' : from[i]; | ||
157 | modname[i] = '\0'; | ||
158 | |||
159 | return modname; | ||
160 | } | ||
161 | |||
146 | /* Take "word word", return malloced "word",NUL,"word",NUL,NUL */ | 162 | /* Take "word word", return malloced "word",NUL,"word",NUL,NUL */ |
147 | static char* str_2_list(const char *str) | 163 | static char* str_2_list(const char *str) |
148 | { | 164 | { |
@@ -212,6 +228,7 @@ static void parse_module(module_info *info, const char *pathname) | |||
212 | reset_stringbuf(); | 228 | reset_stringbuf(); |
213 | pos = 0; | 229 | pos = 0; |
214 | while (1) { | 230 | while (1) { |
231 | unsigned start = stringbuf_idx; | ||
215 | ptr = find_keyword(module_image + pos, len - pos, "alias="); | 232 | ptr = find_keyword(module_image + pos, len - pos, "alias="); |
216 | if (!ptr) { | 233 | if (!ptr) { |
217 | ptr = find_keyword(module_image + pos, len - pos, "__ksymtab_"); | 234 | ptr = find_keyword(module_image + pos, len - pos, "__ksymtab_"); |
@@ -228,6 +245,31 @@ static void parse_module(module_info *info, const char *pathname) | |||
228 | } | 245 | } |
229 | append(ptr); | 246 | append(ptr); |
230 | appendc(' '); | 247 | appendc(' '); |
248 | /* | ||
249 | * Don't add redundant aliases, such as: | ||
250 | * libcrc32c.ko symbol:crc32c symbol:crc32c | ||
251 | */ | ||
252 | if (start) { /* "if we aren't the first alias" */ | ||
253 | char *found, *last; | ||
254 | stringbuf[stringbuf_idx] = '\0'; | ||
255 | last = stringbuf + start; | ||
256 | /* | ||
257 | * String at last-1 is " symbol:crc32c " | ||
258 | * (with both leading and trailing spaces). | ||
259 | */ | ||
260 | if (strncmp(stringbuf, last, stringbuf_idx - start) == 0) | ||
261 | /* First alias matches us */ | ||
262 | found = stringbuf; | ||
263 | else | ||
264 | /* Does any other alias match? */ | ||
265 | found = strstr(stringbuf, last-1); | ||
266 | if (found < last-1) { | ||
267 | /* There is absolutely the same string before us */ | ||
268 | dbg2_error_msg("redundant:'%s'", last); | ||
269 | stringbuf_idx = start; | ||
270 | goto skip; | ||
271 | } | ||
272 | } | ||
231 | skip: | 273 | skip: |
232 | pos = (ptr - module_image); | 274 | pos = (ptr - module_image); |
233 | } | 275 | } |
@@ -251,14 +293,13 @@ static void parse_module(module_info *info, const char *pathname) | |||
251 | 293 | ||
252 | static int pathname_matches_modname(const char *pathname, const char *modname) | 294 | static int pathname_matches_modname(const char *pathname, const char *modname) |
253 | { | 295 | { |
296 | int r; | ||
297 | char name[MODULE_NAME_LEN]; | ||
254 | const char *fname = bb_get_last_path_component_nostrip(pathname); | 298 | const char *fname = bb_get_last_path_component_nostrip(pathname); |
255 | const char *suffix = strrstr(fname, ".ko"); | 299 | const char *suffix = strrstr(fname, ".ko"); |
256 | //TODO: can do without malloc? | 300 | safe_strncpy(name, fname, suffix - fname); |
257 | char *name = xstrndup(fname, suffix - fname); | ||
258 | int r; | ||
259 | replace(name, '-', '_'); | 301 | replace(name, '-', '_'); |
260 | r = (strcmp(name, modname) == 0); | 302 | r = (strcmp(name, modname) == 0); |
261 | free(name); | ||
262 | return r; | 303 | return r; |
263 | } | 304 | } |
264 | 305 | ||
@@ -421,11 +462,12 @@ static void write_out_dep_bb(int fd) | |||
421 | } | 462 | } |
422 | } | 463 | } |
423 | 464 | ||
424 | static module_info* find_alias(const char *alias) | 465 | static module_info** find_alias(const char *alias) |
425 | { | 466 | { |
426 | int i; | 467 | int i; |
427 | int dep_bb_fd; | 468 | int dep_bb_fd; |
428 | module_info *result; | 469 | int infoidx; |
470 | module_info **infovec; | ||
429 | dbg1_error_msg("find_alias('%s')", alias); | 471 | dbg1_error_msg("find_alias('%s')", alias); |
430 | 472 | ||
431 | try_again: | 473 | try_again: |
@@ -438,7 +480,9 @@ static module_info* find_alias(const char *alias) | |||
438 | if (!modinfo[i].aliases) { | 480 | if (!modinfo[i].aliases) { |
439 | parse_module(&modinfo[i], modinfo[i].pathname); | 481 | parse_module(&modinfo[i], modinfo[i].pathname); |
440 | } | 482 | } |
441 | return &modinfo[i]; | 483 | infovec = xzalloc(2 * sizeof(infovec[0])); |
484 | infovec[0] = &modinfo[i]; | ||
485 | return infovec; | ||
442 | } | 486 | } |
443 | i++; | 487 | i++; |
444 | } | 488 | } |
@@ -451,16 +495,13 @@ static module_info* find_alias(const char *alias) | |||
451 | 495 | ||
452 | /* Scan all module bodies, extract modinfo (it contains aliases) */ | 496 | /* Scan all module bodies, extract modinfo (it contains aliases) */ |
453 | i = 0; | 497 | i = 0; |
454 | result = NULL; | 498 | infoidx = 0; |
499 | infovec = NULL; | ||
455 | while (modinfo[i].pathname) { | 500 | while (modinfo[i].pathname) { |
456 | char *desc, *s; | 501 | char *desc, *s; |
457 | if (!modinfo[i].aliases) { | 502 | if (!modinfo[i].aliases) { |
458 | parse_module(&modinfo[i], modinfo[i].pathname); | 503 | parse_module(&modinfo[i], modinfo[i].pathname); |
459 | } | 504 | } |
460 | if (result) { | ||
461 | i++; | ||
462 | continue; | ||
463 | } | ||
464 | /* "alias1 symbol:sym1 alias2 symbol:sym2" */ | 505 | /* "alias1 symbol:sym1 alias2 symbol:sym2" */ |
465 | desc = str_2_list(modinfo[i].aliases); | 506 | desc = str_2_list(modinfo[i].aliases); |
466 | /* Does matching substring exist? */ | 507 | /* Does matching substring exist? */ |
@@ -472,13 +513,12 @@ static module_info* find_alias(const char *alias) | |||
472 | if (fnmatch(s, alias, 0) == 0) { | 513 | if (fnmatch(s, alias, 0) == 0) { |
473 | dbg1_error_msg("found alias '%s' in module '%s'", | 514 | dbg1_error_msg("found alias '%s' in module '%s'", |
474 | alias, modinfo[i].pathname); | 515 | alias, modinfo[i].pathname); |
475 | result = &modinfo[i]; | 516 | infovec = xrealloc_vector(infovec, 1, infoidx); |
517 | infovec[infoidx++] = &modinfo[i]; | ||
476 | break; | 518 | break; |
477 | } | 519 | } |
478 | } | 520 | } |
479 | free(desc); | 521 | free(desc); |
480 | if (result && dep_bb_fd < 0) | ||
481 | return result; | ||
482 | i++; | 522 | i++; |
483 | } | 523 | } |
484 | 524 | ||
@@ -487,8 +527,8 @@ static module_info* find_alias(const char *alias) | |||
487 | write_out_dep_bb(dep_bb_fd); | 527 | write_out_dep_bb(dep_bb_fd); |
488 | } | 528 | } |
489 | 529 | ||
490 | dbg1_error_msg("find_alias '%s' returns %p", alias, result); | 530 | dbg1_error_msg("find_alias '%s' returns %d results", alias, infoidx); |
491 | return result; | 531 | return infovec; |
492 | } | 532 | } |
493 | 533 | ||
494 | #if ENABLE_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED | 534 | #if ENABLE_FEATURE_MODPROBE_SMALL_CHECK_ALREADY_LOADED |
@@ -524,14 +564,23 @@ static int already_loaded(const char *name) | |||
524 | static void process_module(char *name, const char *cmdline_options) | 564 | static void process_module(char *name, const char *cmdline_options) |
525 | { | 565 | { |
526 | char *s, *deps, *options; | 566 | char *s, *deps, *options; |
567 | module_info **infovec; | ||
527 | module_info *info; | 568 | module_info *info; |
569 | int infoidx; | ||
528 | int is_rmmod = (option_mask32 & OPT_r) != 0; | 570 | int is_rmmod = (option_mask32 & OPT_r) != 0; |
571 | |||
529 | dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); | 572 | dbg1_error_msg("process_module('%s','%s')", name, cmdline_options); |
530 | 573 | ||
531 | replace(name, '-', '_'); | 574 | replace(name, '-', '_'); |
532 | 575 | ||
533 | dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod); | 576 | dbg1_error_msg("already_loaded:%d is_rmmod:%d", already_loaded(name), is_rmmod); |
534 | if (already_loaded(name) != is_rmmod) { | 577 | /* |
578 | * We used to have "is_rmmod != already_loaded(name)" check here, but | ||
579 | * modprobe -r pci:v00008086d00007010sv00000000sd00000000bc01sc01i80 | ||
580 | * won't unload modules (there are more than one) | ||
581 | * which have this alias. | ||
582 | */ | ||
583 | if (!is_rmmod && already_loaded(name)) { | ||
535 | dbg1_error_msg("nothing to do for '%s'", name); | 584 | dbg1_error_msg("nothing to do for '%s'", name); |
536 | return; | 585 | return; |
537 | } | 586 | } |
@@ -560,39 +609,51 @@ static void process_module(char *name, const char *cmdline_options) | |||
560 | if (!module_count) { | 609 | if (!module_count) { |
561 | /* Scan module directory. This is done only once. | 610 | /* Scan module directory. This is done only once. |
562 | * It will attempt module load, and will exit(EXIT_SUCCESS) | 611 | * It will attempt module load, and will exit(EXIT_SUCCESS) |
563 | * on success. */ | 612 | * on success. |
613 | */ | ||
564 | module_found_idx = -1; | 614 | module_found_idx = -1; |
565 | recursive_action(".", | 615 | recursive_action(".", |
566 | ACTION_RECURSE, /* flags */ | 616 | ACTION_RECURSE, /* flags */ |
567 | fileAction, /* file action */ | 617 | fileAction, /* file action */ |
568 | NULL, /* dir action */ | 618 | NULL, /* dir action */ |
569 | name, /* user data */ | 619 | name, /* user data */ |
570 | 0); /* depth */ | 620 | 0 /* depth */ |
621 | ); | ||
571 | dbg1_error_msg("dirscan complete"); | 622 | dbg1_error_msg("dirscan complete"); |
572 | /* Module was not found, or load failed, or is_rmmod */ | 623 | /* Module was not found, or load failed, or is_rmmod */ |
573 | if (module_found_idx >= 0) { /* module was found */ | 624 | if (module_found_idx >= 0) { /* module was found */ |
574 | info = &modinfo[module_found_idx]; | 625 | infovec = xzalloc(2 * sizeof(infovec[0])); |
626 | infovec[0] = &modinfo[module_found_idx]; | ||
575 | } else { /* search for alias, not a plain module name */ | 627 | } else { /* search for alias, not a plain module name */ |
576 | info = find_alias(name); | 628 | infovec = find_alias(name); |
577 | } | 629 | } |
578 | } else { | 630 | } else { |
579 | info = find_alias(name); | 631 | infovec = find_alias(name); |
580 | } | 632 | } |
581 | 633 | ||
582 | // Problem here: there can be more than one module | 634 | /* There can be more than one module for the given alias. For example, |
583 | // for the given alias. For example, | 635 | * "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches |
584 | // "pci:v00008086d00007010sv00000000sd00000000bc01sc01i80" matches | 636 | * ata_piix because it has alias "pci:v00008086d00007010sv*sd*bc*sc*i*" |
585 | // ata_piix because it has an alias "pci:v00008086d00007010sv*sd*bc*sc*i*" | 637 | * and ata_generic, it has alias "pci:v*d*sv*sd*bc01sc01i*" |
586 | // and ata_generic, it has an alias "alias=pci:v*d*sv*sd*bc01sc01i*" | 638 | * Standard modprobe loads them both. We achieve it by returning |
587 | // Standard modprobe would load them both. | 639 | * a *list* of modinfo pointers from find_alias(). |
588 | // In this code, find_alias() returns only the first matching module. | 640 | */ |
589 | 641 | ||
590 | /* rmmod? unload it by name */ | 642 | /* rmmod or modprobe -r? unload module(s) */ |
591 | if (is_rmmod) { | 643 | if (is_rmmod) { |
592 | if (delete_module(name, O_NONBLOCK | O_EXCL) != 0) { | 644 | infoidx = 0; |
593 | if (!(option_mask32 & OPT_q)) | 645 | while ((info = infovec[infoidx++]) != NULL) { |
594 | bb_perror_msg("remove '%s'", name); | 646 | int r; |
595 | goto ret; | 647 | char modname[MODULE_NAME_LEN]; |
648 | |||
649 | filename2modname(info->pathname, modname); | ||
650 | r = delete_module(modname, O_NONBLOCK | O_EXCL); | ||
651 | dbg1_error_msg("delete_module('%s', O_NONBLOCK | O_EXCL):%d", modname, r); | ||
652 | if (r != 0) { | ||
653 | if (!(option_mask32 & OPT_q)) | ||
654 | bb_perror_msg("remove '%s'", modname); | ||
655 | goto ret; | ||
656 | } | ||
596 | } | 657 | } |
597 | 658 | ||
598 | if (applet_name[0] == 'r') { | 659 | if (applet_name[0] == 'r') { |
@@ -608,7 +669,7 @@ static void process_module(char *name, const char *cmdline_options) | |||
608 | */ | 669 | */ |
609 | } | 670 | } |
610 | 671 | ||
611 | if (!info) { | 672 | if (!infovec) { |
612 | /* both dirscan and find_alias found nothing */ | 673 | /* both dirscan and find_alias found nothing */ |
613 | if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ | 674 | if (!is_rmmod && applet_name[0] != 'd') /* it wasn't rmmod or depmod */ |
614 | bb_error_msg("module '%s' not found", name); | 675 | bb_error_msg("module '%s' not found", name); |
@@ -616,36 +677,41 @@ static void process_module(char *name, const char *cmdline_options) | |||
616 | goto ret; | 677 | goto ret; |
617 | } | 678 | } |
618 | 679 | ||
619 | /* Iterate thru dependencies, trying to (un)load them */ | 680 | infoidx = 0; |
620 | deps = str_2_list(info->deps); | 681 | while ((info = infovec[infoidx++]) != NULL) { |
621 | for (s = deps; *s; s += strlen(s) + 1) { | 682 | /* Iterate thru dependencies, trying to (un)load them */ |
622 | //if (strcmp(name, s) != 0) // N.B. do loops exist? | 683 | deps = str_2_list(info->deps); |
623 | dbg1_error_msg("recurse on dep '%s'", s); | 684 | for (s = deps; *s; s += strlen(s) + 1) { |
624 | process_module(s, NULL); | 685 | //if (strcmp(name, s) != 0) // N.B. do loops exist? |
625 | dbg1_error_msg("recurse on dep '%s' done", s); | 686 | dbg1_error_msg("recurse on dep '%s'", s); |
626 | } | 687 | process_module(s, NULL); |
627 | free(deps); | 688 | dbg1_error_msg("recurse on dep '%s' done", s); |
689 | } | ||
690 | free(deps); | ||
628 | 691 | ||
629 | /* modprobe -> load it */ | 692 | if (is_rmmod) |
630 | if (!is_rmmod) { | 693 | continue; |
631 | if (!options || strstr(options, "blacklist") == NULL) { | 694 | |
632 | errno = 0; | 695 | /* We are modprobe: load it */ |
633 | if (load_module(info->pathname, options) != 0) { | 696 | if (options && strstr(options, "blacklist")) { |
634 | if (EEXIST != errno) { | ||
635 | bb_error_msg("'%s': %s", | ||
636 | info->pathname, | ||
637 | moderror(errno)); | ||
638 | } else { | ||
639 | dbg1_error_msg("'%s': %s", | ||
640 | info->pathname, | ||
641 | moderror(errno)); | ||
642 | } | ||
643 | } | ||
644 | } else { | ||
645 | dbg1_error_msg("'%s': blacklisted", info->pathname); | 697 | dbg1_error_msg("'%s': blacklisted", info->pathname); |
698 | continue; | ||
699 | } | ||
700 | errno = 0; | ||
701 | if (load_module(info->pathname, options) != 0) { | ||
702 | if (EEXIST != errno) { | ||
703 | bb_error_msg("'%s': %s", | ||
704 | info->pathname, | ||
705 | moderror(errno)); | ||
706 | } else { | ||
707 | dbg1_error_msg("'%s': %s", | ||
708 | info->pathname, | ||
709 | moderror(errno)); | ||
710 | } | ||
646 | } | 711 | } |
647 | } | 712 | } |
648 | ret: | 713 | ret: |
714 | free(infovec); | ||
649 | free(options); | 715 | free(options); |
650 | //TODO: return load attempt result from process_module. | 716 | //TODO: return load attempt result from process_module. |
651 | //If dep didn't load ok, continuing makes little sense. | 717 | //If dep didn't load ok, continuing makes little sense. |
@@ -703,10 +769,6 @@ The following options are useful for people managing distributions: | |||
703 | 769 | ||
704 | //usage:#if ENABLE_MODPROBE_SMALL | 770 | //usage:#if ENABLE_MODPROBE_SMALL |
705 | 771 | ||
706 | //// Note: currently, help system shows modprobe --help text for all aliased cmds | ||
707 | //// (see APPLET_ODDNAME macro definition). | ||
708 | //// All other help texts defined below are not used. FIXME? | ||
709 | |||
710 | //usage:#define depmod_trivial_usage NOUSAGE_STR | 772 | //usage:#define depmod_trivial_usage NOUSAGE_STR |
711 | //usage:#define depmod_full_usage "" | 773 | //usage:#define depmod_full_usage "" |
712 | 774 | ||
@@ -720,7 +782,7 @@ The following options are useful for people managing distributions: | |||
720 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") | 782 | //usage: IF_NOT_FEATURE_2_4_MODULES("FILE ") |
721 | //usage: "[SYMBOL=VALUE]..." | 783 | //usage: "[SYMBOL=VALUE]..." |
722 | //usage:#define insmod_full_usage "\n\n" | 784 | //usage:#define insmod_full_usage "\n\n" |
723 | //usage: "Load the specified kernel modules into the kernel" | 785 | //usage: "Load kernel module" |
724 | //usage: IF_FEATURE_2_4_MODULES( "\n" | 786 | //usage: IF_FEATURE_2_4_MODULES( "\n" |
725 | //usage: "\n -f Force module to load into the wrong kernel version" | 787 | //usage: "\n -f Force module to load into the wrong kernel version" |
726 | //usage: "\n -k Make module autoclean-able" | 788 | //usage: "\n -k Make module autoclean-able" |
@@ -745,7 +807,7 @@ The following options are useful for people managing distributions: | |||
745 | //usage: "$ rmmod tulip\n" | 807 | //usage: "$ rmmod tulip\n" |
746 | 808 | ||
747 | //usage:#define modprobe_trivial_usage | 809 | //usage:#define modprobe_trivial_usage |
748 | //usage: "[-qfwrsv] MODULE [symbol=value]..." | 810 | //usage: "[-qfwrsv] MODULE [SYMBOL=VALUE]..." |
749 | //usage:#define modprobe_full_usage "\n\n" | 811 | //usage:#define modprobe_full_usage "\n\n" |
750 | //usage: " -r Remove MODULE (stacks) or do autoclean" | 812 | //usage: " -r Remove MODULE (stacks) or do autoclean" |
751 | //usage: "\n -q Quiet" | 813 | //usage: "\n -q Quiet" |
diff --git a/modutils/modprobe.c b/modutils/modprobe.c index 7f7446d8e..f08f0850d 100644 --- a/modutils/modprobe.c +++ b/modutils/modprobe.c | |||
@@ -87,7 +87,7 @@ | |||
87 | //usage: | 87 | //usage: |
88 | //usage:#define modprobe_trivial_usage | 88 | //usage:#define modprobe_trivial_usage |
89 | //usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" | 89 | //usage: "[-alrqvsD" IF_FEATURE_MODPROBE_BLACKLIST("b") "]" |
90 | //usage: " MODULE [symbol=value]..." | 90 | //usage: " MODULE [SYMBOL=VALUE]..." |
91 | //usage:#define modprobe_full_usage "\n\n" | 91 | //usage:#define modprobe_full_usage "\n\n" |
92 | //usage: " -a Load multiple MODULEs" | 92 | //usage: " -a Load multiple MODULEs" |
93 | //usage: "\n -l List (MODULE is a pattern)" | 93 | //usage: "\n -l List (MODULE is a pattern)" |