chiark / gitweb /
a4dc9bf511e92584a1dc81c0e1cc4267e5410755
[elogind.git] / src / libsystemd-bus / bus-control.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #ifdef HAVE_VALGRIND_MEMCHECK_H
23 #include <valgrind/memcheck.h>
24 #endif
25
26 #include <stddef.h>
27 #include <errno.h>
28
29 #include "strv.h"
30
31 #include "sd-bus.h"
32 #include "bus-internal.h"
33 #include "bus-message.h"
34 #include "bus-control.h"
35
36 int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
37         int r;
38
39         if (!bus)
40                 return -EINVAL;
41         if (!unique)
42                 return -EINVAL;
43
44         r = bus_ensure_running(bus);
45         if (r < 0)
46                 return r;
47
48         *unique = bus->unique_name;
49         return 0;
50 }
51
52 int sd_bus_request_name(sd_bus *bus, const char *name, int flags) {
53         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
54         uint32_t ret;
55         int r;
56
57         if (!bus)
58                 return -EINVAL;
59         if (!name)
60                 return -EINVAL;
61         if (!bus->bus_client)
62                 return -EINVAL;
63
64         if (bus->is_kernel) {
65                 struct kdbus_cmd_name *n;
66                 size_t l;
67
68                 l = strlen(name);
69                 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
70                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
71                 n->name_flags = flags;
72                 memcpy(n->name, name, l+1);
73
74 #ifdef HAVE_VALGRIND_MEMCHECK_H
75                 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
76 #endif
77
78                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
79                 if (r < 0)
80                         return -errno;
81
82                 return n->name_flags;
83         } else {
84                 r = sd_bus_call_method(
85                                 bus,
86                                 "org.freedesktop.DBus",
87                                 "/",
88                                 "org.freedesktop.DBus",
89                                 "RequestName",
90                                 NULL,
91                                 &reply,
92                                 "su",
93                                 name,
94                                 flags);
95                 if (r < 0)
96                         return r;
97
98                 r = sd_bus_message_read(reply, "u", &ret);
99                 if (r < 0)
100                         return r;
101
102                 return ret;
103         }
104 }
105
106 int sd_bus_release_name(sd_bus *bus, const char *name) {
107         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
108         uint32_t ret;
109         int r;
110
111         if (!bus)
112                 return -EINVAL;
113         if (!name)
114                 return -EINVAL;
115         if (!bus->bus_client)
116                 return -EINVAL;
117
118         if (bus->is_kernel) {
119                 struct kdbus_cmd_name *n;
120                 size_t l;
121
122                 l = strlen(name);
123                 n = alloca0(offsetof(struct kdbus_cmd_name, name) + l + 1);
124                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
125                 memcpy(n->name, name, l+1);
126
127 #ifdef HAVE_VALGRIND_MEMCHECK_H
128                 VALGRIND_MAKE_MEM_DEFINED(n, n->size);
129 #endif
130                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
131                 if (r < 0)
132                         return -errno;
133
134                 return n->name_flags;
135         } else {
136                 r = sd_bus_call_method(
137                                 bus,
138                                 "org.freedesktop.DBus",
139                                 "/",
140                                 "org.freedesktop.DBus",
141                                 "ReleaseName",
142                                 NULL,
143                                 &reply,
144                                 "s",
145                                 name);
146                 if (r < 0)
147                         return r;
148
149                 r = sd_bus_message_read(reply, "u", &ret);
150                 if (r < 0)
151                         return r;
152         }
153
154         return ret;
155 }
156
157 int sd_bus_list_names(sd_bus *bus, char ***l) {
158         _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
159         char **x = NULL;
160         int r;
161
162         if (!bus)
163                 return -EINVAL;
164         if (!l)
165                 return -EINVAL;
166
167         r = sd_bus_call_method(
168                         bus,
169                         "org.freedesktop.DBus",
170                         "/",
171                         "org.freedesktop.DBus",
172                         "ListNames",
173                         NULL,
174                         &reply1,
175                         NULL);
176         if (r < 0)
177                 return r;
178
179         r = sd_bus_call_method(
180                         bus,
181                         "org.freedesktop.DBus",
182                         "/",
183                         "org.freedesktop.DBus",
184                         "ListActivatableNames",
185                         NULL,
186                         &reply2,
187                         NULL);
188         if (r < 0)
189                 return r;
190
191         r = bus_message_read_strv_extend(reply1, &x);
192         if (r < 0) {
193                 strv_free(x);
194                 return r;
195         }
196
197         r = bus_message_read_strv_extend(reply2, &x);
198         if (r < 0) {
199                 strv_free(x);
200                 return r;
201         }
202
203         *l = strv_uniq(x);
204         return 0;
205 }
206
207 int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
208         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
209         const char *found;
210         int r;
211
212         if (!bus)
213                 return -EINVAL;
214         if (!name)
215                 return -EINVAL;
216
217         r = sd_bus_call_method(
218                         bus,
219                         "org.freedesktop.DBus",
220                         "/",
221                         "org.freedesktop.DBus",
222                         "GetNameOwner",
223                         NULL,
224                         &reply,
225                         "s",
226                         name);
227         if (r < 0)
228                 return r;
229
230         r = sd_bus_message_read(reply, "s", &found);
231         if (r < 0)
232                 return r;
233
234         if (owner) {
235                 char *t;
236
237                 t = strdup(found);
238                 if (!t)
239                         return -ENOMEM;
240
241                 *owner = t;
242         }
243
244         return 0;
245 }
246
247 int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) {
248         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
249         uint32_t u;
250         int r;
251
252         if (!bus)
253                 return -EINVAL;
254         if (!name)
255                 return -EINVAL;
256         if (!uid)
257                 return -EINVAL;
258
259         r = sd_bus_call_method(
260                         bus,
261                         "org.freedesktop.DBus",
262                         "/",
263                         "org.freedesktop.DBus",
264                         "GetConnectionUnixUser",
265                         NULL,
266                         &reply,
267                         "s",
268                         name);
269         if (r < 0)
270                 return r;
271
272         r = sd_bus_message_read(reply, "u", &u);
273         if (r < 0)
274                 return r;
275
276         *uid = (uid_t) u;
277         return 0;
278 }
279
280 int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
281         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
282         uint32_t u;
283         int r;
284
285         if (!bus)
286                 return -EINVAL;
287         if (!name)
288                 return -EINVAL;
289         if (!pid)
290                 return -EINVAL;
291
292         r = sd_bus_call_method(
293                         bus,
294                         "org.freedesktop.DBus",
295                         "/",
296                         "org.freedesktop.DBus",
297                         "GetConnectionUnixProcessID",
298                         NULL,
299                         &reply,
300                         "s",
301                         name);
302         if (r < 0)
303                 return r;
304
305         r = sd_bus_message_read(reply, "u", &u);
306         if (r < 0)
307                 return r;
308
309         if (u == 0)
310                 return -EIO;
311
312         *pid = (uid_t) u;
313         return 0;
314 }
315
316 int bus_add_match_internal(sd_bus *bus, const char *match) {
317         assert(bus);
318         assert(match);
319
320         return sd_bus_call_method(
321                         bus,
322                         "org.freedesktop.DBus",
323                         "/",
324                         "org.freedesktop.DBus",
325                         "AddMatch",
326                         NULL,
327                         NULL,
328                         "s",
329                         match);
330 }
331
332 int bus_remove_match_internal(sd_bus *bus, const char *match) {
333         assert(bus);
334         assert(match);
335
336         return sd_bus_call_method(
337                         bus,
338                         "org.freedesktop.DBus",
339                         "/",
340                         "org.freedesktop.DBus",
341                         "RemoveMatch",
342                         NULL,
343                         NULL,
344                         "s",
345                         match);
346 }
347
348 int sd_bus_get_owner_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
349         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
350         const char *mid;
351         int r;
352
353         if (!bus)
354                 return -EINVAL;
355         if (!name)
356                 return -EINVAL;
357
358         if (streq_ptr(name, bus->unique_name))
359                 return sd_id128_get_machine(machine);
360
361         r = sd_bus_call_method(bus,
362                                name,
363                                "/",
364                                "org.freedesktop.DBus.Peer",
365                                "GetMachineId",
366                                NULL,
367                                &reply,
368                                NULL);
369
370         if (r < 0)
371                 return r;
372
373         r = sd_bus_message_read(reply, "s", &mid);
374         if (r < 0)
375                 return r;
376
377         return sd_id128_from_string(mid, machine);
378 }