Minor doc fix. Added several bugs to the todo list. Fixed the way init
[oweals/busybox.git] / insmod.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * Mini insmod implementation for busybox
4  *
5  * Copyright (C) 1999,2000 by Lineo, inc.
6  * Written by Erik Andersen <andersen@lineo.com>, <andersee@debian.org>
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21  *
22  */
23
24 #include "internal.h"
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <errno.h>
28 #include <unistd.h>
29 #include <dirent.h>
30 #include <sys/syscall.h>
31 #include <linux/module.h>
32
33 #define _PATH_MODULES   "/lib/modules"
34
35 #warning "Danger Will Robinson, Danger!!!"
36 #warning " "
37 #warning "insmod is still under construction.  Don't use it."
38 #warning " "
39 #warning "      You have been warned!"
40 #warning " "
41
42
43 /* Some firendly syscalls to cheer everyone's day...  */
44 _syscall2(int, init_module, const char *, name,
45                   const struct module *, info)
46 #ifndef BB_RMMOD
47 _syscall1(int, delete_module, const char *, name)
48 #else
49 extern int delete_module(const char *);
50 #endif
51
52 #if defined(__i386__) || defined(__m68k__) || defined(__arm__)
53 /* Jump through hoops to fixup error return codes */
54 #define __NR__create_module  __NR_create_module
55 static inline _syscall2(long, _create_module, const char *, name, size_t,
56                                                 size)
57 unsigned long create_module(const char *name, size_t size)
58 {
59         long ret = _create_module(name, size);
60
61         if (ret == -1 && errno > 125) {
62                 ret = -errno;
63                 errno = 0;
64         }
65         return ret;
66 }
67 #else
68 _syscall2(unsigned long, create_module, const char *, name, size_t, size)
69 #endif
70 static char m_filename[BUFSIZ + 1] = "\0";
71 static char m_fullName[BUFSIZ + 1] = "\0";
72 static const char insmod_usage[] =
73         "insmod [OPTION]... MODULE [symbol=value]...\n"
74 #ifndef BB_FEATURE_TRIVIAL_HELP
75         "\nLoads the specified kernel modules into the kernel.\n\n"
76         "Options:\n"
77
78         "\t-f\tForce module to load into the wrong kernel version.\n"
79         "\t-k\tMake module autoclean-able.\n"
80 #endif
81         ;
82
83
84 static int findNamedModule(const char *fileName, struct stat *statbuf)
85 {
86         if (m_fullName[0] == '\0')
87                 return (FALSE);
88         else {
89                 char *tmp = strrchr(fileName, '/');
90
91                 if (tmp == NULL)
92                         tmp = (char *) fileName;
93                 else
94                         tmp++;
95                 if (check_wildcard_match(tmp, m_fullName) == TRUE) {
96                         /* Stop searching if we find a match */
97                         memcpy(m_filename, fileName, strlen(fileName));
98                         return (FALSE);
99                 }
100         }
101         return (TRUE);
102 }
103
104
105 extern int insmod_main(int argc, char **argv)
106 {
107         int len;
108         char *tmp;
109         char m_name[BUFSIZ + 1] = "\0";
110         FILE *fp;
111
112         if (argc <= 1) {
113                 usage(insmod_usage);
114         }
115
116         /* Parse any options */
117         while (--argc > 0 && **(++argv) == '-') {
118                 while (*(++(*argv))) {
119                         switch (**argv) {
120                         case 'f':
121                                 break;
122                         case 'k':
123                                 break;
124                         default:
125                                 usage(insmod_usage);
126                         }
127                 }
128         }
129
130         if (argc <= 0)
131                 usage(insmod_usage);
132
133         /* Grab the module name */
134         if ((tmp = strrchr(*argv, '/')) != NULL)
135                 tmp++;
136         else
137                 tmp = *argv;
138         len = strlen(tmp);
139
140         if (len > 2 && tmp[len - 2] == '.' && tmp[len - 1] == 'o')
141                 len -= 2;
142         memcpy(m_name, tmp, len);
143         strcpy(m_fullName, m_name);
144         strcat(m_fullName, ".o");
145
146         /* Get a filedesc for the module */
147         if ((fp = fopen(*argv, "r")) == NULL) {
148                 /* Hmpf.  Could not open it. Search through _PATH_MODULES to find a module named m_name */
149                 if (recursiveAction(_PATH_MODULES, TRUE, FALSE, FALSE,
150                                                         findNamedModule, findNamedModule) == FALSE) {
151                         if (m_filename[0] == '\0'
152                                 || ((fp = fopen(m_filename, "r")) == NULL)) {
153                                 perror("No module by that name found in " _PATH_MODULES
154                                            "\n");
155                                 exit(FALSE);
156                         }
157                 }
158         } else
159                 memcpy(m_filename, *argv, strlen(*argv));
160
161
162         fprintf(stderr, "m_filename='%s'\n", m_filename);
163         fprintf(stderr, "m_name='%s'\n", m_name);
164
165
166         /* TODO: do something roughtly like this... */
167 #if 0
168
169         if ((f = obj_load(fp)) == NULL) {
170                 perror("Could not load the module\n");
171                 exit(FALSE);
172         }
173
174         /* Let the module know about the kernel symbols.  */
175         add_kernel_symbols(f);
176
177         if (!create_this_module(f, m_name)) {
178                 perror("Could not create the module\n");
179                 exit(FALSE);
180         }
181
182         if (!obj_check_undefineds(f, quiet)) {
183                 perror("Undefined symbols in the module\n");
184                 exit(FALSE);
185         }
186         obj_allocate_commons(f);
187
188         /* Perse the module's arguments */
189         while (argc-- > 0 && *(argv++) != '\0') {
190                 if (!process_module_arguments(f, argc - optind, argv + optind)) {
191                         perror("Undefined symbols in the module\n");
192                         exit(FALSE);
193                 }
194         }
195
196         /* Find current size of the module */
197         m_size = obj_load_size(f);
198
199
200         errno = 0;
201         m_addr = create_module(m_name, m_size);
202         switch (errno) {
203                 /* yada yada */
204         default:
205                 perror("create_module: %m");
206
207         }
208
209 #endif
210
211         fclose(fp);
212         exit(TRUE);
213 }