chiark / gitweb /
sd-daemon: drop SCM_CREDENTIALS passing since it is redundant, the kernel fills this...
[elogind.git] / src / systemctl.c
index 30f6b2a1e5ff305fa9842e9e721d33a65f76e09a..9da8303b2e997d8b1df80e66a91f5c249bf30709 100644 (file)
@@ -69,6 +69,11 @@ static bool arg_quiet = false;
 static bool arg_full = false;
 static bool arg_force = false;
 static bool arg_defaults = false;
+static bool arg_sysv_compat = false; /* this is undocumented, and
+                                      * exists simply to make
+                                      * implementation of SysV
+                                      * compatible shell glue
+                                      * easier */
 static char **arg_wall = NULL;
 static usec_t arg_when = 0;
 static enum action {
@@ -1359,7 +1364,7 @@ static int check_unit(DBusConnection *bus, char **args, unsigned n) {
                 if (!arg_quiet)
                         puts(state);
 
-                if (streq(state, "active") || startswith(state, "reloading"))
+                if (streq(state, "active") || streq(state, "reloading"))
                         r = 0;
 
                 dbus_message_unref(m);
@@ -1484,6 +1489,11 @@ typedef struct UnitStatusInfo {
         const char *path;
         const char *default_control_group;
 
+        usec_t inactive_exit_timestamp;
+        usec_t active_enter_timestamp;
+        usec_t active_exit_timestamp;
+        usec_t inactive_enter_timestamp;
+
         bool need_daemon_reload;
 
         /* Service */
@@ -1518,6 +1528,9 @@ typedef struct UnitStatusInfo {
 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 since2[FORMAT_TIMESTAMP_MAX], *s2;
 
         assert(i);
 
@@ -1554,17 +1567,34 @@ static void print_status_info(UnitStatusInfo *i) {
                 on = off = "";
 
         if (ss)
-                printf("\t  Active: %s%s (%s)%s\n",
+                printf("\t  Active: %s%s (%s)%s",
                        on,
                        strna(i->active_state),
                        ss,
                        off);
         else
-                printf("\t  Active: %s%s%s\n",
+                printf("\t  Active: %s%s%s",
                        on,
                        strna(i->active_state),
                        off);
 
+        timestamp = (streq_ptr(i->active_state, "active")      ||
+                     streq_ptr(i->active_state, "reloading"))   ? i->active_enter_timestamp :
+                    (streq_ptr(i->active_state, "inactive")    ||
+                     streq_ptr(i->active_state, "maintenance")) ? i->inactive_enter_timestamp :
+                    streq_ptr(i->active_state, "activating")    ? i->inactive_exit_timestamp :
+                                                                  i->active_exit_timestamp;
+
+        s1 = format_timestamp_pretty(since1, sizeof(since1), timestamp);
+        s2 = format_timestamp(since2, sizeof(since2), timestamp);
+
+        if (s1)
+                printf(" since [%s; %s]\n", s2, s1);
+        else if (s2)
+                printf(" since [%s]\n", s2);
+        else
+                printf("\n");
+
         if (i->sysfs_path)
                 printf("\t  Device: %s\n", i->sysfs_path);
         else if (i->where)
@@ -1583,7 +1613,7 @@ static void print_status_info(UnitStatusInfo *i) {
                         continue;
 
                 t = strv_join(p->argv, " ");
-                printf("\t  Exited: %u (%s, code=%s, ", p->pid, strna(t), sigchld_code_to_string(p->code));
+                printf("\t Process: %u (%s, code=%s, ", p->pid, strna(t), sigchld_code_to_string(p->code));
                 free(t);
 
                 if (p->code == CLD_EXITED) {
@@ -1612,7 +1642,7 @@ static void print_status_info(UnitStatusInfo *i) {
                 printf("\t");
 
                 if (i->main_pid > 0) {
-                        printf("    Main: %u", (unsigned) i->main_pid);
+                        printf("Main PID: %u", (unsigned) i->main_pid);
 
                         if (i->running) {
                                 char *t = NULL;
@@ -1777,6 +1807,14 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                         i->start_timestamp = (usec_t) u;
                 else if (streq(name, "ExecMainExitTimestamp"))
                         i->exit_timestamp = (usec_t) u;
+                else if (streq(name, "ActiveEnterTimestamp"))
+                        i->active_enter_timestamp = (usec_t) u;
+                else if (streq(name, "InactiveEnterTimestamp"))
+                        i->inactive_enter_timestamp = (usec_t) u;
+                else if (streq(name, "InactiveExitTimestamp"))
+                        i->inactive_exit_timestamp = (usec_t) u;
+                else if (streq(name, "ActiveExitTimestamp"))
+                        i->active_exit_timestamp = (usec_t) u;
 
                 break;
         }
@@ -2150,16 +2188,27 @@ static int show_one(DBusConnection *bus, const char *path, bool show_properties,
                 dbus_message_iter_next(&sub);
         }
 
-        if (!show_properties)
-                print_status_info(&info);
+        r = 0;
+
+        if (!show_properties) {
+                if (arg_sysv_compat &&
+                    !streq_ptr(info.active_state, "active") &&
+                    !streq_ptr(info.active_state, "reloading")) {
+
+                        /* If the SysV compatibility mode is on, we
+                         * will refuse to run "status" on units that
+                         * aren't active */
+                        log_error("Unit not active.");
+                        r = -EADDRNOTAVAIL;
+                } else
+                        print_status_info(&info);
+        }
 
         while ((p = info.exec)) {
                 LIST_REMOVE(ExecStatusInfo, exec, info.exec, p);
                 exec_status_info_free(p);
         }
 
-        r = 0;
-
 finish:
         if (m)
                 dbus_message_unref(m);
@@ -3895,7 +3944,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_FULL,
                 ARG_FORCE,
                 ARG_NO_RELOAD,
-                ARG_DEFAULTS
+                ARG_DEFAULTS,
+                ARG_SYSV_COMPAT
         };
 
         static const struct option options[] = {
@@ -3915,7 +3965,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "require",   no_argument,       NULL, ARG_REQUIRE   },
                 { "force",     no_argument,       NULL, ARG_FORCE     },
                 { "no-reload", no_argument,       NULL, ARG_NO_RELOAD },
-                { "defaults",   no_argument,      NULL, ARG_DEFAULTS  },
+                { "defaults",  no_argument,       NULL, ARG_DEFAULTS  },
+                { "sysv-compat", no_argument,     NULL, ARG_SYSV_COMPAT },
                 { NULL,        0,                 NULL, 0             }
         };
 
@@ -4009,6 +4060,10 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_defaults = true;
                         break;
 
+                case ARG_SYSV_COMPAT:
+                        arg_sysv_compat = true;
+                        break;
+
                 case '?':
                         return -EINVAL;