1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2011 Lennart Poettering
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
28 #include "cgroup-util.h"
33 #include "unit-name.h"
34 #include "dbus-common.h"
35 #include "logind-user.h"
37 User* user_new(Manager *m, uid_t uid, gid_t gid, const char *name) {
47 u->name = strdup(name);
51 if (asprintf(&u->state_file, "/run/systemd/users/%lu", (unsigned long) uid) < 0)
54 if (hashmap_put(m->users, ULONG_TO_PTR((unsigned long) uid), u) < 0)
71 void user_free(User *u) {
75 LIST_REMOVE(User, gc_queue, u->manager->user_gc_queue, u);
78 session_free(u->sessions);
81 hashmap_remove(u->manager->user_units, u->slice);
86 hashmap_remove(u->manager->user_units, u->service);
93 free(u->runtime_path);
95 hashmap_remove(u->manager->users, ULONG_TO_PTR((unsigned long) u->uid));
102 int user_save(User *u) {
103 _cleanup_free_ char *temp_path = NULL;
104 _cleanup_fclose_ FILE *f = NULL;
108 assert(u->state_file);
113 r = mkdir_safe_label("/run/systemd/users", 0755, 0, 0);
117 r = fopen_temporary(u->state_file, &f, &temp_path);
121 fchmod(fileno(f), 0644);
124 "# This is private data. Do not parse.\n"
128 user_state_to_string(user_get_state(u)));
131 fprintf(f, "RUNTIME=%s\n", u->runtime_path);
134 fprintf(f, "SERVICE=%s\n", u->service);
136 fprintf(f, "SERVICE_JOB=%s\n", u->service_job);
139 fprintf(f, "SLICE=%s\n", u->slice);
141 fprintf(f, "SLICE_JOB=%s\n", u->slice_job);
144 fprintf(f, "DISPLAY=%s\n", u->display->id);
146 if (dual_timestamp_is_set(&u->timestamp))
150 (unsigned long long) u->timestamp.realtime,
151 (unsigned long long) u->timestamp.monotonic);
157 fputs("SESSIONS=", f);
159 LIST_FOREACH(sessions_by_user, i, u->sessions) {
168 fputs("\nSEATS=", f);
170 LIST_FOREACH(sessions_by_user, i, u->sessions) {
179 fputs(i->seat->id, f);
182 fputs("\nACTIVE_SESSIONS=", f);
184 LIST_FOREACH(sessions_by_user, i, u->sessions) {
185 if (!session_is_active(i))
196 fputs("\nONLINE_SESSIONS=", f);
198 LIST_FOREACH(sessions_by_user, i, u->sessions) {
199 if (session_get_state(i) == SESSION_CLOSING)
210 fputs("\nACTIVE_SEATS=", f);
212 LIST_FOREACH(sessions_by_user, i, u->sessions) {
213 if (!session_is_active(i) || !i->seat)
221 fputs(i->seat->id, f);
224 fputs("\nONLINE_SEATS=", f);
226 LIST_FOREACH(sessions_by_user, i, u->sessions) {
227 if (session_get_state(i) == SESSION_CLOSING || !i->seat)
235 fputs(i->seat->id, f);
242 if (ferror(f) || rename(temp_path, u->state_file) < 0) {
244 unlink(u->state_file);
250 log_error("Failed to save user data for %s: %s", u->name, strerror(-r));
255 int user_load(User *u) {
256 _cleanup_free_ char *display = NULL, *realtime = NULL, *monotonic = NULL;
262 r = parse_env_file(u->state_file, NEWLINE,
263 "RUNTIME", &u->runtime_path,
264 "SERVICE", &u->service,
265 "SERVICE_JOB", &u->service_job,
267 "SLICE_JOB", &u->slice_job,
269 "REALTIME", &realtime,
270 "MONOTONIC", &monotonic,
276 log_error("Failed to read %s: %s", u->state_file, strerror(-r));
281 s = hashmap_get(u->manager->sessions, display);
283 if (s && s->display && display_is_local(s->display))
287 unsigned long long l;
288 if (sscanf(realtime, "%llu", &l) > 0)
289 u->timestamp.realtime = l;
293 unsigned long long l;
294 if (sscanf(monotonic, "%llu", &l) > 0)
295 u->timestamp.monotonic = l;
301 static int user_mkdir_runtime_path(User *u) {
307 r = mkdir_safe_label("/run/user", 0755, 0, 0);
309 log_error("Failed to create /run/user: %s", strerror(-r));
313 if (!u->runtime_path) {
314 if (asprintf(&p, "/run/user/%lu", (unsigned long) u->uid) < 0)
319 r = mkdir_safe_label(p, 0700, u->uid, u->gid);
321 log_error("Failed to create runtime directory %s: %s", p, strerror(-r));
323 u->runtime_path = NULL;
331 static int user_start_slice(User *u) {
338 dbus_error_init(&error);
341 char lu[DECIMAL_STR_MAX(unsigned long) + 1];
342 sprintf(lu, "%lu", (unsigned long) u->uid);
344 r = build_subslice(SPECIAL_USER_SLICE, lu, &u->slice);
348 r = hashmap_put(u->manager->user_units, u->slice, u);
350 log_warning("Failed to create mapping between unit and user");
353 r = manager_start_unit(u->manager, u->slice, &error, &job);
355 log_error("Failed to start user slice: %s", bus_error(&error, r));
356 dbus_error_free(&error);
365 static int user_start_service(User *u) {
372 dbus_error_init(&error);
375 char lu[DECIMAL_STR_MAX(unsigned long) + 1];
376 sprintf(lu, "%lu", (unsigned long) u->uid);
378 u->service = unit_name_build("user", lu, ".service");
382 r = hashmap_put(u->manager->user_units, u->service, u);
384 log_warning("Failed to create mapping between service and user");
387 r = manager_start_unit(u->manager, u->service, &error, &job);
389 log_error("Failed to start user service: %s", bus_error(&error, r));
390 dbus_error_free(&error);
392 free(u->service_job);
393 u->service_job = job;
399 int user_start(User *u) {
407 log_debug("New user %s logged in.", u->name);
409 /* Make XDG_RUNTIME_DIR */
410 r = user_mkdir_runtime_path(u);
415 r = user_start_slice(u);
419 /* Spawn user systemd */
420 r = user_start_service(u);
424 if (!dual_timestamp_is_set(&u->timestamp))
425 dual_timestamp_get(&u->timestamp);
429 /* Save new user data */
432 user_send_signal(u, true);
437 static int user_stop_slice(User *u) {
444 dbus_error_init(&error);
449 r = manager_stop_unit(u->manager, u->slice, &error, &job);
451 log_error("Failed to stop user slice: %s", bus_error(&error, r));
452 dbus_error_free(&error);
462 static int user_stop_service(User *u) {
469 dbus_error_init(&error);
474 r = manager_stop_unit(u->manager, u->service, &error, &job);
476 log_error("Failed to stop user service: %s", bus_error(&error, r));
477 dbus_error_free(&error);
481 free(u->service_job);
482 u->service_job = job;
487 /* static int user_shall_kill(User *u) { */
490 /* if (!u->manager->kill_user_processes) */
493 /* if (strv_contains(u->manager->kill_exclude_users, u->name)) */
496 /* if (strv_isempty(u->manager->kill_only_users)) */
499 /* return strv_contains(u->manager->kill_only_users, u->name); */
502 static int user_remove_runtime_path(User *u) {
507 if (!u->runtime_path)
510 r = rm_rf(u->runtime_path, false, true, false);
512 log_error("Failed to remove runtime directory %s: %s", u->runtime_path, strerror(-r));
514 free(u->runtime_path);
515 u->runtime_path = NULL;
520 int user_stop(User *u) {
526 log_debug("User %s logged out.", u->name);
528 LIST_FOREACH(sessions_by_user, s, u->sessions) {
535 k = user_stop_service(u);
540 k = user_stop_slice(u);
544 /* Kill XDG_RUNTIME_DIR */
545 k = user_remove_runtime_path(u);
549 unlink(u->state_file);
550 user_add_to_gc_queue(u);
553 user_send_signal(u, false);
560 int user_get_idle_hint(User *u, dual_timestamp *t) {
562 bool idle_hint = true;
563 dual_timestamp ts = { 0, 0 };
567 LIST_FOREACH(sessions_by_user, s, u->sessions) {
571 ih = session_get_idle_hint(s, &k);
577 if (k.monotonic < ts.monotonic)
583 } else if (idle_hint) {
585 if (k.monotonic > ts.monotonic)
596 static int user_check_linger_file(User *u) {
600 if (asprintf(&p, "/var/lib/systemd/linger/%s", u->name) < 0)
603 r = access(p, F_OK) >= 0;
609 int user_check_gc(User *u, bool drop_not_started) {
612 if (drop_not_started && !u->started)
618 if (user_check_linger_file(u) > 0)
624 void user_add_to_gc_queue(User *u) {
630 LIST_PREPEND(User, gc_queue, u->manager->user_gc_queue, u);
631 u->in_gc_queue = true;
634 UserState user_get_state(User *u) {
636 bool all_closing = true;
640 if (u->slice_job || u->service_job)
641 return u->started ? USER_OPENING : USER_CLOSING;
643 LIST_FOREACH(sessions_by_user, i, u->sessions) {
644 if (session_is_active(i))
646 if (session_get_state(i) != SESSION_CLOSING)
651 return all_closing ? USER_CLOSING : USER_ONLINE;
653 if (user_check_linger_file(u) > 0)
654 return USER_LINGERING;
659 int user_kill(User *u, int signo) {
665 return manager_kill_unit(u->manager, u->slice, KILL_ALL, signo, NULL);
668 static const char* const user_state_table[_USER_STATE_MAX] = {
669 [USER_OFFLINE] = "offline",
670 [USER_OPENING] = "opening",
671 [USER_LINGERING] = "lingering",
672 [USER_ONLINE] = "online",
673 [USER_ACTIVE] = "active",
674 [USER_CLOSING] = "closing"
677 DEFINE_STRING_TABLE_LOOKUP(user_state, UserState);