diff -uprN ConsoleKit-0.4.1-backup/configure.ac ConsoleKit-0.4.1/configure.ac --- ConsoleKit-0.4.1-backup/configure.ac 2009-11-10 15:28:55.524301156 +0800 +++ ConsoleKit-0.4.1/configure.ac 2009-11-10 15:31:24.985394958 +0800 @@ -81,10 +81,10 @@ AC_PATH_PROG(GLIB_GENMARSHAL, glib-genma EXTRA_COMPILE_WARNINGS(yes) -# Solaris requires libresolv for daemon() +# Solaris requires libscf 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 -uprN ConsoleKit-0.4.1-backup/data/ConsoleKit.conf ConsoleKit-0.4.1/data/ConsoleKit.conf --- ConsoleKit-0.4.1-backup/data/ConsoleKit.conf 2009-11-10 15:28:55.525135254 +0800 +++ ConsoleKit-0.4.1/data/ConsoleKit.conf 2009-11-10 15:31:24.985644376 +0800 @@ -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 @@ -759,13 +763,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 @@ -799,7 +805,7 @@ auth_ready_callback (PolkitAuthority 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, @@ -825,7 +831,8 @@ static void check_polkit_permissions (CkManager *manager, DBusGMethodInvocation *context, const char *action, - AuthorizedCallback callback) + AuthorizedCallback callback, + void *arg) { const char *sender; PolkitSubject *subject; @@ -843,6 +850,7 @@ check_polkit_permissions (CkManager data->manager = g_object_ref (manager); data->context = context; data->callback = callback; + data->arg = arg; polkit_authority_check_authorization (manager->priv->pol_ctx, subject, @@ -1048,7 +1056,8 @@ static gboolean check_rbac_permissions (CkManager *manager, DBusGMethodInvocation *context, const char *action, - AuthorizedCallback callback) + AuthorizedCallback callback, + void *arg) { const char *sender; char *username; @@ -1085,7 +1094,7 @@ out: g_free (username); if (res && callback) { - callback (manager, context); + callback (manager, context, arg); } return res; @@ -1094,7 +1103,8 @@ out: static void do_restart (CkManager *manager, - DBusGMethodInvocation *context) + DBusGMethodInvocation *context, + void *arg) { GError *error; gboolean res; @@ -1145,9 +1155,10 @@ ck_manager_restart (CkManager 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, RBAC_SHUTDOWN_KEY, do_restart); + check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_restart, + NULL); #else g_warning ("Compiled without PolicyKit or RBAC support!"); #endif @@ -1168,7 +1179,7 @@ ck_manager_can_restart (CkManager *mana get_polkit_permissions (manager, action, context); #else if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, - NULL)) { + NULL, NULL)) { dbus_g_method_return (context, TRUE); } else { dbus_g_method_return (context, FALSE); @@ -1180,7 +1191,8 @@ ck_manager_can_restart (CkManager *mana static void do_stop (CkManager *manager, - DBusGMethodInvocation *context) + DBusGMethodInvocation *context, + void *arg) { GError *error; gboolean res; @@ -1221,9 +1233,10 @@ ck_manager_stop (CkManager * } #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, RBAC_SHUTDOWN_KEY, do_stop); + check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_stop, + NULL); #else g_warning ("Compiled without PolicyKit or RBAC support!"); #endif @@ -1243,7 +1256,7 @@ ck_manager_can_stop (CkManager *manager get_polkit_permissions (manager, action, context); #else if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, - NULL)) { + NULL, NULL)) { dbus_g_method_return (context, TRUE); } else { dbus_g_method_return (context, FALSE); @@ -1253,6 +1266,218 @@ 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); + } +#if defined(__x86__) || defined(__x86) + } 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); + } +#endif + } + } + 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, RBAC_SHUTDOWN_KEY, + do_restart_with_parameters, (void *)parameters); +#endif + return TRUE; +} + static void on_seat_active_session_changed_full (CkSeat *seat, CkSession *old_session, diff -uprN ConsoleKit-0.4.1-backup/src/ck-manager.h ConsoleKit-0.4.1/src/ck-manager.h --- ConsoleKit-0.4.1-backup/src/ck-manager.h 2009-11-10 15:28:55.534101649 +0800 +++ ConsoleKit-0.4.1/src/ck-manager.h 2009-11-10 15:31:24.987857782 +0800 @@ -88,6 +88,11 @@ gboolean ck_manager_can_stop 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 -uprN ConsoleKit-0.4.1-backup/src/org.freedesktop.ConsoleKit.Manager.xml ConsoleKit-0.4.1/src/org.freedesktop.ConsoleKit.Manager.xml --- ConsoleKit-0.4.1-backup/src/org.freedesktop.ConsoleKit.Manager.xml 2009-11-10 15:28:55.540314508 +0800 +++ ConsoleKit-0.4.1/src/org.freedesktop.ConsoleKit.Manager.xml 2009-11-10 15:31:24.988157959 +0800 @@ -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. + + + +