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