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/>.
22 #include <sys/types.h>
24 #include <sys/ioctl.h>
31 #include "cgroup-util.h"
34 #include "bus-error.h"
37 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
43 d = hashmap_get(m->devices, sysfs);
48 /* we support adding master-flags, but not removing them */
49 d->master = d->master || master;
54 d = device_new(m, sysfs, master);
64 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
70 s = hashmap_get(m->seats, id);
88 int manager_add_session(Manager *m, const char *id, Session **_session) {
94 s = hashmap_get(m->sessions, id);
102 s = session_new(m, id);
112 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
118 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
126 u = user_new(m, uid, gid, name);
136 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
144 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
148 return manager_add_user(m, uid, gid, name, _user);
151 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
159 return errno ? -errno : -ENOENT;
161 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
164 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
170 i = hashmap_get(m->inhibitors, id);
178 i = inhibitor_new(m, id);
188 int manager_add_button(Manager *m, const char *name, Button **_button) {
194 b = hashmap_get(m->buttons, name);
202 b = button_new(m, name);
212 int manager_watch_busname(Manager *m, const char *name) {
219 if (set_get(m->busnames, (char*) name))
226 r = set_put(m->busnames, n);
235 void manager_drop_busname(Manager *m, const char *name) {
242 /* keep it if the name still owns a controller */
243 HASHMAP_FOREACH(session, m->sessions, i)
244 if (session_is_controller(session, name))
247 free(set_remove(m->busnames, (char*) name));
250 int manager_process_seat_device(Manager *m, struct udev_device *d) {
256 if (streq_ptr(udev_device_get_action(d), "remove")) {
258 device = hashmap_get(m->devices, udev_device_get_syspath(d));
262 seat_add_to_gc_queue(device->seat);
270 sn = udev_device_get_property_value(d, "ID_SEAT");
274 if (!seat_name_is_valid(sn)) {
275 log_warning("Device with invalid seat name %s found, ignoring.", sn);
279 /* ignore non-master devices for unknown seats */
280 master = udev_device_has_tag(d, "master-of-seat");
281 if (!master && !(seat = hashmap_get(m->seats, sn)))
284 r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
289 r = manager_add_seat(m, sn, &seat);
298 device_attach(device, seat);
305 int manager_process_button_device(Manager *m, struct udev_device *d) {
312 if (streq_ptr(udev_device_get_action(d), "remove")) {
314 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
323 r = manager_add_button(m, udev_device_get_sysname(d), &b);
327 sn = udev_device_get_property_value(d, "ID_SEAT");
331 button_set_seat(b, sn);
338 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
339 _cleanup_free_ char *unit = NULL;
349 r = cg_pid_get_unit(pid, &unit);
353 s = hashmap_get(m->session_units, unit);
361 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
362 _cleanup_free_ char *unit = NULL;
372 r = cg_pid_get_slice(pid, &unit);
376 u = hashmap_get(m->user_units, unit);
384 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
387 dual_timestamp ts = { 0, 0 };
392 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
394 HASHMAP_FOREACH(s, m->sessions, i) {
398 ih = session_get_idle_hint(s, &k);
404 if (k.monotonic < ts.monotonic)
410 } else if (idle_hint) {
412 if (k.monotonic > ts.monotonic)
423 bool manager_shall_kill(Manager *m, const char *user) {
427 if (!m->kill_user_processes)
430 if (strv_contains(m->kill_exclude_users, user))
433 if (strv_isempty(m->kill_only_users))
436 return strv_contains(m->kill_only_users, user);
439 static int vt_is_busy(unsigned int vtnr) {
440 struct vt_stat vt_stat;
445 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
446 * we'd open the latter we'd open the foreground tty which
447 * hence would be unconditionally busy. By opening /dev/tty1
448 * we avoid this. Since tty1 is special and needs to be an
449 * explicitly loaded getty or DM this is safe. */
451 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
455 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
458 r = !!(vt_stat.v_state & (1 << vtnr));
460 close_nointr_nofail(fd);
465 int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
466 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
467 _cleanup_free_ char *name = NULL;
473 if (vtnr > m->n_autovts &&
474 vtnr != m->reserve_vt)
477 if (vtnr != m->reserve_vt) {
478 /* If this is the reserved TTY, we'll start the getty
479 * on it in any case, but otherwise only if it is not
482 r = vt_is_busy(vtnr);
489 if (asprintf(&name, "autovt@tty%u.service", vtnr) < 0)
492 r = sd_bus_call_method(
494 "org.freedesktop.systemd1",
495 "/org/freedesktop/systemd1",
496 "org.freedesktop.systemd1.Manager",
502 log_error("Failed to start %s: %s", name, bus_error_message(&error, r));