chiark / gitweb /
networkd,resolved: make use of watch_bind feature to connect to the bus
[elogind.git] / src / shared / bus-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2 /***
3   This file is part of systemd.
4
5   Copyright 2013 Lennart Poettering
6
7   systemd is free software; you can redistribute it and/or modify it
8   under the terms of the GNU Lesser General Public License as published by
9   the Free Software Foundation; either version 2.1 of the License, or
10   (at your option) any later version.
11
12   systemd is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   Lesser General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with systemd; If not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #include <errno.h>
22 #include <fcntl.h>
23 #include <inttypes.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <sys/ioctl.h>
28 #include <sys/resource.h>
29 #include <sys/socket.h>
30 #include <unistd.h>
31
32 #include "sd-bus-protocol.h"
33 #include "sd-bus.h"
34 #include "sd-daemon.h"
35 #include "sd-event.h"
36 #include "sd-id128.h"
37
38 #include "alloc-util.h"
39 #include "bus-internal.h"
40 #include "bus-label.h"
41 #include "bus-message.h"
42 #include "bus-util.h"
43 #include "cap-list.h"
44 #include "cgroup-util.h"
45 #include "def.h"
46 #include "escape.h"
47 #include "fd-util.h"
48 #include "missing.h"
49 #include "mount-util.h"
50 #include "nsflags.h"
51 #include "parse-util.h"
52 #include "proc-cmdline.h"
53 //#include "rlimit-util.h"
54 #include "stdio-util.h"
55 #include "strv.h"
56 #include "user-util.h"
57
58 #if 0 /// UNNEEDED by elogind
59 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
60         sd_event *e = userdata;
61
62         assert(m);
63         assert(e);
64
65         sd_bus_close(sd_bus_message_get_bus(m));
66         sd_event_exit(e, 0);
67
68         return 1;
69 }
70
71 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
72         const char *match;
73         const char *unique;
74         int r;
75
76         assert(e);
77         assert(bus);
78         assert(name);
79
80         /* We unregister the name here and then wait for the
81          * NameOwnerChanged signal for this event to arrive before we
82          * quit. We do this in order to make sure that any queued
83          * requests are still processed before we really exit. */
84
85         r = sd_bus_get_unique_name(bus, &unique);
86         if (r < 0)
87                 return r;
88
89         match = strjoina(
90                         "sender='org.freedesktop.DBus',"
91                         "type='signal',"
92                         "interface='org.freedesktop.DBus',"
93                         "member='NameOwnerChanged',"
94                         "path='/org/freedesktop/DBus',"
95                         "arg0='", name, "',",
96                         "arg1='", unique, "',",
97                         "arg2=''");
98
99         r = sd_bus_add_match_async(bus, NULL, match, name_owner_change_callback, NULL, e);
100         if (r < 0)
101                 return r;
102
103         r = sd_bus_release_name_async(bus, NULL, name, NULL, NULL);
104         if (r < 0)
105                 return r;
106
107         return 0;
108 }
109
110 int bus_event_loop_with_idle(
111                 sd_event *e,
112                 sd_bus *bus,
113                 const char *name,
114                 usec_t timeout,
115                 check_idle_t check_idle,
116                 void *userdata) {
117         bool exiting = false;
118         int r, code;
119
120         assert(e);
121         assert(bus);
122         assert(name);
123
124         for (;;) {
125                 bool idle;
126
127                 r = sd_event_get_state(e);
128                 if (r < 0)
129                         return r;
130                 if (r == SD_EVENT_FINISHED)
131                         break;
132
133                 if (check_idle)
134                         idle = check_idle(userdata);
135                 else
136                         idle = true;
137
138                 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
139                 if (r < 0)
140                         return r;
141
142                 if (r == 0 && !exiting && idle) {
143
144                         r = sd_bus_try_close(bus);
145                         if (r == -EBUSY)
146                                 continue;
147
148                         /* Fallback for dbus1 connections: we
149                          * unregister the name and wait for the
150                          * response to come through for it */
151                         if (r == -EOPNOTSUPP) {
152
153                                 /* Inform the service manager that we
154                                  * are going down, so that it will
155                                  * queue all further start requests,
156                                  * instead of assuming we are already
157                                  * running. */
158                                 sd_notify(false, "STOPPING=1");
159
160                                 r = bus_async_unregister_and_exit(e, bus, name);
161                                 if (r < 0)
162                                         return r;
163
164                                 exiting = true;
165                                 continue;
166                         }
167
168                         if (r < 0)
169                                 return r;
170
171                         sd_event_exit(e, 0);
172                         break;
173                 }
174         }
175
176         r = sd_event_get_exit_code(e, &code);
177         if (r < 0)
178                 return r;
179
180         return code;
181 }
182 #endif // 0
183
184 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
185         _cleanup_(sd_bus_message_unrefp) sd_bus_message *rep = NULL;
186         int r, has_owner = 0;
187
188         assert(c);
189         assert(name);
190
191         r = sd_bus_call_method(c,
192                                "org.freedesktop.DBus",
193                                "/org/freedesktop/dbus",
194                                "org.freedesktop.DBus",
195                                "NameHasOwner",
196                                error,
197                                &rep,
198                                "s",
199                                name);
200         if (r < 0)
201                 return r;
202
203         r = sd_bus_message_read_basic(rep, 'b', &has_owner);
204         if (r < 0)
205                 return sd_bus_error_set_errno(error, r);
206
207         return has_owner;
208 }
209
210 static int check_good_user(sd_bus_message *m, uid_t good_user) {
211         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
212         uid_t sender_uid;
213         int r;
214
215         assert(m);
216
217         if (good_user == UID_INVALID)
218                 return 0;
219
220         r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
221         if (r < 0)
222                 return r;
223
224         /* Don't trust augmented credentials for authorization */
225         assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
226
227         r = sd_bus_creds_get_euid(creds, &sender_uid);
228         if (r < 0)
229                 return r;
230
231         return sender_uid == good_user;
232 }
233
234 int bus_test_polkit(
235                 sd_bus_message *call,
236                 int capability,
237                 const char *action,
238                 const char **details,
239                 uid_t good_user,
240                 bool *_challenge,
241                 sd_bus_error *e) {
242
243         int r;
244
245         assert(call);
246         assert(action);
247
248         /* Tests non-interactively! */
249
250         r = check_good_user(call, good_user);
251         if (r != 0)
252                 return r;
253
254         r = sd_bus_query_sender_privilege(call, capability);
255         if (r < 0)
256                 return r;
257         else if (r > 0)
258                 return 1;
259 #if ENABLE_POLKIT
260         else {
261                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *request = NULL;
262                 _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
263                 int authorized = false, challenge = false;
264                 const char *sender, **k, **v;
265
266                 sender = sd_bus_message_get_sender(call);
267                 if (!sender)
268                         return -EBADMSG;
269
270                 r = sd_bus_message_new_method_call(
271                                 call->bus,
272                                 &request,
273                                 "org.freedesktop.PolicyKit1",
274                                 "/org/freedesktop/PolicyKit1/Authority",
275                                 "org.freedesktop.PolicyKit1.Authority",
276                                 "CheckAuthorization");
277                 if (r < 0)
278                         return r;
279
280                 r = sd_bus_message_append(
281                                 request,
282                                 "(sa{sv})s",
283                                 "system-bus-name", 1, "name", "s", sender,
284                                 action);
285                 if (r < 0)
286                         return r;
287
288                 r = sd_bus_message_open_container(request, 'a', "{ss}");
289                 if (r < 0)
290                         return r;
291
292                 STRV_FOREACH_PAIR(k, v, details) {
293                         r = sd_bus_message_append(request, "{ss}", *k, *v);
294                         if (r < 0)
295                                 return r;
296                 }
297
298                 r = sd_bus_message_close_container(request);
299                 if (r < 0)
300                         return r;
301
302                 r = sd_bus_message_append(request, "us", 0, NULL);
303                 if (r < 0)
304                         return r;
305
306                 r = sd_bus_call(call->bus, request, 0, e, &reply);
307                 if (r < 0) {
308                         /* Treat no PK available as access denied */
309                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
310                                 sd_bus_error_free(e);
311                                 return -EACCES;
312                         }
313
314                         return r;
315                 }
316
317                 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
318                 if (r < 0)
319                         return r;
320
321                 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
322                 if (r < 0)
323                         return r;
324
325                 if (authorized)
326                         return 1;
327
328                 if (_challenge) {
329                         *_challenge = challenge;
330                         return 0;
331                 }
332         }
333 #endif
334
335         return -EACCES;
336 }
337
338 #if ENABLE_POLKIT
339
340 typedef struct AsyncPolkitQuery {
341         sd_bus_message *request, *reply;
342         sd_bus_message_handler_t callback;
343         void *userdata;
344         sd_bus_slot *slot;
345         Hashmap *registry;
346 } AsyncPolkitQuery;
347
348 static void async_polkit_query_free(AsyncPolkitQuery *q) {
349
350         if (!q)
351                 return;
352
353         sd_bus_slot_unref(q->slot);
354
355         if (q->registry && q->request)
356                 hashmap_remove(q->registry, q->request);
357
358         sd_bus_message_unref(q->request);
359         sd_bus_message_unref(q->reply);
360
361         free(q);
362 }
363
364 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
365         _cleanup_(sd_bus_error_free) sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
366         AsyncPolkitQuery *q = userdata;
367         int r;
368
369         assert(reply);
370         assert(q);
371
372         q->slot = sd_bus_slot_unref(q->slot);
373         q->reply = sd_bus_message_ref(reply);
374
375         r = sd_bus_message_rewind(q->request, true);
376         if (r < 0) {
377                 r = sd_bus_reply_method_errno(q->request, r, NULL);
378                 goto finish;
379         }
380
381         r = q->callback(q->request, q->userdata, &error_buffer);
382         r = bus_maybe_reply_error(q->request, r, &error_buffer);
383
384 finish:
385         async_polkit_query_free(q);
386
387         return r;
388 }
389
390 #endif
391
392 int bus_verify_polkit_async(
393                 sd_bus_message *call,
394                 int capability,
395                 const char *action,
396                 const char **details,
397                 bool interactive,
398                 uid_t good_user,
399                 Hashmap **registry,
400                 sd_bus_error *error) {
401
402 #if ENABLE_POLKIT
403         _cleanup_(sd_bus_message_unrefp) sd_bus_message *pk = NULL;
404         AsyncPolkitQuery *q;
405         const char *sender, **k, **v;
406         sd_bus_message_handler_t callback;
407         void *userdata;
408         int c;
409 #endif
410         int r;
411
412         assert(call);
413         assert(action);
414         assert(registry);
415
416         r = check_good_user(call, good_user);
417         if (r != 0)
418                 return r;
419
420 #if ENABLE_POLKIT
421         q = hashmap_get(*registry, call);
422         if (q) {
423                 int authorized, challenge;
424
425                 /* This is the second invocation of this function, and
426                  * there's already a response from polkit, let's
427                  * process it */
428                 assert(q->reply);
429
430                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
431                         const sd_bus_error *e;
432
433                         /* Copy error from polkit reply */
434                         e = sd_bus_message_get_error(q->reply);
435                         sd_bus_error_copy(error, e);
436
437                         /* Treat no PK available as access denied */
438                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
439                                 return -EACCES;
440
441                         return -sd_bus_error_get_errno(e);
442                 }
443
444                 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
445                 if (r >= 0)
446                         r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
447
448                 if (r < 0)
449                         return r;
450
451                 if (authorized)
452                         return 1;
453
454                 if (challenge)
455                         return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
456
457                 return -EACCES;
458         }
459 #endif
460
461         r = sd_bus_query_sender_privilege(call, capability);
462         if (r < 0)
463                 return r;
464         else if (r > 0)
465                 return 1;
466
467 #if ENABLE_POLKIT
468         if (sd_bus_get_current_message(call->bus) != call)
469                 return -EINVAL;
470
471         callback = sd_bus_get_current_handler(call->bus);
472         if (!callback)
473                 return -EINVAL;
474
475         userdata = sd_bus_get_current_userdata(call->bus);
476
477         sender = sd_bus_message_get_sender(call);
478         if (!sender)
479                 return -EBADMSG;
480
481         c = sd_bus_message_get_allow_interactive_authorization(call);
482         if (c < 0)
483                 return c;
484         if (c > 0)
485                 interactive = true;
486
487         r = hashmap_ensure_allocated(registry, NULL);
488         if (r < 0)
489                 return r;
490
491         r = sd_bus_message_new_method_call(
492                         call->bus,
493                         &pk,
494                         "org.freedesktop.PolicyKit1",
495                         "/org/freedesktop/PolicyKit1/Authority",
496                         "org.freedesktop.PolicyKit1.Authority",
497                         "CheckAuthorization");
498         if (r < 0)
499                 return r;
500
501         r = sd_bus_message_append(
502                         pk,
503                         "(sa{sv})s",
504                         "system-bus-name", 1, "name", "s", sender,
505                         action);
506         if (r < 0)
507                 return r;
508
509         r = sd_bus_message_open_container(pk, 'a', "{ss}");
510         if (r < 0)
511                 return r;
512
513         STRV_FOREACH_PAIR(k, v, details) {
514                 r = sd_bus_message_append(pk, "{ss}", *k, *v);
515                 if (r < 0)
516                         return r;
517         }
518
519         r = sd_bus_message_close_container(pk);
520         if (r < 0)
521                 return r;
522
523         r = sd_bus_message_append(pk, "us", !!interactive, NULL);
524         if (r < 0)
525                 return r;
526
527         q = new0(AsyncPolkitQuery, 1);
528         if (!q)
529                 return -ENOMEM;
530
531         q->request = sd_bus_message_ref(call);
532         q->callback = callback;
533         q->userdata = userdata;
534
535         r = hashmap_put(*registry, call, q);
536         if (r < 0) {
537                 async_polkit_query_free(q);
538                 return r;
539         }
540
541         q->registry = *registry;
542
543         r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
544         if (r < 0) {
545                 async_polkit_query_free(q);
546                 return r;
547         }
548
549         return 0;
550 #endif
551
552         return -EACCES;
553 }
554
555 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
556 #if ENABLE_POLKIT
557         hashmap_free_with_destructor(registry, async_polkit_query_free);
558 #endif
559 }
560
561 #if 0 /// UNNEEDED by elogind
562 int bus_check_peercred(sd_bus *c) {
563         struct ucred ucred;
564         int fd, r;
565
566         assert(c);
567
568         fd = sd_bus_get_fd(c);
569         if (fd < 0)
570                 return fd;
571
572         r = getpeercred(fd, &ucred);
573         if (r < 0)
574                 return r;
575
576         if (ucred.uid != 0 && ucred.uid != geteuid())
577                 return -EPERM;
578
579         return 1;
580 }
581
582 int bus_connect_system_systemd(sd_bus **_bus) {
583         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
584         int r;
585
586         assert(_bus);
587
588         if (geteuid() != 0)
589                 return sd_bus_default_system(_bus);
590
591         /* If we are root then let's talk directly to the system
592          * instance, instead of going via the bus */
593
594         r = sd_bus_new(&bus);
595         if (r < 0)
596                 return r;
597
598         r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
599         if (r < 0)
600                 return r;
601
602         r = sd_bus_start(bus);
603         if (r < 0)
604                 return sd_bus_default_system(_bus);
605
606         r = bus_check_peercred(bus);
607         if (r < 0)
608                 return r;
609
610         *_bus = bus;
611         bus = NULL;
612
613         return 0;
614 }
615
616 int bus_connect_user_systemd(sd_bus **_bus) {
617         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
618         _cleanup_free_ char *ee = NULL;
619         const char *e;
620         int r;
621
622         assert(_bus);
623
624         e = secure_getenv("XDG_RUNTIME_DIR");
625         if (!e)
626                 return sd_bus_default_user(_bus);
627
628         ee = bus_address_escape(e);
629         if (!ee)
630                 return -ENOMEM;
631
632         r = sd_bus_new(&bus);
633         if (r < 0)
634                 return r;
635
636         bus->address = strjoin("unix:path=", ee, "/systemd/private");
637         if (!bus->address)
638                 return -ENOMEM;
639
640         r = sd_bus_start(bus);
641         if (r < 0)
642                 return sd_bus_default_user(_bus);
643
644         r = bus_check_peercred(bus);
645         if (r < 0)
646                 return r;
647
648         *_bus = bus;
649         bus = NULL;
650
651         return 0;
652 }
653 #endif // 0
654
655 #define print_property(name, fmt, ...)                                  \
656         do {                                                            \
657                 if (value)                                              \
658                         printf(fmt "\n", __VA_ARGS__);                  \
659                 else                                                    \
660                         printf("%s=" fmt "\n", name, __VA_ARGS__);      \
661         } while (0)
662
663 int bus_print_property(const char *name, sd_bus_message *property, bool value, bool all) {
664         char type;
665         const char *contents;
666         int r;
667
668         assert(name);
669         assert(property);
670
671         r = sd_bus_message_peek_type(property, &type, &contents);
672         if (r < 0)
673                 return r;
674
675         switch (type) {
676
677         case SD_BUS_TYPE_STRING: {
678                 const char *s;
679
680                 r = sd_bus_message_read_basic(property, type, &s);
681                 if (r < 0)
682                         return r;
683
684                 if (all || !isempty(s)) {
685                         bool good;
686
687                         /* This property has a single value, so we need to take
688                          * care not to print a new line, everything else is OK. */
689                         good = !strchr(s, '\n');
690                         print_property(name, "%s", good ? s : "[unprintable]");
691                 }
692
693                 return 1;
694         }
695
696         case SD_BUS_TYPE_BOOLEAN: {
697                 int b;
698
699                 r = sd_bus_message_read_basic(property, type, &b);
700                 if (r < 0)
701                         return r;
702
703                 print_property(name, "%s", yes_no(b));
704
705                 return 1;
706         }
707
708         case SD_BUS_TYPE_UINT64: {
709                 uint64_t u;
710
711                 r = sd_bus_message_read_basic(property, type, &u);
712                 if (r < 0)
713                         return r;
714
715                 /* Yes, heuristics! But we can change this check
716                  * should it turn out to not be sufficient */
717
718                 if (endswith(name, "Timestamp")) {
719                         char timestamp[FORMAT_TIMESTAMP_MAX], *t;
720
721                         t = format_timestamp(timestamp, sizeof(timestamp), u);
722                         if (t || all)
723                                 print_property(name, "%s", strempty(t));
724
725                 } else if (strstr(name, "USec")) {
726                         char timespan[FORMAT_TIMESPAN_MAX];
727
728                         print_property(name, "%s", format_timespan(timespan, sizeof(timespan), u, 0));
729                 } else if (streq(name, "RestrictNamespaces")) {
730                         _cleanup_free_ char *s = NULL;
731                         const char *result;
732
733                         if ((u & NAMESPACE_FLAGS_ALL) == 0)
734                                 result = "yes";
735                         else if ((u & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
736                                 result = "no";
737                         else {
738                                 r = namespace_flag_to_string_many(u, &s);
739                                 if (r < 0)
740                                         return r;
741
742                                 result = s;
743                         }
744
745                         print_property(name, "%s", result);
746
747                 } else if (streq(name, "MountFlags")) {
748                         const char *result;
749
750                         result = mount_propagation_flags_to_string(u);
751                         if (!result)
752                                 return -EINVAL;
753
754                         print_property(name, "%s", result);
755
756                 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
757                         _cleanup_free_ char *s = NULL;
758
759                         r = capability_set_to_string_alloc(u, &s);
760                         if (r < 0)
761                                 return r;
762
763                         print_property(name, "%s", s);
764
765                 } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
766                            (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
767                            (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
768                            (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
769                            (endswith(name, "NSec") && u == (uint64_t) -1))
770
771                         print_property(name, "%s", "[not set]");
772
773                 else if ((STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
774                          (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
775                          (startswith(name, "Limit") && u == (uint64_t) -1) ||
776                          (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
777
778                         print_property(name, "%s", "infinity");
779                 else
780                         print_property(name, "%"PRIu64, u);
781
782                 return 1;
783         }
784
785         case SD_BUS_TYPE_INT64: {
786                 int64_t i;
787
788                 r = sd_bus_message_read_basic(property, type, &i);
789                 if (r < 0)
790                         return r;
791
792                 print_property(name, "%"PRIi64, i);
793
794                 return 1;
795         }
796
797         case SD_BUS_TYPE_UINT32: {
798                 uint32_t u;
799
800                 r = sd_bus_message_read_basic(property, type, &u);
801                 if (r < 0)
802                         return r;
803
804                 if (strstr(name, "UMask") || strstr(name, "Mode"))
805                         print_property(name, "%04o", u);
806                 else if (streq(name, "UID")) {
807                         if (u == UID_INVALID)
808                                 print_property(name, "%s", "[not set]");
809                         else
810                                 print_property(name, "%"PRIu32, u);
811                 } else if (streq(name, "GID")) {
812                         if (u == GID_INVALID)
813                                 print_property(name, "%s", "[not set]");
814                         else
815                                 print_property(name, "%"PRIu32, u);
816                 } else
817                         print_property(name, "%"PRIu32, u);
818
819                 return 1;
820         }
821
822         case SD_BUS_TYPE_INT32: {
823                 int32_t i;
824
825                 r = sd_bus_message_read_basic(property, type, &i);
826                 if (r < 0)
827                         return r;
828
829                 print_property(name, "%"PRIi32, i);
830                 return 1;
831         }
832
833         case SD_BUS_TYPE_DOUBLE: {
834                 double d;
835
836                 r = sd_bus_message_read_basic(property, type, &d);
837                 if (r < 0)
838                         return r;
839
840                 print_property(name, "%g", d);
841                 return 1;
842         }
843
844         case SD_BUS_TYPE_ARRAY:
845                 if (streq(contents, "s")) {
846                         bool first = true;
847                         const char *str;
848
849                         r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
850                         if (r < 0)
851                                 return r;
852
853                         while ((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
854                                 bool good;
855
856                                 if (first && !value)
857                                         printf("%s=", name);
858
859                                 /* This property has multiple space-separated values, so
860                                  * neither spaces not newlines can be allowed in a value. */
861                                 good = str[strcspn(str, " \n")] == '\0';
862
863                                 printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
864
865                                 first = false;
866                         }
867                         if (r < 0)
868                                 return r;
869
870                         if (first && all && !value)
871                                 printf("%s=", name);
872                         if (!first || all)
873                                 puts("");
874
875                         r = sd_bus_message_exit_container(property);
876                         if (r < 0)
877                                 return r;
878
879                         return 1;
880
881                 } else if (streq(contents, "y")) {
882                         const uint8_t *u;
883                         size_t n;
884
885                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
886                         if (r < 0)
887                                 return r;
888
889                         if (all || n > 0) {
890                                 unsigned int i;
891
892                                 if (!value)
893                                         printf("%s=", name);
894
895                                 for (i = 0; i < n; i++)
896                                         printf("%02x", u[i]);
897
898                                 puts("");
899                         }
900
901                         return 1;
902
903                 } else if (streq(contents, "u")) {
904                         uint32_t *u;
905                         size_t n;
906
907                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
908                         if (r < 0)
909                                 return r;
910
911                         if (all || n > 0) {
912                                 unsigned int i;
913
914                                 if (!value)
915                                         printf("%s=", name);
916
917                                 for (i = 0; i < n; i++)
918                                         printf("%08x", u[i]);
919
920                                 puts("");
921                         }
922
923                         return 1;
924                 }
925
926                 break;
927         }
928
929         return 0;
930 }
931
932 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool value, bool all) {
933         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
934         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
935         int r;
936
937         assert(bus);
938         assert(path);
939
940         r = sd_bus_call_method(bus,
941                         dest,
942                         path,
943                         "org.freedesktop.DBus.Properties",
944                         "GetAll",
945                         &error,
946                         &reply,
947                         "s", "");
948         if (r < 0)
949                 return r;
950
951         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
952         if (r < 0)
953                 return r;
954
955         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
956                 const char *name;
957                 const char *contents;
958
959                 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
960                 if (r < 0)
961                         return r;
962
963                 if (!filter || strv_find(filter, name)) {
964                         r = sd_bus_message_peek_type(reply, NULL, &contents);
965                         if (r < 0)
966                                 return r;
967
968                         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
969                         if (r < 0)
970                                 return r;
971
972                         r = bus_print_property(name, reply, value, all);
973                         if (r < 0)
974                                 return r;
975                         if (r == 0) {
976                                 if (all)
977                                         printf("%s=[unprintable]\n", name);
978                                 /* skip what we didn't read */
979                                 r = sd_bus_message_skip(reply, contents);
980                                 if (r < 0)
981                                         return r;
982                         }
983
984                         r = sd_bus_message_exit_container(reply);
985                         if (r < 0)
986                                 return r;
987                 } else {
988                         r = sd_bus_message_skip(reply, "v");
989                         if (r < 0)
990                                 return r;
991                 }
992
993                 r = sd_bus_message_exit_container(reply);
994                 if (r < 0)
995                         return r;
996         }
997         if (r < 0)
998                 return r;
999
1000         r = sd_bus_message_exit_container(reply);
1001         if (r < 0)
1002                 return r;
1003
1004         return 0;
1005 }
1006
1007 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1008         sd_id128_t *p = userdata;
1009         const void *v;
1010         size_t n;
1011         int r;
1012
1013         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
1014         if (r < 0)
1015                 return r;
1016
1017         if (n == 0)
1018                 *p = SD_ID128_NULL;
1019         else if (n == 16)
1020                 memcpy((*p).bytes, v, n);
1021         else
1022                 return -EINVAL;
1023
1024         return 0;
1025 }
1026
1027 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1028         char type;
1029         int r;
1030
1031         r = sd_bus_message_peek_type(m, &type, NULL);
1032         if (r < 0)
1033                 return r;
1034
1035         switch (type) {
1036
1037         case SD_BUS_TYPE_STRING: {
1038                 char **p = userdata;
1039                 const char *s;
1040
1041                 r = sd_bus_message_read_basic(m, type, &s);
1042                 if (r < 0)
1043                         return r;
1044
1045                 if (isempty(s))
1046                         s = NULL;
1047
1048                 return free_and_strdup(p, s);
1049         }
1050
1051         case SD_BUS_TYPE_ARRAY: {
1052                 _cleanup_strv_free_ char **l = NULL;
1053                 char ***p = userdata;
1054
1055                 r = bus_message_read_strv_extend(m, &l);
1056                 if (r < 0)
1057                         return r;
1058
1059                 strv_free(*p);
1060                 *p = l;
1061                 l = NULL;
1062                 return 0;
1063         }
1064
1065         case SD_BUS_TYPE_BOOLEAN: {
1066                 unsigned b;
1067                 int *p = userdata;
1068
1069                 r = sd_bus_message_read_basic(m, type, &b);
1070                 if (r < 0)
1071                         return r;
1072
1073                 *p = b;
1074                 return 0;
1075         }
1076
1077         case SD_BUS_TYPE_INT32:
1078         case SD_BUS_TYPE_UINT32: {
1079                 uint32_t u, *p = userdata;
1080
1081                 r = sd_bus_message_read_basic(m, type, &u);
1082                 if (r < 0)
1083                         return r;
1084
1085                 *p = u;
1086                 return 0;
1087         }
1088
1089         case SD_BUS_TYPE_INT64:
1090         case SD_BUS_TYPE_UINT64: {
1091                 uint64_t t, *p = userdata;
1092
1093                 r = sd_bus_message_read_basic(m, type, &t);
1094                 if (r < 0)
1095                         return r;
1096
1097                 *p = t;
1098                 return 0;
1099         }
1100
1101         case SD_BUS_TYPE_DOUBLE: {
1102                 double d, *p = userdata;
1103
1104                 r = sd_bus_message_read_basic(m, type, &d);
1105                 if (r < 0)
1106                         return r;
1107
1108                 *p = d;
1109                 return 0;
1110         }}
1111
1112         return -EOPNOTSUPP;
1113 }
1114
1115 int bus_message_map_all_properties(
1116                 sd_bus_message *m,
1117                 const struct bus_properties_map *map,
1118                 sd_bus_error *error,
1119                 void *userdata) {
1120
1121         int r;
1122
1123         assert(m);
1124         assert(map);
1125
1126         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1127         if (r < 0)
1128                 return r;
1129
1130         while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1131                 const struct bus_properties_map *prop;
1132                 const char *member;
1133                 const char *contents;
1134                 void *v;
1135                 unsigned i;
1136
1137                 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1138                 if (r < 0)
1139                         return r;
1140
1141                 for (i = 0, prop = NULL; map[i].member; i++)
1142                         if (streq(map[i].member, member)) {
1143                                 prop = &map[i];
1144                                 break;
1145                         }
1146
1147                 if (prop) {
1148                         r = sd_bus_message_peek_type(m, NULL, &contents);
1149                         if (r < 0)
1150                                 return r;
1151
1152                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1153                         if (r < 0)
1154                                 return r;
1155
1156                         v = (uint8_t *)userdata + prop->offset;
1157                         if (map[i].set)
1158                                 r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
1159                         else
1160                                 r = map_basic(sd_bus_message_get_bus(m), member, m, error, v);
1161                         if (r < 0)
1162                                 return r;
1163
1164                         r = sd_bus_message_exit_container(m);
1165                         if (r < 0)
1166                                 return r;
1167                 } else {
1168                         r = sd_bus_message_skip(m, "v");
1169                         if (r < 0)
1170                                 return r;
1171                 }
1172
1173                 r = sd_bus_message_exit_container(m);
1174                 if (r < 0)
1175                         return r;
1176         }
1177         if (r < 0)
1178                 return r;
1179
1180         return sd_bus_message_exit_container(m);
1181 }
1182
1183 #if 0 /// UNNEEDED by elogind
1184 int bus_message_map_properties_changed(
1185                 sd_bus_message *m,
1186                 const struct bus_properties_map *map,
1187                 sd_bus_error *error,
1188                 void *userdata) {
1189
1190         const char *member;
1191         int r, invalidated, i;
1192
1193         assert(m);
1194         assert(map);
1195
1196         r = bus_message_map_all_properties(m, map, error, userdata);
1197         if (r < 0)
1198                 return r;
1199
1200         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1201         if (r < 0)
1202                 return r;
1203
1204         invalidated = 0;
1205         while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1206                 for (i = 0; map[i].member; i++)
1207                         if (streq(map[i].member, member)) {
1208                                 ++invalidated;
1209                                 break;
1210                         }
1211         if (r < 0)
1212                 return r;
1213
1214         r = sd_bus_message_exit_container(m);
1215         if (r < 0)
1216                 return r;
1217
1218         return invalidated;
1219 }
1220 #endif // 0
1221
1222 int bus_map_all_properties(
1223                 sd_bus *bus,
1224                 const char *destination,
1225                 const char *path,
1226                 const struct bus_properties_map *map,
1227                 sd_bus_error *error,
1228                 void *userdata) {
1229
1230         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1231         int r;
1232
1233         assert(bus);
1234         assert(destination);
1235         assert(path);
1236         assert(map);
1237
1238         r = sd_bus_call_method(
1239                         bus,
1240                         destination,
1241                         path,
1242                         "org.freedesktop.DBus.Properties",
1243                         "GetAll",
1244                         error,
1245                         &m,
1246                         "s", "");
1247         if (r < 0)
1248                 return r;
1249
1250         return bus_message_map_all_properties(m, map, error, userdata);
1251 }
1252
1253 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
1254         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1255         int r;
1256
1257         assert(transport >= 0);
1258         assert(transport < _BUS_TRANSPORT_MAX);
1259         assert(ret);
1260
1261         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1262         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1263
1264         switch (transport) {
1265
1266         case BUS_TRANSPORT_LOCAL:
1267 #if 0 /// elogind does not support a user bus
1268                 if (user)
1269                         r = sd_bus_default_user(&bus);
1270                 else
1271 #endif // 0
1272                         r = sd_bus_default_system(&bus);
1273
1274                 break;
1275
1276         case BUS_TRANSPORT_REMOTE:
1277                 r = sd_bus_open_system_remote(&bus, host);
1278                 break;
1279
1280         case BUS_TRANSPORT_MACHINE:
1281                 r = sd_bus_open_system_machine(&bus, host);
1282                 break;
1283
1284         default:
1285                 assert_not_reached("Hmm, unknown transport type.");
1286         }
1287         if (r < 0)
1288                 return r;
1289
1290         r = sd_bus_set_exit_on_disconnect(bus, true);
1291         if (r < 0)
1292                 return r;
1293
1294         *ret = bus;
1295         bus = NULL;
1296
1297         return 0;
1298 }
1299
1300 #if 0 /// UNNEEDED by elogind
1301 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1302         int r;
1303
1304         assert(transport >= 0);
1305         assert(transport < _BUS_TRANSPORT_MAX);
1306         assert(bus);
1307
1308         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1309         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1310
1311         switch (transport) {
1312
1313         case BUS_TRANSPORT_LOCAL:
1314                 if (user)
1315                         r = bus_connect_user_systemd(bus);
1316                 else
1317                         r = bus_connect_system_systemd(bus);
1318
1319                 break;
1320
1321         case BUS_TRANSPORT_REMOTE:
1322                 r = sd_bus_open_system_remote(bus, host);
1323                 break;
1324
1325         case BUS_TRANSPORT_MACHINE:
1326                 r = sd_bus_open_system_machine(bus, host);
1327                 break;
1328
1329         default:
1330                 assert_not_reached("Hmm, unknown transport type.");
1331         }
1332
1333         return r;
1334 }
1335 #endif // 0
1336
1337 int bus_property_get_bool(
1338                 sd_bus *bus,
1339                 const char *path,
1340                 const char *interface,
1341                 const char *property,
1342                 sd_bus_message *reply,
1343                 void *userdata,
1344                 sd_bus_error *error) {
1345
1346         int b = *(bool*) userdata;
1347
1348         return sd_bus_message_append_basic(reply, 'b', &b);
1349 }
1350
1351 #if 0 /// UNNEEDED by elogind
1352 int bus_property_get_id128(
1353                 sd_bus *bus,
1354                 const char *path,
1355                 const char *interface,
1356                 const char *property,
1357                 sd_bus_message *reply,
1358                 void *userdata,
1359                 sd_bus_error *error) {
1360
1361         sd_id128_t *id = userdata;
1362
1363         if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */
1364                 return sd_bus_message_append(reply, "ay", 0);
1365         else
1366                 return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
1367 }
1368 #endif // 0
1369
1370 #if __SIZEOF_SIZE_T__ != 8
1371 int bus_property_get_size(
1372                 sd_bus *bus,
1373                 const char *path,
1374                 const char *interface,
1375                 const char *property,
1376                 sd_bus_message *reply,
1377                 void *userdata,
1378                 sd_bus_error *error) {
1379
1380         uint64_t sz = *(size_t*) userdata;
1381
1382         return sd_bus_message_append_basic(reply, 't', &sz);
1383 }
1384 #endif
1385
1386 #if __SIZEOF_LONG__ != 8
1387 int bus_property_get_long(
1388                 sd_bus *bus,
1389                 const char *path,
1390                 const char *interface,
1391                 const char *property,
1392                 sd_bus_message *reply,
1393                 void *userdata,
1394                 sd_bus_error *error) {
1395
1396         int64_t l = *(long*) userdata;
1397
1398         return sd_bus_message_append_basic(reply, 'x', &l);
1399 }
1400
1401 int bus_property_get_ulong(
1402                 sd_bus *bus,
1403                 const char *path,
1404                 const char *interface,
1405                 const char *property,
1406                 sd_bus_message *reply,
1407                 void *userdata,
1408                 sd_bus_error *error) {
1409
1410         uint64_t ul = *(unsigned long*) userdata;
1411
1412         return sd_bus_message_append_basic(reply, 't', &ul);
1413 }
1414 #endif
1415
1416 int bus_log_parse_error(int r) {
1417         return log_error_errno(r, "Failed to parse bus message: %m");
1418 }
1419
1420 #if 0 /// UNNEEDED by elogind
1421 int bus_log_create_error(int r) {
1422         return log_error_errno(r, "Failed to create bus message: %m");
1423 }
1424
1425 #endif // 0
1426 #if 0 /// UNNEEDED by elogind
1427 /**
1428  * bus_path_encode_unique() - encode unique object path
1429  * @b: bus connection or NULL
1430  * @prefix: object path prefix
1431  * @sender_id: unique-name of client, or NULL
1432  * @external_id: external ID to be chosen by client, or NULL
1433  * @ret_path: storage for encoded object path pointer
1434  *
1435  * Whenever we provide a bus API that allows clients to create and manage
1436  * server-side objects, we need to provide a unique name for these objects. If
1437  * we let the server choose the name, we suffer from a race condition: If a
1438  * client creates an object asynchronously, it cannot destroy that object until
1439  * it received the method reply. It cannot know the name of the new object,
1440  * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1441  *
1442  * Therefore, many APIs allow the client to choose the unique name for newly
1443  * created objects. There're two problems to solve, though:
1444  *    1) Object names are usually defined via dbus object paths, which are
1445  *       usually globally namespaced. Therefore, multiple clients must be able
1446  *       to choose unique object names without interference.
1447  *    2) If multiple libraries share the same bus connection, they must be
1448  *       able to choose unique object names without interference.
1449  * The first problem is solved easily by prefixing a name with the
1450  * unique-bus-name of a connection. The server side must enforce this and
1451  * reject any other name. The second problem is solved by providing unique
1452  * suffixes from within sd-bus.
1453  *
1454  * This helper allows clients to create unique object-paths. It uses the
1455  * template '/prefix/sender_id/external_id' and returns the new path in
1456  * @ret_path (must be freed by the caller).
1457  * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1458  * NULL, this function allocates a unique suffix via @b (by requesting a new
1459  * cookie). If both @sender_id and @external_id are given, @b can be passed as
1460  * NULL.
1461  *
1462  * Returns: 0 on success, negative error code on failure.
1463  */
1464 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
1465         _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
1466         char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
1467         int r;
1468
1469         assert_return(b || (sender_id && external_id), -EINVAL);
1470         assert_return(object_path_is_valid(prefix), -EINVAL);
1471         assert_return(ret_path, -EINVAL);
1472
1473         if (!sender_id) {
1474                 r = sd_bus_get_unique_name(b, &sender_id);
1475                 if (r < 0)
1476                         return r;
1477         }
1478
1479         if (!external_id) {
1480                 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
1481                 external_id = external_buf;
1482         }
1483
1484         sender_label = bus_label_escape(sender_id);
1485         if (!sender_label)
1486                 return -ENOMEM;
1487
1488         external_label = bus_label_escape(external_id);
1489         if (!external_label)
1490                 return -ENOMEM;
1491
1492         p = strjoin(prefix, "/", sender_label, "/", external_label);
1493         if (!p)
1494                 return -ENOMEM;
1495
1496         *ret_path = p;
1497         return 0;
1498 }
1499
1500 /**
1501  * bus_path_decode_unique() - decode unique object path
1502  * @path: object path to decode
1503  * @prefix: object path prefix
1504  * @ret_sender: output parameter for sender-id label
1505  * @ret_external: output parameter for external-id label
1506  *
1507  * This does the reverse of bus_path_encode_unique() (see its description for
1508  * details). Both trailing labels, sender-id and external-id, are unescaped and
1509  * returned in the given output parameters (the caller must free them).
1510  *
1511  * Note that this function returns 0 if the path does not match the template
1512  * (see bus_path_encode_unique()), 1 if it matched.
1513  *
1514  * Returns: Negative error code on failure, 0 if the given object path does not
1515  *          match the template (return parameters are set to NULL), 1 if it was
1516  *          parsed successfully (return parameters contain allocated labels).
1517  */
1518 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
1519         const char *p, *q;
1520         char *sender, *external;
1521
1522         assert(object_path_is_valid(path));
1523         assert(object_path_is_valid(prefix));
1524         assert(ret_sender);
1525         assert(ret_external);
1526
1527         p = object_path_startswith(path, prefix);
1528         if (!p) {
1529                 *ret_sender = NULL;
1530                 *ret_external = NULL;
1531                 return 0;
1532         }
1533
1534         q = strchr(p, '/');
1535         if (!q) {
1536                 *ret_sender = NULL;
1537                 *ret_external = NULL;
1538                 return 0;
1539         }
1540
1541         sender = bus_label_unescape_n(p, q - p);
1542         external = bus_label_unescape(q + 1);
1543         if (!sender || !external) {
1544                 free(sender);
1545                 free(external);
1546                 return -ENOMEM;
1547         }
1548
1549         *ret_sender = sender;
1550         *ret_external = external;
1551         return 1;
1552 }
1553 #endif // 0
1554
1555 #if 0 /// UNNEEDED by elogind
1556 int bus_property_get_rlimit(
1557                 sd_bus *bus,
1558                 const char *path,
1559                 const char *interface,
1560                 const char *property,
1561                 sd_bus_message *reply,
1562                 void *userdata,
1563                 sd_bus_error *error) {
1564
1565         struct rlimit *rl;
1566         uint64_t u;
1567         rlim_t x;
1568         const char *is_soft;
1569
1570         assert(bus);
1571         assert(reply);
1572         assert(userdata);
1573
1574         is_soft = endswith(property, "Soft");
1575         rl = *(struct rlimit**) userdata;
1576         if (rl)
1577                 x = is_soft ? rl->rlim_cur : rl->rlim_max;
1578         else {
1579                 struct rlimit buf = {};
1580                 int z;
1581                 const char *s;
1582
1583                 s = is_soft ? strndupa(property, is_soft - property) : property;
1584
1585                 z = rlimit_from_string(strstr(s, "Limit"));
1586                 assert(z >= 0);
1587
1588                 getrlimit(z, &buf);
1589                 x = is_soft ? buf.rlim_cur : buf.rlim_max;
1590         }
1591
1592         /* rlim_t might have different sizes, let's map
1593          * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1594          * all archs */
1595         u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
1596
1597         return sd_bus_message_append(reply, "t", u);
1598 }
1599
1600 int bus_track_add_name_many(sd_bus_track *t, char **l) {
1601         int r = 0;
1602         char **i;
1603
1604         assert(t);
1605
1606         /* Continues adding after failure, and returns the first failure. */
1607
1608         STRV_FOREACH(i, l) {
1609                 int k;
1610
1611                 k = sd_bus_track_add_name(t, *i);
1612                 if (k < 0 && r >= 0)
1613                         r = k;
1614         }
1615
1616         return r;
1617 }
1618 #endif // 0
1619
1620 int bus_open_system_watch_bind(sd_bus **ret) {
1621         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1622         const char *e;
1623         int r;
1624
1625         assert(ret);
1626
1627         /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1628
1629         r = sd_bus_new(&bus);
1630         if (r < 0)
1631                 return r;
1632
1633         e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1634         if (!e)
1635                 e = DEFAULT_SYSTEM_BUS_ADDRESS;
1636
1637         r = sd_bus_set_address(bus, e);
1638         if (r < 0)
1639                 return r;
1640
1641         r = sd_bus_set_bus_client(bus, true);
1642         if (r < 0)
1643                 return r;
1644
1645         r = sd_bus_set_trusted(bus, true);
1646         if (r < 0)
1647                 return r;
1648
1649         r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
1650         if (r < 0)
1651                 return r;
1652
1653         r = sd_bus_set_watch_bind(bus, true);
1654         if (r < 0)
1655                 return r;
1656
1657         r = sd_bus_set_connected_signal(bus, true);
1658         if (r < 0)
1659                 return r;
1660
1661         r = sd_bus_start(bus);
1662         if (r < 0)
1663                 return r;
1664
1665         *ret = bus;
1666         bus = NULL;
1667
1668         return 0;
1669 }