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