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