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