logind-dbus.c revision c2a23db0b91faca3795099fd4b41587bac170ff7
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen/***
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen This file is part of systemd.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Copyright 2011 Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is free software; you can redistribute it and/or modify it
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen under the terms of the GNU Lesser General Public License as published by
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen the Free Software Foundation; either version 2.1 of the License, or
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (at your option) any later version.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen systemd is distributed in the hope that it will be useful, but
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen WITHOUT ANY WARRANTY; without even the implied warranty of
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Lesser General Public License for more details.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen You should have received a copy of the GNU Lesser General Public License
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen***/
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <errno.h>
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include <string.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <unistd.h>
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen#include <pwd.h>
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
b5efdb8af40ea759a1ea584c1bc44ecc81dd00ceLennart Poettering#include "sd-messages.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "strv.h"
3ffd4af22052963e7a29431721ee204e634bea75Lennart Poettering#include "mkdir.h"
a5a807e63a50314e190e9166d8a453cd8dd258e3Zbigniew Jędrzejewski-Szmek#include "path-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "special.h"
c004493cdefc1f43a3956ca529e8070f8d70be56Lennart Poettering#include "sleep-config.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "fileio-label.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "unit-name.h"
822db23cfa98a9fbc48f41e11caafb6f1017e052Lennart Poettering#include "audit.h"
6bedfcbb2970e06a4d3280c8fb62083d252ede73Lennart Poettering#include "bus-util.h"
3df3e884ae1237ef0d4d23b0e80f4ffda95ac135Ronny Chevalier#include "bus-error.h"
39d8db043b599a7382f94bfc904d5e108af438bdLennart Poettering#include "bus-common-errors.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "udev-util.h"
5f402ae84bbc08fe8de5682e371b3f66c387da52Daniel Mack#include "selinux-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "efivars.h"
f8dc7e343d903f053070d01f3273db819deee951Lennart Poettering#include "logind.h"
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack#include "formats-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "process-util.h"
8b43440b7ef4b81c69c31de7ff820dc07a780254Lennart Poettering#include "terminal-util.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering#include "utmp-wtmp.h"
07630cea1f3a845c09309f197ac7c4f11edd3b62Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_session_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Session **ret) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Session *session;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(message);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(ret);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(name)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_SESSION|SD_BUS_CREDS_AUGMENT, &creds);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_creds_get_session(creds, &name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering session = hashmap_get(m->sessions, name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!session)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SESSION, "No session '%s' known", name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *ret = session;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering}
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_user_from_creds(Manager *m, sd_bus_message *message, uid_t uid, sd_bus_error *error, User **ret) {
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering User *user;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(message);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(ret);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (uid == UID_INVALID) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering /* Note that we get the owner UID of the session, not the actual client UID here! */
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering if (r < 0)
21d73c87b09ec2b8642424bc714ce9af3da4fc40Lennart Poettering return r;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering r = sd_bus_creds_get_owner_uid(creds, &uid);
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering user = hashmap_get(m->users, UID_TO_PTR(uid));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!user)
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_USER, "No user "UID_FMT" known or logged in", uid);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *ret = user;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringint manager_get_seat_from_creds(Manager *m, sd_bus_message *message, const char *name, sd_bus_error *error, Seat **ret) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Seat *seat;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(message);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(ret);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen if (isempty(name)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Session *session;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_get_session_from_creds(m, message, NULL, error, &session);
0dd25fb9f005d8ab7ac4bc10a609d00569f8c56aLennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering seat = session->seat;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "Session has no seat.");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen seat = hashmap_get(m->seats, name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering *ret = seat;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int property_get_idle_hint(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus *bus,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *path,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *interface,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *property,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_message *reply,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen assert(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_message_append(reply, "b", manager_get_idle_hint(m, NULL) > 0);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int property_get_idle_since_hint(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus *bus,
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen const char *path,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *interface,
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen const char *property,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_message *reply,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering dual_timestamp t;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering manager_get_idle_hint(m, &t);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_message_append(reply, "t", streq(property, "IdleSinceHint") ? t.realtime : t.monotonic);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int property_get_inhibited(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus *bus,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *path,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *interface,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *property,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_message *reply,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering InhibitWhat w;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
3e044c492e3ebe64f4e3175c94f9db8a62557b82Markus Elfring assert(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_message_append(reply, "s", inhibit_what_to_string(w));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int property_get_preparing(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus *bus,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *path,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *interface,
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poettering const char *property,
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen sd_bus_message *reply,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering void *userdata,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
cc98b3025eeb89addb76a27390cb2baca4eab8b9Torstein Husebø bool b;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (streq(property, "PreparingForShutdown"))
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering b = !!(m->action_what & INHIBIT_SHUTDOWN);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen b = !!(m->action_what & INHIBIT_SLEEP);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_message_append(reply, "b", b);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int property_get_scheduled_shutdown(
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus *bus,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *path,
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen const char *interface,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *property,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering sd_bus_message *reply,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen void *userdata,
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_bus_message_open_container(reply, 'r', "st");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen r = sd_bus_message_append(reply, "st", m->scheduled_shutdown_type, m->scheduled_shutdown_timeout);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return sd_bus_message_close_container(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic BUS_DEFINE_PROPERTY_GET_ENUM(property_get_handle_action, handle_action, HandleAction);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int method_get_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen _cleanup_free_ char *p = NULL;
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *name;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Session *session;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(message);
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_message_read(message, "s", &name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_get_session_from_creds(m, message, name, error, &session);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1c4baffc1895809bae9ac36b670af90a4cb9cd7dTom Gundersen return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p = session_bus_path(session);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!p)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int method_get_session_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *p = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Session *session = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering pid_t pid;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(message);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert_cc(sizeof(pid_t) == sizeof(uint32_t));
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt r = sd_bus_message_read(message, "u", &pid);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (pid <= 0) {
da927ba997d68401563b927f92e6e40e021a8e5cMichal Schmidt r = manager_get_session_from_creds(m, message, NULL, error, &session);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_get_session_by_pid(m, pid, &session);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!session)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID, "PID "PID_FMT" does not belong to any known session", pid);
0014a4ad505d119c7ac4346d9d774c3f17f663a5Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p = session_bus_path(session);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!p)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int method_get_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *p = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering uint32_t uid;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering User *user;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(message);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_message_read(message, "u", &uid);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = manager_get_user_from_creds(m, message, uid, error, &user);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering p = user_bus_path(user);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (!p)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return -ENOMEM;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int method_get_user_by_pid(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering _cleanup_free_ char *p = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering Manager *m = userdata;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering User *user = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering pid_t pid;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(bus);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(message);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(m);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert_cc(sizeof(pid_t) == sizeof(uint32_t));
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_read(message, "u", &pid);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (pid <= 0) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = manager_get_user_from_creds(m, message, UID_INVALID, error, &user);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
422baca0f230913158078fddf884e06c8c64a316Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering } else {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = manager_get_user_by_pid(m, pid, &user);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (!user)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID, "PID "PID_FMT" does not belong to any known or logged in user", pid);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering p = user_bus_path(user);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (!p)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return -ENOMEM;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int method_get_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ char *p = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering Manager *m = userdata;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering const char *name;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering Seat *seat;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(bus);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(message);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(m);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_message_read(message, "s", &name);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = manager_get_seat_from_creds(m, message, name, error, &seat);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering p = seat_bus_path(seat);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (!p)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return -ENOMEM;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return sd_bus_reply_method_return(message, "o", p);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poetteringstatic int method_list_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering Manager *m = userdata;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering Session *session;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering Iterator i;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering int r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(bus);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(message);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
56f64d95763a799ba4475daf44d8e9f72a1bd474Michal Schmidt return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(susso)");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering HASHMAP_FOREACH(session, m->sessions, i) {
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering _cleanup_free_ char *p = NULL;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt p = session_bus_path(session);
8d3d7072e609ef0e0fb37e1d19a29307d58146c3Michal Schmidt if (!p)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return -ENOMEM;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_append(reply, "(susso)",
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering session->id,
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering (uint32_t) session->user->uid,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering session->user->name,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering session->seat ? session->seat->id : "",
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering p);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering }
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_message_close_container(reply);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return sd_bus_send(bus, reply, NULL);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poetteringstatic int method_list_users(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering Manager *m = userdata;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering User *user;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering Iterator i;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering int r;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(bus);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(message);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering assert(m);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (r < 0)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return r;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(uso)");
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (r < 0)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return r;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering HASHMAP_FOREACH(user, m->users, i) {
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering _cleanup_free_ char *p = NULL;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering p = user_bus_path(user);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering if (!p)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = sd_bus_message_append(reply, "(uso)",
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (uint32_t) user->uid,
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering user->name,
c92e531c82a9815ec349aa1bf31236b86b2d5311Lennart Poettering p);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_bus_message_close_container(reply);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return sd_bus_send(bus, reply, NULL);
af49ca27ffd790d78dbbb465b978266dfd5c93daLennart Poettering}
5cb36f41f01cf4b1f4395abfffd1b33116591e58Lennart Poettering
00fa60ae3b2823036cb3e7734f16bce30cb7441dLennart Poetteringstatic int method_list_seats(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering Manager *m = userdata;
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering Seat *seat;
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering Iterator i;
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering int r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(bus);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(message);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen assert(m);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = sd_bus_message_new_method_return(message, &reply);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return r;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(so)");
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering HASHMAP_FOREACH(seat, m->seats, i) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_free_ char *p = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering p = seat_bus_path(seat);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!p)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_message_append(reply, "(so)", seat->id, p);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_message_close_container(reply);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return sd_bus_send(bus, reply, NULL);
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering}
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersenstatic int method_list_inhibitors(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Manager *m = userdata;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Inhibitor *inhibitor;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen Iterator i;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering int r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering r = sd_bus_message_new_method_return(message, &reply);
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (r < 0)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering r = sd_bus_message_open_container(reply, 'a', "(ssssuu)");
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering if (r < 0)
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering return r;
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack r = sd_bus_message_append(reply, "(ssssuu)",
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering strempty(inhibit_what_to_string(inhibitor->what)),
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering strempty(inhibitor->who),
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering strempty(inhibitor->why),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering strempty(inhibit_mode_to_string(inhibitor->mode)),
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (uint32_t) inhibitor->uid,
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen (uint32_t) inhibitor->pid);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering
4b95f1798f22c1bb75295f448188560cb6ec9eceLennart Poettering r = sd_bus_message_close_container(reply);
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering if (r < 0)
a51c10485af349eb15faa4d1a63b9818bcf3e589Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_send(bus, reply, NULL);
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering}
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poetteringstatic int method_create_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *service, *type, *class, *cseat, *tty, *display, *remote_user, *remote_host, *desktop;
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering uint32_t uid, leader, audit_id = 0;
cab5b05903096e1c9cf5575ccc73f89d15c8db69Lennart Poettering _cleanup_free_ char *id = NULL;
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering Session *session = NULL;
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering Manager *m = userdata;
f0e1546763304aedc90e91d70dab9eeb7c966cf8Lennart Poettering User *user = NULL;
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering Seat *seat = NULL;
096b6773886bd7a0c8c97aa684b0b67dfae58355Lennart Poettering int remote;
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen uint32_t vtnr = 0;
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering SessionType t;
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering SessionClass c;
a564ca2fd113b2876e677beab60b38d50591e246Lennart Poettering int r;
edc501d4674dadc304d45a7e1c5b69e207eb8cd4Lennart Poettering
bc7702b098b63031767174206f5df14a8ccb45cfDaniel Mack assert(bus);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(message);
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_message_read(message, "uusssssussbss", &uid, &leader, &service, &type, &class, &desktop, &cseat, &vtnr, &tty, &display, &remote, &remote_user, &remote_host);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (r < 0)
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering return r;
4d506d6bb757af3b99e0876234c465e6898c5ea4Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (leader == 1)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid leader PID");
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (isempty(type))
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering t = _SESSION_TYPE_INVALID;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering else {
d9fcf2ba1abe81ed3a7a151d6db09139b4dc7a09Lennart Poettering t = session_type_from_string(type);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (t < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session type %s", type);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering }
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering
0d2cd47617b423f37d7425be7a56ae2fca8ff9f6Lennart Poettering if (isempty(class))
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen c = _SESSION_CLASS_INVALID;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering c = session_class_from_string(class);
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (c < 0)
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid session class %s", class);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (isempty(desktop))
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering desktop = NULL;
40a1eebde6be7ac3f1885147fc24e06ad1da260cDavid Herrmann else {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!string_is_safe(desktop))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid desktop string %s", desktop);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (isempty(cseat))
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering seat = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering seat = hashmap_get(m->seats, cseat);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_SEAT, "No seat '%s' known", cseat);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (tty_is_vc(tty)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int v;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!seat)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering seat = m->seat0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (seat != m->seat0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "TTY %s is virtual console but seat %s is not seat0", tty, seat->id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering v = vtnr_from_tty(tty);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (v <= 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Cannot determine VT number from virtual console TTY %s", tty);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!vtnr)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering vtnr = (uint32_t) v;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (vtnr != (uint32_t) v)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified TTY and VT number do not match");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering } else if (tty_is_console(tty)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!seat)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering seat = m->seat0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else if (seat != m->seat0)
a38d99451f2bf8026ec51aee91662292e823c6a8Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but seat is not seat0");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
ad867662936a4c7ab2c7116d804c272338801231Lennart Poettering if (vtnr != 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Console TTY specified but VT number is not 0");
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (seat) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen if (seat_has_vts(seat)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!vtnr || vtnr > 63)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "VT number out of range");
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen } else {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (vtnr != 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat has no VTs but VT number not 0");
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_bus_message_enter_container(message, 'a', "(sv)");
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (t == _SESSION_TYPE_INVALID) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (!isempty(display))
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering t = SESSION_X11;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering else if (!isempty(tty))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering t = SESSION_TTY;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering else
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering t = SESSION_UNSPECIFIED;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
2a1288ff89322a2f49c79f6d1832c8164c14a05cLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (c == _SESSION_CLASS_INVALID) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (t == SESSION_UNSPECIFIED)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering c = SESSION_BACKGROUND;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering else
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering c = SESSION_USER;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (leader <= 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_PID, &creds);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_bus_creds_get_pid(creds, (pid_t*) &leader);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering manager_get_session_by_pid(m, leader, &session);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (session) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering _cleanup_free_ char *path = NULL;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering _cleanup_close_ int fifo_fd = -1;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering /* Session already exists, client is probably
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * something like "su" which changes uid but is still
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering * the same session */
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen fifo_fd = session_create_fifo(session);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (fifo_fd < 0)
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return fifo_fd;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering path = session_bus_path(session);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (!path)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering log_debug("Sending reply about an existing session: "
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering "id=%s object_path=%s uid=%u runtime_path=%s "
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering "session_fd=%d seat=%s vtnr=%u",
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering session->id,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering path,
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering (uint32_t) session->user->uid,
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering session->user->runtime_path,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering fifo_fd,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering session->seat ? session->seat->id : "",
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering (uint32_t) session->vtnr);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
a5f035960006556beab51c42e6948985635e261aLennart Poettering return sd_bus_reply_method_return(
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering message, "soshusub",
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering session->id,
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen path,
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen session->user->runtime_path,
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen fifo_fd,
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen (uint32_t) session->user->uid,
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen session->seat ? session->seat->id : "",
86ad4cd709ced8daf2b75ab564dece1ce82ffed9Tom Gundersen (uint32_t) session->vtnr,
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering true);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering audit_session_from_pid(leader, &audit_id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (audit_id > 0) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Keep our session IDs and the audit session IDs in sync */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (asprintf(&id, "%"PRIu32, audit_id) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Wut? There's already a session by this name and we
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * didn't find it above? Weird, then let's not trust
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * the audit data and let's better register a new
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * ID */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (hashmap_get(m->sessions, id)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering log_warning("Existing logind session ID %s used by new audit session, ignoring", id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering audit_id = 0;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free(id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering id = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!id) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering do {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering free(id);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering id = NULL;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (asprintf(&id, "c%lu", ++m->session_counter) < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen } while (hashmap_get(m->sessions, id));
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen r = manager_add_user_by_uid(m, uid, &user);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (r < 0)
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen goto fail;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen r = manager_add_session(m, id, &session);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (r < 0)
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen goto fail;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session_set_user(session, user);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session->leader = leader;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session->audit_id = audit_id;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session->type = t;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session->class = c;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session->remote = remote;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session->vtnr = vtnr;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (!isempty(tty)) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session->tty = strdup(tty);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (!session->tty) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen r = -ENOMEM;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen goto fail;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
deb3f3d335d64601bb2d8a7520d8303f99d8a071Lennart Poettering
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (!isempty(display)) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen session->display = strdup(display);
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen if (!session->display) {
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen r = -ENOMEM;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen goto fail;
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen }
72290734be81e83e6ef9520c07692f68095eb5b2Tom Gundersen
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (!isempty(remote_user)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering session->remote_user = strdup(remote_user);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!session->remote_user) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -ENOMEM;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!isempty(remote_host)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering session->remote_host = strdup(remote_host);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!session->remote_host) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = -ENOMEM;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!isempty(service)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering session->service = strdup(service);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!session->service) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = -ENOMEM;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering goto fail;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering }
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!isempty(desktop)) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering session->desktop = strdup(desktop);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (!session->desktop) {
091a364c802e34a58f3260c9cb5db9b75c62215cTom Gundersen r = -ENOMEM;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (seat) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = seat_attach_session(seat, session);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering }
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = session_start(session);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering goto fail;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering session->create_message = sd_bus_message_ref(message);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering /* Now, let's wait until the slice unit and stuff got
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * created. We send the reply back from
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering * session_send_create_reply(). */
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return 1;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringfail:
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (session)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering session_add_to_gc_queue(session);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (user)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering user_add_to_gc_queue(user);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int method_release_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering Manager *m = userdata;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering Session *session;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering const char *name;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(message);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = sd_bus_message_read(message, "s", &name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = manager_get_session_from_creds(m, message, name, error, &session);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = session_release(session);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return sd_bus_reply_method_return(message, NULL);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poetteringstatic int method_activate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Manager *m = userdata;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Session *session;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering const char *name;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering int r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(bus);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(message);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering assert(m);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering r = sd_bus_message_read(message, "s", &name);
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering if (r < 0)
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering return r;
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering r = manager_get_session_from_creds(m, message, name, error, &session);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering if (r < 0)
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering return bus_session_method_activate(bus, message, session, error);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering}
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
deb3f3d335d64601bb2d8a7520d8303f99d8a071Lennart Poetteringstatic int method_activate_session_on_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
a2a416f768e2aa7db5b975cd50eb19237cac9cceLennart Poettering const char *session_name, *seat_name;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering Manager *m = userdata;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering Session *session;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering Seat *seat;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering int r;
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(bus);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(message);
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering assert(m);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering /* Same as ActivateSession() but refuses to work if
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering * the seat doesn't match */
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering r = sd_bus_message_read(message, "ss", &session_name, &seat_name);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (r < 0)
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering r = manager_get_session_from_creds(m, message, session_name, error, &session);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (r < 0)
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering r = manager_get_seat_from_creds(m, message, seat_name, error, &seat);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (r < 0)
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return r;
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering if (session->seat != seat)
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering return sd_bus_error_setf(error, BUS_ERROR_SESSION_NOT_ON_SEAT, "Session %s not on seat %s", session_name, seat_name);
e1c959948c0e31d6997bcdfbabfbd077784b2baeLennart Poettering
1716f6dcf54d4c181c2e2558e3d5414f54c8d9caLennart Poettering r = session_activate(session);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (r < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return sd_bus_reply_method_return(message, NULL);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic int method_lock_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering Manager *m = userdata;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering Session *session;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering const char *name;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(bus);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(message);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering assert(m);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = sd_bus_message_read(message, "s", &name);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering r = manager_get_session_from_creds(m, message, name, error, &session);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering if (r < 0)
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return r;
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering return bus_session_method_lock(bus, message, session, error);
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poetteringstatic int method_lock_sessions(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering Manager *m = userdata;
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering int r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(bus);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(message);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = bus_verify_polkit_async(
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering message,
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering CAP_SYS_ADMIN,
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering "org.freedesktop.login1.lock-sessions",
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering false,
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering UID_INVALID,
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering &m->polkit_registry,
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering error);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r == 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return 1; /* Will call us back */
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering r = session_send_lock_all(m, streq(sd_bus_message_get_member(message), "LockSessions"));
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering if (r < 0)
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering return r;
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering return sd_bus_reply_method_return(message, NULL);
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering}
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poetteringstatic int method_kill_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
556a22945fcc88ca27ae7ecc46c9bb2727e37895Lennart Poettering const char *name;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering Manager *m = userdata;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering Session *session;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(bus);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(message);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(m);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_read(message, "s", &name);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = manager_get_session_from_creds(m, message, name, error, &session);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return bus_session_method_kill(bus, message, session, error);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
eb60f9cd4e93ff5016dc1b5486fd1b7e1565fd92Lennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int method_kill_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering Manager *m = userdata;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering uint32_t uid;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering User *user;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(bus);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(message);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering assert(m);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = sd_bus_message_read(message, "u", &uid);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering r = manager_get_user_from_creds(m, message, uid, error, &user);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering if (r < 0)
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering return bus_user_method_kill(bus, message, user, error);
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering}
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poetteringstatic int method_terminate_session(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering Manager *m = userdata;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering const char *name;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering Session *session;
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering int r;
ec2c5e4398f9d65e5dfe61530f2556224733d1e6Lennart Poettering
4e945a6f7971fd7d1f6b2c62ee3afdaff3c95ce4Lennart Poettering assert(bus);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering assert(message);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering assert(m);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering r = sd_bus_message_read(message, "s", &name);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (r < 0)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return r;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering r = manager_get_session_from_creds(m, message, name, error, &session);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (r < 0)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return r;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack return bus_session_method_terminate(bus, message, session, error);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering}
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poetteringstatic int method_terminate_user(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering Manager *m = userdata;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack uint32_t uid;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack User *user;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack int r;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack assert(bus);
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack assert(message);
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack assert(m);
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack r = sd_bus_message_read(message, "u", &uid);
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack if (r < 0)
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack return r;
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack
b4f1862df2e45aba90386887d685b8bf3c840e10Daniel Mack r = manager_get_user_from_creds(m, message, uid, error, &user);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering if (r < 0)
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return r;
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering return bus_user_method_terminate(bus, message, user, error);
a407657425a3e47fd2b559cd3bc800f791303f63Lennart Poettering}
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poetteringstatic int method_terminate_seat(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering Manager *m = userdata;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering const char *name;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering Seat *seat;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering int r;
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering assert(bus);
902bb5d8abb2a7d258741828d212ca549ab16950Lennart Poettering assert(message);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering assert(m);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = sd_bus_message_read(message, "s", &name);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering r = manager_get_seat_from_creds(m, message, name, error, &seat);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering if (r < 0)
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering return bus_seat_method_terminate(bus, message, seat, error);
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering}
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poetteringstatic int method_set_user_linger(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering _cleanup_free_ char *cc = NULL;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering Manager *m = userdata;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering int b, r;
78c6a153c47f8d597c827bdcaf8c4e42ac87f738Lennart Poettering struct passwd *pw;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering const char *path;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering uint32_t uid;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering int interactive;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(bus);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(message);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering assert(m);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = sd_bus_message_read(message, "ubb", &uid, &b, &interactive);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (r < 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return r;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (uid == UID_INVALID) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering /* Note that we get the owner UID of the session, not the actual client UID here! */
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_OWNER_UID|SD_BUS_CREDS_AUGMENT, &creds);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (r < 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return r;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = sd_bus_creds_get_owner_uid(creds, &uid);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (r < 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return r;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering }
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering errno = 0;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering pw = getpwuid(uid);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (!pw)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return errno ? -errno : -ENOENT;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = bus_verify_polkit_async(
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering message,
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering CAP_SYS_ADMIN,
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering "org.freedesktop.login1.set-user-linger",
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering interactive,
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering UID_INVALID,
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering &m->polkit_registry,
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering error);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (r < 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return r;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (r == 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering mkdir_p_label("/var/lib/systemd", 0755);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (r < 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return r;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering cc = cescape(pw->pw_name);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (!cc)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return -ENOMEM;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering path = strjoina("/var/lib/systemd/linger/", cc);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (b) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering User *u;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = touch(path);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (r < 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return r;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (manager_add_user_by_uid(m, uid, &u) >= 0)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering user_start(u);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering } else {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering User *u;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering r = unlink(path);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (r < 0 && errno != ENOENT)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return -errno;
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering u = hashmap_get(m->users, UID_TO_PTR(uid));
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering if (u)
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering user_add_to_gc_queue(u);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering }
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering return sd_bus_reply_method_return(message, NULL);
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering}
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poetteringstatic int trigger_device(Manager *m, struct udev_device *d) {
9176a57c101d51b4a7fb4141240b5ce03abac57dLennart Poettering _cleanup_udev_enumerate_unref_ struct udev_enumerate *e = NULL;
struct udev_list_entry *first, *item;
int r;
assert(m);
e = udev_enumerate_new(m->udev);
if (!e)
return -ENOMEM;
if (d) {
r = udev_enumerate_add_match_parent(e, d);
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_free_ char *t = NULL;
const char *p;
p = udev_list_entry_get_name(item);
t = strappend(p, "/uevent");
if (!t)
return -ENOMEM;
write_string_file(t, "change");
}
return 0;
}
static int attach_device(Manager *m, const char *seat, const char *sysfs) {
_cleanup_udev_device_unref_ struct udev_device *d = NULL;
_cleanup_free_ char *rule = NULL, *file = NULL;
const char *id_for_seat;
int r;
assert(m);
assert(seat);
assert(sysfs);
d = udev_device_new_from_syspath(m->udev, sysfs);
if (!d)
return -ENODEV;
if (!udev_device_has_tag(d, "seat"))
return -ENODEV;
id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
if (!id_for_seat)
return -ENODEV;
if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0)
return -ENOMEM;
if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0)
return -ENOMEM;
mkdir_p_label("/etc/udev/rules.d", 0755);
mac_selinux_init("/etc");
r = write_string_file_atomic_label(file, rule);
if (r < 0)
return r;
return trigger_device(m, d);
}
static int flush_devices(Manager *m) {
_cleanup_closedir_ DIR *d;
assert(m);
d = opendir("/etc/udev/rules.d");
if (!d) {
if (errno != ENOENT)
log_warning_errno(errno, "Failed to open /etc/udev/rules.d: %m");
} else {
struct dirent *de;
while ((de = readdir(d))) {
if (!dirent_is_file(de))
continue;
if (!startswith(de->d_name, "72-seat-"))
continue;
if (!endswith(de->d_name, ".rules"))
continue;
if (unlinkat(dirfd(d), de->d_name, 0) < 0)
log_warning_errno(errno, "Failed to unlink %s: %m", de->d_name);
}
}
return trigger_device(m, NULL);
}
static int method_attach_device(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *sysfs, *seat;
Manager *m = userdata;
int interactive, r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "ssb", &seat, &sysfs, &interactive);
if (r < 0)
return r;
if (!path_startswith(sysfs, "/sys"))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not in /sys", sysfs);
if (!seat_name_is_valid(seat))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Seat %s is not valid", seat);
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.attach-device",
interactive,
UID_INVALID,
&m->polkit_registry,
error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = attach_device(m, seat, sysfs);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int method_flush_devices(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
int interactive, r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "b", &interactive);
if (r < 0)
return r;
r = bus_verify_polkit_async(
message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.flush-devices",
interactive,
UID_INVALID,
&m->polkit_registry,
error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = flush_devices(m);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int have_multiple_sessions(
Manager *m,
uid_t uid) {
Session *session;
Iterator i;
assert(m);
/* Check for other users' sessions. Greeter sessions do not
* count, and non-login sessions do not count either. */
HASHMAP_FOREACH(session, m->sessions, i)
if (session->class == SESSION_USER &&
session->user->uid != uid)
return true;
return false;
}
static int bus_manager_log_shutdown(
Manager *m,
InhibitWhat w,
const char *unit_name) {
const char *p, *q;
assert(m);
assert(unit_name);
if (w != INHIBIT_SHUTDOWN)
return 0;
if (streq(unit_name, SPECIAL_POWEROFF_TARGET)) {
p = "MESSAGE=System is powering down.";
q = "SHUTDOWN=power-off";
} else if (streq(unit_name, SPECIAL_HALT_TARGET)) {
p = "MESSAGE=System is halting.";
q = "SHUTDOWN=halt";
} else if (streq(unit_name, SPECIAL_REBOOT_TARGET)) {
p = "MESSAGE=System is rebooting.";
q = "SHUTDOWN=reboot";
} else if (streq(unit_name, SPECIAL_KEXEC_TARGET)) {
p = "MESSAGE=System is rebooting with kexec.";
q = "SHUTDOWN=kexec";
} else {
p = "MESSAGE=System is shutting down.";
q = NULL;
}
return log_struct(LOG_NOTICE,
LOG_MESSAGE_ID(SD_MESSAGE_SHUTDOWN),
p,
q,
NULL);
}
static int lid_switch_ignore_handler(sd_event_source *e, uint64_t usec, void *userdata) {
Manager *m = userdata;
assert(e);
assert(m);
m->lid_switch_ignore_event_source = sd_event_source_unref(m->lid_switch_ignore_event_source);
return 0;
}
int manager_set_lid_switch_ignore(Manager *m, usec_t until) {
int r;
assert(m);
if (until <= now(CLOCK_MONOTONIC))
return 0;
/* We want to ignore the lid switch for a while after each
* suspend, and after boot-up. Hence let's install a timer for
* this. As long as the event source exists we ignore the lid
* switch. */
if (m->lid_switch_ignore_event_source) {
usec_t u;
r = sd_event_source_get_time(m->lid_switch_ignore_event_source, &u);
if (r < 0)
return r;
if (until <= u)
return 0;
r = sd_event_source_set_time(m->lid_switch_ignore_event_source, until);
} else
r = sd_event_add_time(
m->event,
&m->lid_switch_ignore_event_source,
CLOCK_MONOTONIC,
until, 0,
lid_switch_ignore_handler, m);
return r;
}
static int execute_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *unit_name,
sd_bus_error *error) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
const char *p;
char *c;
int r;
assert(m);
assert(w >= 0);
assert(w < _INHIBIT_WHAT_MAX);
assert(unit_name);
bus_manager_log_shutdown(m, w, unit_name);
r = sd_bus_call_method(
m->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit",
error,
&reply,
"ss", unit_name, "replace-irreversibly");
if (r < 0)
return r;
r = sd_bus_message_read(reply, "o", &p);
if (r < 0)
return r;
c = strdup(p);
if (!c)
return -ENOMEM;
m->action_unit = unit_name;
free(m->action_job);
m->action_job = c;
m->action_what = w;
/* Make sure the lid switch is ignored for a while */
manager_set_lid_switch_ignore(m, now(CLOCK_MONOTONIC) + m->holdoff_timeout_usec);
return 0;
}
static int manager_inhibit_timeout_handler(
sd_event_source *s,
uint64_t usec,
void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
Inhibitor *offending = NULL;
Manager *manager = userdata;
int r;
assert(manager);
assert(manager->inhibit_timeout_source == s);
if (manager->action_what == 0 || manager->action_job)
return 0;
if (manager_is_inhibited(manager, manager->action_what, INHIBIT_DELAY, NULL, false, false, 0, &offending)) {
_cleanup_free_ char *comm = NULL, *u = NULL;
(void) get_process_comm(offending->pid, &comm);
u = uid_to_name(offending->uid);
log_notice("Delay lock is active (UID "UID_FMT"/%s, PID "PID_FMT"/%s) but inhibitor timeout is reached.",
offending->uid, strna(u),
offending->pid, strna(comm));
}
/* Actually do the operation */
r = execute_shutdown_or_sleep(manager, manager->action_what, manager->action_unit, &error);
if (r < 0) {
log_warning("Failed to send delayed message: %s", bus_error_message(&error, r));
manager->action_unit = NULL;
manager->action_what = 0;
}
return 0;
}
static int delay_shutdown_or_sleep(
Manager *m,
InhibitWhat w,
const char *unit_name) {
int r;
usec_t timeout_val;
assert(m);
assert(w >= 0);
assert(w < _INHIBIT_WHAT_MAX);
assert(unit_name);
timeout_val = now(CLOCK_MONOTONIC) + m->inhibit_delay_max;
if (m->inhibit_timeout_source) {
r = sd_event_source_set_time(m->inhibit_timeout_source, timeout_val);
if (r < 0)
return log_error_errno(r, "sd_event_source_set_time() failed: %m");
r = sd_event_source_set_enabled(m->inhibit_timeout_source, SD_EVENT_ONESHOT);
if (r < 0)
return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
} else {
r = sd_event_add_time(m->event, &m->inhibit_timeout_source, CLOCK_MONOTONIC,
timeout_val, 0, manager_inhibit_timeout_handler, m);
if (r < 0)
return r;
}
m->action_unit = unit_name;
m->action_what = w;
return 0;
}
static int send_prepare_for(Manager *m, InhibitWhat w, bool _active) {
static const char * const signal_name[_INHIBIT_WHAT_MAX] = {
[INHIBIT_SHUTDOWN] = "PrepareForShutdown",
[INHIBIT_SLEEP] = "PrepareForSleep"
};
int active = _active;
assert(m);
assert(w >= 0);
assert(w < _INHIBIT_WHAT_MAX);
assert(signal_name[w]);
return sd_bus_emit_signal(m->bus,
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
signal_name[w],
"b",
active);
}
int bus_manager_shutdown_or_sleep_now_or_later(
Manager *m,
const char *unit_name,
InhibitWhat w,
sd_bus_error *error) {
bool delayed;
int r;
assert(m);
assert(unit_name);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
assert(!m->action_job);
/* Tell everybody to prepare for shutdown/sleep */
send_prepare_for(m, w, true);
delayed =
m->inhibit_delay_max > 0 &&
manager_is_inhibited(m, w, INHIBIT_DELAY, NULL, false, false, 0, NULL);
if (delayed)
/* Shutdown is delayed, keep in mind what we
* want to do, and start a timeout */
r = delay_shutdown_or_sleep(m, w, unit_name);
else
/* Shutdown is not delayed, execute it
* immediately */
r = execute_shutdown_or_sleep(m, w, unit_name, error);
return r;
}
static int verify_shutdown_creds(
Manager *m,
sd_bus_message *message,
InhibitWhat w,
bool interactive,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
bool multiple_sessions, blocked;
uid_t uid;
int r;
assert(m);
assert(message);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_euid(creds, &uid);
if (r < 0)
return r;
r = have_multiple_sessions(m, uid);
if (r < 0)
return r;
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
if (multiple_sessions && action_multiple_sessions) {
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_multiple_sessions, interactive, UID_INVALID, &m->polkit_registry, error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
if (blocked && action_ignore_inhibit) {
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action_ignore_inhibit, interactive, UID_INVALID, &m->polkit_registry, error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
if (!multiple_sessions && !blocked && action) {
r = bus_verify_polkit_async(message, CAP_SYS_BOOT, action, interactive, UID_INVALID, &m->polkit_registry, error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
}
return 0;
}
static int method_do_shutdown_or_sleep(
Manager *m,
sd_bus_message *message,
const char *unit_name,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
sd_bus_error *error) {
int interactive, r;
assert(m);
assert(message);
assert(unit_name);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
r = sd_bus_message_read(message, "b", &interactive);
if (r < 0)
return r;
/* Don't allow multiple jobs being executed at the same time */
if (m->action_what)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "There's already a shutdown or sleep operation in progress");
if (sleep_verb) {
r = can_sleep(sleep_verb);
if (r < 0)
return r;
if (r == 0)
return sd_bus_error_setf(error, BUS_ERROR_SLEEP_VERB_NOT_SUPPORTED, "Sleep verb not supported");
}
r = verify_shutdown_creds(m, message, w, interactive, action, action_multiple_sessions,
action_ignore_inhibit, error);
if (r != 0)
return r;
r = bus_manager_shutdown_or_sleep_now_or_later(m, unit_name, w, error);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int method_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
m, message,
SPECIAL_POWEROFF_TARGET,
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.power-off",
"org.freedesktop.login1.power-off-multiple-sessions",
"org.freedesktop.login1.power-off-ignore-inhibit",
NULL,
error);
}
static int method_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
m, message,
SPECIAL_REBOOT_TARGET,
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.reboot",
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
NULL,
error);
}
static int method_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
m, message,
SPECIAL_SUSPEND_TARGET,
INHIBIT_SLEEP,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"suspend",
error);
}
static int nologin_timeout_handler(
sd_event_source *s,
uint64_t usec,
void *userdata) {
Manager *m = userdata;
int r;
log_info("Creating /run/nologin, blocking further logins...");
r = write_string_file_atomic("/run/nologin", "System is going down.");
if (r < 0)
log_error_errno(r, "Failed to create /run/nologin: %m");
else
m->unlink_nologin = true;
return 0;
}
static int update_schedule_file(Manager *m) {
int r;
_cleanup_fclose_ FILE *f = NULL;
_cleanup_free_ char *t = NULL, *temp_path = NULL;
assert(m);
r = mkdir_safe_label("/run/systemd/shutdown", 0755, 0, 0);
if (r < 0)
return log_error_errno(r, "Failed to create shutdown subdirectory: %m");
t = cescape(m->wall_message);
if (!t)
return log_oom();
r = fopen_temporary("/run/systemd/shutdown/scheduled", &f, &temp_path);
if (r < 0)
return log_error_errno(r, "Failed to save information about scheduled shutdowns: %m");
(void) fchmod(fileno(f), 0644);
fprintf(f,
"USEC="USEC_FMT"\n"
"WARN_WALL=%i\n"
"MODE=%s\n",
m->scheduled_shutdown_timeout,
m->enable_wall_messages,
m->scheduled_shutdown_type);
if (!isempty(m->wall_message))
fprintf(f, "WALL_MESSAGE=%s\n", t);
(void) fflush_and_check(f);
if (ferror(f) || rename(temp_path, "/run/systemd/shutdown/scheduled") < 0) {
log_error_errno(errno, "Failed to write information about scheduled shutdowns: %m");
r = -errno;
(void) unlink(temp_path);
(void) unlink("/run/systemd/shutdown/scheduled");
}
return r;
}
static int manager_scheduled_shutdown_handler(
sd_event_source *s,
uint64_t usec,
void *userdata) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
Manager *m = userdata;
const char *target;
int r;
assert(m);
if (isempty(m->scheduled_shutdown_type))
return 0;
if (streq(m->scheduled_shutdown_type, "halt"))
target = SPECIAL_HALT_TARGET;
else if (streq(m->scheduled_shutdown_type, "poweroff"))
target = SPECIAL_POWEROFF_TARGET;
else
target = SPECIAL_REBOOT_TARGET;
r = execute_shutdown_or_sleep(m, 0, target, &error);
if (r < 0)
return log_error_errno(r, "Unable to execute transition to %s: %m", target);
return 0;
}
static int method_schedule_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
const char *action_multiple_sessions = NULL;
const char *action_ignore_inhibit = NULL;
const char *action = NULL;
uint64_t elapse;
char *type;
int r;
assert(m);
assert(message);
r = sd_bus_message_read(message, "st", &type, &elapse);
if (r < 0)
return r;
if (streq(type, "reboot")) {
action = "org.freedesktop.login1.reboot";
action_multiple_sessions = "org.freedesktop.login1.reboot-multiple-sessions";
action_ignore_inhibit = "org.freedesktop.login1.reboot-ignore-inhibit";
} else if (streq(type, "halt")) {
action = "org.freedesktop.login1.halt";
action_multiple_sessions = "org.freedesktop.login1.halt-multiple-sessions";
action_ignore_inhibit = "org.freedesktop.login1.halt-ignore-inhibit";
} else if (streq(type, "poweroff")) {
action = "org.freedesktop.login1.poweroff";
action_multiple_sessions = "org.freedesktop.login1.poweroff-multiple-sessions";
action_ignore_inhibit = "org.freedesktop.login1.poweroff-ignore-inhibit";
} else
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Unsupported shutdown type");
r = verify_shutdown_creds(m, message, INHIBIT_SHUTDOWN, false,
action, action_multiple_sessions, action_ignore_inhibit, error);
if (r != 0)
return r;
if (m->scheduled_shutdown_timeout_source) {
r = sd_event_source_set_time(m->scheduled_shutdown_timeout_source, elapse);
if (r < 0)
return log_error_errno(r, "sd_event_source_set_time() failed: %m");
r = sd_event_source_set_enabled(m->scheduled_shutdown_timeout_source, SD_EVENT_ONESHOT);
if (r < 0)
return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
} else {
r = sd_event_add_time(m->event, &m->scheduled_shutdown_timeout_source,
CLOCK_REALTIME, elapse, 0, manager_scheduled_shutdown_handler, m);
if (r < 0)
return log_error_errno(r, "sd_event_add_time() failed: %m");
}
r = free_and_strdup(&m->scheduled_shutdown_type, type);
if (r < 0) {
m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
return log_oom();
}
if (m->nologin_timeout_source) {
r = sd_event_source_set_time(m->nologin_timeout_source, elapse);
if (r < 0)
return log_error_errno(r, "sd_event_source_set_time() failed: %m");
r = sd_event_source_set_enabled(m->nologin_timeout_source, SD_EVENT_ONESHOT);
if (r < 0)
return log_error_errno(r, "sd_event_source_set_enabled() failed: %m");
} else {
r = sd_event_add_time(m->event, &m->nologin_timeout_source,
CLOCK_REALTIME, elapse - 5 * USEC_PER_MINUTE, 0, nologin_timeout_handler, m);
if (r < 0)
return log_error_errno(r, "sd_event_add_time() failed: %m");
}
m->scheduled_shutdown_timeout = elapse;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
if (r >= 0) {
const char *tty;
(void) sd_bus_creds_get_uid(creds, &m->scheduled_shutdown_uid);
(void) sd_bus_creds_get_tty(creds, &tty);
r = free_and_strdup(&m->scheduled_shutdown_tty, tty);
if (r < 0) {
m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
return log_oom();
}
}
r = manager_setup_wall_message_timer(m);
if (r < 0)
return r;
if (!isempty(type)) {
r = update_schedule_file(m);
if (r < 0)
return r;
} else
(void) unlink("/run/systemd/shutdown/scheduled");
return sd_bus_reply_method_return(message, NULL);
}
static int method_cancel_scheduled_shutdown(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
bool cancelled;
assert(m);
assert(message);
cancelled = m->scheduled_shutdown_type != NULL;
m->scheduled_shutdown_timeout_source = sd_event_source_unref(m->scheduled_shutdown_timeout_source);
m->wall_message_timeout_source = sd_event_source_unref(m->wall_message_timeout_source);
m->nologin_timeout_source = sd_event_source_unref(m->nologin_timeout_source);
free(m->scheduled_shutdown_type);
m->scheduled_shutdown_type = NULL;
m->scheduled_shutdown_timeout = 0;
if (cancelled) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
const char *tty = NULL;
uid_t uid = 0;
int r;
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_AUGMENT|SD_BUS_CREDS_TTY|SD_BUS_CREDS_UID, &creds);
if (r >= 0) {
(void) sd_bus_creds_get_uid(creds, &uid);
(void) sd_bus_creds_get_tty(creds, &tty);
}
utmp_wall("The system shutdown has been cancelled",
lookup_uid(uid), tty, logind_wall_tty_filter, m);
}
return sd_bus_reply_method_return(message, "b", cancelled);
}
static int method_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
m, message,
SPECIAL_HIBERNATE_TARGET,
INHIBIT_SLEEP,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hibernate",
error);
}
static int method_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_do_shutdown_or_sleep(
m, message,
SPECIAL_HYBRID_SLEEP_TARGET,
INHIBIT_SLEEP,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
error);
}
static int method_can_shutdown_or_sleep(
Manager *m,
sd_bus_message *message,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_verb,
sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
bool multiple_sessions, challenge, blocked;
const char *result = NULL;
uid_t uid;
int r;
assert(m);
assert(message);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
assert(action);
assert(action_multiple_sessions);
assert(action_ignore_inhibit);
if (sleep_verb) {
r = can_sleep(sleep_verb);
if (r < 0)
return r;
if (r == 0)
return sd_bus_reply_method_return(message, "s", "na");
}
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_euid(creds, &uid);
if (r < 0)
return r;
r = have_multiple_sessions(m, uid);
if (r < 0)
return r;
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL, false, true, uid, NULL);
if (multiple_sessions) {
r = bus_test_polkit(message, CAP_SYS_BOOT, action_multiple_sessions, UID_INVALID, &challenge, error);
if (r < 0)
return r;
if (r > 0)
result = "yes";
else if (challenge)
result = "challenge";
else
result = "no";
}
if (blocked) {
r = bus_test_polkit(message, CAP_SYS_BOOT, action_ignore_inhibit, UID_INVALID, &challenge, error);
if (r < 0)
return r;
if (r > 0 && !result)
result = "yes";
else if (challenge && (!result || streq(result, "yes")))
result = "challenge";
else
result = "no";
}
if (!multiple_sessions && !blocked) {
/* If neither inhibit nor multiple sessions
* apply then just check the normal policy */
r = bus_test_polkit(message, CAP_SYS_BOOT, action, UID_INVALID, &challenge, error);
if (r < 0)
return r;
if (r > 0)
result = "yes";
else if (challenge)
result = "challenge";
else
result = "no";
}
return sd_bus_reply_method_return(message, "s", result);
}
static int method_can_poweroff(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
m, message,
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.power-off",
"org.freedesktop.login1.power-off-multiple-sessions",
"org.freedesktop.login1.power-off-ignore-inhibit",
NULL,
error);
}
static int method_can_reboot(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
m, message,
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.reboot",
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
NULL,
error);
}
static int method_can_suspend(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
m, message,
INHIBIT_SLEEP,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"suspend",
error);
}
static int method_can_hibernate(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
m, message,
INHIBIT_SLEEP,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hibernate",
error);
}
static int method_can_hybrid_sleep(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
return method_can_shutdown_or_sleep(
m, message,
INHIBIT_SLEEP,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"hybrid-sleep",
error);
}
static int property_get_reboot_to_firmware_setup(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
int r;
assert(bus);
assert(reply);
assert(userdata);
r = efi_get_reboot_to_firmware();
if (r < 0 && r != -EOPNOTSUPP)
return r;
return sd_bus_message_append(reply, "b", r > 0);
}
static int method_set_reboot_to_firmware_setup(
sd_bus *bus,
sd_bus_message *message,
void *userdata,
sd_bus_error *error) {
int b, r;
Manager *m = userdata;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "b", &b);
if (r < 0)
return r;
r = bus_verify_polkit_async(message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.set-reboot-to-firmware-setup",
false,
UID_INVALID,
&m->polkit_registry,
error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = efi_set_reboot_to_firmware(b);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
static int method_can_reboot_to_firmware_setup(
sd_bus *bus,
sd_bus_message *message,
void *userdata,
sd_bus_error *error) {
int r;
bool challenge;
const char *result;
Manager *m = userdata;
assert(bus);
assert(message);
assert(m);
r = efi_reboot_to_firmware_supported();
if (r == -EOPNOTSUPP)
return sd_bus_reply_method_return(message, "s", "na");
else if (r < 0)
return r;
r = bus_test_polkit(message,
CAP_SYS_ADMIN,
"org.freedesktop.login1.set-reboot-to-firmware-setup",
UID_INVALID,
&challenge,
error);
if (r < 0)
return r;
if (r > 0)
result = "yes";
else if (challenge)
result = "challenge";
else
result = "no";
return sd_bus_reply_method_return(message, "s", result);
}
static int method_inhibit(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
const char *who, *why, *what, *mode;
_cleanup_free_ char *id = NULL;
_cleanup_close_ int fifo_fd = -1;
Manager *m = userdata;
Inhibitor *i = NULL;
InhibitMode mm;
InhibitWhat w;
pid_t pid;
uid_t uid;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "ssss", &what, &who, &why, &mode);
if (r < 0)
return r;
w = inhibit_what_from_string(what);
if (w <= 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid what specification %s", what);
mm = inhibit_mode_from_string(mode);
if (mm < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid mode specification %s", mode);
/* Delay is only supported for shutdown/sleep */
if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Delay inhibitors only supported for shutdown and sleep");
/* Don't allow taking delay locks while we are already
* executing the operation. We shouldn't create the impression
* that the lock was successful if the machine is about to go
* down/suspend any moment. */
if (m->action_what & w)
return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS, "The operation inhibition has been requested for is already running");
r = bus_verify_polkit_async(
message,
CAP_SYS_BOOT,
w == INHIBIT_SHUTDOWN ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-shutdown" : "org.freedesktop.login1.inhibit-delay-shutdown") :
w == INHIBIT_SLEEP ? (mm == INHIBIT_BLOCK ? "org.freedesktop.login1.inhibit-block-sleep" : "org.freedesktop.login1.inhibit-delay-sleep") :
w == INHIBIT_IDLE ? "org.freedesktop.login1.inhibit-block-idle" :
w == INHIBIT_HANDLE_POWER_KEY ? "org.freedesktop.login1.inhibit-handle-power-key" :
w == INHIBIT_HANDLE_SUSPEND_KEY ? "org.freedesktop.login1.inhibit-handle-suspend-key" :
w == INHIBIT_HANDLE_HIBERNATE_KEY ? "org.freedesktop.login1.inhibit-handle-hibernate-key" :
"org.freedesktop.login1.inhibit-handle-lid-switch",
false,
UID_INVALID,
&m->polkit_registry,
error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID, &creds);
if (r < 0)
return r;
r = sd_bus_creds_get_euid(creds, &uid);
if (r < 0)
return r;
r = sd_bus_creds_get_pid(creds, &pid);
if (r < 0)
return r;
do {
free(id);
id = NULL;
if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0)
return -ENOMEM;
} while (hashmap_get(m->inhibitors, id));
r = manager_add_inhibitor(m, id, &i);
if (r < 0)
return r;
i->what = w;
i->mode = mm;
i->pid = pid;
i->uid = uid;
i->why = strdup(why);
i->who = strdup(who);
if (!i->why || !i->who) {
r = -ENOMEM;
goto fail;
}
fifo_fd = inhibitor_create_fifo(i);
if (fifo_fd < 0) {
r = fifo_fd;
goto fail;
}
inhibitor_start(i);
return sd_bus_reply_method_return(message, "h", fifo_fd);
fail:
if (i)
inhibitor_free(i);
return r;
}
const sd_bus_vtable manager_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_WRITABLE_PROPERTY("EnableWallMessages", "b", NULL, NULL, offsetof(Manager, enable_wall_messages), 0),
SD_BUS_WRITABLE_PROPERTY("WallMessage", "s", NULL, NULL, offsetof(Manager, wall_message), 0),
SD_BUS_PROPERTY("NAutoVTs", "u", NULL, offsetof(Manager, n_autovts), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillOnlyUsers", "as", NULL, offsetof(Manager, kill_only_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillExcludeUsers", "as", NULL, offsetof(Manager, kill_exclude_users), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("KillUserProcesses", "b", NULL, offsetof(Manager, kill_user_processes), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("RebootToFirmwareSetup", "b", property_get_reboot_to_firmware_setup, 0, SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleHint", "b", property_get_idle_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("BlockInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("DelayInhibited", "s", property_get_inhibited, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
SD_BUS_PROPERTY("InhibitDelayMaxUSec", "t", NULL, offsetof(Manager, inhibit_delay_max), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandlePowerKey", "s", property_get_handle_action, offsetof(Manager, handle_power_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleSuspendKey", "s", property_get_handle_action, offsetof(Manager, handle_suspend_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleHibernateKey", "s", property_get_handle_action, offsetof(Manager, handle_hibernate_key), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitch", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HandleLidSwitchDocked", "s", property_get_handle_action, offsetof(Manager, handle_lid_switch_docked), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("HoldoffTimeoutUSec", "t", NULL, offsetof(Manager, holdoff_timeout_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleAction", "s", property_get_handle_action, offsetof(Manager, idle_action), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("IdleActionUSec", "t", NULL, offsetof(Manager, idle_action_usec), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0),
SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0),
SD_BUS_PROPERTY("ScheduledShutdown", "(st)", property_get_scheduled_shutdown, 0, 0),
SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CreateSession", "uusssssussbssa(sv)", "soshusub", method_create_session, 0),
SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0),
SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("ScheduleShutdown", "st", NULL, method_schedule_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CancelScheduledShutdown", NULL, "b", method_cancel_scheduled_shutdown, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("CanRebootToFirmwareSetup", NULL, "s", method_can_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD("SetRebootToFirmwareSetup", "b", NULL, method_set_reboot_to_firmware_setup, SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_SIGNAL("SessionNew", "so", 0),
SD_BUS_SIGNAL("SessionRemoved", "so", 0),
SD_BUS_SIGNAL("UserNew", "uo", 0),
SD_BUS_SIGNAL("UserRemoved", "uo", 0),
SD_BUS_SIGNAL("SeatNew", "so", 0),
SD_BUS_SIGNAL("SeatRemoved", "so", 0),
SD_BUS_SIGNAL("PrepareForShutdown", "b", 0),
SD_BUS_SIGNAL("PrepareForSleep", "b", 0),
SD_BUS_VTABLE_END
};
static int session_jobs_reply(Session *s, const char *unit, const char *result) {
int r = 0;
assert(s);
assert(unit);
if (!s->started)
return r;
if (streq(result, "done"))
r = session_send_create_reply(s, NULL);
else {
_cleanup_bus_error_free_ sd_bus_error e = SD_BUS_ERROR_NULL;
sd_bus_error_setf(&e, BUS_ERROR_JOB_FAILED, "Start job for unit %s failed with '%s'", unit, result);
r = session_send_create_reply(s, &e);
}
return r;
}
int match_job_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *path, *result, *unit;
Manager *m = userdata;
Session *session;
uint32_t id;
User *user;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "uoss", &id, &path, &unit, &result);
if (r < 0) {
bus_log_parse_error(r);
return r;
}
if (m->action_job && streq(m->action_job, path)) {
log_info("Operation finished.");
/* Tell people that they now may take a lock again */
send_prepare_for(m, m->action_what, false);
free(m->action_job);
m->action_job = NULL;
m->action_unit = NULL;
m->action_what = 0;
return 0;
}
session = hashmap_get(m->session_units, unit);
if (session) {
if (streq_ptr(path, session->scope_job)) {
free(session->scope_job);
session->scope_job = NULL;
}
session_jobs_reply(session, unit, result);
session_save(session);
session_add_to_gc_queue(session);
}
user = hashmap_get(m->user_units, unit);
if (user) {
if (streq_ptr(path, user->service_job)) {
free(user->service_job);
user->service_job = NULL;
}
if (streq_ptr(path, user->slice_job)) {
free(user->slice_job);
user->slice_job = NULL;
}
LIST_FOREACH(sessions_by_user, session, user->sessions) {
session_jobs_reply(session, unit, result);
}
user_save(user);
user_add_to_gc_queue(user);
}
return 0;
}
int match_unit_removed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *path, *unit;
Manager *m = userdata;
Session *session;
User *user;
int r;
assert(bus);
assert(message);
assert(m);
r = sd_bus_message_read(message, "so", &unit, &path);
if (r < 0) {
bus_log_parse_error(r);
return r;
}
session = hashmap_get(m->session_units, unit);
if (session)
session_add_to_gc_queue(session);
user = hashmap_get(m->user_units, unit);
if (user)
user_add_to_gc_queue(user);
return 0;
}
int match_properties_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
_cleanup_free_ char *unit = NULL;
Manager *m = userdata;
const char *path;
Session *session;
User *user;
int r;
assert(bus);
assert(message);
assert(m);
path = sd_bus_message_get_path(message);
if (!path)
return 0;
r = unit_name_from_dbus_path(path, &unit);
if (r == -EINVAL) /* not a unit */
return 0;
if (r < 0)
return r;
session = hashmap_get(m->session_units, unit);
if (session)
session_add_to_gc_queue(session);
user = hashmap_get(m->user_units, unit);
if (user)
user_add_to_gc_queue(user);
return 0;
}
int match_reloading(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
Manager *m = userdata;
Session *session;
Iterator i;
int b, r;
assert(bus);
r = sd_bus_message_read(message, "b", &b);
if (r < 0) {
bus_log_parse_error(r);
return r;
}
if (b)
return 0;
/* systemd finished reloading, let's recheck all our sessions */
log_debug("System manager has been reloaded, rechecking sessions...");
HASHMAP_FOREACH(session, m->sessions, i)
session_add_to_gc_queue(session);
return 0;
}
int match_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) {
const char *name, *old, *new;
Manager *m = userdata;
Session *session;
Iterator i;
int r;
char *key;
r = sd_bus_message_read(message, "sss", &name, &old, &new);
if (r < 0) {
bus_log_parse_error(r);
return r;
}
if (isempty(old) || !isempty(new))
return 0;
key = set_remove(m->busnames, (char*) old);
if (!key)
return 0;
/* Drop all controllers owned by this name */
free(key);
HASHMAP_FOREACH(session, m->sessions, i)
if (session_is_controller(session, old))
session_drop_controller(session);
return 0;
}
int manager_send_changed(Manager *manager, const char *property, ...) {
char **l;
assert(manager);
l = strv_from_stdarg_alloca(property);
return sd_bus_emit_properties_changed_strv(
manager->bus,
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
l);
}
int manager_start_scope(
Manager *manager,
const char *scope,
pid_t pid,
const char *slice,
const char *description,
const char *after, const char *after2,
sd_bus_error *error,
char **job) {
_cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
int r;
assert(manager);
assert(scope);
assert(pid > 1);
r = sd_bus_message_new_method_call(
manager->bus,
&m,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartTransientUnit");
if (r < 0)
return r;
r = sd_bus_message_append(m, "ss", strempty(scope), "fail");
if (r < 0)
return r;
r = sd_bus_message_open_container(m, 'a', "(sv)");
if (r < 0)
return r;
if (!isempty(slice)) {
r = sd_bus_message_append(m, "(sv)", "Slice", "s", slice);
if (r < 0)
return r;
}
if (!isempty(description)) {
r = sd_bus_message_append(m, "(sv)", "Description", "s", description);
if (r < 0)
return r;
}
if (!isempty(after)) {
r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after);
if (r < 0)
return r;
}
if (!isempty(after2)) {
r = sd_bus_message_append(m, "(sv)", "After", "as", 1, after2);
if (r < 0)
return r;
}
/* cgroup empty notification is not available in containers
* currently. To make this less problematic, let's shorten the
* stop timeout for sessions, so that we don't wait
* forever. */
/* Make sure that the session shells are terminated with
* SIGHUP since bash and friends tend to ignore SIGTERM */
r = sd_bus_message_append(m, "(sv)", "SendSIGHUP", "b", true);
if (r < 0)
return r;
r = sd_bus_message_append(m, "(sv)", "PIDs", "au", 1, pid);
if (r < 0)
return r;
r = sd_bus_message_close_container(m);
if (r < 0)
return r;
r = sd_bus_message_append(m, "a(sa(sv))", 0);
if (r < 0)
return r;
r = sd_bus_call(manager->bus, m, 0, error, &reply);
if (r < 0)
return r;
if (job) {
const char *j;
char *copy;
r = sd_bus_message_read(reply, "o", &j);
if (r < 0)
return r;
copy = strdup(j);
if (!copy)
return -ENOMEM;
*job = copy;
}
return 1;
}
int manager_start_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
int r;
assert(manager);
assert(unit);
r = sd_bus_call_method(
manager->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit",
error,
&reply,
"ss", unit, "fail");
if (r < 0)
return r;
if (job) {
const char *j;
char *copy;
r = sd_bus_message_read(reply, "o", &j);
if (r < 0)
return r;
copy = strdup(j);
if (!copy)
return -ENOMEM;
*job = copy;
}
return 1;
}
int manager_stop_unit(Manager *manager, const char *unit, sd_bus_error *error, char **job) {
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
int r;
assert(manager);
assert(unit);
r = sd_bus_call_method(
manager->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StopUnit",
error,
&reply,
"ss", unit, "fail");
if (r < 0) {
if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED)) {
if (job)
*job = NULL;
sd_bus_error_free(error);
return 0;
}
return r;
}
if (job) {
const char *j;
char *copy;
r = sd_bus_message_read(reply, "o", &j);
if (r < 0)
return r;
copy = strdup(j);
if (!copy)
return -ENOMEM;
*job = copy;
}
return 1;
}
int manager_abandon_scope(Manager *manager, const char *scope, sd_bus_error *error) {
_cleanup_free_ char *path = NULL;
int r;
assert(manager);
assert(scope);
path = unit_dbus_path_from_name(scope);
if (!path)
return -ENOMEM;
r = sd_bus_call_method(
manager->bus,
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Scope",
"Abandon",
error,
NULL,
NULL);
if (r < 0) {
if (sd_bus_error_has_name(error, BUS_ERROR_NO_SUCH_UNIT) ||
sd_bus_error_has_name(error, BUS_ERROR_LOAD_FAILED) ||
sd_bus_error_has_name(error, BUS_ERROR_SCOPE_NOT_RUNNING)) {
sd_bus_error_free(error);
return 0;
}
return r;
}
return 1;
}
int manager_kill_unit(Manager *manager, const char *unit, KillWho who, int signo, sd_bus_error *error) {
assert(manager);
assert(unit);
return sd_bus_call_method(
manager->bus,
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"KillUnit",
error,
NULL,
"ssi", unit, who == KILL_LEADER ? "main" : "all", signo);
}
int manager_unit_is_active(Manager *manager, const char *unit) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
_cleanup_free_ char *path = NULL;
const char *state;
int r;
assert(manager);
assert(unit);
path = unit_dbus_path_from_name(unit);
if (!path)
return -ENOMEM;
r = sd_bus_get_property(
manager->bus,
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Unit",
"ActiveState",
&error,
&reply,
"s");
if (r < 0) {
/* systemd might have droppped off momentarily, let's
* not make this an error */
if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
return true;
/* If the unit is already unloaded then it's not
* active */
if (sd_bus_error_has_name(&error, BUS_ERROR_NO_SUCH_UNIT) ||
sd_bus_error_has_name(&error, BUS_ERROR_LOAD_FAILED))
return false;
return r;
}
r = sd_bus_message_read(reply, "s", &state);
if (r < 0)
return -EINVAL;
return !streq(state, "inactive") && !streq(state, "failed");
}
int manager_job_is_active(Manager *manager, const char *path) {
_cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
_cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
int r;
assert(manager);
assert(path);
r = sd_bus_get_property(
manager->bus,
"org.freedesktop.systemd1",
path,
"org.freedesktop.systemd1.Job",
"State",
&error,
&reply,
"s");
if (r < 0) {
if (sd_bus_error_has_name(&error, SD_BUS_ERROR_NO_REPLY) ||
sd_bus_error_has_name(&error, SD_BUS_ERROR_DISCONNECTED))
return true;
if (sd_bus_error_has_name(&error, SD_BUS_ERROR_UNKNOWN_OBJECT))
return false;
return r;
}
/* We don't actually care about the state really. The fact
* that we could read the job state is enough for us */
return true;
}