- }
-
- closedir(d);
-
- return r;
-}
-
-int manager_dispatch_seat_udev(Manager *m) {
- struct udev_device *d;
- int r;
-
- assert(m);
-
- d = udev_monitor_receive_device(m->udev_seat_monitor);
- if (!d)
- return -ENOMEM;
-
- r = manager_process_seat_device(m, d);
- udev_device_unref(d);
-
- return r;
-}
-
-int manager_dispatch_vcsa_udev(Manager *m) {
- struct udev_device *d;
- int r = 0;
- const char *name;
-
- assert(m);
-
- d = udev_monitor_receive_device(m->udev_vcsa_monitor);
- if (!d)
- return -ENOMEM;
-
- name = udev_device_get_sysname(d);
-
- /* Whenever a VCSA device is removed try to reallocate our
- * VTs, to make sure our auto VTs never go away. */
-
- if (name && startswith(name, "vcsa") && streq_ptr(udev_device_get_action(d), "remove"))
- r = seat_preallocate_vts(m->vtconsole);
-
- udev_device_unref(d);
-
- return r;
-}
-
-int manager_dispatch_button_udev(Manager *m) {
- struct udev_device *d;
- int r;
-
- assert(m);
-
- d = udev_monitor_receive_device(m->udev_button_monitor);
- if (!d)
- return -ENOMEM;
-
- r = manager_process_button_device(m, d);
- udev_device_unref(d);
-
- return r;
-}
-
-int manager_dispatch_console(Manager *m) {
- assert(m);
-
- if (m->vtconsole)
- seat_read_active_vt(m->vtconsole);
-
- return 0;
-}
-
-static int vt_is_busy(int vtnr) {
- struct vt_stat vt_stat;
- int r = 0, 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));
-
- close_nointr_nofail(fd);
-
- return r;
-}
-
-int manager_spawn_autovt(Manager *m, int vtnr) {
- int r;
- char *name = NULL;
- const char *mode = "fail";
-
- assert(m);
- assert(vtnr >= 1);
-
- if ((unsigned) vtnr > m->n_autovts &&
- (unsigned) vtnr != m->reserve_vt)
- return 0;
-
- if ((unsigned) 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;
- }
-
- if (asprintf(&name, "autovt@tty%i.service", vtnr) < 0) {
- log_error("Could not allocate service name.");
- r = -ENOMEM;
- goto finish;
- }
-
- r = bus_method_call_with_reply (
- m->bus,
- "org.freedesktop.systemd1",
- "/org/freedesktop/systemd1",
- "org.freedesktop.systemd1.Manager",
- "StartUnit",
- NULL,
- NULL,
- DBUS_TYPE_STRING, &name,
- DBUS_TYPE_STRING, &mode,
- DBUS_TYPE_INVALID);
-
-finish:
- free(name);
-
- return r;
-}
-
-static int manager_reserve_vt(Manager *m) {
- _cleanup_free_ char *p = NULL;
-
- assert(m);
-
- if (m->reserve_vt <= 0)
- return 0;
-
- if (asprintf(&p, "/dev/tty%u", m->reserve_vt) < 0)
- return log_oom();
-
- m->reserve_vt_fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC|O_NONBLOCK);
- if (m->reserve_vt_fd < 0) {
-
- /* Don't complain on VT-less systems */
- if (errno != ENOENT)
- log_warning("Failed to pin reserved VT: %m");
- return -errno;
- }
-
- return 0;
-}
-
-int manager_get_session_by_cgroup(Manager *m, const char *cgroup, Session **session) {
- Session *s;
- char *p;
-
- assert(m);
- assert(cgroup);
- assert(session);
-
- s = hashmap_get(m->session_cgroups, cgroup);
- if (s) {
- *session = s;
- return 1;
- }
-
- p = strdup(cgroup);
- if (!p)
- return log_oom();
-
- for (;;) {
- char *e;
-
- e = strrchr(p, '/');
- if (!e || e == p) {
- free(p);
- *session = NULL;
- return 0;