chiark / gitweb /
c4e44b1fa4d5003c33c8ea5c5681e493cda3ea3c
[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 #include "unit-name.h"
34
35 #include "sd-bus.h"
36 #include "bus-error.h"
37 #include "bus-message.h"
38 #include "bus-util.h"
39 #include "bus-internal.h"
40
41 static int name_owner_change_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
42         sd_event *e = userdata;
43
44         assert(bus);
45         assert(m);
46         assert(e);
47
48         sd_bus_close(bus);
49         sd_event_exit(e, 0);
50
51         return 1;
52 }
53
54 int bus_async_unregister_and_exit(sd_event *e, sd_bus *bus, const char *name) {
55         _cleanup_free_ char *match = NULL;
56         const char *unique;
57         int r;
58
59         assert(e);
60         assert(bus);
61         assert(name);
62
63         /* We unregister the name here and then wait for the
64          * NameOwnerChanged signal for this event to arrive before we
65          * quit. We do this in order to make sure that any queued
66          * requests are still processed before we really exit. */
67
68         r = sd_bus_get_unique_name(bus, &unique);
69         if (r < 0)
70                 return r;
71
72         r = asprintf(&match,
73                      "sender='org.freedesktop.DBus',"
74                      "type='signal',"
75                      "interface='org.freedesktop.DBus',"
76                      "member='NameOwnerChanged',"
77                      "path='/org/freedesktop/DBus',"
78                      "arg0='%s',"
79                      "arg1='%s',"
80                      "arg2=''", name, unique);
81         if (r < 0)
82                 return -ENOMEM;
83
84         r = sd_bus_add_match(bus, NULL, match, name_owner_change_callback, e);
85         if (r < 0)
86                 return r;
87
88         r = sd_bus_release_name(bus, name);
89         if (r < 0)
90                 return r;
91
92         return 0;
93 }
94
95 int bus_event_loop_with_idle(
96                 sd_event *e,
97                 sd_bus *bus,
98                 const char *name,
99                 usec_t timeout,
100                 check_idle_t check_idle,
101                 void *userdata) {
102         bool exiting = false;
103         int r, code;
104
105         assert(e);
106         assert(bus);
107         assert(name);
108
109         for (;;) {
110                 bool idle;
111
112                 r = sd_event_get_state(e);
113                 if (r < 0)
114                         return r;
115                 if (r == SD_EVENT_FINISHED)
116                         break;
117
118                 if (check_idle)
119                         idle = check_idle(userdata);
120                 else
121                         idle = true;
122
123                 r = sd_event_run(e, exiting || !idle ? (uint64_t) -1 : timeout);
124                 if (r < 0)
125                         return r;
126
127                 if (r == 0 && !exiting && idle) {
128
129                         r = sd_bus_try_close(bus);
130                         if (r == -EBUSY)
131                                 continue;
132
133                         /* Fallback for dbus1 connections: we
134                          * unregister the name and wait for the
135                          * response to come through for it */
136                         if (r == -EOPNOTSUPP) {
137
138                                 /* Inform the service manager that we
139                                  * are going down, so that it will
140                                  * queue all further start requests,
141                                  * instead of assuming we are already
142                                  * running. */
143                                 sd_notify(false, "STOPPING=1");
144
145                                 r = bus_async_unregister_and_exit(e, bus, name);
146                                 if (r < 0)
147                                         return r;
148
149                                 exiting = true;
150                                 continue;
151                         }
152
153                         if (r < 0)
154                                 return r;
155
156                         sd_event_exit(e, 0);
157                         break;
158                 }
159         }
160
161         r = sd_event_get_exit_code(e, &code);
162         if (r < 0)
163                 return r;
164
165         return code;
166 }
167
168 int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) {
169         _cleanup_bus_message_unref_ sd_bus_message *rep = NULL;
170         int r, has_owner = 0;
171
172         assert(c);
173         assert(name);
174
175         r = sd_bus_call_method(c,
176                                "org.freedesktop.DBus",
177                                "/org/freedesktop/dbus",
178                                "org.freedesktop.DBus",
179                                "NameHasOwner",
180                                error,
181                                &rep,
182                                "s",
183                                name);
184         if (r < 0)
185                 return r;
186
187         r = sd_bus_message_read_basic(rep, 'b', &has_owner);
188         if (r < 0)
189                 return sd_bus_error_set_errno(error, r);
190
191         return has_owner;
192 }
193
194 static int check_good_user(sd_bus_message *m, uid_t good_user) {
195         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
196         uid_t sender_uid;
197         int r;
198
199         assert(m);
200
201         if (good_user == UID_INVALID)
202                 return 0;
203
204         r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_EUID, &creds);
205         if (r < 0)
206                 return r;
207
208         r = sd_bus_creds_get_euid(creds, &sender_uid);
209         if (r < 0)
210                 return r;
211
212         return sender_uid == good_user;
213 }
214
215 int bus_test_polkit(
216                 sd_bus_message *call,
217                 int capability,
218                 const char *action,
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         /* Tests non-interactively! */
229
230         r = check_good_user(call, good_user);
231         if (r != 0)
232                 return r;
233
234         r = sd_bus_query_sender_privilege(call, capability);
235         if (r < 0)
236                 return r;
237         else if (r > 0)
238                 return 1;
239 #ifdef ENABLE_POLKIT
240         else {
241                 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
242                 int authorized = false, challenge = false;
243                 const char *sender;
244
245                 sender = sd_bus_message_get_sender(call);
246                 if (!sender)
247                         return -EBADMSG;
248
249                 r = sd_bus_call_method(
250                                 call->bus,
251                                 "org.freedesktop.PolicyKit1",
252                                 "/org/freedesktop/PolicyKit1/Authority",
253                                 "org.freedesktop.PolicyKit1.Authority",
254                                 "CheckAuthorization",
255                                 e,
256                                 &reply,
257                                 "(sa{sv})sa{ss}us",
258                                 "system-bus-name", 1, "name", "s", sender,
259                                 action,
260                                 0,
261                                 0,
262                                 "");
263
264                 if (r < 0) {
265                         /* Treat no PK available as access denied */
266                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
267                                 sd_bus_error_free(e);
268                                 return -EACCES;
269                         }
270
271                         return r;
272                 }
273
274                 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
275                 if (r < 0)
276                         return r;
277
278                 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
279                 if (r < 0)
280                         return r;
281
282                 if (authorized)
283                         return 1;
284
285                 if (_challenge) {
286                         *_challenge = challenge;
287                         return 0;
288                 }
289         }
290 #endif
291
292         return -EACCES;
293 }
294
295 #ifdef ENABLE_POLKIT
296
297 typedef struct AsyncPolkitQuery {
298         sd_bus_message *request, *reply;
299         sd_bus_message_handler_t callback;
300         void *userdata;
301         sd_bus_slot *slot;
302         Hashmap *registry;
303 } AsyncPolkitQuery;
304
305 static void async_polkit_query_free(AsyncPolkitQuery *q) {
306
307         if (!q)
308                 return;
309
310         sd_bus_slot_unref(q->slot);
311
312         if (q->registry && q->request)
313                 hashmap_remove(q->registry, q->request);
314
315         sd_bus_message_unref(q->request);
316         sd_bus_message_unref(q->reply);
317
318         free(q);
319 }
320
321 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
322         _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
323         AsyncPolkitQuery *q = userdata;
324         int r;
325
326         assert(bus);
327         assert(reply);
328         assert(q);
329
330         q->slot = sd_bus_slot_unref(q->slot);
331         q->reply = sd_bus_message_ref(reply);
332
333         r = sd_bus_message_rewind(q->request, true);
334         if (r < 0) {
335                 r = sd_bus_reply_method_errno(q->request, r, NULL);
336                 goto finish;
337         }
338
339         r = q->callback(bus, q->request, q->userdata, &error_buffer);
340         r = bus_maybe_reply_error(q->request, r, &error_buffer);
341
342 finish:
343         async_polkit_query_free(q);
344
345         return r;
346 }
347
348 #endif
349
350 int bus_verify_polkit_async(
351                 sd_bus_message *call,
352                 int capability,
353                 const char *action,
354                 bool interactive,
355                 uid_t good_user,
356                 Hashmap **registry,
357                 sd_bus_error *error) {
358
359 #ifdef ENABLE_POLKIT
360         _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
361         AsyncPolkitQuery *q;
362         const char *sender;
363         sd_bus_message_handler_t callback;
364         void *userdata;
365         int c;
366 #endif
367         int r;
368
369         assert(call);
370         assert(action);
371         assert(registry);
372
373         r = check_good_user(call, good_user);
374         if (r != 0)
375                 return r;
376
377 #ifdef ENABLE_POLKIT
378         q = hashmap_get(*registry, call);
379         if (q) {
380                 int authorized, challenge;
381
382                 /* This is the second invocation of this function, and
383                  * there's already a response from polkit, let's
384                  * process it */
385                 assert(q->reply);
386
387                 if (sd_bus_message_is_method_error(q->reply, NULL)) {
388                         const sd_bus_error *e;
389
390                         /* Copy error from polkit reply */
391                         e = sd_bus_message_get_error(q->reply);
392                         sd_bus_error_copy(error, e);
393
394                         /* Treat no PK available as access denied */
395                         if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
396                                 return -EACCES;
397
398                         return -sd_bus_error_get_errno(e);
399                 }
400
401                 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
402                 if (r >= 0)
403                         r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
404
405                 if (r < 0)
406                         return r;
407
408                 if (authorized)
409                         return 1;
410
411                 if (challenge)
412                         return sd_bus_error_set(error, SD_BUS_ERROR_INTERACTIVE_AUTHORIZATION_REQUIRED, "Interactive authentication required.");
413
414                 return -EACCES;
415         }
416 #endif
417
418         r = sd_bus_query_sender_privilege(call, capability);
419         if (r < 0)
420                 return r;
421         else if (r > 0)
422                 return 1;
423
424 #ifdef ENABLE_POLKIT
425         if (sd_bus_get_current_message(call->bus) != call)
426                 return -EINVAL;
427
428         callback = sd_bus_get_current_handler(call->bus);
429         if (!callback)
430                 return -EINVAL;
431
432         userdata = sd_bus_get_current_userdata(call->bus);
433
434         sender = sd_bus_message_get_sender(call);
435         if (!sender)
436                 return -EBADMSG;
437
438         c = sd_bus_message_get_allow_interactive_authorization(call);
439         if (c < 0)
440                 return c;
441         if (c > 0)
442                 interactive = true;
443
444         r = hashmap_ensure_allocated(registry, NULL);
445         if (r < 0)
446                 return r;
447
448         r = sd_bus_message_new_method_call(
449                         call->bus,
450                         &pk,
451                         "org.freedesktop.PolicyKit1",
452                         "/org/freedesktop/PolicyKit1/Authority",
453                         "org.freedesktop.PolicyKit1.Authority",
454                         "CheckAuthorization");
455         if (r < 0)
456                 return r;
457
458         r = sd_bus_message_append(
459                         pk,
460                         "(sa{sv})sa{ss}us",
461                         "system-bus-name", 1, "name", "s", sender,
462                         action,
463                         0,
464                         !!interactive,
465                         NULL);
466         if (r < 0)
467                 return r;
468
469         q = new0(AsyncPolkitQuery, 1);
470         if (!q)
471                 return -ENOMEM;
472
473         q->request = sd_bus_message_ref(call);
474         q->callback = callback;
475         q->userdata = userdata;
476
477         r = hashmap_put(*registry, call, q);
478         if (r < 0) {
479                 async_polkit_query_free(q);
480                 return r;
481         }
482
483         q->registry = *registry;
484
485         r = sd_bus_call_async(call->bus, &q->slot, pk, async_polkit_callback, q, 0);
486         if (r < 0) {
487                 async_polkit_query_free(q);
488                 return r;
489         }
490
491         return 0;
492 #endif
493
494         return -EACCES;
495 }
496
497 void bus_verify_polkit_async_registry_free(Hashmap *registry) {
498 #ifdef ENABLE_POLKIT
499         AsyncPolkitQuery *q;
500
501         while ((q = hashmap_steal_first(registry)))
502                 async_polkit_query_free(q);
503
504         hashmap_free(registry);
505 #endif
506 }
507
508 int bus_check_peercred(sd_bus *c) {
509         struct ucred ucred;
510         socklen_t l;
511         int fd;
512
513         assert(c);
514
515         fd = sd_bus_get_fd(c);
516         if (fd < 0)
517                 return fd;
518
519         l = sizeof(struct ucred);
520         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
521                 return -errno;
522
523         if (l != sizeof(struct ucred))
524                 return -E2BIG;
525
526         if (ucred.uid != 0 && ucred.uid != geteuid())
527                 return -EPERM;
528
529         return 1;
530 }
531
532 int bus_open_system_systemd(sd_bus **_bus) {
533         _cleanup_bus_unref_ sd_bus *bus = NULL;
534         int r;
535
536         assert(_bus);
537
538         if (geteuid() != 0)
539                 return sd_bus_open_system(_bus);
540
541         /* If we are root and kdbus is not available, then let's talk
542          * directly to the system instance, instead of going via the
543          * bus */
544
545 #ifdef ENABLE_KDBUS
546         r = sd_bus_new(&bus);
547         if (r < 0)
548                 return r;
549
550         r = sd_bus_set_address(bus, KERNEL_SYSTEM_BUS_ADDRESS);
551         if (r < 0)
552                 return r;
553
554         bus->bus_client = true;
555
556         r = sd_bus_start(bus);
557         if (r >= 0) {
558                 *_bus = bus;
559                 bus = NULL;
560                 return 0;
561         }
562
563         bus = sd_bus_unref(bus);
564 #endif
565
566         r = sd_bus_new(&bus);
567         if (r < 0)
568                 return r;
569
570         r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
571         if (r < 0)
572                 return r;
573
574         r = sd_bus_start(bus);
575         if (r < 0)
576                 return sd_bus_open_system(_bus);
577
578         r = bus_check_peercred(bus);
579         if (r < 0)
580                 return r;
581
582         *_bus = bus;
583         bus = NULL;
584
585         return 0;
586 }
587
588 int bus_open_user_systemd(sd_bus **_bus) {
589         _cleanup_bus_unref_ sd_bus *bus = NULL;
590         _cleanup_free_ char *ee = NULL;
591         const char *e;
592         int r;
593
594         /* Try via kdbus first, and then directly */
595
596         assert(_bus);
597
598 #ifdef ENABLE_KDBUS
599         r = sd_bus_new(&bus);
600         if (r < 0)
601                 return r;
602
603         if (asprintf(&bus->address, KERNEL_USER_BUS_ADDRESS_FMT, getuid()) < 0)
604                 return -ENOMEM;
605
606         bus->bus_client = true;
607
608         r = sd_bus_start(bus);
609         if (r >= 0) {
610                 *_bus = bus;
611                 bus = NULL;
612                 return 0;
613         }
614
615         bus = sd_bus_unref(bus);
616 #endif
617
618         e = secure_getenv("XDG_RUNTIME_DIR");
619         if (!e)
620                 return sd_bus_open_user(_bus);
621
622         ee = bus_address_escape(e);
623         if (!ee)
624                 return -ENOMEM;
625
626         r = sd_bus_new(&bus);
627         if (r < 0)
628                 return r;
629
630         bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL);
631         if (!bus->address)
632                 return -ENOMEM;
633
634         r = sd_bus_start(bus);
635         if (r < 0)
636                 return sd_bus_open_user(_bus);
637
638         r = bus_check_peercred(bus);
639         if (r < 0)
640                 return r;
641
642         *_bus = bus;
643         bus = NULL;
644
645         return 0;
646 }
647
648 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
649         char type;
650         const char *contents;
651         int r;
652
653         assert(name);
654         assert(property);
655
656         r = sd_bus_message_peek_type(property, &type, &contents);
657         if (r < 0)
658                 return r;
659
660         switch (type) {
661
662         case SD_BUS_TYPE_STRING: {
663                 const char *s;
664
665                 r = sd_bus_message_read_basic(property, type, &s);
666                 if (r < 0)
667                         return r;
668
669                 if (all || !isempty(s)) {
670                         _cleanup_free_ char *escaped = NULL;
671
672                         escaped = xescape(s, "\n");
673                         if (!escaped)
674                                 return -ENOMEM;
675
676                         printf("%s=%s\n", name, escaped);
677                 }
678
679                 return 1;
680         }
681
682         case SD_BUS_TYPE_BOOLEAN: {
683                 int b;
684
685                 r = sd_bus_message_read_basic(property, type, &b);
686                 if (r < 0)
687                         return r;
688
689                 printf("%s=%s\n", name, yes_no(b));
690
691                 return 1;
692         }
693
694         case SD_BUS_TYPE_UINT64: {
695                 uint64_t u;
696
697                 r = sd_bus_message_read_basic(property, type, &u);
698                 if (r < 0)
699                         return r;
700
701                 /* Yes, heuristics! But we can change this check
702                  * should it turn out to not be sufficient */
703
704                 if (endswith(name, "Timestamp")) {
705                         char timestamp[FORMAT_TIMESTAMP_MAX], *t;
706
707                         t = format_timestamp(timestamp, sizeof(timestamp), u);
708                         if (t || all)
709                                 printf("%s=%s\n", name, strempty(t));
710
711                 } else if (strstr(name, "USec")) {
712                         char timespan[FORMAT_TIMESPAN_MAX];
713
714                         printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
715                 } else
716                         printf("%s=%llu\n", name, (unsigned long long) u);
717
718                 return 1;
719         }
720
721         case SD_BUS_TYPE_INT64: {
722                 int64_t i;
723
724                 r = sd_bus_message_read_basic(property, type, &i);
725                 if (r < 0)
726                         return r;
727
728                 printf("%s=%lld\n", name, (long long) i);
729
730                 return 1;
731         }
732
733         case SD_BUS_TYPE_UINT32: {
734                 uint32_t u;
735
736                 r = sd_bus_message_read_basic(property, type, &u);
737                 if (r < 0)
738                         return r;
739
740                 if (strstr(name, "UMask") || strstr(name, "Mode"))
741                         printf("%s=%04o\n", name, u);
742                 else
743                         printf("%s=%u\n", name, (unsigned) u);
744
745                 return 1;
746         }
747
748         case SD_BUS_TYPE_INT32: {
749                 int32_t i;
750
751                 r = sd_bus_message_read_basic(property, type, &i);
752                 if (r < 0)
753                         return r;
754
755                 printf("%s=%i\n", name, (int) i);
756                 return 1;
757         }
758
759         case SD_BUS_TYPE_DOUBLE: {
760                 double d;
761
762                 r = sd_bus_message_read_basic(property, type, &d);
763                 if (r < 0)
764                         return r;
765
766                 printf("%s=%g\n", name, d);
767                 return 1;
768         }
769
770         case SD_BUS_TYPE_ARRAY:
771                 if (streq(contents, "s")) {
772                         bool first = true;
773                         const char *str;
774
775                         r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
776                         if (r < 0)
777                                 return r;
778
779                         while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
780                                 _cleanup_free_ char *escaped = NULL;
781
782                                 if (first)
783                                         printf("%s=", name);
784
785                                 escaped = xescape(str, "\n ");
786                                 if (!escaped)
787                                         return -ENOMEM;
788
789                                 printf("%s%s", first ? "" : " ", escaped);
790
791                                 first = false;
792                         }
793                         if (r < 0)
794                                 return r;
795
796                         if (first && all)
797                                 printf("%s=", name);
798                         if (!first || all)
799                                 puts("");
800
801                         r = sd_bus_message_exit_container(property);
802                         if (r < 0)
803                                 return r;
804
805                         return 1;
806
807                 } else if (streq(contents, "y")) {
808                         const uint8_t *u;
809                         size_t n;
810
811                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
812                         if (r < 0)
813                                 return r;
814
815                         if (all || n > 0) {
816                                 unsigned int i;
817
818                                 printf("%s=", name);
819
820                                 for (i = 0; i < n; i++)
821                                         printf("%02x", u[i]);
822
823                                 puts("");
824                         }
825
826                         return 1;
827
828                 } else if (streq(contents, "u")) {
829                         uint32_t *u;
830                         size_t n;
831
832                         r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
833                         if (r < 0)
834                                 return r;
835
836                         if (all || n > 0) {
837                                 unsigned int i;
838
839                                 printf("%s=", name);
840
841                                 for (i = 0; i < n; i++)
842                                         printf("%08x", u[i]);
843
844                                 puts("");
845                         }
846
847                         return 1;
848                 }
849
850                 break;
851         }
852
853         return 0;
854 }
855
856 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
857         _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
858         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
859         int r;
860
861         assert(bus);
862         assert(path);
863
864         r = sd_bus_call_method(bus,
865                         dest,
866                         path,
867                         "org.freedesktop.DBus.Properties",
868                         "GetAll",
869                         &error,
870                         &reply,
871                         "s", "");
872         if (r < 0)
873                 return r;
874
875         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
876         if (r < 0)
877                 return r;
878
879         while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
880                 const char *name;
881                 const char *contents;
882
883                 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
884                 if (r < 0)
885                         return r;
886
887                 if (!filter || strv_find(filter, name)) {
888                         r = sd_bus_message_peek_type(reply, NULL, &contents);
889                         if (r < 0)
890                                 return r;
891
892                         r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
893                         if (r < 0)
894                                 return r;
895
896                         r = bus_print_property(name, reply, all);
897                         if (r < 0)
898                                 return r;
899                         if (r == 0) {
900                                 if (all)
901                                         printf("%s=[unprintable]\n", name);
902                                 /* skip what we didn't read */
903                                 r = sd_bus_message_skip(reply, contents);
904                                 if (r < 0)
905                                         return r;
906                         }
907
908                         r = sd_bus_message_exit_container(reply);
909                         if (r < 0)
910                                 return r;
911                 } else {
912                         r = sd_bus_message_skip(reply, "v");
913                         if (r < 0)
914                                 return r;
915                 }
916
917                 r = sd_bus_message_exit_container(reply);
918                 if (r < 0)
919                         return r;
920         }
921         if (r < 0)
922                 return r;
923
924         r = sd_bus_message_exit_container(reply);
925         if (r < 0)
926                 return r;
927
928         return 0;
929 }
930
931 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
932         sd_id128_t *p = userdata;
933         const void *v;
934         size_t n;
935         int r;
936
937         r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
938         if (r < 0)
939                 return r;
940
941         if (n == 0)
942                 *p = SD_ID128_NULL;
943         else if (n == 16)
944                 memcpy((*p).bytes, v, n);
945         else
946                 return -EINVAL;
947
948         return 0;
949 }
950
951 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
952         char type;
953         int r;
954
955         r = sd_bus_message_peek_type(m, &type, NULL);
956         if (r < 0)
957                 return r;
958
959         switch (type) {
960         case SD_BUS_TYPE_STRING: {
961                 const char *s;
962                 char **p = userdata;
963
964                 r = sd_bus_message_read_basic(m, type, &s);
965                 if (r < 0)
966                         break;
967
968                 if (isempty(s))
969                         break;
970
971                 r = free_and_strdup(p, s);
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, -EOPNOTSUPP);
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, -EOPNOTSUPP);
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 bus_job_get_service_result(BusWaitForJobs *d, char **result) {
1725         _cleanup_free_ char *dbus_path = NULL;
1726
1727         assert(d);
1728         assert(d->name);
1729         assert(result);
1730
1731         dbus_path = unit_dbus_path_from_name(d->name);
1732         if (!dbus_path)
1733                 return -ENOMEM;
1734
1735         return sd_bus_get_property_string(d->bus,
1736                                           "org.freedesktop.systemd1",
1737                                           dbus_path,
1738                                           "org.freedesktop.systemd1.Service",
1739                                           "Result",
1740                                           NULL,
1741                                           result);
1742 }
1743
1744 static const struct {
1745         const char *result, *explanation;
1746 } explanations [] = {
1747         { "resources", "configured resource limit was exceeded" },
1748         { "timeout", "timeout was exceeded" },
1749         { "exit-code", "control process exited with error code" },
1750         { "signal", "fatal signal was delivered to the control process" },
1751         { "core-dump", "fatal signal was delivered to the control process. Core dumped" },
1752         { "watchdog", "service failed to send watchdog ping" },
1753         { "start-limit", "start of the service was attempted too often too quickly" }
1754 };
1755
1756 static void log_job_error_with_service_result(const char* service, const char *result) {
1757         unsigned i;
1758         _cleanup_free_ char *service_shell_quoted = NULL;
1759
1760         assert(service);
1761         assert(result);
1762
1763         service_shell_quoted = shell_maybe_quote(service);
1764
1765         for (i = 0; i < ELEMENTSOF(explanations); ++i)
1766                 if (streq(result, explanations[i].result))
1767                         break;
1768
1769         if (i < ELEMENTSOF(explanations))
1770                 log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1771                           service,
1772                           explanations[i].explanation,
1773                           strna(service_shell_quoted));
1774         else
1775                 log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1776                           service,
1777                           strna(service_shell_quoted));
1778
1779         /* For some results maybe additional explanation is required */
1780         if (streq_ptr(result, "start-limit"))
1781                 log_info("To force a start please invoke \"systemctl reset-failed %s\" followed by \"systemctl start %s\" again.",
1782                          strna(service_shell_quoted),
1783                          strna(service_shell_quoted));
1784 }
1785
1786 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1787         int r = 0;
1788
1789         assert(d->result);
1790
1791         if (!quiet) {
1792                 if (streq(d->result, "canceled"))
1793                         log_error("Job for %s canceled.", strna(d->name));
1794                 else if (streq(d->result, "timeout"))
1795                         log_error("Job for %s timed out.", strna(d->name));
1796                 else if (streq(d->result, "dependency"))
1797                         log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1798                 else if (streq(d->result, "invalid"))
1799                         log_error("Job for %s invalid.", strna(d->name));
1800                 else if (streq(d->result, "assert"))
1801                         log_error("Assertion failed on job for %s.", strna(d->name));
1802                 else if (streq(d->result, "unsupported"))
1803                         log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1804                 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1805                         if (d->name) {
1806                                 int q;
1807                                 _cleanup_free_ char *result = NULL;
1808
1809                                 q = bus_job_get_service_result(d, &result);
1810                                 if (q < 0)
1811                                         log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
1812
1813                                 log_job_error_with_service_result(d->name, result);
1814                         } else
1815                                 log_error("Job failed. See \"journalctl -xe\" for details.");
1816                 }
1817         }
1818
1819         if (streq(d->result, "canceled"))
1820                 r = -ECANCELED;
1821         else if (streq(d->result, "timeout"))
1822                 r = -ETIME;
1823         else if (streq(d->result, "dependency"))
1824                 r = -EIO;
1825         else if (streq(d->result, "invalid"))
1826                 r = -ENOEXEC;
1827         else if (streq(d->result, "assert"))
1828                 r = -EPROTO;
1829         else if (streq(d->result, "unsupported"))
1830                 r = -EOPNOTSUPP;
1831         else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1832                 r = -EIO;
1833
1834         return r;
1835 }
1836
1837 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1838         int r = 0;
1839
1840         assert(d);
1841
1842         while (!set_isempty(d->jobs)) {
1843                 int q;
1844
1845                 q = bus_process_wait(d->bus);
1846                 if (q < 0)
1847                         return log_error_errno(q, "Failed to wait for response: %m");
1848
1849                 if (d->result) {
1850                         q = check_wait_response(d, quiet);
1851                         /* Return the first error as it is most likely to be
1852                          * meaningful. */
1853                         if (q < 0 && r == 0)
1854                                 r = q;
1855
1856                         log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1857                 }
1858
1859                 free(d->name);
1860                 d->name = NULL;
1861
1862                 free(d->result);
1863                 d->result = NULL;
1864         }
1865
1866         return r;
1867 }
1868
1869 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1870         int r;
1871
1872         assert(d);
1873
1874         r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1875         if (r < 0)
1876                 return r;
1877
1878         return set_put_strdup(d->jobs, path);
1879 }
1880
1881 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet) {
1882         const char *type, *path, *source;
1883         int r;
1884
1885         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1886         if (r < 0)
1887                 return bus_log_parse_error(r);
1888
1889         while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1890                 if (!quiet) {
1891                         if (streq(type, "symlink"))
1892                                 log_info("Created symlink from %s to %s.", path, source);
1893                         else
1894                                 log_info("Removed symlink %s.", path);
1895                 }
1896         }
1897         if (r < 0)
1898                 return bus_log_parse_error(r);
1899
1900         r = sd_bus_message_exit_container(m);
1901         if (r < 0)
1902                 return bus_log_parse_error(r);
1903
1904         return 0;
1905 }