It is often advantageous to pass parameters to built-in kernel modules
[opensuse:module-init-tools.git] / modprobe.c
1 /* modprobe.c: add or remove a module from the kernel, intelligently.
2     Copyright (C) 2001  Rusty Russell.
3     Copyright (C) 2002, 2003  Rusty Russell, IBM Corporation.
4
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18 */
19 #define _GNU_SOURCE /* asprintf */
20
21 #include <sys/utsname.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <sys/mman.h>
25 #include <fcntl.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <unistd.h>
33 #include <dirent.h>
34 #include <limits.h>
35 #include <elf.h>
36 #include <getopt.h>
37 #include <fnmatch.h>
38 #include <asm/unistd.h>
39 #include <sys/wait.h>
40 #include <syslog.h>
41
42 #define streq(a,b) (strcmp((a),(b)) == 0)
43 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
44
45 #include "zlibsupport.h"
46 #include "list.h"
47 #include "backwards_compat.c"
48
49 extern long init_module(void *, unsigned long, const char *);
50 extern long delete_module(const char *, unsigned int);
51
52 struct module {
53         struct list_head list;
54         char *modname;
55         char filename[0];
56 };
57
58 #ifndef MODULE_DIR
59 #define MODULE_DIR "/lib/modules"
60 #endif
61
62 typedef void (*errfn_t)(const char *fmt, ...);
63
64 /* Do we use syslog or stderr for messages? */
65 static int log;
66
67 static void message(const char *prefix, const char *fmt, va_list *arglist)
68 {
69         char *buf, *buf2;
70
71         vasprintf(&buf, fmt, *arglist);
72         asprintf(&buf2, "%s%s", prefix, buf);
73
74         if (log)
75                 syslog(LOG_NOTICE, "%s", buf2);
76         else
77                 fprintf(stderr, "%s", buf2);
78         free(buf2);
79         free(buf);
80 }
81
82 static int warned = 0;
83 static void warn(const char *fmt, ...)
84 {
85         va_list arglist;
86         warned++;
87         va_start(arglist, fmt);
88         message("WARNING: ", fmt, &arglist);
89         va_end(arglist);
90 }
91
92 static void fatal(const char *fmt, ...)
93 {
94         va_list arglist;
95         va_start(arglist, fmt);
96         message("FATAL: ", fmt, &arglist);
97         va_end(arglist);
98         exit(1);
99 }
100
101
102 static void grammar(const char *cmd, const char *filename, unsigned int line)
103 {
104         warn("%s line %u: ignoring bad line starting with '%s'\n",
105              filename, line, cmd);
106 }
107
108 static void *do_nofail(void *ptr, const char *file, int line, const char *expr)
109 {
110         if (!ptr) {
111                 fatal("Memory allocation failure %s line %d: %s.\n",
112                       file, line, expr);
113         }
114         return ptr;
115 }
116
117 #define NOFAIL(ptr)     do_nofail((ptr), __FILE__, __LINE__, #ptr)
118
119 static void print_usage(const char *progname)
120 {
121         fprintf(stderr,
122                 "Usage: %s [-v] [-V] [-C config-file] [-n] [-i] [-q] [-b] [-o <modname>] [ --dump-modversions ] <modname> [parameters...]\n"
123                 "%s -r [-n] [-i] [-v] <modulename> ...\n"
124                 "%s -l -t <dirname> [ -a <modulename> ...]\n",
125                 progname, progname, progname);
126         exit(1);
127 }
128
129 static int fgetc_wrapped(FILE *file, unsigned int *linenum)
130 {
131         for (;;) {
132                 int ch = fgetc(file);
133                 if (ch != '\\')
134                         return ch;
135                 ch = fgetc(file);
136                 if (ch != '\n')
137                         return ch;
138                 if (linenum)
139                         (*linenum)++;
140         }
141 }
142
143 static char *getline_wrapped(FILE *file, unsigned int *linenum)
144 {
145         int size = 1024;
146         int i = 0;
147         char *buf = NOFAIL(malloc(size));
148         for(;;) {
149                 int ch = fgetc_wrapped(file, linenum);
150                 if (i == size) {
151                         size *= 2;
152                         buf = NOFAIL(realloc(buf, size));
153                 }
154                 if (ch < 0 && i == 0) {
155                         free(buf);
156                         return NULL;
157                 }
158                 if (ch < 0 || ch == '\n') {
159                         if (linenum)
160                                 (*linenum)++;
161                         buf[i] = '\0';
162                         return NOFAIL(realloc(buf, i+1));
163                 }
164                 buf[i++] = ch;
165         }
166 }
167
168 static struct module *find_module(const char *filename, struct list_head *list)
169 {
170         struct module *i;
171
172         list_for_each_entry(i, list, list) {
173                 if (strcmp(i->filename, filename) == 0)
174                         return i;
175         }
176         return NULL;
177 }
178
179 /* Convert filename to the module name.  Works if filename == modname, too. */
180 static void filename2modname(char *modname, const char *filename)
181 {
182         const char *afterslash;
183         unsigned int i;
184
185         afterslash = strrchr(filename, '/');
186         if (!afterslash)
187                 afterslash = filename;
188         else
189                 afterslash++;
190
191         /* Convert to underscores, stop at first . */
192         for (i = 0; afterslash[i] && afterslash[i] != '.'; i++) {
193                 if (afterslash[i] == '-')
194                         modname[i] = '_';
195                 else
196                         modname[i] = afterslash[i];
197         }
198         modname[i] = '\0';
199 }
200
201 static int lock_file(const char *filename)
202 {
203         int fd = open(filename, O_RDWR, 0);
204
205         if (fd >= 0) {
206                 struct flock lock;
207                 lock.l_type = F_WRLCK;
208                 lock.l_whence = SEEK_SET;
209                 lock.l_start = 0;
210                 lock.l_len = 1;
211                 fcntl(fd, F_SETLKW, &lock);
212         } else
213                 /* Read-only filesystem?  There goes locking... */
214                 fd = open(filename, O_RDONLY, 0);
215         return fd;
216 }
217
218 static void unlock_file(int fd)
219 {
220         /* Valgrind is picky... */
221         close(fd);
222 }
223
224 static void add_module(char *filename, int namelen, struct list_head *list)
225 {
226         struct module *mod;
227
228         /* If it's a duplicate: move it to the end, so it gets
229            inserted where it is *first* required. */
230         mod = find_module(filename, list);
231         if (mod)
232                 list_del(&mod->list);
233         else {
234                 /* No match.  Create a new module. */
235                 mod = NOFAIL(malloc(sizeof(struct module) + namelen + 1));
236                 memcpy(mod->filename, filename, namelen);
237                 mod->filename[namelen] = '\0';
238                 mod->modname = NOFAIL(malloc(namelen + 1));
239                 filename2modname(mod->modname, mod->filename);
240         }
241
242         list_add_tail(&mod->list, list);
243 }
244
245 /* Compare len chars of a to b, with _ and - equivalent. */
246 static int modname_equal(const char *a, const char *b, unsigned int len)
247 {
248         unsigned int i;
249
250         if (strlen(b) != len)
251                 return 0;
252
253         for (i = 0; i < len; i++) {
254                 if ((a[i] == '_' || a[i] == '-')
255                     && (b[i] == '_' || b[i] == '-'))
256                         continue;
257                 if (a[i] != b[i])
258                         return 0;
259         }
260         return 1;
261 }
262
263 /* Fills in list of modules if this is the line we want. */
264 static int add_modules_dep_line(char *line,
265                                 const char *name,
266                                 struct list_head *list)
267 {
268         char *ptr;
269         int len;
270         char *modname;
271
272         /* Ignore lines without : or which start with a # */
273         ptr = strchr(line, ':');
274         if (ptr == NULL || line[strspn(line, "\t ")] == '#')
275                 return 0;
276
277         /* Is this the module we are looking for? */
278         *ptr = '\0';
279         if (strrchr(line, '/'))
280                 modname = strrchr(line, '/') + 1;
281         else
282                 modname = line;
283
284         len = strlen(modname);
285         if (strchr(modname, '.'))
286                 len = strchr(modname, '.') - modname;
287         if (!modname_equal(modname, name, len))
288                 return 0;
289
290         /* Create the list. */
291         add_module(line, ptr - line, list);
292
293         ptr++;
294         for(;;) {
295                 char *dep_start;
296                 ptr += strspn(ptr, " \t");
297                 if (*ptr == '\0')
298                         break;
299                 dep_start = ptr;
300                 ptr += strcspn(ptr, " \t");
301                 add_module(dep_start, ptr - dep_start, list);
302         }
303         return 1;
304 }
305
306 static void read_depends(const char *dirname,
307                          const char *start_name,
308                          struct list_head *list)
309 {
310         char *modules_dep_name;
311         char *line;
312         FILE *modules_dep;
313         int done = 0;
314
315         asprintf(&modules_dep_name, "%s/%s", dirname, "modules.dep");
316         modules_dep = fopen(modules_dep_name, "r");
317         if (!modules_dep)
318                 fatal("Could not load %s: %s\n",
319                       modules_dep_name, strerror(errno));
320
321         /* Stop at first line, as we can have duplicates (eg. symlinks
322            from boot/ */
323         while (!done && (line = getline_wrapped(modules_dep, NULL)) != NULL) {
324                 done = add_modules_dep_line(line, start_name, list);
325                 free(line);
326         }
327         fclose(modules_dep);
328         free(modules_dep_name);
329 }
330
331 /* We use error numbers in a loose translation... */
332 static const char *insert_moderror(int err)
333 {
334         switch (err) {
335         case ENOEXEC:
336                 return "Invalid module format";
337         case ENOENT:
338                 return "Unknown symbol in module, or unknown parameter (see dmesg)";
339         case ENOSYS:
340                 return "Kernel does not have module support";
341         default:
342                 return strerror(err);
343         }
344 }
345
346 static const char *remove_moderror(int err)
347 {
348         switch (err) {
349         case ENOENT:
350                 return "No such module";
351         case ENOSYS:
352                 return "Kernel does not have module unloading support";
353         default:
354                 return strerror(err);
355         }
356 }
357
358 /* Is module in /proc/modules?  If so, fill in usecount if not NULL. 
359    0 means no, 1 means yes, -1 means unknown.
360  */
361 static int module_in_kernel(const char *modname, unsigned int *usecount)
362 {
363         FILE *proc_modules;
364         char *line;
365
366 again:
367         /* Might not be mounted yet.  Don't fail. */
368         proc_modules = fopen("/proc/modules", "r");
369         if (!proc_modules)
370                 return -1;
371
372         while ((line = getline_wrapped(proc_modules, NULL)) != NULL) {
373                 char *entry = strtok(line, " \n");
374
375                 if (entry && streq(entry, modname)) {
376                         /* If it exists, usecount is the third entry. */
377                         if (!strtok(NULL, " \n"))
378                                 goto out;
379
380                         if (!(entry = strtok(NULL, " \n"))) /* usecount */
381                                 goto out;
382                         else
383                                 if (usecount)
384                                         *usecount = atoi(entry);
385
386                         /* Followed by - then status. */
387                         if (strtok(NULL, " \n")
388                             && (entry = strtok(NULL, " \n")) != NULL) {
389                                 /* Locking will fail on ro fs, we might hit
390                                  * cases where module is in flux.  Spin. */
391                                 if (streq(entry, "Loading")
392                                     || streq(entry, "Unloading")) {
393                                         usleep(100000);
394                                         free(line);
395                                         fclose(proc_modules);
396                                         goto again;
397                                 }
398                         }
399
400                 out:
401                         free(line);
402                         fclose(proc_modules);
403                         return 1;
404                 }
405                 free(line);
406         }
407         fclose(proc_modules);
408         return 0;
409 }
410
411 static void replace_modname(struct module *module,
412                             void *mem, unsigned long len,
413                             const char *oldname, const char *newname)
414 {
415         char *p;
416
417         /* 64 - sizeof(unsigned long) - 1 */
418         if (strlen(newname) > 55)
419                 fatal("New name %s is too long\n", newname);
420
421         /* Find where it is in the module structure.  Don't assume layout! */
422         for (p = mem; p < (char *)mem + len - strlen(oldname); p++) {
423                 if (memcmp(p, oldname, strlen(oldname)) == 0) {
424                         strcpy(p, newname);
425                         return;
426                 }
427         }
428
429         warn("Could not find old name in %s to replace!\n", module->filename);
430 }
431
432 static void *get_section32(void *file,
433                            unsigned long size,
434                            const char *name,
435                            unsigned long *secsize)
436 {
437         Elf32_Ehdr *hdr = file;
438         Elf32_Shdr *sechdrs = file + hdr->e_shoff;
439         const char *secnames;
440         unsigned int i;
441
442         /* Too short? */
443         if (size < sizeof(*hdr))
444                 return NULL;
445         if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))
446                 return NULL;
447         if (size < sechdrs[hdr->e_shstrndx].sh_offset)
448                 return NULL;
449                 
450         secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;
451         for (i = 1; i < hdr->e_shnum; i++)
452                 if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) {
453                         *secsize = sechdrs[i].sh_size;
454                         return file + sechdrs[i].sh_offset;
455                 }
456         return NULL;
457 }
458
459 static void *get_section64(void *file,
460                            unsigned long size,
461                            const char *name,
462                            unsigned long *secsize)
463 {
464         Elf64_Ehdr *hdr = file;
465         Elf64_Shdr *sechdrs = file + hdr->e_shoff;
466         const char *secnames;
467         unsigned int i;
468
469         /* Too short? */
470         if (size < sizeof(*hdr))
471                 return NULL;
472         if (size < hdr->e_shoff + hdr->e_shnum * sizeof(sechdrs[0]))
473                 return NULL;
474         if (size < sechdrs[hdr->e_shstrndx].sh_offset)
475                 return NULL;
476                 
477         secnames = file + sechdrs[hdr->e_shstrndx].sh_offset;
478         for (i = 1; i < hdr->e_shnum; i++)
479                 if (strcmp(secnames + sechdrs[i].sh_name, name) == 0) {
480                         *secsize = sechdrs[i].sh_size;
481                         return file + sechdrs[i].sh_offset;
482                 }
483         return NULL;
484 }
485
486 static int elf_ident(void *mod, unsigned long size)
487 {
488         /* "\177ELF" <byte> where byte = 001 for 32-bit, 002 for 64 */
489         char *ident = mod;
490
491         if (size < EI_CLASS || memcmp(mod, ELFMAG, SELFMAG) != 0)
492                 return ELFCLASSNONE;
493         return ident[EI_CLASS];
494 }
495
496 static void *get_section(void *file,
497                          unsigned long size,
498                          const char *name,
499                          unsigned long *secsize)
500 {
501         switch (elf_ident(file, size)) {
502         case ELFCLASS32:
503                 return get_section32(file, size, name, secsize);
504         case ELFCLASS64:
505                 return get_section64(file, size, name, secsize);
506         default:
507                 return NULL;
508         }
509 }
510
511 static void rename_module(struct module *module,
512                           void *mod,
513                           unsigned long len,
514                           const char *newname)
515 {
516         void *modstruct;
517         unsigned long modstruct_len;
518
519         /* Old-style */
520         modstruct = get_section(mod, len, ".gnu.linkonce.this_module",
521                                 &modstruct_len);
522         /* New-style */
523         if (!modstruct)
524                 modstruct = get_section(mod, len, "__module", &modstruct_len);
525         if (!modstruct)
526                 warn("Could not find module name to change in %s\n",
527                      module->filename);
528         else
529                 replace_modname(module, modstruct, modstruct_len,
530                                 module->modname, newname);
531 }
532
533 /* Kernel told to ignore these sections if SHF_ALLOC not set. */
534 static void invalidate_section32(void *mod, const char *secname)
535 {
536         Elf32_Ehdr *hdr = mod;
537         Elf32_Shdr *sechdrs = mod + hdr->e_shoff;
538         const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset;
539         unsigned int i;
540
541         for (i = 1; i < hdr->e_shnum; i++)
542                 if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0)
543                         sechdrs[i].sh_flags &= ~SHF_ALLOC;
544 }
545
546 static void invalidate_section64(void *mod, const char *secname)
547 {
548         Elf64_Ehdr *hdr = mod;
549         Elf64_Shdr *sechdrs = mod + hdr->e_shoff;
550         const char *secnames = mod + sechdrs[hdr->e_shstrndx].sh_offset;
551         unsigned int i;
552
553         for (i = 1; i < hdr->e_shnum; i++)
554                 if (strcmp(secnames+sechdrs[i].sh_name, secname) == 0)
555                         sechdrs[i].sh_flags &= ~(unsigned long long)SHF_ALLOC;
556 }
557
558 static void strip_section(struct module *module,
559                           void *mod,
560                           unsigned long len,
561                           const char *secname)
562 {
563         switch (elf_ident(mod, len)) {
564         case ELFCLASS32:
565                 invalidate_section32(mod, secname);
566                 break;
567         case ELFCLASS64:
568                 invalidate_section64(mod, secname);
569                 break;
570         default:
571                 warn("Unknown module format in %s: not forcing version\n",
572                      module->filename);
573         }
574 }
575
576 static const char *next_string(const char *string, unsigned long *secsize)
577 {
578         /* Skip non-zero chars */
579         while (string[0]) {
580                 string++;
581                 if ((*secsize)-- <= 1)
582                         return NULL;
583         }
584
585         /* Skip any zero padding. */
586         while (!string[0]) {
587                 string++;
588                 if ((*secsize)-- <= 1)
589                         return NULL;
590         }
591         return string;
592 }
593
594 static void clear_magic(struct module *module, void *mod, unsigned long len)
595 {
596         const char *p;
597         unsigned long modlen;
598
599         /* Old-style: __vermagic section */
600         strip_section(module, mod, len, "__vermagic");
601
602         /* New-style: in .modinfo section */
603         for (p = get_section(mod, len, ".modinfo", &modlen);
604              p;
605              p = next_string(p, &modlen)) {
606                 if (strncmp(p, "vermagic=", strlen("vermagic=")) == 0) {
607                         memset((char *)p, 0, strlen(p));
608                         return;
609                 }
610         }
611 }
612
613 struct module_options
614 {
615         struct module_options *next;
616         char *modulename;
617         char *options;
618 };
619
620 struct module_command
621 {
622         struct module_command *next;
623         char *modulename;
624         char *command;
625 };
626
627 struct module_alias
628 {
629         struct module_alias *next;
630         char *module;
631 };
632
633 struct module_blacklist
634 {
635         struct module_blacklist *next;
636         char *modulename;
637 };
638
639 /* Link in a new option line from the config file. */
640 static struct module_options *
641 add_options(const char *modname,
642             const char *option,
643             struct module_options *options)
644 {
645         struct module_options *new;
646         char *tab; 
647
648         new = NOFAIL(malloc(sizeof(*new)));
649         new->modulename = NOFAIL(strdup(modname));
650         new->options = NOFAIL(strdup(option));
651         /* We can handle tabs, kernel can't. */
652         for (tab = strchr(new->options, '\t'); tab; tab = strchr(tab, '\t'))
653                 *tab = ' ';
654         new->next = options;
655         return new;
656 }
657
658 /* Link in a new install line from the config file. */
659 static struct module_command *
660 add_command(const char *modname,
661                const char *command,
662                struct module_command *commands)
663 {
664         struct module_command *new;
665
666         new = NOFAIL(malloc(sizeof(*new)));
667         new->modulename = NOFAIL(strdup(modname));
668         new->command = NOFAIL(strdup(command));
669         new->next = commands;
670         return new;
671 }
672
673 /* Link in a new alias line from the config file. */
674 static struct module_alias *
675 add_alias(const char *modname, struct module_alias *aliases)
676 {
677         struct module_alias *new;
678
679         new = NOFAIL(malloc(sizeof(*new)));
680         new->module = NOFAIL(strdup(modname));
681         new->next = aliases;
682         return new;
683 }
684
685 /* Link in a new blacklist line from the config file. */
686 static struct module_blacklist *
687 add_blacklist(const char *modname, struct module_blacklist *blacklist)
688 {
689         struct module_blacklist *new;
690
691         new = NOFAIL(malloc(sizeof(*new)));
692         new->modulename = NOFAIL(strdup(modname));
693         new->next = blacklist;
694         return new;
695 }
696
697 /* Find blacklist commands if any. */
698 static  int
699 find_blacklist(const char *modname, const struct module_blacklist *blacklist)
700 {
701         while (blacklist) {
702                 if (strcmp(blacklist->modulename, modname) == 0)
703                         return 1;
704                 blacklist = blacklist->next;
705         }
706         return 0;
707 }
708
709 /* return a new alias list, with backlisted elems filtered out */
710 static struct module_alias *
711 apply_blacklist(const struct module_alias *aliases,
712                 const struct module_blacklist *blacklist)
713 {
714         struct module_alias *result = NULL;
715         while (aliases) {
716                 char *modname = aliases->module;
717                 if (!find_blacklist(modname, blacklist))
718                         result = add_alias(modname, result);
719                 aliases = aliases->next;
720         }
721         return result;
722 }
723
724 /* Find install commands if any. */
725 static const char *find_command(const char *modname,
726                                 const struct module_command *commands)
727 {
728         while (commands) {
729                 if (fnmatch(commands->modulename, modname, 0) == 0)
730                         return commands->command;
731                 commands = commands->next;
732         }
733         return NULL;
734 }
735
736 static char *append_option(char *options, const char *newoption)
737 {
738         options = NOFAIL(realloc(options, strlen(options) + 1
739                                  + strlen(newoption) + 1));
740         if (strlen(options)) strcat(options, " ");
741         strcat(options, newoption);
742         return options;
743 }
744
745 /* Add to options */
746 static char *add_extra_options(const char *modname,
747                                char *optstring,
748                                const struct module_options *options)
749 {
750         while (options) {
751                 if (strcmp(options->modulename, modname) == 0)
752                         optstring = append_option(optstring, options->options);
753                 options = options->next;
754         }
755         return optstring;
756 }
757
758 /* If we don't flush, then child processes print before we do */
759 static void verbose_printf(int verbose, const char *fmt, ...)
760 {
761         va_list arglist;
762
763         if (verbose) {
764                 va_start(arglist, fmt);
765                 vprintf(fmt, arglist);
766                 fflush(stdout);
767                 va_end(arglist);
768         }
769 }
770
771 /* Do an install/remove command: replace $CMDLINE_OPTS if it's specified. */
772 static void do_command(const char *modname,
773                        const char *command,
774                        int verbose, int dry_run,
775                        errfn_t error,
776                        const char *type,
777                        const char *cmdline_opts)
778 {
779         int ret;
780         char *p, *replaced_cmd = NOFAIL(strdup(command));
781
782         while ((p = strstr(replaced_cmd, "$CMDLINE_OPTS")) != NULL) {
783                 char *new;
784                 asprintf(&new, "%.*s%s%s",
785                          (int)(p - replaced_cmd), replaced_cmd, cmdline_opts,
786                          p + strlen("$CMDLINE_OPTS"));
787                 NOFAIL(new);
788                 free(replaced_cmd);
789                 replaced_cmd = new;
790         }
791
792         verbose_printf(verbose, "%s %s\n", type, replaced_cmd);
793         if (dry_run)
794                 return;
795
796         setenv("MODPROBE_MODULE", modname, 1);
797         ret = system(replaced_cmd);
798         if (ret == -1 || WEXITSTATUS(ret))
799                 error("Error running %s command for %s\n", type, modname);
800         free(replaced_cmd);
801 }
802
803 /* Actually do the insert.  Frees second arg. */
804 static void insmod(struct list_head *list,
805                    char *optstring,
806                    const char *newname,
807                    int first_time,
808                    errfn_t error,
809                    int dry_run,
810                    int verbose,
811                    const struct module_options *options,
812                    const struct module_command *commands,
813                    int ignore_commands,
814                    int ignore_proc,
815                    int strip_vermagic,
816                    int strip_modversion,
817                    const char *cmdline_opts)
818 {
819         int ret, fd;
820         unsigned long len;
821         void *map;
822         const char *command;
823         struct module *mod = list_entry(list->next, struct module, list);
824
825         /* Take us off the list. */
826         list_del(&mod->list);
827
828         /* Do things we (or parent) depend on first, but don't die if
829          * they fail. */
830         if (!list_empty(list)) {
831                 insmod(list, NOFAIL(strdup("")), NULL, 0, warn,
832                        dry_run, verbose, options, commands, 0, ignore_proc,
833                        strip_vermagic, strip_modversion, "");
834         }
835
836         /* Lock before we look, in case it's initializing. */
837         fd = lock_file(mod->filename);
838         if (fd < 0) {
839                 error("Could not open '%s': %s\n",
840                       mod->filename, strerror(errno));
841                 goto out_optstring;
842         }
843
844         /* Don't do ANYTHING if already in kernel. */
845         if (!ignore_proc
846             && module_in_kernel(newname ?: mod->modname, NULL) == 1) {
847                 if (first_time)
848                         error("Module %s already in kernel.\n",
849                               newname ?: mod->modname);
850                 goto out_unlock;
851         }
852
853         command = find_command(mod->modname, commands);
854         if (command && !ignore_commands) {
855                 /* It might recurse: unlock. */
856                 unlock_file(fd);
857                 do_command(mod->modname, command, verbose, dry_run, error,
858                            "install", cmdline_opts);
859                 goto out_optstring;
860         }
861
862         map = grab_fd(fd, &len);
863         if (!map) {
864                 error("Could not read '%s': %s\n",
865                       mod->filename, strerror(errno));
866                 goto out_unlock;
867         }
868
869         /* Rename it? */
870         if (newname)
871                 rename_module(mod, map, len, newname);
872
873         if (strip_modversion)
874                 strip_section(mod, map, len, "__versions");
875         if (strip_vermagic)
876                 clear_magic(mod, map, len);
877
878         /* Config file might have given more options */
879         optstring = add_extra_options(mod->modname, optstring, options);
880
881         verbose_printf(verbose, "insmod %s %s\n", mod->filename, optstring);
882
883         if (dry_run)
884                 goto out;
885
886         ret = init_module(map, len, optstring);
887         if (ret != 0) {
888                 if (errno == EEXIST) {
889                         if (first_time)
890                                 error("Module %s already in kernel.\n",
891                                       newname ?: mod->modname);
892                         goto out_unlock;
893                 }
894                 error("Error inserting %s (%s): %s\n",
895                       mod->modname, mod->filename, insert_moderror(errno));
896         }
897  out:
898         release_file(map, len);
899  out_unlock:
900         unlock_file(fd);
901  out_optstring:
902         free(optstring);
903         return;
904 }
905
906 /* Do recursive removal. */
907 static void rmmod(struct list_head *list,
908                   const char *name,
909                   int first_time,
910                   errfn_t error,
911                   int dry_run,
912                   int verbose,
913                   struct module_command *commands,
914                   int ignore_commands,
915                   int ignore_inuse,
916                   const char *cmdline_opts,
917                   int flags)
918 {
919         const char *command;
920         unsigned int usecount = 0;
921         int lock;
922         struct module *mod = list_entry(list->next, struct module, list);
923
924         /* Take first one off the list. */
925         list_del(&mod->list);
926
927         /* Ignore failure; it's best effort here. */
928         lock = lock_file(mod->filename);
929
930         if (!name)
931                 name = mod->modname;
932
933         /* Even if renamed, find commands to orig. name. */
934         command = find_command(mod->modname, commands);
935         if (command && !ignore_commands) {
936                 /* It might recurse: unlock. */
937                 unlock_file(lock);
938                 do_command(mod->modname, command, verbose, dry_run, error,
939                            "remove", cmdline_opts);
940                 goto remove_rest_no_unlock;
941         }
942
943         if (module_in_kernel(name, &usecount) == 0)
944                 goto nonexistent_module;
945
946         if (usecount != 0) {
947                 if (!ignore_inuse)
948                         error("Module %s is in use.\n", name);
949                 goto remove_rest;
950         }
951
952         verbose_printf(verbose, "rmmod %s\n", mod->filename);
953
954         if (dry_run)
955                 goto remove_rest;
956
957         if (delete_module(name, O_EXCL) != 0) {
958                 if (errno == ENOENT)
959                         goto nonexistent_module;
960                 error("Error removing %s (%s): %s\n",
961                       name, mod->filename,
962                       remove_moderror(errno));
963         }
964
965  remove_rest:
966         unlock_file(lock);
967  remove_rest_no_unlock:
968         /* Now do things we depend. */
969         if (!list_empty(list))
970                 rmmod(list, NULL, 0, warn, dry_run, verbose, commands,
971                       0, 1, "", flags);
972         return;
973
974 nonexistent_module:
975         if (first_time)
976                 fatal("Module %s is not in kernel.\n", mod->modname);
977         goto remove_rest;
978 }
979
980 /* Does path contain directory(s) subpath? */
981 static int type_matches(const char *path, const char *subpath)
982 {
983         char *subpath_with_slashes;
984         int ret;
985
986         asprintf(&subpath_with_slashes, "/%s/", subpath);
987         NOFAIL(subpath_with_slashes);
988
989         ret = (strstr(path, subpath_with_slashes) != NULL);
990         free(subpath_with_slashes);
991         return ret;
992 }
993
994 /* Careful!  Don't munge - in [ ] as per Debian Bug#350915 */
995 static char *underscores(char *string)
996 {
997         if (string) {
998                 unsigned int i;
999                 int inbracket = 0;
1000                 for (i = 0; string[i]; i++) {
1001                         switch (string[i]) {
1002                         case '[':
1003                                 inbracket++;
1004                                 break;
1005                         case ']':
1006                                 inbracket--;
1007                                 break;
1008                         case '-':
1009                                 if (!inbracket)
1010                                         string[i] = '_';
1011                         }
1012                 }
1013                 if (inbracket)
1014                         warn("Unmatched bracket in %s\n", string);
1015         }
1016         return string;
1017 }
1018
1019 static int do_wildcard(const char *dirname,
1020                        const char *type,
1021                        const char *wildcard)
1022 {
1023         char modules_dep_name[strlen(dirname) + sizeof("modules.dep") + 1];
1024         char *line, *wcard;
1025         FILE *modules_dep;
1026
1027         /* Canonicalize wildcard */
1028         wcard = strdup(wildcard);
1029         underscores(wcard);
1030
1031         sprintf(modules_dep_name, "%s/%s", dirname, "modules.dep");
1032         modules_dep = fopen(modules_dep_name, "r");
1033         if (!modules_dep)
1034                 fatal("Could not load %s: %s\n",
1035                       modules_dep_name, strerror(errno));
1036
1037         while ((line = getline_wrapped(modules_dep, NULL)) != NULL) {
1038                 char *ptr;
1039
1040                 /* Ignore lines without : or which start with a # */
1041                 ptr = strchr(line, ':');
1042                 if (ptr == NULL || line[strspn(line, "\t ")] == '#')
1043                         goto next;
1044                 *ptr = '\0';
1045
1046                 /* "type" must match complete directory component(s). */
1047                 if (!type || type_matches(line, type)) {
1048                         char modname[strlen(line)+1];
1049
1050                         filename2modname(modname, line);
1051                         if (fnmatch(wcard, modname, 0) == 0)
1052                                 printf("%s\n", line);
1053                 }
1054         next:
1055                 free(line);
1056         }
1057
1058         free(wcard);
1059         return 0;
1060 }
1061
1062 static char *strsep_skipspace(char **string, char *delim)
1063 {
1064         if (!*string)
1065                 return NULL;
1066         *string += strspn(*string, delim);
1067         return strsep(string, delim);
1068 }
1069
1070 /* Recursion */
1071 static int read_config(const char *filename,
1072                        const char *name,
1073                        int dump_only,
1074                        int removing,
1075                        struct module_options **options,
1076                        struct module_command **commands,
1077                        struct module_alias **alias,
1078                        struct module_blacklist **blacklist);
1079
1080 /* FIXME: Maybe should be extended to "alias a b [and|or c]...". --RR */
1081 static int read_config_file(const char *filename,
1082                             const char *name,
1083                             int dump_only,
1084                             int removing,
1085                             struct module_options **options,
1086                             struct module_command **commands,
1087                             struct module_alias **aliases,
1088                             struct module_blacklist **blacklist)
1089 {
1090         char *line;
1091         unsigned int linenum = 0;
1092         FILE *cfile;
1093
1094         cfile = fopen(filename, "r");
1095         if (!cfile)
1096                 return 0;
1097
1098         while ((line = getline_wrapped(cfile, &linenum)) != NULL) {
1099                 char *ptr = line;
1100                 char *cmd, *modname;
1101
1102                 if (dump_only)
1103                         printf("%s\n", line);
1104
1105                 cmd = strsep_skipspace(&ptr, "\t ");
1106                 if (cmd == NULL || cmd[0] == '#' || cmd[0] == '\0')
1107                         continue;
1108
1109                 if (strcmp(cmd, "alias") == 0) {
1110                         char *wildcard
1111                                 = underscores(strsep_skipspace(&ptr, "\t "));
1112                         char *realname
1113                                 = underscores(strsep_skipspace(&ptr, "\t "));
1114
1115                         if (!wildcard || !realname)
1116                                 grammar(cmd, filename, linenum);
1117                         else if (fnmatch(wildcard,name,0) == 0)
1118                                 *aliases = add_alias(realname, *aliases);
1119                 } else if (strcmp(cmd, "include") == 0) {
1120                         struct module_alias *newalias = NULL;
1121                         char *newfilename;
1122
1123                         newfilename = strsep_skipspace(&ptr, "\t ");
1124                         if (!newfilename)
1125                                 grammar(cmd, filename, linenum);
1126                         else {
1127                                 if (!read_config(newfilename, name,
1128                                                  dump_only, removing,
1129                                                  options, commands, &newalias,
1130                                                  blacklist))
1131                                         warn("Failed to open included"
1132                                               " config file %s: %s\n",
1133                                               newfilename, strerror(errno));
1134
1135                                 /* Files included override aliases,
1136                                    etc that was already set ... */
1137                                 if (newalias)
1138                                         *aliases = newalias;
1139                         }
1140                 } else if (strcmp(cmd, "options") == 0) {
1141                         modname = strsep_skipspace(&ptr, "\t ");
1142                         if (!modname || !ptr)
1143                                 grammar(cmd, filename, linenum);
1144                         else {
1145                                 ptr += strspn(ptr, "\t ");
1146                                 *options = add_options(underscores(modname),
1147                                                        ptr, *options);
1148                         }
1149                 } else if (strcmp(cmd, "install") == 0) {
1150                         modname = strsep_skipspace(&ptr, "\t ");
1151                         if (!modname || !ptr)
1152                                 grammar(cmd, filename, linenum);
1153                         else if (!removing) {
1154                                 ptr += strspn(ptr, "\t ");
1155                                 *commands = add_command(underscores(modname),
1156                                                         ptr, *commands);
1157                         }
1158                 } else if (strcmp(cmd, "blacklist") == 0) {
1159                         modname = strsep_skipspace(&ptr, "\t ");
1160                         if (!modname)
1161                                 grammar(cmd, filename, linenum);
1162                         else if (!removing) {
1163                                 *blacklist = add_blacklist(underscores(modname),
1164                                                         *blacklist);
1165                         }
1166                 } else if (strcmp(cmd, "remove") == 0) {
1167                         modname = strsep_skipspace(&ptr, "\t ");
1168                         if (!modname || !ptr)
1169                                 grammar(cmd, filename, linenum);
1170                         else if (removing) {
1171                                 ptr += strspn(ptr, "\t ");
1172                                 *commands = add_command(underscores(modname),
1173                                                         ptr, *commands);
1174                         }
1175                 } else
1176                         grammar(cmd, filename, linenum);
1177
1178                 free(line);
1179         }
1180         fclose(cfile);
1181         return 1;
1182 }
1183
1184 /* Simple format, ignore lines starting with #, one command per line.
1185    Returns true or false. */
1186 static int read_config(const char *filename,
1187                        const char *name,
1188                        int dump_only,
1189                        int removing,
1190                        struct module_options **options,
1191                        struct module_command **commands,
1192                        struct module_alias **aliases,
1193                        struct module_blacklist **blacklist)
1194 {
1195         DIR *dir;
1196         int ret = 0;
1197
1198         /* Reiser4 has file/directory duality: treat it as both. */
1199         dir = opendir(filename);
1200         if (dir) {
1201                 struct dirent *i;
1202                 while ((i = readdir(dir)) != NULL) {
1203                         if (!streq(i->d_name,".") && !streq(i->d_name,"..")) {
1204                                 char sub[strlen(filename) + 1
1205                                          + strlen(i->d_name) + 1];
1206
1207                                 sprintf(sub, "%s/%s", filename, i->d_name);
1208                                 if (!read_config(sub, name,
1209                                                  dump_only, removing, options,
1210                                                  commands, aliases, blacklist))
1211                                         warn("Failed to open"
1212                                              " config file %s: %s\n",
1213                                              sub, strerror(errno));
1214                         }
1215                 }
1216                 closedir(dir);
1217                 ret = 1;
1218         }
1219
1220         if (read_config_file(filename, name, dump_only, removing,
1221                              options, commands, aliases, blacklist))
1222                 ret = 1;
1223
1224         return ret;
1225 }
1226
1227 static const char *default_configs[] = 
1228 {
1229         "/etc/modprobe.conf",
1230         "/etc/modprobe.d",
1231 };
1232
1233 static void read_toplevel_config(const char *filename,
1234                                  const char *name,
1235                                  int dump_only,
1236                                  int removing,
1237                                  struct module_options **options,
1238                                  struct module_command **commands,
1239                                  struct module_alias **aliases,
1240                                  struct module_blacklist **blacklist)
1241 {
1242         unsigned int i;
1243
1244         if (filename) {
1245                 if (!read_config(filename, name, dump_only, removing,
1246                                  options, commands, aliases, blacklist))
1247                         fatal("Failed to open config file %s: %s\n",
1248                               filename, strerror(errno));
1249                 return;
1250         }
1251
1252         /* Try defaults. */
1253         for (i = 0; i < ARRAY_SIZE(default_configs); i++) {
1254                 if (read_config(default_configs[i], name, dump_only, removing,
1255                                 options, commands, aliases, blacklist))
1256                         return;
1257         }
1258 }
1259
1260 /* Read possible module arguments from the kernel command line. */
1261 static int read_kcmdline(int dump_only, struct module_options **options)
1262 {
1263         char *line;
1264         unsigned int linenum = 0;
1265         FILE *kcmdline;
1266
1267         kcmdline = fopen("/proc/cmdline", "r");
1268         if (!kcmdline)
1269                 return 0;
1270
1271         while ((line = getline_wrapped(kcmdline, &linenum)) != NULL) {
1272                 char *ptr = line;
1273                 char *arg;
1274
1275                 while ((arg = strsep_skipspace(&ptr, "\t ")) != NULL) {
1276                         char *sep, *modname, *opt;
1277
1278                         sep = strchr(arg, '.');
1279                         if (sep) {
1280                                 if (!strchr(sep, '='))
1281                                         continue;
1282                                 modname = arg;
1283                                 *sep = '\0';
1284                                 opt = ++sep;
1285
1286                                 if (dump_only)
1287                                         printf("options %s %s\n", modname, opt);
1288
1289                                 *options = add_options(underscores(modname),
1290                                                        opt, *options);
1291                         }
1292                 }
1293
1294                 free(line);
1295         }
1296         fclose(kcmdline);
1297         return 1;
1298 }
1299
1300 static void add_to_env_var(const char *option)
1301 {
1302         const char *oldenv;
1303
1304         if ((oldenv = getenv("MODPROBE_OPTIONS")) != NULL) {
1305                 char *newenv;
1306                 asprintf(&newenv, "%s %s", oldenv, option);
1307                 setenv("MODPROBE_OPTIONS", newenv, 1);
1308         } else
1309                 setenv("MODPROBE_OPTIONS", option, 1);
1310 }
1311
1312 /* Prepend options from environment. */
1313 static char **merge_args(char *args, char *argv[], int *argc)
1314 {
1315         char *arg, *argstring;
1316         char **newargs = NULL;
1317         unsigned int i, num_env = 0;
1318
1319         if (!args)
1320                 return argv;
1321
1322         argstring = NOFAIL(strdup(args));
1323         for (arg = strtok(argstring, " "); arg; arg = strtok(NULL, " ")) {
1324                 num_env++;
1325                 newargs = NOFAIL(realloc(newargs,
1326                                          sizeof(newargs[0])
1327                                          * (num_env + *argc + 1)));
1328                 newargs[num_env] = arg;
1329         }
1330
1331         /* Append commandline args */
1332         newargs[0] = argv[0];
1333         for (i = 1; i <= *argc; i++)
1334                 newargs[num_env+i] = argv[i];
1335
1336         *argc += num_env;
1337         return newargs;
1338 }
1339
1340 static char *gather_options(char *argv[])
1341 {
1342         char *optstring = NOFAIL(strdup(""));
1343
1344         /* Rest is module options */
1345         while (*argv) {
1346                 /* Quote value if it contains spaces. */
1347                 unsigned int eq = strcspn(*argv, "=");
1348
1349                 if (strchr(*argv+eq, ' ') && !strchr(*argv, '"')) {
1350                         char quoted[strlen(*argv) + 3];
1351                         (*argv)[eq] = '\0';
1352                         sprintf(quoted, "%s=\"%s\"", *argv, *argv+eq+1);
1353                         optstring = append_option(optstring, quoted);
1354                 } else
1355                         optstring = append_option(optstring, *argv);
1356                 argv++;
1357         }
1358         return optstring;
1359 }
1360
1361 static void handle_module(const char *modname,
1362                           struct list_head *todo_list,
1363                           const char *newname,
1364                           int remove,
1365                           char *options,
1366                           int first_time,
1367                           errfn_t error,
1368                           int dry_run,
1369                           int verbose,
1370                           struct module_options *modoptions,
1371                           struct module_command *commands,
1372                           int ignore_commands,
1373                           int ignore_proc,
1374                           int strip_vermagic,
1375                           int strip_modversion,
1376                           int unknown_silent,
1377                           const char *cmdline_opts,
1378                           int flags)
1379 {
1380         if (list_empty(todo_list)) {
1381                 const char *command;
1382
1383                 /* The dependencies have to be real modules, but
1384                    handle case where the first is completely bogus. */
1385                 command = find_command(modname, commands);
1386                 if (command && !ignore_commands) {
1387                         do_command(modname, command, verbose, dry_run, error,
1388                                    remove ? "remove":"install", cmdline_opts);
1389                         return;
1390                 }
1391
1392                 if (unknown_silent)
1393                         exit(1);
1394                 error("Module %s not found.\n", modname);
1395                 return;
1396         }
1397
1398         if (remove)
1399                 rmmod(todo_list, newname, first_time, error, dry_run, verbose,
1400                       commands, ignore_commands, 0, cmdline_opts, flags);
1401         else
1402                 insmod(todo_list, NOFAIL(strdup(options)), newname,
1403                        first_time, error, dry_run, verbose, modoptions,
1404                        commands, ignore_commands, ignore_proc, strip_vermagic,
1405                        strip_modversion, cmdline_opts);
1406 }
1407
1408 static struct option options[] = { { "verbose", 0, NULL, 'v' },
1409                                    { "version", 0, NULL, 'V' },
1410                                    { "config", 1, NULL, 'C' },
1411                                    { "name", 1, NULL, 'o' },
1412                                    { "remove", 0, NULL, 'r' },
1413                                    { "wait", 0, NULL, 'w' },
1414                                    { "showconfig", 0, NULL, 'c' },
1415                                    { "autoclean", 0, NULL, 'k' },
1416                                    { "quiet", 0, NULL, 'q' },
1417                                    { "show", 0, NULL, 'n' },
1418                                    { "dry-run", 0, NULL, 'n' },
1419                                    { "syslog", 0, NULL, 's' },
1420                                    { "type", 1, NULL, 't' },
1421                                    { "list", 0, NULL, 'l' },
1422                                    { "all", 0, NULL, 'a' },
1423                                    { "ignore-install", 0, NULL, 'i' },
1424                                    { "ignore-remove", 0, NULL, 'i' },
1425                                    { "force", 0, NULL, 'f' },
1426                                    { "force-vermagic", 0, NULL, 1 },
1427                                    { "force-modversion", 0, NULL, 2 },
1428                                    { "set-version", 1, NULL, 'S' },
1429                                    { "show-depends", 0, NULL, 'D' },
1430                                    { "first-time", 0, NULL, 3 },
1431                                    { "use-blacklist", 0, NULL, 'b' },
1432                                    { NULL, 0, NULL, 0 } };
1433
1434 #define MODPROBE_DEVFSD_CONF "/etc/modprobe.devfs"
1435
1436 /* This is a horrible hack to allow devfsd, which calls modprobe with
1437    -C /etc/modules.conf or /etc/modules.devfs, to work.  FIXME. */
1438 /* Modern devfsd or variants should use -q explicitly in 2.6. */
1439 static int is_devfs_call(char *argv[])
1440 {
1441         unsigned int i;
1442
1443         /* Look for "/dev" arg */
1444         for (i = 1; argv[i]; i++) {
1445                 if (strncmp(argv[i], "/dev/", 5) == 0)
1446                         return 1;
1447         }
1448         return 0;
1449 }
1450
1451 int main(int argc, char *argv[])
1452 {
1453         struct utsname buf;
1454         struct stat statbuf;
1455         int opt;
1456         int dump_only = 0;
1457         int dry_run = 0;
1458         int remove = 0;
1459         int verbose = 0;
1460         int unknown_silent = 0;
1461         int list_only = 0;
1462         int all = 0;
1463         int ignore_commands = 0;
1464         int strip_vermagic = 0;
1465         int strip_modversion = 0;
1466         int ignore_proc = 0;
1467         int first_time = 0;
1468         int use_blacklist = 0;
1469         unsigned int i, num_modules;
1470         char *type = NULL;
1471         const char *config = NULL;
1472         char *dirname, *optstring;
1473         char *newname = NULL;
1474         char *aliasfilename, *symfilename;
1475         errfn_t error = fatal;
1476         int flags = O_NONBLOCK|O_EXCL;
1477
1478         /* Prepend options from environment. */
1479         argv = merge_args(getenv("MODPROBE_OPTIONS"), argv, &argc);
1480
1481         /* --set-version overrides version, and disables backwards compat. */
1482         for (opt = 1; opt < argc; opt++)
1483                 if (strncmp(argv[opt],"--set-version",strlen("--set-version"))
1484                     == 0)
1485                         break;
1486
1487         if (opt == argc)
1488                 try_old_version("modprobe", argv);
1489
1490         uname(&buf);
1491         while ((opt = getopt_long(argc, argv, "vVC:o:rknqQsclt:aifbw", options, NULL)) != -1){
1492                 switch (opt) {
1493                 case 'v':
1494                         add_to_env_var("-v");
1495                         verbose = 1;
1496                         break;
1497                 case 'V':
1498                         puts(PACKAGE " version " VERSION);
1499                         exit(0);
1500                 case 'S':
1501                         strncpy(buf.release, optarg, sizeof(buf.release));
1502                         buf.release[sizeof(buf.release)-1] = '\0';
1503                         break;
1504                 case 'C':
1505                         if (is_devfs_call(argv)) {
1506                                 if (streq("/etc/modules.devfs", optarg)) {
1507                                         config = MODPROBE_DEVFSD_CONF;
1508                                         add_to_env_var("-C");
1509                                         add_to_env_var(config);
1510                                         /* Fall thru to -q */
1511                                 } else if (streq("/etc/modules.conf", optarg))
1512                                         /* Ignore config, fall thru to -q */
1513                                         ;
1514                                 else {
1515                                         /* False alarm.  Treat as normal. */
1516                                         config = optarg;
1517                                         add_to_env_var("-C");
1518                                         add_to_env_var(config);
1519                                         break;
1520                                 }
1521                         } else {
1522                                 config = optarg;
1523                                 add_to_env_var("-C");
1524                                 add_to_env_var(config);
1525                                 break;
1526                         }
1527                 case 'q':
1528                         unknown_silent = 1;
1529                         add_to_env_var("-q");
1530                         break;
1531                 case 'D':
1532                         dry_run = 1;
1533                         ignore_proc = 1;
1534                         verbose = 1;
1535                         add_to_env_var("-D");
1536                         break;
1537                 case 'o':
1538                         newname = optarg;
1539                         break;
1540                 case 'r':
1541                         remove = 1;
1542                         break;
1543                 case 'c':
1544                         dump_only = 1;
1545                         break;
1546                 case 't':
1547                         type = optarg;
1548                         break;
1549                 case 'l':
1550                         list_only = 1;
1551                         break;
1552                 case 'a':
1553                         all = 1;
1554                         error = warn;
1555                         break;
1556                 case 'k':
1557                         /* FIXME: This should actually do something */
1558                         break;
1559                 case 'n':
1560                         dry_run = 1;
1561                         break;
1562                 case 's':
1563                         add_to_env_var("-s");
1564                         log = 1;
1565                         break;
1566                 case 'i':
1567                         ignore_commands = 1;
1568                         break;
1569                 case 'f':
1570                         strip_vermagic = 1;
1571                         strip_modversion = 1;
1572                         break;
1573                 case 'b':
1574                         use_blacklist = 1;
1575                         break;
1576                 case 'w':
1577                         flags &= ~O_NONBLOCK;
1578                         break;
1579                 case 1:
1580                         strip_vermagic = 1;
1581                         break;
1582                 case 2:
1583                         strip_modversion = 1;
1584                         break;
1585                 case 3:
1586                         first_time = 1;
1587                         break;
1588                 default:
1589                         print_usage(argv[0]);
1590                 }
1591         }
1592
1593         /* If stderr not open, go to syslog */
1594         if (log || fstat(STDERR_FILENO, &statbuf) != 0) {
1595                 openlog("modprobe", LOG_CONS, LOG_DAEMON);
1596                 log = 1;
1597         }
1598
1599         if (argc < optind + 1 && !dump_only && !list_only && !remove)
1600                 print_usage(argv[0]);
1601
1602         dirname = NOFAIL(malloc(strlen(buf.release) + sizeof(MODULE_DIR) + 1));
1603         sprintf(dirname, "%s/%s", MODULE_DIR, buf.release);
1604         aliasfilename = NOFAIL(malloc(strlen(dirname)
1605                                       + sizeof("/modules.alias")));
1606         sprintf(aliasfilename, "%s/modules.alias", dirname);
1607         symfilename = NOFAIL(malloc(strlen(dirname)
1608                                     + sizeof("/modules.symbols")));
1609         sprintf(symfilename, "%s/modules.symbols", dirname);
1610
1611         /* Old-style -t xxx wildcard?  Only with -l. */
1612         if (list_only) {
1613                 if (optind+1 < argc)
1614                         fatal("Can't have multiple wildcards\n");
1615                 /* fprintf(stderr, "man find\n"); return 1; */
1616                 return do_wildcard(dirname, type, argv[optind]?:"*");
1617         }
1618         if (type)
1619                 fatal("-t only supported with -l");
1620
1621         if (dump_only) {
1622                 struct module_command *commands = NULL;
1623                 struct module_options *modoptions = NULL;
1624                 struct module_alias *aliases = NULL;
1625                 struct module_blacklist *blacklist = NULL;
1626
1627                 read_toplevel_config(config, "", 1, 0,
1628                              &modoptions, &commands, &aliases, &blacklist);
1629                 read_kcmdline(1, &modoptions);
1630                 read_config(aliasfilename, "", 1, 0,&modoptions, &commands,
1631                             &aliases, &blacklist);
1632                 read_config(symfilename, "", 1, 0, &modoptions, &commands,
1633                             &aliases, &blacklist);
1634                 exit(0);
1635         }
1636
1637         if (remove || all) {
1638                 num_modules = argc - optind;
1639                 optstring = NOFAIL(strdup(""));
1640         } else {
1641                 num_modules = 1;
1642                 optstring = gather_options(argv+optind+1);
1643         }
1644
1645         /* num_modules is always 1 except for -r or -a. */
1646         for (i = 0; i < num_modules; i++) {
1647                 struct module_command *commands = NULL;
1648                 struct module_options *modoptions = NULL;
1649                 struct module_alias *aliases = NULL;
1650                 struct module_blacklist *blacklist = NULL;
1651                 LIST_HEAD(list);
1652                 char *modulearg = argv[optind + i];
1653
1654                 /* Convert name we are looking for */
1655                 underscores(modulearg);
1656
1657                 /* Returns the resolved alias, options */
1658                 read_toplevel_config(config, modulearg, 0,
1659                      remove, &modoptions, &commands, &aliases, &blacklist);
1660
1661                 /* Read module options from kernel command line */
1662                 read_kcmdline(0, &modoptions);
1663
1664                 /* No luck?  Try symbol names, if starts with symbol:. */
1665                 if (!aliases
1666                     && strncmp(modulearg, "symbol:", strlen("symbol:")) == 0)
1667                         read_config(symfilename, modulearg, 0,
1668                             remove, &modoptions, &commands,
1669                                 &aliases, &blacklist);
1670
1671                 if (!aliases) {
1672                         /* We only use canned aliases as last resort. */
1673                         read_depends(dirname, modulearg, &list);
1674
1675                         if (list_empty(&list)
1676                             && !find_command(modulearg, commands))
1677                         {
1678                                 read_config(aliasfilename, modulearg, 0,
1679                                             remove, &modoptions, &commands,
1680                                             &aliases, &blacklist);
1681                         }
1682                 }
1683
1684                 aliases = apply_blacklist(aliases, blacklist);
1685                 if (aliases) {
1686                         errfn_t err = error;
1687
1688                         /* More than one alias?  Don't bail out on failure. */
1689                         if (aliases->next)
1690                                 err = warn;
1691                         while (aliases) {
1692                                 /* Add the options for this alias. */
1693                                 char *opts = NOFAIL(strdup(optstring));
1694                                 opts = add_extra_options(modulearg,
1695                                                          opts, modoptions);
1696
1697                                 read_depends(dirname, aliases->module, &list);
1698                                 handle_module(aliases->module, &list, newname,
1699                                               remove, opts, first_time, err,
1700                                               dry_run, verbose, modoptions,
1701                                               commands, ignore_commands,
1702                                               ignore_proc, strip_vermagic,
1703                                               strip_modversion,
1704                                               unknown_silent,
1705                                               optstring, flags);
1706
1707                                 aliases = aliases->next;
1708                                 INIT_LIST_HEAD(&list);
1709                         }
1710                 } else {
1711                         if (use_blacklist
1712                             && find_blacklist(modulearg, blacklist))
1713                                 continue;
1714
1715                         handle_module(modulearg, &list, newname, remove,
1716                                       optstring, first_time, error, dry_run,
1717                                       verbose, modoptions, commands,
1718                                       ignore_commands, ignore_proc,
1719                                       strip_vermagic, strip_modversion,
1720                                       unknown_silent, optstring, flags);
1721                 }
1722         }
1723         if (log)
1724                 closelog();
1725
1726         return 0;
1727 }