logind-user.c revision 6baa7db00812437bbc87e73faa1a11b6cf631958
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering This file is part of systemd.
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering Copyright 2011 Lennart 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 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 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/>.
178cc7700c23ac088cd7190d7854282075028d91Lennart PoetteringUser* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
f8294e4175918117ca6c131720bcf287eadcd029Josh Triplett if (asprintf(&u->state_file, "/run/systemd/users/"UID_FMT, uid) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_REMOVE(gc_queue, u->manager->user_gc_queue, u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering hashmap_remove(u->manager->user_units, u->slice);
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering hashmap_remove(u->manager->user_units, u->service);
ccf23ad5faf228d450d263d7291156a948b61af2Christian Seiler hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = fopen_temporary(u->state_file, &f, &temp_path);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering "# This is private data. Do not parse.\n"
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering user_state_to_string(user_get_state(u)));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "RUNTIME=%s\n", u->runtime_path);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering fprintf(f, "DISPLAY=%s\n", u->display->id);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (dual_timestamp_is_set(&u->timestamp))
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (session_get_state(i) == SESSION_CLOSING)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering LIST_FOREACH(sessions_by_user, i, u->sessions) {
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (session_get_state(i) == SESSION_CLOSING || !i->seat)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (ferror(f) || rename(temp_path, u->state_file) < 0) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering log_error("Failed to save user data %s: %s", u->state_file, strerror(-r));
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = parse_env_file(u->state_file, NEWLINE,
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering log_error("Failed to read %s: %s", u->state_file, strerror(-r));
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering s = hashmap_get(u->manager->sessions, display);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering if (s && s->display && display_is_local(s->display))
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering unsigned long long l;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering unsigned long long l;
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poetteringstatic int user_mkdir_runtime_path(User *u) {
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering r = mkdir_safe_label("/run/user", 0755, 0, 0);
5809560d858f45351856d6fe786a8117306dd0f2Lennart Poettering log_error("Failed to create /run/user: %s", strerror(-r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (asprintf(&p, "/run/user/" UID_FMT, u->uid) < 0)
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering if (path_is_mount_point(p, false) <= 0) {
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);
8457f8d6ac7adc6c6ef31378e6e7761cce522141Lennart Poettering r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
e3bfb7be07d9b1f4ebb12eb22c4c8bcd2a988d51Zbigniew Jędrzejewski-Szmek r = mount("tmpfs", p, "tmpfs", MS_NODEV|MS_NOSUID, t);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_error("Failed to mount per-user tmpfs directory %s: %s", p, strerror(-r));
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;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = build_subslice(SPECIAL_USER_SLICE, lu, &slice);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_start_unit(u->manager, slice, &error, &job);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering log_error("Failed to start user slice: %s", bus_error_message(&error, r));
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering hashmap_put(u->manager->user_units, u->slice, u);
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering char lu[DECIMAL_STR_MAX(uid_t) + 1], *service;
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt service = unit_name_build("user", lu, ".service");
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering r = manager_start_unit(u->manager, service, &error, &job);
4a62c710b62a5a3c7a8a278b810b9d5b5a0c8f4fMichal Schmidt log_error("Failed to start user service: %s", bus_error_message(&error, r));
6355e75610a8d47fc3ba5ab8bd442172a2cfe574Lennart Poettering hashmap_put(u->manager->user_units, u->service, u);
23bbb0de4e3f85d9704a5c12a5afa2dfa0159e41Michal Schmidt log_debug("New user %s logged in.", u->name);
48cef29504b1ffc0df9929f2d8b2af2ad74d2b4aVito Caputo /* Make XDG_RUNTIME_DIR */
35e2e347d38cc2f8bd7c38a0d8a5129f5fbb0ab9Lennart Poettering /* Create cgroup */
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering /* Spawn user systemd */
178cc7700c23ac088cd7190d7854282075028d91Lennart Poettering if (!dual_timestamp_is_set(&u->timestamp))
8a03c9ef744e13dc700a7e7ca6cae8afdcf0d71cZbigniew Jędrzejewski-Szmek /* Save new user data */
char *job;
assert(u);
if (!u->slice)
char *job;
assert(u);
if (!u->service)
assert(u);
if (!u->runtime_path)
Session *s;
assert(u);
if (u->stopping) {
user_save(u);
k = user_stop_service(u);
k = user_stop_slice(u);
u->stopping = true;
user_save(u);
Session *s;
assert(u);
if (u->started)
k = session_finalize(s);
k = user_remove_runtime_path(u);
if (u->started) {
user_send_signal(u, false);
u->started = false;
Session *s;
bool idle_hint = true;
assert(u);
int ih;
if (ih < 0)
return ih;
if (!ih) {
if (!idle_hint) {
ts = k;
idle_hint = false;
ts = k;
} else if (idle_hint) {
ts = k;
*t = ts;
return idle_hint;
char *p = NULL;
if (!cc)
return -ENOMEM;
assert(u);
if (u->sessions)
if (user_check_linger_file(u) > 0)
assert(u);
if (u->in_gc_queue)
u->in_gc_queue = true;
Session *i;
assert(u);
if (u->stopping)
return USER_CLOSING;
return USER_OPENING;
if (u->sessions) {
bool all_closing = true;
return USER_ACTIVE;
all_closing = false;
if (user_check_linger_file(u) > 0)
return USER_LINGERING;
return USER_CLOSING;
assert(u);
if (!u->slice)
return -ESRCH;
assert(u);
if (s->stopping)
graphical = s;
text = s;
other = s;
if (graphical &&
(!u->display ||
if (text &&
(!u->display ||
if (other &&
(!u->display ||
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) {
unsigned long ul;
errno = 0;
if (errno != 0 || f != e) {
log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Failed to parse percentage value, ignoring: %s", rvalue);
log_syntax(unit, LOG_ERR, filename, line, errno ? errno : EINVAL, "Percentage value out of range, ignoring: %s", rvalue);
off_t o;