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