logind-core.c revision 157f50577fbee094eb8ca18f3f0af4e82af8558f
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2011 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* we support adding master-flags, but not removing them */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_seat(Manager *m, const char *id, Seat **_seat) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_session(Manager *m, const char *id, Session **_session) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering u = hashmap_get(m->users, UID_TO_PTR(uid));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_user_by_name(Manager *m, const char *name, User **_user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = get_user_creds(&name, &uid, &gid, NULL, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return manager_add_user(m, uid, gid, name, _user);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_button(Manager *m, const char *name, Button **_button) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_process_seat_device(Manager *m, struct udev_device *d) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (streq_ptr(udev_device_get_action(d), "remove")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering device = hashmap_get(m->devices, udev_device_get_syspath(d));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sn = udev_device_get_property_value(d, "ID_SEAT");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Device with invalid seat name %s found, ignoring.", sn);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering master = udev_device_has_tag(d, "master-of-seat");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Ignore non-master devices for unknown seats */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_process_button_device(Manager *m, struct udev_device *d) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (streq_ptr(udev_device_get_action(d), "remove")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering b = hashmap_get(m->buttons, udev_device_get_sysname(d));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_add_button(m, udev_device_get_sysname(d), &b);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sn = udev_device_get_property_value(d, "ID_SEAT");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_idle_hint(Manager *m, dual_timestamp *t) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenbool manager_shall_kill(Manager *m, const char *user) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (strv_contains(m->kill_exclude_users, user))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return false;
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek return strv_contains(m->kill_only_users, user);
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmekstatic int vt_is_busy(unsigned int vtnr) {
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering * we'd open the latter we'd open the foreground tty which
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * hence would be unconditionally busy. By opening /dev/tty1
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * we avoid this. Since tty1 is special and needs to be an
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * explicitly loaded getty or DM this is safe. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenint manager_spawn_autovt(Manager *m, unsigned int vtnr) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned int)];
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If this is the reserved TTY, we'll start the getty
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * on it in any case, but otherwise only if it is not
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else if (r > 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "org.freedesktop.systemd1.Manager",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to start %s: %s", name, bus_error_message(&error, r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool manager_is_docked(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int manager_count_external_displays(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct udev_list_entry *item = NULL, *first = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = udev_enumerate_add_match_subsystem(e, "drm");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If the parent shares the same subsystem as the
b686acb27ea4de042320fa196cfb14e08f30165bTom Gundersen * device we are looking at then it is a connector,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * which is what we are interested in. */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!streq_ptr(udev_device_get_subsystem(p), "drm"))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen /* Ignore internal displays: the type is encoded in
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * the sysfs name, as the second dash seperated item
b686acb27ea4de042320fa196cfb14e08f30165bTom Gundersen * (the first is the card name, the last the connector
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * number). We implement a whitelist of external
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * displays here, rather than a whitelist, to ensure
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen * we don't block suspends too eagerly. */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Ignore ports that are not enabled */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen enabled = udev_device_get_sysattr_value(d, "enabled");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* We count any connector which is not explicitly
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * "disconnected" as connected. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering status = udev_device_get_sysattr_value(d, "status");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringbool manager_is_docked_or_external_displays(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we are docked don't react to lid closing */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we have more than one display connected,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * assume that we are docked. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning_errno(n, "Display counting failed: %m");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (n >= 1) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("External (%i) displays connected.", n);