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