From 88e3dc903bd543a74b8699c1575b0da9eeab24a2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Sat, 9 Jul 2011 02:58:05 +0200 Subject: [PATCH] loginctl: implement more verbs --- src/loginctl.c | 323 ++++++++++++++++++++++++++++++++++++-- src/logind-dbus.c | 29 ++++ src/logind-session-dbus.c | 37 +++-- src/logind-session.h | 1 + src/sysfs-show.c | 28 ++-- 5 files changed, 386 insertions(+), 32 deletions(-) diff --git a/src/loginctl.c b/src/loginctl.c index 23c998cb..bb5be908 100644 --- a/src/loginctl.c +++ b/src/loginctl.c @@ -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; diff --git a/src/logind-dbus.c b/src/logind-dbus.c index a2a442ee..ec39d56d 100644 --- a/src/logind-dbus.c +++ b/src/logind-dbus.c @@ -75,6 +75,12 @@ " \n" \ " \n" \ " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ + " \n" \ " \n" \ " \n" \ " \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; diff --git a/src/logind-session-dbus.c b/src/logind-session-dbus.c index eca33e5e..5fe391cc 100644 --- a/src/logind-session-dbus.c +++ b/src/logind-session-dbus.c @@ -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; +} diff --git a/src/logind-session.h b/src/logind-session.h index e58ff6fd..d9f44ef0 100644 --- a/src/logind-session.h +++ b/src/logind-session.h @@ -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); diff --git a/src/sysfs-show.c b/src/sysfs-show.c index d12d3ccf..b456bf12 100644 --- a/src/sysfs-show.c +++ b/src/sysfs-show.c @@ -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); } -- 2.39.5