Patch migrated from desktop gate, where it was listed as:
# date:2012-06-08 owner:sethg type:bug bugster:7175632
which corresponds to:
Bug 15797081 - SUNBT7175632 ConsoleKit's bootadm list-menu parser needs to be
much more robust
--- ConsoleKit-0.4.1/src/ck-manager.c-orig Fri Jun 15 10:43:58 2012
+++ ConsoleKit-0.4.1/src/ck-manager.c Fri Jun 15 10:44:03 2012
@@ -41,6 +41,7 @@
#if (defined(sun) && defined(__SVR4))
#include <libscf_priv.h>
+#include <ctype.h>
#endif
#if defined HAVE_POLKIT
@@ -1282,10 +1283,36 @@
#if (defined(sun) && defined(__SVR4))
static gint
+is_decimal_string(gchar *token, gint *indexp)
+{
+ gint i;
+
+ for (i = 0; token[i] != 0; i++)
+ if (!isdigit(token[i]))
+ return (0);
+
+ if (i > 0) {
+ if (indexp)
+ *indexp = strtol(token, 0, 10);
+ return (1);
+ }
+
+ /* If the string is empty, return failure */
+ return (0);
+}
+
+/*
+ * The output of bootadm should be parsed intelligently; not based on
+ * the order of lines, but based on the line semantics. We look for
+ * the keyword "default" when looking for the default entry. Lines
+ * that start with a number specify boot entries that should be
+ * captured for display in the dialog's boot entry list.
+ */
+static gint
parse_output (const gchar *output, GPtrArray **systems)
{
gchar **lines;
- gint default_id = -1;
+ gint id, default_id = -1;
if (output == NULL)
return default_id;
@@ -1292,45 +1319,40 @@
lines = g_strsplit (output, "\n", 0);
for (int i = 0; lines[i] != NULL; i++) {
- gchar *index;
+ gchar **tokens;
- 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};
+ /* Split lines into 2 tokens maximum */
+ tokens = g_strsplit_set(lines[i], " \t", 2);
+ if (tokens == 0) {
+ continue;
+ } else if (tokens[0] == 0) {
+ g_strfreev(tokens);
+ continue;
+ }
- index = strchr (lines[i], ' ');
- if (index && (index + 1)) {
- gint id;
+ if (tokens[1] != 0 && strcmp(tokens[0], "default") == 0) {
+ errno = 0;
+ default_id = strtol (tokens[1], 0, 10);
+ if (errno != 0)
+ default_id = 0;
+ } else if (is_decimal_string(tokens[0], &id) && systems) {
- *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,
+ /* boot menu entries */
+ GValue elem = {0};
+
+ 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),
+ 3, (tokens[1] && tokens[1][0]) ? tokens[1] : "<no title specified>",
4, (default_id == id),
G_MAXUINT);
- g_ptr_array_add (*systems,
- g_value_get_boxed (&elem));
- } else {
- continue;
- }
+ g_ptr_array_add (*systems, g_value_get_boxed (&elem));
}
+ g_strfreev(tokens);
}
g_strfreev (lines);
return default_id;