logind-user.c revision 49e942b2bc9fdedba79cd266a076ce9c9d91fc13
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering/***
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering This file is part of systemd.
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Copyright 2011 Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart 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
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
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 Poettering***/
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <string.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <unistd.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include <errno.h>
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "logind-user.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "mkdir.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "cgroup-util.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "hashmap.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering#include "strv.h"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart PoetteringUser* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering User *u;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(m);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u = new0(User, 1);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->name = strdup(name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u->name) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->state_file);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->manager = m;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->uid = uid;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->gid = gid;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return u;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringvoid user_free(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->in_gc_queue)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_REMOVE(User, gc_queue, u->manager->user_gc_queue, u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering while (u->sessions)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering session_free(u->sessions);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->cgroup_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->service);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->runtime_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->state_file);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint user_save(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering FILE *f;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *temp_path;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u->state_file);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u->started)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = safe_mkdir("/run/systemd/users", 0755, 0, 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering goto finish;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fchmod(fileno(f), 0644);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "# This is private data. Do not parse.\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "NAME=%s\n"
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "STATE=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->name,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering user_state_to_string(user_get_state(u)));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->cgroup_path)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "CGROUP=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->cgroup_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->runtime_path)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "RUNTIME=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->runtime_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->service)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "SERVICE=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->service);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->display)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "DISPLAY=%s\n",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->display->id);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Session *i;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fputs("SESSIONS=", f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "%s%c",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering i->id,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering i->sessions_by_user_next ? ' ' : '\n');
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fputs("SEATS=", f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (i->seat)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "%s%c",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering i->seat->id,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering i->sessions_by_user_next ? ' ' : '\n');
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fputs("ACTIVE_SESSIONS=", f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (session_is_active(i))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "%lu%c",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering (unsigned long) i->user->uid,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering i->sessions_by_user_next ? ' ' : '\n');
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fputs("ACTIVE_SEATS=", f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (session_is_active(i) && i->seat)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fprintf(f,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "%s%c",
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering i->seat->id,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering i->sessions_by_user_next ? ' ' : '\n');
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fflush(f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ferror(f) || rename(temp_path, u->state_file) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = -errno;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unlink(u->state_file);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unlink(temp_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering fclose(f);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(temp_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringfinish:
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to save user data for %s: %s", u->name, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint user_load(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *display = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Session *s = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = parse_env_file(u->state_file, NEWLINE,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "CGROUP", &u->cgroup_path,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "RUNTIME", &u->runtime_path,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "SERVICE", &u->service,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering "DISPLAY", &display,
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering NULL);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(display);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r == -ENOENT)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to read %s: %s", u->state_file, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (display) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering s = hashmap_get(u->manager->sessions, display);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(display);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (s && s->display && display_is_local(s->display))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->display = s;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_mkdir_runtime_path(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *p;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = safe_mkdir("/run/user", 0755, 0, 0);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create /run/user: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u->runtime_path) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p = strappend("/run/user/", u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!p) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Out of memory");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p = u->runtime_path;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = safe_mkdir(p, 0700, u->uid, u->gid);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create runtime directory %s: %s", p, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(p);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->runtime_path = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->runtime_path = p;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_create_cgroup(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char **k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char *p;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u->cgroup_path) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (asprintf(&p, "%s/%s", u->manager->cgroup_path, u->name) < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Out of memory");
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return -ENOMEM;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering p = u->cgroup_path;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = cg_create(SYSTEMD_CGROUP_CONTROLLER, p);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to create cgroup "SYSTEMD_CGROUP_CONTROLLER":%s: %s", p, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(p);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->cgroup_path = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->cgroup_path = p;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering STRV_FOREACH(k, u->manager->controllers) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (strv_contains(u->manager->reset_controllers, *k))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering continue;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = cg_create(*k, p);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_warning("Failed to create cgroup %s:%s: %s", *k, p, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_start_service(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* FIXME: Fill me in later ... */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint user_start(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->started)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("New user %s logged in.", u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Make XDG_RUNTIME_DIR */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = user_mkdir_runtime_path(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Create cgroup */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = user_create_cgroup(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Spawn user systemd */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = user_start_service(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dual_timestamp_get(&u->timestamp);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->started = true;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Save new user data */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering user_save(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering user_send_signal(u, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_stop_service(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u->service)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_shall_kill(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u->manager->kill_user_processes)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return false;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (strv_contains(u->manager->kill_exclude_users, u->name))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return false;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (strv_isempty(u->manager->kill_only_users))
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return true;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return strv_contains(u->manager->kill_only_users, u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_terminate_cgroup(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering char **k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u->cgroup_path)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering cg_trim(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (user_shall_kill(u)) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = cg_kill_recursive_and_wait(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to kill user cgroup: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
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 if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to delete user cgroup: %s", strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = -EBUSY;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering STRV_FOREACH(k, u->manager->controllers)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering cg_trim(*k, u->cgroup_path, true);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->cgroup_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->cgroup_path = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringstatic int user_remove_runtime_path(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!u->runtime_path)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return 0;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = rm_rf(u->runtime_path, false, true, false);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (r < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering free(u->runtime_path);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->runtime_path = NULL;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint user_stop(User *u) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Session *s;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int r = 0, k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->started)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering log_debug("User %s logged out.", u->name);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, s, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k = session_stop(s);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (k < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Kill systemd */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k = user_stop_service(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (k < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Kill cgroup */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k = user_terminate_cgroup(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (k < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering /* Kill XDG_RUNTIME_DIR */
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering k = user_remove_runtime_path(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (k < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering r = k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering unlink(u->state_file);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering user_add_to_gc_queue(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (u->started)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering user_send_signal(u, false);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering u->started = false;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return r;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering}
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poetteringint user_get_idle_hint(User *u, dual_timestamp *t) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering Session *s;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering bool idle_hint = true;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dual_timestamp ts = { 0, 0 };
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering assert(u);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering LIST_FOREACH(sessions_by_user, s, u->sessions) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering dual_timestamp k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering int ih;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering ih = session_get_idle_hint(s, &k);
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (ih < 0)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering return ih;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!ih) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (!idle_hint) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering if (k.monotonic < ts.monotonic)
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering ts = k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering idle_hint = false;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering ts = k;
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering }
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering } else if (idle_hint) {
875c2e220e2611165e09051c4747971811f1de58Lennart Poettering
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;
if (asprintf(&p, "/var/lib/systemd/linger/%s", u->name) < 0)
return -ENOMEM;
r = access(p, F_OK) >= 0;
free(p);
if (r > 0)
return 1;
if (u->cgroup_path) {
r = cg_is_empty_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, false);
if (r < 0)
return r;
if (r <= 0)
return 1;
}
return 0;
}
void user_add_to_gc_queue(User *u) {
assert(u);
if (u->in_gc_queue)
return;
LIST_PREPEND(User, gc_queue, u->manager->user_gc_queue, u);
u->in_gc_queue = true;
}
UserState user_get_state(User *u) {
Session *i;
assert(u);
if (!u->sessions)
return USER_LINGERING;
LIST_FOREACH(sessions_by_user, i, u->sessions)
if (session_is_active(i))
return USER_ACTIVE;
return USER_ONLINE;
}
int user_kill(User *u, int signo) {
int r = 0, q;
Set *pid_set = NULL;
assert(u);
if (!u->cgroup_path)
return -ESRCH;
pid_set = set_new(trivial_hash_func, trivial_compare_func);
if (!pid_set)
return -ENOMEM;
q = cg_kill_recursive(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, signo, false, true, false, pid_set);
if (q < 0)
if (q != -EAGAIN && q != -ESRCH && q != -ENOENT)
r = q;
if (pid_set)
set_free(pid_set);
return r;
}
static const char* const user_state_table[_USER_STATE_MAX] = {
[USER_OFFLINE] = "offline",
[USER_LINGERING] = "lingering",
[USER_ONLINE] = "online",
[USER_ACTIVE] = "active"
};
DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);