X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fmain.c;h=a2dc1bc12f707fb69581b28cfee99c8ba99d2b58;hp=e51f6b7a34c1799dc6d6149fe032354001b2cc32;hb=487393e9f11e4a06d91df03232914bd8c4b3368e;hpb=fa0f4d8a3a640b235f12e9eb998ce726495622c1 diff --git a/src/main.c b/src/main.c index e51f6b7a3..a2dc1bc12 100644 --- a/src/main.c +++ b/src/main.c @@ -42,6 +42,7 @@ #include "load-fragment.h" #include "fdset.h" #include "special.h" +#include "conf-parser.h" static enum { ACTION_RUN, @@ -59,6 +60,7 @@ static bool arg_crash_shell = false; static int arg_crash_chvt = -1; static bool arg_confirm_spawn = false; static bool arg_nomodules = false; +static bool arg_show_status = true; static FILE* serialization = NULL; @@ -236,6 +238,7 @@ static int parse_proc_cmdline_word(const char *word) { "4", SPECIAL_RUNLEVEL4_TARGET, "5", SPECIAL_RUNLEVEL5_TARGET }; + bool ignore_quiet = false; if (startswith(word, "systemd.unit=")) return set_default_unit(word + 13); @@ -292,6 +295,16 @@ static int parse_proc_cmdline_word(const char *word) { else arg_crash_chvt = k; + } else if (startswith(word, "systemd.show_status=")) { + int r; + + if ((r = parse_boolean(word + 20)) < 0) + log_warning("Failed to parse show status switch %s, Ignoring.", word + 20); + else { + arg_show_status = r; + ignore_quiet = true; + } + } else if (startswith(word, "systemd.")) { log_warning("Unknown kernel switch %s. Ignoring.", word); @@ -304,13 +317,17 @@ static int parse_proc_cmdline_word(const char *word) { "systemd.log_color=0|1 Highlight important log messages\n" "systemd.log_location=0|1 Include code location in log messages\n" "systemd.dump_core=0|1 Dump core on crash\n" - "systemd.crash_shell=0|1 On crash run shell\n" + "systemd.crash_shell=0|1 Run shell on crash\n" "systemd.crash_chvt=N Change to VT #N on crash\n" - "systemd.confirm_spawn=0|1 Confirm every process spawn"); + "systemd.confirm_spawn=0|1 Confirm every process spawn\n" + "systemd.show_status=0|1 Show status updates on the console during bootup\n"); } else if (streq(word, "nomodules")) arg_nomodules = true; - else { + else if (streq(word, "quiet")) { + if (!ignore_quiet) + arg_show_status = false; + } else { unsigned i; /* SysV compatibility */ @@ -322,6 +339,169 @@ static int parse_proc_cmdline_word(const char *word) { return 0; } +static int config_parse_level( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + const char *rvalue, + void *data, + void *userdata) { + + assert(filename); + assert(lvalue); + assert(rvalue); + + log_set_max_level_from_string(rvalue); + return 0; +} + +static int config_parse_target( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + const char *rvalue, + void *data, + void *userdata) { + + assert(filename); + assert(lvalue); + assert(rvalue); + + log_set_target_from_string(rvalue); + return 0; +} + +static int config_parse_color( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + const char *rvalue, + void *data, + void *userdata) { + + assert(filename); + assert(lvalue); + assert(rvalue); + + log_show_color_from_string(rvalue); + return 0; +} + +static int config_parse_location( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + const char *rvalue, + void *data, + void *userdata) { + + assert(filename); + assert(lvalue); + assert(rvalue); + + log_show_location_from_string(rvalue); + return 0; +} + +static int config_parse_cpu_affinity( + const char *filename, + unsigned line, + const char *section, + const char *lvalue, + const char *rvalue, + void *data, + void *userdata) { + + char *w; + size_t l; + char *state; + cpu_set_t *c = NULL; + unsigned ncpus = 0; + + assert(filename); + assert(lvalue); + assert(rvalue); + + FOREACH_WORD(w, l, rvalue, state) { + char *t; + int r; + unsigned cpu; + + if (!(t = strndup(w, l))) + return -ENOMEM; + + r = safe_atou(t, &cpu); + free(t); + + if (!c) + if (!(c = cpu_set_malloc(&ncpus))) + return -ENOMEM; + + if (r < 0 || cpu >= ncpus) { + log_error("[%s:%u] Failed to parse CPU affinity: %s", filename, line, rvalue); + CPU_FREE(c); + return -EBADMSG; + } + + CPU_SET_S(cpu, CPU_ALLOC_SIZE(ncpus), c); + } + + if (c) { + if (sched_setaffinity(0, CPU_ALLOC_SIZE(ncpus), c) < 0) + log_warning("Failed to set CPU affinity: %m"); + + CPU_FREE(c); + } + + return 0; +} + +static int parse_config_file(void) { + + const ConfigItem items[] = { + { "LogLevel", config_parse_level, NULL, "Manager" }, + { "LogTarget", config_parse_target, NULL, "Manager" }, + { "LogColor", config_parse_color, NULL, "Manager" }, + { "LogLocation", config_parse_location, NULL, "Manager" }, + { "DumpCore", config_parse_bool, &arg_dump_core, "Manager" }, + { "CrashShell", config_parse_bool, &arg_crash_shell, "Manager" }, + { "ShowStatus", config_parse_bool, &arg_show_status, "Manager" }, + { "CrashChVT", config_parse_int, &arg_crash_chvt, "Manager" }, + { "CPUAffinity", config_parse_cpu_affinity, NULL, "Manager" }, + { NULL, NULL, NULL, NULL } + }; + + static const char * const sections[] = { + "Manager", + NULL + }; + + FILE *f; + const char *fn; + int r; + + fn = arg_running_as == MANAGER_SYSTEM ? SYSTEM_CONFIG_FILE : SESSION_CONFIG_FILE; + + if (!(f = fopen(fn, "re"))) { + if (errno == ENOENT) + return 0; + + log_warning("Failed to open configuration file '%s': %m", fn); + return 0; + } + + if ((r = config_parse(fn, f, sections, items, false, NULL)) < 0) + log_warning("Failed to parse configuration file: %s", strerror(-r)); + + fclose(f); + + return 0; +} + static int parse_proc_cmdline(void) { char *line; int r; @@ -367,7 +547,10 @@ static int parse_argv(int argc, char *argv[]) { ARG_RUNNING_AS, ARG_TEST, ARG_DUMP_CONFIGURATION_ITEMS, + ARG_DUMP_CORE, + ARG_CRASH_SHELL, ARG_CONFIRM_SPAWN, + ARG_SHOW_STATUS, ARG_DESERIALIZE, ARG_INTROSPECT }; @@ -382,7 +565,10 @@ static int parse_argv(int argc, char *argv[]) { { "test", no_argument, NULL, ARG_TEST }, { "help", no_argument, NULL, 'h' }, { "dump-configuration-items", no_argument, NULL, ARG_DUMP_CONFIGURATION_ITEMS }, + { "dump-core", no_argument, NULL, ARG_DUMP_CORE }, + { "crash-shell", no_argument, NULL, ARG_CRASH_SHELL }, { "confirm-spawn", no_argument, NULL, ARG_CONFIRM_SPAWN }, + { "show-status", no_argument, NULL, ARG_SHOW_STATUS }, { "deserialize", required_argument, NULL, ARG_DESERIALIZE }, { "introspect", optional_argument, NULL, ARG_INTROSPECT }, { NULL, 0, NULL, 0 } @@ -467,10 +653,22 @@ static int parse_argv(int argc, char *argv[]) { arg_action = ACTION_DUMP_CONFIGURATION_ITEMS; break; + case ARG_DUMP_CORE: + arg_dump_core = true; + break; + + case ARG_CRASH_SHELL: + arg_crash_shell = true; + break; + case ARG_CONFIRM_SPAWN: arg_confirm_spawn = true; break; + case ARG_SHOW_STATUS: + arg_show_status = true; + break; + case ARG_DESERIALIZE: { int fd; FILE *f; @@ -543,14 +741,17 @@ static int help(void) { printf("%s [OPTIONS...]\n\n" "Starts up and maintains the system or a session.\n\n" " -h --help Show this help\n" - " --unit=UNIT Set default unit\n" - " --running-as=AS Set running as (system, session)\n" " --test Determine startup sequence, dump it and exit\n" " --dump-configuration-items Dump understood unit configuration items\n" - " --confirm-spawn Ask for confirmation when spawning processes\n" " --introspect[=INTERFACE] Extract D-Bus interface data\n" - " --log-level=LEVEL Set log level\n" + " --unit=UNIT Set default unit\n" + " --running-as=AS Set running as (system, session)\n" + " --dump-core Dump core on crash\n" + " --crash-shell Run shell on crash\n" + " --confirm-spawn Ask for confirmation when spawning processes\n" + " --show-status Show status updates on the console during bootup\n" " --log-target=TARGET Set log target (console, syslog, kmsg, syslog-or-kmsg, null)\n" + " --log-level=LEVEL Set log level (debug, info, notice, warning, err, crit, alert, emerg)\n" " --log-color[=0|1] Highlight important log messages\n" " --log-location[=0|1] Include code location in log messages\n", program_invocation_short_name); @@ -657,6 +858,9 @@ int main(int argc, char *argv[]) { /* If we are init, we can block sigkill. Yay. */ ignore_signals(SIGNALS_IGNORE, -1); + if (parse_config_file() < 0) + goto finish; + if (arg_running_as == MANAGER_SYSTEM) if (parse_proc_cmdline() < 0) goto finish; @@ -727,18 +931,22 @@ int main(int argc, char *argv[]) { log_debug(PACKAGE_STRING " running in %s mode.", manager_running_as_to_string(arg_running_as)); - if (arg_running_as == MANAGER_SYSTEM) { + if (arg_running_as == MANAGER_SYSTEM && !serialization) { + status_welcome(); modprobe_setup(arg_nomodules); kmod_setup(); hostname_setup(); loopback_setup(); } - if ((r = manager_new(arg_running_as, arg_confirm_spawn, &m)) < 0) { + if ((r = manager_new(arg_running_as, &m)) < 0) { log_error("Failed to allocate manager object: %s", strerror(-r)); goto finish; } + m->confirm_spawn = arg_confirm_spawn; + m->show_status = arg_show_status; + if ((r = manager_startup(m, serialization, fds)) < 0) log_error("Failed to fully start up daemon: %s", strerror(-r));