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