chiark / gitweb /
turn negative options into positive options
[elogind.git] / src / systemctl.c
index b66901b9ed2a073ae72345c098a5e4c8401c14aa..1ad0c48a89f8eef669ab8867960295d2b2373955 100644 (file)
@@ -583,13 +583,10 @@ static DBusHandlerResult wait_filter(DBusConnection *connection, DBusMessage *me
 
 static int enable_wait_for_jobs(DBusConnection *bus) {
         DBusError error;
-        DBusMessage *m = NULL, *reply = NULL;
-        int r;
 
         assert(bus);
 
         dbus_error_init(&error);
-
         dbus_bus_add_match(bus,
                            "type='signal',"
                            "sender='org.freedesktop.systemd1',"
@@ -600,40 +597,12 @@ static int enable_wait_for_jobs(DBusConnection *bus) {
 
         if (dbus_error_is_set(&error)) {
                 log_error("Failed to add match: %s", error.message);
-                r = -EIO;
-                goto finish;
-        }
-
-        if (!(m = dbus_message_new_method_call(
-                              "org.freedesktop.systemd1",
-                              "/org/freedesktop/systemd1",
-                              "org.freedesktop.systemd1.Manager",
-                              "Subscribe"))) {
-                log_error("Could not allocate message.");
-                r = -ENOMEM;
-                goto finish;
-        }
-
-        if (!(reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error))) {
-                log_error("Failed to issue method call: %s", error.message);
-                r = -EIO;
-                goto finish;
+                dbus_error_free(&error);
+                return -EIO;
         }
 
-        r = 0;
-
-finish:
         /* This is slightly dirty, since we don't undo the match registrations. */
-
-        if (m)
-                dbus_message_unref(m);
-
-        if (reply)
-                dbus_message_unref(reply);
-
-        dbus_error_free(&error);
-
-        return r;
+        return 0;
 }
 
 static int wait_for_jobs(DBusConnection *bus, Set *s) {
@@ -1029,6 +998,10 @@ static int print_property(const char *name, DBusMessageIter *iter) {
 
                         if ((t = format_timestamp(timestamp, sizeof(timestamp), u)) || arg_all)
                                 printf("%s=%s\n", name, strempty(t));
+                } else if (strstr(name, "USec")) {
+                        char timespan[FORMAT_TIMESPAN_MAX];
+
+                        printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u));
                 } else
                         printf("%s=%llu\n", name, (unsigned long long) u);
 
@@ -1039,7 +1012,7 @@ static int print_property(const char *name, DBusMessageIter *iter) {
                 uint32_t u;
                 dbus_message_iter_get_basic(iter, &u);
 
-                if (strstr(name, "UMask"))
+                if (strstr(name, "UMask") || strstr(name, "Mode"))
                         printf("%s=%04o\n", name, u);
                 else
                         printf("%s=%u\n", name, (unsigned) u);
@@ -1059,7 +1032,7 @@ static int print_property(const char *name, DBusMessageIter *iter) {
                 DBusMessageIter sub;
                 dbus_message_iter_recurse(iter, &sub);
 
-                if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && strstr(name, "Job")) {
+                if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_UINT32 && streq(name, "Job")) {
                         uint32_t u;
 
                         dbus_message_iter_get_basic(&sub, &u);
@@ -1070,7 +1043,7 @@ static int print_property(const char *name, DBusMessageIter *iter) {
                                 printf("%s=\n", name);
 
                         return 0;
-                } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && strstr(name, "Unit")) {
+                } else if (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRING && streq(name, "Unit")) {
                         const char *s;
 
                         dbus_message_iter_get_basic(&sub, &s);
@@ -1110,6 +1083,131 @@ static int print_property(const char *name, DBusMessageIter *iter) {
                                 puts("");
                         }
 
+                        return 0;
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_BYTE) {
+                        DBusMessageIter sub;
+
+                        dbus_message_iter_recurse(iter, &sub);
+
+                        if (arg_all ||
+                            dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+                                printf("%s=", name);
+
+                                while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
+                                        uint8_t u;
+
+                                        assert(dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_BYTE);
+                                        dbus_message_iter_get_basic(&sub, &u);
+                                        printf("%02x", u);
+
+                                        dbus_message_iter_next(&sub);
+                                }
+
+                                puts("");
+                        }
+
+                        return 0;
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Paths")) {
+                        DBusMessageIter sub, sub2;
+
+                        dbus_message_iter_recurse(iter, &sub);
+
+                        while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+                                const char *type, *path;
+
+                                dbus_message_iter_recurse(&sub, &sub2);
+
+                                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &type, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, false) >= 0)
+                                        printf("%s=%s\n", type, path);
+
+                                dbus_message_iter_next(&sub);
+                        }
+
+                        return 0;
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && streq(name, "Timers")) {
+                        DBusMessageIter sub, sub2;
+
+                        dbus_message_iter_recurse(iter, &sub);
+
+                        while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+                                const char *base;
+                                uint64_t value, next_elapse;
+
+                                dbus_message_iter_recurse(&sub, &sub2);
+
+                                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &base, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &value, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &next_elapse, false) >= 0) {
+                                        char timespan1[FORMAT_TIMESPAN_MAX], timespan2[FORMAT_TIMESPAN_MAX];
+
+                                        printf("%s={ value=%s ; next_elapse=%s }\n",
+                                               base,
+                                               format_timespan(timespan1, sizeof(timespan1), value),
+                                               format_timespan(timespan2, sizeof(timespan2), next_elapse));
+                                }
+
+                                dbus_message_iter_next(&sub);
+                        }
+
+                        return 0;
+                } else if (dbus_message_iter_get_element_type(iter) == DBUS_TYPE_STRUCT && startswith(name, "Exec")) {
+
+                        DBusMessageIter sub, sub2, sub3;
+
+                        dbus_message_iter_recurse(iter, &sub);
+
+                        while (dbus_message_iter_get_arg_type(&sub) == DBUS_TYPE_STRUCT) {
+                                const char *path;
+                                uint64_t start_time, exit_time;
+                                uint32_t pid;
+                                int32_t code, status;
+
+                                dbus_message_iter_recurse(&sub, &sub2);
+
+                                if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &path, true) < 0)
+                                        continue;
+
+                                if (dbus_message_iter_get_arg_type(&sub2) != DBUS_TYPE_ARRAY ||
+                                    dbus_message_iter_get_element_type(&sub2) != DBUS_TYPE_STRING)
+                                        continue;
+
+                                printf("%s={ path=%s ; argv[]=", name, path);
+
+                                dbus_message_iter_recurse(&sub2, &sub3);
+
+                                while (dbus_message_iter_get_arg_type(&sub3) != DBUS_TYPE_INVALID) {
+                                        const char *s;
+
+                                        assert(dbus_message_iter_get_arg_type(&sub3) == DBUS_TYPE_STRING);
+                                        dbus_message_iter_get_basic(&sub3, &s);
+                                        printf("%s ", s);
+                                        dbus_message_iter_next(&sub3);
+                                }
+
+                                if (dbus_message_iter_next(&sub2) &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &start_time, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT64, &exit_time, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &code, true) >= 0 &&
+                                    bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_INT32, &status, false) >= 0) {
+
+                                        char timestamp1[FORMAT_TIMESTAMP_MAX], timestamp2[FORMAT_TIMESTAMP_MAX];
+
+                                        printf("; start=%s ; stop=%s ; pid=%u ; code=%s ; status=%i/%s",
+                                               strna(format_timestamp(timestamp1, sizeof(timestamp1), start_time)),
+                                               strna(format_timestamp(timestamp2, sizeof(timestamp2), exit_time)),
+                                               (unsigned) pid,
+                                               sigchld_code_to_string(code),
+                                               status,
+                                               strna(code == CLD_EXITED ? NULL : strsignal(status)));
+                                }
+
+                                printf(" }\n");
+
+                                dbus_message_iter_next(&sub);
+                        }
+
                         return 0;
                 }
 
