]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/debug-generator/debug-generator.c
tree-wide: make parse_proc_cmdline() strip "rd." prefix automatically
[thirdparty/systemd.git] / src / debug-generator / debug-generator.c
CommitLineData
326bb68c
LP
1/***
2 This file is part of systemd.
3
4 Copyright 2014 Lennart Poettering
5
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
10
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
15
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
18***/
19
b5efdb8a 20#include "alloc-util.h"
326bb68c 21#include "mkdir.h"
6bedfcbb 22#include "parse-util.h"
4e731273 23#include "proc-cmdline.h"
7dcc5671 24#include "special.h"
4e731273
LP
25#include "string-util.h"
26#include "strv.h"
27#include "unit-name.h"
28#include "util.h"
326bb68c 29
7dcc5671 30static char *arg_default_unit = NULL;
326bb68c
LP
31static const char *arg_dest = "/tmp";
32static char **arg_mask = NULL;
3c5a87a8 33static char **arg_wants = NULL;
326bb68c
LP
34static bool arg_debug_shell = false;
35
96287a49 36static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
326bb68c
LP
37 int r;
38
3c5a87a8
LP
39 assert(key);
40
326bb68c
LP
41 if (streq(key, "systemd.mask")) {
42
43 if (!value)
44 log_error("Missing argument for systemd.mask= kernel command line parameter.");
45 else {
46 char *n;
47
7410616c
LP
48 r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n);
49 if (r < 0)
50 return log_error_errno(r, "Failed to glob unit name: %m");
326bb68c
LP
51
52 r = strv_consume(&arg_mask, n);
53 if (r < 0)
54 return log_oom();
55 }
3c5a87a8
LP
56
57 } else if (streq(key, "systemd.wants")) {
58
59 if (!value)
60 log_error("Missing argument for systemd.want= kernel command line parameter.");
61 else {
62 char *n;
63
7410616c
LP
64 r = unit_name_mangle(value, UNIT_NAME_NOGLOB, &n);
65 if (r < 0)
66 return log_error_errno(r, "Failed to glob unit name: %m");
3c5a87a8
LP
67
68 r = strv_consume(&arg_wants, n);
69 if (r < 0)
70 return log_oom();
71 }
72
326bb68c
LP
73 } else if (streq(key, "systemd.debug-shell")) {
74
75 if (value) {
76 r = parse_boolean(value);
77 if (r < 0)
78 log_error("Failed to parse systemd.debug-shell= argument '%s', ignoring.", value);
79 else
80 arg_debug_shell = r;
81 } else
82 arg_debug_shell = true;
7dcc5671
EV
83 } else if (streq(key, "systemd.unit")) {
84
85 if (!value)
86 log_error("Missing argument for systemd.unit= kernel command line parameter.");
87 else {
88 r = free_and_strdup(&arg_default_unit, value);
89 if (r < 0)
90 return log_error_errno(r, "Failed to set default unit %s: %m", value);
91 }
92 } else if (!value) {
93 const char *target;
94
95 target = runlevel_to_target(key);
96 if (target) {
97 r = free_and_strdup(&arg_default_unit, target);
98 if (r < 0)
99 return log_error_errno(r, "Failed to set default unit %s: %m", target);
100 }
326bb68c
LP
101 }
102
103 return 0;
104}
105
106static int generate_mask_symlinks(void) {
107 char **u;
108 int r = 0;
109
110 if (strv_isempty(arg_mask))
111 return 0;
112
113 STRV_FOREACH(u, arg_mask) {
3c5a87a8 114 _cleanup_free_ char *p = NULL;
326bb68c 115
3c5a87a8 116 p = strjoin(arg_dest, "/", *u, NULL);
326bb68c
LP
117 if (!p)
118 return log_oom();
119
1f6b4113 120 if (symlink("/dev/null", p) < 0)
94c156cd
LP
121 r = log_error_errno(errno,
122 "Failed to create mask symlink %s: %m",
123 p);
326bb68c
LP
124 }
125
126 return r;
127}
128
3c5a87a8
LP
129static int generate_wants_symlinks(void) {
130 char **u;
131 int r = 0;
326bb68c 132
3c5a87a8 133 if (strv_isempty(arg_wants))
326bb68c
LP
134 return 0;
135
3c5a87a8
LP
136 STRV_FOREACH(u, arg_wants) {
137 _cleanup_free_ char *p = NULL, *f = NULL;
138
7dcc5671 139 p = strjoin(arg_dest, "/", arg_default_unit, ".wants/", *u, NULL);
3c5a87a8
LP
140 if (!p)
141 return log_oom();
142
143 f = strappend(SYSTEM_DATA_UNIT_PATH "/", *u);
144 if (!f)
145 return log_oom();
326bb68c 146
3c5a87a8 147 mkdir_parents_label(p, 0755);
326bb68c 148
1f6b4113 149 if (symlink(f, p) < 0)
94c156cd
LP
150 r = log_error_errno(errno,
151 "Failed to create wants symlink %s: %m",
152 p);
326bb68c
LP
153 }
154
3c5a87a8 155 return r;
326bb68c
LP
156}
157
158int main(int argc, char *argv[]) {
159 int r, q;
160
161 if (argc > 1 && argc != 4) {
162 log_error("This program takes three or no arguments.");
163 return EXIT_FAILURE;
164 }
165
166 if (argc > 1)
167 arg_dest = argv[2];
168
169 log_set_target(LOG_TARGET_SAFE);
170 log_parse_environment();
171 log_open();
172
173 umask(0022);
174
7dcc5671
EV
175 r = free_and_strdup(&arg_default_unit, SPECIAL_DEFAULT_TARGET);
176 if (r < 0) {
177 log_error_errno(r, "Failed to set default unit %s: %m", SPECIAL_DEFAULT_TARGET);
178 goto finish;
179 }
180
d7f69e16 181 r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
b5884878 182 if (r < 0)
da927ba9 183 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
326bb68c 184
3c5a87a8
LP
185 if (arg_debug_shell) {
186 r = strv_extend(&arg_wants, "debug-shell.service");
187 if (r < 0) {
188 r = log_oom();
189 goto finish;
190 }
191 }
192
326bb68c
LP
193 r = generate_mask_symlinks();
194
3c5a87a8 195 q = generate_wants_symlinks();
326bb68c
LP
196 if (q < 0)
197 r = q;
198
3c5a87a8 199finish:
326bb68c
LP
200 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
201
202}