]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/debug-generator/debug-generator.c
Merge pull request #4548 from keszybz/seccomp-help
[thirdparty/systemd.git] / src / debug-generator / debug-generator.c
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
20 #include "alloc-util.h"
21 #include "mkdir.h"
22 #include "parse-util.h"
23 #include "proc-cmdline.h"
24 #include "special.h"
25 #include "string-util.h"
26 #include "strv.h"
27 #include "unit-name.h"
28 #include "util.h"
29
30 static char *arg_default_unit = NULL;
31 static const char *arg_dest = "/tmp";
32 static char **arg_mask = NULL;
33 static char **arg_wants = NULL;
34 static bool arg_debug_shell = false;
35
36 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
37 int r;
38
39 assert(key);
40
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
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");
51
52 r = strv_consume(&arg_mask, n);
53 if (r < 0)
54 return log_oom();
55 }
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
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");
67
68 r = strv_consume(&arg_wants, n);
69 if (r < 0)
70 return log_oom();
71 }
72
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;
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 }
101 }
102
103 return 0;
104 }
105
106 static 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) {
114 _cleanup_free_ char *p = NULL;
115
116 p = strjoin(arg_dest, "/", *u);
117 if (!p)
118 return log_oom();
119
120 if (symlink("/dev/null", p) < 0)
121 r = log_error_errno(errno,
122 "Failed to create mask symlink %s: %m",
123 p);
124 }
125
126 return r;
127 }
128
129 static int generate_wants_symlinks(void) {
130 char **u;
131 int r = 0;
132
133 if (strv_isempty(arg_wants))
134 return 0;
135
136 STRV_FOREACH(u, arg_wants) {
137 _cleanup_free_ char *p = NULL, *f = NULL;
138
139 p = strjoin(arg_dest, "/", arg_default_unit, ".wants/", *u);
140 if (!p)
141 return log_oom();
142
143 f = strappend(SYSTEM_DATA_UNIT_PATH "/", *u);
144 if (!f)
145 return log_oom();
146
147 mkdir_parents_label(p, 0755);
148
149 if (symlink(f, p) < 0)
150 r = log_error_errno(errno,
151 "Failed to create wants symlink %s: %m",
152 p);
153 }
154
155 return r;
156 }
157
158 int 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
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
181 r = parse_proc_cmdline(parse_proc_cmdline_item, NULL, false);
182 if (r < 0)
183 log_warning_errno(r, "Failed to parse kernel command line, ignoring: %m");
184
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
193 r = generate_mask_symlinks();
194
195 q = generate_wants_symlinks();
196 if (q < 0)
197 r = q;
198
199 finish:
200 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
201
202 }