From 8331cb6e143dc261fd22af9a2a679196822326a9 Mon Sep 17 00:00:00 2001 From: Sven Eden Date: Wed, 31 May 2017 07:35:28 +0200 Subject: [PATCH] Prep v230: Apply missing upstream fixes and updates (6/8) src/login. --- src/login/.gitignore | 1 + src/login/loginctl.c | 249 ++++++++++++++++++++-------- src/login/logind-core.c | 16 +- src/login/logind-dbus.c | 64 ++++---- src/login/logind-gperf.gperf | 3 + src/login/logind-seat.c | 1 - src/login/logind-session-dbus.c | 5 +- src/login/logind-session-device.c | 4 + src/login/logind-session.c | 28 ++-- src/login/logind-session.h | 1 - src/login/logind-user.c | 9 +- src/login/logind-user.h | 5 - src/login/logind.c | 261 +++++++++++++++++------------- src/login/logind.h | 32 ++-- src/login/sysfs-show.c | 4 + src/login/test-login-tables.c | 1 - 16 files changed, 416 insertions(+), 268 deletions(-) diff --git a/src/login/.gitignore b/src/login/.gitignore index bc9ac41a2..42dc3d01d 100644 --- a/src/login/.gitignore +++ b/src/login/.gitignore @@ -1,4 +1,5 @@ /logind-gperf.c +/logind.conf /org.freedesktop.login1.policy /71-seat.rules /73-seat-late.rules diff --git a/src/login/loginctl.c b/src/login/loginctl.c index 3b86cfbfb..ee9816ad0 100644 --- a/src/login/loginctl.c +++ b/src/login/loginctl.c @@ -57,21 +57,26 @@ static bool arg_all = false; static bool arg_value = false; static bool arg_full = false; static bool arg_no_pager = false; +static bool arg_no_wall = false; static bool arg_legend = true; static const char *arg_kill_who = NULL; static int arg_signal = SIGTERM; static BusTransport arg_transport = BUS_TRANSPORT_LOCAL; static char *arg_host = NULL; +static usec_t arg_when = 0; +static char **arg_wall = NULL; static bool arg_ask_password = true; static bool arg_ignore_inhibitors = false; -#if 0 +#if 0 /// UNNEEDED by elogind static unsigned arg_lines = 10; static OutputMode arg_output = OUTPUT_SHORT; #endif // 0 static enum action { _ACTION_INVALID, + ACTION_HALT, ACTION_POWEROFF, ACTION_REBOOT, + ACTION_KEXEC, ACTION_SUSPEND, ACTION_HIBERNATE, ACTION_HYBRID_SLEEP, @@ -80,14 +85,6 @@ static enum action { } arg_action; -static void pager_open_if_enabled(void) { - - if (arg_no_pager) - return; - - pager_open(false); -} - static void polkit_agent_open_if_enabled(void) { /* Open the polkit agent as a child process if necessary */ @@ -124,7 +121,7 @@ static int list_sessions(int argc, char *argv[], void *userdata) { assert(bus); assert(argv); - pager_open_if_enabled(); + pager_open(arg_no_pager, false); r = sd_bus_call_method( bus, @@ -171,7 +168,7 @@ static int list_users(int argc, char *argv[], void *userdata) { assert(bus); assert(argv); - pager_open_if_enabled(); + pager_open(arg_no_pager, false); r = sd_bus_call_method( bus, @@ -217,7 +214,7 @@ static int list_seats(int argc, char *argv[], void *userdata) { assert(bus); assert(argv); - pager_open_if_enabled(); + pager_open(arg_no_pager, false); r = sd_bus_call_method( bus, @@ -258,18 +255,15 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_free_ char *path = NULL; const char *cgroup; - int r; unsigned c; + int r; assert(bus); assert(unit); - if (arg_transport != BUS_TRANSPORT_LOCAL) - return 0; - path = unit_dbus_path_from_name(unit); if (!path) - return -ENOMEM; + return log_oom(); r = sd_bus_get_property( bus, @@ -277,27 +271,40 @@ static int show_unit_cgroup(sd_bus *bus, const char *interface, const char *unit path, interface, "ControlGroup", - &error, &reply, "s"); + &error, + &reply, + "s"); if (r < 0) - return r; + return log_error_errno(r, "Failed to query ControlGroup: %s", bus_error_message(&error, r)); r = sd_bus_message_read(reply, "s", &cgroup); if (r < 0) - return r; + return bus_log_parse_error(r); if (isempty(cgroup)) return 0; - if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0) - return 0; - c = columns(); if (c > 18) c -= 18; else c = 0; - show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, false, &leader, leader > 0, get_output_flags()); + r = unit_show_processes(bus, unit, cgroup, "\t\t ", c, get_output_flags(), &error); + if (r == -EBADR) { + + if (arg_transport == BUS_TRANSPORT_REMOTE) + return 0; + + /* Fallback for older systemd versions where the GetUnitProcesses() call is not yet available */ + + if (cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, cgroup) != 0 && leader <= 0) + return 0; + + show_cgroup_and_extra(SYSTEMD_CGROUP_CONTROLLER, cgroup, "\t\t ", c, &leader, leader > 0, get_output_flags()); + } else if (r < 0) + return log_error_errno(r, "Failed to dump process list: %s", bus_error_message(&error, r)); + return 0; } #endif // 0 @@ -325,6 +332,7 @@ typedef struct SessionStatusInfo { typedef struct UserStatusInfo { uid_t uid; + bool linger; char *name; struct dual_timestamp timestamp; char *state; @@ -557,8 +565,9 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li if (i.scope) { printf("\t Unit: %s\n", i.scope); -#if 0 +#if 0 /// UNNEEDED by elogind show_unit_cgroup(bus, "org.freedesktop.systemd1.Scope", i.scope, i.leader); + if (arg_transport == BUS_TRANSPORT_LOCAL) { show_journal_by_unit( @@ -574,7 +583,6 @@ static int print_session_status_info(sd_bus *bus, const char *path, bool *new_li true, NULL); } - #endif // 0 } @@ -585,6 +593,7 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) static const struct bus_properties_map map[] = { { "Name", "s", NULL, offsetof(UserStatusInfo, name) }, + { "Linger", "b", NULL, offsetof(UserStatusInfo, linger) }, { "Slice", "s", NULL, offsetof(UserStatusInfo, slice) }, { "State", "s", NULL, offsetof(UserStatusInfo, state) }, { "UID", "u", NULL, offsetof(UserStatusInfo, uid) }, @@ -629,20 +638,21 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) char **l; printf("\tSessions:"); - STRV_FOREACH(l, i.sessions) { - if (streq_ptr(*l, i.display)) - printf(" *%s", *l); - else - printf(" %s", *l); - } + STRV_FOREACH(l, i.sessions) + printf(" %s%s", + streq_ptr(*l, i.display) ? "*" : "", + *l); printf("\n"); } + printf("\t Linger: %s\n", yes_no(i.linger)); + if (i.slice) { printf("\t Unit: %s\n", i.slice); -#if 0 +#if 0 /// UNNEEDED by elogind show_unit_cgroup(bus, "org.freedesktop.systemd1.Slice", i.slice, 0); + show_journal_by_unit( stdout, i.slice, @@ -655,7 +665,6 @@ static int print_user_status_info(sd_bus *bus, const char *path, bool *new_line) SD_JOURNAL_LOCAL_ONLY, true, NULL); - #endif // 0 } @@ -896,7 +905,7 @@ static int show_session(int argc, char *argv[], void *userdata) { properties = !strstr(argv[0], "status"); - pager_open_if_enabled(); + pager_open(arg_no_pager, false); if (argc <= 1) { /* If not argument is specified inspect the manager @@ -952,7 +961,7 @@ static int show_user(int argc, char *argv[], void *userdata) { properties = !strstr(argv[0], "status"); - pager_open_if_enabled(); + pager_open(arg_no_pager, false); if (argc <= 1) { /* If not argument is specified inspect the manager @@ -1012,7 +1021,7 @@ static int show_seat(int argc, char *argv[], void *userdata) { properties = !strstr(argv[0], "status"); - pager_open_if_enabled(); + pager_open(arg_no_pager, false); if (argc <= 1) { /* If not argument is specified inspect the manager @@ -1363,9 +1372,39 @@ static int terminate_seat(int argc, char *argv[], void *userdata) { return 0; } +static int logind_set_wall_message(sd_bus* bus, const char* msg) { + _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; + _cleanup_free_ char *m = NULL; + int r; + + if (strv_extend(&arg_wall, msg) < 0) + return log_oom(); + + m = strv_join(arg_wall, " "); + if (!m) + return log_oom(); + + r = sd_bus_call_method( + bus, + "org.freedesktop.login1", + "/org/freedesktop/login1", + "org.freedesktop.login1.Manager", + "SetWallMessage", + &error, + NULL, + "sb", + m, + !arg_no_wall); + + if (r < 0) + return log_warning_errno(r, "Failed to set wall message, ignoring: %s", bus_error_message(&error, r)); + + return 0; +} + /* Ask elogind, which might grant access to unprivileged users * through PolicyKit */ -static int reboot_with_logind(sd_bus *bus, enum action a) { +static int elogind_reboot(sd_bus *bus, enum action a) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; const char *method; int r; @@ -1410,27 +1449,13 @@ static int reboot_with_logind(sd_bus *bus, enum action a) { return -EINVAL; } - if (table[a]) { - r = sd_bus_call_method( - bus, - "org.freedesktop.login1", - "/org/freedesktop/login1", - "org.freedesktop.login1.Manager", - "SetWallMessage", - &error, - NULL, - "sb", - table[a], - true); - - if (r < 0) { - log_warning_errno(r, "Failed to set wall message, ignoring: %s", - bus_error_message(&error, r)); - sd_bus_error_free(&error); - } + r = logind_set_wall_message(bus, table[a]); + if (r < 0) { + log_warning_errno(r, "Failed to set wall message, ignoring: %s", + bus_error_message(&error, r)); + sd_bus_error_free(&error); } - r = sd_bus_call_method( bus, "org.freedesktop.login1", @@ -1467,7 +1492,56 @@ static enum action verb_to_action(const char *verb) { return _ACTION_INVALID; } -static int check_inhibitors(sd_bus *bus, enum action a) { +static int parse_shutdown_time_spec(const char *t, usec_t *_u) { + assert(t); + assert(_u); + + if (streq(t, "now")) + *_u = 0; + else if (!strchr(t, ':')) { + uint64_t u; + + if (safe_atou64(t, &u) < 0) + return -EINVAL; + + *_u = now(CLOCK_REALTIME) + USEC_PER_MINUTE * u; + } else { + char *e = NULL; + long hour, minute; + struct tm tm = {}; + time_t s; + usec_t n; + + errno = 0; + hour = strtol(t, &e, 10); + if (errno > 0 || *e != ':' || hour < 0 || hour > 23) + return -EINVAL; + + minute = strtol(e+1, &e, 10); + if (errno > 0 || *e != 0 || minute < 0 || minute > 59) + return -EINVAL; + + n = now(CLOCK_REALTIME); + s = (time_t) (n / USEC_PER_SEC); + + assert_se(localtime_r(&s, &tm)); + + tm.tm_hour = (int) hour; + tm.tm_min = (int) minute; + tm.tm_sec = 0; + + assert_se(s = mktime(&tm)); + + *_u = (usec_t) s * USEC_PER_SEC; + + while (*_u <= n) + *_u += USEC_PER_DAY; + } + + return 0; +} + +static int check_inhibitors(sd_bus* bus, enum action a) { _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL; _cleanup_strv_free_ char **sessions = NULL; const char *what, *who, *why, *mode; @@ -1476,10 +1550,10 @@ static int check_inhibitors(sd_bus *bus, enum action a) { char **s; int r; - if (!bus) + if (arg_ignore_inhibitors) return 0; - if (arg_ignore_inhibitors) + if (arg_when > 0) return 0; if (geteuid() == 0) @@ -1520,8 +1594,11 @@ static int check_inhibitors(sd_bus *bus, enum action a) { return log_error_errno(ERANGE, "Bad PID %"PRIu32": %m", pid); if (!strv_contains(sv, - a == ACTION_POWEROFF || - a == ACTION_REBOOT ? "shutdown" : "sleep")) + IN_SET(a, + ACTION_HALT, + ACTION_POWEROFF, + ACTION_REBOOT, + ACTION_KEXEC) ? "shutdown" : "sleep")) continue; get_process_comm(pid, &comm); @@ -1565,8 +1642,7 @@ static int check_inhibitors(sd_bus *bus, enum action a) { if (c <= 0) return 0; - log_error("Please retry operation after closing inhibitors and logging out other users.\n" - "Alternatively, ignore inhibitors and users with 'loginctl %s -i'.", + log_error("Please retry operation after closing inhibitors and logging out other users.\nAlternatively, ignore inhibitors and users with 'systemctl %s -i'.", action_table[a].verb); return -EPERM; @@ -1598,7 +1674,7 @@ static int start_special(int argc, char *argv[], void *userdata) { if ((a == ACTION_POWEROFF || a == ACTION_REBOOT) && (arg_action == ACTION_CANCEL_SHUTDOWN)) - return reboot_with_logind(bus, arg_action); + return elogind_reboot(bus, arg_action); /* Otherwise perform requested action */ if (a == ACTION_POWEROFF || @@ -1606,7 +1682,7 @@ static int start_special(int argc, char *argv[], void *userdata) { a == ACTION_SUSPEND || a == ACTION_HIBERNATE || a == ACTION_HYBRID_SLEEP) - return reboot_with_logind(bus, a); + return elogind_reboot(bus, a); return -EOPNOTSUPP; } @@ -1618,6 +1694,7 @@ static int help(int argc, char *argv[], void *userdata) { " -h --help Show this help\n" " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" + " --no-wall Do not print any wall message\n" " --no-legend Do not show the headers and footers\n" " --no-ask-password Don't prompt for password\n" " -H --host=[USER@]HOST Operate on remote host\n" @@ -1628,7 +1705,7 @@ static int help(int argc, char *argv[], void *userdata) { " -l --full Do not ellipsize output\n" " --kill-who=WHO Who to send signal to\n" " -s --signal=SIGNAL Which signal to send\n" -#if 0 +#if 0 /// UNNEEDED by elogind " -n --lines=INTEGER Number of journal entries to show\n" " -o --output=STRING Change journal output mode (short, short-monotonic,\n" " verbose, export, json, json-pretty, json-sse, cat)\n\n" @@ -1678,6 +1755,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_VERSION = 0x100, ARG_VALUE, ARG_NO_PAGER, + ARG_NO_WALL, ARG_NO_LEGEND, ARG_KILL_WHO, ARG_NO_ASK_PASSWORD, @@ -1691,13 +1769,14 @@ static int parse_argv(int argc, char *argv[]) { { "value", no_argument, NULL, ARG_VALUE }, { "full", no_argument, NULL, 'l' }, { "no-pager", no_argument, NULL, ARG_NO_PAGER }, + { "no-wall", no_argument, NULL, ARG_NO_WALL }, { "no-legend", no_argument, NULL, ARG_NO_LEGEND }, { "kill-who", required_argument, NULL, ARG_KILL_WHO }, { "signal", required_argument, NULL, 's' }, { "host", required_argument, NULL, 'H' }, { "machine", required_argument, NULL, 'M' }, { "no-ask-password", no_argument, NULL, ARG_NO_ASK_PASSWORD }, -#if 0 +#if 0 /// UNNEEDED by elogind { "lines", required_argument, NULL, 'n' }, { "output", required_argument, NULL, 'o' }, #endif // 0 @@ -1705,6 +1784,7 @@ static int parse_argv(int argc, char *argv[]) { {} }; + char **wall = NULL; int c, r; assert(argc >= 0); @@ -1744,7 +1824,8 @@ static int parse_argv(int argc, char *argv[]) { case 'l': arg_full = true; break; -#if 0 + +#if 0 /// UNNEEDED by elogind case 'n': if (safe_atou(optarg, &arg_lines) < 0) { log_error("Failed to parse lines '%s'", optarg); @@ -1760,10 +1841,15 @@ static int parse_argv(int argc, char *argv[]) { } break; #endif // 0 + case ARG_NO_PAGER: arg_no_pager = true; break; + case ARG_NO_WALL: + arg_no_wall = true; + break; + case ARG_NO_LEGEND: arg_legend = false; break; @@ -1809,6 +1895,30 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached("Unhandled option"); } + if (argc > optind && arg_action != ACTION_CANCEL_SHUTDOWN) { + r = parse_shutdown_time_spec(argv[optind], &arg_when); + if (r < 0) { + log_error("Failed to parse time specification: %s", argv[optind]); + return r; + } + } else + arg_when = now(CLOCK_REALTIME) + USEC_PER_MINUTE; + + if (argc > optind && arg_action == ACTION_CANCEL_SHUTDOWN) + /* No time argument for shutdown cancel */ + wall = argv + optind; + else if (argc > optind + 1) + /* We skip the time argument */ + wall = argv + optind + 1; + + if (wall) { + arg_wall = strv_copy(wall); + if (!arg_wall) + return log_oom(); + } + + optind = argc; + return 1; } @@ -1879,6 +1989,7 @@ finish: polkit_agent_close(); strv_free(arg_property); + strv_free(arg_wall); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/login/logind-core.c b/src/login/logind-core.c index 5e62e5ecd..23d2aee43 100644 --- a/src/login/logind-core.c +++ b/src/login/logind-core.c @@ -115,8 +115,8 @@ int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User ** } int manager_add_user_by_name(Manager *m, const char *name, User **_user) { - uid_t uid = 1000; - gid_t gid = 1000; + uid_t uid; + gid_t gid; int r; assert(m); @@ -345,7 +345,6 @@ int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) { *user = s->user; #endif // 0 - return 1; } @@ -392,19 +391,16 @@ bool manager_shall_kill(Manager *m, const char *user) { assert(m); assert(user); - if (!m->kill_user_processes) - return false; - if (!m->kill_exclude_users && streq(user, "root")) return false; if (strv_contains(m->kill_exclude_users, user)) return false; - if (strv_isempty(m->kill_only_users)) - return true; + if (!strv_isempty(m->kill_only_users)) + return strv_contains(m->kill_only_users, user); - return strv_contains(m->kill_only_users, user); + return m->kill_user_processes; } #if 0 /// UNNEEDED by elogind @@ -462,7 +458,7 @@ int manager_spawn_autovt(Manager *m, unsigned int vtnr) { m->bus, "org.freedesktop.systemd1", "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", + "org.freedesktop.systemd.Manager", "StartUnit", &error, NULL, diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 0a30dfd16..44fe5e507 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -870,13 +870,17 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus session->create_message = sd_bus_message_ref(message); - /* Here upstream systemd starts cgroups and the user systemd, - and arranges to reply asynchronously. We reply - directly. */ +#if 0 /// UNNEEDED by elogind + /* Now, let's wait until the slice unit and stuff got + * created. We send the reply back from + * session_send_create_reply(). */ +#else + /* We reply directly. */ r = session_send_create_reply(session, NULL); if (r < 0) goto fail; +#endif // 0 return 1; @@ -1558,39 +1562,39 @@ static int execute_shutdown_or_sleep( log_info("Running in dry run, suppressing action."); reset_scheduled_shutdown(m); } else { - r = sd_bus_call_method( - m->bus, - "org.freedesktop.systemd1", - "/org/freedesktop/systemd1", - "org.freedesktop.systemd1.Manager", - "StartUnit", - error, - &reply, - "ss", unit_name, "replace-irreversibly"); + r = sd_bus_call_method( + m->bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "StartUnit", + error, + &reply, + "ss", unit_name, "replace-irreversibly"); + if (r < 0) + return r; + + r = sd_bus_message_read(reply, "o", &p); + if (r < 0) + return r; + + c = strdup(p); + if (!c) + return -ENOMEM; + + m->action_unit = unit_name; + free(m->action_job); + m->action_job = c; + m->action_what = w; + } #else r = shutdown_or_sleep(m, action); /* no more pending actions, whether this failed or not */ m->pending_action = HANDLE_IGNORE; m->action_what = 0; -#endif // 0 - if (r < 0) - return r; - -#if 0 /// elogind neither needs a dbus reply, nor supports systemd action jobs - r = sd_bus_message_read(reply, "o", &p); if (r < 0) return r; - - c = strdup(p); - if (!c) - return -ENOMEM; - } - - m->action_unit = unit_name; - free(m->action_job); - m->action_job = c; - m->action_what = w; #endif // 0 /* Make sure the lid switch is ignored for a while */ @@ -1960,8 +1964,8 @@ static int update_schedule_file(Manager *m) { return 0; fail: - (void) unlink(temp_path); - (void) unlink("/run/systemd/shutdown/scheduled"); + (void) unlink(temp_path); + (void) unlink("/run/systemd/shutdown/scheduled"); return log_error_errno(r, "Failed to write information about scheduled shutdowns: %m"); } diff --git a/src/login/logind-gperf.gperf b/src/login/logind-gperf.gperf index 9705dd5b1..4dbabd455 100644 --- a/src/login/logind-gperf.gperf +++ b/src/login/logind-gperf.gperf @@ -32,6 +32,9 @@ Login.IdleAction, config_parse_handle_action, 0, offsetof(Manag Login.IdleActionSec, config_parse_sec, 0, offsetof(Manager, idle_action_usec) Login.RuntimeDirectorySize, config_parse_tmpfs_size, 0, offsetof(Manager, runtime_dir_size) Login.RemoveIPC, config_parse_bool, 0, offsetof(Manager, remove_ipc) +Login.InhibitorsMax, config_parse_uint64, 0, offsetof(Manager, inhibitors_max) +Login.SessionsMax, config_parse_uint64, 0, offsetof(Manager, sessions_max) +Login.UserTasksMax, config_parse_uint64, 0, offsetof(Manager, user_tasks_max) Sleep.SuspendMode, config_parse_strv, 0, offsetof(Manager, suspend_mode) Sleep.SuspendState, config_parse_strv, 0, offsetof(Manager, suspend_state) Sleep.HibernateMode, config_parse_strv, 0, offsetof(Manager, hibernate_mode) diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 33fd3afac..ae42811de 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -368,7 +368,6 @@ int seat_active_vt_changed(Seat *s, unsigned int vtnr) { } r = seat_set_active(s, new_active); - #if 0 /// elogind does not spawn autovt manager_spawn_autovt(s->manager, vtnr); #endif // 0 diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index d1e652344..d51743393 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -768,10 +768,9 @@ int session_send_create_reply(Session *s, sd_bus_error *error) { if (fifo_fd < 0) return fifo_fd; - /* Update the session and user state files before we notify - * the client about the result. */ + /* Update the session state file before we notify the client + * about the result. */ session_save(s); - user_save(s->user); p = session_bus_path(s); if (!p) diff --git a/src/login/logind-session-device.c b/src/login/logind-session-device.c index 4055a2327..6c65607b9 100644 --- a/src/login/logind-session-device.c +++ b/src/login/logind-session-device.c @@ -23,7 +23,11 @@ #include #include +#if 0 /// elogind needs the systems udev header #include "libudev.h" +#else +#include +#endif // 0 #include "alloc-util.h" #include "bus-util.h" diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 902578890..3a77b833f 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -46,7 +46,7 @@ #include "user-util.h" #include "util.h" -// #define RELEASE_USEC (20*USEC_PER_SEC) +#define RELEASE_USEC (20*USEC_PER_SEC) static void session_remove_fifo(Session *s); @@ -550,8 +550,7 @@ static int session_start_scope(Session *s) { return 0; } -#endif // 0 - +#else static int session_start_cgroup(Session *s) { int r; @@ -570,7 +569,7 @@ static int session_start_cgroup(Session *s) { return 0; } - +#endif // 0 int session_start(Session *s) { int r; @@ -588,9 +587,7 @@ int session_start(Session *s) { return r; /* Create cgroup */ -/// elogind does its own session management without systemd units, -/// slices and scopes -#if 0 +#if 0 /// elogind does its own session management r = session_start_scope(s); #else r = session_start_cgroup(s); @@ -665,8 +662,7 @@ static int session_stop_scope(Session *s, bool force) { return 0; } -#endif // 0 - +#else static int session_stop_cgroup(Session *s, bool force) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; @@ -681,6 +677,7 @@ static int session_stop_cgroup(Session *s, bool force) { return 0; } +#endif // 0 int session_stop(Session *s, bool force) { int r; @@ -785,17 +782,16 @@ int session_release(Session *s) { if (s->timer_event_source) return 0; - /* In systemd, session release is triggered by user jobs - dying. In elogind we don't have that so go ahead and stop - now. */ -#if 0 +#if 0 /// UNNEEDED by elogind return sd_event_add_time(s->manager->event, &s->timer_event_source, CLOCK_MONOTONIC, now(CLOCK_MONOTONIC) + RELEASE_USEC, 0, release_timeout_callback, s); - #else + /* In systemd, session release is triggered by user jobs + dying. In elogind we don't have that so go ahead and stop + now. */ return session_stop(s, false); #endif // 0 } @@ -1028,10 +1024,6 @@ bool session_check_gc(Session *s, bool drop_not_started) { return true; #endif // 0 - if ( s->user->manager - && (cg_is_empty_recursive (SYSTEMD_CGROUP_CONTROLLER, s->user->manager->cgroup_root) > 0) ) - return true; - return false; } diff --git a/src/login/logind-session.h b/src/login/logind-session.h index 23f971a52..d86ba61ad 100644 --- a/src/login/logind-session.h +++ b/src/login/logind-session.h @@ -87,7 +87,6 @@ struct Session { char *service; char *desktop; - /* always NULL */ char *scope; #if 0 /// UNNEEDED by elogind char *scope_job; diff --git a/src/login/logind-user.c b/src/login/logind-user.c index 8a557df35..a89d1bef7 100644 --- a/src/login/logind-user.c +++ b/src/login/logind-user.c @@ -124,6 +124,7 @@ User *user_free(User *u) { u->slice_job = mfree(u->slice_job); u->service_job = mfree(u->service_job); #endif // 0 + u->service = mfree(u->service); u->slice = mfree(u->slice); u->runtime_path = mfree(u->runtime_path); @@ -383,7 +384,7 @@ static int user_mkdir_runtime_path(User *u) { return 0; fail: - /* Try to clean up, but ignore errors */ + /* Try to clean up, but ignore errors */ (void) rmdir(u->runtime_path); return r; } @@ -439,11 +440,11 @@ static int user_start_service(User *u) { u->service, &error, &job); - if (r < 0) { + if (r < 0) { /* we don't fail due to this, let's try to continue */ log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r)); - } else { - u->service_job = job; + } else { + u->service_job = job; } #else assert(u); diff --git a/src/login/logind-user.h b/src/login/logind-user.h index f3fa4403d..043870b24 100644 --- a/src/login/logind-user.h +++ b/src/login/logind-user.h @@ -42,14 +42,9 @@ struct User { char *name; char *state_file; char *runtime_path; - - /* These are always NULL, and here just for logind-user-dbus.c - to easily provide a NULL value for the user's service and - slice properties. */ char *slice; char *service; - #if 0 /// UNNEEDED by elogind char *service_job; char *slice_job; diff --git a/src/login/logind.c b/src/login/logind.c index e0cd70448..4c0b1df0e 100644 --- a/src/login/logind.c +++ b/src/login/logind.c @@ -22,7 +22,11 @@ #include #include +#if 0 /// elogind needs the systems udev header #include "libudev.h" +#else +#include +#endif // 0 #include "sd-daemon.h" #include "alloc-util.h" @@ -46,26 +50,14 @@ #include "musl_missing.h" static void manager_free(Manager *m); -static int manager_parse_config_file(Manager *m); -static Manager *manager_new(void) { +static void manager_reset_config(Manager *m) { + #ifdef ENABLE_DEBUG_ELOGIND int dbg_cnt; #endif // ENABLE_DEBUG_ELOGIND - Manager *m; - int r; - - m = new0(Manager, 1); - if (!m) - return NULL; - - m->pin_cgroupfs_fd = -1; - - m->console_active_fd = -1; #if 0 /// elogind does not support autospawning of vts - m->reserve_vt_fd = -1; - m->n_autovts = 6; m->reserve_vt = 6; #endif // 0 @@ -76,83 +68,37 @@ static Manager *manager_new(void) { m->handle_hibernate_key = HANDLE_HIBERNATE; m->handle_lid_switch = HANDLE_SUSPEND; m->handle_lid_switch_docked = HANDLE_IGNORE; + m->power_key_ignore_inhibited = false; + m->suspend_key_ignore_inhibited = false; + m->hibernate_key_ignore_inhibited = false; m->lid_switch_ignore_inhibited = true; + m->holdoff_timeout_usec = 30 * USEC_PER_SEC; m->idle_action_usec = 30 * USEC_PER_MINUTE; m->idle_action = HANDLE_IGNORE; - m->idle_action_not_before_usec = now(CLOCK_MONOTONIC); m->runtime_dir_size = PAGE_ALIGN((size_t) (physical_memory() / 10)); /* 10% */ - m->user_tasks_max = UINT64_C(12288); - - m->devices = hashmap_new(&string_hash_ops); - m->seats = hashmap_new(&string_hash_ops); - m->sessions = hashmap_new(&string_hash_ops); - m->users = hashmap_new(NULL); - m->inhibitors = hashmap_new(&string_hash_ops); - m->buttons = hashmap_new(&string_hash_ops); - - m->user_units = hashmap_new(&string_hash_ops); - m->session_units = hashmap_new(&string_hash_ops); - - m->running_as = MANAGER_SYSTEM; - m->test_run = false; - - if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units) - goto fail; - - m->kill_exclude_users = strv_new("root", NULL); - if (!m->kill_exclude_users) - goto fail; - - /* If elogind should be its own controller, mount its cgroup */ - if (streq(SYSTEMD_CGROUP_CONTROLLER, "name=elogind")) { - r = mount_setup(true); - if (r < 0) - goto fail; - } - - /* Make cgroups */ - r = manager_setup_cgroup(m); - if (r < 0) - goto fail; + m->user_tasks_max = 12288; + m->sessions_max = 8192; + m->inhibitors_max = 8192; - m->suspend_mode = NULL; - m->suspend_state = NULL; - m->hibernate_mode = NULL; - m->hibernate_state = NULL; - m->hybrid_sleep_mode = NULL; - m->hybrid_sleep_state = NULL; + m->kill_user_processes = KILL_USER_PROCESSES; - manager_parse_config_file(m); + m->kill_only_users = strv_free(m->kill_only_users); + m->kill_exclude_users = strv_free(m->kill_exclude_users); /* Set default Sleep config if not already set by logind.conf */ - if (!m->suspend_state) { + if (!m->suspend_state) m->suspend_state = strv_new("mem", "standby", "freeze", NULL); - if (!m->suspend_state) - goto fail; - } - if (!m->hibernate_mode) { + if (!m->hibernate_mode) m->hibernate_mode = strv_new("platform", "shutdown", NULL); - if (!m->hibernate_mode) - goto fail; - } - if (!m->hibernate_state) { + if (!m->hibernate_state) m->hibernate_state = strv_new("disk", NULL); - if (!m->hibernate_state) - goto fail; - } - if (!m->hybrid_sleep_mode) { + if (!m->hybrid_sleep_mode) m->hybrid_sleep_mode = strv_new("suspend", "platform", "shutdown", NULL); - if (!m->hybrid_sleep_mode) - goto fail; - } - if (!m->hybrid_sleep_state) { + if (!m->hybrid_sleep_state) m->hybrid_sleep_state = strv_new("disk", NULL); - if (!m->hybrid_sleep_state) - goto fail; - } #ifdef ENABLE_DEBUG_ELOGIND dbg_cnt = -1; @@ -180,6 +126,57 @@ static Manager *manager_new(void) { log_debug_elogind("hybrid_sleep_state[%d] = %s", dbg_cnt, m->hybrid_sleep_state[dbg_cnt]); #endif // ENABLE_DEBUG_ELOGIND +} + +static Manager *manager_new(void) { + Manager *m; + int r; + + m = new0(Manager, 1); + if (!m) + return NULL; + + m->pin_cgroupfs_fd = -1; + m->console_active_fd = -1; +#if 0 /// UNNEEDED by elogind + m->reserve_vt_fd = -1; +#endif // 0 + + m->idle_action_not_before_usec = now(CLOCK_MONOTONIC); + + m->devices = hashmap_new(&string_hash_ops); + m->seats = hashmap_new(&string_hash_ops); + m->sessions = hashmap_new(&string_hash_ops); + m->users = hashmap_new(NULL); + m->inhibitors = hashmap_new(&string_hash_ops); + m->buttons = hashmap_new(&string_hash_ops); + + m->user_units = hashmap_new(&string_hash_ops); + m->session_units = hashmap_new(&string_hash_ops); + + m->test_run = false; + + if (!m->devices || !m->seats || !m->sessions || !m->users || !m->inhibitors || !m->buttons || !m->user_units || !m->session_units) + goto fail; + + /* If elogind should be its own controller, mount its cgroup */ + if (streq(SYSTEMD_CGROUP_CONTROLLER, "name=elogind")) { + r = mount_setup(true); + if (r < 0) + goto fail; + } + + /* Make cgroups */ + r = manager_setup_cgroup(m); + if (r < 0) + goto fail; + + m->suspend_mode = NULL; + m->suspend_state = NULL; + m->hibernate_mode = NULL; + m->hibernate_state = NULL; + m->hybrid_sleep_mode = NULL; + m->hybrid_sleep_state = NULL; m->udev = udev_new(); if (!m->udev) @@ -191,6 +188,8 @@ static Manager *manager_new(void) { sd_event_set_watchdog(m->event, true); + manager_reset_config(m); + return m; fail: @@ -251,12 +250,12 @@ static void manager_free(Manager *m) { safe_close(m->console_active_fd); - udev_monitor_unref(m->udev_seat_monitor); - udev_monitor_unref(m->udev_device_monitor); - udev_monitor_unref(m->udev_vcsa_monitor); - udev_monitor_unref(m->udev_button_monitor); + udev_monitor_unref(m->udev_seat_monitor); + udev_monitor_unref(m->udev_device_monitor); + udev_monitor_unref(m->udev_vcsa_monitor); + udev_monitor_unref(m->udev_button_monitor); - udev_unref(m->udev); + udev_unref(m->udev); if (m->unlink_nologin) (void) unlink("/run/nologin"); @@ -286,6 +285,9 @@ static void manager_free(Manager *m) { strv_free(m->hybrid_sleep_mode); strv_free(m->hybrid_sleep_state); +#if 0 /// UNNEEDED by elogind + free(m->action_job); +#endif // 0 free(m); } @@ -686,14 +688,26 @@ static int manager_reserve_vt(Manager *m) { #endif // 0 static int signal_agent_released(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL; Manager *m = userdata; - Session *s; const char *cgroup; + Session *s; + uid_t sender_uid; int r; assert(message); assert(m); + /* only accept org.freedesktop.systemd1.Agent from UID=0 */ + r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); + if (r < 0) + return r; + + r = sd_bus_creds_get_euid(creds, &sender_uid); + if (r < 0 || sender_uid != 0) + return 0; + + /* parse 'cgroup-empty' notification */ r = sd_bus_message_read(message, "s", &cgroup); if (r < 0) { bus_log_parse_error(r); @@ -729,12 +743,14 @@ static int manager_connect_bus(Manager *m) { return log_error_errno(r, "Failed to add manager object vtable: %m"); /* elogind relies on signals from its release agent */ - r = sd_bus_add_match(m->bus, NULL, - "type='signal'," - "interface='org.freedesktop.elogind.Agent'," - "member='Released'," - "path='/org/freedesktop/elogind/agent'", - signal_agent_released, m); + r = sd_bus_add_match( + m->bus, + NULL, + "type='signal'," + "interface='org.freedesktop.elogind.Agent'," + "member='Released'," + "path='/org/freedesktop/elogind/agent'", + signal_agent_released, m); r = sd_bus_add_fallback_vtable(m->bus, NULL, "/org/freedesktop/login1/seat", "org.freedesktop.login1.Seat", seat_vtable, seat_object_find, m); if (r < 0) @@ -1134,6 +1150,43 @@ static int manager_dispatch_idle_action(sd_event_source *s, uint64_t t, void *us return 0; } +static int manager_parse_config_file(Manager *m) { +#if 0 /// elogind parses its own config file + assert(m); + + return config_parse_many(PKGSYSCONFDIR "/logind.conf", + CONF_PATHS_NULSTR("systemd/logind.conf.d"), + "Login\0", + config_item_perf_lookup, logind_gperf_lookup, + false, m); +#else + const char* logind_conf = getenv("ELOGIND_CONF_FILE"); + + assert(m); + + if (!logind_conf) + logind_conf = PKGSYSCONFDIR "/logind.conf"; + + return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0", + config_item_perf_lookup, logind_gperf_lookup, + false, false, true, m); +#endif // 0 +} + +static int manager_dispatch_reload_signal(sd_event_source *s, const struct signalfd_siginfo *si, void *userdata) { + Manager *m = userdata; + int r; + + manager_reset_config(m); + r = manager_parse_config_file(m); + if (r < 0) + log_warning_errno(r, "Failed to parse config file, using defaults: %m"); + else + log_info("Config file reloaded."); + + return 0; +} + static int manager_startup(Manager *m) { int r; Seat *seat; @@ -1145,6 +1198,12 @@ static int manager_startup(Manager *m) { assert(m); + assert_se(sigprocmask_many(SIG_SETMASK, NULL, SIGHUP, -1) >= 0); + + r = sd_event_add_signal(m->event, NULL, SIGHUP, manager_dispatch_reload_signal, m); + if (r < 0) + return log_error_errno(r, "Failed to register SIGHUP handler: %m"); + /* Connect to console */ r = manager_connect_console(m); if (r < 0) @@ -1249,30 +1308,6 @@ static int manager_run(Manager *m) { } } -static int manager_parse_config_file(Manager *m) { -#if 0 /// elogind parses its own config file - - assert(m); - - return config_parse_many(PKGSYSCONFDIR "/logind.conf", - CONF_PATHS_NULSTR("systemd/logind.conf.d"), - "Login\0", - config_item_perf_lookup, logind_gperf_lookup, - false, m); -#else - const char* logind_conf = getenv("ELOGIND_CONF_FILE"); - - assert(m); - - if (!logind_conf) - logind_conf = PKGSYSCONFDIR "/logind.conf"; - - return config_parse(NULL, logind_conf, NULL, "Login\0Sleep\0", - config_item_perf_lookup, logind_gperf_lookup, - false, false, true, m); -#endif // 0 -} - int main(int argc, char *argv[]) { Manager *m = NULL; int r; @@ -1334,6 +1369,8 @@ int main(int argc, char *argv[]) { goto finish; } + manager_parse_config_file(m); + r = manager_startup(m); if (r < 0) { log_error_errno(r, "Failed to fully start up daemon: %m"); @@ -1355,7 +1392,7 @@ finish: "STOPPING=1\n" "STATUS=Shutting down..."); - manager_free(m); + manager_free(m); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } diff --git a/src/login/logind.h b/src/login/logind.h index 752d4e399..53c2b3884 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -21,14 +21,17 @@ #include +#if 0 /// elogind needs the systems udev header #include "libudev.h" +#else +#include +#endif // 0 #include "sd-bus.h" #include "sd-event.h" #include "cgroup-util.h" #include "hashmap.h" #include "list.h" -#include "path-lookup.h" #include "set.h" typedef struct Manager Manager; @@ -63,12 +66,19 @@ struct Manager { sd_event_source *udev_vcsa_event_source; sd_event_source *udev_button_event_source; +#if 0 /// elogind does not support autospawning of vts + int console_active_fd; + + unsigned n_autovts; + + unsigned reserve_vt; + int reserve_vt_fd; +#else /* Make sure the user cannot accidentally unmount our cgroup * file system */ int pin_cgroupfs_fd; /* Flags */ - ManagerRunningAs running_as; bool test_run:1; /* Data specific to the cgroup subsystem */ @@ -76,12 +86,6 @@ struct Manager { char *cgroup_root; int console_active_fd; - -#if 0 /// elogind does not support autospawning of vts - unsigned n_autovts; - - unsigned reserve_vt; - int reserve_vt_fd; #endif // 0 Seat *seat0; @@ -115,8 +119,12 @@ struct Manager { contains the action we are supposed to perform after the delay is over */ HandleAction pending_action; -#endif // 0 + char **suspend_state, **suspend_mode; + char **hibernate_state, **hibernate_mode; + char **hybrid_sleep_state, **hybrid_sleep_mode; + +#endif // 0 sd_event_source *inhibit_timeout_source; char *scheduled_shutdown_type; @@ -151,10 +159,6 @@ struct Manager { bool remove_ipc; - char **suspend_state, **suspend_mode; - char **hibernate_state, **hibernate_mode; - char **hybrid_sleep_state, **hybrid_sleep_mode; - Hashmap *polkit_registry; usec_t holdoff_timeout_usec; @@ -210,7 +214,7 @@ int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_ #if 0 /// UNNEEDED by elogind int manager_start_slice(Manager *manager, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job); -int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, sd_bus_error *error, char **job); +int manager_start_scope(Manager *manager, const char *scope, pid_t pid, const char *slice, const char *description, const char *after, const char *after2, uint64_t tasks_max, sd_bus_error *error, char **job); int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); diff --git a/src/login/sysfs-show.c b/src/login/sysfs-show.c index 29785e2f1..cb5bb5e5f 100644 --- a/src/login/sysfs-show.c +++ b/src/login/sysfs-show.c @@ -20,7 +20,11 @@ #include #include +#if 0 /// elogind needs the systems udev header #include "libudev.h" +#else +#include +#endif // 0 #include "alloc-util.h" #include "locale-util.h" diff --git a/src/login/test-login-tables.c b/src/login/test-login-tables.c index a4196bf14..4fbc893a9 100644 --- a/src/login/test-login-tables.c +++ b/src/login/test-login-tables.c @@ -19,7 +19,6 @@ #include "logind-action.h" #include "logind-session.h" - #include "test-tables.h" int main(int argc, char **argv) { -- 2.30.2