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