]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-bus/bus-util.c
login: revert lazy session-activation on non-VT seats
[thirdparty/systemd.git] / src / libsystemd-bus / 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 "util.h"
25 #include "strv.h"
26 #include "macro.h"
27 #include "def.h"
28 #include "missing.h"
29
30 #include "sd-event.h"
31 #include "sd-bus.h"
32 #include "bus-error.h"
33 #include "bus-message.h"
34 #include "bus-util.h"
35 #include "bus-internal.h"
36
37 static int quit_callback(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
38 sd_event *e = userdata;
39
40 assert(bus);
41 assert(m);
42 assert(e);
43
44 sd_event_request_quit(e);
45 return 1;
46 }
47
48 int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) {
49 _cleanup_free_ char *match = NULL;
50 int r;
51
52 assert(e);
53 assert(bus);
54 assert(name);
55
56 r = asprintf(&match, "type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='NameLost',arg0='%s'", name);
57 if (r < 0)
58 return r;
59
60 r = sd_bus_add_match(bus, match, quit_callback, e);
61 if (r < 0)
62 return r;
63
64 r = sd_bus_release_name(bus, name);
65 if (r < 0)
66 return r;
67
68 if (r != SD_BUS_NAME_RELEASED)
69 return -EIO;
70
71 return 0;
72 }
73
74 int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t timeout) {
75 bool exiting = false;
76 int r;
77
78 assert(e);
79 assert(bus);
80 assert(name);
81
82 for (;;) {
83 r = sd_event_get_state(e);
84 if (r < 0)
85 return r;
86
87 if (r == SD_EVENT_FINISHED)
88 break;
89
90 r = sd_event_run(e, exiting ? (uint64_t) -1 : timeout);
91 if (r < 0)
92 return r;
93
94 if (r == 0 && !exiting) {
95 r = bus_async_unregister_and_quit(e, bus, name);
96 if (r < 0)
97 return r;
98
99 exiting = true;
100 }
101 }
102
103 return 0;
104 }
105
106 int bus_verify_polkit(
107 sd_bus *bus,
108 sd_bus_message *m,
109 const char *action,
110 bool interactive,
111 bool *_challenge,
112 sd_bus_error *e) {
113
114 const char *sender;
115 uid_t uid;
116 int r;
117
118 assert(bus);
119 assert(m);
120 assert(action);
121
122 sender = sd_bus_message_get_sender(m);
123 if (!sender)
124 return -EBADMSG;
125
126 r = sd_bus_get_owner_uid(bus, sender, &uid);
127 if (r < 0)
128 return r;
129
130 if (uid == 0)
131 return 1;
132
133 #ifdef ENABLE_POLKIT
134 else {
135 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
136 int authorized = false, challenge = false;
137
138 r = sd_bus_call_method(
139 bus,
140 "org.freedesktop.PolicyKit1",
141 "/org/freedesktop/PolicyKit1/Authority",
142 "org.freedesktop.PolicyKit1.Authority",
143 "CheckAuthorization",
144 e,
145 &reply,
146 "(sa{sv})sa{ss}us",
147 "system-bus-name", 1, "name", "s", sender,
148 action,
149 0,
150 interactive ? 1 : 0,
151 "");
152
153 if (r < 0) {
154 /* Treat no PK available as access denied */
155 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN)) {
156 sd_bus_error_free(e);
157 return -EACCES;
158 }
159
160 return r;
161 }
162
163 r = sd_bus_message_enter_container(reply, 'r', "bba{ss}");
164 if (r >= 0)
165 r = sd_bus_message_read(reply, "bb", &authorized, &challenge);
166
167 if (authorized)
168 return 1;
169
170 if (_challenge) {
171 *_challenge = challenge;
172 return 0;
173 }
174 }
175 #endif
176
177 return -EACCES;
178 }
179
180 #ifdef ENABLE_POLKIT
181
182 typedef struct AsyncPolkitQuery {
183 sd_bus_message *request, *reply;
184 sd_bus_message_handler_t callback;
185 void *userdata;
186 uint64_t serial;
187 Hashmap *registry;
188 } AsyncPolkitQuery;
189
190 static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) {
191
192 if (!q)
193 return;
194
195 if (q->serial > 0 && b)
196 sd_bus_call_async_cancel(b, q->serial);
197
198 if (q->registry && q->request)
199 hashmap_remove(q->registry, q->request);
200
201 sd_bus_message_unref(q->request);
202 sd_bus_message_unref(q->reply);
203
204 free(q);
205 }
206
207 static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) {
208 _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL;
209 AsyncPolkitQuery *q = userdata;
210 int r;
211
212 assert(bus);
213 assert(reply);
214 assert(q);
215
216 q->reply = sd_bus_message_ref(reply);
217 q->serial = 0;
218
219 r = sd_bus_message_rewind(q->request, true);
220 if (r < 0) {
221 r = sd_bus_reply_method_errno(q->request, r, NULL);
222 goto finish;
223 }
224
225 r = q->callback(bus, q->request, q->userdata, &error_buffer);
226 r = bus_maybe_reply_error(q->request, r, &error_buffer);
227
228 finish:
229 async_polkit_query_free(bus, q);
230 return r;
231 }
232
233 #endif
234
235 int bus_verify_polkit_async(
236 sd_bus *bus,
237 Hashmap **registry,
238 sd_bus_message *m,
239 const char *action,
240 bool interactive,
241 sd_bus_error *error,
242 sd_bus_message_handler_t callback,
243 void *userdata) {
244
245 #ifdef ENABLE_POLKIT
246 _cleanup_bus_message_unref_ sd_bus_message *pk = NULL;
247 AsyncPolkitQuery *q;
248 #endif
249 const char *sender;
250 uid_t uid;
251 int r;
252
253 assert(bus);
254 assert(registry);
255 assert(m);
256 assert(action);
257
258 #ifdef ENABLE_POLKIT
259 q = hashmap_get(*registry, m);
260 if (q) {
261 int authorized, challenge;
262
263 /* This is the second invocation of this function, and
264 * there's already a response from polkit, let's
265 * process it */
266 assert(q->reply);
267
268 if (sd_bus_message_is_method_error(q->reply, NULL)) {
269 const sd_bus_error *e;
270
271 /* Copy error from polkit reply */
272 e = sd_bus_message_get_error(q->reply);
273 sd_bus_error_copy(error, e);
274
275 /* Treat no PK available as access denied */
276 if (sd_bus_error_has_name(e, SD_BUS_ERROR_SERVICE_UNKNOWN))
277 return -EACCES;
278
279 return sd_bus_error_get_errno(e);
280 }
281
282 r = sd_bus_message_enter_container(q->reply, 'r', "bba{ss}");
283 if (r >= 0)
284 r = sd_bus_message_read(q->reply, "bb", &authorized, &challenge);
285
286 if (r < 0)
287 return r;
288
289 if (authorized)
290 return 1;
291
292 return -EACCES;
293 }
294 #endif
295
296 sender = sd_bus_message_get_sender(m);
297 if (!sender)
298 return -EBADMSG;
299
300 r = sd_bus_get_owner_uid(bus, sender, &uid);
301 if (r < 0)
302 return r;
303
304 if (uid == 0)
305 return 1;
306 #ifdef ENABLE_POLKIT
307
308 r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func);
309 if (r < 0)
310 return r;
311
312 r = sd_bus_message_new_method_call(
313 bus,
314 "org.freedesktop.PolicyKit1",
315 "/org/freedesktop/PolicyKit1/Authority",
316 "org.freedesktop.PolicyKit1.Authority",
317 "CheckAuthorization",
318 &pk);
319 if (r < 0)
320 return r;
321
322 r = sd_bus_message_append(
323 pk,
324 "(sa{sv})sa{ss}us",
325 "system-bus-name", 1, "name", "s", sender,
326 action,
327 0,
328 interactive ? 1 : 0,
329 NULL);
330 if (r < 0)
331 return r;
332
333 q = new0(AsyncPolkitQuery, 1);
334 if (!q)
335 return -ENOMEM;
336
337 q->request = sd_bus_message_ref(m);
338 q->callback = callback;
339 q->userdata = userdata;
340
341 r = hashmap_put(*registry, m, q);
342 if (r < 0) {
343 async_polkit_query_free(bus, q);
344 return r;
345 }
346
347 q->registry = *registry;
348
349 r = sd_bus_call_async(bus, pk, async_polkit_callback, q, 0, &q->serial);
350 if (r < 0) {
351 async_polkit_query_free(bus, q);
352 return r;
353 }
354
355 return 0;
356 #endif
357
358 return -EACCES;
359 }
360
361 void bus_verify_polkit_async_registry_free(sd_bus *bus, Hashmap *registry) {
362 #ifdef ENABLE_POLKIT
363 AsyncPolkitQuery *q;
364
365 while ((q = hashmap_steal_first(registry)))
366 async_polkit_query_free(bus, q);
367
368 hashmap_free(registry);
369 #endif
370 }
371
372 int bus_check_peercred(sd_bus *c) {
373 struct ucred ucred;
374 socklen_t l;
375 int fd;
376
377 assert(c);
378
379 fd = sd_bus_get_fd(c);
380 if (fd < 0)
381 return fd;
382
383 l = sizeof(struct ucred);
384 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l) < 0)
385 return -errno;
386
387 if (l != sizeof(struct ucred))
388 return -E2BIG;
389
390 if (ucred.uid != 0 && ucred.uid != geteuid())
391 return -EPERM;
392
393 return 1;
394 }
395
396 int bus_open_system_systemd(sd_bus **_bus) {
397 _cleanup_bus_unref_ sd_bus *bus = NULL;
398 int r;
399
400 assert(_bus);
401
402 if (geteuid() != 0)
403 return sd_bus_open_system(_bus);
404
405 /* If we are root, then let's talk directly to the system
406 * instance, instead of going via the bus */
407
408 r = sd_bus_new(&bus);
409 if (r < 0)
410 return r;
411
412 r = sd_bus_set_address(bus, "unix:path=/run/systemd/private");
413 if (r < 0)
414 return r;
415
416 r = sd_bus_start(bus);
417 if (r < 0)
418 return r;
419
420 r = bus_check_peercred(bus);
421 if (r < 0)
422 return r;
423
424 *_bus = bus;
425 bus = NULL;
426
427 return 0;
428 }
429
430 int bus_open_user_systemd(sd_bus **_bus) {
431 _cleanup_bus_unref_ sd_bus *bus = NULL;
432 _cleanup_free_ char *p = NULL;
433 const char *e;
434 int r;
435
436 /* If we are supposed to talk to the instance, try via
437 * XDG_RUNTIME_DIR first, then fallback to normal bus
438 * access */
439
440 assert(_bus);
441
442 e = secure_getenv("XDG_RUNTIME_DIR");
443 if (e) {
444 if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0)
445 return -ENOMEM;
446 }
447
448 r = sd_bus_new(&bus);
449 if (r < 0)
450 return r;
451
452 r = sd_bus_set_address(bus, p);
453 if (r < 0)
454 return r;
455
456 r = sd_bus_start(bus);
457 if (r < 0)
458 return r;
459
460 r = bus_check_peercred(bus);
461 if (r < 0)
462 return r;
463
464 *_bus = bus;
465 bus = NULL;
466
467 return 0;
468 }
469
470 int bus_print_property(const char *name, sd_bus_message *property, bool all) {
471 char type;
472 const char *contents;
473 int r;
474
475 assert(name);
476 assert(property);
477
478 r = sd_bus_message_peek_type(property, &type, &contents);
479 if (r < 0)
480 return r;
481
482 switch (type) {
483
484 case SD_BUS_TYPE_STRING: {
485 const char *s;
486
487 r = sd_bus_message_read_basic(property, type, &s);
488 if (r < 0)
489 return r;
490
491 if (all || !isempty(s))
492 printf("%s=%s\n", name, s);
493
494 return 1;
495 }
496
497 case SD_BUS_TYPE_BOOLEAN: {
498 bool b;
499
500 r = sd_bus_message_read_basic(property, type, &b);
501 if (r < 0)
502 return r;
503
504 printf("%s=%s\n", name, yes_no(b));
505
506 return 1;
507 }
508
509 case SD_BUS_TYPE_UINT64: {
510 uint64_t u;
511
512 r = sd_bus_message_read_basic(property, type, &u);
513 if (r < 0)
514 return r;
515
516 /* Yes, heuristics! But we can change this check
517 * should it turn out to not be sufficient */
518
519 if (endswith(name, "Timestamp")) {
520 char timestamp[FORMAT_TIMESTAMP_MAX], *t;
521
522 t = format_timestamp(timestamp, sizeof(timestamp), u);
523 if (t || all)
524 printf("%s=%s\n", name, strempty(t));
525
526 } else if (strstr(name, "USec")) {
527 char timespan[FORMAT_TIMESPAN_MAX];
528
529 printf("%s=%s\n", name, format_timespan(timespan, sizeof(timespan), u, 0));
530 } else
531 printf("%s=%llu\n", name, (unsigned long long) u);
532
533 return 1;
534 }
535
536 case SD_BUS_TYPE_UINT32: {
537 uint32_t u;
538
539 r = sd_bus_message_read_basic(property, type, &u);
540 if (r < 0)
541 return r;
542
543 if (strstr(name, "UMask") || strstr(name, "Mode"))
544 printf("%s=%04o\n", name, u);
545 else
546 printf("%s=%u\n", name, (unsigned) u);
547
548 return 1;
549 }
550
551 case SD_BUS_TYPE_INT32: {
552 int32_t i;
553
554 r = sd_bus_message_read_basic(property, type, &i);
555 if (r < 0)
556 return r;
557
558 printf("%s=%i\n", name, (int) i);
559 return 1;
560 }
561
562 case SD_BUS_TYPE_DOUBLE: {
563 double d;
564
565 r = sd_bus_message_read_basic(property, type, &d);
566 if (r < 0)
567 return r;
568
569 printf("%s=%g\n", name, d);
570 return 1;
571 }
572
573 case SD_BUS_TYPE_ARRAY:
574 if (streq(contents, "s")) {
575 bool first = true;
576 const char *str;
577
578 r = sd_bus_message_enter_container(property, SD_BUS_TYPE_ARRAY, contents);
579 if (r < 0)
580 return r;
581
582 while((r = sd_bus_message_read_basic(property, SD_BUS_TYPE_STRING, &str)) > 0) {
583 if (first)
584 printf("%s=", name);
585
586 printf("%s%s", first ? "" : " ", str);
587
588 first = false;
589 }
590 if (r < 0)
591 return r;
592
593 if (first && all)
594 printf("%s=", name);
595 if (!first || all)
596 puts("");
597
598 r = sd_bus_message_exit_container(property);
599 if (r < 0)
600 return r;
601
602 return 1;
603
604 } else if (streq(contents, "y")) {
605 const uint8_t *u;
606 size_t n;
607
608 r = sd_bus_message_read_array(property, SD_BUS_TYPE_BYTE, (const void**) &u, &n);
609 if (r < 0)
610 return r;
611
612 if (all || n > 0) {
613 unsigned int i;
614
615 printf("%s=", name);
616
617 for (i = 0; i < n; i++)
618 printf("%02x", u[i]);
619
620 puts("");
621 }
622
623 return 1;
624
625 } else if (streq(contents, "u")) {
626 uint32_t *u;
627 size_t n;
628
629 r = sd_bus_message_read_array(property, SD_BUS_TYPE_UINT32, (const void**) &u, &n);
630 if (r < 0)
631 return r;
632
633 if (all || n > 0) {
634 unsigned int i;
635
636 printf("%s=", name);
637
638 for (i = 0; i < n; i++)
639 printf("%08x", u[i]);
640
641 puts("");
642 }
643
644 return 1;
645 }
646
647 break;
648 }
649
650 return 0;
651 }
652
653 int bus_print_all_properties(sd_bus *bus, const char *dest, const char *path, char **filter, bool all) {
654 _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
655 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
656 int r;
657
658 assert(bus);
659 assert(path);
660
661 r = sd_bus_call_method(bus,
662 dest,
663 path,
664 "org.freedesktop.DBus.Properties",
665 "GetAll",
666 &error,
667 &reply,
668 "s", "");
669 if (r < 0)
670 return r;
671
672 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_ARRAY, "{sv}");
673 if (r < 0)
674 return r;
675
676 while ((r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
677 const char *name;
678 const char *contents;
679
680 r = sd_bus_message_read_basic(reply, SD_BUS_TYPE_STRING, &name);
681 if (r < 0)
682 return r;
683
684 if (!filter || strv_find(filter, name)) {
685 r = sd_bus_message_peek_type(reply, NULL, &contents);
686 if (r < 0)
687 return r;
688
689 r = sd_bus_message_enter_container(reply, SD_BUS_TYPE_VARIANT, contents);
690 if (r < 0)
691 return r;
692
693 r = bus_print_property(name, reply, all);
694 if (r < 0)
695 return r;
696 if (r == 0) {
697 if (all)
698 printf("%s=[unprintable]\n", name);
699 /* skip what we didn't read */
700 r = sd_bus_message_skip(reply, contents);
701 if (r < 0)
702 return r;
703 }
704
705 r = sd_bus_message_exit_container(reply);
706 if (r < 0)
707 return r;
708 } else {
709 r = sd_bus_message_skip(reply, "v");
710 if (r < 0)
711 return r;
712 }
713
714 r = sd_bus_message_exit_container(reply);
715 if (r < 0)
716 return r;
717 }
718 if (r < 0)
719 return r;
720
721 r = sd_bus_message_exit_container(reply);
722 if (r < 0)
723 return r;
724
725 return 0;
726 }
727
728 int bus_map_id128(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
729 sd_id128_t *p = userdata;
730 const void *v;
731 size_t n;
732 int r;
733
734 r = sd_bus_message_read_array(m, SD_BUS_TYPE_BYTE, &v, &n);
735 if (r < 0)
736 return r;
737
738 if (n == 0)
739 *p = SD_ID128_NULL;
740 else if (n == 16)
741 memcpy((*p).bytes, v, n);
742 else
743 return -EINVAL;
744
745 return 0;
746 }
747
748 static int map_basic(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
749 char type;
750 int r;
751
752 r = sd_bus_message_peek_type(m, &type, NULL);
753 if (r < 0)
754 return r;
755
756 switch (type) {
757 case SD_BUS_TYPE_STRING: {
758 const char *s;
759 char *str;
760 char **p = userdata;
761
762 r = sd_bus_message_read_basic(m, type, &s);
763 if (r < 0)
764 break;
765
766 if (isempty(s))
767 break;
768
769 str = strdup(s);
770 if (!str) {
771 r = -ENOMEM;
772 break;
773 }
774 free(*p);
775 *p = str;
776
777 break;
778 }
779
780 case SD_BUS_TYPE_ARRAY: {
781 _cleanup_strv_free_ char **l = NULL;
782 char ***p = userdata;
783
784 r = bus_message_read_strv_extend(m, &l);
785 if (r < 0)
786 break;
787
788 strv_free(*p);
789 *p = l;
790 l = NULL;
791
792 break;
793 }
794
795 case SD_BUS_TYPE_BOOLEAN: {
796 unsigned b;
797 bool *p = userdata;
798
799 r = sd_bus_message_read_basic(m, type, &b);
800 if (r < 0)
801 break;
802
803 *p = b;
804
805 break;
806 }
807
808 case SD_BUS_TYPE_UINT32: {
809 uint64_t u;
810 uint32_t *p = userdata;
811
812 r = sd_bus_message_read_basic(m, type, &u);
813 if (r < 0)
814 break;
815
816 *p = u;
817
818 break;
819 }
820
821 case SD_BUS_TYPE_UINT64: {
822 uint64_t t;
823 uint64_t *p = userdata;
824
825 r = sd_bus_message_read_basic(m, type, &t);
826 if (r < 0)
827 break;
828
829 *p = t;
830
831 break;
832 }
833
834 default:
835 break;
836 }
837
838 return r;
839 }
840
841 int bus_map_all_properties(sd_bus *bus,
842 const char *destination,
843 const char *path,
844 const struct bus_properties_map *map,
845 void *userdata) {
846 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
847 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
848 int r;
849
850 assert(bus);
851 assert(destination);
852 assert(path);
853 assert(map);
854
855 r = sd_bus_call_method( bus,
856 destination,
857 path,
858 "org.freedesktop.DBus.Properties",
859 "GetAll",
860 &error,
861 &m,
862 "s", "");
863 if (r < 0)
864 return r;
865
866 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{sv}");
867 if (r < 0)
868 return r;
869
870 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "sv")) > 0) {
871 const struct bus_properties_map *prop;
872 const char *member;
873 const char *contents;
874 void *v;
875 unsigned i;
876
877 r = sd_bus_message_read_basic(m, SD_BUS_TYPE_STRING, &member);
878 if (r < 0)
879 return r;
880
881 for (i = 0, prop = NULL; map[i].member; i++)
882 if (streq(map[i].member, member)) {
883 prop = &map[i];
884 break;
885 }
886
887 if (prop) {
888 r = sd_bus_message_peek_type(m, NULL, &contents);
889 if (r < 0)
890 return r;
891
892 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_VARIANT, contents);
893 if (r < 0)
894 return r;
895
896 v = (uint8_t *)userdata + prop->offset;
897 if (map[i].set)
898 r = prop->set(bus, member, m, &error, v);
899 else
900 r = map_basic(bus, member, m, &error, v);
901
902 r = sd_bus_message_exit_container(m);
903 if (r < 0)
904 return r;
905 } else {
906 r = sd_bus_message_skip(m, "v");
907 if (r < 0)
908 return r;
909 }
910
911 r = sd_bus_message_exit_container(m);
912 if (r < 0)
913 return r;
914 }
915
916 return r;
917 }
918
919 int bus_open_transport(BusTransport transport, const char *host, bool user, sd_bus **bus) {
920 int r;
921
922 assert(transport >= 0);
923 assert(transport < _BUS_TRANSPORT_MAX);
924 assert(bus);
925
926 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
927 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
928
929 switch (transport) {
930
931 case BUS_TRANSPORT_LOCAL:
932 if (user)
933 r = sd_bus_default_user(bus);
934 else
935 r = sd_bus_default_system(bus);
936
937 break;
938
939 case BUS_TRANSPORT_REMOTE:
940 r = sd_bus_open_system_remote(host, bus);
941 break;
942
943 case BUS_TRANSPORT_CONTAINER:
944 r = sd_bus_open_system_container(host, bus);
945 break;
946
947 default:
948 assert_not_reached("Hmm, unknown transport type.");
949 }
950
951 return r;
952 }
953
954 int bus_open_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus) {
955 int r;
956
957 assert(transport >= 0);
958 assert(transport < _BUS_TRANSPORT_MAX);
959 assert(bus);
960
961 assert_return((transport == BUS_TRANSPORT_LOCAL) == !host, -EINVAL);
962 assert_return(transport == BUS_TRANSPORT_LOCAL || !user, -ENOTSUP);
963
964 switch (transport) {
965
966 case BUS_TRANSPORT_LOCAL:
967 if (user)
968 r = bus_open_user_systemd(bus);
969 else
970 r = bus_open_system_systemd(bus);
971
972 break;
973
974 case BUS_TRANSPORT_REMOTE:
975 r = sd_bus_open_system_remote(host, bus);
976 break;
977
978 case BUS_TRANSPORT_CONTAINER:
979 r = sd_bus_open_system_container(host, bus);
980 break;
981
982 default:
983 assert_not_reached("Hmm, unknown transport type.");
984 }
985
986 return r;
987 }
988
989 int bus_property_get_tristate(
990 sd_bus *bus,
991 const char *path,
992 const char *interface,
993 const char *property,
994 sd_bus_message *reply,
995 void *userdata,
996 sd_bus_error *error) {
997
998 int *tristate = userdata;
999
1000 return sd_bus_message_append(reply, "b", *tristate > 0);
1001 }
1002
1003 int bus_property_get_bool(
1004 sd_bus *bus,
1005 const char *path,
1006 const char *interface,
1007 const char *property,
1008 sd_bus_message *reply,
1009 void *userdata,
1010 sd_bus_error *error) {
1011
1012 int b = *(bool*) userdata;
1013
1014 return sd_bus_message_append_basic(reply, 'b', &b);
1015 }
1016
1017 #if __SIZEOF_SIZE_T__ != 8
1018 int bus_property_get_size(
1019 sd_bus *bus,
1020 const char *path,
1021 const char *interface,
1022 const char *property,
1023 sd_bus_message *reply,
1024 void *userdata,
1025 sd_bus_error *error) {
1026
1027 uint64_t sz = *(size_t*) userdata;
1028
1029 return sd_bus_message_append_basic(reply, 't', &sz);
1030 }
1031 #endif
1032
1033 #if __SIZEOF_LONG__ != 8
1034 int bus_property_get_long(
1035 sd_bus *bus,
1036 const char *path,
1037 const char *interface,
1038 const char *property,
1039 sd_bus_message *reply,
1040 void *userdata,
1041 sd_bus_error *error) {
1042
1043 int64_t l = *(long*) userdata;
1044
1045 return sd_bus_message_append_basic(reply, 'x', &l);
1046 }
1047
1048 int bus_property_get_ulong(
1049 sd_bus *bus,
1050 const char *path,
1051 const char *interface,
1052 const char *property,
1053 sd_bus_message *reply,
1054 void *userdata,
1055 sd_bus_error *error) {
1056
1057 uint64_t ul = *(unsigned long*) userdata;
1058
1059 return sd_bus_message_append_basic(reply, 't', &ul);
1060 }
1061 #endif
1062
1063 int bus_log_parse_error(int r) {
1064 log_error("Failed to parse message: %s", strerror(-r));
1065 return r;
1066 }
1067
1068 int bus_log_create_error(int r) {
1069 log_error("Failed to create message: %s", strerror(-r));
1070 return r;
1071 }
1072
1073 int bus_parse_unit_info(sd_bus_message *message, UnitInfo *u) {
1074 assert(message);
1075 assert(u);
1076
1077 return sd_bus_message_read(
1078 message,
1079 "(ssssssouso)",
1080 &u->id,
1081 &u->description,
1082 &u->load_state,
1083 &u->active_state,
1084 &u->sub_state,
1085 &u->following,
1086 &u->unit_path,
1087 &u->job_id,
1088 &u->job_type,
1089 &u->job_path);
1090 }
1091
1092 int bus_maybe_reply_error(sd_bus_message *m, int r, sd_bus_error *error) {
1093 assert(m);
1094
1095 if (r < 0) {
1096 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1097 sd_bus_reply_method_errno(m, r, error);
1098
1099 } else if (sd_bus_error_is_set(error)) {
1100 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1101 sd_bus_reply_method_error(m, error);
1102 } else
1103 return r;
1104
1105 log_debug("Failed to process message [type=%s sender=%s path=%s interface=%s member=%s signature=%s]: %s",
1106 bus_message_type_to_string(m->header->type),
1107 strna(m->sender),
1108 strna(m->path),
1109 strna(m->interface),
1110 strna(m->member),
1111 strna(m->root_container.signature),
1112 bus_error_message(error, r));
1113
1114 return 1;
1115 }