logind-core.c revision b80120c4cba7d134b5437a58437a23fdf7ab2084
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering/***
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering This file is part of systemd.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering Copyright 2011 Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering systemd is free software; you can redistribute it and/or modify it
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering under the terms of the GNU Lesser General Public License as published by
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering (at your option) any later version.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering systemd is distributed in the hope that it will be useful, but
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering Lesser General Public License for more details.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering You should have received a copy of the GNU Lesser General Public License
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering***/
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include <sys/types.h>
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include <sys/ioctl.h>
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include <fcntl.h>
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include <pwd.h>
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther#include <linux/vt.h>
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering#include "strv.h"
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#include "cgroup-util.h"
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include "bus-util.h"
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering#include "bus-error.h"
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#include "udev-util.h"
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering#include "logind.h"
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek#include "terminal-util.h"
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poetteringint manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering Device *d;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering assert(m);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering assert(sysfs);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering d = hashmap_get(m->devices, sysfs);
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering if (d)
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering /* we support adding master-flags, but not removing them */
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering d->master = d->master || master;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering else {
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering d = device_new(m, sysfs, master);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering if (!d)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return -ENOMEM;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering }
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering if (_device)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering *_device = d;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return 0;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering}
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poetteringint manager_add_seat(Manager *m, const char *id, Seat **_seat) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering Seat *s;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering assert(m);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering assert(id);
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering s = hashmap_get(m->seats, id);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (!s) {
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering s = seat_new(m, id);
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering if (!s)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering return -ENOMEM;
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering }
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering if (_seat)
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering *_seat = s;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering return 0;
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering}
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poetteringint manager_add_session(Manager *m, const char *id, Session **_session) {
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering Session *s;
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering assert(m);
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering assert(id);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
d7bd3de0654669e65b9642c248c5fa6d1d9a9f61Lennart Poettering s = hashmap_get(m->sessions, id);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering if (!s) {
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering s = session_new(m, id);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (!s)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return -ENOMEM;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering }
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (_session)
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek *_session = s;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return 0;
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering}
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poetteringint manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering User *u;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering assert(m);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering assert(name);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering u = hashmap_get(m->users, UID_TO_PTR(uid));
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (!u) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering u = user_new(m, uid, gid, name);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (!u)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return -ENOMEM;
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering }
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (_user)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering *_user = u;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return 0;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering}
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poetteringint manager_add_user_by_name(Manager *m, const char *name, User **_user) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering uid_t uid;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering gid_t gid;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering int r;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering assert(m);
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering assert(name);
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering
374ec6abf31ada6ca554cc8ea99b282373fac010Lennart Poettering r = get_user_creds(&name, &uid, &gid, NULL, NULL);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering if (r < 0)
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return r;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering return manager_add_user(m, uid, gid, name, _user);
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering}
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poetteringint manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering struct passwd *p;
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering assert(m);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering errno = 0;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering p = getpwuid(uid);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!p)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return errno ? -errno : -ENOENT;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering}
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poetteringint manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering Inhibitor *i;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering assert(m);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering assert(id);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering i = hashmap_get(m->inhibitors, id);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (i) {
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (_inhibitor)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering *_inhibitor = i;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return 0;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering }
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering i = inhibitor_new(m, id);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!i)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return -ENOMEM;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (_inhibitor)
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering *_inhibitor = i;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering return 0;
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering}
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poetteringint manager_add_button(Manager *m, const char *name, Button **_button) {
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering Button *b;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering assert(m);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering assert(name);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering b = hashmap_get(m->buttons, name);
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (!b) {
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering b = button_new(m, name);
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering if (!b)
1021b21bc6f8dd522b46116e8598b17f9f93f1b7Lennart Poettering return -ENOMEM;
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering }
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (_button)
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering *_button = b;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return 0;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering}
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poetteringint manager_watch_busname(Manager *m, const char *name) {
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering char *n;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering int r;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering assert(m);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering assert(name);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering if (set_get(m->busnames, (char*) name))
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return 0;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering n = strdup(name);
e13bb5d2b133f9ae51c0a2d20aa51071c780e9aeKay Sievers if (!n)
e13bb5d2b133f9ae51c0a2d20aa51071c780e9aeKay Sievers return -ENOMEM;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering r = set_put(m->busnames, n);
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering if (r < 0) {
a0ab566574303be1ca12cdb334f284cfd407caa5Lennart Poettering free(n);
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering return r;
ae018d9bc900d6355dea4af05119b49c67945184Lennart Poettering }
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering return 0;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering}
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poetteringvoid manager_drop_busname(Manager *m, const char *name) {
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering Session *session;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering Iterator i;
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering assert(m);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering assert(name);
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering /* keep it if the name still owns a controller */
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering HASHMAP_FOREACH(session, m->sessions, i)
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (session_is_controller(session, name))
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering free(set_remove(m->busnames, (char*) name));
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering}
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poetteringint manager_process_seat_device(Manager *m, struct udev_device *d) {
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering Device *device;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering int r;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering assert(m);
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (streq_ptr(udev_device_get_action(d), "remove")) {
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering device = hashmap_get(m->devices, udev_device_get_syspath(d));
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (!device)
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering return 0;
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering seat_add_to_gc_queue(device->seat);
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek device_free(device);
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering
6c03089c32c251d823173bda4d809a9e643219f0Lennart Poettering } else {
7027ff61a34a12487712b382a061c654acc3a679Lennart Poettering const char *sn;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering Seat *seat = NULL;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering bool master;
9444b1f20e311f073864d81e913bd4f32fe95cfdLennart Poettering
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther sn = udev_device_get_property_value(d, "ID_SEAT");
aff38e74bd776471f15ba54b305a24b0251eb865Lennart Poettering if (isempty(sn))
143bfdaf0b890fa7acadf02d1eafacaef1b696bdHolger Hans Peter Freyther sn = "seat0";
78edb35ab4f4227485cb9ec816b43c37e0d5e62aLennart Poettering
a016b9228f338cb9b380ce7e00826ef462767d98Lennart Poettering if (!seat_name_is_valid(sn)) {
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek log_warning("Device with invalid seat name %s found, ignoring.", sn);
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek return 0;
96cde13ace6406582688028f3df5668a172ba628Zbigniew Jędrzejewski-Szmek }
seat = hashmap_get(m->seats, sn);
master = udev_device_has_tag(d, "master-of-seat");
/* Ignore non-master devices for unknown seats */
if (!master && !seat)
return 0;
r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
if (r < 0)
return r;
if (!seat) {
r = manager_add_seat(m, sn, &seat);
if (r < 0) {
if (!device->seat)
device_free(device);
return r;
}
}
device_attach(device, seat);
seat_start(seat);
}
return 0;
}
int manager_process_button_device(Manager *m, struct udev_device *d) {
Button *b;
int r;
assert(m);
if (streq_ptr(udev_device_get_action(d), "remove")) {
b = hashmap_get(m->buttons, udev_device_get_sysname(d));
if (!b)
return 0;
button_free(b);
} else {
const char *sn;
r = manager_add_button(m, udev_device_get_sysname(d), &b);
if (r < 0)
return r;
sn = udev_device_get_property_value(d, "ID_SEAT");
if (isempty(sn))
sn = "seat0";
button_set_seat(b, sn);
button_open(b);
}
return 0;
}
int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
_cleanup_free_ char *unit = NULL;
Session *s;
int r;
assert(m);
if (pid < 1)
return -EINVAL;
r = cg_pid_get_unit(pid, &unit);
if (r < 0)
return 0;
s = hashmap_get(m->session_units, unit);
if (!s)
return 0;
if (session)
*session = s;
return 1;
}
int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
_cleanup_free_ char *unit = NULL;
User *u;
int r;
assert(m);
assert(user);
if (pid < 1)
return -EINVAL;
r = cg_pid_get_slice(pid, &unit);
if (r < 0)
return 0;
u = hashmap_get(m->user_units, unit);
if (!u)
return 0;
*user = u;
return 1;
}
int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
Session *s;
bool idle_hint;
dual_timestamp ts = DUAL_TIMESTAMP_NULL;
Iterator i;
assert(m);
idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0, NULL);
HASHMAP_FOREACH(s, m->sessions, i) {
dual_timestamp k;
int ih;
ih = session_get_idle_hint(s, &k);
if (ih < 0)
return ih;
if (!ih) {
if (!idle_hint) {
if (k.monotonic < ts.monotonic)
ts = k;
} else {
idle_hint = false;
ts = k;
}
} else if (idle_hint) {
if (k.monotonic > ts.monotonic)
ts = k;
}
}
if (t)
*t = ts;
return idle_hint;
}
bool manager_shall_kill(Manager *m, const char *user) {
assert(m);
assert(user);
if (!m->kill_user_processes)
return false;
if (strv_contains(m->kill_exclude_users, user))
return false;
if (strv_isempty(m->kill_only_users))
return true;
return strv_contains(m->kill_only_users, user);
}
static int vt_is_busy(unsigned int vtnr) {
struct vt_stat vt_stat;
int r = 0;
_cleanup_close_ int fd;
assert(vtnr >= 1);
/* We explicitly open /dev/tty1 here instead of /dev/tty0. If
* we'd open the latter we'd open the foreground tty which
* hence would be unconditionally busy. By opening /dev/tty1
* we avoid this. Since tty1 is special and needs to be an
* explicitly loaded getty or DM this is safe. */
fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
if (fd < 0)
return -errno;
if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
r = -errno;
else
r = !!(vt_stat.v_state & (1 << vtnr));
return r;
}
int manager_spawn_autovt(Manager *m, unsigned int vtnr) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
char name[sizeof("autovt@tty.service") + DECIMAL_STR_MAX(unsigned int)];
int r;
assert(m);
assert(vtnr >= 1);
if (vtnr > m->n_autovts &&
vtnr != m->reserve_vt)
return 0;
if (vtnr != m->reserve_vt) {
/* If this is the reserved TTY, we'll start the getty
* on it in any case, but otherwise only if it is not
* busy. */
r = vt_is_busy(vtnr);
if (r < 0)
return r;
else if (r > 0)
return -EBUSY;
}
snprintf(name, sizeof(name), "autovt@tty%u.service", vtnr);
r = sd_bus_call_method(
m->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit",
&error,
NULL,
"ss", name, "fail");
if (r < 0)
log_error("Failed to start %s: %s", name, bus_error_message(&error, r));
return r;
}
static bool manager_is_docked(Manager *m) {
Iterator i;
Button *b;
HASHMAP_FOREACH(b, m->buttons, i)
if (b->docked)
return true;
return false;
}
static int manager_count_external_displays(Manager *m) {
_cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
struct udev_list_entry *item = NULL, *first = NULL;
int r;
int n = 0;
e = udev_enumerate_new(m->udev);
if (!e)
return -ENOMEM;
r = udev_enumerate_add_match_subsystem(e, "drm");
if (r < 0)
return r;
r = udev_enumerate_scan_devices(e);
if (r < 0)
return r;
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
struct udev_device *p;
const char *status, *enabled, *dash, *nn, *i;
bool external = false;
d = udev_device_new_from_syspath(m->udev, udev_list_entry_get_name(item));
if (!d)
return -ENOMEM;
p = udev_device_get_parent(d);
if (!p)
continue;
/* If the parent shares the same subsystem as the
* device we are looking at then it is a connector,
* which is what we are interested in. */
if (!streq_ptr(udev_device_get_subsystem(p), "drm"))
continue;
nn = udev_device_get_sysname(d);
if (!nn)
continue;
/* Ignore internal displays: the type is encoded in
* the sysfs name, as the second dash seperated item
* (the first is the card name, the last the connector
* number). We implement a whitelist of external
* displays here, rather than a whitelist, to ensure
* we don't block suspends too eagerly. */
dash = strchr(nn, '-');
if (!dash)
continue;
dash++;
FOREACH_STRING(i, "VGA-", "DVI-I-", "DVI-D-", "DVI-A-"
"Composite-", "SVIDEO-", "Component-",
"DIN-", "DP-", "HDMI-A-", "HDMI-B-", "TV-") {
if (startswith(dash, i)) {
external = true;
break;
}
}
if (!external)
continue;
/* Ignore ports that are not enabled */
enabled = udev_device_get_sysattr_value(d, "enabled");
if (!enabled)
continue;
if (!streq_ptr(enabled, "enabled"))
continue;
/* We count any connector which is not explicitly
* "disconnected" as connected. */
status = udev_device_get_sysattr_value(d, "status");
if (!streq_ptr(status, "disconnected"))
n++;
}
return n;
}
bool manager_is_docked_or_external_displays(Manager *m) {
int n;
/* If we are docked don't react to lid closing */
if (manager_is_docked(m)) {
log_debug("System is docked.");
return true;
}
/* If we have more than one display connected,
* assume that we are docked. */
n = manager_count_external_displays(m);
if (n < 0)
log_warning_errno(n, "Display counting failed: %m");
else if (n >= 1) {
log_debug("External (%i) displays connected.", n);
return true;
}
return false;
}