]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-convenience.c
bus: let's simplify things by getting rid of unnecessary bus parameters
[thirdparty/systemd.git] / src / libsystemd-bus / bus-convenience.c
CommitLineData
992c052c
LP
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 "bus-internal.h"
23#include "bus-message.h"
24#include "bus-signature.h"
40ca29a1 25#include "bus-util.h"
e5609878 26#include "bus-type.h"
992c052c 27
d9f644e2 28_public_ int sd_bus_emit_signal(
992c052c
LP
29 sd_bus *bus,
30 const char *path,
31 const char *interface,
32 const char *member,
33 const char *types, ...) {
34
35 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
36 int r;
37
f69dc9a3
LP
38 assert_return(bus, -EINVAL);
39 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
40 assert_return(!bus_pid_changed(bus), -ECHILD);
992c052c
LP
41
42 r = sd_bus_message_new_signal(bus, path, interface, member, &m);
43 if (r < 0)
44 return r;
45
46 if (!isempty(types)) {
47 va_list ap;
48
49 va_start(ap, types);
50 r = bus_message_append_ap(m, types, ap);
51 va_end(ap);
52 if (r < 0)
53 return r;
54 }
55
56 return sd_bus_send(bus, m, NULL);
57}
58
d9f644e2 59_public_ int sd_bus_call_method(
992c052c
LP
60 sd_bus *bus,
61 const char *destination,
62 const char *path,
63 const char *interface,
64 const char *member,
65 sd_bus_error *error,
66 sd_bus_message **reply,
67 const char *types, ...) {
68
69 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
70 int r;
71
f69dc9a3
LP
72 assert_return(bus, -EINVAL);
73 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
74 assert_return(!bus_pid_changed(bus), -ECHILD);
992c052c
LP
75
76 r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
77 if (r < 0)
78 return r;
79
80 if (!isempty(types)) {
81 va_list ap;
82
83 va_start(ap, types);
84 r = bus_message_append_ap(m, types, ap);
85 va_end(ap);
86 if (r < 0)
87 return r;
88 }
89
c49b30a2 90 return sd_bus_call(bus, m, 0, error, reply);
992c052c
LP
91}
92
d9f644e2 93_public_ int sd_bus_reply_method_return(
992c052c
LP
94 sd_bus_message *call,
95 const char *types, ...) {
96
97 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
98 int r;
99
f69dc9a3
LP
100 assert_return(call, -EINVAL);
101 assert_return(call->sealed, -EPERM);
40ca29a1 102 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
df2d202e
LP
103 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
104 assert_return(!bus_pid_changed(call->bus), -ECHILD);
992c052c
LP
105
106 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
107 return 0;
108
df2d202e 109 r = sd_bus_message_new_method_return(call, &m);
992c052c
LP
110 if (r < 0)
111 return r;
112
113 if (!isempty(types)) {
114 va_list ap;
115
116 va_start(ap, types);
117 r = bus_message_append_ap(m, types, ap);
118 va_end(ap);
119 if (r < 0)
120 return r;
121 }
122
df2d202e 123 return sd_bus_send(call->bus, m, NULL);
992c052c
LP
124}
125
d9f644e2 126_public_ int sd_bus_reply_method_error(
992c052c
LP
127 sd_bus_message *call,
128 const sd_bus_error *e) {
129
130 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
131 int r;
132
f69dc9a3
LP
133 assert_return(call, -EINVAL);
134 assert_return(call->sealed, -EPERM);
40ca29a1 135 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
f69dc9a3 136 assert_return(sd_bus_error_is_set(e), -EINVAL);
df2d202e
LP
137 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
138 assert_return(!bus_pid_changed(call->bus), -ECHILD);
992c052c
LP
139
140 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
141 return 0;
142
df2d202e 143 r = sd_bus_message_new_method_error(call, e, &m);
992c052c
LP
144 if (r < 0)
145 return r;
146
df2d202e 147 return sd_bus_send(call->bus, m, NULL);
992c052c
LP
148}
149
d9f644e2 150_public_ int sd_bus_reply_method_errorf(
992c052c
LP
151 sd_bus_message *call,
152 const char *name,
153 const char *format,
154 ...) {
155
156 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
157 va_list ap;
158 int r;
159
f69dc9a3
LP
160 assert_return(call, -EINVAL);
161 assert_return(call->sealed, -EPERM);
40ca29a1 162 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
df2d202e
LP
163 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
164 assert_return(!bus_pid_changed(call->bus), -ECHILD);
f69dc9a3
LP
165
166 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
167 return 0;
168
40ca29a1
LP
169 va_start(ap, format);
170 r = bus_error_setfv(&error, name, format, ap);
171 va_end(ap);
992c052c 172
40ca29a1
LP
173 if (r < 0)
174 return r;
992c052c 175
df2d202e 176 return sd_bus_reply_method_error(call, &error);
40ca29a1 177}
992c052c 178
d9f644e2 179_public_ int sd_bus_reply_method_errno(
40ca29a1
LP
180 sd_bus_message *call,
181 int error,
182 const sd_bus_error *p) {
992c052c 183
40ca29a1
LP
184 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
185
40ca29a1
LP
186 assert_return(call, -EINVAL);
187 assert_return(call->sealed, -EPERM);
188 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
df2d202e
LP
189 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
190 assert_return(!bus_pid_changed(call->bus), -ECHILD);
40ca29a1
LP
191
192 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
193 return 0;
194
195 if (sd_bus_error_is_set(p))
df2d202e 196 return sd_bus_reply_method_error(call, p);
40ca29a1
LP
197
198 sd_bus_error_set_errno(&berror, error);
199
df2d202e 200 return sd_bus_reply_method_error(call, &berror);
40ca29a1
LP
201}
202
d9f644e2 203_public_ int sd_bus_reply_method_errnof(
40ca29a1
LP
204 sd_bus_message *call,
205 int error,
206 const char *format,
207 ...) {
208
209 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
210 va_list ap;
211
40ca29a1
LP
212 assert_return(call, -EINVAL);
213 assert_return(call->sealed, -EPERM);
214 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
df2d202e
LP
215 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
216 assert_return(!bus_pid_changed(call->bus), -ECHILD);
40ca29a1
LP
217
218 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
219 return 0;
220
221 va_start(ap, format);
222 bus_error_set_errnofv(&berror, error, format, ap);
223 va_end(ap);
224
df2d202e 225 return sd_bus_reply_method_error(call, &berror);
992c052c
LP
226}
227
d9f644e2 228_public_ int sd_bus_get_property(
992c052c
LP
229 sd_bus *bus,
230 const char *destination,
231 const char *path,
232 const char *interface,
233 const char *member,
234 sd_bus_error *error,
235 sd_bus_message **reply,
236 const char *type) {
237
238 sd_bus_message *rep = NULL;
239 int r;
240
f69dc9a3
LP
241 assert_return(bus, -EINVAL);
242 assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
243 assert_return(member_name_is_valid(member), -EINVAL);
244 assert_return(reply, -EINVAL);
245 assert_return(signature_is_single(type, false), -EINVAL);
246 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
247 assert_return(!bus_pid_changed(bus), -ECHILD);
992c052c
LP
248
249 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
250 if (r < 0)
251 return r;
252
253 r = sd_bus_message_enter_container(rep, 'v', type);
254 if (r < 0) {
255 sd_bus_message_unref(rep);
256 return r;
257 }
258
259 *reply = rep;
260 return 0;
261}
262
d9f644e2 263_public_ int sd_bus_get_property_trivial(
e5609878
LP
264 sd_bus *bus,
265 const char *destination,
266 const char *path,
267 const char *interface,
268 const char *member,
269 sd_bus_error *error,
270 char type, void *ptr) {
271
272 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
273 int r;
274
275 assert_return(bus, -EINVAL);
276 assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
277 assert_return(member_name_is_valid(member), -EINVAL);
278 assert_return(bus_type_is_trivial(type), -EINVAL);
279 assert_return(ptr, -EINVAL);
280 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
281 assert_return(!bus_pid_changed(bus), -ECHILD);
282
283 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
284 if (r < 0)
285 return r;
286
287 r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
288 if (r < 0)
289 return r;
290
291 r = sd_bus_message_read_basic(reply, type, ptr);
292 if (r < 0)
293 return r;
294
295 return 0;
296}
297
63be1989
LP
298_public_ int sd_bus_get_property_string(
299 sd_bus *bus,
300 const char *destination,
301 const char *path,
302 const char *interface,
303 const char *member,
304 sd_bus_error *error,
305 char **ret) {
306
307 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
308 const char *s;
309 char *n;
310 int r;
311
312 assert_return(bus, -EINVAL);
313 assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
314 assert_return(member_name_is_valid(member), -EINVAL);
315 assert_return(ret, -EINVAL);
316 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
317 assert_return(!bus_pid_changed(bus), -ECHILD);
318
319 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
320 if (r < 0)
321 return r;
322
323 r = sd_bus_message_enter_container(reply, 'v', "s");
324 if (r < 0)
325 return r;
326
327 r = sd_bus_message_read_basic(reply, 's', &s);
328 if (r < 0)
329 return r;
330
331 n = strdup(s);
332 if (!n)
333 return -ENOMEM;
334
335 *ret = n;
336 return 0;
337}
338
339_public_ int sd_bus_get_property_strv(
340 sd_bus *bus,
341 const char *destination,
342 const char *path,
343 const char *interface,
344 const char *member,
345 sd_bus_error *error,
346 char ***ret) {
347
348 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
349 int r;
350
351 assert_return(bus, -EINVAL);
352 assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
353 assert_return(member_name_is_valid(member), -EINVAL);
354 assert_return(ret, -EINVAL);
355 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
356 assert_return(!bus_pid_changed(bus), -ECHILD);
357
358 r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
359 if (r < 0)
360 return r;
361
362 r = sd_bus_message_enter_container(reply, 'v', NULL);
363 if (r < 0)
364 return r;
365
366 r = sd_bus_message_read_strv(reply, ret);
367 if (r < 0)
368 return r;
369
370 return 0;
371}
372
d9f644e2 373_public_ int sd_bus_set_property(
992c052c
LP
374 sd_bus *bus,
375 const char *destination,
376 const char *path,
377 const char *interface,
378 const char *member,
379 sd_bus_error *error,
380 const char *type, ...) {
381
382 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
383 va_list ap;
384 int r;
385
f69dc9a3
LP
386 assert_return(bus, -EINVAL);
387 assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL);
388 assert_return(member_name_is_valid(member), -EINVAL);
389 assert_return(signature_is_single(type, false), -EINVAL);
390 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
391 assert_return(!bus_pid_changed(bus), -ECHILD);
992c052c
LP
392
393 r = sd_bus_message_new_method_call(bus, destination, path, "org.freedesktop.DBus.Properties", "Set", &m);
394 if (r < 0)
395 return r;
396
397 r = sd_bus_message_append(m, "ss", strempty(interface), member);
398 if (r < 0)
399 return r;
400
401 r = sd_bus_message_open_container(m, 'v', type);
402 if (r < 0)
403 return r;
404
405 va_start(ap, type);
406 r = bus_message_append_ap(m, type, ap);
407 va_end(ap);
408 if (r < 0)
409 return r;
410
411 r = sd_bus_message_close_container(m);
412 if (r < 0)
413 return r;
414
c49b30a2 415 return sd_bus_call(bus, m, 0, error, NULL);
992c052c 416}