Hello,
I want to bring the system to suspend from a C user application.
I’m successful in this way, that I defined this policy in polkit
polkit.addRule(function(action, subject) {
if (subject.isInGroup("user") &&
((action.id == "org.freedesktop.login1.suspend") ||
(action.id == "org.freedesktop.login1.suspend-multiple-sessions") ||
(action.id == "org.freedesktop.login1.reboot") ||
(action.id == "org.freedesktop.login1.reboot-multiple-sessions")
(action.id == "org.freedesktop.login1.power-off") ||
(action.id == "org.freedesktop.login1.power-off-multiple-sessions")))
{
return polkit.Result.YES;
}
});
in /etc/polkit-1/rules.d/00-power.rules. Therefore the unprivileged ‘user’ can call
$ systemctl suspend
to suspend the system.
The second step was to use the system sd-bus API in my C application:
sd_bus_error error = SD_BUS_ERROR_NULL;
sd_bus_message* m = nullptr;
sd_bus* bus = nullptr;
if (sd_bus_open_system(&bus) < 0)
{
perror("failed to connect to system bus");
}
else if (sd_bus_call_method(
bus,
"org.freedesktop.login1",
"/org/freedesktop/login1",
"org.freedesktop.login1.Manager",
"Suspend",
&error,
&m,
"b",
"true"
) < 0)
{
perror("failed to issue method call: %s", error.message);
}
else
{
// wait, as long as systemd-suspend.servie is running
// but how?
}
sd_bus_error_free(&error);
sd_bus_message_unref(m);
sd_bus_unref(bus);
So far so good.
My problem is the last ‘else’. Since the systemd-suspend.service is called asynchronous, I have to wait as long as the service is running. But I don’t know how to get this information from the sd-bus.
On the command line I can call
$ systemctl is-active systemd-suspend.service
but in the sd-bus I didn’t find any object-path, interface or method to get this information.
Can somebody give me a hint? Or is there a better, easier way to achieve my goal?
Best regards,
Markus