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 "dbus-common.h"
34 int manager_add_device(Manager *m, const char *sysfs, bool master, Device **_device) {
40 d = hashmap_get(m->devices, sysfs);
45 /* we support adding master-flags, but not removing them */
46 d->master = d->master || master;
51 d = device_new(m, sysfs, master);
61 int manager_add_seat(Manager *m, const char *id, Seat **_seat) {
67 s = hashmap_get(m->seats, id);
85 int manager_add_session(Manager *m, const char *id, Session **_session) {
91 s = hashmap_get(m->sessions, id);
99 s = session_new(m, id);
109 int manager_add_user(Manager *m, uid_t uid, gid_t gid, const char *name, User **_user) {
115 u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
123 u = user_new(m, uid, gid, name);
133 int manager_add_user_by_name(Manager *m, const char *name, User **_user) {
141 r = get_user_creds(&name, &uid, &gid, NULL, NULL);
145 return manager_add_user(m, uid, gid, name, _user);
148 int manager_add_user_by_uid(Manager *m, uid_t uid, User **_user) {
156 return errno ? -errno : -ENOENT;
158 return manager_add_user(m, uid, p->pw_gid, p->pw_name, _user);
161 int manager_add_inhibitor(Manager *m, const char* id, Inhibitor **_inhibitor) {
167 i = hashmap_get(m->inhibitors, id);
175 i = inhibitor_new(m, id);
185 int manager_add_button(Manager *m, const char *name, Button **_button) {
191 b = hashmap_get(m->buttons, name);
199 b = button_new(m, name);
209 int manager_watch_busname(Manager *m, const char *name) {
216 if (hashmap_get(m->busnames, name))
223 r = hashmap_put(m->busnames, n, n);
232 void manager_drop_busname(Manager *m, const char *name) {
240 if (!hashmap_get(m->busnames, name))
243 /* keep it if the name still owns a controller */
244 HASHMAP_FOREACH(session, m->sessions, i)
245 if (session_is_controller(session, name))
248 key = hashmap_remove(m->busnames, name);
253 int manager_process_seat_device(Manager *m, struct udev_device *d) {
259 if (streq_ptr(udev_device_get_action(d), "remove")) {
261 device = hashmap_get(m->devices, udev_device_get_syspath(d));
265 seat_add_to_gc_queue(device->seat);
273 sn = udev_device_get_property_value(d, "ID_SEAT");
277 if (!seat_name_is_valid(sn)) {
278 log_warning("Device with invalid seat name %s found, ignoring.", sn);
282 /* ignore non-master devices for unknown seats */
283 master = udev_device_has_tag(d, "master-of-seat");
284 if (!master && !(seat = hashmap_get(m->seats, sn)))
287 r = manager_add_device(m, udev_device_get_syspath(d), master, &device);
292 r = manager_add_seat(m, sn, &seat);
301 device_attach(device, seat);
308 int manager_process_button_device(Manager *m, struct udev_device *d) {
315 if (streq_ptr(udev_device_get_action(d), "remove")) {
317 b = hashmap_get(m->buttons, udev_device_get_sysname(d));
326 r = manager_add_button(m, udev_device_get_sysname(d), &b);
330 sn = udev_device_get_property_value(d, "ID_SEAT");
334 button_set_seat(b, sn);
341 int manager_get_session_by_pid(Manager *m, pid_t pid, Session **session) {
342 _cleanup_free_ char *unit = NULL;
352 r = cg_pid_get_unit(pid, &unit);
356 s = hashmap_get(m->session_units, unit);
364 int manager_get_user_by_pid(Manager *m, pid_t pid, User **user) {
365 _cleanup_free_ char *unit = NULL;
375 r = cg_pid_get_slice(pid, &unit);
379 u = hashmap_get(m->user_units, unit);
387 int manager_get_idle_hint(Manager *m, dual_timestamp *t) {
390 dual_timestamp ts = { 0, 0 };
395 idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false, false, 0);
397 HASHMAP_FOREACH(s, m->sessions, i) {
401 ih = session_get_idle_hint(s, &k);
407 if (k.monotonic < ts.monotonic)
413 } else if (idle_hint) {
415 if (k.monotonic > ts.monotonic)
426 bool manager_shall_kill(Manager *m, const char *user) {
430 if (!m->kill_user_processes)
433 if (strv_contains(m->kill_exclude_users, user))
436 if (strv_isempty(m->kill_only_users))
439 return strv_contains(m->kill_only_users, user);
442 static int vt_is_busy(int vtnr) {
443 struct vt_stat vt_stat;
448 /* We explicitly open /dev/tty1 here instead of /dev/tty0. If
449 * we'd open the latter we'd open the foreground tty which
450 * hence would be unconditionally busy. By opening /dev/tty1
451 * we avoid this. Since tty1 is special and needs to be an
452 * explicitly loaded getty or DM this is safe. */
454 fd = open_terminal("/dev/tty1", O_RDWR|O_NOCTTY|O_CLOEXEC);
458 if (ioctl(fd, VT_GETSTATE, &vt_stat) < 0)
461 r = !!(vt_stat.v_state & (1 << vtnr));
463 close_nointr_nofail(fd);
468 int manager_spawn_autovt(Manager *m, int vtnr) {
471 const char *mode = "fail";
476 if ((unsigned) vtnr > m->n_autovts &&
477 (unsigned) vtnr != m->reserve_vt)
480 if ((unsigned) vtnr != m->reserve_vt) {
481 /* If this is the reserved TTY, we'll start the getty
482 * on it in any case, but otherwise only if it is not
485 r = vt_is_busy(vtnr);
492 if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
493 log_error("Could not allocate service name.");
498 r = bus_method_call_with_reply (
500 "org.freedesktop.systemd1",
501 "/org/freedesktop/systemd1",
502 "org.freedesktop.systemd1.Manager",
506 DBUS_TYPE_STRING, &name,
507 DBUS_TYPE_STRING, &mode,