chiark / gitweb /
tree-wide: use TAKE_PTR() and TAKE_FD() macros
[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 = TAKE_PTR(bus);
611
612         return 0;
613 }
614
615 int bus_connect_user_systemd(sd_bus **_bus) {
616         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
617         _cleanup_free_ char *ee = NULL;
618         const char *e;
619         int r;
620
621         assert(_bus);
622
623         e = secure_getenv("XDG_RUNTIME_DIR");
624         if (!e)
625                 return sd_bus_default_user(_bus);
626
627         ee = bus_address_escape(e);
628         if (!ee)
629                 return -ENOMEM;
630
631         r = sd_bus_new(&bus);
632         if (r < 0)
633                 return r;
634
635         bus->address = strjoin("unix:path=", ee, "/systemd/private");
636         if (!bus->address)
637                 return -ENOMEM;
638
639         r = sd_bus_start(bus);
640         if (r < 0)
641                 return sd_bus_default_user(_bus);
642
643         r = bus_check_peercred(bus);
644         if (r < 0)
645                 return r;
646
647         *_bus = TAKE_PTR(bus);
648
649         return 0;
650 }
651 #endif // 0
652
653 #define print_property(name, fmt, ...)                                  \
654         do {                                                            \
655                 if (value)                                              \
656                         printf(fmt "\n", __VA_ARGS__);                  \
657                 else                                                    \
658                         printf("%s=" fmt "\n", name, __VA_ARGS__);      \
659         } while (0)
660
661 int bus_print_property(const char *name, sd_bus_message *m, bool value, bool all) {
662         char type;
663         const char *contents;
664         int r;
665
666         assert(name);
667         assert(m);
668
669         r = sd_bus_message_peek_type(m, &type, &contents);
670         if (r < 0)
671                 return r;
672
673         switch (type) {
674
675         case SD_BUS_TYPE_STRING: {
676                 const char *s;
677
678                 r = sd_bus_message_read_basic(m, type, &s);
679                 if (r < 0)
680                         return r;
681
682                 if (all || !isempty(s)) {
683                         bool good;
684
685                         /* This property has a single value, so we need to take
686                          * care not to print a new line, everything else is OK. */
687                         good = !strchr(s, '\n');
688                         print_property(name, "%s", good ? s : "[unprintable]");
689                 }
690
691                 return 1;
692         }
693
694         case SD_BUS_TYPE_BOOLEAN: {
695                 int b;
696
697                 r = sd_bus_message_read_basic(m, type, &b);
698                 if (r < 0)
699                         return r;
700
701                 print_property(name, "%s", yes_no(b));
702
703                 return 1;
704         }
705
706         case SD_BUS_TYPE_UINT64: {
707                 uint64_t u;
708
709                 r = sd_bus_message_read_basic(m, type, &u);
710                 if (r < 0)
711                         return r;
712
713                 /* Yes, heuristics! But we can change this check
714                  * should it turn out to not be sufficient */
715
716                 if (endswith(name, "Timestamp") || STR_IN_SET(name, "NextElapseUSecRealtime", "LastTriggerUSec")) {
717                         char timestamp[FORMAT_TIMESTAMP_MAX], *t;
718
719                         t = format_timestamp(timestamp, sizeof(timestamp), u);
720                         if (t || all)
721                                 print_property(name, "%s", strempty(t));
722
723                 } else if (strstr(name, "USec")) {
724                         char timespan[FORMAT_TIMESPAN_MAX];
725
726                         print_property(name, "%s", format_timespan(timespan, sizeof(timespan), u, 0));
727                 } else if (streq(name, "RestrictNamespaces")) {
728                         _cleanup_free_ char *s = NULL;
729                         const char *result;
730
731                         if ((u & NAMESPACE_FLAGS_ALL) == 0)
732                                 result = "yes";
733                         else if ((u & NAMESPACE_FLAGS_ALL) == NAMESPACE_FLAGS_ALL)
734                                 result = "no";
735                         else {
736                                 r = namespace_flag_to_string_many(u, &s);
737                                 if (r < 0)
738                                         return r;
739
740                                 result = s;
741                         }
742
743                         print_property(name, "%s", result);
744
745                 } else if (streq(name, "MountFlags")) {
746                         const char *result;
747
748                         result = mount_propagation_flags_to_string(u);
749                         if (!result)
750                                 return -EINVAL;
751
752                         print_property(name, "%s", result);
753
754                 } else if (STR_IN_SET(name, "CapabilityBoundingSet", "AmbientCapabilities")) {
755                         _cleanup_free_ char *s = NULL;
756
757                         r = capability_set_to_string_alloc(u, &s);
758                         if (r < 0)
759                                 return r;
760
761                         print_property(name, "%s", s);
762
763                 } else if ((STR_IN_SET(name, "CPUWeight", "StartupCPUWeight", "IOWeight", "StartupIOWeight") && u == CGROUP_WEIGHT_INVALID) ||
764                            (STR_IN_SET(name, "CPUShares", "StartupCPUShares") && u == CGROUP_CPU_SHARES_INVALID) ||
765                            (STR_IN_SET(name, "BlockIOWeight", "StartupBlockIOWeight") && u == CGROUP_BLKIO_WEIGHT_INVALID) ||
766                            (STR_IN_SET(name, "MemoryCurrent", "TasksCurrent") && u == (uint64_t) -1) ||
767                            (endswith(name, "NSec") && u == (uint64_t) -1))
768
769                         print_property(name, "%s", "[not set]");
770
771                 else if ((STR_IN_SET(name, "MemoryLow", "MemoryHigh", "MemoryMax", "MemorySwapMax", "MemoryLimit") && u == CGROUP_LIMIT_MAX) ||
772                          (STR_IN_SET(name, "TasksMax", "DefaultTasksMax") && u == (uint64_t) -1) ||
773                          (startswith(name, "Limit") && u == (uint64_t) -1) ||
774                          (startswith(name, "DefaultLimit") && u == (uint64_t) -1))
775
776                         print_property(name, "%s", "infinity");
777                 else
778                         print_property(name, "%"PRIu64, u);
779
780                 return 1;
781         }
782
783         case SD_BUS_TYPE_INT64: {
784                 int64_t i;
785
786                 r = sd_bus_message_read_basic(m, type, &i);
787                 if (r < 0)
788                         return r;
789
790                 print_property(name, "%"PRIi64, i);
791
792                 return 1;
793         }
794
795         case SD_BUS_TYPE_UINT32: {
796                 uint32_t u;
797
798                 r = sd_bus_message_read_basic(m, type, &u);
799                 if (r < 0)
800                         return r;
801
802                 if (strstr(name, "UMask") || strstr(name, "Mode"))
803                         print_property(name, "%04o", u);
804                 else if (streq(name, "UID")) {
805                         if (u == UID_INVALID)
806                                 print_property(name, "%s", "[not set]");
807                         else
808                                 print_property(name, "%"PRIu32, u);
809                 } else if (streq(name, "GID")) {
810                         if (u == GID_INVALID)
811                                 print_property(name, "%s", "[not set]");
812                         else
813                                 print_property(name, "%"PRIu32, u);
814                 } else
815                         print_property(name, "%"PRIu32, u);
816
817                 return 1;
818         }
819
820         case SD_BUS_TYPE_INT32: {
821                 int32_t i;
822
823                 r = sd_bus_message_read_basic(m, type, &i);
824                 if (r < 0)
825                         return r;
826
827                 print_property(name, "%"PRIi32, i);
828                 return 1;
829         }
830
831         case SD_BUS_TYPE_DOUBLE: {
832                 double d;
833
834                 r = sd_bus_message_read_basic(m, type, &d);
835                 if (r < 0)
836                         return r;
837
838                 print_property(name, "%g", d);
839                 return 1;
840         }
841
842         case SD_BUS_TYPE_ARRAY:
843                 if (streq(contents, "s")) {
844                         bool first = true;
845                         const char *str;
846
847                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, contents);
848                         if (r < 0)
849                                 return r;
850
851                         while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &str)) > 0) {
852                                 bool good;
853
854                                 if (first && !value)
855                                         printf("%s=", name);
856
857                                 /* This property has multiple space-separated values, so
858                                  * neither spaces not newlines can be allowed in a value. */
859                                 good = str[strcspn(str, " \n")] == '\0';
860
861                                 printf("%s%s", first ? "" : " ", good ? str : "[unprintable]");
862
863                                 first = false;
864                         }
865                         if (r < 0)
866                                 return r;
867
868                         if (first && all && !value)
869                                 printf("%s=", name);
870                         if (!first || all)
871                                 puts("");
872
873                         r = sd_bus_message_exit_container(m);
874                         if (r < 0)
875                                 return r;
876
877                         return 1;
878
879                 } else if (streq(contents, "y")) {
880                         const uint8_t *u;
881                         size_t n;
882
883                         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
884                         if (r < 0)
885                                 return r;
886
887                         if (all || n > 0) {
888                                 unsigned int i;
889
890                                 if (!value)
891                                         printf("%s=", name);
892
893                                 for (i = 0; i < n; i++)
894                                         printf("%02x", u[i]);
895
896                                 puts("");
897                         }
898
899                         return 1;
900
901                 } else if (streq(contents, "u")) {
902                         uint32_t *u;
903                         size_t n;
904
905                         r = sd_bus_message_read_array(m, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
906                         if (r < 0)
907                                 return r;
908
909                         if (all || n > 0) {
910                                 unsigned int i;
911
912                                 if (!value)
913                                         printf("%s=", name);
914
915                                 for (i = 0; i < n; i++)
916                                         printf("%08x", u[i]);
917
918                                 puts("");
919                         }
920
921                         return 1;
922                 }
923
924                 break;
925         }
926
927         return 0;
928 }
929
930 int bus_message_print_all_properties(
931                 sd_bus_message *m,
932                 bus_message_print_t func,
933                 char **filter,
934                 bool value,
935                 bool all,
936                 Set **found_properties) {
937
938         int r;
939
940         assert(m);
941
942         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
943         if (r < 0)
944                 return r;
945
946         while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
947                 const char *name;
948                 const char *contents;
949
950                 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &name);
951                 if (r < 0)
952                         return r;
953
954                 if (found_properties) {
955                         r = set_ensure_allocated(found_properties, &string_hash_ops);
956                         if (r < 0)
957                                 return log_oom();
958
959                         r = set_put(*found_properties, name);
960                         if (r < 0 && r != EEXIST)
961                                 return log_oom();
962                 }
963
964                 if (!filter || strv_find(filter, name)) {
965                         r = sd_bus_message_peek_type(m, NULL, &contents);
966                         if (r < 0)
967                                 return r;
968
969                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
970                         if (r < 0)
971                                 return r;
972
973                         if (func)
974                                 r = func(name, m, value, all);
975                         if (!func || r == 0)
976                                 r = bus_print_property(name, m, value, all);
977                         if (r < 0)
978                                 return r;
979                         if (r == 0) {
980                                 if (all)
981                                         printf("%s=[unprintable]\n", name);
982                                 /* skip what we didn't read */
983                                 r = sd_bus_message_skip(m, contents);
984                                 if (r < 0)
985                                         return r;
986                         }
987
988                         r = sd_bus_message_exit_container(m);
989                         if (r < 0)
990                                 return r;
991                 } else {
992                         r = sd_bus_message_skip(m, "v");
993                         if (r < 0)
994                                 return r;
995                 }
996
997                 r = sd_bus_message_exit_container(m);
998                 if (r < 0)
999                         return r;
1000         }
1001         if (r < 0)
1002                 return r;
1003
1004         r = sd_bus_message_exit_container(m);
1005         if (r < 0)
1006                 return r;
1007
1008         return 0;
1009 }
1010
1011 int bus_print_all_properties(
1012                 sd_bus *bus,
1013                 const char *dest,
1014                 const char *path,
1015                 bus_message_print_t func,
1016                 char **filter,
1017                 bool value,
1018                 bool all,
1019                 Set **found_properties) {
1020
1021         _cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
1022         _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
1023         int r;
1024
1025         assert(bus);
1026         assert(path);
1027
1028         r = sd_bus_call_method(bus,
1029                         dest,
1030                         path,
1031                         "org.freedesktop.DBus.Properties",
1032                         "GetAll",
1033                         &error,
1034                         &reply,
1035                         "s", "");
1036         if (r < 0)
1037                 return r;
1038
1039         return bus_message_print_all_properties(reply, func, filter, value, all, found_properties);
1040 }
1041
1042 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
1043         sd_id128_t *p = userdata;
1044         const void *v;
1045         size_t n;
1046         int r;
1047
1048         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
1049         if (r < 0)
1050                 return r;
1051
1052         if (n == 0)
1053                 *p = SD_ID128_NULL;
1054         else if (n == 16)
1055                 memcpy((*p).bytes, v, n);
1056         else
1057                 return -EINVAL;
1058
1059         return 0;
1060 }
1061
1062 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, unsigned flags, sd_bus_error *error, void *userdata) {
1063         char type;
1064         int r;
1065
1066         r = sd_bus_message_peek_type(m, &type, NULL);
1067         if (r < 0)
1068                 return r;
1069
1070         switch (type) {
1071
1072         case SD_BUS_TYPE_STRING: {
1073                 const char **p = userdata;
1074                 const char *s;
1075
1076                 r = sd_bus_message_read_basic(m, type, &s);
1077                 if (r < 0)
1078                         return r;
1079
1080                 if (isempty(s))
1081                         s = NULL;
1082
1083                 if (flags & BUS_MAP_STRDUP)
1084                         return free_and_strdup((char **) userdata, s);
1085
1086                 *p = s;
1087                 return 0;
1088         }
1089
1090         case SD_BUS_TYPE_ARRAY: {
1091                 _cleanup_strv_free_ char **l = NULL;
1092                 char ***p = userdata;
1093
1094                 r = bus_message_read_strv_extend(m, &l);
1095                 if (r < 0)
1096                         return r;
1097
1098                 strv_free(*p);
1099                 *p = TAKE_PTR(l);
1100                 return 0;
1101         }
1102
1103         case SD_BUS_TYPE_BOOLEAN: {
1104                 int b;
1105
1106                 r = sd_bus_message_read_basic(m, type, &b);
1107                 if (r < 0)
1108                         return r;
1109
1110                 if (flags & BUS_MAP_BOOLEAN_AS_BOOL)
1111                         * (bool*) userdata = !!b;
1112                 else
1113                         * (int*) userdata = b;
1114
1115                 return 0;
1116         }
1117
1118         case SD_BUS_TYPE_INT32:
1119         case SD_BUS_TYPE_UINT32: {
1120                 uint32_t u, *p = userdata;
1121
1122                 r = sd_bus_message_read_basic(m, type, &u);
1123                 if (r < 0)
1124                         return r;
1125
1126                 *p = u;
1127                 return 0;
1128         }
1129
1130         case SD_BUS_TYPE_INT64:
1131         case SD_BUS_TYPE_UINT64: {
1132                 uint64_t t, *p = userdata;
1133
1134                 r = sd_bus_message_read_basic(m, type, &t);
1135                 if (r < 0)
1136                         return r;
1137
1138                 *p = t;
1139                 return 0;
1140         }
1141
1142         case SD_BUS_TYPE_DOUBLE: {
1143                 double d, *p = userdata;
1144
1145                 r = sd_bus_message_read_basic(m, type, &d);
1146                 if (r < 0)
1147                         return r;
1148
1149                 *p = d;
1150                 return 0;
1151         }}
1152
1153         return -EOPNOTSUPP;
1154 }
1155
1156 int bus_message_map_all_properties(
1157                 sd_bus_message *m,
1158                 const struct bus_properties_map *map,
1159                 unsigned flags,
1160                 sd_bus_error *error,
1161                 void *userdata) {
1162
1163         int r;
1164
1165         assert(m);
1166         assert(map);
1167
1168         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1169         if (r < 0)
1170                 return r;
1171
1172         while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1173                 const struct bus_properties_map *prop;
1174                 const char *member;
1175                 const char *contents;
1176                 void *v;
1177                 unsigned i;
1178
1179                 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1180                 if (r < 0)
1181                         return r;
1182
1183                 for (i = 0, prop = NULL; map[i].member; i++)
1184                         if (streq(map[i].member, member)) {
1185                                 prop = &map[i];
1186                                 break;
1187                         }
1188
1189                 if (prop) {
1190                         r = sd_bus_message_peek_type(m, NULL, &contents);
1191                         if (r < 0)
1192                                 return r;
1193
1194                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1195                         if (r < 0)
1196                                 return r;
1197
1198                         v = (uint8_t *)userdata + prop->offset;
1199                         if (map[i].set)
1200                                 r = prop->set(sd_bus_message_get_bus(m), member, m, error, v);
1201                         else
1202                                 r = map_basic(sd_bus_message_get_bus(m), member, m, flags, error, v);
1203                         if (r < 0)
1204                                 return r;
1205
1206                         r = sd_bus_message_exit_container(m);
1207                         if (r < 0)
1208                                 return r;
1209                 } else {
1210                         r = sd_bus_message_skip(m, "v");
1211                         if (r < 0)
1212                                 return r;
1213                 }
1214
1215                 r = sd_bus_message_exit_container(m);
1216                 if (r < 0)
1217                         return r;
1218         }
1219         if (r < 0)
1220                 return r;
1221
1222         return sd_bus_message_exit_container(m);
1223 }
1224
1225 #if 0 /// UNNEEDED by elogind
1226 int bus_message_map_properties_changed(
1227                 sd_bus_message *m,
1228                 const struct bus_properties_map *map,
1229                 unsigned flags,
1230                 sd_bus_error *error,
1231                 void *userdata) {
1232
1233         const char *member;
1234         int r, invalidated, i;
1235
1236         assert(m);
1237         assert(map);
1238
1239         r = bus_message_map_all_properties(m, map, flags, error, userdata);
1240         if (r < 0)
1241                 return r;
1242
1243         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1244         if (r < 0)
1245                 return r;
1246
1247         invalidated = 0;
1248         while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1249                 for (i = 0; map[i].member; i++)
1250                         if (streq(map[i].member, member)) {
1251                                 ++invalidated;
1252                                 break;
1253                         }
1254         if (r < 0)
1255                 return r;
1256
1257         r = sd_bus_message_exit_container(m);
1258         if (r < 0)
1259                 return r;
1260
1261         return invalidated;
1262 }
1263 #endif // 0
1264
1265 int bus_map_all_properties(
1266                 sd_bus *bus,
1267                 const char *destination,
1268                 const char *path,
1269                 const struct bus_properties_map *map,
1270                 unsigned flags,
1271                 sd_bus_error *error,
1272                 sd_bus_message **reply,
1273                 void *userdata) {
1274
1275         _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
1276         int r;
1277
1278         assert(bus);
1279         assert(destination);
1280         assert(path);
1281         assert(map);
1282         assert(reply || (flags & BUS_MAP_STRDUP));
1283
1284         r = sd_bus_call_method(
1285                         bus,
1286                         destination,
1287                         path,
1288                         "org.freedesktop.DBus.Properties",
1289                         "GetAll",
1290                         error,
1291                         &m,
1292                         "s", "");
1293         if (r < 0)
1294                 return r;
1295
1296         r = bus_message_map_all_properties(m, map, flags, error, userdata);
1297         if (r < 0)
1298                 return r;
1299
1300         if (reply)
1301                 *reply = sd_bus_message_ref(m);
1302
1303         return r;
1304 }
1305
1306 int bus_connect_transport(BusTransport transport, const char *host, bool user, sd_bus **ret) {
1307         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1308         int r;
1309
1310         assert(transport >= 0);
1311         assert(transport < _BUS_TRANSPORT_MAX);
1312         assert(ret);
1313
1314         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1315         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1316
1317         switch (transport) {
1318
1319         case BUS_TRANSPORT_LOCAL:
1320 #if 0 /// elogind does not support a user bus
1321                 if (user)
1322                         r = sd_bus_default_user(&bus);
1323                 else
1324 #endif // 0
1325                         r = sd_bus_default_system(&bus);
1326
1327                 break;
1328
1329         case BUS_TRANSPORT_REMOTE:
1330                 r = sd_bus_open_system_remote(&bus, host);
1331                 break;
1332
1333         case BUS_TRANSPORT_MACHINE:
1334                 r = sd_bus_open_system_machine(&bus, host);
1335                 break;
1336
1337         default:
1338                 assert_not_reached("Hmm, unknown transport type.");
1339         }
1340         if (r < 0)
1341                 return r;
1342
1343         r = sd_bus_set_exit_on_disconnect(bus, true);
1344         if (r < 0)
1345                 return r;
1346
1347         *ret = TAKE_PTR(bus);
1348
1349         return 0;
1350 }
1351
1352 #if 0 /// UNNEEDED by elogind
1353 int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1354         int r;
1355
1356         assert(transport >= 0);
1357         assert(transport < _BUS_TRANSPORT_MAX);
1358         assert(bus);
1359
1360         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1361         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1362
1363         switch (transport) {
1364
1365         case BUS_TRANSPORT_LOCAL:
1366                 if (user)
1367                         r = bus_connect_user_systemd(bus);
1368                 else
1369                         r = bus_connect_system_systemd(bus);
1370
1371                 break;
1372
1373         case BUS_TRANSPORT_REMOTE:
1374                 r = sd_bus_open_system_remote(bus, host);
1375                 break;
1376
1377         case BUS_TRANSPORT_MACHINE:
1378                 r = sd_bus_open_system_machine(bus, host);
1379                 break;
1380
1381         default:
1382                 assert_not_reached("Hmm, unknown transport type.");
1383         }
1384
1385         return r;
1386 }
1387 #endif // 0
1388
1389 int bus_property_get_bool(
1390                 sd_bus *bus,
1391                 const char *path,
1392                 const char *interface,
1393                 const char *property,
1394                 sd_bus_message *reply,
1395                 void *userdata,
1396                 sd_bus_error *error) {
1397
1398         int b = *(bool*) userdata;
1399
1400         return sd_bus_message_append_basic(reply, 'b', &b);
1401 }
1402
1403 int bus_property_set_bool(
1404                 sd_bus *bus,
1405                 const char *path,
1406                 const char *interface,
1407                 const char *property,
1408                 sd_bus_message *value,
1409                 void *userdata,
1410                 sd_bus_error *error) {
1411
1412         int b, r;
1413
1414         r = sd_bus_message_read(value, "b", &b);
1415         if (r < 0)
1416                 return r;
1417
1418         *(bool *) userdata = !!b;
1419         return 0;
1420 }
1421
1422 #if 0 /// UNNEEDED by elogind
1423 int bus_property_get_id128(
1424                 sd_bus *bus,
1425                 const char *path,
1426                 const char *interface,
1427                 const char *property,
1428                 sd_bus_message *reply,
1429                 void *userdata,
1430                 sd_bus_error *error) {
1431
1432         sd_id128_t *id = userdata;
1433
1434         if (sd_id128_is_null(*id)) /* Add an empty array if the ID is zero */
1435                 return sd_bus_message_append(reply, "ay", 0);
1436         else
1437                 return sd_bus_message_append_array(reply, 'y', id->bytes, 16);
1438 }
1439 #endif // 0
1440
1441 #if __SIZEOF_SIZE_T__ != 8
1442 int bus_property_get_size(
1443                 sd_bus *bus,
1444                 const char *path,
1445                 const char *interface,
1446                 const char *property,
1447                 sd_bus_message *reply,
1448                 void *userdata,
1449                 sd_bus_error *error) {
1450
1451         uint64_t sz = *(size_t*) userdata;
1452
1453         return sd_bus_message_append_basic(reply, 't', &sz);
1454 }
1455 #endif
1456
1457 #if __SIZEOF_LONG__ != 8
1458 int bus_property_get_long(
1459                 sd_bus *bus,
1460                 const char *path,
1461                 const char *interface,
1462                 const char *property,
1463                 sd_bus_message *reply,
1464                 void *userdata,
1465                 sd_bus_error *error) {
1466
1467         int64_t l = *(long*) userdata;
1468
1469         return sd_bus_message_append_basic(reply, 'x', &l);
1470 }
1471
1472 int bus_property_get_ulong(
1473                 sd_bus *bus,
1474                 const char *path,
1475                 const char *interface,
1476                 const char *property,
1477                 sd_bus_message *reply,
1478                 void *userdata,
1479                 sd_bus_error *error) {
1480
1481         uint64_t ul = *(unsigned long*) userdata;
1482
1483         return sd_bus_message_append_basic(reply, 't', &ul);
1484 }
1485 #endif
1486
1487 int bus_log_parse_error(int r) {
1488         return log_error_errno(r, "Failed to parse bus message: %m");
1489 }
1490
1491 #if 0 /// UNNEEDED by elogind
1492 int bus_log_create_error(int r) {
1493         return log_error_errno(r, "Failed to create bus message: %m");
1494 }
1495
1496 #endif // 0
1497 #if 0 /// UNNEEDED by elogind
1498 /**
1499  * bus_path_encode_unique() - encode unique object path
1500  * @b: bus connection or NULL
1501  * @prefix: object path prefix
1502  * @sender_id: unique-name of client, or NULL
1503  * @external_id: external ID to be chosen by client, or NULL
1504  * @ret_path: storage for encoded object path pointer
1505  *
1506  * Whenever we provide a bus API that allows clients to create and manage
1507  * server-side objects, we need to provide a unique name for these objects. If
1508  * we let the server choose the name, we suffer from a race condition: If a
1509  * client creates an object asynchronously, it cannot destroy that object until
1510  * it received the method reply. It cannot know the name of the new object,
1511  * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1512  *
1513  * Therefore, many APIs allow the client to choose the unique name for newly
1514  * created objects. There're two problems to solve, though:
1515  *    1) Object names are usually defined via dbus object paths, which are
1516  *       usually globally namespaced. Therefore, multiple clients must be able
1517  *       to choose unique object names without interference.
1518  *    2) If multiple libraries share the same bus connection, they must be
1519  *       able to choose unique object names without interference.
1520  * The first problem is solved easily by prefixing a name with the
1521  * unique-bus-name of a connection. The server side must enforce this and
1522  * reject any other name. The second problem is solved by providing unique
1523  * suffixes from within sd-bus.
1524  *
1525  * This helper allows clients to create unique object-paths. It uses the
1526  * template '/prefix/sender_id/external_id' and returns the new path in
1527  * @ret_path (must be freed by the caller).
1528  * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1529  * NULL, this function allocates a unique suffix via @b (by requesting a new
1530  * cookie). If both @sender_id and @external_id are given, @b can be passed as
1531  * NULL.
1532  *
1533  * Returns: 0 on success, negative error code on failure.
1534  */
1535 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
1536         _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
1537         char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
1538         int r;
1539
1540         assert_return(b || (sender_id && external_id), -EINVAL);
1541         assert_return(object_path_is_valid(prefix), -EINVAL);
1542         assert_return(ret_path, -EINVAL);
1543
1544         if (!sender_id) {
1545                 r = sd_bus_get_unique_name(b, &sender_id);
1546                 if (r < 0)
1547                         return r;
1548         }
1549
1550         if (!external_id) {
1551                 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
1552                 external_id = external_buf;
1553         }
1554
1555         sender_label = bus_label_escape(sender_id);
1556         if (!sender_label)
1557                 return -ENOMEM;
1558
1559         external_label = bus_label_escape(external_id);
1560         if (!external_label)
1561                 return -ENOMEM;
1562
1563         p = strjoin(prefix, "/", sender_label, "/", external_label);
1564         if (!p)
1565                 return -ENOMEM;
1566
1567         *ret_path = p;
1568         return 0;
1569 }
1570
1571 /**
1572  * bus_path_decode_unique() - decode unique object path
1573  * @path: object path to decode
1574  * @prefix: object path prefix
1575  * @ret_sender: output parameter for sender-id label
1576  * @ret_external: output parameter for external-id label
1577  *
1578  * This does the reverse of bus_path_encode_unique() (see its description for
1579  * details). Both trailing labels, sender-id and external-id, are unescaped and
1580  * returned in the given output parameters (the caller must free them).
1581  *
1582  * Note that this function returns 0 if the path does not match the template
1583  * (see bus_path_encode_unique()), 1 if it matched.
1584  *
1585  * Returns: Negative error code on failure, 0 if the given object path does not
1586  *          match the template (return parameters are set to NULL), 1 if it was
1587  *          parsed successfully (return parameters contain allocated labels).
1588  */
1589 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
1590         const char *p, *q;
1591         char *sender, *external;
1592
1593         assert(object_path_is_valid(path));
1594         assert(object_path_is_valid(prefix));
1595         assert(ret_sender);
1596         assert(ret_external);
1597
1598         p = object_path_startswith(path, prefix);
1599         if (!p) {
1600                 *ret_sender = NULL;
1601                 *ret_external = NULL;
1602                 return 0;
1603         }
1604
1605         q = strchr(p, '/');
1606         if (!q) {
1607                 *ret_sender = NULL;
1608                 *ret_external = NULL;
1609                 return 0;
1610         }
1611
1612         sender = bus_label_unescape_n(p, q - p);
1613         external = bus_label_unescape(q + 1);
1614         if (!sender || !external) {
1615                 free(sender);
1616                 free(external);
1617                 return -ENOMEM;
1618         }
1619
1620         *ret_sender = sender;
1621         *ret_external = external;
1622         return 1;
1623 }
1624 #endif // 0
1625
1626 #if 0 /// UNNEEDED by elogind
1627 int bus_property_get_rlimit(
1628                 sd_bus *bus,
1629                 const char *path,
1630                 const char *interface,
1631                 const char *property,
1632                 sd_bus_message *reply,
1633                 void *userdata,
1634                 sd_bus_error *error) {
1635
1636         struct rlimit *rl;
1637         uint64_t u;
1638         rlim_t x;
1639         const char *is_soft;
1640
1641         assert(bus);
1642         assert(reply);
1643         assert(userdata);
1644
1645         is_soft = endswith(property, "Soft");
1646         rl = *(struct rlimit**) userdata;
1647         if (rl)
1648                 x = is_soft ? rl->rlim_cur : rl->rlim_max;
1649         else {
1650                 struct rlimit buf = {};
1651                 int z;
1652                 const char *s;
1653
1654                 s = is_soft ? strndupa(property, is_soft - property) : property;
1655
1656                 z = rlimit_from_string(strstr(s, "Limit"));
1657                 assert(z >= 0);
1658
1659                 getrlimit(z, &buf);
1660                 x = is_soft ? buf.rlim_cur : buf.rlim_max;
1661         }
1662
1663         /* rlim_t might have different sizes, let's map
1664          * RLIMIT_INFINITY to (uint64_t) -1, so that it is the same on
1665          * all archs */
1666         u = x == RLIM_INFINITY ? (uint64_t) -1 : (uint64_t) x;
1667
1668         return sd_bus_message_append(reply, "t", u);
1669 }
1670
1671 int bus_track_add_name_many(sd_bus_track *t, char **l) {
1672         int r = 0;
1673         char **i;
1674
1675         assert(t);
1676
1677         /* Continues adding after failure, and returns the first failure. */
1678
1679         STRV_FOREACH(i, l) {
1680                 int k;
1681
1682                 k = sd_bus_track_add_name(t, *i);
1683                 if (k < 0 && r >= 0)
1684                         r = k;
1685         }
1686
1687         return r;
1688 }
1689 #endif // 0
1690
1691 int bus_open_system_watch_bind(sd_bus **ret) {
1692         _cleanup_(sd_bus_unrefp) sd_bus *bus = NULL;
1693         const char *e;
1694         int r;
1695
1696         assert(ret);
1697
1698         /* Match like sd_bus_open_system(), but with the "watch_bind" feature and the Connected() signal turned on. */
1699
1700         r = sd_bus_new(&bus);
1701         if (r < 0)
1702                 return r;
1703
1704         e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
1705         if (!e)
1706                 e = DEFAULT_SYSTEM_BUS_ADDRESS;
1707
1708         r = sd_bus_set_address(bus, e);
1709         if (r < 0)
1710                 return r;
1711
1712         r = sd_bus_set_bus_client(bus, true);
1713         if (r < 0)
1714                 return r;
1715
1716         r = sd_bus_set_trusted(bus, true);
1717         if (r < 0)
1718                 return r;
1719
1720         r = sd_bus_negotiate_creds(bus, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_EFFECTIVE_CAPS);
1721         if (r < 0)
1722                 return r;
1723
1724         r = sd_bus_set_watch_bind(bus, true);
1725         if (r < 0)
1726                 return r;
1727
1728         r = sd_bus_set_connected_signal(bus, true);
1729         if (r < 0)
1730                 return r;
1731
1732         r = sd_bus_start(bus);
1733         if (r < 0)
1734                 return r;
1735
1736         *ret = TAKE_PTR(bus);
1737
1738         return 0;
1739 }