]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/debug-generator/debug-generator.c
pkgconfig: define variables relative to ${prefix}/${rootprefix}/${sysconfdir}
[thirdparty/systemd.git] / src / debug-generator / debug-generator.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #include "alloc-util.h"
4 #include "mkdir.h"
5 #include "parse-util.h"
6 #include "proc-cmdline.h"
7 #include "special.h"
8 #include "string-util.h"
9 #include "strv.h"
10 #include "unit-name.h"
11 #include "util.h"
12
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;
18
19 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
20 int r;
21
22 assert(key);
23
24 if (streq(key, "systemd.mask")) {
25 char *n;
26
27 if (proc_cmdline_value_missing(key, value))
28 return 0;
29
30 r = unit_name_mangle(value, UNIT_NAME_MANGLE_WARN, &n);
31 if (r < 0)
32 return log_error_errno(r, "Failed to glob unit name: %m");
33
34 r = strv_consume(&arg_mask, n);
35 if (r < 0)
36 return log_oom();
37
38 } else if (streq(key, "systemd.wants")) {
39 char *n;
40
41 if (proc_cmdline_value_missing(key, value))
42 return 0;
43
44 r = unit_name_mangle(value, UNIT_NAME_MANGLE_WARN, &n);
45 if (r < 0)
46 return log_error_errno(r, "Failed to glob unit name: %m");
47
48 r = strv_consume(&arg_wants, n);
49 if (r < 0)
50 return log_oom();
51
52 } else if (proc_cmdline_key_streq(key, "systemd.debug_shell")) {
53
54 if (value) {
55 r = parse_boolean(value);
56 if (r < 0)
57 log_error("Failed to parse systemd.debug_shell= argument '%s', ignoring.", value);
58 else
59 arg_debug_shell = r;
60 } else
61 arg_debug_shell = true;
62
63 } else if (streq(key, "systemd.unit")) {
64
65 if (proc_cmdline_value_missing(key, value))
66 return 0;
67
68 r = free_and_strdup(&arg_default_unit, value);
69 if (r < 0)
70 return log_error_errno(r, "Failed to set default unit %s: %m", value);
71
72 } else if (!value) {
73 const char *target;
74
75 target = runlevel_to_target(key);
76 if (target) {
77 r = free_and_strdup(&arg_default_unit, target);
78 if (r < 0)
79 return log_error_errno(r, "Failed to set default unit %s: %m", target);
80 }
81 }
82
83 return 0;
84 }
85
86 static int generate_mask_symlinks(void) {
87 char **u;
88 int r = 0;
89
90 if (strv_isempty(arg_mask))
91 return 0;
92
93 STRV_FOREACH(u, arg_mask) {
94 _cleanup_free_ char *p = NULL;
95
96 p = strjoin(arg_dest, "/", *u);
97 if (!p)
98 return log_oom();
99
100 if (symlink("/dev/null", p) < 0)
101 r = log_error_errno(errno,
102 "Failed to create mask symlink %s: %m",
103 p);
104 }
105
106 return r;
107 }
108
109 static int generate_wants_symlinks(void) {
110 char **u;
111 int r = 0;
112
113 if (strv_isempty(arg_wants))
114 return 0;
115
116 STRV_FOREACH(u, arg_wants) {
117 _cleanup_free_ char *p = NULL, *f = NULL;
118 const char *target = arg_default_unit ?: SPECIAL_DEFAULT_TARGET;
119
120 p = strjoin(arg_dest, "/", target, ".wants/", *u);
121 if (!p)
122 return log_oom();
123
124 f = strappend(SYSTEM_DATA_UNIT_PATH "/", *u);
125 if (!f)
126 return log_oom();
127
128 mkdir_parents_label(p, 0755);
129
130 if (symlink(f, p) < 0)
131 r = log_error_errno(errno,
132 "Failed to create wants symlink %s: %m",
133 p);
134 }
135
136 return r;
137 }
138
139 int main(int argc, char *argv[]) {
140 int r, q;
141
142 if (argc > 1 && argc != 4) {
143 log_error("This program takes three or no arguments.");
144 return EXIT_FAILURE;
145 }
146
147 if (argc > 1)
148 arg_dest = argv[2];
149
150 log_set_prohibit_ipc(true);
151 log_set_target(LOG_TARGET_AUTO);
152 log_parse_environment();
153 log_open();
154
155 umask(0022);
156
157 r = proc_cmdline_parse(parse_proc_cmdline_item, NULL, PROC_CMDLINE_RD_STRICT | PROC_CMDLINE_STRIP_RD_PREFIX);
158 if (r < 0)
159 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
160
161 if (arg_debug_shell) {
162 r = strv_extend(&arg_wants, "debug-shell.service");
163 if (r < 0) {
164 r = log_oom();
165 goto finish;
166 }
167 }
168
169 r = generate_mask_symlinks();
170
171 q = generate_wants_symlinks();
172 if (q < 0)
173 r = q;
174
175 finish:
176 arg_default_unit = mfree(arg_default_unit);
177 strv_free(arg_wants);
178 strv_free(arg_mask);
179
180 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
181 }