logind-button.c revision 6de0e0e500d9d534c6e4baab242fc2a146f021fa
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering/***
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering This file is part of systemd.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Copyright 2012 Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is free software; you can redistribute it and/or modify it
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering under the terms of the GNU Lesser General Public License as published by
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering (at your option) any later version.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering systemd is distributed in the hope that it will be useful, but
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Lesser General Public License for more details.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering You should have received a copy of the GNU Lesser General Public License
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering***/
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <assert.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <string.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <errno.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <fcntl.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <sys/ioctl.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <unistd.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <linux/input.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include <sys/epoll.h>
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "conf-parser.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "util.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "logind-button.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "special.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering#include "dbus-common.h"
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart PoetteringButton* button_new(Manager *m, const char *name) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Button *b;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(m);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering b = new0(Button, 1);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!b)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering b->name = strdup(name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!b->name) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(b);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (hashmap_put(m->buttons, b->name, b) < 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(b->name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(b);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering b->manager = m;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering b->fd = -1;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return b;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringvoid button_free(Button *b) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(b);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering hashmap_remove(b->manager->buttons, b->name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (b->fd >= 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering hashmap_remove(b->manager->button_fds, INT_TO_PTR(b->fd + 1));
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert_se(epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_DEL, b->fd, NULL) == 0);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering close_nointr_nofail(b->fd);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(b->name);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(b->seat);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering free(b);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringint button_set_seat(Button *b, const char *sn) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering char *s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(b);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(sn);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = strdup(sn);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!s)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -ENOMEM;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering free(b->seat);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering b->seat = s;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering}
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringint button_open(Button *b) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering char name[256], *p;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering struct epoll_event ev;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering int r;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering assert(b);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (b->fd >= 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering close_nointr_nofail(b->fd);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering b->fd = -1;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering p = strappend("/dev/input/", b->name);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (!p) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_error("Out of memory");
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return -ENOMEM;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering b->fd = open(p, O_RDWR|O_CLOEXEC|O_NOCTTY|O_NONBLOCK);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering free(p);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (b->fd < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_warning("Failed to open %s: %m", b->name);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return -errno;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (ioctl(b->fd, EVIOCGNAME(sizeof(name)), name) < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_error("Failed to get input name: %m");
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = -errno;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering goto fail;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering zero(ev);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering ev.events = EPOLLIN;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering ev.data.u32 = FD_OTHER_BASE + b->fd;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_ADD, b->fd, &ev) < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_error("Failed to add to epoll: %m");
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = -errno;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering goto fail;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering r = hashmap_put(b->manager->button_fds, INT_TO_PTR(b->fd + 1), b);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (r < 0) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_error("Failed to add to hash map: %s", strerror(-r));
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering assert_se(epoll_ctl(b->manager->epoll_fd, EPOLL_CTL_DEL, b->fd, NULL) == 0);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering goto fail;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering log_info("Watching system buttons on /dev/input/%s (%s)", b->name, name);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return 0;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringfail:
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering close_nointr_nofail(b->fd);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering b->fd = -1;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poetteringstatic Session *button_get_session(Button *b) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering Seat *seat;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(b);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!b->seat)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering seat = hashmap_get(b->manager->seats, b->seat);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (!seat)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return NULL;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return seat->active;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering}
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poetteringstatic int button_power_off(Button *b, HandleButton handle) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering DBusError error;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering int r;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering assert(b);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (handle == HANDLE_OFF)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (handle == HANDLE_NO_SESSION) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (hashmap_size(b->manager->sessions) > 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Refusing power-off, user is logged in.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering warn_melody();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EPERM;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering } else if (handle == HANDLE_TTY_SESSION ||
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering handle == HANDLE_ANY_SESSION) {
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen unsigned n;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Session *s;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering n = hashmap_size(b->manager->sessions);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering s = button_get_session(b);
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering /* Silently ignore events of graphical sessions */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (handle == HANDLE_TTY_SESSION &&
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s && s->type == SESSION_X11)
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen return 0;
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering if (n > 1 || (n == 1 && !s)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Refusing power-off, other user is logged in.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering warn_melody();
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering return -EPERM;
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (handle != HANDLE_ALWAYS) {
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (manager_is_inhibited(b->manager, INHIBIT_SHUTDOWN, INHIBIT_BLOCK, NULL)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Refusing power-off, shutdown is inhibited.");
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering warn_melody();
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen return -EPERM;
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen }
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen }
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen log_info("Powering off...");
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen dbus_error_init(&error);
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, SPECIAL_POWEROFF_TARGET, INHIBIT_SHUTDOWN, &error);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering if (r < 0) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering log_error("Failed to power off: %s", bus_error_message(&error));
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen dbus_error_free(&error);
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering }
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen return r;
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen}
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersenstatic int button_suspend(Button *b, HandleButton handle) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering DBusError error;
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering int r;
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen assert(b);
636db02d54b64fb5bbad86c8015a9ef51299693bTom Gundersen
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (handle == HANDLE_OFF)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
6d0c65ffb4f82e8c6dceb453919b3db54343fc27Lennart Poettering if (handle == HANDLE_NO_SESSION) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (hashmap_size(b->manager->sessions) > 0) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Refusing suspend, user is logged in.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering warn_melody();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EPERM;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering } else if (handle == HANDLE_TTY_SESSION ||
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering handle == HANDLE_ANY_SESSION) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering unsigned n;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering Session *s;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering n = hashmap_size(b->manager->sessions);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s = button_get_session(b);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering /* Silently ignore events of graphical sessions */
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (handle == HANDLE_TTY_SESSION &&
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering s && s->type == SESSION_X11)
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return 0;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (n > 1 || (n == 1 && !s)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Refusing suspend, other user is logged in.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering warn_melody();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EPERM;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (handle != HANDLE_ALWAYS) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (manager_is_inhibited(b->manager, INHIBIT_SLEEP, INHIBIT_BLOCK, NULL)) {
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_error("Refusing suspend, sleeping is inhibited.");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering warn_melody();
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering return -EPERM;
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering }
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering log_info("Suspending...");
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering dbus_error_init(&error);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering r = bus_manager_shutdown_or_sleep_now_or_later(b->manager, SPECIAL_SUSPEND_TARGET, INHIBIT_SLEEP, &error);
ee8c45689526ca973407cbb77bce7b96a062c40bLennart Poettering if (r < 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_error("Failed to suspend: %s", bus_error_message(&error));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering dbus_error_free(&error);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return r;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering}
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringint button_process(Button *b) {
df3fb561b2df486a495a5f0bcc83168bd1860533Lennart Poettering struct input_event ev;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering ssize_t l;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering assert(b);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering l = read(b->fd, &ev, sizeof(ev));
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (l < 0)
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return errno != EAGAIN ? -errno : 0;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if ((size_t) l < sizeof(ev))
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return -EIO;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering if (ev.type == EV_KEY && ev.value > 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering switch (ev.code) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case KEY_POWER:
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case KEY_POWER2:
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_info("Power key pressed.");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return button_power_off(b, b->manager->handle_power_key);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case KEY_SLEEP:
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case KEY_SUSPEND:
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_info("Sleep key pressed.");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return button_suspend(b, b->manager->handle_sleep_key);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering } else if (ev.type == EV_SW && ev.value > 0) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering switch (ev.code) {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering case SW_LID:
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering log_info("Lid closed.");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return button_suspend(b, b->manager->handle_lid_switch);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering }
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering return 0;
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering}
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poetteringstatic const char* const handle_button_table[_HANDLE_BUTTON_MAX] = {
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering [HANDLE_OFF] = "off",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering [HANDLE_NO_SESSION] = "no-session",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering [HANDLE_TTY_SESSION] = "tty-session",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering [HANDLE_ANY_SESSION] = "any-session",
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering [HANDLE_ALWAYS] = "always"
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering};
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart PoetteringDEFINE_STRING_TABLE_LOOKUP(handle_button, HandleButton);
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart PoetteringDEFINE_CONFIG_PARSE_ENUM(config_parse_handle_button, handle_button, HandleButton, "Failed to parse handle button setting");
9085f64a6694f2928c79fcce365edb1dca6937d4Lennart Poettering