1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 #include "alloc-util.h"
5 #include "parse-util.h"
6 #include "proc-cmdline.h"
8 #include "string-util.h"
10 #include "unit-name.h"
13 static char *arg_default_unit
= NULL
;
14 static const char *arg_dest
= "/tmp";
15 static char **arg_mask
= NULL
;
16 static char **arg_wants
= NULL
;
17 static bool arg_debug_shell
= false;
19 static int parse_proc_cmdline_item(const char *key
, const char *value
, void *data
) {
24 if (streq(key
, "systemd.mask")) {
27 if (proc_cmdline_value_missing(key
, value
))
30 r
= unit_name_mangle(value
, UNIT_NAME_MANGLE_WARN
, &n
);
32 return log_error_errno(r
, "Failed to glob unit name: %m");
34 r
= strv_consume(&arg_mask
, n
);
38 } else if (streq(key
, "systemd.wants")) {
41 if (proc_cmdline_value_missing(key
, value
))
44 r
= unit_name_mangle(value
, UNIT_NAME_MANGLE_WARN
, &n
);
46 return log_error_errno(r
, "Failed to glob unit name: %m");
48 r
= strv_consume(&arg_wants
, n
);
52 } else if (proc_cmdline_key_streq(key
, "systemd.debug_shell")) {
55 r
= parse_boolean(value
);
57 log_error("Failed to parse systemd.debug_shell= argument '%s', ignoring.", value
);
61 arg_debug_shell
= true;
63 } else if (streq(key
, "systemd.unit")) {
65 if (proc_cmdline_value_missing(key
, value
))
68 r
= free_and_strdup(&arg_default_unit
, value
);
70 return log_error_errno(r
, "Failed to set default unit %s: %m", value
);
75 target
= runlevel_to_target(key
);
77 r
= free_and_strdup(&arg_default_unit
, target
);
79 return log_error_errno(r
, "Failed to set default unit %s: %m", target
);
86 static int generate_mask_symlinks(void) {
90 if (strv_isempty(arg_mask
))
93 STRV_FOREACH(u
, arg_mask
) {
94 _cleanup_free_
char *p
= NULL
;
96 p
= strjoin(arg_dest
, "/", *u
);
100 if (symlink("/dev/null", p
) < 0)
101 r
= log_error_errno(errno
,
102 "Failed to create mask symlink %s: %m",
109 static int generate_wants_symlinks(void) {
113 if (strv_isempty(arg_wants
))
116 STRV_FOREACH(u
, arg_wants
) {
117 _cleanup_free_
char *p
= NULL
, *f
= NULL
;
118 const char *target
= arg_default_unit
?: SPECIAL_DEFAULT_TARGET
;
120 p
= strjoin(arg_dest
, "/", target
, ".wants/", *u
);
124 f
= strappend(SYSTEM_DATA_UNIT_PATH
"/", *u
);
128 mkdir_parents_label(p
, 0755);
130 if (symlink(f
, p
) < 0)
131 r
= log_error_errno(errno
,
132 "Failed to create wants symlink %s: %m",
139 int main(int argc
, char *argv
[]) {
142 if (argc
> 1 && argc
!= 4) {
143 log_error("This program takes three or no arguments.");
150 log_set_prohibit_ipc(true);
151 log_set_target(LOG_TARGET_AUTO
);
152 log_parse_environment();
157 r
= proc_cmdline_parse(parse_proc_cmdline_item
, NULL
, PROC_CMDLINE_RD_STRICT
| PROC_CMDLINE_STRIP_RD_PREFIX
);
159 log_warning_errno(r
, "Failed to parse kernel command line, ignoring: %m");
161 if (arg_debug_shell
) {
162 r
= strv_extend(&arg_wants
, "debug-shell.service");
169 r
= generate_mask_symlinks();
171 q
= generate_wants_symlinks();
176 arg_default_unit
= mfree(arg_default_unit
);
177 strv_free(arg_wants
);
180 return r
< 0 ? EXIT_FAILURE
: EXIT_SUCCESS
;