chiark / gitweb /
e51f6b7a34c1799dc6d6149fe032354001b2cc32
[elogind.git] / src / main.c
1 /*-*- Mode: C; c-basic-offset: 8 -*-*/
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 General Public License as published by
10   the Free Software Foundation; either version 2 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   General Public License for more details.
17
18   You should have received a copy of the GNU 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
35 #include "manager.h"
36 #include "log.h"
37 #include "mount-setup.h"
38 #include "hostname-setup.h"
39 #include "loopback-setup.h"
40 #include "kmod-setup.h"
41 #include "modprobe-setup.h"
42 #include "load-fragment.h"
43 #include "fdset.h"
44 #include "special.h"
45
46 static enum {
47         ACTION_RUN,
48         ACTION_HELP,
49         ACTION_TEST,
50         ACTION_DUMP_CONFIGURATION_ITEMS,
51         ACTION_DONE
52 } arg_action = ACTION_RUN;
53
54 static char *arg_default_unit = NULL;
55 static ManagerRunningAs arg_running_as = _MANAGER_RUNNING_AS_INVALID;
56
57 static bool arg_dump_core = true;
58 static bool arg_crash_shell = false;
59 static int arg_crash_chvt = -1;
60 static bool arg_confirm_spawn = false;
61 static bool arg_nomodules = false;
62
63 static FILE* serialization = NULL;
64
65 _noreturn_ static void freeze(void) {
66         for (;;)
67                 pause();
68 }
69
70 static void nop_handler(int sig) {
71 }
72
73 _noreturn_ static void crash(int sig) {
74
75         if (!arg_dump_core)
76                 log_error("Caught <%s>, not dumping core.", strsignal(sig));
77         else {
78                 struct sigaction sa;
79                 pid_t pid;
80
81                 /* We want to wait for the core process, hence let's enable SIGCHLD */
82                 zero(sa);
83                 sa.sa_handler = nop_handler;
84                 sa.sa_flags = SA_NOCLDSTOP|SA_RESTART;
85                 assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
86
87                 if ((pid = fork()) < 0)
88                         log_error("Caught <%s>, cannot fork for core dump: %s", strsignal(sig), strerror(errno));
89
90                 else if (pid == 0) {
91                         struct rlimit rl;
92
93                         /* Enable default signal handler for core dump */
94                         zero(sa);
95                         sa.sa_handler = SIG_DFL;
96                         assert_se(sigaction(sig, &sa, NULL) == 0);
97
98                         /* Don't limit the core dump size */
99                         zero(rl);
100                         rl.rlim_cur = RLIM_INFINITY;
101                         rl.rlim_max = RLIM_INFINITY;
102                         setrlimit(RLIMIT_CORE, &rl);
103
104                         /* Just to be sure... */
105                         assert_se(chdir("/") == 0);
106
107                         /* Raise the signal again */
108                         raise(sig);
109
110                         assert_not_reached("We shouldn't be here...");
111                         _exit(1);
112
113                 } else {
114                         int status, r;
115
116                         /* Order things nicely. */
117                         if ((r = waitpid(pid, &status, 0)) < 0)
118                                 log_error("Caught <%s>, waitpid() failed: %s", strsignal(sig), strerror(errno));
119                         else if (!WCOREDUMP(status))
120                                 log_error("Caught <%s>, core dump failed.", strsignal(sig));
121                         else
122                                 log_error("Caught <%s>, dumped core as pid %lu.", strsignal(sig), (unsigned long) pid);
123                 }
124         }
125
126         if (arg_crash_chvt)
127                 chvt(arg_crash_chvt);
128
129         if (arg_crash_shell) {
130                 struct sigaction sa;
131                 pid_t pid;
132
133                 log_info("Executing crash shell in 10s...");
134                 sleep(10);
135
136                 /* Let the kernel reap children for us */
137                 zero(sa);
138                 sa.sa_handler = SIG_IGN;
139                 sa.sa_flags = SA_NOCLDSTOP|SA_NOCLDWAIT|SA_RESTART;
140                 assert_se(sigaction(SIGCHLD, &sa, NULL) == 0);
141
142                 if ((pid = fork()) < 0)
143                         log_error("Failed to fork off crash shell: %s", strerror(errno));
144                 else if (pid == 0) {
145                         int fd, r;
146
147                         if ((fd = acquire_terminal("/dev/console", false, true, true)) < 0)
148                                 log_error("Failed to acquire terminal: %s", strerror(-fd));
149                         else if ((r = make_stdio(fd)) < 0)
150                                 log_error("Failed to duplicate terminal fd: %s", strerror(-r));
151
152                         execl("/bin/sh", "/bin/sh", NULL);
153
154                         log_error("execl() failed: %s", strerror(errno));
155                         _exit(1);
156                 }
157
158                 log_info("Successfully spawned crash shall as pid %lu.", (unsigned long) pid);
159         }
160
161         log_info("Freezing execution.");
162         freeze();
163 }
164
165 static void install_crash_handler(void) {
166         struct sigaction sa;
167
168         zero(sa);
169
170         sa.sa_handler = crash;
171         sa.sa_flags = SA_NODEFER;
172
173         sigaction_many(&sa, SIGNALS_CRASH_HANDLER, -1);
174 }
175
176 static int make_null_stdio(void) {
177         int null_fd, r;
178
179         if ((null_fd = open("/dev/null", O_RDWR|O_NOCTTY)) < 0) {
180                 log_error("Failed to open /dev/null: %m");
181                 return -errno;
182         }
183
184         if ((r = make_stdio(null_fd)) < 0)
185                 log_warning("Failed to dup2() device: %s", strerror(-r));
186
187         return r;
188 }
189
190 static int console_setup(bool do_reset) {
191         int tty_fd, r;
192
193         /* If we are init, we connect stdin/stdout/stderr to /dev/null
194          * and make sure we don't have a controlling tty. */
195
196         release_terminal();
197
198         if (!do_reset)
199                 return 0;
200
201         if ((tty_fd = open_terminal("/dev/console", O_WRONLY|O_NOCTTY|O_CLOEXEC)) < 0) {
202                 log_error("Failed to open /dev/console: %s", strerror(-tty_fd));
203                 return -tty_fd;
204         }
205
206         if ((r = reset_terminal(tty_fd)) < 0)
207                 log_error("Failed to reset /dev/console: %s", strerror(-r));
208
209         close_nointr_nofail(tty_fd);
210         return r;
211 }
212
213 static int set_default_unit(const char *u) {
214         char *c;
215
216         assert(u);
217
218         if (!(c = strdup(u)))
219                 return -ENOMEM;
220
221         free(arg_default_unit);
222         arg_default_unit = c;
223         return 0;
224 }
225
226 static int parse_proc_cmdline_word(const char *word) {
227
228         static const char * const rlmap[] = {
229                 "single", SPECIAL_RESCUE_TARGET,
230                 "-s",     SPECIAL_RESCUE_TARGET,
231                 "s",      SPECIAL_RESCUE_TARGET,
232                 "S",      SPECIAL_RESCUE_TARGET,
233                 "1",      SPECIAL_RESCUE_TARGET,
234                 "2",      SPECIAL_RUNLEVEL2_TARGET,
235                 "3",      SPECIAL_RUNLEVEL3_TARGET,
236                 "4",      SPECIAL_RUNLEVEL4_TARGET,
237                 "5",      SPECIAL_RUNLEVEL5_TARGET
238         };
239
240         if (startswith(word, "systemd.unit="))
241                 return set_default_unit(word + 13);
242
243         else if (startswith(word, "systemd.log_target=")) {
244
245                 if (log_set_target_from_string(word + 19) < 0)
246                         log_warning("Failed to parse log target %s. Ignoring.", word + 19);
247
248         } else if (startswith(word, "systemd.log_level=")) {
249
250                 if (log_set_max_level_from_string(word + 18) < 0)
251                         log_warning("Failed to parse log level %s. Ignoring.", word + 18);
252
253         } else if (startswith(word, "systemd.log_color=")) {
254
255                 if (log_show_color_from_string(word + 18) < 0)
256                         log_warning("Failed to parse log color setting %s. Ignoring.", word + 18);
257
258         } else if (startswith(word, "systemd.log_location=")) {
259
260                 if (log_show_location_from_string(word + 21) < 0)
261                         log_warning("Failed to parse log location setting %s. Ignoring.", word + 21);
262
263         } else if (startswith(word, "systemd.dump_core=")) {
264                 int r;
265
266                 if ((r = parse_boolean(word + 18)) < 0)
267                         log_warning("Failed to parse dump core switch %s, Ignoring.", word + 18);
268                 else
269                         arg_dump_core = r;
270
271         } else if (startswith(word, "systemd.crash_shell=")) {
272                 int r;
273
274                 if ((r = parse_boolean(word + 20)) < 0)
275                         log_warning("Failed to parse crash shell switch %s, Ignoring.", word + 20);
276                 else
277                         arg_crash_shell = r;
278
279         } else if (startswith(word, "systemd.confirm_spawn=")) {
280                 int r;
281
282                 if ((r = parse_boolean(word + 22)) < 0)
283                         log_warning("Failed to parse confirm spawn switch %s, Ignoring.", word + 22);
284                 else
285                         arg_confirm_spawn = r;
286
287         } else if (startswith(word, "systemd.crash_chvt=")) {
288                 int k;
289
290                 if (safe_atoi(word + 19, &k) < 0)
291                         log_warning("Failed to parse crash chvt switch %s, Ignoring.", word + 19);
292                 else
293                         arg_crash_chvt = k;
294
295         } else if (startswith(word, "systemd.")) {
296
297                 log_warning("Unknown kernel switch %s. Ignoring.", word);
298
299                 log_info("Supported kernel switches:\n"
300                          "systemd.unit=UNIT                        Default unit to start\n"
301                          "systemd.log_target=console|kmsg|syslog|  Log target\n"
302                          "                   syslog-org-kmsg|null\n"
303                          "systemd.log_level=LEVEL                  Log level\n"
304                          "systemd.log_color=0|1                    Highlight important log messages\n"
305                          "systemd.log_location=0|1                 Include code location in log messages\n"
306                          "systemd.dump_core=0|1                    Dump core on crash\n"
307                          "systemd.crash_shell=0|1                  On crash run shell\n"
308                          "systemd.crash_chvt=N                     Change to VT #N on crash\n"
309                          "systemd.confirm_spawn=0|1                Confirm every process spawn");
310
311         } else if (streq(word, "nomodules"))
312                 arg_nomodules = true;
313         else {
314                 unsigned i;
315
316                 /* SysV compatibility */
317                 for (i = 0; i < ELEMENTSOF(rlmap); i += 2)
318                         if (streq(word, rlmap[i]))
319                                 return set_default_unit(rlmap[i+1]);
320         }
321
322         return 0;
323 }
324
325 static int parse_proc_cmdline(void) {
326         char *line;
327         int r;
328         char *w;
329         size_t l;
330         char *state;
331
332         if ((r = read_one_line_file("/proc/cmdline", &line)) < 0) {
333                 log_warning("Failed to read /proc/cmdline, ignoring: %s", strerror(errno));
334                 return 0;
335         }
336
337         FOREACH_WORD_QUOTED(w, l, line, state) {
338                 char *word;
339
340                 if (!(word = strndup(w, l))) {
341                         r = -ENOMEM;
342                         goto finish;
343                 }
344
345                 r = parse_proc_cmdline_word(word);
346                 free(word);
347
348                 if (r < 0)
349                         goto finish;
350         }
351
352         r = 0;
353
354 finish:
355         free(line);
356         return r;
357 }
358
359 static int parse_argv(int argc, char *argv[]) {
360
361         enum {
362                 ARG_LOG_LEVEL = 0x100,
363                 ARG_LOG_TARGET,
364                 ARG_LOG_COLOR,
365                 ARG_LOG_LOCATION,
366                 ARG_UNIT,
367                 ARG_RUNNING_AS,
368                 ARG_TEST,
369                 ARG_DUMP_CONFIGURATION_ITEMS,
370                 ARG_CONFIRM_SPAWN,
371                 ARG_DESERIALIZE,
372                 ARG_INTROSPECT
373         };
374
375         static const struct option options[] = {
376                 { "log-level",                required_argument, NULL, ARG_LOG_LEVEL                },
377                 { "log-target",               required_argument, NULL, ARG_LOG_TARGET               },
378                 { "log-color",                optional_argument, NULL, ARG_LOG_COLOR                },
379                 { "log-location",             optional_argument, NULL, ARG_LOG_LOCATION             },
380                 { "unit",                     required_argument, NULL, ARG_UNIT                     },
381                 { "running-as",               required_argument, NULL, ARG_RUNNING_AS               },
382                 { "test",                     no_argument,       NULL, ARG_TEST                     },
383                 { "help",                     no_argument,       NULL, 'h'                          },
384                 { "dump-configuration-items", no_argument,       NULL, ARG_DUMP_CONFIGURATION_ITEMS },
385                 { "confirm-spawn",            no_argument,       NULL, ARG_CONFIRM_SPAWN            },
386                 { "deserialize",              required_argument, NULL, ARG_DESERIALIZE              },
387                 { "introspect",               optional_argument, NULL, ARG_INTROSPECT               },
388                 { NULL,                       0,                 NULL, 0                            }
389         };
390
391         int c, r;
392
393         assert(argc >= 1);
394         assert(argv);
395
396         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
397
398                 switch (c) {
399
400                 case ARG_LOG_LEVEL:
401                         if ((r = log_set_max_level_from_string(optarg)) < 0) {
402                                 log_error("Failed to parse log level %s.", optarg);
403                                 return r;
404                         }
405
406                         break;
407
408                 case ARG_LOG_TARGET:
409
410                         if ((r = log_set_target_from_string(optarg)) < 0) {
411                                 log_error("Failed to parse log target %s.", optarg);
412                                 return r;
413                         }
414
415                         break;
416
417                 case ARG_LOG_COLOR:
418
419                         if (optarg) {
420                                 if ((r = log_show_color_from_string(optarg)) < 0) {
421                                         log_error("Failed to parse log color setting %s.", optarg);
422                                         return r;
423                                 }
424                         } else
425                                 log_show_color(true);
426
427                         break;
428
429                 case ARG_LOG_LOCATION:
430
431                         if (optarg) {
432                                 if ((r = log_show_location_from_string(optarg)) < 0) {
433                                         log_error("Failed to parse log location setting %s.", optarg);
434                                         return r;
435                                 }
436                         } else
437                                 log_show_location(true);
438
439                         break;
440
441                 case ARG_UNIT:
442
443                         if ((r = set_default_unit(optarg)) < 0) {
444                                 log_error("Failed to set default unit %s: %s", optarg, strerror(-r));
445                                 return r;
446                         }
447
448                         break;
449
450                 case ARG_RUNNING_AS: {
451                         ManagerRunningAs as;
452
453                         if ((as = manager_running_as_from_string(optarg)) < 0) {
454                                 log_error("Failed to parse running as value %s", optarg);
455                                 return -EINVAL;
456                         }
457
458                         arg_running_as = as;
459                         break;
460                 }
461
462                 case ARG_TEST:
463                         arg_action = ACTION_TEST;
464                         break;
465
466                 case ARG_DUMP_CONFIGURATION_ITEMS:
467                         arg_action = ACTION_DUMP_CONFIGURATION_ITEMS;
468                         break;
469
470                 case ARG_CONFIRM_SPAWN:
471                         arg_confirm_spawn = true;
472                         break;
473
474                 case ARG_DESERIALIZE: {
475                         int fd;
476                         FILE *f;
477
478                         if ((r = safe_atoi(optarg, &fd)) < 0 || fd < 0) {
479                                 log_error("Failed to parse deserialize option %s.", optarg);
480                                 return r;
481                         }
482
483                         if (!(f = fdopen(fd, "r"))) {
484                                 log_error("Failed to open serialization fd: %m");
485                                 return r;
486                         }
487
488                         if (serialization)
489                                 fclose(serialization);
490
491                         serialization = f;
492
493                         break;
494                 }
495
496                 case ARG_INTROSPECT: {
497                         const char * const * i = NULL;
498
499                         for (i = bus_interface_table; *i; i += 2)
500                                 if (!optarg || streq(i[0], optarg)) {
501                                         fputs(DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
502                                               "<node>\n", stdout);
503                                         fputs(i[1], stdout);
504                                         fputs("</node>\n", stdout);
505
506                                         if (optarg)
507                                                 break;
508                                 }
509
510                         if (!i[0] && optarg)
511                                 log_error("Unknown interface %s.", optarg);
512
513                         arg_action = ACTION_DONE;
514                         break;
515                 }
516
517                 case 'h':
518                         arg_action = ACTION_HELP;
519                         break;
520
521                 case '?':
522                         return -EINVAL;
523
524                 default:
525                         log_error("Unknown option code %c", c);
526                         return -EINVAL;
527                 }
528
529         /* PID 1 will get the kernel arguments as parameters, which we
530          * ignore and unconditionally read from
531          * /proc/cmdline. However, we need to ignore those arguments
532          * here. */
533         if (arg_running_as != MANAGER_SYSTEM && optind < argc) {
534                 log_error("Excess arguments.");
535                 return -EINVAL;
536         }
537
538         return 0;
539 }
540
541 static int help(void) {
542
543         printf("%s [OPTIONS...]\n\n"
544                "Starts up and maintains the system or a session.\n\n"
545                "  -h --help                      Show this help\n"
546                "     --unit=UNIT                 Set default unit\n"
547                "     --running-as=AS             Set running as (system, session)\n"
548                "     --test                      Determine startup sequence, dump it and exit\n"
549                "     --dump-configuration-items  Dump understood unit configuration items\n"
550                "     --confirm-spawn             Ask for confirmation when spawning processes\n"
551                "     --introspect[=INTERFACE]    Extract D-Bus interface data\n"
552                "     --log-level=LEVEL           Set log level\n"
553                "     --log-target=TARGET         Set log target (console, syslog, kmsg, syslog-or-kmsg, null)\n"
554                "     --log-color[=0|1]           Highlight important log messages\n"
555                "     --log-location[=0|1]        Include code location in log messages\n",
556                program_invocation_short_name);
557
558         return 0;
559 }
560
561 static int prepare_reexecute(Manager *m, FILE **_f, FDSet **_fds) {
562         FILE *f = NULL;
563         FDSet *fds = NULL;
564         int r;
565
566         assert(m);
567         assert(_f);
568         assert(_fds);
569
570         if ((r = manager_open_serialization(&f)) < 0) {
571                 log_error("Failed to create serialization faile: %s", strerror(-r));
572                 goto fail;
573         }
574
575         if (!(fds = fdset_new())) {
576                 r = -ENOMEM;
577                 log_error("Failed to allocate fd set: %s", strerror(-r));
578                 goto fail;
579         }
580
581         if ((r = manager_serialize(m, f, fds)) < 0) {
582                 log_error("Failed to serialize state: %s", strerror(-r));
583                 goto fail;
584         }
585
586         if (fseeko(f, 0, SEEK_SET) < 0) {
587                 log_error("Failed to rewind serialization fd: %m");
588                 goto fail;
589         }
590
591         if ((r = fd_cloexec(fileno(f), false)) < 0) {
592                 log_error("Failed to disable O_CLOEXEC for serialization: %s", strerror(-r));
593                 goto fail;
594         }
595
596         if ((r = fdset_cloexec(fds, false)) < 0) {
597                 log_error("Failed to disable O_CLOEXEC for serialization fds: %s", strerror(-r));
598                 goto fail;
599         }
600
601         *_f = f;
602         *_fds = fds;
603
604         return 0;
605
606 fail:
607         fdset_free(fds);
608
609         if (f)
610                 fclose(f);
611
612         return r;
613 }
614
615 int main(int argc, char *argv[]) {
616         Manager *m = NULL;
617         Unit *target = NULL;
618         Job *job = NULL;
619         int r, retval = 1;
620         FDSet *fds = NULL;
621         bool reexecute = false;
622
623         if (getpid() != 1 && strstr(program_invocation_short_name, "init")) {
624                 /* This is compatbility support for SysV, where
625                  * calling init as a user is identical to telinit. */
626
627                 errno = -ENOENT;
628                 execv(SYSTEMCTL_BINARY_PATH, argv);
629                 log_error("Failed to exec " SYSTEMCTL_BINARY_PATH ": %m");
630                 return 1;
631         }
632
633         log_show_color(true);
634         log_show_location(false);
635         log_set_max_level(LOG_DEBUG);
636
637         if (getpid() == 1) {
638                 arg_running_as = MANAGER_SYSTEM;
639                 log_set_target(LOG_TARGET_SYSLOG_OR_KMSG);
640         } else {
641                 arg_running_as = MANAGER_SESSION;
642                 log_set_target(LOG_TARGET_CONSOLE);
643         }
644
645         if (set_default_unit(SPECIAL_DEFAULT_TARGET) < 0)
646                 goto finish;
647
648         /* Mount /proc, /sys and friends, so that /proc/cmdline and
649          * /proc/$PID/fd is available. */
650         if (geteuid() == 0)
651                 if (mount_setup() < 0)
652                         goto finish;
653
654         /* Reset all signal handlers. */
655         assert_se(reset_all_signal_handlers() == 0);
656
657         /* If we are init, we can block sigkill. Yay. */
658         ignore_signals(SIGNALS_IGNORE, -1);
659
660         if (arg_running_as == MANAGER_SYSTEM)
661                 if (parse_proc_cmdline() < 0)
662                         goto finish;
663
664         log_parse_environment();
665
666         if (parse_argv(argc, argv) < 0)
667                 goto finish;
668
669         if (arg_action == ACTION_HELP) {
670                 retval = help();
671                 goto finish;
672         } else if (arg_action == ACTION_DUMP_CONFIGURATION_ITEMS) {
673                 unit_dump_config_items(stdout);
674                 retval = 0;
675                 goto finish;
676         } else if (arg_action == ACTION_DONE) {
677                 retval = 0;
678                 goto finish;
679         }
680
681         assert_se(arg_action == ACTION_RUN || arg_action == ACTION_TEST);
682
683         /* Remember open file descriptors for later deserialization */
684         if (serialization) {
685                 if ((r = fdset_new_fill(&fds)) < 0) {
686                         log_error("Failed to allocate fd set: %s", strerror(-r));
687                         goto finish;
688                 }
689
690                 assert_se(fdset_remove(fds, fileno(serialization)) >= 0);
691         } else
692                 close_all_fds(NULL, 0);
693
694         /* Set up PATH unless it is already set */
695         setenv("PATH",
696                "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
697                arg_running_as == MANAGER_SYSTEM);
698
699         /* Move out of the way, so that we won't block unmounts */
700         assert_se(chdir("/")  == 0);
701
702         if (arg_running_as == MANAGER_SYSTEM) {
703                 /* Become a session leader if we aren't one yet. */
704                 setsid();
705
706                 /* Disable the umask logic */
707                 umask(0);
708         }
709
710         /* Make sure D-Bus doesn't fiddle with the SIGPIPE handlers */
711         dbus_connection_set_change_sigpipe(FALSE);
712
713         /* Reset the console, but only if this is really init and we
714          * are freshly booted */
715         if (arg_running_as == MANAGER_SYSTEM && arg_action == ACTION_RUN) {
716                 console_setup(getpid() == 1 && !serialization);
717                 make_null_stdio();
718         }
719
720         /* Open the logging devices, if possible and necessary */
721         log_open();
722
723         /* Make sure we leave a core dump without panicing the
724          * kernel. */
725         if (getpid() == 1)
726                 install_crash_handler();
727
728         log_debug(PACKAGE_STRING " running in %s mode.", manager_running_as_to_string(arg_running_as));
729
730         if (arg_running_as == MANAGER_SYSTEM) {
731                 modprobe_setup(arg_nomodules);
732                 kmod_setup();
733                 hostname_setup();
734                 loopback_setup();
735         }
736
737         if ((r = manager_new(arg_running_as, arg_confirm_spawn, &m)) < 0) {
738                 log_error("Failed to allocate manager object: %s", strerror(-r));
739                 goto finish;
740         }
741
742         if ((r = manager_startup(m, serialization, fds)) < 0)
743                 log_error("Failed to fully start up daemon: %s", strerror(-r));
744
745         if (fds) {
746                 /* This will close all file descriptors that were opened, but
747                  * not claimed by any unit. */
748
749                 fdset_free(fds);
750                 fds = NULL;
751         }
752
753         if (serialization) {
754                 fclose(serialization);
755                 serialization = NULL;
756         } else {
757                 log_debug("Activating default unit: %s", arg_default_unit);
758
759                 if ((r = manager_load_unit(m, arg_default_unit, NULL, &target)) < 0) {
760                         log_error("Failed to load default target: %s", strerror(-r));
761
762                         log_info("Trying to load rescue target...");
763                         if ((r = manager_load_unit(m, SPECIAL_RESCUE_TARGET, NULL, &target)) < 0) {
764                                 log_error("Failed to load rescue target: %s", strerror(-r));
765                                 goto finish;
766                         }
767                 }
768
769                 if (arg_action == ACTION_TEST) {
770                         printf("-> By units:\n");
771                         manager_dump_units(m, stdout, "\t");
772                 }
773
774                 if ((r = manager_add_job(m, JOB_START, target, JOB_REPLACE, false, &job)) < 0) {
775                         log_error("Failed to start default target: %s", strerror(-r));
776                         goto finish;
777                 }
778
779                 if (arg_action == ACTION_TEST) {
780                         printf("-> By jobs:\n");
781                         manager_dump_jobs(m, stdout, "\t");
782                         retval = 0;
783                         goto finish;
784                 }
785         }
786
787         for (;;) {
788                 if ((r = manager_loop(m)) < 0) {
789                         log_error("Failed to run mainloop: %s", strerror(-r));
790                         goto finish;
791                 }
792
793                 switch (m->exit_code) {
794
795                 case MANAGER_EXIT:
796                         retval = 0;
797                         log_debug("Exit.");
798                         goto finish;
799
800                 case MANAGER_RELOAD:
801                         if ((r = manager_reload(m)) < 0)
802                                 log_error("Failed to reload: %s", strerror(-r));
803                         break;
804
805                 case MANAGER_REEXECUTE:
806                         if (prepare_reexecute(m, &serialization, &fds) < 0)
807                                 goto finish;
808
809                         reexecute = true;
810                         log_debug("Reexecuting.");
811                         goto finish;
812
813                 default:
814                         assert_not_reached("Unknown exit code.");
815                 }
816         }
817
818 finish:
819         if (m)
820                 manager_free(m);
821
822         free(arg_default_unit);
823
824         dbus_shutdown();
825
826         if (reexecute) {
827                 const char *args[11];
828                 unsigned i = 0;
829                 char sfd[16];
830
831                 assert(serialization);
832                 assert(fds);
833
834                 args[i++] = SYSTEMD_BINARY_PATH;
835
836                 args[i++] = "--log-level";
837                 args[i++] = log_level_to_string(log_get_max_level());
838
839                 args[i++] = "--log-target";
840                 args[i++] = log_target_to_string(log_get_target());
841
842                 args[i++] = "--running-as";
843                 args[i++] = manager_running_as_to_string(arg_running_as);
844
845                 snprintf(sfd, sizeof(sfd), "%i", fileno(serialization));
846                 char_array_0(sfd);
847
848                 args[i++] = "--deserialize";
849                 args[i++] = sfd;
850
851                 if (arg_confirm_spawn)
852                         args[i++] = "--confirm-spawn";
853
854                 args[i++] = NULL;
855
856                 assert(i <= ELEMENTSOF(args));
857
858                 execv(args[0], (char* const*) args);
859
860                 log_error("Failed to reexecute: %m");
861         }
862
863         if (serialization)
864                 fclose(serialization);
865
866         if (fds)
867                 fdset_free(fds);
868
869         if (getpid() == 1)
870                 freeze();
871
872         return retval;
873 }