]> git.ipfire.org Git - thirdparty/systemd.git/blob - 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
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"
25 #include "bus-util.h"
26 #include "bus-type.h"
27
28 _public_ int sd_bus_emit_signal(
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
38 assert_return(bus, -EINVAL);
39 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
40 assert_return(!bus_pid_changed(bus), -ECHILD);
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
59 _public_ int sd_bus_call_method(
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
72 assert_return(bus, -EINVAL);
73 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
74 assert_return(!bus_pid_changed(bus), -ECHILD);
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
90 return sd_bus_call(bus, m, 0, error, reply);
91 }
92
93 _public_ int sd_bus_reply_method_return(
94 sd_bus_message *call,
95 const char *types, ...) {
96
97 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
98 int r;
99
100 assert_return(call, -EINVAL);
101 assert_return(call->sealed, -EPERM);
102 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
103 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
104 assert_return(!bus_pid_changed(call->bus), -ECHILD);
105
106 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
107 return 0;
108
109 r = sd_bus_message_new_method_return(call, &m);
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
123 return sd_bus_send(call->bus, m, NULL);
124 }
125
126 _public_ int sd_bus_reply_method_error(
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
133 assert_return(call, -EINVAL);
134 assert_return(call->sealed, -EPERM);
135 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
136 assert_return(sd_bus_error_is_set(e), -EINVAL);
137 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
138 assert_return(!bus_pid_changed(call->bus), -ECHILD);
139
140 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
141 return 0;
142
143 r = sd_bus_message_new_method_error(call, e, &m);
144 if (r < 0)
145 return r;
146
147 return sd_bus_send(call->bus, m, NULL);
148 }
149
150 _public_ int sd_bus_reply_method_errorf(
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
160 assert_return(call, -EINVAL);
161 assert_return(call->sealed, -EPERM);
162 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
163 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
164 assert_return(!bus_pid_changed(call->bus), -ECHILD);
165
166 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
167 return 0;
168
169 va_start(ap, format);
170 r = bus_error_setfv(&error, name, format, ap);
171 va_end(ap);
172
173 if (r < 0)
174 return r;
175
176 return sd_bus_reply_method_error(call, &error);
177 }
178
179 _public_ int sd_bus_reply_method_errno(
180 sd_bus_message *call,
181 int error,
182 const sd_bus_error *p) {
183
184 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
185
186 assert_return(call, -EINVAL);
187 assert_return(call->sealed, -EPERM);
188 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
189 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
190 assert_return(!bus_pid_changed(call->bus), -ECHILD);
191
192 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
193 return 0;
194
195 if (sd_bus_error_is_set(p))
196 return sd_bus_reply_method_error(call, p);
197
198 sd_bus_error_set_errno(&berror, error);
199
200 return sd_bus_reply_method_error(call, &berror);
201 }
202
203 _public_ int sd_bus_reply_method_errnof(
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
212 assert_return(call, -EINVAL);
213 assert_return(call->sealed, -EPERM);
214 assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
215 assert_return(call->bus && BUS_IS_OPEN(call->bus->state), -ENOTCONN);
216 assert_return(!bus_pid_changed(call->bus), -ECHILD);
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
225 return sd_bus_reply_method_error(call, &berror);
226 }
227
228 _public_ int sd_bus_get_property(
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
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);
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
263 _public_ int sd_bus_get_property_trivial(
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
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
373 _public_ int sd_bus_set_property(
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
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);
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
415 return sd_bus_call(bus, m, 0, error, NULL);
416 }