logind-user.c revision 90558f315844ec35e3fd4f1a19ac38c8721c9354
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2011 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart 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
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
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/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek#include <errno.h>
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek#include <string.h>
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek#include <sys/mount.h>
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek#include <unistd.h>
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "alloc-util.h"
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek#include "bus-common-errors.h"
7263f72499e962b3fd54cdb7c79d49ca72121edeZbigniew Jędrzejewski-Szmek#include "bus-error.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "bus-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "clean-ipc.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "conf-parser.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "escape.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "fd-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "fileio.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "formats-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "fs-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "hashmap.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "label.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "logind-user.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "mkdir.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "mount-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "parse-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "path-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "rm-rf.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "smack-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "special.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "stdio-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "string-table.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "unit-name.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "user-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart PoetteringUser* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering User *u;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(m);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering u = new0(User, 1);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!u)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering u->name = strdup(name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (!u->name)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (hashmap_put(m->users, UID_TO_PTR(uid), u) < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering u->manager = m;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering u->uid = uid;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering u->gid = gid;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return u;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringfail:
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->state_file);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringvoid user_free(User *u) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(u);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (u->in_gc_queue)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering while (u->sessions)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering session_free(u->sessions);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (u->slice) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering hashmap_remove(u->manager->user_units, u->slice);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->slice);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (u->service) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering hashmap_remove(u->manager->user_units, u->service);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->service);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->slice_job);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->service_job);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->runtime_path);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering hashmap_remove(u->manager->users, UID_TO_PTR(u->uid));
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->name);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u->state_file);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering free(u);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int user_save_internal(User *u) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_free_ char *temp_path = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering _cleanup_fclose_ FILE *f = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(u);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(u->state_file);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering if (r < 0)
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fchmod(fileno(f), 0644);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fprintf(f,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering "# This is private data. Do not parse.\n"
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering "NAME=%s\n"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering "STATE=%s\n",
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering u->name,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering user_state_to_string(user_get_state(u)));
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (u->runtime_path)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fprintf(f, "RUNTIME=%s\n", u->runtime_path);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (u->service)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fprintf(f, "SERVICE=%s\n", u->service);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (u->service_job)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (u->slice)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fprintf(f, "SLICE=%s\n", u->slice);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (u->slice_job)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (u->display)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fprintf(f, "DISPLAY=%s\n", u->display->id);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (dual_timestamp_is_set(&u->timestamp))
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fprintf(f,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering "REALTIME="USEC_FMT"\n"
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering "MONOTONIC="USEC_FMT"\n",
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering u->timestamp.realtime,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering u->timestamp.monotonic);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (u->sessions) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering Session *i;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering bool first;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering fputs("SESSIONS=", f);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering first = true;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (first)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering first = false;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering else
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering fputc(' ', f);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering fputs(i->id, f);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering fputs("\nSEATS=", f);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering first = true;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
23432a1c249b9c513e438bffe9778a7ce2ee74feZbigniew Jędrzejewski-Szmek if (!i->seat)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering continue;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (first)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering first = false;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering else
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering fputc(' ', f);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputs(i->seat->id, f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputs("\nACTIVE_SESSIONS=", f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering first = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!session_is_active(i))
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering continue;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (first)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering first = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering fputc(' ', f);
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering fputs(i->id, f);
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering }
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering fputs("\nONLINE_SESSIONS=", f);
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering first = true;
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering if (session_get_state(i) == SESSION_CLOSING)
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (first)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering first = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputc(' ', f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputs(i->id, f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputs("\nACTIVE_SEATS=", f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering first = true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!session_is_active(i) || !i->seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (first)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering first = false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputc(' ', f);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fputs(i->seat->id, f);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering fputs("\nONLINE_SEATS=", f);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering first = true;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (session_get_state(i) == SESSION_CLOSING || !i->seat)
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering continue;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek if (first)
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek first = false;
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poettering else
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering fputc(' ', f);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering fputs(i->seat->id, f);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek }
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering fputc('\n', f);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering }
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = fflush_and_check(f);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek if (r < 0)
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering goto fail;
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek if (rename(temp_path, u->state_file) < 0) {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = -errno;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek goto fail;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering }
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek return 0;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmekfail:
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek (void) unlink(u->state_file);
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (temp_path)
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering (void) unlink(temp_path);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering return log_error_errno(r, "Failed to save user data %s: %m", u->state_file);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering}
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmekint user_save(User *u) {
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek assert(u);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (!u->started)
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek return 0;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek return user_save_internal (u);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering}
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringint user_load(User *u) {
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering Session *s = NULL;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering int r;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert(u);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = parse_env_file(u->state_file, NEWLINE,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering "RUNTIME", &u->runtime_path,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering "SERVICE", &u->service,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering "SERVICE_JOB", &u->service_job,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering "SLICE", &u->slice,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering "SLICE_JOB", &u->slice_job,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering "DISPLAY", &display,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering "REALTIME", &realtime,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering "MONOTONIC", &monotonic,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering NULL);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r == -ENOENT)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_error_errno(r, "Failed to read %s: %m", u->state_file);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (display)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering s = hashmap_get(u->manager->sessions, display);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (s && s->display && display_is_local(s->display))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering u->display = s;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (realtime) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering unsigned long long l;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (sscanf(realtime, "%llu", &l) > 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering u->timestamp.realtime = l;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (monotonic) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering unsigned long long l;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (sscanf(monotonic, "%llu", &l) > 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering u->timestamp.monotonic = l;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering }
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poetteringstatic int user_mkdir_runtime_path(User *u) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering char *p;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering int r;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert(u);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = mkdir_safe_label("/run/user", 0755, 0, 0);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return log_error_errno(r, "Failed to create /run/user: %m");
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering if (!u->runtime_path) {
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering if (asprintf(&p, "/run/user/" UID_FMT, u->uid) < 0)
fd0b4602f6332c3f1660eb208c8f5c719709a009Lennart Poettering return log_oom();
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering } else
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering p = u->runtime_path;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (path_is_mount_point(p, 0) <= 0) {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering _cleanup_free_ char *t = NULL;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering (void) mkdir_label(p, 0700);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (mac_smack_use())
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering else
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0) {
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poettering r = log_oom();
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = mount("tmpfs", p, "tmpfs", MS_NODEV|MS_NOSUID, t);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (errno != EPERM) {
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", p);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek goto fail;
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek }
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek /* Lacking permissions, maybe
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek * CAP_SYS_ADMIN-less container? In this case,
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek * just use a normal directory. */
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek r = chmod_and_chown(p, 0700, u->uid, u->gid);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek if (r < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error_errno(r, "Failed to change runtime directory ownership and mode: %m");
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = label_fix(p, false, false);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering log_warning_errno(r, "Failed to fix label of '%s', ignoring: %m", p);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering }
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering u->runtime_path = p;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return 0;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poetteringfail:
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (p) {
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering /* Try to clean up, but ignore errors */
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering (void) rmdir(p);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering free(p);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering }
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek u->runtime_path = NULL;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek return r;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek}
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmekstatic int user_start_slice(User *u) {
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek int r;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek assert(u);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (!u->slice) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice, *job;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek const char *description;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek u->slice_job = mfree(u->slice_job);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering xsprintf(lu, UID_FMT, u->uid);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering r = slice_build_subslice(SPECIAL_USER_SLICE, lu, &slice);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering if (r < 0)
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering return log_error_errno(r, "Failed to build slice name: %m");
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering description = strjoina("User Slice of ", u->name);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek r = manager_start_slice(
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek u->manager,
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek slice,
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek description,
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek "systemd-logind.service",
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek "systemd-user-sessions.service",
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering u->manager->user_tasks_max,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering &error,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering &job);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (sd_bus_error_has_name(&error, BUS_ERROR_UNIT_EXISTS))
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek /* The slice already exists? If so, that's fine, let's just reuse it */
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek u->slice = slice;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek else {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to start user slice %s, ignoring: %s (%s)", slice, bus_error_message(&error, r), error.name);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek free(slice);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek /* we don't fail due to this, let's try to continue */
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek }
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek } else {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek u->slice = slice;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek u->slice_job = job;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek }
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek }
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (u->slice)
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek (void) hashmap_put(u->manager->user_units, u->slice, u);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return 0;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek}
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmekstatic int user_start_service(User *u) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek char *job;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek int r;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek assert(u);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (!u->service) {
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek xsprintf(lu, UID_FMT, u->uid);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek r = unit_name_build("user", lu, ".service", &service);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek return log_error_errno(r, "Failed to build service name: %m");
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = manager_start_unit(
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering u->manager,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering service,
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering &error,
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering &job);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error_errno(r, "Failed to start user service, ignoring: %s", bus_error_message(&error, r));
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering free(service);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek /* we don't fail due to this, let's try to continue */
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering } else {
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering u->service = service;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering free(u->service_job);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering u->service_job = job;
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering }
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering }
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering if (u->service)
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering (void) hashmap_put(u->manager->user_units, u->service, u);
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering
9c92ce6d67f88beb31dd6555d12ae3f632218a39Lennart Poettering return 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering}
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringint user_start(User *u) {
8ac4e9e1e54397f6d1745c2a7a806132418c7da2Lennart Poettering int r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(u);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (u->started)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_debug("New user %s logged in.", u->name);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* Make XDG_RUNTIME_DIR */
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = user_mkdir_runtime_path(u);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return r;
9de3e3294065e8697ff10130b53f274319cdcf6fZbigniew Jędrzejewski-Szmek
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek /* Create cgroup */
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek r = user_start_slice(u);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek if (r < 0)
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek return r;
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek /* Save the user data so far, because pam_systemd will read the
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek * XDG_RUNTIME_DIR out of it while starting up systemd --user.
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek * We need to do user_save_internal() because we have not
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek * "officially" started yet. */
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek user_save_internal(u);
2e276efc7b0398a3086629a52970bdd4ab7252f9Zbigniew Jędrzejewski-Szmek
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* Spawn user systemd */
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = user_start_service(u);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!dual_timestamp_is_set(&u->timestamp))
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering dual_timestamp_get(&u->timestamp);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering u->started = true;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* Save new user data */
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering user_save(u);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek user_send_signal(u, true);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering}
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmekstatic int user_stop_slice(User *u) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering char *job;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int r;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(u);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!u->slice)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = manager_stop_unit(u->manager, u->slice, &error, &job);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering free(u->slice_job);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering u->slice_job = job;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek return r;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek}
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmekstatic int user_stop_service(User *u) {
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek char *job;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek int r;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek assert(u);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek if (!u->service)
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return 0;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek r = manager_stop_unit(u->manager, u->service, &error, &job);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek if (r < 0) {
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek log_error("Failed to stop user service: %s", bus_error_message(&error, r));
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek return r;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek }
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek free(u->service_job);
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek u->service_job = job;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek return r;
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek}
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmek
0dae31d468b1a0e22d98921f7b0dbd92fd217167Zbigniew Jędrzejewski-Szmekstatic int user_remove_runtime_path(User *u) {
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek int r;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek assert(u);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering if (!u->runtime_path)
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering return 0;
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering r = rm_rf(u->runtime_path, 0);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering if (r < 0)
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering /* Ignore cases where the directory isn't mounted, as that's
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering * quite possible, if we lacked the permissions to mount
42cc2eebb01056beb7acd3ecfe8e533558237f84Lennart Poettering * something */
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmek r = umount2(u->runtime_path, MNT_DETACH);
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmek if (r < 0 && errno != EINVAL && errno != ENOENT)
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmek log_error_errno(errno, "Failed to unmount user runtime directory %s: %m", u->runtime_path);
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmek
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmek r = rm_rf(u->runtime_path, REMOVE_ROOT);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek if (r < 0)
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek log_error_errno(r, "Failed to remove runtime directory %s: %m", u->runtime_path);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering u->runtime_path = mfree(u->runtime_path);
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmek
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek return r;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek}
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmek
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmekint user_stop(User *u, bool force) {
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek Session *s;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek int r = 0, k;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(u);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
ff3d6560bead6879a2fed1bf99bfe8273b3723f1Zbigniew Jędrzejewski-Szmek /* Stop jobs have already been queued */
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (u->stopping) {
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek user_save(u);
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek return r;
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek }
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek LIST_FOREACH(sessions_by_user, s, u->sessions) {
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek k = session_stop(s, force);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (k < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = k;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
8db0d2f5c37e7e8f5bfce016cfdad7947a3ea939Zbigniew Jędrzejewski-Szmek
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* Kill systemd */
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering k = user_stop_service(u);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (k < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = k;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* Kill cgroup */
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering k = user_stop_slice(u);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (k < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = k;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering u->stopping = true;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering user_save(u);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return r;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering}
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poetteringint user_finalize(User *u) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering Session *s;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int r = 0, k;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(u);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (u->started)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering log_debug("User %s logged out.", u->name);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering LIST_FOREACH(sessions_by_user, s, u->sessions) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering k = session_finalize(s);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (k < 0)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = k;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
/* Kill XDG_RUNTIME_DIR */
k = user_remove_runtime_path(u);
if (k < 0)
r = k;
/* Clean SysV + POSIX IPC objects */
if (u->manager->remove_ipc) {
k = clean_ipc(u->uid);
if (k < 0)
r = k;
}
unlink(u->state_file);
user_add_to_gc_queue(u);
if (u->started) {
user_send_signal(u, false);
u->started = false;
}
return r;
}
int user_get_idle_hint(User *u, dual_timestamp *t) {
Session *s;
bool idle_hint = true;
dual_timestamp ts = DUAL_TIMESTAMP_NULL;
assert(u);
LIST_FOREACH(sessions_by_user, s, u->sessions) {
dual_timestamp k;
int ih;
ih = session_get_idle_hint(s, &k);
if (ih < 0)
return ih;
if (!ih) {
if (!idle_hint) {
if (k.monotonic < ts.monotonic)
ts = k;
} else {
idle_hint = false;
ts = k;
}
} else if (idle_hint) {
if (k.monotonic > ts.monotonic)
ts = k;
}
}
if (t)
*t = ts;
return idle_hint;
}
int user_check_linger_file(User *u) {
_cleanup_free_ char *cc = NULL;
char *p = NULL;
cc = cescape(u->name);
if (!cc)
return -ENOMEM;
p = strjoina("/var/lib/systemd/linger/", cc);
return access(p, F_OK) >= 0;
}
bool user_check_gc(User *u, bool drop_not_started) {
assert(u);
if (drop_not_started && !u->started)
return false;
if (u->sessions)
return true;
if (user_check_linger_file(u) > 0)
return true;
if (u->slice_job && manager_job_is_active(u->manager, u->slice_job))
return true;
if (u->service_job && manager_job_is_active(u->manager, u->service_job))
return true;
return false;
}
void user_add_to_gc_queue(User *u) {
assert(u);
if (u->in_gc_queue)
return;
LIST_PREPEND(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->stopping)
return USER_CLOSING;
if (!u->started || u->slice_job || u->service_job)
return USER_OPENING;
if (u->sessions) {
bool all_closing = true;
LIST_FOREACH(sessions_by_user, i, u->sessions) {
SessionState state;
state = session_get_state(i);
if (state == SESSION_ACTIVE)
return USER_ACTIVE;
if (state != SESSION_CLOSING)
all_closing = false;
}
return all_closing ? USER_CLOSING : USER_ONLINE;
}
if (user_check_linger_file(u) > 0)
return USER_LINGERING;
return USER_CLOSING;
}
int user_kill(User *u, int signo) {
assert(u);
if (!u->slice)
return -ESRCH;
return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
}
static bool elect_display_filter(Session *s) {
/* Return true if the session is a candidate for the user’s ‘primary
* session’ or ‘display’. */
assert(s);
return (s->class == SESSION_USER && !s->stopping);
}
static int elect_display_compare(Session *s1, Session *s2) {
/* Indexed by SessionType. Lower numbers mean more preferred. */
const int type_ranks[_SESSION_TYPE_MAX] = {
[SESSION_UNSPECIFIED] = 0,
[SESSION_TTY] = -2,
[SESSION_X11] = -3,
[SESSION_WAYLAND] = -3,
[SESSION_MIR] = -3,
[SESSION_WEB] = -1,
};
/* Calculate the partial order relationship between s1 and s2,
* returning < 0 if s1 is preferred as the user’s ‘primary session’,
* 0 if s1 and s2 are equally preferred or incomparable, or > 0 if s2
* is preferred.
*
* s1 or s2 may be NULL. */
if (!s1 && !s2)
return 0;
if ((s1 == NULL) != (s2 == NULL))
return (s1 == NULL) - (s2 == NULL);
if (s1->stopping != s2->stopping)
return s1->stopping - s2->stopping;
if ((s1->class != SESSION_USER) != (s2->class != SESSION_USER))
return (s1->class != SESSION_USER) - (s2->class != SESSION_USER);
if ((s1->type == _SESSION_TYPE_INVALID) != (s2->type == _SESSION_TYPE_INVALID))
return (s1->type == _SESSION_TYPE_INVALID) - (s2->type == _SESSION_TYPE_INVALID);
if (s1->type != s2->type)
return type_ranks[s1->type] - type_ranks[s2->type];
return 0;
}
void user_elect_display(User *u) {
Session *s;
assert(u);
/* This elects a primary session for each user, which we call
* the "display". We try to keep the assignment stable, but we
* "upgrade" to better choices. */
log_debug("Electing new display for user %s", u->name);
LIST_FOREACH(sessions_by_user, s, u->sessions) {
if (!elect_display_filter(s)) {
log_debug("Ignoring session %s", s->id);
continue;
}
if (elect_display_compare(s, u->display) < 0) {
log_debug("Choosing session %s in preference to %s", s->id, u->display ? u->display->id : "-");
u->display = s;
}
}
}
static const char* const user_state_table[_USER_STATE_MAX] = {
[USER_OFFLINE] = "offline",
[USER_OPENING] = "opening",
[USER_LINGERING] = "lingering",
[USER_ONLINE] = "online",
[USER_ACTIVE] = "active",
[USER_CLOSING] = "closing"
};
DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);
int config_parse_tmpfs_size(
const char* unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
size_t *sz = data;
const char *e;
int r;
assert(filename);
assert(lvalue);
assert(rvalue);
assert(data);
e = endswith(rvalue, "%");
if (e) {
unsigned long ul;
char *f;
errno = 0;
ul = strtoul(rvalue, &f, 10);
if (errno != 0 || f != e) {
log_syntax(unit, LOG_ERR, filename, line, errno, "Failed to parse percentage value, ignoring: %s", rvalue);
return 0;
}
if (ul <= 0 || ul >= 100) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Percentage value out of range, ignoring: %s", rvalue);
return 0;
}
*sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100));
} else {
uint64_t k;
r = parse_size(rvalue, 1024, &k);
if (r < 0 || (uint64_t) (size_t) k != k) {
log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse size value, ignoring: %s", rvalue);
return 0;
}
*sz = PAGE_ALIGN((size_t) k);
}
return 0;
}