]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/core/main.c
main: set PR_SET_CHILD_REAPER for MANAGER_USER
[thirdparty/systemd.git] / src / core / main.c
CommitLineData
d6c9574f 1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
60918275 2
a7334b09
LP
3/***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
5430f7f2
LP
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
a7334b09
LP
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
5430f7f2 16 Lesser General Public License for more details.
a7334b09 17
5430f7f2 18 You should have received a copy of the GNU Lesser General Public License
a7334b09
LP
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
ea430986
LP
22#include <dbus/dbus.h>
23
60918275
LP
24#include <stdio.h>
25#include <errno.h>
26#include <string.h>
16354eff 27#include <unistd.h>
4ade7963
LP
28#include <sys/types.h>
29#include <sys/stat.h>
f170852a 30#include <getopt.h>
97c4f35c 31#include <signal.h>
4fc935ca 32#include <sys/wait.h>
80876c20 33#include <fcntl.h>
f3b6a3ed 34#include <sys/prctl.h>
664f88a7 35#include <sys/mount.h>
60918275
LP
36
37#include "manager.h"
16354eff 38#include "log.h"
302e8c4c 39#include "load-fragment.h"
a16e1123 40#include "fdset.h"
514f4ef5 41#include "special.h"
487393e9 42#include "conf-parser.h"
398ef8ba 43#include "bus-errors.h"
ad780f19 44#include "missing.h"
e51bc1a2 45#include "label.h"
302e27c8 46#include "build.h"
06d4c99a 47#include "strv.h"
f6a6225e 48#include "def.h"
b52aae1d 49#include "virt.h"
e96d6be7 50#include "watchdog.h"
664f88a7 51#include "path-util.h"
41669317 52#include "switch-root.h"
ec8927ca 53#include "capability.h"
bd3fa1d2 54#include "killall.h"
60918275 55
b6e66135
LP
56#include "mount-setup.h"
57#include "loopback-setup.h"
58#include "kmod-setup.h"
59#include "hostname-setup.h"
60#include "machine-id-setup.h"
61#include "locale-setup.h"
bbc98d32 62#include "hwclock.h"
b6e66135
LP
63#include "selinux-setup.h"
64#include "ima-setup.h"
65
f170852a
LP
66static enum {
67 ACTION_RUN,
e965d56d 68 ACTION_HELP,
9ba0bc4e 69 ACTION_VERSION,
e537352b 70 ACTION_TEST,
4288f619
LP
71 ACTION_DUMP_CONFIGURATION_ITEMS,
72 ACTION_DONE
fa0f4d8a 73} arg_action = ACTION_RUN;
f170852a 74
fa0f4d8a
LP
75static char *arg_default_unit = NULL;
76static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
77
78static bool arg_dump_core = true;
79static bool arg_crash_shell = false;
80static int arg_crash_chvt = -1;
81static bool arg_confirm_spawn = false;
9e58ff9c 82static bool arg_show_status = true;
bf4df7c3 83static bool arg_switched_root = false;
06d4c99a 84static char **arg_default_controllers = NULL;
0c85a4f3 85static char ***arg_join_controllers = NULL;
706343f4 86static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
0a494f1f 87static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
e96d6be7
LP
88static usec_t arg_runtime_watchdog = 0;
89static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
c93ff2e9 90static struct rlimit *arg_default_rlimit[RLIMIT_NLIMITS] = {};
ec8927ca 91static uint64_t arg_capability_bounding_set_drop = 0;
aa0f64ac 92static nsec_t arg_timer_slack_nsec = (nsec_t) -1;
4fc935ca 93
a16e1123 94static FILE* serialization = NULL;
80876c20 95
6f5e3f35
LP
96static void nop_handler(int sig) {
97}
98
93a46b0b 99_noreturn_ static void crash(int sig) {
97c4f35c 100
fa0f4d8a 101 if (!arg_dump_core)
582a507f 102 log_error("Caught <%s>, not dumping core.", signal_to_string(sig));
97c4f35c 103 else {
6f5e3f35 104 struct sigaction sa;
97c4f35c
LP
105 pid_t pid;
106
6f5e3f35
LP
107 /* We want to wait for the core process, hence let's enable SIGCHLD */
108 zero(sa);
109 sa.sa_handler = nop_handler;
110 sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
111 assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
112
97c4f35c 113 if ((pid = fork()) < 0)
582a507f 114 log_error("Caught <%s>, cannot fork for core dump: %s", signal_to_string(sig), strerror(errno));
97c4f35c
LP
115
116 else if (pid == 0) {
97c4f35c
LP
117 struct rlimit rl;
118
119 /* Enable default signal handler for core dump */
120 zero(sa);
121 sa.sa_handler = SIG_DFL;
122 assert_se(sigaction(sig, &sa, NULL) == 0);
123
124 /* Don't limit the core dump size */
125 zero(rl);
126 rl.rlim_cur = RLIM_INFINITY;
127 rl.rlim_max = RLIM_INFINITY;
128 setrlimit(RLIMIT_CORE, &rl);
129
130 /* Just to be sure... */
131 assert_se(chdir("/") == 0);
132
133 /* Raise the signal again */
134 raise(sig);
135
136 assert_not_reached("We shouldn't be here...");
137 _exit(1);
4fc935ca
LP
138
139 } else {
8e12a6ae
LP
140 siginfo_t status;
141 int r;
4fc935ca
LP
142
143 /* Order things nicely. */
8e12a6ae
LP
144 if ((r = wait_for_terminate(pid, &status)) < 0)
145 log_error("Caught <%s>, waitpid() failed: %s", signal_to_string(sig), strerror(-r));
146 else if (status.si_code != CLD_DUMPED)
582a507f 147 log_error("Caught <%s>, core dump failed.", signal_to_string(sig));
4fc935ca 148 else
582a507f 149 log_error("Caught <%s>, dumped core as pid %lu.", signal_to_string(sig), (unsigned long) pid);
97c4f35c
LP
150 }
151 }
152
fa0f4d8a
LP
153 if (arg_crash_chvt)
154 chvt(arg_crash_chvt);
601f6a1e 155
fa0f4d8a 156 if (arg_crash_shell) {
6f5e3f35
LP
157 struct sigaction sa;
158 pid_t pid;
8c43883a 159
4fc935ca
LP
160 log_info("Executing crash shell in 10s...");
161 sleep(10);
162
6f5e3f35
LP
163 /* Let the kernel reap children for us */
164 zero(sa);
165 sa.sa_handler = SIG_IGN;
166 sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART;
167 assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
8c43883a 168
cd3bd60a
LP
169 pid = fork();
170 if (pid < 0)
6f5e3f35
LP
171 log_error("Failed to fork off crash shell: %s", strerror(errno));
172 else if (pid == 0) {
cd3bd60a 173 make_console_stdio();
6f5e3f35
LP
174 execl("/bin/sh", "/bin/sh", NULL);
175
176 log_error("execl() failed: %s", strerror(errno));
177 _exit(1);
178 }
c99b188e 179
f8e08a77 180 log_info("Successfully spawned crash shell as pid %lu.", (unsigned long) pid);
4fc935ca
LP
181 }
182
183 log_info("Freezing execution.");
97c4f35c
LP
184 freeze();
185}
186
187static void install_crash_handler(void) {
188 struct sigaction sa;
189
190 zero(sa);
191
192 sa.sa_handler = crash;
193 sa.sa_flags = SA_NODEFER;
194
1b91d3e8 195 sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
97c4f35c 196}
f170852a 197
843d2643
LP
198static int console_setup(bool do_reset) {
199 int tty_fd, r;
80876c20 200
843d2643
LP
201 /* If we are init, we connect stdin/stdout/stderr to /dev/null
202 * and make sure we don't have a controlling tty. */
80876c20 203
843d2643
LP
204 release_terminal();
205
206 if (!do_reset)
207 return 0;
80876c20 208
512947d4
MS
209 tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
210 if (tty_fd < 0) {
843d2643
LP
211 log_error("Failed to open /dev/console: %s", strerror(-tty_fd));
212 return -tty_fd;
213 }
80876c20 214
512947d4
MS
215 /* We don't want to force text mode.
216 * plymouth may be showing pictures already from initrd. */
217 r = reset_terminal_fd(tty_fd, false);
218 if (r < 0)
843d2643
LP
219 log_error("Failed to reset /dev/console: %s", strerror(-r));
220
221 close_nointr_nofail(tty_fd);
80876c20
LP
222 return r;
223}
224
f170852a
LP
225static int set_default_unit(const char *u) {
226 char *c;
227
228 assert(u);
229
bf4df7c3
LP
230 c = strdup(u);
231 if (!c)
f170852a
LP
232 return -ENOMEM;
233
fa0f4d8a
LP
234 free(arg_default_unit);
235 arg_default_unit = c;
bf4df7c3 236
f170852a
LP
237 return 0;
238}
239
240static int parse_proc_cmdline_word(const char *word) {
241
242 static const char * const rlmap[] = {
ed370f5d 243 "emergency", SPECIAL_EMERGENCY_TARGET,
099663ff 244 "-b", SPECIAL_EMERGENCY_TARGET,
ed370f5d
LP
245 "single", SPECIAL_RESCUE_TARGET,
246 "-s", SPECIAL_RESCUE_TARGET,
247 "s", SPECIAL_RESCUE_TARGET,
248 "S", SPECIAL_RESCUE_TARGET,
249 "1", SPECIAL_RESCUE_TARGET,
250 "2", SPECIAL_RUNLEVEL2_TARGET,
251 "3", SPECIAL_RUNLEVEL3_TARGET,
252 "4", SPECIAL_RUNLEVEL4_TARGET,
253 "5", SPECIAL_RUNLEVEL5_TARGET,
f170852a
LP
254 };
255
5192bd19
LP
256 assert(word);
257
bf4df7c3
LP
258 if (startswith(word, "systemd.unit=")) {
259
260 if (!in_initrd())
261 return set_default_unit(word + 13);
262
263 } else if (startswith(word, "rd.systemd.unit=")) {
264
265 if (in_initrd())
266 return set_default_unit(word + 16);
f170852a 267
bf4df7c3 268 } else if (startswith(word, "systemd.log_target=")) {
f170852a
LP
269
270 if (log_set_target_from_string(word + 19) < 0)
271 log_warning("Failed to parse log target %s. Ignoring.", word + 19);
272
273 } else if (startswith(word, "systemd.log_level=")) {
274
275 if (log_set_max_level_from_string(word + 18) < 0)
276 log_warning("Failed to parse log level %s. Ignoring.", word + 18);
277
bbe63281
LP
278 } else if (startswith(word, "systemd.log_color=")) {
279
280 if (log_show_color_from_string(word + 18) < 0)
281 log_warning("Failed to parse log color setting %s. Ignoring.", word + 18);
282
283 } else if (startswith(word, "systemd.log_location=")) {
284
285 if (log_show_location_from_string(word + 21) < 0)
286 log_warning("Failed to parse log location setting %s. Ignoring.", word + 21);
287
4fc935ca
LP
288 } else if (startswith(word, "systemd.dump_core=")) {
289 int r;
290
291 if ((r = parse_boolean(word + 18)) < 0)
509b6efb 292 log_warning("Failed to parse dump core switch %s. Ignoring.", word + 18);
4fc935ca 293 else
fa0f4d8a 294 arg_dump_core = r;
4fc935ca
LP
295
296 } else if (startswith(word, "systemd.crash_shell=")) {
297 int r;
298
299 if ((r = parse_boolean(word + 20)) < 0)
509b6efb 300 log_warning("Failed to parse crash shell switch %s. Ignoring.", word + 20);
4fc935ca 301 else
fa0f4d8a 302 arg_crash_shell = r;
5e7ee61c
LP
303
304 } else if (startswith(word, "systemd.confirm_spawn=")) {
305 int r;
306
307 if ((r = parse_boolean(word + 22)) < 0)
509b6efb 308 log_warning("Failed to parse confirm spawn switch %s. Ignoring.", word + 22);
5e7ee61c 309 else
fa0f4d8a 310 arg_confirm_spawn = r;
5e7ee61c 311
601f6a1e
LP
312 } else if (startswith(word, "systemd.crash_chvt=")) {
313 int k;
314
315 if (safe_atoi(word + 19, &k) < 0)
509b6efb 316 log_warning("Failed to parse crash chvt switch %s. Ignoring.", word + 19);
601f6a1e 317 else
fa0f4d8a 318 arg_crash_chvt = k;
601f6a1e 319
9e58ff9c
LP
320 } else if (startswith(word, "systemd.show_status=")) {
321 int r;
322
323 if ((r = parse_boolean(word + 20)) < 0)
509b6efb 324 log_warning("Failed to parse show status switch %s. Ignoring.", word + 20);
6e98720f 325 else
9e58ff9c 326 arg_show_status = r;
0a494f1f
LP
327 } else if (startswith(word, "systemd.default_standard_output=")) {
328 int r;
329
330 if ((r = exec_output_from_string(word + 32)) < 0)
509b6efb 331 log_warning("Failed to parse default standard output switch %s. Ignoring.", word + 32);
0a494f1f
LP
332 else
333 arg_default_std_output = r;
334 } else if (startswith(word, "systemd.default_standard_error=")) {
335 int r;
336
337 if ((r = exec_output_from_string(word + 31)) < 0)
509b6efb 338 log_warning("Failed to parse default standard error switch %s. Ignoring.", word + 31);
0a494f1f
LP
339 else
340 arg_default_std_error = r;
9e7c5357
WD
341 } else if (startswith(word, "systemd.setenv=")) {
342 char *cenv, *eq;
343 int r;
344
345 cenv = strdup(word + 15);
346 if (!cenv)
347 return -ENOMEM;
348
349 eq = strchr(cenv, '=');
350 if (!eq) {
351 r = unsetenv(cenv);
352 if (r < 0)
353 log_warning("unsetenv failed %s. Ignoring.", strerror(errno));
354 } else {
355 *eq = 0;
356 r = setenv(cenv, eq + 1, 1);
357 if (r < 0)
358 log_warning("setenv failed %s. Ignoring.", strerror(errno));
359 }
360 free(cenv);
9e58ff9c 361
66a78c2b
LP
362 } else if (startswith(word, "systemd.") ||
363 (in_initrd() && startswith(word, "rd.systemd."))) {
4fc935ca
LP
364
365 log_warning("Unknown kernel switch %s. Ignoring.", word);
366
bbe63281
LP
367 log_info("Supported kernel switches:\n"
368 "systemd.unit=UNIT Default unit to start\n"
bf4df7c3 369 "rd.systemd.unit=UNIT Default unit to start when run in initrd\n"
bbe63281 370 "systemd.dump_core=0|1 Dump core on crash\n"
9e58ff9c 371 "systemd.crash_shell=0|1 Run shell on crash\n"
bbe63281 372 "systemd.crash_chvt=N Change to VT #N on crash\n"
9e58ff9c 373 "systemd.confirm_spawn=0|1 Confirm every process spawn\n"
6e98720f 374 "systemd.show_status=0|1 Show status updates on the console during bootup\n"
4cfa2c99 375 "systemd.log_target=console|kmsg|journal|journal-or-kmsg|syslog|syslog-or-kmsg|null\n"
6e98720f
LP
376 " Log target\n"
377 "systemd.log_level=LEVEL Log level\n"
378 "systemd.log_color=0|1 Highlight important log messages\n"
0a494f1f 379 "systemd.log_location=0|1 Include code location in log messages\n"
706343f4 380 "systemd.default_standard_output=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
0a494f1f 381 " Set default log output for services\n"
706343f4 382 "systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
c66e7bc7
LP
383 " Set default log error output for services\n"
384 "systemd.setenv=ASSIGNMENT Set an environment variable for all spawned processes\n");
4fc935ca 385
d081dffb 386 } else if (streq(word, "quiet"))
6e98720f 387 arg_show_status = false;
d081dffb 388 else if (!in_initrd()) {
f170852a
LP
389 unsigned i;
390
391 /* SysV compatibility */
f170852a
LP
392 for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
393 if (streq(word, rlmap[i]))
394 return set_default_unit(rlmap[i+1]);
395 }
396
397 return 0;
398}
399
f975e971 400static int config_parse_level2(
487393e9
LP
401 const char *filename,
402 unsigned line,
403 const char *section,
404 const char *lvalue,
3731f1ea 405 int ltype,
487393e9
LP
406 const char *rvalue,
407 void *data,
408 void *userdata) {
409
410 assert(filename);
411 assert(lvalue);
412 assert(rvalue);
413
414 log_set_max_level_from_string(rvalue);
415 return 0;
416}
417
418static int config_parse_target(
419 const char *filename,
420 unsigned line,
421 const char *section,
422 const char *lvalue,
3731f1ea 423 int ltype,
487393e9
LP
424 const char *rvalue,
425 void *data,
426 void *userdata) {
427
428 assert(filename);
429 assert(lvalue);
430 assert(rvalue);
431
432 log_set_target_from_string(rvalue);
433 return 0;
434}
435
436static int config_parse_color(
437 const char *filename,
438 unsigned line,
439 const char *section,
440 const char *lvalue,
3731f1ea 441 int ltype,
487393e9
LP
442 const char *rvalue,
443 void *data,
444 void *userdata) {
445
446 assert(filename);
447 assert(lvalue);
448 assert(rvalue);
449
450 log_show_color_from_string(rvalue);
451 return 0;
452}
453
454static int config_parse_location(
455 const char *filename,
456 unsigned line,
457 const char *section,
458 const char *lvalue,
3731f1ea 459 int ltype,
487393e9
LP
460 const char *rvalue,
461 void *data,
462 void *userdata) {
463
464 assert(filename);
465 assert(lvalue);
466 assert(rvalue);
467
468 log_show_location_from_string(rvalue);
469 return 0;
470}
471
f975e971 472static int config_parse_cpu_affinity2(
487393e9
LP
473 const char *filename,
474 unsigned line,
475 const char *section,
476 const char *lvalue,
3731f1ea 477 int ltype,
487393e9
LP
478 const char *rvalue,
479 void *data,
480 void *userdata) {
481
482 char *w;
483 size_t l;
484 char *state;
485 cpu_set_t *c = NULL;
486 unsigned ncpus = 0;
487
488 assert(filename);
489 assert(lvalue);
490 assert(rvalue);
491
f60f22df 492 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
487393e9
LP
493 char *t;
494 int r;
495 unsigned cpu;
496
497 if (!(t = strndup(w, l)))
498 return -ENOMEM;
499
500 r = safe_atou(t, &cpu);
501 free(t);
502
503 if (!c)
504 if (!(c = cpu_set_malloc(&ncpus)))
505 return -ENOMEM;
506
507 if (r < 0 || cpu >= ncpus) {
508 log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
509 CPU_FREE(c);
510 return -EBADMSG;
511 }
512
513 CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
514 }
515
516 if (c) {
517 if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
518 log_warning("Failed to set CPU affinity: %m");
519
520 CPU_FREE(c);
521 }
522
523 return 0;
524}
525
0c85a4f3
LP
526static void strv_free_free(char ***l) {
527 char ***i;
528
529 if (!l)
530 return;
531
532 for (i = l; *i; i++)
533 strv_free(*i);
534
535 free(l);
536}
537
538static void free_join_controllers(void) {
539 if (!arg_join_controllers)
540 return;
541
542 strv_free_free(arg_join_controllers);
543 arg_join_controllers = NULL;
544}
545
546static int config_parse_join_controllers(
547 const char *filename,
548 unsigned line,
549 const char *section,
550 const char *lvalue,
551 int ltype,
552 const char *rvalue,
553 void *data,
554 void *userdata) {
555
556 unsigned n = 0;
557 char *state, *w;
558 size_t length;
559
560 assert(filename);
561 assert(lvalue);
562 assert(rvalue);
563
564 free_join_controllers();
565
566 FOREACH_WORD_QUOTED(w, length, rvalue, state) {
567 char *s, **l;
568
569 s = strndup(w, length);
570 if (!s)
571 return -ENOMEM;
572
573 l = strv_split(s, ",");
574 free(s);
575
576 strv_uniq(l);
577
578 if (strv_length(l) <= 1) {
579 strv_free(l);
580 continue;
581 }
582
583 if (!arg_join_controllers) {
584 arg_join_controllers = new(char**, 2);
585 if (!arg_join_controllers) {
586 strv_free(l);
587 return -ENOMEM;
588 }
589
590 arg_join_controllers[0] = l;
591 arg_join_controllers[1] = NULL;
592
593 n = 1;
594 } else {
595 char ***a;
596 char ***t;
597
598 t = new0(char**, n+2);
599 if (!t) {
600 strv_free(l);
601 return -ENOMEM;
602 }
603
604 n = 0;
605
606 for (a = arg_join_controllers; *a; a++) {
607
608 if (strv_overlap(*a, l)) {
609 char **c;
610
611 c = strv_merge(*a, l);
612 if (!c) {
613 strv_free(l);
614 strv_free_free(t);
615 return -ENOMEM;
616 }
617
618 strv_free(l);
619 l = c;
620 } else {
621 char **c;
622
623 c = strv_copy(*a);
624 if (!c) {
625 strv_free(l);
626 strv_free_free(t);
627 return -ENOMEM;
628 }
629
630 t[n++] = c;
631 }
632 }
633
634 t[n++] = strv_uniq(l);
635
636 strv_free_free(arg_join_controllers);
637 arg_join_controllers = t;
638 }
639 }
640
641 return 0;
642}
643
487393e9
LP
644static int parse_config_file(void) {
645
f975e971
LP
646 const ConfigTableItem items[] = {
647 { "Manager", "LogLevel", config_parse_level2, 0, NULL },
648 { "Manager", "LogTarget", config_parse_target, 0, NULL },
649 { "Manager", "LogColor", config_parse_color, 0, NULL },
650 { "Manager", "LogLocation", config_parse_location, 0, NULL },
651 { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
652 { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
653 { "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status },
f975e971
LP
654 { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
655 { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
f975e971
LP
656 { "Manager", "DefaultControllers", config_parse_strv, 0, &arg_default_controllers },
657 { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
658 { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
0c85a4f3 659 { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
e96d6be7
LP
660 { "Manager", "RuntimeWatchdogSec", config_parse_usec, 0, &arg_runtime_watchdog },
661 { "Manager", "ShutdownWatchdogSec", config_parse_usec, 0, &arg_shutdown_watchdog },
ec8927ca 662 { "Manager", "CapabilityBoundingSet", config_parse_bounding_set, 0, &arg_capability_bounding_set_drop },
aa0f64ac 663 { "Manager", "TimerSlackNSec", config_parse_nsec, 0, &arg_timer_slack_nsec },
c93ff2e9
FC
664 { "Manager", "DefaultLimitCPU", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CPU]},
665 { "Manager", "DefaultLimitFSIZE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_FSIZE]},
666 { "Manager", "DefaultLimitDATA", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_DATA]},
667 { "Manager", "DefaultLimitSTACK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_STACK]},
668 { "Manager", "DefaultLimitCORE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_CORE]},
669 { "Manager", "DefaultLimitRSS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RSS]},
670 { "Manager", "DefaultLimitNOFILE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NOFILE]},
671 { "Manager", "DefaultLimitAS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_AS]},
672 { "Manager", "DefaultLimitNPROC", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NPROC]},
673 { "Manager", "DefaultLimitMEMLOCK", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MEMLOCK]},
674 { "Manager", "DefaultLimitLOCKS", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_LOCKS]},
675 { "Manager", "DefaultLimitSIGPENDING",config_parse_limit, 0, &arg_default_rlimit[RLIMIT_SIGPENDING]},
676 { "Manager", "DefaultLimitMSGQUEUE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_MSGQUEUE]},
677 { "Manager", "DefaultLimitNICE", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_NICE]},
678 { "Manager", "DefaultLimitRTPRIO", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTPRIO]},
679 { "Manager", "DefaultLimitRTTIME", config_parse_limit, 0, &arg_default_rlimit[RLIMIT_RTTIME]},
f975e971 680 { NULL, NULL, NULL, 0, NULL }
487393e9
LP
681 };
682
683 FILE *f;
684 const char *fn;
685 int r;
686
af2d49f7 687 fn = arg_running_as == MANAGER_SYSTEM ? SYSTEM_CONFIG_FILE : USER_CONFIG_FILE;
f975e971
LP
688 f = fopen(fn, "re");
689 if (!f) {
487393e9
LP
690 if (errno == ENOENT)
691 return 0;
692
693 log_warning("Failed to open configuration file '%s': %m", fn);
694 return 0;
695 }
696
f975e971
LP
697 r = config_parse(fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, NULL);
698 if (r < 0)
487393e9
LP
699 log_warning("Failed to parse configuration file: %s", strerror(-r));
700
701 fclose(f);
702
703 return 0;
704}
705
f170852a 706static int parse_proc_cmdline(void) {
52661efd 707 char *line, *w, *state;
f170852a 708 int r;
f170852a 709 size_t l;
f170852a 710
b770165a
LP
711 /* Don't read /proc/cmdline if we are in a container, since
712 * that is only relevant for the host system */
713 if (detect_container(NULL) > 0)
714 return 0;
715
f170852a 716 if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
e364ad06 717 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
f170852a
LP
718 return 0;
719 }
720
721 FOREACH_WORD_QUOTED(w, l, line, state) {
722 char *word;
723
724 if (!(word = strndup(w, l))) {
725 r = -ENOMEM;
726 goto finish;
727 }
728
729 r = parse_proc_cmdline_word(word);
730 free(word);
731
732 if (r < 0)
733 goto finish;
734 }
735
736 r = 0;
737
738finish:
739 free(line);
740 return r;
741}
742
743static int parse_argv(int argc, char *argv[]) {
744
745 enum {
746 ARG_LOG_LEVEL = 0x100,
747 ARG_LOG_TARGET,
bbe63281
LP
748 ARG_LOG_COLOR,
749 ARG_LOG_LOCATION,
2f198e2f 750 ARG_UNIT,
edb9aaa8 751 ARG_SYSTEM,
af2d49f7 752 ARG_USER,
e537352b 753 ARG_TEST,
9ba0bc4e 754 ARG_VERSION,
80876c20 755 ARG_DUMP_CONFIGURATION_ITEMS,
9e58ff9c
LP
756 ARG_DUMP_CORE,
757 ARG_CRASH_SHELL,
a16e1123 758 ARG_CONFIRM_SPAWN,
9e58ff9c 759 ARG_SHOW_STATUS,
4288f619 760 ARG_DESERIALIZE,
2660882b 761 ARG_SWITCHED_ROOT,
0a494f1f
LP
762 ARG_INTROSPECT,
763 ARG_DEFAULT_STD_OUTPUT,
764 ARG_DEFAULT_STD_ERROR
f170852a
LP
765 };
766
767 static const struct option options[] = {
a16e1123
LP
768 { "log-level", required_argument, NULL, ARG_LOG_LEVEL },
769 { "log-target", required_argument, NULL, ARG_LOG_TARGET },
bbe63281
LP
770 { "log-color", optional_argument, NULL, ARG_LOG_COLOR },
771 { "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
2f198e2f 772 { "unit", required_argument, NULL, ARG_UNIT },
edb9aaa8 773 { "system", no_argument, NULL, ARG_SYSTEM },
af2d49f7 774 { "user", no_argument, NULL, ARG_USER },
a16e1123
LP
775 { "test", no_argument, NULL, ARG_TEST },
776 { "help", no_argument, NULL, 'h' },
9ba0bc4e 777 { "version", no_argument, NULL, ARG_VERSION },
a16e1123 778 { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
a5d87bf0
LP
779 { "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
780 { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
781 { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN },
6e98720f 782 { "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
a16e1123 783 { "deserialize", required_argument, NULL, ARG_DESERIALIZE },
2660882b 784 { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT },
4288f619 785 { "introspect", optional_argument, NULL, ARG_INTROSPECT },
0a494f1f
LP
786 { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, },
787 { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, },
a16e1123 788 { NULL, 0, NULL, 0 }
f170852a
LP
789 };
790
791 int c, r;
792
793 assert(argc >= 1);
794 assert(argv);
795
b770165a
LP
796 if (getpid() == 1)
797 opterr = 0;
798
099663ff 799 while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0)
f170852a
LP
800
801 switch (c) {
802
803 case ARG_LOG_LEVEL:
804 if ((r = log_set_max_level_from_string(optarg)) < 0) {
805 log_error("Failed to parse log level %s.", optarg);
806 return r;
807 }
808
809 break;
810
811 case ARG_LOG_TARGET:
812
813 if ((r = log_set_target_from_string(optarg)) < 0) {
814 log_error("Failed to parse log target %s.", optarg);
815 return r;
816 }
817
818 break;
819
bbe63281
LP
820 case ARG_LOG_COLOR:
821
d0b170c8
LP
822 if (optarg) {
823 if ((r = log_show_color_from_string(optarg)) < 0) {
824 log_error("Failed to parse log color setting %s.", optarg);
825 return r;
826 }
827 } else
828 log_show_color(true);
bbe63281
LP
829
830 break;
831
832 case ARG_LOG_LOCATION:
833
d0b170c8
LP
834 if (optarg) {
835 if ((r = log_show_location_from_string(optarg)) < 0) {
836 log_error("Failed to parse log location setting %s.", optarg);
837 return r;
838 }
839 } else
840 log_show_location(true);
bbe63281
LP
841
842 break;
843
0a494f1f
LP
844 case ARG_DEFAULT_STD_OUTPUT:
845
846 if ((r = exec_output_from_string(optarg)) < 0) {
847 log_error("Failed to parse default standard output setting %s.", optarg);
848 return r;
849 } else
850 arg_default_std_output = r;
851 break;
852
853 case ARG_DEFAULT_STD_ERROR:
854
855 if ((r = exec_output_from_string(optarg)) < 0) {
856 log_error("Failed to parse default standard error output setting %s.", optarg);
857 return r;
858 } else
859 arg_default_std_error = r;
860 break;
861
2f198e2f 862 case ARG_UNIT:
f170852a
LP
863
864 if ((r = set_default_unit(optarg)) < 0) {
865 log_error("Failed to set default unit %s: %s", optarg, strerror(-r));
866 return r;
867 }
868
869 break;
870
edb9aaa8
LP
871 case ARG_SYSTEM:
872 arg_running_as = MANAGER_SYSTEM;
873 break;
a5dab5ce 874
af2d49f7
LP
875 case ARG_USER:
876 arg_running_as = MANAGER_USER;
a5dab5ce 877 break;
a5dab5ce 878
e965d56d 879 case ARG_TEST:
fa0f4d8a 880 arg_action = ACTION_TEST;
e965d56d
LP
881 break;
882
9ba0bc4e
ZJS
883 case ARG_VERSION:
884 arg_action = ACTION_VERSION;
885 break;
886
e537352b 887 case ARG_DUMP_CONFIGURATION_ITEMS:
fa0f4d8a 888 arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
e537352b
LP
889 break;
890
9e58ff9c 891 case ARG_DUMP_CORE:
a5d87bf0
LP
892 r = optarg ? parse_boolean(optarg) : 1;
893 if (r < 0) {
894 log_error("Failed to parse dump core boolean %s.", optarg);
895 return r;
896 }
897 arg_dump_core = r;
9e58ff9c
LP
898 break;
899
900 case ARG_CRASH_SHELL:
a5d87bf0
LP
901 r = optarg ? parse_boolean(optarg) : 1;
902 if (r < 0) {
903 log_error("Failed to parse crash shell boolean %s.", optarg);
904 return r;
905 }
906 arg_crash_shell = r;
9e58ff9c
LP
907 break;
908
80876c20 909 case ARG_CONFIRM_SPAWN:
a5d87bf0
LP
910 r = optarg ? parse_boolean(optarg) : 1;
911 if (r < 0) {
912 log_error("Failed to parse confirm spawn boolean %s.", optarg);
913 return r;
914 }
915 arg_confirm_spawn = r;
80876c20
LP
916 break;
917
9e58ff9c 918 case ARG_SHOW_STATUS:
a5d87bf0
LP
919 r = optarg ? parse_boolean(optarg) : 1;
920 if (r < 0) {
921 log_error("Failed to parse show status boolean %s.", optarg);
922 return r;
923 }
924 arg_show_status = r;
6e98720f 925 break;
a5d87bf0 926
a16e1123
LP
927 case ARG_DESERIALIZE: {
928 int fd;
929 FILE *f;
930
931 if ((r = safe_atoi(optarg, &fd)) < 0 || fd < 0) {
932 log_error("Failed to parse deserialize option %s.", optarg);
933 return r;
934 }
935
936 if (!(f = fdopen(fd, "r"))) {
937 log_error("Failed to open serialization fd: %m");
938 return r;
939 }
940
941 if (serialization)
942 fclose(serialization);
943
944 serialization = f;
945
946 break;
947 }
948
2660882b 949 case ARG_SWITCHED_ROOT:
bf4df7c3 950 arg_switched_root = true;
d03bc1b8
HH
951 break;
952
4288f619
LP
953 case ARG_INTROSPECT: {
954 const char * const * i = NULL;
955
956 for (i = bus_interface_table; *i; i += 2)
957 if (!optarg || streq(i[0], optarg)) {
958 fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
959 "<node>\n", stdout);
960 fputs(i[1], stdout);
961 fputs("</node>\n", stdout);
962
963 if (optarg)
964 break;
965 }
966
967 if (!i[0] && optarg)
968 log_error("Unknown interface %s.", optarg);
969
fa0f4d8a 970 arg_action = ACTION_DONE;
4288f619
LP
971 break;
972 }
973
f170852a 974 case 'h':
fa0f4d8a 975 arg_action = ACTION_HELP;
f170852a
LP
976 break;
977
1d2e23ab
LP
978 case 'D':
979 log_set_max_level(LOG_DEBUG);
980 break;
981
099663ff
LP
982 case 'b':
983 case 's':
984 case 'z':
985 /* Just to eat away the sysvinit kernel
986 * cmdline args without getopt() error
987 * messages that we'll parse in
988 * parse_proc_cmdline_word() or ignore. */
f170852a 989
099663ff 990 case '?':
f170852a 991 default:
099663ff
LP
992 if (getpid() != 1) {
993 log_error("Unknown option code %c", c);
994 return -EINVAL;
995 }
996
997 break;
f170852a
LP
998 }
999
d821e6d6
LP
1000 if (optind < argc && getpid() != 1) {
1001 /* Hmm, when we aren't run as init system
1002 * let's complain about excess arguments */
1003
1004 log_error("Excess arguments.");
1005 return -EINVAL;
1006 }
1007
1008 if (detect_container(NULL) > 0) {
1009 char **a;
1010
1011 /* All /proc/cmdline arguments the kernel didn't
1012 * understand it passed to us. We're not really
1013 * interested in that usually since /proc/cmdline is
1014 * more interesting and complete. With one exception:
1015 * if we are run in a container /proc/cmdline is not
1016 * relevant for the container, hence we rely on argv[]
1017 * instead. */
1018
1019 for (a = argv; a < argv + argc; a++)
1020 if ((r = parse_proc_cmdline_word(*a)) < 0)
1021 return r;
51f0e189
LP
1022 }
1023
f170852a
LP
1024 return 0;
1025}
1026
1027static int help(void) {
1028
2e33c433 1029 printf("%s [OPTIONS...]\n\n"
af2d49f7 1030 "Starts up and maintains the system or user services.\n\n"
e537352b 1031 " -h --help Show this help\n"
e537352b 1032 " --test Determine startup sequence, dump it and exit\n"
80876c20 1033 " --dump-configuration-items Dump understood unit configuration items\n"
bbe63281 1034 " --introspect[=INTERFACE] Extract D-Bus interface data\n"
9e58ff9c 1035 " --unit=UNIT Set default unit\n"
edb9aaa8 1036 " --system Run a system instance, even if PID != 1\n"
af2d49f7 1037 " --user Run a user instance\n"
a5d87bf0
LP
1038 " --dump-core[=0|1] Dump core on crash\n"
1039 " --crash-shell[=0|1] Run shell on crash\n"
1040 " --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n"
6e98720f 1041 " --show-status[=0|1] Show status updates on the console during bootup\n"
4cfa2c99 1042 " --log-target=TARGET Set log target (console, journal, syslog, kmsg, journal-or-kmsg, syslog-or-kmsg, null)\n"
9e58ff9c 1043 " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n"
2218198b 1044 " --log-color[=0|1] Highlight important log messages\n"
0a494f1f
LP
1045 " --log-location[=0|1] Include code location in log messages\n"
1046 " --default-standard-output= Set default standard output for services\n"
1047 " --default-standard-error= Set default standard error output for services\n",
5b6319dc 1048 program_invocation_short_name);
f170852a
LP
1049
1050 return 0;
1051}
1052
9ba0bc4e
ZJS
1053static int version(void) {
1054 puts(PACKAGE_STRING);
1055 puts(DISTRIBUTION);
1056 puts(SYSTEMD_FEATURES);
1057
1058 return 0;
1059}
1060
6b78f9b4 1061static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds, bool serialize_jobs) {
a16e1123
LP
1062 FILE *f = NULL;
1063 FDSet *fds = NULL;
1064 int r;
1065
1066 assert(m);
1067 assert(_f);
1068 assert(_fds);
1069
a7556052
LP
1070 /* Make sure nothing is really destructed when we shut down */
1071 m->n_reloading ++;
1072
6b78f9b4
LP
1073 r = manager_open_serialization(m, &f);
1074 if (r < 0) {
35b8ca3a 1075 log_error("Failed to create serialization file: %s", strerror(-r));
a16e1123
LP
1076 goto fail;
1077 }
1078
6b78f9b4
LP
1079 fds = fdset_new();
1080 if (!fds) {
a16e1123
LP
1081 r = -ENOMEM;
1082 log_error("Failed to allocate fd set: %s", strerror(-r));
1083 goto fail;
1084 }
1085
6b78f9b4
LP
1086 r = manager_serialize(m, f, fds, serialize_jobs);
1087 if (r < 0) {
a16e1123
LP
1088 log_error("Failed to serialize state: %s", strerror(-r));
1089 goto fail;
1090 }
1091
1092 if (fseeko(f, 0, SEEK_SET) < 0) {
1093 log_error("Failed to rewind serialization fd: %m");
1094 goto fail;
1095 }
1096
6b78f9b4
LP
1097 r = fd_cloexec(fileno(f), false);
1098 if (r < 0) {
a16e1123
LP
1099 log_error("Failed to disable O_CLOEXEC for serialization: %s", strerror(-r));
1100 goto fail;
1101 }
1102
6b78f9b4
LP
1103 r = fdset_cloexec(fds, false);
1104 if (r < 0) {
a16e1123
LP
1105 log_error("Failed to disable O_CLOEXEC for serialization fds: %s", strerror(-r));
1106 goto fail;
1107 }
1108
1109 *_f = f;
1110 *_fds = fds;
1111
1112 return 0;
1113
1114fail:
1115 fdset_free(fds);
1116
1117 if (f)
1118 fclose(f);
1119
1120 return r;
1121}
1122
e9ddabc2
LP
1123static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
1124 const char *e;
1125 unsigned long long a, b;
1126
1127 assert(t);
1128
966a5d37
LP
1129 e = getenv("RD_TIMESTAMP");
1130 if (!e)
e9ddabc2
LP
1131 return NULL;
1132
1133 if (sscanf(e, "%llu %llu", &a, &b) != 2)
1134 return NULL;
1135
1136 t->realtime = (usec_t) a;
1137 t->monotonic = (usec_t) b;
1138
1139 return t;
1140}
1141
6ee5bbf8
LP
1142static void test_mtab(void) {
1143 char *p;
1144
80758717
LP
1145 /* Check that /etc/mtab is a symlink */
1146
6ee5bbf8
LP
1147 if (readlink_malloc("/etc/mtab", &p) >= 0) {
1148 bool b;
1149
ed86ebc4 1150 b = streq(p, "/proc/self/mounts") || streq(p, "/proc/mounts");
6ee5bbf8
LP
1151 free(p);
1152
1153 if (b)
1154 return;
1155 }
1156
80758717
LP
1157 log_warning("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. "
1158 "This is not supported anymore. "
1159 "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
1160}
1161
1162static void test_usr(void) {
80758717 1163
ed1c99fc 1164 /* Check that /usr is not a separate fs */
80758717 1165
871c44a7
LP
1166 if (dir_is_empty("/usr") <= 0)
1167 return;
1168
2376ce13 1169 log_warning("/usr appears to be on its own filesytem and is not already mounted. This is not a supported setup. "
871c44a7
LP
1170 "Some things will probably break (sometimes even silently) in mysterious ways. "
1171 "Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information.");
1172}
1173
1174static void test_cgroups(void) {
1175
1176 if (access("/proc/cgroups", F_OK) >= 0)
1177 return;
1178
1179 log_warning("CONFIG_CGROUPS was not set when your kernel was compiled. "
1180 "Systems without control groups are not supported. "
1181 "We will now sleep for 10s, and then continue boot-up. "
1182 "Expect breakage and please do not file bugs. "
966a5d37
LP
1183 "Instead fix your kernel and enable CONFIG_CGROUPS. "
1184 "Consult http://0pointer.de/blog/projects/cgroups-vs-cgroups.html for more information.");
871c44a7
LP
1185
1186 sleep(10);
6ee5bbf8
LP
1187}
1188
60918275
LP
1189int main(int argc, char *argv[]) {
1190 Manager *m = NULL;
22f4096c 1191 int r, retval = EXIT_FAILURE;
9d76d730
LP
1192 usec_t before_startup, after_startup;
1193 char timespan[FORMAT_TIMESPAN_MAX];
a16e1123
LP
1194 FDSet *fds = NULL;
1195 bool reexecute = false;
b9080b03 1196 const char *shutdown_verb = NULL;
e9ddabc2 1197 dual_timestamp initrd_timestamp = { 0ULL, 0ULL };
5d6b1584 1198 static char systemd[] = "systemd";
2660882b 1199 bool skip_setup = false;
0b3325e7
LP
1200 int j;
1201 bool loaded_policy = false;
e96d6be7 1202 bool arm_reboot_watchdog = false;
bf4df7c3 1203 bool queue_default_job = false;
41669317 1204 char *switch_root_dir = NULL, *switch_root_init = NULL;
27b14a22 1205
058dc6f3 1206#ifdef HAVE_SYSV_COMPAT
2cb1a60d 1207 if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
35b8ca3a 1208 /* This is compatibility support for SysV, where
2cb1a60d
LP
1209 * calling init as a user is identical to telinit. */
1210
1211 errno = -ENOENT;
1212 execv(SYSTEMCTL_BINARY_PATH, argv);
1213 log_error("Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
1214 return 1;
1215 }
058dc6f3 1216#endif
2cb1a60d 1217
0b3325e7
LP
1218 /* Determine if this is a reexecution or normal bootup. We do
1219 * the full command line parsing much later, so let's just
1220 * have a quick peek here. */
0b3325e7
LP
1221 for (j = 1; j < argc; j++)
1222 if (streq(argv[j], "--deserialize")) {
2660882b 1223 skip_setup = true;
7aaa27f2 1224 break;
0b3325e7
LP
1225 }
1226
2660882b
LP
1227 /* If we have switched root, do all the special setup
1228 * things */
d03bc1b8 1229 for (j = 1; j < argc; j++)
2660882b
LP
1230 if (streq(argv[j], "--switched-root")) {
1231 skip_setup = false;
d03bc1b8
HH
1232 break;
1233 }
1234
f3b6a3ed
LP
1235 /* If we get started via the /sbin/init symlink then we are
1236 called 'init'. After a subsequent reexecution we are then
1237 called 'systemd'. That is confusing, hence let's call us
1238 systemd right-away. */
f3b6a3ed
LP
1239 program_invocation_short_name = systemd;
1240 prctl(PR_SET_NAME, systemd);
5d6b1584 1241
9a0e6896
LP
1242 saved_argv = argv;
1243 saved_argc = argc;
f3b6a3ed 1244
2cc59dbf 1245 log_show_color(isatty(STDERR_FILENO) > 0);
bbe63281 1246 log_show_location(false);
7c706717 1247 log_set_max_level(LOG_INFO);
bbe63281 1248
843d2643 1249 if (getpid() == 1) {
c3ba6250
HH
1250 if (in_initrd()) {
1251 char *rd_timestamp = NULL;
1252
1253 dual_timestamp_get(&initrd_timestamp);
1254 asprintf(&rd_timestamp, "%llu %llu",
1255 (unsigned long long) initrd_timestamp.realtime,
1256 (unsigned long long) initrd_timestamp.monotonic);
1257 if (rd_timestamp) {
1258 setenv("RD_TIMESTAMP", rd_timestamp, 1);
1259 free(rd_timestamp);
1260 }
1261 }
1262
fa0f4d8a 1263 arg_running_as = MANAGER_SYSTEM;
a0a38448 1264 log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_JOURNAL : LOG_TARGET_JOURNAL_OR_KMSG);
0ff4cdd9 1265
2660882b 1266 if (!skip_setup) {
0b3325e7
LP
1267 if (selinux_setup(&loaded_policy) < 0)
1268 goto finish;
81611586
RS
1269 if (ima_setup() < 0)
1270 goto finish;
1271 }
0b3325e7
LP
1272
1273 log_open();
c4dcdb9f 1274
e9a5ef7c 1275 if (label_init(NULL) < 0)
0ff4cdd9 1276 goto finish;
7948c4df 1277
2660882b 1278 if (!skip_setup)
0b3325e7
LP
1279 if (hwclock_is_localtime() > 0) {
1280 int min;
7948c4df 1281
0b3325e7
LP
1282 r = hwclock_apply_localtime_delta(&min);
1283 if (r < 0)
1284 log_error("Failed to apply local time delta, ignoring: %s", strerror(-r));
1285 else
1286 log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
1287 }
871e5809 1288
bbe63281 1289 } else {
af2d49f7 1290 arg_running_as = MANAGER_USER;
eeecf6e6 1291 log_set_target(LOG_TARGET_AUTO);
871e5809 1292 log_open();
bbe63281 1293 }
a5dab5ce 1294
0c85a4f3 1295 /* Initialize default unit */
f170852a
LP
1296 if (set_default_unit(SPECIAL_DEFAULT_TARGET) < 0)
1297 goto finish;
60918275 1298
0c85a4f3
LP
1299 /* By default, mount "cpu" and "cpuacct" together */
1300 arg_join_controllers = new(char**, 2);
1301 if (!arg_join_controllers)
1302 goto finish;
1303
1304 arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
1305 arg_join_controllers[1] = NULL;
1306
1307 if (!arg_join_controllers[0])
1308 goto finish;
1309
f170852a
LP
1310 /* Mount /proc, /sys and friends, so that /proc/cmdline and
1311 * /proc/$PID/fd is available. */
0c85a4f3
LP
1312 if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
1313 r = mount_setup(loaded_policy);
1314 if (r < 0)
8efe3c01 1315 goto finish;
0c85a4f3 1316 }
4ade7963
LP
1317
1318 /* Reset all signal handlers. */
1319 assert_se(reset_all_signal_handlers() == 0);
1320
078e4539 1321 /* If we are init, we can block sigkill. Yay. */
9a34ec5f 1322 ignore_signals(SIGNALS_IGNORE, -1);
078e4539 1323
487393e9
LP
1324 if (parse_config_file() < 0)
1325 goto finish;
1326
fa0f4d8a 1327 if (arg_running_as == MANAGER_SYSTEM)
a5dab5ce
LP
1328 if (parse_proc_cmdline() < 0)
1329 goto finish;
f170852a
LP
1330
1331 log_parse_environment();
1332
1333 if (parse_argv(argc, argv) < 0)
1334 goto finish;
1335
b5c6cf87
LP
1336 if (arg_action == ACTION_TEST && geteuid() == 0) {
1337 log_error("Don't run test mode as root.");
1338 goto finish;
1339 }
1340
fe783b03
LP
1341 if (arg_running_as == MANAGER_SYSTEM &&
1342 arg_action == ACTION_RUN &&
1343 running_in_chroot() > 0) {
1344 log_error("Cannot be run in a chroot() environment.");
1345 goto finish;
1346 }
1347
fa0f4d8a 1348 if (arg_action == ACTION_HELP) {
f170852a
LP
1349 retval = help();
1350 goto finish;
9ba0bc4e
ZJS
1351 } else if (arg_action == ACTION_VERSION) {
1352 retval = version();
1353 goto finish;
fa0f4d8a 1354 } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) {
e537352b 1355 unit_dump_config_items(stdout);
22f4096c 1356 retval = EXIT_SUCCESS;
e537352b 1357 goto finish;
fa0f4d8a 1358 } else if (arg_action == ACTION_DONE) {
22f4096c 1359 retval = EXIT_SUCCESS;
4288f619 1360 goto finish;
f170852a
LP
1361 }
1362
fa0f4d8a 1363 assert_se(arg_action == ACTION_RUN || arg_action == ACTION_TEST);
f170852a 1364
871e5809
LP
1365 /* Close logging fds, in order not to confuse fdset below */
1366 log_close();
1367
a16e1123
LP
1368 /* Remember open file descriptors for later deserialization */
1369 if (serialization) {
966a5d37
LP
1370 r = fdset_new_fill(&fds);
1371 if (r < 0) {
a16e1123
LP
1372 log_error("Failed to allocate fd set: %s", strerror(-r));
1373 goto finish;
1374 }
1375
1376 assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
1377 } else
1378 close_all_fds(NULL, 0);
1379
09082a94 1380 /* Set up PATH unless it is already set */
e537352b 1381 setenv("PATH",
2c6db6fb 1382#ifdef HAVE_SPLIT_USR
e537352b 1383 "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
2c6db6fb
LP
1384#else
1385 "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
1386#endif
fa0f4d8a 1387 arg_running_as == MANAGER_SYSTEM);
09082a94 1388
39439087 1389 if (arg_running_as == MANAGER_SYSTEM) {
71ecc858
LP
1390 /* Parse the data passed to us. We leave this
1391 * variables set, but the manager later on will not
1392 * pass them on to our children. */
2660882b 1393 if (!in_initrd())
c3ba6250 1394 parse_initrd_timestamp(&initrd_timestamp);
e9ddabc2
LP
1395
1396 /* Unset some environment variables passed in from the
1397 * kernel that don't really make sense for us. */
39439087
LP
1398 unsetenv("HOME");
1399 unsetenv("TERM");
b770165a 1400
9543ad16
LP
1401 /* When we are invoked by a shell, these might be set,
1402 * but make little sense to pass on */
1403 unsetenv("PWD");
1404 unsetenv("SHLVL");
1405 unsetenv("_");
1406
2660882b 1407 /* When we are invoked by a chroot-like tool such as
9f28b98e
LP
1408 * nspawn, these might be set, but make little sense
1409 * to pass on */
1410 unsetenv("USER");
1411 unsetenv("LOGNAME");
1412
b770165a
LP
1413 /* All other variables are left as is, so that clients
1414 * can still read them via /proc/1/environ */
39439087 1415 }
1104f3c1 1416
f170852a
LP
1417 /* Move out of the way, so that we won't block unmounts */
1418 assert_se(chdir("/") == 0);
1419
fa0f4d8a 1420 if (arg_running_as == MANAGER_SYSTEM) {
80876c20
LP
1421 /* Become a session leader if we aren't one yet. */
1422 setsid();
4ade7963 1423
80876c20
LP
1424 /* Disable the umask logic */
1425 umask(0);
1426 }
1427
843d2643
LP
1428 /* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
1429 dbus_connection_set_change_sigpipe(FALSE);
1430
2146621b
LP
1431 /* Reset the console, but only if this is really init and we
1432 * are freshly booted */
fa0f4d8a 1433 if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN) {
2660882b 1434 console_setup(getpid() == 1 && !skip_setup);
843d2643
LP
1435 make_null_stdio();
1436 }
4ade7963 1437
18149b9f 1438 /* Open the logging devices, if possible and necessary */
843d2643 1439 log_open();
4ade7963 1440
5373d602
LP
1441 /* Make sure we leave a core dump without panicing the
1442 * kernel. */
4fc935ca
LP
1443 if (getpid() == 1)
1444 install_crash_handler();
97c4f35c 1445
0c85a4f3
LP
1446 if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
1447 r = mount_cgroup_controllers(arg_join_controllers);
1448 if (r < 0)
1449 goto finish;
1450 }
1451
c20f5ac7
LP
1452 if (arg_running_as == MANAGER_SYSTEM) {
1453 const char *virtualization = NULL;
1454
1455 log_info(PACKAGE_STRING " running in system mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")");
1456
1457 detect_virtualization(&virtualization);
1458 if (virtualization)
1459 log_info("Detected virtualization '%s'.", virtualization);
1460
26a1efdf
LP
1461 if (in_initrd())
1462 log_info("Running in initial RAM disk.");
1463
c20f5ac7
LP
1464 } else
1465 log_debug(PACKAGE_STRING " running in user mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")");
a5dab5ce 1466
2660882b 1467 if (arg_running_as == MANAGER_SYSTEM && !skip_setup) {
72bca11b
LP
1468 locale_setup();
1469
6faa1114 1470 if (arg_show_status || plymouth_running())
888c6216
LP
1471 status_welcome();
1472
888c6216
LP
1473 kmod_setup();
1474 hostname_setup();
d7ccca2e 1475 machine_id_setup();
888c6216 1476 loopback_setup();
490aed58 1477
6ee5bbf8 1478 test_mtab();
80758717 1479 test_usr();
871c44a7 1480 test_cgroups();
af5bc85d 1481 }
302e8c4c 1482
e96d6be7
LP
1483 if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0)
1484 watchdog_set_timeout(&arg_runtime_watchdog);
1485
aa0f64ac
LP
1486 if (arg_timer_slack_nsec != (nsec_t) -1)
1487 if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
1488 log_error("Failed to adjust timer slack: %m");
1489
ec8927ca
LP
1490 if (arg_capability_bounding_set_drop) {
1491 r = capability_bounding_set_drop(arg_capability_bounding_set_drop, true);
1492 if (r < 0) {
1493 log_error("Failed to drop capability bounding set: %s", strerror(-r));
1494 goto finish;
1495 }
939b8f14
LP
1496 r = capability_bounding_set_drop_usermode(arg_capability_bounding_set_drop);
1497 if (r < 0) {
1498 log_error("Failed to drop capability bounding set of usermode helpers: %s", strerror(-r));
1499 goto finish;
1500 }
ec8927ca
LP
1501 }
1502
d4447f4d
AK
1503 if (arg_running_as == MANAGER_USER) {
1504 /* Become reaper of our children */
1505 r = prctl(PR_SET_CHILD_SUBREAPER, 1);
1506 if (r < 0)
1507 log_error("Failed to prctl(PR_SET_CHILD_SUBREAPER): %s", strerror(-r));
1508 if (r == -EINVAL)
1509 log_error("Perhaps the kernel version is too old (< 3.4?)");
1510 }
1511
e96d6be7
LP
1512 r = manager_new(arg_running_as, &m);
1513 if (r < 0) {
8e274523 1514 log_error("Failed to allocate manager object: %s", strerror(-r));
60918275
LP
1515 goto finish;
1516 }
1517
9e58ff9c 1518 m->confirm_spawn = arg_confirm_spawn;
0a494f1f
LP
1519 m->default_std_output = arg_default_std_output;
1520 m->default_std_error = arg_default_std_error;
e96d6be7
LP
1521 m->runtime_watchdog = arg_runtime_watchdog;
1522 m->shutdown_watchdog = arg_shutdown_watchdog;
9e58ff9c 1523
c93ff2e9
FC
1524 manager_set_default_rlimits(m, arg_default_rlimit);
1525
e9ddabc2
LP
1526 if (dual_timestamp_is_set(&initrd_timestamp))
1527 m->initrd_timestamp = initrd_timestamp;
1528
06d4c99a
LP
1529 if (arg_default_controllers)
1530 manager_set_default_controllers(m, arg_default_controllers);
1531
27d340c7
LP
1532 manager_set_show_status(m, arg_show_status);
1533
bf4df7c3
LP
1534 /* Remember whether we should queue the default job */
1535 queue_default_job = !serialization || arg_switched_root;
1536
9d76d730
LP
1537 before_startup = now(CLOCK_MONOTONIC);
1538
e96d6be7
LP
1539 r = manager_startup(m, serialization, fds);
1540 if (r < 0)
6e2ef85b 1541 log_error("Failed to fully start up daemon: %s", strerror(-r));
a16e1123 1542
bf4df7c3
LP
1543 /* This will close all file descriptors that were opened, but
1544 * not claimed by any unit. */
a16e1123 1545 if (fds) {
a16e1123
LP
1546 fdset_free(fds);
1547 fds = NULL;
f50e0a01
LP
1548 }
1549
a16e1123
LP
1550 if (serialization) {
1551 fclose(serialization);
1552 serialization = NULL;
bf4df7c3
LP
1553 }
1554
1555 if (queue_default_job) {
398ef8ba 1556 DBusError error;
1c27d3f3 1557 Unit *target = NULL;
bacbccb7 1558 Job *default_unit_job;
398ef8ba
LP
1559
1560 dbus_error_init(&error);
1561
fa0f4d8a 1562 log_debug("Activating default unit: %s", arg_default_unit);
a16e1123 1563
e96d6be7
LP
1564 r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
1565 if (r < 0) {
398ef8ba
LP
1566 log_error("Failed to load default target: %s", bus_error(&error, r));
1567 dbus_error_free(&error);
ac155bb8
MS
1568 } else if (target->load_state == UNIT_ERROR)
1569 log_error("Failed to load default target: %s", strerror(-target->load_error));
1570 else if (target->load_state == UNIT_MASKED)
6daf4f90 1571 log_error("Default target masked.");
27b14a22 1572
ac155bb8 1573 if (!target || target->load_state != UNIT_LOADED) {
a16e1123 1574 log_info("Trying to load rescue target...");
1c27d3f3 1575
e96d6be7
LP
1576 r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
1577 if (r < 0) {
398ef8ba
LP
1578 log_error("Failed to load rescue target: %s", bus_error(&error, r));
1579 dbus_error_free(&error);
a16e1123 1580 goto finish;
ac155bb8
MS
1581 } else if (target->load_state == UNIT_ERROR) {
1582 log_error("Failed to load rescue target: %s", strerror(-target->load_error));
1c27d3f3 1583 goto finish;
ac155bb8 1584 } else if (target->load_state == UNIT_MASKED) {
6daf4f90 1585 log_error("Rescue target masked.");
00dc5d76 1586 goto finish;
a16e1123
LP
1587 }
1588 }
37d88da7 1589
ac155bb8 1590 assert(target->load_state == UNIT_LOADED);
00dc5d76 1591
fa0f4d8a 1592 if (arg_action == ACTION_TEST) {
40d50879 1593 printf("-> By units:\n");
a16e1123
LP
1594 manager_dump_units(m, stdout, "\t");
1595 }
1596
bacbccb7
MS
1597 r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
1598 if (r < 0) {
398ef8ba
LP
1599 log_error("Failed to start default target: %s", bus_error(&error, r));
1600 dbus_error_free(&error);
37d88da7
LP
1601 goto finish;
1602 }
bacbccb7 1603 m->default_unit_job_id = default_unit_job->id;
60918275 1604
07672f49
LP
1605 after_startup = now(CLOCK_MONOTONIC);
1606 log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG,
1607 "Loaded units and determined initial transaction in %s.",
1608 format_timespan(timespan, sizeof(timespan), after_startup - before_startup));
1609
fa0f4d8a 1610 if (arg_action == ACTION_TEST) {
40d50879 1611 printf("-> By jobs:\n");
a16e1123 1612 manager_dump_jobs(m, stdout, "\t");
22f4096c 1613 retval = EXIT_SUCCESS;
a16e1123
LP
1614 goto finish;
1615 }
e965d56d 1616 }
d46de8a1 1617
a16e1123 1618 for (;;) {
e96d6be7
LP
1619 r = manager_loop(m);
1620 if (r < 0) {
a16e1123
LP
1621 log_error("Failed to run mainloop: %s", strerror(-r));
1622 goto finish;
1623 }
11dd41ce 1624
a16e1123 1625 switch (m->exit_code) {
e965d56d 1626
a16e1123 1627 case MANAGER_EXIT:
22f4096c 1628 retval = EXIT_SUCCESS;
a16e1123
LP
1629 log_debug("Exit.");
1630 goto finish;
e965d56d 1631
a16e1123 1632 case MANAGER_RELOAD:
e015090f 1633 log_info("Reloading.");
e96d6be7
LP
1634 r = manager_reload(m);
1635 if (r < 0)
a16e1123
LP
1636 log_error("Failed to reload: %s", strerror(-r));
1637 break;
cea8e32e 1638
a16e1123 1639 case MANAGER_REEXECUTE:
664f88a7 1640
6b78f9b4 1641 if (prepare_reexecute(m, &serialization, &fds, true) < 0)
a16e1123 1642 goto finish;
60918275 1643
a16e1123 1644 reexecute = true;
e015090f 1645 log_notice("Reexecuting.");
a16e1123
LP
1646 goto finish;
1647
664f88a7
LP
1648 case MANAGER_SWITCH_ROOT:
1649 /* Steal the switch root parameters */
41669317 1650 switch_root_dir = m->switch_root;
664f88a7
LP
1651 switch_root_init = m->switch_root_init;
1652 m->switch_root = m->switch_root_init = NULL;
1653
1654 if (!switch_root_init)
6b78f9b4 1655 if (prepare_reexecute(m, &serialization, &fds, false) < 0)
664f88a7
LP
1656 goto finish;
1657
1658 reexecute = true;
1659 log_notice("Switching root.");
1660 goto finish;
1661
b9080b03
FF
1662 case MANAGER_REBOOT:
1663 case MANAGER_POWEROFF:
1664 case MANAGER_HALT:
1665 case MANAGER_KEXEC: {
1666 static const char * const table[_MANAGER_EXIT_CODE_MAX] = {
1667 [MANAGER_REBOOT] = "reboot",
1668 [MANAGER_POWEROFF] = "poweroff",
1669 [MANAGER_HALT] = "halt",
1670 [MANAGER_KEXEC] = "kexec"
1671 };
1672
1673 assert_se(shutdown_verb = table[m->exit_code]);
e96d6be7 1674 arm_reboot_watchdog = m->exit_code == MANAGER_REBOOT;
b9080b03
FF
1675
1676 log_notice("Shutting down.");
1677 goto finish;
1678 }
1679
a16e1123
LP
1680 default:
1681 assert_not_reached("Unknown exit code.");
1682 }
1683 }
f170852a 1684
60918275
LP
1685finish:
1686 if (m)
1687 manager_free(m);
1688
c93ff2e9
FC
1689 for (j = 0; j < RLIMIT_NLIMITS; j++)
1690 free (arg_default_rlimit[j]);
1691
fa0f4d8a 1692 free(arg_default_unit);
06d4c99a 1693 strv_free(arg_default_controllers);
0c85a4f3 1694 free_join_controllers();
b9cd2ec1 1695
ea430986 1696 dbus_shutdown();
b2bb3dbe
LP
1697 label_finish();
1698
a16e1123 1699 if (reexecute) {
664f88a7 1700 const char **args;
e564a982 1701 unsigned i, args_size;
a16e1123 1702
664f88a7
LP
1703 /* Close and disarm the watchdog, so that the new
1704 * instance can reinitialize it, but doesn't get
1705 * rebooted while we do that */
1706 watchdog_close(true);
a16e1123 1707
41669317 1708 if (switch_root_dir) {
cee530bb
LP
1709 /* Kill all remaining processes from the
1710 * initrd, but don't wait for them, so that we
1711 * can handle the SIGCHLD for them after
1712 * deserializing. */
1713 broadcast_signal(SIGTERM, false);
bd3fa1d2
LP
1714
1715 /* And switch root */
41669317
LP
1716 r = switch_root(switch_root_dir);
1717 if (r < 0)
1718 log_error("Failed to switch root, ignoring: %s", strerror(-r));
1719 }
a16e1123 1720
d03bc1b8 1721 args_size = MAX(6, argc+1);
e564a982 1722 args = newa(const char*, args_size);
a16e1123 1723
664f88a7
LP
1724 if (!switch_root_init) {
1725 char sfd[16];
a16e1123 1726
664f88a7
LP
1727 /* First try to spawn ourselves with the right
1728 * path, and with full serialization. We do
1729 * this only if the user didn't specify an
1730 * explicit init to spawn. */
edb9aaa8 1731
664f88a7
LP
1732 assert(serialization);
1733 assert(fds);
edb9aaa8 1734
664f88a7
LP
1735 snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
1736 char_array_0(sfd);
edb9aaa8 1737
664f88a7
LP
1738 i = 0;
1739 args[i++] = SYSTEMD_BINARY_PATH;
41669317 1740 if (switch_root_dir)
2660882b 1741 args[i++] = "--switched-root";
664f88a7
LP
1742 args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user";
1743 args[i++] = "--deserialize";
1744 args[i++] = sfd;
1745 args[i++] = NULL;
edb9aaa8 1746
e564a982 1747 assert(i <= args_size);
664f88a7
LP
1748 execv(args[0], (char* const*) args);
1749 }
6e98720f 1750
664f88a7
LP
1751 /* Try the fallback, if there is any, without any
1752 * serialization. We pass the original argv[] and
1753 * envp[]. (Well, modulo the ordering changes due to
1754 * getopt() in argv[], and some cleanups in envp[],
1755 * but let's hope that doesn't matter.) */
a16e1123 1756
b8f83232 1757 if (serialization) {
664f88a7 1758 fclose(serialization);
b8f83232
LP
1759 serialization = NULL;
1760 }
a16e1123 1761
b8f83232 1762 if (fds) {
664f88a7 1763 fdset_free(fds);
b8f83232
LP
1764 fds = NULL;
1765 }
a16e1123 1766
a504223d
HH
1767 /* Reopen the console */
1768 make_console_stdio();
1769
b8f83232 1770 for (j = 1, i = 1; j < argc; j++)
664f88a7 1771 args[i++] = argv[j];
a16e1123 1772 args[i++] = NULL;
e564a982 1773 assert(i <= args_size);
b8f83232
LP
1774
1775 if (switch_root_init) {
1776 args[0] = switch_root_init;
1777 execv(args[0], (char* const*) args);
1778 log_warning("Failed to execute configured init, trying fallback: %m");
1779 }
1780
1781 args[0] = "/sbin/init";
a16e1123
LP
1782 execv(args[0], (char* const*) args);
1783
745e2fb7
KS
1784 if (errno == ENOENT) {
1785 log_warning("No /sbin/init, trying fallback");
b8f83232 1786
745e2fb7
KS
1787 args[0] = "/bin/sh";
1788 args[1] = NULL;
1789 execv(args[0], (char* const*) args);
1790 log_error("Failed to execute /bin/sh, giving up: %m");
1791 } else
1792 log_warning("Failed to execute /sbin/init, giving up: %m");
a16e1123
LP
1793 }
1794
1795 if (serialization)
1796 fclose(serialization);
1797
1798 if (fds)
1799 fdset_free(fds);
1800
b9080b03
FF
1801 if (shutdown_verb) {
1802 const char * command_line[] = {
1803 SYSTEMD_SHUTDOWN_BINARY_PATH,
1804 shutdown_verb,
1805 NULL
1806 };
d18f337c 1807 char **env_block;
b9080b03 1808
e96d6be7 1809 if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
d18f337c
LP
1810 char e[32];
1811
e96d6be7
LP
1812 /* If we reboot let's set the shutdown
1813 * watchdog and tell the shutdown binary to
1814 * repeatedly ping it */
1815 watchdog_set_timeout(&arg_shutdown_watchdog);
1816 watchdog_close(false);
1817
1818 /* Tell the binary how often to ping */
1819 snprintf(e, sizeof(e), "WATCHDOG_USEC=%llu", (unsigned long long) arg_shutdown_watchdog);
1820 char_array_0(e);
d18f337c
LP
1821
1822 env_block = strv_append(environ, e);
1823 } else {
1824 env_block = strv_copy(environ);
e96d6be7 1825 watchdog_close(true);
d18f337c 1826 }
e96d6be7 1827
d18f337c
LP
1828 execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
1829 free(env_block);
b9080b03
FF
1830 log_error("Failed to execute shutdown binary, freezing: %m");
1831 }
1832
c3b3c274
LP
1833 if (getpid() == 1)
1834 freeze();
1835
60918275
LP
1836 return retval;
1837}