logind-user.c revision 129eebe020118fc1bf0274c9ea75ffb6178a280f
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2011 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
091a364c802e34a58f3260c9cb5db9b75c62215cTom GundersenUser* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_REMOVE(User, gc_queue, u->manager->user_gc_queue, u);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = safe_mkdir("/run/systemd/users", 0755, 0, 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "# This is private data. Do not parse.\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering user_state_to_string(user_get_state(u)));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "CGROUP=%s\n",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "RUNTIME=%s\n",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "SERVICE=%s\n",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "DISPLAY=%s\n",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (ferror(f) || rename(temp_path, u->state_file) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to save user data for %s: %s", u->name, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = parse_env_file(u->state_file, NEWLINE,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to read %s: %s", u->state_file, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = hashmap_get(u->manager->sessions, display);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (s && s->display && display_is_local(s->display))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int user_mkdir_runtime_path(User *u) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to create /run/user: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to create runtime directory %s: %s", p, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering STRV_FOREACH(k, u->manager->controllers) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (strv_contains(u->manager->reset_controllers, *k))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* FIXME: Fill me in later ... */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_debug("New user %s logged in.", u->name);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* Make XDG_RUNTIME_DIR */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* Create cgroup */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* Spawn user systemd */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering /* Save new user data */
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (strv_contains(u->manager->kill_exclude_users, u->name))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (strv_isempty(u->manager->kill_only_users))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return strv_contains(u->manager->kill_only_users, u->name);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int user_terminate_cgroup(User *u) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering cg_trim(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_error("Failed to kill user cgroup: %s", strerror(-r));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_error("Failed to check user cgroup: %s", strerror(-r));
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering else if (r > 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering log_error("Failed to delete user cgroup: %s", strerror(-r));
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poetteringstatic int user_remove_runtime_path(User *u) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering r = rm_rf(u->runtime_path, false, true, false);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering log_debug("User %s logged out.", u->name);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering LIST_FOREACH(sessions_by_user, s, u->sessions) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering /* Kill systemd */
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering /* Kill cgroup */
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering /* Kill XDG_RUNTIME_DIR */
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint user_get_idle_hint(User *u, dual_timestamp *t) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen LIST_FOREACH(sessions_by_user, s, u->sessions) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint user_check_gc(User *u, bool drop_not_started) {
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (asprintf(&p, "/var/lib/systemd/linger/%s", u->name) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen LIST_PREPEND(User, gc_queue, u->manager->user_gc_queue, u);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid_set = set_new(trivial_hash_func, trivial_compare_func);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poetteringstatic const char* const user_state_table[_USER_STATE_MAX] = {