chiark / gitweb /
7c139cfd32cab7cb579e837056d58204ce7a9466
[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 #include <stddef.h>
23 #include <errno.h>
24
25 #include "strv.h"
26
27 #include "sd-bus.h"
28 #include "bus-internal.h"
29 #include "bus-message.h"
30 #include "bus-control.h"
31
32 int sd_bus_get_unique_name(sd_bus *bus, const char **unique) {
33         int r;
34
35         if (!bus)
36                 return -EINVAL;
37         if (!unique)
38                 return -EINVAL;
39
40         r = bus_ensure_running(bus);
41         if (r < 0)
42                 return r;
43
44         *unique = bus->unique_name;
45         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         uint32_t ret;
51         int r;
52
53         if (!bus)
54                 return -EINVAL;
55         if (!name)
56                 return -EINVAL;
57         if (!bus->bus_client)
58                 return -EINVAL;
59
60         if (bus->is_kernel) {
61                 struct kdbus_cmd_name *n;
62                 size_t l;
63
64                 l = strlen(name);
65                 n = alloca(offsetof(struct kdbus_cmd_name, name) + l + 1);
66                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
67                 n->flags = flags;
68                 n->id = 0;
69                 memcpy(n->name, name, l+1);
70
71                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
72                 if (r < 0)
73                         return -errno;
74
75                 return n->flags;
76         } else {
77                 r = sd_bus_call_method(
78                                 bus,
79                                 "org.freedesktop.DBus",
80                                 "/",
81                                 "org.freedesktop.DBus",
82                                 "RequestName",
83                                 NULL,
84                                 &reply,
85                                 "su",
86                                 name,
87                                 flags);
88                 if (r < 0)
89                         return r;
90
91                 r = sd_bus_message_read(reply, "u", &ret);
92                 if (r < 0)
93                         return r;
94
95                 return ret;
96         }
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         uint32_t ret;
102         int r;
103
104         if (!bus)
105                 return -EINVAL;
106         if (!name)
107                 return -EINVAL;
108         if (!bus->bus_client)
109                 return -EINVAL;
110
111         if (bus->is_kernel) {
112                 struct kdbus_cmd_name *n;
113                 size_t l;
114
115                 l = strlen(name);
116                 n = alloca(offsetof(struct kdbus_cmd_name, name) + l + 1);
117                 n->size = offsetof(struct kdbus_cmd_name, name) + l + 1;
118                 n->flags = 0;
119                 n->id = 0;
120                 memcpy(n->name, name, l+1);
121
122                 r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
123                 if (r < 0)
124                         return -errno;
125
126                 return n->flags;
127         } else {
128                 r = sd_bus_call_method(
129                                 bus,
130                                 "org.freedesktop.DBus",
131                                 "/",
132                                 "org.freedesktop.DBus",
133                                 "ReleaseName",
134                                 NULL,
135                                 &reply,
136                                 "s",
137                                 name);
138                 if (r < 0)
139                         return r;
140
141                 r = sd_bus_message_read(reply, "u", &ret);
142                 if (r < 0)
143                         return r;
144         }
145
146         return ret;
147 }
148
149 int sd_bus_list_names(sd_bus *bus, char ***l) {
150         _cleanup_bus_message_unref_ sd_bus_message *reply1 = NULL, *reply2 = NULL;
151         char **x = NULL;
152         int r;
153
154         if (!bus)
155                 return -EINVAL;
156         if (!l)
157                 return -EINVAL;
158
159         r = sd_bus_call_method(
160                         bus,
161                         "org.freedesktop.DBus",
162                         "/",
163                         "org.freedesktop.DBus",
164                         "ListNames",
165                         NULL,
166                         &reply1,
167                         NULL);
168         if (r < 0)
169                 return r;
170
171         r = sd_bus_call_method(
172                         bus,
173                         "org.freedesktop.DBus",
174                         "/",
175                         "org.freedesktop.DBus",
176                         "ListActivatableNames",
177                         NULL,
178                         &reply2,
179                         NULL);
180         if (r < 0)
181                 return r;
182
183         r = bus_message_read_strv_extend(reply1, &x);
184         if (r < 0) {
185                 strv_free(x);
186                 return r;
187         }
188
189         r = bus_message_read_strv_extend(reply2, &x);
190         if (r < 0) {
191                 strv_free(x);
192                 return r;
193         }
194
195         *l = strv_uniq(x);
196         return 0;
197 }
198
199 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         int r;
203
204         if (!bus)
205                 return -EINVAL;
206         if (!name)
207                 return -EINVAL;
208
209         r = sd_bus_call_method(
210                         bus,
211                         "org.freedesktop.DBus",
212                         "/",
213                         "org.freedesktop.DBus",
214                         "GetNameOwner",
215                         NULL,
216                         &reply,
217                         "s",
218                         name);
219         if (r < 0)
220                 return r;
221
222         r = sd_bus_message_read(reply, "s", &found);
223         if (r < 0)
224                 return r;
225
226         if (owner) {
227                 char *t;
228
229                 t = strdup(found);
230                 if (!t)
231                         return -ENOMEM;
232
233                 *owner = t;
234         }
235
236         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         uint32_t u;
242         int r;
243
244         if (!bus)
245                 return -EINVAL;
246         if (!name)
247                 return -EINVAL;
248         if (!uid)
249                 return -EINVAL;
250
251         r = sd_bus_call_method(
252                         bus,
253                         "org.freedesktop.DBus",
254                         "/",
255                         "org.freedesktop.DBus",
256                         "GetConnectionUnixUser",
257                         NULL,
258                         &reply,
259                         "s",
260                         name);
261         if (r < 0)
262                 return r;
263
264         r = sd_bus_message_read(reply, "u", &u);
265         if (r < 0)
266                 return r;
267
268         *uid = (uid_t) u;
269         return 0;
270 }
271
272 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         uint32_t u;
275         int r;
276
277         if (!bus)
278                 return -EINVAL;
279         if (!name)
280                 return -EINVAL;
281         if (!pid)
282                 return -EINVAL;
283
284         r = sd_bus_call_method(
285                         bus,
286                         "org.freedesktop.DBus",
287                         "/",
288                         "org.freedesktop.DBus",
289                         "GetConnectionUnixProcessID",
290                         NULL,
291                         &reply,
292                         "s",
293                         name);
294         if (r < 0)
295                 return r;
296
297         r = sd_bus_message_read(reply, "u", &u);
298         if (r < 0)
299                 return r;
300
301         if (u == 0)
302                 return -EIO;
303
304         *pid = (uid_t) u;
305         return 0;
306 }
307
308 int bus_add_match_internal(sd_bus *bus, const char *match) {
309         assert(bus);
310         assert(match);
311
312         return sd_bus_call_method(
313                         bus,
314                         "org.freedesktop.DBus",
315                         "/",
316                         "org.freedesktop.DBus",
317                         "AddMatch",
318                         NULL,
319                         NULL,
320                         "s",
321                         match);
322 }
323
324 int bus_remove_match_internal(sd_bus *bus, const char *match) {
325         assert(bus);
326         assert(match);
327
328         return sd_bus_call_method(
329                         bus,
330                         "org.freedesktop.DBus",
331                         "/",
332                         "org.freedesktop.DBus",
333                         "RemoveMatch",
334                         NULL,
335                         NULL,
336                         "s",
337                         match);
338 }