chiark / gitweb /
28b33ab8d08a58aca23c9d329afab20bd0d8660e
[elogind.git] / src / libsystemd / 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 == -ENOTSUP) {
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_verify_polkit(
215                 sd_bus_message *call,
216                 int capability,
217                 const char *action,
218                 bool interactive,
219                 uid_t good_user,
220                 bool *_challenge,
221                 sd_bus_error *e) {
222
223         int r;
224
225         assert(call);
226         assert(action);
227
228         r = check_good_user(call, good_user);
229         if (r != 0)
230                 return r;
231
232         r = sd_bus_query_sender_privilege(call, capability);
233         if (r < 0)
234                 return r;
235         else if (r > 0)
236                 return 1;
237 #ifdef ENABLE_POLKIT
238         else {
239                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
240                 int authorized = false, challenge = false, c;
241                 const char *sender;
242
243                 sender = sd_bus_message_get_sender(call);
244                 if (!sender)
245                         return -EBADMSG;
246
247                 c = sd_bus_message_get_allow_interactive_authorization(call);
248                 if (c < 0)
249                         return c;
250                 if (c > 0)
251                         interactive = true;
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                                 !!interactive,
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 *bus, 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(bus);
331         assert(reply);
332         assert(q);
333
334         q->slot = sd_bus_slot_unref(q->slot);
335         q->reply = sd_bus_message_ref(reply);
336
337         r = sd_bus_message_rewind(q->request, true);
338         if (r < 0) {
339                 r = sd_bus_reply_method_errno(q->request, r, NULL);
340                 goto finish;
341         }
342
343         r = q->callback(bus, q->request, q->userdata, &error_buffer);
344         r = bus_maybe_reply_error(q->request, r, &error_buffer);
345
346 finish:
347         async_polkit_query_free(q);
348
349         return r;
350 }
351
352 #endif
353
354 int bus_verify_polkit_async(
355                 sd_bus_message *call,
356                 int capability,
357                 const char *action,
358                 bool interactive,
359                 uid_t good_user,
360                 Hashmap **registry,
361                 sd_bus_error *error) {
362
363 #ifdef ENABLE_POLKIT
364         _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
365         AsyncPolkitQuery *q;
366         const char *sender;
367         sd_bus_message_handler_t callback;
368         void *userdata;
369         int c;
370 #endif
371         int r;
372
373         assert(call);
374         assert(action);
375         assert(registry);
376
377         r = check_good_user(call, good_user);
378         if (r != 0)
379                 return r;
380
381 #ifdef ENABLE_POLKIT
382         q = hashmap_get(*registry, call);
383         if (q) {
384                 int authorized, challenge;
385
386                 /* This is the second invocation of this function, and
387                  * there's already a response from polkit, let's
388                  * process it */
389                 assert(q->reply);
390
391                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
392                         const sd_bus_error *e;
393
394                         /* Copy error from polkit reply */
395                         e = sd_bus_message_get_error(q->reply);
396                         sd_bus_error_copy(error, e);
397
398                         /* Treat no PK available as access denied */
399                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
400                                 return -EACCES;
401
402                         return -sd_bus_error_get_errno(e);
403                 }
404
405                 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
406                 if (r >= 0)
407                         r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
408
409                 if (r < 0)
410                         return r;
411
412                 if (authorized)
413                         return 1;
414
415                 if (challenge)
416                         return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
417
418                 return -EACCES;
419         }
420 #endif
421
422         r = sd_bus_query_sender_privilege(call, capability);
423         if (r < 0)
424                 return r;
425         else if (r > 0)
426                 return 1;
427
428 #ifdef ENABLE_POLKIT
429         if (sd_bus_get_current_message(call->bus) != call)
430                 return -EINVAL;
431
432         callback = sd_bus_get_current_handler(call->bus);
433         if (!callback)
434                 return -EINVAL;
435
436         userdata = sd_bus_get_current_userdata(call->bus);
437
438         sender = sd_bus_message_get_sender(call);
439         if (!sender)
440                 return -EBADMSG;
441
442         c = sd_bus_message_get_allow_interactive_authorization(call);
443         if (c < 0)
444                 return c;
445         if (c > 0)
446                 interactive = true;
447
448         r = hashmap_ensure_allocated(registry, NULL);
449         if (r < 0)
450                 return r;
451
452         r = sd_bus_message_new_method_call(
453                         call->bus,
454                         &pk,
455                         "org.freedesktop.PolicyKit1",
456                         "/org/freedesktop/PolicyKit1/Authority",
457                         "org.freedesktop.PolicyKit1.Authority",
458                         "CheckAuthorization");
459         if (r < 0)
460                 return r;
461
462         r = sd_bus_message_append(
463                         pk,
464                         "(sa{sv})sa{ss}us",
465                         "system-bus-name", 1, "name", "s", sender,
466                         action,
467                         0,
468                         !!interactive,
469                         NULL);
470         if (r < 0)
471                 return r;
472
473         q = new0(AsyncPolkitQuery, 1);
474         if (!q)
475                 return -ENOMEM;
476
477         q->request = sd_bus_message_ref(call);
478         q->callback = callback;
479         q->userdata = userdata;
480
481         r = hashmap_put(*registry, call, q);
482         if (r < 0) {
483                 async_polkit_query_free(q);
484                 return r;
485         }
486
487         q->registry = *registry;
488
489         r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
490         if (r < 0) {
491                 async_polkit_query_free(q);
492                 return r;
493         }
494
495         return 0;
496 #endif
497
498         return -EACCES;
499 }
500
501 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
502 #ifdef ENABLE_POLKIT
503         AsyncPolkitQuery *q;
504
505         while ((q = hashmap_steal_first(registry)))
506                 async_polkit_query_free(q);
507
508         hashmap_free(registry);
509 #endif
510 }
511
512 int bus_check_peercred(sd_bus *c) {
513         struct ucred ucred;
514         socklen_t l;
515         int fd;
516
517         assert(c);
518
519         fd = sd_bus_get_fd(c);
520         if (fd < 0)
521                 return fd;
522
523         l = sizeof(struct ucred);
524         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
525                 return -errno;
526
527         if (l != sizeof(struct ucred))
528                 return -E2BIG;
529
530         if (ucred.uid != 0 && ucred.uid != geteuid())
531                 return -EPERM;
532
533         return 1;
534 }
535
536 int bus_open_system_systemd(sd_bus **_bus) {
537         _cleanup_bus_unref_ sd_bus *bus = NULL;
538         int r;
539
540         assert(_bus);
541
542         if (geteuid() != 0)
543                 return sd_bus_open_system(_bus);
544
545         /* If we are root and kdbus is not available, then let's talk
546          * directly to the system instance, instead of going via the
547          * bus */
548
549 #ifdef ENABLE_KDBUS
550         r = sd_bus_new(&bus);
551         if (r < 0)
552                 return r;
553
554         r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
555         if (r < 0)
556                 return r;
557
558         bus->bus_client = true;
559
560         r = sd_bus_start(bus);
561         if (r >= 0) {
562                 *_bus = bus;
563                 bus = NULL;
564                 return 0;
565         }
566
567         bus = sd_bus_unref(bus);
568 #endif
569
570         r = sd_bus_new(&bus);
571         if (r < 0)
572                 return r;
573
574         r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
575         if (r < 0)
576                 return r;
577
578         r = sd_bus_start(bus);
579         if (r < 0)
580                 return sd_bus_open_system(_bus);
581
582         r = bus_check_peercred(bus);
583         if (r < 0)
584                 return r;
585
586         *_bus = bus;
587         bus = NULL;
588
589         return 0;
590 }
591
592 int bus_open_user_systemd(sd_bus **_bus) {
593         _cleanup_bus_unref_ sd_bus *bus = NULL;
594         _cleanup_free_ char *ee = NULL;
595         const char *e;
596         int r;
597
598         /* Try via kdbus first, and then directly */
599
600         assert(_bus);
601
602 #ifdef ENABLE_KDBUS
603         r = sd_bus_new(&bus);
604         if (r < 0)
605                 return r;
606
607         if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
608                 return -ENOMEM;
609
610         bus->bus_client = true;
611
612         r = sd_bus_start(bus);
613         if (r >= 0) {
614                 *_bus = bus;
615                 bus = NULL;
616                 return 0;
617         }
618
619         bus = sd_bus_unref(bus);
620 #endif
621
622         e = secure_getenv("XDG_RUNTIME_DIR");
623         if (!e)
624                 return sd_bus_open_user(_bus);
625
626         ee = bus_address_escape(e);
627         if (!ee)
628                 return -ENOMEM;
629
630         r = sd_bus_new(&bus);
631         if (r < 0)
632                 return r;
633
634         bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
635         if (!bus->address)
636                 return -ENOMEM;
637
638         r = sd_bus_start(bus);
639         if (r < 0)
640                 return sd_bus_open_user(_bus);
641
642         r = bus_check_peercred(bus);
643         if (r < 0)
644                 return r;
645
646         *_bus = bus;
647         bus = NULL;
648
649         return 0;
650 }
651
652 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
653         char type;
654         const char *contents;
655         int r;
656
657         assert(name);
658         assert(property);
659
660         r = sd_bus_message_peek_type(property, &type, &contents);
661         if (r < 0)
662                 return r;
663
664         switch (type) {
665
666         case SD_BUS_TYPE_STRING: {
667                 const char *s;
668
669                 r = sd_bus_message_read_basic(property, type, &s);
670                 if (r < 0)
671                         return r;
672
673                 if (all || !isempty(s)) {
674                         _cleanup_free_ char *escaped = NULL;
675
676                         escaped = xescape(s, "\n");
677                         if (!escaped)
678                                 return -ENOMEM;
679
680                         printf("%s=%s\n", name, escaped);
681                 }
682
683                 return 1;
684         }
685
686         case SD_BUS_TYPE_BOOLEAN: {
687                 int b;
688
689                 r = sd_bus_message_read_basic(property, type, &b);
690                 if (r < 0)
691                         return r;
692
693                 printf("%s=%s\n", name, yes_no(b));
694
695                 return 1;
696         }
697
698         case SD_BUS_TYPE_UINT64: {
699                 uint64_t u;
700
701                 r = sd_bus_message_read_basic(property, type, &u);
702                 if (r < 0)
703                         return r;
704
705                 /* Yes, heuristics! But we can change this check
706                  * should it turn out to not be sufficient */
707
708                 if (endswith(name, "Timestamp")) {
709                         char timestamp[FORMAT_TIMESTAMP_MAX], *t;
710
711                         t = format_timestamp(timestamp, sizeof(timestamp), u);
712                         if (t || all)
713                                 printf("%s=%s\n", name, strempty(t));
714
715                 } else if (strstr(name, "USec")) {
716                         char timespan[FORMAT_TIMESPAN_MAX];
717
718                         printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
719                 } else
720                         printf("%s=%llu\n", name, (unsigned long long) u);
721
722                 return 1;
723         }
724
725         case SD_BUS_TYPE_UINT32: {
726                 uint32_t u;
727
728                 r = sd_bus_message_read_basic(property, type, &u);
729                 if (r < 0)
730                         return r;
731
732                 if (strstr(name, "UMask") || strstr(name, "Mode"))
733                         printf("%s=%04o\n", name, u);
734                 else
735                         printf("%s=%u\n", name, (unsigned) u);
736
737                 return 1;
738         }
739
740         case SD_BUS_TYPE_INT32: {
741                 int32_t i;
742
743                 r = sd_bus_message_read_basic(property, type, &i);
744                 if (r < 0)
745                         return r;
746
747                 printf("%s=%i\n", name, (int) i);
748                 return 1;
749         }
750
751         case SD_BUS_TYPE_DOUBLE: {
752                 double d;
753
754                 r = sd_bus_message_read_basic(property, type, &d);
755                 if (r < 0)
756                         return r;
757
758                 printf("%s=%g\n", name, d);
759                 return 1;
760         }
761
762         case SD_BUS_TYPE_ARRAY:
763                 if (streq(contents, "s")) {
764                         bool first = true;
765                         const char *str;
766
767                         r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
768                         if (r < 0)
769                                 return r;
770
771                         while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
772                                 _cleanup_free_ char *escaped = NULL;
773
774                                 if (first)
775                                         printf("%s=", name);
776
777                                 escaped = xescape(str, "\n ");
778                                 if (!escaped)
779                                         return -ENOMEM;
780
781                                 printf("%s%s", first ? "" : " ", escaped);
782
783                                 first = false;
784                         }
785                         if (r < 0)
786                                 return r;
787
788                         if (first && all)
789                                 printf("%s=", name);
790                         if (!first || all)
791                                 puts("");
792
793                         r = sd_bus_message_exit_container(property);
794                         if (r < 0)
795                                 return r;
796
797                         return 1;
798
799                 } else if (streq(contents, "y")) {
800                         const uint8_t *u;
801                         size_t n;
802
803                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
804                         if (r < 0)
805                                 return r;
806
807                         if (all || n > 0) {
808                                 unsigned int i;
809
810                                 printf("%s=", name);
811
812                                 for (i = 0; i < n; i++)
813                                         printf("%02x", u[i]);
814
815                                 puts("");
816                         }
817
818                         return 1;
819
820                 } else if (streq(contents, "u")) {
821                         uint32_t *u;
822                         size_t n;
823
824                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
825                         if (r < 0)
826                                 return r;
827
828                         if (all || n > 0) {
829                                 unsigned int i;
830
831                                 printf("%s=", name);
832
833                                 for (i = 0; i < n; i++)
834                                         printf("%08x", u[i]);
835
836                                 puts("");
837                         }
838
839                         return 1;
840                 }
841
842                 break;
843         }
844
845         return 0;
846 }
847
848 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
849         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
850         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
851         int r;
852
853         assert(bus);
854         assert(path);
855
856         r = sd_bus_call_method(bus,
857                         dest,
858                         path,
859                         "org.freedesktop.DBus.Properties",
860                         "GetAll",
861                         &error,
862                         &reply,
863                         "s", "");
864         if (r < 0)
865                 return r;
866
867         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
868         if (r < 0)
869                 return r;
870
871         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
872                 const char *name;
873                 const char *contents;
874
875                 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
876                 if (r < 0)
877                         return r;
878
879                 if (!filter || strv_find(filter, name)) {
880                         r = sd_bus_message_peek_type(reply, NULL, &contents);
881                         if (r < 0)
882                                 return r;
883
884                         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
885                         if (r < 0)
886                                 return r;
887
888                         r = bus_print_property(name, reply, all);
889                         if (r < 0)
890                                 return r;
891                         if (r == 0) {
892                                 if (all)
893                                         printf("%s=[unprintable]\n", name);
894                                 /* skip what we didn't read */
895                                 r = sd_bus_message_skip(reply, contents);
896                                 if (r < 0)
897                                         return r;
898                         }
899
900                         r = sd_bus_message_exit_container(reply);
901                         if (r < 0)
902                                 return r;
903                 } else {
904                         r = sd_bus_message_skip(reply, "v");
905                         if (r < 0)
906                                 return r;
907                 }
908
909                 r = sd_bus_message_exit_container(reply);
910                 if (r < 0)
911                         return r;
912         }
913         if (r < 0)
914                 return r;
915
916         r = sd_bus_message_exit_container(reply);
917         if (r < 0)
918                 return r;
919
920         return 0;
921 }
922
923 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
924         sd_id128_t *p = userdata;
925         const void *v;
926         size_t n;
927         int r;
928
929         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
930         if (r < 0)
931                 return r;
932
933         if (n == 0)
934                 *p = SD_ID128_NULL;
935         else if (n == 16)
936                 memcpy((*p).bytes, v, n);
937         else
938                 return -EINVAL;
939
940         return 0;
941 }
942
943 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
944         char type;
945         int r;
946
947         r = sd_bus_message_peek_type(m, &type, NULL);
948         if (r < 0)
949                 return r;
950
951         switch (type) {
952         case SD_BUS_TYPE_STRING: {
953                 const char *s;
954                 char *str;
955                 char **p = userdata;
956
957                 r = sd_bus_message_read_basic(m, type, &s);
958                 if (r < 0)
959                         break;
960
961                 if (isempty(s))
962                         break;
963
964                 str = strdup(s);
965                 if (!str) {
966                         r = -ENOMEM;
967                         break;
968                 }
969                 free(*p);
970                 *p = str;
971
972                 break;
973         }
974
975         case SD_BUS_TYPE_ARRAY: {
976                _cleanup_strv_free_ char **l = NULL;
977                char ***p = userdata;
978
979                 r = bus_message_read_strv_extend(m, &l);
980                 if (r < 0)
981                         break;
982
983                 strv_free(*p);
984                 *p = l;
985                 l = NULL;
986
987                 break;
988         }
989
990         case SD_BUS_TYPE_BOOLEAN: {
991                 unsigned b;
992                 bool *p = userdata;
993
994                 r = sd_bus_message_read_basic(m, type, &b);
995                 if (r < 0)
996                         break;
997
998                 *p = b;
999
1000                 break;
1001         }
1002
1003         case SD_BUS_TYPE_UINT32: {
1004                 uint64_t u;
1005                 uint32_t *p = userdata;
1006
1007                 r = sd_bus_message_read_basic(m, type, &u);
1008                 if (r < 0)
1009                         break;
1010
1011                 *p = u;
1012
1013                 break;
1014         }
1015
1016         case SD_BUS_TYPE_UINT64: {
1017                 uint64_t t;
1018                 uint64_t *p = userdata;
1019
1020                 r = sd_bus_message_read_basic(m, type, &t);
1021                 if (r < 0)
1022                         break;
1023
1024                 *p = t;
1025
1026                 break;
1027         }
1028
1029         default:
1030                 break;
1031         }
1032
1033         return r;
1034 }
1035
1036 int bus_message_map_all_properties(sd_bus *bus,
1037                                    sd_bus_message *m,
1038                                    const struct bus_properties_map *map,
1039                                    void *userdata) {
1040         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1041         int r;
1042
1043         assert(bus);
1044         assert(m);
1045         assert(map);
1046
1047         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
1048         if (r < 0)
1049                 return r;
1050
1051         while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
1052                 const struct bus_properties_map *prop;
1053                 const char *member;
1054                 const char *contents;
1055                 void *v;
1056                 unsigned i;
1057
1058                 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
1059                 if (r < 0)
1060                         return r;
1061
1062                 for (i = 0, prop = NULL; map[i].member; i++)
1063                         if (streq(map[i].member, member)) {
1064                                 prop = &map[i];
1065                                 break;
1066                         }
1067
1068                 if (prop) {
1069                         r = sd_bus_message_peek_type(m, NULL, &contents);
1070                         if (r < 0)
1071                                 return r;
1072
1073                         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
1074                         if (r < 0)
1075                                 return r;
1076
1077                         v = (uint8_t *)userdata + prop->offset;
1078                         if (map[i].set)
1079                                 r = prop->set(bus, member, m, &error, v);
1080                         else
1081                                 r = map_basic(bus, member, m, &error, v);
1082                         if (r < 0)
1083                                 return r;
1084
1085                         r = sd_bus_message_exit_container(m);
1086                         if (r < 0)
1087                                 return r;
1088                 } else {
1089                         r = sd_bus_message_skip(m, "v");
1090                         if (r < 0)
1091                                 return r;
1092                 }
1093
1094                 r = sd_bus_message_exit_container(m);
1095                 if (r < 0)
1096                         return r;
1097         }
1098
1099         return sd_bus_message_exit_container(m);
1100 }
1101
1102 int bus_message_map_properties_changed(sd_bus *bus,
1103                                        sd_bus_message *m,
1104                                        const struct bus_properties_map *map,
1105                                        void *userdata) {
1106         const char *member;
1107         int r, invalidated, i;
1108
1109         assert(bus);
1110         assert(m);
1111         assert(map);
1112
1113         r = bus_message_map_all_properties(bus, m, map, userdata);
1114         if (r < 0)
1115                 return r;
1116
1117         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "s");
1118         if (r < 0)
1119                 return r;
1120
1121         invalidated = 0;
1122         while ((r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member)) > 0)
1123                 for (i = 0; map[i].member; i++)
1124                         if (streq(map[i].member, member)) {
1125                                 ++invalidated;
1126                                 break;
1127                         }
1128
1129         r = sd_bus_message_exit_container(m);
1130         if (r < 0)
1131                 return r;
1132
1133         return invalidated;
1134 }
1135
1136 int bus_map_all_properties(sd_bus *bus,
1137                            const char *destination,
1138                            const char *path,
1139                            const struct bus_properties_map *map,
1140                            void *userdata) {
1141         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1142         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
1143         int r;
1144
1145         assert(bus);
1146         assert(destination);
1147         assert(path);
1148         assert(map);
1149
1150         r = sd_bus_call_method(
1151                         bus,
1152                         destination,
1153                         path,
1154                         "org.freedesktop.DBus.Properties",
1155                         "GetAll",
1156                         &error,
1157                         &m,
1158                         "s", "");
1159         if (r < 0)
1160                 return r;
1161
1162         return bus_message_map_all_properties(bus, m, map, userdata);
1163 }
1164
1165 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1166         int r;
1167
1168         assert(transport >= 0);
1169         assert(transport < _BUS_TRANSPORT_MAX);
1170         assert(bus);
1171
1172         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1173         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1174
1175         switch (transport) {
1176
1177         case BUS_TRANSPORT_LOCAL:
1178                 if (user)
1179                         r = sd_bus_default_user(bus);
1180                 else
1181                         r = sd_bus_default_system(bus);
1182
1183                 break;
1184
1185         case BUS_TRANSPORT_REMOTE:
1186                 r = sd_bus_open_system_remote(bus, host);
1187                 break;
1188
1189         case BUS_TRANSPORT_MACHINE:
1190                 r = sd_bus_open_system_machine(bus, host);
1191                 break;
1192
1193         default:
1194                 assert_not_reached("Hmm, unknown transport type.");
1195         }
1196
1197         return r;
1198 }
1199
1200 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
1201         int r;
1202
1203         assert(transport >= 0);
1204         assert(transport < _BUS_TRANSPORT_MAX);
1205         assert(bus);
1206
1207         assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
1208         assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
1209
1210         switch (transport) {
1211
1212         case BUS_TRANSPORT_LOCAL:
1213                 if (user)
1214                         r = bus_open_user_systemd(bus);
1215                 else
1216                         r = bus_open_system_systemd(bus);
1217
1218                 break;
1219
1220         case BUS_TRANSPORT_REMOTE:
1221                 r = sd_bus_open_system_remote(bus, host);
1222                 break;
1223
1224         case BUS_TRANSPORT_MACHINE:
1225                 r = sd_bus_open_system_machine(bus, host);
1226                 break;
1227
1228         default:
1229                 assert_not_reached("Hmm, unknown transport type.");
1230         }
1231
1232         return r;
1233 }
1234
1235 int bus_property_get_bool(
1236                 sd_bus *bus,
1237                 const char *path,
1238                 const char *interface,
1239                 const char *property,
1240                 sd_bus_message *reply,
1241                 void *userdata,
1242                 sd_bus_error *error) {
1243
1244         int b = *(bool*) userdata;
1245
1246         return sd_bus_message_append_basic(reply, 'b', &b);
1247 }
1248
1249 #if __SIZEOF_SIZE_T__ != 8
1250 int bus_property_get_size(
1251                 sd_bus *bus,
1252                 const char *path,
1253                 const char *interface,
1254                 const char *property,
1255                 sd_bus_message *reply,
1256                 void *userdata,
1257                 sd_bus_error *error) {
1258
1259         uint64_t sz = *(size_t*) userdata;
1260
1261         return sd_bus_message_append_basic(reply, 't', &sz);
1262 }
1263 #endif
1264
1265 #if __SIZEOF_LONG__ != 8
1266 int bus_property_get_long(
1267                 sd_bus *bus,
1268                 const char *path,
1269                 const char *interface,
1270                 const char *property,
1271                 sd_bus_message *reply,
1272                 void *userdata,
1273                 sd_bus_error *error) {
1274
1275         int64_t l = *(long*) userdata;
1276
1277         return sd_bus_message_append_basic(reply, 'x', &l);
1278 }
1279
1280 int bus_property_get_ulong(
1281                 sd_bus *bus,
1282                 const char *path,
1283                 const char *interface,
1284                 const char *property,
1285                 sd_bus_message *reply,
1286                 void *userdata,
1287                 sd_bus_error *error) {
1288
1289         uint64_t ul = *(unsigned long*) userdata;
1290
1291         return sd_bus_message_append_basic(reply, 't', &ul);
1292 }
1293 #endif
1294
1295 int bus_log_parse_error(int r) {
1296         return log_error_errno(r, "Failed to parse bus message: %m");
1297 }
1298
1299 int bus_log_create_error(int r) {
1300         return log_error_errno(r, "Failed to create bus message: %m");
1301 }
1302
1303 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1304         assert(message);
1305         assert(u);
1306
1307         u->machine = NULL;
1308
1309         return sd_bus_message_read(
1310                         message,
1311                         "(ssssssouso)",
1312                         &u->id,
1313                         &u->description,
1314                         &u->load_state,
1315                         &u->active_state,
1316                         &u->sub_state,
1317                         &u->following,
1318                         &u->unit_path,
1319                         &u->job_id,
1320                         &u->job_type,
1321                         &u->job_path);
1322 }
1323
1324 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1325         assert(m);
1326
1327         if (r < 0) {
1328                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1329                         sd_bus_reply_method_errno(m, r, error);
1330
1331         } else if (sd_bus_error_is_set(error)) {
1332                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1333                         sd_bus_reply_method_error(m, error);
1334         } else
1335                 return r;
1336
1337         log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1338                   bus_message_type_to_string(m->header->type),
1339                   strna(m->sender),
1340                   strna(m->path),
1341                   strna(m->interface),
1342                   strna(m->member),
1343                   strna(m->root_container.signature),
1344                   bus_error_message(error, r));
1345
1346         return 1;
1347 }
1348
1349 int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignment) {
1350         const char *eq, *field;
1351         int r;
1352
1353         assert(m);
1354         assert(assignment);
1355
1356         eq = strchr(assignment, '=');
1357         if (!eq) {
1358                 log_error("Not an assignment: %s", assignment);
1359                 return -EINVAL;
1360         }
1361
1362         field = strndupa(assignment, eq - assignment);
1363         eq ++;
1364
1365         if (streq(field, "CPUQuota")) {
1366
1367                 if (isempty(eq)) {
1368
1369                         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1370                         if (r < 0)
1371                                 return bus_log_create_error(r);
1372
1373                         r = sd_bus_message_append(m, "v", "t", USEC_INFINITY);
1374
1375                 } else if (endswith(eq, "%")) {
1376                         double percent;
1377
1378                         if (sscanf(eq, "%lf%%", &percent) != 1 || percent <= 0) {
1379                                 log_error("CPU quota '%s' invalid.", eq);
1380                                 return -EINVAL;
1381                         }
1382
1383                         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, "CPUQuotaPerSecUSec");
1384                         if (r < 0)
1385                                 return bus_log_create_error(r);
1386
1387                         r = sd_bus_message_append(m, "v", "t", (usec_t) percent * USEC_PER_SEC / 100);
1388                 } else {
1389                         log_error("CPU quota needs to be in percent.");
1390                         return -EINVAL;
1391                 }
1392
1393                 if (r < 0)
1394                         return bus_log_create_error(r);
1395
1396                 return 0;
1397         }
1398
1399         r = sd_bus_message_append_basic(m, SD_BUS_TYPE_STRING, field);
1400         if (r < 0)
1401                 return bus_log_create_error(r);
1402
1403         if (STR_IN_SET(field,
1404                        "CPUAccounting", "MemoryAccounting", "BlockIOAccounting",
1405                        "SendSIGHUP", "SendSIGKILL", "WakeSystem", "DefaultDependencies")) {
1406
1407                 r = parse_boolean(eq);
1408                 if (r < 0) {
1409                         log_error("Failed to parse boolean assignment %s.", assignment);
1410                         return -EINVAL;
1411                 }
1412
1413                 r = sd_bus_message_append(m, "v", "b", r);
1414
1415         } else if (streq(field, "MemoryLimit")) {
1416                 off_t bytes;
1417
1418                 r = parse_size(eq, 1024, &bytes);
1419                 if (r < 0) {
1420                         log_error("Failed to parse bytes specification %s", assignment);
1421                         return -EINVAL;
1422                 }
1423
1424                 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1425
1426         } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1427                 uint64_t u;
1428
1429                 r = safe_atou64(eq, &u);
1430                 if (r < 0) {
1431                         log_error("Failed to parse %s value %s.", field, eq);
1432                         return -EINVAL;
1433                 }
1434
1435                 r = sd_bus_message_append(m, "v", "t", u);
1436
1437         } else if (STR_IN_SET(field, "User", "Group", "DevicePolicy", "KillMode"))
1438                 r = sd_bus_message_append(m, "v", "s", eq);
1439
1440         else if (streq(field, "DeviceAllow")) {
1441
1442                 if (isempty(eq))
1443                         r = sd_bus_message_append(m, "v", "a(ss)", 0);
1444                 else {
1445                         const char *path, *rwm, *e;
1446
1447                         e = strchr(eq, ' ');
1448                         if (e) {
1449                                 path = strndupa(eq, e - eq);
1450                                 rwm = e+1;
1451                         } else {
1452                                 path = eq;
1453                                 rwm = "";
1454                         }
1455
1456                         if (!path_startswith(path, "/dev")) {
1457                                 log_error("%s is not a device file in /dev.", path);
1458                                 return -EINVAL;
1459                         }
1460
1461                         r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1462                 }
1463
1464         } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1465
1466                 if (isempty(eq))
1467                         r = sd_bus_message_append(m, "v", "a(st)", 0);
1468                 else {
1469                         const char *path, *bandwidth, *e;
1470                         off_t bytes;
1471
1472                         e = strchr(eq, ' ');
1473                         if (e) {
1474                                 path = strndupa(eq, e - eq);
1475                                 bandwidth = e+1;
1476                         } else {
1477                                 log_error("Failed to parse %s value %s.", field, eq);
1478                                 return -EINVAL;
1479                         }
1480
1481                         if (!path_startswith(path, "/dev")) {
1482                                 log_error("%s is not a device file in /dev.", path);
1483                                 return -EINVAL;
1484                         }
1485
1486                         r = parse_size(bandwidth, 1000, &bytes);
1487                         if (r < 0) {
1488                                 log_error("Failed to parse byte value %s.", bandwidth);
1489                                 return -EINVAL;
1490                         }
1491
1492                         r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1493                 }
1494
1495         } else if (streq(field, "BlockIODeviceWeight")) {
1496
1497                 if (isempty(eq))
1498                         r = sd_bus_message_append(m, "v", "a(st)", 0);
1499                 else {
1500                         const char *path, *weight, *e;
1501                         uint64_t u;
1502
1503                         e = strchr(eq, ' ');
1504                         if (e) {
1505                                 path = strndupa(eq, e - eq);
1506                                 weight = e+1;
1507                         } else {
1508                                 log_error("Failed to parse %s value %s.", field, eq);
1509                                 return -EINVAL;
1510                         }
1511
1512                         if (!path_startswith(path, "/dev")) {
1513                                 log_error("%s is not a device file in /dev.", path);
1514                                 return -EINVAL;
1515                         }
1516
1517                         r = safe_atou64(weight, &u);
1518                         if (r < 0) {
1519                                 log_error("Failed to parse %s value %s.", field, weight);
1520                                 return -EINVAL;
1521                         }
1522                         r = sd_bus_message_append(m, "v", "a(st)", path, u);
1523                 }
1524
1525         } else if (rlimit_from_string(field) >= 0) {
1526                 uint64_t rl;
1527
1528                 if (streq(eq, "infinity"))
1529                         rl = (uint64_t) -1;
1530                 else {
1531                         r = safe_atou64(eq, &rl);
1532                         if (r < 0) {
1533                                 log_error("Invalid resource limit: %s", eq);
1534                                 return -EINVAL;
1535                         }
1536                 }
1537
1538                 r = sd_bus_message_append(m, "v", "t", rl);
1539
1540         } else if (streq(field, "Nice")) {
1541                 int32_t i;
1542
1543                 r = safe_atoi32(eq, &i);
1544                 if (r < 0) {
1545                         log_error("Failed to parse %s value %s.", field, eq);
1546                         return -EINVAL;
1547                 }
1548
1549                 r = sd_bus_message_append(m, "v", "i", i);
1550
1551         } else if (streq(field, "Environment")) {
1552
1553                 r = sd_bus_message_append(m, "v", "as", 1, eq);
1554
1555         } else if (streq(field, "KillSignal")) {
1556                 int sig;
1557
1558                 sig = signal_from_string_try_harder(eq);
1559                 if (sig < 0) {
1560                         log_error("Failed to parse %s value %s.", field, eq);
1561                         return -EINVAL;
1562                 }
1563
1564                 r = sd_bus_message_append(m, "v", "i", sig);
1565
1566         } else if (streq(field, "AccuracySec")) {
1567                 usec_t u;
1568
1569                 r = parse_sec(eq, &u);
1570                 if (r < 0) {
1571                         log_error("Failed to parse %s value %s", field, eq);
1572                         return -EINVAL;
1573                 }
1574
1575                 r = sd_bus_message_append(m, "v", "t", u);
1576
1577         } else {
1578                 log_error("Unknown assignment %s.", assignment);
1579                 return -EINVAL;
1580         }
1581
1582         if (r < 0)
1583                 return bus_log_create_error(r);
1584
1585         return 0;
1586 }
1587
1588 typedef struct BusWaitForJobs {
1589         sd_bus *bus;
1590         Set *jobs;
1591
1592         char *name;
1593         char *result;
1594
1595         sd_bus_slot *slot_job_removed;
1596         sd_bus_slot *slot_disconnected;
1597 } BusWaitForJobs;
1598
1599 static int match_disconnected(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1600         assert(bus);
1601         assert(m);
1602
1603         log_error("Warning! D-Bus connection terminated.");
1604         sd_bus_close(bus);
1605
1606         return 0;
1607 }
1608
1609 static int match_job_removed(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) {
1610         const char *path, *unit, *result;
1611         BusWaitForJobs *d = userdata;
1612         uint32_t id;
1613         char *found;
1614         int r;
1615
1616         assert(bus);
1617         assert(m);
1618         assert(d);
1619
1620         r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1621         if (r < 0) {
1622                 bus_log_parse_error(r);
1623                 return 0;
1624         }
1625
1626         found = set_remove(d->jobs, (char*) path);
1627         if (!found)
1628                 return 0;
1629
1630         free(found);
1631
1632         if (!isempty(result))
1633                 d->result = strdup(result);
1634
1635         if (!isempty(unit))
1636                 d->name = strdup(unit);
1637
1638         return 0;
1639 }
1640
1641 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1642         if (!d)
1643                 return;
1644
1645         set_free_free(d->jobs);
1646
1647         sd_bus_slot_unref(d->slot_disconnected);
1648         sd_bus_slot_unref(d->slot_job_removed);
1649
1650         sd_bus_unref(d->bus);
1651
1652         free(d->name);
1653         free(d->result);
1654
1655         free(d);
1656 }
1657
1658 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1659         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1660         int r;
1661
1662         assert(bus);
1663         assert(ret);
1664
1665         d = new0(BusWaitForJobs, 1);
1666         if (!d)
1667                 return -ENOMEM;
1668
1669         d->bus = sd_bus_ref(bus);
1670
1671         /* When we are a bus client we match by sender. Direct
1672          * connections OTOH have no initialized sender field, and
1673          * hence we ignore the sender then */
1674         r = sd_bus_add_match(
1675                         bus,
1676                         &d->slot_job_removed,
1677                         bus->bus_client ?
1678                         "type='signal',"
1679                         "sender='org.freedesktop.systemd1',"
1680                         "interface='org.freedesktop.systemd1.Manager',"
1681                         "member='JobRemoved',"
1682                         "path='/org/freedesktop/systemd1'" :
1683                         "type='signal',"
1684                         "interface='org.freedesktop.systemd1.Manager',"
1685                         "member='JobRemoved',"
1686                         "path='/org/freedesktop/systemd1'",
1687                         match_job_removed, d);
1688         if (r < 0)
1689                 return r;
1690
1691         r = sd_bus_add_match(
1692                         bus,
1693                         &d->slot_disconnected,
1694                         "type='signal',"
1695                         "sender='org.freedesktop.DBus.Local',"
1696                         "interface='org.freedesktop.DBus.Local',"
1697                         "member='Disconnected'",
1698                         match_disconnected, d);
1699         if (r < 0)
1700                 return r;
1701
1702         *ret = d;
1703         d = NULL;
1704
1705         return 0;
1706 }
1707
1708 static int bus_process_wait(sd_bus *bus) {
1709         int r;
1710
1711         for (;;) {
1712                 r = sd_bus_process(bus, NULL);
1713                 if (r < 0)
1714                         return r;
1715                 if (r > 0)
1716                         return 0;
1717
1718                 r = sd_bus_wait(bus, (uint64_t) -1);
1719                 if (r < 0)
1720                         return r;
1721         }
1722 }
1723
1724 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1725         int r = 0;
1726
1727         assert(d->result);
1728
1729         if (!quiet) {
1730                 if (streq(d->result, "canceled"))
1731                         log_error("Job for %s canceled.", strna(d->name));
1732                 else if (streq(d->result, "timeout"))
1733                         log_error("Job for %s timed out.", strna(d->name));
1734                 else if (streq(d->result, "dependency"))
1735                         log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1736                 else if (streq(d->result, "invalid"))
1737                         log_error("Job for %s invalid.", strna(d->name));
1738                 else if (streq(d->result, "assert"))
1739                         log_error("Assertion failed on job for %s.", strna(d->name));
1740                 else if (streq(d->result, "unsupported"))
1741                         log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1742                 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1743                         if (d->name) {
1744                                 bool quotes;
1745
1746                                 quotes = chars_intersect(d->name, SHELL_NEED_QUOTES);
1747
1748                                 log_error("Job for %s failed. See \"systemctl status %s%s%s\" and \"journalctl -xe\" for details.",
1749                                           d->name,
1750                                           quotes ? "'" : "", d->name, quotes ? "'" : "");
1751                         } else
1752                                 log_error("Job failed. See \"journalctl -xe\" for details.");
1753                 }
1754         }
1755
1756         if (streq(d->result, "canceled"))
1757                 r = -ECANCELED;
1758         else if (streq(d->result, "timeout"))
1759                 r = -ETIME;
1760         else if (streq(d->result, "dependency"))
1761                 r = -EIO;
1762         else if (streq(d->result, "invalid"))
1763                 r = -ENOEXEC;
1764         else if (streq(d->result, "assert"))
1765                 r = -EPROTO;
1766         else if (streq(d->result, "unsupported"))
1767                 r = -ENOTSUP;
1768         else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1769                 r = -EIO;
1770
1771         return r;
1772 }
1773
1774 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1775         int r = 0;
1776
1777         assert(d);
1778
1779         while (!set_isempty(d->jobs)) {
1780                 int q;
1781
1782                 q = bus_process_wait(d->bus);
1783                 if (q < 0)
1784                         return log_error_errno(q, "Failed to wait for response: %m");
1785
1786                 if (d->result) {
1787                         q = check_wait_response(d, quiet);
1788                         /* Return the first error as it is most likely to be
1789                          * meaningful. */
1790                         if (q < 0 && r == 0)
1791                                 r = q;
1792
1793                         log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1794                 }
1795
1796                 free(d->name);
1797                 d->name = NULL;
1798
1799                 free(d->result);
1800                 d->result = NULL;
1801         }
1802
1803         return r;
1804 }
1805
1806 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1807         int r;
1808
1809         assert(d);
1810
1811         r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1812         if (r < 0)
1813                 return r;
1814
1815         return set_put_strdup(d->jobs, path);
1816 }
1817
1818 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
1819         const char *type, *path, *source;
1820         int r;
1821
1822         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1823         if (r < 0)
1824                 return bus_log_parse_error(r);
1825
1826         while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1827                 if (!quiet) {
1828                         if (streq(type, "symlink"))
1829                                 log_info("Created symlink from %s to %s.", path, source);
1830                         else
1831                                 log_info("Removed symlink %s.", path);
1832                 }
1833         }
1834         if (r < 0)
1835                 return bus_log_parse_error(r);
1836
1837         r = sd_bus_message_exit_container(m);
1838         if (r < 0)
1839                 return bus_log_parse_error(r);
1840
1841         return 0;
1842 }