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"
35 #include "udev-util.h"
38 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
44 d = hashmap_get(m->devices, sysfs);
46 /* we support adding master-flags, but not removing them */
47 d->master = d->master || master;
49 d = device_new(m, sysfs, master);
60 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
66 s = hashmap_get(m->seats, id);
79 int manager_add_session(Manager *m, const char *id, Session **_session) {
85 s = hashmap_get(m->sessions, id);
87 s = session_new(m, id);
98 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
104 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
106 u = user_new(m, uid, gid, name);
117 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
125 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
129 return manager_add_user(m, uid, gid, name, _user);
132 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
140 return errno ? -errno : -ENOENT;
142 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
145 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
151 i = hashmap_get(m->inhibitors, id);
159 i = inhibitor_new(m, id);
169 int manager_add_button(Manager *m, const char *name, Button **_button) {
175 b = hashmap_get(m->buttons, name);
177 b = button_new(m, name);
188 int manager_watch_busname(Manager *m, const char *name) {
195 if (set_get(m->busnames, (char*) name))
202 r = set_put(m->busnames, n);
211 void manager_drop_busname(Manager *m, const char *name) {
218 /* keep it if the name still owns a controller */
219 HASHMAP_FOREACH(session, m->sessions, i)
220 if (session_is_controller(session, name))
223 free(set_remove(m->busnames, (char*) name));
226 int manager_process_seat_device(Manager *m, struct udev_device *d) {
232 if (streq_ptr(udev_device_get_action(d), "remove")) {
234 device = hashmap_get(m->devices, udev_device_get_syspath(d));
238 seat_add_to_gc_queue(device->seat);
246 sn = udev_device_get_property_value(d, "ID_SEAT");
250 if (!seat_name_is_valid(sn)) {
251 log_warning("Device with invalid seat name %s found, ignoring.", sn);
255 seat = hashmap_get(m->seats, sn);
256 master = udev_device_has_tag(d, "master-of-seat");
258 /* Ignore non-master devices for unknown seats */
259 if (!master && !seat)
262 r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
267 r = manager_add_seat(m, sn, &seat);
276 device_attach(device, seat);
283 int manager_process_button_device(Manager *m, struct udev_device *d) {
290 if (streq_ptr(udev_device_get_action(d), "remove")) {
292 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
301 r = manager_add_button(m, udev_device_get_sysname(d), &b);
305 sn = udev_device_get_property_value(d, "ID_SEAT");
309 button_set_seat(b, sn);
316 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
317 _cleanup_free_ char *unit = NULL;
327 r = cg_pid_get_unit(pid, &unit);
331 s = hashmap_get(m->session_units, unit);
339 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
340 _cleanup_free_ char *unit = NULL;
350 r = cg_pid_get_slice(pid, &unit);
354 u = hashmap_get(m->user_units, unit);
362 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
365 dual_timestamp ts = { 0, 0 };
370 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
372 HASHMAP_FOREACH(s, m->sessions, i) {
376 ih = session_get_idle_hint(s, &k);
382 if (k.monotonic < ts.monotonic)
388 } else if (idle_hint) {
390 if (k.monotonic > ts.monotonic)
401 bool manager_shall_kill(Manager *m, const char *user) {
405 if (!m->kill_user_processes)
408 if (strv_contains(m->kill_exclude_users, user))
411 if (strv_isempty(m->kill_only_users))
414 return strv_contains(m->kill_only_users, user);
417 static int vt_is_busy(unsigned int vtnr) {
418 struct vt_stat vt_stat;
420 _cleanup_close_ int fd;
424 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
425 * we'd open the latter we'd open the foreground tty which
426 * hence would be unconditionally busy. By opening /dev/tty1
427 * we avoid this. Since tty1 is special and needs to be an
428 * explicitly loaded getty or DM this is safe. */
430 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
434 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
437 r = !!(vt_stat.v_state & (1 << vtnr));
442 int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
443 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
444 char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned int)];
450 if (vtnr > m->n_autovts &&
451 vtnr != m->reserve_vt)
454 if (vtnr != m->reserve_vt) {
455 /* If this is the reserved TTY, we'll start the getty
456 * on it in any case, but otherwise only if it is not
459 r = vt_is_busy(vtnr);
466 snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr);
467 r = sd_bus_call_method(
469 "org.freedesktop.systemd1",
470 "/org/freedesktop/systemd1",
471 "org.freedesktop.systemd1.Manager",
477 log_error("Failed to start %s: %s", name, bus_error_message(&error, r));
482 bool manager_is_docked(Manager *m) {
486 HASHMAP_FOREACH(b, m->buttons, i)
493 int manager_count_displays(Manager *m) {
494 _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
495 struct udev_list_entry *item = NULL, *first = NULL;
499 e = udev_enumerate_new(m->udev);
503 r = udev_enumerate_add_match_subsystem(e, "drm");
507 r = udev_enumerate_scan_devices(e);
511 first = udev_enumerate_get_list_entry(e);
512 udev_list_entry_foreach(item, first) {
513 _cleanup_udev_device_unref_ struct udev_device *d = NULL;
514 struct udev_device *p;
517 d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
521 p = udev_device_get_parent(d);
525 /* If the parent shares the same subsystem as the
526 * device we are looking at then it is a connector,
527 * which is what we are interested in. */
528 if (!streq_ptr(udev_device_get_subsystem(p), "drm"))
531 /* We count any connector which is not explicitly
532 * "disconnected" as connected. */
533 status = udev_device_get_sysattr_value(d, "status");
534 if (!streq_ptr(status, "disconnected"))
541 bool manager_is_docked_or_multiple_displays(Manager *m) {
544 /* If we are docked don't react to lid closing */
545 if (manager_is_docked(m)) {
546 log_debug("System is docked.");
550 /* If we have more than one display connected,
551 * assume that we are docked. */
552 n = manager_count_displays(m);
554 log_warning("Display counting failed: %s", strerror(-n));
556 log_debug("Multiple (%i) displays connected.", n);