m->udev_vcsa_fd = -1;
m->udev_button_fd = -1;
m->epoll_fd = -1;
+ m->reserve_vt_fd = -1;
m->n_autovts = 6;
+ m->reserve_vt = 6;
m->inhibit_delay_max = 5 * USEC_PER_SEC;
- m->handle_power_key = HANDLE_NO_SESSION;
- m->handle_sleep_key = HANDLE_TTY_SESSION;
- m->handle_lid_switch = HANDLE_OFF;
+ m->handle_power_key = HANDLE_POWEROFF;
+ m->handle_sleep_key = HANDLE_SUSPEND;
+ m->handle_lid_switch = HANDLE_SUSPEND;
+ m->lid_switch_ignore_inhibited = true;
m->devices = hashmap_new(string_hash_func, string_compare_func);
m->seats = hashmap_new(string_hash_func, string_compare_func);
if (m->epoll_fd >= 0)
close_nointr_nofail(m->epoll_fd);
+ if (m->reserve_vt_fd >= 0)
+ close_nointr_nofail(m->reserve_vt_fd);
+
strv_free(m->controllers);
strv_free(m->reset_controllers);
strv_free(m->kill_only_users);
/* Loads buttons from udev */
- if (m->handle_power_key == HANDLE_OFF &&
- m->handle_sleep_key == HANDLE_OFF &&
- m->handle_lid_switch == HANDLE_OFF)
+ if (m->handle_power_key == HANDLE_IGNORE &&
+ m->handle_sleep_key == HANDLE_IGNORE &&
+ m->handle_lid_switch == HANDLE_IGNORE)
return 0;
e = udev_enumerate_new(m->udev);
assert(m);
assert(vtnr >= 1);
- if ((unsigned) vtnr > m->n_autovts)
+ if ((unsigned) vtnr > m->n_autovts &&
+ (unsigned) vtnr != m->reserve_vt)
return 0;
- r = vt_is_busy(vtnr);
- if (r < 0)
- return r;
- else if (r > 0)
- return -EBUSY;
+ 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",
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;
return -errno;
/* Don't watch keys if nobody cares */
- if (m->handle_power_key != HANDLE_OFF ||
- m->handle_sleep_key != HANDLE_OFF ||
- m->handle_lid_switch != HANDLE_OFF) {
+ if (m->handle_power_key != HANDLE_IGNORE ||
+ m->handle_sleep_key != HANDLE_IGNORE ||
+ m->handle_lid_switch != HANDLE_IGNORE) {
m->udev_button_monitor = udev_monitor_new_from_netlink(m->udev, "udev");
if (!m->udev_button_monitor)
assert(m);
- idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t);
+ idle_hint = !manager_is_inhibited(m, INHIBIT_IDLE, INHIBIT_BLOCK, t, false);
HASHMAP_FOREACH(s, m->sessions, i) {
dual_timestamp k;
/* Remove stale objects before we start them */
manager_gc(m, false);
+ /* Reserve the special reserved VT */
+ manager_reserve_vt(m);
+
/* And start everything */
HASHMAP_FOREACH(seat, m->seats, i)
seat_start(seat);
return 0;
}
+static int manager_recheck_buttons(Manager *m) {
+ Iterator i;
+ Button *b;
+ int r = 0;
+
+ assert(m);
+
+ HASHMAP_FOREACH(b, m->buttons, i) {
+ int q;
+
+ q = button_recheck(b);
+ if (q > 0)
+ return 1;
+ if (q < 0)
+ r = q;
+ }
+
+ return r;
+}
+
int manager_run(Manager *m) {
assert(m);
if (manager_dispatch_delayed(m) > 0)
continue;
+ if (manager_recheck_buttons(m) > 0)
+ continue;
+
if (dbus_connection_dispatch(m->bus) != DBUS_DISPATCH_COMPLETE)
continue;