chiark / gitweb /
build-sys: move public header files into a dir of their own
[elogind.git] / src / systemctl.c
index 7373e64e8c24c53011694634e01e767fc3136569..9b915f65d6248b6723a6c45f3bc438b151f3f13d 100644 (file)
@@ -35,6 +35,8 @@
 #include <sys/prctl.h>
 #include <dbus/dbus.h>
 
+#include <systemd/sd-daemon.h>
+
 #include "log.h"
 #include "util.h"
 #include "macro.h"
@@ -49,7 +51,6 @@
 #include "list.h"
 #include "path-lookup.h"
 #include "conf-parser.h"
-#include "sd-daemon.h"
 #include "shutdownd.h"
 #include "exit-status.h"
 #include "bus-errors.h"
@@ -58,6 +59,7 @@
 #include "pager.h"
 #include "spawn-agent.h"
 #include "install.h"
+#include "logs-show.h"
 
 static const char *arg_type = NULL;
 static char **arg_property = NULL;
@@ -117,6 +119,9 @@ static enum transport {
         TRANSPORT_POLKIT
 } arg_transport = TRANSPORT_NORMAL;
 static const char *arg_host = NULL;
+static bool arg_follow = false;
+static unsigned arg_lines = 10;
+static OutputMode arg_output = OUTPUT_SHORT;
 
 static bool private_bus = false;
 
