chiark / gitweb /
core: add missing show-status.[ch]
[elogind.git] / src / core / main.c
index fc85eedfe923ee3a40edf4670af21944a38d7244..4ca847c78124daf63f6f28263b31681ee18bf7b7 100644 (file)
@@ -35,6 +35,9 @@
 #ifdef HAVE_VALGRIND_VALGRIND_H
 #include <valgrind/valgrind.h>
 #endif
+#ifdef HAVE_SECCOMP
+#include <seccomp.h>
+#endif
 
 #include "sd-daemon.h"
 #include "sd-messages.h"
@@ -51,6 +54,7 @@
 #include "strv.h"
 #include "def.h"
 #include "virt.h"
+#include "architecture.h"
 #include "watchdog.h"
 #include "path-util.h"
 #include "switch-root.h"
@@ -88,7 +92,7 @@ static bool arg_dump_core = true;
 static bool arg_crash_shell = false;
 static int arg_crash_chvt = -1;
 static bool arg_confirm_spawn = false;
-static ShowStatus arg_show_status = SHOW_STATUS_UNSET;
+static ShowStatus arg_show_status = _SHOW_STATUS_UNSET;
 static bool arg_switched_root = false;
 static char ***arg_join_controllers = NULL;
 static ExecOutput arg_default_std_output = EXEC_OUTPUT_JOURNAL;
@@ -106,6 +110,9 @@ static uint64_t arg_capability_bounding_set_drop = 0;
 static nsec_t arg_timer_slack_nsec = (nsec_t) -1;
 static Set* arg_syscall_archs = NULL;
 static FILE* arg_serialization = NULL;
+static bool arg_default_cpu_accounting = false;
+static bool arg_default_blockio_accounting = false;
+static bool arg_default_memory_accounting = false;
 
 static void nop_handler(int sig) {}
 
