]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/main.c
relicense to LGPLv2.1 (with exceptions)
[thirdparty/systemd.git] / src / 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 "mount-setup.h"
39 #include "hostname-setup.h"
40 #include "loopback-setup.h"
41 #include "kmod-setup.h"
42 #include "locale-setup.h"
43 #include "selinux-setup.h"
44 #include "ima-setup.h"
45 #include "machine-id-setup.h"
46 #include "load-fragment.h"
47 #include "fdset.h"
48 #include "special.h"
49 #include "conf-parser.h"
50 #include "bus-errors.h"
51 #include "missing.h"
52 #include "label.h"
53 #include "build.h"
54 #include "strv.h"
55 #include "def.h"
56 #include "virt.h"
57 #include "watchdog.h"
58
59 static enum {
60 ACTION_RUN,
61 ACTION_HELP,
62 ACTION_TEST,
63 ACTION_DUMP_CONFIGURATION_ITEMS,
64 ACTION_DONE
65 } arg_action = ACTION_RUN;
66
67 static char *arg_default_unit = NULL;
68 static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
69
70 static bool arg_dump_core = true;
71 static bool arg_crash_shell = false;
72 static int arg_crash_chvt = -1;
73 static bool arg_confirm_spawn = false;
74 static bool arg_show_status = true;
75 #ifdef HAVE_SYSV_COMPAT
76 static bool arg_sysv_console = true;
77 #endif
78 static bool arg_mount_auto = true;
79 static bool arg_swap_auto = true;
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", "MountAuto", config_parse_bool, 0, &arg_mount_auto },
661 { "Manager", "SwapAuto", config_parse_bool, 0, &arg_swap_auto },
662 { "Manager", "DefaultControllers", config_parse_strv, 0, &arg_default_controllers },
663 { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
664 { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
665 { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
666 { "Manager", "RuntimeWatchdogSec", config_parse_usec, 0, &arg_runtime_watchdog },
667 { "Manager", "ShutdownWatchdogSec", config_parse_usec, 0, &arg_shutdown_watchdog },
668 { NULL, NULL, NULL, 0, NULL }
669 };
670
671 FILE *f;
672 const char *fn;
673 int r;
674
675 fn = arg_running_as == MANAGER_SYSTEM ? SYSTEM_CONFIG_FILE : USER_CONFIG_FILE;
676 f = fopen(fn, "re");
677 if (!f) {
678 if (errno == ENOENT)
679 return 0;
680
681 log_warning("Failed to open configuration file '%s': %m", fn);
682 return 0;
683 }
684
685 r = config_parse(fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, NULL);
686 if (r < 0)
687 log_warning("Failed to parse configuration file: %s", strerror(-r));
688
689 fclose(f);
690
691 return 0;
692 }
693
694 static int parse_proc_cmdline(void) {
695 char *line, *w, *state;
696 int r;
697 size_t l;
698
699 /* Don't read /proc/cmdline if we are in a container, since
700 * that is only relevant for the host system */
701 if (detect_container(NULL) > 0)
702 return 0;
703
704 if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
705 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
706 return 0;
707 }
708
709 FOREACH_WORD_QUOTED(w, l, line, state) {
710 char *word;
711
712 if (!(word = strndup(w, l))) {
713 r = -ENOMEM;
714 goto finish;
715 }
716
717 r = parse_proc_cmdline_word(word);
718 free(word);
719
720 if (r < 0)
721 goto finish;
722 }
723
724 r = 0;
725
726 finish:
727 free(line);
728 return r;
729 }
730
731 static int parse_argv(int argc, char *argv[]) {
732
733 enum {
734 ARG_LOG_LEVEL = 0x100,
735 ARG_LOG_TARGET,
736 ARG_LOG_COLOR,
737 ARG_LOG_LOCATION,
738 ARG_UNIT,
739 ARG_SYSTEM,
740 ARG_USER,
741 ARG_TEST,
742 ARG_DUMP_CONFIGURATION_ITEMS,
743 ARG_DUMP_CORE,
744 ARG_CRASH_SHELL,
745 ARG_CONFIRM_SPAWN,
746 ARG_SHOW_STATUS,
747 ARG_SYSV_CONSOLE,
748 ARG_DESERIALIZE,
749 ARG_INTROSPECT,
750 ARG_DEFAULT_STD_OUTPUT,
751 ARG_DEFAULT_STD_ERROR
752 };
753
754 static const struct option options[] = {
755 { "log-level", required_argument, NULL, ARG_LOG_LEVEL },
756 { "log-target", required_argument, NULL, ARG_LOG_TARGET },
757 { "log-color", optional_argument, NULL, ARG_LOG_COLOR },
758 { "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
759 { "unit", required_argument, NULL, ARG_UNIT },
760 { "system", no_argument, NULL, ARG_SYSTEM },
761 { "user", no_argument, NULL, ARG_USER },
762 { "test", no_argument, NULL, ARG_TEST },
763 { "help", no_argument, NULL, 'h' },
764 { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
765 { "dump-core", no_argument, NULL, ARG_DUMP_CORE },
766 { "crash-shell", no_argument, NULL, ARG_CRASH_SHELL },
767 { "confirm-spawn", no_argument, NULL, ARG_CONFIRM_SPAWN },
768 { "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
769 #ifdef HAVE_SYSV_COMPAT
770 { "sysv-console", optional_argument, NULL, ARG_SYSV_CONSOLE },
771 #endif
772 { "deserialize", required_argument, NULL, ARG_DESERIALIZE },
773 { "introspect", optional_argument, NULL, ARG_INTROSPECT },
774 { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, },
775 { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, },
776 { NULL, 0, NULL, 0 }
777 };
778
779 int c, r;
780
781 assert(argc >= 1);
782 assert(argv);
783
784 if (getpid() == 1)
785 opterr = 0;
786
787 while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0)
788
789 switch (c) {
790
791 case ARG_LOG_LEVEL:
792 if ((r = log_set_max_level_from_string(optarg)) < 0) {
793 log_error("Failed to parse log level %s.", optarg);
794 return r;
795 }
796
797 break;
798
799 case ARG_LOG_TARGET:
800
801 if ((r = log_set_target_from_string(optarg)) < 0) {
802 log_error("Failed to parse log target %s.", optarg);
803 return r;
804 }
805
806 break;
807
808 case ARG_LOG_COLOR:
809
810 if (optarg) {
811 if ((r = log_show_color_from_string(optarg)) < 0) {
812 log_error("Failed to parse log color setting %s.", optarg);
813 return r;
814 }
815 } else
816 log_show_color(true);
817
818 break;
819
820 case ARG_LOG_LOCATION:
821
822 if (optarg) {
823 if ((r = log_show_location_from_string(optarg)) < 0) {
824 log_error("Failed to parse log location setting %s.", optarg);
825 return r;
826 }
827 } else
828 log_show_location(true);
829
830 break;
831
832 case ARG_DEFAULT_STD_OUTPUT:
833
834 if ((r = exec_output_from_string(optarg)) < 0) {
835 log_error("Failed to parse default standard output setting %s.", optarg);
836 return r;
837 } else
838 arg_default_std_output = r;
839 break;
840
841 case ARG_DEFAULT_STD_ERROR:
842
843 if ((r = exec_output_from_string(optarg)) < 0) {
844 log_error("Failed to parse default standard error output setting %s.", optarg);
845 return r;
846 } else
847 arg_default_std_error = r;
848 break;
849
850 case ARG_UNIT:
851
852 if ((r = set_default_unit(optarg)) < 0) {
853 log_error("Failed to set default unit %s: %s", optarg, strerror(-r));
854 return r;
855 }
856
857 break;
858
859 case ARG_SYSTEM:
860 arg_running_as = MANAGER_SYSTEM;
861 break;
862
863 case ARG_USER:
864 arg_running_as = MANAGER_USER;
865 break;
866
867 case ARG_TEST:
868 arg_action = ACTION_TEST;
869 break;
870
871 case ARG_DUMP_CONFIGURATION_ITEMS:
872 arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
873 break;
874
875 case ARG_DUMP_CORE:
876 arg_dump_core = true;
877 break;
878
879 case ARG_CRASH_SHELL:
880 arg_crash_shell = true;
881 break;
882
883 case ARG_CONFIRM_SPAWN:
884 arg_confirm_spawn = true;
885 break;
886
887 case ARG_SHOW_STATUS:
888
889 if (optarg) {
890 if ((r = parse_boolean(optarg)) < 0) {
891 log_error("Failed to show status boolean %s.", optarg);
892 return r;
893 }
894 arg_show_status = r;
895 } else
896 arg_show_status = true;
897 break;
898 #ifdef HAVE_SYSV_COMPAT
899 case ARG_SYSV_CONSOLE:
900
901 if (optarg) {
902 if ((r = parse_boolean(optarg)) < 0) {
903 log_error("Failed to SysV console boolean %s.", optarg);
904 return r;
905 }
906 arg_sysv_console = r;
907 } else
908 arg_sysv_console = true;
909 break;
910 #endif
911
912 case ARG_DESERIALIZE: {
913 int fd;
914 FILE *f;
915
916 if ((r = safe_atoi(optarg, &fd)) < 0 || fd < 0) {
917 log_error("Failed to parse deserialize option %s.", optarg);
918 return r;
919 }
920
921 if (!(f = fdopen(fd, "r"))) {
922 log_error("Failed to open serialization fd: %m");
923 return r;
924 }
925
926 if (serialization)
927 fclose(serialization);
928
929 serialization = f;
930
931 break;
932 }
933
934 case ARG_INTROSPECT: {
935 const char * const * i = NULL;
936
937 for (i = bus_interface_table; *i; i += 2)
938 if (!optarg || streq(i[0], optarg)) {
939 fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
940 "<node>\n", stdout);
941 fputs(i[1], stdout);
942 fputs("</node>\n", stdout);
943
944 if (optarg)
945 break;
946 }
947
948 if (!i[0] && optarg)
949 log_error("Unknown interface %s.", optarg);
950
951 arg_action = ACTION_DONE;
952 break;
953 }
954
955 case 'h':
956 arg_action = ACTION_HELP;
957 break;
958
959 case 'D':
960 log_set_max_level(LOG_DEBUG);
961 break;
962
963 case 'b':
964 case 's':
965 case 'z':
966 /* Just to eat away the sysvinit kernel
967 * cmdline args without getopt() error
968 * messages that we'll parse in
969 * parse_proc_cmdline_word() or ignore. */
970
971 case '?':
972 default:
973 if (getpid() != 1) {
974 log_error("Unknown option code %c", c);
975 return -EINVAL;
976 }
977
978 break;
979 }
980
981 if (optind < argc && getpid() != 1) {
982 /* Hmm, when we aren't run as init system
983 * let's complain about excess arguments */
984
985 log_error("Excess arguments.");
986 return -EINVAL;
987 }
988
989 if (detect_container(NULL) > 0) {
990 char **a;
991
992 /* All /proc/cmdline arguments the kernel didn't
993 * understand it passed to us. We're not really
994 * interested in that usually since /proc/cmdline is
995 * more interesting and complete. With one exception:
996 * if we are run in a container /proc/cmdline is not
997 * relevant for the container, hence we rely on argv[]
998 * instead. */
999
1000 for (a = argv; a < argv + argc; a++)
1001 if ((r = parse_proc_cmdline_word(*a)) < 0)
1002 return r;
1003 }
1004
1005 return 0;
1006 }
1007
1008 static int help(void) {
1009
1010 printf("%s [OPTIONS...]\n\n"
1011 "Starts up and maintains the system or user services.\n\n"
1012 " -h --help Show this help\n"
1013 " --test Determine startup sequence, dump it and exit\n"
1014 " --dump-configuration-items Dump understood unit configuration items\n"
1015 " --introspect[=INTERFACE] Extract D-Bus interface data\n"
1016 " --unit=UNIT Set default unit\n"
1017 " --system Run a system instance, even if PID != 1\n"
1018 " --user Run a user instance\n"
1019 " --dump-core Dump core on crash\n"
1020 " --crash-shell Run shell on crash\n"
1021 " --confirm-spawn Ask for confirmation when spawning processes\n"
1022 " --show-status[=0|1] Show status updates on the console during bootup\n"
1023 #ifdef HAVE_SYSV_COMPAT
1024 " --sysv-console[=0|1] Connect output of SysV scripts to console\n"
1025 #endif
1026 " --log-target=TARGET Set log target (console, journal, syslog, kmsg, journal-or-kmsg, syslog-or-kmsg, null)\n"
1027 " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n"
1028 " --log-color[=0|1] Highlight important log messages\n"
1029 " --log-location[=0|1] Include code location in log messages\n"
1030 " --default-standard-output= Set default standard output for services\n"
1031 " --default-standard-error= Set default standard error output for services\n",
1032 program_invocation_short_name);
1033
1034 return 0;
1035 }
1036
1037 static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds) {
1038 FILE *f = NULL;
1039 FDSet *fds = NULL;
1040 int r;
1041
1042 assert(m);
1043 assert(_f);
1044 assert(_fds);
1045
1046 /* Make sure nothing is really destructed when we shut down */
1047 m->n_reloading ++;
1048
1049 if ((r = manager_open_serialization(m, &f)) < 0) {
1050 log_error("Failed to create serialization file: %s", strerror(-r));
1051 goto fail;
1052 }
1053
1054 if (!(fds = fdset_new())) {
1055 r = -ENOMEM;
1056 log_error("Failed to allocate fd set: %s", strerror(-r));
1057 goto fail;
1058 }
1059
1060 if ((r = manager_serialize(m, f, fds)) < 0) {
1061 log_error("Failed to serialize state: %s", strerror(-r));
1062 goto fail;
1063 }
1064
1065 if (fseeko(f, 0, SEEK_SET) < 0) {
1066 log_error("Failed to rewind serialization fd: %m");
1067 goto fail;
1068 }
1069
1070 if ((r = fd_cloexec(fileno(f), false)) < 0) {
1071 log_error("Failed to disable O_CLOEXEC for serialization: %s", strerror(-r));
1072 goto fail;
1073 }
1074
1075 if ((r = fdset_cloexec(fds, false)) < 0) {
1076 log_error("Failed to disable O_CLOEXEC for serialization fds: %s", strerror(-r));
1077 goto fail;
1078 }
1079
1080 *_f = f;
1081 *_fds = fds;
1082
1083 return 0;
1084
1085 fail:
1086 fdset_free(fds);
1087
1088 if (f)
1089 fclose(f);
1090
1091 return r;
1092 }
1093
1094 static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
1095 const char *e;
1096 unsigned long long a, b;
1097
1098 assert(t);
1099
1100 e = getenv("RD_TIMESTAMP");
1101 if (!e)
1102 return NULL;
1103
1104 if (sscanf(e, "%llu %llu", &a, &b) != 2)
1105 return NULL;
1106
1107 t->realtime = (usec_t) a;
1108 t->monotonic = (usec_t) b;
1109
1110 return t;
1111 }
1112
1113 static void test_mtab(void) {
1114 char *p;
1115
1116 /* Check that /etc/mtab is a symlink */
1117
1118 if (readlink_malloc("/etc/mtab", &p) >= 0) {
1119 bool b;
1120
1121 b = streq(p, "/proc/self/mounts") || streq(p, "/proc/mounts");
1122 free(p);
1123
1124 if (b)
1125 return;
1126 }
1127
1128 log_warning("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. "
1129 "This is not supported anymore. "
1130 "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
1131 }
1132
1133 static void test_usr(void) {
1134
1135 /* Check that /usr is not a separate fs */
1136
1137 if (dir_is_empty("/usr") <= 0)
1138 return;
1139
1140 log_warning("/usr appears to be on its own filesytem and is not already mounted. This is not a supported setup. "
1141 "Some things will probably break (sometimes even silently) in mysterious ways. "
1142 "Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information.");
1143 }
1144
1145 static void test_cgroups(void) {
1146
1147 if (access("/proc/cgroups", F_OK) >= 0)
1148 return;
1149
1150 log_warning("CONFIG_CGROUPS was not set when your kernel was compiled. "
1151 "Systems without control groups are not supported. "
1152 "We will now sleep for 10s, and then continue boot-up. "
1153 "Expect breakage and please do not file bugs. "
1154 "Instead fix your kernel and enable CONFIG_CGROUPS. "
1155 "Consult http://0pointer.de/blog/projects/cgroups-vs-cgroups.html for more information.");
1156
1157 sleep(10);
1158 }
1159
1160 int main(int argc, char *argv[]) {
1161 Manager *m = NULL;
1162 int r, retval = EXIT_FAILURE;
1163 usec_t before_startup, after_startup;
1164 char timespan[FORMAT_TIMESPAN_MAX];
1165 FDSet *fds = NULL;
1166 bool reexecute = false;
1167 const char *shutdown_verb = NULL;
1168 dual_timestamp initrd_timestamp = { 0ULL, 0ULL };
1169 static char systemd[] = "systemd";
1170 bool is_reexec = false;
1171 int j;
1172 bool loaded_policy = false;
1173 bool arm_reboot_watchdog = false;
1174
1175 #ifdef HAVE_SYSV_COMPAT
1176 if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
1177 /* This is compatibility support for SysV, where
1178 * calling init as a user is identical to telinit. */
1179
1180 errno = -ENOENT;
1181 execv(SYSTEMCTL_BINARY_PATH, argv);
1182 log_error("Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
1183 return 1;
1184 }
1185 #endif
1186
1187 /* Determine if this is a reexecution or normal bootup. We do
1188 * the full command line parsing much later, so let's just
1189 * have a quick peek here. */
1190
1191 for (j = 1; j < argc; j++)
1192 if (streq(argv[j], "--deserialize")) {
1193 is_reexec = true;
1194 break;
1195 }
1196
1197 /* If we get started via the /sbin/init symlink then we are
1198 called 'init'. After a subsequent reexecution we are then
1199 called 'systemd'. That is confusing, hence let's call us
1200 systemd right-away. */
1201 program_invocation_short_name = systemd;
1202 prctl(PR_SET_NAME, systemd);
1203
1204 saved_argv = argv;
1205 saved_argc = argc;
1206
1207 log_show_color(isatty(STDERR_FILENO) > 0);
1208 log_show_location(false);
1209 log_set_max_level(LOG_INFO);
1210
1211 if (getpid() == 1) {
1212 arg_running_as = MANAGER_SYSTEM;
1213 log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_CONSOLE : LOG_TARGET_JOURNAL_OR_KMSG);
1214
1215 if (!is_reexec) {
1216 if (selinux_setup(&loaded_policy) < 0)
1217 goto finish;
1218 if (ima_setup() < 0)
1219 goto finish;
1220 }
1221
1222 log_open();
1223
1224 if (label_init() < 0)
1225 goto finish;
1226
1227 if (!is_reexec)
1228 if (hwclock_is_localtime() > 0) {
1229 int min;
1230
1231 r = hwclock_apply_localtime_delta(&min);
1232 if (r < 0)
1233 log_error("Failed to apply local time delta, ignoring: %s", strerror(-r));
1234 else
1235 log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
1236 }
1237
1238 } else {
1239 arg_running_as = MANAGER_USER;
1240 log_set_target(LOG_TARGET_AUTO);
1241 log_open();
1242 }
1243
1244 /* Initialize default unit */
1245 if (set_default_unit(SPECIAL_DEFAULT_TARGET) < 0)
1246 goto finish;
1247
1248 /* By default, mount "cpu" and "cpuacct" together */
1249 arg_join_controllers = new(char**, 2);
1250 if (!arg_join_controllers)
1251 goto finish;
1252
1253 arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
1254 arg_join_controllers[1] = NULL;
1255
1256 if (!arg_join_controllers[0])
1257 goto finish;
1258
1259 /* Mount /proc, /sys and friends, so that /proc/cmdline and
1260 * /proc/$PID/fd is available. */
1261 if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
1262 r = mount_setup(loaded_policy);
1263 if (r < 0)
1264 goto finish;
1265 }
1266
1267 /* Reset all signal handlers. */
1268 assert_se(reset_all_signal_handlers() == 0);
1269
1270 /* If we are init, we can block sigkill. Yay. */
1271 ignore_signals(SIGNALS_IGNORE, -1);
1272
1273 if (parse_config_file() < 0)
1274 goto finish;
1275
1276 if (arg_running_as == MANAGER_SYSTEM)
1277 if (parse_proc_cmdline() < 0)
1278 goto finish;
1279
1280 log_parse_environment();
1281
1282 if (parse_argv(argc, argv) < 0)
1283 goto finish;
1284
1285 if (arg_action == ACTION_TEST && geteuid() == 0) {
1286 log_error("Don't run test mode as root.");
1287 goto finish;
1288 }
1289
1290 if (arg_running_as == MANAGER_SYSTEM &&
1291 arg_action == ACTION_RUN &&
1292 running_in_chroot() > 0) {
1293 log_error("Cannot be run in a chroot() environment.");
1294 goto finish;
1295 }
1296
1297 if (arg_action == ACTION_HELP) {
1298 retval = help();
1299 goto finish;
1300 } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) {
1301 unit_dump_config_items(stdout);
1302 retval = EXIT_SUCCESS;
1303 goto finish;
1304 } else if (arg_action == ACTION_DONE) {
1305 retval = EXIT_SUCCESS;
1306 goto finish;
1307 }
1308
1309 assert_se(arg_action == ACTION_RUN || arg_action == ACTION_TEST);
1310
1311 /* Close logging fds, in order not to confuse fdset below */
1312 log_close();
1313
1314 /* Remember open file descriptors for later deserialization */
1315 if (serialization) {
1316 r = fdset_new_fill(&fds);
1317 if (r < 0) {
1318 log_error("Failed to allocate fd set: %s", strerror(-r));
1319 goto finish;
1320 }
1321
1322 assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
1323 } else
1324 close_all_fds(NULL, 0);
1325
1326 /* Set up PATH unless it is already set */
1327 setenv("PATH",
1328 #ifdef HAVE_SPLIT_USR
1329 "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
1330 #else
1331 "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
1332 #endif
1333 arg_running_as == MANAGER_SYSTEM);
1334
1335 if (arg_running_as == MANAGER_SYSTEM) {
1336 /* Parse the data passed to us. We leave this
1337 * variables set, but the manager later on will not
1338 * pass them on to our children. */
1339 parse_initrd_timestamp(&initrd_timestamp);
1340
1341 /* Unset some environment variables passed in from the
1342 * kernel that don't really make sense for us. */
1343 unsetenv("HOME");
1344 unsetenv("TERM");
1345
1346 /* When we are invoked by a shell, these might be set,
1347 * but make little sense to pass on */
1348 unsetenv("PWD");
1349 unsetenv("SHLVL");
1350 unsetenv("_");
1351
1352 /* All other variables are left as is, so that clients
1353 * can still read them via /proc/1/environ */
1354 }
1355
1356 /* Move out of the way, so that we won't block unmounts */
1357 assert_se(chdir("/") == 0);
1358
1359 if (arg_running_as == MANAGER_SYSTEM) {
1360 /* Become a session leader if we aren't one yet. */
1361 setsid();
1362
1363 /* Disable the umask logic */
1364 umask(0);
1365 }
1366
1367 /* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
1368 dbus_connection_set_change_sigpipe(FALSE);
1369
1370 /* Reset the console, but only if this is really init and we
1371 * are freshly booted */
1372 if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN) {
1373 console_setup(getpid() == 1 && !is_reexec);
1374 make_null_stdio();
1375 }
1376
1377 /* Open the logging devices, if possible and necessary */
1378 log_open();
1379
1380 /* Make sure we leave a core dump without panicing the
1381 * kernel. */
1382 if (getpid() == 1)
1383 install_crash_handler();
1384
1385 if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
1386 r = mount_cgroup_controllers(arg_join_controllers);
1387 if (r < 0)
1388 goto finish;
1389 }
1390
1391 log_full(arg_running_as == MANAGER_SYSTEM ? LOG_INFO : LOG_DEBUG,
1392 PACKAGE_STRING " running in %s mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")", manager_running_as_to_string(arg_running_as));
1393
1394 if (arg_running_as == MANAGER_SYSTEM && !is_reexec) {
1395 locale_setup();
1396
1397 if (arg_show_status || plymouth_running())
1398 status_welcome();
1399
1400 kmod_setup();
1401 hostname_setup();
1402 machine_id_setup();
1403 loopback_setup();
1404
1405 test_mtab();
1406 test_usr();
1407 test_cgroups();
1408 }
1409
1410 if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0)
1411 watchdog_set_timeout(&arg_runtime_watchdog);
1412
1413 r = manager_new(arg_running_as, &m);
1414 if (r < 0) {
1415 log_error("Failed to allocate manager object: %s", strerror(-r));
1416 goto finish;
1417 }
1418
1419 m->confirm_spawn = arg_confirm_spawn;
1420 #ifdef HAVE_SYSV_COMPAT
1421 m->sysv_console = arg_sysv_console;
1422 #endif
1423 m->mount_auto = arg_mount_auto;
1424 m->swap_auto = arg_swap_auto;
1425 m->default_std_output = arg_default_std_output;
1426 m->default_std_error = arg_default_std_error;
1427 m->runtime_watchdog = arg_runtime_watchdog;
1428 m->shutdown_watchdog = arg_shutdown_watchdog;
1429
1430 if (dual_timestamp_is_set(&initrd_timestamp))
1431 m->initrd_timestamp = initrd_timestamp;
1432
1433 if (arg_default_controllers)
1434 manager_set_default_controllers(m, arg_default_controllers);
1435
1436 manager_set_show_status(m, arg_show_status);
1437
1438 before_startup = now(CLOCK_MONOTONIC);
1439
1440 r = manager_startup(m, serialization, fds);
1441 if (r < 0)
1442 log_error("Failed to fully start up daemon: %s", strerror(-r));
1443
1444 if (fds) {
1445 /* This will close all file descriptors that were opened, but
1446 * not claimed by any unit. */
1447
1448 fdset_free(fds);
1449 fds = NULL;
1450 }
1451
1452 if (serialization) {
1453 fclose(serialization);
1454 serialization = NULL;
1455 } else {
1456 DBusError error;
1457 Unit *target = NULL;
1458 Job *default_unit_job;
1459
1460 dbus_error_init(&error);
1461
1462 log_debug("Activating default unit: %s", arg_default_unit);
1463
1464 r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
1465 if (r < 0) {
1466 log_error("Failed to load default target: %s", bus_error(&error, r));
1467 dbus_error_free(&error);
1468 } else if (target->load_state == UNIT_ERROR)
1469 log_error("Failed to load default target: %s", strerror(-target->load_error));
1470 else if (target->load_state == UNIT_MASKED)
1471 log_error("Default target masked.");
1472
1473 if (!target || target->load_state != UNIT_LOADED) {
1474 log_info("Trying to load rescue target...");
1475
1476 r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
1477 if (r < 0) {
1478 log_error("Failed to load rescue target: %s", bus_error(&error, r));
1479 dbus_error_free(&error);
1480 goto finish;
1481 } else if (target->load_state == UNIT_ERROR) {
1482 log_error("Failed to load rescue target: %s", strerror(-target->load_error));
1483 goto finish;
1484 } else if (target->load_state == UNIT_MASKED) {
1485 log_error("Rescue target masked.");
1486 goto finish;
1487 }
1488 }
1489
1490 assert(target->load_state == UNIT_LOADED);
1491
1492 if (arg_action == ACTION_TEST) {
1493 printf("-> By units:\n");
1494 manager_dump_units(m, stdout, "\t");
1495 }
1496
1497 r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
1498 if (r < 0) {
1499 log_error("Failed to start default target: %s", bus_error(&error, r));
1500 dbus_error_free(&error);
1501 goto finish;
1502 }
1503 m->default_unit_job_id = default_unit_job->id;
1504
1505 after_startup = now(CLOCK_MONOTONIC);
1506 log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG,
1507 "Loaded units and determined initial transaction in %s.",
1508 format_timespan(timespan, sizeof(timespan), after_startup - before_startup));
1509
1510 if (arg_action == ACTION_TEST) {
1511 printf("-> By jobs:\n");
1512 manager_dump_jobs(m, stdout, "\t");
1513 retval = EXIT_SUCCESS;
1514 goto finish;
1515 }
1516 }
1517
1518 for (;;) {
1519 r = manager_loop(m);
1520 if (r < 0) {
1521 log_error("Failed to run mainloop: %s", strerror(-r));
1522 goto finish;
1523 }
1524
1525 switch (m->exit_code) {
1526
1527 case MANAGER_EXIT:
1528 retval = EXIT_SUCCESS;
1529 log_debug("Exit.");
1530 goto finish;
1531
1532 case MANAGER_RELOAD:
1533 log_info("Reloading.");
1534 r = manager_reload(m);
1535 if (r < 0)
1536 log_error("Failed to reload: %s", strerror(-r));
1537 break;
1538
1539 case MANAGER_REEXECUTE:
1540 if (prepare_reexecute(m, &serialization, &fds) < 0)
1541 goto finish;
1542
1543 reexecute = true;
1544 log_notice("Reexecuting.");
1545 goto finish;
1546
1547 case MANAGER_REBOOT:
1548 case MANAGER_POWEROFF:
1549 case MANAGER_HALT:
1550 case MANAGER_KEXEC: {
1551 static const char * const table[_MANAGER_EXIT_CODE_MAX] = {
1552 [MANAGER_REBOOT] = "reboot",
1553 [MANAGER_POWEROFF] = "poweroff",
1554 [MANAGER_HALT] = "halt",
1555 [MANAGER_KEXEC] = "kexec"
1556 };
1557
1558 assert_se(shutdown_verb = table[m->exit_code]);
1559 arm_reboot_watchdog = m->exit_code == MANAGER_REBOOT;
1560
1561 log_notice("Shutting down.");
1562 goto finish;
1563 }
1564
1565 default:
1566 assert_not_reached("Unknown exit code.");
1567 }
1568 }
1569
1570 finish:
1571 if (m)
1572 manager_free(m);
1573
1574 free(arg_default_unit);
1575 strv_free(arg_default_controllers);
1576 free_join_controllers();
1577
1578 dbus_shutdown();
1579
1580 label_finish();
1581
1582 if (reexecute) {
1583 const char *args[15];
1584 unsigned i = 0;
1585 char sfd[16];
1586
1587 assert(serialization);
1588 assert(fds);
1589
1590 args[i++] = SYSTEMD_BINARY_PATH;
1591
1592 args[i++] = "--log-level";
1593 args[i++] = log_level_to_string(log_get_max_level());
1594
1595 args[i++] = "--log-target";
1596 args[i++] = log_target_to_string(log_get_target());
1597
1598 if (arg_running_as == MANAGER_SYSTEM)
1599 args[i++] = "--system";
1600 else
1601 args[i++] = "--user";
1602
1603 if (arg_dump_core)
1604 args[i++] = "--dump-core";
1605
1606 if (arg_crash_shell)
1607 args[i++] = "--crash-shell";
1608
1609 if (arg_confirm_spawn)
1610 args[i++] = "--confirm-spawn";
1611
1612 if (arg_show_status)
1613 args[i++] = "--show-status=1";
1614 else
1615 args[i++] = "--show-status=0";
1616
1617 #ifdef HAVE_SYSV_COMPAT
1618 if (arg_sysv_console)
1619 args[i++] = "--sysv-console=1";
1620 else
1621 args[i++] = "--sysv-console=0";
1622 #endif
1623
1624 snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
1625 char_array_0(sfd);
1626
1627 args[i++] = "--deserialize";
1628 args[i++] = sfd;
1629
1630 args[i++] = NULL;
1631
1632 assert(i <= ELEMENTSOF(args));
1633
1634 /* Close and disarm the watchdog, so that the new
1635 * instance can reinitialize it, but doesn't get
1636 * rebooted while we do that */
1637 watchdog_close(true);
1638
1639 execv(args[0], (char* const*) args);
1640
1641 log_error("Failed to reexecute: %m");
1642 }
1643
1644 if (serialization)
1645 fclose(serialization);
1646
1647 if (fds)
1648 fdset_free(fds);
1649
1650 if (shutdown_verb) {
1651 char e[32];
1652
1653 const char * command_line[] = {
1654 SYSTEMD_SHUTDOWN_BINARY_PATH,
1655 shutdown_verb,
1656 NULL
1657 };
1658 const char * env_block[] = {
1659 NULL,
1660 NULL
1661 };
1662
1663 if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
1664 /* If we reboot let's set the shutdown
1665 * watchdog and tell the shutdown binary to
1666 * repeatedly ping it */
1667 watchdog_set_timeout(&arg_shutdown_watchdog);
1668 watchdog_close(false);
1669
1670 /* Tell the binary how often to ping */
1671 snprintf(e, sizeof(e), "WATCHDOG_USEC=%llu", (unsigned long long) arg_shutdown_watchdog);
1672 char_array_0(e);
1673 env_block[0] = e;
1674 } else
1675 watchdog_close(true);
1676
1677 execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, (char**) env_block);
1678 log_error("Failed to execute shutdown binary, freezing: %m");
1679 }
1680
1681 if (getpid() == 1)
1682 freeze();
1683
1684 return retval;
1685 }