logind-user.c revision 49e942b2bc9fdedba79cd266a076ce9c9d91fc13
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 General Public License as published by
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering the Free Software Foundation; either version 2 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 General Public License for more details.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering You should have received a copy of the GNU 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->users, ULONG_TO_PTR((unsigned long) u->uid));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = safe_mkdir("/run/systemd/users", 0755, 0, 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "# This is private data. Do not parse.\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering user_state_to_string(user_get_state(u)));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "CGROUP=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "RUNTIME=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "SERVICE=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "DISPLAY=%s\n",
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 (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 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 Poetteringstatic int user_mkdir_runtime_path(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create /run/user: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create runtime directory %s: %s", p, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering STRV_FOREACH(k, u->manager->controllers) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (strv_contains(u->manager->reset_controllers, *k))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* FIXME: Fill me in later ... */
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 /* Save new user data */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (strv_contains(u->manager->kill_exclude_users, u->name))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (strv_isempty(u->manager->kill_only_users))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return strv_contains(u->manager->kill_only_users, u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_terminate_cgroup(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering cg_trim(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to kill user cgroup: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to check user cgroup: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering else if (r > 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = cg_delete(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to delete user cgroup: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart 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 */
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint user_get_idle_hint(User *u, dual_timestamp *t) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, s, u->sessions) {
ts = k;
*t = ts;
return idle_hint;
assert(u);
if (u->sessions)
return -ENOMEM;
free(p);
if (u->cgroup_path) {
assert(u);
if (u->in_gc_queue)
u->in_gc_queue = true;
Session *i;
assert(u);
if (!u->sessions)
return USER_LINGERING;
if (session_is_active(i))
return USER_ACTIVE;
return USER_ONLINE;
assert(u);
if (!u->cgroup_path)
return -ESRCH;
if (!pid_set)
return -ENOMEM;
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
if (pid_set)