chiark / gitweb /
systemctl: move "dump" command from systemctl to systemd-analyze
[elogind.git] / src / systemctl / systemctl.c
index 6fdbc417b6e28776344d68edb30451531c32e889..4e33a4182f219e1bc9cdf7972da0b516faacf231 100644 (file)
@@ -69,7 +69,7 @@
 #include "fileio.h"
 
 static char **arg_types = NULL;
-static char **arg_load_states = NULL;
+static char **arg_states = NULL;
 static char **arg_properties = NULL;
 static bool arg_all = false;
 static enum dependency {
@@ -93,7 +93,6 @@ static bool arg_quiet = false;
 static bool arg_full = false;
 static int arg_force = 0;
 static bool arg_ask_password = true;
-static bool arg_failed = false;
 static bool arg_runtime = false;
 static char **arg_wall = NULL;
 static const char *arg_kill_who = NULL;
@@ -301,12 +300,11 @@ static int compare_unit_info(const void *a, const void *b) {
 static bool output_show_unit(const struct unit_info *u) {
         const char *dot;
 
-        if (arg_failed)
-                return streq(u->active_state, "failed");
+        if (!strv_isempty(arg_states))
+                return strv_contains(arg_states, u->load_state) || strv_contains(arg_states, u->sub_state) || strv_contains(arg_states, u->active_state);
 
         return (!arg_types || ((dot = strrchr(u->id, '.')) &&
                                strv_find(arg_types, dot+1))) &&
-                (!arg_load_states || strv_find(arg_load_states, u->load_state)) &&
                 (arg_all || !(streq(u->active_state, "inactive")
                               || u->following[0]) || u->job_id > 0);
 }
@@ -2534,6 +2532,10 @@ typedef struct UnitStatusInfo {
 
         usec_t condition_timestamp;
         bool condition_result;
+        bool failed_condition_trigger;
+        bool failed_condition_negate;
+        const char *failed_condition;
+        const char *failed_condition_param;
 
         /* Socket */
         unsigned n_accepted;
@@ -2676,10 +2678,15 @@ static void print_status_info(UnitStatusInfo *i) {
                 s1 = format_timestamp_relative(since1, sizeof(since1), i->condition_timestamp);
                 s2 = format_timestamp(since2, sizeof(since2), i->condition_timestamp);
 
-                if (s1)
-                        printf("          start condition failed at %s; %s\n", s2, s1);
-                else if (s2)
-                        printf("          start condition failed at %s\n", s2);
+                printf("           start condition failed at %s%s%s\n",
+                       s2, s1 ? "; " : "", s1 ? s1 : "");
+                if (i->failed_condition_trigger)
+                        printf("           none of the trigger conditions were met\n");
+                else if (i->failed_condition)
+                        printf("           %s=%s%s was not met\n",
+                               i->failed_condition,
+                               i->failed_condition_negate ? "!" : "",
+                               i->failed_condition_param);
         }
 
         if (i->sysfs_path)
@@ -3038,15 +3045,18 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                                 ExecStatusInfo *info;
                                 int r;
 
-                                if (!(info = new0(ExecStatusInfo, 1)))
+                                info = new0(ExecStatusInfo, 1);
+                                if (!info)
                                         return -ENOMEM;
 
-                                if (!(info->name = strdup(name))) {
+                                info->name = strdup(name);
+                                if (!info->name) {
                                         free(info);
                                         return -ENOMEM;
                                 }
 
-                                if ((r = exec_status_info_deserialize(&sub, info)) < 0) {
+                                r = exec_status_info_deserialize(&sub, info);
+                                if (r < 0) {
                                         free(info);
                                         return r;
                                 }
@@ -3056,7 +3066,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
                                 dbus_message_iter_next(&sub);
                         }
 
-                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Listen")) {
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
+                           streq(name, "Listen")) {
                         DBusMessageIter sub, sub2;
 
                         dbus_message_iter_recurse(iter, &sub);
@@ -3082,7 +3093,8 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
 
                         return 0;
 
-                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING && streq(name, "DropInPaths")) {
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRING &&
+                           streq(name, "DropInPaths")) {
                         int r = bus_parse_strv_iter(iter, &i->dropin_paths);
                         if (r < 0)
                                 return r;
@@ -3105,6 +3117,36 @@ static int status_property(const char *name, DBusMessageIter *iter, UnitStatusIn
 
                                 dbus_message_iter_next(&sub);
                         }
+
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT &&
+                           streq(name, "Conditions")) {
+                        DBusMessageIter sub, sub2;
+
+                        dbus_message_iter_recurse(iter, &sub);
+                        while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+                                const char *cond, *param;
+                                dbus_bool_t trigger, negate;
+                                dbus_int32_t state;
+
+                                dbus_message_iter_recurse(&sub, &sub2);
+                                log_debug("here");
+
+                                if(bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &cond, true) >= 0 &&
+                                   bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &trigger, true) >= 0 &&
+                                   bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_BOOLEAN, &negate, true) >= 0 &&
+                                   bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &param, true) >= 0 &&
+                                   bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &state, false) >= 0) {
+                                        log_debug("%s %d %d %s %d", cond, trigger, negate, param, state);
+                                        if (state < 0 && (!trigger || !i->failed_condition)) {
+                                                i->failed_condition = cond;
+                                                i->failed_condition_trigger = trigger;
+                                                i->failed_condition_negate = negate;
+                                                i->failed_condition_param = param;
+                                        }
+                                }
+
+                                dbus_message_iter_next(&sub);
+                        }
                 }
 
                 break;
