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. + + + +