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