summaryrefslogtreecommitdiff
path: root/src/login/logind-user.c
diff options
context:
space:
mode:
authorSven Eden <yamakuzure@gmx.net>2017-01-26 09:56:23 +0100
committerSven Eden <yamakuzure@gmx.net>2017-03-14 10:23:10 +0100
commitdb74dfab5842da3f83d3bb9e2fa3bf8736939ecf (patch)
treef33a44512dea72f0dd475c98d19a1cb223b36e26 /src/login/logind-user.c
parentfaf2e887be42215c1999950d16d1975e70bbdfe9 (diff)
Remove dependency of systemd units, services and slices for new sessions.
* elogind does not support systemd services and units. But at least the units are needed to support the systemd cgroup slice/scope system. * Remove systemd subscription to scope, service and slice jobs. These can not be supported in any way, as they depend on systemd running the machine. * The functions session_start_scope(), user_start_service() and user_start_slice() no longer try to call systemd via dbus for assistance. This way they generate their proper scope, service and slice names, and store them in the Managers HashMaps for session and user units. This should enable us to reverse track pids to users and such stuff, as that is what systemd-logind does, not knowing whether any unit *really* has been started or not. However, this will not work out of the box until we find a way to integrate cg_create_everywhere() into elogind without becoming dependent of systemd unit, service and job knowledge again.
Diffstat (limited to 'src/login/logind-user.c')
-rw-r--r--src/login/logind-user.c184
1 files changed, 133 insertions, 51 deletions
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 987244e27..2733117c6 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -36,9 +36,10 @@
#include "bus-error.h"
#include "conf-parser.h"
#include "clean-ipc.h"
-#include "logind-user.h"
#include "smack-util.h"
#include "formats-util.h"
+#include "label.h"
+#include "logind-user.h"
User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
User *u;
@@ -93,8 +94,11 @@ void user_free(User *u) {
free(u->service);
}
+/// elogind does not support slice and service jobs
+#if 0
free(u->slice_job);
free(u->service_job);
+#endif // 0
free(u->runtime_path);
@@ -105,7 +109,7 @@ void user_free(User *u) {
free(u);
}
-int user_save(User *u) {
+static int user_save_internal(User *u) {
_cleanup_free_ char *temp_path = NULL;
_cleanup_fclose_ FILE *f = NULL;
int r;
@@ -113,9 +117,6 @@ int user_save(User *u) {
assert(u);
assert(u->state_file);
- if (!u->started)
- return 0;
-
r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
if (r < 0)
goto fail;
@@ -138,13 +139,19 @@ int user_save(User *u) {
if (u->service)
fprintf(f, "SERVICE=%s\n", u->service);
+/// elogind does not support service jobs
+#if 0
if (u->service_job)
fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
+#endif // 0
if (u->slice)
fprintf(f, "SLICE=%s\n", u->slice);
+/// elogind does not support slice jobs
+#if 0
if (u->slice_job)
fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
+#endif // 0
if (u->display)
fprintf(f, "DISPLAY=%s\n", u->display->id);
@@ -263,6 +270,15 @@ fail:
return log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
}
+int user_save(User *u) {
+ assert(u);
+
+ if (!u->started)
+ return 0;
+
+ return user_save_internal (u);
+}
+
int user_load(User *u) {
_cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
Session *s = NULL;
@@ -273,9 +289,15 @@ int user_load(User *u) {
r = parse_env_file(u->state_file, NEWLINE,
"RUNTIME", &u->runtime_path,
"SERVICE", &u->service,
+/// elogind does not support service jobs
+#if 0
"SERVICE_JOB", &u->service_job,
+#endif // 0
"SLICE", &u->slice,
+/// elogind does not support slice jobs
+#if 0
"SLICE_JOB", &u->slice_job,
+#endif // 0
"DISPLAY", &display,
"REALTIME", &realtime,
"MONOTONIC", &monotonic,
@@ -325,10 +347,10 @@ static int user_mkdir_runtime_path(User *u) {
} else
p = u->runtime_path;
- if (path_is_mount_point(p, false) <= 0) {
+ if (path_is_mount_point(p, 0) <= 0) {
_cleanup_free_ char *t = NULL;
- (void) mkdir(p, 0700);
+ (void) mkdir_label(p, 0700);
if (mac_smack_use())
r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
@@ -356,6 +378,10 @@ static int user_mkdir_runtime_path(User *u) {
goto fail;
}
}
+
+ r = label_fix(p, false, false);
+ if (r < 0)
+ log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", p);
}
u->runtime_path = p;
@@ -373,7 +399,7 @@ fail:
}
static int user_start_slice(User *u) {
- char *job;
+ // char *job;
int r;
assert(u);
@@ -387,15 +413,21 @@ static int user_start_slice(User *u) {
if (r < 0)
return r;
+/// elogind : Do not try to use dbus to ask systemd
+#if 0
r = manager_start_unit(u->manager, slice, &error, &job);
+#endif // 0
if (r < 0) {
log_error("Failed to start user slice: %s", bus_error_message(&error, r));
free(slice);
} else {
u->slice = slice;
+/// elogind does not support slice jobs
+#if 0
free(u->slice_job);
u->slice_job = job;
+#endif // 0
}
}
@@ -407,7 +439,7 @@ static int user_start_slice(User *u) {
static int user_start_service(User *u) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
+ // char *job;
int r;
assert(u);
@@ -420,15 +452,21 @@ static int user_start_service(User *u) {
if (r < 0)
return log_error_errno(r, "Failed to build service name: %m");
+/// elogind : Do not try to use dbus to ask systemd
+#if 0
r = manager_start_unit(u->manager, service, &error, &job);
+#endif // 0
if (r < 0) {
log_error("Failed to start user service: %s", bus_error_message(&error, r));
free(service);
} else {
u->service = service;
+/// elogind does not support service jobs
+#if 0
free(u->service_job);
u->service_job = job;
+#endif // 0
}
}
@@ -458,6 +496,12 @@ int user_start(User *u) {
if (r < 0)
return r;
+ /* Save the user data so far, because pam_systemd will read the
+ * XDG_RUNTIME_DIR out of it while starting up systemd --user.
+ * We need to do user_save_internal() because we have not
+ * "officially" started yet. */
+ user_save_internal(u);
+
/* Spawn user systemd */
r = user_start_service(u);
if (r < 0)
@@ -476,10 +520,12 @@ int user_start(User *u) {
return 0;
}
+/// UNNEEDED by elogind
+#if 0
static int user_stop_slice(User *u) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
- int r;
+ // char *job;
+ int r = 0;
assert(u);
@@ -500,8 +546,8 @@ static int user_stop_slice(User *u) {
static int user_stop_service(User *u) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
- char *job;
- int r;
+ // char *job;
+ int r = 0;
assert(u);
@@ -519,6 +565,7 @@ static int user_stop_service(User *u) {
return r;
}
+#endif // 0
static int user_remove_runtime_path(User *u) {
int r;
@@ -567,6 +614,8 @@ int user_stop(User *u, bool force) {
}
/* Kill systemd */
+/// elogind does not support service or slice jobs
+#if 0
k = user_stop_service(u);
if (k < 0)
r = k;
@@ -575,6 +624,7 @@ int user_stop(User *u, bool force) {
k = user_stop_slice(u);
if (k < 0)
r = k;
+#endif // 0
u->stopping = true;
@@ -624,7 +674,7 @@ int user_finalize(User *u) {
int user_get_idle_hint(User *u, dual_timestamp *t) {
Session *s;
bool idle_hint = true;
- dual_timestamp ts = { 0, 0 };
+ dual_timestamp ts = DUAL_TIMESTAMP_NULL;
assert(u);
@@ -682,11 +732,14 @@ bool user_check_gc(User *u, bool drop_not_started) {
if (user_check_linger_file(u) > 0)
return true;
+/// elogind does not support systemd services and slices
+#if 0
if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
return true;
if (u->service_job && manager_job_is_active(u->manager, u->service_job))
return true;
+#endif // 0
return false;
}
@@ -709,7 +762,12 @@ UserState user_get_state(User *u) {
if (u->stopping)
return USER_CLOSING;
- if (u->slice_job || u->service_job)
+/// elogind does not support slice and service jobs
+#if 0
+ if (!u->started || u->slice_job || u->service_job)
+#else
+ if (!u->started)
+#endif // 0
return USER_OPENING;
if (u->sessions) {
@@ -737,60 +795,84 @@ UserState user_get_state(User *u) {
int user_kill(User *u, int signo) {
assert(u);
+/// FIXME: Without direct cgroup support, elogind can not kill users
+#if 0
if (!u->slice)
return -ESRCH;
return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
+#else
+ return -ESRCH;
+#endif // 0
+}
+
+static bool elect_display_filter(Session *s) {
+ /* Return true if the session is a candidate for the user’s ‘primary
+ * session’ or ‘display’. */
+ assert(s);
+
+ return (s->class == SESSION_USER && !s->stopping);
+}
+
+static int elect_display_compare(Session *s1, Session *s2) {
+ /* Indexed by SessionType. Lower numbers mean more preferred. */
+ const int type_ranks[_SESSION_TYPE_MAX] = {
+ [SESSION_UNSPECIFIED] = 0,
+ [SESSION_TTY] = -2,
+ [SESSION_X11] = -3,
+ [SESSION_WAYLAND] = -3,
+ [SESSION_MIR] = -3,
+ [SESSION_WEB] = -1,
+ };
+
+ /* Calculate the partial order relationship between s1 and s2,
+ * returning < 0 if s1 is preferred as the user’s ‘primary session’,
+ * 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
+ * is preferred.
+ *
+ * s1 or s2 may be NULL. */
+ if (!s1 && !s2)
+ return 0;
+
+ if ((s1 == NULL) != (s2 == NULL))
+ return (s1 == NULL) - (s2 == NULL);
+
+ if (s1->stopping != s2->stopping)
+ return s1->stopping - s2->stopping;
+
+ if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
+ return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
+
+ if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
+ return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
+
+ if (s1->type != s2->type)
+ return type_ranks[s1->type] - type_ranks[s2->type];
+
+ return 0;
}
void user_elect_display(User *u) {
- Session *graphical = NULL, *text = NULL, *other = NULL, *s;
+ Session *s;
assert(u);
/* This elects a primary session for each user, which we call
* the "display". We try to keep the assignment stable, but we
* "upgrade" to better choices. */
+ log_debug("Electing new display for user %s", u->name);
LIST_FOREACH(sessions_by_user, s, u->sessions) {
-
- if (s->class != SESSION_USER)
+ if (!elect_display_filter(s)) {
+ log_debug("Ignoring session %s", s->id);
continue;
+ }
- if (s->stopping)
- continue;
-
- if (SESSION_TYPE_IS_GRAPHICAL(s->type))
- graphical = s;
- else if (s->type == SESSION_TTY)
- text = s;
- else
- other = s;
- }
-
- if (graphical &&
- (!u->display ||
- u->display->class != SESSION_USER ||
- u->display->stopping ||
- !SESSION_TYPE_IS_GRAPHICAL(u->display->type))) {
- u->display = graphical;
- return;
- }
-
- if (text &&
- (!u->display ||
- u->display->class != SESSION_USER ||
- u->display->stopping ||
- u->display->type != SESSION_TTY)) {
- u->display = text;
- return;
+ if (elect_display_compare(s, u->display) < 0) {
+ log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
+ u->display = s;
+ }
}
-
- if (other &&
- (!u->display ||
- u->display->class != SESSION_USER ||
- u->display->stopping))
- u->display = other;
}
static const char* const user_state_table[_USER_STATE_MAX] = {