logind-user.c revision c9caad802128a5dc599342c1400a61f31e8b17b5
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2011 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
d7671a3efdaef690b4316a03011038f731f2eea9Zbigniew Jędrzejewski-SzmekUser* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0) {
36d9205d669bcdcb04fa730d1f3549a9fc9a9001Tom Gundersen if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0) {
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering LIST_REMOVE(User, gc_queue, u->manager->user_gc_queue, u);
58db254ade4fb2ef77de68f28c4f13814819f6a1Lennart Poettering hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "# This is private data. Do not parse.\n"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering user_state_to_string(user_get_state(u)));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "CGROUP=%s\n",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "RUNTIME=%s\n",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "SERVICE=%s\n",
1b4f6e79ec51a57003896a0b605fba427b4a98d2Lennart Poettering "DISPLAY=%s\n",
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering if (ferror(f) || rename(temp_path, u->state_file) < 0) {
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering log_error("Failed to save user data for %s: %s", u->name, strerror(-r));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = parse_env_file(u->state_file, NEWLINE,
5d27351f8546530cf779847b0b04b0172c09f9d0Tom Gundersen log_error("Failed to read %s: %s", u->state_file, strerror(-r));
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering s = hashmap_get(u->manager->sessions, display);
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering if (s && s->display && display_is_local(s->display))
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poetteringstatic int user_mkdir_runtime_path(User *u) {
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering r = mkdir_safe_label("/run/user", 0755, 0, 0);
547973dea7abd6c124ff6c79fe2bbe322a7314aeLennart Poettering log_error("Failed to create /run/user: %s", strerror(-r));
547973dea7abd6c124ff6c79fe2bbe322a7314aeLennart Poettering if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0)
801ad6a6a9cd8fbd58b9f9c27f20dbb3c87d47ddLennart Poettering r = mkdir_safe_label(p, 0700, u->uid, u->gid);
547973dea7abd6c124ff6c79fe2bbe322a7314aeLennart Poettering log_error("Failed to create runtime directory %s: %s", p, strerror(-r));
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering STRV_FOREACH(k, u->manager->controllers) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (strv_contains(u->manager->reset_controllers, *k))
d5099efc47d4e6ac60816b5381a5f607ab03f06eMichal Schmidt log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r));
f2af5ea3cbf54998ed41d2d21a3448abb92ca7ffLennart Poettering hashmap_put(u->manager->user_cgroups, u->cgroup_path, u);
d23a27a964748967e1ad20e86de869a753af555bTom Gundersen /* FIXME: Fill me in later ... */
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_debug("New user %s logged in.", u->name);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* Make XDG_RUNTIME_DIR */
f57e3cd5fa709ec0f52531eccba909ac0851927cLennart Poettering /* Create cgroup */
f57e3cd5fa709ec0f52531eccba909ac0851927cLennart Poettering /* Spawn user systemd */
f57e3cd5fa709ec0f52531eccba909ac0851927cLennart Poettering /* Save new user data */
f57e3cd5fa709ec0f52531eccba909ac0851927cLennart Poettering if (strv_contains(u->manager->kill_exclude_users, u->name))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (strv_isempty(u->manager->kill_only_users))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return strv_contains(u->manager->kill_only_users, u->name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int user_terminate_cgroup(User *u) {
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering cg_trim(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering log_error("Failed to kill user cgroup: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to check user cgroup: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (r > 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to delete user cgroup: %s", strerror(-r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering hashmap_remove(u->manager->user_cgroups, u->cgroup_path);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poetteringstatic int user_remove_runtime_path(User *u) {
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poettering r = rm_rf(u->runtime_path, false, true, false);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering log_debug("User %s logged out.", u->name);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering LIST_FOREACH(sessions_by_user, s, u->sessions) {
abf126a355e2f2b62b6c51ab3bb37895d1e3eee7Tom Gundersen /* Kill systemd */
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering /* Kill cgroup */
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek /* Kill XDG_RUNTIME_DIR */
151226ab4bf276d60d51864330a99f886b923697Zbigniew Jędrzejewski-Szmek k = user_remove_runtime_path(u);
5d45a8808431987c370706d365fb0cc95cf03d52Tom Gundersenint user_get_idle_hint(User *u, dual_timestamp *t) {
48d45d2b49d2adb870cd5f1bc7cb389b33655f1cZbigniew Jędrzejewski-Szmek LIST_FOREACH(sessions_by_user, s, u->sessions) {
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek ih = session_get_idle_hint(s, &k);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int user_check_linger_file(User *u) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (asprintf(&p, "/var/lib/systemd/linger/%s", u->name) < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringint user_check_gc(User *u, bool drop_not_started) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering LIST_PREPEND(User, gc_queue, u->manager->user_gc_queue, u);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
4d247a6cd3f69acbc5a09e8ac7e4fbb50eaa3228Lennart Poettering if (session_get_state(i) != SESSION_CLOSING)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return all_closing ? USER_CLOSING : USER_ONLINE;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering pid_set = set_new(trivial_hash_func, trivial_compare_func);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringstatic const char* const user_state_table[_USER_STATE_MAX] = {