]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/modules-load/modules-load.c
Unify parse_argv style
[thirdparty/systemd.git] / src / modules-load / modules-load.c
CommitLineData
b2423f1f
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
b2423f1f
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
b2423f1f 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
b2423f1f
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <unistd.h>
23#include <fcntl.h>
24#include <errno.h>
25#include <string.h>
26#include <sys/stat.h>
27#include <limits.h>
28#include <dirent.h>
fabe5c0e 29#include <getopt.h>
83684a35 30#include <libkmod.h>
b2423f1f
LP
31
32#include "log.h"
33#include "util.h"
34#include "strv.h"
2c21044f 35#include "conf-files.h"
a5c32cff 36#include "fileio.h"
eb9da376 37#include "build.h"
03658d4f
LP
38
39static char **arg_proc_cmdline_modules = NULL;
b2423f1f 40
fabe5c0e
LP
41static const char conf_file_dirs[] =
42 "/etc/modules-load.d\0"
43 "/run/modules-load.d\0"
44 "/usr/local/lib/modules-load.d\0"
45 "/usr/lib/modules-load.d\0"
46#ifdef HAVE_SPLIT_USR
47 "/lib/modules-load.d\0"
48#endif
49 ;
50
83684a35 51static void systemd_kmod_log(void *data, int priority, const char *file, int line,
f168c273 52 const char *fn, const char *format, va_list args) {
bcfce235
LP
53
54 DISABLE_WARNING_FORMAT_NONLITERAL;
e62abb62 55 log_metav(priority, file, line, fn, format, args);
bcfce235 56 REENABLE_WARNING;
83684a35
TG
57}
58
03658d4f 59static int add_modules(const char *p) {
fabe5c0e 60 _cleanup_strv_free_ char **k = NULL;
03658d4f
LP
61
62 k = strv_split(p, ",");
0d0f0c50
SL
63 if (!k)
64 return log_oom();
03658d4f 65
e3e45d4f 66 if (strv_extend_strv(&arg_proc_cmdline_modules, k) < 0)
0d0f0c50 67 return log_oom();
03658d4f 68
03658d4f
LP
69 return 0;
70}
71
059cb385 72static int parse_proc_cmdline_item(const char *key, const char *value) {
74df0fca 73 int r;
03658d4f 74
059cb385
LP
75 if (STR_IN_SET(key, "modules-load", "rd.modules-load") && value) {
76 r = add_modules(value);
141a79f4
ZJS
77 if (r < 0)
78 return r;
03658d4f
LP
79 }
80
c007bb1b 81 return 0;
03658d4f
LP
82}
83
84static int load_module(struct kmod_ctx *ctx, const char *m) {
27fda47f 85 const int probe_flags = KMOD_PROBE_APPLY_BLACKLIST;
03658d4f
LP
86 struct kmod_list *itr, *modlist = NULL;
87 int r = 0;
88
9f6445e3 89 log_debug("load: %s", m);
03658d4f
LP
90
91 r = kmod_module_new_from_lookup(ctx, m, &modlist);
92 if (r < 0) {
93 log_error("Failed to lookup alias '%s': %s", m, strerror(-r));
94 return r;
95 }
96
27fda47f
MS
97 if (!modlist) {
98 log_error("Failed to find module '%s'", m);
8f9c0b4c 99 return -ENOENT;
27fda47f
MS
100 }
101
03658d4f
LP
102 kmod_list_foreach(itr, modlist) {
103 struct kmod_module *mod;
27fda47f 104 int state, err;
03658d4f
LP
105
106 mod = kmod_module_get_module(itr);
27fda47f
MS
107 state = kmod_module_get_initstate(mod);
108
109 switch (state) {
110 case KMOD_MODULE_BUILTIN:
111 log_info("Module '%s' is builtin", kmod_module_get_name(mod));
112 break;
113
114 case KMOD_MODULE_LIVE:
b56c267f 115 log_debug("Module '%s' is already loaded", kmod_module_get_name(mod));
27fda47f
MS
116 break;
117
118 default:
119 err = kmod_module_probe_insert_module(mod, probe_flags,
120 NULL, NULL, NULL, NULL);
121
122 if (err == 0)
123 log_info("Inserted module '%s'", kmod_module_get_name(mod));
124 else if (err == KMOD_PROBE_APPLY_BLACKLIST)
125 log_info("Module '%s' is blacklisted", kmod_module_get_name(mod));
126 else {
127 log_error("Failed to insert '%s': %s", kmod_module_get_name(mod),
128 strerror(-err));
129 r = err;
130 }
03658d4f
LP
131 }
132
133 kmod_module_unref(mod);
134 }
135
136 kmod_module_unref_list(modlist);
137
138 return r;
139}
140
fabe5c0e
LP
141static int apply_file(struct kmod_ctx *ctx, const char *path, bool ignore_enoent) {
142 _cleanup_fclose_ FILE *f = NULL;
143 int r;
144
145 assert(ctx);
146 assert(path);
147
4cf7ea55 148 r = search_and_fopen_nulstr(path, "re", NULL, conf_file_dirs, &f);
fabe5c0e
LP
149 if (r < 0) {
150 if (ignore_enoent && r == -ENOENT)
151 return 0;
152
153 log_error("Failed to open %s, ignoring: %s", path, strerror(-r));
154 return r;
155 }
156
9f6445e3 157 log_debug("apply: %s", path);
fabe5c0e
LP
158 for (;;) {
159 char line[LINE_MAX], *l;
160 int k;
161
162 if (!fgets(line, sizeof(line), f)) {
163 if (feof(f))
164 break;
165
166 log_error("Failed to read file '%s', ignoring: %m", path);
167 return -errno;
168 }
169
170 l = strstrip(line);
171 if (!*l)
172 continue;
d3b6d0c2 173 if (strchr(COMMENTS "\n", *l))
fabe5c0e
LP
174 continue;
175
176 k = load_module(ctx, l);
177 if (k < 0 && r == 0)
178 r = k;
179 }
180
181 return r;
182}
183
601185b4 184static void help(void) {
fabe5c0e
LP
185 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
186 "Loads statically configured kernel modules.\n\n"
eb9da376
LP
187 " -h --help Show this help\n"
188 " --version Show package version\n",
fabe5c0e 189 program_invocation_short_name);
fabe5c0e
LP
190}
191
192static int parse_argv(int argc, char *argv[]) {
193
eb9da376
LP
194 enum {
195 ARG_VERSION = 0x100,
196 };
197
fabe5c0e
LP
198 static const struct option options[] = {
199 { "help", no_argument, NULL, 'h' },
eb9da376
LP
200 { "version", no_argument, NULL, ARG_VERSION },
201 {}
fabe5c0e
LP
202 };
203
204 int c;
205
206 assert(argc >= 0);
207 assert(argv);
208
601185b4 209 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
fabe5c0e
LP
210
211 switch (c) {
212
213 case 'h':
601185b4
ZJS
214 help();
215 return 0;
eb9da376
LP
216
217 case ARG_VERSION:
218 puts(PACKAGE_STRING);
219 puts(SYSTEMD_FEATURES);
fabe5c0e
LP
220 return 0;
221
222 case '?':
223 return -EINVAL;
224
225 default:
eb9da376 226 assert_not_reached("Unhandled option");
fabe5c0e 227 }
fabe5c0e
LP
228
229 return 1;
230}
231
b2423f1f 232int main(int argc, char *argv[]) {
fabe5c0e 233 int r, k;
83684a35 234 struct kmod_ctx *ctx;
b2423f1f 235
fabe5c0e
LP
236 r = parse_argv(argc, argv);
237 if (r <= 0)
238 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b2423f1f 239
4cfa2c99 240 log_set_target(LOG_TARGET_AUTO);
b2423f1f
LP
241 log_parse_environment();
242 log_open();
243
4c12626c
LP
244 umask(0022);
245
059cb385 246 if (parse_proc_cmdline(parse_proc_cmdline_item) < 0)
03658d4f
LP
247 return EXIT_FAILURE;
248
4e2075ce
LP
249 ctx = kmod_new(NULL, NULL);
250 if (!ctx) {
83684a35 251 log_error("Failed to allocate memory for kmod.");
b2423f1f
LP
252 goto finish;
253 }
254
83684a35 255 kmod_load_resources(ctx);
83684a35 256 kmod_set_log_fn(ctx, systemd_kmod_log, NULL);
b2423f1f 257
fabe5c0e 258 r = 0;
03658d4f 259
fabe5c0e
LP
260 if (argc > optind) {
261 int i;
b2423f1f 262
fabe5c0e
LP
263 for (i = optind; i < argc; i++) {
264 k = apply_file(ctx, argv[i], false);
265 if (k < 0 && r == 0)
266 r = k;
b2423f1f
LP
267 }
268
fabe5c0e
LP
269 } else {
270 _cleanup_free_ char **files = NULL;
271 char **fn, **i;
b2423f1f 272
fabe5c0e
LP
273 STRV_FOREACH(i, arg_proc_cmdline_modules) {
274 k = load_module(ctx, *i);
b857193b
LP
275 if (k < 0 && r == 0)
276 r = k;
b2423f1f
LP
277 }
278
4b462d1a
LP
279 k = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
280 if (k < 0) {
281 log_error("Failed to enumerate modules-load.d files: %s", strerror(-k));
282 if (r == 0)
283 r = k;
fabe5c0e 284 goto finish;
b2423f1f
LP
285 }
286
fabe5c0e
LP
287 STRV_FOREACH(fn, files) {
288 k = apply_file(ctx, *fn, true);
289 if (k < 0 && r == 0)
290 r = k;
291 }
b2423f1f
LP
292 }
293
b2423f1f 294finish:
83684a35 295 kmod_unref(ctx);
03658d4f 296 strv_free(arg_proc_cmdline_modules);
b2423f1f 297
fabe5c0e 298 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
b2423f1f 299}