bus-control.c 9.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/

/***
  This file is part of systemd.

  Copyright 2013 Lennart Poettering

  systemd is free software; you can redistribute it and/or modify it
  under the terms of the GNU Lesser General Public License as published by
  the Free Software Foundation; either version 2.1 of the License, or
  (at your option) any later version.

  systemd is distributed in the hope that it will be useful, but
  WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  Lesser General Public License for more details.

  You should have received a copy of the GNU Lesser General Public License
  along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/

#include <stddef.h>
#include <errno.h>

#include "strv.h"

#include "sd-bus.h"
#include "bus-internal.h"
#include "bus-message.h"
30
#include "bus-control.h"
31

32 33 34
int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
        int r;

35
        if (!bus)
36 37 38 39 40 41 42
                return -EINVAL;
        if (!unique)
                return -EINVAL;

        r = bus_ensure_running(bus);
        if (r < 0)
                return r;
43

44 45
        *unique = bus->unique_name;
        return 0;
46 47 48
}

int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
49
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
50 51 52 53 54 55 56
        uint32_t ret;
        int r;

        if (!bus)
                return -EINVAL;
        if (!name)
                return -EINVAL;
57 58
        if (!bus->bus_client)
                return -EINVAL;
59

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
        if (bus->is_kernel) {
                struct kdbus_cmd_name *n;
                size_t l;

                l = strlen(name);
                n = alloca(offsetof(struct kdbus_cmd_name, name) + l + 1);
                n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
                n->flags = flags;
                n->id = 0;
                memcpy(n->name, name, l+1);

                r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
                if (r < 0)
                        return -errno;

                return n->flags;
        } else {
                r = sd_bus_call_method(
                                bus,
                                "org.freedesktop.DBus",
                                "/",
                                "org.freedesktop.DBus",
                                "RequestName",
                                NULL,
                                &reply,
                                "su",
                                name,
                                flags);
                if (r < 0)
                        return r;

                r = sd_bus_message_read(reply, "u", &ret);
                if (r < 0)
                        return r;

                return ret;
        }
97 98 99
}

int sd_bus_release_name(sd_bus *bus, const char *name) {
100
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
101 102 103 104 105 106 107
        uint32_t ret;
        int r;

        if (!bus)
                return -EINVAL;
        if (!name)
                return -EINVAL;
108 109
        if (!bus->bus_client)
                return -EINVAL;
110

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
        if (bus->is_kernel) {
                struct kdbus_cmd_name *n;
                size_t l;

                l = strlen(name);
                n = alloca(offsetof(struct kdbus_cmd_name, name) + l + 1);
                n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
                n->flags = 0;
                n->id = 0;
                memcpy(n->name, name, l+1);

                r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
                if (r < 0)
                        return -errno;

                return n->flags;
        } else {
                r = sd_bus_call_method(
                                bus,
                                "org.freedesktop.DBus",
                                "/",
                                "org.freedesktop.DBus",
                                "ReleaseName",
                                NULL,
                                &reply,
                                "s",
                                name);
                if (r < 0)
                        return r;

                r = sd_bus_message_read(reply, "u", &ret);
                if (r < 0)
                        return r;
        }
145 146 147 148 149

        return ret;
}

int sd_bus_list_names(sd_bus *bus, char ***l) {
150
        _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
151 152 153 154 155 156 157 158
        char **x = NULL;
        int r;

        if (!bus)
                return -EINVAL;
        if (!l)
                return -EINVAL;

159
        r = sd_bus_call_method(
160 161 162 163 164
                        bus,
                        "org.freedesktop.DBus",
                        "/",
                        "org.freedesktop.DBus",
                        "ListNames",
165 166 167
                        NULL,
                        &reply1,
                        NULL);
168 169 170
        if (r < 0)
                return r;

171
        r = sd_bus_call_method(
172 173 174 175 176
                        bus,
                        "org.freedesktop.DBus",
                        "/",
                        "org.freedesktop.DBus",
                        "ListActivatableNames",
177 178 179
                        NULL,
                        &reply2,
                        NULL);
180 181 182
        if (r < 0)
                return r;

183 184 185
        r = bus_message_read_strv_extend(reply1, &x);
        if (r < 0) {
                strv_free(x);
186
                return r;
187
        }
188

189 190 191
        r = bus_message_read_strv_extend(reply2, &x);
        if (r < 0) {
                strv_free(x);
192
                return r;
193
        }
194 195 196 197 198 199

        *l = strv_uniq(x);
        return 0;
}

int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
200
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
201
        const char *found;
202 203 204 205 206 207 208
        int r;

        if (!bus)
                return -EINVAL;
        if (!name)
                return -EINVAL;

209
        r = sd_bus_call_method(
210 211 212 213 214
                        bus,
                        "org.freedesktop.DBus",
                        "/",
                        "org.freedesktop.DBus",
                        "GetNameOwner",
215 216 217 218
                        NULL,
                        &reply,
                        "s",
                        name);
219 220 221
        if (r < 0)
                return r;

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
        r = sd_bus_message_read(reply, "s", &found);
        if (r < 0)
                return r;

        if (owner) {
                char *t;

                t = strdup(found);
                if (!t)
                        return -ENOMEM;

                *owner = t;
        }

        return 0;
237 238 239
}

int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) {
240
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
241 242 243 244 245 246 247 248 249 250
        uint32_t u;
        int r;

        if (!bus)
                return -EINVAL;
        if (!name)
                return -EINVAL;
        if (!uid)
                return -EINVAL;

251
        r = sd_bus_call_method(
252 253 254 255 256
                        bus,
                        "org.freedesktop.DBus",
                        "/",
                        "org.freedesktop.DBus",
                        "GetConnectionUnixUser",
257 258 259 260
                        NULL,
                        &reply,
                        "s",
                        name);
261 262 263 264 265 266 267 268 269 270 271 272
        if (r < 0)
                return r;

        r = sd_bus_message_read(reply, "u", &u);
        if (r < 0)
                return r;

        *uid = (uid_t) u;
        return 0;
}

int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
273
        _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
274 275 276 277 278 279 280 281 282 283
        uint32_t u;
        int r;

        if (!bus)
                return -EINVAL;
        if (!name)
                return -EINVAL;
        if (!pid)
                return -EINVAL;

284
        r = sd_bus_call_method(
285 286 287 288
                        bus,
                        "org.freedesktop.DBus",
                        "/",
                        "org.freedesktop.DBus",
289
                        "GetConnectionUnixProcessID",
290 291 292 293
                        NULL,
                        &reply,
                        "s",
                        name);
294 295 296 297 298 299 300 301 302 303 304 305 306 307
        if (r < 0)
                return r;

        r = sd_bus_message_read(reply, "u", &u);
        if (r < 0)
                return r;

        if (u == 0)
                return -EIO;

        *pid = (uid_t) u;
        return 0;
}

308 309 310
int bus_add_match_internal(sd_bus *bus, const char *match) {
        assert(bus);
        assert(match);
311

312
        return sd_bus_call_method(
313 314 315 316 317
                        bus,
                        "org.freedesktop.DBus",
                        "/",
                        "org.freedesktop.DBus",
                        "AddMatch",
318 319 320 321
                        NULL,
                        NULL,
                        "s",
                        match);
322 323
}

324 325 326
int bus_remove_match_internal(sd_bus *bus, const char *match) {
        assert(bus);
        assert(match);
327

328
        return sd_bus_call_method(
329 330 331 332 333
                        bus,
                        "org.freedesktop.DBus",
                        "/",
                        "org.freedesktop.DBus",
                        "RemoveMatch",
334 335 336 337
                        NULL,
                        NULL,
                        "s",
                        match);
338
}