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