summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac3
-rw-r--r--src/ck-manager.c46
-rw-r--r--src/ck-manager.h10
-rw-r--r--src/ck-sysdeps-freebsd.c67
-rw-r--r--src/ck-sysdeps-gnu.c14
-rw-r--r--src/ck-sysdeps-linux.c37
-rw-r--r--src/ck-sysdeps-openbsd.c12
-rw-r--r--src/ck-sysdeps-solaris.c14
-rw-r--r--src/ck-sysdeps.h3
-rw-r--r--src/org.freedesktop.ConsoleKit.Manager.xml122
10 files changed, 322 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac
index 743e3a9..45ba83c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -50,7 +50,8 @@ POLKIT_REQUIRED_VERSION=0.92
AC_CHECK_HEADERS([unistd.h paths.h sys/vt.h sys/consio.h fcntl.h limits.h \
sys/ioctl.h sys/param.h sys/socket.h syslog.h kvm.h \
- sys/sysctl.h sys/user.h poll.h])
+ sys/sysctl.h sys/user.h sys/wait.h sys/resource.h \
+ poll.h])
AC_CHECK_FUNCS([getpeerucred getpeereid memset setenv strchr strdup \
strerror strrchr strspn strstr strtol strtoul uname])
diff --git a/src/ck-manager.c b/src/ck-manager.c
index eff383c..6d80304 100644
--- a/src/ck-manager.c
+++ b/src/ck-manager.c
@@ -1355,8 +1355,8 @@ ck_manager_suspend (CkManager *manager,
}
gboolean
-ck_manager_can_suspend (CkManager *manager,
- DBusGMethodInvocation *context)
+ck_manager_auth_suspend (CkManager *manager,
+ DBusGMethodInvocation *context)
{
const char *action;
@@ -1377,6 +1377,20 @@ ck_manager_can_suspend (CkManager *manager,
return TRUE;
}
+gboolean
+ck_manager_can_suspend (CkManager *manager,
+ DBusGMethodInvocation *context)
+
+{
+ if (ck_system_can_suspend ()) {
+ dbus_g_method_return (context, TRUE);
+ } else {
+ dbus_g_method_return (context, FALSE);
+ }
+
+ return TRUE;
+}
+
static void
do_hibernate (CkManager *manager,
DBusGMethodInvocation *context)
@@ -1442,8 +1456,8 @@ ck_manager_hibernate (CkManager *manager,
}
gboolean
-ck_manager_can_hibernate (CkManager *manager,
- DBusGMethodInvocation *context)
+ck_manager_auth_hibernate (CkManager *manager,
+ DBusGMethodInvocation *context)
{
const char *action;
@@ -1464,6 +1478,30 @@ ck_manager_can_hibernate (CkManager *manager,
return TRUE;
}
+gboolean
+ck_manager_can_hibernate (CkManager *manager,
+ DBusGMethodInvocation *context)
+
+{
+ if (ck_system_can_hibernate ()) {
+ dbus_g_method_return (context, TRUE);
+ } else {
+ dbus_g_method_return (context, FALSE);
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_manager_inhibit (CkManager *manager,
+ gchar *what,
+ gchar *who,
+ gchar *why,
+ DBusGMethodInvocation *context)
+{
+ return TRUE;
+}
+
static void
on_seat_active_session_changed_full (CkSeat *seat,
CkSession *old_session,
diff --git a/src/ck-manager.h b/src/ck-manager.h
index bfa2c01..d464056 100644
--- a/src/ck-manager.h
+++ b/src/ck-manager.h
@@ -97,6 +97,16 @@ gboolean ck_manager_can_suspend (CkManager *manage
DBusGMethodInvocation *context);
gboolean ck_manager_can_hibernate (CkManager *manager,
DBusGMethodInvocation *context);
+gboolean ck_manager_auth_suspend (CkManager *manager,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_auth_hibernate (CkManager *manager,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_inhibit (CkManager *manager,
+ gchar *what,
+ gchar *who,
+ gchar *why,
+ DBusGMethodInvocation *context);
+
/* Authoritative properties */
gboolean ck_manager_open_session (CkManager *manager,
DBusGMethodInvocation *context);
diff --git a/src/ck-sysdeps-freebsd.c b/src/ck-sysdeps-freebsd.c
index 1d6d5b4..07d0b36 100644
--- a/src/ck-sysdeps-freebsd.c
+++ b/src/ck-sysdeps-freebsd.c
@@ -37,7 +37,12 @@
#include <sys/sysctl.h>
#include <sys/user.h>
#include <sys/ioctl.h>
-
+#ifdef HAVE_SYS_WAIT_H
+#include <sys/wait.h>
+#endif
+#ifdef HAVE_SYS_RESOURCE_H
+#include <sys/resource.h>
+#endif
#include <sys/consio.h>
#define DEV_ENCODE(M,m) ( \
@@ -526,3 +531,63 @@ ck_get_active_console_num (int console_fd,
return ret;
}
+
+static gchar *
+get_string_sysctl (GError **err, const gchar *format, ...)
+{
+ va_list args;
+ gchar *name;
+ size_t value_len;
+ gchar *str = NULL;
+
+ g_return_val_if_fail(format != NULL, FALSE);
+
+ va_start (args, format);
+ name = g_strdup_vprintf (format, args);
+ va_end (args);
+
+ if (sysctlbyname (name, NULL, &value_len, NULL, 0) == 0) {
+ str = g_new (char, value_len + 1);
+ if (sysctlbyname (name, str, &value_len, NULL, 0) == 0) {
+ str[value_len] = 0;
+ } else {
+ g_free (str);
+ str = NULL;
+ }
+ }
+
+ if (!str)
+ g_set_error (err, 0, 0, "%s", g_strerror(errno));
+
+ g_free(name);
+ return str;
+}
+
+static gboolean
+freebsd_supports_sleep_state (const gchar *state)
+{
+ gboolean ret = FALSE;
+ gchar *sleep_states;
+
+ sleep_states = get_string_sysctl (NULL, "hw.acpi.supported_sleep_state");
+ if (sleep_states != NULL) {
+ if (strstr (sleep_states, state) != NULL)
+ ret = TRUE;
+ }
+
+ g_free (sleep_states);
+
+ return ret;
+}
+
+gboolean
+ck_system_can_suspend (void)
+{
+ return freebsd_supports_sleep_state ("S3");
+}
+
+gboolean
+ck_system_can_suspend (void)
+{
+ return freebsd_supports_sleep_state ("S4");
+}
diff --git a/src/ck-sysdeps-gnu.c b/src/ck-sysdeps-gnu.c
index 254f7ef..57fc7b7 100644
--- a/src/ck-sysdeps-gnu.c
+++ b/src/ck-sysdeps-gnu.c
@@ -400,3 +400,17 @@ ck_get_active_console_num (int console_fd,
return ret;
}
+
+gboolean
+ck_system_can_suspend (void)
+{
+ /* TODO: not implemented */
+ return FALSE;
+}
+
+gboolean
+ck_system_can_hibernate (void)
+{
+ /* TODO: not implemented */
+ return FALSE;
+}
diff --git a/src/ck-sysdeps-linux.c b/src/ck-sysdeps-linux.c
index 153f784..c3786bf 100644
--- a/src/ck-sysdeps-linux.c
+++ b/src/ck-sysdeps-linux.c
@@ -778,6 +778,43 @@ ck_get_active_console_num (int console_fd,
return ret;
}
+static gboolean
+linux_supports_sleep_state (const gchar *state)
+{
+ gboolean ret = FALSE;
+ gchar *command;
+ GError *error = NULL;
+ gint exit_status;
+
+ /* run script from pm-utils */
+ command = g_strdup_printf ("/usr/bin/pm-is-supported --%s", state);
+ g_debug ("excuting command: %s", command);
+ ret = g_spawn_command_line_sync (command, NULL, NULL, &exit_status, &error);
+ if (!ret) {
+ g_warning ("failed to run script: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+ ret = (WIFEXITED(exit_status) && (WEXITSTATUS(exit_status) == EXIT_SUCCESS));
+
+out:
+ g_free (command);
+
+ return ret;
+}
+
+gboolean
+ck_system_can_suspend (void)
+{
+ return linux_supports_sleep_state ("suspend");
+}
+
+gboolean
+ck_system_can_hibernate (void)
+{
+ return linux_supports_sleep_state ("hibernate");
+}
+
#ifdef HAVE_SYS_VT_SIGNAL
/* For the moment this is Linux only.
* Returns the vt file descriptor or < 0 on failure.
diff --git a/src/ck-sysdeps-openbsd.c b/src/ck-sysdeps-openbsd.c
index 29bb4ba..25ccc04 100644
--- a/src/ck-sysdeps-openbsd.c
+++ b/src/ck-sysdeps-openbsd.c
@@ -469,3 +469,15 @@ ck_get_active_console_num (int console_fd,
return ret;
}
+
+gboolean
+ck_system_can_suspend (void)
+{
+ return TRUE;
+}
+
+gboolean
+ck_system_can_hibernate (void)
+{
+ return TRUE;
+}
diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c
index bb37e1e..63cb6e0 100644
--- a/src/ck-sysdeps-solaris.c
+++ b/src/ck-sysdeps-solaris.c
@@ -529,3 +529,17 @@ ck_get_active_console_num (int console_fd,
return ret;
}
+
+gboolean
+ck_system_can_suspend (void)
+{
+ /* TODO: not implemented */
+ return FALSE;
+}
+
+gboolean
+ck_system_can_hibernate (void)
+{
+ /* TODO: not implemented */
+ return FALSE;
+}
diff --git a/src/ck-sysdeps.h b/src/ck-sysdeps.h
index 644d053..73c2608 100644
--- a/src/ck-sysdeps.h
+++ b/src/ck-sysdeps.h
@@ -73,6 +73,9 @@ gboolean ck_activate_console_num (int console_fd,
gboolean ck_wait_for_active_console_num (int console_fd,
guint num);
+gboolean ck_system_can_suspend (void);
+gboolean ck_system_can_hibernate (void);
+
#ifdef HAVE_SYS_VT_SIGNAL
gint ck_get_vt_signal_fd (void);
gboolean ck_wait_for_console_switch (gint sys_fd,
diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml
index ae6a90c..7070225 100644
--- a/src/org.freedesktop.ConsoleKit.Manager.xml
+++ b/src/org.freedesktop.ConsoleKit.Manager.xml
@@ -16,6 +16,11 @@
<method name="CanRestart">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="can_restart" type="b" direction="out"/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method returns whether the user is authorized to restart the computer system.</doc:para>
+ </doc:description>
+ </doc:doc>
</method>
<method name="Stop">
@@ -30,6 +35,11 @@
<method name="CanStop">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="can_stop" type="b" direction="out"/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method returns whether the user is authorized to shutdown the computer system.</doc:para>
+ </doc:description>
+ </doc:doc>
</method>
<method name="Suspend">
@@ -44,6 +54,21 @@
<method name="CanSuspend">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="can_suspend" type="b" direction="out"/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method returns whether the computer system is capable of suspending.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="AuthSuspend">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="auth_suspend" type="b" direction="out"/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method returns whether the user is authorized to suspend the computer system.</doc:para>
+ </doc:description>
+ </doc:doc>
</method>
<method name="Hibernate">
@@ -58,6 +83,103 @@
<method name="CanHibernate">
<annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
<arg name="can_hibernate" type="b" direction="out"/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method returns whether the computer system is capable of hibernating.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="AuthHibernate">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="auth_hibernate" type="b" direction="out"/>
+ <doc:doc>
+ <doc:description>
+ <doc:para>This method returns whether the user is authorized to hibernate the computer system.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </method>
+
+ <method name="Inhibit">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="what" type="s" direction="in">
+ <doc:doc>
+ <doc:summary>What is a colon-separated list of lock types. The list of lock types are: shutdown, sleep, idle, handle-power-key, handle-suspend-key, handle-hibernate-key. Example: "shutdown:idle"</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="who" type="s" direction="in">
+ <doc:doc>
+ <doc:summary>Who is a human-readable, descriptive string of who is taking the lock. Example: "Xfburn"</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="why" type="s" direction="in">
+ <doc:doc>
+ <doc:summary>Why is a human-readable, descriptive string of why the program is taking the lock. Example: "Burning a DVD, interrupting now will ruin the DVD."</doc:summary>
+ </doc:doc>
+ </arg>
+ <arg name="fd" type="h" direction="out">
+ <doc:doc>
+ <doc:description>
+ <doc:para>Returns a file descriptor that encapsulates the lock, or -1 on failure. As soon as the file descriptor is closed (and all its duplicates) the lock is automatically released. If the client dies while the lock is taken it is automatically closed and the lock is automatically released.</doc:para>
+ </doc:description>
+ </doc:doc>
+ </arg>
+ <doc:doc>
+ <doc:description>
+ <doc:para>See this simple example:
+ <doc:example language="c" title="simple example"><doc:code>
+ DBusConnection *bus_connection;
+ DBusMessage *message = NULL, *reply = NULL;
+ DBusError error;
+ gint fd = -1;
+ const char *what = "shutdown:sleep";
+ const char *who = "Xfburn";
+ const char *why = "Burning a DVD, interrupting now will ruin the DVD.";
+
+ message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit",
+ "/org/freedesktop/ConsoleKit/Manager",
+ "org.freedesktop.ConsoleKit.Manager",
+ "Inhibit");
+
+ if (!message)
+ {
+ g_warning ("Unable to call Inhibit()");
+ return fd;
+ }
+
+ if (!dbus_message_append_args (message,
+ DBUS_TYPE_STRING, &amp;what,
+ DBUS_TYPE_STRING, &amp;who,
+ DBUS_TYPE_STRING, &amp;why,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Unable to call Inhibit()");
+ dbus_message_unref (message);
+ return fd;
+ }
+
+ reply = dbus_connection_send_with_reply_and_block (bus_connection, message, -1, &amp;error);
+ if (!reply)
+ {
+ g_warning ("Unable to inhibit: %s", error.message);
+ dbus_message_unref (message);
+ return fd;
+ }
+
+ if (!dbus_message_get_args (reply, &amp;error,
+ DBUS_TYPE_UNIX_FD, &amp;fd,
+ DBUS_TYPE_INVALID))
+ {
+ g_warning ("Inhibit() reply parsing failed: %s", error.message);
+ }
+
+ dbus_message_unref (message);
+ dbus_message_unref (reply);
+ dbus_error_free (&amp;error);
+ return fd;
+ </doc:code></doc:example></doc:para>
+ </doc:description>
+ </doc:doc>
</method>
<method name="OpenSession">