1 #include <sdbusplus/async.hpp>
2 
3 #include <iostream>
4 #include <string>
5 #include <variant>
6 #include <vector>
7 
8 auto startup(sdbusplus::async::context& ctx) -> sdbusplus::async::task<>
9 {
10     // Create a proxy to the systemd manager object.
11     constexpr auto systemd = sdbusplus::async::proxy()
12                                  .service("org.freedesktop.systemd1")
13                                  .path("/org/freedesktop/systemd1")
14                                  .interface("org.freedesktop.systemd1.Manager");
15 
16     // Call ListUnitFiles method.
17     using ret_type = std::vector<std::tuple<std::string, std::string>>;
18     for (auto& [file, status] :
19          co_await systemd.call<ret_type>(ctx, "ListUnitFiles"))
20     {
21         std::cout << file << " " << status << std::endl;
22     }
23 
24     // Get the Architecture property.
25     std::cout << co_await systemd.get_property<std::string>(ctx, "Architecture")
26               << std::endl;
27 
28     // Get all the properties.
29     using variant_type =
30         std::variant<bool, std::string, std::vector<std::string>, uint64_t,
31                      int32_t, uint32_t, double>;
32     for (auto& [property, value] :
33          co_await systemd.get_all_properties<variant_type>(ctx))
34     {
35         std::cout
36             << property << " is "
37             << std::visit(
38                    // Convert the variant member to a string for printing.
39                    [](auto v) {
40                        if constexpr (std::is_same_v<
41                                          std::remove_cvref_t<decltype(v)>,
42                                          std::vector<std::string>>)
43                        {
44                            return std::string{"Array"};
45                        }
46                        else if constexpr (std::is_same_v<
47                                               std::remove_cvref_t<decltype(v)>,
48                                               std::string>)
49                        {
50                            return v;
51                        }
52                        else
53                        {
54                            return std::to_string(v);
55                        }
56                    },
57                    value)
58             << std::endl;
59     }
60 
61     // Try to set the Architecture property (which won't work).
62     try
63     {
64         co_await systemd.set_property(ctx, "Architecture", "arm64");
65     }
66     catch (const std::exception& e)
67     {
68         std::cout << "Caught exception because you cannot set Architecture: "
69                   << e.what() << std::endl;
70     }
71 
72     // Create a match for the NameOwnerChanged signal.
73     namespace rules = sdbusplus::bus::match::rules;
74     auto match = sdbusplus::async::match(ctx, rules::nameOwnerChanged());
75 
76     // Listen for the signal 4 times...
77     for (size_t i = 0; i < 4; ++i)
78     {
79         auto [service, old_name, new_name] =
80             co_await match.next<std::string, std::string, std::string>();
81 
82         if (!new_name.empty())
83         {
84             std::cout << new_name << " owns " << service << std::endl;
85         }
86         else
87         {
88             std::cout << service << " released" << std::endl;
89         }
90     };
91 
92     // We are all done, so shutdown the server.
93     ctx.request_stop();
94 
95     co_return;
96 }
97 
98 int main()
99 {
100     sdbusplus::async::context ctx;
101     ctx.spawn(startup(ctx));
102     ctx.run();
103 
104     return 0;
105 }
106