]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-bus.c
bus: fix counting of argN= matches
[thirdparty/systemd.git] / src / libsystemd-bus / sd-bus.c
CommitLineData
de1c301e
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 <endian.h>
23#include <assert.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <netdb.h>
27#include <sys/poll.h>
28#include <byteswap.h>
29
30#include "util.h"
31#include "macro.h"
2fd9ae2e 32#include "strv.h"
0a72c2bd 33#include "set.h"
de1c301e
LP
34
35#include "sd-bus.h"
36#include "bus-internal.h"
37#include "bus-message.h"
38#include "bus-type.h"
a7e3212d 39#include "bus-socket.h"
6629161f 40#include "bus-kernel.h"
392d5b37 41#include "bus-control.h"
de1c301e 42
e3017af9
LP
43static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
44
de1c301e
LP
45static void bus_free(sd_bus *b) {
46 struct filter_callback *f;
a652755d 47 struct object_callback *c;
89ffcd2a 48 unsigned i;
de1c301e
LP
49
50 assert(b);
51
e82c9509 52 sd_bus_close(b);
de1c301e
LP
53
54 free(b->rbuffer);
89ffcd2a 55 free(b->unique_name);
2181a7f5 56 free(b->auth_buffer);
89ffcd2a 57 free(b->address);
e9a967f9 58 free(b->kernel);
89ffcd2a 59
2fd9ae2e
LP
60 free(b->exec_path);
61 strv_free(b->exec_argv);
62
2c93b4ef
LP
63 close_many(b->fds, b->n_fds);
64 free(b->fds);
65
89ffcd2a
LP
66 for (i = 0; i < b->rqueue_size; i++)
67 sd_bus_message_unref(b->rqueue[i]);
de1c301e 68 free(b->rqueue);
89ffcd2a
LP
69
70 for (i = 0; i < b->wqueue_size; i++)
71 sd_bus_message_unref(b->wqueue[i]);
de1c301e 72 free(b->wqueue);
de1c301e
LP
73
74 hashmap_free_free(b->reply_callbacks);
e3017af9 75 prioq_free(b->reply_callbacks_prioq);
de1c301e
LP
76
77 while ((f = b->filter_callbacks)) {
78 LIST_REMOVE(struct filter_callback, callbacks, b->filter_callbacks, f);
79 free(f);
80 }
81
a652755d
LP
82 while ((c = hashmap_steal_first(b->object_callbacks))) {
83 free(c->path);
84 free(c);
85 }
86
87 hashmap_free(b->object_callbacks);
88
392d5b37
LP
89 bus_match_free(&b->match_callbacks);
90
de1c301e
LP
91 free(b);
92}
93
021a1e78 94int sd_bus_new(sd_bus **ret) {
de1c301e
LP
95 sd_bus *r;
96
021a1e78
LP
97 if (!ret)
98 return -EINVAL;
99
de1c301e
LP
100 r = new0(sd_bus, 1);
101 if (!r)
021a1e78 102 return -ENOMEM;
de1c301e
LP
103
104 r->n_ref = 1;
e82c9509 105 r->input_fd = r->output_fd = -1;
de1c301e 106 r->message_version = 1;
021a1e78 107 r->negotiate_fds = true;
de1c301e
LP
108
109 /* We guarantee that wqueue always has space for at least one
110 * entry */
111 r->wqueue = new(sd_bus_message*, 1);
112 if (!r->wqueue) {
113 free(r);
021a1e78 114 return -ENOMEM;
de1c301e
LP
115 }
116
021a1e78
LP
117 *ret = r;
118 return 0;
119}
120
121int sd_bus_set_address(sd_bus *bus, const char *address) {
122 char *a;
123
124 if (!bus)
125 return -EINVAL;
126 if (bus->state != BUS_UNSET)
127 return -EPERM;
128 if (!address)
129 return -EINVAL;
130
131 a = strdup(address);
132 if (!a)
133 return -ENOMEM;
134
135 free(bus->address);
136 bus->address = a;
137
138 return 0;
139}
140
e82c9509 141int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
021a1e78
LP
142 if (!bus)
143 return -EINVAL;
144 if (bus->state != BUS_UNSET)
145 return -EPERM;
e82c9509
LP
146 if (input_fd < 0)
147 return -EINVAL;
148 if (output_fd < 0)
021a1e78
LP
149 return -EINVAL;
150
e82c9509
LP
151 bus->input_fd = input_fd;
152 bus->output_fd = output_fd;
021a1e78
LP
153 return 0;
154}
155
2fd9ae2e
LP
156int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
157 char *p, **a;
158
159 if (!bus)
160 return -EINVAL;
161 if (bus->state != BUS_UNSET)
162 return -EPERM;
163 if (!path)
164 return -EINVAL;
165 if (strv_isempty(argv))
166 return -EINVAL;
167
168 p = strdup(path);
169 if (!p)
170 return -ENOMEM;
171
172 a = strv_copy(argv);
173 if (!a) {
174 free(p);
175 return -ENOMEM;
176 }
177
178 free(bus->exec_path);
179 strv_free(bus->exec_argv);
180
181 bus->exec_path = p;
182 bus->exec_argv = a;
183
184 return 0;
185}
186
94bbf1ba 187int sd_bus_set_bus_client(sd_bus *bus, int b) {
021a1e78
LP
188 if (!bus)
189 return -EINVAL;
190 if (bus->state != BUS_UNSET)
191 return -EPERM;
192
94bbf1ba 193 bus->bus_client = !!b;
021a1e78
LP
194 return 0;
195}
196
197int sd_bus_set_negotiate_fds(sd_bus *bus, int b) {
198 if (!bus)
199 return -EINVAL;
200 if (bus->state != BUS_UNSET)
201 return -EPERM;
202
203 bus->negotiate_fds = !!b;
204 return 0;
205}
de1c301e 206
98178d39 207int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
2181a7f5
LP
208 if (!bus)
209 return -EINVAL;
98178d39 210 if (!b && !sd_id128_equal(server_id, SD_ID128_NULL))
2181a7f5
LP
211 return -EINVAL;
212 if (bus->state != BUS_UNSET)
213 return -EPERM;
214
215 bus->is_server = !!b;
98178d39 216 bus->server_id = server_id;
2181a7f5
LP
217 return 0;
218}
219
220int sd_bus_set_anonymous(sd_bus *bus, int b) {
221 if (!bus)
222 return -EINVAL;
223 if (bus->state != BUS_UNSET)
224 return -EPERM;
225
226 bus->anonymous_auth = !!b;
227 return 0;
228}
229
e3017af9 230static int hello_callback(sd_bus *bus, int error, sd_bus_message *reply, void *userdata) {
de1c301e
LP
231 const char *s;
232 int r;
233
234 assert(bus);
021a1e78 235 assert(bus->state == BUS_HELLO);
e3017af9
LP
236
237 if (error != 0)
238 return -error;
239
de1c301e
LP
240 assert(reply);
241
de1c301e
LP
242 r = sd_bus_message_read(reply, "s", &s);
243 if (r < 0)
244 return r;
245
dafb7591
LP
246 if (!service_name_is_valid(s) || s[0] != ':')
247 return -EBADMSG;
248
de1c301e
LP
249 bus->unique_name = strdup(s);
250 if (!bus->unique_name)
251 return -ENOMEM;
252
dafb7591
LP
253 bus->state = BUS_RUNNING;
254
de1c301e
LP
255 return 1;
256}
257
258static int bus_send_hello(sd_bus *bus) {
259 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
260 int r;
261
262 assert(bus);
263
6629161f 264 if (!bus->bus_client || bus->is_kernel)
021a1e78
LP
265 return 0;
266
de1c301e
LP
267 r = sd_bus_message_new_method_call(
268 bus,
269 "org.freedesktop.DBus",
270 "/",
271 "org.freedesktop.DBus",
272 "Hello",
273 &m);
274 if (r < 0)
275 return r;
276
9d373862 277 return sd_bus_send_with_reply(bus, m, hello_callback, NULL, 0, &bus->hello_serial);
de1c301e
LP
278}
279
a7e3212d 280int bus_start_running(sd_bus *bus) {
de1c301e
LP
281 assert(bus);
282
f08838da 283 if (bus->bus_client && !bus->is_kernel) {
de1c301e 284 bus->state = BUS_HELLO;
e3017af9 285 return 1;
de1c301e
LP
286 }
287
288 bus->state = BUS_RUNNING;
e3017af9 289 return 1;
de1c301e
LP
290}
291
292static int parse_address_key(const char **p, const char *key, char **value) {
293 size_t l, n = 0;
294 const char *a;
295 char *r = NULL;
296
297 assert(p);
298 assert(*p);
de1c301e
LP
299 assert(value);
300
2fd9ae2e
LP
301 if (key) {
302 l = strlen(key);
303 if (strncmp(*p, key, l) != 0)
304 return 0;
de1c301e 305
2fd9ae2e
LP
306 if ((*p)[l] != '=')
307 return 0;
de1c301e 308
2fd9ae2e
LP
309 if (*value)
310 return -EINVAL;
de1c301e 311
2fd9ae2e
LP
312 a = *p + l + 1;
313 } else
314 a = *p;
315
316 while (*a != ';' && *a != ',' && *a != 0) {
de1c301e
LP
317 char c, *t;
318
319 if (*a == '%') {
320 int x, y;
321
322 x = unhexchar(a[1]);
323 if (x < 0) {
324 free(r);
325 return x;
326 }
327
328 y = unhexchar(a[2]);
329 if (y < 0) {
330 free(r);
331 return y;
332 }
333
de1c301e 334 c = (char) ((x << 4) | y);
89ffcd2a
LP
335 a += 3;
336 } else {
de1c301e 337 c = *a;
89ffcd2a
LP
338 a++;
339 }
de1c301e 340
89ffcd2a 341 t = realloc(r, n + 2);
de1c301e
LP
342 if (!t) {
343 free(r);
344 return -ENOMEM;
345 }
346
347 r = t;
348 r[n++] = c;
349 }
350
89ffcd2a
LP
351 if (!r) {
352 r = strdup("");
353 if (!r)
354 return -ENOMEM;
355 } else
356 r[n] = 0;
357
358 if (*a == ',')
359 a++;
360
de1c301e 361 *p = a;
2fd9ae2e
LP
362
363 free(*value);
de1c301e 364 *value = r;
2fd9ae2e 365
de1c301e
LP
366 return 1;
367}
368
369static void skip_address_key(const char **p) {
370 assert(p);
371 assert(*p);
372
89ffcd2a
LP
373 *p += strcspn(*p, ",");
374
375 if (**p == ',')
376 (*p) ++;
de1c301e
LP
377}
378
2fd9ae2e
LP
379static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
380 _cleanup_free_ char *path = NULL, *abstract = NULL;
381 size_t l;
de1c301e
LP
382 int r;
383
384 assert(b);
2fd9ae2e
LP
385 assert(p);
386 assert(*p);
387 assert(guid);
de1c301e 388
2fd9ae2e
LP
389 while (**p != 0 && **p != ';') {
390 r = parse_address_key(p, "guid", guid);
391 if (r < 0)
392 return r;
393 else if (r > 0)
394 continue;
de1c301e 395
2fd9ae2e
LP
396 r = parse_address_key(p, "path", &path);
397 if (r < 0)
398 return r;
399 else if (r > 0)
400 continue;
de1c301e 401
2fd9ae2e
LP
402 r = parse_address_key(p, "abstract", &abstract);
403 if (r < 0)
404 return r;
405 else if (r > 0)
406 continue;
de1c301e 407
2fd9ae2e
LP
408 skip_address_key(p);
409 }
de1c301e 410
2fd9ae2e
LP
411 if (!path && !abstract)
412 return -EINVAL;
de1c301e 413
2fd9ae2e
LP
414 if (path && abstract)
415 return -EINVAL;
416
417 if (path) {
418 l = strlen(path);
419 if (l > sizeof(b->sockaddr.un.sun_path))
420 return -E2BIG;
de1c301e 421
2fd9ae2e
LP
422 b->sockaddr.un.sun_family = AF_UNIX;
423 strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path));
424 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l;
425 } else if (abstract) {
426 l = strlen(abstract);
427 if (l > sizeof(b->sockaddr.un.sun_path) - 1)
428 return -E2BIG;
429
430 b->sockaddr.un.sun_family = AF_UNIX;
431 b->sockaddr.un.sun_path[0] = 0;
432 strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1);
433 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
434 }
435
436 return 0;
437}
438
439static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
440 _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
2fd9ae2e 441 int r;
b92bea5d
ZJS
442 struct addrinfo *result, hints = {
443 .ai_socktype = SOCK_STREAM,
444 .ai_flags = AI_ADDRCONFIG,
445 };
2fd9ae2e
LP
446
447 assert(b);
448 assert(p);
449 assert(*p);
450 assert(guid);
451
452 while (**p != 0 && **p != ';') {
453 r = parse_address_key(p, "guid", guid);
454 if (r < 0)
455 return r;
456 else if (r > 0)
457 continue;
458
459 r = parse_address_key(p, "host", &host);
460 if (r < 0)
461 return r;
462 else if (r > 0)
463 continue;
464
465 r = parse_address_key(p, "port", &port);
466 if (r < 0)
467 return r;
468 else if (r > 0)
469 continue;
470
471 r = parse_address_key(p, "family", &family);
472 if (r < 0)
473 return r;
474 else if (r > 0)
475 continue;
476
477 skip_address_key(p);
478 }
479
480 if (!host || !port)
481 return -EINVAL;
482
2fd9ae2e
LP
483 if (family) {
484 if (streq(family, "ipv4"))
485 hints.ai_family = AF_INET;
486 else if (streq(family, "ipv6"))
487 hints.ai_family = AF_INET6;
488 else
489 return -EINVAL;
490 }
491
492 r = getaddrinfo(host, port, &hints, &result);
493 if (r == EAI_SYSTEM)
494 return -errno;
495 else if (r != 0)
496 return -EADDRNOTAVAIL;
497
498 memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
499 b->sockaddr_size = result->ai_addrlen;
500
501 freeaddrinfo(result);
502
503 return 0;
504}
505
506static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
507 char *path = NULL;
508 unsigned n_argv = 0, j;
509 char **argv = NULL;
510 int r;
511
512 assert(b);
513 assert(p);
514 assert(*p);
515 assert(guid);
516
517 while (**p != 0 && **p != ';') {
518 r = parse_address_key(p, "guid", guid);
519 if (r < 0)
520 goto fail;
521 else if (r > 0)
522 continue;
523
524 r = parse_address_key(p, "path", &path);
525 if (r < 0)
526 goto fail;
527 else if (r > 0)
528 continue;
529
530 if (startswith(*p, "argv")) {
531 unsigned ul;
532
533 errno = 0;
534 ul = strtoul(*p + 4, (char**) p, 10);
8333c77e 535 if (errno > 0 || **p != '=' || ul > 256) {
2fd9ae2e
LP
536 r = -EINVAL;
537 goto fail;
538 }
539
540 (*p) ++;
541
542 if (ul >= n_argv) {
543 char **x;
544
545 x = realloc(argv, sizeof(char*) * (ul + 2));
546 if (!x) {
547 r = -ENOMEM;
548 goto fail;
549 }
550
551 memset(x + n_argv, 0, sizeof(char*) * (ul - n_argv + 2));
552
553 argv = x;
554 n_argv = ul + 1;
555 }
556
557 r = parse_address_key(p, NULL, argv + ul);
de1c301e 558 if (r < 0)
2fd9ae2e 559 goto fail;
de1c301e 560
2fd9ae2e 561 continue;
de1c301e
LP
562 }
563
2fd9ae2e
LP
564 skip_address_key(p);
565 }
de1c301e 566
5a0f6033
LP
567 if (!path) {
568 r = -EINVAL;
2fd9ae2e 569 goto fail;
5a0f6033 570 }
de1c301e 571
2fd9ae2e
LP
572 /* Make sure there are no holes in the array, with the
573 * exception of argv[0] */
574 for (j = 1; j < n_argv; j++)
575 if (!argv[j]) {
576 r = -EINVAL;
577 goto fail;
578 }
579
580 if (argv && argv[0] == NULL) {
581 argv[0] = strdup(path);
582 if (!argv[0]) {
583 r = -ENOMEM;
584 goto fail;
585 }
586 }
de1c301e 587
2fd9ae2e
LP
588 b->exec_path = path;
589 b->exec_argv = argv;
590 return 0;
de1c301e 591
2fd9ae2e
LP
592fail:
593 for (j = 0; j < n_argv; j++)
594 free(argv[j]);
595
596 free(argv);
597 free(path);
598 return r;
599}
600
6629161f
LP
601static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
602 _cleanup_free_ char *path = NULL;
603 int r;
604
605 assert(b);
606 assert(p);
607 assert(*p);
608 assert(guid);
609
610 while (**p != 0 && **p != ';') {
611 r = parse_address_key(p, "guid", guid);
612 if (r < 0)
613 return r;
614 else if (r > 0)
615 continue;
616
617 r = parse_address_key(p, "path", &path);
618 if (r < 0)
619 return r;
620 else if (r > 0)
621 continue;
622
623 skip_address_key(p);
624 }
625
626 if (!path)
627 return -EINVAL;
628
629 free(b->kernel);
630 b->kernel = path;
631 path = NULL;
632
633 return 0;
634}
635
2fd9ae2e
LP
636static void bus_reset_parsed_address(sd_bus *b) {
637 assert(b);
638
639 zero(b->sockaddr);
640 b->sockaddr_size = 0;
641 strv_free(b->exec_argv);
642 free(b->exec_path);
643 b->exec_path = NULL;
644 b->exec_argv = NULL;
98178d39 645 b->server_id = SD_ID128_NULL;
6629161f
LP
646 free(b->kernel);
647 b->kernel = NULL;
2fd9ae2e
LP
648}
649
650static int bus_parse_next_address(sd_bus *b) {
651 _cleanup_free_ char *guid = NULL;
652 const char *a;
653 int r;
654
655 assert(b);
656
657 if (!b->address)
658 return 0;
659 if (b->address[b->address_index] == 0)
660 return 0;
661
662 bus_reset_parsed_address(b);
663
664 a = b->address + b->address_index;
de1c301e 665
2fd9ae2e 666 while (*a != 0) {
de1c301e 667
2fd9ae2e
LP
668 if (*a == ';') {
669 a++;
670 continue;
de1c301e
LP
671 }
672
2fd9ae2e
LP
673 if (startswith(a, "unix:")) {
674 a += 5;
de1c301e 675
2fd9ae2e 676 r = parse_unix_address(b, &a, &guid);
de1c301e
LP
677 if (r < 0)
678 return r;
2fd9ae2e 679 break;
de1c301e 680
2fd9ae2e 681 } else if (startswith(a, "tcp:")) {
de1c301e 682
2fd9ae2e
LP
683 a += 4;
684 r = parse_tcp_address(b, &a, &guid);
de1c301e
LP
685 if (r < 0)
686 return r;
de1c301e 687
2fd9ae2e
LP
688 break;
689
690 } else if (startswith(a, "unixexec:")) {
691
692 a += 9;
693 r = parse_exec_address(b, &a, &guid);
de1c301e
LP
694 if (r < 0)
695 return r;
de1c301e 696
2fd9ae2e 697 break;
de1c301e 698
6629161f
LP
699 } else if (startswith(a, "kernel:")) {
700
701 a += 7;
702 r = parse_kernel_address(b, &a, &guid);
703 if (r < 0)
704 return r;
705
706 break;
de1c301e
LP
707 }
708
2fd9ae2e
LP
709 a = strchr(a, ';');
710 if (!a)
711 return 0;
de1c301e
LP
712 }
713
714 if (guid) {
98178d39 715 r = sd_id128_from_string(guid, &b->server_id);
de1c301e
LP
716 if (r < 0)
717 return r;
718 }
719
2fd9ae2e 720 b->address_index = a - b->address;
de1c301e
LP
721 return 1;
722}
723
a7e3212d 724static int bus_start_address(sd_bus *b) {
2fd9ae2e
LP
725 int r;
726
727 assert(b);
728
729 for (;;) {
e82c9509 730 sd_bus_close(b);
2fd9ae2e
LP
731
732 if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
a7e3212d
LP
733
734 r = bus_socket_connect(b);
2fd9ae2e
LP
735 if (r >= 0)
736 return r;
737
738 b->last_connect_error = -r;
739
740 } else if (b->exec_path) {
741
a7e3212d 742 r = bus_socket_exec(b);
2fd9ae2e
LP
743 if (r >= 0)
744 return r;
745
6629161f
LP
746 b->last_connect_error = -r;
747 } else if (b->kernel) {
748
749 r = bus_kernel_connect(b);
750 if (r >= 0)
751 return r;
752
2fd9ae2e
LP
753 b->last_connect_error = -r;
754 }
755
756 r = bus_parse_next_address(b);
757 if (r < 0)
758 return r;
759 if (r == 0)
760 return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
de1c301e
LP
761 }
762}
763
a7e3212d
LP
764int bus_next_address(sd_bus *b) {
765 assert(b);
766
767 bus_reset_parsed_address(b);
768 return bus_start_address(b);
769}
770
021a1e78 771static int bus_start_fd(sd_bus *b) {
6629161f 772 struct stat st;
021a1e78
LP
773 int r;
774
775 assert(b);
e82c9509
LP
776 assert(b->input_fd >= 0);
777 assert(b->output_fd >= 0);
021a1e78 778
e82c9509 779 r = fd_nonblock(b->input_fd, true);
021a1e78
LP
780 if (r < 0)
781 return r;
782
e82c9509 783 r = fd_cloexec(b->input_fd, true);
021a1e78
LP
784 if (r < 0)
785 return r;
786
e82c9509
LP
787 if (b->input_fd != b->output_fd) {
788 r = fd_nonblock(b->output_fd, true);
789 if (r < 0)
790 return r;
791
792 r = fd_cloexec(b->output_fd, true);
793 if (r < 0)
794 return r;
795 }
796
6629161f
LP
797 if (fstat(b->input_fd, &st) < 0)
798 return -errno;
799
800 if (S_ISCHR(b->input_fd))
801 return bus_kernel_take_fd(b);
802 else
803 return bus_socket_take_fd(b);
021a1e78
LP
804}
805
806int sd_bus_start(sd_bus *bus) {
807 int r;
808
809 if (!bus)
810 return -EINVAL;
811 if (bus->state != BUS_UNSET)
812 return -EPERM;
813
814 bus->state = BUS_OPENING;
815
2181a7f5
LP
816 if (bus->is_server && bus->bus_client)
817 return -EINVAL;
818
e82c9509 819 if (bus->input_fd >= 0)
021a1e78 820 r = bus_start_fd(bus);
6629161f 821 else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel)
a7e3212d 822 r = bus_start_address(bus);
021a1e78
LP
823 else
824 return -EINVAL;
825
826 if (r < 0)
827 return r;
828
829 return bus_send_hello(bus);
830}
831
de1c301e
LP
832int sd_bus_open_system(sd_bus **ret) {
833 const char *e;
834 sd_bus *b;
835 int r;
836
837 if (!ret)
838 return -EINVAL;
839
021a1e78
LP
840 r = sd_bus_new(&b);
841 if (r < 0)
842 return r;
843
de1c301e
LP
844 e = getenv("DBUS_SYSTEM_BUS_ADDRESS");
845 if (e) {
021a1e78 846 r = sd_bus_set_address(b, e);
de1c301e 847 if (r < 0)
021a1e78 848 goto fail;
89ffcd2a 849 } else {
89ffcd2a
LP
850 b->sockaddr.un.sun_family = AF_UNIX;
851 strncpy(b->sockaddr.un.sun_path, "/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
852 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/dbus/system_bus_socket") - 1;
89ffcd2a 853 }
de1c301e 854
94bbf1ba 855 b->bus_client = true;
021a1e78
LP
856
857 r = sd_bus_start(b);
858 if (r < 0)
859 goto fail;
de1c301e
LP
860
861 *ret = b;
862 return 0;
021a1e78
LP
863
864fail:
865 bus_free(b);
866 return r;
de1c301e
LP
867}
868
869int sd_bus_open_user(sd_bus **ret) {
870 const char *e;
871 sd_bus *b;
872 size_t l;
873 int r;
874
875 if (!ret)
876 return -EINVAL;
877
021a1e78
LP
878 r = sd_bus_new(&b);
879 if (r < 0)
880 return r;
881
de1c301e
LP
882 e = getenv("DBUS_SESSION_BUS_ADDRESS");
883 if (e) {
021a1e78 884 r = sd_bus_set_address(b, e);
de1c301e 885 if (r < 0)
021a1e78 886 goto fail;
89ffcd2a
LP
887 } else {
888 e = getenv("XDG_RUNTIME_DIR");
021a1e78
LP
889 if (!e) {
890 r = -ENOENT;
891 goto fail;
892 }
de1c301e 893
89ffcd2a 894 l = strlen(e);
021a1e78
LP
895 if (l + 4 > sizeof(b->sockaddr.un.sun_path)) {
896 r = -E2BIG;
897 goto fail;
898 }
de1c301e 899
89ffcd2a
LP
900 b->sockaddr.un.sun_family = AF_UNIX;
901 memcpy(mempcpy(b->sockaddr.un.sun_path, e, l), "/bus", 4);
902 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l + 4;
de1c301e
LP
903 }
904
94bbf1ba 905 b->bus_client = true;
de1c301e 906
021a1e78 907 r = sd_bus_start(b);
2571ead1
LP
908 if (r < 0)
909 goto fail;
de1c301e
LP
910
911 *ret = b;
912 return 0;
2571ead1
LP
913
914fail:
021a1e78 915 bus_free(b);
2571ead1 916 return r;
de1c301e
LP
917}
918
919void sd_bus_close(sd_bus *bus) {
920 if (!bus)
921 return;
de1c301e 922
e82c9509
LP
923 if (bus->input_fd >= 0)
924 close_nointr_nofail(bus->input_fd);
925 if (bus->output_fd >= 0 && bus->output_fd != bus->input_fd)
926 close_nointr_nofail(bus->output_fd);
927
928 bus->input_fd = bus->output_fd = -1;
de1c301e
LP
929}
930
931sd_bus *sd_bus_ref(sd_bus *bus) {
932 if (!bus)
933 return NULL;
934
935 assert(bus->n_ref > 0);
936
937 bus->n_ref++;
938 return bus;
939}
940
941sd_bus *sd_bus_unref(sd_bus *bus) {
942 if (!bus)
943 return NULL;
944
945 assert(bus->n_ref > 0);
946 bus->n_ref--;
947
948 if (bus->n_ref <= 0)
949 bus_free(bus);
950
951 return NULL;
952}
953
e3017af9
LP
954int sd_bus_is_open(sd_bus *bus) {
955 if (!bus)
956 return -EINVAL;
957
e82c9509 958 return bus->state != BUS_UNSET && bus->input_fd >= 0;
e3017af9
LP
959}
960
d728d708
LP
961int sd_bus_can_send(sd_bus *bus, char type) {
962 int r;
963
de1c301e
LP
964 if (!bus)
965 return -EINVAL;
e82c9509 966 if (bus->output_fd < 0)
021a1e78 967 return -ENOTCONN;
de1c301e 968
d728d708 969 if (type == SD_BUS_TYPE_UNIX_FD) {
021a1e78
LP
970 if (!bus->negotiate_fds)
971 return 0;
972
20902f3e 973 r = bus_ensure_running(bus);
d728d708
LP
974 if (r < 0)
975 return r;
de1c301e 976
d728d708
LP
977 return bus->can_fds;
978 }
979
980 return bus_type_is_valid(type);
de1c301e
LP
981}
982
98178d39 983int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
d728d708 984 int r;
de1c301e
LP
985
986 if (!bus)
987 return -EINVAL;
98178d39 988 if (!server_id)
d728d708 989 return -EINVAL;
de1c301e 990
20902f3e 991 r = bus_ensure_running(bus);
d728d708
LP
992 if (r < 0)
993 return r;
de1c301e 994
98178d39 995 *server_id = bus->server_id;
d728d708 996 return 0;
de1c301e
LP
997}
998
999static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
1000 assert(m);
1001
89ffcd2a
LP
1002 if (m->header->version > b->message_version)
1003 return -EPERM;
1004
de1c301e
LP
1005 if (m->sealed)
1006 return 0;
1007
9a17484d 1008 return bus_message_seal(m, ++b->serial);
de1c301e
LP
1009}
1010
de1c301e 1011static int dispatch_wqueue(sd_bus *bus) {
e3017af9 1012 int r, ret = 0;
de1c301e
LP
1013
1014 assert(bus);
89ffcd2a 1015 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1016
e82c9509 1017 if (bus->output_fd < 0)
de1c301e
LP
1018 return -ENOTCONN;
1019
1020 while (bus->wqueue_size > 0) {
1021
6629161f
LP
1022 if (bus->is_kernel)
1023 r = bus_kernel_write_message(bus, bus->wqueue[0]);
1024 else
1025 r = bus_socket_write_message(bus, bus->wqueue[0], &bus->windex);
1026
de1c301e
LP
1027 if (r < 0) {
1028 sd_bus_close(bus);
1029 return r;
1030 } else if (r == 0)
e3017af9
LP
1031 /* Didn't do anything this time */
1032 return ret;
6629161f 1033 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
de1c301e
LP
1034 /* Fully written. Let's drop the entry from
1035 * the queue.
1036 *
1037 * This isn't particularly optimized, but
1038 * well, this is supposed to be our worst-case
1039 * buffer only, and the socket buffer is
1040 * supposed to be our primary buffer, and if
1041 * it got full, then all bets are off
1042 * anyway. */
1043
1044 sd_bus_message_unref(bus->wqueue[0]);
1045 bus->wqueue_size --;
1046 memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1047 bus->windex = 0;
1048
e3017af9 1049 ret = 1;
de1c301e
LP
1050 }
1051 }
1052
e3017af9 1053 return ret;
de1c301e
LP
1054}
1055
1056static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
2bf938c1 1057 sd_bus_message *z = NULL;
e3017af9 1058 int r, ret = 0;
de1c301e
LP
1059
1060 assert(bus);
1061 assert(m);
89ffcd2a 1062 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1063
e82c9509 1064 if (bus->input_fd < 0)
de1c301e
LP
1065 return -ENOTCONN;
1066
1067 if (bus->rqueue_size > 0) {
1068 /* Dispatch a queued message */
1069
1070 *m = bus->rqueue[0];
1071 bus->rqueue_size --;
1072 memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
1073 return 1;
1074 }
1075
1076 /* Try to read a new message */
e3017af9 1077 do {
6629161f
LP
1078 if (bus->is_kernel)
1079 r = bus_kernel_read_message(bus, &z);
1080 else
1081 r = bus_socket_read_message(bus, &z);
1082
e3017af9
LP
1083 if (r < 0) {
1084 sd_bus_close(bus);
1085 return r;
1086 }
1087 if (r == 0)
1088 return ret;
de1c301e 1089
e3017af9
LP
1090 r = 1;
1091 } while (!z);
1092
1093 *m = z;
1094 return 1;
de1c301e
LP
1095}
1096
1097int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
1098 int r;
1099
1100 if (!bus)
1101 return -EINVAL;
021a1e78
LP
1102 if (bus->state == BUS_UNSET)
1103 return -ENOTCONN;
e82c9509 1104 if (bus->output_fd < 0)
de1c301e
LP
1105 return -ENOTCONN;
1106 if (!m)
1107 return -EINVAL;
021a1e78
LP
1108
1109 if (m->n_fds > 0) {
1110 r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1111 if (r < 0)
1112 return r;
1113 if (r == 0)
1114 return -ENOTSUP;
1115 }
de1c301e 1116
29f6aadd
LP
1117 /* If the serial number isn't kept, then we know that no reply
1118 * is expected */
1119 if (!serial && !m->sealed)
1120 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1121
de1c301e
LP
1122 r = bus_seal_message(bus, m);
1123 if (r < 0)
1124 return r;
1125
5407f2de
LP
1126 /* If this is a reply and no reply was requested, then let's
1127 * suppress this, if we can */
1128 if (m->dont_send && !serial)
1129 return 0;
1130
89ffcd2a 1131 if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
de1c301e
LP
1132 size_t idx = 0;
1133
6629161f
LP
1134 if (bus->is_kernel)
1135 r = bus_kernel_write_message(bus, m);
1136 else
1137 r = bus_socket_write_message(bus, m, &idx);
1138
de1c301e
LP
1139 if (r < 0) {
1140 sd_bus_close(bus);
1141 return r;
6629161f 1142 } else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
de1c301e
LP
1143 /* Wasn't fully written. So let's remember how
1144 * much was written. Note that the first entry
1145 * of the wqueue array is always allocated so
1146 * that we always can remember how much was
1147 * written. */
1148 bus->wqueue[0] = sd_bus_message_ref(m);
1149 bus->wqueue_size = 1;
1150 bus->windex = idx;
1151 }
1152 } else {
1153 sd_bus_message **q;
1154
1155 /* Just append it to the queue. */
1156
25220239 1157 if (bus->wqueue_size >= BUS_WQUEUE_MAX)
de1c301e
LP
1158 return -ENOBUFS;
1159
1160 q = realloc(bus->wqueue, sizeof(sd_bus_message*) * (bus->wqueue_size + 1));
1161 if (!q)
1162 return -ENOMEM;
1163
1164 bus->wqueue = q;
1165 q[bus->wqueue_size ++] = sd_bus_message_ref(m);
1166 }
1167
1168 if (serial)
1169 *serial = BUS_MESSAGE_SERIAL(m);
1170
1171 return 0;
1172}
1173
1174static usec_t calc_elapse(uint64_t usec) {
1175 if (usec == (uint64_t) -1)
1176 return 0;
1177
1178 if (usec == 0)
e3017af9 1179 usec = BUS_DEFAULT_TIMEOUT;
de1c301e
LP
1180
1181 return now(CLOCK_MONOTONIC) + usec;
1182}
1183
e3017af9
LP
1184static int timeout_compare(const void *a, const void *b) {
1185 const struct reply_callback *x = a, *y = b;
1186
1187 if (x->timeout != 0 && y->timeout == 0)
1188 return -1;
1189
1190 if (x->timeout == 0 && y->timeout != 0)
1191 return 1;
1192
1193 if (x->timeout < y->timeout)
1194 return -1;
1195
1196 if (x->timeout > y->timeout)
1197 return 1;
1198
1199 return 0;
1200}
1201
de1c301e
LP
1202int sd_bus_send_with_reply(
1203 sd_bus *bus,
1204 sd_bus_message *m,
52f3ba91 1205 sd_bus_message_handler_t callback,
de1c301e
LP
1206 void *userdata,
1207 uint64_t usec,
1208 uint64_t *serial) {
1209
1210 struct reply_callback *c;
1211 int r;
1212
1213 if (!bus)
1214 return -EINVAL;
021a1e78
LP
1215 if (bus->state == BUS_UNSET)
1216 return -ENOTCONN;
e82c9509 1217 if (bus->output_fd < 0)
de1c301e
LP
1218 return -ENOTCONN;
1219 if (!m)
1220 return -EINVAL;
1221 if (!callback)
1222 return -EINVAL;
89ffcd2a 1223 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1224 return -EINVAL;
89ffcd2a
LP
1225 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1226 return -EINVAL;
1227
1228 r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
1229 if (r < 0)
1230 return r;
de1c301e 1231
e3017af9
LP
1232 if (usec != (uint64_t) -1) {
1233 r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
1234 if (r < 0)
1235 return r;
1236 }
1237
de1c301e
LP
1238 r = bus_seal_message(bus, m);
1239 if (r < 0)
1240 return r;
1241
eba8617e 1242 c = new0(struct reply_callback, 1);
de1c301e
LP
1243 if (!c)
1244 return -ENOMEM;
1245
1246 c->callback = callback;
1247 c->userdata = userdata;
1248 c->serial = BUS_MESSAGE_SERIAL(m);
1249 c->timeout = calc_elapse(usec);
1250
1251 r = hashmap_put(bus->reply_callbacks, &c->serial, c);
1252 if (r < 0) {
1253 free(c);
1254 return r;
1255 }
1256
e3017af9
LP
1257 if (c->timeout != 0) {
1258 r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1259 if (r < 0) {
1260 c->timeout = 0;
1261 sd_bus_send_with_reply_cancel(bus, c->serial);
1262 return r;
1263 }
1264 }
1265
de1c301e
LP
1266 r = sd_bus_send(bus, m, serial);
1267 if (r < 0) {
e3017af9 1268 sd_bus_send_with_reply_cancel(bus, c->serial);
de1c301e
LP
1269 return r;
1270 }
1271
1272 return r;
1273}
1274
1275int sd_bus_send_with_reply_cancel(sd_bus *bus, uint64_t serial) {
e3017af9 1276 struct reply_callback *c;
de1c301e
LP
1277
1278 if (!bus)
1279 return -EINVAL;
1280 if (serial == 0)
1281 return -EINVAL;
1282
1283 c = hashmap_remove(bus->reply_callbacks, &serial);
1284 if (!c)
1285 return 0;
1286
e3017af9
LP
1287 if (c->timeout != 0)
1288 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1289
de1c301e
LP
1290 free(c);
1291 return 1;
1292}
1293
20902f3e 1294int bus_ensure_running(sd_bus *bus) {
89ffcd2a
LP
1295 int r;
1296
1297 assert(bus);
1298
e82c9509 1299 if (bus->input_fd < 0)
021a1e78
LP
1300 return -ENOTCONN;
1301 if (bus->state == BUS_UNSET)
1302 return -ENOTCONN;
1303
d728d708
LP
1304 if (bus->state == BUS_RUNNING)
1305 return 1;
89ffcd2a
LP
1306
1307 for (;;) {
1308 r = sd_bus_process(bus, NULL);
1309 if (r < 0)
1310 return r;
d728d708
LP
1311 if (bus->state == BUS_RUNNING)
1312 return 1;
e3017af9
LP
1313 if (r > 0)
1314 continue;
89ffcd2a
LP
1315
1316 r = sd_bus_wait(bus, (uint64_t) -1);
1317 if (r < 0)
1318 return r;
1319 }
1320}
1321
de1c301e
LP
1322int sd_bus_send_with_reply_and_block(
1323 sd_bus *bus,
1324 sd_bus_message *m,
1325 uint64_t usec,
1326 sd_bus_error *error,
1327 sd_bus_message **reply) {
1328
1329 int r;
1330 usec_t timeout;
1331 uint64_t serial;
1332 bool room = false;
1333
1334 if (!bus)
1335 return -EINVAL;
e82c9509 1336 if (bus->output_fd < 0)
de1c301e 1337 return -ENOTCONN;
021a1e78
LP
1338 if (bus->state == BUS_UNSET)
1339 return -ENOTCONN;
de1c301e
LP
1340 if (!m)
1341 return -EINVAL;
89ffcd2a 1342 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
de1c301e 1343 return -EINVAL;
89ffcd2a 1344 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
de1c301e 1345 return -EINVAL;
89ffcd2a
LP
1346 if (bus_error_is_dirty(error))
1347 return -EINVAL;
1348
20902f3e 1349 r = bus_ensure_running(bus);
89ffcd2a
LP
1350 if (r < 0)
1351 return r;
de1c301e
LP
1352
1353 r = sd_bus_send(bus, m, &serial);
1354 if (r < 0)
1355 return r;
1356
1357 timeout = calc_elapse(usec);
1358
1359 for (;;) {
1360 usec_t left;
e3017af9 1361 sd_bus_message *incoming = NULL;
de1c301e
LP
1362
1363 if (!room) {
1364 sd_bus_message **q;
1365
25220239
LP
1366 if (bus->rqueue_size >= BUS_RQUEUE_MAX)
1367 return -ENOBUFS;
1368
de1c301e
LP
1369 /* Make sure there's room for queuing this
1370 * locally, before we read the message */
1371
1372 q = realloc(bus->rqueue, (bus->rqueue_size + 1) * sizeof(sd_bus_message*));
1373 if (!q)
1374 return -ENOMEM;
1375
1376 bus->rqueue = q;
1377 room = true;
1378 }
1379
6629161f
LP
1380 if (bus->is_kernel)
1381 r = bus_kernel_read_message(bus, &incoming);
1382 else
1383 r = bus_socket_read_message(bus, &incoming);
de1c301e
LP
1384 if (r < 0)
1385 return r;
e3017af9 1386 if (incoming) {
89ffcd2a 1387
de1c301e
LP
1388 if (incoming->reply_serial == serial) {
1389 /* Found a match! */
1390
1391 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_RETURN) {
b7f247e0
LP
1392
1393 if (reply)
1394 *reply = incoming;
1395 else
1396 sd_bus_message_unref(incoming);
1397
de1c301e
LP
1398 return 0;
1399 }
1400
1401 if (incoming->header->type == SD_BUS_MESSAGE_TYPE_METHOD_ERROR) {
1402 int k;
1403
1404 r = sd_bus_error_copy(error, &incoming->error);
1405 if (r < 0) {
1406 sd_bus_message_unref(incoming);
1407 return r;
1408 }
1409
1410 k = bus_error_to_errno(&incoming->error);
1411 sd_bus_message_unref(incoming);
1412 return k;
1413 }
1414
1415 sd_bus_message_unref(incoming);
1416 return -EIO;
1417 }
1418
1419 /* There's already guaranteed to be room for
1420 * this, so need to resize things here */
1421 bus->rqueue[bus->rqueue_size ++] = incoming;
1422 room = false;
1423
1424 /* Try to read more, right-away */
1425 continue;
1426 }
e3017af9
LP
1427 if (r != 0)
1428 continue;
de1c301e
LP
1429
1430 if (timeout > 0) {
1431 usec_t n;
1432
1433 n = now(CLOCK_MONOTONIC);
1434 if (n >= timeout)
1435 return -ETIMEDOUT;
1436
1437 left = timeout - n;
1438 } else
1439 left = (uint64_t) -1;
1440
e3017af9 1441 r = bus_poll(bus, true, left);
de1c301e
LP
1442 if (r < 0)
1443 return r;
1444
1445 r = dispatch_wqueue(bus);
1446 if (r < 0)
1447 return r;
1448 }
1449}
1450
1451int sd_bus_get_fd(sd_bus *bus) {
1452 if (!bus)
1453 return -EINVAL;
e82c9509 1454 if (bus->input_fd < 0)
89ffcd2a 1455 return -ENOTCONN;
e82c9509
LP
1456 if (bus->input_fd != bus->output_fd)
1457 return -EPERM;
de1c301e 1458
e82c9509 1459 return bus->input_fd;
de1c301e
LP
1460}
1461
1462int sd_bus_get_events(sd_bus *bus) {
1463 int flags = 0;
1464
1465 if (!bus)
1466 return -EINVAL;
021a1e78
LP
1467 if (bus->state == BUS_UNSET)
1468 return -ENOTCONN;
e82c9509 1469 if (bus->input_fd < 0)
89ffcd2a 1470 return -ENOTCONN;
de1c301e
LP
1471
1472 if (bus->state == BUS_OPENING)
1473 flags |= POLLOUT;
89ffcd2a
LP
1474 else if (bus->state == BUS_AUTHENTICATING) {
1475
2181a7f5 1476 if (bus_socket_auth_needs_write(bus))
89ffcd2a
LP
1477 flags |= POLLOUT;
1478
1479 flags |= POLLIN;
1480
1481 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
de1c301e
LP
1482 if (bus->rqueue_size <= 0)
1483 flags |= POLLIN;
1484 if (bus->wqueue_size > 0)
1485 flags |= POLLOUT;
1486 }
1487
1488 return flags;
1489}
1490
e3017af9
LP
1491int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
1492 struct reply_callback *c;
1493
1494 if (!bus)
1495 return -EINVAL;
1496 if (!timeout_usec)
1497 return -EINVAL;
021a1e78
LP
1498 if (bus->state == BUS_UNSET)
1499 return -ENOTCONN;
e82c9509 1500 if (bus->input_fd < 0)
e3017af9
LP
1501 return -ENOTCONN;
1502
1503 if (bus->state == BUS_AUTHENTICATING) {
1504 *timeout_usec = bus->auth_timeout;
1505 return 1;
1506 }
1507
adee69fa
LP
1508 if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) {
1509 *timeout_usec = (uint64_t) -1;
e3017af9 1510 return 0;
adee69fa 1511 }
e3017af9
LP
1512
1513 c = prioq_peek(bus->reply_callbacks_prioq);
adee69fa
LP
1514 if (!c) {
1515 *timeout_usec = (uint64_t) -1;
e3017af9 1516 return 0;
adee69fa 1517 }
e3017af9
LP
1518
1519 *timeout_usec = c->timeout;
1520 return 1;
1521}
1522
1523static int process_timeout(sd_bus *bus) {
e3017af9
LP
1524 struct reply_callback *c;
1525 usec_t n;
1526 int r;
1527
1528 assert(bus);
1529
1530 c = prioq_peek(bus->reply_callbacks_prioq);
1531 if (!c)
1532 return 0;
1533
1534 n = now(CLOCK_MONOTONIC);
1535 if (c->timeout > n)
1536 return 0;
1537
1538 assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
1539 hashmap_remove(bus->reply_callbacks, &c->serial);
1540
1541 r = c->callback(bus, ETIMEDOUT, NULL, c->userdata);
1542 free(c);
1543
1544 return r < 0 ? r : 1;
1545}
1546
9d373862
LP
1547static int process_hello(sd_bus *bus, sd_bus_message *m) {
1548 assert(bus);
1549 assert(m);
1550
1551 if (bus->state != BUS_HELLO)
1552 return 0;
1553
1554 /* Let's make sure the first message on the bus is the HELLO
1555 * reply. But note that we don't actually parse the message
2181a7f5
LP
1556 * here (we leave that to the usual handling), we just verify
1557 * we don't let any earlier msg through. */
9d373862
LP
1558
1559 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1560 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1561 return -EIO;
1562
1563 if (m->reply_serial != bus->hello_serial)
1564 return -EIO;
1565
1566 return 0;
1567}
1568
a652755d
LP
1569static int process_reply(sd_bus *bus, sd_bus_message *m) {
1570 struct reply_callback *c;
1571 int r;
1572
1573 assert(bus);
1574 assert(m);
1575
1576 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_RETURN &&
1577 m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_ERROR)
1578 return 0;
1579
1580 c = hashmap_remove(bus->reply_callbacks, &m->reply_serial);
1581 if (!c)
1582 return 0;
1583
1584 if (c->timeout != 0)
1585 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1586
1587 r = c->callback(bus, 0, m, c->userdata);
1588 free(c);
1589
1590 return r;
1591}
1592
1593static int process_filter(sd_bus *bus, sd_bus_message *m) {
1594 struct filter_callback *l;
1595 int r;
1596
392d5b37
LP
1597 assert(bus);
1598 assert(m);
1599
7286037f
LP
1600 do {
1601 bus->filter_callbacks_modified = false;
1602
1603 LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
1604
1605 if (bus->filter_callbacks_modified)
1606 break;
1607
1608 /* Don't run this more than once per iteration */
1609 if (l->last_iteration == bus->iteration_counter)
1610 continue;
1611
1612 l->last_iteration = bus->iteration_counter;
1613
1614 r = l->callback(bus, 0, m, l->userdata);
1615 if (r != 0)
1616 return r;
1617
1618 }
1619
1620 } while (bus->filter_callbacks_modified);
a652755d
LP
1621
1622 return 0;
1623}
1624
392d5b37 1625static int process_match(sd_bus *bus, sd_bus_message *m) {
7286037f
LP
1626 int r;
1627
392d5b37
LP
1628 assert(bus);
1629 assert(m);
1630
7286037f
LP
1631 do {
1632 bus->match_callbacks_modified = false;
1633
1634 r = bus_match_run(bus, &bus->match_callbacks, 0, m);
1635 if (r != 0)
1636 return r;
1637
1638 } while (bus->match_callbacks_modified);
1639
1640 return 0;
392d5b37
LP
1641}
1642
b9bf7e2b
LP
1643static int process_builtin(sd_bus *bus, sd_bus_message *m) {
1644 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1645 int r;
1646
1647 assert(bus);
1648 assert(m);
1649
1650 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1651 return 0;
1652
1653 if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
1654 return 0;
1655
1656 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1657 return 1;
1658
1659 if (streq_ptr(m->member, "Ping"))
1660 r = sd_bus_message_new_method_return(bus, m, &reply);
1661 else if (streq_ptr(m->member, "GetMachineId")) {
1662 sd_id128_t id;
1663 char sid[33];
1664
1665 r = sd_id128_get_machine(&id);
1666 if (r < 0)
1667 return r;
1668
1669 r = sd_bus_message_new_method_return(bus, m, &reply);
1670 if (r < 0)
1671 return r;
1672
1673 r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
1674 } else {
c784c5ce 1675 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
b9bf7e2b
LP
1676
1677 sd_bus_error_set(&error,
1678 "org.freedesktop.DBus.Error.UnknownMethod",
1679 "Unknown method '%s' on interface '%s'.", m->member, m->interface);
1680
1681 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1682 }
1683
1684 if (r < 0)
1685 return r;
1686
1687 r = sd_bus_send(bus, reply, NULL);
1688 if (r < 0)
1689 return r;
1690
1691 return 1;
1692}
1693
a652755d 1694static int process_object(sd_bus *bus, sd_bus_message *m) {
c784c5ce 1695 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
a652755d
LP
1696 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1697 struct object_callback *c;
e3017af9 1698 int r;
a652755d 1699 bool found = false;
7286037f 1700 size_t pl;
e3017af9
LP
1701
1702 assert(bus);
1703 assert(m);
1704
a652755d
LP
1705 if (m->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
1706 return 0;
e3017af9 1707
a652755d
LP
1708 if (hashmap_isempty(bus->object_callbacks))
1709 return 0;
e3017af9 1710
7286037f 1711 pl = strlen(m->path);
a652755d 1712
7286037f
LP
1713 do {
1714 char p[pl+1];
e3017af9 1715
7286037f 1716 bus->object_callbacks_modified = false;
a652755d 1717
7286037f
LP
1718 c = hashmap_get(bus->object_callbacks, m->path);
1719 if (c && c->last_iteration != bus->iteration_counter) {
a652755d 1720
7286037f 1721 c->last_iteration = bus->iteration_counter;
a652755d 1722
a652755d 1723 r = c->callback(bus, 0, m, c->userdata);
e3017af9
LP
1724 if (r != 0)
1725 return r;
a652755d
LP
1726
1727 found = true;
e3017af9 1728 }
7286037f
LP
1729
1730 /* Look for fallback prefixes */
1731 strcpy(p, m->path);
1732 for (;;) {
1733 char *e;
1734
1735 if (bus->object_callbacks_modified)
1736 break;
1737
1738 e = strrchr(p, '/');
1739 if (e == p || !e)
1740 break;
1741
1742 *e = 0;
1743
1744 c = hashmap_get(bus->object_callbacks, p);
1745 if (c && c->last_iteration != bus->iteration_counter && c->is_fallback) {
1746
1747 c->last_iteration = bus->iteration_counter;
1748
1749 r = c->callback(bus, 0, m, c->userdata);
1750 if (r != 0)
1751 return r;
1752
1753 found = true;
1754 }
1755 }
1756
1757 } while (bus->object_callbacks_modified);
e3017af9 1758
0a72c2bd
LP
1759 /* We found some handlers but none wanted to take this, then
1760 * return this -- with one exception, we can handle
1761 * introspection minimally ourselves */
1762 if (!found || sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
a652755d
LP
1763 return 0;
1764
1765 sd_bus_error_set(&error,
1766 "org.freedesktop.DBus.Error.UnknownMethod",
1767 "Unknown method '%s' or interface '%s'.", m->member, m->interface);
1768
1769 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1770 if (r < 0)
1771 return r;
1772
1773 r = sd_bus_send(bus, reply, NULL);
1774 if (r < 0)
1775 return r;
e3017af9 1776
a652755d
LP
1777 return 1;
1778}
1779
0a72c2bd
LP
1780static int process_introspect(sd_bus *bus, sd_bus_message *m) {
1781 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1782 _cleanup_free_ char *introspection = NULL;
1783 _cleanup_set_free_free_ Set *s = NULL;
1784 _cleanup_fclose_ FILE *f = NULL;
1785 struct object_callback *c;
1786 Iterator i;
1787 size_t size = 0;
1788 char *node;
1789 int r;
1790
1791 assert(bus);
1792 assert(m);
1793
1794 if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect"))
1795 return 0;
1796
1797 if (!m->path)
1798 return 0;
1799
1800 s = set_new(string_hash_func, string_compare_func);
1801 if (!s)
1802 return -ENOMEM;
1803
1804 HASHMAP_FOREACH(c, bus->object_callbacks, i) {
1805 const char *e;
1806 char *a, *p;
1807
1808 if (streq(c->path, "/"))
1809 continue;
1810
1811 if (streq(m->path, "/"))
1812 e = c->path;
1813 else {
1814 e = startswith(c->path, m->path);
1815 if (!e || *e != '/')
1816 continue;
1817 }
1818
1819 a = strdup(e+1);
1820 if (!a)
1821 return -ENOMEM;
1822
1823 p = strchr(a, '/');
1824 if (p)
1825 *p = 0;
1826
1827 r = set_put(s, a);
1828 if (r < 0) {
1829 free(a);
1830
1831 if (r != -EEXIST)
1832 return r;
1833 }
1834 }
1835
1836 f = open_memstream(&introspection, &size);
1837 if (!f)
1838 return -ENOMEM;
1839
1840 fputs(SD_BUS_INTROSPECT_DOCTYPE, f);
1841 fputs("<node>\n", f);
1842 fputs(SD_BUS_INTROSPECT_INTERFACE_PEER, f);
1843 fputs(SD_BUS_INTROSPECT_INTERFACE_INTROSPECTABLE, f);
1844
1845 while ((node = set_steal_first(s))) {
1846 fprintf(f, " <node name=\"%s\"/>\n", node);
1847 free(node);
1848 }
1849
1850 fputs("</node>\n", f);
1851
1852 fflush(f);
1853
1854 if (ferror(f))
1855 return -ENOMEM;
1856
1857 r = sd_bus_message_new_method_return(bus, m, &reply);
1858 if (r < 0)
1859 return r;
1860
1861 r = sd_bus_message_append(reply, "s", introspection);
1862 if (r < 0)
1863 return r;
1864
1865 r = sd_bus_send(bus, reply, NULL);
1866 if (r < 0)
1867 return r;
1868
1869 return 1;
1870}
1871
a652755d
LP
1872static int process_message(sd_bus *bus, sd_bus_message *m) {
1873 int r;
1874
1875 assert(bus);
1876 assert(m);
1877
7286037f
LP
1878 bus->iteration_counter++;
1879
9d373862
LP
1880 r = process_hello(bus, m);
1881 if (r != 0)
1882 return r;
1883
a652755d
LP
1884 r = process_reply(bus, m);
1885 if (r != 0)
1886 return r;
1887
1888 r = process_filter(bus, m);
1889 if (r != 0)
1890 return r;
1891
392d5b37
LP
1892 r = process_match(bus, m);
1893 if (r != 0)
1894 return r;
1895
a652755d
LP
1896 r = process_builtin(bus, m);
1897 if (r != 0)
1898 return r;
1899
0a72c2bd
LP
1900 r = process_object(bus, m);
1901 if (r != 0)
1902 return r;
1903
1904 return process_introspect(bus, m);
e3017af9
LP
1905}
1906
a7e3212d
LP
1907static int process_running(sd_bus *bus, sd_bus_message **ret) {
1908 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
de1c301e
LP
1909 int r;
1910
a7e3212d
LP
1911 assert(bus);
1912 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1913
a7e3212d
LP
1914 r = process_timeout(bus);
1915 if (r != 0)
1916 goto null_message;
de1c301e 1917
a7e3212d
LP
1918 r = dispatch_wqueue(bus);
1919 if (r != 0)
1920 goto null_message;
de1c301e 1921
a7e3212d
LP
1922 r = dispatch_rqueue(bus, &m);
1923 if (r < 0)
1924 return r;
1925 if (!m)
1926 goto null_message;
de1c301e 1927
a7e3212d
LP
1928 r = process_message(bus, m);
1929 if (r != 0)
1930 goto null_message;
de1c301e 1931
a7e3212d
LP
1932 if (ret) {
1933 *ret = m;
1934 m = NULL;
1935 return 1;
1936 }
de1c301e 1937
a7e3212d
LP
1938 if (m->header->type == SD_BUS_MESSAGE_TYPE_METHOD_CALL) {
1939 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
c784c5ce 1940 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
de1c301e 1941
a7e3212d 1942 sd_bus_error_set(&error, "org.freedesktop.DBus.Error.UnknownObject", "Unknown object '%s'.", m->path);
de1c301e 1943
a7e3212d
LP
1944 r = sd_bus_message_new_method_error(bus, m, &error, &reply);
1945 if (r < 0)
1946 return r;
de1c301e 1947
a7e3212d
LP
1948 r = sd_bus_send(bus, reply, NULL);
1949 if (r < 0)
1950 return r;
1951 }
e3017af9 1952
a7e3212d 1953 return 1;
de1c301e 1954
a7e3212d
LP
1955null_message:
1956 if (r >= 0 && ret)
1957 *ret = NULL;
de1c301e 1958
a7e3212d
LP
1959 return r;
1960}
e3017af9 1961
a7e3212d
LP
1962int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
1963 int r;
de1c301e 1964
a7e3212d
LP
1965 /* Returns 0 when we didn't do anything. This should cause the
1966 * caller to invoke sd_bus_wait() before returning the next
1967 * time. Returns > 0 when we did something, which possibly
1968 * means *ret is filled in with an unprocessed message. */
de1c301e 1969
a7e3212d
LP
1970 if (!bus)
1971 return -EINVAL;
e82c9509 1972 if (bus->input_fd < 0)
a7e3212d 1973 return -ENOTCONN;
de1c301e 1974
6807947e
LP
1975 /* We don't allow recursively invoking sd_bus_process(). */
1976 if (bus->processing)
1977 return -EBUSY;
1978
a7e3212d 1979 switch (bus->state) {
de1c301e 1980
a7e3212d
LP
1981 case BUS_UNSET:
1982 return -ENOTCONN;
de1c301e 1983
a7e3212d
LP
1984 case BUS_OPENING:
1985 r = bus_socket_process_opening(bus);
1986 if (r < 0)
1987 return r;
1988 if (ret)
1989 *ret = NULL;
1990 return r;
b9bf7e2b 1991
a7e3212d 1992 case BUS_AUTHENTICATING:
89ffcd2a 1993
a7e3212d
LP
1994 r = bus_socket_process_authenticating(bus);
1995 if (r < 0)
1996 return r;
1997 if (ret)
1998 *ret = NULL;
1999 return r;
89ffcd2a 2000
a7e3212d
LP
2001 case BUS_RUNNING:
2002 case BUS_HELLO:
89ffcd2a 2003
6807947e
LP
2004 bus->processing = true;
2005 r = process_running(bus, ret);
2006 bus->processing = false;
2007
2008 return r;
de1c301e
LP
2009 }
2010
89ffcd2a 2011 assert_not_reached("Unknown state");
de1c301e
LP
2012}
2013
e3017af9 2014static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
b92bea5d 2015 struct pollfd p[2] = {};
e82c9509 2016 int r, e, n;
de1c301e 2017 struct timespec ts;
e3017af9
LP
2018 usec_t until, m;
2019
2020 assert(bus);
de1c301e 2021
e82c9509 2022 if (bus->input_fd < 0)
89ffcd2a
LP
2023 return -ENOTCONN;
2024
de1c301e
LP
2025 e = sd_bus_get_events(bus);
2026 if (e < 0)
2027 return e;
2028
e3017af9
LP
2029 if (need_more)
2030 e |= POLLIN;
2031
2032 r = sd_bus_get_timeout(bus, &until);
2033 if (r < 0)
2034 return r;
2035 if (r == 0)
2036 m = (uint64_t) -1;
2037 else {
e82c9509
LP
2038 usec_t nw;
2039 nw = now(CLOCK_MONOTONIC);
2040 m = until > nw ? until - nw : 0;
e3017af9
LP
2041 }
2042
2043 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
2044 m = timeout_usec;
2045
e82c9509 2046 p[0].fd = bus->input_fd;
e82c9509
LP
2047 if (bus->output_fd == bus->input_fd) {
2048 p[0].events = e;
2049 n = 1;
2050 } else {
2051 p[0].events = e & POLLIN;
2052 p[1].fd = bus->output_fd;
2053 p[1].events = e & POLLOUT;
2054 n = 2;
2055 }
de1c301e 2056
e82c9509 2057 r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
de1c301e 2058 if (r < 0)
89ffcd2a 2059 return -errno;
de1c301e 2060
e3017af9
LP
2061 return r > 0 ? 1 : 0;
2062}
2063
2064int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
2065
2066 if (!bus)
2067 return -EINVAL;
021a1e78
LP
2068 if (bus->state == BUS_UNSET)
2069 return -ENOTCONN;
e82c9509 2070 if (bus->input_fd < 0)
e3017af9
LP
2071 return -ENOTCONN;
2072 if (bus->rqueue_size > 0)
2073 return 0;
2074
2075 return bus_poll(bus, false, timeout_usec);
de1c301e
LP
2076}
2077
2078int sd_bus_flush(sd_bus *bus) {
2079 int r;
2080
2081 if (!bus)
2082 return -EINVAL;
021a1e78
LP
2083 if (bus->state == BUS_UNSET)
2084 return -ENOTCONN;
e82c9509 2085 if (bus->output_fd < 0)
de1c301e
LP
2086 return -ENOTCONN;
2087
20902f3e 2088 r = bus_ensure_running(bus);
89ffcd2a
LP
2089 if (r < 0)
2090 return r;
2091
2092 if (bus->wqueue_size <= 0)
de1c301e
LP
2093 return 0;
2094
2095 for (;;) {
2096 r = dispatch_wqueue(bus);
2097 if (r < 0)
2098 return r;
2099
89ffcd2a 2100 if (bus->wqueue_size <= 0)
de1c301e
LP
2101 return 0;
2102
e3017af9 2103 r = bus_poll(bus, false, (uint64_t) -1);
de1c301e
LP
2104 if (r < 0)
2105 return r;
2106 }
2107}
2108
52f3ba91 2109int sd_bus_add_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
de1c301e
LP
2110 struct filter_callback *f;
2111
2112 if (!bus)
2113 return -EINVAL;
2114 if (!callback)
2115 return -EINVAL;
2116
eba8617e 2117 f = new0(struct filter_callback, 1);
de1c301e
LP
2118 if (!f)
2119 return -ENOMEM;
2120 f->callback = callback;
2121 f->userdata = userdata;
2122
7286037f 2123 bus->filter_callbacks_modified = true;
de1c301e
LP
2124 LIST_PREPEND(struct filter_callback, callbacks, bus->filter_callbacks, f);
2125 return 0;
2126}
2127
52f3ba91 2128int sd_bus_remove_filter(sd_bus *bus, sd_bus_message_handler_t callback, void *userdata) {
de1c301e
LP
2129 struct filter_callback *f;
2130
2131 if (!bus)
2132 return -EINVAL;
2133 if (!callback)
2134 return -EINVAL;
2135
2136 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
2137 if (f->callback == callback && f->userdata == userdata) {
7286037f 2138 bus->filter_callbacks_modified = true;
de1c301e
LP
2139 LIST_REMOVE(struct filter_callback, callbacks, bus->filter_callbacks, f);
2140 free(f);
2141 return 1;
2142 }
2143 }
2144
2145 return 0;
2146}
a652755d
LP
2147
2148static int bus_add_object(
2149 sd_bus *bus,
2150 bool fallback,
2151 const char *path,
52f3ba91 2152 sd_bus_message_handler_t callback,
a652755d
LP
2153 void *userdata) {
2154
2155 struct object_callback *c;
2156 int r;
2157
2158 if (!bus)
2159 return -EINVAL;
2160 if (!path)
2161 return -EINVAL;
2162 if (!callback)
2163 return -EINVAL;
2164
2165 r = hashmap_ensure_allocated(&bus->object_callbacks, string_hash_func, string_compare_func);
2166 if (r < 0)
2167 return r;
2168
eba8617e 2169 c = new0(struct object_callback, 1);
a652755d
LP
2170 if (!c)
2171 return -ENOMEM;
2172
2173 c->path = strdup(path);
531991b6 2174 if (!c->path) {
a652755d
LP
2175 free(c);
2176 return -ENOMEM;
2177 }
2178
2179 c->callback = callback;
2180 c->userdata = userdata;
2181 c->is_fallback = fallback;
2182
7286037f 2183 bus->object_callbacks_modified = true;
a652755d
LP
2184 r = hashmap_put(bus->object_callbacks, c->path, c);
2185 if (r < 0) {
2186 free(c->path);
2187 free(c);
2188 return r;
2189 }
2190
2191 return 0;
2192}
2193
2194static int bus_remove_object(
2195 sd_bus *bus,
2196 bool fallback,
2197 const char *path,
52f3ba91 2198 sd_bus_message_handler_t callback,
a652755d
LP
2199 void *userdata) {
2200
2201 struct object_callback *c;
2202
2203 if (!bus)
2204 return -EINVAL;
2205 if (!path)
2206 return -EINVAL;
2207 if (!callback)
2208 return -EINVAL;
2209
2210 c = hashmap_get(bus->object_callbacks, path);
2211 if (!c)
2212 return 0;
2213
2214 if (c->callback != callback || c->userdata != userdata || c->is_fallback != fallback)
2215 return 0;
2216
7286037f 2217 bus->object_callbacks_modified = true;
a652755d
LP
2218 assert_se(c == hashmap_remove(bus->object_callbacks, c->path));
2219
2220 free(c->path);
2221 free(c);
2222
2223 return 1;
2224}
2225
52f3ba91 2226int sd_bus_add_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2227 return bus_add_object(bus, false, path, callback, userdata);
2228}
2229
52f3ba91 2230int sd_bus_remove_object(sd_bus *bus, const char *path, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2231 return bus_remove_object(bus, false, path, callback, userdata);
2232}
2233
52f3ba91 2234int sd_bus_add_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2235 return bus_add_object(bus, true, prefix, callback, userdata);
2236}
2237
52f3ba91 2238int sd_bus_remove_fallback(sd_bus *bus, const char *prefix, sd_bus_message_handler_t callback, void *userdata) {
a652755d
LP
2239 return bus_remove_object(bus, true, prefix, callback, userdata);
2240}
392d5b37 2241
52f3ba91 2242int sd_bus_add_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
392d5b37
LP
2243 int r = 0;
2244
2245 if (!bus)
2246 return -EINVAL;
2247 if (!match)
2248 return -EINVAL;
2249
2250 if (bus->bus_client) {
2251 r = bus_add_match_internal(bus, match);
2252 if (r < 0)
2253 return r;
2254 }
2255
2256 if (callback) {
7286037f 2257 bus->match_callbacks_modified = true;
392d5b37
LP
2258 r = bus_match_add(&bus->match_callbacks, match, callback, userdata, NULL);
2259 if (r < 0) {
2260
2261 if (bus->bus_client)
2262 bus_remove_match_internal(bus, match);
2263 }
2264 }
2265
2266 return r;
2267}
2268
52f3ba91 2269int sd_bus_remove_match(sd_bus *bus, const char *match, sd_bus_message_handler_t callback, void *userdata) {
392d5b37
LP
2270 int r = 0, q = 0;
2271
2272 if (!bus)
2273 return -EINVAL;
2274 if (!match)
2275 return -EINVAL;
2276
2277 if (bus->bus_client)
2278 r = bus_remove_match_internal(bus, match);
2279
7286037f
LP
2280 if (callback) {
2281 bus->match_callbacks_modified = true;
392d5b37 2282 q = bus_match_remove(&bus->match_callbacks, match, callback, userdata);
7286037f 2283 }
392d5b37
LP
2284
2285 if (r < 0)
2286 return r;
2287 return q;
2288}
917b5dc7
LP
2289
2290int sd_bus_emit_signal(
2291 sd_bus *bus,
2292 const char *path,
2293 const char *interface,
2294 const char *member,
2295 const char *types, ...) {
2296
2297 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2298 va_list ap;
2299 int r;
2300
2301 if (!bus)
2302 return -EINVAL;
2303
2304 r = sd_bus_message_new_signal(bus, path, interface, member, &m);
2305 if (r < 0)
2306 return r;
2307
2308 va_start(ap, types);
2309 r = bus_message_append_ap(m, types, ap);
2310 va_end(ap);
2311 if (r < 0)
2312 return r;
2313
2314 return sd_bus_send(bus, m, NULL);
2315}
2316
2317int sd_bus_call_method(
2318 sd_bus *bus,
2319 const char *destination,
2320 const char *path,
2321 const char *interface,
2322 const char *member,
2323 sd_bus_error *error,
2324 sd_bus_message **reply,
2325 const char *types, ...) {
2326
2327 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2328 va_list ap;
2329 int r;
2330
2331 if (!bus)
2332 return -EINVAL;
2333
2334 r = sd_bus_message_new_method_call(bus, destination, path, interface, member, &m);
2335 if (r < 0)
2336 return r;
2337
2338 va_start(ap, types);
2339 r = bus_message_append_ap(m, types, ap);
2340 va_end(ap);
2341 if (r < 0)
2342 return r;
2343
2344 return sd_bus_send_with_reply_and_block(bus, m, 0, error, reply);
2345}
f10dda3b
LP
2346
2347int sd_bus_reply_method_return(
2348 sd_bus *bus,
2349 sd_bus_message *call,
2350 const char *types, ...) {
2351
2352 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2353 va_list ap;
2354 int r;
2355
2356 if (!bus)
2357 return -EINVAL;
2358 if (!call)
2359 return -EINVAL;
2360 if (!call->sealed)
2361 return -EPERM;
2362 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2363 return -EINVAL;
2364
2365 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
2366 return 0;
2367
2368 r = sd_bus_message_new_method_return(bus, call, &m);
2369 if (r < 0)
2370 return r;
2371
2372 va_start(ap, types);
2373 r = bus_message_append_ap(m, types, ap);
2374 va_end(ap);
2375 if (r < 0)
2376 return r;
2377
2378 return sd_bus_send(bus, m, NULL);
2379}
2380
2381int sd_bus_reply_method_error(
2382 sd_bus *bus,
2383 sd_bus_message *call,
2384 const sd_bus_error *e) {
2385
2386 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2387 int r;
2388
2389 if (!bus)
2390 return -EINVAL;
2391 if (!call)
2392 return -EINVAL;
2393 if (!call->sealed)
2394 return -EPERM;
2395 if (call->header->type != SD_BUS_MESSAGE_TYPE_METHOD_CALL)
2396 return -EINVAL;
2397 if (!sd_bus_error_is_set(e))
2398 return -EINVAL;
2399
2400 if (call->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
2401 return 0;
2402
2403 r = sd_bus_message_new_method_error(bus, call, e, &m);
2404 if (r < 0)
2405 return r;
2406
2407 return sd_bus_send(bus, m, NULL);
2408}