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