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