Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <unistd.h>
4 : #include <sys/types.h>
5 :
6 : #include "bus-internal.h"
7 : #include "bus-message.h"
8 : #include "bus-signature.h"
9 : #include "bus-type.h"
10 : #include "bus-util.h"
11 : #include "string-util.h"
12 :
13 0 : _public_ int sd_bus_emit_signal(
14 : sd_bus *bus,
15 : const char *path,
16 : const char *interface,
17 : const char *member,
18 : const char *types, ...) {
19 :
20 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
21 : int r;
22 :
23 0 : assert_return(bus, -EINVAL);
24 0 : assert_return(bus = bus_resolve(bus), -ENOPKG);
25 0 : assert_return(!bus_pid_changed(bus), -ECHILD);
26 :
27 0 : if (!BUS_IS_OPEN(bus->state))
28 0 : return -ENOTCONN;
29 :
30 0 : r = sd_bus_message_new_signal(bus, &m, path, interface, member);
31 0 : if (r < 0)
32 0 : return r;
33 :
34 0 : if (!isempty(types)) {
35 : va_list ap;
36 :
37 0 : va_start(ap, types);
38 0 : r = sd_bus_message_appendv(m, types, ap);
39 0 : va_end(ap);
40 0 : if (r < 0)
41 0 : return r;
42 : }
43 :
44 0 : return sd_bus_send(bus, m, NULL);
45 : }
46 :
47 34 : _public_ int sd_bus_call_method_async(
48 : sd_bus *bus,
49 : sd_bus_slot **slot,
50 : const char *destination,
51 : const char *path,
52 : const char *interface,
53 : const char *member,
54 : sd_bus_message_handler_t callback,
55 : void *userdata,
56 : const char *types, ...) {
57 :
58 34 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
59 : int r;
60 :
61 34 : assert_return(bus, -EINVAL);
62 34 : assert_return(bus = bus_resolve(bus), -ENOPKG);
63 34 : assert_return(!bus_pid_changed(bus), -ECHILD);
64 :
65 34 : if (!BUS_IS_OPEN(bus->state))
66 16 : return -ENOTCONN;
67 :
68 18 : r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
69 18 : if (r < 0)
70 0 : return r;
71 :
72 18 : if (!isempty(types)) {
73 : va_list ap;
74 :
75 17 : va_start(ap, types);
76 17 : r = sd_bus_message_appendv(m, types, ap);
77 17 : va_end(ap);
78 17 : if (r < 0)
79 0 : return r;
80 : }
81 :
82 18 : return sd_bus_call_async(bus, slot, m, callback, userdata, 0);
83 : }
84 :
85 31 : _public_ int sd_bus_call_method(
86 : sd_bus *bus,
87 : const char *destination,
88 : const char *path,
89 : const char *interface,
90 : const char *member,
91 : sd_bus_error *error,
92 : sd_bus_message **reply,
93 : const char *types, ...) {
94 :
95 31 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
96 : int r;
97 :
98 31 : bus_assert_return(bus, -EINVAL, error);
99 31 : bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
100 :
101 31 : if (!BUS_IS_OPEN(bus->state)) {
102 0 : r = -ENOTCONN;
103 0 : goto fail;
104 : }
105 :
106 31 : r = sd_bus_message_new_method_call(bus, &m, destination, path, interface, member);
107 31 : if (r < 0)
108 0 : goto fail;
109 :
110 31 : if (!isempty(types)) {
111 : va_list ap;
112 :
113 14 : va_start(ap, types);
114 14 : r = sd_bus_message_appendv(m, types, ap);
115 14 : va_end(ap);
116 14 : if (r < 0)
117 0 : goto fail;
118 : }
119 :
120 31 : return sd_bus_call(bus, m, 0, error, reply);
121 :
122 0 : fail:
123 0 : return sd_bus_error_set_errno(error, r);
124 : }
125 :
126 20 : _public_ int sd_bus_reply_method_return(
127 : sd_bus_message *call,
128 : const char *types, ...) {
129 :
130 20 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
131 : int r;
132 :
133 20 : assert_return(call, -EINVAL);
134 20 : assert_return(call->sealed, -EPERM);
135 20 : assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
136 20 : assert_return(call->bus, -EINVAL);
137 20 : assert_return(!bus_pid_changed(call->bus), -ECHILD);
138 :
139 20 : if (!BUS_IS_OPEN(call->bus->state))
140 0 : return -ENOTCONN;
141 :
142 20 : if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
143 3 : return 0;
144 :
145 17 : r = sd_bus_message_new_method_return(call, &m);
146 17 : if (r < 0)
147 0 : return r;
148 :
149 17 : if (!isempty(types)) {
150 : va_list ap;
151 :
152 3 : va_start(ap, types);
153 3 : r = sd_bus_message_appendv(m, types, ap);
154 3 : va_end(ap);
155 3 : if (r < 0)
156 0 : return r;
157 : }
158 :
159 17 : return sd_bus_send(call->bus, m, NULL);
160 : }
161 :
162 4 : _public_ int sd_bus_reply_method_error(
163 : sd_bus_message *call,
164 : const sd_bus_error *e) {
165 :
166 4 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
167 : int r;
168 :
169 4 : assert_return(call, -EINVAL);
170 4 : assert_return(call->sealed, -EPERM);
171 4 : assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
172 4 : assert_return(sd_bus_error_is_set(e), -EINVAL);
173 4 : assert_return(call->bus, -EINVAL);
174 4 : assert_return(!bus_pid_changed(call->bus), -ECHILD);
175 :
176 4 : if (!BUS_IS_OPEN(call->bus->state))
177 0 : return -ENOTCONN;
178 :
179 4 : if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
180 0 : return 0;
181 :
182 4 : r = sd_bus_message_new_method_error(call, &m, e);
183 4 : if (r < 0)
184 0 : return r;
185 :
186 4 : return sd_bus_send(call->bus, m, NULL);
187 : }
188 :
189 4 : _public_ int sd_bus_reply_method_errorf(
190 : sd_bus_message *call,
191 : const char *name,
192 : const char *format,
193 : ...) {
194 :
195 4 : _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
196 : va_list ap;
197 :
198 4 : assert_return(call, -EINVAL);
199 4 : assert_return(call->sealed, -EPERM);
200 4 : assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
201 4 : assert_return(call->bus, -EINVAL);
202 4 : assert_return(!bus_pid_changed(call->bus), -ECHILD);
203 :
204 4 : if (!BUS_IS_OPEN(call->bus->state))
205 0 : return -ENOTCONN;
206 :
207 4 : if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
208 0 : return 0;
209 :
210 4 : va_start(ap, format);
211 4 : bus_error_setfv(&error, name, format, ap);
212 4 : va_end(ap);
213 :
214 4 : return sd_bus_reply_method_error(call, &error);
215 : }
216 :
217 0 : _public_ int sd_bus_reply_method_errno(
218 : sd_bus_message *call,
219 : int error,
220 : const sd_bus_error *p) {
221 :
222 0 : _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
223 :
224 0 : assert_return(call, -EINVAL);
225 0 : assert_return(call->sealed, -EPERM);
226 0 : assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
227 0 : assert_return(call->bus, -EINVAL);
228 0 : assert_return(!bus_pid_changed(call->bus), -ECHILD);
229 :
230 0 : if (!BUS_IS_OPEN(call->bus->state))
231 0 : return -ENOTCONN;
232 :
233 0 : if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
234 0 : return 0;
235 :
236 0 : if (sd_bus_error_is_set(p))
237 0 : return sd_bus_reply_method_error(call, p);
238 :
239 0 : sd_bus_error_set_errno(&berror, error);
240 :
241 0 : return sd_bus_reply_method_error(call, &berror);
242 : }
243 :
244 0 : _public_ int sd_bus_reply_method_errnof(
245 : sd_bus_message *call,
246 : int error,
247 : const char *format,
248 : ...) {
249 :
250 0 : _cleanup_(sd_bus_error_free) sd_bus_error berror = SD_BUS_ERROR_NULL;
251 : va_list ap;
252 :
253 0 : assert_return(call, -EINVAL);
254 0 : assert_return(call->sealed, -EPERM);
255 0 : assert_return(call->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
256 0 : assert_return(call->bus, -EINVAL);
257 0 : assert_return(!bus_pid_changed(call->bus), -ECHILD);
258 :
259 0 : if (!BUS_IS_OPEN(call->bus->state))
260 0 : return -ENOTCONN;
261 :
262 0 : if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
263 0 : return 0;
264 :
265 0 : va_start(ap, format);
266 0 : sd_bus_error_set_errnofv(&berror, error, format, ap);
267 0 : va_end(ap);
268 :
269 0 : return sd_bus_reply_method_error(call, &berror);
270 : }
271 :
272 3 : _public_ int sd_bus_get_property(
273 : sd_bus *bus,
274 : const char *destination,
275 : const char *path,
276 : const char *interface,
277 : const char *member,
278 : sd_bus_error *error,
279 : sd_bus_message **reply,
280 : const char *type) {
281 :
282 3 : sd_bus_message *rep = NULL;
283 : int r;
284 :
285 3 : bus_assert_return(bus, -EINVAL, error);
286 3 : bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
287 3 : bus_assert_return(member_name_is_valid(member), -EINVAL, error);
288 3 : bus_assert_return(reply, -EINVAL, error);
289 3 : bus_assert_return(signature_is_single(type, false), -EINVAL, error);
290 3 : bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
291 :
292 3 : if (!BUS_IS_OPEN(bus->state)) {
293 0 : r = -ENOTCONN;
294 0 : goto fail;
295 : }
296 :
297 3 : r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &rep, "ss", strempty(interface), member);
298 3 : if (r < 0)
299 0 : return r;
300 :
301 3 : r = sd_bus_message_enter_container(rep, 'v', type);
302 3 : if (r < 0) {
303 0 : sd_bus_message_unref(rep);
304 0 : goto fail;
305 : }
306 :
307 3 : *reply = rep;
308 3 : return 0;
309 :
310 0 : fail:
311 0 : return sd_bus_error_set_errno(error, r);
312 : }
313 :
314 0 : _public_ int sd_bus_get_property_trivial(
315 : sd_bus *bus,
316 : const char *destination,
317 : const char *path,
318 : const char *interface,
319 : const char *member,
320 : sd_bus_error *error,
321 : char type, void *ptr) {
322 :
323 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
324 : int r;
325 :
326 0 : bus_assert_return(bus, -EINVAL, error);
327 0 : bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
328 0 : bus_assert_return(member_name_is_valid(member), -EINVAL, error);
329 0 : bus_assert_return(bus_type_is_trivial(type), -EINVAL, error);
330 0 : bus_assert_return(ptr, -EINVAL, error);
331 0 : bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
332 :
333 0 : if (!BUS_IS_OPEN(bus->state)) {
334 0 : r = -ENOTCONN;
335 0 : goto fail;
336 : }
337 :
338 0 : r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
339 0 : if (r < 0)
340 0 : return r;
341 :
342 0 : r = sd_bus_message_enter_container(reply, 'v', CHAR_TO_STR(type));
343 0 : if (r < 0)
344 0 : goto fail;
345 :
346 0 : r = sd_bus_message_read_basic(reply, type, ptr);
347 0 : if (r < 0)
348 0 : goto fail;
349 :
350 0 : return 0;
351 :
352 0 : fail:
353 0 : return sd_bus_error_set_errno(error, r);
354 : }
355 :
356 0 : _public_ int sd_bus_get_property_string(
357 : sd_bus *bus,
358 : const char *destination,
359 : const char *path,
360 : const char *interface,
361 : const char *member,
362 : sd_bus_error *error,
363 : char **ret) {
364 :
365 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
366 : const char *s;
367 : char *n;
368 : int r;
369 :
370 0 : bus_assert_return(bus, -EINVAL, error);
371 0 : bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
372 0 : bus_assert_return(member_name_is_valid(member), -EINVAL, error);
373 0 : bus_assert_return(ret, -EINVAL, error);
374 0 : bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
375 :
376 0 : if (!BUS_IS_OPEN(bus->state)) {
377 0 : r = -ENOTCONN;
378 0 : goto fail;
379 : }
380 :
381 0 : r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
382 0 : if (r < 0)
383 0 : return r;
384 :
385 0 : r = sd_bus_message_enter_container(reply, 'v', "s");
386 0 : if (r < 0)
387 0 : goto fail;
388 :
389 0 : r = sd_bus_message_read_basic(reply, 's', &s);
390 0 : if (r < 0)
391 0 : goto fail;
392 :
393 0 : n = strdup(s);
394 0 : if (!n) {
395 0 : r = -ENOMEM;
396 0 : goto fail;
397 : }
398 :
399 0 : *ret = n;
400 0 : return 0;
401 :
402 0 : fail:
403 0 : return sd_bus_error_set_errno(error, r);
404 : }
405 :
406 0 : _public_ int sd_bus_get_property_strv(
407 : sd_bus *bus,
408 : const char *destination,
409 : const char *path,
410 : const char *interface,
411 : const char *member,
412 : sd_bus_error *error,
413 : char ***ret) {
414 :
415 0 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
416 : int r;
417 :
418 0 : bus_assert_return(bus, -EINVAL, error);
419 0 : bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
420 0 : bus_assert_return(member_name_is_valid(member), -EINVAL, error);
421 0 : bus_assert_return(ret, -EINVAL, error);
422 0 : bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
423 :
424 0 : if (!BUS_IS_OPEN(bus->state)) {
425 0 : r = -ENOTCONN;
426 0 : goto fail;
427 : }
428 :
429 0 : r = sd_bus_call_method(bus, destination, path, "org.freedesktop.DBus.Properties", "Get", error, &reply, "ss", strempty(interface), member);
430 0 : if (r < 0)
431 0 : return r;
432 :
433 0 : r = sd_bus_message_enter_container(reply, 'v', NULL);
434 0 : if (r < 0)
435 0 : goto fail;
436 :
437 0 : r = sd_bus_message_read_strv(reply, ret);
438 0 : if (r < 0)
439 0 : goto fail;
440 :
441 0 : return 0;
442 :
443 0 : fail:
444 0 : return sd_bus_error_set_errno(error, r);
445 : }
446 :
447 3 : _public_ int sd_bus_set_property(
448 : sd_bus *bus,
449 : const char *destination,
450 : const char *path,
451 : const char *interface,
452 : const char *member,
453 : sd_bus_error *error,
454 : const char *type, ...) {
455 :
456 3 : _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
457 : va_list ap;
458 : int r;
459 :
460 3 : bus_assert_return(bus, -EINVAL, error);
461 3 : bus_assert_return(isempty(interface) || interface_name_is_valid(interface), -EINVAL, error);
462 3 : bus_assert_return(member_name_is_valid(member), -EINVAL, error);
463 3 : bus_assert_return(signature_is_single(type, false), -EINVAL, error);
464 3 : bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
465 :
466 3 : if (!BUS_IS_OPEN(bus->state)) {
467 0 : r = -ENOTCONN;
468 0 : goto fail;
469 : }
470 :
471 3 : r = sd_bus_message_new_method_call(bus, &m, destination, path, "org.freedesktop.DBus.Properties", "Set");
472 3 : if (r < 0)
473 0 : goto fail;
474 :
475 3 : r = sd_bus_message_append(m, "ss", strempty(interface), member);
476 3 : if (r < 0)
477 0 : goto fail;
478 :
479 3 : r = sd_bus_message_open_container(m, 'v', type);
480 3 : if (r < 0)
481 0 : goto fail;
482 :
483 3 : va_start(ap, type);
484 3 : r = sd_bus_message_appendv(m, type, ap);
485 3 : va_end(ap);
486 3 : if (r < 0)
487 0 : goto fail;
488 :
489 3 : r = sd_bus_message_close_container(m);
490 3 : if (r < 0)
491 0 : goto fail;
492 :
493 3 : return sd_bus_call(bus, m, 0, error, NULL);
494 :
495 0 : fail:
496 0 : return sd_bus_error_set_errno(error, r);
497 : }
498 :
499 13 : _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
500 : sd_bus_creds *c;
501 :
502 13 : assert_return(call, -EINVAL);
503 13 : assert_return(call->sealed, -EPERM);
504 13 : assert_return(call->bus, -EINVAL);
505 13 : assert_return(!bus_pid_changed(call->bus), -ECHILD);
506 :
507 13 : if (!BUS_IS_OPEN(call->bus->state))
508 0 : return -ENOTCONN;
509 :
510 13 : c = sd_bus_message_get_creds(call);
511 :
512 : /* All data we need? */
513 13 : if (c && (mask & ~c->mask) == 0) {
514 0 : *creds = sd_bus_creds_ref(c);
515 0 : return 0;
516 : }
517 :
518 : /* No data passed? Or not enough data passed to retrieve the missing bits? */
519 13 : if (!c || !(c->mask & SD_BUS_CREDS_PID)) {
520 : /* We couldn't read anything from the call, let's try
521 : * to get it from the sender or peer. */
522 :
523 13 : if (call->sender)
524 : /* There's a sender, but the creds are missing. */
525 0 : return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
526 : else
527 : /* There's no sender. For direct connections
528 : * the credentials of the AF_UNIX peer matter,
529 : * which may be queried via sd_bus_get_owner_creds(). */
530 13 : return sd_bus_get_owner_creds(call->bus, mask, creds);
531 : }
532 :
533 0 : return bus_creds_extend_by_pid(c, mask, creds);
534 : }
535 :
536 13 : _public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {
537 13 : _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
538 : uid_t our_uid;
539 13 : bool know_caps = false;
540 : int r;
541 :
542 13 : assert_return(call, -EINVAL);
543 13 : assert_return(call->sealed, -EPERM);
544 13 : assert_return(call->bus, -EINVAL);
545 13 : assert_return(!bus_pid_changed(call->bus), -ECHILD);
546 :
547 13 : if (!BUS_IS_OPEN(call->bus->state))
548 0 : return -ENOTCONN;
549 :
550 13 : if (capability >= 0) {
551 :
552 13 : r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds);
553 13 : if (r < 0)
554 0 : return r;
555 :
556 : /* We cannot use augmented caps for authorization,
557 : * since then data is acquired raceful from
558 : * /proc. This can never actually happen, but let's
559 : * better be safe than sorry, and do an extra check
560 : * here. */
561 13 : assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EFFECTIVE_CAPS) == 0, -EPERM);
562 :
563 13 : r = sd_bus_creds_has_effective_cap(creds, capability);
564 13 : if (r > 0)
565 0 : return 1;
566 13 : if (r == 0)
567 0 : know_caps = true;
568 : } else {
569 0 : r = sd_bus_query_sender_creds(call, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID, &creds);
570 0 : if (r < 0)
571 0 : return r;
572 : }
573 :
574 : /* Now, check the UID, but only if the capability check wasn't
575 : * sufficient */
576 13 : our_uid = getuid();
577 13 : if (our_uid != 0 || !know_caps || capability < 0) {
578 : uid_t sender_uid;
579 :
580 : /* We cannot use augmented uid/euid for authorization,
581 : * since then data is acquired raceful from
582 : * /proc. This can never actually happen, but let's
583 : * better be safe than sorry, and do an extra check
584 : * here. */
585 26 : assert_return((sd_bus_creds_get_augmented_mask(creds) & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID)) == 0, -EPERM);
586 :
587 : /* Try to use the EUID, if we have it. */
588 13 : r = sd_bus_creds_get_euid(creds, &sender_uid);
589 13 : if (r < 0)
590 0 : r = sd_bus_creds_get_uid(creds, &sender_uid);
591 :
592 13 : if (r >= 0) {
593 : /* Sender has same UID as us, then let's grant access */
594 13 : if (sender_uid == our_uid)
595 13 : return 1;
596 :
597 : /* Sender is root, we are not root. */
598 0 : if (our_uid != 0 && sender_uid == 0)
599 0 : return 1;
600 : }
601 : }
602 :
603 0 : return 0;
604 : }
605 :
606 : #define make_expression(sender, path, interface, member) \
607 : strjoina( \
608 : "type='signal'", \
609 : sender ? ",sender='" : "", \
610 : sender ?: "", \
611 : sender ? "'" : "", \
612 : path ? ",path='" : "", \
613 : path ?: "", \
614 : path ? "'" : "", \
615 : interface ? ",interface='" : "", \
616 : interface ?: "", \
617 : interface ? "'" : "", \
618 : member ? ",member='" : "", \
619 : member ?: "", \
620 : member ? "'" : "" \
621 : )
622 :
623 1 : _public_ int sd_bus_match_signal(
624 : sd_bus *bus,
625 : sd_bus_slot **ret,
626 : const char *sender,
627 : const char *path,
628 : const char *interface,
629 : const char *member,
630 : sd_bus_message_handler_t callback,
631 : void *userdata) {
632 :
633 : const char *expression;
634 :
635 1 : assert_return(bus, -EINVAL);
636 1 : assert_return(bus = bus_resolve(bus), -ENOPKG);
637 1 : assert_return(!bus_pid_changed(bus), -ECHILD);
638 1 : assert_return(!sender || service_name_is_valid(sender), -EINVAL);
639 1 : assert_return(!path || object_path_is_valid(path), -EINVAL);
640 1 : assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
641 1 : assert_return(!member || member_name_is_valid(member), -EINVAL);
642 :
643 27 : expression = make_expression(sender, path, interface, member);
644 :
645 1 : return sd_bus_add_match(bus, ret, expression, callback, userdata);
646 : }
647 :
648 26 : _public_ int sd_bus_match_signal_async(
649 : sd_bus *bus,
650 : sd_bus_slot **ret,
651 : const char *sender,
652 : const char *path,
653 : const char *interface,
654 : const char *member,
655 : sd_bus_message_handler_t callback,
656 : sd_bus_message_handler_t install_callback,
657 : void *userdata) {
658 :
659 : const char *expression;
660 :
661 26 : assert_return(bus, -EINVAL);
662 26 : assert_return(bus = bus_resolve(bus), -ENOPKG);
663 26 : assert_return(!bus_pid_changed(bus), -ECHILD);
664 26 : assert_return(!sender || service_name_is_valid(sender), -EINVAL);
665 26 : assert_return(!path || object_path_is_valid(path), -EINVAL);
666 26 : assert_return(!interface || interface_name_is_valid(interface), -EINVAL);
667 26 : assert_return(!member || member_name_is_valid(member), -EINVAL);
668 :
669 702 : expression = make_expression(sender, path, interface, member);
670 :
671 26 : return sd_bus_add_match_async(bus, ret, expression, callback, install_callback, userdata);
672 : }
|