logind-user.c revision 6baa7db00812437bbc87e73faa1a11b6cf631958
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/***
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2011 Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is free software; you can redistribute it and/or modify it
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering under the terms of the GNU Lesser General Public License as published by
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering (at your option) any later version.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering systemd is distributed in the hope that it will be useful, but
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Lesser General Public License for more details.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering You should have received a copy of the GNU Lesser General Public License
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
4871690d9e32608bbd9b18505b5326c2079c9690Allin Cottrell***/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <sys/mount.h>
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering#include <string.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <unistd.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <errno.h>
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "mkdir.h"
afc5dbf37fd2399d37976388d9dd9ab470ecf446Lennart Poettering#include "hashmap.h"
3b7124a8db56ed57525b9ecfd19cfdc8c9facba0Lennart Poettering#include "strv.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "fileio.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "path-util.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "special.h"
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen#include "unit-name.h"
0b452006de98294d1690f045f6ea2f7f6630ec3bRonny Chevalier#include "bus-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "bus-error.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "conf-parser.h"
15a5e95075a7f6007dd97b2a165c8ed16fe683dfLennart Poettering#include "clean-ipc.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "logind-user.h"
7ccbd1ae843d77275f2c542582a9a80e5e058a70Lennart Poettering#include "smack-util.h"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart PoetteringUser* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering User *u;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering assert(m);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek assert(name);
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek u = new0(User, 1);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek if (!u)
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek return NULL;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek u->name = strdup(name);
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek if (!u->name)
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering goto fail;
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek
f8294e4175918117ca6c131720bcf287eadcd029Josh Triplett if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->manager = m;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->uid = uid;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->gid = gid;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return u;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringfail:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->state_file);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->name);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringvoid user_free(User *u) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->in_gc_queue)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering while (u->sessions)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering session_free(u->sessions);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->slice) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering hashmap_remove(u->manager->user_units, u->slice);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->slice);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (u->service) {
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering hashmap_remove(u->manager->user_units, u->service);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->service);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler free(u->slice_job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->service_job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->runtime_path);
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->name);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->state_file);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering}
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint user_save(User *u) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ char *temp_path = NULL;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering _cleanup_fclose_ FILE *f = NULL;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering assert(u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering assert(u->state_file);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!u->started)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto finish;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto finish;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fchmod(fileno(f), 0644);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "# This is private data. Do not parse.\n"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "NAME=%s\n"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "STATE=%s\n",
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering u->name,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering user_state_to_string(user_get_state(u)));
3b97fcbd28f92a1e51887fef5de8844a89bde523Lennart Poettering
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek if (u->runtime_path)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "RUNTIME=%s\n", u->runtime_path);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->service)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "SERVICE=%s\n", u->service);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->service_job)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->slice)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "SLICE=%s\n", u->slice);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->slice_job)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->display)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "DISPLAY=%s\n", u->display->id);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (dual_timestamp_is_set(&u->timestamp))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "REALTIME="USEC_FMT"\n"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "MONOTONIC="USEC_FMT"\n",
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->timestamp.realtime,
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->timestamp.monotonic);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Session *i;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering bool first;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs("SESSIONS=", f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = true;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (first)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = false;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputc(' ', f);
5ffa8c818120e35c89becd938d160235c069dd12Zbigniew Jędrzejewski-Szmek
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs(i->id, f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs("\nSEATS=", f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = true;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!i->seat)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering continue;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (first)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = false;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputc(' ', f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs(i->seat->id, f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs("\nACTIVE_SESSIONS=", f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = true;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!session_is_active(i))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering continue;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (first)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = false;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek fputc(' ', f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs(i->id, f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs("\nONLINE_SESSIONS=", f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = true;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (session_get_state(i) == SESSION_CLOSING)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering continue;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (first)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = false;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputc(' ', f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek fputs(i->id, f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs("\nACTIVE_SEATS=", f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = true;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!session_is_active(i) || !i->seat)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering continue;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (first)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = false;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputc(' ', f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs(i->seat->id, f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs("\nONLINE_SEATS=", f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = true;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (session_get_state(i) == SESSION_CLOSING || !i->seat)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering continue;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (first)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering first = false;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputc(' ', f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fputs(i->seat->id, f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8Filipe Brandenburger fputc('\n', f);
ec5ff4445cca6a1d786b8da36cf6fe0acc0b94c8Filipe Brandenburger }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
e88baee88fad8bc59d33b55a7a2d640ef9e16cd6Zbigniew Jędrzejewski-Szmek fflush(f);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (ferror(f) || rename(temp_path, u->state_file) < 0) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = -errno;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering unlink(u->state_file);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering unlink(temp_path);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringfinish:
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering log_error("Failed to save user data %s: %s", u->state_file, strerror(-r));
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering}
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringint user_load(User *u) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering Session *s = NULL;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering int r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(u);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = parse_env_file(u->state_file, NEWLINE,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering "RUNTIME", &u->runtime_path,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering "SERVICE", &u->service,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering "SERVICE_JOB", &u->service_job,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering "SLICE", &u->slice,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering "SLICE_JOB", &u->slice_job,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering "DISPLAY", &display,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering "REALTIME", &realtime,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering "MONOTONIC", &monotonic,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering NULL);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r == -ENOENT)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return 0;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering log_error("Failed to read %s: %s", u->state_file, strerror(-r));
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (display)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering s = hashmap_get(u->manager->sessions, display);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (s && s->display && display_is_local(s->display))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering u->display = s;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (realtime) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering unsigned long long l;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (sscanf(realtime, "%llu", &l) > 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering u->timestamp.realtime = l;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (monotonic) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering unsigned long long l;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (sscanf(monotonic, "%llu", &l) > 0)
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering u->timestamp.monotonic = l;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering}
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int user_mkdir_runtime_path(User *u) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering char *p;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering int r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering assert(u);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = mkdir_safe_label("/run/user", 0755, 0, 0);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (r < 0) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering log_error("Failed to create /run/user: %s", strerror(-r));
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering return r;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!u->runtime_path) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (asprintf(&p, "/run/user/" UID_FMT, u->uid) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return log_oom();
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering } else
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering p = u->runtime_path;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (path_is_mount_point(p, false) <= 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_free_ char *t = NULL;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering
13f5402c6b734ed4c2b3e8b7c3d3bf6d815e7661Aleksander Adamowski mkdir(p, 0700);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (mac_smack_use())
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering else
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = log_oom();
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek r = mount("tmpfs", p, "tmpfs", MS_NODEV|MS_NOSUID, t);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_error("Failed to mount per-user tmpfs directory %s: %s", p, strerror(-r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering goto fail;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->runtime_path = p;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringfail:
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(p);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->runtime_path = NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen}
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensen
40b71e89bae4e51768db4dc50ec64c1e9c96eec4Sebastian Thorarensenstatic int user_start_slice(User *u) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char *job;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
d054f0a4d451120c26494263fc4dc175bfd405b1Daniel Mack
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering assert(u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering if (!u->slice) {
d054f0a4d451120c26494263fc4dc175bfd405b1Daniel Mack _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering char lu[DECIMAL_STR_MAX(uid_t) + 1], *slice;
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering sprintf(lu, UID_FMT, u->uid);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = build_subslice(SPECIAL_USER_SLICE, lu, &slice);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering if (r < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_start_unit(u->manager, slice, &error, &job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (r < 0) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_error("Failed to start user slice: %s", bus_error_message(&error, r));
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering free(slice);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering } else {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->slice = slice;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->slice_job);
63c372cb9df3bee01e3bf8cd7f96f336bddda846Lennart Poettering u->slice_job = job;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
968f319679d9069af037240d0c3bcd126181cdacZbigniew Jędrzejewski-Szmek if (u->slice)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering hashmap_put(u->manager->user_units, u->slice, u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return 0;
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering}
3b3154df7e2773332bb814e167187367a0ccae4aLennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringstatic int user_start_service(User *u) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char *job;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
46b131574fdd7d77c15a0919ca9010cad7aa6ac7Lennart Poettering
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek assert(u);
03ee5c38cb0da193dd08733fb4c0c2809cee6a99Lennart Poettering
b92bea5d2a9481de69bb627a7b442a9f58fca43dZbigniew Jędrzejewski-Szmek if (!u->service) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering sprintf(lu, UID_FMT, u->uid);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt service = unit_name_build("user", lu, ".service");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (!service)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering return log_oom();
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_start_unit(u->manager, service, &error, &job);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt if (r < 0) {
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt log_error("Failed to start user service: %s", bus_error_message(&error, r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(service);
4a61c3e51e96a747c30598d78ee3a24e7c569e9fZbigniew Jędrzejewski-Szmek } else {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->service = service;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering free(u->service_job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering u->service_job = job;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt }
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt }
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->service)
6355e75610a8d47fc3ba5ab8bd442172a2cfe574Lennart Poettering hashmap_put(u->manager->user_units, u->service, u);
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering return 0;
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt}
d682b3a7e7c7c2941a4d3e193f1e330dbc9fae89Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poetteringint user_start(User *u) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering int r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt assert(u);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (u->started)
8531ae707d4d0203e83304d4af948b8169a5fce1Lennart Poettering return 0;
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt log_debug("New user %s logged in.", u->name);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo /* Make XDG_RUNTIME_DIR */
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo r = user_mkdir_runtime_path(u);
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo if (r < 0)
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo return r;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Create cgroup */
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering r = user_start_slice(u);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (r < 0)
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return r;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering /* Spawn user systemd */
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering r = user_start_service(u);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (r < 0)
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return r;
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (!dual_timestamp_is_set(&u->timestamp))
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering dual_timestamp_get(&u->timestamp);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek u->started = true;
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek /* Save new user data */
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek user_save(u);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering user_send_signal(u, true);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering return 0;
}
static int user_stop_slice(User *u) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
char *job;
int r;
assert(u);
if (!u->slice)
return 0;
r = manager_stop_unit(u->manager, u->slice, &error, &job);
if (r < 0) {
log_error("Failed to stop user slice: %s", bus_error_message(&error, r));
return r;
}
free(u->slice_job);
u->slice_job = job;
return r;
}
static int user_stop_service(User *u) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
char *job;
int r;
assert(u);
if (!u->service)
return 0;
r = manager_stop_unit(u->manager, u->service, &error, &job);
if (r < 0) {
log_error("Failed to stop user service: %s", bus_error_message(&error, r));
return r;
}
free(u->service_job);
u->service_job = job;
return r;
}
static int user_remove_runtime_path(User *u) {
int r;
assert(u);
if (!u->runtime_path)
return 0;
r = rm_rf(u->runtime_path, false, false, false);
if (r < 0)
log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
if (umount2(u->runtime_path, MNT_DETACH) < 0)
log_error("Failed to unmount user runtime directory %s: %m", u->runtime_path);
r = rm_rf(u->runtime_path, false, true, false);
if (r < 0)
log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
free(u->runtime_path);
u->runtime_path = NULL;
return r;
}
int user_stop(User *u, bool force) {
Session *s;
int r = 0, k;
assert(u);
/* Stop jobs have already been queued */
if (u->stopping) {
user_save(u);
return r;
}
LIST_FOREACH(sessions_by_user, s, u->sessions) {
k = session_stop(s, force);
if (k < 0)
r = k;
}
/* Kill systemd */
k = user_stop_service(u);
if (k < 0)
r = k;
/* Kill cgroup */
k = user_stop_slice(u);
if (k < 0)
r = k;
u->stopping = true;
user_save(u);
return r;
}
int user_finalize(User *u) {
Session *s;
int r = 0, k;
assert(u);
if (u->started)
log_debug("User %s logged out.", u->name);
LIST_FOREACH(sessions_by_user, s, u->sessions) {
k = session_finalize(s);
if (k < 0)
r = k;
}
/* 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 = { 0, 0 };
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 = strappenda("/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->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);
}
void user_elect_display(User *u) {
Session *graphical = NULL, *text = NULL, *other = NULL, *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. */
LIST_FOREACH(sessions_by_user, s, u->sessions) {
if (s->class != SESSION_USER)
continue;
if (s->stopping)
continue;
if (SESSION_TYPE_IS_GRAPHICAL(s->type))
graphical = s;
else if (s->type == SESSION_TTY)
text = s;
else
other = s;
}
if (graphical &&
(!u->display ||
u->display->class != SESSION_USER ||
u->display->stopping ||
!SESSION_TYPE_IS_GRAPHICAL(u->display->type))) {
u->display = graphical;
return;
}
if (text &&
(!u->display ||
u->display->class != SESSION_USER ||
u->display->stopping ||
u->display->type != SESSION_TTY)) {
u->display = text;
return;
}
if (other &&
(!u->display ||
u->display->class != SESSION_USER ||
u->display->stopping))
u->display = other;
}
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 ? errno : EINVAL, "Failed to parse percentage value, ignoring: %s", rvalue);
return 0;
}
if (ul <= 0 || ul >= 100) {
log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Percentage value out of range, ignoring: %s", rvalue);
return 0;
}
*sz = PAGE_ALIGN((size_t) ((physical_memory() * (uint64_t) ul) / (uint64_t) 100));
} else {
off_t o;
r = parse_size(rvalue, 1024, &o);
if (r < 0 || (off_t) (size_t) o != o) {
log_syntax(unit, LOG_ERR, filename, line, r < 0 ? -r : ERANGE, "Failed to parse size value, ignoring: %s", rvalue);
return 0;
}
*sz = PAGE_ALIGN((size_t) o);
}
return 0;
}