@@ -3755,40 +3797,6 @@ static int set_property(DBusConnection *bus, char **args) {
         return 0;
 }
 
-static int dump(DBusConnection *bus, char **args) {
-        _cleanup_free_ DBusMessage *reply = NULL;
-        DBusError error;
-        int r;
-        const char *text;
-
-        dbus_error_init(&error);
-
-        pager_open_if_enabled();
-
-        r = bus_method_call_with_reply(
-                        bus,
-                        "org.freedesktop.systemd1",
-                        "/org/freedesktop/systemd1",
-                        "org.freedesktop.systemd1.Manager",
-                        "Dump",
-                        &reply,
-                        NULL,
-                        DBUS_TYPE_INVALID);
-        if (r < 0)
-                return r;
-
-        if (!dbus_message_get_args(reply, &error,
-                                   DBUS_TYPE_STRING, &text,
-                                   DBUS_TYPE_INVALID)) {
-                log_error("Failed to parse reply: %s", bus_error_message(&error));
-                dbus_error_free(&error);
-                return  -EIO;
-        }
-
-        fputs(text, stdout);
-        return 0;
-}
-
 static int snapshot(DBusConnection *bus, char **args) {
         _cleanup_dbus_message_unref_ DBusMessage *reply = NULL;
         DBusError error;
@@ -4661,12 +4669,12 @@ static int systemctl_help(void) {
                "  -h --help           Show this help\n"
                "     --version        Show package version\n"
                "  -t --type=TYPE      List only units of a particular type\n"
+               "     --state=STATE    Show only units with particular LOAD or SUB or ACTIVE state\n"
                "  -p --property=NAME  Show only properties by this name\n"
                "  -a --all            Show all loaded units/properties, including dead/empty\n"
                "                      ones. To list all units installed on the system, use\n"
                "                      the 'list-unit-files' command instead.\n"
                "     --reverse        Show reverse dependencies with 'list-dependencies'\n"
-               "     --failed         Show only failed units\n"
                "  -l --full           Don't ellipsize unit names on output\n"
                "     --fail           When queueing a new job, fail if conflicting jobs are\n"
                "                      pending\n"
@@ -4745,8 +4753,6 @@ static int systemctl_help(void) {
                "Job Commands:\n"
                "  list-jobs                       List jobs\n"
                "  cancel [JOB...]                 Cancel all, one, or more jobs\n\n"
-               "Status Commands:\n"
-               "  dump                            Dump server status\n"
                "Snapshot Commands:\n"
                "  snapshot [NAME]                 Create a snapshot\n"
                "  delete [NAME...]                Remove one or more snapshots\n\n"
@@ -4852,13 +4858,6 @@ static int help_types(void) {
                         puts(t);
         }
 
-        puts("\nAvailable unit load states: ");
-        for(i = 0; i < _UNIT_LOAD_STATE_MAX; i++) {
-                t = unit_load_state_to_string(i);
-                if (t)
-                        puts(t);
-        }
-
         return 0;
 }
 
@@ -4887,46 +4886,48 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                 ARG_FAILED,
                 ARG_RUNTIME,
                 ARG_FORCE,
-                ARG_PLAIN
+                ARG_PLAIN,
+                ARG_STATE
         };
 
         static const struct option options[] = {
-                { "help",      no_argument,       NULL, 'h'           },
-                { "version",   no_argument,       NULL, ARG_VERSION   },
-                { "type",      required_argument, NULL, 't'           },
-                { "property",  required_argument, NULL, 'p'           },
-                { "all",       no_argument,       NULL, 'a'           },
-                { "reverse",   no_argument,       NULL, ARG_REVERSE   },
-                { "after",     no_argument,       NULL, ARG_AFTER     },
-                { "before",    no_argument,       NULL, ARG_BEFORE    },
-                { "show-types", no_argument,      NULL, ARG_SHOW_TYPES },
-                { "failed",    no_argument,       NULL, ARG_FAILED    },
-                { "full",      no_argument,       NULL, 'l'           },
-                { "fail",      no_argument,       NULL, ARG_FAIL      },
-                { "irreversible", no_argument,    NULL, ARG_IRREVERSIBLE },
-                { "ignore-dependencies", no_argument, NULL, ARG_IGNORE_DEPENDENCIES },
-                { "ignore-inhibitors", no_argument, NULL, 'i'         },
-                { "user",      no_argument,       NULL, ARG_USER      },
-                { "system",    no_argument,       NULL, ARG_SYSTEM    },
-                { "global",    no_argument,       NULL, ARG_GLOBAL    },
-                { "no-block",  no_argument,       NULL, ARG_NO_BLOCK  },
-                { "no-legend", no_argument,       NULL, ARG_NO_LEGEND },
-                { "no-pager",  no_argument,       NULL, ARG_NO_PAGER  },
-                { "no-wall",   no_argument,       NULL, ARG_NO_WALL   },
-                { "quiet",     no_argument,       NULL, 'q'           },
-                { "root",      required_argument, NULL, ARG_ROOT      },
-                { "force",     no_argument,       NULL, ARG_FORCE     },
-                { "no-reload", no_argument,       NULL, ARG_NO_RELOAD },
-                { "kill-who",  required_argument, NULL, ARG_KILL_WHO  },
-                { "signal",    required_argument, NULL, 's'           },
-                { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD },
-                { "host",      required_argument, NULL, 'H'           },
-                { "privileged",no_argument,       NULL, 'P'           },
-                { "runtime",   no_argument,       NULL, ARG_RUNTIME   },
-                { "lines",     required_argument, NULL, 'n'           },
-                { "output",    required_argument, NULL, 'o'           },
-                { "plain",     no_argument,       NULL, ARG_PLAIN     },
-                { NULL,        0,                 NULL, 0             }
+                { "help",                no_argument,       NULL, 'h'                     },
+                { "version",             no_argument,       NULL, ARG_VERSION             },
+                { "type",                required_argument, NULL, 't'                     },
+                { "property",            required_argument, NULL, 'p'                     },
+                { "all",                 no_argument,       NULL, 'a'                     },
+                { "reverse",             no_argument,       NULL, ARG_REVERSE             },
+                { "after",               no_argument,       NULL, ARG_AFTER               },
+                { "before",              no_argument,       NULL, ARG_BEFORE              },
+                { "show-types",          no_argument,       NULL, ARG_SHOW_TYPES          },
+                { "failed",              no_argument,       NULL, ARG_FAILED              }, /* compatibility only */
+                { "full",                no_argument,       NULL, 'l'                     },
+                { "fail",                no_argument,       NULL, ARG_FAIL                },
+                { "irreversible",        no_argument,       NULL, ARG_IRREVERSIBLE        },
+                { "ignore-dependencies", no_argument,       NULL, ARG_IGNORE_DEPENDENCIES },
+                { "ignore-inhibitors",   no_argument,       NULL, 'i'                     },
+                { "user",                no_argument,       NULL, ARG_USER                },
+                { "system",              no_argument,       NULL, ARG_SYSTEM              },
+                { "global",              no_argument,       NULL, ARG_GLOBAL              },
+                { "no-block",            no_argument,       NULL, ARG_NO_BLOCK            },
+                { "no-legend",           no_argument,       NULL, ARG_NO_LEGEND           },
+                { "no-pager",            no_argument,       NULL, ARG_NO_PAGER            },
+                { "no-wall",             no_argument,       NULL, ARG_NO_WALL             },
+                { "quiet",               no_argument,       NULL, 'q'                     },
+                { "root",                required_argument, NULL, ARG_ROOT                },
+                { "force",               no_argument,       NULL, ARG_FORCE               },
+                { "no-reload",           no_argument,       NULL, ARG_NO_RELOAD           },
+                { "kill-who",            required_argument, NULL, ARG_KILL_WHO            },
+                { "signal",              required_argument, NULL, 's'                     },
+                { "no-ask-password",     no_argument,       NULL, ARG_NO_ASK_PASSWORD     },
+                { "host",                required_argument, NULL, 'H'                     },
+                { "privileged",          no_argument,       NULL, 'P'                     },
+                { "runtime",             no_argument,       NULL, ARG_RUNTIME             },
+                { "lines",               required_argument, NULL, 'n'                     },
+                { "output",              required_argument, NULL, 'o'                     },
+                { "plain",               no_argument,       NULL, ARG_PLAIN               },
+                { "state",               required_argument, NULL, ARG_STATE               },
+                { NULL,                  0,                 NULL, 0                       }
         };
 
         int c;
@@ -4970,8 +4971,12 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                                         continue;
                                 }
 
