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