chiark / gitweb /
systemctl: enable chkconfig compat only if chkconfig is found rather than based on...
[elogind.git] / src / systemctl / systemctl.c
index b82c79435d29acf9cd2f8c5ac937c5de73ffe01f..b71d5de30a6f2c48979422646be152e64b9e3ab3 100644 (file)
@@ -426,6 +426,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
                                "SUB    = The low-level unit activation state, values depend on unit type.\n");
                         if (job_count)
                                 printf("JOB    = Pending job for the unit.\n");
+                        puts("");
                         on = ansi_highlight(true);
                         off = ansi_highlight(false);
                 } else {
@@ -434,11 +435,11 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
                 }
 
                 if (arg_all)
-                        printf("\n%s%u loaded units listed.%s\n"
+                        printf("%s%u loaded units listed.%s\n"
                                "To show all installed unit files use 'systemctl list-unit-files'.\n",
                                on, n_shown, off);
                 else
-                        printf("\n%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
+                        printf("%s%u loaded units listed.%s Pass --all to see loaded but inactive units, too.\n"
                                "To show all installed unit files use 'systemctl list-unit-files'.\n",
                                on, n_shown, off);
         }
@@ -1341,9 +1342,9 @@ static int wait_for_jobs(DBusConnection *bus, Set *s) {
                         else if (streq(d.result, "canceled"))
                                 log_error("Job for %s canceled.", strna(d.name));
                         else if (streq(d.result, "dependency"))
-                                log_error("A dependency job for %s failed. See 'journalctl -n' for details.", strna(d.name));
+                                log_error("A dependency job for %s failed. See 'journalctl -xn' for details.", strna(d.name));
                         else if (!streq(d.result, "done") && !streq(d.result, "skipped"))
-                                log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -n' for details.", strna(d.name), strna(d.name));
+                                log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xn' for details.", strna(d.name), strna(d.name));
                 }
 
                 if (streq_ptr(d.result, "timeout"))
@@ -1365,7 +1366,7 @@ static int wait_for_jobs(DBusConnection *bus, Set *s) {
         return r;
 }
 
-static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
+static int check_one_unit(DBusConnection *bus, char *name, char **check_states, bool quiet) {
         DBusMessage *reply = NULL;
         DBusMessageIter iter, sub;
         const char
@@ -1439,7 +1440,7 @@ static int check_one_unit(DBusConnection *bus, char *name, bool quiet) {
         if (!quiet)
                 puts(state);
 
-        if (streq(state, "active") || streq(state, "reloading"))
+        if (strv_find(check_states, state))
                 r = 0;
         else
                 r = 3; /* According to LSB: "program is not running" */
@@ -1502,6 +1503,7 @@ static void check_triggering_units(
         sub = iter;
 
         while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+                char **check_states = NULL;
 
                 if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRING) {
                         log_error("Failed to parse reply.");
@@ -1510,7 +1512,9 @@ static void check_triggering_units(
 
                 dbus_message_iter_get_basic(&sub, &service_trigger);
 
-                r = check_one_unit(bus, service_trigger, true);
+                check_states = strv_new("active", "reloading", NULL);
+                r = check_one_unit(bus, service_trigger, check_states, true);
+                strv_free(check_states);
                 if (r < 0)
                         return;
                 if (r == 0) {
@@ -1846,7 +1850,7 @@ static int start_special(DBusConnection *bus, char **args) {
         return r;
 }
 
-static int check_unit(DBusConnection *bus, char **args) {
+static int check_unit_active(DBusConnection *bus, char **args) {
         char **name;
         int r = 3; /* According to LSB: "program is not running" */
 
@@ -1854,7 +1858,29 @@ static int check_unit(DBusConnection *bus, char **args) {
         assert(args);
 
         STRV_FOREACH(name, args+1) {
-                int state = check_one_unit(bus, *name, arg_quiet);
+                char **check_states = strv_new("active", "reloading", NULL);
+                int state = check_one_unit(bus, *name, check_states, arg_quiet);
+                strv_free(check_states);
+                if (state < 0)
+                        return state;
+                if (state == 0)
+                        r = 0;
+        }
+
+        return r;
+}
+
+static int check_unit_failed(DBusConnection *bus, char **args) {
+        char **name;
+        int r = 1;
+
+        assert(bus);
+        assert(args);
+
+        STRV_FOREACH(name, args+1) {
+                char **check_states = strv_new("failed", NULL);
+                int state = check_one_unit(bus, *name, check_states, arg_quiet);
+                strv_free(check_states);
                 if (state < 0)
                         return state;
                 if (state == 0)
@@ -2055,7 +2081,7 @@ static void print_status_info(UnitStatusInfo *i) {
         ExecStatusInfo *p;
         const char *on, *off, *ss;
         usec_t timestamp;
-        char since1[FORMAT_TIMESTAMP_PRETTY_MAX], *s1;
+        char since1[FORMAT_TIMESTAMP_RELATIVE_MAX], *s1;
         char since2[FORMAT_TIMESTAMP_MAX], *s2;
         const char *path;
 
@@ -2124,7 +2150,7 @@ static void print_status_info(UnitStatusInfo *i) {
                     streq_ptr(i->active_state, "activating")    ? i->inactive_exit_timestamp :
                                                                   i->active_exit_timestamp;
 
-        s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
+        s1 = format_timestamp_relative(since1, sizeof(since1), timestamp);
         s2 = format_timestamp(since2, sizeof(since2), timestamp);
 
         if (s1)
@@ -2135,7 +2161,7 @@ static void print_status_info(UnitStatusInfo *i) {
                 printf("\n");
 
         if (!i->condition_result && i->condition_timestamp > 0) {
-                s1 = format_timestamp_pretty(since1, sizeof(since1), i->condition_timestamp);
+                s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
                 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
 
                 if (s1)
@@ -2264,7 +2290,8 @@ static void print_status_info(UnitStatusInfo *i) {
         if (i->status_text)
                 printf("\t  Status: \"%s\"\n", i->status_text);
 
-        if (i->default_control_group) {
+        if (i->default_control_group &&
+            (i->main_pid > 0 || i->control_pid > 0 || cg_is_empty_by_spec(i->default_control_group, false) == 0)) {
                 unsigned c;
 
                 printf("\t  CGroup: %s\n", i->default_control_group);
@@ -3322,7 +3349,8 @@ finish:
 
 static int switch_root(DBusConnection *bus, char **args) {
         unsigned l;
-        const char *root, *init;
+        const char *root;
+        _cleanup_free_ char *init = NULL;
 
         l = strv_length(args);
         if (l < 2 || l > 3) {
@@ -3331,7 +3359,23 @@ static int switch_root(DBusConnection *bus, char **args) {
         }
 
         root = args[1];
-        init = l >= 3 ? args[2] : "";
+
+        if (l >= 3)
+                init = strdup(args[2]);
+        else {
+                parse_env_file("/proc/cmdline", WHITESPACE,
+                               "init", &init,
+                               NULL);
+
+                if (!init)
+                        init = strdup("");
+
+                if (!init)
+                        return log_oom();
+
+        }
+
+        log_debug("switching root - root: %s; init: %s", root, init);
 
         return bus_method_call_with_reply (
                         bus,
@@ -3392,7 +3436,7 @@ finish:
 static int enable_sysv_units(char **args) {
         int r = 0;
 
-#if defined (HAVE_SYSV_COMPAT) && (defined(TARGET_FEDORA) || defined(TARGET_MANDRIVA) || defined(TARGET_SUSE) || defined(TARGET_ALTLINUX) || defined(TARGET_MAGEIA))
+#if defined(HAVE_SYSV_COMPAT) && defined(HAVE_CHKCONFIG)
         const char *verb = args[0];
         unsigned f = 1, t = 1;
         LookupPaths paths;
@@ -3781,7 +3825,16 @@ static int enable_unit(DBusConnection *bus, char **args) {
         }
 
         if (carries_install_info == 0)
-                log_warning("The unit files have no [Install] section. They are not meant to be enabled using systemctl.");
+                log_warning(
+"The unit files have no [Install] section. They are not meant to be enabled\n"
+"using systemctl.\n"
+"Possible reasons for having this kind of units are:\n"
+"1) A unit may be statically enabled by being symlinked from another unit's\n"
+"   .wants/ or .requires/ directory.\n"
+"2) A unit's purpose may be to act as a helper for some other unit which has\n"
+"   a requirement dependency on it.\n"
+"3) A unit may be started when needed via activation (socket, path, timer,\n"
+"   D-Bus, udev, scripted systemctl call, ...).\n");
 
 finish:
         if (m)
@@ -3932,13 +3985,14 @@ static int systemctl_help(void) {
                "  reload [NAME...]                Reload one or more units\n"
                "  restart [NAME...]               Start or restart one or more units\n"
                "  try-restart [NAME...]           Restart one or more units if active\n"
-               "  reload-or-restart [NAME...]     Reload one or more units is possible,\n"
+               "  reload-or-restart [NAME...]     Reload one or more units if possible,\n"
                "                                  otherwise start or restart\n"
-               "  reload-or-try-restart [NAME...] Reload one or more units is possible,\n"
+               "  reload-or-try-restart [NAME...] Reload one or more units if possible,\n"
                "                                  otherwise restart if active\n"
                "  isolate [NAME]                  Start one unit and stop all others\n"
                "  kill [NAME...]                  Send signal to processes of a unit\n"
                "  is-active [NAME...]             Check whether units are active\n"
+               "  is-failed [NAME...]             Check whether units are failed\n"
                "  status [NAME...|PID...]         Show runtime status of one or more units\n"
                "  show [NAME...|JOB...]           Show properties of one or more\n"
                "                                  units/jobs or the manager\n"
@@ -4057,6 +4111,22 @@ static int runlevel_help(void) {
         return 0;
 }
 
+static int help_types(void) {
+        int i;
+
+        puts("Available unit types:");
+        for(i = UNIT_SERVICE; i < _UNIT_TYPE_MAX; i++)
+                if (unit_type_table[i])
+                        puts(unit_type_table[i]);
+
+        puts("\nAvailable unit load states: ");
+        for(i = UNIT_STUB; i < _UNIT_LOAD_STATE_MAX; i++)
+                if (unit_type_table[i])
+                        puts(unit_load_state_table[i]);
+
+        return 0;
+}
+
 static int systemctl_parse_argv(int argc, char *argv[]) {
 
         enum {
@@ -4136,6 +4206,11 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         return 0;
 
                 case 't':
+                        if (streq(optarg, "help")) {
+                                help_types();
+                                return 0;
+                        }
+
                         if (unit_type_from_string(optarg) >= 0) {
                                 arg_type = optarg;
                                 break;
@@ -4146,6 +4221,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         }
                         log_error("Unkown unit type or load state '%s'.",
                                   optarg);
+                        log_info("Use -t help to see a list of allowed values.");
                         return -EINVAL;
                 case 'p': {
                         char **l;
@@ -4895,8 +4971,9 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "condrestart",           MORE,  2, start_unit        }, /* For compatibility with RH */
                 { "isolate",               EQUAL, 2, start_unit        },
                 { "kill",                  MORE,  2, kill_unit         },
-                { "is-active",             MORE,  2, check_unit        },
-                { "check",                 MORE,  2, check_unit        },
+                { "is-active",             MORE,  2, check_unit_active },
+                { "check",                 MORE,  2, check_unit_active },
+                { "is-failed",             MORE,  2, check_unit_failed },
                 { "show",                  MORE,  1, show              },
                 { "status",                MORE,  2, show              },
                 { "help",                  MORE,  2, show              },