blob: 0b81142d56581f6ccbcdb9d51b8a1e5abe0a6a5a [file] [log] [blame]
Eric Andersen0139ca92001-07-22 23:01:03 +00001/* vi: set sw=4 ts=4: */
2/*
3 * really dumb modprobe implementation for busybox
4 * Copyright (C) 2001 Lineo, davidm@lineo.com
Eric Andersen60e56f52002-04-26 06:04:01 +00005 *
6 * CONFIG_MODPROBE_DEPEND stuff was added and is
7 * Copyright (C) 2002 Robert Griebl, griebl@gmx.de
8 *
Eric Andersen0139ca92001-07-22 23:01:03 +00009 */
10
11#include <stdio.h>
12#include <getopt.h>
13#include <stdlib.h>
14#include <unistd.h>
15#include <syslog.h>
16#include <string.h>
Eric Andersen60e56f52002-04-26 06:04:01 +000017#include <ctype.h>
Eric Andersen0139ca92001-07-22 23:01:03 +000018#include "busybox.h"
19
20static char cmd[128];
21
Eric Andersen60e56f52002-04-26 06:04:01 +000022#define CONFIG_MODPROBE_DEPEND
23
24#ifdef CONFIG_MODPROBE_DEPEND
25
26#include <sys/utsname.h>
27
28struct dep_t {
29 char * m_module;
30 int m_depcnt;
31 char ** m_deparr;
32
33 struct dep_t * m_next;
34};
35
36
37static struct dep_t *build_dep ( )
38{
39 struct utsname un;
40 FILE *f;
41 struct dep_t *first = 0;
42 struct dep_t *current = 0;
43 char buffer [4096];
44 char *filename = buffer;
45 int continuation_line = 0;
46
47 if ( uname ( &un ))
48 return 0;
49 strcpy ( filename, "/lib/modules/" );
50 strcat ( filename, un. release );
51 strcat ( filename, "/modules.dep" );
52
53 f = fopen ( filename, "r" );
54 if ( !f )
55 return 0;
56
57 while ( fgets ( buffer, sizeof( buffer), f )) {
58 int l = strlen ( buffer );
59 char *p = 0;
60
61 if ( buffer [l-1] == '\n' ) {
62 buffer [l-1] = 0;
63 l--;
64 }
65
66 if ( l == 0 ) {
67 continuation_line = 0;
68 continue;
69 }
70
71 if ( !continuation_line ) {
72 char *col = strchr ( buffer, ':' );
73
74 if ( col ) {
75 char *mods;
76 char *mod;
77
78 *col = 0;
79 mods = strrchr ( buffer, '/' );
80
81 if ( !mods )
82 mods = buffer;
83 else
84 mods++;
85
86 mod = (char *) malloc ( col - mods + 1 );
87 strncpy ( mod, mods, col - mods );
88 mod [col - mods] = 0;
89
90 if ( !current ) {
91 first = current = (struct dep_t *) malloc ( sizeof ( struct dep_t ));
92 }
93 else {
94 current-> m_next = (struct dep_t *) malloc ( sizeof ( struct dep_t ));
95 current = current-> m_next;
96 }
97 current-> m_module = mod;
98 current-> m_depcnt = 0;
99 current-> m_deparr = 0;
100 current-> m_next = 0;
101
102 /* printf ( "%s:\n", mod ); */
103
104 p = col + 1;
105 }
106 else
107 p = 0;
108 }
109 else
110 p = buffer;
111
112 if ( p && *p ) {
113 char *end = &buffer [l-1];
114 char *deps = strrchr ( end, '/' );
115 char *dep;
116
117 while ( isblank ( *end ) || ( *end == '\\' ))
118 end--;
119
120 deps = strrchr ( p, '/' );
121
122 if ( !deps || ( deps < p )) {
123 deps = p;
124
125 while ( isblank ( *deps ))
126 deps++;
127 }
128 else
129 deps++;
130
131 dep = (char *) malloc ( end - deps + 2 );
132 strncpy ( dep, deps, end - deps + 1 );
133 dep [end - deps + 1] = 0;
134
135 current-> m_depcnt++;
136 current-> m_deparr = (char **) realloc ( current-> m_deparr, sizeof ( char *) * current-> m_depcnt );
137 current-> m_deparr [current-> m_depcnt - 1] = dep;
138
139 /* printf ( " %d) %s\n", current-> m_depcnt, current-> m_deparr [current-> m_depcnt -1] ); */
140 }
141
142 if ( buffer [l-1] == '\\' )
143 continuation_line = 1;
144 else
145 continuation_line = 0;
146 }
147 fclose ( f );
148
149 return first;
150}
151
152
153static struct dep_t *find_dep ( struct dep_t *dt, char *mod )
154{
155 int lm = strlen ( mod );
156 int hasext = 0;
157
158 if (( mod [lm-2] == '.' ) && ( mod [lm-1] == 'o' ))
159 hasext = 1;
160
161 while ( dt ) {
162 if ( hasext && !strcmp ( dt-> m_module, mod ))
163 break;
164 else if ( !hasext && !strncmp ( dt-> m_module, mod, strlen ( dt-> m_module ) - 2 ))
165 break;
166
167 dt = dt-> m_next;
168 }
169 return dt;
170}
171
172
173static void check_dep ( char *mod, int loadit )
174{
175 static struct dep_t *depend = (struct dep_t *) -1;
176 struct dep_t *dt;
177
178 if ( depend == (struct dep_t *) -1 )
179 depend = build_dep ( );
180
181 /* printf ( "CHECK: %s (%p)\n", mod, depend ); */
182
183 if (( dt = find_dep ( depend, mod ))) {
184 int i;
185
186 for ( i = 0; i < dt-> m_depcnt; i++ )
187 check_dep ( dt-> m_deparr [i], 1 );
188 }
189 if ( loadit ) {
190 char lcmd [128];
191
192 sprintf ( lcmd, "insmod -k %s 2>/dev/null", mod );
193 system ( lcmd );
194 }
195}
196
197#endif
198
199
Eric Andersen0139ca92001-07-22 23:01:03 +0000200extern int modprobe_main(int argc, char** argv)
201{
202 int ch, rc = 0;
203 int loadall = 0, showconfig = 0, debug = 0, autoclean = 0, list = 0;
Eric Andersen1b064192001-07-25 07:23:38 +0000204 int show_only = 0, quiet = 0, remove_opt = 0, do_syslog = 0, verbose = 0;
205 char *load_type = NULL, *config = NULL;
Eric Andersen0139ca92001-07-22 23:01:03 +0000206
207 while ((ch = getopt(argc, argv, "acdklnqrst:vVC:")) != -1)
208 switch(ch) {
209 case 'a':
210 loadall++;
211 break;
212 case 'c':
213 showconfig++;
214 break;
215 case 'd':
216 debug++;
217 break;
218 case 'k':
219 autoclean++;
220 break;
221 case 'l':
222 list++;
223 break;
224 case 'n':
225 show_only++;
226 break;
227 case 'q':
228 quiet++;
229 break;
230 case 'r':
Eric Andersen1b064192001-07-25 07:23:38 +0000231 remove_opt++;
Eric Andersen0139ca92001-07-22 23:01:03 +0000232 break;
233 case 's':
234 do_syslog++;
235 break;
236 case 't':
237 load_type = optarg;
238 break;
239 case 'v':
240 verbose++;
241 break;
242 case 'C':
243 config = optarg;
244 break;
245 case 'V':
246 default:
247 show_usage();
248 break;
249 }
250
251 if (load_type || config) {
252 fprintf(stderr, "-t and -C not supported\n");
253 exit(EXIT_FAILURE);
254 }
255
256 if (showconfig)
257 exit(EXIT_SUCCESS);
258
259 if (list)
260 exit(EXIT_SUCCESS);
261
Eric Andersen1b064192001-07-25 07:23:38 +0000262 if (remove_opt) {
Eric Andersen0139ca92001-07-22 23:01:03 +0000263 do {
264 sprintf(cmd, "rmmod %s %s %s",
265 optind >= argc ? "-a" : "",
266 do_syslog ? "-s" : "",
267 optind < argc ? argv[optind] : "");
268 if (do_syslog)
269 syslog(LOG_INFO, "%s", cmd);
270 if (show_only || verbose)
271 printf("%s\n", cmd);
272 if (!show_only)
273 rc = system(cmd);
274 } while (++optind < argc);
275 exit(EXIT_SUCCESS);
276 }
277
278 if (optind >= argc) {
279 fprintf(stderr, "No module or pattern provided\n");
280 exit(EXIT_FAILURE);
281 }
282
283 sprintf(cmd, "insmod %s %s %s",
284 do_syslog ? "-s" : "",
285 quiet ? "-q" : "",
286 autoclean ? "-k" : "");
Eric Andersen60e56f52002-04-26 06:04:01 +0000287
288#ifdef CONFIG_MODPROBE_DEPEND
289 check_dep ( argv [optind], 0 );
290#endif
291
Eric Andersen0139ca92001-07-22 23:01:03 +0000292 while (optind < argc) {
Eric Andersen0139ca92001-07-22 23:01:03 +0000293 strcat(cmd, " ");
Matt Kraai8a35c9a2001-11-27 17:28:01 +0000294 strcat(cmd, argv[optind]);
Eric Andersen0139ca92001-07-22 23:01:03 +0000295 optind++;
296 }
297 if (do_syslog)
298 syslog(LOG_INFO, "%s", cmd);
299 if (show_only || verbose)
300 printf("%s\n", cmd);
301 if (!show_only)
302 rc = system(cmd);
303 else
304 rc = 0;
305
306 exit(rc ? EXIT_FAILURE : EXIT_SUCCESS);
307}
308
309