1 /* SPDX-License-Identifier: CC0-1.0 */
2 
3 #include <errno.h>
4 #include <stdbool.h>
5 #include <stddef.h>
6 #include <stdlib.h>
7 #include <stdio.h>
8 #include <systemd/sd-bus.h>
9 
10 #define _cleanup_(f) __attribute__((cleanup(f)))
11 
12 #define check(x) ({                             \
13   int r = (x);                                  \
14   errno = r < 0 ? -r : 0;                       \
15   printf(#x ": %m\n");                          \
16   if (r < 0)                                    \
17     return EXIT_FAILURE;                        \
18   })
19 
20 typedef struct object {
21   char *name;
22   uint32_t number;
23 } object;
24 
method(sd_bus_message * m,void * userdata,sd_bus_error * error)25 static int method(sd_bus_message *m, void *userdata, sd_bus_error *error) {
26   printf("Got called with userdata=%p\n", userdata);
27 
28   if (sd_bus_message_is_method_call(m,
29                                     "org.freedesktop.systemd.VtableExample",
30                                     "Method4"))
31     return 1;
32 
33   const char *string;
34   check(sd_bus_message_read(m, "s", &string));
35   check(sd_bus_reply_method_return(m, "s", string));
36 
37   return 1;
38 }
39 
40 static const sd_bus_vtable vtable[] = {
41         SD_BUS_VTABLE_START(0),
42         SD_BUS_METHOD(
43             "Method1", "s", "s", method, 0),
44         SD_BUS_METHOD_WITH_NAMES_OFFSET(
45             "Method2",
46             "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
47             "s", SD_BUS_PARAM(returnstring),
48             method, offsetof(object, number),
49             SD_BUS_VTABLE_DEPRECATED),
50         SD_BUS_METHOD_WITH_ARGS_OFFSET(
51             "Method3",
52             SD_BUS_ARGS("s", string, "o", path),
53             SD_BUS_RESULT("s", returnstring),
54             method, offsetof(object, number),
55             SD_BUS_VTABLE_UNPRIVILEGED),
56         SD_BUS_METHOD_WITH_ARGS(
57             "Method4",
58             SD_BUS_NO_ARGS,
59             SD_BUS_NO_RESULT,
60             method,
61             SD_BUS_VTABLE_UNPRIVILEGED),
62         SD_BUS_SIGNAL(
63             "Signal1",
64             "so",
65             0),
66         SD_BUS_SIGNAL_WITH_NAMES(
67             "Signal2",
68             "so", SD_BUS_PARAM(string) SD_BUS_PARAM(path),
69             0),
70         SD_BUS_SIGNAL_WITH_ARGS(
71             "Signal3",
72             SD_BUS_ARGS("s", string, "o", path),
73             0),
74         SD_BUS_WRITABLE_PROPERTY(
75             "AutomaticStringProperty", "s", NULL, NULL,
76             offsetof(object, name),
77             SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE),
78         SD_BUS_WRITABLE_PROPERTY(
79             "AutomaticIntegerProperty", "u", NULL, NULL,
80             offsetof(object, number),
81             SD_BUS_VTABLE_PROPERTY_EMITS_INVALIDATION),
82         SD_BUS_VTABLE_END
83 };
84 
main(int argc,char ** argv)85 int main(int argc, char **argv) {
86   _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL;
87 
88   sd_bus_default(&bus);
89 
90   object object = { .number = 666 };
91   check((object.name = strdup("name")) != NULL);
92 
93   check(sd_bus_add_object_vtable(bus, NULL,
94                                  "/org/freedesktop/systemd/VtableExample",
95                                  "org.freedesktop.systemd.VtableExample",
96                                  vtable,
97                                  &object));
98 
99   check(sd_bus_request_name(bus,
100                             "org.freedesktop.systemd.VtableExample",
101                             0));
102 
103   for (;;) {
104     check(sd_bus_wait(bus, UINT64_MAX));
105     check(sd_bus_process(bus, NULL));
106   }
107 
108   check(sd_bus_release_name(bus, "org.freedesktop.systemd.VtableExample"));
109   free(object.name);
110 
111   return 0;
112 }
113