chiark / gitweb /
bus: parse matches locally and allow registration of callbacks for them
[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 *m = NULL, *reply = NULL;
50         uint32_t ret;
51         int r;
52
53         if (!bus)
54                 return -EINVAL;
55         if (!name)
56                 return -EINVAL;
57
58         r = sd_bus_message_new_method_call(
59                         bus,
60                         "org.freedesktop.DBus",
61                         "/",
62                         "org.freedesktop.DBus",
63                         "RequestName",
64                         &m);
65         if (r < 0)
66                 return r;
67
68         r = sd_bus_message_append(m, "su", name, flags);
69         if (r < 0)
70                 return r;
71
72         r = sd_bus_send_with_reply_and_block(bus, m, 0, NULL, &reply);
73         if (r < 0)
74                 return r;
75
76         r = sd_bus_message_read(reply, "u", &ret);
77         if (r < 0)
78                 return r;
79
80         return ret;
81 }
82
83 int sd_bus_release_name(sd_bus *bus, const char *name) {
84         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
85         uint32_t ret;
86         int r;
87
88         if (!bus)
89                 return -EINVAL;
90         if (!name)
91                 return -EINVAL;
92
93         r = sd_bus_message_new_method_call(
94                         bus,
95                         "org.freedesktop.DBus",
96                         "/",
97                         "org.freedesktop.DBus",
98                         "ReleaseName",
99                         &m);
100         if (r < 0)
101                 return r;
102
103         r = sd_bus_message_append(m, "s", name);
104         if (r < 0)
105                 return r;
106
107         r = sd_bus_send_with_reply_and_block(bus, m, 0, NULL, &reply);
108         if (r < 0)
109                 return r;
110
111         r = sd_bus_message_read(reply, "u", &ret);
112         if (r < 0)
113                 return r;
114
115         return ret;
116 }
117
118 int sd_bus_list_names(sd_bus *bus, char ***l) {
119         _cleanup_bus_message_unref_ sd_bus_message *m1 = NULL, *reply1 = NULL, *m2 = NULL, *reply2 = NULL;
120         char **x = NULL;
121         int r;
122
123         if (!bus)
124                 return -EINVAL;
125         if (!l)
126                 return -EINVAL;
127
128         r = sd_bus_message_new_method_call(
129                         bus,
130                         "org.freedesktop.DBus",
131                         "/",
132                         "org.freedesktop.DBus",
133                         "ListNames",
134                         &m1);
135         if (r < 0)
136                 return r;
137
138         r = sd_bus_message_new_method_call(
139                         bus,
140                         "org.freedesktop.DBus",
141                         "/",
142                         "org.freedesktop.DBus",
143                         "ListActivatableNames",
144                         &m2);
145         if (r < 0)
146                 return r;
147
148         r = sd_bus_send_with_reply_and_block(bus, m1, 0, NULL, &reply1);
149         if (r < 0)
150                 return r;
151
152         r = sd_bus_send_with_reply_and_block(bus, m2, 0, NULL, &reply2);
153         if (r < 0)
154                 return r;
155
156         r = bus_message_read_strv_extend(reply1, &x);
157         if (r < 0) {
158                 strv_free(x);
159                 return r;
160         }
161
162         r = bus_message_read_strv_extend(reply2, &x);
163         if (r < 0) {
164                 strv_free(x);
165                 return r;
166         }
167
168         *l = strv_uniq(x);
169         return 0;
170 }
171
172 int sd_bus_get_owner(sd_bus *bus, const char *name, char **owner) {
173         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
174         const char *found;
175         int r;
176
177         if (!bus)
178                 return -EINVAL;
179         if (!name)
180                 return -EINVAL;
181
182         r = sd_bus_message_new_method_call(
183                         bus,
184                         "org.freedesktop.DBus",
185                         "/",
186                         "org.freedesktop.DBus",
187                         "GetNameOwner",
188                         &m);
189         if (r < 0)
190                 return r;
191
192         r = sd_bus_message_append(m, "s", name);
193         if (r < 0)
194                 return r;
195
196         r = sd_bus_send_with_reply_and_block(bus, m, 0, NULL, &reply);
197         if (r < 0)
198                 return r;
199
200         r = sd_bus_message_read(reply, "s", &found);
201         if (r < 0)
202                 return r;
203
204         if (owner) {
205                 char *t;
206
207                 t = strdup(found);
208                 if (!t)
209                         return -ENOMEM;
210
211                 *owner = t;
212         }
213
214         return 0;
215 }
216
217 int sd_bus_get_owner_uid(sd_bus *bus, const char *name, uid_t *uid) {
218         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
219         uint32_t u;
220         int r;
221
222         if (!bus)
223                 return -EINVAL;
224         if (!name)
225                 return -EINVAL;
226         if (!uid)
227                 return -EINVAL;
228
229         r = sd_bus_message_new_method_call(
230                         bus,
231                         "org.freedesktop.DBus",
232                         "/",
233                         "org.freedesktop.DBus",
234                         "GetConnectionUnixUser",
235                         &m);
236         if (r < 0)
237                 return r;
238
239         r = sd_bus_message_append(m, "s", name);
240         if (r < 0)
241                 return r;
242
243         r = sd_bus_send_with_reply_and_block(bus, m, 0, NULL, &reply);
244         if (r < 0)
245                 return r;
246
247         r = sd_bus_message_read(reply, "u", &u);
248         if (r < 0)
249                 return r;
250
251         *uid = (uid_t) u;
252         return 0;
253 }
254
255 int sd_bus_get_owner_pid(sd_bus *bus, const char *name, pid_t *pid) {
256         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
257         uint32_t u;
258         int r;
259
260         if (!bus)
261                 return -EINVAL;
262         if (!name)
263                 return -EINVAL;
264         if (!pid)
265                 return -EINVAL;
266
267         r = sd_bus_message_new_method_call(
268                         bus,
269                         "org.freedesktop.DBus",
270                         "/",
271                         "org.freedesktop.DBus",
272                         "GetConnectionUnixProcessID",
273                         &m);
274         if (r < 0)
275                 return r;
276
277         r = sd_bus_message_append(m, "s", name);
278         if (r < 0)
279                 return r;
280
281         r = sd_bus_send_with_reply_and_block(bus, m, 0, NULL, &reply);
282         if (r < 0)
283                 return r;
284
285         r = sd_bus_message_read(reply, "u", &u);
286         if (r < 0)
287                 return r;
288
289         if (u == 0)
290                 return -EIO;
291
292         *pid = (uid_t) u;
293         return 0;
294 }
295
296 int bus_add_match_internal(sd_bus *bus, const char *match) {
297         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
298         int r;
299
300         assert(bus);
301         assert(match);
302
303         r = sd_bus_message_new_method_call(
304                         bus,
305                         "org.freedesktop.DBus",
306                         "/",
307                         "org.freedesktop.DBus",
308                         "AddMatch",
309                         &m);
310         if (r < 0)
311                 return r;
312
313         r = sd_bus_message_append(m, "s", match);
314         if (r < 0)
315                 return r;
316
317         return sd_bus_send_with_reply_and_block(bus, m, 0, NULL, &reply);
318 }
319
320 int bus_remove_match_internal(sd_bus *bus, const char *match) {
321         _cleanup_bus_message_unref_ sd_bus_message *m = NULL, *reply = NULL;
322         int r;
323
324         assert(bus);
325         assert(match);
326
327         r = sd_bus_message_new_method_call(
328                         bus,
329                         "org.freedesktop.DBus",
330                         "/",
331                         "org.freedesktop.DBus",
332                         "RemoveMatch",
333                         &m);
334         if (r < 0)
335                 return r;
336
337         r = sd_bus_message_append(m, "s", match);
338         if (r < 0)
339                 return r;
340
341         return sd_bus_send_with_reply_and_block(bus, m, 0, NULL, &reply);
342 }