diff options
-rw-r--r-- | src/login/logind-dbus.c | 18 | ||||
-rw-r--r-- | src/login/logind-session-dbus.c | 3 | ||||
-rw-r--r-- | src/login/logind-session.c | 43 | ||||
-rw-r--r-- | src/login/logind-session.h | 4 | ||||
-rw-r--r-- | src/login/logind-user.c | 184 | ||||
-rw-r--r-- | src/login/logind-user.h | 6 | ||||
-rw-r--r-- | src/login/logind.h | 14 |
7 files changed, 210 insertions, 62 deletions
diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index fdf95fc50..31580af52 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -821,6 +821,15 @@ static int method_create_session(sd_bus_message *message, void *userdata, sd_bus * created. We send the reply back from * session_send_create_reply(). */ + /* Elogind note: replying directly, since we're not actually + starting slices and thus we aren't waiting on systemd. */ + + r = session_send_create_reply(session, NULL); + if (r < 0) + goto fail; + + session_save(session); + return 1; fail: @@ -2568,8 +2577,11 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err session = hashmap_get(m->session_units, unit); if (session) { +/// elogind does not support scope jobs +#if 0 if (streq_ptr(path, session->scope_job)) session->scope_job = mfree(session->scope_job); +#endif // 0 session_jobs_reply(session, unit, result); @@ -2580,11 +2592,14 @@ int match_job_removed(sd_bus_message *message, void *userdata, sd_bus_error *err user = hashmap_get(m->user_units, unit); if (user) { +/// elogind does not support slice and service jobs +#if 0 if (streq_ptr(path, user->service_job)) user->service_job = mfree(user->service_job); if (streq_ptr(path, user->slice_job)) user->slice_job = mfree(user->slice_job); +#endif // 0 LIST_FOREACH(sessions_by_user, session, user->sessions) session_jobs_reply(session, unit, result); @@ -2698,6 +2713,8 @@ int manager_send_changed(Manager *manager, const char *property, ...) { l); } +/// UNNEEDED by elogind +#if 0 int manager_start_scope( Manager *manager, const char *scope, @@ -3015,3 +3032,4 @@ int manager_job_is_active(Manager *manager, const char *path) { return true; } +#endif // diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index e6b4ccd7c..b0db8e2cc 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -704,8 +704,11 @@ int session_send_create_reply(Session *s, sd_bus_error *error) { if (!s->create_message) return 0; +/// elogind does not support scope and service jobs +#if 0 if (!sd_bus_error_is_set(error) && (s->scope_job || s->user->service_job)) return 0; +#endif // 0 c = s->create_message; s->create_message = NULL; diff --git a/src/login/logind-session.c b/src/login/logind-session.c index a277cda48..1a3567194 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -125,7 +125,10 @@ void session_free(Session *s) { free(s->scope); } +/// elogind does not support systemd scope_jobs +#if 0 free(s->scope_job); +#endif // 0 sd_bus_message_unref(s->create_message); @@ -196,8 +199,11 @@ int session_save(Session *s) { if (s->scope) fprintf(f, "SCOPE=%s\n", s->scope); +/// elogind does not support systemd scope_jobs +#if 0 if (s->scope_job) fprintf(f, "SCOPE_JOB=%s\n", s->scope_job); +#endif // 0 if (s->fifo_path) fprintf(f, "FIFO=%s\n", s->fifo_path); @@ -324,7 +330,10 @@ int session_load(Session *s) { r = parse_env_file(s->state_file, NEWLINE, "REMOTE", &remote, "SCOPE", &s->scope, +/// elogind does not support systemd scope_jobs +#if 0 "SCOPE_JOB", &s->scope_job, +#endif // 0 "FIFO", &s->fifo_path, "SEAT", &seat, "TTY", &s->tty, @@ -500,7 +509,7 @@ int session_activate(Session *s) { } static int session_start_scope(Session *s) { - int r; + int r = 0; assert(s); assert(s->user); @@ -509,7 +518,7 @@ static int session_start_scope(Session *s) { if (!s->scope) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_free_ char *description = NULL; - char *scope, *job = NULL; + char *scope = NULL; //, *job = NULL; description = strjoin("Session ", s->id, " of user ", s->user->name, NULL); if (!description) @@ -519,7 +528,10 @@ static int session_start_scope(Session *s) { if (!scope) return log_oom(); +/// elogind : Do not try to use dbus to call systemd +#if 0 r = manager_start_scope(s->manager, scope, s->leader, s->user->slice, description, "logind.service", "systemd-user-sessions.service", &error, &job); +#endif // 0 if (r < 0) { log_error("Failed to start session scope %s: %s %s", scope, bus_error_message(&error, r), error.name); @@ -527,9 +539,11 @@ static int session_start_scope(Session *s) { return r; } else { s->scope = scope; - +/// elogind does not support scope jobs +#if 0 free(s->scope_job); s->scope_job = job; +#endif // 0 } } @@ -596,6 +610,8 @@ int session_start(Session *s) { return 0; } +/// UNNEEDED by elogind +#if 0 static int session_stop_scope(Session *s, bool force) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; char *job = NULL; @@ -625,9 +641,10 @@ static int session_stop_scope(Session *s, bool force) { return 0; } +#endif // 0 int session_stop(Session *s, bool force) { - int r; + int r = 0; assert(s); @@ -643,7 +660,12 @@ int session_stop(Session *s, bool force) { session_remove_fifo(s); /* Kill cgroup */ +/// @todo : Currently elogind does not start scopes. It remains to be seen +/// whether this is really not needed, but then, elogind is not a +/// systemd cgroups manager. +#if 0 r = session_stop_scope(s, force); +#endif // 0 s->stopping = true; @@ -932,11 +954,14 @@ bool session_check_gc(Session *s, bool drop_not_started) { return true; } +/// elogind supports neither scopes nor jobs +#if 0 if (s->scope_job && manager_job_is_active(s->manager, s->scope_job)) return true; if (s->scope && manager_unit_is_active(s->manager, s->scope)) return true; +#endif // 0 return false; } @@ -958,7 +983,12 @@ SessionState session_get_state(Session *s) { if (s->stopping || s->timer_event_source) return SESSION_CLOSING; +/// elogind does not support systemd scope_jobs +#if 0 if (s->scope_job || s->fifo_fd < 0) +#else + if (s->fifo_fd < 0) +#endif // 0 return SESSION_OPENING; if (session_is_active(s)) @@ -970,10 +1000,15 @@ SessionState session_get_state(Session *s) { int session_kill(Session *s, KillWho who, int signo) { assert(s); +/// FIXME: Without direct cgroup support, elogind can not kill sessions +#if 0 if (!s->scope) return -ESRCH; return manager_kill_unit(s->manager, s->scope, who, signo, NULL); +#else + return -ESRCH; +#endif // 0 } static int session_open_vt(Session *s) { diff --git a/src/login/logind-session.h b/src/login/logind-session.h index d054c33ce..202446833 100644 --- a/src/login/logind-session.h +++ b/src/login/logind-session.h @@ -89,8 +89,12 @@ struct Session { char *service; char *desktop; + /* always NULL */ char *scope; +/// UNNEEDED (and unsupported) by elogind +#if 0 char *scope_job; +#endif // 0 Seat *seat; unsigned int vtnr; 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] = { diff --git a/src/login/logind-user.h b/src/login/logind-user.h index 722247806..b30e7d60c 100644 --- a/src/login/logind-user.h +++ b/src/login/logind-user.h @@ -47,11 +47,17 @@ struct User { 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 *service; char *slice; +/// UNNEEDED (and unsupported) by elogind +#if 0 char *service_job; char *slice_job; +#endif // 0 Session *display; diff --git a/src/login/logind.h b/src/login/logind.h index c0ae52359..a74a3e483 100644 --- a/src/login/logind.h +++ b/src/login/logind.h @@ -185,13 +185,13 @@ int bus_manager_shutdown_or_sleep_now_or_later(Manager *m, const char *unit_name int manager_send_changed(Manager *manager, const char *property, ...) _sentinel_; -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_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); -int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error); -int manager_unit_is_active(Manager *manager, const char *unit); -int manager_job_is_active(Manager *manager, const char *path); +// UNNEEDED 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); +// UNNEEDED int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); +// UNNEEDED int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job); +// UNNEEDED int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error); +// UNNEEDED int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error); +// UNNEEDED int manager_unit_is_active(Manager *manager, const char *unit); +// UNNEEDED int manager_job_is_active(Manager *manager, const char *path); /* gperf lookup function */ const struct ConfigPerfItem* logind_gperf_lookup(const char *key, GPERF_LEN_TYPE length); |