chiark / gitweb /
Prep v222: Update build system:
[elogind.git] / src / shared / bus-util.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4   This file is part of systemd.
5
6   Copyright 2013 Lennart Poettering
7
8   systemd is free software; you can redistribute it and/or modify it
9   under the terms of the GNU Lesser General Public License as published by
10   the Free Software Foundation; either version 2.1 of the License, or
11   (at your option) any later version.
12
13   systemd is distributed in the hope that it will be useful, but
14   WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16   Lesser General Public License for more details.
17
18   You should have received a copy of the GNU Lesser General Public License
19   along with systemd; If not, see <http://www.gnu.org/licenses/>.
20 ***/
21
22 #include <sys/socket.h>
23
24 #include "sd-daemon.h"
25 #include "sd-event.h"
26 #include "util.h"
27 #include "strv.h"
28 #include "macro.h"
29 #include "def.h"
30 #include "path-util.h"
31 #include "missing.h"
32 #include "set.h"
33 #include "signal-util.h"
34 #include "unit-name.h"
35
36 #include "sd-bus.h"
37 #include "bus-error.h"
38 #include "bus-label.h"
39 #include "bus-message.h"
40 #include "bus-util.h"
41 #include "bus-internal.h"
42
43 static int name_owner_change_callback(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
44         sd_event *e = userdata;
45
46         assert(m);
47         assert(e);
48
49         sd_bus_close(sd_bus_message_get_bus(m));
50         sd_event_exit(e, 0);
51
52         return 1;
53 }
54
55 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
56         _cleanup_free_ char *match = NULL;
57         const char *unique;
58         int r;
59
60         assert(e);
61         assert(bus);
62         assert(name);
63
64         /* We unregister the name here and then wait for the
65          * NameOwnerChanged signal for this event to arrive before we
66          * quit. We do this in order to make sure that any queued
67          * requests are still processed before we really exit. */
68
69         r = sd_bus_get_unique_name(bus, &unique);
70         if (r < 0)
71                 return r;
72
73         r = asprintf(&match,
74                      "sender='org.freedesktop.DBus',"
75                      "type='signal',"
76                      "interface='org.freedesktop.DBus',"
77                      "member='NameOwnerChanged',"
78                      "path='/org/freedesktop/DBus',"
79                      "arg0='%s',"
80                      "arg1='%s',"
81                      "arg2=''", name, unique);
82         if (r < 0)
83                 return -ENOMEM;
84
85         r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
86         if (r < 0)
87                 return r;
88
89         r = sd_bus_release_name(bus, name);
90         if (r < 0)
91                 return r;
92
93         return 0;
94 }
95
96 int bus_event_loop_with_idle(
97                 sd_event *e,
98                 sd_bus *bus,
99                 const char *name,
100                 usec_t timeout,
101                 check_idle_t check_idle,
102                 void *userdata) {
103         bool exiting = false;
104         int r, code;
105
106         assert(e);
107         assert(bus);
108         assert(name);
109
110         for (;;) {
111                 bool idle;
112
113                 r = sd_event_get_state(e);
114                 if (r < 0)
115                         return r;
116                 if (r == SD_EVENT_FINISHED)
117                         break;
118
119                 if (check_idle)
120                         idle = check_idle(userdata);
121                 else
122                         idle = true;
123
124                 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
125                 if (r < 0)
126                         return r;
127
128                 if (r == 0 && !exiting && idle) {
129
130                         r = sd_bus_try_close(bus);
131                         if (r == -EBUSY)
132                                 continue;
133
134                         /* Fallback for dbus1 connections: we
135                          * unregister the name and wait for the
136                          * response to come through for it */
137                         if (r == -EOPNOTSUPP) {
138
139                                 /* Inform the service manager that we
140                                  * are going down, so that it will
141                                  * queue all further start requests,
142                                  * instead of assuming we are already
143                                  * running. */
144                                 sd_notify(false, "STOPPING=1");
145
146                                 r = bus_async_unregister_and_exit(e, bus, name);
147                                 if (r < 0)
148                                         return r;
149
150                                 exiting = true;
151                                 continue;
152                         }
153
154                         if (r < 0)
155                                 return r;
156
157                         sd_event_exit(e, 0);
158                         break;
159                 }
160         }
161
162         r = sd_event_get_exit_code(e, &code);
163         if (r < 0)
164                 return r;
165
166         return code;
167 }
168
169 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
170         _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
171         int r, has_owner = 0;
172
173         assert(c);
174         assert(name);
175
176         r = sd_bus_call_method(c,
177                                "org.freedesktop.DBus",
178                                "/org/freedesktop/dbus",
179                                "org.freedesktop.DBus",
180                                "NameHasOwner",
181                                error,
182                                &rep,
183                                "s",
184                                name);
185         if (r < 0)
186                 return r;
187
188         r = sd_bus_message_read_basic(rep, 'b', &has_owner);
189         if (r < 0)
190                 return sd_bus_error_set_errno(error, r);
191
192         return has_owner;
193 }
194
195 static int check_good_user(sd_bus_message *m, uid_t good_user) {
196         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
197         uid_t sender_uid;
198         int r;
199
200         assert(m);
201
202         if (good_user == UID_INVALID)
203                 return 0;
204
205         r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
206         if (r < 0)
207                 return r;
208
209         /* Don't trust augmented credentials for authorization */
210         assert_return((sd_bus_creds_get_augmented_mask(creds) & SD_BUS_CREDS_EUID) == 0, -EPERM);
211
212         r = sd_bus_creds_get_euid(creds, &sender_uid);
213         if (r < 0)
214                 return r;
215
216         return sender_uid == good_user;
217 }
218
219 int bus_test_polkit(
220                 sd_bus_message *call,
221                 int capability,
222                 const char *action,
223                 uid_t good_user,
224                 bool *_challenge,
225                 sd_bus_error *e) {
226
227         int r;
228
229         assert(call);
230         assert(action);
231
232         /* Tests non-interactively! */
233
234         r = check_good_user(call, good_user);
235         if (r != 0)
236                 return r;
237
238         r = sd_bus_query_sender_privilege(call, capability);
239         if (r < 0)
240                 return r;
241         else if (r > 0)
242                 return 1;
243 #ifdef ENABLE_POLKIT
244         else {
245                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
246                 int authorized = false, challenge = false;
247                 const char *sender;
248
249                 sender = sd_bus_message_get_sender(call);
250                 if (!sender)
251                         return -EBADMSG;
252
253                 r = sd_bus_call_method(
254                                 call->bus,
255                                 "org.freedesktop.PolicyKit1",
256                                 "/org/freedesktop/PolicyKit1/Authority",
257                                 "org.freedesktop.PolicyKit1.Authority",
258                                 "CheckAuthorization",
259                                 e,
260                                 &reply,
261                                 "(sa{sv})sa{ss}us",
262                                 "system-bus-name", 1, "name", "s", sender,
263                                 action,
264                                 0,
265                                 0,
266                                 "");
267
268                 if (r < 0) {
269                         /* Treat no PK available as access denied */
270                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
271                                 sd_bus_error_free(e);
272                                 return -EACCES;
273                         }
274
275                         return r;
276                 }
277
278                 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
279                 if (r < 0)
280                         return r;
281
282                 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
283                 if (r < 0)
284                         return r;
285
286                 if (authorized)
287                         return 1;
288
289                 if (_challenge) {
290                         *_challenge = challenge;
291                         return 0;
292                 }
293         }
294 #endif
295
296         return -EACCES;
297 }
298
299 #ifdef ENABLE_POLKIT
300
301 typedef struct AsyncPolkitQuery {
302         sd_bus_message *request, *reply;
303         sd_bus_message_handler_t callback;
304         void *userdata;
305         sd_bus_slot *slot;
306         Hashmap *registry;
307 } AsyncPolkitQuery;
308
309 static void async_polkit_query_free(AsyncPolkitQuery *q) {
310
311         if (!q)
312                 return;
313
314         sd_bus_slot_unref(q->slot);
315
316         if (q->registry && q->request)
317                 hashmap_remove(q->registry, q->request);
318
319         sd_bus_message_unref(q->request);
320         sd_bus_message_unref(q->reply);
321
322         free(q);
323 }
324
325 static int async_polkit_callback(sd_bus_message *reply, void *userdata, sd_bus_error *error) {
326         _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
327         AsyncPolkitQuery *q = userdata;
328         int r;
329
330         assert(reply);
331         assert(q);
332
333         q->slot = sd_bus_slot_unref(q->slot);
334         q->reply = sd_bus_message_ref(reply);
335
336         r = sd_bus_message_rewind(q->request, true);
337         if (r < 0) {
338                 r = sd_bus_reply_method_errno(q->request, r, NULL);
339                 goto finish;
340         }
341
342         r = q->callback(q->request, q->userdata, &error_buffer);
343         r = bus_maybe_reply_error(q->request, r, &error_buffer);
344
345 finish:
346         async_polkit_query_free(q);
347
348         return r;
349 }
350
351 #endif
352
353 int bus_verify_polkit_async(
354                 sd_bus_message *call,
355                 int capability,
356                 const char *action,
357                 bool interactive,
358                 uid_t good_user,
359                 Hashmap **registry,
360                 sd_bus_error *error) {
361
362 #ifdef ENABLE_POLKIT
363         _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
364         AsyncPolkitQuery *q;
365         const char *sender;
366         sd_bus_message_handler_t callback;
367         void *userdata;
368         int c;
369 #endif
370         int r;
371
372         assert(call);
373         assert(action);
374         assert(registry);
375
376         r = check_good_user(call, good_user);
377         if (r != 0)
378                 return r;
379
380 #ifdef ENABLE_POLKIT
381         q = hashmap_get(*registry, call);
382         if (q) {
383                 int authorized, challenge;
384
385                 /* This is the second invocation of this function, and
386                  * there's already a response from polkit, let's
387                  * process it */
388                 assert(q->reply);
389
390                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
391                         const sd_bus_error *e;
392
393                         /* Copy error from polkit reply */
394                         e = sd_bus_message_get_error(q->reply);
395                         sd_bus_error_copy(error, e);
396
397                         /* Treat no PK available as access denied */
398                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
399                                 return -EACCES;
400
401                         return -sd_bus_error_get_errno(e);
402                 }
403
404                 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
405                 if (r >= 0)
406                         r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
407
408                 if (r < 0)
409                         return r;
410
411                 if (authorized)
412                         return 1;
413
414                 if (challenge)
415                         return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
416
417                 return -EACCES;
418         }
419 #endif
420
421         r = sd_bus_query_sender_privilege(call, capability);
422         if (r < 0)
423                 return r;
424         else if (r > 0)
425                 return 1;
426
427 #ifdef ENABLE_POLKIT
428         if (sd_bus_get_current_message(call->bus) != call)
429                 return -EINVAL;
430
431         callback = sd_bus_get_current_handler(call->bus);
432         if (!callback)
433                 return -EINVAL;
434
435         userdata = sd_bus_get_current_userdata(call->bus);
436
437         sender = sd_bus_message_get_sender(call);
438         if (!sender)
439                 return -EBADMSG;
440
441         c = sd_bus_message_get_allow_interactive_authorization(call);
442         if (c < 0)
443                 return c;
444         if (c > 0)
445                 interactive = true;
446
447         r = hashmap_ensure_allocated(registry, NULL);
448         if (r < 0)
449                 return r;
450
451         r = sd_bus_message_new_method_call(
452                         call->bus,
453                         &pk,
454                         "org.freedesktop.PolicyKit1",
455                         "/org/freedesktop/PolicyKit1/Authority",
456                         "org.freedesktop.PolicyKit1.Authority",
457                         "CheckAuthorization");
458         if (r < 0)
459                 return r;
460
461         r = sd_bus_message_append(
462                         pk,
463                         "(sa{sv})sa{ss}us",
464                         "system-bus-name", 1, "name", "s", sender,
465                         action,
466                         0,
467                         !!interactive,
468                         NULL);
469         if (r < 0)
470                 return r;
471
472         q = new0(AsyncPolkitQuery, 1);
473         if (!q)
474                 return -ENOMEM;
475
476         q->request = sd_bus_message_ref(call);
477         q->callback = callback;
478         q->userdata = userdata;
479
480         r = hashmap_put(*registry, call, q);
481         if (r < 0) {
482                 async_polkit_query_free(q);
483                 return r;
484         }
485
486         q->registry = *registry;
487
488         r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
489         if (r < 0) {
490                 async_polkit_query_free(q);
491                 return r;
492         }
493
494         return 0;
495 #endif
496
497         return -EACCES;
498 }
499
500 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
501 #ifdef ENABLE_POLKIT
502         AsyncPolkitQuery *q;
503
504         while ((q = hashmap_steal_first(registry)))
505                 async_polkit_query_free(q);
506
507         hashmap_free(registry);
508 #endif
509 }
510
511 int bus_check_peercred(sd_bus *c) {
512         struct ucred ucred;
513         socklen_t l;
514         int fd;
515
516         assert(c);
517
518         fd = sd_bus_get_fd(c);
519         if (fd < 0)
520                 return fd;
521
522         l = sizeof(struct ucred);
523         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
524                 return -errno;
525
526         if (l != sizeof(struct ucred))
527                 return -E2BIG;
528
529         if (ucred.uid != 0 && ucred.uid != geteuid())
530                 return -EPERM;
531
532         return 1;
533 }
534
535 int bus_open_system_systemd(sd_bus **_bus) {
536         _cleanup_bus_unref_ sd_bus *bus = NULL;
537         int r;
538
539         assert(_bus);
540
541         if (geteuid() != 0)
542                 return sd_bus_open_system(_bus);
543
544         /* If we are root and kdbus is not available, then let's talk
545          * directly to the system instance, instead of going via the
546          * bus */
547
548         r = sd_bus_new(&bus);
549         if (r < 0)
550                 return r;
551
552         r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
553         if (r < 0)
554                 return r;
555
556         bus->bus_client = true;
557
558         r = sd_bus_start(bus);
559         if (r >= 0) {
560                 *_bus = bus;
561                 bus = NULL;
562                 return 0;
563         }
564
565         bus = sd_bus_unref(bus);
566
567         r = sd_bus_new(&bus);
568         if (r < 0)
569                 return r;
570
571         r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
572         if (r < 0)
573                 return r;
574
575         r = sd_bus_start(bus);
576         if (r < 0)
577                 return sd_bus_open_system(_bus);
578
579         r = bus_check_peercred(bus);
580         if (r < 0)
581                 return r;
582
583         *_bus = bus;
584         bus = NULL;
585
586         return 0;
587 }
588
589 int bus_open_user_systemd(sd_bus **_bus) {
590         _cleanup_bus_unref_ sd_bus *bus = NULL;
591         _cleanup_free_ char *ee = NULL;
592         const char *e;
593         int r;
594
595         /* Try via kdbus first, and then directly */
596
597         assert(_bus);
598
599         r = sd_bus_new(&bus);
600         if (r < 0)
601                 return r;
602
603         if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
604                 return -ENOMEM;
605
606         bus->bus_client = true;
607
608         r = sd_bus_start(bus);
609         if (r >= 0) {
610                 *_bus = bus;
611                 bus = NULL;
612                 return 0;
613         }
614
615         bus = sd_bus_unref(bus);
616
617         e = secure_getenv("XDG_RUNTIME_DIR");
618         if (!e)
619                 return sd_bus_open_user(_bus);
620
621         ee = bus_address_escape(e);
622         if (!ee)
623                 return -ENOMEM;
624
625         r = sd_bus_new(&bus);
626         if (r < 0)
627                 return r;
628
629         bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
630         if (!bus->address)
631                 return -ENOMEM;
632
633         r = sd_bus_start(bus);
634         if (r < 0)
635                 return sd_bus_open_user(_bus);
636
637         r = bus_check_peercred(bus);
638         if (r < 0)
639                 return r;
640
641         *_bus = bus;
642         bus = NULL;
643
644         return 0;
645 }
646
647 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
648         char type;
649         const char *contents;
650         int r;
651
652         assert(name);
653         assert(property);
654
655         r = sd_bus_message_peek_type(property, &type, &contents);
656         if (r < 0)
657                 return r;
658
659         switch (type) {
660
661         case SD_BUS_TYPE_STRING: {
662                 const char *s;
663
664                 r = sd_bus_message_read_basic(property, type, &s);
665                 if (r < 0)
666                         return r;
667
668                 if (all || !isempty(s)) {
669                         _cleanup_free_ char *escaped = NULL;
670
671                         escaped = xescape(s, "\n");
672                         if (!escaped)
673                                 return -ENOMEM;
674
675                         printf("%s=%s\n", name, escaped);
676                 }
677
678                 return 1;
679         }
680
681         case SD_BUS_TYPE_BOOLEAN: {
682                 int b;
683
684                 r = sd_bus_message_read_basic(property, type, &b);
685                 if (r < 0)
686                         return r;
687
688                 printf("%s=%s\n", name, yes_no(b));
689
690                 return 1;
691         }
692
693         case SD_BUS_TYPE_UINT64: {
694                 uint64_t u;
695
696                 r = sd_bus_message_read_basic(property, type, &u);
697                 if (r < 0)
698                         return r;
699
700                 /* Yes, heuristics! But we can change this check
701                  * should it turn out to not be sufficient */
702
703                 if (endswith(name, "Timestamp")) {
704                         char timestamp[FORMAT_TIMESTAMP_MAX], *t;
705
706                         t = format_timestamp(timestamp, sizeof(timestamp), u);
707                         if (t || all)
708                                 printf("%s=%s\n", name, strempty(t));
709
710                 } else if (strstr(name, "USec")) {
711                         char timespan[FORMAT_TIMESPAN_MAX];
712
713                         printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
714                 } else
715                         printf("%s=%llu\n", name, (unsigned long long) u);
716
717                 return 1;
718         }
719
720         case SD_BUS_TYPE_INT64: {
721                 int64_t i;
722
723                 r = sd_bus_message_read_basic(property, type, &i);
724                 if (r < 0)
725                         return r;
726
727                 printf("%s=%lld\n", name, (long long) i);
728
729                 return 1;
730         }
731
732         case SD_BUS_TYPE_UINT32: {
733                 uint32_t u;
734
735                 r = sd_bus_message_read_basic(property, type, &u);
736                 if (r < 0)
737                         return r;
738
739                 if (strstr(name, "UMask") || strstr(name, "Mode"))
740                         printf("%s=%04o\n", name, u);
741                 else
742                         printf("%s=%u\n", name, (unsigned) u);
743
744                 return 1;
745         }
746
747         case SD_BUS_TYPE_INT32: {
748                 int32_t i;
749
750                 r = sd_bus_message_read_basic(property, type, &i);
751                 if (r < 0)
752                         return r;
753
754                 printf("%s=%i\n", name, (int) i);
755                 return 1;
756         }
757
758         case SD_BUS_TYPE_DOUBLE: {
759                 double d;
760
761                 r = sd_bus_message_read_basic(property, type, &d);
762                 if (r < 0)
763                         return r;
764
765                 printf("%s=%g\n", name, d);
766                 return 1;
767         }
768
769         case SD_BUS_TYPE_ARRAY:
770                 if (streq(contents, "s")) {
771                         bool first = true;
772                         const char *str;
773
774                         r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
775                         if (r < 0)
776                                 return r;
777
778                         while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
779                                 _cleanup_free_ char *escaped = NULL;
780
781                                 if (first)
782                                         printf("%s=", name);
783
784                                 escaped = xescape(str, "\n ");
785                                 if (!escaped)
786                                         return -ENOMEM;
787
788                                 printf("%s%s", first ? "" : " ", escaped);
789
790                                 first = false;
791                         }
792                         if (r < 0)
793                                 return r;
794
795                         if (first && all)
796                                 printf("%s=", name);
797                         if (!first || all)
798                                 puts("");
799
800                         r = sd_bus_message_exit_container(property);
801                         if (r < 0)
802                                 return r;
803
804                         return 1;
805
806                 } else if (streq(contents, "y")) {
807                         const uint8_t *u;
808                         size_t n;
809
810                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
811                         if (r < 0)
812                                 return r;
813
814                         if (all || n > 0) {
815                                 unsigned int i;
816
817                                 printf("%s=", name);
818
819                                 for (i = 0; i < n; i++)
820                                         printf("%02x", u[i]);
821
822                                 puts("");
823                         }
824
825                         return 1;
826
827                 } else if (streq(contents, "u")) {
828                         uint32_t *u;
829                         size_t n;
830
831                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
832                         if (r < 0)
833                                 return r;
834
835                         if (all || n > 0) {
836                                 unsigned int i;
837
838                                 printf("%s=", name);
839
840                                 for (i = 0; i < n; i++)
841                                         printf("%08x", u[i]);
842
843                                 puts("");
844                         }
845
846                         return 1;
847                 }
848
849                 break;
850         }
851
852         return 0;
853 }
854
855 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
856         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
857         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
858         int r;
859
860         assert(bus);
861         assert(path);
862
863         r = sd_bus_call_method(bus,
864                         dest,
865                         path,
866                         "org.freedesktop.DBus.Properties",
867                         "GetAll",
868                         &error,
869                         &reply,
870                         "s", "");
871         if (r < 0)
872                 return r;
873
874         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
875         if (r < 0)
876                 return r;
877
878         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
879                 const char *name;
880                 const char *contents;
881
882                 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
883                 if (r < 0)
884                         return r;
885
886                 if (!filter || strv_find(filter, name)) {
887                         r = sd_bus_message_peek_type(reply, NULL, &contents);
888                         if (r < 0)
889                                 return r;
890
891                         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
892                         if (r < 0)
893                                 return r;
894
895                         r = bus_print_property(name, reply, all);
896                         if (r < 0)
897                                 return r;
898                         if (r == 0) {
899                                 if (all)
900                                         printf("%s=[unprintable]\n", name);
901                                 /* skip what we didn't read */
902                                 r = sd_bus_message_skip(reply, contents);
903                                 if (r < 0)
904                                         return r;
905                         }
906
907                         r = sd_bus_message_exit_container(reply);
908                         if (r < 0)
909                                 return r;
910                 } else {
911                         r = sd_bus_message_skip(reply, "v");
912                         if (r < 0)
913                                 return r;
914                 }
915
916                 r = sd_bus_message_exit_container(reply);
917                 if (r < 0)
918                         return r;
919         }
920         if (r < 0)
921                 return r;
922
923         r = sd_bus_message_exit_container(reply);
924         if (r < 0)
925                 return r;
926
927         return 0;
928 }
929
930 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
931         sd_id128_t *p = userdata;
932         const void *v;
933         size_t n;
934         int r;
935
936         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
937         if (r < 0)
938                 return r;
939
940         if (n == 0)
941                 *p = SD_ID128_NULL;
942         else if (n == 16)
943                 memcpy((*p).bytes, v, n);
944         else
945                 return -EINVAL;
946
947         return 0;
948 }
949
950 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
951         char type;
952         int r;
953
954         r = sd_bus_message_peek_type(m, &type, NULL);
955         if (r < 0)
956                 return r;
957
958         switch (type) {
959         case SD_BUS_TYPE_STRING: {
960                 const char *s;
961                 char **p = userdata;
962
963                 r = sd_bus_message_read_basic(m, type, &s);
964                 if (r < 0)
965                         break;
966
967                 if (isempty(s))
968                         break;
969
970                 r = free_and_strdup(p, s);
971                 break;
972         }
973
974         case SD_BUS_TYPE_ARRAY: {
975                _cleanup_strv_free_ char **l = NULL;
976                char ***p = userdata;
977
978                 r = bus_message_read_strv_extend(m, &l);
979                 if (r < 0)
980                         break;
981
982                 strv_free(*p);
983                 *p = l;
984                 l = NULL;
985
986                 break;
987         }
988
989         case SD_BUS_TYPE_BOOLEAN: {
990                 unsigned b;
991                 bool *p = userdata;
992
993                 r = sd_bus_message_read_basic(m, type, &b);
994                 if (r < 0)
995                         break;
996
997                 *p = b;
998
999                 break;
1000         }
1001
1002         case SD_BUS_TYPE_UINT32: {
1003                 uint64_t u;
1004                 uint32_t *p = userdata;
1005
1006                 r = sd_bus_message_read_basic(m, type, &u);
1007                 if (r < 0)
1008                         break;
1009
1010                 *p = u;
1011
1012                 break;
1013         }
1014
1015         case SD_BUS_TYPE_UINT64: {
1016                 uint64_t t;
1017                 uint64_t *p = userdata;
1018
1019                 r = sd_bus_message_read_basic(m, type, &t);
1020                 if (r < 0)
1021                         break;
1022
1023                 *p = t;
1024
1025                 break;
1026         }
1027
1028         default:
1029                 break;
1030         }
1031
1032         return r;
1033 }
1034
1035 int bus_message_map_all_properties(
1036                 sd_bus_message *m,
1037                 const struct bus_properties_map *map,
1038                 void *userdata) {
1039
1040         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1041         int r;
1042
1043         assert(m);
1044         assert(map);
1045
1046         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1047         if (r < 0)
1048                 return r;
1049
1050         while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1051                 const struct bus_properties_map *prop;
1052                 const char *member;
1053                 const char *contents;
1054                 void *v;
1055                 unsigned i;
1056
1057                 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1058                 if (r < 0)
1059                         return r;
1060
1061                 for (i = 0, prop = NULL; map[i].member; i++)
1062                         if (streq(map[i].member, member)) {
1063                                 prop = &map[i];
1064                                 break;
1065                         }
1066
1067                 if (prop) {
1068                         r = sd_bus_message_peek_type(m, NULL, &contents);
1069                         if (r < 0)
1070                                 return r;
1071
1072                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1073                         if (r < 0)
1074                                 return r;
1075
1076                         v = (uint8_t *)userdata + prop->offset;
1077                         if (map[i].set)
1078                                 r = prop->set(sd_bus_message_get_bus(m), member, m, &error, v);
1079                         else
1080                                 r = map_basic(sd_bus_message_get_bus(m), member, m, &error, v);
1081                         if (r < 0)
1082                                 return r;
1083
1084                         r = sd_bus_message_exit_container(m);
1085                         if (r < 0)
1086                                 return r;
1087                 } else {
1088                         r = sd_bus_message_skip(m, "v");
1089                         if (r < 0)
1090                                 return r;
1091                 }
1092
1093                 r = sd_bus_message_exit_container(m);
1094                 if (r < 0)
1095                         return r;
1096         }
1097         if (r < 0)
1098                 return r;
1099
1100         return sd_bus_message_exit_container(m);
1101 }
1102
1103 int bus_message_map_properties_changed(
1104                 sd_bus_message *m,
1105                 const struct bus_properties_map *map,
1106                 void *userdata) {
1107
1108         const char *member;
1109         int r, invalidated, i;
1110
1111         assert(m);
1112         assert(map);
1113
1114         r = bus_message_map_all_properties(m, map, userdata);
1115         if (r < 0)
1116                 return r;
1117
1118         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1119         if (r < 0)
1120                 return r;
1121
1122         invalidated = 0;
1123         while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1124                 for (i = 0; map[i].member; i++)
1125                         if (streq(map[i].member, member)) {
1126                                 ++invalidated;
1127                                 break;
1128                         }
1129         if (r < 0)
1130                 return r;
1131
1132         r = sd_bus_message_exit_container(m);
1133         if (r < 0)
1134                 return r;
1135
1136         return invalidated;
1137 }
1138
1139 int bus_map_all_properties(
1140                 sd_bus *bus,
1141                 const char *destination,
1142                 const char *path,
1143                 const struct bus_properties_map *map,
1144                 void *userdata) {
1145
1146         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1147         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1148         int r;
1149
1150         assert(bus);
1151         assert(destination);
1152         assert(path);
1153         assert(map);
1154
1155         r = sd_bus_call_method(
1156                         bus,
1157                         destination,
1158                         path,
1159                         "org.freedesktop.DBus.Properties",
1160                         "GetAll",
1161                         &error,
1162                         &m,
1163                         "s", "");
1164         if (r < 0)
1165                 return r;
1166
1167         return bus_message_map_all_properties(m, map, userdata);
1168 }
1169
1170 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1171         int r;
1172
1173         assert(transport >= 0);
1174         assert(transport < _BUS_TRANSPORT_MAX);
1175         assert(bus);
1176
1177         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1178         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1179
1180         switch (transport) {
1181
1182         case BUS_TRANSPORT_LOCAL:
1183                 if (user)
1184                         r = sd_bus_default_user(bus);
1185                 else
1186                         r = sd_bus_default_system(bus);
1187
1188                 break;
1189
1190         case BUS_TRANSPORT_REMOTE:
1191                 r = sd_bus_open_system_remote(bus, host);
1192                 break;
1193
1194         case BUS_TRANSPORT_MACHINE:
1195                 r = sd_bus_open_system_machine(bus, host);
1196                 break;
1197
1198         default:
1199                 assert_not_reached("Hmm, unknown transport type.");
1200         }
1201
1202         return r;
1203 }
1204
1205 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1206         int r;
1207
1208         assert(transport >= 0);
1209         assert(transport < _BUS_TRANSPORT_MAX);
1210         assert(bus);
1211
1212         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1213         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1214
1215         switch (transport) {
1216
1217         case BUS_TRANSPORT_LOCAL:
1218                 if (user)
1219                         r = bus_open_user_systemd(bus);
1220                 else
1221                         r = bus_open_system_systemd(bus);
1222
1223                 break;
1224
1225         case BUS_TRANSPORT_REMOTE:
1226                 r = sd_bus_open_system_remote(bus, host);
1227                 break;
1228
1229         case BUS_TRANSPORT_MACHINE:
1230                 r = sd_bus_open_system_machine(bus, host);
1231                 break;
1232
1233         default:
1234                 assert_not_reached("Hmm, unknown transport type.");
1235         }
1236
1237         return r;
1238 }
1239
1240 int bus_property_get_bool(
1241                 sd_bus *bus,
1242                 const char *path,
1243                 const char *interface,
1244                 const char *property,
1245                 sd_bus_message *reply,
1246                 void *userdata,
1247                 sd_bus_error *error) {
1248
1249         int b = *(bool*) userdata;
1250
1251         return sd_bus_message_append_basic(reply, 'b', &b);
1252 }
1253
1254 #if __SIZEOF_SIZE_T__ != 8
1255 int bus_property_get_size(
1256                 sd_bus *bus,
1257                 const char *path,
1258                 const char *interface,
1259                 const char *property,
1260                 sd_bus_message *reply,
1261                 void *userdata,
1262                 sd_bus_error *error) {
1263
1264         uint64_t sz = *(size_t*) userdata;
1265
1266         return sd_bus_message_append_basic(reply, 't', &sz);
1267 }
1268 #endif
1269
1270 #if __SIZEOF_LONG__ != 8
1271 int bus_property_get_long(
1272                 sd_bus *bus,
1273                 const char *path,
1274                 const char *interface,
1275                 const char *property,
1276                 sd_bus_message *reply,
1277                 void *userdata,
1278                 sd_bus_error *error) {
1279
1280         int64_t l = *(long*) userdata;
1281
1282         return sd_bus_message_append_basic(reply, 'x', &l);
1283 }
1284
1285 int bus_property_get_ulong(
1286                 sd_bus *bus,
1287                 const char *path,
1288                 const char *interface,
1289                 const char *property,
1290                 sd_bus_message *reply,
1291                 void *userdata,
1292                 sd_bus_error *error) {
1293
1294         uint64_t ul = *(unsigned long*) userdata;
1295
1296         return sd_bus_message_append_basic(reply, 't', &ul);
1297 }
1298 #endif
1299
1300 int bus_log_parse_error(int r) {
1301         return log_error_errno(r, "Failed to parse bus message: %m");
1302 }
1303
1304 int bus_log_create_error(int r) {
1305         return log_error_errno(r, "Failed to create bus message: %m");
1306 }
1307
1308 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1309         assert(message);
1310         assert(u);
1311
1312         u->machine = NULL;
1313
1314         return sd_bus_message_read(
1315                         message,
1316                         "(ssssssouso)",
1317                         &u->id,
1318                         &u->description,
1319                         &u->load_state,
1320                         &u->active_state,
1321                         &u->sub_state,
1322                         &u->following,
1323                         &u->unit_path,
1324                         &u->job_id,
1325                         &u->job_type,
1326                         &u->job_path);
1327 }
1328
1329 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1330         const char *eq, *field;
1331         int r;
1332
1333         assert(m);
1334         assert(assignment);
1335
1336         eq = strchr(assignment, '=');
1337         if (!eq) {
1338                 log_error("Not an assignment: %s", assignment);
1339                 return -EINVAL;
1340         }
1341
1342         field = strndupa(assignment, eq - assignment);
1343         eq ++;
1344
1345         if (streq(field, "CPUQuota")) {
1346
1347                 if (isempty(eq)) {
1348
1349                         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1350                         if (r < 0)
1351                                 return bus_log_create_error(r);
1352
1353                         r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1354
1355                 } else if (endswith(eq, "%")) {
1356                         double percent;
1357
1358                         if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1359                                 log_error("CPU quota '%s' invalid.", eq);
1360                                 return -EINVAL;
1361                         }
1362
1363                         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1364                         if (r < 0)
1365                                 return bus_log_create_error(r);
1366
1367                         r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1368                 } else {
1369                         log_error("CPU quota needs to be in percent.");
1370                         return -EINVAL;
1371                 }
1372
1373                 if (r < 0)
1374                         return bus_log_create_error(r);
1375
1376                 return 0;
1377         }
1378
1379         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1380         if (r < 0)
1381                 return bus_log_create_error(r);
1382
1383         if (STR_IN_SET(field,
1384                        "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1385                        "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies")) {
1386
1387                 r = parse_boolean(eq);
1388                 if (r < 0) {
1389                         log_error("Failed to parse boolean assignment %s.", assignment);
1390                         return -EINVAL;
1391                 }
1392
1393                 r = sd_bus_message_append(m, "v", "b", r);
1394
1395         } else if (streq(field, "MemoryLimit")) {
1396                 off_t bytes;
1397
1398                 r = parse_size(eq, 1024, &bytes);
1399                 if (r < 0) {
1400                         log_error("Failed to parse bytes specification %s", assignment);
1401                         return -EINVAL;
1402                 }
1403
1404                 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1405
1406         } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1407                 uint64_t u;
1408
1409                 r = safe_atou64(eq, &u);
1410                 if (r < 0) {
1411                         log_error("Failed to parse %s value %s.", field, eq);
1412                         return -EINVAL;
1413                 }
1414
1415                 r = sd_bus_message_append(m, "v", "t", u);
1416
1417         } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1418                 r = sd_bus_message_append(m, "v", "s", eq);
1419
1420         else if (streq(field, "DeviceAllow")) {
1421
1422                 if (isempty(eq))
1423                         r = sd_bus_message_append(m, "v", "a(ss)", 0);
1424                 else {
1425                         const char *path, *rwm, *e;
1426
1427                         e = strchr(eq, ' ');
1428                         if (e) {
1429                                 path = strndupa(eq, e - eq);
1430                                 rwm = e+1;
1431                         } else {
1432                                 path = eq;
1433                                 rwm = "";
1434                         }
1435
1436                         if (!path_startswith(path, "/dev")) {
1437                                 log_error("%s is not a device file in /dev.", path);
1438                                 return -EINVAL;
1439                         }
1440
1441                         r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1442                 }
1443
1444         } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1445
1446                 if (isempty(eq))
1447                         r = sd_bus_message_append(m, "v", "a(st)", 0);
1448                 else {
1449                         const char *path, *bandwidth, *e;
1450                         off_t bytes;
1451
1452                         e = strchr(eq, ' ');
1453                         if (e) {
1454                                 path = strndupa(eq, e - eq);
1455                                 bandwidth = e+1;
1456                         } else {
1457                                 log_error("Failed to parse %s value %s.", field, eq);
1458                                 return -EINVAL;
1459                         }
1460
1461                         if (!path_startswith(path, "/dev")) {
1462                                 log_error("%s is not a device file in /dev.", path);
1463                                 return -EINVAL;
1464                         }
1465
1466                         r = parse_size(bandwidth, 1000, &bytes);
1467                         if (r < 0) {
1468                                 log_error("Failed to parse byte value %s.", bandwidth);
1469                                 return -EINVAL;
1470                         }
1471
1472                         r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1473                 }
1474
1475         } else if (streq(field, "BlockIODeviceWeight")) {
1476
1477                 if (isempty(eq))
1478                         r = sd_bus_message_append(m, "v", "a(st)", 0);
1479                 else {
1480                         const char *path, *weight, *e;
1481                         uint64_t u;
1482
1483                         e = strchr(eq, ' ');
1484                         if (e) {
1485                                 path = strndupa(eq, e - eq);
1486                                 weight = e+1;
1487                         } else {
1488                                 log_error("Failed to parse %s value %s.", field, eq);
1489                                 return -EINVAL;
1490                         }
1491
1492                         if (!path_startswith(path, "/dev")) {
1493                                 log_error("%s is not a device file in /dev.", path);
1494                                 return -EINVAL;
1495                         }
1496
1497                         r = safe_atou64(weight, &u);
1498                         if (r < 0) {
1499                                 log_error("Failed to parse %s value %s.", field, weight);
1500                                 return -EINVAL;
1501                         }
1502                         r = sd_bus_message_append(m, "v", "a(st)", path, u);
1503                 }
1504
1505         } else if (rlimit_from_string(field) >= 0) {
1506                 uint64_t rl;
1507
1508                 if (streq(eq, "infinity"))
1509                         rl = (uint64_t) -1;
1510                 else {
1511                         r = safe_atou64(eq, &rl);
1512                         if (r < 0) {
1513                                 log_error("Invalid resource limit: %s", eq);
1514                                 return -EINVAL;
1515                         }
1516                 }
1517
1518                 r = sd_bus_message_append(m, "v", "t", rl);
1519
1520         } else if (streq(field, "Nice")) {
1521                 int32_t i;
1522
1523                 r = safe_atoi32(eq, &i);
1524                 if (r < 0) {
1525                         log_error("Failed to parse %s value %s.", field, eq);
1526                         return -EINVAL;
1527                 }
1528
1529                 r = sd_bus_message_append(m, "v", "i", i);
1530
1531         } else if (streq(field, "Environment")) {
1532
1533                 r = sd_bus_message_append(m, "v", "as", 1, eq);
1534
1535         } else if (streq(field, "KillSignal")) {
1536                 int sig;
1537
1538                 sig = signal_from_string_try_harder(eq);
1539                 if (sig < 0) {
1540                         log_error("Failed to parse %s value %s.", field, eq);
1541                         return -EINVAL;
1542                 }
1543
1544                 r = sd_bus_message_append(m, "v", "i", sig);
1545
1546         } else if (streq(field, "AccuracySec")) {
1547                 usec_t u;
1548
1549                 r = parse_sec(eq, &u);
1550                 if (r < 0) {
1551                         log_error("Failed to parse %s value %s", field, eq);
1552                         return -EINVAL;
1553                 }
1554
1555                 r = sd_bus_message_append(m, "v", "t", u);
1556
1557         } else {
1558                 log_error("Unknown assignment %s.", assignment);
1559                 return -EINVAL;
1560         }
1561
1562         if (r < 0)
1563                 return bus_log_create_error(r);
1564
1565         return 0;
1566 }
1567
1568 typedef struct BusWaitForJobs {
1569         sd_bus *bus;
1570         Set *jobs;
1571
1572         char *name;
1573         char *result;
1574
1575         sd_bus_slot *slot_job_removed;
1576         sd_bus_slot *slot_disconnected;
1577 } BusWaitForJobs;
1578
1579 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1580         assert(m);
1581
1582         log_error("Warning! D-Bus connection terminated.");
1583         sd_bus_close(sd_bus_message_get_bus(m));
1584
1585         return 0;
1586 }
1587
1588 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1589         const char *path, *unit, *result;
1590         BusWaitForJobs *d = userdata;
1591         uint32_t id;
1592         char *found;
1593         int r;
1594
1595         assert(m);
1596         assert(d);
1597
1598         r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1599         if (r < 0) {
1600                 bus_log_parse_error(r);
1601                 return 0;
1602         }
1603
1604         found = set_remove(d->jobs, (char*) path);
1605         if (!found)
1606                 return 0;
1607
1608         free(found);
1609
1610         if (!isempty(result))
1611                 d->result = strdup(result);
1612
1613         if (!isempty(unit))
1614                 d->name = strdup(unit);
1615
1616         return 0;
1617 }
1618
1619 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1620         if (!d)
1621                 return;
1622
1623         set_free_free(d->jobs);
1624
1625         sd_bus_slot_unref(d->slot_disconnected);
1626         sd_bus_slot_unref(d->slot_job_removed);
1627
1628         sd_bus_unref(d->bus);
1629
1630         free(d->name);
1631         free(d->result);
1632
1633         free(d);
1634 }
1635
1636 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1637         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1638         int r;
1639
1640         assert(bus);
1641         assert(ret);
1642
1643         d = new0(BusWaitForJobs, 1);
1644         if (!d)
1645                 return -ENOMEM;
1646
1647         d->bus = sd_bus_ref(bus);
1648
1649         /* When we are a bus client we match by sender. Direct
1650          * connections OTOH have no initialized sender field, and
1651          * hence we ignore the sender then */
1652         r = sd_bus_add_match(
1653                         bus,
1654                         &d->slot_job_removed,
1655                         bus->bus_client ?
1656                         "type='signal',"
1657                         "sender='org.freedesktop.systemd1',"
1658                         "interface='org.freedesktop.systemd1.Manager',"
1659                         "member='JobRemoved',"
1660                         "path='/org/freedesktop/systemd1'" :
1661                         "type='signal',"
1662                         "interface='org.freedesktop.systemd1.Manager',"
1663                         "member='JobRemoved',"
1664                         "path='/org/freedesktop/systemd1'",
1665                         match_job_removed, d);
1666         if (r < 0)
1667                 return r;
1668
1669         r = sd_bus_add_match(
1670                         bus,
1671                         &d->slot_disconnected,
1672                         "type='signal',"
1673                         "sender='org.freedesktop.DBus.Local',"
1674                         "interface='org.freedesktop.DBus.Local',"
1675                         "member='Disconnected'",
1676                         match_disconnected, d);
1677         if (r < 0)
1678                 return r;
1679
1680         *ret = d;
1681         d = NULL;
1682
1683         return 0;
1684 }
1685
1686 static int bus_process_wait(sd_bus *bus) {
1687         int r;
1688
1689         for (;;) {
1690                 r = sd_bus_process(bus, NULL);
1691                 if (r < 0)
1692                         return r;
1693                 if (r > 0)
1694                         return 0;
1695
1696                 r = sd_bus_wait(bus, (uint64_t) -1);
1697                 if (r < 0)
1698                         return r;
1699         }
1700 }
1701
1702 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
1703         _cleanup_free_ char *dbus_path = NULL;
1704
1705         assert(d);
1706         assert(d->name);
1707         assert(result);
1708
1709         dbus_path = unit_dbus_path_from_name(d->name);
1710         if (!dbus_path)
1711                 return -ENOMEM;
1712
1713         return sd_bus_get_property_string(d->bus,
1714                                           "org.freedesktop.systemd1",
1715                                           dbus_path,
1716                                           "org.freedesktop.systemd1.Service",
1717                                           "Result",
1718                                           NULL,
1719                                           result);
1720 }
1721
1722 static const struct {
1723         const char *result, *explanation;
1724 } explanations [] = {
1725         { "resources",   "a configured resource limit was exceeded" },
1726         { "timeout",     "a timeout was exceeded" },
1727         { "exit-code",   "the control process exited with error code" },
1728         { "signal",      "a fatal signal was delivered to the control process" },
1729         { "core-dump",   "a fatal signal was delivered causing the control process to dump core" },
1730         { "watchdog",    "the service failed to send watchdog ping" },
1731         { "start-limit", "start of the service was attempted too often" }
1732 };
1733
1734 static void log_job_error_with_service_result(const char* service, const char *result) {
1735         _cleanup_free_ char *service_shell_quoted = NULL;
1736
1737         assert(service);
1738
1739         service_shell_quoted = shell_maybe_quote(service);
1740
1741         if (!isempty(result)) {
1742                 unsigned i;
1743
1744                 for (i = 0; i < ELEMENTSOF(explanations); ++i)
1745                         if (streq(result, explanations[i].result))
1746                                 break;
1747
1748                 if (i < ELEMENTSOF(explanations)) {
1749                         log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1750                                   service,
1751                                   explanations[i].explanation,
1752                                   strna(service_shell_quoted));
1753
1754                         goto finish;
1755                 }
1756         }
1757
1758         log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1759                   service,
1760                   strna(service_shell_quoted));
1761
1762 finish:
1763         /* For some results maybe additional explanation is required */
1764         if (streq_ptr(result, "start-limit"))
1765                 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
1766                          strna(service_shell_quoted));
1767 }
1768
1769 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1770         int r = 0;
1771
1772         assert(d->result);
1773
1774         if (!quiet) {
1775                 if (streq(d->result, "canceled"))
1776                         log_error("Job for %s canceled.", strna(d->name));
1777                 else if (streq(d->result, "timeout"))
1778                         log_error("Job for %s timed out.", strna(d->name));
1779                 else if (streq(d->result, "dependency"))
1780                         log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1781                 else if (streq(d->result, "invalid"))
1782                         log_error("Job for %s invalid.", strna(d->name));
1783                 else if (streq(d->result, "assert"))
1784                         log_error("Assertion failed on job for %s.", strna(d->name));
1785                 else if (streq(d->result, "unsupported"))
1786                         log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1787                 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1788                         if (d->name) {
1789                                 int q;
1790                                 _cleanup_free_ char *result = NULL;
1791
1792                                 q = bus_job_get_service_result(d, &result);
1793                                 if (q < 0)
1794                                         log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
1795
1796                                 log_job_error_with_service_result(d->name, result);
1797                         } else
1798                                 log_error("Job failed. See \"journalctl -xe\" for details.");
1799                 }
1800         }
1801
1802         if (streq(d->result, "canceled"))
1803                 r = -ECANCELED;
1804         else if (streq(d->result, "timeout"))
1805                 r = -ETIME;
1806         else if (streq(d->result, "dependency"))
1807                 r = -EIO;
1808         else if (streq(d->result, "invalid"))
1809                 r = -ENOEXEC;
1810         else if (streq(d->result, "assert"))
1811                 r = -EPROTO;
1812         else if (streq(d->result, "unsupported"))
1813                 r = -EOPNOTSUPP;
1814         else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1815                 r = -EIO;
1816
1817         return r;
1818 }
1819
1820 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1821         int r = 0;
1822
1823         assert(d);
1824
1825         while (!set_isempty(d->jobs)) {
1826                 int q;
1827
1828                 q = bus_process_wait(d->bus);
1829                 if (q < 0)
1830                         return log_error_errno(q, "Failed to wait for response: %m");
1831
1832                 if (d->result) {
1833                         q = check_wait_response(d, quiet);
1834                         /* Return the first error as it is most likely to be
1835                          * meaningful. */
1836                         if (q < 0 && r == 0)
1837                                 r = q;
1838
1839                         log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1840                 }
1841
1842                 free(d->name);
1843                 d->name = NULL;
1844
1845                 free(d->result);
1846                 d->result = NULL;
1847         }
1848
1849         return r;
1850 }
1851
1852 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1853         int r;
1854
1855         assert(d);
1856
1857         r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1858         if (r < 0)
1859                 return r;
1860
1861         return set_put_strdup(d->jobs, path);
1862 }
1863
1864 /// UNNEEDED by elogind
1865 #if 0
1866 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
1867         const char *type, *path, *source;
1868         int r;
1869
1870         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1871         if (r < 0)
1872                 return bus_log_parse_error(r);
1873
1874         while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1875                 if (!quiet) {
1876                         if (streq(type, "symlink"))
1877                                 log_info("Created symlink from %s to %s.", path, source);
1878                         else
1879                                 log_info("Removed symlink %s.", path);
1880                 }
1881
1882                 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
1883                 if (r < 0)
1884                         return r;
1885         }
1886         if (r < 0)
1887                 return bus_log_parse_error(r);
1888
1889         r = sd_bus_message_exit_container(m);
1890         if (r < 0)
1891                 return bus_log_parse_error(r);
1892
1893         return 0;
1894 }
1895 #endif // 0
1896
1897 /**
1898  * bus_path_encode_unique() - encode unique object path
1899  * @b: bus connection or NULL
1900  * @prefix: object path prefix
1901  * @sender_id: unique-name of client, or NULL
1902  * @external_id: external ID to be chosen by client, or NULL
1903  * @ret_path: storage for encoded object path pointer
1904  *
1905  * Whenever we provide a bus API that allows clients to create and manage
1906  * server-side objects, we need to provide a unique name for these objects. If
1907  * we let the server choose the name, we suffer from a race condition: If a
1908  * client creates an object asynchronously, it cannot destroy that object until
1909  * it received the method reply. It cannot know the name of the new object,
1910  * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1911  *
1912  * Therefore, many APIs allow the client to choose the unique name for newly
1913  * created objects. There're two problems to solve, though:
1914  *    1) Object names are usually defined via dbus object paths, which are
1915  *       usually globally namespaced. Therefore, multiple clients must be able
1916  *       to choose unique object names without interference.
1917  *    2) If multiple libraries share the same bus connection, they must be
1918  *       able to choose unique object names without interference.
1919  * The first problem is solved easily by prefixing a name with the
1920  * unique-bus-name of a connection. The server side must enforce this and
1921  * reject any other name. The second problem is solved by providing unique
1922  * suffixes from within sd-bus.
1923  *
1924  * This helper allows clients to create unique object-paths. It uses the
1925  * template '/prefix/sender_id/external_id' and returns the new path in
1926  * @ret_path (must be freed by the caller).
1927  * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1928  * NULL, this function allocates a unique suffix via @b (by requesting a new
1929  * cookie). If both @sender_id and @external_id are given, @b can be passed as
1930  * NULL.
1931  *
1932  * Returns: 0 on success, negative error code on failure.
1933  */
1934 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
1935         _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
1936         char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
1937         int r;
1938
1939         assert_return(b || (sender_id && external_id), -EINVAL);
1940         assert_return(object_path_is_valid(prefix), -EINVAL);
1941         assert_return(ret_path, -EINVAL);
1942
1943         if (!sender_id) {
1944                 r = sd_bus_get_unique_name(b, &sender_id);
1945                 if (r < 0)
1946                         return r;
1947         }
1948
1949         if (!external_id) {
1950                 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
1951                 external_id = external_buf;
1952         }
1953
1954         sender_label = bus_label_escape(sender_id);
1955         if (!sender_label)
1956                 return -ENOMEM;
1957
1958         external_label = bus_label_escape(external_id);
1959         if (!external_label)
1960                 return -ENOMEM;
1961
1962         p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
1963         if (!p)
1964                 return -ENOMEM;
1965
1966         *ret_path = p;
1967         return 0;
1968 }
1969
1970 /**
1971  * bus_path_decode_unique() - decode unique object path
1972  * @path: object path to decode
1973  * @prefix: object path prefix
1974  * @ret_sender: output parameter for sender-id label
1975  * @ret_external: output parameter for external-id label
1976  *
1977  * This does the reverse of bus_path_encode_unique() (see its description for
1978  * details). Both trailing labels, sender-id and external-id, are unescaped and
1979  * returned in the given output parameters (the caller must free them).
1980  *
1981  * Note that this function returns 0 if the path does not match the template
1982  * (see bus_path_encode_unique()), 1 if it matched.
1983  *
1984  * Returns: Negative error code on failure, 0 if the given object path does not
1985  *          match the template (return parameters are set to NULL), 1 if it was
1986  *          parsed successfully (return parameters contain allocated labels).
1987  */
1988 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
1989         const char *p, *q;
1990         char *sender, *external;
1991
1992         assert(object_path_is_valid(path));
1993         assert(object_path_is_valid(prefix));
1994         assert(ret_sender);
1995         assert(ret_external);
1996
1997         p = object_path_startswith(path, prefix);
1998         if (!p) {
1999                 *ret_sender = NULL;
2000                 *ret_external = NULL;
2001                 return 0;
2002         }
2003
2004         q = strchr(p, '/');
2005         if (!q) {
2006                 *ret_sender = NULL;
2007                 *ret_external = NULL;
2008                 return 0;
2009         }
2010
2011         sender = bus_label_unescape_n(p, q - p);
2012         external = bus_label_unescape(q + 1);
2013         if (!sender || !external) {
2014                 free(sender);
2015                 free(external);
2016                 return -ENOMEM;
2017         }
2018
2019         *ret_sender = sender;
2020         *ret_external = external;
2021         return 1;
2022 }
2023
2024 bool is_kdbus_wanted(void) {
2025         _cleanup_free_ char *value = NULL;
2026 #ifdef ENABLE_KDBUS
2027         const bool configured = true;
2028 #else
2029         const bool configured = false;
2030 #endif
2031
2032         int r;
2033
2034         if (get_proc_cmdline_key("kdbus", NULL) > 0)
2035                 return true;
2036
2037         r = get_proc_cmdline_key("kdbus=", &value);
2038         if (r <= 0)
2039                 return configured;
2040
2041         return parse_boolean(value) == 1;
2042 }
2043
2044 bool is_kdbus_available(void) {
2045         _cleanup_close_ int fd = -1;
2046         struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2047
2048         if (!is_kdbus_wanted())
2049                 return false;
2050
2051         fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2052         if (fd < 0)
2053                 return false;
2054
2055         return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
2056 }