+/* ask systemd-logind, which might grant access to unprivileged users through polkit */
+static int reboot_with_logind(DBusConnection *bus, enum action a) {
+#ifdef HAVE_LOGIND
+ const char *method;
+ DBusMessage *m = NULL, *reply = NULL;
+ DBusError error;
+ dbus_bool_t interactive = true;
+ int r;
+
+ dbus_error_init(&error);
+
+ switch (a) {
+
+ case ACTION_REBOOT:
+ method = "Reboot";
+ break;
+
+ case ACTION_POWEROFF:
+ method = "PowerOff";
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ m = dbus_message_new_method_call(
+ "org.freedesktop.login1",
+ "/org/freedesktop/login1",
+ "org.freedesktop.login1.Manager",
+ method);
+ if (!m) {
+ log_error("Could not allocate message.");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ if (!dbus_message_append_args(m,
+ DBUS_TYPE_BOOLEAN, &interactive,
+ DBUS_TYPE_INVALID)) {
+ log_error("Could not append arguments to message.");
+ r = -ENOMEM;
+ goto finish;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block(bus, m, -1, &error);
+ if (!reply) {
+ if (error_is_no_service(&error)) {
+ log_debug("Failed to issue method call: %s", bus_error_message(&error));
+ r = -ENOENT;
+ goto finish;
+ }
+
+ if (dbus_error_has_name(&error, DBUS_ERROR_ACCESS_DENIED)) {
+ log_debug("Failed to issue method call: %s", bus_error_message(&error));
+ r = -EACCES;
+ goto finish;
+ }
+
+ log_info("Failed to issue method call: %s", bus_error_message(&error));
+ r = -EIO;
+ goto finish;
+ }
+
+ r = 0;
+
+finish:
+ if (m)
+ dbus_message_unref(m);
+
+ if (reply)
+ dbus_message_unref(reply);
+
+ dbus_error_free(&error);
+
+ return r;
+#else
+ return -ENOSYS;
+#endif
+}
+