X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flogind-user.c;h=dacf148f7829e603c2224447408054e8cb052a58;hp=7d6df8db7a8d6989be36b4b70a44db5d6c0fc7d2;hb=69fc152fc133172433d2bacb6a1fb8b97b866e9d;hpb=d2f92cdfd0189491387069da45734816effd8cbd diff --git a/src/logind-user.c b/src/logind-user.c index 7d6df8db7..dacf148f7 100644 --- a/src/logind-user.c +++ b/src/logind-user.c @@ -45,7 +45,7 @@ User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) { return NULL; } - if (asprintf(&u->state_file, "/run/systemd/user/%lu", (unsigned long) uid) < 0) { + if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0) { free(u->name); free(u); return NULL; @@ -94,7 +94,10 @@ int user_save(User *u) { assert(u); assert(u->state_file); - r = safe_mkdir("/run/systemd/user", 0755, 0, 0); + if (!u->started) + return 0; + + r = safe_mkdir("/run/systemd/users", 0755, 0, 0); if (r < 0) goto finish; @@ -152,11 +155,11 @@ finish: int user_load(User *u) { int r; char *display = NULL; - Session *s; + Session *s = NULL; assert(u); - r = parse_env_file(u->state_file, "r", + r = parse_env_file(u->state_file, NEWLINE, "CGROUP", &u->cgroup_path, "RUNTIME", &u->runtime_path, "SERVICE", &u->service, @@ -172,10 +175,12 @@ int user_load(User *u) { return r; } - s = hashmap_get(u->manager->sessions, display); - free(display); + if (display) { + s = hashmap_get(u->manager->sessions, display); + free(display); + } - if (s && s->display && x11_display_is_local(s->display)) + if (s && s->display && display_is_local(s->display)) u->display = s; return r; @@ -232,15 +237,19 @@ static int user_create_cgroup(User *u) { r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p); if (r < 0) { + log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r)); free(p); u->cgroup_path = NULL; - log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r)); return r; } u->cgroup_path = p; STRV_FOREACH(k, u->manager->controllers) { + + if (strv_contains(u->manager->reset_controllers, *k)) + continue; + r = cg_create(*k, p); if (r < 0) log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r)); @@ -260,6 +269,11 @@ int user_start(User *u) { assert(u); + if (u->started) + return 0; + + log_info("New user %s logged in.", u->name); + /* Make XDG_RUNTIME_DIR */ r = user_mkdir_runtime_path(u); if (r < 0) @@ -275,10 +289,14 @@ int user_start(User *u) { if (r < 0) return r; + dual_timestamp_get(&u->timestamp); + + u->started = true; + /* Save new user data */ user_save(u); - dual_timestamp_get(&u->timestamp); + user_send_signal(u, true); return 0; } @@ -295,7 +313,16 @@ static int user_stop_service(User *u) { static int user_shall_kill(User *u) { assert(u); - return u->manager->kill_user_processes; + if (!u->manager->kill_user_processes) + return false; + + if (strv_contains(u->manager->kill_exclude_users, u->name)) + return false; + + if (strv_isempty(u->manager->kill_only_users)) + return true; + + return strv_contains(u->manager->kill_only_users, u->name); } static int user_kill_cgroup(User *u) { @@ -359,6 +386,9 @@ int user_stop(User *u) { int r = 0, k; assert(u); + if (u->started) + log_info("User %s logged out.", u->name); + LIST_FOREACH(sessions_by_user, s, u->sessions) { k = session_stop(s); if (k < 0) @@ -383,15 +413,59 @@ int user_stop(User *u) { unlink(u->state_file); user_add_to_gc_queue(u); + if (u->started) + user_send_signal(u, false); + + u->started = false; + return r; } -int user_check_gc(User *u) { +int user_get_idle_hint(User *u, dual_timestamp *t) { + Session *s; + bool idle_hint = true; + dual_timestamp ts = { 0, 0 }; + + assert(u); + + LIST_FOREACH(sessions_by_user, s, u->sessions) { + dual_timestamp k; + int ih; + + ih = session_get_idle_hint(s, &k); + if (ih < 0) + return ih; + + if (!ih) { + if (!idle_hint) { + if (k.monotonic < ts.monotonic) + ts = k; + } else { + idle_hint = false; + ts = k; + } + } else if (idle_hint) { + + if (k.monotonic > ts.monotonic) + ts = k; + } + } + + if (t) + *t = ts; + + return idle_hint; +} + +int user_check_gc(User *u, bool drop_not_started) { int r; char *p; assert(u); + if (drop_not_started && !u->started) + return 0; + if (u->sessions) return 1;