diff --git a/configure.ac b/configure.ac
index 117d788..a06b0f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -81,10 +81,11 @@ AC_PATH_PROG(GLIB_GENMARSHAL, glib-genmarshal)
EXTRA_COMPILE_WARNINGS(yes)
-# Solaris requires libresolv for daemon()
+# Solaris requires libresolv and libscf for daemon()
case "$host" in
*-*-solaris*)
AC_CHECK_LIB(resolv, daemon, [CONSOLE_KIT_LIBS="$CONSOLE_KIT_LIBS -lresolv"])
+ AC_CHECK_LIB(scf, daemon, [CONSOLE_KIT_LIBS="$CONSOLE_KIT_LIBS -lscf"])
;;
esac
diff --git a/data/ConsoleKit.conf b/data/ConsoleKit.conf
index 948f95f..541227d 100644
--- a/data/ConsoleKit.conf
+++ b/data/ConsoleKit.conf
@@ -38,6 +38,12 @@
send_member="CanStop"/>
+
+
#include
+#if (defined(sun) && defined(__SVR4))
+#include
+#endif
+
#if defined HAVE_POLKIT
#include
#elif defined ENABLE_RBAC_SHUTDOWN
@@ -741,13 +745,15 @@ get_cookie_for_pid (CkManager *manager,
}
typedef void (*AuthorizedCallback) (CkManager *manager,
- DBusGMethodInvocation *context);
+ DBusGMethodInvocation *context,
+ void *arg);
typedef struct
{
CkManager *manager;
DBusGMethodInvocation *context;
AuthorizedCallback callback;
+ void *arg;
} AuthorizedCallbackData;
static void
@@ -781,7 +787,7 @@ auth_ready_callback (PolkitAuthority *authority,
g_error_free (error);
}
else if (polkit_authorization_result_get_is_authorized (result)) {
- data->callback (data->manager, data->context);
+ data->callback (data->manager, data->context, data->arg);
}
else if (polkit_authorization_result_get_is_challenge (result)) {
error = g_error_new (CK_MANAGER_ERROR,
@@ -807,7 +813,8 @@ static void
check_polkit_permissions (CkManager *manager,
DBusGMethodInvocation *context,
const char *action,
- AuthorizedCallback callback)
+ AuthorizedCallback callback,
+ void *arg)
{
const char *sender;
PolkitSubject *subject;
@@ -825,6 +832,7 @@ check_polkit_permissions (CkManager *manager,
data->manager = g_object_ref (manager);
data->context = context;
data->callback = callback;
+ data->arg = arg;
polkit_authority_check_authorization (manager->priv->pol_ctx,
subject,
@@ -1029,7 +1037,8 @@ get_system_num_users (CkManager *manager)
static void
check_rbac_permissions (CkManager *manager,
DBusGMethodInvocation *context,
- AuthorizedCallback callback)
+ AuthorizedCallback callback,
+ void *arg)
{
const char *sender;
char *username;
@@ -1066,14 +1075,16 @@ out:
g_free (username);
if (res) {
- callback (manager, context);
+ callback (manager, context, arg);
}
+ return;
}
#endif
static void
do_restart (CkManager *manager,
- DBusGMethodInvocation *context)
+ DBusGMethodInvocation *context,
+ void *arg)
{
GError *error;
gboolean res;
@@ -1124,9 +1135,9 @@ ck_manager_restart (CkManager *manager,
g_debug ("ConsoleKit Restart: %s", action);
#if defined HAVE_POLKIT
- check_polkit_permissions (manager, context, action, do_restart);
+ check_polkit_permissions (manager, context, action, do_restart, NULL);
#elif defined ENABLE_RBAC_SHUTDOWN
- check_rbac_permissions (manager, context, do_restart);
+ check_rbac_permissions (manager, context, do_restart, NULL);
#else
g_warning ("Compiled without PolicyKit or RBAC support!");
#endif
@@ -1154,7 +1165,8 @@ ck_manager_can_restart (CkManager *manager,
static void
do_stop (CkManager *manager,
- DBusGMethodInvocation *context)
+ DBusGMethodInvocation *context,
+ void *arg)
{
GError *error;
gboolean res;
@@ -1195,9 +1207,9 @@ ck_manager_stop (CkManager *manager,
}
#if defined HAVE_POLKIT
- check_polkit_permissions (manager, context, action, do_stop);
+ check_polkit_permissions (manager, context, action, do_stop, NULL);
#elif defined ENABLE_RBAC_SHUTDOWN
- check_rbac_permissions (manager, context, do_stop);
+ check_rbac_permissions (manager, context, do_stop, NULL);
#else
g_warning ("Compiled without PolicyKit or RBAC support!");
#endif
@@ -1222,6 +1234,216 @@ ck_manager_can_stop (CkManager *manager,
return TRUE;
}
+#define OS_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray", \
+ G_TYPE_INT, \
+ G_TYPE_STRING, \
+ G_TYPE_STRING, \
+ G_TYPE_STRING, \
+ G_TYPE_BOOLEAN, \
+ G_TYPE_INVALID))
+
+#if (defined(sun) && defined(__SVR4))
+static gint
+parse_output (const gchar *output, GPtrArray **systems)
+{
+ gchar **lines;
+ gint default_id = -1;
+
+ if (output == NULL)
+ return default_id;
+
+ lines = g_strsplit (output, "\n", 0);
+ for (int i = 0; lines[i] != NULL; i++) {
+ gchar *index;
+
+ if (i == 0 || i == 2) {
+ /* We do not care 1st & 2nd line. */
+ continue;
+ } else if (i == 1) {
+ /* default boot menu entry */
+ index = strchr (lines[i], ' ');
+ if (index && (index + 1)) {
+ default_id = atol (index + 1);
+ } else {
+ continue;
+ }
+ } else if (lines[i][0] != NULL && systems) {
+ /* boot menu entries */
+ GValue elem = {0};
+
+ index = strchr (lines[i], ' ');
+ if (index && (index + 1)) {
+ gint id;
+
+ *index = '\0';
+ id = atoi (lines[i]);
+ g_value_init (&elem, OS_STRUCT_TYPE);
+ g_value_take_boxed (&elem,
+ dbus_g_type_specialized_construct (OS_STRUCT_TYPE));
+ dbus_g_type_struct_set (&elem,
+ 0, id,
+ 1, "",
+ 2, "",
+ 3, (index + 1),
+ 4, (default_id == id),
+ G_MAXUINT);
+ g_ptr_array_add (*systems,
+ g_value_get_boxed (&elem));
+ } else {
+ continue;
+ }
+ }
+ }
+ g_strfreev (lines);
+ return default_id;
+}
+
+static gint
+get_available_boot_environment (CkManager *manager,
+ GPtrArray **systems,
+ DBusGMethodInvocation *context)
+{
+ gchar *cmd[] = {"/usr/sbin/bootadm", "list-menu", NULL};
+ gchar *output = NULL;
+ GError *err = NULL;
+ gint status;
+ gint ret = -1;
+
+ g_spawn_sync (NULL, cmd, NULL,
+ G_SPAWN_STDERR_TO_DEV_NULL, NULL,
+ NULL, &output, NULL,
+ &status, &err);
+ if (err) {
+ g_error_free (err);
+ return ret;
+ }
+
+ if (status == 0) {
+ ret = parse_output (output, systems);
+ }
+ if (output)
+ g_free (output);
+ return ret;
+}
+#endif
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.GetAvailableOperatingSystems
+*/
+gboolean
+ck_manager_get_available_operating_systems (CkManager *manager,
+ DBusGMethodInvocation *context)
+{
+ GPtrArray *systems;
+
+ g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
+
+ systems = g_ptr_array_new ();
+#if (defined(sun) && defined(__SVR4))
+ get_available_boot_environment (manager, &systems, context);
+#endif
+ dbus_g_method_return (context, systems);
+
+ return TRUE;
+}
+
+#if (defined(sun) && defined(__SVR4))
+static void
+set_default_boot_entry (CkManager *manager,
+ gint id,
+ DBusGMethodInvocation *context)
+{
+ gint default_id;
+
+ default_id = get_available_boot_environment (manager, NULL, context);
+ if (default_id != id) {
+ gchar *cmd;
+
+ g_debug ("Set default boot entry from %d to %d",
+ default_id, id);
+ cmd = g_strdup_printf ("/usr/sbin/bootadm set-menu default=%d",
+ id);
+ if (g_spawn_command_line_async (cmd, NULL) == FALSE) {
+ g_warning ("Unable to set default boot entry");
+ }
+ g_free (cmd);
+ }
+}
+#endif
+
+static void
+do_restart_with_parameters (CkManager *manager,
+ DBusGMethodInvocation *context,
+ void *parameters)
+{
+#if (defined(sun) && defined(__SVR4))
+ gchar **param;
+
+ if (parameters == NULL)
+ return;
+
+ param = g_strsplit ((gchar*)parameters, " ", 0);
+ for (int i = 0; param[i] != NULL; i++) {
+ if (strncmp (param[i], "id:", 3) == 0) {
+ if (g_ascii_isdigit(param[i][3])) {
+ gint id;
+
+ id = atoi (¶m[i][3]);
+ set_default_boot_entry (manager, id, context);
+ }
+ } else if (strncmp (param[i], "fast:", 5) == 0) {
+ if (g_ascii_isdigit(param[i][5])) {
+ gint val;
+
+ val = atoi (¶m[i][5]);
+ if (val == 1)
+ scf_fastreboot_default_set_transient (1);
+ else if (val == 0)
+ scf_fastreboot_default_set_transient (0);
+ }
+ }
+ }
+ g_strfreev (param);
+#endif
+ do_restart (manager, context, NULL);
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.RestartWithParameters \
+ string:"id:0 fast:1"
+*/
+gboolean
+ck_manager_restart_with_parameters (CkManager *manager,
+ const gchar *parameters,
+ DBusGMethodInvocation *context)
+{
+ const char *action;
+
+ g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
+
+#if defined HAVE_POLKIT
+ if (get_system_num_users (manager) > 1) {
+ action = "org.freedesktop.consolekit.system.restart-multiple-users";
+ } else {
+ action = "org.freedesktop.consolekit.system.restart";
+ }
+ check_polkit_permissions (manager, context, action,
+ do_restart_with_parameters, (void *)parameters);
+#elif defined ENABLE_RBAC_SHUTDOWN
+ check_rbac_permissions (manager, context,
+ do_restart_with_parameters, (void *)parameters);
+#endif
+ 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 4bd56e8..0fc0ee7 100644
--- a/src/ck-manager.h
+++ b/src/ck-manager.h
@@ -87,6 +87,11 @@ gboolean ck_manager_can_stop (CkManager *manage
DBusGMethodInvocation *context);
gboolean ck_manager_can_restart (CkManager *manager,
DBusGMethodInvocation *context);
+gboolean ck_manager_get_available_operating_systems (CkManager *manager,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_restart_with_parameters (CkManager *manager,
+ const gchar *parameters,
+ DBusGMethodInvocation *context);
/* Authoritative properties */
gboolean ck_manager_open_session (CkManager *manager,
DBusGMethodInvocation *context);
diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml
index f903b55..7b8b4e5 100644
--- a/src/org.freedesktop.ConsoleKit.Manager.xml
+++ b/src/org.freedesktop.ConsoleKit.Manager.xml
@@ -32,6 +32,34 @@
+
+
+
+
+ An array of available operating systems
+
+
+
+
+ This method returns an array of available operating systems.
+
+
+
+
+
+
+
+
+ The parameeters used to restart.
+
+
+
+
+ This method initiates a request to restart (ie. reboot) with system specific parameters.
+
+
+
+