1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
6 #include "alloc-util.h"
8 #include "conf-files.h"
10 #include "errno-util.h"
14 #include "main-func.h"
15 #include "module-util.h"
16 #include "pretty-print.h"
17 #include "proc-cmdline.h"
18 #include "string-util.h"
21 static char **arg_proc_cmdline_modules
= NULL
;
22 static const char conf_file_dirs
[] = CONF_PATHS_NULSTR("modules-load.d");
24 STATIC_DESTRUCTOR_REGISTER(arg_proc_cmdline_modules
, strv_freep
);
26 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
29 if (proc_cmdline_key_streq(key
, "modules_load")) {
31 if (proc_cmdline_value_missing(key
, value
))
34 r
= strv_split_and_extend(&arg_proc_cmdline_modules
, value
, ",", /* filter_duplicates = */ true);
36 return log_error_errno(r
, "Failed to parse modules_load= kernel command line option: %m");
42 static int apply_file(struct kmod_ctx
*ctx
, const char *path
, bool ignore_enoent
) {
43 _cleanup_fclose_
FILE *f
= NULL
;
44 _cleanup_free_
char *pp
= NULL
;
50 r
= search_and_fopen_nulstr(path
, "re", NULL
, conf_file_dirs
, &f
, &pp
);
52 if (ignore_enoent
&& r
== -ENOENT
)
55 return log_error_errno(r
, "Failed to open %s: %m", path
);
58 log_debug("apply: %s", pp
);
60 _cleanup_free_
char *line
= NULL
;
63 k
= read_stripped_line(f
, LONG_LINE_MAX
, &line
);
65 return log_error_errno(k
, "Failed to read file '%s': %m", pp
);
71 if (strchr(COMMENTS
, *line
))
74 k
= module_load_and_warn(ctx
, line
, true);
83 static int help(void) {
84 _cleanup_free_
char *link
= NULL
;
87 r
= terminal_urlify_man("systemd-modules-load.service", "8", &link
);
91 printf("%s [OPTIONS...] [CONFIGURATION FILE...]\n\n"
92 "Loads statically configured kernel modules.\n\n"
93 " -h --help Show this help\n"
94 " --version Show package version\n"
95 "\nSee the %s for details.\n",
96 program_invocation_short_name
,
102 static int parse_argv(int argc
, char *argv
[]) {
107 static const struct option options
[] = {
108 { "help", no_argument
, NULL
, 'h' },
109 { "version", no_argument
, NULL
, ARG_VERSION
},
118 while ((c
= getopt_long(argc
, argv
, "h", options
, NULL
)) >= 0)
131 assert_not_reached();
137 static int run(int argc
, char *argv
[]) {
138 _cleanup_(sym_kmod_unrefp
) struct kmod_ctx
*ctx
= NULL
;
141 r
= parse_argv(argc
, argv
);
149 r
= proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_STRIP_RD_PREFIX
);
151 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
153 r
= module_setup_context(&ctx
);
155 return log_error_errno(r
, "Failed to initialize libkmod context: %m");
160 for (int i
= optind
; i
< argc
; i
++)
161 RET_GATHER(r
, apply_file(ctx
, argv
[i
], false));
164 _cleanup_strv_free_
char **files
= NULL
;
166 STRV_FOREACH(i
, arg_proc_cmdline_modules
) {
167 k
= module_load_and_warn(ctx
, *i
, true);
173 k
= conf_files_list_nulstr(&files
, ".conf", NULL
, 0, conf_file_dirs
);
175 return log_error_errno(k
, "Failed to enumerate modules-load.d files: %m");
177 STRV_FOREACH(fn
, files
)
178 RET_GATHER(r
, apply_file(ctx
, *fn
, true));
184 DEFINE_MAIN_FUNCTION(run
);