summaryrefslogtreecommitdiff
path: root/src/login
diff options
context:
space:
mode:
Diffstat (limited to 'src/login')
-rw-r--r--src/login/.gitignore1
-rw-r--r--src/login/loginctl.c249
-rw-r--r--src/login/logind-core.c16
-rw-r--r--src/login/logind-dbus.c64
-rw-r--r--src/login/logind-gperf.gperf3
-rw-r--r--src/login/logind-seat.c1
-rw-r--r--src/login/logind-session-dbus.c5
-rw-r--r--src/login/logind-session-device.c4
-rw-r--r--src/login/logind-session.c28
-rw-r--r--src/login/logind-session.h1
-rw-r--r--src/login/logind-user.c9
-rw-r--r--src/login/logind-user.h5
-rw-r--r--src/login/logind.c261
-rw-r--r--src/login/logind.h32
-rw-r--r--src/login/sysfs-show.c4
-rw-r--r--src/login/test-login-tables.c1
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 <sys/ioctl.h>
#include <sys/types.h>
+#if 0 /// elogind needs the systems udev header
#include "libudev.h"
+#else
+#include <libudev.h>
+#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 <string.h>
#include <unistd.h>
+#if 0 /// elogind needs the systems udev header
#include "libudev.h"
+#else
+#include <libudev.h>
+#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 <stdbool.h>
+#if 0 /// elogind needs the systems udev header
#include "libudev.h"
+#else
+#include <libudev.h>
+#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 <errno.h>
#include <string.h>
+#if 0 /// elogind needs the systems udev header
#include "libudev.h"
+#else
+#include <libudev.h>
+#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) {