+                                /* It's much nicer to use --state= for
+                                 * load states, but let's support this
+                                 * in --types= too for compatibility
+                                 * with old versions */
                                 if (unit_load_state_from_string(optarg) >= 0) {
-                                        if (strv_push(&arg_load_states, type))
+                                        if (strv_push(&arg_states, type) < 0)
                                                 return log_oom();
                                         type = NULL;
                                         continue;
@@ -5003,7 +5008,7 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                                         if (!prop)
                                                 return log_oom();
 
-                                        if (strv_push(&arg_properties, prop)) {
+                                        if (strv_push(&arg_properties, prop) < 0) {
                                                 free(prop);
                                                 return log_oom();
                                         }
@@ -5087,7 +5092,9 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         break;
 
                 case ARG_FAILED:
-                        arg_failed = true;
+                        if (strv_extend(&arg_states, "failed") < 0)
+                                return log_oom();
+
                         break;
 
                 case 'q':
@@ -5157,6 +5164,25 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
                         arg_plain = true;
                         break;
 
+                case ARG_STATE: {
+                        char *word, *state;
+                        size_t size;
+
+                        FOREACH_WORD_SEPARATOR(word, size, optarg, ",", state) {
+                                char *s;
+
+                                s = strndup(word, size);
+                                if (!s)
+                                        return log_oom();
+
+                                if (strv_push(&arg_states, s) < 0) {
+                                        free(s);
+                                        return log_oom();
+                                }
+                        }
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -5767,7 +5793,6 @@ static int systemctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "show",                  MORE,  1, show              },
                 { "status",                MORE,  1, show              },
                 { "help",                  MORE,  2, show              },
-                { "dump",                  EQUAL, 1, dump              },
                 { "snapshot",              LESS,  2, snapshot          },
                 { "delete",                MORE,  2, delete_snapshot   },
                 { "daemon-reload",         EQUAL, 1, daemon_reload     },
@@ -6213,7 +6238,7 @@ finish:
         dbus_shutdown();
 
         strv_free(arg_types);
-        strv_free(arg_load_states);
+        strv_free(arg_states);
         strv_free(arg_properties);
 
         pager_close();