bus-util.c revision cab2aca3e7dc9966eb9f45416f34729719f01dd4
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen/***
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen This file is part of systemd.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Copyright 2013 Lennart Poettering
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is free software; you can redistribute it and/or modify it
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen under the terms of the GNU Lesser General Public License as published by
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen the Free Software Foundation; either version 2.1 of the License, or
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen (at your option) any later version.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen systemd is distributed in the hope that it will be useful, but
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen WITHOUT ANY WARRANTY; without even the implied warranty of
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Lesser General Public License for more details.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen You should have received a copy of the GNU Lesser General Public License
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen along with systemd; If not, see <http://www.gnu.org/licenses/>.
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen***/
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <errno.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <fcntl.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <inttypes.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <stdio.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <stdlib.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <string.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <sys/ioctl.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <sys/resource.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <sys/socket.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include <unistd.h>
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "sd-bus-protocol.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "sd-bus.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "sd-daemon.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "sd-event.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "sd-id128.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "alloc-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "bus-internal.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "bus-label.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "bus-message.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "bus-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "cgroup-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "def.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "env-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "escape.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "extract-word.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "fd-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "hashmap.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "install.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "kdbus.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "log.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "macro.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "missing.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "parse-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "path-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "proc-cmdline.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "process-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "rlimit-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "set.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "signal-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "stdio-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "string-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "strv.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "syslog-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "time-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "unit-name.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "user-util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "utf8.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#include "util.h"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event *e = userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(m);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_close(sd_bus_message_get_bus(m));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_exit(e, 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *match = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *unique;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* We unregister the name here and then wait for the
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * NameOwnerChanged signal for this event to arrive before we
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * quit. We do this in order to make sure that any queued
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * requests are still processed before we really exit. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_get_unique_name(bus, &unique);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = asprintf(&match,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "sender='org.freedesktop.DBus',"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "type='signal',"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "interface='org.freedesktop.DBus',"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "member='NameOwnerChanged',"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "path='/org/freedesktop/DBus',"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "arg0='%s',"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "arg1='%s',"
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "arg2=''", name, unique);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -ENOMEM;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_release_name(bus, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_event_loop_with_idle(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event *e,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus *bus,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *name,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen usec_t timeout,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen check_idle_t check_idle,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool exiting = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r, code;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen for (;;) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool idle;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_get_state(e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == SD_EVENT_FINISHED)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (check_idle)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen idle = check_idle(userdata);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen idle = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == 0 && !exiting && idle) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_try_close(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == -EBUSY)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Fallback for dbus1 connections: we
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * unregister the name and wait for the
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * response to come through for it */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r == -EOPNOTSUPP) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Inform the service manager that we
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * are going down, so that it will
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * queue all further start requests,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * instead of assuming we are already
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * running. */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_notify(false, "STOPPING=1");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = bus_async_unregister_and_exit(e, bus, name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen exiting = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen continue;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_event_exit(e, 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_event_get_exit_code(e, &code);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return code;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r, has_owner = 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(c);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_call_method(c,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "org.freedesktop.DBus",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "/org/freedesktop/dbus",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "org.freedesktop.DBus",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "NameHasOwner",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen error,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen &rep,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "s",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(rep, 'b', &has_owner);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return sd_bus_error_set_errno(error, r);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return has_owner;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int check_good_user(sd_bus_message *m, uid_t good_user) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uid_t sender_uid;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(m);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (good_user == UID_INVALID)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Don't trust augmented credentials for authorization */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_creds_get_euid(creds, &sender_uid);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return sender_uid == good_user;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_test_polkit(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_message *call,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int capability,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *action,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char **details,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uid_t good_user,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool *_challenge,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_error *e) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(call);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(action);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Tests non-interactively! */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = check_good_user(call, good_user);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r != 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_query_sender_privilege(call, capability);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else if (r > 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#ifdef ENABLE_POLKIT
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int authorized = false, challenge = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *sender, **k, **v;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sender = sd_bus_message_get_sender(call);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!sender)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EBADMSG;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_new_method_call(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen call->bus,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen &request,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "org.freedesktop.PolicyKit1",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "/org/freedesktop/PolicyKit1/Authority",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "org.freedesktop.PolicyKit1.Authority",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "CheckAuthorization");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_append(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen request,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "(sa{sv})s",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "system-bus-name", 1, "name", "s", sender,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen action);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_open_container(request, 'a', "{ss}");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen STRV_FOREACH_PAIR(k, v, details) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_append(request, "{ss}", *k, *v);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_close_container(request);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_append(request, "us", 0, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_call(call->bus, request, 0, e, &reply);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Treat no PK available as access denied */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_error_free(e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EACCES;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (authorized)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (_challenge) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *_challenge = challenge;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#endif
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EACCES;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#ifdef ENABLE_POLKIT
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersentypedef struct AsyncPolkitQuery {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_message *request, *reply;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_message_handler_t callback;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_slot *slot;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Hashmap *registry;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen} AsyncPolkitQuery;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic void async_polkit_query_free(AsyncPolkitQuery *q) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!q)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_slot_unref(q->slot);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (q->registry && q->request)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen hashmap_remove(q->registry, q->request);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_message_unref(q->request);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_message_unref(q->reply);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen free(q);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenstatic int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen AsyncPolkitQuery *q = userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(reply);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(q);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen q->slot = sd_bus_slot_unref(q->slot);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen q->reply = sd_bus_message_ref(reply);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_rewind(q->request, true);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_reply_method_errno(q->request, r, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen goto finish;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = q->callback(q->request, q->userdata, &error_buffer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = bus_maybe_reply_error(q->request, r, &error_buffer);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenfinish:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen async_polkit_query_free(q);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#endif
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_verify_polkit_async(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_message *call,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int capability,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *action,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char **details,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool interactive,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uid_t good_user,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen Hashmap **registry,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_error *error) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#ifdef ENABLE_POLKIT
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen AsyncPolkitQuery *q;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *sender, **k, **v;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_message_handler_t callback;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen void *userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int c;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#endif
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(call);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(action);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(registry);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = check_good_user(call, good_user);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r != 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#ifdef ENABLE_POLKIT
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen q = hashmap_get(*registry, call);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (q) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int authorized, challenge;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* This is the second invocation of this function, and
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * there's already a response from polkit, let's
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * process it */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(q->reply);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (sd_bus_message_is_method_error(q->reply, NULL)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const sd_bus_error *e;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Copy error from polkit reply */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen e = sd_bus_message_get_error(q->reply);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sd_bus_error_copy(error, e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Treat no PK available as access denied */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EACCES;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -sd_bus_error_get_errno(e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r >= 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (authorized)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (challenge)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EACCES;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#endif
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_query_sender_privilege(call, capability);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else if (r > 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#ifdef ENABLE_POLKIT
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (sd_bus_get_current_message(call->bus) != call)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EINVAL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen callback = sd_bus_get_current_handler(call->bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!callback)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EINVAL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen userdata = sd_bus_get_current_userdata(call->bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen sender = sd_bus_message_get_sender(call);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!sender)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EBADMSG;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen c = sd_bus_message_get_allow_interactive_authorization(call);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (c < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return c;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (c > 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen interactive = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = hashmap_ensure_allocated(registry, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_new_method_call(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen call->bus,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen &pk,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "org.freedesktop.PolicyKit1",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "/org/freedesktop/PolicyKit1/Authority",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "org.freedesktop.PolicyKit1.Authority",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "CheckAuthorization");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_append(
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen pk,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "(sa{sv})s",
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen "system-bus-name", 1, "name", "s", sender,
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen action);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_open_container(pk, 'a', "{ss}");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen STRV_FOREACH_PAIR(k, v, details) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_append(pk, "{ss}", *k, *v);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_close_container(pk);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_append(pk, "us", !!interactive, NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen q = new0(AsyncPolkitQuery, 1);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!q)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -ENOMEM;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen q->request = sd_bus_message_ref(call);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen q->callback = callback;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen q->userdata = userdata;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = hashmap_put(*registry, call, q);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen async_polkit_query_free(q);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen q->registry = *registry;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen async_polkit_query_free(q);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#endif
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EACCES;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenvoid bus_verify_polkit_async_registry_free(Hashmap *registry) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#ifdef ENABLE_POLKIT
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen AsyncPolkitQuery *q;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen while ((q = hashmap_steal_first(registry)))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen async_polkit_query_free(q);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen hashmap_free(registry);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen#endif
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_check_peercred(sd_bus *c) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen struct ucred ucred;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen socklen_t l;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(c);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen fd = sd_bus_get_fd(c);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (fd < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return fd;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen l = sizeof(struct ucred);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -errno;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (l != sizeof(struct ucred))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -E2BIG;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (ucred.uid != 0 && ucred.uid != geteuid())
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -EPERM;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_connect_system_systemd(sd_bus **_bus) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(_bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (geteuid() != 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return sd_bus_default_system(_bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* If we are root and kdbus is not available, then let's talk
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * directly to the system instance, instead of going via the
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * bus */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_new(&bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus->bus_client = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_start(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r >= 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *_bus = bus;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus = sd_bus_unref(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_new(&bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_start(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return sd_bus_default_system(_bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = bus_check_peercred(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *_bus = bus;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_connect_user_systemd(sd_bus **_bus) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *ee = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *e;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Try via kdbus first, and then directly */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(_bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_new(&bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -ENOMEM;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus->bus_client = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_start(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r >= 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *_bus = bus;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus = sd_bus_unref(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen e = secure_getenv("XDG_RUNTIME_DIR");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!e)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return sd_bus_default_user(_bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen ee = bus_address_escape(e);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!ee)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -ENOMEM;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_new(&bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!bus->address)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -ENOMEM;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_start(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return sd_bus_default_user(_bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = bus_check_peercred(bus);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen *_bus = bus;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bus = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 0;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen}
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersenint bus_print_property(const char *name, sd_bus_message *property, bool all) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char type;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *contents;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen assert(property);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_peek_type(property, &type, &contents);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen switch (type) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case SD_BUS_TYPE_STRING: {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *s;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(property, type, &s);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (all || !isempty(s)) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *escaped = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen escaped = xescape(s, "\n");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!escaped)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -ENOMEM;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%s\n", name, escaped);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case SD_BUS_TYPE_BOOLEAN: {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int b;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(property, type, &b);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%s\n", name, yes_no(b));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case SD_BUS_TYPE_UINT64: {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint64_t u;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(property, type, &u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen /* Yes, heuristics! But we can change this check
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen * should it turn out to not be sufficient */
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (endswith(name, "Timestamp")) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char timestamp[FORMAT_TIMESTAMP_MAX], *t;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen t = format_timestamp(timestamp, sizeof(timestamp), u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (t || all)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%s\n", name, strempty(t));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (strstr(name, "USec")) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen char timespan[FORMAT_TIMESPAN_MAX];
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%llu\n", name, (unsigned long long) u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case SD_BUS_TYPE_INT64: {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int64_t i;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(property, type, &i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%lld\n", name, (long long) i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case SD_BUS_TYPE_UINT32: {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint32_t u;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(property, type, &u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (strstr(name, "UMask") || strstr(name, "Mode"))
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%04o\n", name, u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen else
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%u\n", name, (unsigned) u);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case SD_BUS_TYPE_INT32: {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen int32_t i;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(property, type, &i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%i\n", name, (int) i);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case SD_BUS_TYPE_DOUBLE: {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen double d;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_basic(property, type, &d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=%g\n", name, d);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen case SD_BUS_TYPE_ARRAY:
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (streq(contents, "s")) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen bool first = true;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const char *str;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen _cleanup_free_ char *escaped = NULL;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (first)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=", name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen escaped = xescape(str, "\n ");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!escaped)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return -ENOMEM;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s%s", first ? "" : " ", escaped);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen first = false;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (first && all)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=", name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (!first || all)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen puts("");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_exit_container(property);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (streq(contents, "y")) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen const uint8_t *u;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen size_t n;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (all || n > 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unsigned int i;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=", name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen for (i = 0; i < n; i++)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%02x", u[i]);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen puts("");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen } else if (streq(contents, "u")) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen uint32_t *u;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen size_t n;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (r < 0)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return r;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen if (all || n > 0) {
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen unsigned int i;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%s=", name);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen for (i = 0; i < n; i++)
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen printf("%08x", u[i]);
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen puts("");
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen return 1;
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen }
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen
95ed3294c632f5606327149f10cef1eb34422862Thomas Hindoe Paaboel Andersen break;
}
return 0;
}
int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
assert(path);
r = sd_bus_call_method(bus,
dest,
path,
"org.freedesktop.DBus.Properties",
"GetAll",
&error,
&reply,
"s", "");
if (r < 0)
return r;
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
if (r < 0)
return r;
while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
const char *name;
const char *contents;
r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
if (r < 0)
return r;
if (!filter || strv_find(filter, name)) {
r = sd_bus_message_peek_type(reply, NULL, &contents);
if (r < 0)
return r;
r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
if (r < 0)
return r;
r = bus_print_property(name, reply, all);
if (r < 0)
return r;
if (r == 0) {
if (all)
printf("%s=[unprintable]\n", name);
/* skip what we didn't read */
r = sd_bus_message_skip(reply, contents);
if (r < 0)
return r;
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return r;
} else {
r = sd_bus_message_skip(reply, "v");
if (r < 0)
return r;
}
r = sd_bus_message_exit_container(reply);
if (r < 0)
return r;
}
if (r < 0)
return r;
r = sd_bus_message_exit_container(reply);
if (r < 0)
return r;
return 0;
}
int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
sd_id128_t *p = userdata;
const void *v;
size_t n;
int r;
r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
if (r < 0)
return r;
if (n == 0)
*p = SD_ID128_NULL;
else if (n == 16)
memcpy((*p).bytes, v, n);
else
return -EINVAL;
return 0;
}
static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
char type;
int r;
r = sd_bus_message_peek_type(m, &type, NULL);
if (r < 0)
return r;
switch (type) {
case SD_BUS_TYPE_STRING: {
const char *s;
char **p = userdata;
r = sd_bus_message_read_basic(m, type, &s);
if (r < 0)
break;
if (isempty(s))
break;
r = free_and_strdup(p, s);
break;
}
case SD_BUS_TYPE_ARRAY: {
_cleanup_strv_free_ char **l = NULL;
char ***p = userdata;
r = bus_message_read_strv_extend(m, &l);
if (r < 0)
break;
strv_free(*p);
*p = l;
l = NULL;
break;
}
case SD_BUS_TYPE_BOOLEAN: {
unsigned b;
bool *p = userdata;
r = sd_bus_message_read_basic(m, type, &b);
if (r < 0)
break;
*p = b;
break;
}
case SD_BUS_TYPE_UINT32: {
uint64_t u;
uint32_t *p = userdata;
r = sd_bus_message_read_basic(m, type, &u);
if (r < 0)
break;
*p = u;
break;
}
case SD_BUS_TYPE_UINT64: {
uint64_t t;
uint64_t *p = userdata;
r = sd_bus_message_read_basic(m, type, &t);
if (r < 0)
break;
*p = t;
break;
}
default:
break;
}
return r;
}
int bus_message_map_all_properties(
sd_bus_message *m,
const struct bus_properties_map *map,
void *userdata) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(m);
assert(map);
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
if (r < 0)
return r;
while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
const struct bus_properties_map *prop;
const char *member;
const char *contents;
void *v;
unsigned i;
r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
if (r < 0)
return r;
for (i = 0, prop = NULL; map[i].member; i++)
if (streq(map[i].member, member)) {
prop = &map[i];
break;
}
if (prop) {
r = sd_bus_message_peek_type(m, NULL, &contents);
if (r < 0)
return r;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
if (r < 0)
return r;
v = (uint8_t *)userdata + prop->offset;
if (map[i].set)
r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v);
else
r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v);
if (r < 0)
return r;
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
} else {
r = sd_bus_message_skip(m, "v");
if (r < 0)
return r;
}
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
}
if (r < 0)
return r;
return sd_bus_message_exit_container(m);
}
int bus_message_map_properties_changed(
sd_bus_message *m,
const struct bus_properties_map *map,
void *userdata) {
const char *member;
int r, invalidated, i;
assert(m);
assert(map);
r = bus_message_map_all_properties(m, map, userdata);
if (r < 0)
return r;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
if (r < 0)
return r;
invalidated = 0;
while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
for (i = 0; map[i].member; i++)
if (streq(map[i].member, member)) {
++invalidated;
break;
}
if (r < 0)
return r;
r = sd_bus_message_exit_container(m);
if (r < 0)
return r;
return invalidated;
}
int bus_map_all_properties(
sd_bus *bus,
const char *destination,
const char *path,
const struct bus_properties_map *map,
void *userdata) {
_cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
int r;
assert(bus);
assert(destination);
assert(path);
assert(map);
r = sd_bus_call_method(
bus,
destination,
path,
"org.freedesktop.DBus.Properties",
"GetAll",
&error,
&m,
"s", "");
if (r < 0)
return r;
return bus_message_map_all_properties(m, map, userdata);
}
int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
int r;
assert(transport >= 0);
assert(transport < _BUS_TRANSPORT_MAX);
assert(bus);
assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
switch (transport) {
case BUS_TRANSPORT_LOCAL:
if (user)
r = sd_bus_default_user(bus);
else
r = sd_bus_default_system(bus);
break;
case BUS_TRANSPORT_REMOTE:
r = sd_bus_open_system_remote(bus, host);
break;
case BUS_TRANSPORT_MACHINE:
r = sd_bus_open_system_machine(bus, host);
break;
default:
assert_not_reached("Hmm, unknown transport type.");
}
return r;
}
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
int r;
assert(transport >= 0);
assert(transport < _BUS_TRANSPORT_MAX);
assert(bus);
assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
switch (transport) {
case BUS_TRANSPORT_LOCAL:
if (user)
r = bus_connect_user_systemd(bus);
else
r = bus_connect_system_systemd(bus);
break;
case BUS_TRANSPORT_REMOTE:
r = sd_bus_open_system_remote(bus, host);
break;
case BUS_TRANSPORT_MACHINE:
r = sd_bus_open_system_machine(bus, host);
break;
default:
assert_not_reached("Hmm, unknown transport type.");
}
return r;
}
int bus_property_get_bool(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
int b = *(bool*) userdata;
return sd_bus_message_append_basic(reply, 'b', &b);
}
#if __SIZEOF_SIZE_T__ != 8
int bus_property_get_size(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
uint64_t sz = *(size_t*) userdata;
return sd_bus_message_append_basic(reply, 't', &sz);
}
#endif
#if __SIZEOF_LONG__ != 8
int bus_property_get_long(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
int64_t l = *(long*) userdata;
return sd_bus_message_append_basic(reply, 'x', &l);
}
int bus_property_get_ulong(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
uint64_t ul = *(unsigned long*) userdata;
return sd_bus_message_append_basic(reply, 't', &ul);
}
#endif
int bus_log_parse_error(int r) {
return log_error_errno(r, "Failed to parse bus message: %m");
}
int bus_log_create_error(int r) {
return log_error_errno(r, "Failed to create bus message: %m");
}
int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
assert(message);
assert(u);
u->machine = NULL;
return sd_bus_message_read(
message,
"(ssssssouso)",
&u->id,
&u->description,
&u->load_state,
&u->active_state,
&u->sub_state,
&u->following,
&u->unit_path,
&u->job_id,
&u->job_type,
&u->job_path);
}
int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
const char *eq, *field;
int r, rl;
assert(m);
assert(assignment);
eq = strchr(assignment, '=');
if (!eq) {
log_error("Not an assignment: %s", assignment);
return -EINVAL;
}
r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
if (r < 0)
return bus_log_create_error(r);
field = strndupa(assignment, eq - assignment);
eq ++;
if (streq(field, "CPUQuota")) {
if (isempty(eq))
r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", USEC_INFINITY);
else if (endswith(eq, "%")) {
double percent;
if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
log_error("CPU quota '%s' invalid.", eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "sv", "CPUQuotaPerSecUSec", "t", (usec_t) percent * USEC_PER_SEC / 100);
} else {
log_error("CPU quota needs to be in percent.");
return -EINVAL;
}
goto finish;
} else if (streq(field, "EnvironmentFile")) {
r = sd_bus_message_append(m, "sv", "EnvironmentFiles", "a(sb)", 1,
eq[0] == '-' ? eq + 1 : eq,
eq[0] == '-');
goto finish;
} else if (STR_IN_SET(field, "AccuracySec", "RandomizedDelaySec")) {
char *n;
usec_t t;
size_t l;
r = parse_sec(eq, &t);
if (r < 0)
return log_error_errno(r, "Failed to parse %s= parameter: %s", field, eq);
l = strlen(field);
n = newa(char, l + 2);
if (!n)
return log_oom();
/* Change suffix Sec → USec */
strcpy(mempcpy(n, field, l - 3), "USec");
r = sd_bus_message_append(m, "sv", n, "t", t);
goto finish;
}
r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
if (r < 0)
return bus_log_create_error(r);
rl = rlimit_from_string(field);
if (rl >= 0) {
const char *sn;
struct rlimit l;
r = rlimit_parse(rl, eq, &l);
if (r < 0)
return log_error_errno(r, "Failed to parse resource limit: %s", eq);
r = sd_bus_message_append(m, "v", "t", l.rlim_max);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, SD_BUS_TYPE_STRUCT, "sv");
if (r < 0)
return bus_log_create_error(r);
sn = strjoina(field, "Soft");
r = sd_bus_message_append(m, "sv", sn, "t", l.rlim_cur);
} else if (STR_IN_SET(field,
"CPUAccounting", "MemoryAccounting", "BlockIOAccounting", "TasksAccounting",
"SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies",
"IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit",
"PrivateTmp", "PrivateDevices", "PrivateNetwork", "NoNewPrivileges",
"SyslogLevelPrefix", "Delegate", "RemainAfterElapse")) {
r = parse_boolean(eq);
if (r < 0)
return log_error_errno(r, "Failed to parse boolean assignment %s.", assignment);
r = sd_bus_message_append(m, "v", "b", r);
} else if (streq(field, "MemoryLimit")) {
uint64_t bytes;
if (isempty(eq) || streq(eq, "infinity"))
bytes = (uint64_t) -1;
else {
r = parse_size(eq, 1024, &bytes);
if (r < 0) {
log_error("Failed to parse bytes specification %s", assignment);
return -EINVAL;
}
}
r = sd_bus_message_append(m, "v", "t", bytes);
} else if (streq(field, "TasksMax")) {
uint64_t n;
if (isempty(eq) || streq(eq, "infinity"))
n = (uint64_t) -1;
else {
r = safe_atou64(eq, &n);
if (r < 0) {
log_error("Failed to parse maximum tasks specification %s", assignment);
return -EINVAL;
}
}
r = sd_bus_message_append(m, "v", "t", n);
} else if (STR_IN_SET(field, "CPUShares", "StartupCPUShares")) {
uint64_t u;
r = cg_cpu_shares_parse(eq, &u);
if (r < 0) {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "t", u);
} else if (STR_IN_SET(field, "BlockIOWeight", "StartupBlockIOWeight")) {
uint64_t u;
r = cg_cpu_shares_parse(eq, &u);
if (r < 0) {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "t", u);
} else if (STR_IN_SET(field,
"User", "Group", "DevicePolicy", "KillMode",
"UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
"StandardInput", "StandardOutput", "StandardError",
"Description", "Slice", "Type", "WorkingDirectory",
"RootDirectory", "SyslogIdentifier", "ProtectSystem",
"ProtectHome"))
r = sd_bus_message_append(m, "v", "s", eq);
else if (streq(field, "SyslogLevel")) {
int level;
level = log_level_from_string(eq);
if (level < 0) {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "i", level);
} else if (streq(field, "SyslogFacility")) {
int facility;
facility = log_facility_unshifted_from_string(eq);
if (facility < 0) {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "i", facility);
} else if (streq(field, "DeviceAllow")) {
if (isempty(eq))
r = sd_bus_message_append(m, "v", "a(ss)", 0);
else {
const char *path, *rwm, *e;
e = strchr(eq, ' ');
if (e) {
path = strndupa(eq, e - eq);
rwm = e+1;
} else {
path = eq;
rwm = "";
}
if (!path_startswith(path, "/dev")) {
log_error("%s is not a device file in /dev.", path);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
}
} else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
if (isempty(eq))
r = sd_bus_message_append(m, "v", "a(st)", 0);
else {
const char *path, *bandwidth, *e;
uint64_t bytes;
e = strchr(eq, ' ');
if (e) {
path = strndupa(eq, e - eq);
bandwidth = e+1;
} else {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
if (!path_startswith(path, "/dev")) {
log_error("%s is not a device file in /dev.", path);
return -EINVAL;
}
r = parse_size(bandwidth, 1000, &bytes);
if (r < 0) {
log_error("Failed to parse byte value %s.", bandwidth);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "a(st)", 1, path, bytes);
}
} else if (streq(field, "BlockIODeviceWeight")) {
if (isempty(eq))
r = sd_bus_message_append(m, "v", "a(st)", 0);
else {
const char *path, *weight, *e;
uint64_t u;
e = strchr(eq, ' ');
if (e) {
path = strndupa(eq, e - eq);
weight = e+1;
} else {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
if (!path_startswith(path, "/dev")) {
log_error("%s is not a device file in /dev.", path);
return -EINVAL;
}
r = safe_atou64(weight, &u);
if (r < 0) {
log_error("Failed to parse %s value %s.", field, weight);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "a(st)", path, u);
}
} else if (streq(field, "Nice")) {
int32_t i;
r = safe_atoi32(eq, &i);
if (r < 0) {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "i", i);
} else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
const char *p;
r = sd_bus_message_open_container(m, 'v', "as");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
p = eq;
for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES|EXTRACT_CUNESCAPE);
if (r < 0) {
log_error("Failed to parse Environment value %s", eq);
return -EINVAL;
}
if (r == 0)
break;
if (streq(field, "Environment")) {
if (!env_assignment_is_valid(word)) {
log_error("Invalid environment assignment: %s", word);
return -EINVAL;
}
} else { /* PassEnvironment */
if (!env_name_is_valid(word)) {
log_error("Invalid environment variable name: %s", word);
return -EINVAL;
}
}
r = sd_bus_message_append_basic(m, 's', word);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
} else if (streq(field, "KillSignal")) {
int sig;
sig = signal_from_string_try_harder(eq);
if (sig < 0) {
log_error("Failed to parse %s value %s.", field, eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "i", sig);
} else if (streq(field, "TimerSlackNSec")) {
nsec_t n;
r = parse_nsec(eq, &n);
if (r < 0) {
log_error("Failed to parse %s value %s", field, eq);
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "t", n);
} else if (streq(field, "OOMScoreAdjust")) {
int oa;
r = safe_atoi(eq, &oa);
if (r < 0) {
log_error("Failed to parse %s value %s", field, eq);
return -EINVAL;
}
if (!oom_score_adjust_is_valid(oa)) {
log_error("OOM score adjust value out of range");
return -EINVAL;
}
r = sd_bus_message_append(m, "v", "i", oa);
} else if (STR_IN_SET(field, "ReadWriteDirectories", "ReadOnlyDirectories", "InaccessibleDirectories")) {
const char *p;
r = sd_bus_message_open_container(m, 'v', "as");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
p = eq;
for (;;) {
_cleanup_free_ char *word = NULL;
int offset;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r < 0) {
log_error("Failed to parse %s value %s", field, eq);
return -EINVAL;
}
if (r == 0)
break;
if (!utf8_is_valid(word)) {
log_error("Failed to parse %s value %s", field, eq);
return -EINVAL;
}
offset = word[0] == '-';
if (!path_is_absolute(word + offset)) {
log_error("Failed to parse %s value %s", field, eq);
return -EINVAL;
}
path_kill_slashes(word + offset);
r = sd_bus_message_append_basic(m, 's', word);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
} else if (streq(field, "RuntimeDirectory")) {
const char *p;
r = sd_bus_message_open_container(m, 'v', "as");
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_open_container(m, 'a', "s");
if (r < 0)
return bus_log_create_error(r);
p = eq;
for (;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, EXTRACT_QUOTES);
if (r < 0)
return log_error_errno(r, "Failed to parse %s value %s", field, eq);
if (r == 0)
break;
r = sd_bus_message_append_basic(m, 's', word);
if (r < 0)
return bus_log_create_error(r);
}
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
} else {
log_error("Unknown assignment %s.", assignment);
return -EINVAL;
}
finish:
if (r < 0)
return bus_log_create_error(r);
r = sd_bus_message_close_container(m);
if (r < 0)
return bus_log_create_error(r);
return 0;
}
typedef struct BusWaitForJobs {
sd_bus *bus;
Set *jobs;
char *name;
char *result;
sd_bus_slot *slot_job_removed;
sd_bus_slot *slot_disconnected;
} BusWaitForJobs;
static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
assert(m);
log_error("Warning! D-Bus connection terminated.");
sd_bus_close(sd_bus_message_get_bus(m));
return 0;
}
static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
const char *path, *unit, *result;
BusWaitForJobs *d = userdata;
uint32_t id;
char *found;
int r;
assert(m);
assert(d);
r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
if (r < 0) {
bus_log_parse_error(r);
return 0;
}
found = set_remove(d->jobs, (char*) path);
if (!found)
return 0;
free(found);
if (!isempty(result))
d->result = strdup(result);
if (!isempty(unit))
d->name = strdup(unit);
return 0;
}
void bus_wait_for_jobs_free(BusWaitForJobs *d) {
if (!d)
return;
set_free_free(d->jobs);
sd_bus_slot_unref(d->slot_disconnected);
sd_bus_slot_unref(d->slot_job_removed);
sd_bus_unref(d->bus);
free(d->name);
free(d->result);
free(d);
}
int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
_cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
int r;
assert(bus);
assert(ret);
d = new0(BusWaitForJobs, 1);
if (!d)
return -ENOMEM;
d->bus = sd_bus_ref(bus);
/* When we are a bus client we match by sender. Direct
* connections OTOH have no initialized sender field, and
* hence we ignore the sender then */
r = sd_bus_add_match(
bus,
&d->slot_job_removed,
bus->bus_client ?
"type='signal',"
"sender='org.freedesktop.systemd1',"
"interface='org.freedesktop.systemd1.Manager',"
"member='JobRemoved',"
"path='/org/freedesktop/systemd1'" :
"type='signal',"
"interface='org.freedesktop.systemd1.Manager',"
"member='JobRemoved',"
"path='/org/freedesktop/systemd1'",
match_job_removed, d);
if (r < 0)
return r;
r = sd_bus_add_match(
bus,
&d->slot_disconnected,
"type='signal',"
"sender='org.freedesktop.DBus.Local',"
"interface='org.freedesktop.DBus.Local',"
"member='Disconnected'",
match_disconnected, d);
if (r < 0)
return r;
*ret = d;
d = NULL;
return 0;
}
static int bus_process_wait(sd_bus *bus) {
int r;
for (;;) {
r = sd_bus_process(bus, NULL);
if (r < 0)
return r;
if (r > 0)
return 0;
r = sd_bus_wait(bus, (uint64_t) -1);
if (r < 0)
return r;
}
}
static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
_cleanup_free_ char *dbus_path = NULL;
assert(d);
assert(d->name);
assert(result);
dbus_path = unit_dbus_path_from_name(d->name);
if (!dbus_path)
return -ENOMEM;
return sd_bus_get_property_string(d->bus,
"org.freedesktop.systemd1",
dbus_path,
"org.freedesktop.systemd1.Service",
"Result",
NULL,
result);
}
static const struct {
const char *result, *explanation;
} explanations [] = {
{ "resources", "a configured resource limit was exceeded" },
{ "timeout", "a timeout was exceeded" },
{ "exit-code", "the control process exited with error code" },
{ "signal", "a fatal signal was delivered to the control process" },
{ "core-dump", "a fatal signal was delivered causing the control process to dump core" },
{ "watchdog", "the service failed to send watchdog ping" },
{ "start-limit", "start of the service was attempted too often" }
};
static void log_job_error_with_service_result(const char* service, const char *result, const char *extra_args) {
_cleanup_free_ char *service_shell_quoted = NULL, *systemctl_extra_args = NULL;
assert(service);
service_shell_quoted = shell_maybe_quote(service);
systemctl_extra_args = strjoin("systemctl ", extra_args, " ", NULL);
if (!systemctl_extra_args) {
log_oom();
return;
}
systemctl_extra_args = strstrip(systemctl_extra_args);
if (!isempty(result)) {
unsigned i;
for (i = 0; i < ELEMENTSOF(explanations); ++i)
if (streq(result, explanations[i].result))
break;
if (i < ELEMENTSOF(explanations)) {
log_error("Job for %s failed because %s. See \"%s status %s\" and \"journalctl -xe\" for details.\n",
service,
explanations[i].explanation,
systemctl_extra_args,
strna(service_shell_quoted));
goto finish;
}
}
log_error("Job for %s failed. See \"%s status %s\" and \"journalctl -xe\" for details.\n",
service,
systemctl_extra_args,
strna(service_shell_quoted));
finish:
/* For some results maybe additional explanation is required */
if (streq_ptr(result, "start-limit"))
log_info("To force a start use \"%1$s reset-failed %2$s\" followed by \"%1$s start %2$s\" again.",
systemctl_extra_args,
strna(service_shell_quoted));
}
static int check_wait_response(BusWaitForJobs *d, bool quiet, const char *extra_args) {
int r = 0;
assert(d->result);
if (!quiet) {
if (streq(d->result, "canceled"))
log_error("Job for %s canceled.", strna(d->name));
else if (streq(d->result, "timeout"))
log_error("Job for %s timed out.", strna(d->name));
else if (streq(d->result, "dependency"))
log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
else if (streq(d->result, "invalid"))
log_error("%s is not active, cannot reload.", strna(d->name));
else if (streq(d->result, "assert"))
log_error("Assertion failed on job for %s.", strna(d->name));
else if (streq(d->result, "unsupported"))
log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
if (d->name) {
int q;
_cleanup_free_ char *result = NULL;
q = bus_job_get_service_result(d, &result);
if (q < 0)
log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
log_job_error_with_service_result(d->name, result, extra_args);
} else
log_error("Job failed. See \"journalctl -xe\" for details.");
}
}
if (streq(d->result, "canceled"))
r = -ECANCELED;
else if (streq(d->result, "timeout"))
r = -ETIME;
else if (streq(d->result, "dependency"))
r = -EIO;
else if (streq(d->result, "invalid"))
r = -ENOEXEC;
else if (streq(d->result, "assert"))
r = -EPROTO;
else if (streq(d->result, "unsupported"))
r = -EOPNOTSUPP;
else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
r = -EIO;
return r;
}
int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet, const char *extra_args) {
int r = 0;
assert(d);
while (!set_isempty(d->jobs)) {
int q;
q = bus_process_wait(d->bus);
if (q < 0)
return log_error_errno(q, "Failed to wait for response: %m");
if (d->result) {
q = check_wait_response(d, quiet, extra_args);
/* Return the first error as it is most likely to be
* meaningful. */
if (q < 0 && r == 0)
r = q;
log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
}
d->name = mfree(d->name);
d->result = mfree(d->result);
}
return r;
}
int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
int r;
assert(d);
r = set_ensure_allocated(&d->jobs, &string_hash_ops);
if (r < 0)
return r;
return set_put_strdup(d->jobs, path);
}
int bus_wait_for_jobs_one(BusWaitForJobs *d, const char *path, bool quiet) {
int r;
r = bus_wait_for_jobs_add(d, path);
if (r < 0)
return log_oom();
return bus_wait_for_jobs(d, quiet, NULL);
}
int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
const char *type, *path, *source;
int r;
r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
if (r < 0)
return bus_log_parse_error(r);
while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
if (!quiet) {
if (streq(type, "symlink"))
log_info("Created symlink from %s to %s.", path, source);
else
log_info("Removed symlink %s.", path);
}
r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
if (r < 0)
return r;
}
if (r < 0)
return bus_log_parse_error(r);
r = sd_bus_message_exit_container(m);
if (r < 0)
return bus_log_parse_error(r);
return 0;
}
/**
* bus_path_encode_unique() - encode unique object path
* @b: bus connection or NULL
* @prefix: object path prefix
* @sender_id: unique-name of client, or NULL
* @external_id: external ID to be chosen by client, or NULL
* @ret_path: storage for encoded object path pointer
*
* Whenever we provide a bus API that allows clients to create and manage
* server-side objects, we need to provide a unique name for these objects. If
* we let the server choose the name, we suffer from a race condition: If a
* client creates an object asynchronously, it cannot destroy that object until
* it received the method reply. It cannot know the name of the new object,
* thus, it cannot destroy it. Furthermore, it enforces a round-trip.
*
* Therefore, many APIs allow the client to choose the unique name for newly
* created objects. There're two problems to solve, though:
* 1) Object names are usually defined via dbus object paths, which are
* usually globally namespaced. Therefore, multiple clients must be able
* to choose unique object names without interference.
* 2) If multiple libraries share the same bus connection, they must be
* able to choose unique object names without interference.
* The first problem is solved easily by prefixing a name with the
* unique-bus-name of a connection. The server side must enforce this and
* reject any other name. The second problem is solved by providing unique
* suffixes from within sd-bus.
*
* This helper allows clients to create unique object-paths. It uses the
* template '/prefix/sender_id/external_id' and returns the new path in
* @ret_path (must be freed by the caller).
* If @sender_id is NULL, the unique-name of @b is used. If @external_id is
* NULL, this function allocates a unique suffix via @b (by requesting a new
* cookie). If both @sender_id and @external_id are given, @b can be passed as
* NULL.
*
* Returns: 0 on success, negative error code on failure.
*/
int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
_cleanup_free_ char *sender_label = NULL, *external_label = NULL;
char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
int r;
assert_return(b || (sender_id && external_id), -EINVAL);
assert_return(object_path_is_valid(prefix), -EINVAL);
assert_return(ret_path, -EINVAL);
if (!sender_id) {
r = sd_bus_get_unique_name(b, &sender_id);
if (r < 0)
return r;
}
if (!external_id) {
xsprintf(external_buf, "%"PRIu64, ++b->cookie);
external_id = external_buf;
}
sender_label = bus_label_escape(sender_id);
if (!sender_label)
return -ENOMEM;
external_label = bus_label_escape(external_id);
if (!external_label)
return -ENOMEM;
p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
if (!p)
return -ENOMEM;
*ret_path = p;
return 0;
}
/**
* bus_path_decode_unique() - decode unique object path
* @path: object path to decode
* @prefix: object path prefix
* @ret_sender: output parameter for sender-id label
* @ret_external: output parameter for external-id label
*
* This does the reverse of bus_path_encode_unique() (see its description for
* details). Both trailing labels, sender-id and external-id, are unescaped and
* returned in the given output parameters (the caller must free them).
*
* Note that this function returns 0 if the path does not match the template
* (see bus_path_encode_unique()), 1 if it matched.
*
* Returns: Negative error code on failure, 0 if the given object path does not
* match the template (return parameters are set to NULL), 1 if it was
* parsed successfully (return parameters contain allocated labels).
*/
int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
const char *p, *q;
char *sender, *external;
assert(object_path_is_valid(path));
assert(object_path_is_valid(prefix));
assert(ret_sender);
assert(ret_external);
p = object_path_startswith(path, prefix);
if (!p) {
*ret_sender = NULL;
*ret_external = NULL;
return 0;
}
q = strchr(p, '/');
if (!q) {
*ret_sender = NULL;
*ret_external = NULL;
return 0;
}
sender = bus_label_unescape_n(p, q - p);
external = bus_label_unescape(q + 1);
if (!sender || !external) {
free(sender);
free(external);
return -ENOMEM;
}
*ret_sender = sender;
*ret_external = external;
return 1;
}
bool is_kdbus_wanted(void) {
_cleanup_free_ char *value = NULL;
#ifdef ENABLE_KDBUS
const bool configured = true;
#else
const bool configured = false;
#endif
int r;
if (get_proc_cmdline_key("kdbus", NULL) > 0)
return true;
r = get_proc_cmdline_key("kdbus=", &value);
if (r <= 0)
return configured;
return parse_boolean(value) == 1;
}
bool is_kdbus_available(void) {
_cleanup_close_ int fd = -1;
struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
if (!is_kdbus_wanted())
return false;
fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
if (fd < 0)
return false;
return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
}
int bus_property_get_rlimit(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
struct rlimit *rl;
uint64_t u;
rlim_t x;
const char *is_soft;
assert(bus);
assert(reply);
assert(userdata);
is_soft = endswith(property, "Soft");
rl = *(struct rlimit**) userdata;
if (rl)
x = is_soft ? rl->rlim_cur : rl->rlim_max;
else {
struct rlimit buf = {};
int z;
const char *s;
s = is_soft ? strndupa(property, is_soft - property) : property;
z = rlimit_from_string(strstr(s, "Limit"));
assert(z >= 0);
getrlimit(z, &buf);
x = is_soft ? buf.rlim_cur : buf.rlim_max;
}
/* rlim_t might have different sizes, let's map
* RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
* all archs */
u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
return sd_bus_message_append(reply, "t", u);
}