chiark / gitweb /
759809ce8d489b38248d782cd082a391d3053a38
[elogind.git] / src / libelogind / sd-bus / 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
34 #include "sd-bus.h"
35 #include "bus-error.h"
36 #include "bus-message.h"
37 #include "bus-util.h"
38 #include "bus-internal.h"
39
40 static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
41         sd_event *e = userdata;
42
43         assert(bus);
44         assert(m);
45         assert(e);
46
47         sd_bus_close(bus);
48         sd_event_exit(e, 0);
49
50         return 1;
51 }
52
53 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
54         _cleanup_free_ char *match = NULL;
55         const char *unique;
56         int r;
57
58         assert(e);
59         assert(bus);
60         assert(name);
61
62         /* We unregister the name here and then wait for the
63          * NameOwnerChanged signal for this event to arrive before we
64          * quit. We do this in order to make sure that any queued
65          * requests are still processed before we really exit. */
66
67         r = sd_bus_get_unique_name(bus, &unique);
68         if (r < 0)
69                 return r;
70
71         r = asprintf(&match,
72                      "sender='org.freedesktop.DBus',"
73                      "type='signal',"
74                      "interface='org.freedesktop.DBus',"
75                      "member='NameOwnerChanged',"
76                      "path='/org/freedesktop/DBus',"
77                      "arg0='%s',"
78                      "arg1='%s',"
79                      "arg2=''", name, unique);
80         if (r < 0)
81                 return -ENOMEM;
82
83         r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
84         if (r < 0)
85                 return r;
86
87         r = sd_bus_release_name(bus, name);
88         if (r < 0)
89                 return r;
90
91         return 0;
92 }
93
94 int bus_event_loop_with_idle(
95                 sd_event *e,
96                 sd_bus *bus,
97                 const char *name,
98                 usec_t timeout,
99                 check_idle_t check_idle,
100                 void *userdata) {
101         bool exiting = false;
102         int r, code;
103
104         assert(e);
105         assert(bus);
106         assert(name);
107
108         for (;;) {
109                 bool idle;
110
111                 r = sd_event_get_state(e);
112                 if (r < 0)
113                         return r;
114                 if (r == SD_EVENT_FINISHED)
115                         break;
116
117                 if (check_idle)
118                         idle = check_idle(userdata);
119                 else
120                         idle = true;
121
122                 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
123                 if (r < 0)
124                         return r;
125
126                 if (r == 0 && !exiting && idle) {
127
128                         r = sd_bus_try_close(bus);
129                         if (r == -EBUSY)
130                                 continue;
131
132                         /* Fallback for dbus1 connections: we
133                          * unregister the name and wait for the
134                          * response to come through for it */
135                         if (r == -EOPNOTSUPP) {
136
137                                 /* Inform the service manager that we
138                                  * are going down, so that it will
139                                  * queue all further start requests,
140                                  * instead of assuming we are already
141                                  * running. */
142                                 sd_notify(false, "STOPPING=1");
143
144                                 r = bus_async_unregister_and_exit(e, bus, name);
145                                 if (r < 0)
146                                         return r;
147
148                                 exiting = true;
149                                 continue;
150                         }
151
152                         if (r < 0)
153                                 return r;
154
155                         sd_event_exit(e, 0);
156                         break;
157                 }
158         }
159
160         r = sd_event_get_exit_code(e, &code);
161         if (r < 0)
162                 return r;
163
164         return code;
165 }
166
167 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
168         _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
169         int r, has_owner = 0;
170
171         assert(c);
172         assert(name);
173
174         r = sd_bus_call_method(c,
175                                "org.freedesktop.DBus",
176                                "/org/freedesktop/dbus",
177                                "org.freedesktop.DBus",
178                                "NameHasOwner",
179                                error,
180                                &rep,
181                                "s",
182                                name);
183         if (r < 0)
184                 return r;
185
186         r = sd_bus_message_read_basic(rep, 'b', &has_owner);
187         if (r < 0)
188                 return sd_bus_error_set_errno(error, r);
189
190         return has_owner;
191 }
192
193 static int check_good_user(sd_bus_message *m, uid_t good_user) {
194         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
195         uid_t sender_uid;
196         int r;
197
198         assert(m);
199
200         if (good_user == UID_INVALID)
201                 return 0;
202
203         r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
204         if (r < 0)
205                 return r;
206
207         r = sd_bus_creds_get_euid(creds, &sender_uid);
208         if (r < 0)
209                 return r;
210
211         return sender_uid == good_user;
212 }
213
214 int bus_test_polkit(
215                 sd_bus_message *call,
216                 int capability,
217                 const char *action,
218                 uid_t good_user,
219                 bool *_challenge,
220                 sd_bus_error *e) {
221
222         int r;
223
224         assert(call);
225         assert(action);
226
227         /* Tests non-interactively! */
228
229         r = check_good_user(call, good_user);
230         if (r != 0)
231                 return r;
232
233         r = sd_bus_query_sender_privilege(call, capability);
234         if (r < 0)
235                 return r;
236         else if (r > 0)
237                 return 1;
238 #ifdef ENABLE_POLKIT
239         else {
240                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
241                 int authorized = false, challenge = false;
242                 const char *sender;
243
244                 sender = sd_bus_message_get_sender(call);
245                 if (!sender)
246                         return -EBADMSG;
247
248                 r = sd_bus_call_method(
249                                 call->bus,
250                                 "org.freedesktop.PolicyKit1",
251                                 "/org/freedesktop/PolicyKit1/Authority",
252                                 "org.freedesktop.PolicyKit1.Authority",
253                                 "CheckAuthorization",
254                                 e,
255                                 &reply,
256                                 "(sa{sv})sa{ss}us",
257                                 "system-bus-name", 1, "name", "s", sender,
258                                 action,
259                                 0,
260                                 0,
261                                 "");
262
263                 if (r < 0) {
264                         /* Treat no PK available as access denied */
265                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
266                                 sd_bus_error_free(e);
267                                 return -EACCES;
268                         }
269
270                         return r;
271                 }
272
273                 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
274                 if (r < 0)
275                         return r;
276
277                 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
278                 if (r < 0)
279                         return r;
280
281                 if (authorized)
282                         return 1;
283
284                 if (_challenge) {
285                         *_challenge = challenge;
286                         return 0;
287                 }
288         }
289 #endif
290
291         return -EACCES;
292 }
293
294 #ifdef ENABLE_POLKIT
295
296 typedef struct AsyncPolkitQuery {
297         sd_bus_message *request, *reply;
298         sd_bus_message_handler_t callback;
299         void *userdata;
300         sd_bus_slot *slot;
301         Hashmap *registry;
302 } AsyncPolkitQuery;
303
304 static void async_polkit_query_free(AsyncPolkitQuery *q) {
305
306         if (!q)
307                 return;
308
309         sd_bus_slot_unref(q->slot);
310
311         if (q->registry && q->request)
312                 hashmap_remove(q->registry, q->request);
313
314         sd_bus_message_unref(q->request);
315         sd_bus_message_unref(q->reply);
316
317         free(q);
318 }
319
320 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
321         _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
322         AsyncPolkitQuery *q = userdata;
323         int r;
324
325         assert(bus);
326         assert(reply);
327         assert(q);
328
329         q->slot = sd_bus_slot_unref(q->slot);
330         q->reply = sd_bus_message_ref(reply);
331
332         r = sd_bus_message_rewind(q->request, true);
333         if (r < 0) {
334                 r = sd_bus_reply_method_errno(q->request, r, NULL);
335                 goto finish;
336         }
337
338         r = q->callback(bus, q->request, q->userdata, &error_buffer);
339         r = bus_maybe_reply_error(q->request, r, &error_buffer);
340
341 finish:
342         async_polkit_query_free(q);
343
344         return r;
345 }
346
347 #endif
348
349 int bus_verify_polkit_async(
350                 sd_bus_message *call,
351                 int capability,
352                 const char *action,
353                 bool interactive,
354                 uid_t good_user,
355                 Hashmap **registry,
356                 sd_bus_error *error) {
357
358 #ifdef ENABLE_POLKIT
359         _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
360         AsyncPolkitQuery *q;
361         const char *sender;
362         sd_bus_message_handler_t callback;
363         void *userdata;
364         int c;
365 #endif
366         int r;
367
368         assert(call);
369         assert(action);
370         assert(registry);
371
372         r = check_good_user(call, good_user);
373         if (r != 0)
374                 return r;
375
376 #ifdef ENABLE_POLKIT
377         q = hashmap_get(*registry, call);
378         if (q) {
379                 int authorized, challenge;
380
381                 /* This is the second invocation of this function, and
382                  * there's already a response from polkit, let's
383                  * process it */
384                 assert(q->reply);
385
386                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
387                         const sd_bus_error *e;
388
389                         /* Copy error from polkit reply */
390                         e = sd_bus_message_get_error(q->reply);
391                         sd_bus_error_copy(error, e);
392
393                         /* Treat no PK available as access denied */
394                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
395                                 return -EACCES;
396
397                         return -sd_bus_error_get_errno(e);
398                 }
399
400                 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
401                 if (r >= 0)
402                         r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
403
404                 if (r < 0)
405                         return r;
406
407                 if (authorized)
408                         return 1;
409
410                 if (challenge)
411                         return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
412
413                 return -EACCES;
414         }
415 #endif
416
417         r = sd_bus_query_sender_privilege(call, capability);
418         if (r < 0)
419                 return r;
420         else if (r > 0)
421                 return 1;
422
423 #ifdef ENABLE_POLKIT
424         if (sd_bus_get_current_message(call->bus) != call)
425                 return -EINVAL;
426
427         callback = sd_bus_get_current_handler(call->bus);
428         if (!callback)
429                 return -EINVAL;
430
431         userdata = sd_bus_get_current_userdata(call->bus);
432
433         sender = sd_bus_message_get_sender(call);
434         if (!sender)
435                 return -EBADMSG;
436
437         c = sd_bus_message_get_allow_interactive_authorization(call);
438         if (c < 0)
439                 return c;
440         if (c > 0)
441                 interactive = true;
442
443         r = hashmap_ensure_allocated(registry, NULL);
444         if (r < 0)
445                 return r;
446
447         r = sd_bus_message_new_method_call(
448                         call->bus,
449                         &pk,
450                         "org.freedesktop.PolicyKit1",
451                         "/org/freedesktop/PolicyKit1/Authority",
452                         "org.freedesktop.PolicyKit1.Authority",
453                         "CheckAuthorization");
454         if (r < 0)
455                 return r;
456
457         r = sd_bus_message_append(
458                         pk,
459                         "(sa{sv})sa{ss}us",
460                         "system-bus-name", 1, "name", "s", sender,
461                         action,
462                         0,
463                         !!interactive,
464                         NULL);
465         if (r < 0)
466                 return r;
467
468         q = new0(AsyncPolkitQuery, 1);
469         if (!q)
470                 return -ENOMEM;
471
472         q->request = sd_bus_message_ref(call);
473         q->callback = callback;
474         q->userdata = userdata;
475
476         r = hashmap_put(*registry, call, q);
477         if (r < 0) {
478                 async_polkit_query_free(q);
479                 return r;
480         }
481
482         q->registry = *registry;
483
484         r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
485         if (r < 0) {
486                 async_polkit_query_free(q);
487                 return r;
488         }
489
490         return 0;
491 #endif
492
493         return -EACCES;
494 }
495
496 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
497 #ifdef ENABLE_POLKIT
498         AsyncPolkitQuery *q;
499
500         while ((q = hashmap_steal_first(registry)))
501                 async_polkit_query_free(q);
502
503         hashmap_free(registry);
504 #endif
505 }
506
507 int bus_check_peercred(sd_bus *c) {
508         struct ucred ucred;
509         socklen_t l;
510         int fd;
511
512         assert(c);
513
514         fd = sd_bus_get_fd(c);
515         if (fd < 0)
516                 return fd;
517
518         l = sizeof(struct ucred);
519         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
520                 return -errno;
521
522         if (l != sizeof(struct ucred))
523                 return -E2BIG;
524
525         if (ucred.uid != 0 && ucred.uid != geteuid())
526                 return -EPERM;
527
528         return 1;
529 }
530
531 int bus_open_system_systemd(sd_bus **_bus) {
532         _cleanup_bus_unref_ sd_bus *bus = NULL;
533         int r;
534
535         assert(_bus);
536
537         if (geteuid() != 0)
538                 return sd_bus_open_system(_bus);
539
540         /* If we are root and kdbus is not available, then let's talk
541          * directly to the system instance, instead of going via the
542          * bus */
543
544 #ifdef ENABLE_KDBUS
545         r = sd_bus_new(&bus);
546         if (r < 0)
547                 return r;
548
549         r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
550         if (r < 0)
551                 return r;
552
553         bus->bus_client = true;
554
555         r = sd_bus_start(bus);
556         if (r >= 0) {
557                 *_bus = bus;
558                 bus = NULL;
559                 return 0;
560         }
561
562         bus = sd_bus_unref(bus);
563 #endif
564
565         r = sd_bus_new(&bus);
566         if (r < 0)
567                 return r;
568
569         r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
570         if (r < 0)
571                 return r;
572
573         r = sd_bus_start(bus);
574         if (r < 0)
575                 return sd_bus_open_system(_bus);
576
577         r = bus_check_peercred(bus);
578         if (r < 0)
579                 return r;
580
581         *_bus = bus;
582         bus = NULL;
583
584         return 0;
585 }
586
587 int bus_open_user_systemd(sd_bus **_bus) {
588         _cleanup_bus_unref_ sd_bus *bus = NULL;
589         _cleanup_free_ char *ee = NULL;
590         const char *e;
591         int r;
592
593         /* Try via kdbus first, and then directly */
594
595         assert(_bus);
596
597 #ifdef ENABLE_KDBUS
598         r = sd_bus_new(&bus);
599         if (r < 0)
600                 return r;
601
602         if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
603                 return -ENOMEM;
604
605         bus->bus_client = true;
606
607         r = sd_bus_start(bus);
608         if (r >= 0) {
609                 *_bus = bus;
610                 bus = NULL;
611                 return 0;
612         }
613
614         bus = sd_bus_unref(bus);
615 #endif
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(sd_bus *bus,
1036                                    sd_bus_message *m,
1037                                    const struct bus_properties_map *map,
1038                                    void *userdata) {
1039         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1040         int r;
1041
1042         assert(bus);
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(bus, member, m, &error, v);
1079                         else
1080                                 r = map_basic(bus, 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
1098         return sd_bus_message_exit_container(m);
1099 }
1100
1101 int bus_message_map_properties_changed(sd_bus *bus,
1102                                        sd_bus_message *m,
1103                                        const struct bus_properties_map *map,
1104                                        void *userdata) {
1105         const char *member;
1106         int r, invalidated, i;
1107
1108         assert(bus);
1109         assert(m);
1110         assert(map);
1111
1112         r = bus_message_map_all_properties(bus, m, map, userdata);
1113         if (r < 0)
1114                 return r;
1115
1116         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1117         if (r < 0)
1118                 return r;
1119
1120         invalidated = 0;
1121         while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1122                 for (i = 0; map[i].member; i++)
1123                         if (streq(map[i].member, member)) {
1124                                 ++invalidated;
1125                                 break;
1126                         }
1127
1128         r = sd_bus_message_exit_container(m);
1129         if (r < 0)
1130                 return r;
1131
1132         return invalidated;
1133 }
1134
1135 int bus_map_all_properties(sd_bus *bus,
1136                            const char *destination,
1137                            const char *path,
1138                            const struct bus_properties_map *map,
1139                            void *userdata) {
1140         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1141         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1142         int r;
1143
1144         assert(bus);
1145         assert(destination);
1146         assert(path);
1147         assert(map);
1148
1149         r = sd_bus_call_method(
1150                         bus,
1151                         destination,
1152                         path,
1153                         "org.freedesktop.DBus.Properties",
1154                         "GetAll",
1155                         &error,
1156                         &m,
1157                         "s", "");
1158         if (r < 0)
1159                 return r;
1160
1161         return bus_message_map_all_properties(bus, m, map, userdata);
1162 }
1163
1164 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1165         int r;
1166
1167         assert(transport >= 0);
1168         assert(transport < _BUS_TRANSPORT_MAX);
1169         assert(bus);
1170
1171         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1172         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1173
1174         switch (transport) {
1175
1176         case BUS_TRANSPORT_LOCAL:
1177                 if (user)
1178                         r = sd_bus_default_user(bus);
1179                 else
1180                         r = sd_bus_default_system(bus);
1181
1182                 break;
1183
1184         case BUS_TRANSPORT_REMOTE:
1185                 r = sd_bus_open_system_remote(bus, host);
1186                 break;
1187
1188         case BUS_TRANSPORT_MACHINE:
1189                 r = sd_bus_open_system_machine(bus, host);
1190                 break;
1191
1192         default:
1193                 assert_not_reached("Hmm, unknown transport type.");
1194         }
1195
1196         return r;
1197 }
1198
1199 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1200         int r;
1201
1202         assert(transport >= 0);
1203         assert(transport < _BUS_TRANSPORT_MAX);
1204         assert(bus);
1205
1206         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1207         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -EOPNOTSUPP);
1208
1209         switch (transport) {
1210
1211         case BUS_TRANSPORT_LOCAL:
1212                 if (user)
1213                         r = bus_open_user_systemd(bus);
1214                 else
1215                         r = bus_open_system_systemd(bus);
1216
1217                 break;
1218
1219         case BUS_TRANSPORT_REMOTE:
1220                 r = sd_bus_open_system_remote(bus, host);
1221                 break;
1222
1223         case BUS_TRANSPORT_MACHINE:
1224                 r = sd_bus_open_system_machine(bus, host);
1225                 break;
1226
1227         default:
1228                 assert_not_reached("Hmm, unknown transport type.");
1229         }
1230
1231         return r;
1232 }
1233
1234 int bus_property_get_bool(
1235                 sd_bus *bus,
1236                 const char *path,
1237                 const char *interface,
1238                 const char *property,
1239                 sd_bus_message *reply,
1240                 void *userdata,
1241                 sd_bus_error *error) {
1242
1243         int b = *(bool*) userdata;
1244
1245         return sd_bus_message_append_basic(reply, 'b', &b);
1246 }
1247
1248 #if __SIZEOF_SIZE_T__ != 8
1249 int bus_property_get_size(
1250                 sd_bus *bus,
1251                 const char *path,
1252                 const char *interface,
1253                 const char *property,
1254                 sd_bus_message *reply,
1255                 void *userdata,
1256                 sd_bus_error *error) {
1257
1258         uint64_t sz = *(size_t*) userdata;
1259
1260         return sd_bus_message_append_basic(reply, 't', &sz);
1261 }
1262 #endif
1263
1264 #if __SIZEOF_LONG__ != 8
1265 int bus_property_get_long(
1266                 sd_bus *bus,
1267                 const char *path,
1268                 const char *interface,
1269                 const char *property,
1270                 sd_bus_message *reply,
1271                 void *userdata,
1272                 sd_bus_error *error) {
1273
1274         int64_t l = *(long*) userdata;
1275
1276         return sd_bus_message_append_basic(reply, 'x', &l);
1277 }
1278
1279 int bus_property_get_ulong(
1280                 sd_bus *bus,
1281                 const char *path,
1282                 const char *interface,
1283                 const char *property,
1284                 sd_bus_message *reply,
1285                 void *userdata,
1286                 sd_bus_error *error) {
1287
1288         uint64_t ul = *(unsigned long*) userdata;
1289
1290         return sd_bus_message_append_basic(reply, 't', &ul);
1291 }
1292 #endif
1293
1294 int bus_log_parse_error(int r) {
1295         return log_error_errno(r, "Failed to parse bus message: %m");
1296 }
1297
1298 int bus_log_create_error(int r) {
1299         return log_error_errno(r, "Failed to create bus message: %m");
1300 }
1301
1302 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1303         assert(message);
1304         assert(u);
1305
1306         u->machine = NULL;
1307
1308         return sd_bus_message_read(
1309                         message,
1310                         "(ssssssouso)",
1311                         &u->id,
1312                         &u->description,
1313                         &u->load_state,
1314                         &u->active_state,
1315                         &u->sub_state,
1316                         &u->following,
1317                         &u->unit_path,
1318                         &u->job_id,
1319                         &u->job_type,
1320                         &u->job_path);
1321 }
1322
1323 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1324         assert(m);
1325
1326         if (r < 0) {
1327                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1328                         sd_bus_reply_method_errno(m, r, error);
1329
1330         } else if (sd_bus_error_is_set(error)) {
1331                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1332                         sd_bus_reply_method_error(m, error);
1333         } else
1334                 return r;
1335
1336         log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1337                   bus_message_type_to_string(m->header->type),
1338                   strna(m->sender),
1339                   strna(m->path),
1340                   strna(m->interface),
1341                   strna(m->member),
1342                   strna(m->root_container.signature),
1343                   bus_error_message(error, r));
1344
1345         return 1;
1346 }
1347
1348 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1349         const char *eq, *field;
1350         int r;
1351
1352         assert(m);
1353         assert(assignment);
1354
1355         eq = strchr(assignment, '=');
1356         if (!eq) {
1357                 log_error("Not an assignment: %s", assignment);
1358                 return -EINVAL;
1359         }
1360
1361         field = strndupa(assignment, eq - assignment);
1362         eq ++;
1363
1364         if (streq(field, "CPUQuota")) {
1365
1366                 if (isempty(eq)) {
1367
1368                         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1369                         if (r < 0)
1370                                 return bus_log_create_error(r);
1371
1372                         r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1373
1374                 } else if (endswith(eq, "%")) {
1375                         double percent;
1376
1377                         if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1378                                 log_error("CPU quota '%s' invalid.", eq);
1379                                 return -EINVAL;
1380                         }
1381
1382                         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1383                         if (r < 0)
1384                                 return bus_log_create_error(r);
1385
1386                         r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1387                 } else {
1388                         log_error("CPU quota needs to be in percent.");
1389                         return -EINVAL;
1390                 }
1391
1392                 if (r < 0)
1393                         return bus_log_create_error(r);
1394
1395                 return 0;
1396         }
1397
1398         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1399         if (r < 0)
1400                 return bus_log_create_error(r);
1401
1402         if (STR_IN_SET(field,
1403                        "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1404                        "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies")) {
1405
1406                 r = parse_boolean(eq);
1407                 if (r < 0) {
1408                         log_error("Failed to parse boolean assignment %s.", assignment);
1409                         return -EINVAL;
1410                 }
1411
1412                 r = sd_bus_message_append(m, "v", "b", r);
1413
1414         } else if (streq(field, "MemoryLimit")) {
1415                 off_t bytes;
1416
1417                 r = parse_size(eq, 1024, &bytes);
1418                 if (r < 0) {
1419                         log_error("Failed to parse bytes specification %s", assignment);
1420                         return -EINVAL;
1421                 }
1422
1423                 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1424
1425         } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1426                 uint64_t u;
1427
1428                 r = safe_atou64(eq, &u);
1429                 if (r < 0) {
1430                         log_error("Failed to parse %s value %s.", field, eq);
1431                         return -EINVAL;
1432                 }
1433
1434                 r = sd_bus_message_append(m, "v", "t", u);
1435
1436         } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1437                 r = sd_bus_message_append(m, "v", "s", eq);
1438
1439         else if (streq(field, "DeviceAllow")) {
1440
1441                 if (isempty(eq))
1442                         r = sd_bus_message_append(m, "v", "a(ss)", 0);
1443                 else {
1444                         const char *path, *rwm, *e;
1445
1446                         e = strchr(eq, ' ');
1447                         if (e) {
1448                                 path = strndupa(eq, e - eq);
1449                                 rwm = e+1;
1450                         } else {
1451                                 path = eq;
1452                                 rwm = "";
1453                         }
1454
1455                         if (!path_startswith(path, "/dev")) {
1456                                 log_error("%s is not a device file in /dev.", path);
1457                                 return -EINVAL;
1458                         }
1459
1460                         r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1461                 }
1462
1463         } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1464
1465                 if (isempty(eq))
1466                         r = sd_bus_message_append(m, "v", "a(st)", 0);
1467                 else {
1468                         const char *path, *bandwidth, *e;
1469                         off_t bytes;
1470
1471                         e = strchr(eq, ' ');
1472                         if (e) {
1473                                 path = strndupa(eq, e - eq);
1474                                 bandwidth = e+1;
1475                         } else {
1476                                 log_error("Failed to parse %s value %s.", field, eq);
1477                                 return -EINVAL;
1478                         }
1479
1480                         if (!path_startswith(path, "/dev")) {
1481                                 log_error("%s is not a device file in /dev.", path);
1482                                 return -EINVAL;
1483                         }
1484
1485                         r = parse_size(bandwidth, 1000, &bytes);
1486                         if (r < 0) {
1487                                 log_error("Failed to parse byte value %s.", bandwidth);
1488                                 return -EINVAL;
1489                         }
1490
1491                         r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1492                 }
1493
1494         } else if (streq(field, "BlockIODeviceWeight")) {
1495
1496                 if (isempty(eq))
1497                         r = sd_bus_message_append(m, "v", "a(st)", 0);
1498                 else {
1499                         const char *path, *weight, *e;
1500                         uint64_t u;
1501
1502                         e = strchr(eq, ' ');
1503                         if (e) {
1504                                 path = strndupa(eq, e - eq);
1505                                 weight = e+1;
1506                         } else {
1507                                 log_error("Failed to parse %s value %s.", field, eq);
1508                                 return -EINVAL;
1509                         }
1510
1511                         if (!path_startswith(path, "/dev")) {
1512                                 log_error("%s is not a device file in /dev.", path);
1513                                 return -EINVAL;
1514                         }
1515
1516                         r = safe_atou64(weight, &u);
1517                         if (r < 0) {
1518                                 log_error("Failed to parse %s value %s.", field, weight);
1519                                 return -EINVAL;
1520                         }
1521                         r = sd_bus_message_append(m, "v", "a(st)", path, u);
1522                 }
1523
1524         } else if (rlimit_from_string(field) >= 0) {
1525                 uint64_t rl;
1526
1527                 if (streq(eq, "infinity"))
1528                         rl = (uint64_t) -1;
1529                 else {
1530                         r = safe_atou64(eq, &rl);
1531                         if (r < 0) {
1532                                 log_error("Invalid resource limit: %s", eq);
1533                                 return -EINVAL;
1534                         }
1535                 }
1536
1537                 r = sd_bus_message_append(m, "v", "t", rl);
1538
1539         } else if (streq(field, "Nice")) {
1540                 int32_t i;
1541
1542                 r = safe_atoi32(eq, &i);
1543                 if (r < 0) {
1544                         log_error("Failed to parse %s value %s.", field, eq);
1545                         return -EINVAL;
1546                 }
1547
1548                 r = sd_bus_message_append(m, "v", "i", i);
1549
1550         } else if (streq(field, "Environment")) {
1551
1552                 r = sd_bus_message_append(m, "v", "as", 1, eq);
1553
1554         } else if (streq(field, "KillSignal")) {
1555                 int sig;
1556
1557                 sig = signal_from_string_try_harder(eq);
1558                 if (sig < 0) {
1559                         log_error("Failed to parse %s value %s.", field, eq);
1560                         return -EINVAL;
1561                 }
1562
1563                 r = sd_bus_message_append(m, "v", "i", sig);
1564
1565         } else if (streq(field, "AccuracySec")) {
1566                 usec_t u;
1567
1568                 r = parse_sec(eq, &u);
1569                 if (r < 0) {
1570                         log_error("Failed to parse %s value %s", field, eq);
1571                         return -EINVAL;
1572                 }
1573
1574                 r = sd_bus_message_append(m, "v", "t", u);
1575
1576         } else {
1577                 log_error("Unknown assignment %s.", assignment);
1578                 return -EINVAL;
1579         }
1580
1581         if (r < 0)
1582                 return bus_log_create_error(r);
1583
1584         return 0;
1585 }
1586
1587 typedef struct BusWaitForJobs {
1588         sd_bus *bus;
1589         Set *jobs;
1590
1591         char *name;
1592         char *result;
1593
1594         sd_bus_slot *slot_job_removed;
1595         sd_bus_slot *slot_disconnected;
1596 } BusWaitForJobs;
1597
1598 static int match_disconnected(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1599         assert(bus);
1600         assert(m);
1601
1602         log_error("Warning! D-Bus connection terminated.");
1603         sd_bus_close(bus);
1604
1605         return 0;
1606 }
1607
1608 static int match_job_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1609         const char *path, *unit, *result;
1610         BusWaitForJobs *d = userdata;
1611         uint32_t id;
1612         char *found;
1613         int r;
1614
1615         assert(bus);
1616         assert(m);
1617         assert(d);
1618
1619         r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1620         if (r < 0) {
1621                 bus_log_parse_error(r);
1622                 return 0;
1623         }
1624
1625         found = set_remove(d->jobs, (char*) path);
1626         if (!found)
1627                 return 0;
1628
1629         free(found);
1630
1631         if (!isempty(result))
1632                 d->result = strdup(result);
1633
1634         if (!isempty(unit))
1635                 d->name = strdup(unit);
1636
1637         return 0;
1638 }
1639
1640 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1641         if (!d)
1642                 return;
1643
1644         set_free_free(d->jobs);
1645
1646         sd_bus_slot_unref(d->slot_disconnected);
1647         sd_bus_slot_unref(d->slot_job_removed);
1648
1649         sd_bus_unref(d->bus);
1650
1651         free(d->name);
1652         free(d->result);
1653
1654         free(d);
1655 }
1656
1657 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1658         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1659         int r;
1660
1661         assert(bus);
1662         assert(ret);
1663
1664         d = new0(BusWaitForJobs, 1);
1665         if (!d)
1666                 return -ENOMEM;
1667
1668         d->bus = sd_bus_ref(bus);
1669
1670         /* When we are a bus client we match by sender. Direct
1671          * connections OTOH have no initialized sender field, and
1672          * hence we ignore the sender then */
1673         r = sd_bus_add_match(
1674                         bus,
1675                         &d->slot_job_removed,
1676                         bus->bus_client ?
1677                         "type='signal',"
1678                         "sender='org.freedesktop.systemd1',"
1679                         "interface='org.freedesktop.systemd1.Manager',"
1680                         "member='JobRemoved',"
1681                         "path='/org/freedesktop/systemd1'" :
1682                         "type='signal',"
1683                         "interface='org.freedesktop.systemd1.Manager',"
1684                         "member='JobRemoved',"
1685                         "path='/org/freedesktop/systemd1'",
1686                         match_job_removed, d);
1687         if (r < 0)
1688                 return r;
1689
1690         r = sd_bus_add_match(
1691                         bus,
1692                         &d->slot_disconnected,
1693                         "type='signal',"
1694                         "sender='org.freedesktop.DBus.Local',"
1695                         "interface='org.freedesktop.DBus.Local',"
1696                         "member='Disconnected'",
1697                         match_disconnected, d);
1698         if (r < 0)
1699                 return r;
1700
1701         *ret = d;
1702         d = NULL;
1703
1704         return 0;
1705 }
1706
1707 static int bus_process_wait(sd_bus *bus) {
1708         int r;
1709
1710         for (;;) {
1711                 r = sd_bus_process(bus, NULL);
1712                 if (r < 0)
1713                         return r;
1714                 if (r > 0)
1715                         return 0;
1716
1717                 r = sd_bus_wait(bus, (uint64_t) -1);
1718                 if (r < 0)
1719                         return r;
1720         }
1721 }
1722
1723 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1724         int r = 0;
1725
1726         assert(d->result);
1727
1728         if (!quiet) {
1729                 if (streq(d->result, "canceled"))
1730                         log_error("Job for %s canceled.", strna(d->name));
1731                 else if (streq(d->result, "timeout"))
1732                         log_error("Job for %s timed out.", strna(d->name));
1733                 else if (streq(d->result, "dependency"))
1734                         log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1735                 else if (streq(d->result, "invalid"))
1736                         log_error("Job for %s invalid.", strna(d->name));
1737                 else if (streq(d->result, "assert"))
1738                         log_error("Assertion failed on job for %s.", strna(d->name));
1739                 else if (streq(d->result, "unsupported"))
1740                         log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1741                 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1742                         _cleanup_free_ char *quoted = NULL;
1743
1744                         if (d->name)
1745                                 quoted = shell_maybe_quote(d->name);
1746
1747                         if (quoted)
1748                                 log_error("Job for %s failed. See 'systemctl status %s' and 'journalctl -xe' for details.", d->name, quoted);
1749                         else
1750                                 log_error("Job failed. See 'journalctl -xe' for details.");
1751                 }
1752         }
1753
1754         if (streq(d->result, "canceled"))
1755                 r = -ECANCELED;
1756         else if (streq(d->result, "timeout"))
1757                 r = -ETIME;
1758         else if (streq(d->result, "dependency"))
1759                 r = -EIO;
1760         else if (streq(d->result, "invalid"))
1761                 r = -ENOEXEC;
1762         else if (streq(d->result, "assert"))
1763                 r = -EPROTO;
1764         else if (streq(d->result, "unsupported"))
1765                 r = -EOPNOTSUPP;
1766         else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1767                 r = -EIO;
1768
1769         return r;
1770 }
1771
1772 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1773         int r = 0;
1774
1775         assert(d);
1776
1777         while (!set_isempty(d->jobs)) {
1778                 int q;
1779
1780                 q = bus_process_wait(d->bus);
1781                 if (q < 0)
1782                         return log_error_errno(q, "Failed to wait for response: %m");
1783
1784                 if (d->result) {
1785                         q = check_wait_response(d, quiet);
1786                         /* Return the first error as it is most likely to be
1787                          * meaningful. */
1788                         if (q < 0 && r == 0)
1789                                 r = q;
1790
1791                         log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1792                 }
1793
1794                 free(d->name);
1795                 d->name = NULL;
1796
1797                 free(d->result);
1798                 d->result = NULL;
1799         }
1800
1801         return r;
1802 }
1803
1804 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1805         int r;
1806
1807         assert(d);
1808
1809         r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1810         if (r < 0)
1811                 return r;
1812
1813         return set_put_strdup(d->jobs, path);
1814 }
1815
1816 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
1817         const char *type, *path, *source;
1818         int r;
1819
1820         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1821         if (r < 0)
1822                 return bus_log_parse_error(r);
1823
1824         while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1825                 if (!quiet) {
1826                         if (streq(type, "symlink"))
1827                                 log_info("Created symlink from %s to %s.", path, source);
1828                         else
1829                                 log_info("Removed symlink %s.", path);
1830                 }
1831         }
1832         if (r < 0)
1833                 return bus_log_parse_error(r);
1834
1835         r = sd_bus_message_exit_container(m);
1836         if (r < 0)
1837                 return bus_log_parse_error(r);
1838
1839         return 0;
1840 }