@@ -1245,7 +1343,7 @@ static int show(DBusConnection *bus, char **args, unsigned n) {
                                               "org.freedesktop.systemd1",
                                               "/org/freedesktop/systemd1",
                                               "org.freedesktop.systemd1.Manager",
-                                              "GetUnit"))) {
+                                              "LoadUnit"))) {
                                 log_error("Could not allocate message.");
                                 r = -ENOMEM;
                                 goto finish;
@@ -1984,7 +2082,7 @@ static int systemctl_help(void) {
                "Send control commands to the systemd manager.\n\n"
                "  -h --help          Show this help\n"
                "  -t --type=TYPE     List only units of a particular type\n"
-               "  -p --property=NAME Show only property by this name\n"
+               "  -p --property=NAME Show only properties by this name\n"
                "  -a --all           Show all units/properties, including dead/empty ones\n"
                "     --replace       When installing a new job, replace existing conflicting ones\n"
                "     --system        Connect to system bus\n"
@@ -2000,7 +2098,7 @@ static int systemctl_help(void) {
                "  reload [NAME...]                Reload one or more units\n"
                "  isolate [NAME]                  Start one unit and stop all others\n"
                "  check [NAME...]                 Check whether any of the passed units are active\n"
-               "  show [NAME...|JOB...]           Show information about one or more units\n"
+               "  show [NAME...|JOB...]           Show information about one or more units/jobs/manager\n"
                "  load [NAME...]                  Load one or more units\n"
                "  list-jobs                       List jobs\n"
                "  cancel [JOB...]                 Cancel one or more jobs\n"