logind-core.c revision 157f50577fbee094eb8ca18f3f0af4e82af8558f
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/***
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2011 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
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
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
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/>.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen***/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <sys/types.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <sys/ioctl.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <fcntl.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <pwd.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <linux/vt.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "alloc-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "bus-error.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "bus-util.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "cgroup-util.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "fd-util.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "logind.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "strv.h"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include "terminal-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "udev-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "user-util.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Device *d;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(sysfs);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering d = hashmap_get(m->devices, sysfs);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (d)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* we support adding master-flags, but not removing them */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering d->master = d->master || master;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering d = device_new(m, sysfs, master);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!d)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_device)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_device = d;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_seat(Manager *m, const char *id, Seat **_seat) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Seat *s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = hashmap_get(m->seats, id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!s) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = seat_new(m, id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!s)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_seat = s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_session(Manager *m, const char *id, Session **_session) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Session *s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = hashmap_get(m->sessions, id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!s) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = session_new(m, id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!s)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_session)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_session = s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering User *u;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering u = hashmap_get(m->users, UID_TO_PTR(uid));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!u) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = user_new(&u, m, uid, gid, name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_user)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_user = u;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_user_by_name(Manager *m, const char *name, User **_user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uid_t uid;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering gid_t gid;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = get_user_creds(&name, &uid, &gid, NULL, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return manager_add_user(m, uid, gid, name, _user);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct passwd *p;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering errno = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p = getpwuid(uid);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!p)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return errno ? -errno : -ENOENT;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Inhibitor *i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering i = hashmap_get(m->inhibitors, id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_inhibitor)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_inhibitor = i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering i = inhibitor_new(m, id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!i)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_inhibitor)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_inhibitor = i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_add_button(Manager *m, const char *name, Button **_button) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Button *b;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering b = hashmap_get(m->buttons, name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!b) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering b = button_new(m, name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!b)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (_button)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *_button = b;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_process_seat_device(Manager *m, struct udev_device *d) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Device *device;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (streq_ptr(udev_device_get_action(d), "remove")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering device = hashmap_get(m->devices, udev_device_get_syspath(d));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!device)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering seat_add_to_gc_queue(device->seat);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering device_free(device);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *sn;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Seat *seat = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen bool master;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sn = udev_device_get_property_value(d, "ID_SEAT");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(sn))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sn = "seat0";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!seat_name_is_valid(sn)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Device with invalid seat name %s found, ignoring.", sn);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering seat = hashmap_get(m->seats, sn);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering master = udev_device_has_tag(d, "master-of-seat");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Ignore non-master devices for unknown seats */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!master && !seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!seat) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_add_seat(m, sn, &seat);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!device->seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering device_free(device);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering device_attach(device, seat);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering seat_start(seat);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_process_button_device(Manager *m, struct udev_device *d) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Button *b;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (streq_ptr(udev_device_get_action(d), "remove")) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering b = hashmap_get(m->buttons, udev_device_get_sysname(d));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!b)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering button_free(b);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *sn;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_add_button(m, udev_device_get_sysname(d), &b);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sn = udev_device_get_property_value(d, "ID_SEAT");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(sn))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sn = "seat0";
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering button_set_seat(b, sn);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering button_open(b);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *unit = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Session *s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (pid < 1)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -EINVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = cg_pid_get_unit(pid, &unit);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering s = hashmap_get(m->session_units, unit);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!s)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (session)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *session = s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *unit = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen User *u;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(user);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (pid < 1)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return -EINVAL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = cg_pid_get_slice(pid, &unit);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering u = hashmap_get(m->user_units, unit);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!u)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *user = u;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return 1;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_idle_hint(Manager *m, dual_timestamp *t) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Session *s;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering bool idle_hint;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dual_timestamp ts = DUAL_TIMESTAMP_NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen HASHMAP_FOREACH(s, m->sessions, i) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen dual_timestamp k;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int ih;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen ih = session_get_idle_hint(s, &k);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (ih < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return ih;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!ih) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!idle_hint) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (k.monotonic < ts.monotonic)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen ts = k;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen idle_hint = false;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen ts = k;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else if (idle_hint) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (k.monotonic > ts.monotonic)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen ts = k;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (t)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *t = ts;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return idle_hint;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenbool manager_shall_kill(Manager *m, const char *user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(user);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!m->kill_user_processes)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return false;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (strv_contains(m->kill_exclude_users, user))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return false;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (strv_isempty(m->kill_only_users))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return true;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek return strv_contains(m->kill_only_users, user);
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek}
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmek
36f822c4bd077f9121757e24b6516e5c7ada63b5Zbigniew Jędrzejewski-Szmekstatic int vt_is_busy(unsigned int vtnr) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen struct vt_stat vt_stat;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int r = 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen _cleanup_close_ int fd;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(vtnr >= 1);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
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. */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (fd < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -errno;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = -errno;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = !!(vt_stat.v_state & (1 << vtnr));
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
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 int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(vtnr >= 1);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (vtnr > m->n_autovts &&
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering vtnr != m->reserve_vt)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (vtnr != m->reserve_vt) {
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
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * busy. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = vt_is_busy(vtnr);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen else if (r > 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return -EBUSY;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_call_method(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering m->bus,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "org.freedesktop.systemd1",
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "/org/freedesktop/systemd1",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "org.freedesktop.systemd1.Manager",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "StartUnit",
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering &error,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering NULL,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "ss", name, "fail");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_error("Failed to start %s: %s", name, bus_error_message(&error, r));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic bool manager_is_docked(Manager *m) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Iterator i;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Button *b;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen HASHMAP_FOREACH(b, m->buttons, i)
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering if (b->docked)
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering return true;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
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;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int n = 0;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering e = udev_enumerate_new(m->udev);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!e)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = udev_enumerate_add_match_subsystem(e, "drm");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = udev_enumerate_scan_devices(e);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen first = udev_enumerate_get_list_entry(e);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen udev_list_entry_foreach(item, first) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_udev_device_unref_ struct udev_device *d = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering struct udev_device *p;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen const char *status, *enabled, *dash, *nn, *i;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen bool external = false;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!d)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p = udev_device_get_parent(d);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!p)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen continue;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
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 continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering nn = udev_device_get_sysname(d);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!nn)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
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 dash = strchr(nn, '-');
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!dash)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen continue;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen dash++;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "Composite-", "SVIDEO-", "Component-",
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen "DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (startswith(dash, i)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering external = true;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen break;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!external)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Ignore ports that are not enabled */
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen enabled = udev_device_get_sysattr_value(d, "enabled");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!enabled)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!streq_ptr(enabled, "enabled"))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering continue;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
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");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (!streq_ptr(status, "disconnected"))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n++;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return n;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringbool manager_is_docked_or_external_displays(Manager *m) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen int n;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we are docked don't react to lid closing */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (manager_is_docked(m)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_debug("System is docked.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* If we have more than one display connected,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * assume that we are docked. */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering n = manager_count_external_displays(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (n < 0)
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);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return true;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return false;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering