1 /* SPDX-License-Identifier: LGPL-2.1+ */
10 #include "conf-files.h"
15 #include "module-util.h"
16 #include "proc-cmdline.h"
17 #include "string-util.h"
19 #include "terminal-util.h"
22 static char **arg_proc_cmdline_modules
= NULL
;
24 static const char conf_file_dirs
[] = CONF_PATHS_NULSTR("modules-load.d");
26 static void systemd_kmod_log(void *data
, int priority
, const char *file
, int line
,
27 const char *fn
, const char *format
, va_list args
) {
29 DISABLE_WARNING_FORMAT_NONLITERAL
;
30 log_internalv(priority
, 0, file
, line
, fn
, format
, args
);
34 static int add_modules(const char *p
) {
35 _cleanup_strv_free_
char **k
= NULL
;
37 k
= strv_split(p
, ",");
41 if (strv_extend_strv(&arg_proc_cmdline_modules
, k
, true) < 0)
47 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
50 if (proc_cmdline_key_streq(key
, "modules_load")) {
52 if (proc_cmdline_value_missing(key
, value
))
55 r
= add_modules(value
);
63 static int apply_file(struct kmod_ctx
*ctx
, const char *path
, bool ignore_enoent
) {
64 _cleanup_fclose_
FILE *f
= NULL
;
70 r
= search_and_fopen_nulstr(path
, "re", NULL
, conf_file_dirs
, &f
);
72 if (ignore_enoent
&& r
== -ENOENT
)
75 return log_error_errno(r
, "Failed to open %s: %m", path
);
78 log_debug("apply: %s", path
);
80 _cleanup_free_
char *line
= NULL
;
84 k
= read_line(f
, LONG_LINE_MAX
, &line
);
86 return log_error_errno(k
, "Failed to read file '%s': %m", path
);
93 if (strchr(COMMENTS
, *l
))
96 k
= module_load_and_warn(ctx
, l
, true);
104 static int help(void) {
105 _cleanup_free_
char *link
= NULL
;
108 r
= terminal_urlify_man("systemd-modules-load.service", "8", &link
);
112 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
113 "Loads statically configured kernel modules.\n\n"
114 " -h --help Show this help\n"
115 " --version Show package version\n"
116 "\nSee the %s for details.\n"
117 , program_invocation_short_name
124 static int parse_argv(int argc
, char *argv
[]) {
130 static const struct option options
[] = {
131 { "help", no_argument
, NULL
, 'h' },
132 { "version", no_argument
, NULL
, ARG_VERSION
},
141 while ((c
= getopt_long(argc
, argv
, "h", options
, NULL
)) >= 0)
155 assert_not_reached("Unhandled option");
161 int main(int argc
, char *argv
[]) {
163 _cleanup_(kmod_unrefp
) struct kmod_ctx
*ctx
= NULL
;
165 r
= parse_argv(argc
, argv
);
167 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;
173 r
= proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_STRIP_RD_PREFIX
);
175 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
177 ctx
= kmod_new(NULL
, NULL
);
179 log_error("Failed to allocate memory for kmod.");
183 kmod_load_resources(ctx
);
184 kmod_set_log_fn(ctx
, systemd_kmod_log
, NULL
);
191 for (i
= optind
; i
< argc
; i
++) {
192 k
= apply_file(ctx
, argv
[i
], false);
198 _cleanup_strv_free_
char **files
= NULL
;
201 STRV_FOREACH(i
, arg_proc_cmdline_modules
) {
202 k
= module_load_and_warn(ctx
, *i
, true);
207 k
= conf_files_list_nulstr(&files
, ".conf", NULL
, 0, conf_file_dirs
);
209 log_error_errno(k
, "Failed to enumerate modules-load.d files: %m");
215 STRV_FOREACH(fn
, files
) {
216 k
= apply_file(ctx
, *fn
, true);
223 strv_free(arg_proc_cmdline_modules
);
225 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;