@@ -303,7 +310,8 @@ static int parse_proc_cmdline_word(const char *word) {
         } else if (startswith(word, "systemd.dump_core=")) {
                 int r;
 
-                if ((r = parse_boolean(word + 18)) < 0)
+                r = parse_boolean(word + 18);
+                if (r < 0)
                         log_warning("Failed to parse dump core switch %s. Ignoring.", word + 18);
                 else
                         arg_dump_core = r;
@@ -311,7 +319,8 @@ static int parse_proc_cmdline_word(const char *word) {
         } else if (startswith(word, "systemd.crash_shell=")) {
                 int r;
 
-                if ((r = parse_boolean(word + 20)) < 0)
+                r = parse_boolean(word + 20);
+                if (r < 0)
                         log_warning("Failed to parse crash shell switch %s. Ignoring.", word + 20);
                 else
                         arg_crash_shell = r;
@@ -319,7 +328,8 @@ static int parse_proc_cmdline_word(const char *word) {
         } else if (startswith(word, "systemd.confirm_spawn=")) {
                 int r;
 
-                if ((r = parse_boolean(word + 22)) < 0)
+                r = parse_boolean(word + 22);
+                if (r < 0)
                         log_warning("Failed to parse confirm spawn switch %s. Ignoring.", word + 22);
                 else
                         arg_confirm_spawn = r;
@@ -341,23 +351,21 @@ static int parse_proc_cmdline_word(const char *word) {
         } else if (startswith(word, "systemd.default_standard_output=")) {
                 int r;
 
-                if ((r = exec_output_from_string(word + 32)) < 0)
+                r = exec_output_from_string(word + 32);
+                if (r < 0)
                         log_warning("Failed to parse default standard output switch %s. Ignoring.", word + 32);
                 else
                         arg_default_std_output = r;
         } else if (startswith(word, "systemd.default_standard_error=")) {
                 int r;
 
-                if ((r = exec_output_from_string(word + 31)) < 0)
+                r = exec_output_from_string(word + 31);
+                if (r < 0)
                         log_warning("Failed to parse default standard error switch %s. Ignoring.", word + 31);
                 else
                         arg_default_std_error = r;
         } else if (startswith(word, "systemd.setenv=")) {
-                _cleanup_free_ char *cenv = NULL;
-
-                cenv = strdup(word + 15);
-                if (!cenv)
-                        return -ENOMEM;
+                const char *cenv = word + 15;
 
                 if (env_assignment_is_valid(cenv)) {
                         char **env;
@@ -366,7 +374,8 @@ static int parse_proc_cmdline_word(const char *word) {
                         if (env)
                                 arg_default_environment = env;
                         else
-                                log_warning("Setting environment variable '%s' failed, ignoring: %m", cenv);
+                                log_warning("Setting environment variable '%s' failed, ignoring: %s",
+                                            cenv, strerror(ENOMEM));
                 } else
                         log_warning("Environment variable name '%s' is not valid. Ignoring.", cenv);
 
@@ -406,7 +415,7 @@ static int parse_proc_cmdline_word(const char *word) {
                 }
 
         } else if (streq(word, "quiet")) {
-                if (arg_show_status == SHOW_STATUS_UNSET)
+                if (arg_show_status == _SHOW_STATUS_UNSET)
                         arg_show_status = SHOW_STATUS_AUTO;
         } else if (streq(word, "debug")) {
                 /* Log to kmsg, the journal socket will fill up before the
@@ -459,16 +468,17 @@ DEFINE_SETTER(config_parse_target, log_set_target_from_string, "target")
 DEFINE_SETTER(config_parse_color, log_show_color_from_string, "color" )
 DEFINE_SETTER(config_parse_location, log_show_location_from_string, "location")
 
-static int config_parse_cpu_affinity2(const char *unit,
-                                      const char *filename,
-                                      unsigned line,
-                                      const char *section,
-                                      unsigned section_line,
-                                      const char *lvalue,
-                                      int ltype,
-                                      const char *rvalue,
-                                      void *data,
-                                      void *userdata) {
+static int config_parse_cpu_affinity2(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
 
         char *w;
         size_t l;
@@ -515,6 +525,36 @@ static int config_parse_cpu_affinity2(const char *unit,
         return 0;
 }
 
+static int config_parse_show_status(
+                const char* unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        int k;
+        ShowStatus *b = data;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        k = parse_show_status(rvalue, b);
+        if (k < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, -k,
+                           "Failed to parse show status setting, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        return 0;
+}
+
 static void strv_free_free(char ***l) {
         char ***i;
 
@@ -670,6 +710,9 @@ static int parse_config_file(void) {
                 { "Manager", "DefaultLimitNICE",          config_parse_limit,            0, &arg_default_rlimit[RLIMIT_NICE]       },
                 { "Manager", "DefaultLimitRTPRIO",        config_parse_limit,            0, &arg_default_rlimit[RLIMIT_RTPRIO]     },
                 { "Manager", "DefaultLimitRTTIME",        config_parse_limit,            0, &arg_default_rlimit[RLIMIT_RTTIME]     },
+                { "Manager", "DefaultCPUAccounting",      config_parse_bool,             0, &arg_default_cpu_accounting            },
+                { "Manager", "DefaultBlockIOAccounting",  config_parse_bool,             0, &arg_default_blockio_accounting        },
+                { "Manager", "DefaultMemoryAccounting",   config_parse_bool,             0, &arg_default_memory_accounting         },
                 {}
         };
 
@@ -737,7 +780,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "switched-root",            no_argument,       NULL, ARG_SWITCHED_ROOT            },
                 { "default-standard-output",  required_argument, NULL, ARG_DEFAULT_STD_OUTPUT,      },
                 { "default-standard-error",   required_argument, NULL, ARG_DEFAULT_STD_ERROR,       },
-                { NULL,                       0,                 NULL, 0                            }
+                {}
         };
 
         int c, r;
@@ -753,7 +796,8 @@ static int parse_argv(int argc, char *argv[]) {
                 switch (c) {
 
                 case ARG_LOG_LEVEL:
-                        if ((r = log_set_max_level_from_string(optarg)) < 0) {
+                        r = log_set_max_level_from_string(optarg);
+                        if (r < 0) {
                                 log_error("Failed to parse log level %s.", optarg);
                                 return r;
                         }
@@ -761,8 +805,8 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_LOG_TARGET:
-
-                        if ((r = log_set_target_from_string(optarg)) < 0) {
+                        r = log_set_target_from_string(optarg);
+                        if (r < 0) {
                                 log_error("Failed to parse log target %s.", optarg);
                                 return r;
                         }
@@ -772,7 +816,8 @@ static int parse_argv(int argc, char *argv[]) {
                 case ARG_LOG_COLOR:
 
                         if (optarg) {
-                                if ((r = log_show_color_from_string(optarg)) < 0) {
+                                r = log_show_color_from_string(optarg);
+                                if (r < 0) {
                                         log_error("Failed to parse log color setting %s.", optarg);
                                         return r;
                                 }
@@ -782,9 +827,9 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_LOG_LOCATION:
-
                         if (optarg) {
-                                if ((r = log_show_location_from_string(optarg)) < 0) {
+                                r = log_show_location_from_string(optarg);
+                                if (r < 0) {
                                         log_error("Failed to parse log location setting %s.", optarg);
                                         return r;
                                 }
@@ -794,8 +839,8 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_DEFAULT_STD_OUTPUT:
-
-                        if ((r = exec_output_from_string(optarg)) < 0) {
+                        r = exec_output_from_string(optarg);
+                        if (r < 0) {
                                 log_error("Failed to parse default standard output setting %s.", optarg);
                                 return r;
                         } else
@@ -803,8 +848,8 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_DEFAULT_STD_ERROR:
-
-                        if ((r = exec_output_from_string(optarg)) < 0) {
+                        r = exec_output_from_string(optarg);
+                        if (r < 0) {
                                 log_error("Failed to parse default standard error output setting %s.", optarg);
                                 return r;
                         } else
@@ -813,7 +858,8 @@ static int parse_argv(int argc, char *argv[]) {
 
                 case ARG_UNIT:
 
-                        if ((r = set_default_unit(optarg)) < 0) {
+                        r = set_default_unit(optarg);
+                        if (r < 0) {
                                 log_error("Failed to set default unit %s: %s", optarg, strerror(-r));
                                 return r;
                         }
@@ -1186,6 +1232,12 @@ static int enforce_syscall_archs(Set *archs) {
                 }
         }
 
+        r = seccomp_attr_set(seccomp, SCMP_FLTATR_CTL_NNP, 0);
+        if (r < 0) {
+                log_error("Failed to unset NO_NEW_PRIVS: %s", strerror(-r));
+                goto finish;
+        }
+
         r = seccomp_load(seccomp);
         if (r < 0)
                 log_error("Failed to add install architecture seccomp: %s", strerror(-r));
@@ -1198,6 +1250,24 @@ finish:
 #endif
 }
 
+static int status_welcome(void) {
+        _cleanup_free_ char *pretty_name = NULL, *ansi_color = NULL;
+        int r;
+
+        r = parse_env_file("/etc/os-release", NEWLINE,
+                           "PRETTY_NAME", &pretty_name,
+                           "ANSI_COLOR", &ansi_color,
+                           NULL);
+
+        if (r < 0 && r != -ENOENT)
+                log_warning("Failed to read /etc/os-release: %s", strerror(-r));
+
+        return status_printf(NULL, false, false,
+                             "\nWelcome to \x1B[%sm%s\x1B[0m!\n",
+                             isempty(ansi_color) ? "1" : ansi_color,
+                             isempty(pretty_name) ? "Linux" : pretty_name);
+}
+
 int main(int argc, char *argv[]) {
         Manager *m = NULL;
         int r, retval = EXIT_FAILURE;
@@ -1280,7 +1350,7 @@ int main(int argc, char *argv[]) {
                                 goto finish;
                         if (ima_setup() < 0)
                                 goto finish;
-                        if (smack_setup() < 0)
+                        if (smack_setup(&loaded_policy) < 0)
                                 goto finish;
                         dual_timestamp_get(&security_finish_timestamp);
                 }
@@ -1459,6 +1529,9 @@ int main(int argc, char *argv[]) {
         /* Open the logging devices, if possible and necessary */
         log_open();
 
+        if (arg_show_status == _SHOW_STATUS_UNSET)
+                arg_show_status = SHOW_STATUS_YES;
+
         /* Make sure we leave a core dump without panicing the
          * kernel. */
         if (getpid() == 1) {
@@ -1478,6 +1551,8 @@ int main(int argc, char *argv[]) {
                 if (virtualization)
                         log_info("Detected virtualization '%s'.", virtualization);
 
+                log_info("Detected architecture '%s'.", architecture_to_string(uname_architecture()));
+
                 if (in_initrd())
                         log_info("Running in initial RAM disk.");
 
@@ -1556,6 +1631,9 @@ int main(int argc, char *argv[]) {
         m->default_timeout_stop_usec = arg_default_timeout_stop_usec;
         m->default_start_limit_interval = arg_default_start_limit_interval;
         m->default_start_limit_burst = arg_default_start_limit_burst;
+        m->default_cpu_accounting = arg_default_cpu_accounting;
+        m->default_blockio_accounting = arg_default_blockio_accounting;
+        m->default_memory_accounting = arg_default_memory_accounting;
         m->runtime_watchdog = arg_runtime_watchdog;
         m->shutdown_watchdog = arg_shutdown_watchdog;
         m->userspace_timestamp = userspace_timestamp;
@@ -1565,12 +1643,7 @@ int main(int argc, char *argv[]) {
         m->security_finish_timestamp = security_finish_timestamp;
 
         manager_set_default_rlimits(m, arg_default_rlimit);
-
-        if (arg_default_environment)
-                manager_environment_add(m, NULL, arg_default_environment);
-
-        if (arg_show_status == SHOW_STATUS_UNSET)
-                arg_show_status = SHOW_STATUS_YES;
+        manager_environment_add(m, NULL, arg_default_environment);
         manager_set_show_status(m, arg_show_status);
 
         /* Remember whether we should queue the default job */
@@ -1876,14 +1949,42 @@ finish:
 #endif
 
         if (shutdown_verb) {
-                const char * command_line[] = {
+                char log_level[DECIMAL_STR_MAX(int) + 1];
+                const char* command_line[9] = {
                         SYSTEMD_SHUTDOWN_BINARY_PATH,
                         shutdown_verb,
-                        NULL
+                        "--log-level", log_level,
+                        "--log-target",
                 };
+                unsigned pos = 5;
                 _cleanup_strv_free_ char **env_block = NULL;
+
+                assert(command_line[pos] == NULL);
                 env_block = strv_copy(environ);
 
+                snprintf(log_level, sizeof(log_level), "%d", log_get_max_level());
+
+                switch (log_get_target()) {
+                case LOG_TARGET_KMSG:
+                case LOG_TARGET_JOURNAL_OR_KMSG:
+                case LOG_TARGET_SYSLOG_OR_KMSG:
+                        command_line[pos++] = "kmsg";
+                        break;
+
+                case LOG_TARGET_CONSOLE:
+                default:
+                        command_line[pos++] = "console";
+                        break;
+                };
+
+                if (log_get_show_color())
+                        command_line[pos++] = "--log-color";
+
+                if (log_get_show_location())
+                        command_line[pos++] = "--log-location";
+
+                assert(pos + 1 < ELEMENTSOF(command_line));
+
                 if (arm_reboot_watchdog && arg_shutdown_watchdog > 0) {
                         char *e;
 
@@ -1906,7 +2007,8 @@ finish:
                         cg_uninstall_release_agent(SYSTEMD_CGROUP_CONTROLLER);
 
                 execve(SYSTEMD_SHUTDOWN_BINARY_PATH, (char **) command_line, env_block);
-                log_error("Failed to execute shutdown binary, freezing: %m");
+                log_error("Failed to execute shutdown binary, %s: %m",
+                          getpid() == 1 ? "freezing" : "quitting");
         }
 
         if (getpid() == 1)