chiark / gitweb /
loginctl: implement more verbs
authorLennart Poettering <lennart@poettering.net>
Sat, 9 Jul 2011 00:58:05 +0000 (02:58 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 13 Jul 2011 17:59:28 +0000 (19:59 +0200)
src/loginctl.c
src/logind-dbus.c
src/logind-session-dbus.c
src/logind-session.h
src/sysfs-show.c

index 23c998cba2c7bab2cd27e940196c28f3a09a919d..bb5be908f6cc008eaf2cf5e77e4c3cd40b1c33b8 100644 (file)
@@ -527,14 +527,13 @@ static void print_seat_status_info(SeatStatusInfo *i) {
                 unsigned c;
 
                 c = columns();
-                if (c > 18)
-                        c -= 18;
+                if (c > 21)
+                        c -= 21;
                 else
                         c = 0;
 
                 printf("\t Devices:\n");
 
-
                 show_sysfs(i->id, "\t\t  ", c);
         }
 }
@@ -1166,7 +1165,10 @@ static int activate(DBusConnection *bus, char **args, unsigned n) {
                                 "org.freedesktop.login1",
                                 "/org/freedesktop/login1",
                                 "org.freedesktop.login1.Manager",
-                                "ActivateSession");
+                                streq(args[0], "lock-session")      ? "LockSession" :
+                                streq(args[0], "unlock-session")    ? "UnlockSession" :
+                                streq(args[0], "terminate-session") ? "TerminateSession" :
+                                                                      "ActivateSession");
                 if (!m) {
                         log_error("Could not allocate message.");
                         ret = -ENOMEM;
@@ -1210,19 +1212,312 @@ static int kill_session(DBusConnection *bus, char **args, unsigned n) {
 }
 
 static int enable_linger(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+        dbus_bool_t b, interactive = true;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        b = streq(args[0], "enable-linger");
+
+        for (i = 1; i < n; i++) {
+                uint32_t uid;
+
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "SetUserLinger");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (safe_atou32(args[i], &uid) < 0) {
+                        struct passwd *pw;
+
+                        errno = 0;
+                        pw = getpwnam(args[i]);
+                        if (!pw) {
+                                ret = errno ? -errno : -ENOENT;
+                                log_error("Failed to resolve user %s: %s", args[i], strerror(-ret));
+                                goto finish;
+                        }
+
+                        uid = pw->pw_uid;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_UINT32, &uid,
+                                              DBUS_TYPE_BOOLEAN, &b,
+                                              DBUS_TYPE_BOOLEAN, &interactive,
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
+}
+
+static int terminate_user(DBusConnection *bus, char **args, unsigned n) {
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        for (i = 1; i < n; i++) {
+                uint32_t u;
+
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "TerminateUser");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (safe_atou32(args[i], &u) < 0) {
+                        struct passwd *pw;
+
+                        errno = 0;
+                        pw = getpwnam(args[i]);
+                        if (!pw) {
+                                ret = errno ? -errno : -ENOENT;
+                                log_error("Failed to look up user %s: %s", args[i], strerror(-ret));
+                                goto finish;
+                        }
+
+                        u = pw->pw_uid;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_UINT32, &u,
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int attach(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+        dbus_bool_t interactive = true;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        for (i = 2; i < n; i++) {
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "AttachDevice");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_STRING, &args[1],
+                                              DBUS_TYPE_STRING, &args[i],
+                                              DBUS_TYPE_BOOLEAN, &interactive,
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int flush_devices(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        dbus_bool_t interactive = true;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        m = dbus_message_new_method_call(
+                        "org.freedesktop.login1",
+                        "/org/freedesktop/login1",
+                        "org.freedesktop.login1.Manager",
+                        "FlushDevices");
+        if (!m) {
+                log_error("Could not allocate message.");
+                ret = -ENOMEM;
+                goto finish;
+        }
+
+        if (!dbus_message_append_args(m,
+                                      DBUS_TYPE_BOOLEAN, &interactive,
+                                      DBUS_TYPE_INVALID)) {
+                log_error("Could not append arguments to message.");
+                ret = -ENOMEM;
+                goto finish;
+        }
+
+        reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+        if (!reply) {
+                log_error("Failed to issue method call: %s", bus_error_message(&error));
+                ret = -EIO;
+                goto finish;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int terminate_seat(DBusConnection *bus, char **args, unsigned n) {
-        return 0;
+        DBusMessage *m = NULL, *reply = NULL;
+        int ret = 0;
+        DBusError error;
+        unsigned i;
+
+        assert(bus);
+        assert(args);
+
+        dbus_error_init(&error);
+
+        for (i = 1; i < n; i++) {
+                m = dbus_message_new_method_call(
+                                "org.freedesktop.login1",
+                                "/org/freedesktop/login1",
+                                "org.freedesktop.login1.Manager",
+                                "TerminateSeat");
+                if (!m) {
+                        log_error("Could not allocate message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                if (!dbus_message_append_args(m,
+                                              DBUS_TYPE_STRING, &args[i],
+                                              DBUS_TYPE_INVALID)) {
+                        log_error("Could not append arguments to message.");
+                        ret = -ENOMEM;
+                        goto finish;
+                }
+
+                reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+                if (!reply) {
+                        log_error("Failed to issue method call: %s", bus_error_message(&error));
+                        ret = -EIO;
+                        goto finish;
+                }
+
+                dbus_message_unref(m);
+                dbus_message_unref(reply);
+                m = reply = NULL;
+        }
+
+finish:
+        if (m)
+                dbus_message_unref(m);
+
+        if (reply)
+                dbus_message_unref(reply);
+
+        dbus_error_free(&error);
+
+        return ret;
 }
 
 static int help(void) {
@@ -1245,6 +1540,7 @@ static int help(void) {
                "  show-session [ID...]            Show property of one or more sessions\n"
                "  activate [ID]                   Activate a session\n"
                "  lock-session [ID...]            Screen lock one or more sessions\n"
+               "  unlock-session [ID...]          Screen unlock one or more sessions\n"
                "  terminate-session [ID...]       Terminate one or more sessions\n"
                "  kill-session [ID...]            Send signal to processes of a session\n"
                "  list-users                      List users\n"
@@ -1381,22 +1677,23 @@ static int loginctl_main(DBusConnection *bus, int argc, char *argv[], DBusError
                 { "show-session",          MORE,   1, show             },
                 { "activate",              EQUAL,  2, activate         },
                 { "lock-session",          MORE,   2, activate         },
+                { "unlock-session",        MORE,   2, activate         },
                 { "terminate-session",     MORE,   2, activate         },
-                { "kill-session",          MORE,   2, kill_session     },
+                { "kill-session",          MORE,   2, kill_session     }, /* missing */
                 { "list-users",            EQUAL,  1, list_users       },
                 { "user-status",           MORE,   2, show             },
                 { "show-user",             MORE,   1, show             },
                 { "enable-linger",         MORE,   2, enable_linger    },
                 { "disable-linger",        MORE,   2, enable_linger    },
-                { "terminate-user",        MORE,   2, enable_linger    },
-                { "kill-user",             MORE,   2, kill_session     },
+                { "terminate-user",        MORE,   2, terminate_user   },
+                { "kill-user",             MORE,   2, kill_session     }, /* missing */
                 { "list-seats",            EQUAL,  1, list_seats       },
                 { "seat-status",           MORE,   2, show             },
                 { "show-seat",             MORE,   1, show             },
                 { "attach",                MORE,   3, attach           },
                 { "flush-devices",         EQUAL,  1, flush_devices    },
-                { "terminate-seat",        MORE,   2, terminate_seat   },
-                { "kill-seat",             MORE,   2, kill_session     },
+                { "terminate-seat",        MORE,   2, terminate_seat   }, /* missing */
+                { "kill-seat",             MORE,   2, kill_session     }, /* missing */
         };
 
         int left;
index a2a442ee271732d589e1b7db491f2ae4c25c853e..ec39d56d9e2ce13f7ace722998f7cc3509da4d11 100644 (file)
         "  <method name=\"ActivateSession\">\n"                         \
         "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
         "  </method>\n"                                                 \
+        "  <method name=\"LockSession\">\n"                             \
+        "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
+        "  </method>\n"                                                 \
+        "  <method name=\"UnlockSession\">\n"                           \
+        "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
+        "  </method>\n"                                                 \
         "  <method name=\"TerminateSession\">\n"                        \
         "   <arg name=\"id\" type=\"s\" direction=\"in\"/>\n"           \
         "  </method>\n"                                                 \
@@ -980,6 +986,29 @@ static DBusHandlerResult manager_message_handler(
                 if (!reply)
                         goto oom;
 
+        } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSession") ||
+                   dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "UnlockSession")) {
+                const char *name;
+                Session *session;
+
+                if (!dbus_message_get_args(
+                                    message,
+                                    &error,
+                                    DBUS_TYPE_STRING, &name,
+                                    DBUS_TYPE_INVALID))
+                        return bus_send_error_reply(connection, message, &error, -EINVAL);
+
+                session = hashmap_get(m->sessions, name);
+                if (!session)
+                        return bus_send_error_reply(connection, message, &error, -ENOENT);
+
+                if (session_send_lock(session, streq(dbus_message_get_member(message), "LockSession")) < 0)
+                        goto oom;
+
+                reply = dbus_message_new_method_return(message);
+                if (!reply)
+                        goto oom;
+
         } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSession")) {
                 const char *name;
                 Session *session;
index eca33e5e24788673e38df8cf9d97a9b1ad7f76f2..5fe391cca493f8c2eee404c41e039a08bcdbd4c7 100644 (file)
@@ -283,17 +283,8 @@ static DBusHandlerResult session_message_dispatch(
 
         } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Lock") ||
                    dbus_message_is_method_call(message, "org.freedesktop.login1.Session", "Unlock")) {
-                bool b;
-                DBusMessage *sig;
 
-                sig = dbus_message_new_signal(dbus_message_get_path(message), "org.freedesktop.login1.Session", dbus_message_get_member(message));
-                if (!sig)
-                        goto oom;
-
-                b = dbus_connection_send(connection, sig, NULL);
-                dbus_message_unref(sig);
-
-                if (!b)
+                if (session_send_signal(s, streq(dbus_message_get_member(message), "Lock")) < 0)
                         goto oom;
 
                 reply = dbus_message_new_method_return(message);
@@ -460,3 +451,29 @@ finish:
 
         return r;
 }
+
+int session_send_lock(Session *s, bool lock) {
+        DBusMessage *m;
+        bool b;
+        char *p;
+
+        assert(s);
+
+        p = session_bus_path(s);
+        if (!p)
+                return -ENOMEM;
+
+        m = dbus_message_new_signal(p, "org.freedesktop.login1.Session", lock ? "Lock" : "Unlock");
+        free(p);
+
+        if (!m)
+                return -ENOMEM;
+
+        b = dbus_connection_send(s->manager->bus, m, NULL);
+        dbus_message_unref(m);
+
+        if (!b)
+                return -ENOMEM;
+
+        return 0;
+}
index e58ff6fd8f53fa97b78e192f3b897b654bae58f6..d9f44ef0e04d8cd93973a26370bcc3374901d497 100644 (file)
@@ -105,6 +105,7 @@ extern const DBusObjectPathVTable bus_session_vtable;
 
 int session_send_signal(Session *s, bool new_session);
 int session_send_changed(Session *s, const char *properties);
+int session_send_lock(Session *s, bool lock);
 
 const char* session_type_to_string(SessionType t);
 SessionType session_type_from_string(const char *s);
index d12d3ccfc92b6de0f5a1bc489fa81183ea0e46e4..b456bf1271c730c45097533c452116f28c819515 100644 (file)
@@ -59,7 +59,8 @@ static int show_sysfs_one(
         while (*item) {
                 struct udev_list_entry *next, *lookahead;
                 struct udev_device *d;
-                const char *sn, *id, *name, *sysfs, *subsystem, *sysname;
+                const char *sn, *name, *sysfs, *subsystem, *sysname;
+                char *l, *k;
 
                 sysfs = udev_list_entry_get_name(*item);
                 if (!path_startswith(sysfs, sub))
@@ -82,7 +83,6 @@ static int show_sysfs_one(
                         continue;
                 }
 
-                id = udev_device_get_property_value(d, "ID_FOR_SEAT");
                 name = udev_device_get_sysattr_value(d, "name");
                 if (!name)
                         name = udev_device_get_sysattr_value(d, "id");
@@ -109,7 +109,7 @@ static int show_sysfs_one(
                                         if (isempty(lookahead_sn))
                                                 lookahead_sn = "seat0";
 
-                                        found = streq(seat, lookahead_sn) && device_has_tag(d, "seat");
+                                        found = streq(seat, lookahead_sn) && device_has_tag(lookahead_d, "seat");
                                         udev_device_unref(lookahead_d);
 
                                         if (found)
@@ -120,19 +120,29 @@ static int show_sysfs_one(
                         lookahead = udev_list_entry_get_next(lookahead);
                 }
 
-                printf("%s%s %s (%s:%s)", prefix, lookahead ? "\342\224\234" : "\342\224\224", id ? id : sysfs, subsystem, sysname);
+                k = ellipsize(sysfs, n_columns, 20);
+                printf("%s%s %s\n", prefix, lookahead ? "\342\224\234" : "\342\224\224", k ? k : sysfs);
+                free(k);
 
-                if (name)
-                        printf(" \"%s\"\n", name);
-                else
-                        printf("\n");
+                if (asprintf(&l,
+                             "(%s:%s)%s%s%s",
+                             subsystem, sysname,
+                             name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) {
+                        udev_device_unref(d);
+                        return -ENOMEM;
+                }
+
+                k = ellipsize(l, n_columns, 70);
+                printf("%s%s %s\n", prefix, lookahead ? "\342\224\202" : " ", k ? k : l);
+                free(k);
+                free(l);
 
                 *item = next;
                 if (*item) {
                         char *p;
 
                         p = strappend(prefix, lookahead ? "\342\224\202 " : "  ");
-                        show_sysfs_one(udev, seat, item, sysfs, p, n_columns - 2);
+                        show_sysfs_one(udev, seat, item, sysfs, p ? p : prefix, n_columns - 2);
                         free(p);
                 }