1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
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.
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.
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/>.
22 #include <dbus/dbus.h>
28 #include <sys/types.h>
34 #include <sys/prctl.h>
35 #include <sys/mount.h>
39 #include "load-fragment.h"
42 #include "conf-parser.h"
43 #include "bus-errors.h"
51 #include "path-util.h"
52 #include "switch-root.h"
54 #include "mount-setup.h"
55 #include "loopback-setup.h"
56 #include "kmod-setup.h"
57 #include "hostname-setup.h"
58 #include "machine-id-setup.h"
59 #include "locale-setup.h"
61 #include "selinux-setup.h"
62 #include "ima-setup.h"
68 ACTION_DUMP_CONFIGURATION_ITEMS,
70 } arg_action = ACTION_RUN;
72 static char *arg_default_unit = NULL;
73 static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
75 static bool arg_dump_core = true;
76 static bool arg_crash_shell = false;
77 static int arg_crash_chvt = -1;
78 static bool arg_confirm_spawn = false;
79 static bool arg_show_status = true;
80 #ifdef HAVE_SYSV_COMPAT
81 static bool arg_sysv_console = true;
83 static char **arg_default_controllers = NULL;
84 static char ***arg_join_controllers = NULL;
85 static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
86 static ExecOutput arg_default_std_error = EXEC_OUTPUT_INHERIT;
87 static usec_t arg_runtime_watchdog = 0;
88 static usec_t arg_shutdown_watchdog = 10 * USEC_PER_MINUTE;
90 static FILE* serialization = NULL;
92 static void nop_handler(int sig) {
95 _noreturn_ static void crash(int sig) {
98 log_error("Caught <%s>, not dumping core.", signal_to_string(sig));
103 /* We want to wait for the core process, hence let's enable SIGCHLD */
105 sa.sa_handler = nop_handler;
106 sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
107 assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
109 if ((pid = fork()) < 0)
110 log_error("Caught <%s>, cannot fork for core dump: %s", signal_to_string(sig), strerror(errno));
115 /* Enable default signal handler for core dump */
117 sa.sa_handler = SIG_DFL;
118 assert_se(sigaction(sig, &sa, NULL) == 0);
120 /* Don't limit the core dump size */
122 rl.rlim_cur = RLIM_INFINITY;
123 rl.rlim_max = RLIM_INFINITY;
124 setrlimit(RLIMIT_CORE, &rl);
126 /* Just to be sure... */
127 assert_se(chdir("/") == 0);
129 /* Raise the signal again */
132 assert_not_reached("We shouldn't be here...");
139 /* Order things nicely. */
140 if ((r = wait_for_terminate(pid, &status)) < 0)
141 log_error("Caught <%s>, waitpid() failed: %s", signal_to_string(sig), strerror(-r));
142 else if (status.si_code != CLD_DUMPED)
143 log_error("Caught <%s>, core dump failed.", signal_to_string(sig));
145 log_error("Caught <%s>, dumped core as pid %lu.", signal_to_string(sig), (unsigned long) pid);
150 chvt(arg_crash_chvt);
152 if (arg_crash_shell) {
156 log_info("Executing crash shell in 10s...");
159 /* Let the kernel reap children for us */
161 sa.sa_handler = SIG_IGN;
162 sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART;
163 assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
165 if ((pid = fork()) < 0)
166 log_error("Failed to fork off crash shell: %s", strerror(errno));
170 if ((fd = acquire_terminal("/dev/console", false, true, true)) < 0)
171 log_error("Failed to acquire terminal: %s", strerror(-fd));
172 else if ((r = make_stdio(fd)) < 0)
173 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
175 execl("/bin/sh", "/bin/sh", NULL);
177 log_error("execl() failed: %s", strerror(errno));
181 log_info("Successfully spawned crash shell as pid %lu.", (unsigned long) pid);
184 log_info("Freezing execution.");
188 static void install_crash_handler(void) {
193 sa.sa_handler = crash;
194 sa.sa_flags = SA_NODEFER;
196 sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
199 static int console_setup(bool do_reset) {
202 /* If we are init, we connect stdin/stdout/stderr to /dev/null
203 * and make sure we don't have a controlling tty. */
210 tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC);
212 log_error("Failed to open /dev/console: %s", strerror(-tty_fd));
216 /* We don't want to force text mode.
217 * plymouth may be showing pictures already from initrd. */
218 r = reset_terminal_fd(tty_fd, false);
220 log_error("Failed to reset /dev/console: %s", strerror(-r));
222 close_nointr_nofail(tty_fd);
226 static int set_default_unit(const char *u) {
231 if (!(c = strdup(u)))
234 free(arg_default_unit);
235 arg_default_unit = c;
239 static int parse_proc_cmdline_word(const char *word) {
241 static const char * const rlmap[] = {
242 "emergency", SPECIAL_EMERGENCY_TARGET,
243 "-b", SPECIAL_EMERGENCY_TARGET,
244 "single", SPECIAL_RESCUE_TARGET,
245 "-s", SPECIAL_RESCUE_TARGET,
246 "s", SPECIAL_RESCUE_TARGET,
247 "S", SPECIAL_RESCUE_TARGET,
248 "1", SPECIAL_RESCUE_TARGET,
249 "2", SPECIAL_RUNLEVEL2_TARGET,
250 "3", SPECIAL_RUNLEVEL3_TARGET,
251 "4", SPECIAL_RUNLEVEL4_TARGET,
252 "5", SPECIAL_RUNLEVEL5_TARGET,
257 if (startswith(word, "systemd.unit="))
258 return set_default_unit(word + 13);
260 else if (startswith(word, "systemd.log_target=")) {
262 if (log_set_target_from_string(word + 19) < 0)
263 log_warning("Failed to parse log target %s. Ignoring.", word + 19);
265 } else if (startswith(word, "systemd.log_level=")) {
267 if (log_set_max_level_from_string(word + 18) < 0)
268 log_warning("Failed to parse log level %s. Ignoring.", word + 18);
270 } else if (startswith(word, "systemd.log_color=")) {
272 if (log_show_color_from_string(word + 18) < 0)
273 log_warning("Failed to parse log color setting %s. Ignoring.", word + 18);
275 } else if (startswith(word, "systemd.log_location=")) {
277 if (log_show_location_from_string(word + 21) < 0)
278 log_warning("Failed to parse log location setting %s. Ignoring.", word + 21);
280 } else if (startswith(word, "systemd.dump_core=")) {
283 if ((r = parse_boolean(word + 18)) < 0)
284 log_warning("Failed to parse dump core switch %s. Ignoring.", word + 18);
288 } else if (startswith(word, "systemd.crash_shell=")) {
291 if ((r = parse_boolean(word + 20)) < 0)
292 log_warning("Failed to parse crash shell switch %s. Ignoring.", word + 20);
296 } else if (startswith(word, "systemd.confirm_spawn=")) {
299 if ((r = parse_boolean(word + 22)) < 0)
300 log_warning("Failed to parse confirm spawn switch %s. Ignoring.", word + 22);
302 arg_confirm_spawn = r;
304 } else if (startswith(word, "systemd.crash_chvt=")) {
307 if (safe_atoi(word + 19, &k) < 0)
308 log_warning("Failed to parse crash chvt switch %s. Ignoring.", word + 19);
312 } else if (startswith(word, "systemd.show_status=")) {
315 if ((r = parse_boolean(word + 20)) < 0)
316 log_warning("Failed to parse show status switch %s. Ignoring.", word + 20);
319 } else if (startswith(word, "systemd.default_standard_output=")) {
322 if ((r = exec_output_from_string(word + 32)) < 0)
323 log_warning("Failed to parse default standard output switch %s. Ignoring.", word + 32);
325 arg_default_std_output = r;
326 } else if (startswith(word, "systemd.default_standard_error=")) {
329 if ((r = exec_output_from_string(word + 31)) < 0)
330 log_warning("Failed to parse default standard error switch %s. Ignoring.", word + 31);
332 arg_default_std_error = r;
333 } else if (startswith(word, "systemd.setenv=")) {
337 cenv = strdup(word + 15);
341 eq = strchr(cenv, '=');
345 log_warning("unsetenv failed %s. Ignoring.", strerror(errno));
348 r = setenv(cenv, eq + 1, 1);
350 log_warning("setenv failed %s. Ignoring.", strerror(errno));
353 #ifdef HAVE_SYSV_COMPAT
354 } else if (startswith(word, "systemd.sysv_console=")) {
357 if ((r = parse_boolean(word + 21)) < 0)
358 log_warning("Failed to parse SysV console switch %s. Ignoring.", word + 20);
360 arg_sysv_console = r;
363 } else if (startswith(word, "systemd.")) {
365 log_warning("Unknown kernel switch %s. Ignoring.", word);
367 log_info("Supported kernel switches:\n"
368 "systemd.unit=UNIT Default unit to start\n"
369 "systemd.dump_core=0|1 Dump core on crash\n"
370 "systemd.crash_shell=0|1 Run shell on crash\n"
371 "systemd.crash_chvt=N Change to VT #N on crash\n"
372 "systemd.confirm_spawn=0|1 Confirm every process spawn\n"
373 "systemd.show_status=0|1 Show status updates on the console during bootup\n"
374 #ifdef HAVE_SYSV_COMPAT
375 "systemd.sysv_console=0|1 Connect output of SysV scripts to console\n"
377 "systemd.log_target=console|kmsg|journal|journal-or-kmsg|syslog|syslog-or-kmsg|null\n"
379 "systemd.log_level=LEVEL Log level\n"
380 "systemd.log_color=0|1 Highlight important log messages\n"
381 "systemd.log_location=0|1 Include code location in log messages\n"
382 "systemd.default_standard_output=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
383 " Set default log output for services\n"
384 "systemd.default_standard_error=null|tty|syslog|syslog+console|kmsg|kmsg+console|journal|journal+console\n"
385 " Set default log error output for services\n");
387 } else if (streq(word, "quiet")) {
388 arg_show_status = false;
389 #ifdef HAVE_SYSV_COMPAT
390 arg_sysv_console = false;
395 /* SysV compatibility */
396 for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
397 if (streq(word, rlmap[i]))
398 return set_default_unit(rlmap[i+1]);
404 static int config_parse_level2(
405 const char *filename,
418 log_set_max_level_from_string(rvalue);
422 static int config_parse_target(
423 const char *filename,
436 log_set_target_from_string(rvalue);
440 static int config_parse_color(
441 const char *filename,
454 log_show_color_from_string(rvalue);
458 static int config_parse_location(
459 const char *filename,
472 log_show_location_from_string(rvalue);
476 static int config_parse_cpu_affinity2(
477 const char *filename,
496 FOREACH_WORD_QUOTED(w, l, rvalue, state) {
501 if (!(t = strndup(w, l)))
504 r = safe_atou(t, &cpu);
508 if (!(c = cpu_set_malloc(&ncpus)))
511 if (r < 0 || cpu >= ncpus) {
512 log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue);
517 CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c);
521 if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0)
522 log_warning("Failed to set CPU affinity: %m");
530 static void strv_free_free(char ***l) {
542 static void free_join_controllers(void) {
543 if (!arg_join_controllers)
546 strv_free_free(arg_join_controllers);
547 arg_join_controllers = NULL;
550 static int config_parse_join_controllers(
551 const char *filename,
568 free_join_controllers();
570 FOREACH_WORD_QUOTED(w, length, rvalue, state) {
573 s = strndup(w, length);
577 l = strv_split(s, ",");
582 if (strv_length(l) <= 1) {
587 if (!arg_join_controllers) {
588 arg_join_controllers = new(char**, 2);
589 if (!arg_join_controllers) {
594 arg_join_controllers[0] = l;
595 arg_join_controllers[1] = NULL;
602 t = new0(char**, n+2);
610 for (a = arg_join_controllers; *a; a++) {
612 if (strv_overlap(*a, l)) {
615 c = strv_merge(*a, l);
638 t[n++] = strv_uniq(l);
640 strv_free_free(arg_join_controllers);
641 arg_join_controllers = t;
648 static int parse_config_file(void) {
650 const ConfigTableItem items[] = {
651 { "Manager", "LogLevel", config_parse_level2, 0, NULL },
652 { "Manager", "LogTarget", config_parse_target, 0, NULL },
653 { "Manager", "LogColor", config_parse_color, 0, NULL },
654 { "Manager", "LogLocation", config_parse_location, 0, NULL },
655 { "Manager", "DumpCore", config_parse_bool, 0, &arg_dump_core },
656 { "Manager", "CrashShell", config_parse_bool, 0, &arg_crash_shell },
657 { "Manager", "ShowStatus", config_parse_bool, 0, &arg_show_status },
658 #ifdef HAVE_SYSV_COMPAT
659 { "Manager", "SysVConsole", config_parse_bool, 0, &arg_sysv_console },
661 { "Manager", "CrashChVT", config_parse_int, 0, &arg_crash_chvt },
662 { "Manager", "CPUAffinity", config_parse_cpu_affinity2, 0, NULL },
663 { "Manager", "DefaultControllers", config_parse_strv, 0, &arg_default_controllers },
664 { "Manager", "DefaultStandardOutput", config_parse_output, 0, &arg_default_std_output },
665 { "Manager", "DefaultStandardError", config_parse_output, 0, &arg_default_std_error },
666 { "Manager", "JoinControllers", config_parse_join_controllers, 0, &arg_join_controllers },
667 { "Manager", "RuntimeWatchdogSec", config_parse_usec, 0, &arg_runtime_watchdog },
668 { "Manager", "ShutdownWatchdogSec", config_parse_usec, 0, &arg_shutdown_watchdog },
669 { NULL, NULL, NULL, 0, NULL }
676 fn = arg_running_as == MANAGER_SYSTEM ? SYSTEM_CONFIG_FILE : USER_CONFIG_FILE;
682 log_warning("Failed to open configuration file '%s': %m", fn);
686 r = config_parse(fn, f, "Manager\0", config_item_table_lookup, (void*) items, false, NULL);
688 log_warning("Failed to parse configuration file: %s", strerror(-r));
695 static int parse_proc_cmdline(void) {
696 char *line, *w, *state;
700 /* Don't read /proc/cmdline if we are in a container, since
701 * that is only relevant for the host system */
702 if (detect_container(NULL) > 0)
705 if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
706 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(-r));
710 FOREACH_WORD_QUOTED(w, l, line, state) {
713 if (!(word = strndup(w, l))) {
718 r = parse_proc_cmdline_word(word);
732 static int parse_argv(int argc, char *argv[]) {
735 ARG_LOG_LEVEL = 0x100,
743 ARG_DUMP_CONFIGURATION_ITEMS,
752 ARG_DEFAULT_STD_OUTPUT,
753 ARG_DEFAULT_STD_ERROR
756 static const struct option options[] = {
757 { "log-level", required_argument, NULL, ARG_LOG_LEVEL },
758 { "log-target", required_argument, NULL, ARG_LOG_TARGET },
759 { "log-color", optional_argument, NULL, ARG_LOG_COLOR },
760 { "log-location", optional_argument, NULL, ARG_LOG_LOCATION },
761 { "unit", required_argument, NULL, ARG_UNIT },
762 { "system", no_argument, NULL, ARG_SYSTEM },
763 { "user", no_argument, NULL, ARG_USER },
764 { "test", no_argument, NULL, ARG_TEST },
765 { "help", no_argument, NULL, 'h' },
766 { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS },
767 { "dump-core", optional_argument, NULL, ARG_DUMP_CORE },
768 { "crash-shell", optional_argument, NULL, ARG_CRASH_SHELL },
769 { "confirm-spawn", optional_argument, NULL, ARG_CONFIRM_SPAWN },
770 { "show-status", optional_argument, NULL, ARG_SHOW_STATUS },
771 #ifdef HAVE_SYSV_COMPAT
772 { "sysv-console", optional_argument, NULL, ARG_SYSV_CONSOLE },
774 { "deserialize", required_argument, NULL, ARG_DESERIALIZE },
775 { "switched-root", no_argument, NULL, ARG_SWITCHED_ROOT },
776 { "introspect", optional_argument, NULL, ARG_INTROSPECT },
777 { "default-standard-output", required_argument, NULL, ARG_DEFAULT_STD_OUTPUT, },
778 { "default-standard-error", required_argument, NULL, ARG_DEFAULT_STD_ERROR, },
790 while ((c = getopt_long(argc, argv, "hDbsz:", options, NULL)) >= 0)
795 if ((r = log_set_max_level_from_string(optarg)) < 0) {
796 log_error("Failed to parse log level %s.", optarg);
804 if ((r = log_set_target_from_string(optarg)) < 0) {
805 log_error("Failed to parse log target %s.", optarg);
814 if ((r = log_show_color_from_string(optarg)) < 0) {
815 log_error("Failed to parse log color setting %s.", optarg);
819 log_show_color(true);
823 case ARG_LOG_LOCATION:
826 if ((r = log_show_location_from_string(optarg)) < 0) {
827 log_error("Failed to parse log location setting %s.", optarg);
831 log_show_location(true);
835 case ARG_DEFAULT_STD_OUTPUT:
837 if ((r = exec_output_from_string(optarg)) < 0) {
838 log_error("Failed to parse default standard output setting %s.", optarg);
841 arg_default_std_output = r;
844 case ARG_DEFAULT_STD_ERROR:
846 if ((r = exec_output_from_string(optarg)) < 0) {
847 log_error("Failed to parse default standard error output setting %s.", optarg);
850 arg_default_std_error = r;
855 if ((r = set_default_unit(optarg)) < 0) {
856 log_error("Failed to set default unit %s: %s", optarg, strerror(-r));
863 arg_running_as = MANAGER_SYSTEM;
867 arg_running_as = MANAGER_USER;
871 arg_action = ACTION_TEST;
874 case ARG_DUMP_CONFIGURATION_ITEMS:
875 arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
879 r = optarg ? parse_boolean(optarg) : 1;
881 log_error("Failed to parse dump core boolean %s.", optarg);
887 case ARG_CRASH_SHELL:
888 r = optarg ? parse_boolean(optarg) : 1;
890 log_error("Failed to parse crash shell boolean %s.", optarg);
896 case ARG_CONFIRM_SPAWN:
897 r = optarg ? parse_boolean(optarg) : 1;
899 log_error("Failed to parse confirm spawn boolean %s.", optarg);
902 arg_confirm_spawn = r;
905 case ARG_SHOW_STATUS:
906 r = optarg ? parse_boolean(optarg) : 1;
908 log_error("Failed to parse show status boolean %s.", optarg);
914 #ifdef HAVE_SYSV_COMPAT
915 case ARG_SYSV_CONSOLE:
916 r = optarg ? parse_boolean(optarg) : 1;
918 log_error("Failed to parse SysV console boolean %s.", optarg);
921 arg_sysv_console = r;
925 case ARG_DESERIALIZE: {
929 if ((r = safe_atoi(optarg, &fd)) < 0 || fd < 0) {
930 log_error("Failed to parse deserialize option %s.", optarg);
934 if (!(f = fdopen(fd, "r"))) {
935 log_error("Failed to open serialization fd: %m");
940 fclose(serialization);
947 case ARG_SWITCHED_ROOT:
948 /* Nothing special yet */
951 case ARG_INTROSPECT: {
952 const char * const * i = NULL;
954 for (i = bus_interface_table; *i; i += 2)
955 if (!optarg || streq(i[0], optarg)) {
956 fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
959 fputs("</node>\n", stdout);
966 log_error("Unknown interface %s.", optarg);
968 arg_action = ACTION_DONE;
973 arg_action = ACTION_HELP;
977 log_set_max_level(LOG_DEBUG);
983 /* Just to eat away the sysvinit kernel
984 * cmdline args without getopt() error
985 * messages that we'll parse in
986 * parse_proc_cmdline_word() or ignore. */
991 log_error("Unknown option code %c", c);
998 if (optind < argc && getpid() != 1) {
999 /* Hmm, when we aren't run as init system
1000 * let's complain about excess arguments */
1002 log_error("Excess arguments.");
1006 if (detect_container(NULL) > 0) {
1009 /* All /proc/cmdline arguments the kernel didn't
1010 * understand it passed to us. We're not really
1011 * interested in that usually since /proc/cmdline is
1012 * more interesting and complete. With one exception:
1013 * if we are run in a container /proc/cmdline is not
1014 * relevant for the container, hence we rely on argv[]
1017 for (a = argv; a < argv + argc; a++)
1018 if ((r = parse_proc_cmdline_word(*a)) < 0)
1025 static int help(void) {
1027 printf("%s [OPTIONS...]\n\n"
1028 "Starts up and maintains the system or user services.\n\n"
1029 " -h --help Show this help\n"
1030 " --test Determine startup sequence, dump it and exit\n"
1031 " --dump-configuration-items Dump understood unit configuration items\n"
1032 " --introspect[=INTERFACE] Extract D-Bus interface data\n"
1033 " --unit=UNIT Set default unit\n"
1034 " --system Run a system instance, even if PID != 1\n"
1035 " --user Run a user instance\n"
1036 " --dump-core[=0|1] Dump core on crash\n"
1037 " --crash-shell[=0|1] Run shell on crash\n"
1038 " --confirm-spawn[=0|1] Ask for confirmation when spawning processes\n"
1039 " --show-status[=0|1] Show status updates on the console during bootup\n"
1040 #ifdef HAVE_SYSV_COMPAT
1041 " --sysv-console[=0|1] Connect output of SysV scripts to console\n"
1043 " --log-target=TARGET Set log target (console, journal, syslog, kmsg, journal-or-kmsg, syslog-or-kmsg, null)\n"
1044 " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n"
1045 " --log-color[=0|1] Highlight important log messages\n"
1046 " --log-location[=0|1] Include code location in log messages\n"
1047 " --default-standard-output= Set default standard output for services\n"
1048 " --default-standard-error= Set default standard error output for services\n",
1049 program_invocation_short_name);
1054 static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds) {
1063 /* Make sure nothing is really destructed when we shut down */
1066 if ((r = manager_open_serialization(m, &f)) < 0) {
1067 log_error("Failed to create serialization file: %s", strerror(-r));
1071 if (!(fds = fdset_new())) {
1073 log_error("Failed to allocate fd set: %s", strerror(-r));
1077 if ((r = manager_serialize(m, f, fds)) < 0) {
1078 log_error("Failed to serialize state: %s", strerror(-r));
1082 if (fseeko(f, 0, SEEK_SET) < 0) {
1083 log_error("Failed to rewind serialization fd: %m");
1087 if ((r = fd_cloexec(fileno(f), false)) < 0) {
1088 log_error("Failed to disable O_CLOEXEC for serialization: %s", strerror(-r));
1092 if ((r = fdset_cloexec(fds, false)) < 0) {
1093 log_error("Failed to disable O_CLOEXEC for serialization fds: %s", strerror(-r));
1111 static struct dual_timestamp* parse_initrd_timestamp(struct dual_timestamp *t) {
1113 unsigned long long a, b;
1117 e = getenv("RD_TIMESTAMP");
1121 if (sscanf(e, "%llu %llu", &a, &b) != 2)
1124 t->realtime = (usec_t) a;
1125 t->monotonic = (usec_t) b;
1130 static void test_mtab(void) {
1133 /* Check that /etc/mtab is a symlink */
1135 if (readlink_malloc("/etc/mtab", &p) >= 0) {
1138 b = streq(p, "/proc/self/mounts") || streq(p, "/proc/mounts");
1145 log_warning("/etc/mtab is not a symlink or not pointing to /proc/self/mounts. "
1146 "This is not supported anymore. "
1147 "Please make sure to replace this file by a symlink to avoid incorrect or misleading mount(8) output.");
1150 static void test_usr(void) {
1152 /* Check that /usr is not a separate fs */
1154 if (dir_is_empty("/usr") <= 0)
1157 log_warning("/usr appears to be on its own filesytem and is not already mounted. This is not a supported setup. "
1158 "Some things will probably break (sometimes even silently) in mysterious ways. "
1159 "Consult http://freedesktop.org/wiki/Software/systemd/separate-usr-is-broken for more information.");
1162 static void test_cgroups(void) {
1164 if (access("/proc/cgroups", F_OK) >= 0)
1167 log_warning("CONFIG_CGROUPS was not set when your kernel was compiled. "
1168 "Systems without control groups are not supported. "
1169 "We will now sleep for 10s, and then continue boot-up. "
1170 "Expect breakage and please do not file bugs. "
1171 "Instead fix your kernel and enable CONFIG_CGROUPS. "
1172 "Consult http://0pointer.de/blog/projects/cgroups-vs-cgroups.html for more information.");
1177 int main(int argc, char *argv[]) {
1179 int r, retval = EXIT_FAILURE;
1180 usec_t before_startup, after_startup;
1181 char timespan[FORMAT_TIMESPAN_MAX];
1183 bool reexecute = false;
1184 const char *shutdown_verb = NULL;
1185 dual_timestamp initrd_timestamp = { 0ULL, 0ULL };
1186 static char systemd[] = "systemd";
1187 bool skip_setup = false;
1189 bool loaded_policy = false;
1190 bool arm_reboot_watchdog = false;
1191 char *switch_root_dir = NULL, *switch_root_init = NULL;
1193 #ifdef HAVE_SYSV_COMPAT
1194 if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
1195 /* This is compatibility support for SysV, where
1196 * calling init as a user is identical to telinit. */
1199 execv(SYSTEMCTL_BINARY_PATH, argv);
1200 log_error("Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
1205 /* Determine if this is a reexecution or normal bootup. We do
1206 * the full command line parsing much later, so let's just
1207 * have a quick peek here. */
1208 for (j = 1; j < argc; j++)
1209 if (streq(argv[j], "--deserialize")) {
1214 /* If we have switched root, do all the special setup
1216 for (j = 1; j < argc; j++)
1217 if (streq(argv[j], "--switched-root")) {
1222 /* If we get started via the /sbin/init symlink then we are
1223 called 'init'. After a subsequent reexecution we are then
1224 called 'systemd'. That is confusing, hence let's call us
1225 systemd right-away. */
1226 program_invocation_short_name = systemd;
1227 prctl(PR_SET_NAME, systemd);
1232 log_show_color(isatty(STDERR_FILENO) > 0);
1233 log_show_location(false);
1234 log_set_max_level(LOG_INFO);
1236 if (getpid() == 1) {
1238 char *rd_timestamp = NULL;
1240 dual_timestamp_get(&initrd_timestamp);
1241 asprintf(&rd_timestamp, "%llu %llu",
1242 (unsigned long long) initrd_timestamp.realtime,
1243 (unsigned long long) initrd_timestamp.monotonic);
1245 setenv("RD_TIMESTAMP", rd_timestamp, 1);
1250 arg_running_as = MANAGER_SYSTEM;
1251 log_set_target(detect_container(NULL) > 0 ? LOG_TARGET_JOURNAL : LOG_TARGET_JOURNAL_OR_KMSG);
1254 if (selinux_setup(&loaded_policy) < 0)
1256 if (ima_setup() < 0)
1262 if (label_init(NULL) < 0)
1266 if (hwclock_is_localtime() > 0) {
1269 r = hwclock_apply_localtime_delta(&min);
1271 log_error("Failed to apply local time delta, ignoring: %s", strerror(-r));
1273 log_info("RTC configured in localtime, applying delta of %i minutes to system time.", min);
1277 arg_running_as = MANAGER_USER;
1278 log_set_target(LOG_TARGET_AUTO);
1282 /* Initialize default unit */
1283 if (set_default_unit(SPECIAL_DEFAULT_TARGET) < 0)
1286 /* By default, mount "cpu" and "cpuacct" together */
1287 arg_join_controllers = new(char**, 2);
1288 if (!arg_join_controllers)
1291 arg_join_controllers[0] = strv_new("cpu", "cpuacct", NULL);
1292 arg_join_controllers[1] = NULL;
1294 if (!arg_join_controllers[0])
1297 /* Mount /proc, /sys and friends, so that /proc/cmdline and
1298 * /proc/$PID/fd is available. */
1299 if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
1300 r = mount_setup(loaded_policy);
1305 /* Reset all signal handlers. */
1306 assert_se(reset_all_signal_handlers() == 0);
1308 /* If we are init, we can block sigkill. Yay. */
1309 ignore_signals(SIGNALS_IGNORE, -1);
1311 if (parse_config_file() < 0)
1314 if (arg_running_as == MANAGER_SYSTEM)
1315 if (parse_proc_cmdline() < 0)
1318 log_parse_environment();
1320 if (parse_argv(argc, argv) < 0)
1323 if (arg_action == ACTION_TEST && geteuid() == 0) {
1324 log_error("Don't run test mode as root.");
1328 if (arg_running_as == MANAGER_SYSTEM &&
1329 arg_action == ACTION_RUN &&
1330 running_in_chroot() > 0) {
1331 log_error("Cannot be run in a chroot() environment.");
1335 if (arg_action == ACTION_HELP) {
1338 } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) {
1339 unit_dump_config_items(stdout);
1340 retval = EXIT_SUCCESS;
1342 } else if (arg_action == ACTION_DONE) {
1343 retval = EXIT_SUCCESS;
1347 assert_se(arg_action == ACTION_RUN || arg_action == ACTION_TEST);
1349 /* Close logging fds, in order not to confuse fdset below */
1352 /* Remember open file descriptors for later deserialization */
1353 if (serialization) {
1354 r = fdset_new_fill(&fds);
1356 log_error("Failed to allocate fd set: %s", strerror(-r));
1360 assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
1362 close_all_fds(NULL, 0);
1364 /* Set up PATH unless it is already set */
1366 #ifdef HAVE_SPLIT_USR
1367 "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
1369 "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin",
1371 arg_running_as == MANAGER_SYSTEM);
1373 if (arg_running_as == MANAGER_SYSTEM) {
1374 /* Parse the data passed to us. We leave this
1375 * variables set, but the manager later on will not
1376 * pass them on to our children. */
1378 parse_initrd_timestamp(&initrd_timestamp);
1380 /* Unset some environment variables passed in from the
1381 * kernel that don't really make sense for us. */
1385 /* When we are invoked by a shell, these might be set,
1386 * but make little sense to pass on */
1391 /* When we are invoked by a chroot-like tool such as
1392 * nspawn, these might be set, but make little sense
1395 unsetenv("LOGNAME");
1397 /* All other variables are left as is, so that clients
1398 * can still read them via /proc/1/environ */
1401 /* Move out of the way, so that we won't block unmounts */
1402 assert_se(chdir("/") == 0);
1404 if (arg_running_as == MANAGER_SYSTEM) {
1405 /* Become a session leader if we aren't one yet. */
1408 /* Disable the umask logic */
1412 /* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
1413 dbus_connection_set_change_sigpipe(FALSE);
1415 /* Reset the console, but only if this is really init and we
1416 * are freshly booted */
1417 if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN) {
1418 console_setup(getpid() == 1 && !skip_setup);
1422 /* Open the logging devices, if possible and necessary */
1425 /* Make sure we leave a core dump without panicing the
1428 install_crash_handler();
1430 if (geteuid() == 0 && !getenv("SYSTEMD_SKIP_API_MOUNTS")) {
1431 r = mount_cgroup_controllers(arg_join_controllers);
1436 log_full(arg_running_as == MANAGER_SYSTEM ? LOG_INFO : LOG_DEBUG,
1437 PACKAGE_STRING " running in %s mode. (" SYSTEMD_FEATURES "; " DISTRIBUTION ")", manager_running_as_to_string(arg_running_as));
1439 if (arg_running_as == MANAGER_SYSTEM && !skip_setup) {
1442 if (arg_show_status || plymouth_running())
1455 if (arg_running_as == MANAGER_SYSTEM && arg_runtime_watchdog > 0)
1456 watchdog_set_timeout(&arg_runtime_watchdog);
1458 r = manager_new(arg_running_as, &m);
1460 log_error("Failed to allocate manager object: %s", strerror(-r));
1464 m->confirm_spawn = arg_confirm_spawn;
1465 #ifdef HAVE_SYSV_COMPAT
1466 m->sysv_console = arg_sysv_console;
1468 m->default_std_output = arg_default_std_output;
1469 m->default_std_error = arg_default_std_error;
1470 m->runtime_watchdog = arg_runtime_watchdog;
1471 m->shutdown_watchdog = arg_shutdown_watchdog;
1473 if (dual_timestamp_is_set(&initrd_timestamp))
1474 m->initrd_timestamp = initrd_timestamp;
1476 if (arg_default_controllers)
1477 manager_set_default_controllers(m, arg_default_controllers);
1479 manager_set_show_status(m, arg_show_status);
1481 before_startup = now(CLOCK_MONOTONIC);
1483 r = manager_startup(m, serialization, fds);
1485 log_error("Failed to fully start up daemon: %s", strerror(-r));
1488 /* This will close all file descriptors that were opened, but
1489 * not claimed by any unit. */
1495 if (serialization) {
1496 fclose(serialization);
1497 serialization = NULL;
1500 Unit *target = NULL;
1501 Job *default_unit_job;
1503 dbus_error_init(&error);
1505 log_debug("Activating default unit: %s", arg_default_unit);
1507 r = manager_load_unit(m, arg_default_unit, NULL, &error, &target);
1509 log_error("Failed to load default target: %s", bus_error(&error, r));
1510 dbus_error_free(&error);
1511 } else if (target->load_state == UNIT_ERROR)
1512 log_error("Failed to load default target: %s", strerror(-target->load_error));
1513 else if (target->load_state == UNIT_MASKED)
1514 log_error("Default target masked.");
1516 if (!target || target->load_state != UNIT_LOADED) {
1517 log_info("Trying to load rescue target...");
1519 r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &error, &target);
1521 log_error("Failed to load rescue target: %s", bus_error(&error, r));
1522 dbus_error_free(&error);
1524 } else if (target->load_state == UNIT_ERROR) {
1525 log_error("Failed to load rescue target: %s", strerror(-target->load_error));
1527 } else if (target->load_state == UNIT_MASKED) {
1528 log_error("Rescue target masked.");
1533 assert(target->load_state == UNIT_LOADED);
1535 if (arg_action == ACTION_TEST) {
1536 printf("-> By units:\n");
1537 manager_dump_units(m, stdout, "\t");
1540 r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &error, &default_unit_job);
1542 log_error("Failed to start default target: %s", bus_error(&error, r));
1543 dbus_error_free(&error);
1546 m->default_unit_job_id = default_unit_job->id;
1548 after_startup = now(CLOCK_MONOTONIC);
1549 log_full(arg_action == ACTION_TEST ? LOG_INFO : LOG_DEBUG,
1550 "Loaded units and determined initial transaction in %s.",
1551 format_timespan(timespan, sizeof(timespan), after_startup - before_startup));
1553 if (arg_action == ACTION_TEST) {
1554 printf("-> By jobs:\n");
1555 manager_dump_jobs(m, stdout, "\t");
1556 retval = EXIT_SUCCESS;
1562 r = manager_loop(m);
1564 log_error("Failed to run mainloop: %s", strerror(-r));
1568 switch (m->exit_code) {
1571 retval = EXIT_SUCCESS;
1575 case MANAGER_RELOAD:
1576 log_info("Reloading.");
1577 r = manager_reload(m);
1579 log_error("Failed to reload: %s", strerror(-r));
1582 case MANAGER_REEXECUTE:
1584 if (prepare_reexecute(m, &serialization, &fds) < 0)
1588 log_notice("Reexecuting.");
1591 case MANAGER_SWITCH_ROOT:
1592 /* Steal the switch root parameters */
1593 switch_root_dir = m->switch_root;
1594 switch_root_init = m->switch_root_init;
1595 m->switch_root = m->switch_root_init = NULL;
1597 if (!switch_root_init)
1598 if (prepare_reexecute(m, &serialization, &fds) < 0)
1602 log_notice("Switching root.");
1605 case MANAGER_REBOOT:
1606 case MANAGER_POWEROFF:
1608 case MANAGER_KEXEC: {
1609 static const char * const table[_MANAGER_EXIT_CODE_MAX] = {
1610 [MANAGER_REBOOT] = "reboot",
1611 [MANAGER_POWEROFF] = "poweroff",
1612 [MANAGER_HALT] = "halt",
1613 [MANAGER_KEXEC] = "kexec"
1616 assert_se(shutdown_verb = table[m->exit_code]);
1617 arm_reboot_watchdog = m->exit_code == MANAGER_REBOOT;
1619 log_notice("Shutting down.");
1624 assert_not_reached("Unknown exit code.");
1632 free(arg_default_unit);
1633 strv_free(arg_default_controllers);
1634 free_join_controllers();
1641 unsigned i, args_size;
1643 /* Close and disarm the watchdog, so that the new
1644 * instance can reinitialize it, but doesn't get
1645 * rebooted while we do that */
1646 watchdog_close(true);
1648 if (switch_root_dir) {
1649 r = switch_root(switch_root_dir);
1651 log_error("Failed to switch root, ignoring: %s", strerror(-r));
1654 args_size = MAX(6, argc+1);
1655 args = newa(const char*, args_size);
1657 if (!switch_root_init) {
1660 /* First try to spawn ourselves with the right
1661 * path, and with full serialization. We do
1662 * this only if the user didn't specify an
1663 * explicit init to spawn. */
1665 assert(serialization);
1668 snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
1672 args[i++] = SYSTEMD_BINARY_PATH;
1673 if (switch_root_dir)
1674 args[i++] = "--switched-root";
1675 args[i++] = arg_running_as == MANAGER_SYSTEM ? "--system" : "--user";
1676 args[i++] = "--deserialize";
1680 assert(i <= args_size);
1681 execv(args[0], (char* const*) args);
1684 /* Try the fallback, if there is any, without any
1685 * serialization. We pass the original argv[] and
1686 * envp[]. (Well, modulo the ordering changes due to
1687 * getopt() in argv[], and some cleanups in envp[],
1688 * but let's hope that doesn't matter.) */
1690 if (serialization) {
1691 fclose(serialization);
1692 serialization = NULL;
1700 for (j = 1, i = 1; j < argc; j++)
1701 args[i++] = argv[j];
1703 assert(i <= args_size);
1705 if (switch_root_init) {
1706 args[0] = switch_root_init;
1707 execv(args[0], (char* const*) args);
1708 log_warning("Failed to execute configured init, trying fallback: %m");
1711 args[0] = "/sbin/init";
1712 execv(args[0], (char* const*) args);
1714 log_warning("Failed to execute /sbin/init, trying fallback: %m");
1716 args[0] = "/bin/sh";
1718 execv(args[0], (char* const*) args);
1719 log_error("Failed to execute /bin/sh, giving up: %m");
1723 fclose(serialization);
1728 if (shutdown_verb) {
1729 const char * command_line[] = {
1730 SYSTEMD_SHUTDOWN_BINARY_PATH,
1736 if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
1739 /* If we reboot let's set the shutdown
1740 * watchdog and tell the shutdown binary to
1741 * repeatedly ping it */
1742 watchdog_set_timeout(&arg_shutdown_watchdog);
1743 watchdog_close(false);
1745 /* Tell the binary how often to ping */
1746 snprintf(e, sizeof(e), "WATCHDOG_USEC=%llu", (unsigned long long) arg_shutdown_watchdog);
1749 env_block = strv_append(environ, e);
1751 env_block = strv_copy(environ);
1752 watchdog_close(true);
1755 execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
1757 log_error("Failed to execute shutdown binary, freezing: %m");