logind-dbus.c revision 5e4a79da3ac3859c2a1295e019b95a1e5589b9c1
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering/***
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering This file is part of systemd.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Copyright 2011 Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is free software; you can redistribute it and/or modify it
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering under the terms of the GNU Lesser General Public License as published by
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering (at your option) any later version.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering systemd is distributed in the hope that it will be useful, but
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering Lesser General Public License for more details.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering You should have received a copy of the GNU Lesser General Public License
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering***/
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering#include <errno.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <string.h>
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include <unistd.h>
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include <pwd.h>
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "logind.h"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#include "dbus-common.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "strv.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "mkdir.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "path-util.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "polkit.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#include "special.h"
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering#define BUS_MANAGER_INTERFACE \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <interface name=\"org.freedesktop.login1.Manager\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"GetSession\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"GetSessionByPID\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"pid\" type=\"u\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"session\" type=\"o\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"GetUser\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"user\" type=\"o\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"GetSeat\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"seat\" type=\"o\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"ListSessions\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"sessions\" type=\"a(susso)\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"ListUsers\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"users\" type=\"a(uso)\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"ListSeats\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"seats\" type=\"a(so)\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"CreateSession\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"leader\" type=\"u\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"sevice\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"type\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"class\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"vtnr\" type=\"u\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"tty\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"display\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"remote\" type=\"b\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"remote_user\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"remote_host\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"controllers\" type=\"as\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"reset_controllers\" type=\"as\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"kill_processes\" type=\"b\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"path\" type=\"o\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"runtime_path\" type=\"o\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"seat\" type=\"s\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"vtnr\" type=\"u\" direction=\"out\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"ReleaseSession\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"ActivateSession\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"ActivateSessionOnSeat\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"LockSession\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"UnlockSession\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"KillSession\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"signal\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"KillUser\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"signal\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"TerminateSession\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"TerminateUser\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"TerminateSeat\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"SetUserLinger\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"uid\" type=\"u\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"b\" type=\"b\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <method name=\"AttachDevice\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"seat\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"sysfs\" type=\"s\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " </method>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <method name=\"FlushDevices\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"PowerOff\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"Reboot\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"Suspend\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"Hibernate\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"interactive\" type=\"b\" direction=\"in\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"CanPowerOff\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"CanReboot\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"CanSuspend\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"CanHibernate\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"result\" type=\"s\" direction=\"out\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " </method>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <method name=\"Inhibit\">\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"what\" type=\"s\" direction=\"in\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"who\" type=\"s\" direction=\"in\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"why\" type=\"s\" direction=\"in\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"mode\" type=\"s\" direction=\"in\"/>\n" \
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering " <arg name=\"fd\" type=\"h\" direction=\"out\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " </method>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <method name=\"ListInhibitors\">\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"inhibitors\" type=\"a(ssssuu)\" direction=\"out\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " </method>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <signal name=\"SessionNew\">\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"id\" type=\"s\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"path\" type=\"o\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " </signal>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <signal name=\"SessionRemoved\">\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"id\" type=\"s\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"path\" type=\"o\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " </signal>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <signal name=\"UserNew\">\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"uid\" type=\"u\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"path\" type=\"o\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " </signal>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <signal name=\"UserRemoved\">\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"uid\" type=\"u\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"path\" type=\"o\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " </signal>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <signal name=\"SeatNew\">\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"id\" type=\"s\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <arg name=\"path\" type=\"o\"/>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " </signal>\n" \
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering " <signal name=\"SeatRemoved\">\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <arg name=\"id\" type=\"s\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <arg name=\"path\" type=\"o\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " </signal>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <signal name=\"PrepareForShutdown\">\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <arg name=\"active\" type=\"b\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " </signal>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <signal name=\"PrepareForSleep\">\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <arg name=\"active\" type=\"b\"/>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " </signal>\n" \
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering " <property name=\"ControlGroupHierarchy\" type=\"s\" access=\"read\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <property name=\"Controllers\" type=\"as\" access=\"read\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <property name=\"ResetControllers\" type=\"as\" access=\"read\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <property name=\"NAutoVTs\" type=\"u\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"KillOnlyUsers\" type=\"as\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"KillExcludeUsers\" type=\"as\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"KillUserProcesses\" type=\"b\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"IdleHint\" type=\"b\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"IdleSinceHint\" type=\"t\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"IdleSinceHintMonotonic\" type=\"t\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"BlockInhibited\" type=\"s\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"DelayInhibited\" type=\"s\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"InhibitDelayMaxUSec\" type=\"t\" access=\"read\"/>\n" \
8bf52d3d17d364438191077d0750b8b80b5dc53aLennart Poettering " <property name=\"HandlePowerKey\" type=\"s\" access=\"read\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <property name=\"HandleSleepKey\" type=\"s\" access=\"read\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <property name=\"HandleLidSwitch\" type=\"s\" access=\"read\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <property name=\"PreparingForShutdown\" type=\"b\" access=\"read\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " <property name=\"PreparingForSleep\" type=\"b\" access=\"read\"/>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering " </interface>\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define INTROSPECTION_BEGIN \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "<node>\n" \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering BUS_MANAGER_INTERFACE \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering BUS_PROPERTIES_INTERFACE \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering BUS_PEER_INTERFACE \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering BUS_INTROSPECTABLE_INTERFACE
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define INTROSPECTION_END \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "</node>\n"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering#define INTERFACES_LIST \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering BUS_GENERIC_INTERFACES_LIST \
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering "org.freedesktop.login1.Manager\0"
74b2466e14a1961bf3ac0e8a60cfaceec705bd59Lennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int bus_manager_append_idle_hint(DBusMessageIter *i, const char *property, void *data) {
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering Manager *m = data;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering dbus_bool_t b;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(i);
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering assert(property);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering assert(m);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering b = manager_get_idle_hint(m, NULL) > 0;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek if (!dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b))
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek return -ENOMEM;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering return 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poetteringstatic int bus_manager_append_idle_hint_since(DBusMessageIter *i, const char *property, void *data) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering Manager *m = data;
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering dual_timestamp t;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering uint64_t u;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert(i);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert(property);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(m);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering manager_get_idle_hint(m, &t);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering u = streq(property, "IdleSinceHint") ? t.realtime : t.monotonic;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_UINT64, &u))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -ENOMEM;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int bus_manager_append_inhibited(DBusMessageIter *i, const char *property, void *data) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering Manager *m = data;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering InhibitWhat w;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering const char *p;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering w = manager_inhibit_what(m, streq(property, "BlockInhibited") ? INHIBIT_BLOCK : INHIBIT_DELAY);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering p = inhibit_what_to_string(w);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (!dbus_message_iter_append_basic(i, DBUS_TYPE_STRING, &p))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return -ENOMEM;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering return 0;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering}
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poetteringstatic int bus_manager_append_preparing(DBusMessageIter *i, const char *property, void *data) {
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering Manager *m = data;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering dbus_bool_t b;
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(i);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering assert(property);
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering if (streq(property, "PreparingForShutdown"))
623a4c97b9175f95c4b1c6fc34e36c56f1e4ddbfLennart Poettering b = !!(m->delayed_what & INHIBIT_SHUTDOWN);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering else
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering b = !!(m->delayed_what & INHIBIT_SLEEP);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering dbus_message_iter_append_basic(i, DBUS_TYPE_BOOLEAN, &b);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return 0;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering}
faa133f3aa7a18f26563dc5d6b95898cb315c37aLennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poetteringstatic int bus_manager_create_session(Manager *m, DBusMessage *message, DBusMessage **_reply) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering Session *session = NULL;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering User *user = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering const char *type, *class, *seat, *tty, *display, *remote_user, *remote_host, *service;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering uint32_t uid, leader, audit_id = 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_bool_t remote, kill_processes;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering char **controllers = NULL, **reset_controllers = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering SessionType t;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering SessionClass c;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering Seat *s;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering DBusMessageIter iter;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int r;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering char *id = NULL, *p;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering uint32_t vtnr = 0;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int fifo_fd = -1;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering DBusMessage *reply = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering bool b;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering assert(m);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(message);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering assert(_reply);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (!dbus_message_iter_init(message, &iter) ||
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return -EINVAL;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering dbus_message_iter_get_basic(&iter, &uid);
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering if (!dbus_message_iter_next(&iter) ||
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering return -EINVAL;
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering
7e8e0422aeb16f2a09a40546c61df753d10029b6Lennart Poettering dbus_message_iter_get_basic(&iter, &leader);
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek if (leader <= 0 ||
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek !dbus_message_iter_next(&iter) ||
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek return -EINVAL;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &service);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (!dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return -EINVAL;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &type);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering t = session_type_from_string(type);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (t < 0 ||
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering !dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &class);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (isempty(class))
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering c = SESSION_USER;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering else
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering c = session_class_from_string(class);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (c < 0 ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering !dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering dbus_message_iter_get_basic(&iter, &seat);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (isempty(seat))
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering s = NULL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering else {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering s = hashmap_get(m->seats, seat);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!s)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -ENOENT;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!dbus_message_iter_next(&iter) ||
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_UINT32)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &vtnr);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &tty);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (tty_is_vc(tty)) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering int v;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!s)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering s = m->vtconsole;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering else if (s != m->vtconsole)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering v = vtnr_from_tty(tty);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (v <= 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return v < 0 ? v : -EINVAL;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (vtnr <= 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering vtnr = (uint32_t) v;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering else if (vtnr != (uint32_t) v)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering } else if (tty_is_console(tty)) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!s)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering s = m->vtconsole;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering else if (s != m->vtconsole)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (vtnr != 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek } else if (!isempty(tty) && s && seat_is_vtconsole(s))
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek return -EINVAL;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek if (s) {
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek if (seat_can_multi_session(s)) {
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek if (vtnr > 63)
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek return -EINVAL;
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek } else {
946c70944ebdf428ffeb9991a7449edbd4011461Zbigniew Jędrzejewski-Szmek if (vtnr != 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &display);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &remote);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (!dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering dbus_message_iter_get_basic(&iter, &remote_user);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!dbus_message_iter_next(&iter) ||
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &remote_host);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = bus_parse_strv_iter(&iter, &controllers);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering return -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (strv_contains(controllers, "systemd") ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering !dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = bus_parse_strv_iter(&iter, &reset_controllers);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (strv_contains(reset_controllers, "systemd") ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering !dbus_message_iter_next(&iter) ||
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_BOOLEAN) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = -EINVAL;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering dbus_message_iter_get_basic(&iter, &kill_processes);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = manager_add_user_by_uid(m, uid, &user);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (r < 0)
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering audit_session_from_pid(leader, &audit_id);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (audit_id > 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering asprintf(&id, "%lu", (unsigned long) audit_id);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!id) {
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering r = -ENOMEM;
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering session = hashmap_get(m->sessions, id);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (session) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering free(id);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering fifo_fd = session_create_fifo(session);
322345fdb9865ef2477fba8e4bdde0e1183ef505Lennart Poettering if (fifo_fd < 0) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = fifo_fd;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering /* Session already exists, client is probably
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering * something like "su" which changes uid but
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering * is still the same audit session */
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering reply = dbus_message_new_method_return(message);
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering if (!reply) {
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering r = -ENOMEM;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering goto fail;
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering }
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering
2d4c5cbc0ed3ccb09dc086a040088b454c22c644Lennart Poettering p = session_bus_path(session);
if (!p) {
r = -ENOMEM;
goto fail;
}
seat = session->seat ? session->seat->id : "";
vtnr = session->vtnr;
b = dbus_message_append_args(
reply,
DBUS_TYPE_STRING, &session->id,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_STRING, &session->user->runtime_path,
DBUS_TYPE_UNIX_FD, &fifo_fd,
DBUS_TYPE_STRING, &seat,
DBUS_TYPE_UINT32, &vtnr,
DBUS_TYPE_INVALID);
free(p);
if (!b) {
r = -ENOMEM;
goto fail;
}
close_nointr_nofail(fifo_fd);
*_reply = reply;
strv_free(controllers);
strv_free(reset_controllers);
return 0;
}
} else {
do {
free(id);
id = NULL;
if (asprintf(&id, "c%lu", ++m->session_counter) < 0) {
r = -ENOMEM;
goto fail;
}
} while (hashmap_get(m->sessions, id));
}
r = manager_add_session(m, user, id, &session);
free(id);
if (r < 0)
goto fail;
session->leader = leader;
session->audit_id = audit_id;
session->type = t;
session->class = c;
session->remote = remote;
session->controllers = controllers;
session->reset_controllers = reset_controllers;
session->kill_processes = kill_processes;
session->vtnr = vtnr;
controllers = reset_controllers = NULL;
if (!isempty(tty)) {
session->tty = strdup(tty);
if (!session->tty) {
r = -ENOMEM;
goto fail;
}
}
if (!isempty(display)) {
session->display = strdup(display);
if (!session->display) {
r = -ENOMEM;
goto fail;
}
}
if (!isempty(remote_user)) {
session->remote_user = strdup(remote_user);
if (!session->remote_user) {
r = -ENOMEM;
goto fail;
}
}
if (!isempty(remote_host)) {
session->remote_host = strdup(remote_host);
if (!session->remote_host) {
r = -ENOMEM;
goto fail;
}
}
if (!isempty(service)) {
session->service = strdup(service);
if (!session->service) {
r = -ENOMEM;
goto fail;
}
}
fifo_fd = session_create_fifo(session);
if (fifo_fd < 0) {
r = fifo_fd;
goto fail;
}
if (s) {
r = seat_attach_session(s, session);
if (r < 0)
goto fail;
}
r = session_start(session);
if (r < 0)
goto fail;
reply = dbus_message_new_method_return(message);
if (!reply) {
r = -ENOMEM;
goto fail;
}
p = session_bus_path(session);
if (!p) {
r = -ENOMEM;
goto fail;
}
seat = s ? s->id : "";
b = dbus_message_append_args(
reply,
DBUS_TYPE_STRING, &session->id,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_STRING, &session->user->runtime_path,
DBUS_TYPE_UNIX_FD, &fifo_fd,
DBUS_TYPE_STRING, &seat,
DBUS_TYPE_UINT32, &vtnr,
DBUS_TYPE_INVALID);
free(p);
if (!b) {
r = -ENOMEM;
goto fail;
}
close_nointr_nofail(fifo_fd);
*_reply = reply;
return 0;
fail:
strv_free(controllers);
strv_free(reset_controllers);
if (session)
session_add_to_gc_queue(session);
if (user)
user_add_to_gc_queue(user);
if (fifo_fd >= 0)
close_nointr_nofail(fifo_fd);
if (reply)
dbus_message_unref(reply);
return r;
}
static int bus_manager_inhibit(Manager *m, DBusConnection *connection, DBusMessage *message, DBusError *error, DBusMessage **_reply) {
Inhibitor *i = NULL;
char *id = NULL;
const char *who, *why, *what, *mode;
pid_t pid;
InhibitWhat w;
InhibitMode mm;
unsigned long ul;
int r, fifo_fd = -1;
DBusMessage *reply = NULL;
assert(m);
assert(connection);
assert(message);
assert(error);
assert(_reply);
if (!dbus_message_get_args(
message,
error,
DBUS_TYPE_STRING, &what,
DBUS_TYPE_STRING, &who,
DBUS_TYPE_STRING, &why,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID)) {
r = -EIO;
goto fail;
}
w = inhibit_what_from_string(what);
if (w <= 0) {
r = -EINVAL;
goto fail;
}
mm = inhibit_mode_from_string(mode);
if (mm < 0) {
r = -EINVAL;
goto fail;
}
r = verify_polkit(connection, message,
m == INHIBIT_BLOCK ?
"org.freedesktop.login1.inhibit-block" :
"org.freedesktop.login1.inhibit-delay", false, NULL, error);
if (r < 0)
goto fail;
ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
if (ul == (unsigned long) -1) {
r = -EIO;
goto fail;
}
pid = bus_get_unix_process_id(connection, dbus_message_get_sender(message), error);
if (pid <= 0) {
r = -EIO;
goto fail;
}
do {
free(id);
id = NULL;
if (asprintf(&id, "%lu", ++m->inhibit_counter) < 0) {
r = -ENOMEM;
goto fail;
}
} while (hashmap_get(m->inhibitors, id));
r = manager_add_inhibitor(m, id, &i);
free(id);
if (r < 0)
goto fail;
i->what = w;
i->mode = mm;
i->pid = pid;
i->uid = (uid_t) ul;
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;
}
reply = dbus_message_new_method_return(message);
if (!reply) {
r = -ENOMEM;
goto fail;
}
if (!dbus_message_append_args(
reply,
DBUS_TYPE_UNIX_FD, &fifo_fd,
DBUS_TYPE_INVALID)) {
r = -ENOMEM;
goto fail;
}
close_nointr_nofail(fifo_fd);
*_reply = reply;
inhibitor_start(i);
return 0;
fail:
if (i)
inhibitor_free(i);
if (fifo_fd >= 0)
close_nointr_nofail(fifo_fd);
if (reply)
dbus_message_unref(reply);
return r;
}
static int trigger_device(Manager *m, struct udev_device *d) {
struct udev_enumerate *e;
struct udev_list_entry *first, *item;
int r;
assert(m);
e = udev_enumerate_new(m->udev);
if (!e) {
r = -ENOMEM;
goto finish;
}
if (d) {
if (udev_enumerate_add_match_parent(e, d) < 0) {
r = -EIO;
goto finish;
}
}
if (udev_enumerate_scan_devices(e) < 0) {
r = -EIO;
goto finish;
}
first = udev_enumerate_get_list_entry(e);
udev_list_entry_foreach(item, first) {
char *t;
const char *p;
p = udev_list_entry_get_name(item);
t = strappend(p, "/uevent");
if (!t) {
r = -ENOMEM;
goto finish;
}
write_one_line_file(t, "change");
free(t);
}
r = 0;
finish:
if (e)
udev_enumerate_unref(e);
return r;
}
static int attach_device(Manager *m, const char *seat, const char *sysfs) {
struct udev_device *d;
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")) {
r = -ENODEV;
goto finish;
}
id_for_seat = udev_device_get_property_value(d, "ID_FOR_SEAT");
if (!id_for_seat) {
r = -ENODEV;
goto finish;
}
if (asprintf(&file, "/etc/udev/rules.d/72-seat-%s.rules", id_for_seat) < 0) {
r = -ENOMEM;
goto finish;
}
if (asprintf(&rule, "TAG==\"seat\", ENV{ID_FOR_SEAT}==\"%s\", ENV{ID_SEAT}=\"%s\"", id_for_seat, seat) < 0) {
r = -ENOMEM;
goto finish;
}
mkdir_p_label("/etc/udev/rules.d", 0755);
r = write_one_line_file_atomic(file, rule);
if (r < 0)
goto finish;
r = trigger_device(m, d);
finish:
free(rule);
free(file);
if (d)
udev_device_unref(d);
return r;
}
static int flush_devices(Manager *m) {
DIR *d;
assert(m);
d = opendir("/etc/udev/rules.d");
if (!d) {
if (errno != ENOENT)
log_warning("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("Failed to unlink %s: %m", de->d_name);
}
closedir(d);
}
return trigger_device(m, NULL);
}
static int have_multiple_sessions(
DBusConnection *connection,
Manager *m,
DBusMessage *message,
DBusError *error) {
Session *session;
Iterator i;
unsigned long ul;
assert(m);
ul = dbus_bus_get_unix_user(connection, dbus_message_get_sender(message), error);
if (ul == (unsigned long) -1)
return -EIO;
/* Check for other users' sessions. Greeter sessions do not count. */
HASHMAP_FOREACH(session, m->sessions, i)
if (session->class == SESSION_USER && session->user->uid != ul)
return true;
return false;
}
static int send_start_unit(DBusConnection *connection, const char *unit_name, DBusError *error) {
DBusMessage *message, *reply;
const char *mode = "replace";
assert(connection);
assert(unit_name);
message = dbus_message_new_method_call(
"org.freedesktop.systemd1",
"/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager",
"StartUnit");
if (!message)
return -ENOMEM;
if (!dbus_message_append_args(message,
DBUS_TYPE_STRING, &unit_name,
DBUS_TYPE_STRING, &mode,
DBUS_TYPE_INVALID)) {
dbus_message_unref(message);
return -ENOMEM;
}
reply = dbus_connection_send_with_reply_and_block(connection, message, -1, error);
dbus_message_unref(message);
if (!reply)
return -EIO;
dbus_message_unref(reply);
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"
};
dbus_bool_t active = _active;
DBusMessage *message;
int r = 0;
assert(m);
assert(w >= 0);
assert(w < _INHIBIT_WHAT_MAX);
assert(signal_name[w]);
message = dbus_message_new_signal("/org/freedesktop/login1", "org.freedesktop.login1.Manager", signal_name[w]);
if (!message)
return -ENOMEM;
if (!dbus_message_append_args(message, DBUS_TYPE_BOOLEAN, &active, DBUS_TYPE_INVALID) ||
!dbus_connection_send(m->bus, message, NULL))
r = -ENOMEM;
dbus_message_unref(message);
return r;
}
static int delay_shutdown_or_sleep(Manager *m, InhibitWhat w, const char *unit_name) {
assert(m);
assert(w >= 0);
assert(w < _INHIBIT_WHAT_MAX);
/* Tell everybody to prepare for shutdown/sleep */
send_prepare_for(m, w, true);
/* Update timestamp for timeout */
if (!m->delayed_unit)
m->delayed_timestamp = now(CLOCK_MONOTONIC);
/* Remember what we want to do, possibly overriding what kind
* of unit we previously queued. */
m->delayed_unit = unit_name;
m->delayed_what = w;
return 0;
}
static int bus_manager_can_shutdown_or_sleep(
Manager *m,
DBusConnection *connection,
DBusMessage *message,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_type,
DBusError *error,
DBusMessage **_reply) {
bool multiple_sessions, challenge, blocked, b;
const char *result;
DBusMessage *reply = NULL;
int r;
assert(m);
assert(connection);
assert(message);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
assert(action);
assert(action_multiple_sessions);
assert(action_ignore_inhibit);
assert(error);
assert(_reply);
if (sleep_type) {
r = can_sleep(sleep_type);
if (r < 0)
return r;
if (r == 0) {
result = "na";
goto finish;
}
}
r = have_multiple_sessions(connection, m, message, error);
if (r < 0)
return r;
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL);
if (multiple_sessions) {
r = verify_polkit(connection, message, action_multiple_sessions, false, &challenge, error);
if (r < 0)
return r;
if (r > 0)
result = "yes";
else if (challenge)
result = "challenge";
else
result = "no";
}
if (blocked) {
r = verify_polkit(connection, message, action_ignore_inhibit, false, &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 = verify_polkit(connection, message, action, false, &challenge, error);
if (r < 0)
return r;
if (r > 0)
result = "yes";
else if (challenge)
result = "challenge";
else
result = "no";
}
finish:
reply = dbus_message_new_method_return(message);
if (!reply)
return -ENOMEM;
b = dbus_message_append_args(
reply,
DBUS_TYPE_STRING, &result,
DBUS_TYPE_INVALID);
if (!b) {
dbus_message_unref(reply);
return -ENOMEM;
}
*_reply = reply;
return 0;
}
int bus_manager_shutdown_or_sleep_now_or_later(
Manager *m,
const char *unit_name,
InhibitWhat w,
DBusError *error) {
bool delayed;
int r;
assert(m);
assert(unit_name);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
delayed =
m->inhibit_delay_max > 0 &&
manager_is_inhibited(m, w, INHIBIT_DELAY, 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 = send_start_unit(m->bus, unit_name, error);
return r;
}
static int bus_manager_do_shutdown_or_sleep(
Manager *m,
DBusConnection *connection,
DBusMessage *message,
const char *unit_name,
InhibitWhat w,
const char *action,
const char *action_multiple_sessions,
const char *action_ignore_inhibit,
const char *sleep_type,
DBusError *error,
DBusMessage **_reply) {
dbus_bool_t interactive;
bool multiple_sessions, blocked;
DBusMessage *reply = NULL;
int r;
assert(m);
assert(connection);
assert(message);
assert(unit_name);
assert(w >= 0);
assert(w <= _INHIBIT_WHAT_MAX);
assert(action);
assert(action_multiple_sessions);
assert(action_ignore_inhibit);
assert(error);
assert(_reply);
if (!dbus_message_get_args(
message,
error,
DBUS_TYPE_BOOLEAN, &interactive,
DBUS_TYPE_INVALID))
return -EINVAL;
if (sleep_type) {
r = can_sleep(sleep_type);
if (r < 0)
return r;
if (r == 0)
return -ENOTSUP;
}
r = have_multiple_sessions(connection, m, message, error);
if (r < 0)
return r;
multiple_sessions = r > 0;
blocked = manager_is_inhibited(m, w, INHIBIT_BLOCK, NULL);
if (multiple_sessions) {
r = verify_polkit(connection, message, action_multiple_sessions, interactive, NULL, error);
if (r < 0)
return r;
}
if (blocked) {
r = verify_polkit(connection, message, action_ignore_inhibit, interactive, NULL, error);
if (r < 0)
return r;
}
if (!multiple_sessions && !blocked) {
r = verify_polkit(connection, message, action, interactive, NULL, 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;
reply = dbus_message_new_method_return(message);
if (!reply)
return -ENOMEM;
*_reply = reply;
return 0;
}
static DEFINE_BUS_PROPERTY_APPEND_ENUM(bus_manager_append_handle_button, handle_button, HandleButton);
static const BusProperty bus_login_manager_properties[] = {
{ "ControlGroupHierarchy", bus_property_append_string, "s", offsetof(Manager, cgroup_path), true },
{ "Controllers", bus_property_append_strv, "as", offsetof(Manager, controllers), true },
{ "ResetControllers", bus_property_append_strv, "as", offsetof(Manager, reset_controllers), true },
{ "NAutoVTs", bus_property_append_unsigned, "u", offsetof(Manager, n_autovts) },
{ "KillOnlyUsers", bus_property_append_strv, "as", offsetof(Manager, kill_only_users), true },
{ "KillExcludeUsers", bus_property_append_strv, "as", offsetof(Manager, kill_exclude_users), true },
{ "KillUserProcesses", bus_property_append_bool, "b", offsetof(Manager, kill_user_processes) },
{ "IdleHint", bus_manager_append_idle_hint, "b", 0 },
{ "IdleSinceHint", bus_manager_append_idle_hint_since, "t", 0 },
{ "IdleSinceHintMonotonic", bus_manager_append_idle_hint_since, "t", 0 },
{ "BlockInhibited", bus_manager_append_inhibited, "s", 0 },
{ "DelayInhibited", bus_manager_append_inhibited, "s", 0 },
{ "InhibitDelayMaxUSec", bus_property_append_usec, "t", offsetof(Manager, inhibit_delay_max) },
{ "HandlePowerKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_power_key) },
{ "HandleSleepKey", bus_manager_append_handle_button, "s", offsetof(Manager, handle_sleep_key) },
{ "HandleLidSwitch", bus_manager_append_handle_button, "s", offsetof(Manager, handle_lid_switch) },
{ "PreparingForShutdown", bus_manager_append_preparing, "b", 0 },
{ "PreparingForSleep", bus_manager_append_preparing, "b", 0 },
{ NULL, }
};
static DBusHandlerResult manager_message_handler(
DBusConnection *connection,
DBusMessage *message,
void *userdata) {
Manager *m = userdata;
DBusError error;
DBusMessage *reply = NULL;
int r;
assert(connection);
assert(message);
assert(m);
dbus_error_init(&error);
if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSession")) {
const char *name;
char *p;
Session *session;
bool b;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
session = hashmap_get(m->sessions, name);
if (!session)
return bus_send_error_reply(connection, message, &error, -ENOENT);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
p = session_bus_path(session);
if (!p)
goto oom;
b = dbus_message_append_args(
reply,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_INVALID);
free(p);
if (!b)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSessionByPID")) {
uint32_t pid;
char *p;
Session *session;
bool b;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_UINT32, &pid,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
r = manager_get_session_by_pid(m, pid, &session);
if (r <= 0)
return bus_send_error_reply(connection, message, NULL, r < 0 ? r : -ENOENT);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
p = session_bus_path(session);
if (!p)
goto oom;
b = dbus_message_append_args(
reply,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_INVALID);
free(p);
if (!b)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetUser")) {
uint32_t uid;
char *p;
User *user;
bool b;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_UINT32, &uid,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
if (!user)
return bus_send_error_reply(connection, message, &error, -ENOENT);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
p = user_bus_path(user);
if (!p)
goto oom;
b = dbus_message_append_args(
reply,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_INVALID);
free(p);
if (!b)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "GetSeat")) {
const char *name;
char *p;
Seat *seat;
bool b;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
seat = hashmap_get(m->seats, name);
if (!seat)
return bus_send_error_reply(connection, message, &error, -ENOENT);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
p = seat_bus_path(seat);
if (!p)
goto oom;
b = dbus_message_append_args(
reply,
DBUS_TYPE_OBJECT_PATH, &p,
DBUS_TYPE_INVALID);
free(p);
if (!b)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSessions")) {
char *p;
Session *session;
Iterator i;
DBusMessageIter iter, sub;
const char *empty = "";
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
dbus_message_iter_init_append(reply, &iter);
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(susso)", &sub))
goto oom;
HASHMAP_FOREACH(session, m->sessions, i) {
DBusMessageIter sub2;
uint32_t uid;
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
goto oom;
uid = session->user->uid;
p = session_bus_path(session);
if (!p)
goto oom;
if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->id) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &session->user->name) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, session->seat ? (const char**) &session->seat->id : &empty) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
free(p);
goto oom;
}
free(p);
if (!dbus_message_iter_close_container(&sub, &sub2))
goto oom;
}
if (!dbus_message_iter_close_container(&iter, &sub))
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListUsers")) {
char *p;
User *user;
Iterator i;
DBusMessageIter iter, sub;
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
dbus_message_iter_init_append(reply, &iter);
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(uso)", &sub))
goto oom;
HASHMAP_FOREACH(user, m->users, i) {
DBusMessageIter sub2;
uint32_t uid;
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
goto oom;
uid = user->uid;
p = user_bus_path(user);
if (!p)
goto oom;
if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &user->name) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
free(p);
goto oom;
}
free(p);
if (!dbus_message_iter_close_container(&sub, &sub2))
goto oom;
}
if (!dbus_message_iter_close_container(&iter, &sub))
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListSeats")) {
char *p;
Seat *seat;
Iterator i;
DBusMessageIter iter, sub;
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
dbus_message_iter_init_append(reply, &iter);
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(so)", &sub))
goto oom;
HASHMAP_FOREACH(seat, m->seats, i) {
DBusMessageIter sub2;
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
goto oom;
p = seat_bus_path(seat);
if (!p)
goto oom;
if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &seat->id) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_OBJECT_PATH, &p)) {
free(p);
goto oom;
}
free(p);
if (!dbus_message_iter_close_container(&sub, &sub2))
goto oom;
}
if (!dbus_message_iter_close_container(&iter, &sub))
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ListInhibitors")) {
Inhibitor *inhibitor;
Iterator i;
DBusMessageIter iter, sub;
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
dbus_message_iter_init_append(reply, &iter);
if (!dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "(ssssuu)", &sub))
goto oom;
HASHMAP_FOREACH(inhibitor, m->inhibitors, i) {
DBusMessageIter sub2;
dbus_uint32_t uid, pid;
const char *what, *who, *why, *mode;
if (!dbus_message_iter_open_container(&sub, DBUS_TYPE_STRUCT, NULL, &sub2))
goto oom;
what = strempty(inhibit_what_to_string(inhibitor->what));
who = strempty(inhibitor->who);
why = strempty(inhibitor->why);
mode = strempty(inhibit_mode_to_string(inhibitor->mode));
uid = (dbus_uint32_t) inhibitor->uid;
pid = (dbus_uint32_t) inhibitor->pid;
if (!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &what) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &who) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &why) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_STRING, &mode) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &uid) ||
!dbus_message_iter_append_basic(&sub2, DBUS_TYPE_UINT32, &pid))
goto oom;
if (!dbus_message_iter_close_container(&sub, &sub2))
goto oom;
}
if (!dbus_message_iter_close_container(&iter, &sub))
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Inhibit")) {
r = bus_manager_inhibit(m, connection, message, &error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CreateSession")) {
r = bus_manager_create_session(m, message, &reply);
/* Don't delay the work on OOM here, since it might be
* triggered by a low RLIMIT_NOFILE here (since we
* send a dupped fd to the client), and we'd rather
* see this fail quickly then be retried later */
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ReleaseSession")) {
const char *name;
Session *session;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
session = hashmap_get(m->sessions, name);
if (!session)
return bus_send_error_reply(connection, message, &error, -ENOENT);
/* We use the FIFO to detect stray sessions where the
process invoking PAM dies abnormally. We need to make
sure that that process is not killed if at the clean
end of the session it closes the FIFO. Hence, with
this call explicitly turn off the FIFO logic, so that
the PAM code can finish clean up on its own */
session_remove_fifo(session);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSession")) {
const char *name;
Session *session;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
session = hashmap_get(m->sessions, name);
if (!session)
return bus_send_error_reply(connection, message, &error, -ENOENT);
r = session_activate(session);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "ActivateSessionOnSeat")) {
const char *session_name, *seat_name;
Session *session;
Seat *seat;
/* Same as ActivateSession() but refuses to work if
* the seat doesn't match */
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &session_name,
DBUS_TYPE_STRING, &seat_name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
session = hashmap_get(m->sessions, session_name);
if (!session)
return bus_send_error_reply(connection, message, &error, -ENOENT);
seat = hashmap_get(m->seats, seat_name);
if (!seat)
return bus_send_error_reply(connection, message, &error, -ENOENT);
if (session->seat != seat)
return bus_send_error_reply(connection, message, &error, -EINVAL);
r = session_activate(session);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "LockSession") ||
dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "UnlockSession")) {
const char *name;
Session *session;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
session = hashmap_get(m->sessions, name);
if (!session)
return bus_send_error_reply(connection, message, &error, -ENOENT);
if (session_send_lock(session, streq(dbus_message_get_member(message), "LockSession")) < 0)
goto oom;
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillSession")) {
const char *swho;
int32_t signo;
KillWho who;
const char *name;
Session *session;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_STRING, &swho,
DBUS_TYPE_INT32, &signo,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
if (isempty(swho))
who = KILL_ALL;
else {
who = kill_who_from_string(swho);
if (who < 0)
return bus_send_error_reply(connection, message, &error, -EINVAL);
}
if (signo <= 0 || signo >= _NSIG)
return bus_send_error_reply(connection, message, &error, -EINVAL);
session = hashmap_get(m->sessions, name);
if (!session)
return bus_send_error_reply(connection, message, &error, -ENOENT);
r = session_kill(session, who, signo);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "KillUser")) {
uint32_t uid;
User *user;
int32_t signo;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_UINT32, &uid,
DBUS_TYPE_INT32, &signo,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
if (signo <= 0 || signo >= _NSIG)
return bus_send_error_reply(connection, message, &error, -EINVAL);
user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
if (!user)
return bus_send_error_reply(connection, message, &error, -ENOENT);
r = user_kill(user, signo);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSession")) {
const char *name;
Session *session;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
session = hashmap_get(m->sessions, name);
if (!session)
return bus_send_error_reply(connection, message, &error, -ENOENT);
r = session_stop(session);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateUser")) {
uint32_t uid;
User *user;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_UINT32, &uid,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
user = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
if (!user)
return bus_send_error_reply(connection, message, &error, -ENOENT);
r = user_stop(user);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "TerminateSeat")) {
const char *name;
Seat *seat;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
seat = hashmap_get(m->seats, name);
if (!seat)
return bus_send_error_reply(connection, message, &error, -ENOENT);
r = seat_stop_sessions(seat);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, r);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "SetUserLinger")) {
uint32_t uid;
struct passwd *pw;
dbus_bool_t b, interactive;
char *path;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_UINT32, &uid,
DBUS_TYPE_BOOLEAN, &b,
DBUS_TYPE_BOOLEAN, &interactive,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
errno = 0;
pw = getpwuid(uid);
if (!pw)
return bus_send_error_reply(connection, message, NULL, errno ? -errno : -EINVAL);
r = verify_polkit(connection, message, "org.freedesktop.login1.set-user-linger", interactive, NULL, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
mkdir_p_label("/var/lib/systemd", 0755);
r = mkdir_safe_label("/var/lib/systemd/linger", 0755, 0, 0);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
path = strappend("/var/lib/systemd/linger/", pw->pw_name);
if (!path)
goto oom;
if (b) {
User *u;
r = touch(path);
free(path);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
if (manager_add_user_by_uid(m, uid, &u) >= 0)
user_start(u);
} else {
User *u;
r = unlink(path);
free(path);
if (r < 0 && errno != ENOENT)
return bus_send_error_reply(connection, message, &error, -errno);
u = hashmap_get(m->users, ULONG_TO_PTR((unsigned long) uid));
if (u)
user_add_to_gc_queue(u);
}
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "AttachDevice")) {
const char *sysfs, *seat;
dbus_bool_t interactive;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_STRING, &seat,
DBUS_TYPE_STRING, &sysfs,
DBUS_TYPE_BOOLEAN, &interactive,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
if (!path_startswith(sysfs, "/sys") || !seat_name_is_valid(seat))
return bus_send_error_reply(connection, message, NULL, -EINVAL);
r = verify_polkit(connection, message, "org.freedesktop.login1.attach-device", interactive, NULL, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
r = attach_device(m, seat, sysfs);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, -EINVAL);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "FlushDevices")) {
dbus_bool_t interactive;
if (!dbus_message_get_args(
message,
&error,
DBUS_TYPE_BOOLEAN, &interactive,
DBUS_TYPE_INVALID))
return bus_send_error_reply(connection, message, &error, -EINVAL);
r = verify_polkit(connection, message, "org.freedesktop.login1.flush-devices", interactive, NULL, &error);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
r = flush_devices(m);
if (r < 0)
return bus_send_error_reply(connection, message, NULL, -EINVAL);
reply = dbus_message_new_method_return(message);
if (!reply)
goto oom;
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "PowerOff")) {
r = bus_manager_do_shutdown_or_sleep(
m, connection, 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, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Reboot")) {
r = bus_manager_do_shutdown_or_sleep(
m, connection, message,
SPECIAL_REBOOT_TARGET,
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.reboot",
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
NULL,
&error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Suspend")) {
r = bus_manager_do_shutdown_or_sleep(
m, connection, message,
SPECIAL_SUSPEND_TARGET,
INHIBIT_SLEEP,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"mem",
&error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "Hibernate")) {
r = bus_manager_do_shutdown_or_sleep(
m, connection, message,
SPECIAL_HIBERNATE_TARGET,
INHIBIT_SLEEP,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"disk",
&error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanPowerOff")) {
r = bus_manager_can_shutdown_or_sleep(
m, connection, message,
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.power-off",
"org.freedesktop.login1.power-off-multiple-sessions",
"org.freedesktop.login1.power-off-ignore-inhibit",
NULL,
&error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanReboot")) {
r = bus_manager_can_shutdown_or_sleep(
m, connection, message,
INHIBIT_SHUTDOWN,
"org.freedesktop.login1.reboot",
"org.freedesktop.login1.reboot-multiple-sessions",
"org.freedesktop.login1.reboot-ignore-inhibit",
NULL,
&error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanSuspend")) {
r = bus_manager_can_shutdown_or_sleep(
m, connection, message,
INHIBIT_SLEEP,
"org.freedesktop.login1.suspend",
"org.freedesktop.login1.suspend-multiple-sessions",
"org.freedesktop.login1.suspend-ignore-inhibit",
"mem",
&error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.login1.Manager", "CanHibernate")) {
r = bus_manager_can_shutdown_or_sleep(
m, connection, message,
INHIBIT_SLEEP,
"org.freedesktop.login1.hibernate",
"org.freedesktop.login1.hibernate-multiple-sessions",
"org.freedesktop.login1.hibernate-ignore-inhibit",
"disk",
&error, &reply);
if (r < 0)
return bus_send_error_reply(connection, message, &error, r);
} else if (dbus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", "Introspect")) {
char *introspection = NULL;
FILE *f;
Iterator i;
Session *session;
Seat *seat;
User *user;
size_t size;
char *p;
if (!(reply = dbus_message_new_method_return(message)))
goto oom;
/* We roll our own introspection code here, instead of
* relying on bus_default_message_handler() because we
* need to generate our introspection string
* dynamically. */
if (!(f = open_memstream(&introspection, &size)))
goto oom;
fputs(INTROSPECTION_BEGIN, f);
HASHMAP_FOREACH(seat, m->seats, i) {
p = bus_path_escape(seat->id);
if (p) {
fprintf(f, "<node name=\"seat/%s\"/>", p);
free(p);
}
}
HASHMAP_FOREACH(user, m->users, i)
fprintf(f, "<node name=\"user/%llu\"/>", (unsigned long long) user->uid);
HASHMAP_FOREACH(session, m->sessions, i) {
p = bus_path_escape(session->id);
if (p) {
fprintf(f, "<node name=\"session/%s\"/>", p);
free(p);
}
}
fputs(INTROSPECTION_END, f);
if (ferror(f)) {
fclose(f);
free(introspection);
goto oom;
}
fclose(f);
if (!introspection)
goto oom;
if (!dbus_message_append_args(reply, DBUS_TYPE_STRING, &introspection, DBUS_TYPE_INVALID)) {
free(introspection);
goto oom;
}
free(introspection);
} else {
const BusBoundProperties bps[] = {
{ "org.freedesktop.login1.Manager", bus_login_manager_properties, m },
{ NULL, }
};
return bus_default_message_handler(connection, message, NULL, INTERFACES_LIST, bps);
}
if (reply) {
if (!dbus_connection_send(connection, reply, NULL))
goto oom;
dbus_message_unref(reply);
}
return DBUS_HANDLER_RESULT_HANDLED;
oom:
if (reply)
dbus_message_unref(reply);
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_NEED_MEMORY;
}
const DBusObjectPathVTable bus_manager_vtable = {
.message_function = manager_message_handler
};
DBusHandlerResult bus_message_filter(
DBusConnection *connection,
DBusMessage *message,
void *userdata) {
Manager *m = userdata;
DBusError error;
assert(m);
assert(connection);
assert(message);
dbus_error_init(&error);
if (dbus_message_is_signal(message, "org.freedesktop.systemd1.Agent", "Released")) {
const char *cgroup;
if (!dbus_message_get_args(message, &error,
DBUS_TYPE_STRING, &cgroup,
DBUS_TYPE_INVALID))
log_error("Failed to parse Released message: %s", bus_error_message(&error));
else
manager_cgroup_notify_empty(m, cgroup);
}
dbus_error_free(&error);
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
}
int manager_send_changed(Manager *manager, const char *properties) {
DBusMessage *m;
int r = -ENOMEM;
assert(manager);
m = bus_properties_changed_new("/org/freedesktop/login1", "org.freedesktop.login1.Manager", properties);
if (!m)
goto finish;
if (!dbus_connection_send(manager->bus, m, NULL))
goto finish;
r = 0;
finish:
if (m)
dbus_message_unref(m);
return r;
}
int manager_dispatch_delayed(Manager *manager) {
const char *unit_name;
DBusError error;
bool delayed;
int r;
assert(manager);
if (!manager->delayed_unit)
return 0;
/* Continue delay? */
delayed =
manager->delayed_timestamp + manager->inhibit_delay_max > now(CLOCK_MONOTONIC) &&
manager_is_inhibited(manager, manager->delayed_what, INHIBIT_DELAY, NULL);
if (delayed)
return 0;
/* Reset delay data */
unit_name = manager->delayed_unit;
manager->delayed_unit = NULL;
/* Actually do the shutdown */
dbus_error_init(&error);
r = send_start_unit(manager->bus, unit_name, &error);
if (r < 0) {
log_warning("Failed to send delayed message: %s", bus_error_message_or_strerror(&error, -r));
dbus_error_free(&error);
return r;
}
/* Tell people about it */
send_prepare_for(manager, manager->delayed_what, false);
return 1;
}