logind-user.c revision d0af76e68a5bab2e4fd9674b1c64a9f38d7afe97
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering This file is part of systemd.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Copyright 2011 Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is free software; you can redistribute it and/or modify it
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering under the terms of the GNU Lesser General Public License as published by
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (at your option) any later version.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering systemd is distributed in the hope that it will be useful, but
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Lesser General Public License for more details.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering You should have received a copy of the GNU Lesser General Public License
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringUser* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_REMOVE(User, gc_queue, u->manager->user_gc_queue, u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering hashmap_remove(u->manager->user_units, u->slice);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering hashmap_remove(u->manager->user_units, u->service);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering "# This is private data. Do not parse.\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering user_state_to_string(user_get_state(u)));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f, "RUNTIME=%s\n", u->runtime_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f, "DISPLAY=%s\n", u->display->id);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (dual_timestamp_is_set(&u->timestamp))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "REALTIME=%llu\n"
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering "MONOTONIC=%llu\n",
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering (unsigned long long) u->timestamp.realtime,
78fe420ff0bb4cd94de3c4d3f15a3021cc3e2878Lennart Poettering (unsigned long long) u->timestamp.monotonic);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (session_get_state(i) == SESSION_CLOSING)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (session_get_state(i) == SESSION_CLOSING || !i->seat)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ferror(f) || rename(temp_path, u->state_file) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to save user data for %s: %s", u->name, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = parse_env_file(u->state_file, NEWLINE,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to read %s: %s", u->state_file, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering s = hashmap_get(u->manager->sessions, display);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (s && s->display && display_is_local(s->display))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned long long l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unsigned long long l;
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_mkdir_runtime_path(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = mkdir_safe_label("/run/user", 0755, 0, 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create /run/user: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = mkdir_safe_label(p, 0700, u->uid, u->gid);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create runtime directory %s: %s", p, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char lu[DECIMAL_STR_MAX(unsigned long) + 1], *slice;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sprintf(lu, "%lu", (unsigned long) u->uid);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = build_subslice(SPECIAL_USER_SLICE, lu, &slice);
25b3245fb483e52766867dfe33ce271011caaca9Lennart Poettering r = manager_start_unit(u->manager, slice, &error, &job);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to start user slice: %s", bus_error(&error, r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering hashmap_put(u->manager->user_units, u->slice, u);
5034c7bcdfc4493ed3c30722e9d897c8da78fedeLennart Poettering char lu[DECIMAL_STR_MAX(unsigned long) + 1], *service;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering sprintf(lu, "%lu", (unsigned long) u->uid);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering service = unit_name_build("user", lu, ".service");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = manager_start_unit(u->manager, service, &error, &job);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to start user service: %s", bus_error(&error, r));
124aff6251c095367ce1323a21fa23235cbb0490Lennart Poettering hashmap_put(u->manager->user_units, u->service, u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("New user %s logged in.", u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Make XDG_RUNTIME_DIR */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Create cgroup */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Spawn user systemd */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!dual_timestamp_is_set(&u->timestamp))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Save new user data */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = manager_stop_unit(u->manager, u->slice, &error, &job);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to stop user slice: %s", bus_error(&error, r));
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering r = manager_stop_unit(u->manager, u->service, &error, &job);
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering log_error("Failed to stop user service: %s", bus_error(&error, r));
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* static int user_shall_kill(User *u) { */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* assert(u); */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* if (!u->manager->kill_user_processes) */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* return false; */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* if (strv_contains(u->manager->kill_exclude_users, u->name)) */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* return false; */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* if (strv_isempty(u->manager->kill_only_users)) */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* return true; */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poettering/* return strv_contains(u->manager->kill_only_users, u->name); */
4d9ced9956755901238fede6fc5a3d7e4e816aa6Lennart Poetteringstatic int user_remove_runtime_path(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = rm_rf(u->runtime_path, false, true, false);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("User %s logged out.", u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, s, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Kill systemd */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Kill cgroup */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Kill XDG_RUNTIME_DIR */
Session *s;
bool idle_hint = true;
assert(u);
int ih;
if (ih < 0)
return ih;
if (!ih) {
if (!idle_hint) {
ts = k;
idle_hint = false;
ts = k;
} else if (idle_hint) {
ts = k;
*t = ts;
return idle_hint;
return -ENOMEM;
free(p);
assert(u);
if (u->sessions)
if (user_check_linger_file(u) > 0)
assert(u);
if (u->in_gc_queue)
u->in_gc_queue = true;
Session *i;
bool all_closing = true;
assert(u);
if (session_is_active(i))
return USER_ACTIVE;
all_closing = false;
if (u->sessions)
if (user_check_linger_file(u) > 0)
return USER_LINGERING;
return USER_CLOSING;
assert(u);
if (!u->slice)
return -ESRCH;