]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/sd-bus.c
man: simplify socket-proxyd examples
[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>
63edf05e 29#include <sys/mman.h>
45fbe937 30#include <pthread.h>
de1c301e
LP
31
32#include "util.h"
33#include "macro.h"
2fd9ae2e 34#include "strv.h"
0a72c2bd 35#include "set.h"
6c03089c 36#include "missing.h"
de1c301e
LP
37
38#include "sd-bus.h"
39#include "bus-internal.h"
40#include "bus-message.h"
41#include "bus-type.h"
a7e3212d 42#include "bus-socket.h"
6629161f 43#include "bus-kernel.h"
392d5b37 44#include "bus-control.h"
29ddb38f
LP
45#include "bus-introspect.h"
46#include "bus-signature.h"
992c052c 47#include "bus-objects.h"
40ca29a1 48#include "bus-util.h"
a7893c6b 49#include "bus-container.h"
de1c301e 50
e3017af9
LP
51static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec);
52
f54514f3
LP
53static void bus_close_fds(sd_bus *b) {
54 assert(b);
55
56 if (b->input_fd >= 0)
57 close_nointr_nofail(b->input_fd);
58
59 if (b->output_fd >= 0 && b->output_fd != b->input_fd)
60 close_nointr_nofail(b->output_fd);
61
62 b->input_fd = b->output_fd = -1;
63}
64
29ddb38f
LP
65static void bus_node_destroy(sd_bus *b, struct node *n) {
66 struct node_callback *c;
67 struct node_vtable *v;
68 struct node_enumerator *e;
69
70 assert(b);
71
72 if (!n)
73 return;
74
75 while (n->child)
76 bus_node_destroy(b, n->child);
77
78 while ((c = n->callbacks)) {
71fda00f 79 LIST_REMOVE(callbacks, n->callbacks, c);
29ddb38f
LP
80 free(c);
81 }
82
83 while ((v = n->vtables)) {
71fda00f 84 LIST_REMOVE(vtables, n->vtables, v);
29ddb38f
LP
85 free(v->interface);
86 free(v);
87 }
88
89 while ((e = n->enumerators)) {
71fda00f 90 LIST_REMOVE(enumerators, n->enumerators, e);
29ddb38f
LP
91 free(e);
92 }
93
94 if (n->parent)
71fda00f 95 LIST_REMOVE(siblings, n->parent->child, n);
29ddb38f
LP
96
97 assert_se(hashmap_remove(b->nodes, n->path) == n);
98 free(n->path);
99 free(n);
100}
101
de1c301e
LP
102static void bus_free(sd_bus *b) {
103 struct filter_callback *f;
29ddb38f 104 struct node *n;
89ffcd2a 105 unsigned i;
de1c301e
LP
106
107 assert(b);
108
40ca29a1
LP
109 sd_bus_detach_event(b);
110
f54514f3 111 bus_close_fds(b);
de1c301e 112
63edf05e
LP
113 if (b->kdbus_buffer)
114 munmap(b->kdbus_buffer, KDBUS_POOL_SIZE);
115
de1c301e 116 free(b->rbuffer);
89ffcd2a 117 free(b->unique_name);
2181a7f5 118 free(b->auth_buffer);
89ffcd2a 119 free(b->address);
e9a967f9 120 free(b->kernel);
a7893c6b 121 free(b->machine);
89ffcd2a 122
2fd9ae2e
LP
123 free(b->exec_path);
124 strv_free(b->exec_argv);
125
2c93b4ef
LP
126 close_many(b->fds, b->n_fds);
127 free(b->fds);
128
89ffcd2a
LP
129 for (i = 0; i < b->rqueue_size; i++)
130 sd_bus_message_unref(b->rqueue[i]);
de1c301e 131 free(b->rqueue);
89ffcd2a
LP
132
133 for (i = 0; i < b->wqueue_size; i++)
134 sd_bus_message_unref(b->wqueue[i]);
de1c301e 135 free(b->wqueue);
de1c301e
LP
136
137 hashmap_free_free(b->reply_callbacks);
e3017af9 138 prioq_free(b->reply_callbacks_prioq);
de1c301e
LP
139
140 while ((f = b->filter_callbacks)) {
71fda00f 141 LIST_REMOVE(callbacks, b->filter_callbacks, f);
de1c301e
LP
142 free(f);
143 }
144
392d5b37
LP
145 bus_match_free(&b->match_callbacks);
146
29ddb38f
LP
147 hashmap_free_free(b->vtable_methods);
148 hashmap_free_free(b->vtable_properties);
149
150 while ((n = hashmap_first(b->nodes)))
151 bus_node_destroy(b, n);
152
153 hashmap_free(b->nodes);
154
bc7fd8cd
LP
155 bus_kernel_flush_memfd(b);
156
45fbe937
LP
157 assert_se(pthread_mutex_destroy(&b->memfd_cache_mutex) == 0);
158
de1c301e
LP
159 free(b);
160}
161
d9f644e2 162_public_ int sd_bus_new(sd_bus **ret) {
de1c301e
LP
163 sd_bus *r;
164
d6888822 165 assert_return(ret, -EINVAL);
021a1e78 166
de1c301e
LP
167 r = new0(sd_bus, 1);
168 if (!r)
021a1e78 169 return -ENOMEM;
de1c301e 170
e4ee6e5c 171 r->n_ref = REFCNT_INIT;
e82c9509 172 r->input_fd = r->output_fd = -1;
de1c301e 173 r->message_version = 1;
264ad849 174 r->hello_flags |= KDBUS_HELLO_ACCEPT_FD;
d5a2b9a6 175 r->original_pid = getpid();
de1c301e 176
45fbe937
LP
177 assert_se(pthread_mutex_init(&r->memfd_cache_mutex, NULL) == 0);
178
de1c301e
LP
179 /* We guarantee that wqueue always has space for at least one
180 * entry */
181 r->wqueue = new(sd_bus_message*, 1);
182 if (!r->wqueue) {
183 free(r);
021a1e78 184 return -ENOMEM;
de1c301e
LP
185 }
186
021a1e78
LP
187 *ret = r;
188 return 0;
189}
190
d9f644e2 191_public_ int sd_bus_set_address(sd_bus *bus, const char *address) {
021a1e78
LP
192 char *a;
193
d6888822
LP
194 assert_return(bus, -EINVAL);
195 assert_return(bus->state == BUS_UNSET, -EPERM);
196 assert_return(address, -EINVAL);
197 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78
LP
198
199 a = strdup(address);
200 if (!a)
201 return -ENOMEM;
202
203 free(bus->address);
204 bus->address = a;
205
206 return 0;
207}
208
d9f644e2 209_public_ int sd_bus_set_fd(sd_bus *bus, int input_fd, int output_fd) {
d6888822
LP
210 assert_return(bus, -EINVAL);
211 assert_return(bus->state == BUS_UNSET, -EPERM);
212 assert_return(input_fd >= 0, -EINVAL);
213 assert_return(output_fd >= 0, -EINVAL);
214 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78 215
e82c9509
LP
216 bus->input_fd = input_fd;
217 bus->output_fd = output_fd;
021a1e78
LP
218 return 0;
219}
220
d9f644e2 221_public_ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]) {
2fd9ae2e
LP
222 char *p, **a;
223
d6888822
LP
224 assert_return(bus, -EINVAL);
225 assert_return(bus->state == BUS_UNSET, -EPERM);
226 assert_return(path, -EINVAL);
227 assert_return(!strv_isempty(argv), -EINVAL);
228 assert_return(!bus_pid_changed(bus), -ECHILD);
2fd9ae2e
LP
229
230 p = strdup(path);
231 if (!p)
232 return -ENOMEM;
233
234 a = strv_copy(argv);
235 if (!a) {
236 free(p);
237 return -ENOMEM;
238 }
239
240 free(bus->exec_path);
241 strv_free(bus->exec_argv);
242
243 bus->exec_path = p;
244 bus->exec_argv = a;
245
246 return 0;
247}
248
d9f644e2 249_public_ int sd_bus_set_bus_client(sd_bus *bus, int b) {
d6888822
LP
250 assert_return(bus, -EINVAL);
251 assert_return(bus->state == BUS_UNSET, -EPERM);
252 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78 253
94bbf1ba 254 bus->bus_client = !!b;
021a1e78
LP
255 return 0;
256}
257
d9f644e2 258_public_ int sd_bus_negotiate_fds(sd_bus *bus, int b) {
d6888822
LP
259 assert_return(bus, -EINVAL);
260 assert_return(bus->state == BUS_UNSET, -EPERM);
261 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78 262
264ad849
LP
263 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ACCEPT_FD, b);
264 return 0;
265}
266
f21326e6 267_public_ int sd_bus_negotiate_attach_timestamp(sd_bus *bus, int b) {
16be4368
KS
268 assert_return(bus, -EINVAL);
269 assert_return(bus->state == BUS_UNSET, -EPERM);
270 assert_return(!bus_pid_changed(bus), -ECHILD);
271
f21326e6 272 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_TIMESTAMP, b);
16be4368
KS
273 return 0;
274}
275
f21326e6 276_public_ int sd_bus_negotiate_attach_creds(sd_bus *bus, int b) {
16be4368
KS
277 assert_return(bus, -EINVAL);
278 assert_return(bus->state == BUS_UNSET, -EPERM);
279 assert_return(!bus_pid_changed(bus), -ECHILD);
280
f21326e6 281 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CREDS, b);
16be4368
KS
282 return 0;
283}
284
d9f644e2 285_public_ int sd_bus_negotiate_attach_comm(sd_bus *bus, int b) {
d6888822
LP
286 assert_return(bus, -EINVAL);
287 assert_return(bus->state == BUS_UNSET, -EPERM);
288 assert_return(!bus_pid_changed(bus), -ECHILD);
264ad849
LP
289
290 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_COMM, b);
291 return 0;
292}
293
d9f644e2 294_public_ int sd_bus_negotiate_attach_exe(sd_bus *bus, int b) {
d6888822
LP
295 assert_return(bus, -EINVAL);
296 assert_return(bus->state == BUS_UNSET, -EPERM);
297 assert_return(!bus_pid_changed(bus), -ECHILD);
264ad849
LP
298
299 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_EXE, b);
300 return 0;
301}
302
d9f644e2 303_public_ int sd_bus_negotiate_attach_cmdline(sd_bus *bus, int b) {
d6888822
LP
304 assert_return(bus, -EINVAL);
305 assert_return(bus->state == BUS_UNSET, -EPERM);
306 assert_return(!bus_pid_changed(bus), -ECHILD);
264ad849
LP
307
308 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CMDLINE, b);
309 return 0;
310}
311
d9f644e2 312_public_ int sd_bus_negotiate_attach_cgroup(sd_bus *bus, int b) {
d6888822
LP
313 assert_return(bus, -EINVAL);
314 assert_return(bus->state == BUS_UNSET, -EPERM);
315 assert_return(!bus_pid_changed(bus), -ECHILD);
264ad849
LP
316
317 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CGROUP, b);
318 return 0;
319}
320
d9f644e2 321_public_ int sd_bus_negotiate_attach_caps(sd_bus *bus, int b) {
d6888822
LP
322 assert_return(bus, -EINVAL);
323 assert_return(bus->state == BUS_UNSET, -EPERM);
324 assert_return(!bus_pid_changed(bus), -ECHILD);
264ad849
LP
325
326 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_CAPS, b);
327 return 0;
328}
329
d9f644e2 330_public_ int sd_bus_negotiate_attach_selinux_context(sd_bus *bus, int b) {
d6888822
LP
331 assert_return(bus, -EINVAL);
332 assert_return(bus->state == BUS_UNSET, -EPERM);
333 assert_return(!bus_pid_changed(bus), -ECHILD);
264ad849
LP
334
335 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_SECLABEL, b);
336 return 0;
337}
338
d9f644e2 339_public_ int sd_bus_negotiate_attach_audit(sd_bus *bus, int b) {
d6888822
LP
340 assert_return(bus, -EINVAL);
341 assert_return(bus->state == BUS_UNSET, -EPERM);
342 assert_return(!bus_pid_changed(bus), -ECHILD);
264ad849
LP
343
344 SET_FLAG(bus->hello_flags, KDBUS_HELLO_ATTACH_AUDIT, b);
021a1e78
LP
345 return 0;
346}
de1c301e 347
d9f644e2 348_public_ int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id) {
d6888822
LP
349 assert_return(bus, -EINVAL);
350 assert_return(b || sd_id128_equal(server_id, SD_ID128_NULL), -EINVAL);
351 assert_return(bus->state == BUS_UNSET, -EPERM);
352 assert_return(!bus_pid_changed(bus), -ECHILD);
2181a7f5
LP
353
354 bus->is_server = !!b;
98178d39 355 bus->server_id = server_id;
2181a7f5
LP
356 return 0;
357}
358
d9f644e2 359_public_ int sd_bus_set_anonymous(sd_bus *bus, int b) {
d6888822
LP
360 assert_return(bus, -EINVAL);
361 assert_return(bus->state == BUS_UNSET, -EPERM);
362 assert_return(!bus_pid_changed(bus), -ECHILD);
2181a7f5
LP
363
364 bus->anonymous_auth = !!b;
365 return 0;
366}
367
ebcf1f97 368static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
de1c301e
LP
369 const char *s;
370 int r;
371
372 assert(bus);
021a1e78 373 assert(bus->state == BUS_HELLO);
de1c301e
LP
374 assert(reply);
375
40ca29a1 376 r = sd_bus_message_get_errno(reply);
eb01ba5d
LP
377 if (r < 0)
378 return r;
40ca29a1
LP
379 if (r > 0)
380 return -r;
eb01ba5d 381
de1c301e
LP
382 r = sd_bus_message_read(reply, "s", &s);
383 if (r < 0)
384 return r;
385
dafb7591
LP
386 if (!service_name_is_valid(s) || s[0] != ':')
387 return -EBADMSG;
388
de1c301e
LP
389 bus->unique_name = strdup(s);
390 if (!bus->unique_name)
391 return -ENOMEM;
392
dafb7591
LP
393 bus->state = BUS_RUNNING;
394
de1c301e
LP
395 return 1;
396}
397
398static int bus_send_hello(sd_bus *bus) {
399 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
400 int r;
401
402 assert(bus);
403
6629161f 404 if (!bus->bus_client || bus->is_kernel)
021a1e78
LP
405 return 0;
406
de1c301e
LP
407 r = sd_bus_message_new_method_call(
408 bus,
409 "org.freedesktop.DBus",
410 "/",
411 "org.freedesktop.DBus",
412 "Hello",
413 &m);
414 if (r < 0)
415 return r;
416
c49b30a2 417 return sd_bus_call_async(bus, m, hello_callback, NULL, 0, &bus->hello_serial);
de1c301e
LP
418}
419
a7e3212d 420int bus_start_running(sd_bus *bus) {
de1c301e
LP
421 assert(bus);
422
f08838da 423 if (bus->bus_client && !bus->is_kernel) {
de1c301e 424 bus->state = BUS_HELLO;
e3017af9 425 return 1;
de1c301e
LP
426 }
427
428 bus->state = BUS_RUNNING;
e3017af9 429 return 1;
de1c301e
LP
430}
431
432static int parse_address_key(const char **p, const char *key, char **value) {
433 size_t l, n = 0;
434 const char *a;
435 char *r = NULL;
436
437 assert(p);
438 assert(*p);
de1c301e
LP
439 assert(value);
440
2fd9ae2e
LP
441 if (key) {
442 l = strlen(key);
443 if (strncmp(*p, key, l) != 0)
444 return 0;
de1c301e 445
2fd9ae2e
LP
446 if ((*p)[l] != '=')
447 return 0;
de1c301e 448
2fd9ae2e
LP
449 if (*value)
450 return -EINVAL;
de1c301e 451
2fd9ae2e
LP
452 a = *p + l + 1;
453 } else
454 a = *p;
455
456 while (*a != ';' && *a != ',' && *a != 0) {
de1c301e
LP
457 char c, *t;
458
459 if (*a == '%') {
460 int x, y;
461
462 x = unhexchar(a[1]);
463 if (x < 0) {
464 free(r);
465 return x;
466 }
467
468 y = unhexchar(a[2]);
469 if (y < 0) {
470 free(r);
471 return y;
472 }
473
de1c301e 474 c = (char) ((x << 4) | y);
89ffcd2a
LP
475 a += 3;
476 } else {
de1c301e 477 c = *a;
89ffcd2a
LP
478 a++;
479 }
de1c301e 480
89ffcd2a 481 t = realloc(r, n + 2);
de1c301e
LP
482 if (!t) {
483 free(r);
484 return -ENOMEM;
485 }
486
487 r = t;
488 r[n++] = c;
489 }
490
89ffcd2a
LP
491 if (!r) {
492 r = strdup("");
493 if (!r)
494 return -ENOMEM;
495 } else
496 r[n] = 0;
497
498 if (*a == ',')
499 a++;
500
de1c301e 501 *p = a;
2fd9ae2e
LP
502
503 free(*value);
de1c301e 504 *value = r;
2fd9ae2e 505
de1c301e
LP
506 return 1;
507}
508
509static void skip_address_key(const char **p) {
510 assert(p);
511 assert(*p);
512
89ffcd2a
LP
513 *p += strcspn(*p, ",");
514
515 if (**p == ',')
516 (*p) ++;
de1c301e
LP
517}
518
2fd9ae2e
LP
519static int parse_unix_address(sd_bus *b, const char **p, char **guid) {
520 _cleanup_free_ char *path = NULL, *abstract = NULL;
521 size_t l;
de1c301e
LP
522 int r;
523
524 assert(b);
2fd9ae2e
LP
525 assert(p);
526 assert(*p);
527 assert(guid);
de1c301e 528
2fd9ae2e
LP
529 while (**p != 0 && **p != ';') {
530 r = parse_address_key(p, "guid", guid);
531 if (r < 0)
532 return r;
533 else if (r > 0)
534 continue;
de1c301e 535
2fd9ae2e
LP
536 r = parse_address_key(p, "path", &path);
537 if (r < 0)
538 return r;
539 else if (r > 0)
540 continue;
de1c301e 541
2fd9ae2e
LP
542 r = parse_address_key(p, "abstract", &abstract);
543 if (r < 0)
544 return r;
545 else if (r > 0)
546 continue;
de1c301e 547
2fd9ae2e
LP
548 skip_address_key(p);
549 }
de1c301e 550
2fd9ae2e
LP
551 if (!path && !abstract)
552 return -EINVAL;
de1c301e 553
2fd9ae2e
LP
554 if (path && abstract)
555 return -EINVAL;
556
557 if (path) {
558 l = strlen(path);
559 if (l > sizeof(b->sockaddr.un.sun_path))
560 return -E2BIG;
de1c301e 561
2fd9ae2e
LP
562 b->sockaddr.un.sun_family = AF_UNIX;
563 strncpy(b->sockaddr.un.sun_path, path, sizeof(b->sockaddr.un.sun_path));
564 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l;
565 } else if (abstract) {
566 l = strlen(abstract);
567 if (l > sizeof(b->sockaddr.un.sun_path) - 1)
568 return -E2BIG;
569
570 b->sockaddr.un.sun_family = AF_UNIX;
571 b->sockaddr.un.sun_path[0] = 0;
572 strncpy(b->sockaddr.un.sun_path+1, abstract, sizeof(b->sockaddr.un.sun_path)-1);
573 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + 1 + l;
574 }
575
576 return 0;
577}
578
579static int parse_tcp_address(sd_bus *b, const char **p, char **guid) {
580 _cleanup_free_ char *host = NULL, *port = NULL, *family = NULL;
2fd9ae2e 581 int r;
b92bea5d
ZJS
582 struct addrinfo *result, hints = {
583 .ai_socktype = SOCK_STREAM,
584 .ai_flags = AI_ADDRCONFIG,
585 };
2fd9ae2e
LP
586
587 assert(b);
588 assert(p);
589 assert(*p);
590 assert(guid);
591
592 while (**p != 0 && **p != ';') {
593 r = parse_address_key(p, "guid", guid);
594 if (r < 0)
595 return r;
596 else if (r > 0)
597 continue;
598
599 r = parse_address_key(p, "host", &host);
600 if (r < 0)
601 return r;
602 else if (r > 0)
603 continue;
604
605 r = parse_address_key(p, "port", &port);
606 if (r < 0)
607 return r;
608 else if (r > 0)
609 continue;
610
611 r = parse_address_key(p, "family", &family);
612 if (r < 0)
613 return r;
614 else if (r > 0)
615 continue;
616
617 skip_address_key(p);
618 }
619
620 if (!host || !port)
621 return -EINVAL;
622
2fd9ae2e
LP
623 if (family) {
624 if (streq(family, "ipv4"))
625 hints.ai_family = AF_INET;
626 else if (streq(family, "ipv6"))
627 hints.ai_family = AF_INET6;
628 else
629 return -EINVAL;
630 }
631
632 r = getaddrinfo(host, port, &hints, &result);
633 if (r == EAI_SYSTEM)
634 return -errno;
635 else if (r != 0)
636 return -EADDRNOTAVAIL;
637
638 memcpy(&b->sockaddr, result->ai_addr, result->ai_addrlen);
639 b->sockaddr_size = result->ai_addrlen;
640
641 freeaddrinfo(result);
642
643 return 0;
644}
645
646static int parse_exec_address(sd_bus *b, const char **p, char **guid) {
647 char *path = NULL;
648 unsigned n_argv = 0, j;
649 char **argv = NULL;
650 int r;
651
652 assert(b);
653 assert(p);
654 assert(*p);
655 assert(guid);
656
657 while (**p != 0 && **p != ';') {
658 r = parse_address_key(p, "guid", guid);
659 if (r < 0)
660 goto fail;
661 else if (r > 0)
662 continue;
663
664 r = parse_address_key(p, "path", &path);
665 if (r < 0)
666 goto fail;
667 else if (r > 0)
668 continue;
669
670 if (startswith(*p, "argv")) {
671 unsigned ul;
672
673 errno = 0;
674 ul = strtoul(*p + 4, (char**) p, 10);
8333c77e 675 if (errno > 0 || **p != '=' || ul > 256) {
2fd9ae2e
LP
676 r = -EINVAL;
677 goto fail;
678 }
679
680 (*p) ++;
681
682 if (ul >= n_argv) {
683 char **x;
684
685 x = realloc(argv, sizeof(char*) * (ul + 2));
686 if (!x) {
687 r = -ENOMEM;
688 goto fail;
689 }
690
691 memset(x + n_argv, 0, sizeof(char*) * (ul - n_argv + 2));
692
693 argv = x;
694 n_argv = ul + 1;
695 }
696
697 r = parse_address_key(p, NULL, argv + ul);
de1c301e 698 if (r < 0)
2fd9ae2e 699 goto fail;
de1c301e 700
2fd9ae2e 701 continue;
de1c301e
LP
702 }
703
2fd9ae2e
LP
704 skip_address_key(p);
705 }
de1c301e 706
5a0f6033
LP
707 if (!path) {
708 r = -EINVAL;
2fd9ae2e 709 goto fail;
5a0f6033 710 }
de1c301e 711
2fd9ae2e
LP
712 /* Make sure there are no holes in the array, with the
713 * exception of argv[0] */
714 for (j = 1; j < n_argv; j++)
715 if (!argv[j]) {
716 r = -EINVAL;
717 goto fail;
718 }
719
720 if (argv && argv[0] == NULL) {
721 argv[0] = strdup(path);
722 if (!argv[0]) {
723 r = -ENOMEM;
724 goto fail;
725 }
726 }
de1c301e 727
2fd9ae2e
LP
728 b->exec_path = path;
729 b->exec_argv = argv;
730 return 0;
de1c301e 731
2fd9ae2e
LP
732fail:
733 for (j = 0; j < n_argv; j++)
734 free(argv[j]);
735
736 free(argv);
737 free(path);
738 return r;
739}
740
6629161f
LP
741static int parse_kernel_address(sd_bus *b, const char **p, char **guid) {
742 _cleanup_free_ char *path = NULL;
743 int r;
744
745 assert(b);
746 assert(p);
747 assert(*p);
748 assert(guid);
749
750 while (**p != 0 && **p != ';') {
751 r = parse_address_key(p, "guid", guid);
752 if (r < 0)
753 return r;
754 else if (r > 0)
755 continue;
756
757 r = parse_address_key(p, "path", &path);
758 if (r < 0)
759 return r;
760 else if (r > 0)
761 continue;
762
763 skip_address_key(p);
764 }
765
766 if (!path)
767 return -EINVAL;
768
769 free(b->kernel);
770 b->kernel = path;
771 path = NULL;
772
773 return 0;
774}
775
a7893c6b
LP
776static int parse_container_address(sd_bus *b, const char **p, char **guid) {
777 _cleanup_free_ char *machine = NULL;
778 int r;
779
780 assert(b);
781 assert(p);
782 assert(*p);
783 assert(guid);
784
785 while (**p != 0 && **p != ';') {
786 r = parse_address_key(p, "guid", guid);
787 if (r < 0)
788 return r;
789 else if (r > 0)
790 continue;
791
792 r = parse_address_key(p, "machine", &machine);
793 if (r < 0)
794 return r;
795 else if (r > 0)
796 continue;
797
798 skip_address_key(p);
799 }
800
801 if (!machine)
802 return -EINVAL;
803
804 free(b->machine);
805 b->machine = machine;
806 machine = NULL;
807
808 b->sockaddr.un.sun_family = AF_UNIX;
809 strncpy(b->sockaddr.un.sun_path, "/var/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
810 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/var/run/dbus/system_bus_socket") - 1;
811
812 return 0;
813}
814
2fd9ae2e
LP
815static void bus_reset_parsed_address(sd_bus *b) {
816 assert(b);
817
818 zero(b->sockaddr);
819 b->sockaddr_size = 0;
820 strv_free(b->exec_argv);
821 free(b->exec_path);
822 b->exec_path = NULL;
823 b->exec_argv = NULL;
98178d39 824 b->server_id = SD_ID128_NULL;
6629161f
LP
825 free(b->kernel);
826 b->kernel = NULL;
a7893c6b
LP
827 free(b->machine);
828 b->machine = NULL;
2fd9ae2e
LP
829}
830
831static int bus_parse_next_address(sd_bus *b) {
832 _cleanup_free_ char *guid = NULL;
833 const char *a;
834 int r;
835
836 assert(b);
837
838 if (!b->address)
839 return 0;
840 if (b->address[b->address_index] == 0)
841 return 0;
842
843 bus_reset_parsed_address(b);
844
845 a = b->address + b->address_index;
de1c301e 846
2fd9ae2e 847 while (*a != 0) {
de1c301e 848
2fd9ae2e
LP
849 if (*a == ';') {
850 a++;
851 continue;
de1c301e
LP
852 }
853
2fd9ae2e
LP
854 if (startswith(a, "unix:")) {
855 a += 5;
de1c301e 856
2fd9ae2e 857 r = parse_unix_address(b, &a, &guid);
de1c301e
LP
858 if (r < 0)
859 return r;
2fd9ae2e 860 break;
de1c301e 861
2fd9ae2e 862 } else if (startswith(a, "tcp:")) {
de1c301e 863
2fd9ae2e
LP
864 a += 4;
865 r = parse_tcp_address(b, &a, &guid);
de1c301e
LP
866 if (r < 0)
867 return r;
de1c301e 868
2fd9ae2e
LP
869 break;
870
871 } else if (startswith(a, "unixexec:")) {
872
873 a += 9;
874 r = parse_exec_address(b, &a, &guid);
de1c301e
LP
875 if (r < 0)
876 return r;
de1c301e 877
2fd9ae2e 878 break;
de1c301e 879
6629161f
LP
880 } else if (startswith(a, "kernel:")) {
881
882 a += 7;
883 r = parse_kernel_address(b, &a, &guid);
884 if (r < 0)
885 return r;
886
a7893c6b
LP
887 break;
888 } else if (startswith(a, "x-container:")) {
889
890 a += 12;
891 r = parse_container_address(b, &a, &guid);
892 if (r < 0)
893 return r;
894
6629161f 895 break;
de1c301e
LP
896 }
897
2fd9ae2e
LP
898 a = strchr(a, ';');
899 if (!a)
900 return 0;
de1c301e
LP
901 }
902
903 if (guid) {
98178d39 904 r = sd_id128_from_string(guid, &b->server_id);
de1c301e
LP
905 if (r < 0)
906 return r;
907 }
908
2fd9ae2e 909 b->address_index = a - b->address;
de1c301e
LP
910 return 1;
911}
912
a7e3212d 913static int bus_start_address(sd_bus *b) {
2fd9ae2e
LP
914 int r;
915
916 assert(b);
917
918 for (;;) {
e82c9509 919 sd_bus_close(b);
2fd9ae2e 920
a7893c6b 921 if (b->exec_path) {
a7e3212d 922
a7893c6b 923 r = bus_socket_exec(b);
2fd9ae2e
LP
924 if (r >= 0)
925 return r;
926
927 b->last_connect_error = -r;
a7893c6b 928 } else if (b->kernel) {
2fd9ae2e 929
a7893c6b
LP
930 r = bus_kernel_connect(b);
931 if (r >= 0)
932 return r;
2fd9ae2e 933
a7893c6b
LP
934 b->last_connect_error = -r;
935
936 } else if (b->machine) {
937
938 r = bus_container_connect(b);
2fd9ae2e
LP
939 if (r >= 0)
940 return r;
941
6629161f 942 b->last_connect_error = -r;
6629161f 943
a7893c6b
LP
944 } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
945
946 r = bus_socket_connect(b);
6629161f
LP
947 if (r >= 0)
948 return r;
949
2fd9ae2e
LP
950 b->last_connect_error = -r;
951 }
952
953 r = bus_parse_next_address(b);
954 if (r < 0)
955 return r;
956 if (r == 0)
957 return b->last_connect_error ? -b->last_connect_error : -ECONNREFUSED;
de1c301e
LP
958 }
959}
960
a7e3212d
LP
961int bus_next_address(sd_bus *b) {
962 assert(b);
963
964 bus_reset_parsed_address(b);
965 return bus_start_address(b);
966}
967
021a1e78 968static int bus_start_fd(sd_bus *b) {
6629161f 969 struct stat st;
021a1e78
LP
970 int r;
971
972 assert(b);
e82c9509
LP
973 assert(b->input_fd >= 0);
974 assert(b->output_fd >= 0);
021a1e78 975
e82c9509 976 r = fd_nonblock(b->input_fd, true);
021a1e78
LP
977 if (r < 0)
978 return r;
979
e82c9509 980 r = fd_cloexec(b->input_fd, true);
021a1e78
LP
981 if (r < 0)
982 return r;
983
e82c9509
LP
984 if (b->input_fd != b->output_fd) {
985 r = fd_nonblock(b->output_fd, true);
986 if (r < 0)
987 return r;
988
989 r = fd_cloexec(b->output_fd, true);
990 if (r < 0)
991 return r;
992 }
993
6629161f
LP
994 if (fstat(b->input_fd, &st) < 0)
995 return -errno;
996
997 if (S_ISCHR(b->input_fd))
998 return bus_kernel_take_fd(b);
999 else
1000 return bus_socket_take_fd(b);
021a1e78
LP
1001}
1002
d9f644e2 1003_public_ int sd_bus_start(sd_bus *bus) {
021a1e78
LP
1004 int r;
1005
d6888822
LP
1006 assert_return(bus, -EINVAL);
1007 assert_return(bus->state == BUS_UNSET, -EPERM);
1008 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78
LP
1009
1010 bus->state = BUS_OPENING;
1011
2181a7f5
LP
1012 if (bus->is_server && bus->bus_client)
1013 return -EINVAL;
1014
e82c9509 1015 if (bus->input_fd >= 0)
021a1e78 1016 r = bus_start_fd(bus);
a7893c6b 1017 else if (bus->address || bus->sockaddr.sa.sa_family != AF_UNSPEC || bus->exec_path || bus->kernel || bus->machine)
a7e3212d 1018 r = bus_start_address(bus);
021a1e78
LP
1019 else
1020 return -EINVAL;
1021
1022 if (r < 0)
1023 return r;
1024
1025 return bus_send_hello(bus);
1026}
1027
d9f644e2 1028_public_ int sd_bus_open_system(sd_bus **ret) {
de1c301e
LP
1029 const char *e;
1030 sd_bus *b;
1031 int r;
1032
d6888822 1033 assert_return(ret, -EINVAL);
de1c301e 1034
021a1e78
LP
1035 r = sd_bus_new(&b);
1036 if (r < 0)
1037 return r;
1038
6c03089c 1039 e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
de1c301e 1040 if (e) {
021a1e78 1041 r = sd_bus_set_address(b, e);
de1c301e 1042 if (r < 0)
021a1e78 1043 goto fail;
89ffcd2a 1044 } else {
89ffcd2a
LP
1045 b->sockaddr.un.sun_family = AF_UNIX;
1046 strncpy(b->sockaddr.un.sun_path, "/run/dbus/system_bus_socket", sizeof(b->sockaddr.un.sun_path));
1047 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + sizeof("/run/dbus/system_bus_socket") - 1;
89ffcd2a 1048 }
de1c301e 1049
94bbf1ba 1050 b->bus_client = true;
021a1e78
LP
1051
1052 r = sd_bus_start(b);
1053 if (r < 0)
1054 goto fail;
de1c301e
LP
1055
1056 *ret = b;
1057 return 0;
021a1e78
LP
1058
1059fail:
1060 bus_free(b);
1061 return r;
de1c301e
LP
1062}
1063
d9f644e2 1064_public_ int sd_bus_open_user(sd_bus **ret) {
de1c301e
LP
1065 const char *e;
1066 sd_bus *b;
1067 size_t l;
1068 int r;
1069
d6888822 1070 assert_return(ret, -EINVAL);
de1c301e 1071
021a1e78
LP
1072 r = sd_bus_new(&b);
1073 if (r < 0)
1074 return r;
1075
6c03089c 1076 e = secure_getenv("DBUS_SESSION_BUS_ADDRESS");
de1c301e 1077 if (e) {
021a1e78 1078 r = sd_bus_set_address(b, e);
de1c301e 1079 if (r < 0)
021a1e78 1080 goto fail;
89ffcd2a 1081 } else {
6c03089c 1082 e = secure_getenv("XDG_RUNTIME_DIR");
021a1e78
LP
1083 if (!e) {
1084 r = -ENOENT;
1085 goto fail;
1086 }
de1c301e 1087
89ffcd2a 1088 l = strlen(e);
021a1e78
LP
1089 if (l + 4 > sizeof(b->sockaddr.un.sun_path)) {
1090 r = -E2BIG;
1091 goto fail;
1092 }
de1c301e 1093
89ffcd2a
LP
1094 b->sockaddr.un.sun_family = AF_UNIX;
1095 memcpy(mempcpy(b->sockaddr.un.sun_path, e, l), "/bus", 4);
1096 b->sockaddr_size = offsetof(struct sockaddr_un, sun_path) + l + 4;
de1c301e
LP
1097 }
1098
94bbf1ba 1099 b->bus_client = true;
de1c301e 1100
021a1e78 1101 r = sd_bus_start(b);
2571ead1
LP
1102 if (r < 0)
1103 goto fail;
de1c301e
LP
1104
1105 *ret = b;
1106 return 0;
2571ead1
LP
1107
1108fail:
021a1e78 1109 bus_free(b);
2571ead1 1110 return r;
de1c301e
LP
1111}
1112
d9f644e2 1113_public_ int sd_bus_open_system_remote(const char *host, sd_bus **ret) {
0f8bd8de
LP
1114 _cleanup_free_ char *e = NULL;
1115 char *p = NULL;
1116 sd_bus *bus;
1117 int r;
1118
1119 assert_return(host, -EINVAL);
1120 assert_return(ret, -EINVAL);
1121
1122 e = bus_address_escape(host);
1123 if (!e)
1124 return -ENOMEM;
1125
1126 p = strjoin("unixexec:path=ssh,argv1=-xT,argv2=", e, ",argv3=systemd-stdio-bridge", NULL);
1127 if (!p)
1128 return -ENOMEM;
a7893c6b
LP
1129
1130 r = sd_bus_new(&bus);
1131 if (r < 0) {
1132 free(p);
1133 return r;
1134 }
1135
1136 bus->address = p;
1137 bus->bus_client = true;
1138
1139 r = sd_bus_start(bus);
1140 if (r < 0) {
1141 bus_free(bus);
1142 return r;
1143 }
1144
1145 *ret = bus;
1146 return 0;
1147}
1148
d9f644e2 1149_public_ int sd_bus_open_system_container(const char *machine, sd_bus **ret) {
a7893c6b
LP
1150 _cleanup_free_ char *e = NULL;
1151 sd_bus *bus;
1152 char *p;
1153 int r;
1154
1155 assert_return(machine, -EINVAL);
1156 assert_return(ret, -EINVAL);
1157
1158 e = bus_address_escape(machine);
1159 if (!e)
1160 return -ENOMEM;
1161
1162 p = strjoin("x-container:machine=", e, NULL);
1163 if (!p)
1164 return -ENOMEM;
0f8bd8de
LP
1165
1166 r = sd_bus_new(&bus);
1167 if (r < 0) {
1168 free(p);
1169 return r;
1170 }
1171
1172 bus->address = p;
1173 bus->bus_client = true;
1174
1175 r = sd_bus_start(bus);
1176 if (r < 0) {
1177 bus_free(bus);
1178 return r;
1179 }
1180
1181 *ret = bus;
1182 return 0;
1183}
1184
d9f644e2 1185_public_ void sd_bus_close(sd_bus *bus) {
de1c301e
LP
1186 if (!bus)
1187 return;
d5a2b9a6
LP
1188 if (bus->state == BUS_CLOSED)
1189 return;
1190 if (bus_pid_changed(bus))
f54514f3
LP
1191 return;
1192
1193 bus->state = BUS_CLOSED;
e82c9509 1194
40ca29a1
LP
1195 sd_bus_detach_event(bus);
1196
f54514f3
LP
1197 if (!bus->is_kernel)
1198 bus_close_fds(bus);
1199
1200 /* We'll leave the fd open in case this is a kernel bus, since
1201 * there might still be memblocks around that reference this
1202 * bus, and they might need to invoke the
1203 * KDBUS_CMD_MSG_RELEASE ioctl on the fd when they are
1204 * freed. */
de1c301e
LP
1205}
1206
718db961
LP
1207static void bus_enter_closing(sd_bus *bus) {
1208 assert(bus);
1209
1210 if (bus->state != BUS_OPENING &&
1211 bus->state != BUS_AUTHENTICATING &&
1212 bus->state != BUS_HELLO &&
1213 bus->state != BUS_RUNNING)
1214 return;
1215
1216 bus->state = BUS_CLOSING;
1217}
1218
d9f644e2 1219_public_ sd_bus *sd_bus_ref(sd_bus *bus) {
9d6c7c82 1220 assert_return(bus, NULL);
de1c301e 1221
e4ee6e5c 1222 assert_se(REFCNT_INC(bus->n_ref) >= 2);
de1c301e 1223
de1c301e
LP
1224 return bus;
1225}
1226
d9f644e2 1227_public_ sd_bus *sd_bus_unref(sd_bus *bus) {
9d6c7c82 1228 assert_return(bus, NULL);
de1c301e 1229
e4ee6e5c 1230 if (REFCNT_DEC(bus->n_ref) <= 0)
de1c301e
LP
1231 bus_free(bus);
1232
1233 return NULL;
1234}
1235
d9f644e2 1236_public_ int sd_bus_is_open(sd_bus *bus) {
d6888822
LP
1237
1238 assert_return(bus, -EINVAL);
1239 assert_return(!bus_pid_changed(bus), -ECHILD);
e3017af9 1240
f54514f3 1241 return BUS_IS_OPEN(bus->state);
e3017af9
LP
1242}
1243
d9f644e2 1244_public_ int sd_bus_can_send(sd_bus *bus, char type) {
d728d708
LP
1245 int r;
1246
d6888822
LP
1247 assert_return(bus, -EINVAL);
1248 assert_return(bus->state != BUS_UNSET, -ENOTCONN);
1249 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 1250
d728d708 1251 if (type == SD_BUS_TYPE_UNIX_FD) {
264ad849 1252 if (!(bus->hello_flags & KDBUS_HELLO_ACCEPT_FD))
021a1e78
LP
1253 return 0;
1254
20902f3e 1255 r = bus_ensure_running(bus);
d728d708
LP
1256 if (r < 0)
1257 return r;
de1c301e 1258
d728d708
LP
1259 return bus->can_fds;
1260 }
1261
1262 return bus_type_is_valid(type);
de1c301e
LP
1263}
1264
d9f644e2 1265_public_ int sd_bus_get_server_id(sd_bus *bus, sd_id128_t *server_id) {
d728d708 1266 int r;
de1c301e 1267
d6888822
LP
1268 assert_return(bus, -EINVAL);
1269 assert_return(server_id, -EINVAL);
1270 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 1271
20902f3e 1272 r = bus_ensure_running(bus);
d728d708
LP
1273 if (r < 0)
1274 return r;
de1c301e 1275
98178d39 1276 *server_id = bus->server_id;
d728d708 1277 return 0;
de1c301e
LP
1278}
1279
1280static int bus_seal_message(sd_bus *b, sd_bus_message *m) {
1281 assert(m);
1282
89ffcd2a
LP
1283 if (m->header->version > b->message_version)
1284 return -EPERM;
1285
aea93deb
LP
1286 if (m->sealed) {
1287 /* If we copy the same message to multiple
1288 * destinations, avoid using the same serial
1289 * numbers. */
1290 b->serial = MAX(b->serial, BUS_MESSAGE_SERIAL(m));
de1c301e 1291 return 0;
aea93deb 1292 }
de1c301e 1293
9a17484d 1294 return bus_message_seal(m, ++b->serial);
de1c301e
LP
1295}
1296
718db961
LP
1297static int bus_write_message(sd_bus *bus, sd_bus_message *message, size_t *idx) {
1298 int r;
1299
1300 assert(bus);
1301 assert(message);
1302
1303 if (bus->is_kernel)
1304 r = bus_kernel_write_message(bus, message);
1305 else
1306 r = bus_socket_write_message(bus, message, idx);
1307
1308 return r;
1309}
1310
de1c301e 1311static int dispatch_wqueue(sd_bus *bus) {
e3017af9 1312 int r, ret = 0;
de1c301e
LP
1313
1314 assert(bus);
89ffcd2a 1315 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1316
de1c301e
LP
1317 while (bus->wqueue_size > 0) {
1318
718db961
LP
1319 r = bus_write_message(bus, bus->wqueue[0], &bus->windex);
1320 if (r < 0)
de1c301e 1321 return r;
718db961 1322 else if (r == 0)
e3017af9
LP
1323 /* Didn't do anything this time */
1324 return ret;
6629161f 1325 else if (bus->is_kernel || bus->windex >= BUS_MESSAGE_SIZE(bus->wqueue[0])) {
de1c301e
LP
1326 /* Fully written. Let's drop the entry from
1327 * the queue.
1328 *
1329 * This isn't particularly optimized, but
1330 * well, this is supposed to be our worst-case
1331 * buffer only, and the socket buffer is
1332 * supposed to be our primary buffer, and if
1333 * it got full, then all bets are off
1334 * anyway. */
1335
1336 sd_bus_message_unref(bus->wqueue[0]);
1337 bus->wqueue_size --;
1338 memmove(bus->wqueue, bus->wqueue + 1, sizeof(sd_bus_message*) * bus->wqueue_size);
1339 bus->windex = 0;
1340
e3017af9 1341 ret = 1;
de1c301e
LP
1342 }
1343 }
1344
e3017af9 1345 return ret;
de1c301e
LP
1346}
1347
718db961
LP
1348static int bus_read_message(sd_bus *bus, sd_bus_message **m) {
1349 int r;
1350
1351 assert(bus);
1352 assert(m);
1353
1354 if (bus->is_kernel)
1355 r = bus_kernel_read_message(bus, m);
1356 else
1357 r = bus_socket_read_message(bus, m);
1358
1359 return r;
1360}
1361
de1c301e 1362static int dispatch_rqueue(sd_bus *bus, sd_bus_message **m) {
2bf938c1 1363 sd_bus_message *z = NULL;
e3017af9 1364 int r, ret = 0;
de1c301e
LP
1365
1366 assert(bus);
1367 assert(m);
89ffcd2a 1368 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
de1c301e 1369
de1c301e
LP
1370 if (bus->rqueue_size > 0) {
1371 /* Dispatch a queued message */
1372
1373 *m = bus->rqueue[0];
1374 bus->rqueue_size --;
1375 memmove(bus->rqueue, bus->rqueue + 1, sizeof(sd_bus_message*) * bus->rqueue_size);
1376 return 1;
1377 }
1378
1379 /* Try to read a new message */
e3017af9 1380 do {
718db961
LP
1381 r = bus_read_message(bus, &z);
1382 if (r < 0)
e3017af9 1383 return r;
e3017af9
LP
1384 if (r == 0)
1385 return ret;
de1c301e 1386
2e8d788c 1387 ret = 1;
e3017af9
LP
1388 } while (!z);
1389
1390 *m = z;
2e8d788c 1391 return ret;
de1c301e
LP
1392}
1393
d9f644e2 1394_public_ int sd_bus_send(sd_bus *bus, sd_bus_message *m, uint64_t *serial) {
de1c301e
LP
1395 int r;
1396
d6888822
LP
1397 assert_return(bus, -EINVAL);
1398 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1399 assert_return(m, -EINVAL);
1400 assert_return(!bus_pid_changed(bus), -ECHILD);
021a1e78
LP
1401
1402 if (m->n_fds > 0) {
1403 r = sd_bus_can_send(bus, SD_BUS_TYPE_UNIX_FD);
1404 if (r < 0)
1405 return r;
1406 if (r == 0)
1407 return -ENOTSUP;
1408 }
de1c301e 1409
29f6aadd
LP
1410 /* If the serial number isn't kept, then we know that no reply
1411 * is expected */
1412 if (!serial && !m->sealed)
1413 m->header->flags |= SD_BUS_MESSAGE_NO_REPLY_EXPECTED;
1414
de1c301e
LP
1415 r = bus_seal_message(bus, m);
1416 if (r < 0)
1417 return r;
1418
5407f2de
LP
1419 /* If this is a reply and no reply was requested, then let's
1420 * suppress this, if we can */
1421 if (m->dont_send && !serial)
7a37d625 1422 return 1;
5407f2de 1423
89ffcd2a 1424 if ((bus->state == BUS_RUNNING || bus->state == BUS_HELLO) && bus->wqueue_size <= 0) {
de1c301e
LP
1425 size_t idx = 0;
1426
718db961
LP
1427 r = bus_write_message(bus, m, &idx);
1428 if (r < 0)
de1c301e 1429 return r;
718db961 1430 else if (!bus->is_kernel && idx < BUS_MESSAGE_SIZE(m)) {
de1c301e
LP
1431 /* Wasn't fully written. So let's remember how
1432 * much was written. Note that the first entry
1433 * of the wqueue array is always allocated so
1434 * that we always can remember how much was
1435 * written. */
1436 bus->wqueue[0] = sd_bus_message_ref(m);
1437 bus->wqueue_size = 1;
1438 bus->windex = idx;
1439 }
1440 } else {
1441 sd_bus_message **q;
1442
1443 /* Just append it to the queue. */
1444
25220239 1445 if (bus->wqueue_size >= BUS_WQUEUE_MAX)
de1c301e
LP
1446 return -ENOBUFS;
1447
1448 q = realloc(bus->wqueue, sizeof(sd_bus_message*) * (bus->wqueue_size + 1));
1449 if (!q)
1450 return -ENOMEM;
1451
1452 bus->wqueue = q;
1453 q[bus->wqueue_size ++] = sd_bus_message_ref(m);
1454 }
1455
1456 if (serial)
1457 *serial = BUS_MESSAGE_SERIAL(m);
1458
7a37d625 1459 return 1;
de1c301e
LP
1460}
1461
911121a7
LP
1462_public_ int sd_bus_send_to(sd_bus *bus, sd_bus_message *m, const char *destination, uint64_t *serial) {
1463 int r;
1464
1465 assert_return(bus, -EINVAL);
1466 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1467 assert_return(m, -EINVAL);
1468 assert_return(!bus_pid_changed(bus), -ECHILD);
1469
1470 if (!streq_ptr(m->destination, destination)) {
1471
1472 if (!destination)
1473 return -EEXIST;
1474
1475 r = sd_bus_message_set_destination(m, destination);
1476 if (r < 0)
1477 return r;
1478 }
1479
1480 return sd_bus_send(bus, m, serial);
1481}
1482
de1c301e
LP
1483static usec_t calc_elapse(uint64_t usec) {
1484 if (usec == (uint64_t) -1)
1485 return 0;
1486
1487 if (usec == 0)
e3017af9 1488 usec = BUS_DEFAULT_TIMEOUT;
de1c301e
LP
1489
1490 return now(CLOCK_MONOTONIC) + usec;
1491}
1492
e3017af9
LP
1493static int timeout_compare(const void *a, const void *b) {
1494 const struct reply_callback *x = a, *y = b;
1495
1496 if (x->timeout != 0 && y->timeout == 0)
1497 return -1;
1498
1499 if (x->timeout == 0 && y->timeout != 0)
1500 return 1;
1501
1502 if (x->timeout < y->timeout)
1503 return -1;
1504
1505 if (x->timeout > y->timeout)
1506 return 1;
1507
1508 return 0;
1509}
1510
c49b30a2 1511_public_ int sd_bus_call_async(
de1c301e
LP
1512 sd_bus *bus,
1513 sd_bus_message *m,
52f3ba91 1514 sd_bus_message_handler_t callback,
de1c301e
LP
1515 void *userdata,
1516 uint64_t usec,
1517 uint64_t *serial) {
1518
1519 struct reply_callback *c;
1520 int r;
1521
d6888822
LP
1522 assert_return(bus, -EINVAL);
1523 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1524 assert_return(m, -EINVAL);
40ca29a1 1525 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
d6888822
LP
1526 assert_return(!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
1527 assert_return(callback, -EINVAL);
1528 assert_return(!bus_pid_changed(bus), -ECHILD);
89ffcd2a
LP
1529
1530 r = hashmap_ensure_allocated(&bus->reply_callbacks, uint64_hash_func, uint64_compare_func);
1531 if (r < 0)
1532 return r;
de1c301e 1533
e3017af9
LP
1534 if (usec != (uint64_t) -1) {
1535 r = prioq_ensure_allocated(&bus->reply_callbacks_prioq, timeout_compare);
1536 if (r < 0)
1537 return r;
1538 }
1539
de1c301e
LP
1540 r = bus_seal_message(bus, m);
1541 if (r < 0)
1542 return r;
1543
eba8617e 1544 c = new0(struct reply_callback, 1);
de1c301e
LP
1545 if (!c)
1546 return -ENOMEM;
1547
1548 c->callback = callback;
1549 c->userdata = userdata;
1550 c->serial = BUS_MESSAGE_SERIAL(m);
1551 c->timeout = calc_elapse(usec);
1552
1553 r = hashmap_put(bus->reply_callbacks, &c->serial, c);
1554 if (r < 0) {
1555 free(c);
1556 return r;
1557 }
1558
e3017af9
LP
1559 if (c->timeout != 0) {
1560 r = prioq_put(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1561 if (r < 0) {
1562 c->timeout = 0;
c49b30a2 1563 sd_bus_call_async_cancel(bus, c->serial);
e3017af9
LP
1564 return r;
1565 }
1566 }
1567
de1c301e
LP
1568 r = sd_bus_send(bus, m, serial);
1569 if (r < 0) {
c49b30a2 1570 sd_bus_call_async_cancel(bus, c->serial);
de1c301e
LP
1571 return r;
1572 }
1573
1574 return r;
1575}
1576
c49b30a2 1577_public_ int sd_bus_call_async_cancel(sd_bus *bus, uint64_t serial) {
e3017af9 1578 struct reply_callback *c;
de1c301e 1579
d6888822
LP
1580 assert_return(bus, -EINVAL);
1581 assert_return(serial != 0, -EINVAL);
1582 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e
LP
1583
1584 c = hashmap_remove(bus->reply_callbacks, &serial);
1585 if (!c)
1586 return 0;
1587
e3017af9
LP
1588 if (c->timeout != 0)
1589 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1590
de1c301e
LP
1591 free(c);
1592 return 1;
1593}
1594
20902f3e 1595int bus_ensure_running(sd_bus *bus) {
89ffcd2a
LP
1596 int r;
1597
1598 assert(bus);
1599
718db961 1600 if (bus->state == BUS_UNSET || bus->state == BUS_CLOSED || bus->state == BUS_CLOSING)
021a1e78 1601 return -ENOTCONN;
d728d708
LP
1602 if (bus->state == BUS_RUNNING)
1603 return 1;
89ffcd2a
LP
1604
1605 for (;;) {
1606 r = sd_bus_process(bus, NULL);
1607 if (r < 0)
1608 return r;
d728d708
LP
1609 if (bus->state == BUS_RUNNING)
1610 return 1;
e3017af9
LP
1611 if (r > 0)
1612 continue;
89ffcd2a
LP
1613
1614 r = sd_bus_wait(bus, (uint64_t) -1);
1615 if (r < 0)
1616 return r;
1617 }
1618}
1619
c49b30a2 1620_public_ int sd_bus_call(
de1c301e
LP
1621 sd_bus *bus,
1622 sd_bus_message *m,
1623 uint64_t usec,
1624 sd_bus_error *error,
1625 sd_bus_message **reply) {
1626
1627 int r;
1628 usec_t timeout;
1629 uint64_t serial;
1630 bool room = false;
1631
d6888822
LP
1632 assert_return(bus, -EINVAL);
1633 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
1634 assert_return(m, -EINVAL);
40ca29a1 1635 assert_return(m->header->type == SD_BUS_MESSAGE_METHOD_CALL, -EINVAL);
d6888822
LP
1636 assert_return(!(m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED), -EINVAL);
1637 assert_return(!bus_error_is_dirty(error), -EINVAL);
1638 assert_return(!bus_pid_changed(bus), -ECHILD);
89ffcd2a 1639
20902f3e 1640 r = bus_ensure_running(bus);
89ffcd2a
LP
1641 if (r < 0)
1642 return r;
de1c301e
LP
1643
1644 r = sd_bus_send(bus, m, &serial);
1645 if (r < 0)
1646 return r;
1647
1648 timeout = calc_elapse(usec);
1649
1650 for (;;) {
1651 usec_t left;
e3017af9 1652 sd_bus_message *incoming = NULL;
de1c301e
LP
1653
1654 if (!room) {
1655 sd_bus_message **q;
1656
25220239
LP
1657 if (bus->rqueue_size >= BUS_RQUEUE_MAX)
1658 return -ENOBUFS;
1659
de1c301e
LP
1660 /* Make sure there's room for queuing this
1661 * locally, before we read the message */
1662
1663 q = realloc(bus->rqueue, (bus->rqueue_size + 1) * sizeof(sd_bus_message*));
1664 if (!q)
1665 return -ENOMEM;
1666
1667 bus->rqueue = q;
1668 room = true;
1669 }
1670
718db961 1671 r = bus_read_message(bus, &incoming);
de1c301e
LP
1672 if (r < 0)
1673 return r;
718db961 1674
e3017af9 1675 if (incoming) {
89ffcd2a 1676
de1c301e
LP
1677 if (incoming->reply_serial == serial) {
1678 /* Found a match! */
1679
40ca29a1 1680 if (incoming->header->type == SD_BUS_MESSAGE_METHOD_RETURN) {
b7f247e0
LP
1681
1682 if (reply)
1683 *reply = incoming;
1684 else
1685 sd_bus_message_unref(incoming);
1686
7a37d625 1687 return 1;
de1c301e
LP
1688 }
1689
40ca29a1 1690 if (incoming->header->type == SD_BUS_MESSAGE_METHOD_ERROR) {
de1c301e
LP
1691 int k;
1692
1693 r = sd_bus_error_copy(error, &incoming->error);
1694 if (r < 0) {
1695 sd_bus_message_unref(incoming);
1696 return r;
1697 }
1698
40ca29a1 1699 k = sd_bus_error_get_errno(&incoming->error);
de1c301e 1700 sd_bus_message_unref(incoming);
40ca29a1 1701 return -k;
de1c301e
LP
1702 }
1703
1704 sd_bus_message_unref(incoming);
1705 return -EIO;
a8a07f89
LP
1706
1707 } else if (incoming->header->serial == serial &&
1708 bus->unique_name &&
1709 incoming->sender &&
1710 streq(bus->unique_name, incoming->sender)) {
1711
1712 /* Our own message? Somebody is trying
1713 * to send its own client a message,
1714 * let's not dead-lock, let's fail
1715 * immediately. */
1716
1717 sd_bus_message_unref(incoming);
1718 return -ELOOP;
de1c301e
LP
1719 }
1720
1721 /* There's already guaranteed to be room for
1722 * this, so need to resize things here */
1723 bus->rqueue[bus->rqueue_size ++] = incoming;
1724 room = false;
1725
1726 /* Try to read more, right-away */
1727 continue;
1728 }
e3017af9
LP
1729 if (r != 0)
1730 continue;
de1c301e
LP
1731
1732 if (timeout > 0) {
1733 usec_t n;
1734
1735 n = now(CLOCK_MONOTONIC);
1736 if (n >= timeout)
1737 return -ETIMEDOUT;
1738
1739 left = timeout - n;
1740 } else
1741 left = (uint64_t) -1;
1742
e3017af9 1743 r = bus_poll(bus, true, left);
de1c301e
LP
1744 if (r < 0)
1745 return r;
1746
1747 r = dispatch_wqueue(bus);
1748 if (r < 0)
1749 return r;
1750 }
1751}
1752
d9f644e2 1753_public_ int sd_bus_get_fd(sd_bus *bus) {
d6888822
LP
1754
1755 assert_return(bus, -EINVAL);
d6888822
LP
1756 assert_return(bus->input_fd == bus->output_fd, -EPERM);
1757 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 1758
e82c9509 1759 return bus->input_fd;
de1c301e
LP
1760}
1761
d9f644e2 1762_public_ int sd_bus_get_events(sd_bus *bus) {
de1c301e
LP
1763 int flags = 0;
1764
d6888822 1765 assert_return(bus, -EINVAL);
718db961 1766 assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
d6888822 1767 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e
LP
1768
1769 if (bus->state == BUS_OPENING)
1770 flags |= POLLOUT;
89ffcd2a
LP
1771 else if (bus->state == BUS_AUTHENTICATING) {
1772
2181a7f5 1773 if (bus_socket_auth_needs_write(bus))
89ffcd2a
LP
1774 flags |= POLLOUT;
1775
1776 flags |= POLLIN;
1777
1778 } else if (bus->state == BUS_RUNNING || bus->state == BUS_HELLO) {
de1c301e
LP
1779 if (bus->rqueue_size <= 0)
1780 flags |= POLLIN;
1781 if (bus->wqueue_size > 0)
1782 flags |= POLLOUT;
1783 }
1784
1785 return flags;
1786}
1787
d9f644e2 1788_public_ int sd_bus_get_timeout(sd_bus *bus, uint64_t *timeout_usec) {
e3017af9
LP
1789 struct reply_callback *c;
1790
d6888822
LP
1791 assert_return(bus, -EINVAL);
1792 assert_return(timeout_usec, -EINVAL);
718db961 1793 assert_return(BUS_IS_OPEN(bus->state) || bus->state == BUS_CLOSING, -ENOTCONN);
d6888822 1794 assert_return(!bus_pid_changed(bus), -ECHILD);
e3017af9 1795
718db961
LP
1796 if (bus->state == BUS_CLOSING) {
1797 *timeout_usec = 0;
1798 return 1;
1799 }
1800
e3017af9
LP
1801 if (bus->state == BUS_AUTHENTICATING) {
1802 *timeout_usec = bus->auth_timeout;
1803 return 1;
1804 }
1805
adee69fa
LP
1806 if (bus->state != BUS_RUNNING && bus->state != BUS_HELLO) {
1807 *timeout_usec = (uint64_t) -1;
e3017af9 1808 return 0;
adee69fa 1809 }
e3017af9 1810
8efd6381
LP
1811 if (bus->rqueue_size > 0) {
1812 *timeout_usec = 0;
1813 return 1;
1814 }
1815
e3017af9 1816 c = prioq_peek(bus->reply_callbacks_prioq);
adee69fa
LP
1817 if (!c) {
1818 *timeout_usec = (uint64_t) -1;
e3017af9 1819 return 0;
adee69fa 1820 }
e3017af9
LP
1821
1822 *timeout_usec = c->timeout;
1823 return 1;
1824}
1825
1826static int process_timeout(sd_bus *bus) {
ebcf1f97 1827 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
eb01ba5d 1828 _cleanup_bus_message_unref_ sd_bus_message* m = NULL;
e3017af9
LP
1829 struct reply_callback *c;
1830 usec_t n;
1831 int r;
1832
1833 assert(bus);
1834
1835 c = prioq_peek(bus->reply_callbacks_prioq);
1836 if (!c)
1837 return 0;
1838
1839 n = now(CLOCK_MONOTONIC);
1840 if (c->timeout > n)
1841 return 0;
1842
eb01ba5d
LP
1843 r = bus_message_new_synthetic_error(
1844 bus,
1845 c->serial,
14c24659 1846 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out"),
eb01ba5d
LP
1847 &m);
1848 if (r < 0)
1849 return r;
1850
718db961
LP
1851 r = bus_seal_message(bus, m);
1852 if (r < 0)
1853 return r;
1854
e3017af9
LP
1855 assert_se(prioq_pop(bus->reply_callbacks_prioq) == c);
1856 hashmap_remove(bus->reply_callbacks, &c->serial);
1857
718db961
LP
1858 bus->current = m;
1859 bus->iteration_counter ++;
1860
ebcf1f97
LP
1861 r = c->callback(bus, m, c->userdata, &error_buffer);
1862 r = bus_maybe_reply_error(m, r, &error_buffer);
e3017af9
LP
1863 free(c);
1864
718db961
LP
1865 bus->current = NULL;
1866
ebcf1f97 1867 return r;
e3017af9
LP
1868}
1869
9d373862
LP
1870static int process_hello(sd_bus *bus, sd_bus_message *m) {
1871 assert(bus);
1872 assert(m);
1873
1874 if (bus->state != BUS_HELLO)
1875 return 0;
1876
1877 /* Let's make sure the first message on the bus is the HELLO
1878 * reply. But note that we don't actually parse the message
2181a7f5
LP
1879 * here (we leave that to the usual handling), we just verify
1880 * we don't let any earlier msg through. */
9d373862 1881
40ca29a1
LP
1882 if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
1883 m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
9d373862
LP
1884 return -EIO;
1885
1886 if (m->reply_serial != bus->hello_serial)
1887 return -EIO;
1888
1889 return 0;
1890}
1891
a652755d 1892static int process_reply(sd_bus *bus, sd_bus_message *m) {
ebcf1f97 1893 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
a652755d
LP
1894 struct reply_callback *c;
1895 int r;
1896
1897 assert(bus);
1898 assert(m);
1899
40ca29a1
LP
1900 if (m->header->type != SD_BUS_MESSAGE_METHOD_RETURN &&
1901 m->header->type != SD_BUS_MESSAGE_METHOD_ERROR)
a652755d
LP
1902 return 0;
1903
1904 c = hashmap_remove(bus->reply_callbacks, &m->reply_serial);
1905 if (!c)
1906 return 0;
1907
1908 if (c->timeout != 0)
1909 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
1910
88fe224c
LP
1911 r = sd_bus_message_rewind(m, true);
1912 if (r < 0)
1913 return r;
1914
ebcf1f97
LP
1915 r = c->callback(bus, m, c->userdata, &error_buffer);
1916 r = bus_maybe_reply_error(m, r, &error_buffer);
a652755d
LP
1917 free(c);
1918
ebcf1f97 1919 return r;
a652755d
LP
1920}
1921
1922static int process_filter(sd_bus *bus, sd_bus_message *m) {
ebcf1f97 1923 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
a652755d
LP
1924 struct filter_callback *l;
1925 int r;
1926
392d5b37
LP
1927 assert(bus);
1928 assert(m);
1929
7286037f
LP
1930 do {
1931 bus->filter_callbacks_modified = false;
1932
1933 LIST_FOREACH(callbacks, l, bus->filter_callbacks) {
1934
1935 if (bus->filter_callbacks_modified)
1936 break;
1937
1938 /* Don't run this more than once per iteration */
1939 if (l->last_iteration == bus->iteration_counter)
1940 continue;
1941
1942 l->last_iteration = bus->iteration_counter;
1943
88fe224c
LP
1944 r = sd_bus_message_rewind(m, true);
1945 if (r < 0)
1946 return r;
1947
969987ea 1948 r = l->callback(bus, m, l->userdata, &error_buffer);
ebcf1f97 1949 r = bus_maybe_reply_error(m, r, &error_buffer);
7286037f
LP
1950 if (r != 0)
1951 return r;
1952
1953 }
1954
1955 } while (bus->filter_callbacks_modified);
a652755d
LP
1956
1957 return 0;
1958}
1959
392d5b37 1960static int process_match(sd_bus *bus, sd_bus_message *m) {
7286037f
LP
1961 int r;
1962
392d5b37
LP
1963 assert(bus);
1964 assert(m);
1965
7286037f
LP
1966 do {
1967 bus->match_callbacks_modified = false;
1968
eb01ba5d 1969 r = bus_match_run(bus, &bus->match_callbacks, m);
7286037f
LP
1970 if (r != 0)
1971 return r;
1972
1973 } while (bus->match_callbacks_modified);
1974
1975 return 0;
392d5b37
LP
1976}
1977
b9bf7e2b
LP
1978static int process_builtin(sd_bus *bus, sd_bus_message *m) {
1979 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
1980 int r;
1981
1982 assert(bus);
1983 assert(m);
1984
40ca29a1 1985 if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL)
b9bf7e2b
LP
1986 return 0;
1987
1988 if (!streq_ptr(m->interface, "org.freedesktop.DBus.Peer"))
1989 return 0;
1990
1991 if (m->header->flags & SD_BUS_MESSAGE_NO_REPLY_EXPECTED)
1992 return 1;
1993
1994 if (streq_ptr(m->member, "Ping"))
df2d202e 1995 r = sd_bus_message_new_method_return(m, &reply);
b9bf7e2b
LP
1996 else if (streq_ptr(m->member, "GetMachineId")) {
1997 sd_id128_t id;
1998 char sid[33];
1999
2000 r = sd_id128_get_machine(&id);
2001 if (r < 0)
2002 return r;
2003
df2d202e 2004 r = sd_bus_message_new_method_return(m, &reply);
b9bf7e2b
LP
2005 if (r < 0)
2006 return r;
2007
2008 r = sd_bus_message_append(reply, "s", sd_id128_to_string(id, sid));
2009 } else {
29ddb38f 2010 r = sd_bus_message_new_method_errorf(
df2d202e 2011 m, &reply,
40ca29a1 2012 SD_BUS_ERROR_UNKNOWN_METHOD,
b9bf7e2b 2013 "Unknown method '%s' on interface '%s'.", m->member, m->interface);
b9bf7e2b
LP
2014 }
2015
2016 if (r < 0)
2017 return r;
2018
2019 r = sd_bus_send(bus, reply, NULL);
2020 if (r < 0)
2021 return r;
2022
2023 return 1;
2024}
2025
992c052c 2026static int process_message(sd_bus *bus, sd_bus_message *m) {
e3017af9
LP
2027 int r;
2028
2029 assert(bus);
992c052c 2030 assert(m);
e3017af9 2031
affff0b6 2032 bus->current = m;
992c052c 2033 bus->iteration_counter++;
e3017af9 2034
40ca29a1
LP
2035 log_debug("Got message sender=%s object=%s interface=%s member=%s",
2036 strna(sd_bus_message_get_sender(m)),
2037 strna(sd_bus_message_get_path(m)),
2038 strna(sd_bus_message_get_interface(m)),
2039 strna(sd_bus_message_get_member(m)));
2040
992c052c
LP
2041 r = process_hello(bus, m);
2042 if (r != 0)
affff0b6 2043 goto finish;
a652755d 2044
992c052c
LP
2045 r = process_reply(bus, m);
2046 if (r != 0)
affff0b6 2047 goto finish;
e3017af9 2048
992c052c
LP
2049 r = process_filter(bus, m);
2050 if (r != 0)
affff0b6 2051 goto finish;
a652755d 2052
992c052c
LP
2053 r = process_match(bus, m);
2054 if (r != 0)
affff0b6 2055 goto finish;
a652755d 2056
992c052c
LP
2057 r = process_builtin(bus, m);
2058 if (r != 0)
affff0b6
LP
2059 goto finish;
2060
2061 r = bus_process_object(bus, m);
a652755d 2062
affff0b6
LP
2063finish:
2064 bus->current = NULL;
2065 return r;
29ddb38f 2066}
88fe224c 2067
992c052c
LP
2068static int process_running(sd_bus *bus, sd_bus_message **ret) {
2069 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
29ddb38f 2070 int r;
a652755d 2071
29ddb38f 2072 assert(bus);
992c052c 2073 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
7286037f 2074
992c052c
LP
2075 r = process_timeout(bus);
2076 if (r != 0)
2077 goto null_message;
7286037f 2078
992c052c
LP
2079 r = dispatch_wqueue(bus);
2080 if (r != 0)
2081 goto null_message;
7286037f 2082
992c052c
LP
2083 r = dispatch_rqueue(bus, &m);
2084 if (r < 0)
2085 return r;
2086 if (!m)
2087 goto null_message;
7286037f 2088
992c052c
LP
2089 r = process_message(bus, m);
2090 if (r != 0)
2091 goto null_message;
7286037f 2092
992c052c
LP
2093 if (ret) {
2094 r = sd_bus_message_rewind(m, true);
29ddb38f
LP
2095 if (r < 0)
2096 return r;
e3017af9 2097
992c052c
LP
2098 *ret = m;
2099 m = NULL;
2100 return 1;
2101 }
a652755d 2102
40ca29a1 2103 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL) {
a652755d 2104
992c052c 2105 r = sd_bus_reply_method_errorf(
df2d202e 2106 m,
40ca29a1 2107 SD_BUS_ERROR_UNKNOWN_OBJECT,
992c052c 2108 "Unknown object '%s'.", m->path);
29ddb38f
LP
2109 if (r < 0)
2110 return r;
2111 }
e3017af9 2112
992c052c 2113 return 1;
0a72c2bd 2114
992c052c
LP
2115null_message:
2116 if (r >= 0 && ret)
2117 *ret = NULL;
0a72c2bd 2118
992c052c 2119 return r;
29ddb38f 2120}
0a72c2bd 2121
718db961
LP
2122static int process_closing(sd_bus *bus, sd_bus_message **ret) {
2123 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
2124 struct reply_callback *c;
2125 int r;
2126
2127 assert(bus);
2128 assert(bus->state == BUS_CLOSING);
2129
2130 c = hashmap_first(bus->reply_callbacks);
2131 if (c) {
ebcf1f97
LP
2132 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
2133
718db961
LP
2134 /* First, fail all outstanding method calls */
2135 r = bus_message_new_synthetic_error(
2136 bus,
2137 c->serial,
14c24659 2138 &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Connection terminated"),
718db961
LP
2139 &m);
2140 if (r < 0)
2141 return r;
2142
2143 r = bus_seal_message(bus, m);
2144 if (r < 0)
2145 return r;
2146
2147 if (c->timeout != 0)
2148 prioq_remove(bus->reply_callbacks_prioq, c, &c->prioq_idx);
2149
2150 hashmap_remove(bus->reply_callbacks, &c->serial);
2151
2152 bus->current = m;
2153 bus->iteration_counter++;
2154
ebcf1f97
LP
2155 r = c->callback(bus, m, c->userdata, &error_buffer);
2156 r = bus_maybe_reply_error(m, r, &error_buffer);
718db961
LP
2157 free(c);
2158
718db961
LP
2159 goto finish;
2160 }
2161
2162 /* Then, synthesize a Disconnected message */
2163 r = sd_bus_message_new_signal(
2164 bus,
2165 "/org/freedesktop/DBus/Local",
2166 "org.freedesktop.DBus.Local",
2167 "Disconnected",
2168 &m);
2169 if (r < 0)
2170 return r;
2171
2172 r = bus_seal_message(bus, m);
2173 if (r < 0)
2174 return r;
2175
2176 sd_bus_close(bus);
2177
2178 bus->current = m;
2179 bus->iteration_counter++;
2180
2181 r = process_filter(bus, m);
2182 if (r != 0)
2183 goto finish;
2184
2185 r = process_match(bus, m);
2186 if (r != 0)
2187 goto finish;
2188
2189 if (ret) {
2190 *ret = m;
2191 m = NULL;
2192 }
2193
2194 r = 1;
2195
2196finish:
2197 bus->current = NULL;
2198 return r;
2199}
2200
d9f644e2 2201_public_ int sd_bus_process(sd_bus *bus, sd_bus_message **ret) {
8ce2afd6 2202 BUS_DONT_DESTROY(bus);
29ddb38f 2203 int r;
0a72c2bd 2204
992c052c
LP
2205 /* Returns 0 when we didn't do anything. This should cause the
2206 * caller to invoke sd_bus_wait() before returning the next
2207 * time. Returns > 0 when we did something, which possibly
2208 * means *ret is filled in with an unprocessed message. */
0a72c2bd 2209
d6888822
LP
2210 assert_return(bus, -EINVAL);
2211 assert_return(!bus_pid_changed(bus), -ECHILD);
0a72c2bd 2212
992c052c 2213 /* We don't allow recursively invoking sd_bus_process(). */
718db961 2214 assert_return(!bus->current, -EBUSY);
0a72c2bd 2215
992c052c 2216 switch (bus->state) {
0a72c2bd 2217
992c052c
LP
2218 case BUS_UNSET:
2219 case BUS_CLOSED:
2220 return -ENOTCONN;
0a72c2bd 2221
992c052c
LP
2222 case BUS_OPENING:
2223 r = bus_socket_process_opening(bus);
718db961
LP
2224 if (r == -ECONNRESET || r == -EPIPE) {
2225 bus_enter_closing(bus);
2226 r = 1;
2227 } else if (r < 0)
29ddb38f 2228 return r;
992c052c
LP
2229 if (ret)
2230 *ret = NULL;
a652755d
LP
2231 return r;
2232
992c052c 2233 case BUS_AUTHENTICATING:
992c052c 2234 r = bus_socket_process_authenticating(bus);
718db961
LP
2235 if (r == -ECONNRESET || r == -EPIPE) {
2236 bus_enter_closing(bus);
2237 r = 1;
2238 } else if (r < 0)
29ddb38f 2239 return r;
718db961 2240
992c052c
LP
2241 if (ret)
2242 *ret = NULL;
718db961 2243
992c052c 2244 return r;
a652755d 2245
992c052c
LP
2246 case BUS_RUNNING:
2247 case BUS_HELLO:
992c052c 2248 r = process_running(bus, ret);
718db961
LP
2249 if (r == -ECONNRESET || r == -EPIPE) {
2250 bus_enter_closing(bus);
2251 r = 1;
2252
2253 if (ret)
2254 *ret = NULL;
2255 }
43a43f50 2256
43a43f50 2257 return r;
718db961
LP
2258
2259 case BUS_CLOSING:
2260 return process_closing(bus, ret);
992c052c 2261 }
43a43f50 2262
992c052c 2263 assert_not_reached("Unknown state");
e3017af9
LP
2264}
2265
992c052c
LP
2266static int bus_poll(sd_bus *bus, bool need_more, uint64_t timeout_usec) {
2267 struct pollfd p[2] = {};
2268 int r, e, n;
2269 struct timespec ts;
8efd6381 2270 usec_t m = (usec_t) -1;
adcdb374
LP
2271
2272 assert(bus);
718db961
LP
2273
2274 if (bus->state == BUS_CLOSING)
2275 return 1;
2276
d6888822 2277 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
adcdb374 2278
992c052c
LP
2279 e = sd_bus_get_events(bus);
2280 if (e < 0)
2281 return e;
adcdb374 2282
992c052c 2283 if (need_more)
8efd6381
LP
2284 /* The caller really needs some more data, he doesn't
2285 * care about what's already read, or any timeouts
2286 * except its own.*/
992c052c 2287 e |= POLLIN;
992c052c 2288 else {
8efd6381
LP
2289 usec_t until;
2290 /* The caller wants to process if there's something to
2291 * process, but doesn't care otherwise */
2292
2293 r = sd_bus_get_timeout(bus, &until);
2294 if (r < 0)
2295 return r;
2296 if (r > 0) {
2297 usec_t nw;
2298 nw = now(CLOCK_MONOTONIC);
2299 m = until > nw ? until - nw : 0;
2300 }
992c052c 2301 }
adcdb374 2302
992c052c
LP
2303 if (timeout_usec != (uint64_t) -1 && (m == (uint64_t) -1 || timeout_usec < m))
2304 m = timeout_usec;
adcdb374 2305
992c052c
LP
2306 p[0].fd = bus->input_fd;
2307 if (bus->output_fd == bus->input_fd) {
2308 p[0].events = e;
2309 n = 1;
2310 } else {
2311 p[0].events = e & POLLIN;
2312 p[1].fd = bus->output_fd;
2313 p[1].events = e & POLLOUT;
2314 n = 2;
adcdb374
LP
2315 }
2316
992c052c 2317 r = ppoll(p, n, m == (uint64_t) -1 ? NULL : timespec_store(&ts, m), NULL);
adcdb374 2318 if (r < 0)
992c052c 2319 return -errno;
adcdb374 2320
992c052c 2321 return r > 0 ? 1 : 0;
adcdb374
LP
2322}
2323
d9f644e2 2324_public_ int sd_bus_wait(sd_bus *bus, uint64_t timeout_usec) {
9db76355 2325
d6888822 2326 assert_return(bus, -EINVAL);
d6888822 2327 assert_return(!bus_pid_changed(bus), -ECHILD);
9db76355 2328
718db961
LP
2329 if (bus->state == BUS_CLOSING)
2330 return 0;
2331
2332 assert_return(BUS_IS_OPEN(bus->state) , -ENOTCONN);
2333
992c052c
LP
2334 if (bus->rqueue_size > 0)
2335 return 0;
9db76355 2336
992c052c
LP
2337 return bus_poll(bus, false, timeout_usec);
2338}
9db76355 2339
d9f644e2 2340_public_ int sd_bus_flush(sd_bus *bus) {
992c052c 2341 int r;
9db76355 2342
d6888822 2343 assert_return(bus, -EINVAL);
d6888822 2344 assert_return(!bus_pid_changed(bus), -ECHILD);
9db76355 2345
718db961
LP
2346 if (bus->state == BUS_CLOSING)
2347 return 0;
2348
2349 assert_return(BUS_IS_OPEN(bus->state), -ENOTCONN);
2350
992c052c
LP
2351 r = bus_ensure_running(bus);
2352 if (r < 0)
2353 return r;
9db76355 2354
992c052c
LP
2355 if (bus->wqueue_size <= 0)
2356 return 0;
9db76355 2357
992c052c
LP
2358 for (;;) {
2359 r = dispatch_wqueue(bus);
9db76355
LP
2360 if (r < 0)
2361 return r;
2362
992c052c
LP
2363 if (bus->wqueue_size <= 0)
2364 return 0;
9db76355 2365
992c052c 2366 r = bus_poll(bus, false, (uint64_t) -1);
9db76355
LP
2367 if (r < 0)
2368 return r;
9db76355 2369 }
9db76355
LP
2370}
2371
d9f644e2
ZJS
2372_public_ int sd_bus_add_filter(sd_bus *bus,
2373 sd_bus_message_handler_t callback,
2374 void *userdata) {
2375
992c052c 2376 struct filter_callback *f;
de1c301e 2377
d6888822
LP
2378 assert_return(bus, -EINVAL);
2379 assert_return(callback, -EINVAL);
2380 assert_return(!bus_pid_changed(bus), -ECHILD);
de1c301e 2381
992c052c
LP
2382 f = new0(struct filter_callback, 1);
2383 if (!f)
29ddb38f 2384 return -ENOMEM;
992c052c
LP
2385 f->callback = callback;
2386 f->userdata = userdata;
29ddb38f 2387
992c052c 2388 bus->filter_callbacks_modified = true;
71fda00f 2389 LIST_PREPEND(callbacks, bus->filter_callbacks, f);
de1c301e
LP
2390 return 0;
2391}
a652755d 2392
d9f644e2
ZJS
2393_public_ int sd_bus_remove_filter(sd_bus *bus,
2394 sd_bus_message_handler_t callback,
2395 void *userdata) {
2396
992c052c 2397 struct filter_callback *f;
a652755d 2398
d6888822
LP
2399 assert_return(bus, -EINVAL);
2400 assert_return(callback, -EINVAL);
2401 assert_return(!bus_pid_changed(bus), -ECHILD);
a652755d 2402
992c052c
LP
2403 LIST_FOREACH(callbacks, f, bus->filter_callbacks) {
2404 if (f->callback == callback && f->userdata == userdata) {
2405 bus->filter_callbacks_modified = true;
71fda00f 2406 LIST_REMOVE(callbacks, bus->filter_callbacks, f);
992c052c
LP
2407 free(f);
2408 return 1;
29ddb38f
LP
2409 }
2410 }
2411
992c052c 2412 return 0;
a652755d 2413}
392d5b37 2414
d9f644e2
ZJS
2415_public_ int sd_bus_add_match(sd_bus *bus,
2416 const char *match,
2417 sd_bus_message_handler_t callback,
2418 void *userdata) {
2419
992c052c
LP
2420 struct bus_match_component *components = NULL;
2421 unsigned n_components = 0;
2422 uint64_t cookie = 0;
2423 int r = 0;
392d5b37 2424
d6888822
LP
2425 assert_return(bus, -EINVAL);
2426 assert_return(match, -EINVAL);
2427 assert_return(!bus_pid_changed(bus), -ECHILD);
392d5b37 2428
992c052c
LP
2429 r = bus_match_parse(match, &components, &n_components);
2430 if (r < 0)
2431 goto finish;
29ddb38f 2432
992c052c
LP
2433 if (bus->bus_client) {
2434 cookie = ++bus->match_cookie;
29ddb38f 2435
992c052c
LP
2436 r = bus_add_match_internal(bus, match, components, n_components, cookie);
2437 if (r < 0)
2438 goto finish;
392d5b37
LP
2439 }
2440
992c052c
LP
2441 bus->match_callbacks_modified = true;
2442 r = bus_match_add(&bus->match_callbacks, components, n_components, callback, userdata, cookie, NULL);
29ddb38f 2443 if (r < 0) {
992c052c
LP
2444 if (bus->bus_client)
2445 bus_remove_match_internal(bus, match, cookie);
29ddb38f 2446 }
917b5dc7 2447
992c052c
LP
2448finish:
2449 bus_match_parse_free(components, n_components);
2450 return r;
917b5dc7
LP
2451}
2452
d9f644e2
ZJS
2453_public_ int sd_bus_remove_match(sd_bus *bus,
2454 const char *match,
2455 sd_bus_message_handler_t callback,
2456 void *userdata) {
2457
992c052c
LP
2458 struct bus_match_component *components = NULL;
2459 unsigned n_components = 0;
2460 int r = 0, q = 0;
2461 uint64_t cookie = 0;
917b5dc7 2462
d6888822
LP
2463 assert_return(bus, -EINVAL);
2464 assert_return(match, -EINVAL);
2465 assert_return(!bus_pid_changed(bus), -ECHILD);
917b5dc7 2466
992c052c 2467 r = bus_match_parse(match, &components, &n_components);
29ddb38f
LP
2468 if (r < 0)
2469 return r;
f10dda3b 2470
992c052c
LP
2471 bus->match_callbacks_modified = true;
2472 r = bus_match_remove(&bus->match_callbacks, components, n_components, callback, userdata, &cookie);
f10dda3b 2473
992c052c
LP
2474 if (bus->bus_client)
2475 q = bus_remove_match_internal(bus, match, cookie);
f10dda3b 2476
992c052c 2477 bus_match_parse_free(components, n_components);
f10dda3b 2478
992c052c 2479 return r < 0 ? r : q;
f10dda3b
LP
2480}
2481
992c052c
LP
2482bool bus_pid_changed(sd_bus *bus) {
2483 assert(bus);
f10dda3b 2484
992c052c
LP
2485 /* We don't support people creating a bus connection and
2486 * keeping it around over a fork(). Let's complain. */
d5a2b9a6 2487
992c052c 2488 return bus->original_pid != getpid();
d5a2b9a6 2489}
40ca29a1
LP
2490
2491static int io_callback(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
0927756b 2492 sd_bus *bus = userdata;
40ca29a1
LP
2493 int r;
2494
2495 assert(bus);
2496
2497 r = sd_bus_process(bus, NULL);
2498 if (r < 0)
2499 return r;
2500
2501 return 1;
2502}
2503
2504static int time_callback(sd_event_source *s, uint64_t usec, void *userdata) {
0927756b 2505 sd_bus *bus = userdata;
40ca29a1
LP
2506 int r;
2507
2508 assert(bus);
2509
2510 r = sd_bus_process(bus, NULL);
2511 if (r < 0)
2512 return r;
2513
2514 return 1;
2515}
2516
2517static int prepare_callback(sd_event_source *s, void *userdata) {
2518 sd_bus *bus = userdata;
2519 int r, e;
2520 usec_t until;
2521
2522 assert(s);
2523 assert(bus);
2524
2525 e = sd_bus_get_events(bus);
2526 if (e < 0)
2527 return e;
2528
2529 if (bus->output_fd != bus->input_fd) {
2530
2531 r = sd_event_source_set_io_events(bus->input_io_event_source, e & POLLIN);
2532 if (r < 0)
2533 return r;
2534
2535 r = sd_event_source_set_io_events(bus->output_io_event_source, e & POLLOUT);
2536 if (r < 0)
2537 return r;
2538 } else {
2539 r = sd_event_source_set_io_events(bus->input_io_event_source, e);
2540 if (r < 0)
2541 return r;
2542 }
2543
2544 r = sd_bus_get_timeout(bus, &until);
2545 if (r < 0)
2546 return r;
2547 if (r > 0) {
2548 int j;
2549
2550 j = sd_event_source_set_time(bus->time_event_source, until);
2551 if (j < 0)
2552 return j;
2553 }
2554
2555 r = sd_event_source_set_enabled(bus->time_event_source, r > 0);
2556 if (r < 0)
2557 return r;
2558
2559 return 1;
2560}
2561
abc5fe72
LP
2562static int quit_callback(sd_event_source *event, void *userdata) {
2563 sd_bus *bus = userdata;
2564
2565 assert(event);
2566
2567 sd_bus_flush(bus);
2568
2569 return 1;
2570}
2571
d9f644e2 2572_public_ int sd_bus_attach_event(sd_bus *bus, sd_event *event, int priority) {
40ca29a1
LP
2573 int r;
2574
2575 assert_return(bus, -EINVAL);
40ca29a1
LP
2576 assert_return(!bus->event, -EBUSY);
2577
2578 assert(!bus->input_io_event_source);
2579 assert(!bus->output_io_event_source);
2580 assert(!bus->time_event_source);
2581
76b54375
LP
2582 if (event)
2583 bus->event = sd_event_ref(event);
2584 else {
2585 r = sd_event_default(&bus->event);
2586 if (r < 0)
2587 return r;
2588 }
40ca29a1 2589
76b54375 2590 r = sd_event_add_io(bus->event, bus->input_fd, 0, io_callback, bus, &bus->input_io_event_source);
40ca29a1
LP
2591 if (r < 0)
2592 goto fail;
2593
2594 r = sd_event_source_set_priority(bus->input_io_event_source, priority);
2595 if (r < 0)
2596 goto fail;
2597
2598 if (bus->output_fd != bus->input_fd) {
76b54375 2599 r = sd_event_add_io(bus->event, bus->output_fd, 0, io_callback, bus, &bus->output_io_event_source);
40ca29a1
LP
2600 if (r < 0)
2601 goto fail;
2602
2603 r = sd_event_source_set_priority(bus->output_io_event_source, priority);
2604 if (r < 0)
2605 goto fail;
2606 }
2607
2608 r = sd_event_source_set_prepare(bus->input_io_event_source, prepare_callback);
2609 if (r < 0)
2610 goto fail;
2611
76b54375 2612 r = sd_event_add_monotonic(bus->event, 0, 0, time_callback, bus, &bus->time_event_source);
40ca29a1
LP
2613 if (r < 0)
2614 goto fail;
2615
2616 r = sd_event_source_set_priority(bus->time_event_source, priority);
2617 if (r < 0)
2618 goto fail;
2619
76b54375 2620 r = sd_event_add_quit(bus->event, quit_callback, bus, &bus->quit_event_source);
abc5fe72
LP
2621 if (r < 0)
2622 goto fail;
2623
40ca29a1
LP
2624 return 0;
2625
2626fail:
2627 sd_bus_detach_event(bus);
2628 return r;
2629}
2630
d9f644e2 2631_public_ int sd_bus_detach_event(sd_bus *bus) {
40ca29a1
LP
2632 assert_return(bus, -EINVAL);
2633 assert_return(bus->event, -ENXIO);
2634
86befb40
LP
2635 if (bus->input_io_event_source) {
2636 sd_event_source_set_enabled(bus->input_io_event_source, SD_EVENT_OFF);
40ca29a1 2637 bus->input_io_event_source = sd_event_source_unref(bus->input_io_event_source);
86befb40 2638 }
40ca29a1 2639
86befb40
LP
2640 if (bus->output_io_event_source) {
2641 sd_event_source_set_enabled(bus->output_io_event_source, SD_EVENT_OFF);
40ca29a1 2642 bus->output_io_event_source = sd_event_source_unref(bus->output_io_event_source);
86befb40 2643 }
40ca29a1 2644
86befb40
LP
2645 if (bus->time_event_source) {
2646 sd_event_source_set_enabled(bus->time_event_source, SD_EVENT_OFF);
40ca29a1 2647 bus->time_event_source = sd_event_source_unref(bus->time_event_source);
86befb40 2648 }
40ca29a1 2649
86befb40
LP
2650 if (bus->quit_event_source) {
2651 sd_event_source_set_enabled(bus->quit_event_source, SD_EVENT_OFF);
abc5fe72 2652 bus->quit_event_source = sd_event_source_unref(bus->quit_event_source);
86befb40 2653 }
abc5fe72 2654
40ca29a1
LP
2655 if (bus->event)
2656 bus->event = sd_event_unref(bus->event);
2657
2658 return 0;
2659}
affff0b6 2660
2be44176
LP
2661_public_ sd_event* sd_bus_get_event(sd_bus *bus) {
2662 assert_return(bus, NULL);
2663
2664 return bus->event;
2665}
2666
76b54375 2667_public_ sd_bus_message* sd_bus_get_current(sd_bus *bus) {
affff0b6
LP
2668 assert_return(bus, NULL);
2669
2670 return bus->current;
2671}
76b54375
LP
2672
2673static int bus_default(int (*bus_open)(sd_bus **), sd_bus **default_bus, sd_bus **ret) {
2674 sd_bus *b = NULL;
2675 int r;
2676
2677 assert(bus_open);
2678 assert(default_bus);
2679
2680 if (!ret)
2681 return !!*default_bus;
2682
2683 if (*default_bus) {
2684 *ret = sd_bus_ref(*default_bus);
2685 return 0;
2686 }
2687
2688 r = bus_open(&b);
2689 if (r < 0)
2690 return r;
2691
2692 b->default_bus_ptr = default_bus;
2693 b->tid = gettid();
2694 *default_bus = b;
2695
2696 *ret = b;
2697 return 1;
2698}
2699
2700_public_ int sd_bus_default_system(sd_bus **ret) {
2701 static __thread sd_bus *default_system_bus = NULL;
2702
2703 return bus_default(sd_bus_open_system, &default_system_bus, ret);
2704}
2705
2706_public_ int sd_bus_default_user(sd_bus **ret) {
2707 static __thread sd_bus *default_user_bus = NULL;
2708
2709 return bus_default(sd_bus_open_user, &default_user_bus, ret);
2710}
2711
2712_public_ int sd_bus_get_tid(sd_bus *b, pid_t *tid) {
2713 assert_return(b, -EINVAL);
2714 assert_return(tid, -EINVAL);
2715 assert_return(!bus_pid_changed(b), -ECHILD);
2716
2717 if (b->tid != 0) {
2718 *tid = b->tid;
2719 return 0;
2720 }
2721
2722 if (b->event)
2723 return sd_event_get_tid(b->event, tid);
2724
2725 return -ENXIO;
2726}
28383ba1
LP
2727
2728_public_ char *sd_bus_label_escape(const char *s) {
2729 char *r, *t;
2730 const char *f;
2731
2732 assert_return(s, NULL);
2733
2734 /* Escapes all chars that D-Bus' object path cannot deal
2735 * with. Can be reversed with bus_path_unescape(). We special
2736 * case the empty string. */
2737
2738 if (*s == 0)
2739 return strdup("_");
2740
2741 r = new(char, strlen(s)*3 + 1);
2742 if (!r)
2743 return NULL;
2744
2745 for (f = s, t = r; *f; f++) {
2746
2747 /* Escape everything that is not a-zA-Z0-9. We also
2748 * escape 0-9 if it's the first character */
2749
2750 if (!(*f >= 'A' && *f <= 'Z') &&
2751 !(*f >= 'a' && *f <= 'z') &&
2752 !(f > s && *f >= '0' && *f <= '9')) {
2753 *(t++) = '_';
2754 *(t++) = hexchar(*f >> 4);
2755 *(t++) = hexchar(*f);
2756 } else
2757 *(t++) = *f;
2758 }
2759
2760 *t = 0;
2761
2762 return r;
2763}
2764
2765_public_ char *sd_bus_label_unescape(const char *f) {
2766 char *r, *t;
2767
2768 assert_return(f, NULL);
2769
2770 /* Special case for the empty string */
2771 if (streq(f, "_"))
2772 return strdup("");
2773
2774 r = new(char, strlen(f) + 1);
2775 if (!r)
2776 return NULL;
2777
2778 for (t = r; *f; f++) {
2779
2780 if (*f == '_') {
2781 int a, b;
2782
2783 if ((a = unhexchar(f[1])) < 0 ||
2784 (b = unhexchar(f[2])) < 0) {
2785 /* Invalid escape code, let's take it literal then */
2786 *(t++) = '_';
2787 } else {
2788 *(t++) = (char) ((a << 4) | b);
2789 f += 2;
2790 }
2791 } else
2792 *(t++) = *f;
2793 }
2794
2795 *t = 0;
2796
2797 return r;
2798}