diff options
author | Jonathan Maw <jonathan.maw@codethink.co.uk> | 2013-06-28 10:30:15 +0000 |
---|---|---|
committer | Jonathan Maw <jonathan.maw@codethink.co.uk> | 2013-06-28 10:30:15 +0000 |
commit | daba2f7416861898b2c01926ae6a2ef19fecfaab (patch) | |
tree | 6b159c5e7d612368e6bbb8e138ae3db15005c201 /src/login | |
parent | 9a332ba261bea9e9f3c0915bc6f0c6a0d45a1d5d (diff) | |
parent | 606c24e3bd41207c395f24a56bcfcad791e265a5 (diff) | |
download | systemd-daba2f7416861898b2c01926ae6a2ef19fecfaab.tar.gz |
Merge tag 'v204' into new-systemd
systemd 204
Diffstat (limited to 'src/login')
27 files changed, 1031 insertions, 1128 deletions
diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules index d1275f2ca9..a118f8e887 100644 --- a/src/login/70-uaccess.rules +++ b/src/login/70-uaccess.rules @@ -9,7 +9,6 @@ ACTION=="remove", GOTO="uaccess_end" ENV{MAJOR}=="", GOTO="uaccess_end" # PTP/MTP protocol devices, cameras, portable media players -SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="", ENV{DEVTYPE}=="usb_device", IMPORT{builtin}="usb_id" SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess" # Digicams with proprietary protocol diff --git a/src/login/71-seat.rules.in b/src/login/71-seat.rules.in index 4f1a9a59a1..ad26acbbb3 100644 --- a/src/login/71-seat.rules.in +++ b/src/login/71-seat.rules.in @@ -10,7 +10,7 @@ ACTION=="remove", GOTO="seat_end" TAG=="uaccess", SUBSYSTEM!="sound", TAG+="seat" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="seat" SUBSYSTEM=="input", KERNEL=="input*", TAG+="seat" -SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat", TAG+="seat-master" +SUBSYSTEM=="graphics", KERNEL=="fb[0-9]*", TAG+="seat", TAG+="master-of-seat" SUBSYSTEM=="usb", ATTR{bDeviceClass}=="09", TAG+="seat" # 'Plugable' USB hub, sound, network, graphics adapter @@ -38,7 +38,7 @@ SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product} SUBSYSTEM=="usb", ATTR{idVendor}=="17e9", ATTR{idProduct}=="401a", ATTR{product}=="mimo inc", \ ATTR{../idVendor}=="058f", ATTR{../idProduct}=="6254", \ ENV{ID_AVOID_LOOP}=="", \ - RUN+="@bindir@/udevadm trigger --parent-match=%p/.." + RUN+="@rootbindir@/udevadm trigger --parent-match=%p/.." TAG=="seat", ENV{ID_PATH}=="", IMPORT{builtin}="path_id" TAG=="seat", ENV{ID_FOR_SEAT}=="", ENV{ID_PATH_TAG}!="", ENV{ID_FOR_SEAT}="$env{SUBSYSTEM}-$env{ID_PATH_TAG}" diff --git a/src/login/inhibit.c b/src/login/inhibit.c index 9b6613340f..29e50c1447 100644 --- a/src/login/inhibit.c +++ b/src/login/inhibit.c @@ -42,7 +42,7 @@ static enum { } arg_action = ACTION_INHIBIT; static int inhibit(DBusConnection *bus, DBusError *error) { - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; r = bus_method_call_with_reply( @@ -64,15 +64,13 @@ static int inhibit(DBusConnection *bus, DBusError *error) { if (!dbus_message_get_args(reply, error, DBUS_TYPE_UNIX_FD, &r, DBUS_TYPE_INVALID)) - r = -EIO; - - dbus_message_unref(reply); + return -EIO; return r; } static int print_inhibitors(DBusConnection *bus, DBusError *error) { - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; unsigned n = 0; DBusMessageIter iter, sub, sub2; int r; @@ -87,36 +85,22 @@ static int print_inhibitors(DBusConnection *bus, DBusError *error) { NULL, DBUS_TYPE_INVALID); if (r < 0) - goto finish; - - if (!dbus_message_iter_init(reply, &iter)) { - r = -ENOMEM; - goto finish; - } + return r; - if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) { - r = -EIO; - goto finish; - } + if (!dbus_message_iter_init(reply, &iter)) + return -ENOMEM; - printf("%-21s %-20s %-20s %-5s %6s %6s\n", - "WHAT", - "WHO", - "WHY", - "MODE", - "UID", - "PID"); + if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY) + return -EIO; dbus_message_iter_recurse(&iter, &sub); while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) { const char *what, *who, *why, *mode; - char *ewho, *ewhy; + _cleanup_free_ char *comm = NULL, *u = NULL; dbus_uint32_t uid, pid; - if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) { - r = -EIO; - goto finish; - } + if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) + return -EIO; dbus_message_iter_recurse(&sub, &sub2); @@ -125,33 +109,28 @@ static int print_inhibitors(DBusConnection *bus, DBusError *error) { bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &why, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &mode, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &uid, true) < 0 || - bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) { - r = -EIO; - goto finish; - } + bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_UINT32, &pid, false) < 0) + return -EIO; - ewho = ellipsize(who, 20, 66); - ewhy = ellipsize(why, 20, 66); + get_process_comm(pid, &comm); + u = uid_to_name(uid); - printf("%-21s %-20s %-20s %-5s %6lu %6lu\n", - what, ewho ? ewho : who, ewhy ? ewhy : why, mode, (unsigned long) uid, (unsigned long) pid); - - free(ewho); - free(ewhy); + printf(" Who: %s (UID %lu/%s, PID %lu/%s)\n" + " What: %s\n" + " Why: %s\n" + " Mode: %s\n\n", + who, (unsigned long) uid, strna(u), (unsigned long) pid, strna(comm), + what, + why, + mode); dbus_message_iter_next(&sub); n++; } - printf("\n%u inhibitors listed.\n", n); - r = 0; - -finish: - if (reply) - dbus_message_unref(reply); - - return r; + printf("%u inhibitors listed.\n", n); + return 0; } static int help(void) { @@ -239,7 +218,10 @@ static int parse_argv(int argc, char *argv[]) { } } - if (arg_action == ACTION_INHIBIT && optind >= argc) { + if (arg_action == ACTION_INHIBIT && argc == 1) + arg_action = ACTION_LIST; + + else if (arg_action == ACTION_INHIBIT && optind >= argc) { log_error("Missing command line to execute."); return -EINVAL; } @@ -251,7 +233,7 @@ int main(int argc, char *argv[]) { int r, exit_code = 0; DBusConnection *bus = NULL; DBusError error; - int fd = -1; + _cleanup_close_ int fd = -1; dbus_error_init(&error); @@ -273,7 +255,7 @@ int main(int argc, char *argv[]) { r = print_inhibitors(bus, &error); if (r < 0) { - log_error("Failed to list inhibitors: %s", bus_error_message_or_strerror(&error, -r)); + log_error("Failed to list inhibitors: %s", bus_error(&error, r)); goto finish; } @@ -288,7 +270,7 @@ int main(int argc, char *argv[]) { free(w); if (fd < 0) { - log_error("Failed to inhibit: %s", bus_error_message_or_strerror(&error, -r)); + log_error("Failed to inhibit: %s", bus_error(&error, r)); r = fd; goto finish; } @@ -324,8 +306,5 @@ finish: dbus_error_free(&error); - if (fd >= 0) - close_nointr_nofail(fd); - return r < 0 ? EXIT_FAILURE : exit_code; } diff --git a/src/login/libsystemd-login.sym b/src/login/libsystemd-login.sym index ff51be729b..925fb91095 100644 --- a/src/login/libsystemd-login.sym +++ b/src/login/libsystemd-login.sym @@ -53,3 +53,25 @@ global: sd_seat_can_tty; sd_seat_can_graphical; } LIBSYSTEMD_LOGIN_43; + +LIBSYSTEMD_LOGIN_198 { +global: + sd_session_get_tty; +} LIBSYSTEMD_LOGIN_186; + +LIBSYSTEMD_LOGIN_201 { +global: + sd_login_monitor_get_events; + sd_login_monitor_get_timeout; +} LIBSYSTEMD_LOGIN_198; + +LIBSYSTEMD_LOGIN_202 { +global: + sd_pid_get_user_unit; + sd_pid_get_machine_name; +} LIBSYSTEMD_LOGIN_201; + +LIBSYSTEMD_LOGIN_203 { +global: + sd_get_machine_names; +} LIBSYSTEMD_LOGIN_202; diff --git a/src/login/loginctl.c b/src/login/loginctl.c index e2b33a626c..caaea8dfaa 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -40,6 +40,7 @@ static char **arg_property = NULL; static bool arg_all = false; +static bool arg_full = false; static bool arg_no_pager = false; static const char *arg_kill_who = NULL; static int arg_signal = SIGTERM; @@ -57,7 +58,7 @@ static void pager_open_if_enabled(void) { if (arg_no_pager) return; - pager_open(); + pager_open(false); } static void polkit_agent_open_if_enabled(void) { @@ -71,7 +72,7 @@ static void polkit_agent_open_if_enabled(void) { } static int list_sessions(DBusConnection *bus, char **args, unsigned n) { - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; DBusMessageIter iter, sub, sub2; unsigned k = 0; @@ -88,14 +89,13 @@ static int list_sessions(DBusConnection *bus, char **args, unsigned n) { NULL, DBUS_TYPE_INVALID); if (r) - goto finish; + return r; if (!dbus_message_iter_init(reply, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } dbus_message_iter_recurse(&iter, &sub); @@ -109,8 +109,7 @@ static int list_sessions(DBusConnection *bus, char **args, unsigned n) { if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } dbus_message_iter_recurse(&sub, &sub2); @@ -121,8 +120,7 @@ static int list_sessions(DBusConnection *bus, char **args, unsigned n) { bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &seat, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } printf("%10s %10u %-16s %-16s\n", id, (unsigned) uid, user, seat); @@ -135,17 +133,11 @@ static int list_sessions(DBusConnection *bus, char **args, unsigned n) { if (on_tty()) printf("\n%u sessions listed.\n", k); - r = 0; - -finish: - if (reply) - dbus_message_unref(reply); - - return r; + return 0; } static int list_users(DBusConnection *bus, char **args, unsigned n) { - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; DBusMessageIter iter, sub, sub2; unsigned k = 0; @@ -162,14 +154,13 @@ static int list_users(DBusConnection *bus, char **args, unsigned n) { NULL, DBUS_TYPE_INVALID); if (r) - goto finish; + return r; if (!dbus_message_iter_init(reply, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } dbus_message_iter_recurse(&iter, &sub); @@ -183,8 +174,7 @@ static int list_users(DBusConnection *bus, char **args, unsigned n) { if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } dbus_message_iter_recurse(&sub, &sub2); @@ -193,8 +183,7 @@ static int list_users(DBusConnection *bus, char **args, unsigned n) { bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &user, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } printf("%10u %-16s\n", (unsigned) uid, user); @@ -207,17 +196,11 @@ static int list_users(DBusConnection *bus, char **args, unsigned n) { if (on_tty()) printf("\n%u users listed.\n", k); - r = 0; - -finish: - if (reply) - dbus_message_unref(reply); - - return r; + return 0; } static int list_seats(DBusConnection *bus, char **args, unsigned n) { - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; DBusMessageIter iter, sub, sub2; unsigned k = 0; @@ -234,14 +217,13 @@ static int list_seats(DBusConnection *bus, char **args, unsigned n) { NULL, DBUS_TYPE_INVALID); if (r) - goto finish; + return r; if (!dbus_message_iter_init(reply, &iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRUCT) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } dbus_message_iter_recurse(&iter, &sub); @@ -254,8 +236,7 @@ static int list_seats(DBusConnection *bus, char **args, unsigned n) { if (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_STRUCT) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } dbus_message_iter_recurse(&sub, &sub2); @@ -263,8 +244,7 @@ static int list_seats(DBusConnection *bus, char **args, unsigned n) { if (bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_STRING, &seat, true) < 0 || bus_iter_get_basic_and_next(&sub2, DBUS_TYPE_OBJECT_PATH, &object, false) < 0) { log_error("Failed to parse reply."); - r = -EIO; - goto finish; + return -EIO; } printf("%-16s\n", seat); @@ -277,13 +257,7 @@ static int list_seats(DBusConnection *bus, char **args, unsigned n) { if (on_tty()) printf("\n%u seats listed.\n", k); - r = 0; - -finish: - if (reply) - dbus_message_unref(reply); - - return r; + return 0; } typedef struct SessionStatusInfo { @@ -402,6 +376,9 @@ static void print_session_status_info(SessionStatusInfo *i) { if (i->default_control_group) { unsigned c; + int output_flags = + arg_all * OUTPUT_SHOW_ALL | + arg_full * OUTPUT_FULL_WIDTH; printf("\t CGroup: %s\n", i->default_control_group); @@ -412,7 +389,10 @@ static void print_session_status_info(SessionStatusInfo *i) { else c = 0; - show_cgroup_and_extra_by_spec(i->default_control_group, "\t\t ", c, false, arg_all, &i->leader, i->leader > 0 ? 1 : 0); + show_cgroup_and_extra_by_spec(i->default_control_group, + "\t\t ", c, false, &i->leader, + i->leader > 0 ? 1 : 0, + output_flags); } } } @@ -454,6 +434,9 @@ static void print_user_status_info(UserStatusInfo *i) { if (i->default_control_group) { unsigned c; + int output_flags = + arg_all * OUTPUT_SHOW_ALL | + arg_full * OUTPUT_FULL_WIDTH; printf("\t CGroup: %s\n", i->default_control_group); @@ -464,7 +447,8 @@ static void print_user_status_info(UserStatusInfo *i) { else c = 0; - show_cgroup_by_path(i->default_control_group, "\t\t ", c, false, arg_all); + show_cgroup_by_path(i->default_control_group, "\t\t ", + c, false, output_flags); } } } @@ -850,17 +834,13 @@ static int show_one(const char *verb, DBusConnection *bus, const char *path, boo const char *interface = ""; int r; DBusMessageIter iter, sub, sub2, sub3; - SessionStatusInfo session_info; - UserStatusInfo user_info; - SeatStatusInfo seat_info; + SessionStatusInfo session_info = {}; + UserStatusInfo user_info = {}; + SeatStatusInfo seat_info = {}; assert(path); assert(new_line); - zero(session_info); - zero(user_info); - zero(seat_info); - r = bus_method_call_with_reply( bus, "org.freedesktop.login1", @@ -950,7 +930,7 @@ finish: } static int show(DBusConnection *bus, char **args, unsigned n) { - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r, ret = 0; DBusError error; unsigned i; @@ -1037,15 +1017,9 @@ static int show(DBusConnection *bus, char **args, unsigned n) { r = show_one(args[0], bus, path, show_properties, &new_line); if (r != 0) ret = r; - - dbus_message_unref(reply); - reply = NULL; } finish: - if (reply) - dbus_message_unref(reply); - dbus_error_free(&error); return ret; @@ -1081,7 +1055,6 @@ finish: } static int kill_session(DBusConnection *bus, char **args, unsigned n) { - int ret = 0; unsigned i; assert(args); @@ -1090,28 +1063,28 @@ static int kill_session(DBusConnection *bus, char **args, unsigned n) { arg_kill_who = "all"; for (i = 1; i < n; i++) { - ret = bus_method_call_with_reply ( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "KillSession", - NULL, - NULL, - DBUS_TYPE_STRING, &args[i], - DBUS_TYPE_STRING, &arg_kill_who, - DBUS_TYPE_INT32, &arg_signal, - DBUS_TYPE_INVALID); - if (ret) - goto finish; + int r; + + r = bus_method_call_with_reply ( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "KillSession", + NULL, + NULL, + DBUS_TYPE_STRING, &args[i], + DBUS_TYPE_STRING, &arg_kill_who, + DBUS_TYPE_INT32, &arg_signal, + DBUS_TYPE_INVALID); + if (r) + return r; } -finish: - return ret; + return 0; } static int enable_linger(DBusConnection *bus, char **args, unsigned n) { - int ret = 0; unsigned i; dbus_bool_t b, interactive = true; @@ -1124,36 +1097,35 @@ static int enable_linger(DBusConnection *bus, char **args, unsigned n) { for (i = 1; i < n; i++) { uint32_t u; uid_t uid; + int r; - ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL); - if (ret < 0) { - log_error("Failed to resolve user %s: %s", args[i], strerror(-ret)); - goto finish; + r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL); + if (r < 0) { + log_error("Failed to resolve user %s: %s", args[i], strerror(-r)); + return r; } u = (uint32_t) uid; - ret = bus_method_call_with_reply ( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "SetUserLinger", - NULL, - NULL, - DBUS_TYPE_UINT32, &u, - DBUS_TYPE_BOOLEAN, &b, - DBUS_TYPE_BOOLEAN, &interactive, - DBUS_TYPE_INVALID); - if (ret) - goto finish; + r = bus_method_call_with_reply ( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetUserLinger", + NULL, + NULL, + DBUS_TYPE_UINT32, &u, + DBUS_TYPE_BOOLEAN, &b, + DBUS_TYPE_BOOLEAN, &interactive, + DBUS_TYPE_INVALID); + if (r) + return r; } -finish: - return ret; + return 0; } static int terminate_user(DBusConnection *bus, char **args, unsigned n) { - int ret = 0; unsigned i; assert(args); @@ -1161,34 +1133,33 @@ static int terminate_user(DBusConnection *bus, char **args, unsigned n) { for (i = 1; i < n; i++) { uint32_t u; uid_t uid; + int r; - ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL); - if (ret < 0) { - log_error("Failed to look up user %s: %s", args[i], strerror(-ret)); - goto finish; + r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL); + if (r < 0) { + log_error("Failed to look up user %s: %s", args[i], strerror(-r)); + return r; } u = (uint32_t) uid; - ret = bus_method_call_with_reply ( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "TerminateUser", - NULL, - NULL, - DBUS_TYPE_UINT32, &u, - DBUS_TYPE_INVALID); - if (ret) - goto finish; + r = bus_method_call_with_reply ( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "TerminateUser", + NULL, + NULL, + DBUS_TYPE_UINT32, &u, + DBUS_TYPE_INVALID); + if (r) + return r; } -finish: - return ret; + return 0; } static int kill_user(DBusConnection *bus, char **args, unsigned n) { - int ret = 0; unsigned i; assert(args); @@ -1199,35 +1170,34 @@ static int kill_user(DBusConnection *bus, char **args, unsigned n) { for (i = 1; i < n; i++) { uid_t uid; uint32_t u; + int r; - ret = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL); - if (ret < 0) { - log_error("Failed to look up user %s: %s", args[i], strerror(-ret)); - goto finish; + r = get_user_creds((const char**) (args+i), &uid, NULL, NULL, NULL); + if (r < 0) { + log_error("Failed to look up user %s: %s", args[i], strerror(-r)); + return r; } u = (uint32_t) uid; - ret = bus_method_call_with_reply ( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "KillUser", - NULL, - NULL, - DBUS_TYPE_UINT32, &u, - DBUS_TYPE_INT32, &arg_signal, - DBUS_TYPE_INVALID); - if (ret) - goto finish; + r = bus_method_call_with_reply ( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "KillUser", + NULL, + NULL, + DBUS_TYPE_UINT32, &u, + DBUS_TYPE_INT32, &arg_signal, + DBUS_TYPE_INVALID); + if (r) + return r; } -finish: - return ret; + return 0; } static int attach(DBusConnection *bus, char **args, unsigned n) { - int ret = 0; unsigned i; dbus_bool_t interactive = true; @@ -1236,24 +1206,25 @@ static int attach(DBusConnection *bus, char **args, unsigned n) { polkit_agent_open_if_enabled(); for (i = 2; i < n; i++) { - ret = bus_method_call_with_reply ( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "AttachDevice", - NULL, - NULL, - DBUS_TYPE_STRING, &args[1], - DBUS_TYPE_STRING, &args[i], - DBUS_TYPE_BOOLEAN, &interactive, - DBUS_TYPE_INVALID); - if (ret) - goto finish; + int r; + + r = bus_method_call_with_reply ( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "AttachDevice", + NULL, + NULL, + DBUS_TYPE_STRING, &args[1], + DBUS_TYPE_STRING, &args[i], + DBUS_TYPE_BOOLEAN, &interactive, + DBUS_TYPE_INVALID); + if (r) + return r; } -finish: - return ret; + return 0; } static int flush_devices(DBusConnection *bus, char **args, unsigned n) { @@ -1276,6 +1247,8 @@ static int flush_devices(DBusConnection *bus, char **args, unsigned n) { } static int lock_sessions(DBusConnection *bus, char **args, unsigned n) { + assert(args); + polkit_agent_open_if_enabled(); return bus_method_call_with_reply ( @@ -1283,35 +1256,35 @@ static int lock_sessions(DBusConnection *bus, char **args, unsigned n) { "org.freedesktop.login1", "/org/freedesktop/login1", "org.freedesktop.login1.Manager", - "LockSessions", + streq(args[0], "lock-sessions") ? "LockSessions" : "UnlockSessions", NULL, NULL, DBUS_TYPE_INVALID); } static int terminate_seat(DBusConnection *bus, char **args, unsigned n) { - int ret = 0; unsigned i; assert(args); for (i = 1; i < n; i++) { - ret = bus_method_call_with_reply ( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "TerminateSeat", - NULL, - NULL, - DBUS_TYPE_STRING, &args[i], - DBUS_TYPE_INVALID); - if (ret) - goto finish; + int r; + + r = bus_method_call_with_reply ( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "TerminateSeat", + NULL, + NULL, + DBUS_TYPE_STRING, &args[i], + DBUS_TYPE_INVALID); + if (r) + return r; } -finish: - return ret; + return 0; } static int help(void) { @@ -1323,6 +1296,7 @@ static int help(void) { " -p --property=NAME Show only properties by this name\n" " -a --all Show all properties, including empty ones\n" " --kill-who=WHO Who to send signal to\n" + " --full Do not ellipsize output\n" " -s --signal=SIGNAL Which signal to send\n" " --no-ask-password Don't prompt for password\n" " -H --host=[USER@]HOST Show information for remote host\n" @@ -1336,6 +1310,7 @@ static int help(void) { " lock-session [ID...] Screen lock one or more sessions\n" " unlock-session [ID...] Screen unlock one or more sessions\n" " lock-sessions Screen lock all current sessions\n" + " unlock-sessions Screen unlock all current 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" @@ -1362,7 +1337,8 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_NO_PAGER, ARG_KILL_WHO, - ARG_NO_ASK_PASSWORD + ARG_NO_ASK_PASSWORD, + ARG_FULL, }; static const struct option options[] = { @@ -1376,6 +1352,7 @@ static int parse_argv(int argc, char *argv[]) { { "host", required_argument, NULL, 'H' }, { "privileged", no_argument, NULL, 'P' }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, + { "full", no_argument, NULL, ARG_FULL }, { NULL, 0, NULL, 0 } }; @@ -1447,6 +1424,10 @@ static int parse_argv(int argc, char *argv[]) { arg_host = optarg; break; + case ARG_FULL: + arg_full = true; + break; + case '?': return -EINVAL; @@ -1478,6 +1459,7 @@ static int loginctl_main(DBusConnection *bus, int argc, char *argv[], DBusError { "lock-session", MORE, 2, activate }, { "unlock-session", MORE, 2, activate }, { "lock-sessions", EQUAL, 1, lock_sessions }, + { "unlock-sessions", EQUAL, 1, lock_sessions }, { "terminate-session", MORE, 2, activate }, { "kill-session", MORE, 2, kill_session }, { "list-users", EQUAL, 1, list_users }, diff --git a/src/login/logind-action.c b/src/login/logind-action.c index e1517d6ac2..c930591023 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -21,10 +21,13 @@ #include <unistd.h> +#include <systemd/sd-messages.h> + #include "conf-parser.h" #include "special.h" #include "dbus-common.h" #include "logind-action.h" +#include "sleep-config.h" int manager_handle_action( Manager *m, @@ -56,10 +59,15 @@ int manager_handle_action( DBusError error; int r; InhibitWhat inhibit_operation; - bool supported = true; + bool supported; assert(m); + if (m->action_what) { + log_debug("Action already in progress, ignoring."); + return -EALREADY; + } + /* If the key handling is turned off, don't do anything */ if (handle == HANDLE_IGNORE) { log_debug("Refusing operation, as it is turned off."); @@ -67,13 +75,15 @@ int manager_handle_action( } if (handle == HANDLE_SUSPEND) - supported = can_sleep("mem") > 0; + supported = can_sleep("suspend") > 0; else if (handle == HANDLE_HIBERNATE) - supported = can_sleep("disk") > 0; + supported = can_sleep("hibernate") > 0; else if (handle == HANDLE_HYBRID_SLEEP) - supported = can_sleep("disk") > 0 && can_sleep_disk("suspend") > 0; + supported = can_sleep("hybrid-sleep") > 0; else if (handle == HANDLE_KEXEC) supported = access("/sbin/kexec", X_OK) >= 0; + else + supported = true; if (!supported) { log_warning("Requested operation not supported, ignoring."); diff --git a/src/login/logind-action.h b/src/login/logind-action.h index 7ab44644f2..552713637d 100644 --- a/src/login/logind-action.h +++ b/src/login/logind-action.h @@ -46,9 +46,9 @@ int manager_handle_action( bool ignore_inhibited, bool is_edge); -const char* handle_action_to_string(HandleAction h); -HandleAction handle_action_from_string(const char *s); +const char* handle_action_to_string(HandleAction h) _const_; +HandleAction handle_action_from_string(const char *s) _pure_; -int config_parse_handle_action(const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); +int config_parse_handle_action(const char *unit, const char *filename, unsigned line, const char *section, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata); #endif diff --git a/src/login/logind-button.c b/src/login/logind-button.c index dbf3d3c446..ea45c28eef 100644 --- a/src/login/logind-button.c +++ b/src/login/logind-button.c @@ -33,6 +33,7 @@ #include "logind-button.h" #include "special.h" #include "dbus-common.h" +#include "sd-messages.h" Button* button_new(Manager *m, const char *name) { Button *b; @@ -70,7 +71,11 @@ void button_free(Button *b) { if (b->fd >= 0) { hashmap_remove(b->manager->button_fds, INT_TO_PTR(b->fd + 1)); assert_se(epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_DEL, b->fd, NULL) == 0); - close_nointr_nofail(b->fd); + + /* If the device has been unplugged close() returns + * ENODEV, let's ignore this, hence we don't use + * close_nointr_nofail() */ + close(b->fd); } free(b->name); @@ -102,7 +107,7 @@ int button_open(Button *b) { assert(b); if (b->fd >= 0) { - close_nointr_nofail(b->fd); + close(b->fd); b->fd = -1; } @@ -145,7 +150,7 @@ int button_open(Button *b) { return 0; fail: - close_nointr_nofail(b->fd); + close(b->fd); b->fd = -1; return r; } @@ -188,7 +193,10 @@ int button_process(Button *b) { case KEY_POWER: case KEY_POWER2: - log_info("Power key pressed."); + log_struct(LOG_INFO, + "MESSAGE=Power key pressed.", + MESSAGE_ID(SD_MESSAGE_POWER_KEY), + NULL); return button_handle(b, INHIBIT_HANDLE_POWER_KEY, b->manager->handle_power_key, b->manager->power_key_ignore_inhibited, true); /* The kernel is a bit confused here: @@ -198,11 +206,17 @@ int button_process(Button *b) { */ case KEY_SLEEP: - log_info("Suspend key pressed."); + log_struct(LOG_INFO, + "MESSAGE=Suspend key pressed.", + MESSAGE_ID(SD_MESSAGE_SUSPEND_KEY), + NULL); return button_handle(b, INHIBIT_HANDLE_SUSPEND_KEY, b->manager->handle_suspend_key, b->manager->suspend_key_ignore_inhibited, true); case KEY_SUSPEND: - log_info("Hibernate key pressed."); + log_struct(LOG_INFO, + "MESSAGE=Hibernate key pressed.", + MESSAGE_ID(SD_MESSAGE_HIBERNATE_KEY), + NULL); return button_handle(b, INHIBIT_HANDLE_HIBERNATE_KEY, b->manager->handle_hibernate_key, b->manager->hibernate_key_ignore_inhibited, true); } @@ -211,7 +225,10 @@ int button_process(Button *b) { switch (ev.code) { case SW_LID: - log_info("Lid closed."); + log_struct(LOG_INFO, + "MESSAGE=Lid closed.", + MESSAGE_ID(SD_MESSAGE_LID_CLOSED), + NULL); b->lid_close_queued = true; return button_handle(b, INHIBIT_HANDLE_LID_SWITCH, b->manager->handle_lid_switch, b->manager->lid_switch_ignore_inhibited, true); @@ -222,7 +239,10 @@ int button_process(Button *b) { switch (ev.code) { case SW_LID: - log_info("Lid opened."); + log_struct(LOG_INFO, + "MESSAGE=Lid opened.", + MESSAGE_ID(SD_MESSAGE_LID_OPENED), + NULL); b->lid_close_queued = false; break; } diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 77a06f2ce4..4a84b860f1 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -31,8 +31,11 @@ #include "path-util.h" #include "polkit.h" #include "special.h" +#include "sleep-config.h" #include "systemd/sd-id128.h" #include "systemd/sd-messages.h" +#include "fileio-label.h" +#include "label.h" #define BUS_MANAGER_INTERFACE \ " <interface name=\"org.freedesktop.login1.Manager\">\n" \ @@ -64,7 +67,7 @@ " <method name=\"CreateSession\">\n" \ " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \ " <arg name=\"leader\" type=\"u\" direction=\"in\"/>\n" \ - " <arg name=\"sevice\" type=\"s\" direction=\"in\"/>\n" \ + " <arg name=\"service\" type=\"s\" direction=\"in\"/>\n" \ " <arg name=\"type\" type=\"s\" direction=\"in\"/>\n" \ " <arg name=\"class\" type=\"s\" direction=\"in\"/>\n" \ " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \ @@ -102,6 +105,7 @@ " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \ " </method>\n" \ " <method name=\"LockSessions\"/>\n" \ + " <method name=\"UnlockSessions\"/>\n" \ " <method name=\"KillSession\">\n" \ " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \ " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \ @@ -296,30 +300,30 @@ static int bus_manager_append_preparing(DBusMessageIter *i, const char *property assert(property); if (streq(property, "PreparingForShutdown")) - b = !!(m->delayed_what & INHIBIT_SHUTDOWN); + b = !!(m->action_what & INHIBIT_SHUTDOWN); else - b = !!(m->delayed_what & INHIBIT_SLEEP); + b = !!(m->action_what & INHIBIT_SLEEP); dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b); return 0; } static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMessage **_reply) { - Session *session = NULL; - User *user = NULL; - const char *type, *class, *seat, *tty, *display, *remote_user, *remote_host, *service; + const char *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *service; uint32_t uid, leader, audit_id = 0; dbus_bool_t remote, kill_processes, exists; - char **controllers = NULL, **reset_controllers = NULL; + _cleanup_strv_free_ char **controllers = NULL, **reset_controllers = NULL; + _cleanup_free_ char *cgroup = NULL, *id = NULL, *p = NULL; SessionType t; SessionClass c; - Seat *s; DBusMessageIter iter; int r; - char *id = NULL, *p; uint32_t vtnr = 0; - int fifo_fd = -1; - DBusMessage *reply = NULL; + _cleanup_close_ int fifo_fd = -1; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; + Session *session = NULL; + User *user = NULL; + Seat *seat = NULL; bool b; assert(m); @@ -350,31 +354,38 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess return -EINVAL; dbus_message_iter_get_basic(&iter, &type); - t = session_type_from_string(type); + if (isempty(type)) + t = _SESSION_TYPE_INVALID; + else { + t = session_type_from_string(type); + if (t < 0) + return -EINVAL; + } - if (t < 0 || - !dbus_message_iter_next(&iter) || + if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) return -EINVAL; dbus_message_iter_get_basic(&iter, &class); if (isempty(class)) - c = SESSION_USER; - else + c = _SESSION_CLASS_INVALID; + else { c = session_class_from_string(class); + if (c < 0) + return -EINVAL; + } - if (c < 0 || - !dbus_message_iter_next(&iter) || + if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) return -EINVAL; - dbus_message_iter_get_basic(&iter, &seat); + dbus_message_iter_get_basic(&iter, &cseat); - if (isempty(seat)) - s = NULL; + if (isempty(cseat)) + seat = NULL; else { - s = hashmap_get(m->seats, seat); - if (!s) + seat = hashmap_get(m->seats, cseat); + if (!seat) return -ENOENT; } @@ -393,9 +404,9 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess if (tty_is_vc(tty)) { int v; - if (!s) - s = m->vtconsole; - else if (s != m->vtconsole) + if (!seat) + seat = m->vtconsole; + else if (seat != m->vtconsole) return -EINVAL; v = vtnr_from_tty(tty); @@ -409,18 +420,17 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess return -EINVAL; } else if (tty_is_console(tty)) { - if (!s) - s = m->vtconsole; - else if (s != m->vtconsole) + if (!seat) + seat = m->vtconsole; + else if (seat != m->vtconsole) return -EINVAL; if (vtnr != 0) return -EINVAL; - } - if (s) { - if (seat_can_multi_session(s)) { + if (seat) { + if (seat_can_multi_session(seat)) { if (vtnr > 63) return -EINVAL; } else { @@ -439,6 +449,22 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) return -EINVAL; + if (t == _SESSION_TYPE_INVALID) { + if (!isempty(display)) + t = SESSION_X11; + else if (!isempty(tty)) + t = SESSION_TTY; + else + t = SESSION_UNSPECIFIED; + } + + if (c == _SESSION_CLASS_INVALID) { + if (!isempty(display) || !isempty(tty)) + c = SESSION_USER; + else + c = SESSION_BACKGROUND; + } + dbus_message_iter_get_basic(&iter, &remote); if (!dbus_message_iter_next(&iter) || @@ -462,8 +488,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess if (r < 0) return -EINVAL; - if (strv_contains(controllers, "systemd") || - !dbus_message_iter_next(&iter) || + if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING) { r = -EINVAL; @@ -474,8 +499,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess if (r < 0) goto fail; - if (strv_contains(reset_controllers, "systemd") || - !dbus_message_iter_next(&iter) || + if (!dbus_message_iter_next(&iter) || dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) { r = -EINVAL; goto fail; @@ -483,78 +507,84 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess dbus_message_iter_get_basic(&iter, &kill_processes); - r = manager_add_user_by_uid(m, uid, &user); + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, leader, &cgroup); if (r < 0) goto fail; - audit_session_from_pid(leader, &audit_id); - - if (audit_id > 0) { - asprintf(&id, "%lu", (unsigned long) audit_id); + r = manager_get_session_by_cgroup(m, cgroup, &session); + if (r < 0) + goto fail; - if (!id) { - r = -ENOMEM; + if (session) { + fifo_fd = session_create_fifo(session); + if (fifo_fd < 0) { + r = fifo_fd; goto fail; } - session = hashmap_get(m->sessions, id); + /* Session already exists, client is probably + * something like "su" which changes uid but + * is still the same audit session */ - if (session) { - free(id); + reply = dbus_message_new_method_return(message); + if (!reply) { + r = -ENOMEM; + goto fail; + } - fifo_fd = session_create_fifo(session); - if (fifo_fd < 0) { - r = fifo_fd; - goto fail; - } + p = session_bus_path(session); + if (!p) { + r = -ENOMEM; + goto fail; + } - /* Session already exists, client is probably - * something like "su" which changes uid but - * is still the same audit session */ + cseat = session->seat ? session->seat->id : ""; + vtnr = session->vtnr; + exists = true; - reply = dbus_message_new_method_return(message); - if (!reply) { - r = -ENOMEM; - goto fail; - } + b = dbus_message_append_args( + reply, + DBUS_TYPE_STRING, &session->id, + DBUS_TYPE_OBJECT_PATH, &p, + DBUS_TYPE_STRING, &session->user->runtime_path, + DBUS_TYPE_UNIX_FD, &fifo_fd, + DBUS_TYPE_STRING, &cseat, + DBUS_TYPE_UINT32, &vtnr, + DBUS_TYPE_BOOLEAN, &exists, + DBUS_TYPE_INVALID); + if (!b) { + r = -ENOMEM; + goto fail; + } - p = session_bus_path(session); - if (!p) { - r = -ENOMEM; - goto fail; - } + *_reply = reply; + reply = NULL; - seat = session->seat ? session->seat->id : ""; - vtnr = session->vtnr; - exists = true; - - b = dbus_message_append_args( - reply, - DBUS_TYPE_STRING, &session->id, - DBUS_TYPE_OBJECT_PATH, &p, - DBUS_TYPE_STRING, &session->user->runtime_path, - DBUS_TYPE_UNIX_FD, &fifo_fd, - DBUS_TYPE_STRING, &seat, - DBUS_TYPE_UINT32, &vtnr, - DBUS_TYPE_BOOLEAN, &exists, - DBUS_TYPE_INVALID); - free(p); + return 0; + } - if (!b) { - r = -ENOMEM; - goto fail; - } + audit_session_from_pid(leader, &audit_id); + if (audit_id > 0) { + /* Keep our session IDs and the audit session IDs in sync */ - close_nointr_nofail(fifo_fd); - *_reply = reply; + if (asprintf(&id, "%lu", (unsigned long) audit_id) < 0) { + r = -ENOMEM; + goto fail; + } - strv_free(controllers); - strv_free(reset_controllers); + /* Wut? There's already a session by this name and we + * didn't find it above? Weird, then let's not trust + * the audit data and let's better register a new + * ID */ + if (hashmap_get(m->sessions, id)) { + audit_id = 0; - return 0; + free(id); + id = NULL; } + } - } else { + if (!id) { do { free(id); id = NULL; @@ -567,8 +597,11 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess } while (hashmap_get(m->sessions, id)); } + r = manager_add_user_by_uid(m, uid, &user); + if (r < 0) + goto fail; + r = manager_add_session(m, user, id, &session); - free(id); if (r < 0) goto fail; @@ -577,11 +610,11 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess session->type = t; session->class = c; session->remote = remote; - session->controllers = controllers; - session->reset_controllers = reset_controllers; session->kill_processes = kill_processes; session->vtnr = vtnr; + session->controllers = cg_shorten_controllers(controllers); + session->reset_controllers = cg_shorten_controllers(reset_controllers); controllers = reset_controllers = NULL; if (!isempty(tty)) { @@ -630,8 +663,8 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess goto fail; } - if (s) { - r = seat_attach_session(s, session); + if (seat) { + r = seat_attach_session(seat, session); if (r < 0) goto fail; } @@ -652,7 +685,7 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess goto fail; } - seat = s ? s->id : ""; + cseat = seat ? seat->id : ""; exists = false; b = dbus_message_append_args( reply, @@ -660,42 +693,38 @@ static int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMess DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_STRING, &session->user->runtime_path, DBUS_TYPE_UNIX_FD, &fifo_fd, - DBUS_TYPE_STRING, &seat, + DBUS_TYPE_STRING, &cseat, DBUS_TYPE_UINT32, &vtnr, DBUS_TYPE_BOOLEAN, &exists, DBUS_TYPE_INVALID); - free(p); if (!b) { r = -ENOMEM; goto fail; } - close_nointr_nofail(fifo_fd); *_reply = reply; + reply = NULL; return 0; fail: - strv_free(controllers); - strv_free(reset_controllers); - if (session) session_add_to_gc_queue(session); if (user) user_add_to_gc_queue(user); - if (fifo_fd >= 0) - close_nointr_nofail(fifo_fd); - - if (reply) - dbus_message_unref(reply); - return r; } -static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessage *message, DBusError *error, DBusMessage **_reply) { +static int bus_manager_inhibit( + Manager *m, + DBusConnection *connection, + DBusMessage *message, + DBusError *error, + DBusMessage **_reply) { + Inhibitor *i = NULL; char *id = NULL; const char *who, *why, *what, *mode; @@ -704,7 +733,7 @@ static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessa InhibitMode mm; unsigned long ul; int r, fifo_fd = -1; - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; assert(m); assert(connection); @@ -742,6 +771,15 @@ static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessa goto fail; } + /* Don't allow taking delay locks while we are already + * executing the operation. We shouldn't create the impression + * that the lock was successful if the machine is about to go + * down/suspend any moment. */ + if (m->action_what & w) { + r = -EALREADY; + goto fail; + } + r = verify_polkit(connection, message, w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") : w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") : @@ -816,6 +854,7 @@ static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessa close_nointr_nofail(fifo_fd); *_reply = reply; + reply = NULL; inhibitor_start(i); @@ -828,9 +867,6 @@ fail: if (fifo_fd >= 0) close_nointr_nofail(fifo_fd); - if (reply) - dbus_message_unref(reply); - return r; } @@ -872,7 +908,7 @@ static int trigger_device(Manager *m, struct udev_device *d) { goto finish; } - write_one_line_file(t, "change"); + write_string_file(t, "change"); free(t); } @@ -887,7 +923,7 @@ finish: static int attach_device(Manager *m, const char *seat, const char *sysfs) { struct udev_device *d; - char *rule = NULL, *file = NULL; + _cleanup_free_ char *rule = NULL, *file = NULL; const char *id_for_seat; int r; @@ -921,16 +957,14 @@ static int attach_device(Manager *m, const char *seat, const char *sysfs) { } mkdir_p_label("/etc/udev/rules.d", 0755); - r = write_one_line_file_atomic(file, rule); + label_init("/etc"); + r = write_string_file_atomic_label(file, rule); if (r < 0) goto finish; r = trigger_device(m, d); finish: - free(rule); - free(file); - if (d) udev_device_unref(d); @@ -938,7 +972,7 @@ finish: } static int flush_devices(Manager *m) { - DIR *d; + _cleanup_closedir_ DIR *d; assert(m); @@ -963,8 +997,6 @@ static int flush_devices(Manager *m) { if (unlinkat(dirfd(d), de->d_name, 0) < 0) log_warning("Failed to unlink %s: %m", de->d_name); } - - closedir(d); } return trigger_device(m, NULL); @@ -979,75 +1011,115 @@ static int have_multiple_sessions( assert(m); - /* Check for other users' sessions. Greeter sessions do not count. */ + /* Check for other users' sessions. Greeter sessions do not + * count, and non-login sessions do not count either. */ HASHMAP_FOREACH(session, m->sessions, i) - if (session->class == SESSION_USER && session->user->uid != uid) + if (session->class == SESSION_USER && + session->user->uid != uid) return true; return false; } -static int send_start_unit(DBusConnection *connection, const char *unit_name, DBusError *error) { - const char *mode = "replace"; +static int bus_manager_log_shutdown( + Manager *m, + InhibitWhat w, + const char *unit_name) { + + const char *p, *q; + + assert(m); + assert(unit_name); + + if (w != INHIBIT_SHUTDOWN) + return 0; + + if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) { + p = "MESSAGE=System is powering down."; + q = "SHUTDOWN=power-off"; + } else if (streq(unit_name, SPECIAL_HALT_TARGET)) { + p = "MESSAGE=System is halting."; + q = "SHUTDOWN=halt"; + } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) { + p = "MESSAGE=System is rebooting."; + q = "SHUTDOWN=reboot"; + } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) { + p = "MESSAGE=System is rebooting with kexec."; + q = "SHUTDOWN=kexec"; + } else { + p = "MESSAGE=System is shutting down."; + q = NULL; + } + + return log_struct(LOG_NOTICE, MESSAGE_ID(SD_MESSAGE_SHUTDOWN), + p, + q, NULL); +} + +static int execute_shutdown_or_sleep( + Manager *m, + InhibitWhat w, + const char *unit_name, + DBusError *error) { + + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; + const char *mode = "replace-irreversibly", *p; + int r; + char *c; + assert(m); + assert(w >= 0); + assert(w < _INHIBIT_WHAT_MAX); assert(unit_name); - return bus_method_call_with_reply ( - connection, + bus_manager_log_shutdown(m, w, unit_name); + + r = bus_method_call_with_reply( + m->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", "StartUnit", - NULL, - NULL, + &reply, + error, DBUS_TYPE_STRING, &unit_name, DBUS_TYPE_STRING, &mode, DBUS_TYPE_INVALID); -} - -static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { - static const char * const signal_name[_INHIBIT_WHAT_MAX] = { - [INHIBIT_SHUTDOWN] = "PrepareForShutdown", - [INHIBIT_SLEEP] = "PrepareForSleep" - }; - - dbus_bool_t active = _active; - DBusMessage *message; - int r = 0; + if (r < 0) + return r; - assert(m); - assert(w >= 0); - assert(w < _INHIBIT_WHAT_MAX); - assert(signal_name[w]); + if (!dbus_message_get_args( + reply, + error, + DBUS_TYPE_OBJECT_PATH, &p, + DBUS_TYPE_INVALID)) + return -EINVAL; - message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w]); - if (!message) + c = strdup(p); + if (!c) return -ENOMEM; - if (!dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID) || - !dbus_connection_send(m->bus, message, NULL)) - r = -ENOMEM; + m->action_unit = unit_name; + free(m->action_job); + m->action_job = c; + m->action_what = w; - dbus_message_unref(message); - return r; + return 0; } -static int delay_shutdown_or_sleep(Manager *m, InhibitWhat w, const char *unit_name) { +static int delay_shutdown_or_sleep( + Manager *m, + InhibitWhat w, + const char *unit_name) { + assert(m); assert(w >= 0); assert(w < _INHIBIT_WHAT_MAX); + assert(unit_name); - /* Tell everybody to prepare for shutdown/sleep */ - send_prepare_for(m, w, true); - - /* Update timestamp for timeout */ - if (!m->delayed_unit) - m->delayed_timestamp = now(CLOCK_MONOTONIC); - - /* Remember what we want to do, possibly overriding what kind - * of unit we previously queued. */ - m->delayed_unit = unit_name; - m->delayed_what = w; + m->action_timestamp = now(CLOCK_MONOTONIC); + m->action_unit = unit_name; + m->action_what = w; return 0; } @@ -1060,14 +1132,13 @@ static int bus_manager_can_shutdown_or_sleep( const char *action, const char *action_multiple_sessions, const char *action_ignore_inhibit, - const char *sleep_type, - const char *sleep_disk_type, + const char *sleep_verb, DBusError *error, DBusMessage **_reply) { bool multiple_sessions, challenge, blocked, b; - const char *result; - DBusMessage *reply = NULL; + const char *result = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; unsigned long ul; @@ -1082,22 +1153,10 @@ static int bus_manager_can_shutdown_or_sleep( assert(error); assert(_reply); - if (sleep_type) { - r = can_sleep(sleep_type); - if (r < 0) - return r; - - if (r == 0) { - result = "na"; - goto finish; - } - } - - if (sleep_disk_type) { - r = can_sleep_disk(sleep_disk_type); + if (sleep_verb) { + r = can_sleep(sleep_verb); if (r < 0) return r; - if (r == 0) { result = "na"; goto finish; @@ -1166,48 +1225,37 @@ finish: reply, DBUS_TYPE_STRING, &result, DBUS_TYPE_INVALID); - if (!b) { - dbus_message_unref(reply); + if (!b) return -ENOMEM; - } *_reply = reply; + reply = NULL; return 0; } -static int bus_manager_log_shutdown( - Manager *m, - InhibitWhat w, - const char *unit_name) { +static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) { + static const char * const signal_name[_INHIBIT_WHAT_MAX] = { + [INHIBIT_SHUTDOWN] = "PrepareForShutdown", + [INHIBIT_SLEEP] = "PrepareForSleep" + }; - const char *p, *q; + dbus_bool_t active = _active; + _cleanup_dbus_message_unref_ DBusMessage *message = NULL; assert(m); - assert(unit_name); + assert(w >= 0); + assert(w < _INHIBIT_WHAT_MAX); + assert(signal_name[w]); - if (w != INHIBIT_SHUTDOWN) - return 0; + message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w]); + if (!message) + return -ENOMEM; - if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) { - p = "MESSAGE=System is powering down."; - q = "SHUTDOWN=power-off"; - } else if (streq(unit_name, SPECIAL_HALT_TARGET)) { - p = "MESSAGE=System is halting."; - q = "SHUTDOWN=halt"; - } else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) { - p = "MESSAGE=System is rebooting."; - q = "SHUTDOWN=reboot"; - } else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) { - p = "MESSAGE=System is rebooting with kexec."; - q = "SHUTDOWN=kexec"; - } else { - p = "MESSAGE=System is shutting down."; - q = NULL; - } + if (!dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID) || + !dbus_connection_send(m->bus, message, NULL)) + return -ENOMEM; - return log_struct(LOG_NOTICE, MESSAGE_ID(SD_MESSAGE_SHUTDOWN), - p, - q, NULL); + return 0; } int bus_manager_shutdown_or_sleep_now_or_later( @@ -1223,6 +1271,10 @@ int bus_manager_shutdown_or_sleep_now_or_later( assert(unit_name); assert(w >= 0); assert(w <= _INHIBIT_WHAT_MAX); + assert(!m->action_job); + + /* Tell everybody to prepare for shutdown/sleep */ + send_prepare_for(m, w, true); delayed = m->inhibit_delay_max > 0 && @@ -1232,13 +1284,10 @@ int bus_manager_shutdown_or_sleep_now_or_later( /* Shutdown is delayed, keep in mind what we * want to do, and start a timeout */ r = delay_shutdown_or_sleep(m, w, unit_name); - else { - bus_manager_log_shutdown(m, w, unit_name); - + else /* Shutdown is not delayed, execute it * immediately */ - r = send_start_unit(m->bus, unit_name, error); - } + r = execute_shutdown_or_sleep(m, w, unit_name, error); return r; } @@ -1252,8 +1301,7 @@ static int bus_manager_do_shutdown_or_sleep( const char *action, const char *action_multiple_sessions, const char *action_ignore_inhibit, - const char *sleep_type, - const char *sleep_disk_type, + const char *sleep_verb, DBusError *error, DBusMessage **_reply) { @@ -1275,6 +1323,10 @@ static int bus_manager_do_shutdown_or_sleep( assert(error); assert(_reply); + /* Don't allow multiple jobs being executed at the same time */ + if (m->action_what) + return -EALREADY; + if (!dbus_message_get_args( message, error, @@ -1282,17 +1334,8 @@ static int bus_manager_do_shutdown_or_sleep( DBUS_TYPE_INVALID)) return -EINVAL; - if (sleep_type) { - r = can_sleep(sleep_type); - if (r < 0) - return r; - - if (r == 0) - return -ENOTSUP; - } - - if (sleep_disk_type) { - r = can_sleep_disk(sleep_disk_type); + if (sleep_verb) { + r = can_sleep(sleep_verb); if (r < 0) return r; @@ -1376,7 +1419,7 @@ static DBusHandlerResult manager_message_handler( Manager *m = userdata; DBusError error; - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; assert(connection); @@ -1824,8 +1867,10 @@ static DBusHandlerResult manager_message_handler( if (!reply) goto oom; - } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions")) { - r = session_send_lock_all(m, true); + } else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSessions") || + dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "UnlockSessions")) { + + r = session_send_lock_all(m, streq(dbus_message_get_member(message), "LockSessions")); if (r < 0) bus_send_error_reply(connection, message, NULL, r); @@ -2093,7 +2138,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.power-off", "org.freedesktop.login1.power-off-multiple-sessions", "org.freedesktop.login1.power-off-ignore-inhibit", - NULL, NULL, + NULL, &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2105,7 +2150,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.reboot", "org.freedesktop.login1.reboot-multiple-sessions", "org.freedesktop.login1.reboot-ignore-inhibit", - NULL, NULL, + NULL, &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2118,7 +2163,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.suspend", "org.freedesktop.login1.suspend-multiple-sessions", "org.freedesktop.login1.suspend-ignore-inhibit", - "mem", NULL, + "suspend", &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2130,7 +2175,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "disk", NULL, + "hibernate", &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2143,7 +2188,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "disk", "suspend", + "hybrid-sleep", &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2156,7 +2201,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.power-off", "org.freedesktop.login1.power-off-multiple-sessions", "org.freedesktop.login1.power-off-ignore-inhibit", - NULL, NULL, + NULL, &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2167,7 +2212,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.reboot", "org.freedesktop.login1.reboot-multiple-sessions", "org.freedesktop.login1.reboot-ignore-inhibit", - NULL, NULL, + NULL, &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2179,7 +2224,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.suspend", "org.freedesktop.login1.suspend-multiple-sessions", "org.freedesktop.login1.suspend-ignore-inhibit", - "mem", NULL, + "suspend", &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2191,7 +2236,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "disk", NULL, + "hibernate", &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2203,7 +2248,7 @@ static DBusHandlerResult manager_message_handler( "org.freedesktop.login1.hibernate", "org.freedesktop.login1.hibernate-multiple-sessions", "org.freedesktop.login1.hibernate-ignore-inhibit", - "disk", "suspend", + "hybrid-sleep", &error, &reply); if (r < 0) return bus_send_error_reply(connection, message, &error, r); @@ -2282,16 +2327,11 @@ static DBusHandlerResult manager_message_handler( if (reply) { if (!bus_maybe_send_reply(connection, message, reply)) goto oom; - - dbus_message_unref(reply); } return DBUS_HANDLER_RESULT_HANDLED; oom: - if (reply) - dbus_message_unref(reply); - dbus_error_free(&error); return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -2324,6 +2364,30 @@ DBusHandlerResult bus_message_filter( log_error("Failed to parse Released message: %s", bus_error_message(&error)); else manager_cgroup_notify_empty(m, cgroup); + + } else if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Manager", "JobRemoved")) { + uint32_t id; + const char *path, *result, *unit; + + if (!dbus_message_get_args(message, &error, + DBUS_TYPE_UINT32, &id, + DBUS_TYPE_OBJECT_PATH, &path, + DBUS_TYPE_STRING, &unit, + DBUS_TYPE_STRING, &result, + DBUS_TYPE_INVALID)) + log_error("Failed to parse JobRemoved message: %s", bus_error_message(&error)); + + else if (m->action_job && streq(m->action_job, path)) { + log_info("Operation finished."); + + /* Tell people that they now may take a lock again */ + send_prepare_for(m, m->action_what, false); + + free(m->action_job); + m->action_job = NULL; + m->action_unit = NULL; + m->action_what = 0; + } } dbus_error_free(&error); @@ -2332,62 +2396,51 @@ DBusHandlerResult bus_message_filter( } int manager_send_changed(Manager *manager, const char *properties) { - DBusMessage *m; - int r = -ENOMEM; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; assert(manager); - m = bus_properties_changed_new("/org/freedesktop/login1", "org.freedesktop.login1.Manager", properties); + m = bus_properties_changed_new("/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + properties); if (!m) - goto finish; + return -ENOMEM; if (!dbus_connection_send(manager->bus, m, NULL)) - goto finish; - - r = 0; - -finish: - if (m) - dbus_message_unref(m); + return -ENOMEM; - return r; + return 0; } int manager_dispatch_delayed(Manager *manager) { - const char *unit_name; DBusError error; - bool delayed; int r; assert(manager); - if (!manager->delayed_unit) + if (manager->action_what == 0 || manager->action_job) return 0; /* Continue delay? */ - delayed = - manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) && - manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL, false, false, 0); - if (delayed) - return 0; + if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0)) { - bus_manager_log_shutdown(manager, manager->delayed_what, manager->delayed_unit); + if (manager->action_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC)) + return 0; - /* Reset delay data */ - unit_name = manager->delayed_unit; - manager->delayed_unit = NULL; + log_info("Delay lock is active but inhibitor timeout is reached."); + } - /* Actually do the shutdown */ + /* Actually do the operation */ dbus_error_init(&error); - r = send_start_unit(manager->bus, unit_name, &error); + r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error); if (r < 0) { - log_warning("Failed to send delayed message: %s", bus_error_message_or_strerror(&error, -r)); + log_warning("Failed to send delayed message: %s", bus_error(&error, r)); dbus_error_free(&error); + + manager->action_unit = NULL; + manager->action_what = 0; return r; } - /* Tell people about it */ - send_prepare_for(manager, manager->delayed_what, false); - return 1; } diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf index 076d116161..735d2dbc9c 100644 --- a/src/login/logind-gperf.gperf +++ b/src/login/logind-gperf.gperf @@ -21,7 +21,7 @@ Login.KillOnlyUsers, config_parse_strv, 0, offsetof(Manag Login.KillExcludeUsers, config_parse_strv, 0, offsetof(Manager, kill_exclude_users) Login.Controllers, config_parse_strv, 0, offsetof(Manager, controllers) Login.ResetControllers, config_parse_strv, 0, offsetof(Manager, reset_controllers) -Login.InhibitDelayMaxSec, config_parse_usec, 0, offsetof(Manager, inhibit_delay_max) +Login.InhibitDelayMaxSec, config_parse_sec, 0, offsetof(Manager, inhibit_delay_max) Login.HandlePowerKey, config_parse_handle_action, 0, offsetof(Manager, handle_power_key) Login.HandleSuspendKey, config_parse_handle_action, 0, offsetof(Manager, handle_suspend_key) Login.HandleHibernateKey, config_parse_handle_action, 0, offsetof(Manager, handle_hibernate_key) @@ -31,4 +31,4 @@ Login.SuspendKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manag Login.HibernateKeyIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, hibernate_key_ignore_inhibited) Login.LidSwitchIgnoreInhibited, config_parse_bool, 0, offsetof(Manager, lid_switch_ignore_inhibited) Login.IdleAction, config_parse_handle_action, 0, offsetof(Manager, idle_action) -Login.IdleActionSec, config_parse_usec, 0, offsetof(Manager, idle_action_usec) +Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec) diff --git a/src/login/logind-inhibit.c b/src/login/logind-inhibit.c index f1b9cca834..e77088364a 100644 --- a/src/login/logind-inhibit.c +++ b/src/login/logind-inhibit.c @@ -30,6 +30,7 @@ #include "mkdir.h" #include "path-util.h" #include "logind-inhibit.h" +#include "fileio.h" Inhibitor* inhibitor_new(Manager *m, const char* id) { Inhibitor *i; @@ -291,7 +292,7 @@ int inhibitor_create_fifo(Inhibitor *i) { /* Open reading side */ if (i->fifo_fd < 0) { - struct epoll_event ev; + struct epoll_event ev = {}; i->fifo_fd = open(i->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY); if (i->fifo_fd < 0) @@ -301,7 +302,6 @@ int inhibitor_create_fifo(Inhibitor *i) { if (r < 0) return r; - zero(ev); ev.events = 0; ev.data.u32 = FD_OTHER_BASE + i->fifo_fd; @@ -353,9 +353,14 @@ static int pid_is_active(Manager *m, pid_t pid) { int r; r = manager_get_session_by_pid(m, pid, &s); - if (r <= 0) + if (r < 0) return r; + /* If there's no session assigned to it, then it's globally + * active on all ttys */ + if (r == 0) + return 1; + return session_is_active(s); } @@ -439,19 +444,19 @@ InhibitWhat inhibit_what_from_string(const char *s) { size_t l; FOREACH_WORD_SEPARATOR(w, l, s, ":", state) { - if (l == 8 && strncmp(w, "shutdown", l) == 0) + if (l == 8 && strneq(w, "shutdown", l)) what |= INHIBIT_SHUTDOWN; - else if (l == 5 && strncmp(w, "sleep", l) == 0) + else if (l == 5 && strneq(w, "sleep", l)) what |= INHIBIT_SLEEP; - else if (l == 4 && strncmp(w, "idle", l) == 0) + else if (l == 4 && strneq(w, "idle", l)) what |= INHIBIT_IDLE; - else if (l == 16 && strncmp(w, "handle-power-key", l) == 0) + else if (l == 16 && strneq(w, "handle-power-key", l)) what |= INHIBIT_HANDLE_POWER_KEY; - else if (l == 18 && strncmp(w, "handle-suspend-key", l) == 0) + else if (l == 18 && strneq(w, "handle-suspend-key", l)) what |= INHIBIT_HANDLE_SUSPEND_KEY; - else if (l == 20 && strncmp(w, "handle-hibernate-key", l) == 0) + else if (l == 20 && strneq(w, "handle-hibernate-key", l)) what |= INHIBIT_HANDLE_HIBERNATE_KEY; - else if (l == 17 && strncmp(w, "handle-lid-switch", l) == 0) + else if (l == 17 && strneq(w, "handle-lid-switch", l)) what |= INHIBIT_HANDLE_LID_SWITCH; else return _INHIBIT_WHAT_INVALID; diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 7833d70a03..5c535ba0ec 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -61,7 +61,7 @@ static int bus_seat_append_active(DBusMessageIter *i, const char *property, void DBusMessageIter sub; Seat *s = data; const char *id, *path; - char *p = NULL; + _cleanup_free_ char *p = NULL; assert(i); assert(property); @@ -82,12 +82,8 @@ static int bus_seat_append_active(DBusMessageIter *i, const char *property, void } if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) || - !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) { - free(p); + !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) return -ENOMEM; - } - - free(p); if (!dbus_message_iter_close_container(i, &sub)) return -ENOMEM; @@ -108,7 +104,7 @@ static int bus_seat_append_sessions(DBusMessageIter *i, const char *property, vo return -ENOMEM; LIST_FOREACH(sessions_by_seat, session, s->sessions) { - char *p; + _cleanup_free_ char *p = NULL; if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2)) return -ENOMEM; @@ -118,12 +114,8 @@ static int bus_seat_append_sessions(DBusMessageIter *i, const char *property, vo return -ENOMEM; if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) || - !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) { - free(p); + !dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) return -ENOMEM; - } - - free(p); if (!dbus_message_iter_close_container(&sub, &sub2)) return -ENOMEM; @@ -260,7 +252,7 @@ static DBusHandlerResult seat_message_dispatch( DBusMessage *message) { DBusError error; - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; assert(s); @@ -310,18 +302,13 @@ static DBusHandlerResult seat_message_dispatch( } if (reply) { - if (!dbus_connection_send(connection, reply, NULL)) + if (!bus_maybe_send_reply(connection, message, reply)) goto oom; - - dbus_message_unref(reply); } return DBUS_HANDLER_RESULT_HANDLED; oom: - if (reply) - dbus_message_unref(reply); - dbus_error_free(&error); return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -361,7 +348,7 @@ const DBusObjectPathVTable bus_seat_vtable = { }; char *seat_bus_path(Seat *s) { - char *t, *r; + _cleanup_free_ char *t; assert(s); @@ -369,53 +356,41 @@ char *seat_bus_path(Seat *s) { if (!t) return NULL; - r = strappend("/org/freedesktop/login1/seat/", t); - free(t); - - return r; + return strappend("/org/freedesktop/login1/seat/", t); } int seat_send_signal(Seat *s, bool new_seat) { - DBusMessage *m; - int r = -ENOMEM; - char *p = NULL; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; + _cleanup_free_ char *p = NULL; assert(s); m = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", new_seat ? "SeatNew" : "SeatRemoved"); - if (!m) return -ENOMEM; p = seat_bus_path(s); if (!p) - goto finish; + return -ENOMEM; if (!dbus_message_append_args( m, DBUS_TYPE_STRING, &s->id, DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_INVALID)) - goto finish; + return -ENOMEM; if (!dbus_connection_send(s->manager->bus, m, NULL)) - goto finish; - - r = 0; - -finish: - dbus_message_unref(m); - free(p); + return -ENOMEM; - return r; + return 0; } int seat_send_changed(Seat *s, const char *properties) { - DBusMessage *m; - int r = -ENOMEM; - char *p = NULL; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; + _cleanup_free_ char *p = NULL; assert(s); @@ -428,17 +403,10 @@ int seat_send_changed(Seat *s, const char *properties) { m = bus_properties_changed_new(p, "org.freedesktop.login1.Seat", properties); if (!m) - goto finish; + return -ENOMEM; if (!dbus_connection_send(s->manager->bus, m, NULL)) - goto finish; - - r = 0; - -finish: - if (m) - dbus_message_unref(m); - free(p); + return -ENOMEM; - return r; + return 0; } diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index ef73cd434a..ec823af547 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -108,12 +108,8 @@ static int bus_session_append_seat(DBusMessageIter *i, const char *property, voi } if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) || - !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) { - free(p); + !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) return -ENOMEM; - } - - free(p); if (!dbus_message_iter_close_container(i, &sub)) return -ENOMEM; @@ -124,7 +120,7 @@ static int bus_session_append_seat(DBusMessageIter *i, const char *property, voi static int bus_session_append_user(DBusMessageIter *i, const char *property, void *data) { DBusMessageIter sub; User *u = data; - char *p = NULL; + _cleanup_free_ char *p = NULL; assert(i); assert(property); @@ -138,12 +134,8 @@ static int bus_session_append_user(DBusMessageIter *i, const char *property, voi return -ENOMEM; if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_UINT32, &u->uid) || - !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) { - free(p); + !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &p)) return -ENOMEM; - } - - free(p); if (!dbus_message_iter_close_container(i, &sub)) return -ENOMEM; @@ -205,7 +197,7 @@ static int bus_session_append_idle_hint_since(DBusMessageIter *i, const char *pr static int bus_session_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) { Session *s = data; - char *t; + _cleanup_free_ char *t = NULL; int r; bool success; @@ -218,8 +210,6 @@ static int bus_session_append_default_cgroup(DBusMessageIter *i, const char *pro return r; success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t); - free(t); - return success ? 0 : -ENOMEM; } @@ -307,7 +297,7 @@ static DBusHandlerResult session_message_dispatch( DBusMessage *message) { DBusError error; - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; assert(s); @@ -412,18 +402,13 @@ static DBusHandlerResult session_message_dispatch( } if (reply) { - if (!dbus_connection_send(connection, reply, NULL)) + if (!bus_maybe_send_reply(connection, message, reply)) goto oom; - - dbus_message_unref(reply); } return DBUS_HANDLER_RESULT_HANDLED; oom: - if (reply) - dbus_message_unref(reply); - dbus_error_free(&error); return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -463,7 +448,7 @@ const DBusObjectPathVTable bus_session_vtable = { }; char *session_bus_path(Session *s) { - char *t, *r; + _cleanup_free_ char *t; assert(s); @@ -471,16 +456,12 @@ char *session_bus_path(Session *s) { if (!t) return NULL; - r = strappend("/org/freedesktop/login1/session/", t); - free(t); - - return r; + return strappend("/org/freedesktop/login1/session/", t); } int session_send_signal(Session *s, bool new_session) { - DBusMessage *m; - int r = -ENOMEM; - char *p = NULL; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; + _cleanup_free_ char *p = NULL; assert(s); @@ -493,31 +474,24 @@ int session_send_signal(Session *s, bool new_session) { p = session_bus_path(s); if (!p) - goto finish; + return -ENOMEM; if (!dbus_message_append_args( m, DBUS_TYPE_STRING, &s->id, DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_INVALID)) - goto finish; + return -ENOMEM; if (!dbus_connection_send(s->manager->bus, m, NULL)) - goto finish; - - r = 0; - -finish: - dbus_message_unref(m); - free(p); + return -ENOMEM; - return r; + return 0; } int session_send_changed(Session *s, const char *properties) { - DBusMessage *m; - int r = -ENOMEM; - char *p = NULL; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; + _cleanup_free_ char *p = NULL; assert(s); @@ -530,25 +504,18 @@ int session_send_changed(Session *s, const char *properties) { m = bus_properties_changed_new(p, "org.freedesktop.login1.Session", properties); if (!m) - goto finish; + return -ENOMEM; if (!dbus_connection_send(s->manager->bus, m, NULL)) - goto finish; - - r = 0; - -finish: - if (m) - dbus_message_unref(m); - free(p); + return -ENOMEM; - return r; + return 0; } int session_send_lock(Session *s, bool lock) { - DBusMessage *m; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; bool b; - char *p; + _cleanup_free_ char *p = NULL; assert(s); @@ -557,14 +524,11 @@ int session_send_lock(Session *s, bool lock) { 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; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index b64a5d302d..662273b07f 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -33,6 +33,7 @@ #include "path-util.h" #include "cgroup-util.h" #include "logind-session.h" +#include "fileio.h" Session* session_new(Manager *m, User *u, const char *id) { Session *s; @@ -435,15 +436,14 @@ static int session_create_one_group(Session *s, const char *controller, const ch int r; assert(s); - assert(controller); assert(path); if (s->leader > 0) { r = cg_create_and_attach(controller, path, s->leader); if (r < 0) - r = cg_create(controller, path); + r = cg_create(controller, path, NULL); } else - r = cg_create(controller, path); + r = cg_create(controller, path, NULL); if (r < 0) return r; @@ -465,7 +465,18 @@ static int session_create_cgroup(Session *s) { assert(s->user->cgroup_path); if (!s->cgroup_path) { - if (asprintf(&p, "%s/%s", s->user->cgroup_path, s->id) < 0) + _cleanup_free_ char *name = NULL, *escaped = NULL; + + name = strappend(s->id, ".session"); + if (!name) + return log_oom(); + + escaped = cg_escape(name); + if (!escaped) + return log_oom(); + + p = strjoin(s->user->cgroup_path, "/", escaped, NULL); + if (!p) return log_oom(); } else p = s->cgroup_path; @@ -709,6 +720,8 @@ int session_stop(Session *s) { if (s->started) session_send_signal(s, false); + s->started = false; + if (s->seat) { if (s->seat->active == s) seat_set_active(s->seat, NULL); @@ -720,8 +733,6 @@ int session_stop(Session *s) { user_send_changed(s->user, "Sessions\0"); user_save(s->user); - s->started = false; - return r; } @@ -772,7 +783,6 @@ static int get_process_ctty_atime(pid_t pid, usec_t *atime) { } int session_get_idle_hint(Session *s, dual_timestamp *t) { - _cleanup_free_ char *p = NULL; usec_t atime = 0, n; int r; @@ -786,7 +796,7 @@ int session_get_idle_hint(Session *s, dual_timestamp *t) { return s->idle_hint; } - /* Graphical sessions really should really implement a real + /* Graphical sessions should really implement a real * idle hint logic */ if (s->display) goto dont_know; @@ -898,7 +908,7 @@ int session_create_fifo(Session *s) { /* Open reading side */ if (s->fifo_fd < 0) { - struct epoll_event ev; + struct epoll_event ev = {}; s->fifo_fd = open(s->fifo_path, O_RDONLY|O_CLOEXEC|O_NDELAY); if (s->fifo_fd < 0) @@ -908,7 +918,6 @@ int session_create_fifo(Session *s) { if (r < 0) return r; - zero(ev); ev.events = 0; ev.data.u32 = FD_OTHER_BASE + s->fifo_fd; @@ -1057,7 +1066,8 @@ DEFINE_STRING_TABLE_LOOKUP(session_type, SessionType); static const char* const session_class_table[_SESSION_CLASS_MAX] = { [SESSION_USER] = "user", [SESSION_GREETER] = "greeter", - [SESSION_LOCK_SCREEN] = "lock-screen" + [SESSION_LOCK_SCREEN] = "lock-screen", + [SESSION_BACKGROUND] = "background" }; DEFINE_STRING_TABLE_LOOKUP(session_class, SessionClass); diff --git a/src/login/logind-session.h b/src/login/logind-session.h index 7598afa618..a73df3a3bc 100644 --- a/src/login/logind-session.h +++ b/src/login/logind-session.h @@ -37,22 +37,23 @@ typedef enum SessionState { _SESSION_STATE_INVALID = -1 } SessionState; -typedef enum SessionType { - SESSION_UNSPECIFIED, - SESSION_TTY, - SESSION_X11, - _SESSION_TYPE_MAX, - _SESSION_TYPE_INVALID = -1 -} SessionType; - typedef enum SessionClass { SESSION_USER, SESSION_GREETER, SESSION_LOCK_SCREEN, + SESSION_BACKGROUND, _SESSION_CLASS_MAX, _SESSION_CLASS_INVALID = -1 } SessionClass; +typedef enum SessionType { + SESSION_UNSPECIFIED, + SESSION_TTY, + SESSION_X11, + _SESSION_TYPE_MAX, + _SESSION_TYPE_INVALID = -1 +} SessionType; + typedef enum KillWho { KILL_LEADER, KILL_ALL, @@ -134,14 +135,14 @@ int session_send_changed(Session *s, const char *properties); int session_send_lock(Session *s, bool lock); int session_send_lock_all(Manager *m, bool lock); -const char* session_state_to_string(SessionState t); -SessionState session_state_from_string(const char *s); +const char* session_state_to_string(SessionState t) _const_; +SessionState session_state_from_string(const char *s) _pure_; -const char* session_type_to_string(SessionType t); -SessionType session_type_from_string(const char *s); +const char* session_type_to_string(SessionType t) _const_; +SessionType session_type_from_string(const char *s) _pure_; -const char* session_class_to_string(SessionClass t); -SessionClass session_class_from_string(const char *s); +const char* session_class_to_string(SessionClass t) _const_; +SessionClass session_class_from_string(const char *s) _pure_; -const char *kill_who_to_string(KillWho k); -KillWho kill_who_from_string(const char *s); +const char *kill_who_to_string(KillWho k) _const_; +KillWho kill_who_from_string(const char *s) _pure_; diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index ddf9d9d5cf..3ec3ff8e61 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -65,7 +65,7 @@ static int bus_user_append_display(DBusMessageIter *i, const char *property, voi DBusMessageIter sub; User *u = data; const char *id, *path; - char *p = NULL; + _cleanup_free_ char *p = NULL; assert(i); assert(property); @@ -86,12 +86,8 @@ static int bus_user_append_display(DBusMessageIter *i, const char *property, voi } if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &id) || - !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) { - free(p); + !dbus_message_iter_append_basic(&sub, DBUS_TYPE_OBJECT_PATH, &path)) return -ENOMEM; - } - - free(p); if (!dbus_message_iter_close_container(i, &sub)) return -ENOMEM; @@ -191,7 +187,7 @@ static int bus_user_append_idle_hint_since(DBusMessageIter *i, const char *prope static int bus_user_append_default_cgroup(DBusMessageIter *i, const char *property, void *data) { User *u = data; - char *t; + _cleanup_free_ char *t = NULL; int r; bool success; @@ -204,8 +200,6 @@ static int bus_user_append_default_cgroup(DBusMessageIter *i, const char *proper return r; success = dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &t); - free(t); - return success ? 0 : -ENOMEM; } @@ -257,7 +251,7 @@ static DBusHandlerResult user_message_dispatch( DBusMessage *message) { DBusError error; - DBusMessage *reply = NULL; + _cleanup_dbus_message_unref_ DBusMessage *reply = NULL; int r; assert(u); @@ -304,18 +298,13 @@ static DBusHandlerResult user_message_dispatch( } if (reply) { - if (!dbus_connection_send(connection, reply, NULL)) + if (!bus_maybe_send_reply(connection, message, reply)) goto oom; - - dbus_message_unref(reply); } return DBUS_HANDLER_RESULT_HANDLED; oom: - if (reply) - dbus_message_unref(reply); - dbus_error_free(&error); return DBUS_HANDLER_RESULT_NEED_MEMORY; @@ -366,9 +355,8 @@ char *user_bus_path(User *u) { } int user_send_signal(User *u, bool new_user) { - DBusMessage *m; - int r = -ENOMEM; - char *p = NULL; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; + _cleanup_free_ char *p = NULL; uint32_t uid; assert(u); @@ -382,7 +370,7 @@ int user_send_signal(User *u, bool new_user) { p = user_bus_path(u); if (!p) - goto finish; + return -ENOMEM; uid = u->uid; @@ -391,24 +379,17 @@ int user_send_signal(User *u, bool new_user) { DBUS_TYPE_UINT32, &uid, DBUS_TYPE_OBJECT_PATH, &p, DBUS_TYPE_INVALID)) - goto finish; + return -ENOMEM; if (!dbus_connection_send(u->manager->bus, m, NULL)) - goto finish; - - r = 0; - -finish: - dbus_message_unref(m); - free(p); + return -ENOMEM; - return r; + return 0; } int user_send_changed(User *u, const char *properties) { - DBusMessage *m; - int r = -ENOMEM; - char *p = NULL; + _cleanup_dbus_message_unref_ DBusMessage *m = NULL; + _cleanup_free_ char *p = NULL; assert(u); @@ -421,17 +402,10 @@ int user_send_changed(User *u, const char *properties) { m = bus_properties_changed_new(p, "org.freedesktop.login1.User", properties); if (!m) - goto finish; + return -ENOMEM; if (!dbus_connection_send(u->manager->bus, m, NULL)) - goto finish; - - r = 0; - -finish: - if (m) - dbus_message_unref(m); - free(p); + return -ENOMEM; - return r; + return 0; } diff --git a/src/login/logind-user.c b/src/login/logind-user.c index b692b533e2..9e2cbf646b 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -29,6 +29,7 @@ #include "cgroup-util.h" #include "hashmap.h" #include "strv.h" +#include "fileio.h" User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) { User *u; @@ -314,12 +315,22 @@ static int user_create_cgroup(User *u) { assert(u); if (!u->cgroup_path) { - if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) + _cleanup_free_ char *name = NULL, *escaped = NULL; + + if (asprintf(&name, "%lu.user", (unsigned long) u->uid) < 0) + return log_oom(); + + escaped = cg_escape(name); + if (!escaped) + return log_oom(); + + p = strjoin(u->manager->cgroup_path, "/", escaped, NULL); + if (!p) return log_oom(); } else p = u->cgroup_path; - r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p); + r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p, NULL); if (r < 0) { log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r)); free(p); @@ -334,7 +345,7 @@ static int user_create_cgroup(User *u) { if (strv_contains(u->manager->reset_controllers, *k)) continue; - r = cg_create(*k, p); + r = cg_create(*k, p, NULL); if (r < 0) log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r)); } diff --git a/src/login/logind-user.h b/src/login/logind-user.h index a679d43a30..080354da74 100644 --- a/src/login/logind-user.h +++ b/src/login/logind-user.h @@ -80,5 +80,5 @@ extern const DBusObjectPathVTable bus_user_vtable; int user_send_signal(User *u, bool new_user); int user_send_changed(User *u, const char *properties); -const char* user_state_to_string(UserState s); -UserState user_state_from_string(const char *s); +const char* user_state_to_string(UserState s) _const_; +UserState user_state_from_string(const char *s) _pure_; diff --git a/src/login/logind.c b/src/login/logind.c index 6776229ee7..5a394401dc 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -37,6 +37,7 @@ #include "dbus-loop.h" #include "strv.h" #include "conf-parser.h" +#include "mkdir.h" Manager *manager_new(void) { Manager *m; @@ -187,6 +188,8 @@ void manager_free(Manager *m) { strv_free(m->kill_only_users); strv_free(m->kill_exclude_users); + free(m->action_job); + free(m->cgroup_path); free(m); } @@ -459,7 +462,7 @@ int manager_enumerate_devices(Manager *m) { goto finish; } - r = udev_enumerate_add_match_tag(e, "seat-master"); + r = udev_enumerate_add_match_tag(e, "master-of-seat"); if (r < 0) goto finish; @@ -594,9 +597,9 @@ int manager_enumerate_seats(Manager *m) { } static int manager_enumerate_users_from_cgroup(Manager *m) { + _cleanup_closedir_ DIR *d = NULL; int r = 0, k; char *name; - DIR *d; r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, m->cgroup_path, &d); if (r < 0) { @@ -609,31 +612,37 @@ static int manager_enumerate_users_from_cgroup(Manager *m) { while ((k = cg_read_subgroup(d, &name)) > 0) { User *user; + char *e; - k = manager_add_user_by_name(m, name, &user); - if (k < 0) { - free(name); - r = k; - continue; - } - - user_add_to_gc_queue(user); + e = endswith(name, ".user"); + if (e) { + *e = 0; - if (!user->cgroup_path) - if (asprintf(&user->cgroup_path, "%s/%s", m->cgroup_path, name) < 0) { - r = -ENOMEM; + k = manager_add_user_by_name(m, name, &user); + if (k < 0) { free(name); - break; + r = k; + continue; } + user_add_to_gc_queue(user); + + if (!user->cgroup_path) { + user->cgroup_path = strjoin(m->cgroup_path, "/", name, NULL); + if (!user->cgroup_path) { + k = log_oom(); + free(name); + break; + } + } + } + free(name); } - if (r >= 0 && k < 0) + if (k < 0) r = k; - closedir(d); - return r; } @@ -729,7 +738,7 @@ static int manager_enumerate_sessions_from_cgroup(Manager *m) { int r = 0; HASHMAP_FOREACH(u, m->users, i) { - DIR *d; + _cleanup_closedir_ DIR *d = NULL; char *name; int k; @@ -748,30 +757,34 @@ static int manager_enumerate_sessions_from_cgroup(Manager *m) { while ((k = cg_read_subgroup(d, &name)) > 0) { Session *session; + char *e; - if (streq(name, "shared")) - continue; + e = endswith(name, ".session"); + if (e) { + *e = 0; - k = manager_add_session(m, u, name, &session); - if (k < 0) { - free(name); - break; - } + k = manager_add_session(m, u, name, &session); + if (k < 0) { + free(name); + r = k; + continue; + } - session_add_to_gc_queue(session); + session_add_to_gc_queue(session); - if (!session->cgroup_path) - if (asprintf(&session->cgroup_path, "%s/%s", u->cgroup_path, name) < 0) { - k = -ENOMEM; - free(name); - break; + if (!session->cgroup_path) { + session->cgroup_path = strjoin(m->cgroup_path, "/", name, NULL); + if (!session->cgroup_path) { + k = log_oom(); + free(name); + break; + } } + } free(name); } - closedir(d); - if (k < 0) r = k; } @@ -1038,16 +1051,13 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess return 1; } - p = strdup(cgroup); - if (!p) - return log_oom(); + p = strdupa(cgroup); for (;;) { char *e; e = strrchr(p, '/'); if (!e || e == p) { - free(p); *session = NULL; return 0; } @@ -1056,7 +1066,6 @@ int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **sess s = hashmap_get(m->session_cgroups, p); if (s) { - free(p); *session = s; return 1; } @@ -1077,7 +1086,7 @@ int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) { return 1; } - p = strdup(cgroup); + p = strdupa(cgroup); if (!p) return log_oom(); @@ -1086,7 +1095,6 @@ int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) { e = strrchr(p, '/'); if (!e || e == p) { - free(p); *user = NULL; return 0; } @@ -1095,7 +1103,6 @@ int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) { u = hashmap_get(m->user_cgroups, p); if (u) { - free(p); *user = u; return 1; } @@ -1103,21 +1110,18 @@ int manager_get_user_by_cgroup(Manager *m, const char *cgroup, User **user) { } int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) { - char *p; + _cleanup_free_ char *p = NULL; int r; assert(m); assert(pid >= 1); assert(session); - r = cg_get_by_pid(SYSTEMD_CGROUP_CONTROLLER, pid, &p); + r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &p); if (r < 0) return r; - r = manager_get_session_by_cgroup(m, p, session); - free(p); - - return r; + return manager_get_session_by_cgroup(m, p, session); } void manager_cgroup_notify_empty(Manager *m, const char *cgroup) { @@ -1171,7 +1175,10 @@ static void manager_dispatch_other(Manager *m, int fd) { static int manager_connect_bus(Manager *m) { DBusError error; int r; - struct epoll_event ev; + struct epoll_event ev = { + .events = EPOLLIN, + .data.u32 = FD_BUS, + }; assert(m); assert(!m->bus); @@ -1227,10 +1234,6 @@ static int manager_connect_bus(Manager *m) { goto fail; } - zero(ev); - ev.events = EPOLLIN; - ev.data.u32 = FD_BUS; - if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->bus_fd, &ev) < 0) goto fail; @@ -1243,7 +1246,10 @@ fail: } static int manager_connect_console(Manager *m) { - struct epoll_event ev; + struct epoll_event ev = { + .events = 0, + .data.u32 = FD_CONSOLE, + }; assert(m); assert(m->console_active_fd < 0); @@ -1268,10 +1274,6 @@ static int manager_connect_console(Manager *m) { return -errno; } - zero(ev); - ev.events = 0; - ev.data.u32 = FD_CONSOLE; - if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->console_active_fd, &ev) < 0) return -errno; @@ -1279,8 +1281,11 @@ static int manager_connect_console(Manager *m) { } static int manager_connect_udev(Manager *m) { - struct epoll_event ev; int r; + struct epoll_event ev = { + .events = EPOLLIN, + .data.u32 = FD_SEAT_UDEV, + }; assert(m); assert(!m->udev_seat_monitor); @@ -1291,7 +1296,7 @@ static int manager_connect_udev(Manager *m) { if (!m->udev_seat_monitor) return -ENOMEM; - r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "seat-master"); + r = udev_monitor_filter_add_match_tag(m->udev_seat_monitor, "master-of-seat"); if (r < 0) return r; @@ -1301,9 +1306,6 @@ static int manager_connect_udev(Manager *m) { m->udev_seat_fd = udev_monitor_get_fd(m->udev_seat_monitor); - zero(ev); - ev.events = EPOLLIN; - ev.data.u32 = FD_SEAT_UDEV; if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->udev_seat_fd, &ev) < 0) return -errno; @@ -1444,7 +1446,7 @@ int manager_get_idle_hint(Manager *m, dual_timestamp *t) { int manager_dispatch_idle_action(Manager *m) { struct dual_timestamp since; - struct itimerspec its; + struct itimerspec its = {}; int r; usec_t n; @@ -1456,12 +1458,11 @@ int manager_dispatch_idle_action(Manager *m) { goto finish; } - zero(its); n = now(CLOCK_MONOTONIC); r = manager_get_idle_hint(m, &since); if (r <= 0) - /* Not idle. Let's check if after a timeout it it might be idle then. */ + /* Not idle. Let's check if after a timeout it might be idle then. */ timespec_store(&its.it_value, n + m->idle_action_usec); else { /* Idle! Let's see if it's time to do something, or if @@ -1479,7 +1480,10 @@ int manager_dispatch_idle_action(Manager *m) { } if (m->idle_action_fd < 0) { - struct epoll_event ev; + struct epoll_event ev = { + .events = EPOLLIN, + .data.u32 = FD_IDLE_ACTION, + }; m->idle_action_fd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK|TFD_CLOEXEC); if (m->idle_action_fd < 0) { @@ -1488,10 +1492,6 @@ int manager_dispatch_idle_action(Manager *m) { goto finish; } - zero(ev); - ev.events = EPOLLIN; - ev.data.u32 = FD_IDLE_ACTION; - if (epoll_ctl(m->epoll_fd, EPOLL_CTL_ADD, m->idle_action_fd, &ev) < 0) { log_error("Failed to add idle action timer to epoll: %m"); r = -errno; @@ -1626,11 +1626,11 @@ int manager_run(Manager *m) { manager_gc(m, true); - if (m->delayed_unit) { + if (m->action_what != 0 && !m->action_job) { usec_t x, y; x = now(CLOCK_MONOTONIC); - y = m->delayed_timestamp + m->inhibit_delay_max; + y = m->action_timestamp + m->inhibit_delay_max; msec = x >= y ? 0 : (int) ((y - x) / USEC_PER_MSEC); } @@ -1683,13 +1683,12 @@ int manager_run(Manager *m) { } static int manager_parse_config_file(Manager *m) { - FILE *f; - const char *fn; + static const char fn[] = "/etc/systemd/logind.conf"; + _cleanup_fclose_ FILE *f = NULL; int r; assert(m); - fn = "/etc/systemd/logind.conf"; f = fopen(fn, "re"); if (!f) { if (errno == ENOENT) @@ -1699,12 +1698,11 @@ static int manager_parse_config_file(Manager *m) { return -errno; } - r = config_parse(fn, f, "Login\0", config_item_perf_lookup, (void*) logind_gperf_lookup, false, m); + r = config_parse(NULL, fn, f, "Login\0", config_item_perf_lookup, + (void*) logind_gperf_lookup, false, false, m); if (r < 0) log_warning("Failed to parse configuration file: %s", strerror(-r)); - fclose(f); - return r; } @@ -1725,6 +1723,15 @@ int main(int argc, char *argv[]) { goto finish; } + /* Always create the directories people can create inotify + * watches in. Note that some applications might check for the + * existence of /run/systemd/seats/ to determine whether + * logind is available, so please always make sure this check + * stays in. */ + mkdir_label("/run/systemd/seats", 0755); + mkdir_label("/run/systemd/users", 0755); + mkdir_label("/run/systemd/sessions", 0755); + m = manager_new(); if (!m) { r = log_oom(); diff --git a/src/login/logind.h b/src/login/logind.h index 816635dcfc..904dc20467 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -91,16 +91,23 @@ struct Manager { Hashmap *inhibitor_fds; Hashmap *button_fds; - /* If a shutdown was delayed due to a inhibitor this contains - the unit name we are supposed to start after the delay is - over */ - const char *delayed_unit; - InhibitWhat delayed_what; - usec_t delayed_timestamp; - usec_t inhibit_delay_max; - int idle_action_fd; + /* If an action is currently being executed or is delayed, + * this is != 0 and encodes what is being done */ + InhibitWhat action_what; + + /* If a shutdown/suspend was delayed due to a inhibitor this + contains the unit name we are supposed to start after the + delay is over */ + const char *action_unit; + + /* If a shutdown/suspend is currently executed, then this is + * the job of it */ + char *action_job; + usec_t action_timestamp; + + int idle_action_fd; /* the timer_fd */ usec_t idle_action_usec; usec_t idle_action_not_before_usec; HandleAction idle_action; diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in index b5f5db4f6a..0c551d4f9b 100644 --- a/src/login/org.freedesktop.login1.policy.in +++ b/src/login/org.freedesktop.login1.policy.in @@ -158,7 +158,7 @@ <defaults> <allow_any>auth_admin_keep</allow_any> <allow_inactive>auth_admin_keep</allow_inactive> - <allow_active>auth_admin_keep</allow_active> + <allow_active>yes</allow_active> </defaults> <annotate key="org.freedesktop.policykit.imply">org.freedesktop.login1.power-off</annotate> </action> diff --git a/src/login/pam-module.c b/src/login/pam-module.c index 88b0ef9e45..13290fd8ea 100644 --- a/src/login/pam-module.c +++ b/src/login/pam-module.c @@ -32,8 +32,6 @@ #include <security/pam_ext.h> #include <security/pam_misc.h> -#include <systemd/sd-daemon.h> - #include "util.h" #include "audit.h" #include "macro.h" @@ -41,6 +39,7 @@ #include "dbus-common.h" #include "def.h" #include "socket-util.h" +#include "fileio.h" static int parse_argv(pam_handle_t *handle, int argc, const char **argv, @@ -257,13 +256,15 @@ static bool check_user_lists( } static int get_seat_from_display(const char *display, const char **seat, uint32_t *vtnr) { - char *p = NULL; + _cleanup_free_ char *p = NULL; int r; - int fd; - union sockaddr_union sa; + _cleanup_close_ int fd = -1; + union sockaddr_union sa = { + .un.sun_family = AF_UNIX, + }; struct ucred ucred; socklen_t l; - char *tty; + _cleanup_free_ char *tty = NULL; int v; assert(display); @@ -278,27 +279,17 @@ static int get_seat_from_display(const char *display, const char **seat, uint32_ r = socket_from_display(display, &p); if (r < 0) return r; + strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)-1); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0); - if (fd < 0) { - free(p); + if (fd < 0) return -errno; - } - zero(sa); - sa.un.sun_family = AF_UNIX; - strncpy(sa.un.sun_path, p, sizeof(sa.un.sun_path)-1); - free(p); - - if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) { - close_nointr_nofail(fd); + if (connect(fd, &sa.sa, offsetof(struct sockaddr_un, sun_path) + strlen(sa.un.sun_path)) < 0) return -errno; - } l = sizeof(ucred); r = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l); - close_nointr_nofail(fd); - if (r < 0) return -errno; @@ -307,8 +298,6 @@ static int get_seat_from_display(const char *display, const char **seat, uint32_ return r; v = vtnr_from_tty(tty); - free(tty); - if (v < 0) return v; else if (v == 0) @@ -347,8 +336,8 @@ _public_ PAM_EXTERN int pam_sm_open_session( /* pam_syslog(handle, LOG_INFO, "pam-systemd initializing"); */ - /* Make this a NOP on non-systemd systems */ - if (sd_booted() <= 0) + /* Make this a NOP on non-logind systems */ + if (!logind_running()) return PAM_SUCCESS; if (parse_argv(handle, @@ -451,9 +440,10 @@ _public_ PAM_EXTERN int pam_sm_open_session( seat = strempty(seat); if (strchr(tty, ':')) { - /* A tty with a colon is usually an X11 display, place - * there to show up in utmp. We rearrange things and - * don't pretend that an X display was a tty */ + /* A tty with a colon is usually an X11 display, + * placed there to show up in utmp. We rearrange + * things and don't pretend that an X display was a + * tty. */ if (isempty(display)) display = tty; @@ -493,7 +483,7 @@ _public_ PAM_EXTERN int pam_sm_open_session( if (isempty(class)) class = class_pam; if (isempty(class)) - class = "user"; + class = streq(type, "unspecified") ? "background" : "user"; remote = !isempty(remote_host) && !streq(remote_host, "localhost") && diff --git a/src/login/sd-login.c b/src/login/sd-login.c index 45e3bb8dcd..d0dc42f685 100644 --- a/src/login/sd-login.c +++ b/src/login/sd-login.c @@ -23,114 +23,64 @@ #include <string.h> #include <errno.h> #include <sys/inotify.h> +#include <sys/poll.h> #include "util.h" #include "cgroup-util.h" #include "macro.h" #include "sd-login.h" #include "strv.h" +#include "fileio.h" _public_ int sd_pid_get_session(pid_t pid, char **session) { - int r; - char *cgroup, *p; - if (pid < 0) return -EINVAL; if (!session) return -EINVAL; - r = cg_pid_get_cgroup(pid, NULL, &cgroup); - if (r < 0) - return r; - - if (!startswith(cgroup, "/user/")) { - free(cgroup); - return -ENOENT; - } - - p = strchr(cgroup + 6, '/'); - if (!p) { - free(cgroup); - return -ENOENT; - } - - p++; - if (startswith(p, "shared/") || streq(p, "shared")) { - free(cgroup); - return -ENOENT; - } - - p = strndup(p, strcspn(p, "/")); - free(cgroup); - - if (!p) - return -ENOMEM; - - *session = p; - return 0; + return cg_pid_get_session(pid, session); } _public_ int sd_pid_get_unit(pid_t pid, char **unit) { if (pid < 0) return -EINVAL; - if (!unit) return -EINVAL; return cg_pid_get_unit(pid, unit); } -_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { - int r; - char *root, *cgroup, *p, *cc; - struct stat st; +_public_ int sd_pid_get_user_unit(pid_t pid, char **unit) { if (pid < 0) return -EINVAL; - - if (!uid) + if (!unit) return -EINVAL; - r = cg_pid_get_cgroup(pid, &root, &cgroup); - if (r < 0) - return r; - - if (!startswith(cgroup, "/user/")) { - free(cgroup); - free(root); - return -ENOENT; - } - - p = strchr(cgroup + 6, '/'); - if (!p) { - free(cgroup); - return -ENOENT; - } + return cg_pid_get_user_unit(pid, unit); +} - p++; - p += strcspn(p, "/"); - *p = 0; +_public_ int sd_pid_get_machine_name(pid_t pid, char **name) { - r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, root, cgroup, &cc); - free(root); - free(cgroup); + if (pid < 0) + return -EINVAL; + if (!name) + return -EINVAL; - if (r < 0) - return -ENOMEM; + return cg_pid_get_machine_name(pid, name); +} - r = lstat(cc, &st); - free(cc); +_public_ int sd_pid_get_owner_uid(pid_t pid, uid_t *uid) { - if (r < 0) - return -errno; + if (pid < 0) + return -EINVAL; - if (!S_ISDIR(st.st_mode)) - return -ENOTDIR; + if (!uid) + return -EINVAL; - *uid = st.st_uid; - return 0; + return cg_pid_get_owner_uid(pid, uid); } _public_ int sd_uid_get_state(uid_t uid, char**state) { @@ -165,7 +115,8 @@ _public_ int sd_uid_get_state(uid_t uid, char**state) { } _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) { - char *p, *w, *t, *state, *s = NULL; + char *w, *state; + _cleanup_free_ char *t = NULL, *s = NULL, *p = NULL; size_t l; int r; const char *variable; @@ -180,38 +131,26 @@ _public_ int sd_uid_is_on_seat(uid_t uid, int require_active, const char *seat) return -ENOMEM; r = parse_env_file(p, NEWLINE, variable, &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } if (!s) return -EIO; - if (asprintf(&t, "%lu", (unsigned long) uid) < 0) { - free(s); + if (asprintf(&t, "%lu", (unsigned long) uid) < 0) return -ENOMEM; - } FOREACH_WORD(w, l, s, state) { - if (strncmp(t, w, l) == 0) { - free(s); - free(t); - + if (strneq(t, w, l)) return 1; - } } - free(s); - free(t); - return 0; } static int uid_get_array(uid_t uid, const char *variable, char ***array) { - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; char **a; int r; @@ -221,11 +160,7 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) { r = parse_env_file(p, NEWLINE, variable, &s, NULL); - free(p); - if (r < 0) { - free(s); - if (r == -ENOENT) { if (array) *array = NULL; @@ -242,7 +177,6 @@ static int uid_get_array(uid_t uid, const char *variable, char ***array) { } a = strv_split(s, " "); - free(s); if (!a) return -ENOMEM; @@ -304,31 +238,27 @@ static int file_of_session(const char *session, char **_p) { _public_ int sd_session_is_active(const char *session) { int r; - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; r = file_of_session(session, &p); if (r < 0) return r; r = parse_env_file(p, NEWLINE, "ACTIVE", &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } if (!s) return -EIO; r = parse_boolean(s); - free(s); return r; } _public_ int sd_session_get_state(const char *session, char **state) { - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; int r; if (!state) @@ -339,21 +269,21 @@ _public_ int sd_session_get_state(const char *session, char **state) { return r; r = parse_env_file(p, NEWLINE, "STATE", &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } else if (!s) + else if (!s) return -EIO; *state = s; + s = NULL; + return 0; } _public_ int sd_session_get_uid(const char *session, uid_t *uid) { int r; - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; if (!uid) return -EINVAL; @@ -363,24 +293,20 @@ _public_ int sd_session_get_uid(const char *session, uid_t *uid) { return r; r = parse_env_file(p, NEWLINE, "UID", &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } if (!s) return -EIO; r = parse_uid(s, uid); - free(s); return r; } static int session_get_string(const char *session, const char *field, char **value) { - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; int r; if (!value) @@ -391,17 +317,15 @@ static int session_get_string(const char *session, const char *field, char **val return r; r = parse_env_file(p, NEWLINE, field, &s, NULL); - free(p); - if (r < 0) { - free(s); + if (r < 0) return r; - } if (isempty(s)) return -ENOENT; *value = s; + s = NULL; return 0; } @@ -409,6 +333,10 @@ _public_ int sd_session_get_seat(const char *session, char **seat) { return session_get_string(session, "SEAT", seat); } +_public_ int sd_session_get_tty(const char *session, char **tty) { + return session_get_string(session, "TTY", tty); +} + _public_ int sd_session_get_service(const char *session, char **service) { return session_get_string(session, "SERVICE", service); } @@ -434,25 +362,25 @@ static int file_of_seat(const char *seat, char **_p) { if (seat) p = strappend("/run/systemd/seats/", seat); else { - char *buf; + _cleanup_free_ char *buf = NULL; r = sd_session_get_seat(NULL, &buf); if (r < 0) return r; p = strappend("/run/systemd/seats/", buf); - free(buf); } if (!p) return -ENOMEM; *_p = p; + p = NULL; return 0; } _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { - char *p, *s = NULL, *t = NULL; + _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; int r; if (!session && !uid) @@ -466,46 +394,33 @@ _public_ int sd_seat_get_active(const char *seat, char **session, uid_t *uid) { "ACTIVE", &s, "ACTIVE_UID", &t, NULL); - free(p); - - if (r < 0) { - free(s); - free(t); + if (r < 0) return r; - } - if (session && !s) { - free(t); + if (session && !s) return -ENOENT; - } - if (uid && !t) { - free(s); + if (uid && !t) return -ENOENT; - } if (uid && t) { r = parse_uid(t, uid); - if (r < 0) { - free(t); - free(s); + if (r < 0) return r; - } } - free(t); - - if (session && s) + if (session && s) { *session = s; - else - free(s); + s = NULL; + } return 0; } _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **uids, unsigned *n_uids) { - char *p, *s = NULL, *t = NULL, **a = NULL; - uid_t *b = NULL; + _cleanup_free_ char *p = NULL, *s = NULL, *t = NULL; + _cleanup_strv_free_ char **a = NULL; + _cleanup_free_ uid_t *b = NULL; unsigned n = 0; int r; @@ -517,25 +432,16 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui "SESSIONS", &s, "ACTIVE_SESSIONS", &t, NULL); - free(p); - if (r < 0) { - free(s); - free(t); + if (r < 0) return r; - } if (s) { a = strv_split(s, " "); - if (!a) { - free(s); - free(t); + if (!a) return -ENOMEM; - } } - free(s); - if (uids && t) { char *w, *state; size_t l; @@ -543,30 +449,22 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui FOREACH_WORD(w, l, t, state) n++; - if (n == 0) - b = NULL; - else { + if (n > 0) { unsigned i = 0; b = new(uid_t, n); - if (!b) { - strv_free(a); + if (!b) return -ENOMEM; - } FOREACH_WORD(w, l, t, state) { - char *k; + _cleanup_free_ char *k = NULL; k = strndup(w, l); - if (!k) { - free(t); - free(b); - strv_free(a); + if (!k) return -ENOMEM; - } r = parse_uid(k, b + i); - free(k); + if (r < 0) continue; @@ -575,17 +473,17 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui } } - free(t); - r = strv_length(a); - if (sessions) + if (sessions) { *sessions = a; - else - strv_free(a); + a = NULL; + } - if (uids) + if (uids) { *uids = b; + b = NULL; + } if (n_uids) *n_uids = n; @@ -594,7 +492,7 @@ _public_ int sd_seat_get_sessions(const char *seat, char ***sessions, uid_t **ui } static int seat_get_can(const char *seat, const char *variable) { - char *p, *s = NULL; + _cleanup_free_ char *p = NULL, *s = NULL; int r; r = file_of_seat(seat, &p); @@ -604,17 +502,12 @@ static int seat_get_can(const char *seat, const char *variable) { r = parse_env_file(p, NEWLINE, variable, &s, NULL); - free(p); - - if (r < 0) { - free(s); + if (r < 0) return r; - } - if (s) { + if (s) r = parse_boolean(s); - free(s); - } else + else r = 0; return r; @@ -641,10 +534,10 @@ _public_ int sd_get_sessions(char ***sessions) { } _public_ int sd_get_uids(uid_t **users) { - DIR *d; + _cleanup_closedir_ DIR *d; int r = 0; unsigned n = 0; - uid_t *l = NULL; + _cleanup_free_ uid_t *l = NULL; d = opendir("/run/systemd/users/"); if (!d) @@ -657,10 +550,8 @@ _public_ int sd_get_uids(uid_t **users) { uid_t uid; k = readdir_r(d, &buf.de, &de); - if (k != 0) { - r = -k; - goto finish; - } + if (k != 0) + return -k; if (!de) break; @@ -680,10 +571,8 @@ _public_ int sd_get_uids(uid_t **users) { n = MAX(16, 2*r); t = realloc(l, sizeof(uid_t) * n); - if (!t) { - r = -ENOMEM; - goto finish; - } + if (!t) + return -ENOMEM; l = t; } @@ -694,19 +583,51 @@ _public_ int sd_get_uids(uid_t **users) { r++; } -finish: - if (d) - closedir(d); - - if (r >= 0) { - if (users) - *users = l; - } else - free(l); + if (users) { + *users = l; + l = NULL; + } return r; } +_public_ int sd_get_machine_names(char ***machines) { + _cleanup_closedir_ DIR *d = NULL; + _cleanup_strv_free_ char **l = NULL; + _cleanup_free_ char *md = NULL; + char *n; + int c = 0, r; + + r = cg_get_machine_path(NULL, &md); + if (r < 0) + return r; + + r = cg_enumerate_subgroups(SYSTEMD_CGROUP_CONTROLLER, md, &d); + if (r < 0) + return r; + + while ((r = cg_read_subgroup(d, &n)) > 0) { + + r = strv_push(&l, n); + if (r < 0) { + free(n); + return -ENOMEM; + } + + c++; + } + + if (r < 0) + return r; + + if (machines) { + *machines = l; + l = NULL; + } + + return c; +} + static inline int MONITOR_TO_FD(sd_login_monitor *m) { return (int) (unsigned long) m - 1; } @@ -724,7 +645,7 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) { fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (fd < 0) - return errno; + return -errno; if (!category || streq(category, "seat")) { k = inotify_add_watch(fd, "/run/systemd/seats/", IN_MOVED_TO|IN_DELETE); @@ -756,6 +677,27 @@ _public_ int sd_login_monitor_new(const char *category, sd_login_monitor **m) { good = true; } + if (!category || streq(category, "machine")) { + _cleanup_free_ char *md = NULL, *p = NULL; + int r; + + r = cg_get_machine_path(NULL, &md); + if (r < 0) + return r; + + r = cg_get_path(SYSTEMD_CGROUP_CONTROLLER, md, NULL, &p); + if (r < 0) + return r; + + k = inotify_add_watch(fd, p, IN_MOVED_TO|IN_CREATE|IN_DELETE); + if (k < 0) { + close_nointr_nofail(fd); + return -errno; + } + + good = true; + } + if (!good) { close_nointr(fd); return -EINVAL; @@ -792,3 +734,29 @@ _public_ int sd_login_monitor_get_fd(sd_login_monitor *m) { return MONITOR_TO_FD(m); } + +_public_ int sd_login_monitor_get_events(sd_login_monitor *m) { + + if (!m) + return -EINVAL; + + /* For now we will only return POLLIN here, since we don't + * need anything else ever for inotify. However, let's have + * this API to keep our options open should we later on need + * it. */ + return POLLIN; +} + +_public_ int sd_login_monitor_get_timeout(sd_login_monitor *m, uint64_t *timeout_usec) { + + if (!m) + return -EINVAL; + if (!timeout_usec) + return -EINVAL; + + /* For now we will only return (uint64_t) -1, since we don't + * need any timeout. However, let's have this API to keep our + * options open should we later on need it. */ + *timeout_usec = (uint64_t) -1; + return 0; +} diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c index d113ec3e43..3c03bd1f2e 100644 --- a/src/login/sysfs-show.c +++ b/src/login/sysfs-show.c @@ -45,6 +45,7 @@ static int show_sysfs_one( struct udev_device *d; const char *sn, *name, *sysfs, *subsystem, *sysname; char *l, *k; + bool is_master; sysfs = udev_list_entry_get_name(*item); if (!path_startswith(sysfs, sub)) @@ -60,13 +61,15 @@ static int show_sysfs_one( if (isempty(sn)) sn = "seat0"; - /* fixme, also check for tag 'seat' here */ + /* Explicitly also check for tag 'seat' here */ if (!streq(seat, sn) || !udev_device_has_tag(d, "seat")) { udev_device_unref(d); *item = udev_list_entry_get_next(*item); continue; } + is_master = udev_device_has_tag(d, "master-of-seat"); + name = udev_device_get_sysattr_value(d, "name"); if (!name) name = udev_device_get_sysattr_value(d, "id"); @@ -110,7 +113,8 @@ static int show_sysfs_one( free(k); if (asprintf(&l, - "(%s:%s)%s%s%s", + "%s%s:%s%s%s%s", + is_master ? "[MASTER] " : "", subsystem, sysname, name ? " \"" : "", name ? name : "", name ? "\"" : "") < 0) { udev_device_unref(d); diff --git a/src/login/test-login.c b/src/login/test-login.c index 159ff3efc5..945cb38be9 100644 --- a/src/login/test-login.c +++ b/src/login/test-login.c @@ -35,7 +35,7 @@ int main(int argc, char* argv[]) { char *state; char *session2; char *t; - char **seats, **sessions; + char **seats, **sessions, **machines; uid_t *uids; unsigned n; struct pollfd pollfd; @@ -180,15 +180,34 @@ int main(int argc, char* argv[]) { printf("n_uids = %i\n", r); assert_se(sd_get_uids(NULL) == r); - r = sd_login_monitor_new("session", &m); + r = sd_get_machine_names(&machines); assert_se(r >= 0); + assert_se(r == (int) strv_length(machines)); + assert_se(t = strv_join(machines, ", ")); + strv_free(machines); + printf("n_machines = %i\n", r); + printf("machines = %s\n", t); + free(t); - zero(pollfd); - pollfd.fd = sd_login_monitor_get_fd(m); - pollfd.events = POLLIN; + r = sd_login_monitor_new("session", &m); + assert_se(r >= 0); for (n = 0; n < 5; n++) { - r = poll(&pollfd, 1, -1); + usec_t timeout, nw; + + zero(pollfd); + assert_se((pollfd.fd = sd_login_monitor_get_fd(m)) >= 0); + assert_se((pollfd.events = sd_login_monitor_get_events(m)) >= 0); + + assert_se(sd_login_monitor_get_timeout(m, &timeout) >= 0); + + nw = now(CLOCK_MONOTONIC); + + r = poll(&pollfd, 1, + timeout == (uint64_t) -1 ? -1 : + timeout > nw ? (int) ((timeout - nw) / 1000) : + 0); + assert_se(r >= 0); sd_login_monitor_flush(m); diff --git a/src/login/uaccess.c b/src/login/uaccess.c deleted file mode 100644 index 2c530c8f39..0000000000 --- a/src/login/uaccess.c +++ /dev/null @@ -1,91 +0,0 @@ -/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/ - -/*** - This file is part of systemd. - - Copyright 2011 Lennart Poettering - - systemd is free software; you can redistribute it and/or modify it - under the terms of the GNU Lesser General Public License as published by - the Free Software Foundation; either version 2.1 of the License, or - (at your option) any later version. - - systemd is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public License - along with systemd; If not, see <http://www.gnu.org/licenses/>. -***/ - -#include <errno.h> -#include <string.h> - -#include <systemd/sd-daemon.h> -#include <systemd/sd-login.h> - -#include "logind-acl.h" -#include "util.h" -#include "log.h" - -int main(int argc, char *argv[]) { - int r; - const char *path = NULL, *seat; - bool changed_acl = false; - uid_t uid; - - log_set_target(LOG_TARGET_AUTO); - log_parse_environment(); - log_open(); - - umask(0022); - - if (argc < 2 || argc > 3) { - log_error("This program expects one or two arguments."); - r = -EINVAL; - goto finish; - } - - /* Make sure we don't muck around with ACLs the system is not - * running systemd. */ - if (!sd_booted()) - return 0; - - path = argv[1]; - seat = argc < 3 || isempty(argv[2]) ? "seat0" : argv[2]; - - r = sd_seat_get_active(seat, NULL, &uid); - if (r == -ENOENT) { - /* No active session on this seat */ - r = 0; - goto finish; - } else if (r < 0) { - log_error("Failed to determine active user on seat %s.", seat); - goto finish; - } - - r = devnode_acl(path, true, false, 0, true, uid); - if (r < 0) { - log_error("Failed to apply ACL on %s: %s", path, strerror(-r)); - goto finish; - } - - changed_acl = true; - r = 0; - -finish: - if (path && !changed_acl) { - int k; - /* Better be safe that sorry and reset ACL */ - - k = devnode_acl(path, true, false, 0, false, 0); - if (k < 0) { - log_error("Failed to apply ACL on %s: %s", path, strerror(-k)); - if (r >= 0) - r = k; - } - } - - return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; -} diff --git a/src/login/user-sessions.c b/src/login/user-sessions.c index 91531e8f38..41d32044e9 100644 --- a/src/login/user-sessions.c +++ b/src/login/user-sessions.c @@ -26,6 +26,7 @@ #include "log.h" #include "util.h" #include "cgroup-util.h" +#include "fileio.h" int main(int argc, char*argv[]) { int ret = EXIT_FAILURE; @@ -69,7 +70,7 @@ int main(int argc, char*argv[]) { int r, q; char *cgroup_user_tree = NULL; - r = write_one_line_file_atomic("/run/nologin", "System is going down."); + r = write_string_file_atomic("/run/nologin", "System is going down."); if (r < 0) log_error("Failed to create /run/nologin: %s", strerror(-r)); |