diff --git a/gdm-sysconfig-settings.patch b/gdm-sysconfig-settings.patch new file mode 100644 index 0000000..d48d878 --- /dev/null +++ b/gdm-sysconfig-settings.patch @@ -0,0 +1,831 @@ +diff --git a/common/Makefile.am b/common/Makefile.am +index 101b3f4..705c6de 100644 +--- a/common/Makefile.am ++++ b/common/Makefile.am +@@ -83,6 +83,8 @@ libgdmcommon_la_SOURCES = \ + gdm-settings-backend.h \ + gdm-settings-desktop-backend.c \ + gdm-settings-desktop-backend.h \ ++ gdm-settings-system-backend.c \ ++ gdm-settings-system-backend.h \ + gdm-settings-keys.h \ + gdm-settings-utils.h \ + gdm-settings-utils.c \ +diff --git a/common/gdm-settings-system-backend.c b/common/gdm-settings-system-backend.c +new file mode 100644 +index 0000000..eb7f883 +--- /dev/null ++++ b/common/gdm-settings-system-backend.c +@@ -0,0 +1,619 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2008 Hans Petter Jansson ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ */ ++ ++#include "config.h" ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include ++#include ++#include ++#include ++ ++#include "gdm-settings-keys.h" ++#include "gdm-settings-system-backend.h" ++ ++#include "gdm-marshal.h" ++#include "gdm-log.h" ++ ++#define SYSCONFIG_AUTOLOGIN_KEY "DISPLAYMANAGER_AUTOLOGIN" ++ ++#define GDM_SETTINGS_SYSTEM_BACKEND_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GDM_TYPE_SETTINGS_SYSTEM_BACKEND, GdmSettingsSystemBackendPrivate)) ++ ++struct GdmSettingsSystemBackendPrivate ++{ ++ char *filename; ++ gchar **lines; ++ gboolean dirty; ++ guint save_id; ++ ++ gchar *set_autologin_user; ++ gboolean set_autologin_enabled; ++}; ++ ++static void gdm_settings_system_backend_class_init (GdmSettingsSystemBackendClass *klass); ++static void gdm_settings_system_backend_init (GdmSettingsSystemBackend *settings_system_backend); ++static void gdm_settings_system_backend_finalize (GObject *object); ++ ++G_DEFINE_TYPE (GdmSettingsSystemBackend, gdm_settings_system_backend, GDM_TYPE_SETTINGS_BACKEND) ++ ++static gchar ** ++load_settings_file (gchar *file_name) ++{ ++ GIOChannel *channel; ++ GPtrArray *lines; ++ gchar *str; ++ ++ g_debug ("Loading settings from %s", file_name); ++ ++ channel = g_io_channel_new_file (file_name, "r", NULL); ++ if (!channel) { ++ g_debug ("Failed to open %s", file_name); ++ return NULL; ++ } ++ ++ lines = g_ptr_array_new (); ++ ++ while (g_io_channel_read_line (channel, &str, NULL, NULL, NULL) != G_IO_STATUS_EOF) { ++ if (str) { ++ gchar *p0; ++ ++ /* Remove line separators */ ++ ++ for (p0 = str + strlen (str) - 1; p0 >= str && strchr ("\r\n", *p0); p0--) ++ *p0 = '\0'; ++ ++ g_ptr_array_add (lines, str); ++ g_debug ("%s", str); ++ } else { ++ g_ptr_array_add (lines, g_strdup ("")); ++ g_debug ("", str); ++ } ++ } ++ ++ g_io_channel_shutdown (channel, FALSE, NULL); ++ g_io_channel_unref (channel); ++ ++ g_ptr_array_add (lines, NULL); ++ ++ return (gchar **) g_ptr_array_free (lines, FALSE); ++} ++ ++static gboolean ++save_settings_file (gchar *file_name, gchar **lines) ++{ ++ GIOStatus last_status = G_IO_STATUS_ERROR; ++ GIOChannel *channel = NULL; ++ gchar *temp_file_name; ++ gint i; ++ ++ temp_file_name = g_strdup_printf ("%s.new.%u", file_name, g_random_int ()); ++ ++ channel = g_io_channel_new_file (temp_file_name, "w", NULL); ++ if (!channel) ++ goto out; ++ ++ if (!lines) ++ goto out; ++ ++ for (i = 0; lines [i]; i++) { ++ gsize bytes_written; ++ ++ if (lines [i] [0] != '\0') ++ last_status = g_io_channel_write_chars (channel, ++ lines [i], strlen (lines [i]), ++ &bytes_written, ++ NULL); ++ ++ if (last_status != G_IO_STATUS_NORMAL) ++ break; ++ ++ last_status = g_io_channel_write_unichar (channel, '\n', NULL); ++ ++ if (last_status != G_IO_STATUS_NORMAL) ++ break; ++ } ++ ++out: ++ if (channel) { ++ g_io_channel_shutdown (channel, FALSE, NULL); ++ g_io_channel_unref (channel); ++ } ++ ++ if (last_status == G_IO_STATUS_NORMAL && g_rename (temp_file_name, file_name) != 0) ++ last_status = G_IO_STATUS_ERROR; ++ ++ g_free (temp_file_name); ++ return last_status == G_IO_STATUS_NORMAL ? TRUE : FALSE; ++} ++ ++/* Parser for shell-script-like key-value files. Far from complete, but ++ * deals with a couple of common shell oddities. For instance, the following ++ * are parsed correctly: ++ * ++ * KEY=value\0 ++ * KEY = value#comment\0 ++ * KEY = " value with spaces" \0 ++ * KEY = ' it\'s a value with "embedded" quotes'\0 ++ * KEY = "if quotes aren't closed, we assume the string ends at EOL\0 ++ * ++ * It should be good enough for the config files in /etc/sysconfig/. ++ */ ++ ++#define SPACE_CHARS " \t" ++#define KEY_ALLOW_CHARS "_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" ++ ++static const gchar * ++skip_from_start_to_key (const gchar *line) ++{ ++ const gchar *p0; ++ ++ /* Skip initial space */ ++ ++ p0 = line + strspn (line, SPACE_CHARS); ++ ++ /* Ignore comments and other junk */ ++ ++ if (*p0 && strchr (KEY_ALLOW_CHARS, *p0)) ++ return p0; ++ ++ return NULL; ++} ++ ++static const gchar * ++skip_from_start_to_value_of_key (const gchar *line, const gchar *key_normal, gint key_len) ++{ ++ const gchar *p0, *p1; ++ gchar *potential_key_normal; ++ gboolean result; ++ ++ p0 = skip_from_start_to_key (line); ++ if (!p0) ++ return NULL; ++ ++ /* There's at least one key-like character, figure out how many */ ++ ++ p1 = p0 + strspn (p0, KEY_ALLOW_CHARS); ++ ++ /* Is this the key we're looking for? */ ++ ++ if (p1 - p0 != key_len) ++ return NULL; ++ ++ potential_key_normal = g_ascii_strdown (p0, p1 - p0); ++ result = strcmp (key_normal, potential_key_normal) == 0 ? TRUE : FALSE; ++ g_free (potential_key_normal); ++ ++ if (!result) ++ return NULL; ++ ++ /* It's the right key; skip over key-value separator */ ++ ++ p0 = p1 + strspn (p1, SPACE_CHARS); ++ if (*p0 != '=') ++ return NULL; ++ ++ p0++; ++ p0 += strspn (p0, SPACE_CHARS); ++ ++ return p0; ++} ++ ++static const gchar * ++skip_over_value (const gchar *value_start, gchar *quotes_out) ++{ ++ const gchar *p0 = value_start; ++ const gchar *p1; ++ gchar quotes; ++ ++ /* Is the value quoted? */ ++ ++ quotes = *p0; ++ if (quotes == '\'' || quotes == '"') { ++ /* Quoted sequence opened; find closing quote, but skip over escaped ones. If ++ * there's no closing quote on this line, assume the EOL closes it. */ ++ ++ *quotes_out = quotes; ++ ++ p1 = p0; ++ do { ++ p1++; ++ p1 = strchr (p1, quotes); ++ if (!p1) { ++ /* Hit EOL */ ++ ++ p1 = p0 + strlen (p0) - 1; ++ break; ++ } ++ } while (*(p1 - 1) == '\\'); ++ } else { ++ /* No quotes; look for comment or EOL */ ++ ++ *quotes_out = 0; ++ ++ p1 = strchr (p0, '#'); ++ if (!p1) ++ p1 = p0 + strlen (p0); ++ ++ for (p1--; p1 >= p0; p1--) ++ if (!strchr (SPACE_CHARS, *p1)) ++ break; ++ } ++ ++ return p1 + 1; ++} ++ ++static gchar * ++get_value_of_key (const gchar *line, const gchar *key_normal, gint key_len) ++{ ++ const gchar *p0, *p1; ++ gchar quotes; ++ gchar *value; ++ gchar *temp; ++ ++ p0 = skip_from_start_to_value_of_key (line, key_normal, key_len); ++ if (!p0) ++ return NULL; ++ ++ p1 = skip_over_value (p0, "es); ++ ++ if (quotes != 0) { ++ if (p1 - p0 > 2) { ++ temp = g_strndup (p0 + 1, p1 - p0 - 2); ++ value = g_strcompress (temp); ++ g_free (temp); ++ } else { ++ value = g_strdup (""); ++ } ++ } else { ++ temp = g_strndup (p0, p1 - p0); ++ value = g_strcompress (temp); ++ g_free (temp); ++ g_strchomp (value); ++ } ++ ++ return value; ++} ++ ++static gchar * ++get_value (const gchar **lines, const gchar *key) ++{ ++ gchar *value = NULL; ++ gchar *key_normal; ++ gint key_len; ++ gint i; ++ ++ g_return_val_if_fail (key != NULL, NULL); ++ ++ g_debug ("Getting value of %s", key); ++ ++ if (!lines) { ++ g_debug ("Missing configuration data"); ++ return NULL; ++ } ++ ++ key_normal = g_ascii_strdown (key, -1); ++ key_len = strlen (key_normal); ++ ++ for (i = 0; lines [i]; i++) { ++ value = get_value_of_key (lines [i], key_normal, key_len); ++ if (value) ++ break; ++ } ++ ++ g_free (key_normal); ++ ++ g_debug ("Got value of %s: %s", key, value); ++ ++ return value; ++} ++ ++static gchar * ++set_value_of_key (const gchar *line, const gchar *key_normal, gint key_len, const gchar *key, const gchar *value) ++{ ++ const gchar *p0, *p1, *p2; ++ gchar quotes; ++ gchar *escaped_value; ++ gint escaped_value_len; ++ gchar *new_line; ++ gint len; ++ ++ p0 = skip_from_start_to_value_of_key (line, key_normal, key_len); ++ if (!p0) ++ return NULL; ++ ++ escaped_value = g_strescape (value, ""); ++ escaped_value_len = strlen (escaped_value); ++ ++ p1 = skip_over_value (p0, "es); ++ p2 = p1 + strlen (p1); ++ len = (p0 - line) + escaped_value_len + (p2 - p1); ++ ++ new_line = g_malloc (len + 1); ++ memcpy (new_line, line, p0 - line); ++ memcpy (new_line + (p0 - line), escaped_value, escaped_value_len); ++ memcpy (new_line + (p0 - line) + escaped_value_len, p1, p2 - p1); ++ ++ *(new_line + len - 1) = '\0'; ++ ++ g_free (escaped_value); ++ ++ return new_line; ++} ++ ++static gboolean ++set_value (gchar **lines, const gchar *key, const gchar *value) ++{ ++ gboolean result = FALSE; ++ gchar *key_normal; ++ gint key_len; ++ gint i; ++ ++ g_return_val_if_fail (key != NULL, FALSE); ++ ++ if (!lines) ++ return FALSE; ++ ++ key_normal = g_ascii_strdown (key, -1); ++ key_len = strlen (key_normal); ++ ++ for (i = 0; lines [i]; i++) { ++ gchar *new_line; ++ ++ new_line = set_value_of_key (lines [i], key_normal, key_len, key, value); ++ if (new_line) { ++ g_free (lines [i]); ++ lines [i] = new_line; ++ result = TRUE; ++ break; ++ } ++ } ++ ++ g_free (key_normal); ++ ++ return result; ++} ++ ++static gboolean ++gdm_settings_system_backend_get_value (GdmSettingsBackend *backend, ++ const char *key, ++ char **value, ++ GError **error) ++{ ++ GdmSettingsSystemBackend *system_backend = (GdmSettingsSystemBackend *) backend; ++ GdmSettingsSystemBackendPrivate *priv; ++ gchar *val; ++ gboolean ret; ++ ++ g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (backend), FALSE); ++ g_return_val_if_fail (key != NULL, FALSE); ++ ++ priv = system_backend->priv; ++ ret = FALSE; ++ ++ if (value != NULL) { ++ *value = NULL; ++ } ++ ++ if (strcasecmp (key, GDM_KEY_AUTO_LOGIN_ENABLE) && ++ strcasecmp (key, GDM_KEY_AUTO_LOGIN_USER)) { ++ g_set_error (error, GDM_SETTINGS_BACKEND_ERROR, GDM_SETTINGS_BACKEND_ERROR_KEY_NOT_FOUND, "Key not found"); ++ goto out; ++ } ++ ++ if (!strcasecmp (key, GDM_KEY_AUTO_LOGIN_ENABLE)) { ++ if (priv->dirty) { ++ val = g_strdup (priv->set_autologin_enabled ? "true" : "false"); ++ } else { ++ const gchar *new_val; ++ ++ val = get_value ((const gchar **) priv->lines, SYSCONFIG_AUTOLOGIN_KEY); ++ ++ new_val = (val && *val) ? "true" : "false"; ++ g_free (val); ++ val = g_strdup (new_val); ++ } ++ } else { ++ if (priv->dirty && priv->set_autologin_user) { ++ val = g_strdup (priv->set_autologin_user); ++ } else { ++ val = get_value ((const gchar **) priv->lines, SYSCONFIG_AUTOLOGIN_KEY); ++ } ++ } ++ ++ if (value != NULL && val != NULL && *val != '\0') { ++ *value = val; ++ } else { ++ g_free (val); ++ } ++ ++ ret = TRUE; ++ ++ out: ++ return ret; ++} ++ ++static void ++save_settings (GdmSettingsSystemBackend *backend) ++{ ++ GError *local_error; ++ char *contents; ++ gsize length; ++ ++ if (! backend->priv->dirty) { ++ return; ++ } ++ ++ g_debug ("Saving settings to %s", backend->priv->filename); ++ ++ if (!backend->priv->set_autologin_enabled) { ++ g_free (backend->priv->set_autologin_user); ++ backend->priv->set_autologin_user = g_strdup (""); ++ } ++ ++ if (!set_value (backend->priv->lines, SYSCONFIG_AUTOLOGIN_KEY, backend->priv->set_autologin_user)) ++ g_warning ("Unable to set key %s to '%s'.", SYSCONFIG_AUTOLOGIN_KEY, ++ backend->priv->set_autologin_user); ++ ++ if (!save_settings_file (backend->priv->filename, backend->priv->lines)) ++ g_warning ("Unable to save settings to %s.", backend->priv->filename); ++ ++ backend->priv->dirty = FALSE; ++} ++ ++static gboolean ++save_settings_timer (GdmSettingsSystemBackend *backend) ++{ ++ save_settings (backend); ++ backend->priv->save_id = 0; ++ return FALSE; ++} ++ ++static void ++queue_save (GdmSettingsSystemBackend *backend) ++{ ++ if (! backend->priv->dirty) { ++ return; ++ } ++ ++ if (backend->priv->save_id != 0) { ++ /* already pending */ ++ return; ++ } ++ ++ backend->priv->save_id = g_timeout_add_seconds (5, (GSourceFunc)save_settings_timer, backend); ++} ++ ++static gboolean ++gdm_settings_system_backend_set_value (GdmSettingsBackend *backend, ++ const char *key, ++ const char *value, ++ GError **error) ++{ ++ GdmSettingsSystemBackend *system_backend = (GdmSettingsSystemBackend *) backend; ++ GdmSettingsSystemBackendPrivate *priv; ++ gchar *old_val = NULL; ++ ++ g_return_val_if_fail (GDM_IS_SETTINGS_BACKEND (backend), FALSE); ++ g_return_val_if_fail (key != NULL, FALSE); ++ ++ priv = system_backend->priv; ++ ++ if (strcasecmp ("key", GDM_KEY_AUTO_LOGIN_ENABLE) && ++ strcasecmp ("key", GDM_KEY_AUTO_LOGIN_USER)) { ++ g_set_error (error, GDM_SETTINGS_BACKEND_ERROR, GDM_SETTINGS_BACKEND_ERROR_KEY_NOT_FOUND, "Key not found"); ++ return FALSE; ++ } ++ ++ gdm_settings_system_backend_get_value (backend, key, &old_val, NULL); ++ ++ if (!strcasecmp ("key", GDM_KEY_AUTO_LOGIN_ENABLE)) { ++ gchar t = 0; ++ ++ if (value) ++ t = g_ascii_tolower (*value); ++ ++ if (t == 'y' || t == 't') ++ priv->set_autologin_enabled = TRUE; ++ else ++ priv->set_autologin_enabled = FALSE; ++ } else { ++ g_free (priv->set_autologin_user); ++ priv->set_autologin_user = g_strdup (value); ++ } ++ ++ GDM_SETTINGS_SYSTEM_BACKEND (backend)->priv->dirty = TRUE; ++ queue_save (GDM_SETTINGS_SYSTEM_BACKEND (backend)); ++ ++ gdm_settings_backend_value_changed (backend, key, old_val, value); ++ ++ g_free (old_val); ++ ++ return TRUE; ++} ++ ++static void ++gdm_settings_system_backend_class_init (GdmSettingsSystemBackendClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ GdmSettingsBackendClass *backend_class = GDM_SETTINGS_BACKEND_CLASS (klass); ++ ++ object_class->finalize = gdm_settings_system_backend_finalize; ++ ++ backend_class->get_value = gdm_settings_system_backend_get_value; ++ backend_class->set_value = gdm_settings_system_backend_set_value; ++ ++ g_type_class_add_private (klass, sizeof (GdmSettingsSystemBackendPrivate)); ++} ++ ++static void ++gdm_settings_system_backend_init (GdmSettingsSystemBackend *backend) ++{ ++ gboolean res; ++ GError *error; ++ ++ gdm_log_set_debug (TRUE); ++ ++ backend->priv = GDM_SETTINGS_SYSTEM_BACKEND_GET_PRIVATE (backend); ++ ++ backend->priv->filename = g_strdup ("/etc/sysconfig/displaymanager"); ++ backend->priv->lines = load_settings_file (backend->priv->filename); ++ ++ if (!backend->priv->lines) { ++ g_warning ("Unable to load file '%s'", backend->priv->filename); ++ } ++} ++ ++static void ++gdm_settings_system_backend_finalize (GObject *object) ++{ ++ GdmSettingsSystemBackend *backend; ++ ++ g_return_if_fail (object != NULL); ++ g_return_if_fail (GDM_IS_SETTINGS_SYSTEM_BACKEND (object)); ++ ++ backend = GDM_SETTINGS_SYSTEM_BACKEND (object); ++ ++ g_return_if_fail (backend->priv != NULL); ++ ++ save_settings (backend); ++ g_strfreev (backend->priv->lines); ++ g_free (backend->priv->filename); ++ g_free (backend->priv->set_autologin_user); ++ ++ G_OBJECT_CLASS (gdm_settings_system_backend_parent_class)->finalize (object); ++} ++ ++GdmSettingsBackend * ++gdm_settings_system_backend_new (void) ++{ ++ GObject *object; ++ ++ object = g_object_new (GDM_TYPE_SETTINGS_SYSTEM_BACKEND, NULL); ++ ++ return GDM_SETTINGS_BACKEND (object); ++} +diff --git a/common/gdm-settings-system-backend.h b/common/gdm-settings-system-backend.h +new file mode 100644 +index 0000000..3cd16b7 +--- /dev/null ++++ b/common/gdm-settings-system-backend.h +@@ -0,0 +1,56 @@ ++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- ++ * ++ * Copyright (C) 2008 Hans Petter Jansson ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ */ ++ ++ ++#ifndef __GDM_SETTINGS_SYSTEM_BACKEND_H ++#define __GDM_SETTINGS_SYSTEM_BACKEND_H ++ ++#include ++#include "gdm-settings-backend.h" ++ ++G_BEGIN_DECLS ++ ++#define GDM_TYPE_SETTINGS_SYSTEM_BACKEND (gdm_settings_system_backend_get_type ()) ++#define GDM_SETTINGS_SYSTEM_BACKEND(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), GDM_TYPE_SETTINGS_SYSTEM_BACKEND, GdmSettingsSystemBackend)) ++#define GDM_SETTINGS_SYSTEM_BACKEND_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), GDM_TYPE_SETTINGS_SYSTEM_BACKEND, GdmSettingsSystemBackendClass)) ++#define GDM_IS_SETTINGS_SYSTEM_BACKEND(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), GDM_TYPE_SETTINGS_SYSTEM_BACKEND)) ++#define GDM_IS_SETTINGS_SYSTEM_BACKEND_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), GDM_TYPE_SETTINGS_SYSTEM_BACKEND)) ++#define GDM_SETTINGS_SYSTEM_BACKEND_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), GDM_TYPE_SETTINGS_SYSTEM_BACKEND, GdmSettingsSystemBackendClass)) ++ ++typedef struct GdmSettingsSystemBackendPrivate GdmSettingsSystemBackendPrivate; ++ ++typedef struct ++{ ++ GdmSettingsBackend parent; ++ GdmSettingsSystemBackendPrivate *priv; ++} GdmSettingsSystemBackend; ++ ++typedef struct ++{ ++ GdmSettingsBackendClass parent_class; ++} GdmSettingsSystemBackendClass; ++ ++GType gdm_settings_system_backend_get_type (void); ++ ++GdmSettingsBackend *gdm_settings_system_backend_new (void); ++ ++G_END_DECLS ++ ++#endif /* __GDM_SETTINGS_SYSTEM_BACKEND_H */ +diff --git a/common/gdm-settings.c b/common/gdm-settings.c +index 00fe73e..4c31394 100644 +--- a/common/gdm-settings.c ++++ b/common/gdm-settings.c +@@ -41,6 +41,7 @@ + #include "gdm-settings-glue.h" + + #include "gdm-settings-desktop-backend.h" ++#include "gdm-settings-system-backend.h" + + #include "gdm-marshal.h" + +@@ -53,7 +54,7 @@ + struct GdmSettingsPrivate + { + DBusGConnection *connection; +- GdmSettingsBackend *backend; ++ GList *backends; + }; + + enum { +@@ -94,15 +95,29 @@ gdm_settings_get_value (GdmSettings *settings, + { + GError *local_error; + gboolean res; ++ GList *l; + + g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE); + g_return_val_if_fail (key != NULL, FALSE); + + local_error = NULL; +- res = gdm_settings_backend_get_value (settings->priv->backend, +- key, +- value, +- &local_error); ++ ++ for (l = settings->priv->backends; l; l = g_list_next (l)) { ++ GdmSettingsBackend *backend = l->data; ++ ++ if (local_error) { ++ g_error_free (local_error); ++ local_error = NULL; ++ } ++ ++ res = gdm_settings_backend_get_value (backend, ++ key, ++ value, ++ &local_error); ++ if (res) ++ break; ++ } ++ + if (! res) { + g_propagate_error (error, local_error); + } +@@ -122,6 +137,7 @@ gdm_settings_set_value (GdmSettings *settings, + { + GError *local_error; + gboolean res; ++ GList *l; + + g_return_val_if_fail (GDM_IS_SETTINGS (settings), FALSE); + g_return_val_if_fail (key != NULL, FALSE); +@@ -129,10 +145,23 @@ gdm_settings_set_value (GdmSettings *settings, + g_debug ("Setting value %s", key); + + local_error = NULL; +- res = gdm_settings_backend_set_value (settings->priv->backend, +- key, +- value, +- &local_error); ++ ++ for (l = settings->priv->backends; l; l = g_list_next (l)) { ++ GdmSettingsBackend *backend = l->data; ++ ++ if (local_error) { ++ g_error_free (local_error); ++ local_error = NULL; ++ } ++ ++ res = gdm_settings_backend_set_value (backend, ++ key, ++ value, ++ &local_error); ++ if (res) ++ break; ++ } ++ + if (! res) { + g_propagate_error (error, local_error); + } +@@ -210,13 +239,21 @@ backend_value_changed (GdmSettingsBackend *backend, + static void + gdm_settings_init (GdmSettings *settings) + { ++ GList *l; ++ + settings->priv = GDM_SETTINGS_GET_PRIVATE (settings); + +- settings->priv->backend = gdm_settings_desktop_backend_new (); +- g_signal_connect (settings->priv->backend, +- "value-changed", +- G_CALLBACK (backend_value_changed), +- settings); ++ settings->priv->backends = g_list_prepend (NULL, gdm_settings_desktop_backend_new ()); ++ settings->priv->backends = g_list_prepend (settings->priv->backends, gdm_settings_system_backend_new ()); ++ ++ for (l = settings->priv->backends; l; l = g_list_next (l)) { ++ GdmSettingsBackend *backend = l->data; ++ ++ g_signal_connect (backend, ++ "value-changed", ++ G_CALLBACK (backend_value_changed), ++ settings); ++ } + } + + static void +@@ -231,9 +268,9 @@ gdm_settings_finalize (GObject *object) + + g_return_if_fail (settings->priv != NULL); + +- if (settings->priv->backend != NULL) { +- g_object_unref (settings->priv->backend); +- } ++ g_list_foreach (settings->priv->backends, (GFunc) g_object_unref, NULL); ++ g_list_free (settings->priv->backends); ++ settings->priv->backends = NULL; + + G_OBJECT_CLASS (gdm_settings_parent_class)->finalize (object); + } diff --git a/gdm.changes b/gdm.changes index 50c5973..e07b934 100644 --- a/gdm.changes +++ b/gdm.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Fri Nov 7 14:02:20 CET 2008 - vuntz@novell.com + +- Merge hpj's submission: Add gdm-sysconfig-settings.patch, which + fixes bnc#432360. + ------------------------------------------------------------------- Thu Nov 6 20:34:54 CET 2008 - vuntz@novell.com diff --git a/gdm.spec b/gdm.spec index 5b47f8c..5bf9ae0 100644 --- a/gdm.spec +++ b/gdm.spec @@ -57,7 +57,7 @@ PreReq: %insserv_prereq License: GPL v2 or later Group: System/GUI/GNOME Version: 2.24.0 -Release: 6 +Release: 7 Summary: The GNOME 2.x Display Manager Source: %{name}-%{version}.tar.bz2 Source1: gdm.pamd @@ -83,6 +83,8 @@ Patch10: gdm-2.23.92-filter-dupes-from-lang-list.patch Patch11: gdm-2.23.92-fix-crash.patch # PATCH-FIX-UPSTREAM gdm-fix-icon-scale.patch vuntz@novell.com -- From upstream/Fedora: don't have a huge size for icons in the greeter Patch12: gdm-fix-icon-scale.patch +# PATCH-FIX-OPENSUSE gdm-sysconfig-settings.patch bnc432360 hpj@novell.com -- Read autologin options from /etc/sysconfig/displaymanager +Patch13: gdm-sysconfig-settings.patch Patch28: gdm-X_SERVER.patch # PATCH-SUSE: enable SELinux Patch60: gdm-selinux.patch @@ -157,10 +159,12 @@ Authors: %patch10 -p1 %patch11 -p1 %patch12 -p1 +%patch13 -p1 %patch28 %patch60 %build +libtoolize -f -i autoreconf -f -i export CFLAGS="$RPM_OPT_FLAGS -fno-strict-aliasing" %configure\ @@ -264,6 +268,9 @@ fi %files lang -f %{name}.lang %changelog +* Fri Nov 07 2008 vuntz@novell.com +- Merge hpj's submission: Add gdm-sysconfig-settings.patch, which + fixes bnc#432360. * Thu Nov 06 2008 vuntz@novell.com - Add gdm-fix-icon-scale.patch: make icons in the greeter use a reasonable size. Part of bnc#436431.