1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "alloc-util.h"
6 #include "parse-util.h"
7 #include "proc-cmdline.h"
9 #include "string-util.h"
11 #include "unit-name.h"
14 static const char *arg_dest
= NULL
;
15 static char *arg_default_unit
= NULL
;
16 static char **arg_mask
= NULL
;
17 static char **arg_wants
= NULL
;
18 static bool arg_debug_shell
= false;
20 STATIC_DESTRUCTOR_REGISTER(arg_default_unit
, freep
);
21 STATIC_DESTRUCTOR_REGISTER(arg_mask
, strv_freep
);
22 STATIC_DESTRUCTOR_REGISTER(arg_wants
, strv_freep
);
24 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
29 if (streq(key
, "systemd.mask")) {
32 if (proc_cmdline_value_missing(key
, value
))
35 r
= unit_name_mangle(value
, UNIT_NAME_MANGLE_WARN
, &n
);
37 return log_error_errno(r
, "Failed to glob unit name: %m");
39 r
= strv_consume(&arg_mask
, n
);
43 } else if (streq(key
, "systemd.wants")) {
46 if (proc_cmdline_value_missing(key
, value
))
49 r
= unit_name_mangle(value
, UNIT_NAME_MANGLE_WARN
, &n
);
51 return log_error_errno(r
, "Failed to glob unit name: %m");
53 r
= strv_consume(&arg_wants
, n
);
57 } else if (proc_cmdline_key_streq(key
, "systemd.debug_shell")) {
60 r
= parse_boolean(value
);
62 log_error("Failed to parse systemd.debug_shell= argument '%s', ignoring.", value
);
66 arg_debug_shell
= true;
68 } else if (streq(key
, "systemd.unit")) {
70 if (proc_cmdline_value_missing(key
, value
))
73 r
= free_and_strdup(&arg_default_unit
, value
);
75 return log_error_errno(r
, "Failed to set default unit %s: %m", value
);
80 target
= runlevel_to_target(key
);
82 r
= free_and_strdup(&arg_default_unit
, target
);
84 return log_error_errno(r
, "Failed to set default unit %s: %m", target
);
91 static int generate_mask_symlinks(void) {
95 if (strv_isempty(arg_mask
))
98 STRV_FOREACH(u
, arg_mask
) {
99 _cleanup_free_
char *p
= NULL
;
101 p
= strjoin(arg_dest
, "/", *u
);
105 if (symlink("/dev/null", p
) < 0)
106 r
= log_error_errno(errno
,
107 "Failed to create mask symlink %s: %m",
114 static int generate_wants_symlinks(void) {
118 if (strv_isempty(arg_wants
))
121 STRV_FOREACH(u
, arg_wants
) {
122 _cleanup_free_
char *p
= NULL
, *f
= NULL
;
123 const char *target
= arg_default_unit
?: SPECIAL_DEFAULT_TARGET
;
125 p
= strjoin(arg_dest
, "/", target
, ".wants/", *u
);
129 f
= strappend(SYSTEM_DATA_UNIT_PATH
"/", *u
);
133 mkdir_parents_label(p
, 0755);
135 if (symlink(f
, p
) < 0)
136 r
= log_error_errno(errno
,
137 "Failed to create wants symlink %s: %m",
144 static int run(const char *dest
, const char *dest_early
, const char *dest_late
) {
147 assert_se(arg_dest
= dest_early
);
149 r
= proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_RD_STRICT
| PROC_CMDLINE_STRIP_RD_PREFIX
);
151 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
153 if (arg_debug_shell
) {
154 r
= strv_extend(&arg_wants
, "debug-shell.service");
159 r
= generate_mask_symlinks();
160 q
= generate_wants_symlinks();
162 return r
< 0 ? r
: q
;
165 DEFINE_MAIN_GENERATOR_FUNCTION(run
);