@@ -377,8 +382,7 @@ static void output_units_list(const struct unit_info *unit_infos, unsigned c) {
 
                 n_shown++;
 
-                if (!streq(u->load_state, "loaded") &&
-                    !streq(u->load_state, "banned")) {
+                if (streq(u->load_state, "error")) {
                         on_loaded = ansi_highlight(true);
                         off_loaded = ansi_highlight(false);
                 } else
@@ -622,8 +626,6 @@ static int list_unit_files(DBusConnection *bus, char **args) {
 
         dbus_error_init(&error);
 
-        assert(bus);
-
         pager_open_if_enabled();
 
         if (avoid_bus()) {
@@ -659,6 +661,8 @@ static int list_unit_files(DBusConnection *bus, char **args) {
 
                 hashmap_free(h);
         } else {
+                assert(bus);
+
                 m = dbus_message_new_method_call(
                                 "org.freedesktop.systemd1",
                                 "/org/freedesktop/systemd1",
@@ -2001,6 +2005,7 @@ typedef struct UnitStatusInfo {
         const char *load_error;
 
         usec_t inactive_exit_timestamp;
+        usec_t inactive_exit_timestamp_monotonic;
         usec_t active_enter_timestamp;
         usec_t active_exit_timestamp;
         usec_t inactive_enter_timestamp;
@@ -2063,8 +2068,7 @@ static void print_status_info(UnitStatusInfo *i) {
         if (i->following)
                 printf("\t  Follow: unit currently follows state of %s\n", i->following);
 
-        if (streq_ptr(i->load_state, "failed") ||
-            streq_ptr(i->load_state, "banned")) {
+        if (streq_ptr(i->load_state, "error")) {
                 on = ansi_highlight(true);
                 off = ansi_highlight(false);
         } else
@@ -2201,7 +2205,7 @@ static void print_status_info(UnitStatusInfo *i) {
 
                         if (i->running) {
                                 char *t = NULL;
-                                get_process_name(i->main_pid, &t);
+                                get_process_comm(i->main_pid, &t);
                                 if (t) {
                                         printf(" (%s)", t);
                                         free(t);
@@ -2235,7 +2239,7 @@ static void print_status_info(UnitStatusInfo *i) {
 
                         printf(" Control: %u", (unsigned) i->control_pid);
 
-                        get_process_name(i->control_pid, &t);
+                        get_process_comm(i->control_pid, &t);
                         if (t) {
                                 printf(" (%s)", t);
                                 free(t);
@@ -2263,6 +2267,11 @@ static void print_status_info(UnitStatusInfo *i) {
                 }
         }
 
+        if (i->id && arg_transport != TRANSPORT_SSH) {
+                printf("\n");
+                show_journal_by_unit(i->id, arg_output, NULL, 0, i->inactive_exit_timestamp_monotonic, arg_lines, arg_all, arg_follow);
+        }
+
         if (i->need_daemon_reload)
                 printf("\n%sWarning:%s Unit file changed on disk, 'systemctl %s daemon-reload' recommended.\n",
                        ansi_highlight(true),
@@ -2387,6 +2396,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                         i->inactive_enter_timestamp = (usec_t) u;
                 else if (streq(name, "InactiveExitTimestamp"))
                         i->inactive_exit_timestamp = (usec_t) u;
+                else if (streq(name, "InactiveExitTimestampMonotonic"))
+                        i->inactive_exit_timestamp_monotonic = (usec_t) u;
                 else if (streq(name, "ActiveExitTimestamp"))
                         i->active_exit_timestamp = (usec_t) u;
                 else if (streq(name, "ConditionTimestamp"))
@@ -3965,7 +3976,10 @@ static int systemctl_help(void) {
                "  -f --force          When enabling unit files, override existing symlinks\n"
                "                      When shutting down, execute action immediately\n"
                "     --root=PATH      Enable unit files in the specified root directory\n"
-               "     --runtime        Enable unit files only temporarily until next reboot\n\n"
+               "     --runtime        Enable unit files only temporarily until next reboot\n"
+               "  -n --lines=INTEGER  Journal entries to show\n"
+               "     --follow         Follow journal\n"
+               "  -o --output=STRING  Change journal output mode (short, verbose, export, json)\n\n"
                "Unit Commands:\n"
                "  list-units                      List loaded units\n"
                "  start [NAME...]                 Start (activate) one or more units\n"
@@ -4116,7 +4130,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_KILL_WHO,
                 ARG_NO_ASK_PASSWORD,
                 ARG_FAILED,
-                ARG_RUNTIME
+                ARG_RUNTIME,
+                ARG_FOLLOW
         };
 
         static const struct option options[] = {
@@ -4149,6 +4164,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 { "host",      required_argument, NULL, 'H'           },
                 { "privileged",no_argument,       NULL, 'P'           },
                 { "runtime",   no_argument,       NULL, ARG_RUNTIME   },
+                { "lines",     required_argument, NULL, 'n'           },
+                { "follow",    no_argument,       NULL, ARG_FOLLOW    },
+                { "output",    required_argument, NULL, 'o'           },
                 { NULL,        0,                 NULL, 0             }
         };
 
@@ -4160,7 +4178,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
         /* Only when running as systemctl we ask for passwords */
         arg_ask_password = true;
 
-        while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:P", options, NULL)) >= 0) {
+        while ((c = getopt_long(argc, argv, "ht:p:aqfs:H:Pn:o:", options, NULL)) >= 0) {
 
                 switch (c) {
 
@@ -4298,6 +4316,25 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_runtime = true;
                         break;
 
+                case 'n':
+                        if (safe_atou(optarg, &arg_lines) < 0) {
+                                log_error("Failed to parse lines '%s'", optarg);
+                                return -EINVAL;
+                        }
+                        break;
+
+                case ARG_FOLLOW:
+                        arg_follow = true;
+                        break;
+
+                case 'o':
+                        arg_output = output_mode_from_string(optarg);
+                        if (arg_output < 0) {
+                                log_error("Unknown output '%s'.", optarg);
+                                return -EINVAL;
+                        }
+                        break;
+
                 case '?':
                         return -EINVAL;
 
@@ -5000,7 +5037,8 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
          * enable/disable */
         if (!streq(verbs[i].verb, "enable") &&
             !streq(verbs[i].verb, "disable") &&
-            !streq(verbs[i].verb, "is-enable") &&
+            !streq(verbs[i].verb, "is-enabled") &&
+            !streq(verbs[i].verb, "list-unit-files") &&
             !streq(verbs[i].verb, "reenable") &&
             !streq(verbs[i].verb, "preset") &&
             !streq(verbs[i].verb, "mask") &&