chiark / gitweb /
Prep v225: Applying various fixes and changes to src/libelogind/sd-bus that got lost...
[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                        "IgnoreSIGPIPE", "TTYVHangup", "TTYReset", "RemainAfterExit")) {
1398
1399                 r = parse_boolean(eq);
1400                 if (r < 0) {
1401                         log_error("Failed to parse boolean assignment %s.", assignment);
1402                         return -EINVAL;
1403                 }
1404
1405                 r = sd_bus_message_append(m, "v", "b", r);
1406
1407         } else if (streq(field, "MemoryLimit")) {
1408                 off_t bytes;
1409
1410                 r = parse_size(eq, 1024, &bytes);
1411                 if (r < 0) {
1412                         log_error("Failed to parse bytes specification %s", assignment);
1413                         return -EINVAL;
1414                 }
1415
1416                 r = sd_bus_message_append(m, "v", "t", (uint64_t) bytes);
1417
1418         } else if (STR_IN_SET(field, "CPUShares", "BlockIOWeight")) {
1419                 uint64_t u;
1420
1421                 r = safe_atou64(eq, &u);
1422                 if (r < 0) {
1423                         log_error("Failed to parse %s value %s.", field, eq);
1424                         return -EINVAL;
1425                 }
1426
1427                 r = sd_bus_message_append(m, "v", "t", u);
1428
1429         } else if (STR_IN_SET(field,
1430                               "User", "Group", "DevicePolicy", "KillMode",
1431                               "UtmpIdentifier", "UtmpMode", "PAMName", "TTYPath",
1432                               "StandardInput", "StandardOutput", "StandardError",
1433                               "Description", "Slice", "Type"))
1434                 r = sd_bus_message_append(m, "v", "s", eq);
1435
1436         else if (streq(field, "DeviceAllow")) {
1437
1438                 if (isempty(eq))
1439                         r = sd_bus_message_append(m, "v", "a(ss)", 0);
1440                 else {
1441                         const char *path, *rwm, *e;
1442
1443                         e = strchr(eq, ' ');
1444                         if (e) {
1445                                 path = strndupa(eq, e - eq);
1446                                 rwm = e+1;
1447                         } else {
1448                                 path = eq;
1449                                 rwm = "";
1450                         }
1451
1452                         if (!path_startswith(path, "/dev")) {
1453                                 log_error("%s is not a device file in /dev.", path);
1454                                 return -EINVAL;
1455                         }
1456
1457                         r = sd_bus_message_append(m, "v", "a(ss)", 1, path, rwm);
1458                 }
1459
1460         } else if (STR_IN_SET(field, "BlockIOReadBandwidth", "BlockIOWriteBandwidth")) {
1461
1462                 if (isempty(eq))
1463                         r = sd_bus_message_append(m, "v", "a(st)", 0);
1464                 else {
1465                         const char *path, *bandwidth, *e;
1466                         off_t bytes;
1467
1468                         e = strchr(eq, ' ');
1469                         if (e) {
1470                                 path = strndupa(eq, e - eq);
1471                                 bandwidth = e+1;
1472                         } else {
1473                                 log_error("Failed to parse %s value %s.", field, eq);
1474                                 return -EINVAL;
1475                         }
1476
1477                         if (!path_startswith(path, "/dev")) {
1478                                 log_error("%s is not a device file in /dev.", path);
1479                                 return -EINVAL;
1480                         }
1481
1482                         r = parse_size(bandwidth, 1000, &bytes);
1483                         if (r < 0) {
1484                                 log_error("Failed to parse byte value %s.", bandwidth);
1485                                 return -EINVAL;
1486                         }
1487
1488                         r = sd_bus_message_append(m, "v", "a(st)", 1, path, (uint64_t) bytes);
1489                 }
1490
1491         } else if (streq(field, "BlockIODeviceWeight")) {
1492
1493                 if (isempty(eq))
1494                         r = sd_bus_message_append(m, "v", "a(st)", 0);
1495                 else {
1496                         const char *path, *weight, *e;
1497                         uint64_t u;
1498
1499                         e = strchr(eq, ' ');
1500                         if (e) {
1501                                 path = strndupa(eq, e - eq);
1502                                 weight = e+1;
1503                         } else {
1504                                 log_error("Failed to parse %s value %s.", field, eq);
1505                                 return -EINVAL;
1506                         }
1507
1508                         if (!path_startswith(path, "/dev")) {
1509                                 log_error("%s is not a device file in /dev.", path);
1510                                 return -EINVAL;
1511                         }
1512
1513                         r = safe_atou64(weight, &u);
1514                         if (r < 0) {
1515                                 log_error("Failed to parse %s value %s.", field, weight);
1516                                 return -EINVAL;
1517                         }
1518                         r = sd_bus_message_append(m, "v", "a(st)", path, u);
1519                 }
1520
1521         } else if (rlimit_from_string(field) >= 0) {
1522                 uint64_t rl;
1523
1524                 if (streq(eq, "infinity"))
1525                         rl = (uint64_t) -1;
1526                 else {
1527                         r = safe_atou64(eq, &rl);
1528                         if (r < 0) {
1529                                 log_error("Invalid resource limit: %s", eq);
1530                                 return -EINVAL;
1531                         }
1532                 }
1533
1534                 r = sd_bus_message_append(m, "v", "t", rl);
1535
1536         } else if (streq(field, "Nice")) {
1537                 int32_t i;
1538
1539                 r = safe_atoi32(eq, &i);
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", "i", i);
1546
1547         } else if (streq(field, "Environment")) {
1548
1549                 r = sd_bus_message_append(m, "v", "as", 1, eq);
1550
1551         } else if (streq(field, "KillSignal")) {
1552                 int sig;
1553
1554                 sig = signal_from_string_try_harder(eq);
1555                 if (sig < 0) {
1556                         log_error("Failed to parse %s value %s.", field, eq);
1557                         return -EINVAL;
1558                 }
1559
1560                 r = sd_bus_message_append(m, "v", "i", sig);
1561
1562         } else if (streq(field, "AccuracySec")) {
1563                 usec_t u;
1564
1565                 r = parse_sec(eq, &u);
1566                 if (r < 0) {
1567                         log_error("Failed to parse %s value %s", field, eq);
1568                         return -EINVAL;
1569                 }
1570
1571                 r = sd_bus_message_append(m, "v", "t", u);
1572
1573         } else {
1574                 log_error("Unknown assignment %s.", assignment);
1575                 return -EINVAL;
1576         }
1577
1578         if (r < 0)
1579                 return bus_log_create_error(r);
1580
1581         return 0;
1582 }
1583 #endif // 0
1584
1585 typedef struct BusWaitForJobs {
1586         sd_bus *bus;
1587         Set *jobs;
1588
1589         char *name;
1590         char *result;
1591
1592         sd_bus_slot *slot_job_removed;
1593         sd_bus_slot *slot_disconnected;
1594 } BusWaitForJobs;
1595
1596 /// UNNEEDED by elogind
1597 #if 0
1598 static int match_disconnected(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1599         assert(m);
1600
1601         log_error("Warning! D-Bus connection terminated.");
1602         sd_bus_close(sd_bus_message_get_bus(m));
1603
1604         return 0;
1605 }
1606
1607 static int match_job_removed(sd_bus_message *m, void *userdata, sd_bus_error *error) {
1608         const char *path, *unit, *result;
1609         BusWaitForJobs *d = userdata;
1610         uint32_t id;
1611         char *found;
1612         int r;
1613
1614         assert(m);
1615         assert(d);
1616
1617         r = sd_bus_message_read(m, "uoss", &id, &path, &unit, &result);
1618         if (r < 0) {
1619                 bus_log_parse_error(r);
1620                 return 0;
1621         }
1622
1623         found = set_remove(d->jobs, (char*) path);
1624         if (!found)
1625                 return 0;
1626
1627         free(found);
1628
1629         if (!isempty(result))
1630                 d->result = strdup(result);
1631
1632         if (!isempty(unit))
1633                 d->name = strdup(unit);
1634
1635         return 0;
1636 }
1637 #endif // 0
1638
1639 void bus_wait_for_jobs_free(BusWaitForJobs *d) {
1640         if (!d)
1641                 return;
1642
1643         set_free_free(d->jobs);
1644
1645         sd_bus_slot_unref(d->slot_disconnected);
1646         sd_bus_slot_unref(d->slot_job_removed);
1647
1648         sd_bus_unref(d->bus);
1649
1650         free(d->name);
1651         free(d->result);
1652
1653         free(d);
1654 }
1655
1656 /// UNNEEDED by elogind
1657 #if 0
1658 int bus_wait_for_jobs_new(sd_bus *bus, BusWaitForJobs **ret) {
1659         _cleanup_(bus_wait_for_jobs_freep) BusWaitForJobs *d = NULL;
1660         int r;
1661
1662         assert(bus);
1663         assert(ret);
1664
1665         d = new0(BusWaitForJobs, 1);
1666         if (!d)
1667                 return -ENOMEM;
1668
1669         d->bus = sd_bus_ref(bus);
1670
1671         /* When we are a bus client we match by sender. Direct
1672          * connections OTOH have no initialized sender field, and
1673          * hence we ignore the sender then */
1674         r = sd_bus_add_match(
1675                         bus,
1676                         &d->slot_job_removed,
1677                         bus->bus_client ?
1678                         "type='signal',"
1679                         "sender='org.freedesktop.systemd1',"
1680                         "interface='org.freedesktop.systemd1.Manager',"
1681                         "member='JobRemoved',"
1682                         "path='/org/freedesktop/systemd1'" :
1683                         "type='signal',"
1684                         "interface='org.freedesktop.systemd1.Manager',"
1685                         "member='JobRemoved',"
1686                         "path='/org/freedesktop/systemd1'",
1687                         match_job_removed, d);
1688         if (r < 0)
1689                 return r;
1690
1691         r = sd_bus_add_match(
1692                         bus,
1693                         &d->slot_disconnected,
1694                         "type='signal',"
1695                         "sender='org.freedesktop.DBus.Local',"
1696                         "interface='org.freedesktop.DBus.Local',"
1697                         "member='Disconnected'",
1698                         match_disconnected, d);
1699         if (r < 0)
1700                 return r;
1701
1702         *ret = d;
1703         d = NULL;
1704
1705         return 0;
1706 }
1707 #endif // 0
1708
1709 static int bus_process_wait(sd_bus *bus) {
1710         int r;
1711
1712         for (;;) {
1713                 r = sd_bus_process(bus, NULL);
1714                 if (r < 0)
1715                         return r;
1716                 if (r > 0)
1717                         return 0;
1718
1719                 r = sd_bus_wait(bus, (uint64_t) -1);
1720                 if (r < 0)
1721                         return r;
1722         }
1723 }
1724
1725 static int bus_job_get_service_result(BusWaitForJobs *d, char **result) {
1726         _cleanup_free_ char *dbus_path = NULL;
1727
1728         assert(d);
1729         assert(d->name);
1730         assert(result);
1731
1732         dbus_path = unit_dbus_path_from_name(d->name);
1733         if (!dbus_path)
1734                 return -ENOMEM;
1735
1736         return sd_bus_get_property_string(d->bus,
1737                                           "org.freedesktop.systemd1",
1738                                           dbus_path,
1739                                           "org.freedesktop.systemd1.Service",
1740                                           "Result",
1741                                           NULL,
1742                                           result);
1743 }
1744
1745 static const struct {
1746         const char *result, *explanation;
1747 } explanations [] = {
1748         { "resources",   "a configured resource limit was exceeded" },
1749         { "timeout",     "a timeout was exceeded" },
1750         { "exit-code",   "the control process exited with error code" },
1751         { "signal",      "a fatal signal was delivered to the control process" },
1752         { "core-dump",   "a fatal signal was delivered causing the control process to dump core" },
1753         { "watchdog",    "the service failed to send watchdog ping" },
1754         { "start-limit", "start of the service was attempted too often" }
1755 };
1756
1757 static void log_job_error_with_service_result(const char* service, const char *result) {
1758         _cleanup_free_ char *service_shell_quoted = NULL;
1759
1760         assert(service);
1761
1762         service_shell_quoted = shell_maybe_quote(service);
1763
1764         if (!isempty(result)) {
1765                 unsigned i;
1766
1767                 for (i = 0; i < ELEMENTSOF(explanations); ++i)
1768                         if (streq(result, explanations[i].result))
1769                                 break;
1770
1771                 if (i < ELEMENTSOF(explanations)) {
1772                         log_error("Job for %s failed because %s. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1773                                   service,
1774                                   explanations[i].explanation,
1775                                   strna(service_shell_quoted));
1776
1777                         goto finish;
1778                 }
1779         }
1780
1781         log_error("Job for %s failed. See \"systemctl status %s\" and \"journalctl -xe\" for details.\n",
1782                   service,
1783                   strna(service_shell_quoted));
1784
1785 finish:
1786         /* For some results maybe additional explanation is required */
1787         if (streq_ptr(result, "start-limit"))
1788                 log_info("To force a start use \"systemctl reset-failed %1$s\" followed by \"systemctl start %1$s\" again.",
1789                          strna(service_shell_quoted));
1790 }
1791
1792 static int check_wait_response(BusWaitForJobs *d, bool quiet) {
1793         int r = 0;
1794
1795         assert(d->result);
1796
1797         if (!quiet) {
1798                 if (streq(d->result, "canceled"))
1799                         log_error("Job for %s canceled.", strna(d->name));
1800                 else if (streq(d->result, "timeout"))
1801                         log_error("Job for %s timed out.", strna(d->name));
1802                 else if (streq(d->result, "dependency"))
1803                         log_error("A dependency job for %s failed. See 'journalctl -xe' for details.", strna(d->name));
1804                 else if (streq(d->result, "invalid"))
1805                         log_error("Job for %s invalid.", strna(d->name));
1806                 else if (streq(d->result, "assert"))
1807                         log_error("Assertion failed on job for %s.", strna(d->name));
1808                 else if (streq(d->result, "unsupported"))
1809                         log_error("Operation on or unit type of %s not supported on this system.", strna(d->name));
1810                 else if (!streq(d->result, "done") && !streq(d->result, "skipped")) {
1811                         if (d->name) {
1812                                 int q;
1813                                 _cleanup_free_ char *result = NULL;
1814
1815                                 q = bus_job_get_service_result(d, &result);
1816                                 if (q < 0)
1817                                         log_debug_errno(q, "Failed to get Result property of service %s: %m", d->name);
1818
1819                                 log_job_error_with_service_result(d->name, result);
1820                         } else
1821                                 log_error("Job failed. See \"journalctl -xe\" for details.");
1822                 }
1823         }
1824
1825         if (streq(d->result, "canceled"))
1826                 r = -ECANCELED;
1827         else if (streq(d->result, "timeout"))
1828                 r = -ETIME;
1829         else if (streq(d->result, "dependency"))
1830                 r = -EIO;
1831         else if (streq(d->result, "invalid"))
1832                 r = -ENOEXEC;
1833         else if (streq(d->result, "assert"))
1834                 r = -EPROTO;
1835         else if (streq(d->result, "unsupported"))
1836                 r = -EOPNOTSUPP;
1837         else if (!streq(d->result, "done") && !streq(d->result, "skipped"))
1838                 r = -EIO;
1839
1840         return r;
1841 }
1842
1843 int bus_wait_for_jobs(BusWaitForJobs *d, bool quiet) {
1844         int r = 0;
1845
1846         assert(d);
1847
1848         while (!set_isempty(d->jobs)) {
1849                 int q;
1850
1851                 q = bus_process_wait(d->bus);
1852                 if (q < 0)
1853                         return log_error_errno(q, "Failed to wait for response: %m");
1854
1855                 if (d->result) {
1856                         q = check_wait_response(d, quiet);
1857                         /* Return the first error as it is most likely to be
1858                          * meaningful. */
1859                         if (q < 0 && r == 0)
1860                                 r = q;
1861
1862                         log_debug_errno(q, "Got result %s/%m for job %s", strna(d->result), strna(d->name));
1863                 }
1864
1865                 free(d->name);
1866                 d->name = NULL;
1867
1868                 free(d->result);
1869                 d->result = NULL;
1870         }
1871
1872         return r;
1873 }
1874
1875 int bus_wait_for_jobs_add(BusWaitForJobs *d, const char *path) {
1876         int r;
1877
1878         assert(d);
1879
1880         r = set_ensure_allocated(&d->jobs, &string_hash_ops);
1881         if (r < 0)
1882                 return r;
1883
1884         return set_put_strdup(d->jobs, path);
1885 }
1886
1887 /// UNNEEDED by elogind
1888 #if 0
1889 int bus_deserialize_and_dump_unit_file_changes(sd_bus_message *m, bool quiet, UnitFileChange **changes, unsigned *n_changes) {
1890         const char *type, *path, *source;
1891         int r;
1892
1893         r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(sss)");
1894         if (r < 0)
1895                 return bus_log_parse_error(r);
1896
1897         while ((r = sd_bus_message_read(m, "(sss)", &type, &path, &source)) > 0) {
1898                 if (!quiet) {
1899                         if (streq(type, "symlink"))
1900                                 log_info("Created symlink from %s to %s.", path, source);
1901                         else
1902                                 log_info("Removed symlink %s.", path);
1903                 }
1904
1905                 r = unit_file_changes_add(changes, n_changes, streq(type, "symlink") ? UNIT_FILE_SYMLINK : UNIT_FILE_UNLINK, path, source);
1906                 if (r < 0)
1907                         return r;
1908         }
1909         if (r < 0)
1910                 return bus_log_parse_error(r);
1911
1912         r = sd_bus_message_exit_container(m);
1913         if (r < 0)
1914                 return bus_log_parse_error(r);
1915
1916         return 0;
1917 }
1918 #endif // 0
1919
1920 /**
1921  * bus_path_encode_unique() - encode unique object path
1922  * @b: bus connection or NULL
1923  * @prefix: object path prefix
1924  * @sender_id: unique-name of client, or NULL
1925  * @external_id: external ID to be chosen by client, or NULL
1926  * @ret_path: storage for encoded object path pointer
1927  *
1928  * Whenever we provide a bus API that allows clients to create and manage
1929  * server-side objects, we need to provide a unique name for these objects. If
1930  * we let the server choose the name, we suffer from a race condition: If a
1931  * client creates an object asynchronously, it cannot destroy that object until
1932  * it received the method reply. It cannot know the name of the new object,
1933  * thus, it cannot destroy it. Furthermore, it enforces a round-trip.
1934  *
1935  * Therefore, many APIs allow the client to choose the unique name for newly
1936  * created objects. There're two problems to solve, though:
1937  *    1) Object names are usually defined via dbus object paths, which are
1938  *       usually globally namespaced. Therefore, multiple clients must be able
1939  *       to choose unique object names without interference.
1940  *    2) If multiple libraries share the same bus connection, they must be
1941  *       able to choose unique object names without interference.
1942  * The first problem is solved easily by prefixing a name with the
1943  * unique-bus-name of a connection. The server side must enforce this and
1944  * reject any other name. The second problem is solved by providing unique
1945  * suffixes from within sd-bus.
1946  *
1947  * This helper allows clients to create unique object-paths. It uses the
1948  * template '/prefix/sender_id/external_id' and returns the new path in
1949  * @ret_path (must be freed by the caller).
1950  * If @sender_id is NULL, the unique-name of @b is used. If @external_id is
1951  * NULL, this function allocates a unique suffix via @b (by requesting a new
1952  * cookie). If both @sender_id and @external_id are given, @b can be passed as
1953  * NULL.
1954  *
1955  * Returns: 0 on success, negative error code on failure.
1956  */
1957 int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id, const char *external_id, char **ret_path) {
1958         _cleanup_free_ char *sender_label = NULL, *external_label = NULL;
1959         char external_buf[DECIMAL_STR_MAX(uint64_t)], *p;
1960         int r;
1961
1962         assert_return(b || (sender_id && external_id), -EINVAL);
1963         assert_return(object_path_is_valid(prefix), -EINVAL);
1964         assert_return(ret_path, -EINVAL);
1965
1966         if (!sender_id) {
1967                 r = sd_bus_get_unique_name(b, &sender_id);
1968                 if (r < 0)
1969                         return r;
1970         }
1971
1972         if (!external_id) {
1973                 xsprintf(external_buf, "%"PRIu64, ++b->cookie);
1974                 external_id = external_buf;
1975         }
1976
1977         sender_label = bus_label_escape(sender_id);
1978         if (!sender_label)
1979                 return -ENOMEM;
1980
1981         external_label = bus_label_escape(external_id);
1982         if (!external_label)
1983                 return -ENOMEM;
1984
1985         p = strjoin(prefix, "/", sender_label, "/", external_label, NULL);
1986         if (!p)
1987                 return -ENOMEM;
1988
1989         *ret_path = p;
1990         return 0;
1991 }
1992
1993 /**
1994  * bus_path_decode_unique() - decode unique object path
1995  * @path: object path to decode
1996  * @prefix: object path prefix
1997  * @ret_sender: output parameter for sender-id label
1998  * @ret_external: output parameter for external-id label
1999  *
2000  * This does the reverse of bus_path_encode_unique() (see its description for
2001  * details). Both trailing labels, sender-id and external-id, are unescaped and
2002  * returned in the given output parameters (the caller must free them).
2003  *
2004  * Note that this function returns 0 if the path does not match the template
2005  * (see bus_path_encode_unique()), 1 if it matched.
2006  *
2007  * Returns: Negative error code on failure, 0 if the given object path does not
2008  *          match the template (return parameters are set to NULL), 1 if it was
2009  *          parsed successfully (return parameters contain allocated labels).
2010  */
2011 int bus_path_decode_unique(const char *path, const char *prefix, char **ret_sender, char **ret_external) {
2012         const char *p, *q;
2013         char *sender, *external;
2014
2015         assert(object_path_is_valid(path));
2016         assert(object_path_is_valid(prefix));
2017         assert(ret_sender);
2018         assert(ret_external);
2019
2020         p = object_path_startswith(path, prefix);
2021         if (!p) {
2022                 *ret_sender = NULL;
2023                 *ret_external = NULL;
2024                 return 0;
2025         }
2026
2027         q = strchr(p, '/');
2028         if (!q) {
2029                 *ret_sender = NULL;
2030                 *ret_external = NULL;
2031                 return 0;
2032         }
2033
2034         sender = bus_label_unescape_n(p, q - p);
2035         external = bus_label_unescape(q + 1);
2036         if (!sender || !external) {
2037                 free(sender);
2038                 free(external);
2039                 return -ENOMEM;
2040         }
2041
2042         *ret_sender = sender;
2043         *ret_external = external;
2044         return 1;
2045 }
2046
2047 bool is_kdbus_wanted(void) {
2048         _cleanup_free_ char *value = NULL;
2049 #ifdef ENABLE_KDBUS
2050         const bool configured = true;
2051 #else
2052         const bool configured = false;
2053 #endif
2054
2055         int r;
2056
2057         if (get_proc_cmdline_key("kdbus", NULL) > 0)
2058                 return true;
2059
2060         r = get_proc_cmdline_key("kdbus=", &value);
2061         if (r <= 0)
2062                 return configured;
2063
2064         return parse_boolean(value) == 1;
2065 }
2066
2067 bool is_kdbus_available(void) {
2068         _cleanup_close_ int fd = -1;
2069         struct kdbus_cmd cmd = { .size = sizeof(cmd), .flags = KDBUS_FLAG_NEGOTIATE };
2070
2071         if (!is_kdbus_wanted())
2072                 return false;
2073
2074         fd = open("/sys/fs/kdbus/control", O_RDWR | O_CLOEXEC | O_NONBLOCK | O_NOCTTY);
2075         if (fd < 0)
2076                 return false;
2077
2078         return ioctl(fd, KDBUS_CMD_BUS_MAKE, &cmd) >= 0;
2079 }