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