Index: configure.ac
===================================================================
--- configure.ac	(revision 4696)
+++ configure.ac	(working copy)
@@ -1116,6 +1116,47 @@ if test "x$USER_POST_PATH" != "x"; then
    GDM_USER_PATH="$GDM_USER_PATH:$USER_POST_PATH"
 fi
 
+
+# Turn on the additional warnings last, so they don't affect other tests.
+
+AC_ARG_ENABLE(more-warnings,
+  AC_HELP_STRING([--enable-more-warnings], [Maximum compiler warnings]),
+set_more_warnings="$enableval",[
+if test -d $srcdir/.svn; then
+        set_more_warnings=yes
+else
+        set_more_warnings=no
+fi
+])
+AC_MSG_CHECKING(for more warnings)
+if test "$GCC" = "yes" -a "$set_more_warnings" != "no"; then
+        AC_MSG_RESULT(yes)
+        CFLAGS="\
+        -Wall \
+        -Wchar-subscripts -Wmissing-declarations -Wmissing-prototypes \
+        -Wnested-externs -Wpointer-arith \
+        -Wcast-align -Wsign-compare \
+        $CFLAGS"
+
+        for option in -Wno-strict-aliasing -Wno-sign-compare; do
+                SAVE_CFLAGS="$CFLAGS"
+                CFLAGS="$CFLAGS $option"
+                AC_MSG_CHECKING([whether gcc understands $option])
+                AC_TRY_COMPILE([], [],
+                        has_option=yes,
+                        has_option=no,)
+                if test $has_option = no; then
+                        CFLAGS="$SAVE_CFLAGS"
+                fi
+                AC_MSG_RESULT($has_option)
+                unset has_option
+                unset SAVE_CFLAGS
+        done
+        unset option
+else
+        AC_MSG_RESULT(no)
+fi
+
 # Set configuration choices.
 #
 AC_SUBST(HALT_COMMAND)
Index: gui/gdmuser.c
===================================================================
--- gui/gdmuser.c	(revision 4696)
+++ gui/gdmuser.c	(working copy)
@@ -35,6 +35,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 static time_t time_started;
 
Index: gui/gdmdynamic.c
===================================================================
--- gui/gdmdynamic.c	(revision 4696)
+++ gui/gdmdynamic.c	(working copy)
@@ -42,6 +42,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 static char *myname = NULL;  /* name of this program */
 
Index: gui/gdmlogin.c
===================================================================
--- gui/gdmlogin.c	(revision 4696)
+++ gui/gdmlogin.c	(working copy)
@@ -62,6 +62,7 @@
 #include "misc.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 /* set the DOING_GDM_DEVELOPMENT env variable if you aren't running
  * within the protocol */
Index: gui/gdmphotosetup.c
===================================================================
--- gui/gdmphotosetup.c	(revision 4696)
+++ gui/gdmphotosetup.c	(working copy)
@@ -38,6 +38,7 @@
 #include "gdmcomm.h"
 #include "gdmcommon.h"
 #include "gdmconfig.h"
+#include "gdm-daemon-config-keys.h"
 
 static GladeXML *xml;
 static char	*photofile;
Index: gui/gdmsession.c
===================================================================
--- gui/gdmsession.c	(revision 4696)
+++ gui/gdmsession.c	(working copy)
@@ -34,6 +34,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 GHashTable *sessnames        = NULL;
 gchar *default_session       = NULL;
Index: gui/gdmXnestchooser.c
===================================================================
--- gui/gdmXnestchooser.c	(revision 4696)
+++ gui/gdmXnestchooser.c	(working copy)
@@ -43,6 +43,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 static gchar **args_remaining;
 static pid_t xnest_pid = 0;
Index: gui/greeter/greeter_item_customlist.c
===================================================================
--- gui/greeter/greeter_item_customlist.c	(revision 4696)
+++ gui/greeter/greeter_item_customlist.c	(working copy)
@@ -26,6 +26,7 @@
 #include "gdmsession.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "greeter_item.h"
 #include "greeter_configuration.h"
Index: gui/greeter/greeter_canvas_item.c
===================================================================
--- gui/greeter/greeter_canvas_item.c	(revision 4696)
+++ gui/greeter/greeter_canvas_item.c	(working copy)
@@ -29,6 +29,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "greeter.h"
 #include "greeter_item.h"
Index: gui/greeter/greeter_parser.c
===================================================================
--- gui/greeter/greeter_parser.c	(revision 4696)
+++ gui/greeter/greeter_parser.c	(working copy)
@@ -35,6 +35,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "greeter_configuration.h"
 #include "greeter_parser.h"
Index: gui/greeter/greeter_item.c
===================================================================
--- gui/greeter/greeter_item.c	(revision 4696)
+++ gui/greeter/greeter_item.c	(working copy)
@@ -32,6 +32,7 @@
 #include "misc.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "greeter_item.h"
 #include "greeter_configuration.h"
Index: gui/greeter/greeter_item_ulist.c
===================================================================
--- gui/greeter/greeter_item_ulist.c	(revision 4696)
+++ gui/greeter/greeter_item_ulist.c	(working copy)
@@ -40,6 +40,7 @@
 #include "gdmuser.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "greeter.h"
 #include "greeter_item_ulist.h"
Index: gui/greeter/greeter_item_timed.c
===================================================================
--- gui/greeter/greeter_item_timed.c	(revision 4696)
+++ gui/greeter/greeter_item_timed.c	(working copy)
@@ -25,6 +25,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "greeter_parser.h"
 #include "greeter_configuration.h"
Index: gui/greeter/greeter_action_language.c
===================================================================
--- gui/greeter/greeter_action_language.c	(revision 4696)
+++ gui/greeter/greeter_action_language.c	(working copy)
@@ -28,6 +28,8 @@
 #include "gdmconfig.h"
 #include "gdmlanguages.h"
 
+#include "gdm-daemon-config-keys.h"
+
 #include "greeter.h"
 #include "greeter_configuration.h"
 #include "greeter_item_pam.h"
Index: gui/greeter/greeter_session.c
===================================================================
--- gui/greeter/greeter_session.c	(revision 4696)
+++ gui/greeter/greeter_session.c	(working copy)
@@ -34,6 +34,7 @@
 #include "gdmsession.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "greeter.h"
 #include "greeter_session.h"
Index: gui/greeter/greeter_system.c
===================================================================
--- gui/greeter/greeter_system.c	(revision 4696)
+++ gui/greeter/greeter_system.c	(working copy)
@@ -31,6 +31,7 @@
 #include "misc.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "greeter.h"
 #include "greeter_configuration.h"
Index: gui/greeter/greeter.c
===================================================================
--- gui/greeter/greeter.c	(revision 4696)
+++ gui/greeter/greeter.c	(working copy)
@@ -39,6 +39,7 @@
 #include <libgnomecanvas/libgnomecanvas.h>
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 #include "gdm.h"
 #include "gdmwm.h"
Index: gui/gdmcommon.c
===================================================================
--- gui/gdmcommon.c	(revision 4696)
+++ gui/gdmcommon.c	(working copy)
@@ -43,6 +43,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 gint gdm_timed_delay = 0;
 static Atom AT_SPI_IOR;
@@ -677,6 +678,30 @@ gdm_common_pre_fetch_launch (void)
 	g_idle_add (pre_fetch_run, NULL);
 }
 
+static char *
+ve_strftime (struct tm *the_tm, const char *format)
+{
+	char str[1024];
+	char *loc_format;
+
+	loc_format = g_locale_from_utf8 (format, -1, NULL, NULL, NULL);
+	if (loc_format == NULL) {
+		g_warning ("string not in proper utf8 encoding: \"%s\"", format);
+		return NULL;
+	}
+
+	if (strftime (str, sizeof (str)-1, loc_format, the_tm) == 0) {
+		/* according to docs, if the string does not fit, the
+		 * contents of str are undefined, thus just use
+		 * ??? */
+		strcpy (str, "???");
+	}
+	str [sizeof (str)-1] = '\0'; /* just for sanity */
+	g_free (loc_format);
+
+	return g_locale_to_utf8 (str, -1, NULL, NULL, NULL);
+}
+
 /*
  * Returns the string version of the time that the user
  * will need to free.  Requires the user pass in the
Index: gui/gdmcomm.c
===================================================================
--- gui/gdmcomm.c	(revision 4696)
+++ gui/gdmcomm.c	(working copy)
@@ -41,6 +41,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 static gboolean bulk_acs = FALSE;
 static gboolean debug    = FALSE;
Index: gui/gdmcommon.h
===================================================================
--- gui/gdmcommon.h	(revision 4696)
+++ gui/gdmcommon.h	(working copy)
@@ -1,4 +1,6 @@
-/* GDM - The Gnome Display Manager
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * GDM - The Gnome Display Manager
  * Copyright (C) 1999, 2000 Martin K. Petersen <mkp@mkp.net>
  *
  * This file Copyright (c) 2003 George Lebl
Index: gui/gdmflexiserver.c
===================================================================
--- gui/gdmflexiserver.c	(revision 4696)
+++ gui/gdmflexiserver.c	(working copy)
@@ -43,6 +43,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 static GSList *xservers          = NULL;
 static const char *send_command  = NULL;
Index: gui/Makefile.am
===================================================================
--- gui/Makefile.am	(revision 4696)
+++ gui/Makefile.am	(working copy)
@@ -4,16 +4,20 @@ SUBDIRS = . greeter modules faces
 
 ## Process this file with automake to produce makefile.in
 DEFS = @DEFS@ \
-	-DPREFIX=\"@prefix@\" \
-	-DAUTHDIR=\"@authdir@\" \
-	-DDATADIR=\"@datadir@\" \
-	-DDMCONFDIR=\"@dmconfdir@\" \
-	-DGDMLOCALEDIR=\"@gdmlocaledir@\" \
-	-DGDM_GLADE_DIR=\"@datadir@/gdm\" \
-	-DLIBDIR=\"@libdir@\" \
-	-DLIBEXECDIR=\"@libexecdir@\" \
-	-DPIXMAPDIR=\"@pixmapdir@\" \
-	-DSBINDIR=\"@sbindir@\"
+	-DPREFIX=\"@prefix@\" 				\
+	-DAUTHDIR=\"@authdir@\" 			\
+	-DBINDIR=\"@bindir@\" 				\
+	-DDATADIR=\"@datadir@\" 			\
+	-DDMCONFDIR=\"@dmconfdir@\" 			\
+	-DGDMCONFDIR=\"@gdmconfdir@\"			\
+	-DGDMLOCALEDIR=\"@gdmlocaledir@\" 		\
+	-DGDM_GLADE_DIR=\"@datadir@/gdm\" 		\
+	-DLIBDIR=\"@libdir@\" 				\
+	-DLIBEXECDIR=\"@libexecdir@\" 			\
+	-DLOGDIR=\"@logdir@\"				\
+	-DPIXMAPDIR=\"@pixmapdir@\" 			\
+	-DSBINDIR=\"@sbindir@\"				\
+	$(NULL)
 
 INCLUDES = \
 	-I.						\
Index: gui/gdmsetup.c
===================================================================
--- gui/gdmsetup.c	(revision 4696)
+++ gui/gdmsetup.c	(working copy)
@@ -50,6 +50,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 static char     *GdmSoundProgram = NULL;
 static gchar    *GdmExclude      = NULL;
@@ -492,6 +493,15 @@ radiogroup_timeout (GtkWidget *toggle)
 }
 
 static gboolean
+bool_equal (gboolean a, gboolean b)
+{
+	if ((a && b) || (!a && !b))
+		return TRUE;
+	else
+		return FALSE;
+}
+
+static gboolean
 toggle_timeout (GtkWidget *toggle)
 {
 	const char *key = g_object_get_data (G_OBJECT (toggle), "key");
@@ -500,7 +510,7 @@ toggle_timeout (GtkWidget *toggle)
 	if (strcmp (ve_sure_string (key), GDM_KEY_ENTRY_INVISIBLE) == 0) {
 		/* This is a lil bit back to front
 		   true is false and false is true in this case */
-		if ( ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) {
+		if ( bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) {
 			gdm_setup_config_set_bool (key, !GTK_TOGGLE_BUTTON (toggle)->active);
 		}
 	}
@@ -595,7 +605,7 @@ toggle_timeout (GtkWidget *toggle)
 	}	
 	else {
 		/* All other cases */
-		if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) {
+		if ( ! bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) {
 			gdm_setup_config_set_bool (key, GTK_TOGGLE_BUTTON (toggle)->active);
 		}
 	}	
@@ -914,6 +924,46 @@ gdm_load_displays (GKeyFile *cfg,
 	}
 }
 
+static char *
+ve_rest (const char *s)
+{
+	const char *p;
+	gboolean single_quot = FALSE;
+	gboolean double_quot = FALSE;
+	gboolean escape = FALSE;
+
+	if (s == NULL)
+		return NULL;
+
+	for (p = s; *p != '\0'; p++) {
+		if (single_quot) {
+			if (*p == '\'') {
+				single_quot = FALSE;
+			}
+		} else if (escape) {
+			escape = FALSE;
+		} else if (double_quot) {
+			if (*p == '"') {
+				double_quot = FALSE;
+			} else if (*p == '\\') {
+				escape = TRUE;
+			}
+		} else if (*p == '\'') {
+			single_quot = TRUE;
+		} else if (*p == '"') {
+			double_quot = TRUE;
+		} else if (*p == '\\') {
+			escape = TRUE;
+		} else if (*p == ' ' || *p == '\t') {
+			while (*p == ' ' || *p == '\t')
+				p++;
+			return g_strdup (p);
+		}
+	}
+
+	return NULL;
+}
+
 static void
 xservers_get_displays (GtkListStore *store)
 {
@@ -1452,7 +1502,7 @@ combobox_timeout (GtkWidget *combo_box)
 				val_new = (gtk_combo_box_get_active (GTK_COMBO_BOX (style_combobox)) != 0);
 
 				/* Update this servers configuration */
-				if (! ve_bool_equal (val_old, val_new)) {
+				if (! bool_equal (val_old, val_new)) {
 					svr->chooser = val_new;
 					update_xserver (section, svr);
 				}
@@ -3171,7 +3221,7 @@ greeter_toggle_timeout (GtkWidget *toggl
 	const char *key = g_object_get_data (G_OBJECT (toggle), "key");
 	gboolean val = gdm_config_get_bool ((gchar *)key);
 
-	if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) {
+	if ( ! bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) {
 	
 		if (strcmp (ve_sure_string (key), GDM_KEY_BACKGROUND_SCALE_TO_FIT) == 0) {
 	
@@ -5206,8 +5256,7 @@ get_archive_dir (gchar *filename, char *
 		return NULL;
 	}
 
-	/* Note that this adds './' In front to avoid troubles */
-	quoted = ve_shell_quote_filename (filename);
+	quoted = g_shell_quote (filename);
 	tar = find_tar ();
 	unzip = find_unzip (filename);
 
@@ -5835,7 +5884,7 @@ xserver_toggle_timeout (GtkWidget *toggl
 			}
 
 			/* Update this servers configuration */
-			if ( ! ve_bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) {
+			if ( ! bool_equal (val, GTK_TOGGLE_BUTTON (toggle)->active)) {
 				gboolean new_val = GTK_TOGGLE_BUTTON (toggle)->active;
 
 				if (strcmp (ve_sure_string (key),
Index: gui/gdmchooser.c
===================================================================
--- gui/gdmchooser.c	(revision 4696)
+++ gui/gdmchooser.c	(working copy)
@@ -60,6 +60,7 @@
 #include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config-keys.h"
 
 static gboolean RUNNING_UNDER_GDM = FALSE;
 
Index: gui/misc.c
===================================================================
--- gui/misc.c	(revision 4696)
+++ gui/misc.c	(working copy)
@@ -106,8 +106,7 @@ gdm_set_theme (const char *theme_name)
 gboolean
 gdm_working_command_exists (const char *commands)
 {
-	char *command = ve_get_first_working_command
-		(commands, TRUE /* only_existance */);
+	char *command = ve_get_first_working_command (commands, TRUE /* only_existance */);
 	if (command == NULL)
 		return FALSE;
 	g_free (command);
Index: common/gdm-config.h
===================================================================
--- common/gdm-config.h	(revision 0)
+++ common/gdm-config.h	(revision 0)
@@ -0,0 +1,190 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GDM_CONFIG_H
+#define _GDM_CONFIG_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GdmConfig GdmConfig;
+
+typedef enum {
+        GDM_CONFIG_VALUE_INVALID,
+        GDM_CONFIG_VALUE_BOOL,
+        GDM_CONFIG_VALUE_INT,
+        GDM_CONFIG_VALUE_STRING,
+        GDM_CONFIG_VALUE_STRING_ARRAY,
+} GdmConfigValueType;
+
+typedef enum {
+        GDM_CONFIG_SOURCE_INVALID,
+        GDM_CONFIG_SOURCE_MANDATORY,
+        GDM_CONFIG_SOURCE_DEFAULT,
+        GDM_CONFIG_SOURCE_CUSTOM,
+        GDM_CONFIG_SOURCE_BUILT_IN,
+        GDM_CONFIG_SOURCE_RUNTIME_USER,
+} GdmConfigSourceType;
+
+#define GDM_CONFIG_INVALID_ID -1
+
+struct _GdmConfigValue
+{
+	GdmConfigValueType type;
+};
+
+typedef struct _GdmConfigValue GdmConfigValue;
+
+typedef gboolean (* GdmConfigFunc) (GdmConfig          *config,
+				    GdmConfigSourceType source,
+				    const char         *group,
+				    const char         *key,
+				    GdmConfigValue     *value,
+				    int                 id,
+				    gpointer            data);
+
+typedef struct {
+	char              *group;
+	char              *key;
+	GdmConfigValueType type;
+	char              *default_value;
+	int                id;
+} GdmConfigEntry;
+
+#define GDM_CONFIG_ERROR (gdm_config_error_quark ())
+
+typedef enum
+{
+	GDM_CONFIG_ERROR_UNKNOWN_OPTION,
+	GDM_CONFIG_ERROR_BAD_VALUE,
+	GDM_CONFIG_ERROR_PARSE_ERROR,
+	GDM_CONFIG_ERROR_FAILED
+} GdmConfigError;
+
+GQuark                 gdm_config_error_quark            (void);
+
+GdmConfig *            gdm_config_new                    (void);
+void                   gdm_config_free                   (GdmConfig       *config);
+
+void                   gdm_config_set_validate_func      (GdmConfig       *config,
+							  GdmConfigFunc    func,
+							  gpointer         data);
+void                   gdm_config_set_notify_func        (GdmConfig       *config,
+							  GdmConfigFunc    func,
+							  gpointer         data);
+void                   gdm_config_set_default_file       (GdmConfig       *config,
+							  const char      *name);
+void                   gdm_config_set_mandatory_file     (GdmConfig       *config,
+							  const char      *name);
+void                   gdm_config_set_custom_file        (GdmConfig       *config,
+							  const char      *name);
+void                   gdm_config_add_entry              (GdmConfig            *config,
+							  const GdmConfigEntry *entry);
+void                   gdm_config_add_static_entries     (GdmConfig            *config,
+							  const GdmConfigEntry *entries);
+const GdmConfigEntry * gdm_config_lookup_entry           (GdmConfig            *config,
+							  const char           *group,
+							  const char           *key);
+const GdmConfigEntry * gdm_config_lookup_entry_for_id    (GdmConfig            *config,
+							  int                   id);
+
+gboolean               gdm_config_load                   (GdmConfig             *config,
+							  GError               **error);
+gboolean               gdm_config_process_all            (GdmConfig             *config,
+							  GError               **error);
+gboolean               gdm_config_process_entry          (GdmConfig             *config,
+							  const GdmConfigEntry  *entry,
+							  GError               **error);
+gboolean               gdm_config_process_entries        (GdmConfig             *config,
+							  const GdmConfigEntry **entries,
+							  gsize                  n_entries,
+							  GError               **error);
+
+gboolean               gdm_config_save_custom_file       (GdmConfig       *config,
+							  GError         **error);
+char **                gdm_config_get_keys_for_group     (GdmConfig       *config,
+							  const gchar     *group_name,
+							  gsize           *length,
+							  GError         **error);
+
+
+gboolean               gdm_config_get_value              (GdmConfig       *config,
+							  const char      *group,
+							  const char      *key,
+							  GdmConfigValue **value);
+gboolean               gdm_config_set_value              (GdmConfig       *config,
+							  const char      *group,
+							  const char      *key,
+							  GdmConfigValue  *value);
+
+gboolean               gdm_config_get_value_for_id       (GdmConfig       *config,
+							  int              id,
+							  GdmConfigValue **value);
+gboolean               gdm_config_set_value_for_id       (GdmConfig       *config,
+							  int              id,
+							  GdmConfigValue  *value);
+
+gboolean               gdm_config_get_string_for_id      (GdmConfig       *config,
+							  int              id,
+							  char           **str);
+gboolean               gdm_config_get_bool_for_id        (GdmConfig       *config,
+							  int              id,
+							  gboolean        *bool);
+gboolean               gdm_config_set_string_for_id      (GdmConfig       *config,
+							  int              id,
+							  char            *str);
+gboolean               gdm_config_set_bool_for_id        (GdmConfig       *config,
+							  int              id,
+							  gboolean         bool);
+
+/* Config Values */
+
+GdmConfigValue *     gdm_config_value_new              (GdmConfigValueType    type);
+void                 gdm_config_value_free             (GdmConfigValue       *value);
+GdmConfigValue *     gdm_config_value_copy             (const GdmConfigValue *value);
+int                  gdm_config_value_compare          (const GdmConfigValue *value_a,
+							const GdmConfigValue *value_b);
+
+GdmConfigValue *     gdm_config_value_new_from_string  (GdmConfigValueType    type,
+							const char           *str,
+							GError              **error);
+const char *         gdm_config_value_get_string       (const GdmConfigValue *value);
+int                  gdm_config_value_get_int          (const GdmConfigValue *value);
+gboolean             gdm_config_value_get_bool         (const GdmConfigValue *value);
+
+void                 gdm_config_value_set_string       (GdmConfigValue  *value,
+							const char      *str);
+
+void                 gdm_config_value_set_string_array (GdmConfigValue  *value,
+							const char     **array);
+void                 gdm_config_value_set_int          (GdmConfigValue  *value,
+							int              integer);
+void                 gdm_config_value_set_bool         (GdmConfigValue  *value,
+							gboolean         bool);
+char *               gdm_config_value_to_string        (const GdmConfigValue *value);
+
+/* Config Entries */
+GdmConfigEntry *     gdm_config_entry_copy             (const GdmConfigEntry *entry);
+void                 gdm_config_entry_free             (GdmConfigEntry       *entry);
+
+G_END_DECLS
+
+#endif /* _GDM_CONFIG_H */
Index: common/gdm-common-config.c
===================================================================
--- common/gdm-common-config.c	(revision 4696)
+++ common/gdm-common-config.c	(working copy)
@@ -104,6 +104,41 @@ gdm_common_config_load (const char *file
 	return config;
 }
 
+GKeyFile *
+gdm_common_config_load_from_dirs (const char  *filename,
+				  const char **dirs,
+				  GError     **error)
+{
+	GKeyFile *config;
+	int       i;
+
+	config = NULL;
+
+	/* FIXME: hope to have g_key_file_load_from_dirs
+	   see GNOME bug #355334
+	 */
+
+	for (i = 0; dirs[i] != NULL; i++) {
+		char *path;
+
+		path = g_build_filename (dirs[i], filename, NULL);
+		config = gdm_common_config_load (path, NULL);
+		g_free (path);
+		if (config != NULL) {
+			break;
+		}
+	}
+
+	if (config == NULL) {
+		g_set_error (error,
+			     G_KEY_FILE_ERROR,
+			     G_KEY_FILE_ERROR_NOT_FOUND,
+			     "Unable to find file in specified directories");
+	}
+
+	return config;
+}
+
 gboolean
 gdm_common_config_save (GKeyFile   *config,
 			const char *filename,
@@ -239,7 +274,11 @@ gdm_common_config_get_string (GKeyFile  
 
 	group = key = default_value = NULL;
 	if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) {
-		g_set_error (error, G_KEY_FILE_ERROR, G_KEY_FILE_ERROR_PARSE, "Unable to parse key: %s", keystring);
+		g_set_error (error,
+			     G_KEY_FILE_ERROR,
+			     G_KEY_FILE_ERROR_PARSE,
+			     "Unable to parse key: %s",
+			     keystring);
 		return FALSE;
 	}
 
@@ -264,6 +303,50 @@ gdm_common_config_get_string (GKeyFile  
 }
 
 gboolean
+gdm_common_config_get_string_list (GKeyFile   *config,
+				   const char *keystring,
+				   char     ***value,
+				   gsize      *length,
+				   GError    **error)
+{
+	char   *group;
+	char   *key;
+	char   *default_value;
+	char  **val;
+	GError *local_error;
+
+	group = key = default_value = NULL;
+	if (! gdm_common_config_parse_key_string (keystring, &group, &key, &default_value)) {
+		g_set_error (error,
+			     G_KEY_FILE_ERROR,
+			     G_KEY_FILE_ERROR_PARSE,
+			     "Unable to parse key: %s",
+			     keystring);
+		return FALSE;
+	}
+
+	local_error = NULL;
+	val = g_key_file_get_string_list (config,
+					  group,
+					  key,
+					  length,
+					  &local_error);
+	if (local_error != NULL) {
+		/* use the default */
+		val = g_strsplit (default_value, ";", -1);
+		g_propagate_error (error, local_error);
+	}
+
+	*value = val;
+
+	g_free (key);
+	g_free (group);
+	g_free (default_value);
+
+	return TRUE;
+}
+
+gboolean
 gdm_common_config_get_boolean (GKeyFile   *config,
 			       const char *keystring,
 			       gboolean   *value,
Index: common/gdm-common.h
===================================================================
--- common/gdm-common.h	(revision 4696)
+++ common/gdm-common.h	(working copy)
@@ -32,41 +32,21 @@
 
 #include "ve-signal.h"
 #include "gdm-common-config.h"
+#include "gdm-config.h"
 
 G_BEGIN_DECLS
 void           ve_clearenv (void);
 char *	       ve_first_word (const char *s);
 gboolean       ve_first_word_executable (const char *s,
 				   gboolean only_existance);
-char *         ve_rest (const char *s);
 
 /* Gets the first existing command out of a list separated by semicolons */
 char *	       ve_get_first_working_command (const char *list,
 					     gboolean only_existance);
 
-gboolean       ve_bool_equal (gboolean a, gboolean b);
-
-gboolean       ve_is_string_in_list (const GList *list,
-				     const char *string);
-gboolean       ve_is_string_in_list_case_no_locale (const GList *list,
-						    const char *string);
-
 #define        ve_string_empty(x) ((x)==NULL||(x)[0]=='\0')
 #define        ve_sure_string(x) ((x)!=NULL?(x):"")
 
-/* Find a file using the specified list of directories, an absolute path is
- * just checked, whereas a relative path is search in the given directories,
- */
-char *	       ve_find_file_simple		(const char *filename,
-						 const GList *directories);
-
-/* Find a file using the specified list of directories, an absolute path is
- * just checked, whereas a relative path is search in the given directories,
- * gnome_datadir, g_get_prgname() subdirectory, in GNOME_PATH
- * under /share/ and /share/<g_get_prgname()> */
-char *	       ve_find_file			(const char *filename,
-						 const GList *directories);
-
 /* These two functions will ALWAYS return a non-NULL string,
  * if there is an error, they return the unconverted string */
 char *         ve_locale_to_utf8 (const char *str);
@@ -77,20 +57,12 @@ char *         ve_locale_from_utf8 (cons
 char *         ve_filename_to_utf8 (const char *str);
 char *         ve_filename_from_utf8 (const char *str);
 
-/* works with utf-8 strings and always returns something */
-char *         ve_strftime (struct tm *the_tm, const char *format);
-
 /* function which doesn't stop on signals */
 pid_t          ve_waitpid_no_signal (pid_t pid, int *status, int options);
 
 /* Testing for existance of a certain locale */
 gboolean       ve_locale_exists (const char *loc);
 
-char *         ve_find_prog_in_path (const char *prog, const char *path);
-gboolean       ve_is_prog_in_path (const char *prog, const char *path);
-
-char          *ve_shell_quote_filename (const char *name);
-
 #define VE_IGNORE_EINTR(expr) \
 	do {		\
 		errno = 0;	\
Index: common/test-config.c
===================================================================
--- common/test-config.c	(revision 0)
+++ common/test-config.c	(revision 0)
@@ -0,0 +1,294 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <pwd.h>
+#include <string.h>
+#include <errno.h>
+
+#include <locale.h>
+
+#include <glib.h>
+
+#include "gdm-common.h"
+
+#include "../daemon/gdm-daemon-config-entries.h"
+
+static const char *
+source_to_name (GdmConfigSourceType source)
+{
+        const char *name;
+
+        switch (source) {
+        case GDM_CONFIG_SOURCE_DEFAULT:
+                name = "default";
+                break;
+        case GDM_CONFIG_SOURCE_MANDATORY:
+                name = "mandatory";
+                break;
+        case GDM_CONFIG_SOURCE_CUSTOM:
+                name = "custom";
+                break;
+        case GDM_CONFIG_SOURCE_BUILT_IN:
+                name = "built-in";
+                break;
+        case GDM_CONFIG_SOURCE_RUNTIME_USER:
+                name = "runtime-user";
+                break;
+        case GDM_CONFIG_SOURCE_INVALID:
+                name = "Invalid";
+                break;
+        default:
+                name = "Unknown";
+                break;
+        }
+
+        return name;
+}
+
+static const char *
+type_to_name (GdmConfigValueType type)
+{
+        const char *name;
+
+        switch (type) {
+        case GDM_CONFIG_VALUE_INT:
+                name = "int";
+                break;
+        case GDM_CONFIG_VALUE_BOOL:
+                name = "boolean";
+                break;
+        case GDM_CONFIG_VALUE_STRING:
+                name = "string";
+                break;
+        case GDM_CONFIG_VALUE_STRING_ARRAY:
+                name = "string-array";
+                break;
+        case GDM_CONFIG_VALUE_INVALID:
+                name = "invalid";
+                break;
+        default:
+                name = "unknown";
+                break;
+        }
+
+        return name;
+}
+
+static gboolean
+notify_cb (GdmConfig          *config,
+           GdmConfigSourceType source,
+           const char         *group,
+           const char         *key,
+           GdmConfigValue     *value,
+           int                 id,
+           gpointer            data)
+{
+        char *str;
+
+        if (value == NULL) {
+                return FALSE;
+        }
+
+        str = gdm_config_value_to_string (value);
+
+        g_print ("SOURCE=%s GROUP=%s KEY=%s ID=%d TYPE=%s VALUE=%s\n", source_to_name (source), group, key, id, type_to_name (value->type), str);
+        if (strcmp (group, GDM_CONFIG_GROUP_CUSTOM_CMD) == 0 &&
+            g_str_has_prefix (key, "CustomCommand") &&
+            strlen (key) == 14) {
+                g_message ("NOTIFY: Custom command");
+        }
+
+        g_free (str);
+        return TRUE;
+}
+
+static gboolean
+validate_cb (GdmConfig          *config,
+             GdmConfigSourceType source,
+             const char         *group,
+             const char         *key,
+             GdmConfigValue     *value,
+             int                 id,
+             gpointer            data)
+{
+        /* Here you can do validation or override the values */
+
+        switch (id) {
+        case GDM_ID_SOUND_PROGRAM:
+                gdm_config_value_set_string (value, "NONE");
+                break;
+        case GDM_ID_NONE:
+        default:
+                /* doesn't have an ID : match group/key */
+                break;
+        }
+
+        return TRUE;
+}
+
+static void
+load_servers_group (GdmConfig *config)
+{
+        char     **keys;
+        gsize      len;
+        int        i;
+
+        keys = gdm_config_get_keys_for_group (config, GDM_CONFIG_GROUP_SERVERS, &len, NULL);
+        g_message ("Got %d keys for group %s", len, GDM_CONFIG_GROUP_SERVERS);
+
+        /* now construct entries for these groups */
+        for (i = 0; i < len; i++) {
+                GdmConfigEntry  entry;
+                GdmConfigValue *value;
+                char           *new_group;
+                gboolean        res;
+                int             j;
+
+                entry.group = GDM_CONFIG_GROUP_SERVERS;
+                entry.key = keys[i];
+                entry.type = GDM_CONFIG_VALUE_STRING;
+                entry.default_value = NULL;
+                entry.id = GDM_CONFIG_INVALID_ID;
+
+                gdm_config_add_entry (config, &entry);
+                gdm_config_process_entry (config, &entry, NULL);
+
+                res = gdm_config_get_value (config, entry.group, entry.key, &value);
+                if (! res) {
+                        continue;
+                }
+
+                new_group = g_strdup_printf ("server-%s", gdm_config_value_get_string (value));
+                gdm_config_value_free (value);
+
+                for (j = 0; j < G_N_ELEMENTS (gdm_daemon_server_config_entries); j++) {
+                        GdmConfigEntry *srv_entry;
+                        if (gdm_daemon_server_config_entries[j].key == NULL) {
+                                continue;
+                        }
+                        srv_entry = gdm_config_entry_copy (&gdm_daemon_server_config_entries[j]);
+                        g_free (srv_entry->group);
+                        srv_entry->group = g_strdup (new_group);
+                        gdm_config_process_entry (config, srv_entry, NULL);
+                        gdm_config_entry_free (srv_entry);
+                }
+                g_free (new_group);
+        }
+}
+
+static void
+test_config (void)
+{
+        GdmConfig *config;
+        GError    *error;
+        int        i;
+
+        config = gdm_config_new ();
+
+        gdm_config_set_notify_func (config, notify_cb, NULL);
+        gdm_config_set_validate_func (config, validate_cb, NULL);
+
+        gdm_config_add_static_entries (config, gdm_daemon_config_entries);
+
+        /* At first try loading with only defaults */
+        gdm_config_set_default_file (config, DATADIR "/gdm/defaults.conf");
+
+        g_message ("Loading configuration: Default source only");
+
+        /* load the data files */
+        error = NULL;
+        gdm_config_load (config, &error);
+        if (error != NULL) {
+                g_warning ("Unable to load configuration: %s", error->message);
+                g_error_free (error);
+        } else {
+                /* populate the database with all specified entries */
+                gdm_config_process_all (config, &error);
+        }
+
+        g_message ("Getting all standard values");
+        /* now test retrieving these values */
+        for (i = 0; gdm_daemon_config_entries [i].group != NULL; i++) {
+                GdmConfigValue       *value;
+                const GdmConfigEntry *entry;
+                gboolean              res;
+                char                 *str;
+
+                entry = &gdm_daemon_config_entries [i];
+
+                res = gdm_config_get_value (config, entry->group, entry->key, &value);
+                if (! res) {
+                        g_warning ("Unable to lookup entry g=%s k=%s", entry->group, entry->key);
+                        continue;
+                }
+
+                str = gdm_config_value_to_string (value);
+
+                g_print ("Got g=%s k=%s: %s\n", entry->group, entry->key, str);
+
+                g_free (str);
+                gdm_config_value_free (value);
+        }
+
+        g_message ("Setting values");
+        /* now test setting a few values */
+        {
+                GdmConfigValue *value;
+                value = gdm_config_value_new_from_string  (GDM_CONFIG_VALUE_BOOL, "false", NULL);
+                gdm_config_set_value (config, "greeter", "ShowLastSession", value);
+                /* should only see one notification */
+                gdm_config_set_value (config, "greeter", "ShowLastSession", value);
+                gdm_config_value_free (value);
+        }
+
+        g_message ("Loading the server entries");
+        load_servers_group (config);
+
+        g_message ("Loading configuration: Default and Custom sources");
+        /* Now try adding a custom config */
+        gdm_config_set_custom_file (config, GDMCONFDIR "/custom.conf");
+        /* load the data files */
+        error = NULL;
+        gdm_config_load (config, &error);
+        if (error != NULL) {
+                g_warning ("Unable to load configuration: %s", error->message);
+                g_error_free (error);
+        } else {
+                /* populate the database with all specified entries */
+                gdm_config_process_all (config, &error);
+        }
+
+        gdm_config_free (config);
+}
+
+int
+main (int argc, char **argv)
+{
+
+        test_config ();
+
+	return 0;
+}
Index: common/gdm-common-config.h
===================================================================
--- common/gdm-common-config.h	(revision 4696)
+++ common/gdm-common-config.h	(working copy)
@@ -27,6 +27,9 @@ G_BEGIN_DECLS
 
 GKeyFile * gdm_common_config_load             (const char *filename,
 					       GError    **error);
+GKeyFile * gdm_common_config_load_from_dirs   (const char  *filename,
+					       const char **dirs,
+					       GError    **error);
 gboolean   gdm_common_config_save             (GKeyFile   *config,
 					       const char *filename,
 					       GError    **error);
@@ -35,10 +38,15 @@ gboolean   gdm_common_config_get_string 
 					       const char *keystring,
 					       char      **value,
 					       GError    **error);
-gboolean   gdm_common_config_get_translated_string       (GKeyFile   *config,
-							  const char *keystring,
-							  char      **value,
-							  GError    **error);
+gboolean   gdm_common_config_get_translated_string (GKeyFile   *config,
+						    const char *keystring,
+						    char      **value,
+						    GError    **error);
+gboolean   gdm_common_config_get_string_list       (GKeyFile   *config,
+						    const char *keystring,
+						    char     ***value,
+						    gsize      *length,
+						    GError    **error);
 gboolean   gdm_common_config_get_int          (GKeyFile   *config,
 					       const char *keystring,
 					       int        *value,
Index: common/Makefile.am
===================================================================
--- common/Makefile.am	(revision 4696)
+++ common/Makefile.am	(working copy)
@@ -6,6 +6,21 @@ INCLUDES = \
 	-I.					\
 	-I..					\
 	-DGNOMELOCALEDIR=\""$(datadir)/locale"\" \
+	-DAUTHDIR=\"$(authdir)\"			\
+	-DBINDIR=\"$(bindir)\"				\
+	-DDATADIR=\"$(datadir)\"			\
+	-DDMCONFDIR=\"$(dmconfdir)\"			\
+	-DGDMCONFDIR=\"$(gdmconfdir)\"			\
+	-DGDMLOCALEDIR=\"$(gdmlocaledir)\"		\
+	-DLIBDIR=\"$(libdir)\"				\
+	-DLIBEXECDIR=\"$(libexecdir)\"			\
+	-DLOGDIR=\"$(logdir)\"				\
+	-DPIXMAPDIR=\"$(pixmapdir)\"			\
+	-DSBINDIR=\"$(sbindir)\"			\
+	-DGNOMELOCALEDIR=\""$(datadir)/locale"\"	\
+	-DGDM_DEFAULTS_CONF=\"$(GDM_DEFAULTS_CONF)\"	\
+	-DGDM_CUSTOM_CONF=\"$(GDM_CUSTOM_CONF)\"	\
+	-DGDM_OLD_CONF=\"$(GDM_OLD_CONF)\"		\
 	$(GLIB_CFLAGS)
 
 noinst_LIBRARIES = 		\
@@ -17,14 +32,22 @@ libgdmcommon_a_SOURCES =	\
 	gdm-common.c		\
 	gdm-common-config.h	\
 	gdm-common-config.c	\
+	gdm-config.h		\
+	gdm-config.c		\
 	ve-signal.h		\
 	ve-signal.c		\
 	$(NULL)
 
-libgdmcommon_ui_a_SOURCES = 	\
-	$(libgdmcommon_a_SOURCES) \
-	glade-helper.c		\
-	glade-helper.h		\
-	gdm-common-ui.c		\
-	gdm-common-ui.h		\
+noinst_PROGRAMS = 		\
+	test-config		\
+	$(NULL)
+
+test_config_SOURCES = 		\
+	$(top_builddir)/daemon/gdm-daemon-config-entries.h	\
+	test-config.c	 	\
+	$(NULL)
+
+test_config_LDADD =		\
+	$(top_builddir)/common/libgdmcommon.a	\
+	$(GLIB_LIBS)		\
 	$(NULL)
Index: common/gdm-config.c
===================================================================
--- common/gdm-config.c	(revision 0)
+++ common/gdm-config.c	(revision 0)
@@ -0,0 +1,1278 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <syslog.h>
+#include <errno.h>
+#include <sys/stat.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+#include <glib/gi18n.h>
+
+#include "gdm-config.h"
+
+struct _GdmConfig
+{
+	char            *mandatory_filename;
+	char            *default_filename;
+	char            *custom_filename;
+
+	gboolean         mandatory_loaded;
+	gboolean         default_loaded;
+	gboolean         custom_loaded;
+
+	GKeyFile        *mandatory_key_file;
+	GKeyFile        *default_key_file;
+	GKeyFile        *custom_key_file;
+
+	time_t           mandatory_mtime;
+	time_t           default_mtime;
+	time_t           custom_mtime;
+
+	GPtrArray       *entries;
+
+	GHashTable      *value_hash;
+
+	GdmConfigFunc    validate_func;
+	gpointer         validate_func_data;
+	GdmConfigFunc    notify_func;
+	gpointer         notify_func_data;
+};
+
+
+typedef struct _GdmConfigRealValue
+{
+	GdmConfigValueType type;
+	union {
+		gboolean bool;
+		int      integer;
+		char    *str;
+		char   **array;
+	} val;
+} GdmConfigRealValue;
+
+#define REAL_VALUE(x) ((GdmConfigRealValue *)(x))
+
+GQuark
+gdm_config_error_quark (void)
+{
+	return g_quark_from_static_string ("gdm-config-error-quark");
+}
+
+GdmConfigEntry *
+gdm_config_entry_copy (const GdmConfigEntry *src)
+{
+	GdmConfigEntry *dest;
+
+	dest = g_new0 (GdmConfigEntry, 1);
+	dest->group = g_strdup (src->group);
+	dest->key = g_strdup (src->key);
+	dest->default_value = g_strdup (src->default_value);
+	dest->type = src->type;
+	dest->id = src->id;
+
+	return dest;
+}
+
+void
+gdm_config_entry_free (GdmConfigEntry *entry)
+{
+	g_free (entry->group);
+	g_free (entry->key);
+	g_free (entry->default_value);
+
+	g_free (entry);
+}
+
+GdmConfigValue *
+gdm_config_value_new (GdmConfigValueType type)
+{
+	GdmConfigValue *value;
+
+	g_return_val_if_fail (type != GDM_CONFIG_VALUE_INVALID, NULL);
+
+	value = (GdmConfigValue *) g_slice_new0 (GdmConfigRealValue);
+	value->type = type;
+
+	return value;
+}
+
+void
+gdm_config_value_free (GdmConfigValue *value)
+{
+	GdmConfigRealValue *real;
+
+	real = REAL_VALUE (value);
+
+	switch (real->type) {
+        case GDM_CONFIG_VALUE_INVALID:
+        case GDM_CONFIG_VALUE_BOOL:
+        case GDM_CONFIG_VALUE_INT:
+		break;
+        case GDM_CONFIG_VALUE_STRING:
+		g_free (real->val.str);
+		break;
+	case GDM_CONFIG_VALUE_STRING_ARRAY:
+		g_strfreev (real->val.array);
+		break;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
+
+	g_slice_free (GdmConfigRealValue, real);
+}
+
+static void
+set_string (char      **dest,
+	    const char *src)
+{
+	if (*dest != NULL) {
+		g_free (*dest);
+	}
+
+	*dest = src ? g_strdup (src) : NULL;
+}
+
+static void
+set_string_array (char      ***dest,
+		  const char **src)
+{
+	if (*dest != NULL) {
+		g_strfreev (*dest);
+	}
+
+	*dest = src ? g_strdupv ((char **)src) : NULL;
+}
+
+GdmConfigValue *
+gdm_config_value_copy (const GdmConfigValue *src)
+{
+	GdmConfigRealValue *dest;
+	GdmConfigRealValue *real;
+
+	g_return_val_if_fail (src != NULL, NULL);
+
+	real = REAL_VALUE (src);
+	dest = REAL_VALUE (gdm_config_value_new (src->type));
+
+	switch (real->type) {
+	case GDM_CONFIG_VALUE_INT:
+	case GDM_CONFIG_VALUE_BOOL:
+	case GDM_CONFIG_VALUE_INVALID:
+		dest->val = real->val;
+		break;
+	case GDM_CONFIG_VALUE_STRING:
+		set_string (&dest->val.str, real->val.str);
+		break;
+	case GDM_CONFIG_VALUE_STRING_ARRAY:
+		set_string_array (&dest->val.array, (const char **)real->val.array);
+		break;
+	default:
+		g_assert_not_reached();
+	}
+
+	return (GdmConfigValue *) dest;
+}
+
+const char *
+gdm_config_value_get_string (const GdmConfigValue *value)
+{
+	g_return_val_if_fail (value != NULL, NULL);
+	g_return_val_if_fail (value->type == GDM_CONFIG_VALUE_STRING, NULL);
+	return REAL_VALUE (value)->val.str;
+}
+
+gboolean
+gdm_config_value_get_bool (const GdmConfigValue *value)
+{
+	g_return_val_if_fail (value != NULL, FALSE);
+	g_return_val_if_fail (value->type == GDM_CONFIG_VALUE_BOOL, FALSE);
+	return REAL_VALUE (value)->val.bool;
+}
+
+int
+gdm_config_value_get_int (const GdmConfigValue *value)
+{
+	g_return_val_if_fail (value != NULL, 0);
+	g_return_val_if_fail (value->type == GDM_CONFIG_VALUE_INT, 0);
+	return REAL_VALUE (value)->val.integer;
+}
+
+/* based on code from gconf */
+int
+gdm_config_value_compare (const GdmConfigValue *value_a,
+			  const GdmConfigValue *value_b)
+{
+	g_return_val_if_fail (value_a != NULL, 0);
+	g_return_val_if_fail (value_b != NULL, 0);
+
+	if (value_a->type < value_b->type) {
+		return -1;
+	} else if (value_a->type > value_b->type) {
+		return 1;
+	}
+
+	switch (value_a->type) {
+	case GDM_CONFIG_VALUE_INT:
+		if (gdm_config_value_get_int (value_a) < gdm_config_value_get_int (value_b)) {
+			return -1;
+		} else if (gdm_config_value_get_int (value_a) > gdm_config_value_get_int (value_b)) {
+			return 1;
+		} else {
+			return 0;
+		}
+	case GDM_CONFIG_VALUE_STRING:
+		return strcmp (gdm_config_value_get_string (value_a),
+			       gdm_config_value_get_string (value_b));
+	case GDM_CONFIG_VALUE_STRING_ARRAY:
+		{
+			char *str_a;
+			char *str_b;
+			int   res;
+
+			str_a = gdm_config_value_to_string (value_a);
+			str_b = gdm_config_value_to_string (value_a);
+			res = strcmp (str_a, str_b);
+			g_free (str_a);
+			g_free (str_b);
+
+			return res;
+		}
+	case GDM_CONFIG_VALUE_BOOL:
+		if (gdm_config_value_get_bool (value_a) == gdm_config_value_get_bool (value_b)) {
+			return 0;
+		} else if (gdm_config_value_get_bool (value_a)) {
+			return 1;
+		} else {
+			return -1;
+		}
+	case GDM_CONFIG_VALUE_INVALID:
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/* based on code from gconf */
+GdmConfigValue *
+gdm_config_value_new_from_string (GdmConfigValueType type,
+				  const char        *value_str,
+				  GError           **error)
+{
+	GdmConfigValue *value;
+
+	g_return_val_if_fail (type != GDM_CONFIG_VALUE_INVALID, NULL);
+	g_return_val_if_fail (value_str != NULL, NULL);
+
+	value = gdm_config_value_new (type);
+
+        switch (value->type) {
+        case GDM_CONFIG_VALUE_INT:
+		{
+			char* endptr = NULL;
+			glong result;
+
+			errno = 0;
+			result = strtol (value_str, &endptr, 10);
+			if (endptr == value_str) {
+				g_set_error (error,
+					     GDM_CONFIG_ERROR,
+					     GDM_CONFIG_ERROR_PARSE_ERROR,
+					     _("Didn't understand `%s' (expected integer)"),
+					     value_str);
+				gdm_config_value_free (value);
+				value = NULL;
+			} else if (errno == ERANGE) {
+				g_set_error (error,
+					     GDM_CONFIG_ERROR,
+					     GDM_CONFIG_ERROR_PARSE_ERROR,
+					     _("Integer `%s' is too large or small"),
+					     value_str);
+				gdm_config_value_free (value);
+				value = NULL;
+			} else {
+				gdm_config_value_set_int (value, result);
+			}
+		}
+                break;
+        case GDM_CONFIG_VALUE_BOOL:
+		switch (*value_str) {
+		case 't':
+		case 'T':
+		case '1':
+		case 'y':
+		case 'Y':
+			gdm_config_value_set_bool (value, TRUE);
+			break;
+
+		case 'f':
+		case 'F':
+		case '0':
+		case 'n':
+		case 'N':
+			gdm_config_value_set_bool (value, FALSE);
+			break;
+		default:
+			g_set_error (error,
+				     GDM_CONFIG_ERROR,
+				     GDM_CONFIG_ERROR_PARSE_ERROR,
+				     _("Didn't understand `%s' (expected true or false)"),
+				     value_str);
+			gdm_config_value_free (value);
+			value = NULL;
+			break;
+		}
+		break;
+        case GDM_CONFIG_VALUE_STRING:
+		if (! g_utf8_validate (value_str, -1, NULL)) {
+			g_set_error (error,
+				     GDM_CONFIG_ERROR,
+				     GDM_CONFIG_ERROR_PARSE_ERROR,
+				     _("Text contains invalid UTF-8"));
+			gdm_config_value_free (value);
+			value = NULL;
+		} else {
+			gdm_config_value_set_string (value, value_str);
+		}
+                break;
+        case GDM_CONFIG_VALUE_STRING_ARRAY:
+		if (! g_utf8_validate (value_str, -1, NULL)) {
+			g_set_error (error,
+				     GDM_CONFIG_ERROR,
+				     GDM_CONFIG_ERROR_PARSE_ERROR,
+				     _("Text contains invalid UTF-8"));
+			gdm_config_value_free (value);
+			value = NULL;
+		} else {
+			char **split;
+			split = g_strsplit (value_str, ";", -1);
+			gdm_config_value_set_string_array (value, (const char **)split);
+			g_strfreev (split);
+		}
+                break;
+        case GDM_CONFIG_VALUE_INVALID:
+        default:
+		g_assert_not_reached ();
+                break;
+        }
+
+	return value;
+}
+
+void
+gdm_config_value_set_string_array (GdmConfigValue *value,
+				   const char    **array)
+{
+	GdmConfigRealValue *real;
+
+	g_return_if_fail (value != NULL);
+	g_return_if_fail (value->type == GDM_CONFIG_VALUE_STRING_ARRAY);
+
+	real = REAL_VALUE (value);
+
+	g_strfreev (real->val.array);
+	real->val.array = g_strdupv ((char **)array);
+}
+
+void
+gdm_config_value_set_int (GdmConfigValue *value,
+			  int             integer)
+{
+	GdmConfigRealValue *real;
+
+	g_return_if_fail (value != NULL);
+	g_return_if_fail (value->type == GDM_CONFIG_VALUE_INT);
+
+	real = REAL_VALUE (value);
+
+	real->val.integer = integer;
+}
+
+void
+gdm_config_value_set_bool (GdmConfigValue *value,
+			   gboolean        bool)
+{
+	GdmConfigRealValue *real;
+
+	g_return_if_fail (value != NULL);
+	g_return_if_fail (value->type == GDM_CONFIG_VALUE_BOOL);
+
+	real = REAL_VALUE (value);
+
+	real->val.bool = bool;
+}
+
+void
+gdm_config_value_set_string (GdmConfigValue *value,
+			     const char     *str)
+{
+	GdmConfigRealValue *real;
+
+	g_return_if_fail (value != NULL);
+	g_return_if_fail (value->type == GDM_CONFIG_VALUE_STRING);
+
+	real = REAL_VALUE (value);
+
+	g_free (real->val.str);
+	real->val.str = g_strdup (str);
+}
+
+char *
+gdm_config_value_to_string (const GdmConfigValue *value)
+{
+	GdmConfigRealValue *real;
+	char               *ret;
+
+	g_return_val_if_fail (value != NULL, NULL);
+
+	ret = NULL;
+	real = REAL_VALUE (value);
+
+	switch (real->type) {
+        case GDM_CONFIG_VALUE_INVALID:
+		break;
+        case GDM_CONFIG_VALUE_BOOL:
+		ret = real->val.bool ? g_strdup ("true") : g_strdup ("false");
+		break;
+        case GDM_CONFIG_VALUE_INT:
+		ret = g_strdup_printf ("%d", real->val.integer);
+		break;
+        case GDM_CONFIG_VALUE_STRING:
+		ret = g_strdup (real->val.str);
+		break;
+	case GDM_CONFIG_VALUE_STRING_ARRAY:
+		ret = g_strjoinv (";", real->val.array);
+		break;
+	default:
+		g_assert_not_reached ();
+		break;
+	}
+	return ret;
+}
+
+static void
+gdm_config_init (GdmConfig *config)
+{
+	config->entries = g_ptr_array_new ();
+	config->value_hash = g_hash_table_new_full (g_str_hash,
+						    g_str_equal,
+						    (GDestroyNotify)g_free,
+						    (GDestroyNotify)gdm_config_value_free);
+}
+
+GdmConfig *
+gdm_config_new (void)
+{
+	GdmConfig *config;
+
+	config = g_slice_new0 (GdmConfig);
+	gdm_config_init (config);
+
+	return config;
+}
+
+void
+gdm_config_free (GdmConfig *config)
+{
+	g_return_if_fail (config != NULL);
+
+	g_ptr_array_foreach (config->entries, (GFunc)gdm_config_entry_free, NULL);
+	g_ptr_array_free (config->entries, TRUE);
+
+	g_free (config->mandatory_filename);
+	g_free (config->default_filename);
+	g_free (config->custom_filename);
+
+	if (config->mandatory_key_file != NULL) {
+		g_key_file_free (config->mandatory_key_file);
+	}
+	if (config->default_key_file != NULL) {
+		g_key_file_free (config->default_key_file);
+	}
+	if (config->custom_key_file != NULL) {
+		g_key_file_free (config->custom_key_file);
+	}
+	if (config->value_hash != NULL) {
+		g_hash_table_destroy (config->value_hash);
+	}
+
+	g_slice_free (GdmConfig, config);
+}
+
+const GdmConfigEntry *
+gdm_config_lookup_entry (GdmConfig  *config,
+			 const char *group,
+			 const char *key)
+{
+	int                   i;
+	const GdmConfigEntry *entry;
+
+	g_return_val_if_fail (config != NULL, NULL);
+	g_return_val_if_fail (group != NULL, NULL);
+	g_return_val_if_fail (key != NULL, NULL);
+
+	entry = NULL;
+
+	for (i = 0; i < config->entries->len; i++) {
+		GdmConfigEntry *this;
+		this = g_ptr_array_index (config->entries, i);
+		if (strcmp (this->group, group) == 0
+		    && strcmp (this->key, key) == 0) {
+			entry = (const GdmConfigEntry *)this;
+			break;
+		}
+	}
+
+	return entry;
+}
+
+const GdmConfigEntry *
+gdm_config_lookup_entry_for_id (GdmConfig  *config,
+				int         id)
+{
+	int                   i;
+	const GdmConfigEntry *entry;
+
+	g_return_val_if_fail (config != NULL, NULL);
+
+	entry = NULL;
+
+	for (i = 0; i < config->entries->len; i++) {
+		GdmConfigEntry *this;
+		this = g_ptr_array_index (config->entries, i);
+		if (this->id == id) {
+			entry = (const GdmConfigEntry *)this;
+			break;
+		}
+	}
+
+	return entry;
+}
+
+void
+gdm_config_add_entry (GdmConfig            *config,
+		      const GdmConfigEntry *entry)
+{
+	GdmConfigEntry *new_entry;
+
+	g_return_if_fail (config != NULL);
+	g_return_if_fail (entry != NULL);
+
+	new_entry = gdm_config_entry_copy (entry);
+	g_ptr_array_add (config->entries, new_entry);
+}
+
+void
+gdm_config_add_static_entries (GdmConfig            *config,
+			       const GdmConfigEntry *entries)
+{
+	int i;
+
+	g_return_if_fail (config != NULL);
+	g_return_if_fail (entries != NULL);
+
+	for (i = 0; entries[i].group != NULL; i++) {
+		gdm_config_add_entry (config, &entries[i]);
+	}
+}
+
+void
+gdm_config_set_validate_func (GdmConfig       *config,
+			      GdmConfigFunc    func,
+			      gpointer         data)
+{
+	g_return_if_fail (config != NULL);
+
+	config->validate_func = func;
+	config->validate_func_data = data;
+}
+
+void
+gdm_config_set_mandatory_file (GdmConfig  *config,
+			       const char *name)
+{
+	g_return_if_fail (config != NULL);
+
+	g_free (config->mandatory_filename);
+	config->mandatory_filename = g_strdup (name);
+}
+
+void
+gdm_config_set_default_file (GdmConfig  *config,
+			     const char *name)
+{
+	g_return_if_fail (config != NULL);
+
+	g_free (config->default_filename);
+	config->default_filename = g_strdup (name);
+}
+
+void
+gdm_config_set_custom_file (GdmConfig  *config,
+			    const char *name)
+{
+	g_return_if_fail (config != NULL);
+
+	g_free (config->custom_filename);
+	config->custom_filename = g_strdup (name);
+}
+
+void
+gdm_config_set_notify_func (GdmConfig       *config,
+			    GdmConfigFunc    func,
+			    gpointer         data)
+{
+	g_return_if_fail (config != NULL);
+
+	config->notify_func = func;
+	config->notify_func_data = data;
+}
+
+static gboolean
+key_file_get_value (GdmConfig            *config,
+		    GKeyFile             *key_file,
+		    const char           *group,
+		    const char           *key,
+		    GdmConfigValueType    type,
+		    GdmConfigValue      **valuep)
+{
+	char           *val;
+	GError         *error;
+	GdmConfigValue *value;
+	gboolean        ret;
+
+	ret = FALSE;
+	value = NULL;
+
+	error = NULL;
+	val = g_key_file_get_value (key_file,
+				    group,
+				    key,
+				    &error);
+	if (error != NULL) {
+		g_error_free (error);
+		goto out;
+	}
+
+	if (val == NULL) {
+		goto out;
+	}
+
+	error = NULL;
+	value = gdm_config_value_new_from_string (type, val, &error);
+	if (error != NULL) {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+		goto out;
+	}
+
+	ret = TRUE;
+
+ out:
+	*valuep = value;
+
+	return ret;
+}
+
+static void
+entry_get_default_value (GdmConfig            *config,
+			 const GdmConfigEntry *entry,
+			 GdmConfigValue      **valuep)
+{
+	GdmConfigValue *value;
+	GError         *error;
+
+	error = NULL;
+	value = gdm_config_value_new_from_string (entry->type,
+						  entry->default_value ? entry->default_value : "",
+						  &error);
+	if (error != NULL) {
+		g_warning ("%s", error->message);
+		g_error_free (error);
+	}
+
+	*valuep = value;
+}
+
+static gboolean
+load_value_entry (GdmConfig            *config,
+		  const GdmConfigEntry *entry,
+		  GdmConfigValue      **valuep,
+		  GdmConfigSourceType  *sourcep)
+{
+	GdmConfigValue     *value;
+	GdmConfigSourceType source;
+	gboolean            ret;
+	gboolean            res;
+
+	value = NULL;
+
+	/* Look for the first occurence of the key in:
+	   mandatory file, custom file, default file, or built-in-default
+	 */
+
+	if (config->mandatory_filename != NULL) {
+		source = GDM_CONFIG_SOURCE_MANDATORY;
+		res = key_file_get_value (config,
+					  config->mandatory_key_file,
+					  entry->group,
+					  entry->key,
+					  entry->type,
+					  &value);
+		if (res) {
+			goto done;
+		}
+	}
+	if (config->custom_filename != NULL) {
+		source = GDM_CONFIG_SOURCE_CUSTOM;
+		res = key_file_get_value (config,
+					  config->custom_key_file,
+					  entry->group,
+					  entry->key,
+					  entry->type,
+					  &value);
+		if (res) {
+			goto done;
+		}
+	}
+	if (config->default_filename != NULL) {
+		source = GDM_CONFIG_SOURCE_DEFAULT;
+		res = key_file_get_value (config,
+					  config->default_key_file,
+					  entry->group,
+					  entry->key,
+					  entry->type,
+					  &value);
+		if (res) {
+			goto done;
+		}
+	}
+
+
+	source = GDM_CONFIG_SOURCE_BUILT_IN;
+	entry_get_default_value (config, entry, &value);
+
+ done:
+
+	if (value != NULL) {
+		ret = TRUE;
+	} else {
+		ret = FALSE;
+	}
+
+	*valuep = value;
+	*sourcep = source;
+
+	return ret;
+}
+
+static int
+lookup_id_for_key (GdmConfig  *config,
+		   const char *group,
+		   const char *key)
+{
+	int                   id;
+	const GdmConfigEntry *entry;
+
+	id = GDM_CONFIG_INVALID_ID;
+	entry = gdm_config_lookup_entry (config, group, key);
+	if (entry != NULL) {
+		id = entry->id;
+	}
+
+	return id;
+}
+
+static void
+internal_set_value (GdmConfig          *config,
+		    GdmConfigSourceType source,
+		    const char         *group,
+		    const char         *key,
+		    GdmConfigValue     *value)
+{
+	char           *key_path;
+	int             id;
+	GdmConfigValue *v;
+	gboolean        res;
+
+	g_return_if_fail (config != NULL);
+
+	key_path = g_strdup_printf ("%s/%s", group, key);
+
+	v = NULL;
+	res = g_hash_table_lookup_extended (config->value_hash,
+					    key_path,
+					    NULL,
+					    (gpointer *)&v);
+
+	if (res) {
+		if (gdm_config_value_compare (v, value) == 0) {
+			/* value is the same - don't update */
+			goto out;
+		}
+	}
+
+	g_hash_table_insert (config->value_hash,
+			     g_strdup (key_path),
+			     gdm_config_value_copy (value));
+
+	id = lookup_id_for_key (config, group, key);
+
+	if (config->notify_func) {
+		(* config->notify_func) (config, source, group, key, value, id, config->notify_func_data);
+	}
+ out:
+	g_free (key_path);
+}
+
+static void
+store_entry_value (GdmConfig            *config,
+		   const GdmConfigEntry *entry,
+		   GdmConfigSourceType   source,
+		   GdmConfigValue       *value)
+{
+	internal_set_value (config, source, entry->group, entry->key, value);
+}
+
+static gboolean
+load_entry (GdmConfig            *config,
+	    const GdmConfigEntry *entry)
+{
+	GdmConfigValue     *value;
+	GdmConfigSourceType source;
+	gboolean            res;
+
+	value = NULL;
+	source = GDM_CONFIG_SOURCE_INVALID;
+
+	res = load_value_entry (config, entry, &value, &source);
+	if (!res) {
+		return FALSE;
+	}
+
+	res = TRUE;
+	if (config->validate_func) {
+		res = (* config->validate_func) (config, source, entry->group, entry->key, value, entry->id, config->validate_func_data);
+	}
+
+	if (res) {
+		/* store runs notify */
+		store_entry_value (config, entry, source, value);
+	}
+
+	return TRUE;
+}
+
+static void
+add_keys_to_hash (GKeyFile   *key_file,
+		  const char *group_name,
+		  GHashTable *hash)
+{
+	GError     *local_error;
+	char      **keys;
+	gsize       len;
+	int         i;
+
+	local_error = NULL;
+	len = 0;
+	keys = g_key_file_get_keys (key_file,
+				    group_name,
+				    &len,
+				    &local_error);
+	if (local_error != NULL) {
+		g_error_free (local_error);
+		return;
+	}
+
+	for (i = 0; i < len; i++) {
+		g_hash_table_insert (hash, keys[i], GINT_TO_POINTER (1));
+	}
+}
+
+static void
+collect_hash_keys (const char *key,
+		   gpointer    value,
+		   GPtrArray **array)
+{
+	g_message ("Adding %s", key);
+	g_ptr_array_add (*array, g_strdup (key));
+}
+
+char **
+gdm_config_get_keys_for_group (GdmConfig  *config,
+			       const char *group,
+			       gsize      *length,
+			       GError    **error)
+{
+	GHashTable *hash;
+	gsize       len;
+	GPtrArray  *array;
+
+	hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+	if (config->mandatory_filename != NULL) {
+		add_keys_to_hash (config->mandatory_key_file, group, hash);
+	}
+
+	if (config->default_filename != NULL) {
+		add_keys_to_hash (config->default_key_file, group, hash);
+	}
+
+	if (config->custom_filename != NULL) {
+		add_keys_to_hash (config->custom_key_file, group, hash);
+	}
+
+	len = g_hash_table_size (hash);
+	array = g_ptr_array_sized_new (len);
+
+	g_hash_table_foreach (hash, (GHFunc)collect_hash_keys, &array);
+	g_ptr_array_add (array, NULL);
+
+	g_hash_table_destroy (hash);
+
+	if (length != NULL) {
+		*length = array->len - 1;
+	}
+
+	return (char **)g_ptr_array_free (array, FALSE);
+}
+
+static gboolean
+load_backend (GdmConfig  *config,
+	      const char *filename,
+	      GKeyFile  **key_file,
+	      time_t     *mtime)
+{
+	GError     *local_error;
+	gboolean    res;
+	gboolean    ret;
+	struct stat statbuf;
+	GKeyFile   *kf;
+	time_t      lmtime;
+
+	if (filename == NULL) {
+		return FALSE;
+	}
+
+	if (g_stat (filename, &statbuf) != 0) {
+		return FALSE;
+	}
+	lmtime = statbuf.st_mtime;
+
+	/* if already loaded check whether reload is necessary */
+	if (*key_file != NULL) {
+		if (lmtime > *mtime) {
+			/* needs an update */
+			g_key_file_free (*key_file);
+		} else {
+			/* no reload necessary so we're done */
+			return TRUE;
+		}
+	}
+
+	kf = g_key_file_new ();
+
+	local_error = NULL;
+	res = g_key_file_load_from_file (kf,
+					 filename,
+					 G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS,
+					 &local_error);
+	if (! res) {
+		g_error_free (local_error);
+		g_key_file_free (kf);
+		kf = NULL;
+		lmtime = 0;
+		ret = FALSE;
+	} else {
+		ret = TRUE;
+	}
+
+	*key_file = kf;
+	*mtime = lmtime;
+
+	return ret;
+}
+
+gboolean
+gdm_config_load (GdmConfig *config,
+		 GError   **error)
+{
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	config->mandatory_loaded = load_backend (config,
+						 config->mandatory_filename,
+						 &config->mandatory_key_file,
+						 &config->mandatory_mtime);
+	config->default_loaded = load_backend (config,
+					       config->default_filename,
+					       &config->default_key_file,
+					       &config->default_mtime);
+	config->custom_loaded = load_backend (config,
+					      config->custom_filename,
+					      &config->custom_key_file,
+					      &config->custom_mtime);
+
+	return TRUE;
+}
+
+static gboolean
+process_entries (GdmConfig             *config,
+		 const GdmConfigEntry **entries,
+		 gsize                  n_entries,
+		 GError               **error)
+{
+	gboolean ret;
+	int      i;
+
+	ret = TRUE;
+
+	for (i = 0; i < n_entries; i++) {
+		load_entry (config, entries[i]);
+	}
+
+	return ret;
+}
+
+gboolean
+gdm_config_process_entry (GdmConfig            *config,
+			  const GdmConfigEntry *entry,
+			  GError              **error)
+{
+	gboolean  ret;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+	g_return_val_if_fail (entry != NULL, FALSE);
+
+	ret = load_entry (config, entry);
+
+	return ret;
+}
+
+gboolean
+gdm_config_process_entries (GdmConfig             *config,
+			    const GdmConfigEntry **entries,
+			    gsize                  n_entries,
+			    GError               **error)
+{
+	gboolean  ret;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+	g_return_val_if_fail (entries != NULL, FALSE);
+	g_return_val_if_fail (n_entries > 0, FALSE);
+
+	ret = process_entries (config, entries, n_entries, error);
+
+	return ret;
+}
+
+gboolean
+gdm_config_process_all (GdmConfig *config,
+			GError   **error)
+{
+	gboolean  ret;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	ret = process_entries (config,
+			       (const GdmConfigEntry **)config->entries->pdata,
+			       config->entries->len,
+			       error);
+
+	return ret;
+}
+
+gboolean
+gdm_config_get_value (GdmConfig       *config,
+		      const char      *group,
+		      const char      *key,
+		      GdmConfigValue **valuep)
+{
+	gboolean        ret;
+	char           *key_path;
+	GdmConfigValue *value;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	key_path = g_strdup_printf ("%s/%s", group, key);
+	value = NULL;
+	ret = g_hash_table_lookup_extended (config->value_hash,
+					    key_path,
+					    NULL,
+					    (gpointer *)&value);
+	g_free (key_path);
+
+	if (valuep != NULL) {
+		if (ret) {
+			*valuep = gdm_config_value_copy (value);
+		} else {
+			*valuep = NULL;
+		}
+	}
+
+	return ret;
+}
+
+gboolean
+gdm_config_set_value (GdmConfig       *config,
+		      const char      *group,
+		      const char      *key,
+		      GdmConfigValue  *value)
+{
+	g_return_val_if_fail (config != NULL, FALSE);
+	g_return_val_if_fail (group != NULL, FALSE);
+	g_return_val_if_fail (key != NULL, FALSE);
+	g_return_val_if_fail (value != NULL, FALSE);
+
+	internal_set_value (config, GDM_CONFIG_SOURCE_RUNTIME_USER, group, key, value);
+
+	return TRUE;
+}
+
+gboolean
+gdm_config_get_value_for_id (GdmConfig       *config,
+			     int              id,
+			     GdmConfigValue **valuep)
+{
+	const GdmConfigEntry *entry;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	entry = gdm_config_lookup_entry_for_id (config, id);
+	if (entry == NULL) {
+		return FALSE;
+	}
+
+	return gdm_config_get_value (config, entry->group, entry->key, valuep);
+}
+
+gboolean
+gdm_config_set_value_for_id (GdmConfig      *config,
+			     int             id,
+			     GdmConfigValue *valuep)
+{
+	const GdmConfigEntry *entry;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	entry = gdm_config_lookup_entry_for_id (config, id);
+	if (entry == NULL) {
+		return FALSE;
+	}
+
+	return gdm_config_set_value (config, entry->group, entry->key, valuep);
+}
+
+gboolean
+gdm_config_get_string_for_id (GdmConfig       *config,
+			      int              id,
+			      char           **strp)
+{
+	GdmConfigValue *value;
+	const char     *str;
+	gboolean        res;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	res = gdm_config_get_value_for_id (config, id, &value);
+	if (! res) {
+		return FALSE;
+	}
+
+	str = gdm_config_value_get_string (value);
+	if (strp != NULL) {
+		*strp = g_strdup (str);
+	}
+
+	gdm_config_value_free (value);
+
+	return res;
+}
+
+gboolean
+gdm_config_get_bool_for_id (GdmConfig       *config,
+			    int              id,
+			    gboolean        *boolp)
+{
+	GdmConfigValue *value;
+	gboolean        bool;
+	gboolean        res;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	res = gdm_config_get_value_for_id (config, id, &value);
+	if (! res) {
+		return FALSE;
+	}
+
+	bool = gdm_config_value_get_bool (value);
+	if (boolp != NULL) {
+		*boolp = bool;
+	}
+
+	gdm_config_value_free (value);
+
+	return res;
+}
+
+gboolean
+gdm_config_set_string_for_id (GdmConfig      *config,
+			      int             id,
+			      char           *str)
+{
+	GdmConfigValue *value;
+	gboolean        res;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	value = gdm_config_value_new (GDM_CONFIG_VALUE_STRING);
+	gdm_config_value_set_string (value, str);
+
+	res = gdm_config_set_value_for_id (config, id, value);
+	gdm_config_value_free (value);
+
+	return res;
+}
+
+gboolean
+gdm_config_set_bool_for_id (GdmConfig      *config,
+			    int             id,
+			    gboolean        bool)
+{
+	GdmConfigValue *value;
+	gboolean        res;
+
+	g_return_val_if_fail (config != NULL, FALSE);
+
+	value = gdm_config_value_new (GDM_CONFIG_VALUE_BOOL);
+	gdm_config_value_set_bool (value, bool);
+
+	res = gdm_config_set_value_for_id (config, id, value);
+	gdm_config_value_free (value);
+
+	return res;
+}
Index: common/gdm-common.c
===================================================================
--- common/gdm-common.c	(revision 4696)
+++ common/gdm-common.c	(working copy)
@@ -34,12 +34,12 @@
 
 /**
  * ve_clearenv:
- * 
+ *
  * Description: Clears out the environment completely.
  * In case there is no native implementation of clearenv,
  * this could cause leaks depending on the implementation
  * of environment.
- * 
+ *
  **/
 void
 ve_clearenv (void)
@@ -124,116 +124,10 @@ ve_get_first_working_command (const char
 }
 
 char *
-ve_rest (const char *s)
-{
-	const char *p;
-	gboolean single_quot = FALSE;
-	gboolean double_quot = FALSE;
-	gboolean escape = FALSE;
-
-	if (s == NULL)
-		return NULL;
-
-	for (p = s; *p != '\0'; p++) {
-		if (single_quot) {
-			if (*p == '\'') {
-				single_quot = FALSE;
-			}
-		} else if (escape) {
-			escape = FALSE;
-		} else if (double_quot) {
-			if (*p == '"') {
-				double_quot = FALSE;
-			} else if (*p == '\\') {
-				escape = TRUE;
-			}
-		} else if (*p == '\'') {
-			single_quot = TRUE;
-		} else if (*p == '"') {
-			double_quot = TRUE;
-		} else if (*p == '\\') {
-			escape = TRUE;
-		} else if (*p == ' ' || *p == '\t') {
-			while (*p == ' ' || *p == '\t')
-				p++;
-			return g_strdup (p);
-		}
-	}
-
-	return NULL;
-}
-
-gboolean
-ve_bool_equal (gboolean a, gboolean b)
-{
-	if ((a && b) || (!a && !b))
-		return TRUE;
-	else
-		return FALSE;
-}
-
-gboolean
-ve_is_string_in_list (const GList *list, const char *string)
-{
-	g_return_val_if_fail (string != NULL, FALSE);
-
-	while (list != NULL) {
-		if (list->data != NULL &&
-		    strcmp (string, list->data) == 0)
-			return TRUE;
-
-		list = list->next;
-	}
-
-	return FALSE;
-}
-
-gboolean
-ve_is_string_in_list_case_no_locale (const GList *list, const char *string)
-{
-	g_return_val_if_fail (string != NULL, FALSE);
-
-	while (list != NULL) {
-		if (list->data != NULL &&
-		    g_ascii_strcasecmp (string, list->data) == 0)
-			return TRUE;
-
-		list = list->next;
-	}
-
-	return FALSE;
-}
-
-char *
-ve_find_file_simple (const char *filename, const GList *directories)
-{
-	char *s;
-	const GList *li;
-
-	if (filename == NULL)
-		return NULL;
-
-	if (g_access (filename, F_OK) == 0)
-		return g_strdup (filename);
-
-	/* an absolute path is just checked */
-	if (g_path_is_absolute (filename))
-		return NULL;
-
-	for (li = directories; li != NULL; li = li->next) {
-		s = g_build_filename (li->data, filename, NULL);
-		if (g_access (s, F_OK) == 0)
-			return s;
-		g_free (s);
-	}
-
-	return NULL;
-}
-
-char *
 ve_locale_to_utf8 (const char *str)
 {
 	char *ret = g_locale_to_utf8 (str, -1, NULL, NULL, NULL);
+
 	if (ret == NULL) {
 		g_warning ("string not in proper locale encoding: \"%s\"", str);
 		return g_strdup (str);
@@ -246,6 +140,7 @@ char *
 ve_locale_from_utf8 (const char *str)
 {
 	char *ret = g_locale_from_utf8 (str, -1, NULL, NULL, NULL);
+
 	if (ret == NULL) {
 		g_warning ("string not in proper utf8 encoding: \"%s\"", str);
 		return g_strdup (str);
@@ -278,24 +173,6 @@ ve_filename_from_utf8 (const char *str)
 	}
 }
 
-char *
-ve_strftime (struct tm *the_tm, const char *format)
-{
-	char str[1024];
-	char *loc_format = ve_locale_from_utf8 (format);
-
-	if (strftime (str, sizeof (str)-1, loc_format, the_tm) == 0) {
-		/* according to docs, if the string does not fit, the
-		 * contents of str are undefined, thus just use
-		 * ??? */
-		strcpy (str, "???");
-	}
-	str [sizeof (str)-1] = '\0'; /* just for sanity */
-	g_free (loc_format);
-
-	return ve_locale_to_utf8 (str);
-}
-
 pid_t
 ve_waitpid_no_signal (pid_t pid, int *status, int options)
 {
@@ -323,52 +200,3 @@ ve_locale_exists (const char *loc)
 	g_free (old);
 	return ret;
 }
-
-char *
-ve_find_prog_in_path (const char *prog, const char *path)
-{
-	char **vec;
-	int i;
-
-	if (ve_string_empty (prog) || ve_string_empty (path))
-		return NULL;
-
-	vec = g_strsplit (path, ":", -1);
-	for (i = 0; vec != NULL && vec[i] != NULL; i++) {
-		char *full = g_build_filename (vec[i], prog, NULL);
-		/* Do not use X_OK, we may be looking for things
-		   that are not executables */
-		if (g_access (full, F_OK) == 0) {
-			g_strfreev(vec);
-			return full;
-		}
-		g_free (full);
-	}
-	g_strfreev(vec);
-	return NULL;
-}
-
-gboolean
-ve_is_prog_in_path (const char *prog, const char *path)
-{
-	char *full = ve_find_prog_in_path (prog, path);
-	if (full != NULL) {
-		g_free (full);
-		return TRUE;
-	} else {
-		return FALSE;
-	}
-}
-
-char *
-ve_shell_quote_filename (const char *name)
-{
-	if (name[0] != '-') {
-		return g_shell_quote (name);
-	} else {
-		char *fname = g_strconcat ("./", name, NULL);
-		char *quoted = g_shell_quote (fname);
-		g_free (fname);
-		return quoted;
-	}
-}
Index: daemon/errorgui.c
===================================================================
--- daemon/errorgui.c	(revision 4696)
+++ daemon/errorgui.c	(working copy)
@@ -39,11 +39,11 @@
 #include "gdm.h"
 #include "misc.h"
 #include "auth.h"
-#include "gdmconfig.h"
 #include "errorgui.h"
 #include "slave.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 /* set in the main function */
 extern char **stored_argv;
@@ -204,9 +204,9 @@ setup_dialog (GdmDisplay *d, const char 
 	gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */
 
 	if (set_gdm_ids) {
-		setgid (gdm_get_gdmgid ());
-		initgroups (gdm_get_value_string (GDM_KEY_USER), gdm_get_gdmgid ());
-		setuid (gdm_get_gdmuid ());
+		setgid (gdm_daemon_config_get_gdmgid ());
+		initgroups (gdm_daemon_config_get_value_string (GDM_KEY_USER), gdm_daemon_config_get_gdmgid ());
+		setuid (gdm_daemon_config_get_gdmuid ());
 		pw = NULL;
 	} else {
 		pw = getpwuid (uid);
@@ -219,9 +219,9 @@ setup_dialog (GdmDisplay *d, const char 
 
 	openlog ("gdm", LOG_PID, LOG_DAEMON);
 
-	g_setenv ("LOGNAME", gdm_get_value_string (GDM_KEY_USER), TRUE);
-	g_setenv ("USER", gdm_get_value_string (GDM_KEY_USER), TRUE);
-	g_setenv ("USERNAME", gdm_get_value_string (GDM_KEY_USER), TRUE);
+	g_setenv ("LOGNAME", gdm_daemon_config_get_value_string (GDM_KEY_USER), TRUE);
+	g_setenv ("USER", gdm_daemon_config_get_value_string (GDM_KEY_USER), TRUE);
+	g_setenv ("USERNAME", gdm_daemon_config_get_value_string (GDM_KEY_USER), TRUE);
 
 	g_setenv ("DISPLAY", d->name, TRUE);
 	g_unsetenv ("XAUTHORITY");
@@ -233,7 +233,7 @@ setup_dialog (GdmDisplay *d, const char 
 	/* set HOME to /, we don't need no stinking HOME anyway */
 	if (pw == NULL ||
 	    ve_string_empty (pw->pw_dir))
-		g_setenv ("HOME", ve_sure_string (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)), TRUE);
+		g_setenv ("HOME", ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)), TRUE);
 	else
 		g_setenv ("HOME", pw->pw_dir, TRUE);
 
@@ -242,9 +242,9 @@ setup_dialog (GdmDisplay *d, const char 
 	argc = 1;
 
 	if ( ! inhibit_gtk_modules &&
-	    gdm_get_value_bool (GDM_KEY_ADD_GTK_MODULES) &&
-	     ! ve_string_empty (gdm_get_value_string (GDM_KEY_GTK_MODULES_LIST))) {
-		argv[1] = g_strdup_printf ("--gtk-module=%s", gdm_get_value_string (GDM_KEY_GTK_MODULES_LIST));
+	    gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES) &&
+	     ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST))) {
+		argv[1] = g_strdup_printf ("--gtk-module=%s", gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST));
 		argc = 2;
 	}
 
@@ -256,7 +256,7 @@ setup_dialog (GdmDisplay *d, const char 
 
 	if ( ! inhibit_gtk_themes) {
 		const char *theme_name;
-                gchar *gtkrc = gdm_get_value_string (GDM_KEY_GTKRC);
+                const gchar *gtkrc = gdm_daemon_config_get_value_string (GDM_KEY_GTKRC);
 
 		if ( ! ve_string_empty (gtkrc) &&
 		     g_access (gtkrc, R_OK) == 0)
@@ -264,7 +264,7 @@ setup_dialog (GdmDisplay *d, const char 
 
 		theme_name = d->theme_name;
 		if (ve_string_empty (theme_name))
-			theme_name = gdm_get_value_string (GDM_KEY_GTK_THEME);
+			theme_name = gdm_daemon_config_get_value_string (GDM_KEY_GTK_THEME);
 		if ( ! ve_string_empty (theme_name)) {
 			gchar *theme_dir = gtk_rc_get_theme_dir ();
 			char *theme = g_strdup_printf ("%s/%s/gtk-2.0/gtkrc", theme_dir, theme_name);
Index: daemon/gdmconfig.h
===================================================================
--- daemon/gdmconfig.h	(revision 4696)
+++ daemon/gdmconfig.h	(working copy)
@@ -1,93 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
- *
- * GDM - The GNOME Display Manager
- * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
- * Copyright (C) 2005 Brian Cameron <brian.cameron@sun.com>
- *
- * 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_CONFIG_H
-#define _GDM_CONFIG_H
-
-#include "gdm.h"
-
-G_BEGIN_DECLS
-
-
-gchar*         gdm_get_display_custom_config_file
-                                        (const gchar *display);
-gchar*         gdm_get_custom_config_file (void);
-gchar*         gdm_get_value_string     (const gchar *key);
-gboolean       gdm_get_value_bool       (const gchar *key);
-gint           gdm_get_value_int        (const gchar *key);
-gchar*         gdm_get_value_string_per_display (const gchar *display,
-                                                 const gchar *key);
-gboolean       gdm_get_value_bool_per_display   (const gchar *display,
-                                                 const gchar *key);
-gint           gdm_get_value_int_per_display    (const gchar *display,
-                                                 const gchar *key);
-void           gdm_set_value_string     (const gchar *key,
-                                         const gchar *value);
-void           gdm_set_value_bool       (const gchar *key,
-                                         gboolean value);
-void           gdm_set_value_int        (const gchar *key,
-                                         gint value);
-void           gdm_config_key_to_string_per_display
-                                        (const gchar *display,
-                                         const gchar *key,
-                                         gchar **retval);
-void           gdm_config_key_to_string (const gchar *file,
-                                         const gchar *key,
-                                         gchar **retval);
-void           gdm_config_to_string     (const gchar *key,
-                                         const gchar *display,
-                                         gchar **retval);
-gboolean       gdm_update_config        (const gchar *key);
-void           gdm_config_parse         (void);
-GdmXserver*    gdm_find_xserver         (const gchar *id);
-gchar*         gdm_get_xservers         (void);
-int            gdm_compare_displays     (gconstpointer a,
-                                         gconstpointer b);
-uid_t          gdm_get_gdmuid           (void);
-uid_t          gdm_get_gdmgid           (void);
-gint           gdm_get_high_display_num (void);
-void           gdm_set_high_display_num (gint val);
-gboolean       gdm_is_valid_key         (const gchar *key);
-gboolean       gdm_signal_terminthup_was_notified  (void);
-
-gchar*         gdm_get_facefile_from_home
-                                        (const char *homedir,
-                                         guint uid);
-gchar*         gdm_get_facefile_from_global
-                                        (const char *username,
-                                         guint uid);
-void           gdm_get_user_session_lang
-                                        (char **usrsess,
-                                         char **usrlang,
-                                         const char *homedir,
-                                         gboolean *savesess);
-void		gdm_set_user_session_lang (gboolean savesess,
-					 gboolean savelang,
-					 const char *home_dir,
-					 const char *save_session,
-					 const char *save_language);
-char*          gdm_get_session_exec     (const char *session_name,
-                                         gboolean check_try_exec);
-
-
-G_END_DECLS
-
-#endif /* _GDM_CONFIG_H */
Index: daemon/display.c
===================================================================
--- daemon/display.c	(revision 4696)
+++ daemon/display.c	(working copy)
@@ -39,9 +39,9 @@
 #include "choose.h"
 #include "auth.h"
 #include "gdm-net.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 /* External vars */
 extern gint xdmcp_sessions;
@@ -205,7 +205,7 @@ wait_again:
 		    /* rekill the slave to tell it to
 		       hurry up and die if we're getting
 		       killed ourselves */
-		    if ((gdm_signal_terminthup_was_notified ()) ||
+		    if ((gdm_daemon_config_signal_terminthup_was_notified ()) ||
 			(t + 10 <= time (NULL))) {
 			    gdm_debug ("whack_old_slave: GOT ANOTHER SIGTERM (or it was 10 secs already), killing slave again with SIGKILL");
 			    t = time (NULL);
@@ -296,7 +296,7 @@ gdm_display_manage (GdmDisplay *d)
 	d->slavepid = getpid ();
 
 	/* Close XDMCP fd in slave process */
-	if (gdm_get_value_bool (GDM_KEY_XDMCP))
+	if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP))
 	    gdm_xdmcp_close ();
 
 	gdm_connection_close (fifoconn);
Index: daemon/gdm.c
===================================================================
--- daemon/gdm.c	(revision 4696)
+++ daemon/gdm.c	(working copy)
@@ -66,9 +66,10 @@
 #include "gdm-net.h"
 #include "cookie.h"
 #include "filecheck.h"
-#include "gdmconfig.h"
 #include "errorgui.h"
 
+#include "gdm-daemon-config.h"
+
 #define DYNAMIC_ADD     0
 #define DYNAMIC_RELEASE 1
 #define DYNAMIC_REMOVE  2
@@ -154,7 +155,7 @@ GdmLogoutAction safe_logout_action = GDM
 gchar **stored_argv = NULL;
 int stored_argc = 0;
 
-extern gchar *config_file;
+static gchar *config_file = NULL;
 static gboolean gdm_restart_mode = FALSE;
 
 static GMainLoop *main_loop = NULL;
@@ -196,7 +197,7 @@ gdm_daemonify (void)
 
     pid = fork ();
     if (pid > 0) {
-        gchar *pidfile = gdm_get_value_string (GDM_KEY_PID_FILE);
+        const char *pidfile = gdm_daemon_config_get_value_string (GDM_KEY_PID_FILE);
 
         errno = 0;
 	if ((pf = gdm_safe_fopen_w (pidfile)) != NULL) {
@@ -231,7 +232,7 @@ gdm_daemonify (void)
 	gdm_fail (_("%s: setsid () failed: %s!"), "gdm_daemonify",
 		  strerror (errno));
 
-    VE_IGNORE_EINTR (g_chdir (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)));
+    VE_IGNORE_EINTR (g_chdir (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)));
     umask (022);
 
     VE_IGNORE_EINTR (close (0));
@@ -299,7 +300,7 @@ void
 gdm_final_cleanup (void)
 {
 	GSList *list, *li;
-	gchar *pidfile;
+	const char *pidfile;
 	gboolean first;
 
 	gdm_debug ("gdm_final_cleanup");
@@ -366,13 +367,13 @@ gdm_final_cleanup (void)
 
 	/* Close stuff */
 
-	if (gdm_get_value_bool (GDM_KEY_XDMCP))
+	if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP))
 		gdm_xdmcp_close ();
 
 	if (fifoconn != NULL) {
 		char *path;
 		gdm_connection_close (fifoconn);
-		path = g_build_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR), ".gdmfifo", NULL);
+		path = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".gdmfifo", NULL);
 		VE_IGNORE_EINTR (g_unlink (path));
 		g_free (path);
 		fifoconn = NULL;
@@ -396,7 +397,7 @@ gdm_final_cleanup (void)
 
 	closelog ();
 
-	pidfile = gdm_get_value_string (GDM_KEY_PID_FILE);
+	pidfile = gdm_daemon_config_get_value_string (GDM_KEY_PID_FILE);
 	if (pidfile != NULL) {
 		VE_IGNORE_EINTR (g_unlink (pidfile));
 	}
@@ -447,8 +448,8 @@ static gboolean
 deal_with_x_crashes (GdmDisplay *d)
 {
     gboolean just_abort = FALSE;
-    gchar* failsafe = gdm_get_value_string (GDM_KEY_FAILSAFE_XSERVER);
-    gchar* keepscrashing = gdm_get_value_string (GDM_KEY_X_KEEPS_CRASHING);
+    const char *failsafe = gdm_daemon_config_get_value_string (GDM_KEY_FAILSAFE_XSERVER);
+    const char *keepscrashing = gdm_daemon_config_get_value_string (GDM_KEY_X_KEEPS_CRASHING);
 
     if ( ! d->failsafe_xserver &&
 	 ! ve_string_empty (failsafe)) {
@@ -484,7 +485,7 @@ deal_with_x_crashes (GdmDisplay *d)
 
 	    if (pid == 0) {
 		    char *argv[2];
-		    char *xlog = gdm_make_filename (gdm_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
+		    char *xlog = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
 
 		    gdm_unset_signals ();
 
@@ -493,7 +494,7 @@ deal_with_x_crashes (GdmDisplay *d)
 		     * possible children */
 		    setsid ();
 
-		    if (gdm_get_value_bool (GDM_KEY_XDMCP))
+		    if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP))
 			    gdm_xdmcp_close ();
 
 		    closelog ();
@@ -506,7 +507,7 @@ deal_with_x_crashes (GdmDisplay *d)
 		    gdm_open_dev_null (O_RDWR); /* open stdout - fd 1 */
 		    gdm_open_dev_null (O_RDWR); /* open stderr - fd 2 */
 
-		    argv[0] = gdm_get_value_string (GDM_KEY_X_KEEPS_CRASHING);
+		    argv[0] = (char *)gdm_daemon_config_get_value_string (GDM_KEY_X_KEEPS_CRASHING);
 		    argv[1] = NULL;
 
 		    gdm_restoreenv ();
@@ -555,7 +556,7 @@ deal_with_x_crashes (GdmDisplay *d)
 				    errno = 0;
 				    ret = waitpid (extra_process, &status, WNOHANG);
 				    storeerrno = errno;
-				    if ((ret <= 0) && gdm_signal_terminthup_was_notified ()) {
+				    if ((ret <= 0) && gdm_daemon_config_signal_terminthup_was_notified ()) {
 					    kill (-(extra_process), killsignal);
 					    killsignal = SIGKILL;
 				    }
@@ -611,8 +612,8 @@ deal_with_x_crashes (GdmDisplay *d)
 static void
 suspend_machine (void)
 {
-	gchar *suspend = gdm_get_value_string (GDM_KEY_SUSPEND);
-	
+	const gchar *suspend = gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND);
+
 	gdm_info (_("Master suspending..."));
 
 	if (suspend != NULL && fork () == 0) {
@@ -622,7 +623,7 @@ suspend_machine (void)
 		 * wrong with the suspend */
 		sync ();
 
-		if (gdm_get_value_bool (GDM_KEY_XDMCP))
+		if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP))
 			gdm_xdmcp_close ();
 		/* In the child setup empty mask and set all signals to
 		 * default values */
@@ -695,7 +696,7 @@ halt_machine (void)
 #endif /* __linux */
 
 	argv = NULL;
-	s = gdm_get_value_string (GDM_KEY_HALT);
+	s = gdm_daemon_config_get_value_string (GDM_KEY_HALT);
 	if (s != NULL) {
 		g_shell_parse_argv (s, NULL, &argv, NULL);
 	}
@@ -725,7 +726,7 @@ restart_machine (void)
 #endif /* __linux */
 
 	argv = NULL;
-	s = gdm_get_value_string (GDM_KEY_REBOOT);
+	s = gdm_daemon_config_get_value_string (GDM_KEY_REBOOT);
 	if (s != NULL) {
 		g_shell_parse_argv (s, NULL, &argv, NULL);
 	}
@@ -752,7 +753,7 @@ custom_cmd (long cmd_id)
 	}
 
         key_string = g_strdup_printf (_("%s%ld="), GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, cmd_id);
-        if (gdm_get_value_bool (key_string))
+        if (gdm_daemon_config_get_value_bool (key_string))
 	        custom_cmd_no_restart (cmd_id);
 	else
 	        custom_cmd_restart (cmd_id);
@@ -779,7 +780,7 @@ custom_cmd_restart (long cmd_id)
 	key_string = g_strdup_printf (_("%s%ld="), GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_id);
 
 	argv = NULL;
-	s = gdm_get_value_string (key_string);
+	s = gdm_daemon_config_get_value_string (key_string);
 	g_free (key_string);
 	if (s != NULL) {
 		g_shell_parse_argv (s, NULL, &argv, NULL);
@@ -817,7 +818,7 @@ custom_cmd_no_restart (long cmd_id)
 		key_string = g_strdup_printf (_("%s%ld="), GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_id);
 
 		argv = NULL;
-		s = gdm_get_value_string (key_string);
+		s = gdm_daemon_config_get_value_string (key_string);
 		g_free (key_string);
 		if (s != NULL) {
 			g_shell_parse_argv (s, NULL, &argv, NULL);
@@ -917,7 +918,7 @@ gdm_cleanup_children (void)
 		    kill (d->servpid, SIGTERM);
 	    d->servpid = 0;
 
-            if (gdm_get_value_bool (GDM_KEY_DYNAMIC_XSERVERS)) {
+            if (gdm_daemon_config_get_value_bool (GDM_KEY_DYNAMIC_XSERVERS)) {
 		/* XXX - This needs to be handled better */
 		gdm_server_whack_lockfile (d);
 	    }
@@ -941,7 +942,7 @@ gdm_cleanup_children (void)
     d->slavepid = 0;
     d->dispstat = DISPLAY_DEAD;
 
-    sysmenu = gdm_get_value_bool_per_display (d->name, GDM_KEY_SYSTEM_MENU);
+    sysmenu = gdm_daemon_config_get_value_bool_per_display (d->name, GDM_KEY_SYSTEM_MENU);
 
     if ( ! sysmenu &&
 	(status == DISPLAY_RESTARTGDM ||
@@ -964,7 +965,7 @@ gdm_cleanup_children (void)
     if (status == DISPLAY_RUN_CHOOSER) {
 	    /* use the chooser on the next run (but only if allowed) */
 	    if (sysmenu && 
-		gdm_get_value_bool_per_display (d->name, GDM_KEY_CHOOSER_BUTTON))
+		gdm_daemon_config_get_value_bool_per_display (d->name, GDM_KEY_CHOOSER_BUTTON))
 		    d->use_chooser = TRUE;
 	    status = DISPLAY_REMANAGE;
 	    /* go around the display loop detection, these are short
@@ -996,15 +997,15 @@ gdm_cleanup_children (void)
     /* checkout if we can actually do stuff */
     switch (status) {
     case DISPLAY_REBOOT:
-	    if (gdm_get_value_string (GDM_KEY_REBOOT) == NULL)
+	    if (gdm_daemon_config_get_value_string (GDM_KEY_REBOOT) == NULL)
 		    status = DISPLAY_REMANAGE;
 	    break;
     case DISPLAY_HALT:
-	    if (gdm_get_value_string (GDM_KEY_HALT) == NULL)
+	    if (gdm_daemon_config_get_value_string (GDM_KEY_HALT) == NULL)
 		    status = DISPLAY_REMANAGE;
 	    break;
     case DISPLAY_SUSPEND:
-	    if (gdm_get_value_string (GDM_KEY_SUSPEND) == NULL)
+	    if (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND) == NULL)
 		    status = DISPLAY_REMANAGE;
 	    break;
     default:
@@ -1342,7 +1343,7 @@ create_connections (void)
 	int p[2];
 	gchar *path;
 
-	path = g_build_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR), ".gdmfifo", NULL);
+	path = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".gdmfifo", NULL);
 	fifoconn = gdm_connection_open_fifo (path, 0660);
 	g_free (path);
 
@@ -1524,7 +1525,7 @@ gdm_make_global_cookie (void)
 	gdm_global_cookie = (unsigned char *) faked.cookie;
 	gdm_global_bcookie = (unsigned char *) faked.bcookie;
 
-	file = g_build_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR), ".cookie", NULL);
+	file = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), ".cookie", NULL);
 	VE_IGNORE_EINTR (g_unlink (file));
 
 	oldmode = umask (077);
@@ -1549,14 +1550,14 @@ gdm_make_global_cookie (void)
 	g_free (file);
 }
 
-int 
+int
 main (int argc, char *argv[])
 {
     FILE *pf;
     sigset_t mask;
     struct sigaction sig, child, abrt;
     GOptionContext *ctx;
-    gchar *pidfile;
+    const char *pidfile;
     const char *charset;
     int i;
 
@@ -1633,7 +1634,7 @@ main (int argc, char *argv[])
     sigemptyset (&sig.sa_mask);
 
     /* Parse configuration file */
-    gdm_config_parse ();
+    gdm_daemon_config_parse (config_file);
 
     /*
      * Do not call gdm_fail before calling gdm_config_parse ()
@@ -1650,7 +1651,7 @@ main (int argc, char *argv[])
     /* get the name of the root user */
     gdm_root_user ();
 
-    pidfile = gdm_get_value_string (GDM_KEY_PID_FILE);
+    pidfile = gdm_daemon_config_get_value_string (GDM_KEY_PID_FILE);
 
     /* Check if another gdm process is already running */
     if (g_access (pidfile, R_OK) == 0) {
@@ -1665,7 +1666,7 @@ main (int argc, char *argv[])
 	    kill (pidv, 0) == 0 &&
 	    linux_only_is_running (pidv)) {
 		/* make sure the pid file doesn't get wiped */
-		gdm_set_value_string (GDM_KEY_PID_FILE, NULL);
+		gdm_daemon_config_set_value_string (GDM_KEY_PID_FILE, NULL);
 		pidfile = NULL;
 		VE_IGNORE_EINTR (fclose (pf));
 		gdm_fail (_("GDM already running. Aborting!"));
@@ -1701,7 +1702,7 @@ main (int argc, char *argv[])
 
 	}
 
-	VE_IGNORE_EINTR (g_chdir (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)));
+	VE_IGNORE_EINTR (g_chdir (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)));
 	umask (022);
     }
     else
@@ -1805,11 +1806,11 @@ main (int argc, char *argv[])
     gdm_debug ("gdm_main: Here we go...");
 
 #ifdef  HAVE_LOGINDEVPERM
-    di_devperm_login ("/dev/console", gdm_get_gdmuid (), gdm_get_gdmgid (), NULL);
+    di_devperm_login ("/dev/console", gdm_daemon_config_get_gdmuid (), gdm_daemon_config_get_gdmgid (), NULL);
 #endif  /* HAVE_LOGINDEVPERM */
 
     /* Init XDMCP if applicable */
-    if (gdm_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go)
+    if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go)
 	gdm_xdmcp_init ();
 
     create_connections ();
@@ -1825,7 +1826,7 @@ main (int argc, char *argv[])
     gdm_start_first_unborn_local (0 /* delay */);
 
     /* Accept remote connections */
-    if (gdm_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go) {
+    if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP) && ! gdm_wait_for_go) {
 	gdm_debug ("Accepting XDMCP connections...");
 	gdm_xdmcp_run ();
     }
@@ -1876,7 +1877,7 @@ static void
 write_x_servers (GdmDisplay *d)
 {
 	FILE *fp;
-	char *file = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xservers");
+	char *file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xservers");
 	int i;
 	int bogusname;
 
@@ -2029,7 +2030,7 @@ static void
 gdm_handle_message (GdmConnection *conn, const char *msg, gpointer data)
 {
 	/* Evil!, all this for debugging? */
-	if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) {
+	if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) {
 		if (strncmp (msg, GDM_SOP_COOKIE " ",
 			     strlen (GDM_SOP_COOKIE " ")) == 0) {
 			char *s = g_strndup
@@ -2288,7 +2289,7 @@ gdm_handle_message (GdmConnection *conn,
 
 					if (d->attached && di->attached && di->vt > 0)
 						migratable = TRUE;
-					else if (gdm_get_value_string (GDM_KEY_XDMCP_PROXY_RECONNECT) != NULL &&
+					else if (gdm_daemon_config_get_value_string (GDM_KEY_XDMCP_PROXY_RECONNECT) != NULL &&
 						 d->type == TYPE_XDMCP_PROXY && di->type == TYPE_XDMCP_PROXY)
 						migratable = TRUE;
 
@@ -2515,7 +2516,7 @@ gdm_handle_message (GdmConnection *conn,
 			send_slave_command (d, GDM_NOTIFY_GO);
 		}
 		/* Init XDMCP if applicable */
-		if (old_wait && gdm_get_value_bool (GDM_KEY_XDMCP)) {
+		if (old_wait && gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP)) {
 			if (gdm_xdmcp_init ()) {
 				gdm_debug ("Accepting XDMCP connections...");
 				gdm_xdmcp_run ();
@@ -2551,8 +2552,8 @@ gdm_handle_message (GdmConnection *conn,
 
 		gdm_info (_("Master suspending..."));
 
-		sysmenu = gdm_get_value_bool_per_display (d->name, GDM_KEY_SYSTEM_MENU);
-		if (sysmenu && gdm_get_value_string (GDM_KEY_SUSPEND) != NULL) {
+		sysmenu = gdm_daemon_config_get_value_bool_per_display (d->name, GDM_KEY_SYSTEM_MENU);
+		if (sysmenu && gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND) != NULL) {
 			suspend_machine ();
 		}
 	} else if (strncmp (msg, GDM_SOP_CHOSEN_THEME " ",
@@ -2600,7 +2601,7 @@ gdm_handle_message (GdmConnection *conn,
 			send_slave_ack (d, NULL);
 		}		
 	} else if (strcmp (msg, GDM_SOP_FLEXI_XSERVER) == 0) {
-		handle_flexi_server (NULL, TYPE_FLEXI, gdm_get_value_string (GDM_KEY_STANDARD_XSERVER),
+		handle_flexi_server (NULL, TYPE_FLEXI, gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER),
 				     TRUE /* handled */,
 				     FALSE /* chooser */,
 				     NULL, 0, NULL, NULL, NULL);
@@ -3035,7 +3036,7 @@ handle_flexi_server (GdmConnection *conn
 		NEVER_FAILS_seteuid (0);
 
 		if (setegid (pw->pw_gid) < 0)
-			NEVER_FAILS_setegid (gdm_get_gdmgid ());
+			NEVER_FAILS_setegid (gdm_daemon_config_get_gdmgid ());
 
 		if (seteuid (xnest_uid) < 0) {
 			if (conn != NULL)
@@ -3074,7 +3075,7 @@ handle_flexi_server (GdmConnection *conn
 		server_uid = xnest_uid;
 	}
 
-	if (flexi_servers >= gdm_get_value_int (GDM_KEY_FLEXIBLE_XSERVERS)) {
+	if (flexi_servers >= gdm_daemon_config_get_value_int (GDM_KEY_FLEXIBLE_XSERVERS)) {
 		if (conn != NULL)
 			gdm_connection_write (conn,
 					      "ERROR 1 No more flexi servers\n");
@@ -3162,7 +3163,7 @@ handle_dynamic_server (GdmConnection *co
     gchar *full;
     gchar *val;
 
-    if (!(gdm_get_value_bool (GDM_KEY_DYNAMIC_XSERVERS))) {
+    if (!(gdm_daemon_config_get_value_bool (GDM_KEY_DYNAMIC_XSERVERS))) {
         gdm_connection_write (conn, "ERROR 200 Dynamic Displays not allowed\n");
         return;
     }
@@ -3208,13 +3209,13 @@ handle_dynamic_server (GdmConnection *co
         }
         displays = g_slist_insert_sorted (displays,
                                           disp,
-                                          gdm_compare_displays);
+                                          gdm_daemon_config_compare_displays);
 
         disp->dispstat = DISPLAY_CONFIG;
         disp->removeconf = FALSE;
 
-        if (disp_num > gdm_get_high_display_num ())
-            gdm_set_high_display_num (disp_num);
+        if (disp_num > gdm_daemon_config_get_high_display_num ())
+		gdm_daemon_config_set_high_display_num (disp_num);
 
 	gdm_connection_write (conn, "OK\n");
         return;
@@ -3343,7 +3344,7 @@ gdm_handle_user_message (GdmConnection *
 					      "ERROR 100 Not authenticated\n");
 			return;
 		}
-		handle_flexi_server (conn, TYPE_FLEXI, gdm_get_value_string (GDM_KEY_STANDARD_XSERVER),
+		handle_flexi_server (conn, TYPE_FLEXI, gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER),
 				     TRUE /* handled */,
 				     FALSE /* chooser */,
 				     NULL, 0, NULL, NULL, NULL);
@@ -3387,18 +3388,18 @@ gdm_handle_user_message (GdmConnection *
 			name = g_strdup (GDM_STANDARD);
 		}
 
-		svr = gdm_find_xserver (name);
+		svr = gdm_daemon_config_find_xserver (name);
 		if G_UNLIKELY (svr == NULL) {
 			/* Don't print the name to syslog as it might be
 			 * long and dangerous */
 			gdm_error (_("Unknown server type requested; using "
 				     "standard server."));
-			command = gdm_get_value_string (GDM_KEY_STANDARD_XSERVER);
+			command = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER);
 		} else if G_UNLIKELY ( ! svr->flexible) {
 			gdm_error (_("Requested server %s not allowed to be "
 				     "used for flexible servers; using "
 				     "standard server."), name);
-			command = gdm_get_value_string (GDM_KEY_STANDARD_XSERVER);
+			command = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER);
 		} else {
 			command = svr->command;
 		}
@@ -3451,7 +3452,7 @@ gdm_handle_user_message (GdmConnection *
 			return;
 		}
 		
-		handle_flexi_server (conn, TYPE_FLEXI_XNEST, gdm_get_value_string (GDM_KEY_XNEST),
+		handle_flexi_server (conn, TYPE_FLEXI_XNEST, gdm_daemon_config_get_value_string (GDM_KEY_XNEST),
 				     TRUE /* handled */,
 				     FALSE /* chooser */,
 				     dispname, uid, xauthfile, cookie, username);
@@ -3519,7 +3520,7 @@ gdm_handle_user_message (GdmConnection *
 		gdm_connection_write (conn, msg->str);
 		g_string_free (msg, TRUE);
 	} else if (strcmp (msg, GDM_SUP_GET_SERVER_LIST) == 0) {
-		gchar *retval = gdm_get_xservers ();
+		gchar *retval = gdm_daemon_config_get_xservers ();
 
 		if (retval != NULL) {
 			gdm_connection_printf (conn, "OK %s\n", retval);
@@ -3532,7 +3533,7 @@ gdm_handle_user_message (GdmConnection *
 		     strlen (GDM_SUP_GET_SERVER_DETAILS " ")) == 0) {
 		const gchar *server = &msg[strlen (GDM_SUP_GET_SERVER_DETAILS " ")];
 		gchar   **splitstr = g_strsplit (server, " ", 2);
-		GdmXserver  *svr   = gdm_find_xserver ((gchar *)splitstr[0]);
+		GdmXserver  *svr   = gdm_daemon_config_find_xserver ((gchar *)splitstr[0]);
 
 		if (svr != NULL) {
 			if (g_strcasecmp (splitstr[1], "ID") == 0)
@@ -3597,7 +3598,7 @@ gdm_handle_user_message (GdmConnection *
 		const gchar *key = 
 			&msg[strlen (GDM_SUP_UPDATE_CONFIG " ")];
 
-		if (! gdm_update_config ((gchar *)key))
+		if (! gdm_daemon_config_update_key ((gchar *)key))
 			gdm_connection_printf (conn, "ERROR 50 Unsupported key <%s>\n", key);
 		else
 			gdm_connection_write (conn, "OK\n");
@@ -3631,13 +3632,13 @@ gdm_handle_user_message (GdmConnection *
                         * since if it is NULL, it won't try to load the display
 			* value at all.
                         */
-			gdm_config_to_string (splitstr[0], splitstr[1], &retval);
+			gdm_daemon_config_to_string (splitstr[0], splitstr[1], &retval);
 
 	   		if (retval != NULL) {
    				gdm_connection_printf (conn, "OK %s\n", retval);
    				g_free (retval);
 			} else {
-				if (gdm_is_valid_key ((gchar *)splitstr[0]))
+				if (gdm_daemon_config_is_valid_key ((gchar *)splitstr[0]))
 					gdm_connection_printf (conn, "OK \n");
 				else
        		         		gdm_connection_printf (conn,
@@ -3651,7 +3652,7 @@ gdm_handle_user_message (GdmConnection *
 	} else if (strcmp (msg, GDM_SUP_GET_CUSTOM_CONFIG_FILE) == 0) {
 		gchar *ret;
 
-		ret = gdm_get_custom_config_file ();
+		ret = gdm_daemon_config_get_custom_config_file ();
 		if (ret)
 			gdm_connection_printf (conn, "OK %s\n", ret);
 		else
@@ -3676,7 +3677,7 @@ gdm_handle_user_message (GdmConnection *
 			return;
 		}
 
-		sysmenu = gdm_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
+		sysmenu = gdm_daemon_config_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
 		msg = g_string_new ("OK");
 
 		logout_action = disp->logout_action;
@@ -3684,21 +3685,21 @@ gdm_handle_user_message (GdmConnection *
 			logout_action = safe_logout_action;
 
 		if (sysmenu && disp->attached &&
-		    ! ve_string_empty (gdm_get_value_string (GDM_KEY_HALT))) {
+		    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_HALT))) {
 			g_string_append_printf (msg, "%s%s", sep, GDM_SUP_LOGOUT_ACTION_HALT);
 			if (logout_action == GDM_LOGOUT_ACTION_HALT)
 				g_string_append (msg, "!");
 			sep = ";";
 		}
 		if (sysmenu && disp->attached &&
-		    ! ve_string_empty (gdm_get_value_string (GDM_KEY_REBOOT))) {
+		    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_REBOOT))) {
 			g_string_append_printf (msg, "%s%s", sep, GDM_SUP_LOGOUT_ACTION_REBOOT);
 			if (logout_action == GDM_LOGOUT_ACTION_REBOOT)
 				g_string_append (msg, "!");
 			sep = ";";
 		}	
 		if (sysmenu && disp->attached &&
-		    ! ve_string_empty (gdm_get_value_string (GDM_KEY_SUSPEND))) {
+		    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) {
 			g_string_append_printf (msg, "%s%s", sep, GDM_SUP_LOGOUT_ACTION_SUSPEND);
 			if (logout_action == GDM_LOGOUT_ACTION_SUSPEND)
 				g_string_append (msg, "!");
@@ -3709,10 +3710,10 @@ gdm_handle_user_message (GdmConnection *
 			gchar *key_string = NULL; 
 			key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i); 
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (key_string))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
 				g_free (key_string);
 				key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i); 
-				if (gdm_get_value_bool (key_string)) {
+				if (gdm_daemon_config_get_value_bool (key_string)) {
 					g_string_append_printf (msg, "%s%s%d", sep, GDM_SUP_LOGOUT_ACTION_CUSTOM_CMD_TEMPLATE, i);
 					if (logout_action == (GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + i))
 						g_string_append (msg, "!");
@@ -3732,7 +3733,7 @@ gdm_handle_user_message (GdmConnection *
 		gboolean sysmenu;
 
 		disp = gdm_connection_get_display (conn);
-		sysmenu = gdm_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
+		sysmenu = gdm_daemon_config_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
 
 		/* Only allow locally authenticated connections */
 		if ( ! GDM_CONN_AUTHENTICATED (conn) ||
@@ -3750,13 +3751,13 @@ gdm_handle_user_message (GdmConnection *
 			gchar *key_string = NULL; 
 			key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i); 
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (key_string))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
 				g_free (key_string);
 				key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i); 
-				if (gdm_get_value_bool (key_string)) {
+				if (gdm_daemon_config_get_value_bool (key_string)) {
 					g_free (key_string);
 					key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE, i); 
-					g_string_append_printf (msg, "%s%s",  sep, gdm_get_value_string (key_string));
+					g_string_append_printf (msg, "%s%s",  sep, gdm_daemon_config_get_value_string (key_string));
 					sep = ";";
 				}
 			}
@@ -3773,7 +3774,7 @@ gdm_handle_user_message (GdmConnection *
 		unsigned long no_restart_status_flag = 0; /* we can store up-to 32 commands this way */
 
 		disp = gdm_connection_get_display (conn);
-		sysmenu = gdm_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
+		sysmenu = gdm_daemon_config_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
 
 		/* Only allow locally authenticated connections */
 		if ( ! GDM_CONN_AUTHENTICATED (conn) ||
@@ -3791,13 +3792,13 @@ gdm_handle_user_message (GdmConnection *
 			gchar *key_string = NULL; 
 			key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i); 
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (key_string))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
 				g_free (key_string);
 				key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i); 
-				if (gdm_get_value_bool (key_string)) {
+				if (gdm_daemon_config_get_value_bool (key_string)) {
 					g_free (key_string);
 					key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, i); 
-					if(gdm_get_value_bool (key_string))
+					if(gdm_daemon_config_get_value_bool (key_string))
 						no_restart_status_flag |= (1 << i);				 
 				}
 			}
@@ -3828,27 +3829,27 @@ gdm_handle_user_message (GdmConnection *
 			return;
 		}
 
-		sysmenu = gdm_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
+		sysmenu = gdm_daemon_config_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
 		if (strcmp (action, GDM_SUP_LOGOUT_ACTION_NONE) == 0) {
 			disp->logout_action = GDM_LOGOUT_ACTION_NONE;
 			was_ok = TRUE;
 		} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0) {
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (GDM_KEY_HALT))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_HALT))) {
 				disp->logout_action =
 					GDM_LOGOUT_ACTION_HALT;
 				was_ok = TRUE;
 			}
 		} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0) {
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (GDM_KEY_REBOOT))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_REBOOT))) {
 				disp->logout_action =
 					GDM_LOGOUT_ACTION_REBOOT;
 				was_ok = TRUE;
 			}
 		} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0) {
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (GDM_KEY_SUSPEND))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) {
 				disp->logout_action =
 					GDM_LOGOUT_ACTION_SUSPEND;
 				was_ok = TRUE;
@@ -3861,7 +3862,7 @@ gdm_handle_user_message (GdmConnection *
 			   gchar *key_string = NULL; 
 			   key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index); 
 			   if (sysmenu && disp->attached &&
-			       ! ve_string_empty (gdm_get_value_string (key_string))) {
+			       ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
 			           disp->logout_action =
 				           GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index;
 				   was_ok = TRUE;
@@ -3896,27 +3897,27 @@ gdm_handle_user_message (GdmConnection *
 			return;
 		}
 
-		sysmenu = gdm_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
+		sysmenu = gdm_daemon_config_get_value_bool_per_display (disp->name, GDM_KEY_SYSTEM_MENU);
 		if (strcmp (action, GDM_SUP_LOGOUT_ACTION_NONE) == 0) {
 			safe_logout_action = GDM_LOGOUT_ACTION_NONE;
 			was_ok = TRUE;
 		} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_HALT) == 0) {
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (GDM_KEY_HALT))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_HALT))) {
 				safe_logout_action =
 					GDM_LOGOUT_ACTION_HALT;
 				was_ok = TRUE;
 			}
 		} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_REBOOT) == 0) {
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (GDM_KEY_REBOOT))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_REBOOT))) {
 				safe_logout_action =
 					GDM_LOGOUT_ACTION_REBOOT;
 				was_ok = TRUE;
 			}
 		} else if (strcmp (action, GDM_SUP_LOGOUT_ACTION_SUSPEND) == 0) {
 			if (sysmenu && disp->attached &&
-			    ! ve_string_empty (gdm_get_value_string (GDM_KEY_SUSPEND))) {
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) {
 				safe_logout_action =
 					GDM_LOGOUT_ACTION_SUSPEND;
 				was_ok = TRUE;
@@ -3929,7 +3930,7 @@ gdm_handle_user_message (GdmConnection *
 			       gchar *key_string = NULL; 
 			       key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, cmd_index); 
 			       if (sysmenu && disp->attached &&
-				   ! ve_string_empty (gdm_get_value_string (key_string))) {
+				   ! ve_string_empty (gdm_daemon_config_get_value_string (key_string))) {
 			               safe_logout_action =
 				           GDM_LOGOUT_ACTION_CUSTOM_CMD_FIRST + cmd_index;
 				   was_ok = TRUE;
Index: daemon/xdmcp.c
===================================================================
--- daemon/xdmcp.c	(revision 4696)
+++ daemon/xdmcp.c	(working copy)
@@ -101,9 +101,9 @@
 #include "choose.h"
 #include "xdmcp.h"
 #include "cookie.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 /*This is to be changed when the Xdmcp Multicast address is decided */
 #define XDMCP_MULTICAST_ADDRESS "ff02::1"
@@ -378,9 +378,9 @@ gdm_xdmcp_init (void)
     gint addrlen;
     gchar hostbuf[1024];
     struct utsname name;
-    int udpport = gdm_get_value_int (GDM_KEY_UDP_PORT);
+    int udpport = gdm_daemon_config_get_value_int (GDM_KEY_UDP_PORT);
 
-    if ( ! gdm_get_value_bool (GDM_KEY_XDMCP))
+    if ( ! gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP))
 	    return TRUE;
 
     globsessid = g_random_int ();
@@ -414,7 +414,7 @@ gdm_xdmcp_init (void)
     
     if G_UNLIKELY (gdm_xdmcpfd < 0) {
 	gdm_error (_("%s: Could not create socket!"), "gdm_xdmcp_init");
-        gdm_set_value_bool (GDM_KEY_XDMCP, FALSE);
+        gdm_daemon_config_set_value_bool (GDM_KEY_XDMCP, FALSE);
 	return FALSE;
     }
 
@@ -426,7 +426,7 @@ gdm_xdmcp_init (void)
 	addrlen = sizeof (struct sockaddr_in6);
 
 	/* Checking and Setting Multicast options */
-	if (gdm_get_value_bool (GDM_KEY_MULTICAST)) {
+	if (gdm_daemon_config_get_value_bool (GDM_KEY_MULTICAST)) {
             /*
              * socktemp is a temporary socket for getting info about
              * available interfaces
@@ -441,11 +441,11 @@ gdm_xdmcp_init (void)
 	    struct ifreq *ifr;
 
 	    /* Extract Multicast address for IPv6 */
-	    if (ve_string_empty (gdm_get_value_string (GDM_KEY_MULTICAST_ADDR))) {
+	    if (ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_MULTICAST_ADDR))) {
 
 		/* Stuff it with all-node multicast address */
-		gdm_set_value_string (GDM_KEY_MULTICAST_ADDR,
-                                      XDMCP_MULTICAST_ADDRESS);
+		gdm_daemon_config_set_value_string (GDM_KEY_MULTICAST_ADDR,
+                                                    XDMCP_MULTICAST_ADDRESS);
 	    }
 
 	    socktemp = socket (AF_INET, SOCK_DGRAM, 0);
@@ -489,7 +489,7 @@ gdm_xdmcp_init (void)
 
 		    mreq.ipv6mr_interface = ifindex;
 		    inet_pton (AF_INET6,
-                               gdm_get_value_string (GDM_KEY_MULTICAST_ADDR),
+                               gdm_daemon_config_get_value_string (GDM_KEY_MULTICAST_ADDR),
                                &mreq.ipv6mr_multiaddr);
 		    setsockopt (gdm_xdmcpfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
                                 &mreq, sizeof (mreq));
@@ -511,7 +511,7 @@ gdm_xdmcp_init (void)
     if G_UNLIKELY (bind (gdm_xdmcpfd, (struct sockaddr*) &serv_sa, addrlen) == -1) {
 	gdm_error (_("%s: Could not bind to XDMCP socket!"), "gdm_xdmcp_init");
 	gdm_xdmcp_close ();
-	gdm_set_value_bool (GDM_KEY_XDMCP, FALSE);
+	gdm_daemon_config_set_value_bool (GDM_KEY_XDMCP, FALSE);
 	return FALSE;
     }
 
@@ -742,7 +742,7 @@ gdm_xdmcp_handle_query (struct sockaddr_
     
     /* Crude checksumming */
     for (i = 0 ; i < clnt_authlist.length ; i++) {
-	    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) {
+	    if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) {
 		    char *s = g_strndup ((char *) clnt_authlist.data[i].data,
                                          clnt_authlist.length);
 		    gdm_debug ("gdm_xdmcp_handle_query: authlist: %s",
@@ -766,7 +766,7 @@ gdm_xdmcp_handle_query (struct sockaddr_
  	 * the pending list. If found send a FORWARD_QUERY to the
  	 * chosen manager. Otherwise alloc a new indirect display. */
 
-	if (gdm_get_value_bool (GDM_KEY_INDIRECT) &&
+	if (gdm_daemon_config_get_value_bool (GDM_KEY_INDIRECT) &&
 	    type == INDIRECT_QUERY) {
 		GdmIndirectDisplay *id = gdm_choose_indirect_lookup (clnt_sa);
 
@@ -1236,7 +1236,7 @@ gdm_xdmcp_handle_forward_query (struct s
     explen += 2+clnt_port.length;
     
     for (i = 0 ; i < clnt_authlist.length ; i++) {
-	    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) {
+	    if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) {
 		    char *s = g_strndup ((char *) clnt_authlist.data[i].data,
                                          clnt_authlist.length);
 		    gdm_debug ("gdm_xdmcp_handle_forward_query: authlist: %s",
@@ -1367,8 +1367,8 @@ gdm_xdmcp_send_willing (struct sockaddr_
     static time_t last_willing = 0;
     char *bin;
     FILE *fd;
-    char *willing = gdm_get_value_string (GDM_KEY_WILLING);
-    int dispperhost = gdm_get_value_int (GDM_KEY_DISPLAYS_PER_HOST);
+    const char *willing = gdm_daemon_config_get_value_string (GDM_KEY_WILLING);
+    int dispperhost = gdm_daemon_config_get_value_int (GDM_KEY_DISPLAYS_PER_HOST);
     
 #ifdef ENABLE_IPV6
     if (clnt_sa->ss_family == AF_INET6) {
@@ -1734,9 +1734,9 @@ gdm_xdmcp_handle_request (struct sockadd
     gint i;
     gboolean mitauth = FALSE;
     gboolean entered = FALSE;
-    int maxsessions  = gdm_get_value_int (GDM_KEY_MAX_SESSIONS);
-    int maxpending   = gdm_get_value_int (GDM_KEY_MAX_PENDING);
-    int dispperhost  = gdm_get_value_int (GDM_KEY_DISPLAYS_PER_HOST);
+    int maxsessions  = gdm_daemon_config_get_value_int (GDM_KEY_MAX_SESSIONS);
+    int maxpending   = gdm_daemon_config_get_value_int (GDM_KEY_MAX_PENDING);
+    int dispperhost  = gdm_daemon_config_get_value_int (GDM_KEY_DISPLAYS_PER_HOST);
     
 #ifdef ENABLE_IPV6
     char buffer6[INET6_ADDRSTRLEN];
@@ -1888,7 +1888,7 @@ gdm_xdmcp_handle_request (struct sockadd
 	return;
     }
 
-    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) {
+    if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) {
 	    char *s = g_strndup ((char *) clnt_manufacturer.data, clnt_manufacturer.length);
 	    gdm_debug ("gdm_xdmcp_handle_request: xdmcp_pending=%d, MaxPending=%d, xdmcp_sessions=%d, MaxSessions=%d, ManufacturerID=%s",
 		       xdmcp_pending, maxpending, xdmcp_sessions,
@@ -2179,7 +2179,7 @@ gdm_xdmcp_handle_manage (struct sockaddr
 	return;
     }
 
-    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG)) {
+    if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG)) {
 	    char *s = g_strndup ((char *) clnt_dspclass.data, clnt_dspclass.length);
 
 #ifdef ENABLE_IPV6
@@ -2202,7 +2202,7 @@ gdm_xdmcp_handle_manage (struct sockaddr
 
 	gdm_debug ("gdm_xdmcp_handle_manage: Looked up %s", d->name);
 
-	if (gdm_get_value_bool (GDM_KEY_INDIRECT)) {
+	if (gdm_daemon_config_get_value_bool (GDM_KEY_INDIRECT)) {
 		id = gdm_choose_indirect_lookup (clnt_sa);
 
 		/* This was an indirect thingie and nothing was yet chosen,
@@ -2729,11 +2729,11 @@ gdm_xdmcp_display_alloc (
 			 int displaynum)
 {
     GdmDisplay *d  = NULL;
-    char *proxycmd = gdm_get_value_string (GDM_KEY_XDMCP_PROXY_XSERVER);
+    const char *proxycmd = gdm_daemon_config_get_value_string (GDM_KEY_XDMCP_PROXY_XSERVER);
     
     d = g_new0 (GdmDisplay, 1);
 
-    if (gdm_get_value_bool (GDM_KEY_XDMCP_PROXY) && proxycmd != NULL) {
+    if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP_PROXY) && proxycmd != NULL) {
 	    d->type = TYPE_XDMCP_PROXY;
 	    d->command = g_strdup (proxycmd);
 	    gdm_debug ("Using proxy server for XDMCP: %s\n", d->command);
@@ -2769,8 +2769,8 @@ gdm_xdmcp_display_alloc (
     d->login            = NULL;
     d->sleep_before_run = 0;
 
-    if (gdm_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN) &&
-	! ve_string_empty (gdm_get_value_string (GDM_KEY_TIMED_LOGIN))) {
+    if (gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN) &&
+	! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN))) {
 	    d->timed_login_ok = TRUE;
     } else {
 	    d->timed_login_ok = FALSE;
@@ -2821,7 +2821,7 @@ gdm_xdmcp_display_alloc (
 	    d->parent_disp      = d->name;
 	    d->name             = g_strdup (":-1");
 	    d->dispnum          = -1;
-	    d->server_uid       = gdm_get_gdmuid ();
+	    d->server_uid       = gdm_daemon_config_get_gdmuid ();
 	    d->parent_auth_file = d->authfile;
 	    d->authfile         = NULL;
     }
@@ -2904,7 +2904,7 @@ gdm_xdmcp_displays_check (void)
 		if (d != NULL &&
 		    SERVER_IS_XDMCP (d) &&
 		    d->dispstat == XDMCP_PENDING &&
-		    curtime > d->acctime + gdm_get_value_int (GDM_KEY_MAX_WAIT)) {
+		    curtime > d->acctime + gdm_daemon_config_get_value_int (GDM_KEY_MAX_WAIT)) {
 			gdm_debug ("gdm_xdmcp_displays_check: Disposing session id %ld",
 				   (long)d->sessionid);
 			gdm_display_dispose (d);
@@ -2923,9 +2923,9 @@ reconnect_to_parent (GdmDisplay *to)
 {
 	GError *error;
 	gchar *command_argv[10];
-	gchar *proxyreconnect = gdm_get_value_string (GDM_KEY_XDMCP_PROXY_RECONNECT);
+	const gchar *proxyreconnect = gdm_daemon_config_get_value_string (GDM_KEY_XDMCP_PROXY_RECONNECT);
 
-	command_argv[0] = proxyreconnect;
+	command_argv[0] = (char *)proxyreconnect;
 	command_argv[1] = "--display";
 	command_argv[2] = to->parent_disp;
 	command_argv[3] = "--display-authfile";
Index: daemon/gdm.h
===================================================================
--- daemon/gdm.h	(revision 4696)
+++ daemon/gdm.h	(working copy)
@@ -1,4 +1,6 @@
-/* GDM - The GNOME Display Manager
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * GDM - The GNOME Display Manager
  * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -139,215 +141,6 @@ enum {
 #define PIPE_SIZE 4096
 
 /*
- * The following section contains keys used by the GDM configuration files.
- * The key/value pairs defined in the GDM configuration files are considered
- * "stable" interface and should only change in ways that are backwards
- * compatible.  Please keep this in mind when changing GDM configuration.
- * 
- * Developers who add new configuration options should ensure that they do the
- * following:
- * 
- * + Edit the config/gdm.conf file to include the default setting.
- *
- * + Specify the same default in this file as in the config/gdm.conf.in file.
- *
- * + Update the gdm_config_init function in daemon/gdmconfig.c to add the
- *   new key.  Include some documentation about the new key, following the
- *   style of existing comments.
- *
- * + Add any validation to the _gdm_set_value_string, _gdm_set_value_int,
- *   and/or _gdm_set_value_bool functions (depending on the type of the new
- *   key) in gdmconfig.c, if validation is needed.
- *
- * + If GDM_UPDATE_CONFIG should not respond to this configuration setting,
- *   update the update_config function in gdmconfig.c to return FALSE for
- *   this key.  Examples include changing the PidFile, ServAuthDir, or
- *   other values that GDM should not change until it is restarted.  If 
- *   this is true, the next bullet can be ignored.
- *
- * + If the option should cause the greeter (gdmlogin/gdmgreeter) program to
- *   be updated immediately, make sure to update the appropriate 
- *   _gdm_set_value_* function in gdmconfig.c.  This function calls the
- *   notify_displays_* function to call when this value is changed, so you
- *   will need to add your new config value to the list of values sending
- *   such notification.  Supporting logic will need to be added to
- *   gdm_slave_handle_notify function in slave.c to process the notify.
- *   It should be clear to see how to do this from the existing code.
- *
- * + Add the key to the gdm_read_config and gdm_reread_config functions in 
- *   gui/gdmlogin.c, gui/gdmchooser.c, and gui/greeter/greeter.c
- *   if the key is used by those programs.  Note that all GDM slaves load
- *   all their configuration data between calls to gdmcomm_comm_bulk_start()
- *   and gdmcomm_comm_bulk_stop().  This makes sure that the slave only uses
- *   a single sockets connection to get all configuration data.  If a new
- *   config value is read by a slave, make sure to load the key in this
- *   code section for best performance.
- *
- * + The gui/gdmsetup.c program should be updated to support the new option
- *   unless there's a good reason not to (like it is a configuration value
- *   that only someone who really knows what they are doing should change
- *   like GDM_KEY_PID_FILE).
- * 
- * + Currently GDM treats any key in the "gui" and "greeter" categories,
- *   and security/PamStack as available for per-display configuration.  
- *   If a key is appropriate for per-display configuration, and is not
- *   in the "gui" or "greeter" categories, then it will need to be added
- *   to the gdm_config_key_to_string_per_display function.  It may make
- *   sense for some keys used by the daemon to be per-display so this
- *   will need to be coded (refer to GDM_KEY_PAM_STACK for an example).
- *
- * + Update the docs/C/gdm.xml file to include information about the new
- *   option.  Include information about any other interfaces (such as 
- *   ENVIRONMENT variables) that may affect the configuration option.
- *   Patches without documentation will not be accepted.
- *
- * Please do this work *before* submitting an patch.  Patches that are not
- * complete will not likely be accepted.
- */
-
-/* Configuration constants */
-#define GDM_KEY_CHOOSER "daemon/Chooser=" LIBEXECDIR "/gdmchooser"
-#define GDM_KEY_AUTOMATIC_LOGIN_ENABLE "daemon/AutomaticLoginEnable=false"
-#define GDM_KEY_AUTOMATIC_LOGIN "daemon/AutomaticLogin="
-/* The SDTLOGIN feature is Solaris specific, and causes the Xserver to be
- * run with user permissionsinstead of as root, which adds security but
- * disables the AlwaysRestartServer option as highlighted in the gdm
- * documentation */
-#define GDM_KEY_ALWAYS_RESTART_SERVER "daemon/AlwaysRestartServer=" ALWAYS_RESTART_SERVER
-#define GDM_KEY_GREETER "daemon/Greeter=" LIBEXECDIR "/gdmlogin"
-#define GDM_KEY_REMOTE_GREETER "daemon/RemoteGreeter=" LIBEXECDIR "/gdmlogin"
-#define GDM_KEY_ADD_GTK_MODULES "daemon/AddGtkModules=false"
-#define GDM_KEY_GTK_MODULES_LIST "daemon/GtkModulesList="
-#define GDM_KEY_GROUP "daemon/Group=gdm"
-#define GDM_KEY_HALT "daemon/HaltCommand=" HALT_COMMAND
-#define GDM_KEY_DISPLAY_INIT_DIR "daemon/DisplayInitDir=" GDMCONFDIR "/Init"
-#define GDM_KEY_KILL_INIT_CLIENTS "daemon/KillInitClients=true"
-#define GDM_KEY_LOG_DIR "daemon/LogDir=" LOGDIR
-#define GDM_KEY_PATH "daemon/DefaultPath=" GDM_USER_PATH
-#define GDM_KEY_PID_FILE "daemon/PidFile=/var/run/gdm.pid"
-#define GDM_KEY_POSTSESSION "daemon/PostSessionScriptDir=" GDMCONFDIR "/PostSession/"
-#define GDM_KEY_PRESESSION "daemon/PreSessionScriptDir=" GDMCONFDIR "/PreSession/"
-#define GDM_KEY_POSTLOGIN "daemon/PostLoginScriptDir=" GDMCONFDIR "/PreSession/"
-#define GDM_KEY_FAILSAFE_XSERVER "daemon/FailsafeXServer="
-#define GDM_KEY_X_KEEPS_CRASHING "daemon/XKeepsCrashing=" GDMCONFDIR "/XKeepsCrashing"
-#define GDM_KEY_REBOOT  "daemon/RebootCommand=" REBOOT_COMMAND
-#define GDM_KEY_CUSTOM_CMD_TEMPLATE "customcommand/CustomCommand"
-#define GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE "customcommand/CustomCommandLabel"
-#define GDM_KEY_CUSTOM_CMD_LR_LABEL_TEMPLATE "customcommand/CustomCommandLRLabel"
-#define GDM_KEY_CUSTOM_CMD_TEXT_TEMPLATE "customcommand/CustomCommandText"
-#define GDM_KEY_CUSTOM_CMD_TOOLTIP_TEMPLATE "customcommand/CustomCommandTooltip"
-#define GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE "customcommand/CustomCommandNoRestart"
-#define GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE "customcommand/CustomCommandIsPersistent"
-#define GDM_KEY_ROOT_PATH "daemon/RootPath=/sbin:/usr/sbin:" GDM_USER_PATH
-#define GDM_KEY_SERV_AUTHDIR "daemon/ServAuthDir=" AUTHDIR
-#define GDM_KEY_SESSION_DESKTOP_DIR "daemon/SessionDesktopDir=/etc/X11/sessions/:" DMCONFDIR "/Sessions/:" DATADIR "/gdm/BuiltInSessions/:" DATADIR "/xsessions/"
-#define GDM_KEY_BASE_XSESSION "daemon/BaseXsession=" GDMCONFDIR "/Xsession"
-#define GDM_KEY_DEFAULT_SESSION "daemon/DefaultSession=gnome.desktop"
-#define GDM_KEY_SUSPEND "daemon/SuspendCommand=" SUSPEND_COMMAND
-
-#define GDM_KEY_USER_AUTHDIR "daemon/UserAuthDir="
-#define GDM_KEY_USER_AUTHDIR_FALLBACK "daemon/UserAuthFBDir=/tmp"
-#define GDM_KEY_USER_AUTHFILE "daemon/UserAuthFile=.Xauthority"
-#define GDM_KEY_USER "daemon/User=gdm"
-#define GDM_KEY_CONSOLE_NOTIFY "daemon/ConsoleNotify=true"
-
-#define GDM_KEY_DOUBLE_LOGIN_WARNING "daemon/DoubleLoginWarning=true"
-#define GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION "daemon/AlwaysLoginCurrentSession=true"
-
-#define GDM_KEY_DISPLAY_LAST_LOGIN "daemon/DisplayLastLogin=false"
-
-#define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable=false"
-#define GDM_KEY_TIMED_LOGIN "daemon/TimedLogin="
-#define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay=30"
-
-#define GDM_KEY_FLEXI_REAP_DELAY_MINUTES "daemon/FlexiReapDelayMinutes=5"
-
-#define GDM_KEY_STANDARD_XSERVER "daemon/StandardXServer=" X_SERVER
-#define GDM_KEY_FLEXIBLE_XSERVERS "daemon/FlexibleXServers=5"
-#define GDM_KEY_DYNAMIC_XSERVERS "daemon/DynamicXServers=false"
-#define GDM_KEY_XNEST "daemon/Xnest=" X_XNEST_CMD " " X_XNEST_CONFIG_OPTIONS
-#define GDM_KEY_XNEST_UNSCALED_FONT_PATH "daemon/XnestUnscaledFontPath=" X_XNEST_UNSCALED_FONTPATH
-/* Keys for automatic VT allocation rather then letting it up to the
- * X server */
-#define GDM_KEY_FIRST_VT "daemon/FirstVT=7"
-#define GDM_KEY_VT_ALLOCATION "daemon/VTAllocation=true"
-
-#define GDM_KEY_CONSOLE_CANNOT_HANDLE "daemon/ConsoleCannotHandle=am,ar,az,bn,el,fa,gu,hi,ja,ko,ml,mr,pa,ta,zh"
-
-/* How long to wait before assuming an Xserver has timed out */
-#define GDM_KEY_XSERVER_TIMEOUT "daemon/GdmXserverTimeout=10"
-
-/* Per server definitions */
-#define GDM_KEY_SERVER_PREFIX "server-"
-#define GDM_KEY_SERVER_NAME "name=Standard server"
-#define GDM_KEY_SERVER_COMMAND "command=" X_SERVER
-/* runnable as flexi server */
-#define GDM_KEY_SERVER_FLEXIBLE "flexible=true"
-/* choosable from the login screen */
-#define GDM_KEY_SERVER_CHOOSABLE "choosable=false"
-/* Login is handled by gdm, otherwise it's a remote server */
-#define GDM_KEY_SERVER_HANDLED "handled=true"
-/* Instead of the greeter run the chooser */
-#define GDM_KEY_SERVER_CHOOSER "chooser=false"
-/* select a nice level to run the X server at */
-#define GDM_KEY_SERVER_PRIORITY "priority=0"
-
-#define GDM_KEY_ALLOW_ROOT "security/AllowRoot=true"
-#define GDM_KEY_ALLOW_REMOTE_ROOT "security/AllowRemoteRoot=false"
-#define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin=false"
-#define GDM_KEY_USER_MAX_FILE "security/UserMaxFile=65536"
-#define GDM_KEY_RELAX_PERM "security/RelaxPermissions=0"
-#define GDM_KEY_CHECK_DIR_OWNER "security/CheckDirOwner=true"
-#define GDM_KEY_SUPPORT_AUTOMOUNT "security/SupportAutomount=false"
-#define GDM_KEY_RETRY_DELAY "security/RetryDelay=1"
-#define GDM_KEY_DISALLOW_TCP "security/DisallowTCP=true"
-#define GDM_KEY_PAM_STACK "security/PamStack=gdm"
-
-#define GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS "security/NeverPlaceCookiesOnNFS=true"
-#define GDM_KEY_PASSWORD_REQUIRED "security/PasswordRequired=false"
-
-#define GDM_KEY_XDMCP "xdmcp/Enable=false"
-#define GDM_KEY_MAX_PENDING "xdmcp/MaxPending=4"
-#define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions=16"
-#define GDM_KEY_MAX_WAIT "xdmcp/MaxWait=15"
-#define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost=2"
-#define GDM_KEY_UDP_PORT "xdmcp/Port=177"
-#define GDM_KEY_INDIRECT "xdmcp/HonorIndirect=true"
-#define GDM_KEY_MAX_INDIRECT "xdmcp/MaxPendingIndirect=4"
-#define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect=15"
-#define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds=15"
-#define GDM_KEY_WILLING "xdmcp/Willing=" GDMCONFDIR "/Xwilling"
-
-#define GDM_KEY_XDMCP_PROXY "xdmcp/EnableProxy=false"
-#define GDM_KEY_XDMCP_PROXY_XSERVER "xdmcp/ProxyXServer="
-#define GDM_KEY_XDMCP_PROXY_RECONNECT "xdmcp/ProxyReconnect="
-
-#define GDM_KEY_GTK_THEME "gui/GtkTheme=Default"
-#define GDM_KEY_GTKRC "gui/GtkRC=" DATADIR "/themes/Default/gtk-2.0/gtkrc"
-#define GDM_KEY_MAX_ICON_WIDTH "gui/MaxIconWidth=128"
-#define GDM_KEY_MAX_ICON_HEIGHT "gui/MaxIconHeight=128"
-
-#define GDM_KEY_ALLOW_GTK_THEME_CHANGE "gui/AllowGtkThemeChange=true"
-#define GDM_KEY_GTK_THEMES_TO_ALLOW "gui/GtkThemesToAllow=all"
-
-#define GDM_KEY_BROWSER "greeter/Browser=false"
-#define GDM_KEY_INCLUDE "greeter/Include="
-#define GDM_KEY_EXCLUDE "greeter/Exclude=bin,daemon,adm,lp,sync,shutdown,halt,mail,news,uucp,operator,nobody,gdm,postgres,pvm,rpm,nfsnobody,pcap"
-#define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll=false"
-#define GDM_KEY_MINIMAL_UID "greeter/MinimalUID=100"
-#define GDM_KEY_DEFAULT_FACE "greeter/DefaultFace=" PIXMAPDIR "/nobody.png"
-#define GDM_KEY_GLOBAL_FACE_DIR "greeter/GlobalFaceDir=" DATADIR "/pixmaps/faces/"
-#define GDM_KEY_LOCALE_FILE "greeter/LocaleFile=" GDMLOCALEDIR "/locale.alias"
-#define GDM_KEY_LOGO "greeter/Logo=" PIXMAPDIR "/gdm-foot-logo.png"
-#define GDM_KEY_CHOOSER_BUTTON_LOGO "greeter/ChooserButtonLogo=" PIXMAPDIR "/gdm-foot-logo.png"
-#define GDM_KEY_QUIVER "greeter/Quiver=true"
-#define GDM_KEY_SYSTEM_MENU "greeter/SystemMenu=true"
-#define GDM_KEY_CONFIGURATOR "daemon/Configurator=" SBINDIR "/gdmsetup --disable-sound --disable-crash-dialog"
-#define GDM_KEY_CONFIG_AVAILABLE "greeter/ConfigAvailable=true"
-#define GDM_KEY_CHOOSER_BUTTON "greeter/ChooserButton=true"
-#define GDM_KEY_TITLE_BAR "greeter/TitleBar=true"
-
-/*
  * For backwards compatibility, do not set values for DEFAULT_WELCOME or 
  * DEFAULT_REMOTEWELCOME.  This will cause these values to always be 
  * read from the config file, and will cause them to return FALSE if
@@ -362,66 +155,6 @@ enum {
 #define GDM_DEFAULT_WELCOME_MSG "Welcome"
 #define GDM_DEFAULT_REMOTE_WELCOME_MSG "Welcome to %n"
 
-#define GDM_KEY_DEFAULT_WELCOME "greeter/DefaultWelcome=" 
-#define GDM_KEY_DEFAULT_REMOTE_WELCOME "greeter/DefaultRemoteWelcome=" 
-#define GDM_KEY_WELCOME "greeter/Welcome=" GDM_DEFAULT_WELCOME_MSG
-#define GDM_KEY_REMOTE_WELCOME "greeter/RemoteWelcome=" GDM_DEFAULT_REMOTE_WELCOME_MSG
-#define GDM_KEY_XINERAMA_SCREEN "greeter/XineramaScreen=0"
-#define GDM_KEY_BACKGROUND_PROGRAM "greeter/BackgroundProgram="
-#define GDM_KEY_RUN_BACKGROUND_PROGRAM_ALWAYS "greeter/RunBackgroundProgramAlways=false"
-#define GDM_KEY_BACKGROUND_PROGRAM_INITIAL_DELAY "greeter/BackgroundProgramInitialDelay=30"
-#define GDM_KEY_RESTART_BACKGROUND_PROGRAM "greeter/RestartBackgroundProgram=true"
-#define GDM_KEY_BACKGROUND_PROGRAM_RESTART_DELAY "greeter/BackgroundProgramRestartDelay=30"
-#define GDM_KEY_BACKGROUND_IMAGE "greeter/BackgroundImage="
-#define GDM_KEY_BACKGROUND_COLOR "greeter/BackgroundColor=#76848F"
-#define GDM_KEY_BACKGROUND_TYPE "greeter/BackgroundType=2"
-#define GDM_KEY_BACKGROUND_SCALE_TO_FIT "greeter/BackgroundScaleToFit=true"
-#define GDM_KEY_BACKGROUND_REMOTE_ONLY_COLOR "greeter/BackgroundRemoteOnlyColor=true"
-#define GDM_KEY_LOCK_POSITION "greeter/LockPosition=false"
-#define GDM_KEY_SET_POSITION "greeter/SetPosition=false"
-#define GDM_KEY_POSITION_X "greeter/PositionX=0"
-#define GDM_KEY_POSITION_Y "greeter/PositionY=0"
-#define GDM_KEY_USE_24_CLOCK "greeter/Use24Clock=auto"
-#define GDM_KEY_ENTRY_CIRCLES "greeter/UseCirclesInEntry=false"
-#define GDM_KEY_ENTRY_INVISIBLE "greeter/UseInvisibleInEntry=false"
-#define GDM_KEY_GRAPHICAL_THEME "greeter/GraphicalTheme=circles"
-#define GDM_KEY_GRAPHICAL_THEMES "greeter/GraphicalThemes=circles/:happygnome"
-#define GDM_KEY_GRAPHICAL_THEME_RAND "greeter/GraphicalThemeRand=false"
-#define GDM_KEY_GRAPHICAL_THEME_DIR "greeter/GraphicalThemeDir=" DATADIR "/gdm/themes/"
-#define GDM_KEY_GRAPHICAL_THEMED_COLOR "greeter/GraphicalThemedColor=#76848F"
-
-#define GDM_KEY_INFO_MSG_FILE "greeter/InfoMsgFile="
-#define GDM_KEY_INFO_MSG_FONT "greeter/InfoMsgFont="
-
-#define GDM_KEY_PRE_FETCH_PROGRAM "greeter/PreFetchProgram="
-
-#define GDM_KEY_SOUND_ON_LOGIN "greeter/SoundOnLogin=true"
-#define GDM_KEY_SOUND_ON_LOGIN_SUCCESS "greeter/SoundOnLoginSuccess=false"
-#define GDM_KEY_SOUND_ON_LOGIN_FAILURE "greeter/SoundOnLoginFailure=false"
-#define GDM_KEY_SOUND_ON_LOGIN_FILE "greeter/SoundOnLoginFile="
-#define GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE "greeter/SoundOnLoginSuccessFile="
-#define GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE "greeter/SoundOnLoginFailureFile="
-#define GDM_KEY_SOUND_PROGRAM "daemon/SoundProgram=" SOUND_PROGRAM
-
-#define GDM_KEY_SCAN_TIME "chooser/ScanTime=4"
-#define GDM_KEY_DEFAULT_HOST_IMG "chooser/DefaultHostImg=" PIXMAPDIR "/nohost.png"
-#define GDM_KEY_HOST_IMAGE_DIR "chooser/HostImageDir=" DATADIR "/hosts/"
-#define GDM_KEY_HOSTS "chooser/Hosts="
-#define GDM_KEY_MULTICAST "chooser/Multicast=false"
-#define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr=ff02::1"
-#define GDM_KEY_BROADCAST "chooser/Broadcast=true"
-#define GDM_KEY_ALLOW_ADD "chooser/AllowAdd=true"
-
-#define GDM_KEY_DEBUG "debug/Enable=false"
-#define GDM_KEY_DEBUG_GESTURES "debug/Gestures=false"
-
-#define GDM_KEY_SECTION_GREETER "greeter"
-#define GDM_KEY_SECTION_SERVERS "servers"
-
-#define GDM_KEY_SHOW_GNOME_FAILSAFE "greeter/ShowGnomeFailsafeSession=true"
-#define GDM_KEY_SHOW_XTERM_FAILSAFE "greeter/ShowXtermFailsafeSession=true"
-#define GDM_KEY_SHOW_LAST_SESSION "greeter/ShowLastSession=true"
-
 #define GDM_SESSION_FAILSAFE_GNOME "GDM_Failsafe.GNOME"
 #define GDM_SESSION_FAILSAFE_XTERM "GDM_Failsafe.XTERM"
 
@@ -609,6 +342,7 @@ struct _GdmXserver {
 	gboolean choosable; /* not implemented yet */
 	gboolean chooser; /* instead of greeter, run chooser */
 	gboolean handled;
+	int number;
 	int priority;
 };
 
Index: daemon/filecheck.c
===================================================================
--- daemon/filecheck.c	(revision 4696)
+++ daemon/filecheck.c	(working copy)
@@ -24,9 +24,9 @@
 
 #include "gdm.h"
 #include "filecheck.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 /**
  * gdm_file_check:
@@ -60,7 +60,7 @@ gdm_file_check (const gchar *caller, uid
     /* Stat on automounted directory - append the '/.' to dereference mount point.
        Do this only if GdmSupportAutomount is true (default is false)
        2006-09-22, Jerzy Borkowski, CAMK */
-    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_SUPPORT_AUTOMOUNT)) {
+    if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_SUPPORT_AUTOMOUNT)) {
         dirautofs = g_strconcat(dir, "/.", NULL);
         VE_IGNORE_EINTR (r = stat (dirautofs, &statbuf));
         g_free(dirautofs);
@@ -83,7 +83,7 @@ gdm_file_check (const gchar *caller, uid
        the user.
        2004-06-22, Andreas Schubert, MATHEMA Software GmbH */
 
-    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_CHECK_DIR_OWNER) && (statbuf.st_uid != user)) {
+    if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_CHECK_DIR_OWNER) && (statbuf.st_uid != user)) {
         syslog (LOG_WARNING, _("%s: %s is not owned by uid %d."), caller, dir, user);
         return FALSE;
     }
@@ -199,7 +199,7 @@ gdm_auth_file_check (const gchar *caller
 	return FALSE;
     }
 
-    usermaxfile = gdm_get_value_int (GDM_KEY_USER_MAX_FILE);
+    usermaxfile = gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE);
     /* ... and smaller than sysadmin specified limit. */
     if G_UNLIKELY (usermaxfile && statbuf.st_size > usermaxfile) {
 	syslog (LOG_WARNING, _("%s: %s is bigger than sysadmin specified maximum file size."), 
Index: daemon/verify-pam.c
===================================================================
--- daemon/verify-pam.c	(revision 4696)
+++ daemon/verify-pam.c	(working copy)
@@ -37,9 +37,9 @@
 #include "slave.h"
 #include "verify.h"
 #include "errorgui.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 #ifdef	HAVE_LOGINDEVPERM
 #include <libdevinfo.h>
@@ -829,9 +829,9 @@ verify_user_again:
     null_tok = 0;
 
     /* start the timer for timed logins */
-    if ( ! ve_string_empty (gdm_get_value_string (GDM_KEY_TIMED_LOGIN)) &&
+    if ( ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN)) &&
 	d->timed_login_ok &&
-	(local || gdm_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN))) {
+	(local || gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN))) {
 	    gdm_slave_greeter_ctl_no_ret (GDM_STARTTIMER, "");
 	    started_timer = TRUE;
     }
@@ -862,7 +862,7 @@ authenticate_again:
      * PAM Stacks, in case one display should use a different 
      * authentication mechanism than another display.
      */
-    pam_stack = gdm_get_value_string_per_display ((char *)display,
+    pam_stack = gdm_daemon_config_get_value_string_per_display ((char *)display,
 	GDM_KEY_PAM_STACK);
 
     if ( ! create_pamh (d, pam_stack, login, &pamc, display, &pamerr)) {
@@ -888,16 +888,16 @@ authenticate_again:
        when running the configurator.  We wish to ourselves cancel logins
        without a delay, so ... evil */
 #ifdef PAM_FAIL_DELAY
-    pam_fail_delay (pamh, gdm_get_value_int (GDM_KEY_RETRY_DELAY) * 1000000);
+    pam_fail_delay (pamh, gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY) * 1000000);
 #endif /* PAM_FAIL_DELAY */
 #endif
 
     passreq = gdm_read_default ("PASSREQ=");
     if ((passreq != NULL) &&
 	g_ascii_strcasecmp (passreq, "YES") == 0)
-	    gdm_set_value_bool (GDM_KEY_PASSWORD_REQUIRED, TRUE);
+	    gdm_daemon_config_set_value_bool (GDM_KEY_PASSWORD_REQUIRED, TRUE);
 
-    if (gdm_get_value_bool (GDM_KEY_PASSWORD_REQUIRED))
+    if (gdm_daemon_config_get_value_bool (GDM_KEY_PASSWORD_REQUIRED))
 	    null_tok |= PAM_DISALLOW_NULL_AUTHTOK;
 	    
     gdm_verify_select_user (NULL);
@@ -944,7 +944,7 @@ authenticate_again:
 	    if (gdm_slave_action_pending ()) {
 		    /* FIXME: see note above about PAM_FAIL_DELAY */
 /* #ifndef PAM_FAIL_DELAY */
-		    gdm_sleep_no_signal (gdm_get_value_int (GDM_KEY_RETRY_DELAY));
+		    gdm_sleep_no_signal (gdm_daemon_config_get_value_int (GDM_KEY_RETRY_DELAY));
 		    /* wait up to 100ms randomly */
 		    usleep (g_random_int_range (0, 100000));
 /* #endif */ /* PAM_FAIL_DELAY */
@@ -1019,11 +1019,11 @@ authenticate_again:
     consoleonly = gdm_read_default ("CONSOLE=");
     if ((consoleonly != NULL) &&
 	g_ascii_strcasecmp (consoleonly, "/dev/console") == 0)
-	    gdm_set_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT, FALSE);
+	    gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT, FALSE);
 
     pwent = getpwnam (login);
-    if ( ( ! gdm_get_value_bool (GDM_KEY_ALLOW_ROOT) ||
-	  ( ! gdm_get_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT) && ! local) ) &&
+    if ( ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_ROOT) ||
+	  ( ! gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT) && ! local) ) &&
 	pwent != NULL &&
 	pwent->pw_uid == 0) {
 	    gdm_error (_("Root login disallowed on display '%s'"),
@@ -1046,7 +1046,7 @@ authenticate_again:
 	    goto pamerr;
     }
 
-    if (gdm_get_value_bool (GDM_KEY_DISPLAY_LAST_LOGIN)) {
+    if (gdm_daemon_config_get_value_bool (GDM_KEY_DISPLAY_LAST_LOGIN)) {
 	char *info = gdm_get_last_info (login);
 	gdm_slave_greeter_ctl_no_ret (GDM_MSG, info);
 	g_free (info);
@@ -1282,7 +1282,7 @@ gdm_verify_setup_user (GdmDisplay *d, co
      * PAM Stacks, in case one display should use a different 
      * authentication mechanism than another display.
      */
-    pam_stack = gdm_get_value_string_per_display ((char *)display, GDM_KEY_PAM_STACK);
+    pam_stack = gdm_daemon_config_get_value_string_per_display ((char *)display, GDM_KEY_PAM_STACK);
     pam_service_name = g_strdup_printf ("%s-autologin", pam_stack);
 
     if ( ! create_pamh (d, pam_service_name, login, &standalone_pamc,
@@ -1297,9 +1297,9 @@ gdm_verify_setup_user (GdmDisplay *d, co
     passreq = gdm_read_default ("PASSREQ=");
     if ((passreq != NULL) &&
 	g_ascii_strcasecmp (passreq, "YES") == 0)
-	    gdm_set_value_bool (GDM_KEY_PASSWORD_REQUIRED, TRUE);
+	    gdm_daemon_config_set_value_bool (GDM_KEY_PASSWORD_REQUIRED, TRUE);
 
-    if (gdm_get_value_bool (GDM_KEY_PASSWORD_REQUIRED))
+    if (gdm_daemon_config_get_value_bool (GDM_KEY_PASSWORD_REQUIRED))
 	    null_tok |= PAM_DISALLOW_NULL_AUTHTOK;
 
     /* Start authentication session */
@@ -1586,14 +1586,14 @@ gdm_verify_check (void)
 {
 	pam_handle_t *ph = NULL;
 
-	if (pam_start (gdm_get_value_string (GDM_KEY_PAM_STACK), NULL,
+	if (pam_start (gdm_daemon_config_get_value_string (GDM_KEY_PAM_STACK), NULL,
 		&standalone_pamc, &ph) != PAM_SUCCESS) {
 		ph = NULL; /* be anal */
 
 		closelog ();
 		openlog ("gdm", LOG_PID, LOG_DAEMON);
 
-		if (gdm_get_value_bool (GDM_KEY_CONSOLE_NOTIFY))
+		if (gdm_daemon_config_get_value_bool (GDM_KEY_CONSOLE_NOTIFY))
 			gdm_text_message_dialog
 				(C_(N_("Can't find PAM configuration for GDM.")));
 		gdm_fail ("gdm_verify_check: %s",
Index: daemon/gdm-daemon-config-entries.h
===================================================================
--- daemon/gdm-daemon-config-entries.h	(revision 0)
+++ daemon/gdm-daemon-config-entries.h	(revision 0)
@@ -0,0 +1,572 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GDM_DAEMON_CONFIG_ENTRIES_H
+#define _GDM_DAEMON_CONFIG_ENTRIES_H
+
+#include <glib.h>
+
+#include "gdm-config.h"
+
+G_BEGIN_DECLS
+
+#define GDM_CONFIG_GROUP_NONE       NULL
+#define GDM_CONFIG_GROUP_DAEMON     "daemon"
+#define GDM_CONFIG_GROUP_SECURITY   "security"
+#define GDM_CONFIG_GROUP_XDMCP      "xdmcp"
+#define GDM_CONFIG_GROUP_GREETER    "greeter"
+#define GDM_CONFIG_GROUP_GUI        "gui"
+#define GDM_CONFIG_GROUP_CUSTOM_CMD "customcommand"
+#define GDM_CONFIG_GROUP_CHOOSER    "chooser"
+#define GDM_CONFIG_GROUP_SERVERS    "servers"
+#define GDM_CONFIG_GROUP_DEBUG      "debug"
+
+#define GDM_CONFIG_GROUP_SERVER_PREFIX "server-"
+
+#include "gdm-daemon-config-keys.h"
+
+typedef enum {
+	GDM_ID_NONE,
+	GDM_ID_DEBUG,
+	GDM_ID_DEBUG_GESTURES,
+	GDM_ID_CHOOSER,
+	GDM_ID_AUTOMATIC_LOGIN_ENABLE,
+	GDM_ID_AUTOMATIC_LOGIN,
+	GDM_ID_ALWAYS_RESTART_SERVER,
+	GDM_ID_GREETER,
+	GDM_ID_REMOTE_GREETER,
+	GDM_ID_ADD_GTK_MODULES,
+	GDM_ID_GTK_MODULES_LIST,
+	GDM_ID_GROUP,
+	GDM_ID_HALT,
+	GDM_ID_DISPLAY_INIT_DIR,
+	GDM_ID_KILL_INIT_CLIENTS,
+	GDM_ID_LOG_DIR,
+	GDM_ID_PATH,
+	GDM_ID_PID_FILE,
+	GDM_ID_POSTSESSION,
+	GDM_ID_PRESESSION,
+	GDM_ID_POSTLOGIN,
+	GDM_ID_FAILSAFE_XSERVER,
+	GDM_ID_X_KEEPS_CRASHING,
+	GDM_ID_REBOOT ,
+	GDM_ID_CUSTOM_CMD_TEMPLATE,
+	GDM_ID_CUSTOM_CMD_LABEL_TEMPLATE,
+	GDM_ID_CUSTOM_CMD_LR_LABEL_TEMPLATE,
+	GDM_ID_CUSTOM_CMD_TEXT_TEMPLATE,
+	GDM_ID_CUSTOM_CMD_TOOLTIP_TEMPLATE,
+	GDM_ID_CUSTOM_CMD_NO_RESTART_TEMPLATE,
+	GDM_ID_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE,
+	GDM_ID_ROOT_PATH,
+	GDM_ID_SERV_AUTHDIR,
+	GDM_ID_SESSION_DESKTOP_DIR,
+	GDM_ID_BASE_XSESSION,
+	GDM_ID_DEFAULT_SESSION,
+	GDM_ID_SUSPEND,
+	GDM_ID_USER_AUTHDIR,
+	GDM_ID_USER_AUTHDIR_FALLBACK,
+	GDM_ID_USER_AUTHFILE,
+	GDM_ID_USER,
+	GDM_ID_CONSOLE_NOTIFY,
+	GDM_ID_DOUBLE_LOGIN_WARNING,
+	GDM_ID_ALWAYS_LOGIN_CURRENT_SESSION,
+	GDM_ID_DISPLAY_LAST_LOGIN,
+	GDM_ID_TIMED_LOGIN_ENABLE,
+	GDM_ID_TIMED_LOGIN,
+	GDM_ID_TIMED_LOGIN_DELAY,
+	GDM_ID_FLEXI_REAP_DELAY_MINUTES,
+	GDM_ID_STANDARD_XSERVER,
+	GDM_ID_FLEXIBLE_XSERVERS,
+	GDM_ID_DYNAMIC_XSERVERS,
+	GDM_ID_XNEST,
+	GDM_ID_XNEST_UNSCALED_FONT_PATH,
+	GDM_ID_FIRST_VT,
+	GDM_ID_VT_ALLOCATION,
+	GDM_ID_CONSOLE_CANNOT_HANDLE,
+	GDM_ID_XSERVER_TIMEOUT,
+	GDM_ID_SERVER_PREFIX,
+	GDM_ID_SERVER_NAME,
+	GDM_ID_SERVER_COMMAND,
+	GDM_ID_SERVER_FLEXIBLE,
+	GDM_ID_SERVER_CHOOSABLE,
+	GDM_ID_SERVER_HANDLED,
+	GDM_ID_SERVER_CHOOSER,
+	GDM_ID_SERVER_PRIORITY,
+	GDM_ID_ALLOW_ROOT,
+	GDM_ID_ALLOW_REMOTE_ROOT,
+	GDM_ID_ALLOW_REMOTE_AUTOLOGIN,
+	GDM_ID_USER_MAX_FILE,
+	GDM_ID_RELAX_PERM,
+	GDM_ID_CHECK_DIR_OWNER,
+	GDM_ID_SUPPORT_AUTOMOUNT,
+	GDM_ID_RETRY_DELAY,
+	GDM_ID_DISALLOW_TCP,
+	GDM_ID_PAM_STACK,
+	GDM_ID_NEVER_PLACE_COOKIES_ON_NFS,
+	GDM_ID_PASSWORD_REQUIRED,
+	GDM_ID_XDMCP,
+	GDM_ID_MAX_PENDING,
+	GDM_ID_MAX_SESSIONS,
+	GDM_ID_MAX_WAIT,
+	GDM_ID_DISPLAYS_PER_HOST,
+	GDM_ID_UDP_PORT,
+	GDM_ID_INDIRECT,
+	GDM_ID_MAX_INDIRECT,
+	GDM_ID_MAX_WAIT_INDIRECT,
+	GDM_ID_PING_INTERVAL,
+	GDM_ID_WILLING,
+	GDM_ID_XDMCP_PROXY,
+	GDM_ID_XDMCP_PROXY_XSERVER,
+	GDM_ID_XDMCP_PROXY_RECONNECT,
+	GDM_ID_GTK_THEME,
+	GDM_ID_GTKRC,
+	GDM_ID_MAX_ICON_WIDTH,
+	GDM_ID_MAX_ICON_HEIGHT,
+	GDM_ID_ALLOW_GTK_THEME_CHANGE,
+	GDM_ID_GTK_THEMES_TO_ALLOW,
+	GDM_ID_BROWSER,
+	GDM_ID_INCLUDE,
+	GDM_ID_EXCLUDE,
+	GDM_ID_INCLUDE_ALL,
+	GDM_ID_MINIMAL_UID,
+	GDM_ID_DEFAULT_FACE,
+	GDM_ID_GLOBAL_FACE_DIR,
+	GDM_ID_LOCALE_FILE,
+	GDM_ID_LOGO,
+	GDM_ID_CHOOSER_BUTTON_LOGO,
+	GDM_ID_QUIVER,
+	GDM_ID_SYSTEM_MENU,
+	GDM_ID_CONFIGURATOR,
+	GDM_ID_CONFIG_AVAILABLE,
+	GDM_ID_CHOOSER_BUTTON,
+	GDM_ID_TITLE_BAR,
+	GDM_ID_DEFAULT_WELCOME,
+	GDM_ID_DEFAULT_REMOTE_WELCOME,
+	GDM_ID_WELCOME,
+	GDM_ID_REMOTE_WELCOME,
+	GDM_ID_XINERAMA_SCREEN,
+	GDM_ID_BACKGROUND_PROGRAM,
+	GDM_ID_RUN_BACKGROUND_PROGRAM_ALWAYS,
+	GDM_ID_BACKGROUND_PROGRAM_INITIAL_DELAY,
+	GDM_ID_RESTART_BACKGROUND_PROGRAM,
+	GDM_ID_BACKGROUND_PROGRAM_RESTART_DELAY,
+	GDM_ID_BACKGROUND_IMAGE,
+	GDM_ID_BACKGROUND_COLOR,
+	GDM_ID_BACKGROUND_TYPE,
+	GDM_ID_BACKGROUND_SCALE_TO_FIT,
+	GDM_ID_BACKGROUND_REMOTE_ONLY_COLOR,
+	GDM_ID_LOCK_POSITION,
+	GDM_ID_SET_POSITION,
+	GDM_ID_POSITION_X,
+	GDM_ID_POSITION_Y,
+	GDM_ID_USE_24_CLOCK,
+	GDM_ID_ENTRY_CIRCLES,
+	GDM_ID_ENTRY_INVISIBLE,
+	GDM_ID_GRAPHICAL_THEME,
+	GDM_ID_GRAPHICAL_THEMES,
+	GDM_ID_GRAPHICAL_THEME_RAND,
+	GDM_ID_GRAPHICAL_THEME_DIR,
+	GDM_ID_GRAPHICAL_THEMED_COLOR,
+	GDM_ID_INFO_MSG_FILE,
+	GDM_ID_INFO_MSG_FONT,
+	GDM_ID_PRE_FETCH_PROGRAM,
+	GDM_ID_SOUND_ON_LOGIN,
+	GDM_ID_SOUND_ON_LOGIN_SUCCESS,
+	GDM_ID_SOUND_ON_LOGIN_FAILURE,
+	GDM_ID_SOUND_ON_LOGIN_FILE,
+	GDM_ID_SOUND_ON_LOGIN_SUCCESS_FILE,
+	GDM_ID_SOUND_ON_LOGIN_FAILURE_FILE,
+	GDM_ID_SOUND_PROGRAM,
+	GDM_ID_SCAN_TIME,
+	GDM_ID_DEFAULT_HOST_IMG,
+	GDM_ID_HOST_IMAGE_DIR,
+	GDM_ID_HOSTS,
+	GDM_ID_MULTICAST,
+	GDM_ID_MULTICAST_ADDR,
+	GDM_ID_BROADCAST,
+	GDM_ID_ALLOW_ADD,
+	GDM_ID_SECTION_GREETER,
+	GDM_ID_SECTION_SERVERS,
+	GDM_ID_SHOW_GNOME_FAILSAFE,
+	GDM_ID_SHOW_XTERM_FAILSAFE,
+	GDM_ID_SHOW_LAST_SESSION,
+	GDK_KEY_LAST
+} GdmConfigKey;
+
+
+/*
+ * The following section contains keys used by the GDM configuration files.
+ * The key/value pairs defined in the GDM configuration files are considered
+ * "stable" interface and should only change in ways that are backwards
+ * compatible.  Please keep this in mind when changing GDM configuration.
+ *
+ * Developers who add new configuration options should ensure that they do the
+ * following:
+ *
+ * + Edit the config/gdm.conf file to include the default setting.
+ *
+ * + Specify the same default in this file as in the config/gdm.conf.in file.
+ *
+ * + Update the config_options[] to add the
+ *   new key.  Include some documentation about the new key, following the
+ *   style of existing comments.
+ *
+ * + Add any validation to the _gdm_set_value_string, _gdm_set_value_int,
+ *   and/or _gdm_set_value_bool functions (depending on the type of the new
+ *   key) in gdmconfig.c, if validation is needed.
+ *
+ * + If GDM_UPDATE_CONFIG should not respond to this configuration setting,
+ *   update the update_config function in gdmconfig.c to return FALSE for
+ *   this key.  Examples include changing the PidFile, ServAuthDir, or
+ *   other values that GDM should not change until it is restarted.  If
+ *   this is true, the next bullet can be ignored.
+ *
+ * + If the option should cause the greeter (gdmlogin/gdmgreeter) program to
+ *   be updated immediately, make sure to update the appropriate
+ *   _gdm_set_value_* function in gdmconfig.c.  This function calls the
+ *   notify_displays_* function to call when this value is changed, so you
+ *   will need to add your new config value to the list of values sending
+ *   such notification.  Supporting logic will need to be added to
+ *   gdm_slave_handle_notify function in slave.c to process the notify.
+ *   It should be clear to see how to do this from the existing code.
+ *
+ * + Add the key to the gdm_read_config and gdm_reread_config functions in
+ *   gui/gdmlogin.c, gui/gdmchooser.c, and gui/greeter/greeter.c
+ *   if the key is used by those programs.  Note that all GDM slaves load
+ *   all their configuration data between calls to gdmcomm_comm_bulk_start()
+ *   and gdmcomm_comm_bulk_stop().  This makes sure that the slave only uses
+ *   a single sockets connection to get all configuration data.  If a new
+ *   config value is read by a slave, make sure to load the key in this
+ *   code section for best performance.
+ *
+ * + The gui/gdmsetup.c program should be updated to support the new option
+ *   unless there's a good reason not to (like it is a configuration value
+ *   that only someone who really knows what they are doing should change
+ *   like GDM_ID_PID_FILE).
+ *
+ * + Currently GDM treats any key in the "gui" and "greeter" categories,
+ *   and security/PamStack as available for per-display configuration.
+ *   If a key is appropriate for per-display configuration, and is not
+ *   in the "gui" or "greeter" categories, then it will need to be added
+ *   to the gdm_config_key_to_string_per_display function.  It may make
+ *   sense for some keys used by the daemon to be per-display so this
+ *   will need to be coded (refer to GDM_ID_PAM_STACK for an example).
+ *
+ * + Update the docs/C/gdm.xml file to include information about the new
+ *   option.  Include information about any other interfaces (such as
+ *   ENVIRONMENT variables) that may affect the configuration option.
+ *   Patches without documentation will not be accepted.
+ *
+ * Please do this work *before* submitting an patch.  Patches that are not
+ * complete will not likely be accepted.
+ */
+
+#define GDM_DEFAULT_WELCOME_MSG "Welcome"
+#define GDM_DEFAULT_REMOTE_WELCOME_MSG "Welcome to %n"
+
+/* These are processed in order so debug should always be first */
+static const GdmConfigEntry gdm_daemon_config_entries [] = {
+	{ GDM_CONFIG_GROUP_DEBUG, "Enable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_DEBUG },
+	{ GDM_CONFIG_GROUP_DEBUG, "Gestures", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_DEBUG_GESTURES },
+
+
+	{ GDM_CONFIG_GROUP_DAEMON, "Chooser", GDM_CONFIG_VALUE_STRING, LIBEXECDIR "/gdmchooser", GDM_ID_CHOOSER },
+	{ GDM_CONFIG_GROUP_DAEMON, "AutomaticLoginEnable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_AUTOMATIC_LOGIN_ENABLE },
+	{ GDM_CONFIG_GROUP_DAEMON, "AutomaticLogin", GDM_CONFIG_VALUE_STRING, "", GDM_ID_AUTOMATIC_LOGIN },
+
+	/* The SDTLOGIN feature is Solaris specific, and causes the Xserver to be
+	 * run with user permissionsinstead of as root, which adds security but,
+	 * disables the AlwaysRestartServer option as highlighted in the gdm
+	 * documentation */
+
+	{ GDM_CONFIG_GROUP_DAEMON, "AlwaysRestartServer", GDM_CONFIG_VALUE_BOOL, ALWAYS_RESTART_SERVER, GDM_ID_ALWAYS_RESTART_SERVER },
+	{ GDM_CONFIG_GROUP_DAEMON, "Greeter", GDM_CONFIG_VALUE_STRING, LIBEXECDIR "/gdmlogin", GDM_ID_GREETER },
+	{ GDM_CONFIG_GROUP_DAEMON, "RemoteGreeter", GDM_CONFIG_VALUE_STRING, LIBEXECDIR "/gdmlogin", GDM_ID_REMOTE_GREETER },
+	{ GDM_CONFIG_GROUP_DAEMON, "AddGtkModules", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ADD_GTK_MODULES },
+	{ GDM_CONFIG_GROUP_DAEMON, "GtkModulesList", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_GTK_MODULES_LIST },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "User", GDM_CONFIG_VALUE_STRING, "gdm", GDM_ID_USER },
+	{ GDM_CONFIG_GROUP_DAEMON, "Group", GDM_CONFIG_VALUE_STRING, "gdm", GDM_ID_GROUP },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "HaltCommand", GDM_CONFIG_VALUE_STRING_ARRAY, HALT_COMMAND, GDM_ID_HALT },
+	{ GDM_CONFIG_GROUP_DAEMON, "RebootCommand", GDM_CONFIG_VALUE_STRING_ARRAY, REBOOT_COMMAND, GDM_ID_REBOOT },
+	{ GDM_CONFIG_GROUP_DAEMON, "SuspendCommand", GDM_CONFIG_VALUE_STRING_ARRAY, SUSPEND_COMMAND, GDM_ID_SUSPEND },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "DisplayInitDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/Init", GDM_ID_DISPLAY_INIT_DIR },
+	{ GDM_CONFIG_GROUP_DAEMON, "KillInitClients", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_KILL_INIT_CLIENTS },
+	{ GDM_CONFIG_GROUP_DAEMON, "LogDir", GDM_CONFIG_VALUE_STRING, LOGDIR, GDM_ID_LOG_DIR },
+	{ GDM_CONFIG_GROUP_DAEMON, "DefaultPath", GDM_CONFIG_VALUE_STRING, GDM_USER_PATH, GDM_ID_PATH },
+	{ GDM_CONFIG_GROUP_DAEMON, "PidFile", GDM_CONFIG_VALUE_STRING, "/var/run/gdm.pid", GDM_ID_PID_FILE },
+	{ GDM_CONFIG_GROUP_DAEMON, "PostSessionScriptDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/PostSession/", GDM_ID_POSTSESSION },
+	{ GDM_CONFIG_GROUP_DAEMON, "PreSessionScriptDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/PreSession/", GDM_ID_PRESESSION },
+	{ GDM_CONFIG_GROUP_DAEMON, "PostLoginScriptDir", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/PreSession/", GDM_ID_POSTLOGIN },
+	{ GDM_CONFIG_GROUP_DAEMON, "FailsafeXServer", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_FAILSAFE_XSERVER },
+	{ GDM_CONFIG_GROUP_DAEMON, "XKeepsCrashing", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/XKeepsCrashing", GDM_ID_X_KEEPS_CRASHING },
+	{ GDM_CONFIG_GROUP_DAEMON, "RootPath", GDM_CONFIG_VALUE_STRING, "/sbin:/usr/sbin:" GDM_USER_PATH, GDM_ID_ROOT_PATH },
+	{ GDM_CONFIG_GROUP_DAEMON, "ServAuthDir", GDM_CONFIG_VALUE_STRING, AUTHDIR, GDM_ID_SERV_AUTHDIR },
+	{ GDM_CONFIG_GROUP_DAEMON, "SessionDesktopDir", GDM_CONFIG_VALUE_STRING, "/etc/X11/sessions/:" DMCONFDIR "/Sessions/:" DATADIR "/gdm/BuiltInSessions/:" DATADIR "/xsessions/", GDM_ID_SESSION_DESKTOP_DIR },
+	{ GDM_CONFIG_GROUP_DAEMON, "BaseXsession", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/Xsession", GDM_ID_BASE_XSESSION },
+	{ GDM_CONFIG_GROUP_DAEMON, "DefaultSession", GDM_CONFIG_VALUE_STRING, "gnome.desktop", GDM_ID_DEFAULT_SESSION },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "UserAuthDir", GDM_CONFIG_VALUE_STRING, "", GDM_ID_USER_AUTHDIR },
+	{ GDM_CONFIG_GROUP_DAEMON, "UserAuthFBDir", GDM_CONFIG_VALUE_STRING, "/tmp", GDM_ID_USER_AUTHDIR_FALLBACK },
+	{ GDM_CONFIG_GROUP_DAEMON, "UserAuthFile", GDM_CONFIG_VALUE_STRING, ".Xauthority", GDM_ID_USER_AUTHFILE },
+	{ GDM_CONFIG_GROUP_DAEMON, "ConsoleNotify", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_CONSOLE_NOTIFY },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "DoubleLoginWarning", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_DOUBLE_LOGIN_WARNING },
+	{ GDM_CONFIG_GROUP_DAEMON, "AlwaysLoginCurrentSession", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALWAYS_LOGIN_CURRENT_SESSION },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "DisplayLastLogin", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_DISPLAY_LAST_LOGIN },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "TimedLoginEnable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_TIMED_LOGIN_ENABLE },
+	{ GDM_CONFIG_GROUP_DAEMON, "TimedLogin", GDM_CONFIG_VALUE_STRING, "", GDM_ID_TIMED_LOGIN },
+	{ GDM_CONFIG_GROUP_DAEMON, "TimedLoginDelay", GDM_CONFIG_VALUE_INT, "30", GDM_ID_TIMED_LOGIN_DELAY },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "FlexiReapDelayMinutes", GDM_CONFIG_VALUE_INT, "5", GDM_ID_FLEXI_REAP_DELAY_MINUTES },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "StandardXServer", GDM_CONFIG_VALUE_STRING, X_SERVER, GDM_ID_STANDARD_XSERVER },
+	{ GDM_CONFIG_GROUP_DAEMON, "FlexibleXServers", GDM_CONFIG_VALUE_INT, "5", GDM_ID_FLEXIBLE_XSERVERS },
+	{ GDM_CONFIG_GROUP_DAEMON, "DynamicXServers", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_DYNAMIC_XSERVERS },
+	{ GDM_CONFIG_GROUP_DAEMON, "Xnest", GDM_CONFIG_VALUE_STRING, X_XNEST_CMD ", " X_XNEST_CONFIG_OPTIONS, GDM_ID_XNEST },
+	{ GDM_CONFIG_GROUP_DAEMON, "XnestUnscaledFontPath", GDM_CONFIG_VALUE_BOOL, X_XNEST_UNSCALED_FONTPATH, GDM_ID_XNEST_UNSCALED_FONT_PATH },
+
+	/* Keys for automatic VT allocation rather then letting it up to the X server */
+	{ GDM_CONFIG_GROUP_DAEMON, "FirstVT", GDM_CONFIG_VALUE_INT, "7", GDM_ID_FIRST_VT },
+	{ GDM_CONFIG_GROUP_DAEMON, "VTAllocation", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_VT_ALLOCATION },
+
+	{ GDM_CONFIG_GROUP_DAEMON, "ConsoleCannotHandle", GDM_CONFIG_VALUE_STRING, "am,ar,az,bn,el,fa,gu,hi,ja,ko,ml,mr,pa,ta,zh", GDM_ID_CONSOLE_CANNOT_HANDLE },
+
+	/* How long to wait before assuming an Xserver has timed out */
+	{ GDM_CONFIG_GROUP_DAEMON, "GdmXserverTimeout", GDM_CONFIG_VALUE_INT, "10", GDM_ID_XSERVER_TIMEOUT },
+
+	{ GDM_CONFIG_GROUP_SECURITY, "AllowRoot", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALLOW_ROOT },
+	{ GDM_CONFIG_GROUP_SECURITY, "AllowRemoteRoot", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ALLOW_REMOTE_ROOT },
+	{ GDM_CONFIG_GROUP_SECURITY, "AllowRemoteAutoLogin", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ALLOW_REMOTE_AUTOLOGIN },
+	{ GDM_CONFIG_GROUP_SECURITY, "UserMaxFile", GDM_CONFIG_VALUE_INT, "65536", GDM_ID_USER_MAX_FILE },
+	{ GDM_CONFIG_GROUP_SECURITY, "RelaxPermissions", GDM_CONFIG_VALUE_INT, "0", GDM_ID_RELAX_PERM },
+	{ GDM_CONFIG_GROUP_SECURITY, "CheckDirOwner", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_CHECK_DIR_OWNER },
+	{ GDM_CONFIG_GROUP_SECURITY, "SupportAutomount", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SUPPORT_AUTOMOUNT },
+	{ GDM_CONFIG_GROUP_SECURITY, "RetryDelay", GDM_CONFIG_VALUE_INT, "1", GDM_ID_RETRY_DELAY },
+	{ GDM_CONFIG_GROUP_SECURITY, "DisallowTCP", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_DISALLOW_TCP },
+	{ GDM_CONFIG_GROUP_SECURITY, "PamStack", GDM_CONFIG_VALUE_STRING, "gdm", GDM_ID_PAM_STACK },
+
+	{ GDM_CONFIG_GROUP_SECURITY, "NeverPlaceCookiesOnNFS", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_NEVER_PLACE_COOKIES_ON_NFS },
+	{ GDM_CONFIG_GROUP_SECURITY, "PasswordRequired", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_PASSWORD_REQUIRED },
+
+	{ GDM_CONFIG_GROUP_XDMCP, "Enable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_XDMCP },
+	{ GDM_CONFIG_GROUP_XDMCP, "MaxPending", GDM_CONFIG_VALUE_INT, "4", GDM_ID_MAX_PENDING },
+	{ GDM_CONFIG_GROUP_XDMCP, "MaxSessions", GDM_CONFIG_VALUE_INT, "16", GDM_ID_MAX_SESSIONS },
+	{ GDM_CONFIG_GROUP_XDMCP, "MaxWait", GDM_CONFIG_VALUE_INT, "15", GDM_ID_MAX_WAIT },
+	{ GDM_CONFIG_GROUP_XDMCP, "DisplaysPerHost", GDM_CONFIG_VALUE_INT, "2", GDM_ID_DISPLAYS_PER_HOST },
+	{ GDM_CONFIG_GROUP_XDMCP, "Port", GDM_CONFIG_VALUE_INT, "177", GDM_ID_UDP_PORT },
+	{ GDM_CONFIG_GROUP_XDMCP, "HonorIndirect", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_INDIRECT },
+	{ GDM_CONFIG_GROUP_XDMCP, "MaxPendingIndirect", GDM_CONFIG_VALUE_INT, "4", GDM_ID_MAX_INDIRECT },
+	{ GDM_CONFIG_GROUP_XDMCP, "MaxWaitIndirect", GDM_CONFIG_VALUE_INT, "15", GDM_ID_MAX_WAIT_INDIRECT },
+	{ GDM_CONFIG_GROUP_XDMCP, "PingIntervalSeconds", GDM_CONFIG_VALUE_INT, "15", GDM_ID_PING_INTERVAL },
+	{ GDM_CONFIG_GROUP_XDMCP, "Willing", GDM_CONFIG_VALUE_STRING, GDMCONFDIR "/Xwilling", GDM_ID_WILLING },
+
+	{ GDM_CONFIG_GROUP_XDMCP, "EnableProxy", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_XDMCP_PROXY },
+	{ GDM_CONFIG_GROUP_XDMCP, "ProxyXServer", GDM_CONFIG_VALUE_STRING, "", GDM_ID_XDMCP_PROXY_XSERVER },
+	{ GDM_CONFIG_GROUP_XDMCP, "ProxyReconnect", GDM_CONFIG_VALUE_STRING, "", GDM_ID_XDMCP_PROXY_RECONNECT },
+
+	{ GDM_CONFIG_GROUP_GUI, "GtkTheme", GDM_CONFIG_VALUE_STRING, "Default", GDM_ID_GTK_THEME },
+	{ GDM_CONFIG_GROUP_GUI, "GtkRC", GDM_CONFIG_VALUE_STRING, DATADIR "/themes/Default/gtk-2.0/gtkrc", GDM_ID_GTKRC },
+	{ GDM_CONFIG_GROUP_GUI, "MaxIconWidth", GDM_CONFIG_VALUE_INT, "128", GDM_ID_MAX_ICON_WIDTH },
+	{ GDM_CONFIG_GROUP_GUI, "MaxIconHeight", GDM_CONFIG_VALUE_INT, "128", GDM_ID_MAX_ICON_HEIGHT },
+
+	{ GDM_CONFIG_GROUP_GUI, "AllowGtkThemeChange", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALLOW_GTK_THEME_CHANGE },
+	{ GDM_CONFIG_GROUP_GUI, "GtkThemesToAllow", GDM_CONFIG_VALUE_STRING, "all", GDM_ID_GTK_THEMES_TO_ALLOW },
+
+	{ GDM_CONFIG_GROUP_GREETER, "Browser", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_BROWSER },
+	{ GDM_CONFIG_GROUP_GREETER, "Include", GDM_CONFIG_VALUE_STRING, "", GDM_ID_INCLUDE },
+	{ GDM_CONFIG_GROUP_GREETER, "Exclude", GDM_CONFIG_VALUE_STRING, "bin,daemon,adm,lp,sync,shutdown,halt,mail,news,uucp,operator,nobody,gdm,postgres,pvm,rpm,nfsnobody,pcap", GDM_ID_EXCLUDE },
+	{ GDM_CONFIG_GROUP_GREETER, "IncludeAll", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_INCLUDE_ALL },
+	{ GDM_CONFIG_GROUP_GREETER, "MinimalUID", GDM_CONFIG_VALUE_INT, "100", GDM_ID_MINIMAL_UID },
+	{ GDM_CONFIG_GROUP_GREETER, "DefaultFace", GDM_CONFIG_VALUE_STRING, PIXMAPDIR "/nobody.png", GDM_ID_DEFAULT_FACE },
+	{ GDM_CONFIG_GROUP_GREETER, "GlobalFaceDir", GDM_CONFIG_VALUE_STRING, DATADIR "/pixmaps/faces/", GDM_ID_GLOBAL_FACE_DIR },
+	{ GDM_CONFIG_GROUP_GREETER, "LocaleFile", GDM_CONFIG_VALUE_STRING, GDMLOCALEDIR "/locale.alias", GDM_ID_LOCALE_FILE },
+	{ GDM_CONFIG_GROUP_GREETER, "Logo", GDM_CONFIG_VALUE_STRING, PIXMAPDIR "/gdm-foot-logo.png", GDM_ID_LOGO },
+	{ GDM_CONFIG_GROUP_GREETER, "ChooserButtonLogo", GDM_CONFIG_VALUE_STRING, PIXMAPDIR "/gdm-foot-logo.png", GDM_ID_CHOOSER_BUTTON_LOGO },
+	{ GDM_CONFIG_GROUP_GREETER, "Quiver", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_QUIVER },
+	{ GDM_CONFIG_GROUP_GREETER, "SystemMenu", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SYSTEM_MENU },
+	{ GDM_CONFIG_GROUP_DAEMON, "Configurator", GDM_CONFIG_VALUE_STRING, SBINDIR "/gdmsetup --disable-sound --disable-crash-dialog", GDM_ID_CONFIGURATOR },
+	{ GDM_CONFIG_GROUP_GREETER, "ConfigAvailable", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_CONFIG_AVAILABLE },
+	{ GDM_CONFIG_GROUP_GREETER, "ChooserButton", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_CHOOSER_BUTTON },
+	{ GDM_CONFIG_GROUP_GREETER, "TitleBar", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_TITLE_BAR },
+
+	/*
+	 * For backwards compatibility, do not set values for DEFAULT_WELCOME or
+	 * DEFAULT_REMOTEWELCOME.  This will cause these values to always be
+	 * read from the config file, and will cause them to return FALSE if
+	 * no value is set in the config file.  We want the value, "FALSE" if
+	 * the values don't exist in the config file.  The daemon will compare
+	 * the Welcome/RemoveWelcome value with the default string and
+	 * automatically translate the text if the string is the same as the
+	 * default string.  We set the default values of GDM_ID_WELCOME and
+	 * GDM_ID_REMOTEWELCOME so that the default value is returned when
+	 * you run GET_CONFIG on these keys.
+	 */
+	{ GDM_CONFIG_GROUP_GREETER, "DefaultWelcome", GDM_CONFIG_VALUE_BOOL, "", GDM_ID_DEFAULT_WELCOME },
+	{ GDM_CONFIG_GROUP_GREETER, "DefaultRemoteWelcome", GDM_CONFIG_VALUE_BOOL, "", GDM_ID_DEFAULT_REMOTE_WELCOME },
+	{ GDM_CONFIG_GROUP_GREETER, "Welcome", GDM_CONFIG_VALUE_STRING, GDM_DEFAULT_WELCOME_MSG, GDM_ID_WELCOME },
+	{ GDM_CONFIG_GROUP_GREETER, "RemoteWelcome", GDM_CONFIG_VALUE_STRING, GDM_DEFAULT_REMOTE_WELCOME_MSG, GDM_ID_REMOTE_WELCOME },
+	{ GDM_CONFIG_GROUP_GREETER, "XineramaScreen", GDM_CONFIG_VALUE_INT, "0", GDM_ID_XINERAMA_SCREEN },
+	{ GDM_CONFIG_GROUP_GREETER, "BackgroundProgram", GDM_CONFIG_VALUE_STRING, "", GDM_ID_BACKGROUND_PROGRAM },
+	{ GDM_CONFIG_GROUP_GREETER, "RunBackgroundProgramAlways", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_RUN_BACKGROUND_PROGRAM_ALWAYS },
+	{ GDM_CONFIG_GROUP_GREETER, "BackgroundProgramInitialDelay", GDM_CONFIG_VALUE_INT, "30", GDM_ID_BACKGROUND_PROGRAM_INITIAL_DELAY },
+	{ GDM_CONFIG_GROUP_GREETER, "RestartBackgroundProgram", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_RESTART_BACKGROUND_PROGRAM },
+	{ GDM_CONFIG_GROUP_GREETER, "BackgroundProgramRestartDelay", GDM_CONFIG_VALUE_INT, "30", GDM_ID_BACKGROUND_PROGRAM_RESTART_DELAY },
+	{ GDM_CONFIG_GROUP_GREETER, "BackgroundImage", GDM_CONFIG_VALUE_STRING, "", GDM_ID_BACKGROUND_IMAGE },
+	{ GDM_CONFIG_GROUP_GREETER, "BackgroundColor", GDM_CONFIG_VALUE_STRING, "#76848F", GDM_ID_BACKGROUND_COLOR },
+	{ GDM_CONFIG_GROUP_GREETER, "BackgroundType", GDM_CONFIG_VALUE_INT, "2", GDM_ID_BACKGROUND_TYPE },
+	{ GDM_CONFIG_GROUP_GREETER, "BackgroundScaleToFit", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_BACKGROUND_SCALE_TO_FIT },
+	{ GDM_CONFIG_GROUP_GREETER, "BackgroundRemoteOnlyColor", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_BACKGROUND_REMOTE_ONLY_COLOR },
+	{ GDM_CONFIG_GROUP_GREETER, "LockPosition", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_LOCK_POSITION },
+	{ GDM_CONFIG_GROUP_GREETER, "SetPosition", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SET_POSITION },
+	{ GDM_CONFIG_GROUP_GREETER, "PositionX", GDM_CONFIG_VALUE_INT, "0", GDM_ID_POSITION_X },
+	{ GDM_CONFIG_GROUP_GREETER, "PositionY", GDM_CONFIG_VALUE_INT, "0", GDM_ID_POSITION_Y },
+	{ GDM_CONFIG_GROUP_GREETER, "Use24Clock", GDM_CONFIG_VALUE_STRING, "auto", GDM_ID_USE_24_CLOCK },
+	{ GDM_CONFIG_GROUP_GREETER, "UseCirclesInEntry", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ENTRY_CIRCLES },
+	{ GDM_CONFIG_GROUP_GREETER, "UseInvisibleInEntry", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_ENTRY_INVISIBLE },
+	{ GDM_CONFIG_GROUP_GREETER, "GraphicalTheme", GDM_CONFIG_VALUE_STRING, "circles", GDM_ID_GRAPHICAL_THEME },
+	{ GDM_CONFIG_GROUP_GREETER, "GraphicalThemes", GDM_CONFIG_VALUE_STRING, "circles/:happygnome", GDM_ID_GRAPHICAL_THEMES },
+	{ GDM_CONFIG_GROUP_GREETER, "GraphicalThemeRand", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_GRAPHICAL_THEME_RAND },
+	{ GDM_CONFIG_GROUP_GREETER, "GraphicalThemeDir", GDM_CONFIG_VALUE_STRING, DATADIR "/gdm/themes/", GDM_ID_GRAPHICAL_THEME_DIR },
+	{ GDM_CONFIG_GROUP_GREETER, "GraphicalThemedColor", GDM_CONFIG_VALUE_STRING, "#76848F", GDM_ID_GRAPHICAL_THEMED_COLOR },
+
+	{ GDM_CONFIG_GROUP_GREETER, "InfoMsgFile", GDM_CONFIG_VALUE_STRING, "", GDM_ID_INFO_MSG_FILE },
+	{ GDM_CONFIG_GROUP_GREETER, "InfoMsgFont", GDM_CONFIG_VALUE_STRING, "", GDM_ID_INFO_MSG_FONT },
+
+	{ GDM_CONFIG_GROUP_GREETER, "PreFetchProgram", GDM_CONFIG_VALUE_STRING, "", GDM_ID_PRE_FETCH_PROGRAM },
+
+	{ GDM_CONFIG_GROUP_GREETER, "SoundOnLogin", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SOUND_ON_LOGIN },
+	{ GDM_CONFIG_GROUP_GREETER, "SoundOnLoginSuccess", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SOUND_ON_LOGIN_SUCCESS },
+	{ GDM_CONFIG_GROUP_GREETER, "SoundOnLoginFailure", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SOUND_ON_LOGIN_FAILURE },
+	{ GDM_CONFIG_GROUP_GREETER, "SoundOnLoginFile", GDM_CONFIG_VALUE_STRING, "", GDM_ID_SOUND_ON_LOGIN_FILE },
+	{ GDM_CONFIG_GROUP_GREETER, "SoundOnLoginSuccessFile", GDM_CONFIG_VALUE_STRING, "", GDM_ID_SOUND_ON_LOGIN_SUCCESS_FILE },
+	{ GDM_CONFIG_GROUP_GREETER, "SoundOnLoginFailureFile", GDM_CONFIG_VALUE_STRING, "", GDM_ID_SOUND_ON_LOGIN_FAILURE_FILE },
+	{ GDM_CONFIG_GROUP_DAEMON, "SoundProgram", GDM_CONFIG_VALUE_STRING, SOUND_PROGRAM, GDM_ID_SOUND_PROGRAM },
+
+	{ GDM_CONFIG_GROUP_CHOOSER, "ScanTime", GDM_CONFIG_VALUE_INT, "4", GDM_ID_SCAN_TIME },
+	{ GDM_CONFIG_GROUP_CHOOSER, "DefaultHostImg", GDM_CONFIG_VALUE_STRING, PIXMAPDIR "/nohost.png", GDM_ID_DEFAULT_HOST_IMG },
+	{ GDM_CONFIG_GROUP_CHOOSER, "HostImageDir", GDM_CONFIG_VALUE_STRING, DATADIR "/hosts/", GDM_ID_HOST_IMAGE_DIR },
+	{ GDM_CONFIG_GROUP_CHOOSER, "Hosts", GDM_CONFIG_VALUE_STRING, "", GDM_ID_HOSTS },
+	{ GDM_CONFIG_GROUP_CHOOSER, "Multicast", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_MULTICAST },
+	{ GDM_CONFIG_GROUP_CHOOSER, "MulticastAddr", GDM_CONFIG_VALUE_STRING, "ff02::1", GDM_ID_MULTICAST_ADDR },
+	{ GDM_CONFIG_GROUP_CHOOSER, "Broadcast", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_BROADCAST },
+	{ GDM_CONFIG_GROUP_CHOOSER, "AllowAdd", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_ALLOW_ADD },
+
+	{ GDM_CONFIG_GROUP_GREETER, "ShowGnomeFailsafeSession", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SHOW_GNOME_FAILSAFE },
+	{ GDM_CONFIG_GROUP_GREETER, "ShowXtermFailsafeSession", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SHOW_XTERM_FAILSAFE },
+	{ GDM_CONFIG_GROUP_GREETER, "ShowLastSession", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SHOW_LAST_SESSION },
+
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand0", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel0", GDM_CONFIG_VALUE_STRING, "Custom_0", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel0", GDM_CONFIG_VALUE_STRING, "Execute custom command _0", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText0", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip0", GDM_CONFIG_VALUE_STRING, "Execute custom command 0", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart0", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent0", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand1", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel1", GDM_CONFIG_VALUE_STRING, "Custom_1", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel1", GDM_CONFIG_VALUE_STRING, "Execute custom command _1", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText1", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip1", GDM_CONFIG_VALUE_STRING, "Execute custom command 1", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart1", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent1", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand2", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel2", GDM_CONFIG_VALUE_STRING, "Custom_2", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel2", GDM_CONFIG_VALUE_STRING, "Execute custom command _2", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText2", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip2", GDM_CONFIG_VALUE_STRING, "Execute custom command 2", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart2", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent2", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand3", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel3", GDM_CONFIG_VALUE_STRING, "Custom_3", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel3", GDM_CONFIG_VALUE_STRING, "Execute custom command _3", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText3", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip3", GDM_CONFIG_VALUE_STRING, "Execute custom command 3", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart3", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent3", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand4", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel4", GDM_CONFIG_VALUE_STRING, "Custom_4", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel4", GDM_CONFIG_VALUE_STRING, "Execute custom command _4", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText4", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip4", GDM_CONFIG_VALUE_STRING, "Execute custom command 4", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart4", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent4", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand5", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel5", GDM_CONFIG_VALUE_STRING, "Custom_5", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel5", GDM_CONFIG_VALUE_STRING, "Execute custom command _5", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText5", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip5", GDM_CONFIG_VALUE_STRING, "Execute custom command 5", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart5", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent5", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand6", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel6", GDM_CONFIG_VALUE_STRING, "Custom_6", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel6", GDM_CONFIG_VALUE_STRING, "Execute custom command _6", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText6", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip6", GDM_CONFIG_VALUE_STRING, "Execute custom command 6", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart6", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent6", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand7", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel7", GDM_CONFIG_VALUE_STRING, "Custom_7", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel7", GDM_CONFIG_VALUE_STRING, "Execute custom command _7", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText7", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip7", GDM_CONFIG_VALUE_STRING, "Execute custom command 7", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart7", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent7", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand8", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel8", GDM_CONFIG_VALUE_STRING, "Custom_8", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel8", GDM_CONFIG_VALUE_STRING, "Execute custom command _8", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText8", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip8", GDM_CONFIG_VALUE_STRING, "Execute custom command 8", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart8", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent8", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommand9", GDM_CONFIG_VALUE_STRING, NULL, GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLabel9", GDM_CONFIG_VALUE_STRING, "Custom_9", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandLRLabel9", GDM_CONFIG_VALUE_STRING, "Execute custom command _9", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandText9", GDM_CONFIG_VALUE_STRING, "Are you sure?", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandTooltip9", GDM_CONFIG_VALUE_STRING, "Execute custom command 9", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandNoRestart9", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+	{ GDM_CONFIG_GROUP_CUSTOM_CMD, "CustomCommandIsPersistent9", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_NONE },
+
+	{ NULL }
+};
+
+static const GdmConfigEntry gdm_daemon_server_config_entries [] = {
+	/* Per server definitions */
+	{ GDM_CONFIG_GROUP_NONE, "name", GDM_CONFIG_VALUE_STRING, "Standard server", GDM_ID_SERVER_NAME },
+	{ GDM_CONFIG_GROUP_NONE, "command", GDM_CONFIG_VALUE_STRING, X_SERVER, GDM_ID_SERVER_COMMAND },
+	/* runnable as flexi server */
+	{ GDM_CONFIG_GROUP_NONE, "flexible", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SERVER_FLEXIBLE },
+	/* choosable from the login screen */
+	{ GDM_CONFIG_GROUP_NONE, "choosable", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SERVER_CHOOSABLE },
+	/* Login is handled by gdm, otherwise it's a remote server */
+	{ GDM_CONFIG_GROUP_NONE, "handled", GDM_CONFIG_VALUE_BOOL, "true", GDM_ID_SERVER_HANDLED },
+	/* Instead of the greeter run the chooser */
+	{ GDM_CONFIG_GROUP_NONE, "chooser", GDM_CONFIG_VALUE_BOOL, "false", GDM_ID_SERVER_CHOOSER },
+	/* select a nice level to run the X server at */
+	{ GDM_CONFIG_GROUP_NONE, "priority", GDM_CONFIG_VALUE_INT, "0", GDM_ID_SERVER_PRIORITY },
+};
+
+G_END_DECLS
+
+#endif /* _GDM_DAEMON_CONFIG_ENTRIES_H */
Index: daemon/gdm-daemon-config-keys.h
===================================================================
--- daemon/gdm-daemon-config-keys.h	(revision 0)
+++ daemon/gdm-daemon-config-keys.h	(revision 0)
@@ -0,0 +1,203 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _GDM_DAEMON_CONFIG_KEYS_H
+#define _GDM_DAEMON_CONFIG_KEYS_H
+
+#include <glib.h>
+
+#include "gdm-config.h"
+
+G_BEGIN_DECLS
+
+/* BEGIN LEGACY KEYS */
+#define GDM_KEY_CHOOSER "daemon/Chooser=" LIBEXECDIR "/gdmchooser"
+#define GDM_KEY_AUTOMATIC_LOGIN_ENABLE "daemon/AutomaticLoginEnable=false"
+#define GDM_KEY_AUTOMATIC_LOGIN "daemon/AutomaticLogin="
+#define GDM_KEY_ALWAYS_RESTART_SERVER "daemon/AlwaysRestartServer=" ALWAYS_RESTART_SERVER
+#define GDM_KEY_GREETER "daemon/Greeter=" LIBEXECDIR "/gdmlogin"
+#define GDM_KEY_REMOTE_GREETER "daemon/RemoteGreeter=" LIBEXECDIR "/gdmlogin"
+#define GDM_KEY_ADD_GTK_MODULES "daemon/AddGtkModules=false"
+#define GDM_KEY_GTK_MODULES_LIST "daemon/GtkModulesList="
+#define GDM_KEY_GROUP "daemon/Group=gdm"
+#define GDM_KEY_HALT "daemon/HaltCommand=" HALT_COMMAND
+#define GDM_KEY_DISPLAY_INIT_DIR "daemon/DisplayInitDir=" GDMCONFDIR "/Init"
+#define GDM_KEY_KILL_INIT_CLIENTS "daemon/KillInitClients=true"
+#define GDM_KEY_LOG_DIR "daemon/LogDir=" LOGDIR
+#define GDM_KEY_PATH "daemon/DefaultPath=" GDM_USER_PATH
+#define GDM_KEY_PID_FILE "daemon/PidFile=/var/run/gdm.pid"
+#define GDM_KEY_POSTSESSION "daemon/PostSessionScriptDir=" GDMCONFDIR "/PostSession/"
+#define GDM_KEY_PRESESSION "daemon/PreSessionScriptDir=" GDMCONFDIR "/PreSession/"
+#define GDM_KEY_POSTLOGIN "daemon/PostLoginScriptDir=" GDMCONFDIR "/PreSession/"
+#define GDM_KEY_FAILSAFE_XSERVER "daemon/FailsafeXServer="
+#define GDM_KEY_X_KEEPS_CRASHING "daemon/XKeepsCrashing=" GDMCONFDIR "/XKeepsCrashing"
+#define GDM_KEY_REBOOT  "daemon/RebootCommand=" REBOOT_COMMAND
+#define GDM_KEY_CUSTOM_CMD_TEMPLATE "customcommand/CustomCommand"
+#define GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE "customcommand/CustomCommandLabel"
+#define GDM_KEY_CUSTOM_CMD_LR_LABEL_TEMPLATE "customcommand/CustomCommandLRLabel"
+#define GDM_KEY_CUSTOM_CMD_TEXT_TEMPLATE "customcommand/CustomCommandText"
+#define GDM_KEY_CUSTOM_CMD_TOOLTIP_TEMPLATE "customcommand/CustomCommandTooltip"
+#define GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE "customcommand/CustomCommandNoRestart"
+#define GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE "customcommand/CustomCommandIsPersistent"
+#define GDM_KEY_ROOT_PATH "daemon/RootPath=/sbin:/usr/sbin:" GDM_USER_PATH
+#define GDM_KEY_SERV_AUTHDIR "daemon/ServAuthDir=" AUTHDIR
+#define GDM_KEY_SESSION_DESKTOP_DIR "daemon/SessionDesktopDir=/etc/X11/sessions/:" DMCONFDIR "/Sessions/:" DATADIR "/gdm/BuiltInSessions/:" DATADIR "/xsessions/"
+#define GDM_KEY_BASE_XSESSION "daemon/BaseXsession=" GDMCONFDIR "/Xsession"
+#define GDM_KEY_DEFAULT_SESSION "daemon/DefaultSession=gnome.desktop"
+#define GDM_KEY_SUSPEND "daemon/SuspendCommand=" SUSPEND_COMMAND
+#define GDM_KEY_USER_AUTHDIR "daemon/UserAuthDir="
+#define GDM_KEY_USER_AUTHDIR_FALLBACK "daemon/UserAuthFBDir=/tmp"
+#define GDM_KEY_USER_AUTHFILE "daemon/UserAuthFile=.Xauthority"
+#define GDM_KEY_USER "daemon/User=gdm"
+#define GDM_KEY_CONSOLE_NOTIFY "daemon/ConsoleNotify=true"
+#define GDM_KEY_DOUBLE_LOGIN_WARNING "daemon/DoubleLoginWarning=true"
+#define GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION "daemon/AlwaysLoginCurrentSession=true"
+#define GDM_KEY_DISPLAY_LAST_LOGIN "daemon/DisplayLastLogin=false"
+#define GDM_KEY_TIMED_LOGIN_ENABLE "daemon/TimedLoginEnable=false"
+#define GDM_KEY_TIMED_LOGIN "daemon/TimedLogin="
+#define GDM_KEY_TIMED_LOGIN_DELAY "daemon/TimedLoginDelay=30"
+#define GDM_KEY_FLEXI_REAP_DELAY_MINUTES "daemon/FlexiReapDelayMinutes=5"
+#define GDM_KEY_STANDARD_XSERVER "daemon/StandardXServer=" X_SERVER
+#define GDM_KEY_FLEXIBLE_XSERVERS "daemon/FlexibleXServers=5"
+#define GDM_KEY_DYNAMIC_XSERVERS "daemon/DynamicXServers=false"
+#define GDM_KEY_XNEST "daemon/Xnest=" X_XNEST_CMD " " X_XNEST_CONFIG_OPTIONS
+#define GDM_KEY_XNEST_UNSCALED_FONT_PATH "daemon/XnestUnscaledFontPath=" X_XNEST_UNSCALED_FONTPATH
+#define GDM_KEY_FIRST_VT "daemon/FirstVT=7"
+#define GDM_KEY_VT_ALLOCATION "daemon/VTAllocation=true"
+#define GDM_KEY_CONSOLE_CANNOT_HANDLE "daemon/ConsoleCannotHandle=am,ar,az,bn,el,fa,gu,hi,ja,ko,ml,mr,pa,ta,zh"
+#define GDM_KEY_XSERVER_TIMEOUT "daemon/GdmXserverTimeout=10"
+
+#define GDM_KEY_SERVER_PREFIX "server-"
+#define GDM_KEY_SERVER_NAME "name=Standard server"
+#define GDM_KEY_SERVER_COMMAND "command=" X_SERVER
+#define GDM_KEY_SERVER_FLEXIBLE "flexible=true"
+#define GDM_KEY_SERVER_CHOOSABLE "choosable=false"
+#define GDM_KEY_SERVER_HANDLED "handled=true"
+#define GDM_KEY_SERVER_CHOOSER "chooser=false"
+#define GDM_KEY_SERVER_PRIORITY "priority=0"
+
+#define GDM_KEY_ALLOW_ROOT "security/AllowRoot=true"
+#define GDM_KEY_ALLOW_REMOTE_ROOT "security/AllowRemoteRoot=false"
+#define GDM_KEY_ALLOW_REMOTE_AUTOLOGIN "security/AllowRemoteAutoLogin=false"
+#define GDM_KEY_USER_MAX_FILE "security/UserMaxFile=65536"
+#define GDM_KEY_RELAX_PERM "security/RelaxPermissions=0"
+#define GDM_KEY_CHECK_DIR_OWNER "security/CheckDirOwner=true"
+#define GDM_KEY_SUPPORT_AUTOMOUNT "security/SupportAutomount=false"
+#define GDM_KEY_RETRY_DELAY "security/RetryDelay=1"
+#define GDM_KEY_DISALLOW_TCP "security/DisallowTCP=true"
+#define GDM_KEY_PAM_STACK "security/PamStack=gdm"
+#define GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS "security/NeverPlaceCookiesOnNFS=true"
+#define GDM_KEY_PASSWORD_REQUIRED "security/PasswordRequired=false"
+#define GDM_KEY_XDMCP "xdmcp/Enable=false"
+#define GDM_KEY_MAX_PENDING "xdmcp/MaxPending=4"
+#define GDM_KEY_MAX_SESSIONS "xdmcp/MaxSessions=16"
+#define GDM_KEY_MAX_WAIT "xdmcp/MaxWait=15"
+#define GDM_KEY_DISPLAYS_PER_HOST "xdmcp/DisplaysPerHost=2"
+#define GDM_KEY_UDP_PORT "xdmcp/Port=177"
+#define GDM_KEY_INDIRECT "xdmcp/HonorIndirect=true"
+#define GDM_KEY_MAX_INDIRECT "xdmcp/MaxPendingIndirect=4"
+#define GDM_KEY_MAX_WAIT_INDIRECT "xdmcp/MaxWaitIndirect=15"
+#define GDM_KEY_PING_INTERVAL "xdmcp/PingIntervalSeconds=15"
+#define GDM_KEY_WILLING "xdmcp/Willing=" GDMCONFDIR "/Xwilling"
+#define GDM_KEY_XDMCP_PROXY "xdmcp/EnableProxy=false"
+#define GDM_KEY_XDMCP_PROXY_XSERVER "xdmcp/ProxyXServer="
+#define GDM_KEY_XDMCP_PROXY_RECONNECT "xdmcp/ProxyReconnect="
+#define GDM_KEY_GTK_THEME "gui/GtkTheme=Default"
+#define GDM_KEY_GTKRC "gui/GtkRC=" DATADIR "/themes/Default/gtk-2.0/gtkrc"
+#define GDM_KEY_MAX_ICON_WIDTH "gui/MaxIconWidth=128"
+#define GDM_KEY_MAX_ICON_HEIGHT "gui/MaxIconHeight=128"
+#define GDM_KEY_ALLOW_GTK_THEME_CHANGE "gui/AllowGtkThemeChange=true"
+#define GDM_KEY_GTK_THEMES_TO_ALLOW "gui/GtkThemesToAllow=all"
+#define GDM_KEY_BROWSER "greeter/Browser=false"
+#define GDM_KEY_INCLUDE "greeter/Include="
+#define GDM_KEY_EXCLUDE "greeter/Exclude=bin,daemon,adm,lp,sync,shutdown,halt,mail,news,uucp,operator,nobody,gdm,postgres,pvm,rpm,nfsnobody,pcap"
+#define GDM_KEY_INCLUDE_ALL "greeter/IncludeAll=false"
+#define GDM_KEY_MINIMAL_UID "greeter/MinimalUID=100"
+#define GDM_KEY_DEFAULT_FACE "greeter/DefaultFace=" PIXMAPDIR "/nobody.png"
+#define GDM_KEY_GLOBAL_FACE_DIR "greeter/GlobalFaceDir=" DATADIR "/pixmaps/faces/"
+#define GDM_KEY_LOCALE_FILE "greeter/LocaleFile=" GDMLOCALEDIR "/locale.alias"
+#define GDM_KEY_LOGO "greeter/Logo=" PIXMAPDIR "/gdm-foot-logo.png"
+#define GDM_KEY_CHOOSER_BUTTON_LOGO "greeter/ChooserButtonLogo=" PIXMAPDIR "/gdm-foot-logo.png"
+#define GDM_KEY_QUIVER "greeter/Quiver=true"
+#define GDM_KEY_SYSTEM_MENU "greeter/SystemMenu=true"
+#define GDM_KEY_CONFIGURATOR "daemon/Configurator=" SBINDIR "/gdmsetup --disable-sound --disable-crash-dialog"
+#define GDM_KEY_CONFIG_AVAILABLE "greeter/ConfigAvailable=true"
+#define GDM_KEY_CHOOSER_BUTTON "greeter/ChooserButton=true"
+#define GDM_KEY_TITLE_BAR "greeter/TitleBar=true"
+#define GDM_DEFAULT_WELCOME_MSG "Welcome"
+#define GDM_DEFAULT_REMOTE_WELCOME_MSG "Welcome to %n"
+#define GDM_KEY_DEFAULT_WELCOME "greeter/DefaultWelcome="
+#define GDM_KEY_DEFAULT_REMOTE_WELCOME "greeter/DefaultRemoteWelcome="
+#define GDM_KEY_WELCOME "greeter/Welcome=" GDM_DEFAULT_WELCOME_MSG
+#define GDM_KEY_REMOTE_WELCOME "greeter/RemoteWelcome=" GDM_DEFAULT_REMOTE_WELCOME_MSG
+#define GDM_KEY_XINERAMA_SCREEN "greeter/XineramaScreen=0"
+#define GDM_KEY_BACKGROUND_PROGRAM "greeter/BackgroundProgram="
+#define GDM_KEY_RUN_BACKGROUND_PROGRAM_ALWAYS "greeter/RunBackgroundProgramAlways=false"
+#define GDM_KEY_BACKGROUND_PROGRAM_INITIAL_DELAY "greeter/BackgroundProgramInitialDelay=30"
+#define GDM_KEY_RESTART_BACKGROUND_PROGRAM "greeter/RestartBackgroundProgram=true"
+#define GDM_KEY_BACKGROUND_PROGRAM_RESTART_DELAY "greeter/BackgroundProgramRestartDelay=30"
+#define GDM_KEY_BACKGROUND_IMAGE "greeter/BackgroundImage="
+#define GDM_KEY_BACKGROUND_COLOR "greeter/BackgroundColor=#76848F"
+#define GDM_KEY_BACKGROUND_TYPE "greeter/BackgroundType=2"
+#define GDM_KEY_BACKGROUND_SCALE_TO_FIT "greeter/BackgroundScaleToFit=true"
+#define GDM_KEY_BACKGROUND_REMOTE_ONLY_COLOR "greeter/BackgroundRemoteOnlyColor=true"
+#define GDM_KEY_LOCK_POSITION "greeter/LockPosition=false"
+#define GDM_KEY_SET_POSITION "greeter/SetPosition=false"
+#define GDM_KEY_POSITION_X "greeter/PositionX=0"
+#define GDM_KEY_POSITION_Y "greeter/PositionY=0"
+#define GDM_KEY_USE_24_CLOCK "greeter/Use24Clock=auto"
+#define GDM_KEY_ENTRY_CIRCLES "greeter/UseCirclesInEntry=false"
+#define GDM_KEY_ENTRY_INVISIBLE "greeter/UseInvisibleInEntry=false"
+#define GDM_KEY_GRAPHICAL_THEME "greeter/GraphicalTheme=circles"
+#define GDM_KEY_GRAPHICAL_THEMES "greeter/GraphicalThemes=circles/:happygnome"
+#define GDM_KEY_GRAPHICAL_THEME_RAND "greeter/GraphicalThemeRand=false"
+#define GDM_KEY_GRAPHICAL_THEME_DIR "greeter/GraphicalThemeDir=" DATADIR "/gdm/themes/"
+#define GDM_KEY_GRAPHICAL_THEMED_COLOR "greeter/GraphicalThemedColor=#76848F"
+#define GDM_KEY_INFO_MSG_FILE "greeter/InfoMsgFile="
+#define GDM_KEY_INFO_MSG_FONT "greeter/InfoMsgFont="
+#define GDM_KEY_PRE_FETCH_PROGRAM "greeter/PreFetchProgram="
+#define GDM_KEY_SOUND_ON_LOGIN "greeter/SoundOnLogin=true"
+#define GDM_KEY_SOUND_ON_LOGIN_SUCCESS "greeter/SoundOnLoginSuccess=false"
+#define GDM_KEY_SOUND_ON_LOGIN_FAILURE "greeter/SoundOnLoginFailure=false"
+#define GDM_KEY_SOUND_ON_LOGIN_FILE "greeter/SoundOnLoginFile="
+#define GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE "greeter/SoundOnLoginSuccessFile="
+#define GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE "greeter/SoundOnLoginFailureFile="
+#define GDM_KEY_SOUND_PROGRAM "daemon/SoundProgram=" SOUND_PROGRAM
+#define GDM_KEY_SCAN_TIME "chooser/ScanTime=4"
+#define GDM_KEY_DEFAULT_HOST_IMG "chooser/DefaultHostImg=" PIXMAPDIR "/nohost.png"
+#define GDM_KEY_HOST_IMAGE_DIR "chooser/HostImageDir=" DATADIR "/hosts/"
+#define GDM_KEY_HOSTS "chooser/Hosts="
+#define GDM_KEY_MULTICAST "chooser/Multicast=false"
+#define GDM_KEY_MULTICAST_ADDR "chooser/MulticastAddr=ff02::1"
+#define GDM_KEY_BROADCAST "chooser/Broadcast=true"
+#define GDM_KEY_ALLOW_ADD "chooser/AllowAdd=true"
+#define GDM_KEY_DEBUG "debug/Enable=false"
+#define GDM_KEY_DEBUG_GESTURES "debug/Gestures=false"
+#define GDM_KEY_SECTION_GREETER "greeter"
+#define GDM_KEY_SECTION_SERVERS "servers"
+#define GDM_KEY_SHOW_GNOME_FAILSAFE "greeter/ShowGnomeFailsafeSession=true"
+#define GDM_KEY_SHOW_XTERM_FAILSAFE "greeter/ShowXtermFailsafeSession=true"
+#define GDM_KEY_SHOW_LAST_SESSION "greeter/ShowLastSession=true"
+
+/* END LEGACY KEYS */
+
+G_END_DECLS
+
+#endif /* _GDM_DAEMON_CONFIG_KEYS_H */
Index: daemon/getvt.c
===================================================================
--- daemon/getvt.c	(revision 4696)
+++ daemon/getvt.c	(working copy)
@@ -32,9 +32,9 @@
 #include "gdm.h"
 #include "misc.h"
 #include "getvt.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 /* Virtual terminals only supported on Linux, FreeBSD, or DragonFly */
 
@@ -111,7 +111,7 @@ get_free_vt_linux (int *vtfd)
 		return -1;
 	}
 
-	for (vtno = gdm_get_value_int (GDM_KEY_FIRST_VT), vtmask = 1 << vtno;
+	for (vtno = gdm_daemon_config_get_value_int (GDM_KEY_FIRST_VT), vtmask = 1 << vtno;
 			vtstat.v_state & vtmask; vtno++, vtmask <<= 1);
 	if (!vtmask) {
 		VE_IGNORE_EINTR (close (fd));
@@ -160,7 +160,7 @@ get_free_vt_freebsd_dragonfly (int *vtfd
 		return -1;
 	}
 
-	while (vtno < gdm_get_value_int (GDM_KEY_FIRST_VT)) {
+	while (vtno < gdm_daemon_config_get_value_int (GDM_KEY_FIRST_VT)) {
 		int oldvt = vtno;
 		to_close_vts = g_list_prepend (to_close_vts,
 					       GINT_TO_POINTER (fdv));
@@ -196,7 +196,7 @@ cleanup:
 char *
 gdm_get_empty_vt_argument (int *fd, int *vt)
 {
-	if ( ! gdm_get_value_bool (GDM_KEY_VT_ALLOCATION)) {
+	if ( ! gdm_daemon_config_get_value_bool (GDM_KEY_VT_ALLOCATION)) {
 		*fd = -1;
 		return NULL;
 	}
Index: daemon/auth.c
===================================================================
--- daemon/auth.c	(revision 4696)
+++ daemon/auth.c	(working copy)
@@ -39,9 +39,9 @@
 #include "misc.h"
 #include "filecheck.h"
 #include "auth.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 /* Ensure we know about FamilyInternetV6 even if what we're compiling
    against doesn't */
@@ -189,7 +189,7 @@ gdm_auth_secure_display (GdmDisplay *d)
 	    /* Note, Xnest can't use the GDM_KEY_SERV_AUTHDIR unless running as
 	     * root, which is rare anyway. */
 
-	    d->authfile = g_build_filename (gdm_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL);
+	    d->authfile = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL);
 
 	    umask (077);
 	    authfd = g_mkstemp (d->authfile);
@@ -197,7 +197,7 @@ gdm_auth_secure_display (GdmDisplay *d)
 
 	    if G_UNLIKELY (authfd == -1) {
 		    gdm_error (_("%s: Could not make new cookie file in %s"),
-			       "gdm_auth_secure_display", gdm_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK));
+			       "gdm_auth_secure_display", gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK));
 		    g_free (d->authfile);
 		    d->authfile = NULL;
 		    return FALSE;
@@ -216,7 +216,7 @@ gdm_auth_secure_display (GdmDisplay *d)
 
 	    /* Make another authfile since the greeter can't read the server/user
 	     * readable file */
-	    d->authfile_gdm = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth");
+	    d->authfile_gdm = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth");
 	    af_gdm = gdm_safe_fopen_w (d->authfile_gdm);
 
 	    if G_UNLIKELY (af_gdm == NULL) {
@@ -233,7 +233,7 @@ gdm_auth_secure_display (GdmDisplay *d)
 	    }
     } else {
 	    /* gdm and xserver authfile can be the same, server will run as root */
-	    d->authfile = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth");
+	    d->authfile = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR), d->name, ".Xauth");
 	    af = gdm_safe_fopen_w (d->authfile);
 
 	    if G_UNLIKELY (af == NULL) {
@@ -295,7 +295,7 @@ gdm_auth_secure_display (GdmDisplay *d)
     }
     g_setenv ("XAUTHORITY", GDM_AUTHFILE (d), TRUE);
 
-    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG))
+    if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG))
 	    gdm_debug ("gdm_auth_secure_display: Setting up access for %s - %d entries", 
 		       d->name, g_slist_length (d->auths));
 
@@ -501,7 +501,7 @@ get_local_auths (GdmDisplay *d)
 
     }
 
-    if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG))
+    if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG))
 	    gdm_debug ("get_local_auths: Setting up access for %s - %d entries", 
 		       d->name, g_slist_length (auths));
 
@@ -566,8 +566,8 @@ gdm_auth_user_add (GdmDisplay *d, uid_t 
     gint authfd;
     FILE *af;
     GSList *auths = NULL;
-    gchar *userauthdir;
-    gchar *userauthfile;
+    const gchar *userauthdir;
+    const gchar *userauthfile;
     gboolean ret = TRUE;
     gboolean automatic_tmp_dir = FALSE;
     gboolean authdir_is_tmp_dir = FALSE;
@@ -592,8 +592,8 @@ gdm_auth_user_add (GdmDisplay *d, uid_t 
 
     gdm_debug ("gdm_auth_user_add: Adding cookie for %d", user);
 
-    userauthdir  = gdm_get_value_string (GDM_KEY_USER_AUTHDIR);
-    userauthfile = gdm_get_value_string (GDM_KEY_USER_AUTHFILE);
+    userauthdir  = gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR);
+    userauthfile = gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHFILE);
 
     /* Determine whether UserAuthDir is specified. Otherwise ~user is used */
     if ( ! ve_string_empty (userauthdir) &&
@@ -632,8 +632,8 @@ try_user_add_again:
 	/* first the standard paranoia check (this checks the home dir
 	 * too which is useful here) */
 	! gdm_file_check ("gdm_auth_user_add", user, authdir, userauthfile, 
-			  TRUE, FALSE, gdm_get_value_int (GDM_KEY_USER_MAX_FILE),
-                          gdm_get_value_int (GDM_KEY_RELAX_PERM)) ||
+			  TRUE, FALSE, gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE),
+                          gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM)) ||
 
 	/* now the auth file checking routine */
 	! gdm_auth_file_check ("gdm_auth_user_add", user, d->userauth, TRUE /* absentok */, NULL) ||
@@ -644,7 +644,7 @@ try_user_add_again:
 	/* try opening as root, if we can't open as root,
 	   then this is a NFS mounted directory with root squashing,
 	   and we don't want to write cookies over NFS */
-	(gdm_get_value_bool (GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS) &&
+	(gdm_daemon_config_get_value_bool (GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS) &&
          ! try_open_read_as_root (d->userauth))) {
 
         /* if the userauth file didn't exist and we were looking at it,
@@ -662,7 +662,7 @@ try_user_add_again:
 	if (authdir_is_tmp_dir && authdir != NULL)
 		d->userauth = g_build_filename (authdir, ".gdmXXXXXX", NULL);
 	else
-		d->userauth = g_build_filename (gdm_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL);
+		d->userauth = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_USER_AUTHDIR_FALLBACK), ".gdmXXXXXX", NULL);
 	authfd = g_mkstemp (d->userauth);
 
 	if G_UNLIKELY (authfd < 0 && authdir_is_tmp_dir) {
@@ -849,8 +849,8 @@ gdm_auth_user_remove (GdmDisplay *d, uid
      * to it. So we better play it safe... */
 
     if G_UNLIKELY ( ! gdm_file_check ("gdm_auth_user_remove", user, authdir, authfile, 
-			   TRUE, FALSE, gdm_get_value_int (GDM_KEY_USER_MAX_FILE),
-                           gdm_get_value_int (GDM_KEY_RELAX_PERM)) ||
+			   TRUE, FALSE, gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE),
+                           gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM)) ||
 		    /* be even paranoider with permissions */
 		    ! gdm_auth_file_check ("gdm_auth_user_remove", user, d->userauth, FALSE /* absentok */, NULL)) {
 	    g_free (authdir);
Index: daemon/server.c
===================================================================
--- daemon/server.c	(revision 4696)
+++ daemon/server.c	(working copy)
@@ -50,9 +50,9 @@
 #include "auth.h"
 #include "slave.h"
 #include "getvt.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 /* Local prototypes */
 static void gdm_server_spawn (GdmDisplay *d, const char *vtarg);
@@ -375,7 +375,7 @@ busy_ask_user (GdmDisplay *disp)
 static gboolean
 display_parent_no_connect (GdmDisplay *disp)
 {
-	char *logname = gdm_make_filename (gdm_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
+	char *logname = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
 	FILE *fp;
 	char buf[256];
 	char *getsret;
@@ -407,7 +407,7 @@ display_parent_no_connect (GdmDisplay *d
 static gboolean
 display_busy (GdmDisplay *disp)
 {
-	char *logname = gdm_make_filename (gdm_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
+	char *logname = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
 	FILE *fp;
 	char buf[256];
 	char *getsret;
@@ -462,7 +462,7 @@ open_another_logfile (char buf[256], FIL
 static int
 display_vt (GdmDisplay *disp)
 {
-	char *logname = gdm_make_filename (gdm_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
+	char *logname = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
 	FILE *fp;
 	char buf[256];
 	gboolean switched = FALSE;
@@ -563,7 +563,7 @@ do_server_wait (GdmDisplay *d)
 		     * just wait a few seconds and hope things just work,
 		     * fortunately there is no such case yet and probably
 		     * never will, but just for code anality's sake */
-		    gdm_sleep_no_signal (gdm_get_value_int(GDM_KEY_XSERVER_TIMEOUT));
+		    gdm_sleep_no_signal (gdm_daemon_config_get_value_int(GDM_KEY_XSERVER_TIMEOUT));
 	    } else if (d->server_uid != 0) {
 		    int i;
 
@@ -583,7 +583,7 @@ do_server_wait (GdmDisplay *d)
 		    for (i = 0;
 			 d->dsp == NULL &&
 			 d->servstat == SERVER_PENDING &&
-			 i < gdm_get_value_int(GDM_KEY_XSERVER_TIMEOUT);
+			 i < gdm_daemon_config_get_value_int(GDM_KEY_XSERVER_TIMEOUT);
 			 i++) {
 			    d->dsp = XOpenDisplay (d->name);
 			    if (d->dsp == NULL)
@@ -606,7 +606,7 @@ do_server_wait (GdmDisplay *d)
 			    struct timeval tv;
 
 			    /* Wait up to GDM_KEY_XSERVER_TIMEOUT seconds. */
-			    tv.tv_sec = MAX (1, gdm_get_value_int(GDM_KEY_XSERVER_TIMEOUT) 
+			    tv.tv_sec = MAX (1, gdm_daemon_config_get_value_int(GDM_KEY_XSERVER_TIMEOUT) 
 			    	- (time (NULL) - t));
 			    tv.tv_usec = 0;
 
@@ -619,7 +619,7 @@ do_server_wait (GdmDisplay *d)
 				    VE_IGNORE_EINTR (read (server_signal_pipe[0], buf, 4));
 			    }
 			    if ( ! server_signal_notified &&
-				t + gdm_get_value_int(GDM_KEY_XSERVER_TIMEOUT) < time (NULL)) {
+				t + gdm_daemon_config_get_value_int(GDM_KEY_XSERVER_TIMEOUT) < time (NULL)) {
 				    gdm_debug ("do_server_wait: Server timeout");
 				    d->servstat = SERVER_TIMEOUT;
 				    server_signal_notified = TRUE;
@@ -742,7 +742,7 @@ gdm_server_start (GdmDisplay *disp,
     if (SERVER_IS_FLEXI (d) ||
 	treat_as_flexi) {
 	    flexi_disp = gdm_get_free_display
-		    (MAX (gdm_get_high_display_num () + 1, min_flexi_disp) /* start */,
+		    (MAX (gdm_daemon_config_get_high_display_num () + 1, min_flexi_disp) /* start */,
 		     d->server_uid /* server uid */);
 
 	    g_free (d->name);
@@ -875,7 +875,7 @@ gdm_server_start (GdmDisplay *disp,
 			    return gdm_server_start (d,
 						     FALSE /*try_again_if_busy */,
 						     TRUE /* treat as flexi */,
-						     gdm_get_high_display_num () + 1,
+						     gdm_daemon_config_get_high_display_num () + 1,
 						     flexi_retries - 1);
 		    }
 		    _exit (DISPLAY_REMANAGE);
@@ -926,7 +926,7 @@ safer_rename (const char *a, const char 
 static void
 rotate_logs (const char *dname)
 {
-	gchar *logdir = gdm_get_value_string (GDM_KEY_LOG_DIR);
+	const gchar *logdir = gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR);
 
 	/* I'm too lazy to write a loop */
 	char *fname4 = gdm_make_filename (logdir, dname, ".log.4");
@@ -957,7 +957,7 @@ gdm_server_resolve (GdmDisplay *disp)
 
 	bin = ve_first_word (disp->command);
 	if (bin != NULL && bin[0] != '/') {
-		svr = gdm_find_xserver (bin);
+		svr = gdm_daemon_config_find_xserver (bin);
 	}
 	g_free (bin);
 	return svr;
@@ -1010,16 +1010,16 @@ gdm_server_resolve_command_line (GdmDisp
 		const char *str;
 
 		gdm_error (_("Invalid server command '%s'"), disp->command);
-		str = gdm_get_value_string (GDM_KEY_STANDARD_XSERVER);
+		str = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER);
        		g_shell_parse_argv (str, &argc, &argv, NULL);
 	} else if (bin[0] != '/') {
-		GdmXserver *svr = gdm_find_xserver (bin);
+		GdmXserver *svr = gdm_daemon_config_find_xserver (bin);
 		if (svr == NULL) {
 			const char *str;
 
 			gdm_error (_("Server name '%s' not found; "
 				     "using standard server"), bin);
-			str = gdm_get_value_string (GDM_KEY_STANDARD_XSERVER);
+			str = gdm_daemon_config_get_value_string (GDM_KEY_STANDARD_XSERVER);
 			g_shell_parse_argv (str, &argc, &argv, NULL);
 
 		} else {
@@ -1105,7 +1105,7 @@ gdm_server_resolve_command_line (GdmDisp
 		query_in_arglist = TRUE;
 	}
 
-	if (resolve_flags && gdm_get_value_bool (GDM_KEY_DISALLOW_TCP) && ! query_in_arglist) {
+	if (resolve_flags && gdm_daemon_config_get_value_bool (GDM_KEY_DISALLOW_TCP) && ! query_in_arglist) {
 		argv[len++] = g_strdup ("-nolisten");
 		argv[len++] = g_strdup ("tcp");
 		d->tcp_disallowed = TRUE;
@@ -1210,7 +1210,7 @@ gdm_server_spawn (GdmDisplay *d, const c
 	rotate_logs (d->name);
 
         /* Log all output from spawned programs to a file */
-	logfile = gdm_make_filename (gdm_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
+	logfile = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_LOG_DIR), d->name, ".log");
 	VE_IGNORE_EINTR (g_unlink (logfile));
 	VE_IGNORE_EINTR (logfd = open (logfile, O_CREAT|O_TRUNC|O_WRONLY|O_EXCL, 0644));
 
@@ -1595,7 +1595,7 @@ get_font_path (const char *display)
 		if (i != 0)
 			g_string_append_c (gs, ',');
 
-	        if (gdm_get_value_bool (GDM_KEY_XNEST_UNSCALED_FONT_PATH) == TRUE)
+	        if (gdm_daemon_config_get_value_bool (GDM_KEY_XNEST_UNSCALED_FONT_PATH) == TRUE)
 			g_string_append (gs, font_path[i]);
 		else {
 			gchar *unscaled_ptr = NULL;
Index: daemon/cookie.c
===================================================================
--- daemon/cookie.c	(revision 4696)
+++ daemon/cookie.c	(working copy)
@@ -41,9 +41,9 @@
 #include "gdm.h"
 #include "md5.h"
 #include "cookie.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 #define MAXBUFFERSIZE 1024
 
Index: daemon/slave.c
===================================================================
--- daemon/slave.c	(revision 4696)
+++ daemon/slave.c	(working copy)
@@ -88,10 +88,10 @@
 #include "getvt.h"
 #include "errorgui.h"
 #include "cookie.h"
-#include "gdmconfig.h"
 #include "display.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 #ifdef WITH_CONSOLE_KIT
 #include "gdmconsolekit.h"
@@ -734,7 +734,7 @@ gdm_slave_start (GdmDisplay *display)
 	struct sigaction xfsz;
 #endif /* SIGXFSZ */
 	sigset_t mask;
-	int pinginterval = gdm_get_value_int (GDM_KEY_PING_INTERVAL);
+	int pinginterval = gdm_daemon_config_get_value_int (GDM_KEY_PING_INTERVAL);
 
 	/*
 	 * Set d global to display before setting signal handlers,
@@ -884,7 +884,7 @@ gdm_slave_start (GdmDisplay *display)
 
 		gdm_debug ("gdm_slave_start: Reinitializing things");
 
-		if (gdm_get_value_bool (GDM_KEY_ALWAYS_RESTART_SERVER)) {
+		if (gdm_daemon_config_get_value_bool (GDM_KEY_ALWAYS_RESTART_SERVER)) {
 			/* Whack the server if we want to restart it next time
 			 * we run gdm_slave_run */
 			gdm_server_stop (display);
@@ -921,7 +921,7 @@ setup_automatic_session (GdmDisplay *dis
 
 	/* Run the init script. gdmslave suspends until script
 	 * has terminated */
-	gdm_slave_exec_script (display, gdm_get_value_string (GDM_KEY_DISPLAY_INIT_DIR),
+	gdm_slave_exec_script (display, gdm_daemon_config_get_value_string (GDM_KEY_DISPLAY_INIT_DIR),
 			       NULL, NULL, FALSE /* pass_stdout */);
 
 	gdm_debug ("setup_automatic_session: DisplayInit script finished");
@@ -987,10 +987,10 @@ gdm_screen_init (GdmDisplay *display) 
 		if G_UNLIKELY (screen_num <= 0)
 			gdm_fail ("Xinerama active, but <= 0 screens?");
 
-		if (screen_num <= gdm_get_value_int (GDM_KEY_XINERAMA_SCREEN))
-			gdm_set_value_int (GDM_KEY_XINERAMA_SCREEN, 0);
+		if (screen_num <= gdm_daemon_config_get_value_int (GDM_KEY_XINERAMA_SCREEN))
+			gdm_daemon_config_set_value_int (GDM_KEY_XINERAMA_SCREEN, 0);
 
-		xineramascreen = gdm_get_value_int (GDM_KEY_XINERAMA_SCREEN);
+		xineramascreen = gdm_daemon_config_get_value_int (GDM_KEY_XINERAMA_SCREEN);
 
 		display->screenx = xscreens[xineramascreen].x_org;
 		display->screeny = xscreens[xineramascreen].y_org;
@@ -1036,10 +1036,10 @@ gdm_screen_init (GdmDisplay *display) 
 		if G_UNLIKELY (result <= 0)
 			gdm_fail ("Xinerama active, but <= 0 screens?");
 
-		if (n_monitors <= gdm_get_value_int (GDM_KEY_XINERAMA_SCREEN))
-			gdm_set_value_int (GDM_KEY_XINERAMA_SCREEN, 0);
+		if (n_monitors <= gdm_daemon_config_get_value_int (GDM_KEY_XINERAMA_SCREEN))
+			gdm_daemon_config_set_value_int (GDM_KEY_XINERAMA_SCREEN, 0);
 
-		xineramascreen = gdm_get_value_int (GDM_KEY_XINERAMA_SCREEN);
+		xineramascreen = gdm_daemon_config_get_value_int (GDM_KEY_XINERAMA_SCREEN);
 		display->screenx = monitors[xineramascreen].x;
 		display->screeny = monitors[xineramascreen].y;
 		display->screenwidth = monitors[xineramascreen].width;
@@ -1222,12 +1222,12 @@ gdm_slave_check_user_wants_to_log_in (co
 	if (d->type != TYPE_XDMCP_PROXY) {
 		int r;
 
-		if (!gdm_get_value_bool (GDM_KEY_DOUBLE_LOGIN_WARNING)) {
+		if (!gdm_daemon_config_get_value_bool (GDM_KEY_DOUBLE_LOGIN_WARNING)) {
 			g_free (migrate_to);
 			return TRUE;
 		}
 
-		if (gdm_get_value_bool (GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION))
+		if (gdm_daemon_config_get_value_bool (GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION))
 			r = 1;
 		else
 			r = ask_migrate (migrate_to);
@@ -1311,7 +1311,7 @@ gdm_slave_run (GdmDisplay *display)
 {  
     gint openretries = 0;
     gint maxtries = 0;
-    gint pinginterval = gdm_get_value_int (GDM_KEY_PING_INTERVAL);
+    gint pinginterval = gdm_daemon_config_get_value_int (GDM_KEY_PING_INTERVAL);
     
     gdm_reset_locale ();
 
@@ -1372,17 +1372,17 @@ gdm_slave_run (GdmDisplay *display)
     if (d->handled) {
 	    /* Now the display name and hostname is final */
 
-	    char *automaticlogin = gdm_get_value_string (GDM_KEY_AUTOMATIC_LOGIN);
-	    char *timedlogin     = gdm_get_value_string (GDM_KEY_TIMED_LOGIN);
+	    const char *automaticlogin = gdm_daemon_config_get_value_string (GDM_KEY_AUTOMATIC_LOGIN);
+	    const char *timedlogin     = gdm_daemon_config_get_value_string (GDM_KEY_TIMED_LOGIN);
 
-	    if (gdm_get_value_bool (GDM_KEY_AUTOMATIC_LOGIN_ENABLE) && 
+	    if (gdm_daemon_config_get_value_bool (GDM_KEY_AUTOMATIC_LOGIN_ENABLE) && 
 		! ve_string_empty (automaticlogin)) {
 		    g_free (ParsedAutomaticLogin);
 		    ParsedAutomaticLogin = gdm_parse_enriched_login (automaticlogin,
 								     display);
 	    }
 
-	    if (gdm_get_value_bool (GDM_KEY_TIMED_LOGIN_ENABLE) &&
+	    if (gdm_daemon_config_get_value_bool (GDM_KEY_TIMED_LOGIN_ENABLE) &&
 		! ve_string_empty (timedlogin)) {
 		    g_free (ParsedTimedLogin);
 		    ParsedTimedLogin = gdm_parse_enriched_login (timedlogin,
@@ -1725,7 +1725,7 @@ run_config (GdmDisplay *display, struct 
 	   We don't need to worry about defaults.conf as
 	   the daemon wont start without it
 	*/
-	if (gdm_get_custom_config_file() == NULL) {
+	if (gdm_daemon_config_get_custom_config_file () == NULL) {
 		gdm_error_box (d,
 			       GTK_MESSAGE_ERROR,
 			       _("Could not access configuration file (custom.conf). "
@@ -1795,7 +1795,7 @@ run_config (GdmDisplay *display, struct 
 		g_setenv ("USERNAME", pwent->pw_name, TRUE);
 		g_setenv ("HOME", pwent->pw_dir, TRUE);
 		g_setenv ("SHELL", pwent->pw_shell, TRUE);
-		g_setenv ("PATH", gdm_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
+		g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
 		g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
 		if ( ! ve_string_empty (display->theme_name))
 			g_setenv ("GDM_GTK_THEME", display->theme_name, TRUE);
@@ -1819,7 +1819,7 @@ run_config (GdmDisplay *display, struct 
 
 		/* exec the configurator */
 		argv = NULL;
-		s = gdm_get_value_string (GDM_KEY_CONFIGURATOR);
+		s = gdm_daemon_config_get_value_string (GDM_KEY_CONFIGURATOR);
 		if (s != NULL) {
 			g_shell_parse_argv (s, NULL, &argv, NULL);
 		}
@@ -1923,7 +1923,7 @@ restart_the_greeter (void)
 static gboolean
 play_login_sound (const char *sound_file)
 {
-	char *soundprogram = gdm_get_value_string (GDM_KEY_SOUND_PROGRAM);
+	const char *soundprogram = gdm_daemon_config_get_value_string (GDM_KEY_SOUND_PROGRAM);
 	pid_t pid;
 
 	if (ve_string_empty (soundprogram) ||
@@ -1959,7 +1959,7 @@ play_login_sound (const char *sound_file
 static void
 gdm_slave_wait_for_login (void)
 {
-	char *successsound;
+	const char *successsound;
 	char *username;
 	g_free (login);
 	login = NULL;
@@ -2024,8 +2024,8 @@ gdm_slave_wait_for_login (void)
 				 _("You must authenticate as root to run configuration."));
 
 			/* we always allow root for this */
-			oldAllowRoot = gdm_get_value_bool (GDM_KEY_ALLOW_ROOT);
-			gdm_set_value_bool (GDM_KEY_ALLOW_ROOT, TRUE);
+			oldAllowRoot = gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_ROOT);
+			gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_ROOT, TRUE);
 
 			pwent = getpwuid (0);
 			if G_UNLIKELY (pwent == NULL) {
@@ -2039,7 +2039,7 @@ gdm_slave_wait_for_login (void)
 						 pwent->pw_name,
 						 d->name,
 						 d->attached);
-			gdm_set_value_bool (GDM_KEY_ALLOW_ROOT, oldAllowRoot);
+			gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_ROOT, oldAllowRoot);
 
 			/* Clear message */
 			gdm_slave_greeter_ctl_no_ret (GDM_MSG, "");
@@ -2143,14 +2143,14 @@ gdm_slave_wait_for_login (void)
 		}
 
 		if (login == NULL) {
-			char *failuresound = gdm_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE);
+			const char *failuresound = gdm_daemon_config_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE);
 
 			gdm_debug ("gdm_slave_wait_for_login: No login/Bad login");
 			gdm_slave_greeter_ctl_no_ret (GDM_RESET, "");
 
 			/* Play sounds if specified for a failed login */
 			if (d->attached && failuresound &&
-			    gdm_get_value_bool (GDM_KEY_SOUND_ON_LOGIN_FAILURE) &&
+			    gdm_daemon_config_get_value_bool (GDM_KEY_SOUND_ON_LOGIN_FAILURE) &&
 			    ! play_login_sound (failuresound)) {
 				gdm_error (_("Login sound requested on non-local display or the play "
 					     "software cannot be run or the sound does not exist."));
@@ -2169,10 +2169,10 @@ gdm_slave_wait_for_login (void)
 		gdm_debug ("gdm_slave_wait_for_login: Timed Login");
 	}
 
-	successsound = gdm_get_value_string (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE);
+	successsound = gdm_daemon_config_get_value_string (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE);
 	/* Play sounds if specified for a successful login */
 	if (login != NULL && successsound &&
-	    gdm_get_value_bool (GDM_KEY_SOUND_ON_LOGIN_SUCCESS) &&
+	    gdm_daemon_config_get_value_bool (GDM_KEY_SOUND_ON_LOGIN_SUCCESS) &&
 	    d->attached &&
 	    ! play_login_sound (successsound)) {
 		gdm_error (_("Login sound requested on non-local display or the play software "
@@ -2221,25 +2221,25 @@ run_pictures (void)
 		NEVER_FAILS_seteuid (0);
 		if G_UNLIKELY (setegid (pwent->pw_gid) != 0 ||
 			       seteuid (pwent->pw_uid) != 0) {
-			NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+			NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
 			gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
 			continue;
 		}
 
-		picfile = gdm_get_facefile_from_home (pwent->pw_dir, pwent->pw_uid);
+		picfile = gdm_daemon_config_get_facefile_from_home (pwent->pw_dir, pwent->pw_uid);
 
 		if (! picfile)
-			picfile = gdm_get_facefile_from_global (pwent->pw_name, pwent->pw_uid);
+			picfile = gdm_daemon_config_get_facefile_from_global (pwent->pw_name, pwent->pw_uid);
 
 		if (! picfile) {
-			NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+			NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
 			gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
 			continue;
 		}
 
 		VE_IGNORE_EINTR (r = g_stat (picfile, &s));
-		if G_UNLIKELY (r < 0 || s.st_size > gdm_get_value_int (GDM_KEY_USER_MAX_FILE)) {
-			NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+		if G_UNLIKELY (r < 0 || s.st_size > gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE)) {
+			NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
 
 			gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
 			continue;
@@ -2248,7 +2248,7 @@ run_pictures (void)
 		VE_IGNORE_EINTR (fp = fopen (picfile, "r"));
 		g_free (picfile);
 		if G_UNLIKELY (fp == NULL) {
-			NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+			NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
 
 			gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "");
 			continue;
@@ -2262,7 +2262,7 @@ run_pictures (void)
 			VE_IGNORE_EINTR (fclose (fp));
 			g_free (ret);
 
-			NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+			NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
 
 			continue;
 		}
@@ -2340,7 +2340,7 @@ run_pictures (void)
 			
 		gdm_slave_greeter_ctl_no_ret (GDM_READPIC, "done");
 
-		NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+		NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
 	}
 	g_free (response); /* not reached */
 }
@@ -2359,7 +2359,7 @@ copy_auth_file (uid_t fromuid, uid_t tou
 	int cnt;
 
 	NEVER_FAILS_seteuid (0);
-	NEVER_FAILS_setegid (gdm_get_gdmgid ());
+	NEVER_FAILS_setegid (gdm_daemon_config_get_gdmgid ());
 
 	if G_UNLIKELY (seteuid (fromuid) != 0) {
 		NEVER_FAILS_root_set_euid_egid (old, oldg);
@@ -2391,7 +2391,7 @@ copy_auth_file (uid_t fromuid, uid_t tou
 
 	NEVER_FAILS_root_set_euid_egid (0, 0);
 
-	name = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR),
+	name = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR),
 		d->name, ".XnestAuth");
 
 	VE_IGNORE_EINTR (g_unlink (name));
@@ -2443,7 +2443,7 @@ copy_auth_file (uid_t fromuid, uid_t tou
 		cnt = cnt + written;
 		/* this should never occur (we check above)
 		   but we're paranoid) */
-		if G_UNLIKELY (cnt > gdm_get_value_int (GDM_KEY_USER_MAX_FILE))
+		if G_UNLIKELY (cnt > gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE))
 			return NULL;
 	}
 
@@ -2491,15 +2491,15 @@ gdm_slave_greeter (void)
     gint pipe1[2], pipe2[2];  
     struct passwd *pwent;
     pid_t pid;
-    char *command;
-    char *defaultpath;
-    char *gdmuser;
-    char *moduleslist;
+    const char *command;
+    const char *defaultpath;
+    const char *gdmuser;
+    const char *moduleslist;
     
     gdm_debug ("gdm_slave_greeter: Running greeter on %s", d->name);
     
     /* Run the init script. gdmslave suspends until script has terminated */
-    gdm_slave_exec_script (d, gdm_get_value_string (GDM_KEY_DISPLAY_INIT_DIR),
+    gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_DISPLAY_INIT_DIR),
 			   NULL, NULL, FALSE /* pass_stdout */);
 
     /* Open a pipe for greeter communications */
@@ -2548,21 +2548,21 @@ gdm_slave_greeter (void)
 
 	openlog ("gdm", LOG_PID, LOG_DAEMON);
 	
-	if G_UNLIKELY (setgid (gdm_get_gdmgid ()) < 0) 
+	if G_UNLIKELY (setgid (gdm_daemon_config_get_gdmgid ()) < 0) 
 	    gdm_child_exit (DISPLAY_ABORT,
 			    _("%s: Couldn't set groupid to %d"),
-			    "gdm_slave_greeter", gdm_get_gdmgid ());
+			    "gdm_slave_greeter", gdm_daemon_config_get_gdmgid ());
 
-	gdmuser = gdm_get_value_string (GDM_KEY_USER);
-	if G_UNLIKELY (initgroups (gdmuser, gdm_get_gdmgid ()) < 0)
+	gdmuser = gdm_daemon_config_get_value_string (GDM_KEY_USER);
+	if G_UNLIKELY (initgroups (gdmuser, gdm_daemon_config_get_gdmgid ()) < 0)
             gdm_child_exit (DISPLAY_ABORT,
 			    _("%s: initgroups () failed for %s"),
 			    "gdm_slave_greeter", gdmuser);
 	
-	if G_UNLIKELY (setuid (gdm_get_gdmuid ()) < 0) 
+	if G_UNLIKELY (setuid (gdm_daemon_config_get_gdmuid ()) < 0) 
 	    gdm_child_exit (DISPLAY_ABORT,
 			    _("%s: Couldn't set userid to %d"),
-			    "gdm_slave_greeter", gdm_get_gdmuid ());
+			    "gdm_slave_greeter", gdm_daemon_config_get_gdmuid ());
 
 	gdm_restoreenv ();
 	gdm_reset_locale ();
@@ -2589,17 +2589,17 @@ gdm_slave_greeter (void)
 			g_setenv ("HOME", pwent->pw_dir, TRUE);
 		else
 			g_setenv ("HOME",
-				ve_sure_string (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)),
+				ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)),
 				TRUE); /* Hack */
 		g_setenv ("SHELL", pwent->pw_shell, TRUE);
 	} else {
 		g_setenv ("HOME",
-			 ve_sure_string (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)),
+			 ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)),
 			 TRUE); /* Hack */
 		g_setenv ("SHELL", "/bin/sh", TRUE);
 	}
 
-	defaultpath = gdm_get_value_string (GDM_KEY_PATH);
+	defaultpath = gdm_daemon_config_get_value_string (GDM_KEY_PATH);
 	if (ve_string_empty (g_getenv ("PATH"))) {
 		g_setenv ("PATH", defaultpath, TRUE);
 	} else if ( ! ve_string_empty (defaultpath)) {
@@ -2612,7 +2612,7 @@ gdm_slave_greeter (void)
 	if ( ! ve_string_empty (d->theme_name))
 		g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
 
-	if (gdm_get_value_bool (GDM_KEY_DEBUG_GESTURES)) {
+	if (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG_GESTURES)) {
 		g_setenv ("GDM_DEBUG_GESTURES", "true", TRUE);
 	}
 
@@ -2676,9 +2676,9 @@ gdm_slave_greeter (void)
 	}
 
 	if (d->attached)
-		command = gdm_get_value_string (GDM_KEY_GREETER);
+		command = gdm_daemon_config_get_value_string (GDM_KEY_GREETER);
 	else
-		command = gdm_get_value_string (GDM_KEY_REMOTE_GREETER);
+		command = gdm_daemon_config_get_value_string (GDM_KEY_REMOTE_GREETER);
 
 	if G_UNLIKELY (d->try_different_greeter) {
 		/* FIXME: we should also really be able to do standalone failsafe
@@ -2701,9 +2701,9 @@ gdm_slave_greeter (void)
 		}
 	}
 
-	moduleslist = gdm_get_value_string (GDM_KEY_GTK_MODULES_LIST);
+	moduleslist = gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST);
 
-	if (gdm_get_value_bool (GDM_KEY_ADD_GTK_MODULES) &&
+	if (gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES) &&
 	    ! ve_string_empty (moduleslist) &&
 	    /* don't add modules if we're trying to prevent crashes,
 	       perhaps it's the modules causing the problem in the first place */
@@ -2795,7 +2795,7 @@ gdm_slave_send (const char *str, gboolea
 		   these functions.  And if the pipe creation failed
 		   in main daemon just abort the main daemon.  */
 		/* Use the fifo as a fallback only now that we have a pipe */
-		fifopath = g_build_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR),
+		fifopath = g_build_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR),
 			".gdmfifo", NULL);
 		old = geteuid ();
 		if (old != 0)
@@ -2923,7 +2923,7 @@ gdm_slave_send_string (const char *opcod
 {
 	char *msg;
 
-	if G_UNLIKELY (gdm_get_value_bool (GDM_KEY_DEBUG) && gdm_in_signal == 0) {
+	if G_UNLIKELY (gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG) && gdm_in_signal == 0) {
 		gdm_debug ("Sending %s == <secret> for slave %ld",
 			   opcode,
 			   (long)getpid ());
@@ -3007,9 +3007,9 @@ gdm_slave_chooser (void)
 	struct passwd *pwent;
 	pid_t pid;
 	GdmWaitPid *wp;
-	char *defaultpath;
-	char *gdmuser;
-	char *moduleslist;
+	const char *defaultpath;
+	const char *gdmuser;
+	const char *moduleslist;
 
 	gdm_debug ("gdm_slave_chooser: Running chooser on %s", d->name);
 
@@ -3018,7 +3018,7 @@ gdm_slave_chooser (void)
 		gdm_slave_exit (DISPLAY_REMANAGE, _("%s: Can't init pipe to gdmchooser"), "gdm_slave_chooser");
 
 	/* Run the init script. gdmslave suspends until script has terminated */
-	gdm_slave_exec_script (d, gdm_get_value_string (GDM_KEY_DISPLAY_INIT_DIR),
+	gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_DISPLAY_INIT_DIR),
 			       NULL, NULL, FALSE /* pass_stdout */);
 
 	/* Fork. Parent is gdmslave, child is greeter process. */
@@ -3053,21 +3053,21 @@ gdm_slave_chooser (void)
 
 		openlog ("gdm", LOG_PID, LOG_DAEMON);
 
-		if G_UNLIKELY (setgid (gdm_get_gdmgid ()) < 0) 
+		if G_UNLIKELY (setgid (gdm_daemon_config_get_gdmgid ()) < 0) 
 			gdm_child_exit (DISPLAY_ABORT,
 					_("%s: Couldn't set groupid to %d"),
-					"gdm_slave_chooser", gdm_get_gdmgid ());
+					"gdm_slave_chooser", gdm_daemon_config_get_gdmgid ());
 
-		gdmuser = gdm_get_value_string (GDM_KEY_USER);
-		if G_UNLIKELY (initgroups (gdmuser, gdm_get_gdmgid ()) < 0)
+		gdmuser = gdm_daemon_config_get_value_string (GDM_KEY_USER);
+		if G_UNLIKELY (initgroups (gdmuser, gdm_daemon_config_get_gdmgid ()) < 0)
 			gdm_child_exit (DISPLAY_ABORT,
 					_("%s: initgroups () failed for %s"),
 					"gdm_slave_chooser", gdmuser);
 
-		if G_UNLIKELY (setuid (gdm_get_gdmuid ()) < 0) 
+		if G_UNLIKELY (setuid (gdm_daemon_config_get_gdmuid ()) < 0) 
 			gdm_child_exit (DISPLAY_ABORT,
 					_("%s: Couldn't set userid to %d"),
-					"gdm_slave_chooser", gdm_get_gdmuid ());
+					"gdm_slave_chooser", gdm_daemon_config_get_gdmuid ());
 
 		gdm_restoreenv ();
 		gdm_reset_locale ();
@@ -3090,17 +3090,17 @@ gdm_slave_chooser (void)
 				g_setenv ("HOME", pwent->pw_dir, TRUE);
 			else
 				g_setenv ("HOME",
-					ve_sure_string (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)),
+					ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)),
 					TRUE); /* Hack */
 			g_setenv ("SHELL", pwent->pw_shell, TRUE);
 		} else {
 			g_setenv ("HOME",
-				ve_sure_string (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR)),
+				ve_sure_string (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR)),
 				TRUE); /* Hack */
 			g_setenv ("SHELL", "/bin/sh", TRUE);
 		}
 
-		defaultpath = gdm_get_value_string (GDM_KEY_PATH);
+		defaultpath = gdm_daemon_config_get_value_string (GDM_KEY_PATH);
 		if (ve_string_empty (g_getenv ("PATH"))) {
 			g_setenv ("PATH", defaultpath, TRUE);
 		} else if ( ! ve_string_empty (defaultpath)) {
@@ -3113,14 +3113,14 @@ gdm_slave_chooser (void)
 		if ( ! ve_string_empty (d->theme_name))
 			g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
 
-		moduleslist = gdm_get_value_string (GDM_KEY_GTK_MODULES_LIST);
-		if (gdm_get_value_bool (GDM_KEY_ADD_GTK_MODULES) &&
+		moduleslist = gdm_daemon_config_get_value_string (GDM_KEY_GTK_MODULES_LIST);
+		if (gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES) &&
 		    ! ve_string_empty (moduleslist)) {
 			char *modules = g_strdup_printf ("--gtk-module=%s", moduleslist);
-			exec_command (gdm_get_value_string (GDM_KEY_CHOOSER), modules);
+			exec_command (gdm_daemon_config_get_value_string (GDM_KEY_CHOOSER), modules);
 		}
 
-		exec_command (gdm_get_value_string (GDM_KEY_CHOOSER), NULL);
+		exec_command (gdm_daemon_config_get_value_string (GDM_KEY_CHOOSER), NULL);
 
 		gdm_error_box (d,
 			       GTK_MESSAGE_ERROR,
@@ -3203,10 +3203,10 @@ is_session_ok (const char *session_name)
 	    strcmp (session_name, GDM_SESSION_FAILSAFE_XTERM) == 0)
 		return TRUE;
 
-	if (ve_string_empty (gdm_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR)))
+	if (ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR)))
 		return gdm_is_session_magic (session_name);
 
-	exec = gdm_get_session_exec (session_name, TRUE /* check_try_exec */);
+	exec = gdm_daemon_config_get_session_exec (session_name, TRUE /* check_try_exec */);
 	if (exec == NULL)
 		ret = FALSE;
 	g_free (exec);
@@ -3232,7 +3232,7 @@ find_a_session (void)
 	};
 	int i;
 	char *session;
-	char *defaultsession = gdm_get_value_string (GDM_KEY_DEFAULT_SESSION);
+	const char *defaultsession = gdm_daemon_config_get_value_string (GDM_KEY_DEFAULT_SESSION);
 
 	if (!ve_string_empty (defaultsession) &&
 	    is_session_ok (defaultsession))
@@ -3462,7 +3462,7 @@ session_child_run (struct passwd *pwent,
 {
 	char *exec;
 	const char *shell = NULL;
-	char *greeter;
+	const char *greeter;
 	gint result;
 #ifndef HAVE_TSOL
 	char *argv[4];
@@ -3509,9 +3509,9 @@ session_child_run (struct passwd *pwent,
 	/* Determine default greeter type so the PreSession */
 	/* script can set the appropriate background color. */
 	if (d->attached) {
-		greeter = gdm_get_value_string (GDM_KEY_GREETER);
+		greeter = gdm_daemon_config_get_value_string (GDM_KEY_GREETER);
 	} else {
-		greeter = gdm_get_value_string (GDM_KEY_REMOTE_GREETER);		
+		greeter = gdm_daemon_config_get_value_string (GDM_KEY_REMOTE_GREETER);		
 	}
 	
 	if (strstr (greeter, "gdmlogin") != NULL) {
@@ -3524,7 +3524,7 @@ session_child_run (struct passwd *pwent,
 	}
 
 	/* Run the PreSession script */
-	if G_UNLIKELY (gdm_slave_exec_script (d, gdm_get_value_string (GDM_KEY_PRESESSION),
+	if G_UNLIKELY (gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_PRESESSION),
                                               pwent->pw_name, pwent,
 					      TRUE /* pass_stdout */) != EXIT_SUCCESS &&
 		       /* ignore errors in failsafe modes */
@@ -3572,9 +3572,9 @@ session_child_run (struct passwd *pwent,
 
 	/* Special PATH for root */
 	if (pwent->pw_uid == 0)
-		g_setenv ("PATH", gdm_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
+		g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
 	else
-		g_setenv ("PATH", gdm_get_value_string (GDM_KEY_PATH), TRUE);
+		g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_PATH), TRUE);
 
 	/* Eeeeek, this no lookie as a correct language code,
 	 * just use the system default */
@@ -3686,7 +3686,7 @@ session_child_run (struct passwd *pwent,
 	VE_IGNORE_EINTR (g_chdir (home_dir));
 	
         if (usrcfgok && home_dir_ok)
-		gdm_set_user_session_lang (savesess, savelang, home_dir, save_session, language);
+		gdm_daemon_config_set_user_session_lang (savesess, savelang, home_dir, save_session, language);
 	
 	closelog ();
 
@@ -3707,7 +3707,7 @@ session_child_run (struct passwd *pwent,
 	exec = NULL;
 	if (strcmp (session, GDM_SESSION_FAILSAFE_XTERM) != 0 &&
 	    strcmp (session, GDM_SESSION_FAILSAFE_GNOME) != 0) {
-		exec = gdm_get_session_exec (session,
+		exec = gdm_daemon_config_get_session_exec (session,
 			FALSE /* check_try_exec */);
 
 		if G_UNLIKELY (exec == NULL) {
@@ -3731,7 +3731,7 @@ session_child_run (struct passwd *pwent,
 	}
 
 	if (exec != NULL) {
-		char *basexsession = gdm_get_value_string (GDM_KEY_BASE_XSESSION);
+		const char *basexsession = gdm_daemon_config_get_value_string (GDM_KEY_BASE_XSESSION);
 
 		/* cannot be possibly failsafe */
 		if G_UNLIKELY (g_access (basexsession, X_OK) != 0) {
@@ -3748,17 +3748,17 @@ session_child_run (struct passwd *pwent,
 			   exec in just a bit */
 #ifdef HAVE_TSOL
 			if (have_suntsol_extension) {
-				argv[0] = basexsession;
+				argv[0] = g_strdup (basexsession);
 				argv[1] = g_strdup ("/usr/bin/tsoljdslabel");
 				argv[2] = exec;
 				argv[3] = argv[4] = argv[5] = argv[6] = NULL;
 			} else {
 #endif
-			argv[0] = basexsession;
-			argv[1] = exec;
-			argv[2] = NULL;
+				argv[0] = g_strdup (basexsession);
+				argv[1] = exec;
+				argv[2] = NULL;
 #ifdef HAVE_TSOL
-			argv[3] = argv[4] = argv[5] = argv[6] = NULL;
+				argv[3] = argv[4] = argv[5] = argv[6] = NULL;
 			}
 #endif
 		}
@@ -4076,7 +4076,7 @@ gdm_slave_session_start (void)
     logged_in_gid = gid = pwent->pw_gid;
 
     /* Run the PostLogin script */
-    if G_UNLIKELY (gdm_slave_exec_script (d, gdm_get_value_string (GDM_KEY_POSTLOGIN),
+    if G_UNLIKELY (gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_POSTLOGIN),
 					  login, pwent,
 					  TRUE /* pass_stdout */) != EXIT_SUCCESS &&
 		   /* ignore errors in failsafe modes */
@@ -4115,7 +4115,7 @@ gdm_slave_session_start (void)
 
 	    /* Set euid, egid to root:gdm to manage user interaction */
             seteuid (0);
-            setegid (gdm_get_gdmgid ());
+            setegid (gdm_daemon_config_get_gdmgid ());
 
 	    gdm_error (_("%s: Home directory for %s: '%s' does not exist!"),
 		       "gdm_slave_session_start",
@@ -4162,14 +4162,14 @@ gdm_slave_session_start (void)
 	    /* Sanity check on ~user/.dmrc */
 	    usrcfgok = gdm_file_check ("gdm_slave_session_start", pwent->pw_uid,
 				       home_dir, ".dmrc", TRUE, FALSE,
-				       gdm_get_value_int (GDM_KEY_USER_MAX_FILE),
-				       gdm_get_value_int (GDM_KEY_RELAX_PERM));
+				       gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE),
+				       gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM));
     } else {
 	    usrcfgok = FALSE;
     }
 
     if G_LIKELY (usrcfgok) {
-	    gdm_get_user_session_lang (&usrsess, &usrlang, home_dir, &savesess);
+	    gdm_daemon_config_get_user_session_lang (&usrsess, &usrlang, home_dir, &savesess);
     } else {
 	/* This won't get displayed if the .dmrc file simply doesn't
 	 * exist since we pass absentok=TRUE when we call gdm_file_check
@@ -4187,7 +4187,7 @@ gdm_slave_session_start (void)
 	usrlang = g_strdup ("");
     }
 
-    NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+    NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
 
     if (greet) {
 	    tmp = gdm_ensure_extension (usrsess, ".desktop");
@@ -4260,7 +4260,7 @@ gdm_slave_session_start (void)
 	    gdm_slave_whack_greeter ();
     }
 
-    if (gdm_get_value_bool (GDM_KEY_KILL_INIT_CLIENTS))
+    if (gdm_daemon_config_get_value_bool (GDM_KEY_KILL_INIT_CLIENTS))
 	    gdm_server_whack_clients (d->dsp);
 
     /* Now that we will set up the user authorization we will
@@ -4298,7 +4298,7 @@ gdm_slave_session_start (void)
 	    }
     }
 
-    NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+    NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
     
     if G_UNLIKELY ( ! authok) {
 	    gdm_debug ("gdm_slave_session_start: Auth not OK");
@@ -4324,7 +4324,7 @@ gdm_slave_session_start (void)
 	    failsafe = TRUE;
 
     if G_LIKELY ( ! failsafe) {
-	    char *exec = gdm_get_session_exec (session, FALSE /* check_try_exec */);
+	    char *exec = gdm_daemon_config_get_session_exec (session, FALSE /* check_try_exec */);
 	    if ( ! ve_string_empty (exec) &&
 		strcmp (exec, "failsafe") == 0)
 		    failsafe = TRUE;
@@ -4418,7 +4418,7 @@ gdm_slave_session_start (void)
     }
     
     /* this clears internal cache */
-    gdm_get_session_exec (NULL, FALSE);
+    gdm_daemon_config_get_session_exec (NULL, FALSE);
 
     if G_LIKELY (logfilefd >= 0)  {
 	    d->xsession_errors_fd = logfilefd;
@@ -4429,7 +4429,7 @@ gdm_slave_session_start (void)
     }
 
     /* We must be root for this, and we are, but just to make sure */
-    NEVER_FAILS_root_set_euid_egid (0, gdm_get_gdmgid ());
+    NEVER_FAILS_root_set_euid_egid (0, gdm_daemon_config_get_gdmgid ());
     /* Reset all the process limits, pam may have set some up for our process and that
        is quite evil.  But pam is generally evil, so this is to be expected. */
     gdm_reset_limits ();
@@ -4588,14 +4588,14 @@ gdm_slave_session_stop (gboolean run_pos
     else
 	    pwent = getpwnam (local_login);	/* PAM overwrites our pwent */
 
-    x_servers_file = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR),
+    x_servers_file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR),
 					d->name, ".Xservers");
 
     /* if there was a session that ran, run the PostSession script */
     if (run_post_session) {
 	    /* Execute post session script */
 	    gdm_debug ("gdm_slave_session_stop: Running post session script");
-	    gdm_slave_exec_script (d, gdm_get_value_string (GDM_KEY_POSTSESSION), local_login, pwent,
+	    gdm_slave_exec_script (d, gdm_daemon_config_get_value_string (GDM_KEY_POSTSESSION), local_login, pwent,
 				   FALSE /* pass_stdout */);
     }
 
@@ -4760,7 +4760,7 @@ gdm_slave_alrm_handler (int sig)
 	in_ping = TRUE;
 
 	/* schedule next alarm */
-	alarm (gdm_get_value_int (GDM_KEY_PING_INTERVAL));
+	alarm (gdm_daemon_config_get_value_int (GDM_KEY_PING_INTERVAL));
 
 	XSync (d->dsp, True);
 
@@ -5086,26 +5086,26 @@ check_for_interruption (const char *msg)
 			 * it is allowed for this display (it's only allowed
 			 * for the first local display) and if it's set up
 			 * correctly */
-			if ((d->attached || gdm_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN)) 
+			if ((d->attached || gdm_daemon_config_get_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN)) 
                             && d->timed_login_ok &&
 			    ! ve_string_empty (ParsedTimedLogin) &&
                             strcmp (ParsedTimedLogin, gdm_root_user ()) != 0 &&
-			    gdm_get_value_int (GDM_KEY_TIMED_LOGIN_DELAY) > 0) {
+			    gdm_daemon_config_get_value_int (GDM_KEY_TIMED_LOGIN_DELAY) > 0) {
 				do_timed_login = TRUE;
 			}
 			break;
 		case GDM_INTERRUPT_CONFIGURE:
 			if (d->attached &&
-			    gdm_get_value_bool_per_display (d->name, GDM_KEY_CONFIG_AVAILABLE) &&
-			    gdm_get_value_bool_per_display (d->name, GDM_KEY_SYSTEM_MENU) &&
-			    ! ve_string_empty (gdm_get_value_string (GDM_KEY_CONFIGURATOR))) {
+			    gdm_daemon_config_get_value_bool_per_display (d->name, GDM_KEY_CONFIG_AVAILABLE) &&
+			    gdm_daemon_config_get_value_bool_per_display (d->name, GDM_KEY_SYSTEM_MENU) &&
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_CONFIGURATOR))) {
 				do_configurator = TRUE;
 			}
 			break;
 		case GDM_INTERRUPT_SUSPEND:
 			if (d->attached &&
-			    gdm_get_value_bool_per_display (d->name, GDM_KEY_SYSTEM_MENU) &&
-			    ! ve_string_empty (gdm_get_value_string (GDM_KEY_SUSPEND))) {
+			    gdm_daemon_config_get_value_bool_per_display (d->name, GDM_KEY_SYSTEM_MENU) &&
+			    ! ve_string_empty (gdm_daemon_config_get_value_string (GDM_KEY_SUSPEND))) {
 			    	gchar *msg = g_strdup_printf ("%s %ld", 
 					GDM_SOP_SUSPEND_MACHINE,
 					(long)getpid ());
@@ -5118,7 +5118,7 @@ check_for_interruption (const char *msg)
 			return TRUE;
 		case GDM_INTERRUPT_LOGIN_SOUND:
 			if (d->attached &&
-			    ! play_login_sound (gdm_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FILE))) {
+			    ! play_login_sound (gdm_daemon_config_get_value_string (GDM_KEY_SOUND_ON_LOGIN_FILE))) {
 				gdm_error (_("Login sound requested on non-local display or the play software "
 					     "cannot be run or the sound does not exist"));
 			}
@@ -5334,7 +5334,7 @@ create_temp_auth_file (void)
 		g_free (d->parent_temp_auth_file);
 		d->parent_temp_auth_file =
 			copy_auth_file (d->server_uid,
-					gdm_get_gdmuid (),
+					gdm_daemon_config_get_gdmuid (),
 					d->parent_auth_file);
 	}
 }
@@ -5437,7 +5437,7 @@ gdm_slave_exec_script (GdmDisplay *d, co
 	        g_setenv ("USER", login, TRUE);
 	        g_setenv ("USERNAME", login, TRUE);
         } else {
-		char *gdmuser = gdm_get_value_string (GDM_KEY_USER);
+		const char *gdmuser = gdm_daemon_config_get_value_string (GDM_KEY_USER);
 	        g_setenv ("LOGNAME", gdmuser, TRUE);
 	        g_setenv ("USER", gdmuser, TRUE);
 	        g_setenv ("USERNAME", gdmuser, TRUE);
@@ -5467,7 +5467,7 @@ gdm_slave_exec_script (GdmDisplay *d, co
 	set_xnest_parent_stuff ();
 
 	/* some env for use with the Pre and Post scripts */
-	x_servers_file = gdm_make_filename (gdm_get_value_string (GDM_KEY_SERV_AUTHDIR),
+	x_servers_file = gdm_make_filename (gdm_daemon_config_get_value_string (GDM_KEY_SERV_AUTHDIR),
 					    d->name, ".Xservers");
 	g_setenv ("X_SERVERS", x_servers_file, TRUE);
 	g_free (x_servers_file);
@@ -5480,7 +5480,7 @@ gdm_slave_exec_script (GdmDisplay *d, co
 	else
 		g_unsetenv ("XAUTHORITY");
         g_setenv ("DISPLAY", d->name, TRUE);
-	g_setenv ("PATH", gdm_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
+	g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
 	g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
 	if ( ! ve_string_empty (d->theme_name))
 		g_setenv ("GDM_GTK_THEME", d->theme_name, TRUE);
@@ -5621,7 +5621,7 @@ gdm_parse_enriched_login (const gchar *s
 	    g_setenv ("DISPLAY", display->name, TRUE);
 	    if (SERVER_IS_XDMCP (display))
 		    g_setenv ("REMOTE_HOST", display->hostname, TRUE);
-	    g_setenv ("PATH", gdm_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
+	    g_setenv ("PATH", gdm_daemon_config_get_value_string (GDM_KEY_ROOT_PATH), TRUE);
 	    g_setenv ("SHELL", "/bin/sh", TRUE);
 	    g_setenv ("RUNNING_UNDER_GDM", "true", TRUE);
 	    if ( ! ve_string_empty (d->theme_name))
@@ -5675,7 +5675,7 @@ gdm_parse_enriched_login (const gchar *s
          *  automatic login [and timed login] is not performed." -- GDM manual 
 	 */
 	/* fixme: also turn off automatic login */
-	gdm_set_value_bool(GDM_KEY_TIMED_LOGIN_ENABLE, FALSE);
+	gdm_daemon_config_set_value_bool(GDM_KEY_TIMED_LOGIN_ENABLE, FALSE);
 	d->timed_login_ok = FALSE;
 	do_timed_login = FALSE;
 	g_string_free(str, TRUE);
@@ -5691,31 +5691,31 @@ gdm_slave_handle_notify (const char *msg
 	gdm_debug ("Handling slave notify: '%s'", msg);
 
 	if (sscanf (msg, GDM_NOTIFY_ALLOW_ROOT " %d", &val) == 1) {
-		gdm_set_value_bool (GDM_KEY_ALLOW_ROOT, val);
+		gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_ROOT, val);
 	} else if (sscanf (msg, GDM_NOTIFY_ALLOW_REMOTE_ROOT " %d", &val) == 1) {
-		gdm_set_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT, val);
+		gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_REMOTE_ROOT, val);
 	} else if (sscanf (msg, GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN " %d", &val) == 1) {
-		gdm_set_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN, val);
+		gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN, val);
 	} else if (sscanf (msg, GDM_NOTIFY_SYSTEM_MENU " %d", &val) == 1) {
-		gdm_set_value_bool (GDM_KEY_SYSTEM_MENU, val);
+		gdm_daemon_config_set_value_bool (GDM_KEY_SYSTEM_MENU, val);
 		if (d->greetpid > 1)
 			kill (d->greetpid, SIGHUP);
 	} else if (sscanf (msg, GDM_NOTIFY_CONFIG_AVAILABLE " %d", &val) == 1) {
-		gdm_set_value_bool (GDM_KEY_CONFIG_AVAILABLE, val);
+		gdm_daemon_config_set_value_bool (GDM_KEY_CONFIG_AVAILABLE, val);
 		if (d->greetpid > 1)
 			kill (d->greetpid, SIGHUP);
 	} else if (sscanf (msg, GDM_NOTIFY_CHOOSER_BUTTON " %d", &val) == 1) {
-		gdm_set_value_bool (GDM_KEY_CHOOSER_BUTTON, val);
+		gdm_daemon_config_set_value_bool (GDM_KEY_CHOOSER_BUTTON, val);
 		if (d->greetpid > 1)
 			kill (d->greetpid, SIGHUP);
 	} else if (sscanf (msg, GDM_NOTIFY_RETRY_DELAY " %d", &val) == 1) {
-		gdm_set_value_int (GDM_KEY_RETRY_DELAY, val);
+		gdm_daemon_config_set_value_int (GDM_KEY_RETRY_DELAY, val);
 	} else if (sscanf (msg, GDM_NOTIFY_DISALLOW_TCP " %d", &val) == 1) {
-		gdm_set_value_bool (GDM_KEY_DISALLOW_TCP, val);
+		gdm_daemon_config_set_value_bool (GDM_KEY_DISALLOW_TCP, val);
 		remanage_asap = TRUE;
 	} else if (strncmp (msg, GDM_NOTIFY_GREETER " ",
 			    strlen (GDM_NOTIFY_GREETER) + 1) == 0) {
-		gdm_set_value_string (GDM_KEY_GREETER, ((gchar *)&msg[strlen (GDM_NOTIFY_GREETER) + 1]));
+		gdm_daemon_config_set_value_string (GDM_KEY_GREETER, ((gchar *)&msg[strlen (GDM_NOTIFY_GREETER) + 1]));
 
 		if (d->attached) {
 			do_restart_greeter = TRUE;
@@ -5737,7 +5737,7 @@ gdm_slave_handle_notify (const char *msg
 			gchar * key_string = g_strdup_printf(_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, val);
 			/* This assumes that the number of commands is < 100, i.e two digits 
 			   if that is not the case then this will fail */
-			gdm_set_value_string (key_string, ((gchar *)&msg[strlen (GDM_NOTIFY_CUSTOM_CMD_TEMPLATE) + 2]));
+			gdm_daemon_config_set_value_string (key_string, ((gchar *)&msg[strlen (GDM_NOTIFY_CUSTOM_CMD_TEMPLATE) + 2]));
 			g_free(key_string);
 
 			if (d->attached) {
@@ -5757,7 +5757,7 @@ gdm_slave_handle_notify (const char *msg
 		}		
 	} else if (strncmp (msg, GDM_NOTIFY_REMOTE_GREETER " ",
 			    strlen (GDM_NOTIFY_REMOTE_GREETER) + 1) == 0) {
-		gdm_set_value_string (GDM_KEY_REMOTE_GREETER,
+		gdm_daemon_config_set_value_string (GDM_KEY_REMOTE_GREETER,
 			(gchar *)(&msg[strlen (GDM_NOTIFY_REMOTE_GREETER) + 1]));
 		if ( ! d->attached) {
 			do_restart_greeter = TRUE;
@@ -5791,28 +5791,28 @@ gdm_slave_handle_notify (const char *msg
 		}
 	} else if (strncmp (msg, GDM_NOTIFY_SOUND_ON_LOGIN_FILE " ",
 			    strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FILE) + 1) == 0) {
-		gdm_set_value_string (GDM_KEY_SOUND_ON_LOGIN_FILE,
+		gdm_daemon_config_set_value_string (GDM_KEY_SOUND_ON_LOGIN_FILE,
 			(gchar *)(&msg[strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FILE) + 1]));
 		if (d->greetpid > 1)
 			kill (d->greetpid, SIGHUP);
 	} else if (strncmp (msg, GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE " ",
 			    strlen (GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE) + 1) == 0) {
-		gdm_set_value_string (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE,
+		gdm_daemon_config_set_value_string (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE,
 			(gchar *)(&msg[strlen (GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE) + 1]));
 		if (d->greetpid > 1)
 			kill (d->greetpid, SIGHUP);
 	} else if (strncmp (msg, GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE " ",
 			    strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE) + 1) == 0) {
-		gdm_set_value_string (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE,
+		gdm_daemon_config_set_value_string (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE,
 			(gchar *)(&msg[strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE) + 1]));
 		if (d->greetpid > 1)
 			kill (d->greetpid, SIGHUP);
 	} else if (strncmp (msg, GDM_NOTIFY_GTK_MODULES_LIST " ",
 			    strlen (GDM_NOTIFY_GTK_MODULES_LIST) + 1) == 0) {
-		gdm_set_value_string (GDM_KEY_GTK_MODULES_LIST,
+		gdm_daemon_config_set_value_string (GDM_KEY_GTK_MODULES_LIST,
 			(gchar *)(&msg[strlen (GDM_NOTIFY_GTK_MODULES_LIST) + 1]));
 
-		if (gdm_get_value_bool (GDM_KEY_ADD_GTK_MODULES)) {
+		if (gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES)) {
 			do_restart_greeter = TRUE;
 			if (restart_greeter_now) {
 				; /* will get restarted later */
@@ -5827,7 +5827,7 @@ gdm_slave_handle_notify (const char *msg
 			}
 		}
 	} else if (sscanf (msg, GDM_NOTIFY_ADD_GTK_MODULES " %d", &val) == 1) {
-		gdm_set_value_bool (GDM_KEY_ADD_GTK_MODULES, val);
+		gdm_daemon_config_set_value_bool (GDM_KEY_ADD_GTK_MODULES, val);
 
 		do_restart_greeter = TRUE;
 		if (restart_greeter_now) {
Index: daemon/gdm-daemon-config.c
===================================================================
--- daemon/gdm-daemon-config.c	(revision 4696)
+++ daemon/gdm-daemon-config.c	(working copy)
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 3 -*-
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
  *
  * GDM - The GNOME Display Manager
  * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
@@ -33,6 +33,7 @@
  * placed in the _gdm_set_value_string, _gdm_set_value_int, or
  * _gdm_set_value_bool functions.
  */
+
 #include "config.h"
 
 #include <stdlib.h>
@@ -53,7 +54,6 @@
 #include "gdm-common.h"
 
 #include "gdm.h"
-#include "gdmconfig.h"
 #include "verify.h"
 #include "gdm-net.h"
 #include "misc.h"
@@ -61,241 +61,23 @@
 #include "filecheck.h"
 #include "slave.h"
 
-gchar *config_file                     = NULL;
-gchar *custom_config_file              = NULL;
-static time_t config_file_mtime        = 0;
-static time_t custom_config_file_mtime = 0;
+#include "gdm-config.h"
+#include "gdm-daemon-config.h"
+
+static GdmConfig *daemon_config = NULL;
 
 extern gboolean no_console;
 extern gboolean gdm_emergency_server;
 
 GSList *displays          = NULL;
-GSList *displays_inactive = NULL;
 GSList *xservers          = NULL;
 
 gint high_display_num = 0;
-
-typedef enum {
-        CONFIG_BOOL,
-        CONFIG_INT,
-        CONFIG_STRING
-} GdmConfigType;
-
-static GHashTable    *type_hash       = NULL;
-static GHashTable    *val_hash        = NULL;
-static GHashTable    *translated_hash = NULL;
-static GHashTable    *realkey_hash    = NULL;
-static GdmConfigType  bool_type       = CONFIG_BOOL;
-static GdmConfigType  int_type        = CONFIG_INT;
-static GdmConfigType  string_type     = CONFIG_STRING;
+char *custom_config_file = NULL;
 
 static uid_t GdmUserId;   /* Userid  under which gdm should run */
 static gid_t GdmGroupId;  /* Gruopid under which gdm should run */
 
-/* Config options used by daemon */
-/* ----------------------------- */
-static gchar *GdmUser = NULL;
-static gchar *GdmGroup = NULL;
-static gchar *GdmGtkRC = NULL;
-static gchar *GdmGtkTheme = NULL;
-static gchar *GdmSessDir = NULL;
-static gchar *GdmBaseXsession = NULL;
-static gchar *GdmDefaultSession = NULL;
-static gchar *GdmAutomaticLogin = NULL;
-static gchar *GdmConfigurator = NULL;
-static gchar *GdmGlobalFaceDir = NULL;
-static gchar *GdmGreeter = NULL;
-static gchar *GdmRemoteGreeter = NULL;
-static gchar *GdmGtkModulesList = NULL;
-static gchar *GdmChooser = NULL;
-static gchar *GdmLogDir = NULL;
-static gchar *GdmDisplayInitDir = NULL;
-static gchar *GdmPostLogin = NULL;
-static gchar *GdmPreSession = NULL;
-static gchar *GdmPostSession = NULL;
-static gchar *GdmFailsafeXserver = NULL;
-static gchar *GdmXKeepsCrashing = NULL;
-static gchar *GdmHalt = NULL;
-static gchar *GdmReboot = NULL;
-static GdmCustomCmd *GdmCustomCommands = NULL;
-static gchar *GdmSuspend = NULL;
-static gchar *GdmServAuthDir = NULL;
-static gchar *GdmMulticastAddr;
-static gchar *GdmUserAuthDir = NULL;
-static gchar *GdmUserAuthFile = NULL;
-static gchar *GdmUserAuthFallback = NULL;
-static gchar *GdmPidFile = NULL;
-static gchar *GdmPath = NULL;
-static gchar *GdmRootPath = NULL;
-static gchar *GdmWilling = NULL;
-static gchar *GdmXdmcpProxyXserver = NULL;
-static gchar *GdmXdmcpProxyReconnect = NULL;
-static gchar *GdmTimedLogin = NULL;
-static gchar *GdmStandardXserver = NULL;
-static gchar *GdmXnest = NULL;
-static gchar *GdmSoundProgram = NULL;
-static gchar *GdmSoundOnLoginFile = NULL;
-static gchar *GdmSoundOnLoginSuccessFile = NULL;
-static gchar *GdmSoundOnLoginFailureFile = NULL;
-static gchar *GdmConsoleCannotHandle = NULL;
-static gchar *GdmPamStack = NULL;
-
-static gint GdmXineramaScreen = 0;
-static gint GdmUserMaxFile = 0;
-static gint GdmDisplaysPerHost = 0;
-static gint GdmMaxPending = 0;
-static gint GdmMaxSessions = 0;
-static gint GdmUdpPort = 0;
-static gint GdmMaxIndirect = 0;
-static gint GdmMaxWaitIndirect = 0;
-static gint GdmPingInterval = 0;
-static gint GdmRelaxPerm = 0;
-static gint GdmRetryDelay = 0;
-static gint GdmTimedLoginDelay = 0;
-static gint GdmFlexibleXservers = 5;
-static gint GdmFirstVt = 7;
-static gint GdmXserverTimeout = 10;
-
-gboolean GdmAlwaysRestartServer;
-static gboolean GdmAutomaticLoginEnable;
-static gboolean GdmConfigAvailable;
-static gboolean GdmSystemMenu;
-static gboolean GdmChooserButton;
-static gboolean GdmBrowser;
-static gboolean GdmAddGtkModules;
-static gboolean GdmDoubleLoginWarning;
-static gboolean GdmAlwaysLoginCurrentSession;
-static gboolean GdmDisplayLastLogin;
-static gboolean GdmMulticast;
-static gboolean GdmNeverPlaceCookiesOnNfs;
-static gboolean GdmPasswordRequired;
-static gboolean GdmKillInitClients;
-static gboolean GdmXdmcp;
-static gboolean GdmIndirect;
-static gboolean GdmXdmcpProxy;
-static gboolean GdmDebug;
-static gboolean GdmDebugGestures;
-static gboolean GdmAllowRoot;
-static gboolean GdmAllowRemoteRoot;
-static gboolean GdmAllowRemoteAutoLogin;
-static gboolean GdmCheckDirOwner;
-static gboolean GdmSupportAutomount;
-static gboolean GdmTimedLoginEnable;
-static gboolean GdmDynamicXservers;
-static gboolean GdmVTAllocation;
-static gboolean GdmDisallowTcp;
-static gboolean GdmSoundOnLogin;
-static gboolean GdmSoundOnLoginSuccess;
-static gboolean GdmSoundOnLoginFailure;
-static gboolean GdmConsoleNotify;
-static gboolean GdmXnestUnscaledFontPath;
-
-/* Config options used by slave */
-/* ---------------------------- */
-static gchar *GdmGtkThemesToAllow = NULL;
-static gchar *GdmInclude = NULL;
-static gchar *GdmExclude = NULL;
-static gchar *GdmDefaultFace = NULL;
-static gchar *GdmLocaleFile = NULL;
-static gchar *GdmLogo = NULL;
-static gchar *GdmChooserButtonLogo = NULL;
-static gchar *GdmWelcome = NULL;
-static gchar *GdmRemoteWelcome = NULL;
-static gchar *GdmBackgroundProgram = NULL;
-static gchar *GdmBackgroundImage = NULL;
-static gchar *GdmBackgroundColor = NULL;
-static gchar *GdmGraphicalTheme = NULL;
-static gchar *GdmInfoMsgFile = NULL;
-static gchar *GdmInfoMsgFont = NULL;
-static gchar *GdmHost = NULL;
-static gchar *GdmHostImageDir = NULL;
-static gchar *GdmHosts = NULL;
-static gchar *GdmGraphicalThemeColor = NULL;
-static gchar *GdmGraphicalThemeDir = NULL;
-static gchar *GdmGraphicalThemes = NULL;
-static gchar *GdmPreFetchProgram = NULL;
-static gchar *GdmUse24Clock = NULL;
-
-static gint GdmPositionX;
-static gint GdmPositionY;
-static gint GdmMinimalUid;
-static gint GdmMaxIconWidth;
-static gint GdmMaxIconHeight;
-static gint GdmBackgroundType;
-static gint GdmScanTime;
-static gint GdmMaxWait;
-static gint GdmFlexiReapDelayMinutes;
-static gint GdmBackgroundProgramInitialDelay = 30;
-static gint GdmBackgroundProgramRestartDelay = 30;
-
-static gboolean GdmAllowGtkThemeChange;
-static gboolean GdmTitleBar;
-static gboolean GdmIncludeAll;
-static gboolean GdmDefaultWelcome;
-static gboolean GdmDefaultRemoteWelcome;
-static gboolean GdmLockPosition;
-static gboolean GdmBackgroundScaleToFit;
-static gboolean GdmBackgroundRemoteOnlyColor;
-static gboolean GdmRunBackgroundProgramAlways;
-static gboolean GdmSetPosition;
-static gboolean GdmQuiver;
-static gboolean GdmShowGnomeFailsafe;
-static gboolean GdmShowXtermFailsafe;
-static gboolean GdmShowLastSession;
-static gboolean GdmEntryCircles;
-static gboolean GdmEntryInvisible;
-static gboolean GdmGraphicalThemeRand;
-static gboolean GdmBroadcast;
-static gboolean GdmAllowAdd;
-static gboolean GdmRestartBackgroundProgram;
-
-/**
- * gdm_config_add_hash
- *
- * Add config value to the val_hash and type_hash.  Strip the key so
- * it doesn't contain a default value.  This function assumes the
- * val_hash, type_hash, and realkey_hash have been initialized.
- */
-static void
-gdm_config_add_hash (gchar *key, gpointer value, GdmConfigType *type)
-{
-   gchar *p;
-   gchar *newkey = g_strdup (key);
-
-   g_strstrip (newkey);
-   p = strchr (newkey, '=');
-   if (p != NULL)
-      *p = '\0';
-
-   g_hash_table_insert (val_hash, newkey, value);
-   g_hash_table_insert (type_hash, newkey, type);
-   g_hash_table_insert (realkey_hash, newkey, key);
-}
-
-/**
- * gdm_config_hash_lookup
- *
- * Accesses hash with key, stripping it so it doesn't contain a default
- * value.
- */
-static gpointer
-gdm_config_hash_lookup (GHashTable *hash,
-                        const gchar *key)
-{
-   gchar *p;
-   gpointer *ret;
-   gchar *newkey = g_strdup (key);
-
-   g_strstrip (newkey);
-   p = strchr (newkey, '=');
-   if (p != NULL)
-      *p = '\0';
-
-   ret = g_hash_table_lookup (hash, newkey);
-   g_free (newkey);
-   return (ret);
-}
-
 /**
  * is_key
  *
@@ -307,468 +89,198 @@ gdm_config_hash_lookup (GHashTable *hash
 static gboolean
 is_key (const gchar *key1, const gchar *key2)
 {
-   gchar *key1d, *key2d, *p;
-
-   key1d = g_strdup (key1);
-   key2d = g_strdup (key2);
+	gchar *key1d, *key2d, *p;
 
-   g_strstrip (key1d);
-   p = strchr (key1d, '=');
-   if (p != NULL)
-      *p = '\0';
-
-   g_strstrip (key2d);
-   p = strchr (key2d, '=');
-   if (p != NULL)
-      *p = '\0';
-
-   if (strcmp (ve_sure_string (key1d), ve_sure_string (key2d)) == 0) {
-      g_free (key1d);
-      g_free (key2d);
-      return TRUE;
-   } else {
-      g_free (key1d);
-      g_free (key2d);
-      return FALSE;
-   }
-}
-
-/**
- * gdm_config_init
- * 
- * Sets up initial hashes used by configuration routines.
- */ 
-static void 
-gdm_config_init (void)
-{
-   gint i;
-   gchar *key_string = NULL; 
-
-   type_hash    = g_hash_table_new (g_str_hash, g_str_equal);
-   val_hash     = g_hash_table_new (g_str_hash, g_str_equal);
-   realkey_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
-   /* boolean values */
-   gdm_config_add_hash (GDM_KEY_ALLOW_REMOTE_ROOT, &GdmAllowRemoteRoot, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALLOW_ROOT, &GdmAllowRoot, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN,
-      &GdmAllowRemoteAutoLogin, &bool_type);
-   gdm_config_add_hash (GDM_KEY_PASSWORD_REQUIRED, &GdmPasswordRequired, &bool_type);
-   gdm_config_add_hash (GDM_KEY_AUTOMATIC_LOGIN_ENABLE,
-      &GdmAutomaticLoginEnable, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALWAYS_RESTART_SERVER,
-      &GdmAlwaysRestartServer, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ADD_GTK_MODULES, &GdmAddGtkModules, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DOUBLE_LOGIN_WARNING,
-      &GdmDoubleLoginWarning, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION,
-      &GdmAlwaysLoginCurrentSession, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DISPLAY_LAST_LOGIN, &GdmDisplayLastLogin, &bool_type);
-   gdm_config_add_hash (GDM_KEY_KILL_INIT_CLIENTS, &GdmKillInitClients, &bool_type);
-   gdm_config_add_hash (GDM_KEY_CONFIG_AVAILABLE, &GdmConfigAvailable, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SYSTEM_MENU, &GdmSystemMenu, &bool_type);
-   gdm_config_add_hash (GDM_KEY_CHOOSER_BUTTON, &GdmChooserButton, &bool_type);
-   gdm_config_add_hash (GDM_KEY_BROWSER, &GdmBrowser, &bool_type);
-   gdm_config_add_hash (GDM_KEY_MULTICAST, &GdmMulticast, &bool_type);
-   gdm_config_add_hash (GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS,
-      &GdmNeverPlaceCookiesOnNfs, &bool_type);
-   gdm_config_add_hash (GDM_KEY_CONSOLE_NOTIFY, &GdmConsoleNotify, &bool_type);
-   gdm_config_add_hash (GDM_KEY_TIMED_LOGIN_ENABLE, &GdmTimedLoginEnable, &bool_type);
-   gdm_config_add_hash (GDM_KEY_CHECK_DIR_OWNER, &GdmCheckDirOwner, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SUPPORT_AUTOMOUNT, &GdmSupportAutomount, &bool_type);
-   gdm_config_add_hash (GDM_KEY_XDMCP, &GdmXdmcp, &bool_type);
-   gdm_config_add_hash (GDM_KEY_INDIRECT, &GdmIndirect, &bool_type);
-   gdm_config_add_hash (GDM_KEY_XDMCP_PROXY, &GdmXdmcpProxy, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DYNAMIC_XSERVERS, &GdmDynamicXservers, &bool_type);
-   gdm_config_add_hash (GDM_KEY_VT_ALLOCATION, &GdmVTAllocation, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DISALLOW_TCP, &GdmDisallowTcp, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_SUCCESS,
-      &GdmSoundOnLoginSuccess, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_FAILURE,
-      &GdmSoundOnLoginFailure, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DEBUG, &GdmDebug, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DEBUG_GESTURES, &GdmDebugGestures, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALLOW_GTK_THEME_CHANGE,
-      &GdmAllowGtkThemeChange, &bool_type);
-   gdm_config_add_hash (GDM_KEY_TITLE_BAR, &GdmTitleBar, &bool_type);
-   gdm_config_add_hash (GDM_KEY_INCLUDE_ALL, &GdmIncludeAll, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_WELCOME, &GdmDefaultWelcome, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_REMOTE_WELCOME,
-      &GdmDefaultRemoteWelcome, &bool_type);
-   gdm_config_add_hash (GDM_KEY_LOCK_POSITION, &GdmLockPosition, &bool_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_SCALE_TO_FIT,
-      &GdmBackgroundScaleToFit, &bool_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_REMOTE_ONLY_COLOR,
-      &GdmBackgroundRemoteOnlyColor, &bool_type);
-   gdm_config_add_hash (GDM_KEY_RUN_BACKGROUND_PROGRAM_ALWAYS,
-      &GdmRunBackgroundProgramAlways, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SET_POSITION, &GdmSetPosition, &bool_type);
-   gdm_config_add_hash (GDM_KEY_QUIVER, &GdmQuiver, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SHOW_GNOME_FAILSAFE,
-      &GdmShowGnomeFailsafe, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SHOW_XTERM_FAILSAFE,
-      &GdmShowXtermFailsafe, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SHOW_LAST_SESSION,
-      &GdmShowLastSession, &bool_type);
-   gdm_config_add_hash (GDM_KEY_USE_24_CLOCK, &GdmUse24Clock, &string_type);
-   gdm_config_add_hash (GDM_KEY_ENTRY_CIRCLES, &GdmEntryCircles, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ENTRY_INVISIBLE, &GdmEntryInvisible, &bool_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEME_RAND,
-      &GdmGraphicalThemeRand, &bool_type);
-   gdm_config_add_hash (GDM_KEY_BROADCAST, &GdmBroadcast, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALLOW_ADD, &GdmAllowAdd, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN, &GdmSoundOnLogin, &bool_type);
-   gdm_config_add_hash (GDM_KEY_RESTART_BACKGROUND_PROGRAM,
-      &GdmRestartBackgroundProgram, &bool_type);
-   gdm_config_add_hash (GDM_KEY_XNEST_UNSCALED_FONT_PATH,
-      &GdmXnestUnscaledFontPath, &bool_type);
-
-   /* string values */
-   gdm_config_add_hash (GDM_KEY_PATH, &GdmPath, &string_type);
-   gdm_config_add_hash (GDM_KEY_ROOT_PATH, &GdmRootPath, &string_type);
-   gdm_config_add_hash (GDM_KEY_CONSOLE_CANNOT_HANDLE,
-      &GdmConsoleCannotHandle, &string_type);
-   gdm_config_add_hash (GDM_KEY_CHOOSER, &GdmChooser, &string_type);
-   gdm_config_add_hash (GDM_KEY_GREETER, &GdmGreeter, &string_type);
-   gdm_config_add_hash (GDM_KEY_CONFIGURATOR, &GdmConfigurator, &string_type);
-   gdm_config_add_hash (GDM_KEY_POSTLOGIN, &GdmPostLogin, &string_type);
-   gdm_config_add_hash (GDM_KEY_PRESESSION, &GdmPreSession, &string_type);
-   gdm_config_add_hash (GDM_KEY_POSTSESSION, &GdmPostSession, &string_type);
-   gdm_config_add_hash (GDM_KEY_FAILSAFE_XSERVER, &GdmFailsafeXserver, &string_type);
-   gdm_config_add_hash (GDM_KEY_X_KEEPS_CRASHING, &GdmXKeepsCrashing, &string_type);
-   gdm_config_add_hash (GDM_KEY_BASE_XSESSION, &GdmBaseXsession, &string_type);
-   gdm_config_add_hash (GDM_KEY_REMOTE_GREETER, &GdmRemoteGreeter, &string_type);
-   gdm_config_add_hash (GDM_KEY_DISPLAY_INIT_DIR, &GdmDisplayInitDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_AUTOMATIC_LOGIN, &GdmAutomaticLogin, &string_type);
-   gdm_config_add_hash (GDM_KEY_GTK_MODULES_LIST, &GdmGtkModulesList, &string_type);
-   gdm_config_add_hash (GDM_KEY_REBOOT, &GdmReboot, &string_type);
-   gdm_config_add_hash (GDM_KEY_HALT, &GdmHalt, &string_type);
-   gdm_config_add_hash (GDM_KEY_SUSPEND, &GdmSuspend, &string_type);
-   gdm_config_add_hash (GDM_KEY_LOG_DIR, &GdmLogDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_PID_FILE, &GdmPidFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_GLOBAL_FACE_DIR, &GdmGlobalFaceDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_SERV_AUTHDIR, &GdmServAuthDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_USER_AUTHDIR, &GdmUserAuthDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_USER_AUTHFILE, &GdmUserAuthFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_USER_AUTHDIR_FALLBACK,
-      &GdmUserAuthFallback, &string_type);
-   gdm_config_add_hash (GDM_KEY_SESSION_DESKTOP_DIR, &GdmSessDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_SESSION, &GdmDefaultSession, &string_type);
-   gdm_config_add_hash (GDM_KEY_MULTICAST_ADDR, &GdmMulticastAddr, &string_type);
-   gdm_config_add_hash (GDM_KEY_USER, &GdmUser, &string_type);
-   gdm_config_add_hash (GDM_KEY_GROUP, &GdmGroup, &string_type);
-   gdm_config_add_hash (GDM_KEY_GTKRC, &GdmGtkRC, &string_type);
-   gdm_config_add_hash (GDM_KEY_GTK_THEME, &GdmGtkTheme, &string_type);
-   gdm_config_add_hash (GDM_KEY_TIMED_LOGIN, &GdmTimedLogin, &string_type);
-   gdm_config_add_hash (GDM_KEY_WILLING, &GdmWilling, &string_type);
-   gdm_config_add_hash (GDM_KEY_XDMCP_PROXY_XSERVER,
-      &GdmXdmcpProxyXserver, &string_type);
-   gdm_config_add_hash (GDM_KEY_XDMCP_PROXY_RECONNECT,
-      &GdmXdmcpProxyReconnect, &string_type);
-   gdm_config_add_hash (GDM_KEY_STANDARD_XSERVER, &GdmStandardXserver, &string_type);
-   gdm_config_add_hash (GDM_KEY_XNEST, &GdmXnest, &string_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_PROGRAM, &GdmSoundProgram, &string_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_FILE,
-      &GdmSoundOnLoginFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE,
-      &GdmSoundOnLoginSuccessFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE,
-      &GdmSoundOnLoginFailureFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_GTK_THEMES_TO_ALLOW,
-      &GdmGtkThemesToAllow, &string_type);
-   gdm_config_add_hash (GDM_KEY_INCLUDE, &GdmInclude, &string_type);
-   gdm_config_add_hash (GDM_KEY_EXCLUDE, &GdmExclude, &string_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_FACE, &GdmDefaultFace, &string_type);
-   gdm_config_add_hash (GDM_KEY_LOCALE_FILE, &GdmLocaleFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_LOGO, &GdmLogo, &string_type);
-   gdm_config_add_hash (GDM_KEY_CHOOSER_BUTTON_LOGO,
-      &GdmChooserButtonLogo, &string_type);
-   gdm_config_add_hash (GDM_KEY_WELCOME, &GdmWelcome, &string_type);
-   gdm_config_add_hash (GDM_KEY_REMOTE_WELCOME, &GdmRemoteWelcome, &string_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_PROGRAM,
-      &GdmBackgroundProgram, &string_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_IMAGE,
-      &GdmBackgroundImage, &string_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_COLOR,
-      &GdmBackgroundColor, &string_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEME,
-      &GdmGraphicalTheme, &string_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEME_DIR,
-      &GdmGraphicalThemeDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEMES,
-      &GdmGraphicalThemes, &string_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEMED_COLOR,
-      &GdmGraphicalThemeColor, &string_type);
-   gdm_config_add_hash (GDM_KEY_INFO_MSG_FILE, &GdmInfoMsgFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_INFO_MSG_FONT, &GdmInfoMsgFont, &string_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_HOST_IMG, &GdmHost, &string_type);
-   gdm_config_add_hash (GDM_KEY_HOST_IMAGE_DIR, &GdmHostImageDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_HOSTS, &GdmHosts, &string_type);
-   gdm_config_add_hash (GDM_KEY_PRE_FETCH_PROGRAM,
-      &GdmPreFetchProgram, &string_type);
-   gdm_config_add_hash (GDM_KEY_PAM_STACK, &GdmPamStack, &string_type);
-
-   /* custom command string values */
-   GdmCustomCommands = g_new0 (GdmCustomCmd, GDM_CUSTOM_COMMAND_MAX);   
-   for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
-	   /* For each possible custom command */      
-	   key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i); 
-	   GdmCustomCommands[i].command = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=Custom_%d"), GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE, i, i); 
-	   GdmCustomCommands[i].command_label = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_label, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=Execute custom command _%d"), GDM_KEY_CUSTOM_CMD_LR_LABEL_TEMPLATE, i, i);
-	   GdmCustomCommands[i].command_lr_label = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_lr_label, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=Are you sure?"), GDM_KEY_CUSTOM_CMD_TEXT_TEMPLATE, i);
-	   GdmCustomCommands[i].command_text = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_text, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=Execute custom command %d"), GDM_KEY_CUSTOM_CMD_TOOLTIP_TEMPLATE, i, i);
-	   GdmCustomCommands[i].command_tooltip = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_tooltip, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=false"), GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, i);
-	   GdmCustomCommands[i].command_no_restart = FALSE;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_no_restart, &bool_type);  
-
-	   key_string = g_strdup_printf(_("%s%d=false"), GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i);
-	   GdmCustomCommands[i].command_is_persistent = FALSE;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_is_persistent, &bool_type); 
-   }   
-
-   /* int values */
-   gdm_config_add_hash (GDM_KEY_XINERAMA_SCREEN, &GdmXineramaScreen, &int_type);
-   gdm_config_add_hash (GDM_KEY_RETRY_DELAY, &GdmRetryDelay, &int_type);
-   gdm_config_add_hash (GDM_KEY_TIMED_LOGIN_DELAY, &GdmTimedLoginDelay, &int_type);
-   gdm_config_add_hash (GDM_KEY_RELAX_PERM, &GdmRelaxPerm, &int_type);
-   gdm_config_add_hash (GDM_KEY_USER_MAX_FILE, &GdmUserMaxFile, &int_type);
-   gdm_config_add_hash (GDM_KEY_DISPLAYS_PER_HOST, &GdmDisplaysPerHost, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_PENDING, &GdmMaxPending, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_WAIT, &GdmMaxWait, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_SESSIONS, &GdmMaxSessions, &int_type);
-   gdm_config_add_hash (GDM_KEY_UDP_PORT, &GdmUdpPort, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_INDIRECT, &GdmMaxIndirect, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_WAIT_INDIRECT, &GdmMaxWaitIndirect, &int_type);
-   gdm_config_add_hash (GDM_KEY_PING_INTERVAL, &GdmPingInterval, &int_type);
-   gdm_config_add_hash (GDM_KEY_FLEXIBLE_XSERVERS, &GdmFlexibleXservers, &int_type);
-   gdm_config_add_hash (GDM_KEY_FIRST_VT, &GdmFirstVt, &int_type);
-   gdm_config_add_hash (GDM_KEY_POSITION_X, &GdmPositionX, &int_type);
-   gdm_config_add_hash (GDM_KEY_POSITION_Y, &GdmPositionY, &int_type);
-   gdm_config_add_hash (GDM_KEY_MINIMAL_UID, &GdmMinimalUid, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_ICON_WIDTH, &GdmMaxIconWidth, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_ICON_HEIGHT, &GdmMaxIconHeight, &int_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_TYPE, &GdmBackgroundType, &int_type);
-   gdm_config_add_hash (GDM_KEY_SCAN_TIME, &GdmScanTime, &int_type);
-   gdm_config_add_hash (GDM_KEY_FLEXI_REAP_DELAY_MINUTES,
-      &GdmFlexiReapDelayMinutes, &int_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_PROGRAM_INITIAL_DELAY,
-      &GdmBackgroundProgramInitialDelay, &int_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_PROGRAM_RESTART_DELAY,
-      &GdmBackgroundProgramRestartDelay, &int_type);
-   gdm_config_add_hash (GDM_KEY_XSERVER_TIMEOUT, &GdmXserverTimeout, &int_type);
-}
-
-/**
- * gdm_get_config:
- *
- * Get config file.
- */
-static GKeyFile *
-gdm_get_default_config (void)
-{
-   GKeyFile   *config;
-   GError     *error;
-   struct stat statbuf;
-   int         r;
-
-   /* Not NULL if config_file was set by command-line option. */
-   if (config_file == NULL) {
-      config_file = GDM_DEFAULTS_CONF;
-   }
-
-   error = NULL;
-   config = gdm_common_config_load (config_file, &error);
-
-   if (config == NULL) {
-      gdm_error (_("%s: Unable to load configuration from %s: %s"),
-                 "gdm_config_parse",
-                 config_file,
-                 error->message);
-      g_error_free (error);
-      return NULL;
-   }
-
-   VE_IGNORE_EINTR (r = g_stat (config_file, &statbuf));
-   if (r >= 0) {
-      config_file_mtime = statbuf.st_mtime;
-   }
-
-   return config;
-}
-
-/**
- * gdm_get_custom_config:
- *
- * Get the custom config file where gdmsetup saves its changes and
- * where users are encouraged to make modifications.
- */
-static GKeyFile *
-gdm_get_custom_config (void)
-{
-   GKeyFile   *config;
-   GError     *error;
-   struct stat statbuf;
-   int         r;
-
-   /*
-    * First check to see if the old configuration file name is on
-    * the system.  If so, use that as the custom configuration
-    * file.  "make install" will move this file aside, and 
-    * distros probably can also manage moving this file on
-    * upgrade.
-    *
-    * In case this file is on the system, then use it as
-    * the custom configuration file until the user moves it
-    * aside.  This will likely mean all the defaults in
-    * defaults.conf will not get used since the old gdm.conf
-    * file has all the keys in it (except new ones).  But
-    * that would be what the user wants.
-    */
-
-   error = NULL;
-   config = gdm_common_config_load (GDM_OLD_CONF, &error);
-   if (config != NULL) {
-      custom_config_file = g_strdup (GDM_OLD_CONF);
-   } else {
-      g_error_free (error);
-      error = NULL;
-      config = gdm_common_config_load (GDM_CUSTOM_CONF, &error);
-      if (config != NULL) {
-         custom_config_file = g_strdup (GDM_CUSTOM_CONF);
-      } else {
-         g_error_free (error);
-      }
-   }
-
-   VE_IGNORE_EINTR (r = g_stat (custom_config_file, &statbuf));
-   if (r >= 0) {
-      custom_config_file_mtime = statbuf.st_mtime;
-   }
+	key1d = g_strdup (key1);
+	key2d = g_strdup (key2);
 
-   return config;
+	g_strstrip (key1d);
+	p = strchr (key1d, '=');
+	if (p != NULL)
+		*p = '\0';
+
+	g_strstrip (key2d);
+	p = strchr (key2d, '=');
+	if (p != NULL)
+		*p = '\0';
+
+	if (strcmp (ve_sure_string (key1d), ve_sure_string (key2d)) == 0) {
+		g_free (key1d);
+		g_free (key2d);
+		return TRUE;
+	} else {
+		g_free (key1d);
+		g_free (key2d);
+		return FALSE;
+	}
 }
 
 /**
- * gdm_get_per_display_custom_config_file
+ * gdm_daemon_config_get_per_display_custom_config_file
  *
  * Returns the per-display config file for a given display
  * This is always the custom config file name with the display
  * appended, and never gdm.conf.
  */
 static gchar *
-gdm_get_per_display_custom_config_file (const gchar *display)
+gdm_daemon_config_get_per_display_custom_config_file (const gchar *display)
 {
-  return g_strdup_printf ("%s%s", custom_config_file, display);
+	return g_strdup_printf ("%s%s", custom_config_file, display);
 }
- 
+
 /**
- * gdm_get_custom_config_file
+ * gdm_daemon_config_get_custom_config_file
  *
  * Returns the custom config file being used.
  */
 gchar *
-gdm_get_custom_config_file (void)
+gdm_daemon_config_get_custom_config_file (void)
 {
-   return custom_config_file;
+	return custom_config_file;
 }
 
 /**
- * gdm_get_value_int
+ * gdm_daemon_config_get_value_int
  *
  * Gets an integer configuration option by key.  The option must
  * first be loaded, say, by calling gdm_config_parse.
  */
 gint
-gdm_get_value_int (const char *key)
+gdm_daemon_config_get_value_int (const char *keystring)
 {
-   GdmConfigType *type = gdm_config_hash_lookup (type_hash, key);
-   gpointer val        = gdm_config_hash_lookup (val_hash, key);
+	gboolean res;
+	GdmConfigValue *value;
+	char *group;
+	char *key;
+	int   result;
+
+	result = 0;
+
+	res = gdm_common_config_parse_key_string (keystring,
+						  &group,
+						  &key,
+						  NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	res = gdm_config_get_value (daemon_config,
+				    group,
+				    key,
+				    &value);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	if (value->type != GDM_CONFIG_VALUE_INT) {
+		gdm_error ("Request for configuration key %s, but not type INT", keystring);
+		goto out;
+	}
 
-   if (type == NULL || val == NULL) {
-      gdm_error ("Request for invalid configuration key %s", key);
-   } else if (*type != CONFIG_INT) {
-      gdm_error ("Request for configuration key %s, but not type INT", key);
-   } else {
-      gint *intval = (int *)val;
-      return *intval;
-   }
+	result = gdm_config_value_get_int (value);
+ out:
+	g_free (group);
+	g_free (key);
 
-   return 0;
+	return result;
 }
 
 /**
- * gdm_get_value_string
+ * gdm_daemon_config_get_value_string
  *
  * Gets a string configuration option by key.  The option must
- * first be loaded, say, by calling gdm_config_parse.
+ * first be loaded, say, by calling gdm_daemon_config_parse.
  */
-gchar *
-gdm_get_value_string (const char *key)
+const char *
+gdm_daemon_config_get_value_string (const char *keystring)
 {
-   GdmConfigType *type;
-   gpointer val;
+	gboolean res;
+	GdmConfigValue *value;
+	char *group;
+	char *key;
+	const char *result;
+
+	result = NULL;
+
+	res = gdm_common_config_parse_key_string (keystring,
+						  &group,
+						  &key,
+						  NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	res = gdm_config_get_value (daemon_config,
+				    group,
+				    key,
+				    &value);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	if (value->type != GDM_CONFIG_VALUE_STRING) {
+		gdm_error ("Request for configuration key %s, but not type STRING", keystring);
+		goto out;
+	}
 
-   /* First look in translated_hash */
-   if (translated_hash != NULL) {
-      val = gdm_config_hash_lookup (translated_hash, key);
-      if (val) {
-         gchar **charval = (char **)val;
-         return *charval;
-      }
-   }
-
-   type = gdm_config_hash_lookup (type_hash, key);
-   val  = gdm_config_hash_lookup (val_hash, key);
-
-   if (type == NULL || val == NULL) {
-      gdm_error ("Request for invalid configuration key %s", key);
-   } else if (*type != CONFIG_STRING) {
-      gdm_error ("Request for configuration key %s, but not type STRING", key);
-   } else {
-      gchar **charval = (char **)val;
-      return *charval;
-   }
+	result = gdm_config_value_get_string (value);
+ out:
+	g_free (group);
+	g_free (key);
 
-   return NULL;
+	return result;
 }
 
 /**
- * gdm_get_value_bool
- * 
+ * gdm_daemon_config_get_value_bool
+ *
  * Gets a boolean configuration option by key.  The option must
  * first be loaded, say, by calling gdm_config_parse.
  */
 gboolean
-gdm_get_value_bool (const char *key)
+gdm_daemon_config_get_value_bool (const char *keystring)
 {
-   GdmConfigType *type = gdm_config_hash_lookup (type_hash, key);
-   gpointer val        = gdm_config_hash_lookup (val_hash, key);
+	gboolean res;
+	GdmConfigValue *value;
+	char *group;
+	char *key;
+	gboolean result;
+
+	result = FALSE;
+
+	res = gdm_common_config_parse_key_string (keystring,
+						  &group,
+						  &key,
+						  NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	res = gdm_config_get_value (daemon_config,
+				    group,
+				    key,
+				    &value);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	if (value->type != GDM_CONFIG_VALUE_BOOL) {
+		gdm_error ("Request for configuration key %s, but not type BOOLEAN", keystring);
+		goto out;
+	}
 
-   if (type == NULL || val == NULL) {
-      gdm_error ("Request for invalid configuration key %s", key);
-   } else if (*type != CONFIG_BOOL) {
-      gdm_error ("Request for configuration key %s, but not type BOOL", key);
-   } else {
-      gboolean *boolval = (gboolean *)val;
-      return *boolval;
-   }
+	result = gdm_config_value_get_bool (value);
+ out:
+	g_free (group);
+	g_free (key);
 
-   return FALSE;
+	return result;
 }
 
 /**
@@ -779,79 +291,82 @@ gdm_get_value_bool (const char *key)
  */
 
 /**
- * gdm_get_value_int_per_display
+ * gdm_daemon_config_get_value_int_per_display
  *
  * Gets the per-display version  of the configuration, or the default
  * value if none exists.
  */
-gint gdm_get_value_int_per_display (const gchar *display,
-                                    const gchar *key)
+gint
+gdm_daemon_config_get_value_int_per_display (const gchar *display,
+					     const gchar *key)
 {
-   gchar *perdispval;
+	gchar *perdispval;
 
-   gdm_config_key_to_string_per_display (display, key, &perdispval);
+	gdm_daemon_config_key_to_string_per_display (display, key, &perdispval);
 
-   if (perdispval != NULL) {
-      gint val = atoi (perdispval);
-      g_free (perdispval);
-      return val;
-   } else {
-      return (gdm_get_value_int (key));
-   }
+	if (perdispval != NULL) {
+		gint val = atoi (perdispval);
+		g_free (perdispval);
+		return val;
+	} else {
+		return (gdm_daemon_config_get_value_int (key));
+	}
 }
- 
+
 /**
- * gdm_get_value_bool_per_display
+ * gdm_daemon_config_get_value_bool_per_display
  *
  * Gets the per-display version  of the configuration, or the default
  * value if none exists.
  */
-gboolean gdm_get_value_bool_per_display (const gchar *display,
-                                         const gchar *key)
+gboolean
+gdm_daemon_config_get_value_bool_per_display (const gchar *display,
+					      const gchar *key)
 {
-   gchar *perdispval;
+	gchar *perdispval;
 
-   gdm_config_key_to_string_per_display (display, key, &perdispval);
+	gdm_daemon_config_key_to_string_per_display (display, key, &perdispval);
 
-   if (perdispval != NULL) {
-      if (perdispval[0] == 'T' ||
-          perdispval[0] == 't' ||
-          perdispval[0] == 'Y' ||
-          perdispval[0] == 'y' ||
-          atoi (perdispval) != 0) {
-		g_free (perdispval);
-		return TRUE;
-       } else {
-		return FALSE;
-       }
-   } else {
-      return (gdm_get_value_bool (key));
-   }
+	if (perdispval != NULL) {
+		if (perdispval[0] == 'T' ||
+		    perdispval[0] == 't' ||
+		    perdispval[0] == 'Y' ||
+		    perdispval[0] == 'y' ||
+		    atoi (perdispval) != 0) {
+			g_free (perdispval);
+			return TRUE;
+		} else {
+			return FALSE;
+		}
+	} else {
+		return (gdm_daemon_config_get_value_bool (key));
+	}
 }
  
 /**
- * gdm_get_value_string_per_display
+ * gdm_daemon_config_get_value_string_per_display
  *
  * Gets the per-display version  of the configuration, or the default
  * value if none exists.  Note that this value needs to be freed,
  * unlike the non-per-display version.
  */
-gchar * gdm_get_value_string_per_display (const gchar *display,
-                                          const gchar *key)
+gchar *
+gdm_daemon_config_get_value_string_per_display (const gchar *display,
+						const gchar *key)
 {
-   gchar *perdispval;
+	gchar *perdispval;
 
-   gdm_config_key_to_string_per_display (display, key, &perdispval);
+	gdm_daemon_config_key_to_string_per_display (display, key, &perdispval);
 
-   if (perdispval != NULL) {
-      return perdispval;
-   } else {
-      return (g_strdup (gdm_get_value_string (key)));
-   }
+	if (perdispval != NULL) {
+		return perdispval;
+	} else {
+		return (g_strdup (gdm_daemon_config_get_value_string (key)));
+	}
 }
 
 /**
- * gdm_config_key_to_string_per_display
+ * gdm_daemon_config_key_to_string_per_display
  *
  * If the key makes sense to be per-display, return the value,
  * otherwise return NULL.  Keys that only apply to the daemon
@@ -863,748 +378,444 @@ gchar * gdm_get_value_string_per_display
  * sure they are added to the if-test below.
  */
 void
-gdm_config_key_to_string_per_display (const gchar *display,
-                                      const gchar *key,
-                                      gchar **retval)
+gdm_daemon_config_key_to_string_per_display (const gchar *display,
+					     const gchar *key,
+					     gchar **retval)
 {
-   gchar *file;
-   gchar **splitstr = g_strsplit (key, "/", 2);
+	gchar *file;
+	gchar **splitstr = g_strsplit (key, "/", 2);
 
-   *retval = NULL;
+	*retval = NULL;
 
-   if (display == NULL)
-      return;
+	if (display == NULL)
+		return;
 
-   file = gdm_get_per_display_custom_config_file (display);
+	file = gdm_daemon_config_get_per_display_custom_config_file (display);
 
-   if (strcmp (ve_sure_string (splitstr[0]), "greeter") == 0 ||
-       strcmp (ve_sure_string (splitstr[0]), "gui") == 0 ||
-       is_key (key, GDM_KEY_PAM_STACK)) {
-      gdm_config_key_to_string (file, key, retval);
-   }
+	if (strcmp (ve_sure_string (splitstr[0]), "greeter") == 0 ||
+	    strcmp (ve_sure_string (splitstr[0]), "gui") == 0 ||
+	    is_key (key, GDM_KEY_PAM_STACK)) {
+		gdm_daemon_config_key_to_string (file, key, retval);
+	}
 
-   g_free (file);
+	g_free (file);
 
-   return;
+	return;
 }
 
 /**
- * gdm_config_key_to_string
+ * gdm_daemon_config_key_to_string
  *
  * Returns a specific key from the config file, or NULL if not found.
  * Note this returns the value in string form, so the caller needs
  * to parse it properly if it is a bool or int.
  */
 void
-gdm_config_key_to_string (const gchar *file,
-                          const gchar *keystring,
-                          gchar **retval)
-{
-   GKeyFile *config;
-   GdmConfigType *type;
-
-   if (retval != NULL) {
-      *retval = NULL;
-   }
-
-   config = gdm_common_config_load (file, NULL);
-   /* If file doesn't exist, then just return */
-   if (config == NULL)
-      return;
-
-   type = gdm_config_hash_lookup (type_hash, keystring);
-
-   gdm_debug ("Returning value for key <%s>\n", keystring);
-
-   switch (*type) {
-   case CONFIG_BOOL:
-      {
-         gboolean value;
-         gdm_common_config_get_boolean (config, keystring, &value, NULL);
-         if (value)
-            *retval = g_strdup ("true");
-         else
-            *retval = g_strdup ("false");
-      }
-      break;
-   case CONFIG_INT:
-      {
-         gint value;
-         gdm_common_config_get_int (config, keystring, &value, NULL);
-         *retval = g_strdup_printf ("%d", value);
-      }
-      break;
-   case CONFIG_STRING:
-      {
-         gchar *value;
-         gdm_common_config_get_string (config, keystring, &value, NULL);
-         *retval = value;
-      }
-      break;
-   default:
-      break;
-   }
+gdm_daemon_config_key_to_string (const gchar *file,
+				 const gchar *keystring,
+				 gchar **retval)
+{
+	GKeyFile *config;
+	GdmConfigValueType type;
+	gboolean res;
+	char *group;
+	char *key;
+	const GdmConfigEntry *entry;
+
+	if (retval != NULL) {
+		*retval = NULL;
+	}
+
+	res = gdm_common_config_parse_key_string (keystring,
+						  &group,
+						  &key,
+						  NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	entry = gdm_config_lookup_entry (daemon_config, group, key);
+	if (entry == NULL) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+	type = entry->type;
+
+	config = gdm_common_config_load (file, NULL);
+	/* If file doesn't exist, then just return */
+	if (config == NULL)
+		return;
+
+	gdm_debug ("Returning value for key <%s>\n", keystring);
+
+	switch (type) {
+	case GDM_CONFIG_VALUE_BOOL:
+		{
+			gboolean value;
+			gdm_common_config_get_boolean (config, keystring, &value, NULL);
+			if (value)
+				*retval = g_strdup ("true");
+			else
+				*retval = g_strdup ("false");
+		}
+		break;
+	case GDM_CONFIG_VALUE_INT:
+		{
+			gint value;
+			gdm_common_config_get_int (config, keystring, &value, NULL);
+			*retval = g_strdup_printf ("%d", value);
+		}
+		break;
+	case GDM_CONFIG_VALUE_STRING:
+		{
+			gchar *value;
+			gdm_common_config_get_string (config, keystring, &value, NULL);
+			*retval = value;
+		}
+		break;
+	default:
+		break;
+	}
 
-   g_key_file_free (config);
+	g_key_file_free (config);
+ out:
+	g_free (group);
+	g_free (key);
 
-   return;
+	return;
 }
 
 /**
- * gdm_config_to_string
+ * gdm_daemon_config_to_string
  *
  * Returns a configuration option as a string.  Used by GDM's
  * GET_CONFIG socket command.
  */
 void
-gdm_config_to_string (const gchar *key,
-                      const gchar *display,
-                      gchar **retval)
-{
-   GdmConfigType *type = gdm_config_hash_lookup (type_hash, key);
-   *retval = NULL;
-
-   /*
-    * See if there is a per-display config file, returning that value
-    * if it exists.
-    */
-   if (display) {
-      gdm_config_key_to_string_per_display (display, key, retval);
-      if (*retval != NULL)
-         return;
-   }
-
-   /* First look in translated_hash */
-   if (translated_hash != NULL) {
-      gpointer val = gdm_config_hash_lookup (translated_hash, key);
-      if (val) {
-         *retval = g_strdup (val);
-         return;
-      }
-   }
-
-   if (type != NULL) {
-      if (*type == CONFIG_BOOL) {
-         gboolean value = gdm_get_value_bool (key);
-         if (value)
-            *retval = g_strdup ("true");
-         else
-            *retval = g_strdup ("false");
-         return;
-      } else if (*type == CONFIG_INT) {
-         gint value = gdm_get_value_int (key);
-         *retval = g_strdup_printf ("%d", value);
-         return;
-      } else if (*type == CONFIG_STRING) {
-         gchar *value = gdm_get_value_string (key);
-         if (value != NULL)
-            *retval = g_strdup (value);
-         return;
-      }
-   }
+gdm_daemon_config_to_string (const gchar *keystring,
+			     const gchar *display,
+			     gchar **retval)
+{
+	gboolean res;
+	GdmConfigValue *value;
+	char *group;
+	char *key;
+	char *result;
+
+	/*
+	 * See if there is a per-display config file, returning that value
+	 * if it exists.
+	 */
+	if (display != NULL) {
+		gdm_daemon_config_key_to_string_per_display (display, keystring, retval);
+		if (*retval != NULL)
+			return;
+	}
+
+	result = NULL;
+
+	res = gdm_common_config_parse_key_string (keystring,
+						  &group,
+						  &key,
+						  NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	res = gdm_config_get_value (daemon_config,
+				    group,
+				    key,
+				    &value);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	result = gdm_config_value_to_string (value);
+
+ out:
+	g_free (group);
+	g_free (key);
 
-   gdm_debug ("Error returning config key %s\n", key);
-   return;
+	*retval = result;
 }
 
 /**
- * gdm_compare_displays
- * 
+ * gdm_daemon_config_compare_displays
+ *
  * Support function for loading displays from the configuration
  * file
  */
 int
-gdm_compare_displays (gconstpointer a, gconstpointer b)
+gdm_daemon_config_compare_displays (gconstpointer a, gconstpointer b)
 {
-   const GdmDisplay *d1 = a;
-   const GdmDisplay *d2 = b;
-   if (d1->dispnum < d2->dispnum)
-      return -1;
-   else if (d1->dispnum > d2->dispnum)
-      return 1;
-   else
-      return 0;
+	const GdmDisplay *d1 = a;
+	const GdmDisplay *d2 = b;
+	if (d1->dispnum < d2->dispnum)
+		return -1;
+	else if (d1->dispnum > d2->dispnum)
+		return 1;
+	else
+		return 0;
+}
+
+static char *
+lookup_notify_key (GdmConfig  *config,
+		   const char *group,
+		   const char *key)
+{
+	char *nkey;
+	char *keystring;
+
+	keystring = g_strdup_printf ("%s/%s", group, key);
+
+	/* pretty lame but oh well */
+	nkey = NULL;
+
+	/* bools */
+	if (is_key (keystring, GDM_KEY_ALLOW_ROOT))
+		nkey = g_strdup (GDM_NOTIFY_ALLOW_ROOT);
+	else if (is_key (keystring, GDM_KEY_ALLOW_REMOTE_ROOT))
+		nkey = g_strdup (GDM_NOTIFY_ALLOW_REMOTE_ROOT);
+	else if (is_key (keystring, GDM_KEY_ALLOW_REMOTE_AUTOLOGIN))
+		nkey = g_strdup (GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN);
+	else if (is_key (keystring, GDM_KEY_SYSTEM_MENU))
+		nkey = g_strdup (GDM_NOTIFY_SYSTEM_MENU);
+	else if (is_key (keystring, GDM_KEY_CONFIG_AVAILABLE))
+		nkey = g_strdup (GDM_NOTIFY_CONFIG_AVAILABLE);
+	else if (is_key (keystring, GDM_KEY_CHOOSER_BUTTON))
+		nkey = g_strdup (GDM_NOTIFY_CHOOSER_BUTTON);
+	else if (is_key (keystring, GDM_KEY_DISALLOW_TCP))
+		nkey = g_strdup (GDM_NOTIFY_DISALLOW_TCP);
+	else if (is_key (keystring, GDM_KEY_ADD_GTK_MODULES))
+		nkey = g_strdup (GDM_NOTIFY_ADD_GTK_MODULES);
+	else if (is_key (keystring, GDM_KEY_TIMED_LOGIN_ENABLE))
+		nkey = g_strdup (GDM_NOTIFY_TIMED_LOGIN_ENABLE);
+	/* ints */
+	else if (is_key (keystring, GDM_KEY_RETRY_DELAY))
+		nkey = g_strdup (GDM_NOTIFY_RETRY_DELAY);
+	else if (is_key (keystring, GDM_KEY_TIMED_LOGIN_DELAY))
+		nkey = g_strdup (GDM_NOTIFY_TIMED_LOGIN_DELAY);
+	/* strings */
+	else if (is_key (keystring, GDM_KEY_GREETER))
+		nkey = g_strdup (GDM_NOTIFY_GREETER);
+	else if (is_key (keystring, GDM_KEY_REMOTE_GREETER))
+		nkey = g_strdup (GDM_NOTIFY_REMOTE_GREETER);
+	else if (is_key (keystring, GDM_KEY_SOUND_ON_LOGIN_FILE))
+		nkey = g_strdup (GDM_NOTIFY_SOUND_ON_LOGIN_FILE);
+	else if (is_key (keystring, GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE))
+		nkey = g_strdup (GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE);
+	else if (is_key (keystring, GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE))
+		nkey = g_strdup (GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE);
+	else if (is_key (keystring, GDM_KEY_GTK_MODULES_LIST))
+		nkey = g_strdup (GDM_NOTIFY_GTK_MODULES_LIST);
+	else if (is_key (keystring, GDM_KEY_TIMED_LOGIN))
+		nkey = g_strdup (GDM_NOTIFY_TIMED_LOGIN);
+	else if (strcmp (group, GDM_CONFIG_GROUP_CUSTOM_CMD) == 0 &&
+		 g_str_has_prefix (key, "CustomCommand") &&
+		 strlen (key) == 14) {
+		/* this should match 'CustomCommandN' */
+		nkey = g_strdup (key);
+	}
+	g_free (keystring);
+
+	return nkey;
 }
 
 /**
- * notify_displays_int
- * notify_displays_string
+ * notify_displays_value
  *
- * The following two functions will notify the slave programs
+ * This will notify the slave programs
  * (gdmgreeter, gdmlogin, etc.) that a configuration option has
  * been changed so the slave can update with the new option
  * value.  GDM does this notify when it receives a
  * GDM_CONFIG_UPDATE socket command from gdmsetup or from the
- * gdmflexiserver --command option.   notify_displays_int
- * is also used for notifying for boolean values.
+ * gdmflexiserver --command option.
  */
 static void
-notify_displays_int (const gchar *key, int val)
-{
-   GSList *li;
-   for (li = displays; li != NULL; li = li->next) {
-       GdmDisplay *disp = li->data;
-       if (disp->master_notify_fd >= 0) {
-          gdm_fdprintf (disp->master_notify_fd, "%c%s %d\n",
-                        GDM_SLAVE_NOTIFY_KEY, key, val);
-
-          if (disp != NULL && disp->slavepid > 1)
-             kill (disp->slavepid, SIGUSR2);
-      }
-   }
-}
-
-static void
-notify_displays_string (const gchar *key, const gchar *val)
-{
-   GSList *li;
-   for (li = displays; li != NULL; li = li->next) {
-      GdmDisplay *disp = li->data;
-      if (disp->master_notify_fd >= 0) {
-         if (val == NULL) {
-            gdm_fdprintf (disp->master_notify_fd, "%c%s \n",
-                          GDM_SLAVE_NOTIFY_KEY, key);
-         } else {
-            gdm_fdprintf (disp->master_notify_fd, "%c%s %s\n",
-                          GDM_SLAVE_NOTIFY_KEY, key, val);
-         }
-         if (disp != NULL && disp->slavepid > 1)
-            kill (disp->slavepid, SIGUSR2);
-      }
-   }
-}
-
-/**
- * _gdm_set_value_string
- * _gdm_set_value_bool
- * _gdm_set_value_int
- *
- * The following interfaces are used to set values.  The "doing_update"
- * boolean argument which is only set when GDM_UPDATE_CONFIG is called.
- * If doing_update is TRUE, then a notify is sent to slaves.  When
- * loading values at other times (such as when first loading
- * configuration options) there is no need to notify the slaves.  If
- * there is a desire to send a notify to the slaves, the
- * gdm_update_config function should be used instead of calling these
- * functions directly.
- */
-static void
-_gdm_set_value_string (const gchar *key,
-                       const gchar *value_in,
-                       gboolean doing_update)
-{
-   gchar **setting = gdm_config_hash_lookup (val_hash, key);
-   gchar *setting_copy = NULL;
-   gchar *temp_string;
-   const gchar *value;
-   gint i;
-
-   if (! ve_string_empty (value_in))
-      value = value_in;
-   else
-      value = NULL;
-
-   if (setting == NULL) {
-      gdm_error ("Failure setting key %s to %s", key, value);
-      return;
-   }
-
-   if (*setting != NULL) {
-      /* Free old value */
-      setting_copy = g_strdup (*setting);
-      g_free (*setting);
-   }
-
-   /* User PATH */
-   if (is_key (key, GDM_KEY_PATH)) {
-
-      temp_string = gdm_read_default ("PATH=");
-      if (temp_string != NULL)
-         *setting = temp_string;
-      else if (value != NULL)
-         *setting = g_strdup (value);
-      else
-         *setting = NULL;
-
-   /* Root user PATH */
-   } else if (is_key (key, GDM_KEY_ROOT_PATH)) {
-
-      temp_string = gdm_read_default ("SUPATH=");
-      if (temp_string != NULL)
-         *setting = temp_string;
-      else if (value != NULL)
-         *setting = g_strdup (value);
-      else
-         *setting = NULL;
-
-    /* Location of Xsession script */
-    } else if (is_key (key, GDM_KEY_BASE_XSESSION)) {
-       if (value != NULL) {
-          *setting = g_strdup (value);
-       } else {
-          gdm_info (_("%s: BaseXsession empty; using %s/gdm/Xsession"),
-                      "gdm_config_parse",
-                      GDMCONFDIR);
-          *setting = g_build_filename (GDMCONFDIR,
-                                       "gdm", "Xsession", NULL);
-       }
-
-   /* Halt, Reboot, and Suspend commands */
-   } else if (is_key (key, GDM_KEY_HALT) ||
-              is_key (key, GDM_KEY_REBOOT) ||
-              is_key (key, GDM_KEY_SUSPEND)) {
-       if (value != NULL)
-          *setting = ve_get_first_working_command (value, FALSE);
-       else
-          *setting = NULL;
-
-   /* Console cannot handle these languages */
-   } else if (is_key (key, GDM_KEY_CONSOLE_CANNOT_HANDLE)) {
-       if (value != NULL)
-          *setting = g_strdup (value);
-       else
-          *setting = "";
-       gdm_ok_console_language ();
-
-   /* Location of Xserver */
-   } else if (is_key (key, GDM_KEY_STANDARD_XSERVER)) {
-      gchar *bin = NULL;
-
-      if (value != NULL)
-         bin = ve_first_word (value);
-
-      if G_UNLIKELY (ve_string_empty (bin) ||
-                     g_access (bin, X_OK) != 0) {
-         gdm_info (_("%s: Standard X server not found; trying alternatives"),
-                     "gdm_config_parse");
-         if (g_access ("/usr/X11R6/bin/X", X_OK) == 0) {
-            *setting = g_strdup ("/usr/X11R6/bin/X");
-         } else if (g_access ("/opt/X11R6/bin/X", X_OK) == 0) {
-            *setting = g_strdup ("/opt/X11R6/bin/X");
-         } else if (g_access ("/usr/bin/X11/X", X_OK) == 0) {
-            *setting = g_strdup ("/usr/bin/X11/X");
-         } else
-            *setting = g_strdup (value);
-      } else {
-         *setting = g_strdup (value);
-      }
-
-   /* Graphical Theme Directory */
-   } else if (is_key (key, GDM_KEY_GRAPHICAL_THEME_DIR)) {
-      if (value == NULL ||
-          ! g_file_test (value, G_FILE_TEST_IS_DIR))
-      {
-         *setting = g_strdup (GREETERTHEMEDIR);
-      } else {
-         *setting = g_strdup (value);
-      }
-
-   /* Graphical Theme */
-   } else if (is_key (key, GDM_KEY_GRAPHICAL_THEME)) {
-     if (value == NULL)
-        *setting = g_strdup ("circles");
-     else
-        *setting = g_strdup (value);
-
-   /*
-    * Default Welcome Message.  Don't translate here since the
-    * GDM user may not be running with the same language as the user.
-    * The slave programs will translate the string.
-    */
-   } else if (is_key (key, GDM_KEY_WELCOME)) {
-      if (value != NULL)
-         *setting = g_strdup (value);
-      else
-         *setting = g_strdup (GDM_DEFAULT_WELCOME_MSG);
-
-   /*
-    * Default Remote Welcome Message.  Don't translate here since the 
-    * GDM user may not be running with the same language as the user.
-    * The slave programs will translate the string.
-    */
-   } else if (is_key (key, GDM_KEY_REMOTE_WELCOME)) {
-      if (value != NULL)
-         *setting = g_strdup (value);
-      else
-         *setting = g_strdup (GDM_DEFAULT_REMOTE_WELCOME_MSG);
-
-   /* All others */
-   } else {
-       for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
-	       gchar * key_string = NULL;
-	       /* For each possible custom command */
-	       key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
-	       if (is_key (key, key_string)) {
-		       if (value != NULL)
-			       *setting = ve_get_first_working_command (value, FALSE);
-		       else
-			       *setting = NULL;
-		       break;
-	       }
-	       g_free(key_string);
-       }
-
-       if (value != NULL)
-          *setting = g_strdup (value);
-       else {
-          if (is_key (key, GDM_KEY_GREETER))
-             gdm_error (_("%s: No greeter specified."), "gdm_config_parse");
-          else if (is_key (key, GDM_KEY_REMOTE_GREETER))
-             gdm_error (_("%s: No remote greeter specified."), "gdm_config_parse");
-          else if (is_key (key, GDM_KEY_SESSION_DESKTOP_DIR))
-             gdm_error (_("%s: No sessions directory specified."), "gdm_config_parse");
-
-          *setting = NULL;
-       }
-   }
-
-   /* Handle update */
-   if (doing_update == TRUE && 
-       strcmp (ve_sure_string (*setting),
-               ve_sure_string (setting_copy)) != 0) {
-
-      if (is_key (key, GDM_KEY_GREETER))
-         notify_displays_string (GDM_NOTIFY_GREETER, *setting);
-      else if (is_key (key, GDM_KEY_REMOTE_GREETER))
-         notify_displays_string (GDM_NOTIFY_REMOTE_GREETER, *setting);
-      else if (is_key (key, GDM_KEY_SOUND_ON_LOGIN_FILE))
-         notify_displays_string (GDM_NOTIFY_SOUND_ON_LOGIN_FILE, *setting);
-      else if (is_key (key, GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE))
-         notify_displays_string (GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE, *setting);
-      else if (is_key (key, GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE))
-         notify_displays_string (GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE, *setting);
-      else if (is_key (key, GDM_KEY_GTK_MODULES_LIST))
-         notify_displays_string (GDM_NOTIFY_GTK_MODULES_LIST, *setting);
-      else if (is_key (key, GDM_KEY_TIMED_LOGIN))
-         notify_displays_string (GDM_NOTIFY_TIMED_LOGIN, *setting);
-
-      for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {	   	   
-	      gchar * key_string = NULL;
-	      /* For each possible custom command */     
-	      key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i); 
-	      if (is_key (key, key_string)) {
-		      g_free(key_string);
-		      key_string = g_strdup_printf (_("%s%d"), GDM_NOTIFY_CUSTOM_CMD_TEMPLATE, i);
-		      notify_displays_string (key_string, *setting);
-		      break;
-	      }
-	      g_free(key_string);
-      }       
-   }
-
-   if (setting_copy != NULL)
-      g_free (setting_copy);
-
-   if (*setting == NULL)
-      gdm_debug ("set config key %s to string <NULL>", key);
-   else
-      gdm_debug ("set config key %s to string %s", key, *setting);
-}
-
+notify_displays_value (GdmConfig      *config,
+		       const char     *group,
+		       const char     *key,
+		       GdmConfigValue *value)
+{
+	GSList *li;
+	char   *valstr;
+	char   *keystr;
+
+	keystr = lookup_notify_key (config, group, key);
+
+	/* unfortunately, can't always gdm_config_value_to_string()
+	 * here because booleans need to be sent as ints
+	 */
+	switch (value->type) {
+	case GDM_CONFIG_VALUE_BOOL:
+		if (gdm_config_value_get_bool (value)) {
+			valstr = g_strdup ("1");
+		} else {
+			valstr = g_strdup ("0");
+		}
+		break;
+	default:
+		valstr = gdm_config_value_to_string (value);
+		break;
+	}
+
+	if (valstr == NULL) {
+		valstr = g_strdup (" ");
+	}
+
+	for (li = displays; li != NULL; li = li->next) {
+		GdmDisplay *disp = li->data;
+
+		if (disp->master_notify_fd < 0) {
+			/* no point */
+			continue;
+		}
+
+		gdm_fdprintf (disp->master_notify_fd,
+			      "%c%s %s\n",
+			      GDM_SLAVE_NOTIFY_KEY,
+			      keystr,
+			      valstr);
+
+		if (disp != NULL && disp->slavepid > 1) {
+			kill (disp->slavepid, SIGUSR2);
+		}
+	}
+
+	g_free (keystr);
+	g_free (valstr);
+}
+
+/* The following were used to internally set the
+ * stored configuration values.  Now we'll just
+ * ask the GdmConfig to store the entry. */
 void
-gdm_set_value_string (const gchar *key,
-                      const gchar *value_in)
+gdm_daemon_config_set_value_string (const gchar *keystring,
+				    const gchar *value_in)
 {
-   _gdm_set_value_string (key, value_in, TRUE);
-}
-
-static void
-_gdm_set_value_bool (const gchar *key,
-                     gboolean value,
-                     gboolean doing_update)
-{
-   gboolean *setting     = gdm_config_hash_lookup (val_hash, key);
-   gboolean setting_copy = *setting;
-   gchar *temp_string;
-
-   if (setting == NULL) {
-      if (value)
-         gdm_error ("Failure setting key %s to true", key);
-      else
-         gdm_error ("Failure setting key %s to false", key);
-      return;
-   }
-
-   /* Password Required */
-   if (is_key (key, GDM_KEY_PASSWORD_REQUIRED)) {
-      temp_string = gdm_read_default ("PASSREQ=");
-      if (temp_string == NULL)
-         *setting = value;
-      else if (g_ascii_strcasecmp (temp_string, "YES") == 0)
-         *setting = TRUE;
-      else
-         *setting = FALSE;
-      g_free (temp_string);
-
-   /* Allow root login */
-   } else if (is_key (key, GDM_KEY_ALLOW_REMOTE_ROOT)) {
-      temp_string = gdm_read_default ("CONSOLE=");
-
-      if (temp_string == NULL)
-         *setting = value;
-      else if (g_ascii_strcasecmp (temp_string, "/dev/console") != 0)
-         *setting = TRUE;
-      else
-         *setting = FALSE;
-      g_free (temp_string);
-
-   /* XDMCP */
-#ifndef HAVE_LIBXDMCP
-   } else if (is_key (key, GDM_KEY_XDMCP)) {
-      if (value) {
-         gdm_info (_("%s: XDMCP was enabled while there is no XDMCP support; turning it off"), "gdm_config_parse");
-      }
-      *setting = FALSE;
-#endif
-   } else {
-      *setting = value;
-   }
-
-   /* Handle update */
-   if (doing_update == TRUE && *setting != setting_copy) {
-     if (is_key (key, GDM_KEY_ALLOW_ROOT))
-        notify_displays_int (GDM_NOTIFY_ALLOW_ROOT, *setting);
-     else if (is_key (key, GDM_KEY_ALLOW_REMOTE_ROOT))
-        notify_displays_int (GDM_NOTIFY_ALLOW_REMOTE_ROOT, *setting);
-     else if (is_key (key, GDM_KEY_ALLOW_REMOTE_AUTOLOGIN))
-        notify_displays_int (GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN, *setting);
-     else if (is_key (key, GDM_KEY_SYSTEM_MENU))
-        notify_displays_int (GDM_NOTIFY_SYSTEM_MENU, *setting);
-     else if (is_key (key, GDM_KEY_CONFIG_AVAILABLE))
-        notify_displays_int (GDM_NOTIFY_CONFIG_AVAILABLE, *setting);
-     else if (is_key (key, GDM_KEY_CHOOSER_BUTTON))
-        notify_displays_int (GDM_NOTIFY_CHOOSER_BUTTON, *setting); 
-     else if (is_key (key, GDM_KEY_DISALLOW_TCP))
-        notify_displays_int (GDM_NOTIFY_DISALLOW_TCP, *setting);
-     else if (is_key (key, GDM_KEY_ADD_GTK_MODULES))
-        notify_displays_int (GDM_NOTIFY_ADD_GTK_MODULES, *setting);
-     else if (is_key (key, GDM_KEY_TIMED_LOGIN_ENABLE))
-        notify_displays_int (GDM_NOTIFY_TIMED_LOGIN_ENABLE, *setting);
-   }
-
-   if (*setting)
-      gdm_debug ("set config key %s to boolean true", key);
-   else
-      gdm_debug ("set config key %s to boolean false", key);
+	char           *group;
+	char           *key;
+	gboolean        res;
+	GdmConfigValue *value;
+
+	res = gdm_common_config_parse_key_string (keystring, &group, &key, NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		return;
+	}
+
+	value = gdm_config_value_new (GDM_CONFIG_VALUE_STRING);
+	gdm_config_value_set_string (value, value_in);
+
+	res = gdm_config_set_value (daemon_config, group, key, value);
+
+	gdm_config_value_free (value);
+	g_free (group);
+	g_free (key);
 }
 
 void
-gdm_set_value_bool (const gchar *key,
-                    gboolean value)
+gdm_daemon_config_set_value_bool (const gchar *keystring,
+				  gboolean     value_in)
 {
-   _gdm_set_value_bool (key, value, TRUE);
-}
-
-static void
-_gdm_set_value_int (const gchar *key,
-                    gint value,
-                    gboolean doing_update)
-{
-   gint *setting     = gdm_config_hash_lookup (val_hash, key);
-   gint setting_copy = *setting;
-
-   if (setting == NULL) {
-      gdm_error ("Failure setting key %s to %d", key, value);
-      return;
-   }
-
-   if (is_key (key, GDM_KEY_MAX_INDIRECT) ||
-       is_key (key, GDM_KEY_XINERAMA_SCREEN)) {
-      if (value < 0)
-         *setting = 0;
-      else
-         *setting = value;
-   } else if (is_key (key, GDM_KEY_TIMED_LOGIN_DELAY)) {
-      if (value < 5) {
-         gdm_info (_("%s: TimedLoginDelay is less than 5, defaulting to 5."), "gdm_config_parse");
-         *setting = 5;
-      } else
-         *setting = value;
-   } else if (is_key (key, GDM_KEY_MAX_ICON_WIDTH) ||
-              is_key (key, GDM_KEY_MAX_ICON_HEIGHT)) {
-      if (value < 0)
-         *setting = 128;
-      else
-         *setting = value;
-   } else if (is_key (key, GDM_KEY_SCAN_TIME)) {
-      if (value < 1)
-         *setting = 1;
-      else
-         *setting = value;
-   }
- else {
-      *setting = value;
-   }
- 
-   /* Handle update */
-   if (doing_update == TRUE && *setting != setting_copy) {
-      if (is_key (key, GDM_KEY_RETRY_DELAY))
-         notify_displays_int (GDM_NOTIFY_RETRY_DELAY, *setting);
-      else if (is_key (key, GDM_KEY_TIMED_LOGIN_DELAY))
-         notify_displays_int (GDM_NOTIFY_TIMED_LOGIN_DELAY, *setting);
-   }
-
-   gdm_debug ("set config key %s to integer %d", key, *setting);
+	char           *group;
+	char           *key;
+	gboolean        res;
+	GdmConfigValue *value;
+
+	res = gdm_common_config_parse_key_string (keystring, &group, &key, NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		return;
+	}
+
+	value = gdm_config_value_new (GDM_CONFIG_VALUE_BOOL);
+	gdm_config_value_set_bool (value, value_in);
+
+	res = gdm_config_set_value (daemon_config, group, key, value);
+
+	gdm_config_value_free (value);
+	g_free (group);
+	g_free (key);
 }
 
 void
-gdm_set_value_int (const gchar *key,
-                   gint value)
+gdm_daemon_config_set_value_int (const gchar *keystring,
+				 gint         value_in)
 {
-   _gdm_set_value_int (key, value, TRUE);
-}
-
-
-
-/**
- * gdm_set_value
- *
- * This functon is used to set the config values in the hash.  This is called
- * at initial config load time or when gdm_update_config is called to reload
- * them.   It adds translated strings to the hash with their proper keys
- * (greeter/Welcome[cs] for example).
- */
-static gboolean
-gdm_set_value (GKeyFile      *config,
-               GdmConfigType *type,
-               const gchar   *fullkey,
-               gboolean       doing_update)
-{
-   gchar * realkey;
-   gchar *value;
-
-   realkey = gdm_config_hash_lookup (realkey_hash, fullkey);
-
-   if (realkey == NULL) {
-      return FALSE;
-   }
-
-   if (*type == CONFIG_BOOL) {
-      gboolean value;
-      gdm_common_config_get_boolean (config, realkey, &value, NULL);
-      _gdm_set_value_bool (fullkey, value, doing_update);
-      return TRUE;
-   } else if (*type == CONFIG_INT) {
-      gint value;
-      gdm_common_config_get_int (config, realkey, &value, NULL);
-      _gdm_set_value_int (fullkey, value, doing_update);
-      return TRUE;
-   } else if (*type == CONFIG_STRING) {
-
-      /* Process translated strings */
-      if (is_key (fullkey, GDM_KEY_WELCOME) ||
-          is_key (fullkey, GDM_KEY_REMOTE_WELCOME)) {
-         gchar **keys;
-         gsize   length;
-         gchar  *prefix, *basekey;
-         int     i;
-
-         keys = g_key_file_get_keys (config, "greeter", &length, NULL);
-
-         if (is_key (fullkey, GDM_KEY_WELCOME)) {
-            basekey = g_strdup ("Welcome");
-            prefix  = g_strdup ("Welcome[");
-         } else {
-            basekey = g_strdup ("RemoteWelcome");
-            prefix  = g_strdup ("RemoteWelcome[");
-         }
-
-          /*
-           * Loop over translated keys and put all values into the hash
-           * Probably should loop through the hashs and delete any old values,
-           * but this just means that if a translation is deleted from the
-           * config, GDM won't forget about it until restart.  I don't think
-           * this will happen, or be a real problem if it does.
-           */
-         for (i = 0; i < length; i++) {
-            gchar *key;
+	char           *group;
+	char           *key;
+	gboolean        res;
+	GdmConfigValue *value;
 
-            key = keys[i];
+	res = gdm_common_config_parse_key_string (keystring, &group, &key, NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		return;
+	}
 
-            if (g_str_has_prefix (key, prefix) &&
-                g_str_has_suffix (key, "]")) {
-               gchar *transkey, *transvalue;
+	value = gdm_config_value_new (GDM_CONFIG_VALUE_INT);
+	gdm_config_value_set_int (value, value_in);
 
-               if (translated_hash == NULL)
-                  translated_hash = g_hash_table_new (g_str_hash, g_str_equal);
+	res = gdm_config_set_value (daemon_config, group, key, value);
 
-               transkey = g_strdup_printf ("greeter/%s", key);
-               gdm_common_config_get_string (config, transkey, &transvalue, NULL);
-
-               g_hash_table_remove (translated_hash, transkey);
-
-               /*
-                * Store translated values in a separate hash.  Note that we load
-                * the initial values via a g_hash_table_foreach function, so if
-                * we add these to the same hash, we would end up loading these
-                * values in again a second time.
-                */
-               g_hash_table_insert (translated_hash, transkey, transvalue);
-            }
-         }
-
-         g_strfreev (keys);
-         g_free (basekey);
-         g_free (prefix);
-      }
-
-      /* Handle non-translated strings as normal */
-      gdm_common_config_get_string (config, realkey, &value, NULL);
-      _gdm_set_value_string (fullkey, value, doing_update);
-      return TRUE;
-   }
-
-   return FALSE;
+	gdm_config_value_free (value);
+	g_free (group);
+	g_free (key);
 }
 
 /**
- * gdm_find_xserver
+ * gdm_daemon_config_find_xserver
  *
  * Return an xserver with a given ID, or NULL if not found.
  */
 GdmXserver *
-gdm_find_xserver (const gchar *id)
+gdm_daemon_config_find_xserver (const gchar *id)
 {
-   GSList *li;
+	GSList *li;
+
+	if (xservers == NULL)
+		return NULL;
 
-   if (xservers == NULL)
-      return NULL;
+	if (id == NULL)
+		return xservers->data;
 
-   if (id == NULL)
-      return xservers->data;
+	for (li = xservers; li != NULL; li = li->next) {
+		GdmXserver *svr = li->data;
+		if (strcmp (ve_sure_string (svr->id), ve_sure_string (id)) == 0)
+			return svr;
+	}
 
-   for (li = xservers; li != NULL; li = li->next) {
-      GdmXserver *svr = li->data;
-      if (strcmp (ve_sure_string (svr->id), ve_sure_string (id)) == 0)
-         return svr;
-   }
-   return NULL;
+	return NULL;
 }
 
 /**
- * gdm_get_xservers
+ * gdm_daemon_config_get_xservers
  *
  * Prepare a string to be returned for the GET_SERVER_LIST
  * sockets command.
  */
 gchar *
-gdm_get_xservers (void)
+gdm_daemon_config_get_xservers (void)
 {
-   GSList *li;
-   gchar *retval = NULL;
+	GSList *li;
+	gchar *retval = NULL;
 
-   if (xservers == NULL)
-      return NULL;
+	if (xservers == NULL)
+		return NULL;
 
-   for (li = xservers; li != NULL; li = li->next) {
-      GdmXserver *svr = li->data;
-      if (retval != NULL)
-         retval = g_strconcat (retval, ";", svr->id, NULL);
-      else
-         retval = g_strdup (svr->id);
-   }
+	for (li = xservers; li != NULL; li = li->next) {
+		GdmXserver *svr = li->data;
+		if (retval != NULL)
+			retval = g_strconcat (retval, ";", svr->id, NULL);
+		else
+			retval = g_strdup (svr->id);
+	}
 
-   return retval;
+	return retval;
 }
 
 /* PRIO_MIN and PRIO_MAX are not defined on Solaris, but are -20 and 20 */
@@ -1618,128 +829,208 @@ gdm_get_xservers (void)
 #endif
 
 /**
- * gdm_load_xservers
+ * gdm_daemon_config_load_xserver
  *
  * Load [server-foo] sections from a configuration file.
  */
 static void
-gdm_load_xservers (GKeyFile *config)
+gdm_daemon_config_load_xserver (GdmConfig  *config,
+				const char *key,
+				const char *name)
+{
+	GdmXserver     *svr;
+	int             n;
+	char           *group;
+	gboolean        res;
+	GdmConfigValue *value;
+
+	/*
+	 * See if we already loaded a server with this id, skip if
+	 * one already exists.
+	 */
+	if (gdm_daemon_config_find_xserver (name) != NULL) {
+		return;
+	}
+
+	svr = g_new0 (GdmXserver, 1);
+	svr->id = g_strdup (name);
+
+	if (isdigit (*key)) {
+		svr->number = atoi (key);
+	}
+
+	group = g_strdup_printf ("server-%s", name);
+
+	/* string */
+	res = gdm_config_get_value (config, group, "name", &value);
+	if (res) {
+		svr->name = g_strdup (gdm_config_value_get_string (value));
+	}
+	res = gdm_config_get_value (config, group, "command", &value);
+	if (res) {
+		svr->command = g_strdup (gdm_config_value_get_string (value));
+	}
+
+	gdm_debug ("Adding new server id=%s name=%s command=%s", name, svr->name, svr->command);
+
+
+	/* bool */
+	res = gdm_config_get_value (config, group, "flexible", &value);
+	if (res) {
+		svr->flexible = gdm_config_value_get_bool (value);
+	}
+	res = gdm_config_get_value (config, group, "choosable", &value);
+	if (res) {
+		svr->choosable = gdm_config_value_get_bool (value);
+	}
+	res = gdm_config_get_value (config, group, "handled", &value);
+	if (res) {
+		svr->handled = gdm_config_value_get_bool (value);
+	}
+	res = gdm_config_get_value (config, group, "chooser", &value);
+	if (res) {
+		svr->chooser = gdm_config_value_get_bool (value);
+	}
+
+	/* int */
+	res = gdm_config_get_value (config, group, "priority", &value);
+	if (res) {
+		svr->priority = gdm_config_value_get_int (value);
+	}
+
+	/* do some bounds checking */
+	n = svr->priority;
+	if (n < PRIO_MIN)
+		n = PRIO_MIN;
+	else if (n > PRIO_MAX)
+		n = PRIO_MAX;
+
+	if (n != svr->priority) {
+		gdm_error (_("%s: Priority out of bounds; changed to %d"),
+			   "gdm_config_parse", n);
+		svr->priority = n;
+	}
+
+	if (ve_string_empty (svr->command)) {
+		gdm_error (_("%s: Empty server command; "
+			     "using standard command."), "gdm_config_parse");
+		g_free (svr->command);
+		svr->command = g_strdup (X_SERVER);
+	}
+
+	xservers = g_slist_append (xservers, svr);
+}
+
+static void
+gdm_daemon_config_unload_xservers (GdmConfig *config)
 {
-   int i;
-   gsize length;
-   char **groups;
-
-   /* Find server definitions */
-   groups = g_key_file_get_groups (config, &length);
-
-   for (i = 0; i < length; i++) {
-      gchar *id;
-      const char *sec = groups [i];
-
-      if (strncmp (sec, "server-", strlen ("server-")) != 0) {
-         continue;
-      }
-
-      id = g_strdup (sec + strlen ("server-"));
-
-      /*
-       * See if we already loaded a server with this id, skip if
-       * one already exists.
-       */
-      if (gdm_find_xserver (id) != NULL) {
-         g_free (id);
-      } else {
-         GdmXserver *svr = g_new0 (GdmXserver, 1);
-         gchar buf[256];
-         int n;
-
-         svr->id = id;
-
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_NAME, sec);
-         gdm_common_config_get_string (config, buf, &svr->name, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_COMMAND, sec);
-         gdm_common_config_get_string (config, buf, &svr->command, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_FLEXIBLE, sec);
-         gdm_common_config_get_boolean (config, buf, &svr->flexible, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_CHOOSABLE, sec);
-         gdm_common_config_get_boolean (config, buf, &svr->choosable, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_HANDLED, sec);
-         gdm_common_config_get_boolean (config, buf, &svr->handled, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_CHOOSER, sec);
-         gdm_common_config_get_boolean (config, buf, &svr->chooser, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_PRIORITY, sec);
-         gdm_common_config_get_int (config, buf, &svr->priority, NULL);
-
-         /* do some bounds checking */
-         n = svr->priority;
-         if (n < PRIO_MIN)
-            n = PRIO_MIN;
-         else if (n > PRIO_MAX)
-            n = PRIO_MAX;
-         if (n != svr->priority) {
-            gdm_error (_("%s: Priority out of bounds; changed to %d"),
-                       "gdm_config_parse", n);
-            svr->priority = n;
-         }
-
-         if (ve_string_empty (svr->command)) {
-            gdm_error (_("%s: Empty server command; "
-                         "using standard command."), "gdm_config_parse");
-            g_free (svr->command);
-            svr->command = g_strdup (GdmStandardXserver);
-         }
-
-         xservers = g_slist_append (xservers, svr);
-      }
-   }
+	GSList *xli;
 
-   g_strfreev (groups);
+	/* Free list if already loaded */
+	for (xli = xservers; xli != NULL; xli = xli->next) {
+		GdmXserver *xsvr = xli->data;
+
+		g_free (xsvr->id);
+		g_free (xsvr->name);
+		g_free (xsvr->command);
+	}
+
+	if (xservers != NULL) {
+		g_slist_free (xservers);
+		xservers = NULL;
+	}
+}
+
+static void
+gdm_daemon_config_ensure_one_xserver (GdmConfig *config)
+{
+	/* If no "Standard" server was created, then add it */
+	if (xservers == NULL || gdm_daemon_config_find_xserver (GDM_STANDARD) == NULL) {
+		GdmXserver *svr = g_new0 (GdmXserver, 1);
+
+		svr->id        = g_strdup (GDM_STANDARD);
+		svr->name      = g_strdup ("Standard server");
+		svr->command   = g_strdup (X_SERVER);
+		svr->flexible  = TRUE;
+		svr->choosable = TRUE;
+		svr->handled   = TRUE;
+		svr->priority  = 0;
+
+		xservers       = g_slist_append (xservers, svr);
+	}
 }
 
-/**
- * gdm_update_xservers
- *
- * Reload [server-foo] sections from the configuration files.
- */
 static void
-gdm_update_xservers (GKeyFile *cfg,
-                     GKeyFile *custom_cfg)
+load_xservers_group (GdmConfig *config)
 {
-   GSList *xli;
+        char     **keys;
+        gsize      len;
+        int        i;
+
+        keys = gdm_config_get_keys_for_group (config, GDM_CONFIG_GROUP_SERVERS, &len, NULL);
+
+        /* now construct entries for these groups */
+        for (i = 0; i < len; i++) {
+                GdmConfigEntry  entry;
+                GdmConfigValue *value;
+                char           *new_group;
+                gboolean        res;
+                int             j;
+		const char     *name;
+
+                entry.group = GDM_CONFIG_GROUP_SERVERS;
+                entry.key = keys[i];
+                entry.type = GDM_CONFIG_VALUE_STRING;
+                entry.default_value = NULL;
+                entry.id = GDM_CONFIG_INVALID_ID;
+
+                gdm_config_add_entry (config, &entry);
+                gdm_config_process_entry (config, &entry, NULL);
+
+                res = gdm_config_get_value (config, entry.group, entry.key, &value);
+                if (! res) {
+                        continue;
+                }
+
+		name = gdm_config_value_get_string (value);
+		if (name == NULL || name[0] == '\0') {
+			gdm_config_value_free (value);
+			continue;
+		}
+
+		/* skip servers marked as inactive */
+		if (g_ascii_strcasecmp (name, "inactive") == 0) {
+			gdm_config_value_free (value);
+			continue;
+		}
+
+                new_group = g_strdup_printf ("server-%s", name);
+                for (j = 0; j < G_N_ELEMENTS (gdm_daemon_server_config_entries); j++) {
+                        GdmConfigEntry *srv_entry;
+                        if (gdm_daemon_server_config_entries[j].key == NULL) {
+                                continue;
+                        }
+                        srv_entry = gdm_config_entry_copy (&gdm_daemon_server_config_entries[j]);
+                        g_free (srv_entry->group);
+                        srv_entry->group = g_strdup (new_group);
+                        gdm_config_process_entry (config, srv_entry, NULL);
+                        gdm_config_entry_free (srv_entry);
+                }
+		g_free (new_group);
 
-   /* Free list if already loaded */
-   if (xservers != NULL) {
-      for (xli = xservers; xli != NULL; xli = xli->next) {
-         GdmXserver *xsvr = xli->data;
-
-         g_free (xsvr->id);
-         g_free (xsvr->name);
-         g_free (xsvr->command);
-      }
-      g_slist_free (xservers);
-      xservers = NULL;
-   }
-
-   /* Reload first from custom_cfg then from cfg. */
-   if (custom_cfg != NULL)
-      gdm_load_xservers (custom_cfg);
-
-   if (cfg != NULL)
-      gdm_load_xservers (cfg);
-
-   /* If no "Standard" server was created, then add it */
-   if (xservers == NULL || gdm_find_xserver (GDM_STANDARD) == NULL) {
-      GdmXserver *svr = g_new0 (GdmXserver, 1);
-
-      svr->id        = g_strdup (GDM_STANDARD);
-      svr->name      = g_strdup ("Standard server");
-      svr->command   = g_strdup (GdmStandardXserver);
-      svr->flexible  = TRUE;
-      svr->choosable = TRUE;
-      svr->handled   = TRUE;
-      svr->priority  = 0;
-      xservers       = g_slist_append (xservers, svr);
-   }
+		/* now we can add this server */
+		gdm_daemon_config_load_xserver (config, entry.key, gdm_config_value_get_string (value));
+
+                gdm_config_value_free (value);
+        }
+}
+
+static void
+gdm_daemon_config_load_xservers (GdmConfig *config)
+{
+	gdm_daemon_config_unload_xservers (config);
+	load_xservers_group (config);
+	gdm_daemon_config_ensure_one_xserver (config);
 }
 
 /**
@@ -1758,122 +1049,72 @@ gdm_update_xservers (GKeyFile *cfg,
  * functions and in the gdm_slave_handle_notify function in slave.c.
  */
 gboolean
-gdm_update_config (const gchar *key)
+gdm_daemon_config_update_key (const char *keystring)
 {
-   GdmConfigType *type;
-   struct stat statbuf, custom_statbuf;
-   GKeyFile *cfg;
-   GKeyFile *custom_cfg;
-   gboolean rc;
-
-   rc = FALSE;
-   cfg = NULL;
-   custom_cfg = NULL;
-
-   /*
-    * Do not allow these keys to be updated, since GDM would need
-    * additional work, or at least heavy testing, to make these keys
-    * flexible enough to be changed at runtime.
-    */
-   if (is_key (key, GDM_KEY_PID_FILE) ||
-       is_key (key, GDM_KEY_CONSOLE_NOTIFY) ||
-       is_key (key, GDM_KEY_USER) ||
-       is_key (key, GDM_KEY_GROUP) ||
-       is_key (key, GDM_KEY_LOG_DIR) ||
-       is_key (key, GDM_KEY_SERV_AUTHDIR) ||
-       is_key (key, GDM_KEY_USER_AUTHDIR) ||
-       is_key (key, GDM_KEY_USER_AUTHFILE) ||
-       is_key (key, GDM_KEY_USER_AUTHDIR_FALLBACK)) {
-      return FALSE;
-   }
-
-   /* See if custom file is now there */
-   if (custom_config_file == NULL) {
-      custom_cfg = gdm_get_custom_config ();
-   }
-
-   /* Don't bother re-reading configuration if files have not changed */
-   VE_IGNORE_EINTR (g_stat (config_file, &statbuf));
-   VE_IGNORE_EINTR (g_stat (custom_config_file, &custom_statbuf));
-
-  /*
-   * Do not reset mtime to the latest values since there is no
-   * guarantee that only one key was modified since last write.
-   * This check simply avoids re-reading the files if neither
-   * has changed since GDM was started.
-   */
-   if (config_file_mtime        == statbuf.st_mtime &&
-       custom_config_file_mtime == custom_statbuf.st_mtime) {
-      rc = TRUE;
-      goto out;
-   }
-
-   /* Shortcut for updating all XDMCP parameters */
-   if (is_key (key, "xdmcp/PARAMETERS")) {
-      gdm_update_config (GDM_KEY_DISPLAYS_PER_HOST);
-      gdm_update_config (GDM_KEY_MAX_PENDING);
-      gdm_update_config (GDM_KEY_MAX_WAIT);
-      gdm_update_config (GDM_KEY_MAX_SESSIONS);
-      gdm_update_config (GDM_KEY_INDIRECT);
-      gdm_update_config (GDM_KEY_MAX_INDIRECT);
-      gdm_update_config (GDM_KEY_MAX_WAIT_INDIRECT);
-      gdm_update_config (GDM_KEY_PING_INTERVAL);
-      rc = TRUE;
-      goto out;
-   }
-
-   if (custom_config_file != NULL) {
-      custom_cfg = gdm_common_config_load (custom_config_file, NULL);
-   }
-
-   if (is_key (key, "xservers/PARAMETERS")) {
-      cfg = gdm_common_config_load (config_file, NULL);
-
-      gdm_update_xservers (cfg, custom_cfg);
-
-      rc = TRUE;
-      goto out;
-   }
-
-   type = gdm_config_hash_lookup (type_hash, key);
-   if (type == NULL)
-      return FALSE;
-
-   /* First check the custom file */
-   if (custom_cfg != NULL) {
-      char *config_group;
-      char *config_key;
-      gboolean has_key;
-
-      config_group = config_key = NULL;
-      if (! gdm_common_config_parse_key_string (key, &config_group, &config_key, NULL)) {
-         rc = FALSE;
-         goto out;
-      }
-
-      has_key = g_key_file_has_key (custom_cfg, config_group, config_key, NULL);
-      g_free (config_group);
-      g_free (config_key);
-
-      if (has_key) {
-         rc = gdm_set_value (custom_cfg, type, key, TRUE);
-         goto out;
-      }
-   }
+	gboolean              rc;
+	gboolean              res;
+	char                 *group;
+	char                 *key;
+	const GdmConfigEntry *entry;
+
+	rc = FALSE;
+
+	/*
+	 * Do not allow these keys to be updated, since GDM would need
+	 * additional work, or at least heavy testing, to make these keys
+	 * flexible enough to be changed at runtime.
+	 */
+	if (is_key (keystring, GDM_KEY_PID_FILE) ||
+	    is_key (keystring, GDM_KEY_CONSOLE_NOTIFY) ||
+	    is_key (keystring, GDM_KEY_USER) ||
+	    is_key (keystring, GDM_KEY_GROUP) ||
+	    is_key (keystring, GDM_KEY_LOG_DIR) ||
+	    is_key (keystring, GDM_KEY_SERV_AUTHDIR) ||
+	    is_key (keystring, GDM_KEY_USER_AUTHDIR) ||
+	    is_key (keystring, GDM_KEY_USER_AUTHFILE) ||
+	    is_key (keystring, GDM_KEY_USER_AUTHDIR_FALLBACK)) {
+		return FALSE;
+	}
 
-   /* If not in the custom file, check main config file */
-   cfg = gdm_common_config_load (config_file, NULL);
+	/* reload backend files if necessary */
+	gdm_config_load (daemon_config, NULL);
 
-   rc = gdm_set_value (cfg, type, key, TRUE);
+	/* Shortcut for updating all XDMCP parameters */
+	if (is_key (keystring, "xdmcp/PARAMETERS")) {
+		gdm_daemon_config_update_key (GDM_KEY_DISPLAYS_PER_HOST);
+		gdm_daemon_config_update_key (GDM_KEY_MAX_PENDING);
+		gdm_daemon_config_update_key (GDM_KEY_MAX_WAIT);
+		gdm_daemon_config_update_key (GDM_KEY_MAX_SESSIONS);
+		gdm_daemon_config_update_key (GDM_KEY_INDIRECT);
+		gdm_daemon_config_update_key (GDM_KEY_MAX_INDIRECT);
+		gdm_daemon_config_update_key (GDM_KEY_MAX_WAIT_INDIRECT);
+		gdm_daemon_config_update_key (GDM_KEY_PING_INTERVAL);
+		rc = TRUE;
+		goto out;
+	}
+
+	/* find the entry for the key */
+
+	res = gdm_common_config_parse_key_string (keystring,
+						  &group,
+						  &key,
+						  NULL);
+	if (! res) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
+
+	entry = gdm_config_lookup_entry (daemon_config, group, key);
+	if (entry == NULL) {
+		gdm_error ("Request for invalid configuration key %s", keystring);
+		goto out;
+	}
 
- out:
-   if (cfg != NULL)
-      g_key_file_free (cfg);
+	gdm_config_process_entry (daemon_config, entry, NULL);
 
-   if (custom_cfg != NULL)
-      g_key_file_free (custom_cfg);
+ out:
 
-   return rc;
+	return rc;
 }
 
 /**
@@ -1885,538 +1126,920 @@ gdm_update_config (const gchar *key)
 static void
 check_logdir (void)
 {
-        struct stat statbuf;
-        int r;
-
-        VE_IGNORE_EINTR (r = g_stat (GdmLogDir, &statbuf));
-        if (r < 0 ||
-            ! S_ISDIR (statbuf.st_mode))  {
-                gdm_error (_("%s: Logdir %s does not exist or isn't a directory.  Using ServAuthDir %s."), "gdm_config_parse",
-                           GdmLogDir, GdmServAuthDir);
-                g_free (GdmLogDir);
-                GdmLogDir = g_strdup (GdmServAuthDir);
+        struct stat     statbuf;
+        int             r;
+	char           *log_path;
+	const char     *auth_path;
+	GdmConfigValue *value;
+
+	log_path = NULL;
+	auth_path = NULL;
+
+	gdm_config_get_string_for_id (daemon_config, GDM_ID_LOG_DIR, &log_path);
+
+	gdm_config_get_value_for_id (daemon_config, GDM_ID_SERV_AUTHDIR, &value);
+	auth_path = gdm_config_value_get_string (value);
+
+        VE_IGNORE_EINTR (r = g_stat (log_path, &statbuf));
+        if (r < 0 || ! S_ISDIR (statbuf.st_mode))  {
+                gdm_error (_("%s: Logdir %s does not exist or isn't a directory.  Using ServAuthDir %s."),
+			   "gdm_config_parse",
+                           log_path,
+			   auth_path);
+		gdm_config_set_value_for_id (daemon_config, GDM_ID_LOG_DIR, value);
         }
+
+	g_free (log_path);
+	gdm_config_value_free (value);
 }
 
 static void
-check_servauthdir (struct stat *statbuf)
+check_servauthdir (const char  *auth_path,
+		   struct stat *statbuf)
 {
-    int r;
+	int        r;
+	gboolean   console_notify;
 
-    /* Enter paranoia mode */
-    VE_IGNORE_EINTR (r = g_stat (GdmServAuthDir, statbuf));
-    if G_UNLIKELY (r < 0) {
-            if (GdmConsoleNotify) {
-               gchar *s = g_strdup_printf
-                       (C_(N_("Server Authorization directory "
-                              "(daemon/ServAuthDir) is set to %s "
-                              "but this does not exist. Please "
-                              "correct GDM configuration and "
-                              "restart GDM.")), GdmServAuthDir);
-
-               gdm_text_message_dialog (s);
-               g_free (s);
-            }
-
-            GdmPidFile = NULL;
-            gdm_fail (_("%s: Authdir %s does not exist. Aborting."), "gdm_config_parse", GdmServAuthDir);
-    }
-
-    if G_UNLIKELY (! S_ISDIR (statbuf->st_mode)) {
-            if (GdmConsoleNotify) {
-               gchar *s = g_strdup_printf
-                       (C_(N_("Server Authorization directory "
-                              "(daemon/ServAuthDir) is set to %s "
-                              "but this is not a directory. Please "
-                              "correct GDM configuration and "
-                              "restart GDM.")), GdmServAuthDir);
-
-                gdm_text_message_dialog (s);
-                g_free (s);
-            }
-
-            GdmPidFile = NULL;
-            gdm_fail (_("%s: Authdir %s is not a directory. Aborting."), "gdm_config_parse", GdmServAuthDir);
-    }
-}
-
-typedef struct _GdmConfigFiles {
-   GKeyFile *cfg;
-   GKeyFile *custom_cfg;
-} GdmConfigFiles;
+	console_notify = FALSE;
+	gdm_config_get_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, &console_notify);
+
+	/* Enter paranoia mode */
+	VE_IGNORE_EINTR (r = g_stat (auth_path, statbuf));
+	if G_UNLIKELY (r < 0) {
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("Server Authorization directory "
+							  "(daemon/ServAuthDir) is set to %s "
+							  "but this does not exist. Please "
+							  "correct GDM configuration and "
+							  "restart GDM.")),
+						    auth_path);
+
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
+
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: Authdir %s does not exist. Aborting."), "gdm_config_parse", auth_path);
+	}
+
+	if G_UNLIKELY (! S_ISDIR (statbuf->st_mode)) {
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("Server Authorization directory "
+							  "(daemon/ServAuthDir) is set to %s "
+							  "but this is not a directory. Please "
+							  "correct GDM configuration and "
+							  "restart GDM.")),
+						    auth_path);
+
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
+
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: Authdir %s is not a directory. Aborting."), "gdm_config_parse", auth_path);
+	}
+}
+
+static gboolean
+have_display_for_number (int number)
+{
+	GSList *l;
+
+	for (l = displays; l != NULL; l = l->next) {
+		GdmDisplay *disp = l->data;
+		if (disp->dispnum == number) {
+			return TRUE;
+		}
+	}
+
+	return FALSE;
+}
 
-/**
- * gdm_load_displays
- *
- * Load the displays section of the config file
- */
 static void
-gdm_load_displays (GKeyFile *cfg,
-                   char    **keys)
+gdm_daemon_config_load_displays (GdmConfig *config)
 {
-   GSList *li2;
-   int i;
+	GSList *l;
 
-   for (i = 0; keys[i] != NULL; i++) {
-      const gchar *key = keys[i];
+	for (l = xservers; l != NULL; l = l->next) {
+		GdmXserver *xserver;
+		GdmDisplay *disp;
+
+		xserver = l->data;
+
+		gdm_debug ("Loading display for key '%d'", xserver->number);
+
+		gdm_debug ("Got name for server: %s", xserver->id);
+		/* Do not add if already in the list */
+		if (have_display_for_number (xserver->number)) {
+			continue;
+		}
+
+		disp = gdm_server_alloc (xserver->number, xserver->id);
+		if (disp == NULL) {
+			continue;
+		}
+
+		displays = g_slist_insert_sorted (displays, disp, gdm_daemon_config_compare_displays);
+		if (xserver->number > high_display_num) {
+			high_display_num = xserver->number;
+		}
+	}
+}
+
+static gboolean
+validate_path (GdmConfig          *config,
+	       GdmConfigSourceType source,
+	       GdmConfigValue     *value)
+{
+	char    *str;
+
+	/* If the /etc/default has a PATH use that */
+	str = gdm_read_default ("PATH=");
+	if (str != NULL) {
+		gdm_config_value_set_string (value, str);
+		g_free (str);
+	}
 
-      gdm_debug ("Loading display for key '%s'", key);
-      if (isdigit (*key)) {
-         gchar *fullkey;
-         gchar *dispval;
-         int keynum = atoi (key);
-         gboolean skip_entry = FALSE;
-         GError *error;
-
-         fullkey = g_strdup_printf ("%s/%s", GDM_KEY_SECTION_SERVERS, key);
-         dispval = NULL;
-         error = NULL;
-         gdm_common_config_get_string (cfg, fullkey, &dispval, &error);
-         if (error != NULL) {
-            gdm_error ("Unable to get name for server '%s': %s", fullkey, error->message);
-         }
-         g_free (fullkey);
-
-         gdm_debug ("Got name for server: %s", dispval);
-         /* Do not add if already in the list */
-         for (li2 = displays; li2 != NULL; li2 = li2->next) {
-            GdmDisplay *disp = li2->data;
-            if (disp->dispnum == keynum) {
-               skip_entry = TRUE;
-               break;
-            }
-         }
-
-         /* Do not add if this display was marked as inactive already */
-         for (li2 = displays_inactive; li2 != NULL; li2 = li2->next) {
-            gchar *disp = li2->data;
-            if (atoi (disp) == keynum) {
-               skip_entry = TRUE;
-               break;
-            }
-         }
-
-         if (skip_entry == TRUE) {
-            g_free (dispval);
-            continue;
-         }
-
-         if (g_ascii_strcasecmp (ve_sure_string (dispval), "inactive") == 0) {
-            gdm_debug ("display %s is inactive", key);
-            displays_inactive = g_slist_append (displays_inactive, g_strdup (key));
-         } else {
-            GdmDisplay *disp = gdm_server_alloc (keynum, dispval);
-
-            if (disp == NULL)
-               continue;
-
-            displays = g_slist_insert_sorted (displays, disp, gdm_compare_displays);
-            if (keynum > high_display_num)
-               high_display_num = keynum;
-         }
-
-         g_free (dispval);
-
-      } else {
-        gdm_info (_("%s: Invalid server line in config file. Ignoring!"), "gdm_config_parse");
-      }
-   }
+	return TRUE;
+}
+
+static gboolean
+validate_root_path (GdmConfig          *config,
+		    GdmConfigSourceType source,
+		    GdmConfigValue     *value)
+{
+	char    *str;
+
+	/* If the /etc/default has a PATH use that */
+	str = gdm_read_default ("SUPATH=");
+	if (str != NULL) {
+		gdm_config_value_set_string (value, str);
+		g_free (str);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_base_xsession (GdmConfig          *config,
+			GdmConfigSourceType source,
+			GdmConfigValue     *value)
+{
+	const char *str;
+
+	str = gdm_config_value_get_string (value);
+	if (str == NULL || str[0] == '\0') {
+		char *path;
+		path = g_build_filename (GDMCONFDIR, "gdm", "Xsession", NULL);
+		gdm_info (_("%s: BaseXsession empty; using %s"), "gdm_config_parse", path);
+		gdm_config_value_set_string (value, path);
+		g_free (path);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_power_action (GdmConfig          *config,
+		       GdmConfigSourceType source,
+		       GdmConfigValue     *value)
+{
+	/* FIXME: should weed out the commands that don't work */
+
+	return TRUE;
+}
+
+static gboolean
+validate_standard_xserver (GdmConfig          *config,
+			   GdmConfigSourceType source,
+			   GdmConfigValue     *value)
+{
+	gboolean    res;
+	gboolean    is_ok;
+	const char *str;
+	char       *new;
+
+	is_ok = FALSE;
+	new = NULL;
+	str = gdm_config_value_get_string (value);
+
+	if (str != NULL) {
+		char **argv;
+
+		if (g_shell_parse_argv (str, NULL, &argv, NULL)) {
+			if (g_access (argv[0], X_OK) == 0) {
+				is_ok = TRUE;
+			}
+			g_strfreev (argv);
+		}
+	}
+
+	if G_UNLIKELY (! is_ok) {
+		gdm_info (_("%s: Standard X server not found; trying alternatives"), "gdm_config_parse");
+		if (g_access ("/usr/X11R6/bin/X", X_OK) == 0) {
+			new = g_strdup ("/usr/X11R6/bin/X");
+		} else if (g_access ("/opt/X11R6/bin/X", X_OK) == 0) {
+			new = g_strdup ("/opt/X11R6/bin/X");
+		} else if (g_access ("/usr/bin/X11/X", X_OK) == 0) {
+			new = g_strdup ("/usr/bin/X11/X");
+		}
+	}
+
+	if (new != NULL) {
+		gdm_config_value_set_string (value, new);
+		g_free (new);
+	}
+
+	res = TRUE;
+
+	return res;
+}
+
+static gboolean
+validate_graphical_theme_dir (GdmConfig          *config,
+			      GdmConfigSourceType source,
+			      GdmConfigValue     *value)
+{
+	const char *str;
+
+	str = gdm_config_value_get_string (value);
+
+	if (str == NULL || !g_file_test (str, G_FILE_TEST_IS_DIR)) {
+		gdm_config_value_set_string (value, GREETERTHEMEDIR);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_graphical_theme (GdmConfig          *config,
+			  GdmConfigSourceType source,
+			  GdmConfigValue     *value)
+{
+	const char *str;
+
+	str = gdm_config_value_get_string (value);
+
+	if (str == NULL || str[0] == '\0') {
+		gdm_config_value_set_string (value, "circles");
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_greeter (GdmConfig          *config,
+		  GdmConfigSourceType source,
+		  GdmConfigValue     *value)
+{
+	const char *str;
+
+	str = gdm_config_value_get_string (value);
+
+	if (str == NULL || str[0] == '\0') {
+		gdm_error (_("%s: No greeter specified."), "gdm_config_parse");
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_remote_greeter (GdmConfig          *config,
+			 GdmConfigSourceType source,
+			 GdmConfigValue     *value)
+{
+	const char *str;
+
+	str = gdm_config_value_get_string (value);
+
+	if (str == NULL || str[0] == '\0') {
+		gdm_error (_("%s: No remote greeter specified."), "gdm_config_parse");
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_session_desktop_dir (GdmConfig          *config,
+			      GdmConfigSourceType source,
+			      GdmConfigValue     *value)
+{
+	const char *str;
+
+	str = gdm_config_value_get_string (value);
+
+	if (str == NULL || str[0] == '\0') {
+		gdm_error (_("%s: No sessions directory specified."), "gdm_config_parse");
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_password_required (GdmConfig          *config,
+			    GdmConfigSourceType source,
+			    GdmConfigValue     *value)
+{
+	char *str;
+
+	str = gdm_read_default ("PASSREQ=");
+	if (str != NULL && str[0] == '\0') {
+		gboolean val;
+		val = (g_ascii_strcasecmp (str, "YES") == 0);
+		gdm_config_value_set_bool (value, val);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_allow_remote_root (GdmConfig          *config,
+			    GdmConfigSourceType source,
+			    GdmConfigValue     *value)
+{
+	char *str;
+
+	str = gdm_read_default ("CONSOLE=");
+	if (str != NULL && str[0] == '\0') {
+		gboolean val;
+		val = (g_ascii_strcasecmp (str, "/dev/console") != 0);
+		gdm_config_value_set_bool (value, val);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_xdmcp (GdmConfig          *config,
+		GdmConfigSourceType source,
+		GdmConfigValue     *value)
+{
+
+#ifndef HAVE_LIBXDMCP
+	if (gdm_config_value_get_bool (value)) {
+		gdm_info (_("%s: XDMCP was enabled while there is no XDMCP support; turning it off"), "gdm_config_parse");
+		gdm_config_value_set_bool (value, FALSE);
+	}
+#endif
+
+	return TRUE;
+}
+
+static gboolean
+validate_at_least_int (GdmConfig          *config,
+		       GdmConfigSourceType source,
+		       GdmConfigValue     *value,
+		       int                 minval,
+		       int                 defval)
+{
+	if (gdm_config_value_get_int (value) < minval) {
+		gdm_config_value_set_int (value, defval);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+validate_cb (GdmConfig          *config,
+	     GdmConfigSourceType source,
+	     const char         *group,
+	     const char         *key,
+	     GdmConfigValue     *value,
+	     int                 id,
+	     gpointer            data)
+{
+	gboolean res;
+
+	res = TRUE;
+
+        switch (id) {
+        case GDM_ID_PATH:
+		res = validate_path (config, source, value);
+		break;
+        case GDM_ID_ROOT_PATH:
+		res = validate_root_path (config, source, value);
+		break;
+        case GDM_ID_BASE_XSESSION:
+		res = validate_base_xsession (config, source, value);
+		break;
+        case GDM_ID_HALT:
+        case GDM_ID_REBOOT:
+        case GDM_ID_SUSPEND:
+		res = validate_power_action (config, source, value);
+		break;
+        case GDM_ID_STANDARD_XSERVER:
+		res = validate_standard_xserver (config, source, value);
+		break;
+        case GDM_ID_GRAPHICAL_THEME_DIR:
+		res = validate_graphical_theme_dir (config, source, value);
+		break;
+        case GDM_ID_GRAPHICAL_THEME:
+		res = validate_graphical_theme (config, source, value);
+		break;
+        case GDM_ID_GREETER:
+		res = validate_greeter (config, source, value);
+		break;
+        case GDM_ID_REMOTE_GREETER:
+		res = validate_remote_greeter (config, source, value);
+		break;
+        case GDM_ID_SESSION_DESKTOP_DIR:
+		res = validate_session_desktop_dir (config, source, value);
+		break;
+        case GDM_ID_PASSWORD_REQUIRED:
+		res = validate_password_required (config, source, value);
+		break;
+        case GDM_ID_ALLOW_REMOTE_ROOT:
+		res = validate_allow_remote_root (config, source, value);
+		break;
+        case GDM_ID_XDMCP:
+		res = validate_xdmcp (config, source, value);
+		break;
+	case GDM_ID_MAX_INDIRECT:
+	case GDM_ID_XINERAMA_SCREEN:
+		res = validate_at_least_int (config, source, value, 0, 0);
+		break;
+	case GDM_ID_TIMED_LOGIN_DELAY:
+		res = validate_at_least_int (config, source, value, 5, 5);
+		break;
+	case GDM_ID_MAX_ICON_WIDTH:
+	case GDM_ID_MAX_ICON_HEIGHT:
+		res = validate_at_least_int (config, source, value, 0, 128);
+		break;
+	case GDM_ID_SCAN_TIME:
+		res = validate_at_least_int (config, source, value, 1, 1);
+		break;
+        case GDM_ID_NONE:
+        case GDM_CONFIG_INVALID_ID:
+		break;
+	default:
+		break;
+	}
+
+	return res;
+}
+
+static const char *
+source_to_name (GdmConfigSourceType source)
+{
+        const char *name;
+
+        switch (source) {
+        case GDM_CONFIG_SOURCE_DEFAULT:
+                name = "default";
+                break;
+        case GDM_CONFIG_SOURCE_MANDATORY:
+                name = "mandatory";
+                break;
+        case GDM_CONFIG_SOURCE_CUSTOM:
+                name = "custom";
+                break;
+        case GDM_CONFIG_SOURCE_BUILT_IN:
+                name = "built-in";
+                break;
+        case GDM_CONFIG_SOURCE_RUNTIME_USER:
+                name = "runtime-user";
+                break;
+        case GDM_CONFIG_SOURCE_INVALID:
+                name = "Invalid";
+                break;
+        default:
+                name = "Unknown";
+                break;
+        }
+
+        return name;
+}
+
+static gboolean
+notify_cb (GdmConfig          *config,
+	   GdmConfigSourceType source,
+	   const char         *group,
+	   const char         *key,
+	   GdmConfigValue     *value,
+	   int                 id,
+	   gpointer            data)
+{
+	char *valstr;
+
+        switch (id) {
+        case GDM_ID_GREETER:
+        case GDM_ID_REMOTE_GREETER:
+        case GDM_ID_SOUND_ON_LOGIN_FILE:
+        case GDM_ID_SOUND_ON_LOGIN_SUCCESS_FILE:
+        case GDM_ID_SOUND_ON_LOGIN_FAILURE_FILE:
+        case GDM_ID_GTK_MODULES_LIST:
+        case GDM_ID_TIMED_LOGIN:
+        case GDM_ID_ALLOW_ROOT:
+        case GDM_ID_ALLOW_REMOTE_ROOT:
+        case GDM_ID_ALLOW_REMOTE_AUTOLOGIN:
+        case GDM_ID_SYSTEM_MENU:
+        case GDM_ID_CONFIG_AVAILABLE:
+        case GDM_ID_CHOOSER_BUTTON:
+        case GDM_ID_DISALLOW_TCP:
+        case GDM_ID_ADD_GTK_MODULES:
+        case GDM_ID_TIMED_LOGIN_ENABLE:
+	case GDM_ID_RETRY_DELAY:
+	case GDM_ID_TIMED_LOGIN_DELAY:
+		notify_displays_value (config, group, key, value);
+		break;
+        case GDM_ID_NONE:
+        case GDM_CONFIG_INVALID_ID:
+		{
+			/* doesn't have an ID : match group/key */
+			if (group != NULL) {
+				if (strcmp (group, GDM_CONFIG_GROUP_SERVERS) == 0) {
+					/* FIXME: handle this? */
+				} else if (strcmp (group, GDM_CONFIG_GROUP_CUSTOM_CMD) == 0) {
+					notify_displays_value (config, group, key, value);
+				}
+			}
+		}
+                break;
+	default:
+		break;
+        }
+
+	valstr = gdm_config_value_to_string (value);
+	gdm_debug ("Got config %s/%s=%s <%s>\n",
+		   group,
+		   key,
+		   valstr,
+		   source_to_name (source));
+	g_free (valstr);
+
+        return TRUE;
 }
 
-/**
- * gdm_load_config_option
- *
- * Called by gdm_config_parse in a loop to set each key.
- */
 static void
-gdm_load_config_option (gpointer key_in, gpointer value_in, gpointer data)
+handle_no_displays (GdmConfig *config)
 {
-   gchar *key               = (gchar *)key_in;
-   GdmConfigType *type      = (GdmConfigType *)value_in;
-   GdmConfigFiles *cfgfiles = (GdmConfigFiles *)data;
-   gboolean custom_retval;
+	const char *server;
+	gboolean    console_notify;
 
-   if (type != NULL) {
-      /* First check the custom file */
-      if (cfgfiles->custom_cfg != NULL) {
-         gchar *config_group;
-         gchar *config_key;
-         gboolean has_key;
+	console_notify = FALSE;
+	gdm_config_get_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, &console_notify);
 
-         config_group = config_key = NULL;
-         if (! gdm_common_config_parse_key_string (key_in, &config_group, &config_key, NULL)) {
-            return;
-         }
+	/*
+	 * If we requested no static servers (there is no console),
+	 * then don't display errors in console messages
+	 */
+	if (no_console) {
+		gdm_fail (_("%s: XDMCP disabled and no static servers defined. Aborting!"), "gdm_config_parse");
+	}
+
+	server = X_SERVER;
+	if G_LIKELY (g_access (server, X_OK) == 0) {
+	} else if (g_access ("/usr/bin/X11/X", X_OK) == 0) {
+		server = "/usr/bin/X11/X";
+	} else if (g_access ("/usr/X11R6/bin/X", X_OK) == 0) {
+		server = "/usr/X11R6/bin/X";
+	} else if (g_access ("/opt/X11R6/bin/X", X_OK) == 0) {
+		server = "/opt/X11R6/bin/X";
+	}
+
+	/* yay, we can add a backup emergency server */
+	if (server != NULL) {
+		int num = gdm_get_free_display (0 /* start */, 0 /* server uid */);
+
+		gdm_error (_("%s: XDMCP disabled and no static servers defined. Adding %s on :%d to allow configuration!"),
+			   "gdm_config_parse", server, num);
+
+		gdm_emergency_server = TRUE;
+		displays = g_slist_append (displays, gdm_server_alloc (num, server));
+
+		/* ALWAYS run the greeter and don't log anyone in,
+		 * this is just an emergency session */
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_AUTOMATIC_LOGIN, NULL);
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_TIMED_LOGIN, NULL);
+
+	} else {
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("XDMCP is disabled and GDM "
+							  "cannot find any static server "
+							  "to start.  Aborting!  Please "
+							  "correct the configuration "
+							  "and restart GDM.")));
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
 
-         has_key = g_key_file_has_key (cfgfiles->custom_cfg, config_group, config_key, NULL);
-         g_free (config_group);
-         g_free (config_key);
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: XDMCP disabled and no static servers defined. Aborting!"), "gdm_config_parse");
+	}
+}
+
+static void
+gdm_daemon_change_user (GdmConfig *config,
+			uid_t     *uidp,
+			gid_t     *gidp)
+{
+	gboolean    console_notify;
+	char       *username;
+	char       *groupname;
+	uid_t       uid;
+	gid_t       gid;
+	struct passwd *pwent;
+	struct group  *grent;
+
+	console_notify = FALSE;
+	username = NULL;
+	groupname = NULL;
+	uid = 0;
+	gid = 0;
+
+	gdm_config_get_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, &console_notify);
+	gdm_config_get_string_for_id (daemon_config, GDM_ID_USER, &username);
+	gdm_config_get_string_for_id (daemon_config, GDM_ID_GROUP, &groupname);
+
+	/* Lookup user and groupid for the GDM user */
+	pwent = getpwnam (username);
+
+	/* Set uid and gid */
+	if G_UNLIKELY (pwent == NULL) {
+
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("The GDM user '%s' does not exist. "
+							  "Please correct GDM configuration "
+							  "and restart GDM.")),
+						    username);
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
+
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: Can't find the GDM user '%s'. Aborting!"), "gdm_config_parse", username);
+	} else {
+		uid = pwent->pw_uid;
+	}
+
+	if G_UNLIKELY (uid == 0) {
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("The GDM user is set to be root, but "
+							  "this is not allowed since it can "
+							  "pose a security risk.  Please "
+							  "correct GDM configuration and "
+							  "restart GDM.")));
+
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
+
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: The GDM user should not be root. Aborting!"), "gdm_config_parse");
+	}
+
+	grent = getgrnam (groupname);
+
+	if G_UNLIKELY (grent == NULL) {
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("The GDM group '%s' does not exist. "
+							  "Please correct GDM configuration "
+							  "and restart GDM.")),
+						    groupname);
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
+
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: Can't find the GDM group '%s'. Aborting!"), "gdm_config_parse", groupname);
+	} else  {
+		gid = grent->gr_gid;
+	}
+
+	if G_UNLIKELY (gid == 0) {
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("The GDM group is set to be root, but "
+							  "this is not allowed since it can "
+							  "pose a security risk. Please "
+							  "correct GDM configuration and "
+							  "restart GDM.")));
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
+
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: The GDM group should not be root. Aborting!"), "gdm_config_parse");
+	}
+
+	/* gid remains `gdm' */
+	NEVER_FAILS_root_set_euid_egid (uid, gid);
+
+	if (uidp != NULL) {
+		*uidp = uid;
+	}
+
+	if (gidp != NULL) {
+		*gidp = gid;
+	}
 
-         if (has_key) {
-            custom_retval = gdm_set_value (cfgfiles->custom_cfg, type, key, FALSE);
-            return;
-         }
-      }
+	g_free (username);
+	g_free (groupname);
+}
 
-      /* If not in the custom file, check main config file */
-      if (gdm_set_value (cfgfiles->cfg, type, key, FALSE))
-         return;
-   }
+static void
+gdm_daemon_check_permissions (GdmConfig *config,
+			      uid_t      uid,
+			      gid_t      gid)
+{
+	struct stat statbuf;
+	char       *auth_path;
+	gboolean    console_notify;
+
+	console_notify = FALSE;
+	gdm_config_get_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, &console_notify);
+	auth_path = NULL;
+	gdm_config_get_string_for_id (config, GDM_ID_LOG_DIR, &auth_path);
+
+	/* Enter paranoia mode */
+	check_servauthdir (auth_path, &statbuf);
+
+	NEVER_FAILS_root_set_euid_egid (0, 0);
+
+	/* Now set things up for us as  */
+	chown (auth_path, 0, gid);
+	g_chmod (auth_path, (S_IRWXU|S_IRWXG|S_ISVTX));
+
+	NEVER_FAILS_root_set_euid_egid (uid, gid);
+
+	/* Again paranoid */
+	check_servauthdir (auth_path, &statbuf);
+
+	if G_UNLIKELY (statbuf.st_uid != 0 || statbuf.st_gid != gid)  {
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("Server Authorization directory "
+							  "(daemon/ServAuthDir) is set to %s "
+							  "but is not owned by user %d and group "
+							  "%d. Please correct the ownership or "
+							  "GDM configuration and restart "
+							  "GDM.")),
+						    auth_path,
+						    (int)uid,
+						    (int)gid);
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
+
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: Authdir %s is not owned by user %d, group %d. Aborting."),
+			  "gdm_config_parse",
+			  auth_path,
+			  (int)uid,
+			  (int)gid);
+	}
+
+	if G_UNLIKELY (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX))  {
+		if (console_notify) {
+			gchar *s = g_strdup_printf (C_(N_("Server Authorization directory "
+							  "(daemon/ServAuthDir) is set to %s "
+							  "but has the wrong permissions: it "
+							  "should have permissions of %o. "
+							  "Please correct the permissions or "
+							  "the GDM configuration and "
+							  "restart GDM.")),
+						    auth_path,
+						    (S_IRWXU|S_IRWXG|S_ISVTX));
+			gdm_text_message_dialog (s);
+			g_free (s);
+		}
+
+		gdm_config_set_string_for_id (daemon_config, GDM_ID_PID_FILE, NULL);
+
+		gdm_fail (_("%s: Authdir %s has wrong permissions %o. Should be %o. Aborting."),
+			  "gdm_config_parse",
+			  auth_path,
+			  statbuf.st_mode,
+			  (S_IRWXU|S_IRWXG|S_ISVTX));
+	}
 
-   gdm_error ("Cannot set config option %s", key);
+	g_free (auth_path);
 }
 
 /**
- * gdm_config_parse
+ * gdm_daemon_config_parse
  *
  * Loads initial configuration settings.
  */
 void
-gdm_config_parse (void)
+gdm_daemon_config_parse (const char *config_file)
 {
-   GdmConfigFiles cfgfiles;
-   GKeyFile *cfg;
-   GKeyFile *custom_cfg;
-   struct passwd *pwent;
-   struct group *grent;
-   struct stat statbuf;
-   gchar *bin;
-
-   /* Init structures for configuration data */
-   gdm_config_init ();
-
-   displays          = NULL;
-   high_display_num  = 0;
-
-   /*
-    * It is okay if the custom_cfg file is missing, then just use
-    * main configuration file. However if main config file does 
-    * not exist we cannot continue and need to bail out.
-    */
-
-   cfg = gdm_get_default_config ();
-
-   if (cfg == NULL)
-	   gdm_fail (_("%s: Main config file (defaults.conf) is missing. Aborting!"), "gdm_config_parse");
-
-   custom_cfg = gdm_get_custom_config ();
-
-   cfgfiles.cfg = cfg;
-   cfgfiles.custom_cfg = custom_cfg;
-
-   /* Loop over all configuration options and load them */
-   g_hash_table_foreach (type_hash, gdm_load_config_option, &cfgfiles);
-
-   /* Load server-foo sections */
-   gdm_update_xservers (cfg, custom_cfg);
-
-   /* Only read the list if no_console is FALSE at this stage */
-   if (! no_console) {
-      char  **keys;
-      GError *error;
-      GSList *li2;
-      gsize   len;
-
-      /* Find static X server definitions */
-      if (custom_cfg != NULL) {
-         error = NULL;
-         keys = g_key_file_get_keys (custom_cfg, GDM_KEY_SECTION_SERVERS, &len, &error);
-         if (error != NULL) {
-            gdm_error ("Unable to load server list: %s", error->message);
-            g_error_free (error);
-         }
-         if (keys != NULL) {
-            gdm_load_displays (custom_cfg, keys);
-         }
-         g_strfreev (keys);
-      }
-
-      error = NULL;
-      keys = g_key_file_get_keys (cfg, GDM_KEY_SECTION_SERVERS, &len, &error);
-      if (error != NULL) {
-         gdm_error ("Unable to load server list: %s", error->message);
-         g_error_free (error);
-      }
-      if (keys != NULL) {
-         gdm_load_displays (cfg, keys);
-      }
-
-      g_strfreev (keys);
-
-      /* Free list of inactive, not needed anymore */
-      for (li2 = displays_inactive; li2 != NULL; li2 = li2->next) {
-         gchar *disp = li2->data;
-         g_free (disp);
-      }
-      g_slist_free (displays_inactive);
-   }
-
-   if G_UNLIKELY ((displays == NULL) && (! GdmXdmcp) && (!GdmDynamicXservers)) {
-      gchar *server = NULL;
-
-      /*
-       * If we requested no static servers (there is no console),
-       * then don't display errors in console messages
-       */
-      if (no_console) {
-         gdm_fail (_("%s: XDMCP disabled and no static servers defined. Aborting!"), "gdm_config_parse");
-      }
-
-      bin = ve_first_word (GdmStandardXserver);
-      if G_LIKELY (g_access (bin, X_OK) == 0) {
-         server = GdmStandardXserver;
-      } else if (g_access ("/usr/bin/X11/X", X_OK) == 0) {
-         server = "/usr/bin/X11/X";
-      } else if (g_access ("/usr/X11R6/bin/X", X_OK) == 0) {
-         server = "/usr/X11R6/bin/X";
-      } else if (g_access ("/opt/X11R6/bin/X", X_OK) == 0) {
-         server = "/opt/X11R6/bin/X";
-      }
-      g_free (bin);
-
-      /* yay, we can add a backup emergency server */
-      if (server != NULL) {
-         int num = gdm_get_free_display (0 /* start */, 0 /* server uid */);
-         gdm_error (_("%s: XDMCP disabled and no static servers defined. Adding %s on :%d to allow configuration!"),
-                      "gdm_config_parse", server, num);
-
-         gdm_emergency_server = TRUE;
-         displays = g_slist_append (displays, gdm_server_alloc (num, server));
-         /* ALWAYS run the greeter and don't log anyone in,
-          * this is just an emergency session */
-         g_free (GdmAutomaticLogin);
-         g_free (GdmTimedLogin);
-         GdmAutomaticLogin = NULL;
-         GdmTimedLogin     = NULL;
-      } else {
-         if (GdmConsoleNotify) {
-            gchar *s = g_strdup_printf (C_(N_("XDMCP is disabled and GDM "
-                                      "cannot find any static server "
-                                      "to start.  Aborting!  Please "
-                                      "correct the configuration "
-                                      "and restart GDM.")));
-            gdm_text_message_dialog (s);
-            g_free (s);
-         }
-
-         GdmPidFile = NULL;
-         gdm_fail (_("%s: XDMCP disabled and no static servers defined. Aborting!"), "gdm_config_parse");
-      }
-   }
-
-   /* If no displays were found, then obviously
-      we're in a no console mode */
-   if (displays == NULL)
-      no_console = TRUE;
-
-   if (no_console)
-      GdmConsoleNotify = FALSE;
-
-   /* Lookup user and groupid for the GDM user */
-   pwent = getpwnam (GdmUser);
-
-   /* Set GdmUserId and GdmGroupId */
-   if G_UNLIKELY (pwent == NULL) {
-
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("The GDM user '%s' does not exist. "
-                                           "Please correct GDM configuration "
-                                           "and restart GDM.")), GdmUser);
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: Can't find the GDM user '%s'. Aborting!"), "gdm_config_parse", GdmUser);
-   } else {
-      GdmUserId = pwent->pw_uid;
-   }
-
-   if G_UNLIKELY (GdmUserId == 0) {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("The GDM user is set to be root, but "
-                                           "this is not allowed since it can "
-                                           "pose a security risk.  Please "
-                                           "correct GDM configuration and "
-                                           "restart GDM.")));
-
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: The GDM user should not be root. Aborting!"), "gdm_config_parse");
-   }
-
-   grent = getgrnam (GdmGroup);
-
-   if G_UNLIKELY (grent == NULL) {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("The GDM group '%s' does not exist. "
-                                           "Please correct GDM configuration "
-                                           "and restart GDM.")), GdmGroup);
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: Can't find the GDM group '%s'. Aborting!"), "gdm_config_parse", GdmGroup);
-   } else  {
-      GdmGroupId = grent->gr_gid;   
-   }
-
-   if G_UNLIKELY (GdmGroupId == 0) {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("The GDM group is set to be root, but "
-                                           "this is not allowed since it can "
-                                           "pose a security risk. Please "
-                                           "correct GDM configuration and "
-                                           "restart GDM.")));
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: The GDM group should not be root. Aborting!"), "gdm_config_parse");
-   }
-
-   /* gid remains `gdm' */
-   NEVER_FAILS_root_set_euid_egid (GdmUserId, GdmGroupId);
-
-   /* Check that the greeter can be executed */
-   bin = ve_first_word (GdmGreeter);
-   if G_UNLIKELY (ve_string_empty (bin) || g_access (bin, X_OK) != 0) {
-      gdm_error (_("%s: Greeter not found or can't be executed by the GDM user"), "gdm_config_parse");
-   }
-   g_free (bin);
-
-   bin = ve_first_word (GdmRemoteGreeter);
-   if G_UNLIKELY (ve_string_empty (bin) || g_access (bin, X_OK) != 0) {
-      gdm_error (_("%s: Remote greeter not found or can't be executed by the GDM user"), "gdm_config_parse");
-   }
-   g_free (bin);
-
-   /* Check that chooser can be executed */
-   bin = ve_first_word (GdmChooser);
-
-   if G_UNLIKELY (GdmIndirect && (ve_string_empty (bin) || g_access (bin, X_OK) != 0)) {
-      gdm_error (_("%s: Chooser not found or it can't be executed by the GDM user"), "gdm_config_parse");
-   }
-    
-   g_free (bin);
-
-   /* Check the serv auth and log dirs */
-   if G_UNLIKELY (ve_string_empty (GdmServAuthDir)) {
-       if (GdmConsoleNotify) {
-          gdm_text_message_dialog
-             (C_(N_("No daemon/ServAuthDir specified in the GDM configuration file")));
-       }
-       GdmPidFile = NULL;
-       gdm_fail (_("%s: No daemon/ServAuthDir specified."), "gdm_config_parse");
-   }
-
-   if (ve_string_empty (GdmLogDir)) {
-      g_free (GdmLogDir);
-      GdmLogDir = g_strdup (GdmServAuthDir);
-   }
-
-   /* Enter paranoia mode */
-   check_servauthdir (&statbuf);
-
-   NEVER_FAILS_root_set_euid_egid (0, 0);
-
-   /* Now set things up for us as  */
-   chown (GdmServAuthDir, 0, GdmGroupId);
-   g_chmod (GdmServAuthDir, (S_IRWXU|S_IRWXG|S_ISVTX));
-
-   NEVER_FAILS_root_set_euid_egid (GdmUserId, GdmGroupId);
-
-   /* Again paranoid */
-   check_servauthdir (&statbuf);
-
-   if G_UNLIKELY (statbuf.st_uid != 0 || statbuf.st_gid != GdmGroupId)  {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("Server Authorization directory "
-                                           "(daemon/ServAuthDir) is set to %s "
-                                           "but is not owned by user %s and group "
-                                           "%s. Please correct the ownership or "
-                                           "GDM configuration and restart "
-                                           "GDM.")), GdmServAuthDir,
-		   			gdm_root_user (), GdmGroup);
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: Authdir %s is not owned by user %s, group %s. Aborting."),
-                     "gdm_config_parse", GdmServAuthDir, gdm_root_user (), GdmGroup);
-   }
-
-   if G_UNLIKELY (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX))  {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("Server Authorization directory "
-                                    "(daemon/ServAuthDir) is set to %s "
-                                    "but has the wrong permissions: it "
-                                    "should have permissions of %o. "
-                                    "Please correct the permissions or "
-                                    "the GDM configuration and "
-                                    "restart GDM.")), GdmServAuthDir,
-                                    (S_IRWXU|S_IRWXG|S_ISVTX));
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: Authdir %s has wrong permissions %o. Should be %o. Aborting."), "gdm_config_parse", 
-                  GdmServAuthDir, statbuf.st_mode, (S_IRWXU|S_IRWXG|S_ISVTX));
-   }
-
-   NEVER_FAILS_root_set_euid_egid (0, 0);
-
-   check_logdir ();
-
-   /* Check that user authentication is properly configured */
-   gdm_verify_check ();
-
-   if (custom_cfg != NULL)
-      g_key_file_free (custom_cfg);
-   g_key_file_free (cfg);
-}
-
-/** 
- * gdm_get_gdmuid
- * gdm_get_gdmgid
+	uid_t         uid;
+	gid_t         gid;
+	GError       *error;
+	gboolean      xdmcp_enabled;
+	gboolean      dynamic_enabled;
+
+	displays          = NULL;
+	high_display_num  = 0;
+
+	/* Not NULL if config_file was set by command-line option. */
+	if (config_file == NULL) {
+		config_file = GDM_DEFAULTS_CONF;
+	}
+	custom_config_file = g_strdup (GDM_CUSTOM_CONF);
+
+	daemon_config = gdm_config_new ();
+
+	gdm_config_set_notify_func (daemon_config, notify_cb, NULL);
+	gdm_config_set_validate_func (daemon_config, validate_cb, NULL);
+
+	gdm_config_add_static_entries (daemon_config, gdm_daemon_config_entries);
+
+	gdm_config_set_default_file (daemon_config, config_file);
+	gdm_config_set_custom_file (daemon_config, custom_config_file);
+
+	/* load the data files */
+	error = NULL;
+	gdm_config_load (daemon_config, &error);
+	if (error != NULL) {
+		gdm_error ("Unable to load configuration: %s", error->message);
+		g_error_free (error);
+	}
+
+	/* populate the database with all specified entries */
+	gdm_config_process_all (daemon_config, &error);
+
+	gdm_daemon_config_load_xservers (daemon_config);
+
+	/* Only read the list if no_console is FALSE at this stage */
+	if (! no_console) {
+		gdm_daemon_config_load_displays (daemon_config);
+	}
+
+	xdmcp_enabled = FALSE;
+	gdm_config_get_bool_for_id (daemon_config, GDM_ID_XDMCP, &xdmcp_enabled);
+	dynamic_enabled = FALSE;
+	gdm_config_get_bool_for_id (daemon_config, GDM_ID_DYNAMIC_XSERVERS, &dynamic_enabled);
+	if G_UNLIKELY ((displays == NULL) && (! xdmcp_enabled) && (! dynamic_enabled)) {
+		handle_no_displays (daemon_config);
+	}
+
+	/* If no displays were found, then obviously
+	   we're in a no console mode */
+	if (displays == NULL) {
+		no_console = TRUE;
+	}
+
+	if (no_console) {
+		gdm_config_set_bool_for_id (daemon_config, GDM_ID_CONSOLE_NOTIFY, FALSE);
+	}
+
+	gdm_daemon_change_user (daemon_config, &uid, &gid);
+
+	gdm_daemon_check_permissions (daemon_config, uid, gid);
+
+	NEVER_FAILS_root_set_euid_egid (0, 0);
+
+	check_logdir ();
+
+	GdmUserId = uid;
+	GdmGroupId = gid;
+
+	/* Check that user authentication is properly configured */
+	gdm_verify_check ();
+}
+
+/**
+ * gdm_daemon_config_get_gdmuid
+ * gdm_daemon_config_get_gdmgid
  *
  * Access functions for getting the GDM user ID and group ID.
  */
 uid_t
-gdm_get_gdmuid (void)
+gdm_daemon_config_get_gdmuid (void)
 {
-   return GdmUserId;
+	return GdmUserId;
 }
 
 gid_t
-gdm_get_gdmgid (void)
+gdm_daemon_config_get_gdmgid (void)
 {
-   return GdmGroupId;
+	return GdmGroupId;
 }
 
-/** 
- * gdm_get_high_display_num
- * gdm_get_high_display_num
+/**
+ * gdm_daemon_config_get_high_display_num
+ * gdm_daemon_config_get_high_display_num
  *
  * Access functions for getting the high display number.
  */
 gint
-gdm_get_high_display_num (void)
+gdm_daemon_config_get_high_display_num (void)
 {
-   return high_display_num;
+	return high_display_num;
 }
 
 void
-gdm_set_high_display_num (gint val)
+gdm_daemon_config_set_high_display_num (gint val)
 {
-   high_display_num = val;
+	high_display_num = val;
 }
 
 /**
@@ -2425,13 +2048,29 @@ gdm_set_high_display_num (gint val)
  * Returns TRUE if the key is a valid key, FALSE otherwise.
  */
 gboolean
-gdm_is_valid_key (const gchar *key)
+gdm_daemon_config_is_valid_key (const char *keystring)
 {
-   GdmConfigType *type = gdm_config_hash_lookup (type_hash, key);
-   if (type == NULL)
-      return FALSE;
+	char    *group;
+	char    *key;
+	gboolean ret;
+	const GdmConfigEntry *entry;
+
+	ret = gdm_common_config_parse_key_string (keystring,
+						  &group,
+						  &key,
+						  NULL);
+	if (! ret) {
+		goto out;
+	}
+
 
-   return TRUE;
+	entry = gdm_config_lookup_entry (daemon_config, group, key);
+	ret = (entry != NULL);
+
+	g_free (group);
+	g_free (key);
+ out:
+	return ret;
 }
 
 /**
@@ -2442,15 +2081,15 @@ gdm_is_valid_key (const gchar *key)
  * other files
  */
 gboolean
-gdm_signal_terminthup_was_notified (void)
+gdm_daemon_config_signal_terminthup_was_notified (void)
 {
-   if (ve_signal_was_notified (SIGTERM) ||
-       ve_signal_was_notified (SIGINT) ||
-       ve_signal_was_notified (SIGHUP)) {
-      return TRUE;
-   } else {
-      return FALSE;
-   }
+	if (ve_signal_was_notified (SIGTERM) ||
+	    ve_signal_was_notified (SIGINT) ||
+	    ve_signal_was_notified (SIGHUP)) {
+		return TRUE;
+	} else {
+		return FALSE;
+	}
 }
 
 /**
@@ -2459,8 +2098,8 @@ gdm_signal_terminthup_was_notified (void
  * is_in_trusted_pic_dir
  * get_facefile_from_gnome2_dir_config 
  * path_is_local
- * gdm_get_facefile_from_home
- * gdm_get_facefile_from_global
+ * gdm_daemon_config_get_facefile_from_home
+ * gdm_daemon_config_get_facefile_from_global
  *
  * These functions are used for accessing the user's face image from their
  * home directory via vicious-extensions.
@@ -2487,8 +2126,8 @@ check_user_file (const char *path,
                                 dir,
                                 file,
                                 TRUE, TRUE,
-                                gdm_get_value_int (GDM_KEY_USER_MAX_FILE),
-                                gdm_get_value_int (GDM_KEY_RELAX_PERM));
+                                gdm_daemon_config_get_value_int (GDM_KEY_USER_MAX_FILE),
+                                gdm_daemon_config_get_value_int (GDM_KEY_RELAX_PERM));
         g_free (dir);
         g_free (file);
 
@@ -2525,64 +2164,64 @@ static gchar *
 get_facefile_from_gnome2_dir_config (const char *homedir,
                                      guint       uid)
 {
-   char *picfile = NULL;
-   char *cfgdir;
+	char *picfile = NULL;
+	char *cfgdir;
 
-   /* Sanity check on ~user/.gnome2/gdm */
-   cfgdir = g_build_filename (homedir, ".gnome2", "gdm", NULL);
-   if (G_LIKELY (check_user_file (cfgdir, uid))) {
-      GKeyFile *cfg;
-      char *cfgfile;
-
-      cfgfile = g_build_filename (homedir, ".gnome2", "gdm", NULL);
-      cfg = gdm_common_config_load (cfgfile, NULL);
-      g_free (cfgfile);
-
-      if (cfg != NULL) {
-         gdm_common_config_get_string (cfg, "face/picture=", &picfile, NULL);
-         g_key_file_free (cfg);
-      }
-
-      /* must exist and be absolute (note that this check
-       * catches empty strings)*/
-      /* Note that these days we just set ~/.face */
-      if G_UNLIKELY (picfile != NULL &&
-                     (picfile[0] != '/' ||
-                      /* this catches readability by user */
-                      g_access (picfile, R_OK) != 0)) {
-         g_free (picfile);
-         picfile = NULL;
-      }
-
-      if (picfile != NULL) {
-         char buf[PATH_MAX];
-         if (realpath (picfile, buf) == NULL) {
-            g_free (picfile);
-            picfile = NULL;
-         } else {
-            g_free (picfile);
-            picfile = g_strdup (buf);
-         }
-      }
-
-      if G_UNLIKELY (picfile != NULL) {
-         if (! is_in_trusted_pic_dir (picfile)) {
-            /* if not in trusted dir, check it out */
-
-            /* Note that strict permissions checking is done
-             * on this file.  Even if it may not even be owned by the
-             * user.  This setting should ONLY point to pics in trusted
-             * dirs. */
-            if (! check_user_file (picfile, uid)) {
-               g_free (picfile);
-               picfile = NULL;
-            }
-         }
-      }
-   }
-   g_free (cfgdir);
+	/* Sanity check on ~user/.gnome2/gdm */
+	cfgdir = g_build_filename (homedir, ".gnome2", "gdm", NULL);
+	if (G_LIKELY (check_user_file (cfgdir, uid))) {
+		GKeyFile *cfg;
+		char *cfgfile;
+
+		cfgfile = g_build_filename (homedir, ".gnome2", "gdm", NULL);
+		cfg = gdm_common_config_load (cfgfile, NULL);
+		g_free (cfgfile);
+
+		if (cfg != NULL) {
+			gdm_common_config_get_string (cfg, "face/picture=", &picfile, NULL);
+			g_key_file_free (cfg);
+		}
+
+		/* must exist and be absolute (note that this check
+		 * catches empty strings)*/
+		/* Note that these days we just set ~/.face */
+		if G_UNLIKELY (picfile != NULL &&
+			       (picfile[0] != '/' ||
+				/* this catches readability by user */
+				g_access (picfile, R_OK) != 0)) {
+			g_free (picfile);
+			picfile = NULL;
+		}
+
+		if (picfile != NULL) {
+			char buf[PATH_MAX];
+			if (realpath (picfile, buf) == NULL) {
+				g_free (picfile);
+				picfile = NULL;
+			} else {
+				g_free (picfile);
+				picfile = g_strdup (buf);
+			}
+		}
+
+		if G_UNLIKELY (picfile != NULL) {
+			if (! is_in_trusted_pic_dir (picfile)) {
+				/* if not in trusted dir, check it out */
+
+				/* Note that strict permissions checking is done
+				 * on this file.  Even if it may not even be owned by the
+				 * user.  This setting should ONLY point to pics in trusted
+				 * dirs. */
+				if (! check_user_file (picfile, uid)) {
+					g_free (picfile);
+					picfile = NULL;
+				}
+			}
+		}
+	}
+	g_free (cfgdir);
 
-   return picfile;
+	return picfile;
 }
 
 static GHashTable *fstype_hash = NULL;
@@ -2620,313 +2259,332 @@ path_is_local (const char *path)
 }
 
 gchar *
-gdm_get_facefile_from_home (const char *homedir,
-                            guint       uid)
+gdm_daemon_config_get_facefile_from_home (const char *homedir,
+					  guint       uid)
 {
-   char    *picfile = NULL;
-   char    *path;
-   gboolean is_local;
-
-   /* special case: look at parent of home to detect autofs
-      this is so we don't try to trigger an automount */
-   path = g_path_get_dirname (homedir);
-   is_local = path_is_local (path);
-   g_free (path);
-
-   /* now check that home dir itself is local */
-   if (is_local) {
-      is_local = path_is_local (homedir);
-   }
-
-   /* Only look at local home directories so we don't try to
-      read from remote (e.g. NFS) volumes */
-   if (! is_local)
-      return NULL;
-
-   picfile = g_build_filename (homedir, ".face", NULL);
-
-   if (check_user_file (picfile, uid))
-      return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   picfile = g_build_filename (homedir, ".face.icon", NULL);
-
-   if (check_user_file (picfile, uid))
-           return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   picfile = get_facefile_from_gnome2_dir_config (homedir, uid);
-   if (check_user_file (picfile, uid))
-      return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   /* Nothing found yet, try the old locations */
-
-   picfile = g_build_filename (homedir, ".gnome2", "photo", NULL);
-   if (check_user_file (picfile, uid))
-      return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   picfile = g_build_filename (homedir, ".gnome", "photo", NULL);
-   if (check_user_file (picfile, uid))
-      return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
+	char    *picfile = NULL;
+	char    *path;
+	gboolean is_local;
+
+	/* special case: look at parent of home to detect autofs
+	   this is so we don't try to trigger an automount */
+	path = g_path_get_dirname (homedir);
+	is_local = path_is_local (path);
+	g_free (path);
+
+	/* now check that home dir itself is local */
+	if (is_local) {
+		is_local = path_is_local (homedir);
+	}
+
+	/* Only look at local home directories so we don't try to
+	   read from remote (e.g. NFS) volumes */
+	if (! is_local)
+		return NULL;
+
+	picfile = g_build_filename (homedir, ".face", NULL);
+
+	if (check_user_file (picfile, uid))
+		return picfile;
+	else {
+		g_free (picfile);
+		picfile = NULL;
+	}
+
+	picfile = g_build_filename (homedir, ".face.icon", NULL);
+
+	if (check_user_file (picfile, uid))
+		return picfile;
+	else {
+		g_free (picfile);
+		picfile = NULL;
+	}
+
+	picfile = get_facefile_from_gnome2_dir_config (homedir, uid);
+	if (check_user_file (picfile, uid))
+		return picfile;
+	else {
+		g_free (picfile);
+		picfile = NULL;
+	}
+
+	/* Nothing found yet, try the old locations */
+
+	picfile = g_build_filename (homedir, ".gnome2", "photo", NULL);
+	if (check_user_file (picfile, uid))
+		return picfile;
+	else {
+		g_free (picfile);
+		picfile = NULL;
+	}
+
+	picfile = g_build_filename (homedir, ".gnome", "photo", NULL);
+	if (check_user_file (picfile, uid))
+		return picfile;
+	else {
+		g_free (picfile);
+		picfile = NULL;
+	}
 
-   return NULL;
+	return NULL;
 }
 
 gchar *
-gdm_get_facefile_from_global (const char *username,
-                              guint       uid)
+gdm_daemon_config_get_facefile_from_global (const char *username,
+					    guint       uid)
 {
-   char *picfile = NULL;
-   char *facedir = gdm_get_value_string (GDM_KEY_GLOBAL_FACE_DIR);
+	char       *picfile = NULL;
+	const char *facedir;
+
+	facedir = gdm_daemon_config_get_value_string (GDM_KEY_GLOBAL_FACE_DIR);
+
+	/* Try the global face directory */
 
-   /* Try the global face directory */
+	picfile = g_build_filename (facedir, username, NULL);
 
-   picfile = g_build_filename (facedir, username, NULL);
+	if (check_global_file (picfile, uid))
+		return picfile;
 
-   if (check_global_file (picfile, uid))
-      return picfile;
+	g_free (picfile);
+	picfile = gdm_make_filename (facedir, username, ".png");
 
-   g_free (picfile);
-   picfile = gdm_make_filename (facedir, username, ".png");
+	if (check_global_file (picfile, uid))
+		return picfile;
 
-   if (check_global_file (picfile, uid))
-      return picfile;
+	g_free (picfile);
+	return NULL;
+}
+
+static gboolean
+is_prog_in_path (const char *prog)
+{
+	char    *f;
+	gboolean ret;
 
-   g_free (picfile);
-   return NULL;
+	f = g_find_program_in_path (prog);
+	ret = (f != NULL);
+	g_free (f);
+	return ret;
 }
 
 /**
- * gdm_get_session_exec
+ * gdm_daemon_config_get_session_exec
  *
  * This function accesses the GDM session desktop file, via vicious
  * extensions and returns the execution command for starting the
  * session.
+ *
+ * Must be called with the PATH set correctly to find session exec.
  */
 char *
-gdm_get_session_exec (const char *session_name, gboolean check_try_exec)
+gdm_daemon_config_get_session_exec (const char *session_name,
+				    gboolean    check_try_exec)
 {
-   char *file;
-   char *full = NULL;
-   GKeyFile *cfg;
-   static char *exec;
-   static char *cached = NULL;
-   gboolean hidden;
-   char *ret;
-
-   cfg = NULL;
-
-   /* clear cache */
-   if (session_name == NULL) {
-      g_free (exec);
-      exec = NULL;
-      g_free (cached);
-      cached = NULL;
-      return NULL;
-   }
-
-   if (cached != NULL && strcmp (ve_sure_string (session_name), ve_sure_string (cached)) == 0)
-      return g_strdup (exec);
-
-   g_free (exec);
-   exec = NULL;
-   g_free (cached);
-   cached = g_strdup (session_name);
-
-   /* Some ugly special casing for legacy "Default.desktop", oh well,
-    * we changed to "default.desktop" */
-   if (g_ascii_strcasecmp (session_name, "default") == 0 ||
-       g_ascii_strcasecmp (session_name, "default.desktop") == 0) {
-      full = ve_find_prog_in_path ("default.desktop",
-         gdm_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR));
-   }
-
-   if (full == NULL) {
-      file = gdm_ensure_extension (session_name, ".desktop");
-      full = ve_find_prog_in_path (file,
-         gdm_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR));
-      g_free (file);
-   }
-
-   if (ve_string_empty (full) || g_access (full, R_OK) != 0) {
-      g_free (full);
-      if (gdm_is_session_magic (session_name)) {
-         exec = g_strdup (session_name);
-         return g_strdup (exec);
-      } else {
-         return NULL;
-      }
-   }
-
-   cfg = gdm_common_config_load (full, NULL);
-   g_free (full);
-   if (cfg == NULL) {
-      ret = NULL;
-      goto out;
-   }
-
-   hidden = FALSE;
-   gdm_common_config_get_boolean (cfg, "Desktop Entry/Hidden=false", &hidden, NULL);
-   if (hidden) {
-      ret = NULL;
-      goto out;
-   }
-
-   if (check_try_exec) {
-      char *tryexec;
-      tryexec = NULL;
-      gdm_common_config_get_string (cfg, "Desktop Entry/TryExec", &tryexec, NULL);
-      if ( ! ve_string_empty (tryexec) &&
-           ! ve_is_prog_in_path (tryexec, gdm_get_value_string (GDM_KEY_PATH)) &&
-           ! ve_is_prog_in_path (tryexec, gdm_saved_getenv ("PATH"))) {
-         g_free (tryexec);
-         ret = NULL;
-         goto out;
-      }
-      g_free (tryexec);
-   }
-
-   exec = NULL;
-   gdm_common_config_get_string (cfg, "Desktop Entry/Exec", &exec, NULL);
-   ret = g_strdup (exec);
+	char        *session_filename;
+	const char  *path_str;
+	char       **search_dirs;
+	GKeyFile    *cfg;
+	static char *exec;
+	static char *cached = NULL;
+	gboolean     hidden;
+	char        *ret;
+
+	cfg = NULL;
+
+	/* clear cache */
+	if (session_name == NULL) {
+		g_free (exec);
+		exec = NULL;
+		g_free (cached);
+		cached = NULL;
+		return NULL;
+	}
+
+	if (cached != NULL && strcmp (ve_sure_string (session_name), ve_sure_string (cached)) == 0)
+		return g_strdup (exec);
+
+	g_free (exec);
+	exec = NULL;
+	g_free (cached);
+	cached = g_strdup (session_name);
+
+	/* Some ugly special casing for legacy "Default.desktop", oh well,
+	 * we changed to "default.desktop" */
+	if (g_ascii_strcasecmp (session_name, "default") == 0 ||
+	    g_ascii_strcasecmp (session_name, "default.desktop") == 0) {
+		session_filename = g_strdup ("default.desktop");
+	} else {
+		session_filename = gdm_ensure_extension (session_name, ".desktop");
+	}
+
+	path_str = gdm_daemon_config_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR);
+	if (path_str == NULL) {
+		gdm_error ("No session desktop directories defined");
+		goto out;
+	}
+
+	search_dirs = g_strsplit (path_str, ":", -1);
+
+	cfg = gdm_common_config_load_from_dirs (session_filename,
+						(const char **)search_dirs,
+						NULL);
+	g_strfreev (search_dirs);
+
+	if (cfg == NULL) {
+		if (gdm_is_session_magic (session_name)) {
+			exec = g_strdup (session_name);
+		} else {
+			g_free (exec);
+			exec = NULL;
+		}
+		goto out;
+	}
+
+	hidden = FALSE;
+	gdm_common_config_get_boolean (cfg, "Desktop Entry/Hidden=false", &hidden, NULL);
+	if (hidden) {
+		g_free (exec);
+		exec = NULL;
+		goto out;
+	}
+
+	if (check_try_exec) {
+		char *tryexec;
+
+		tryexec = NULL;
+		gdm_common_config_get_string (cfg, "Desktop Entry/TryExec", &tryexec, NULL);
+
+		if (tryexec != NULL &&
+		    tryexec[0] != '\0' &&
+		    ! is_prog_in_path (tryexec)) {
+			g_free (tryexec);
+			g_free (exec);
+			exec = NULL;
+			goto out;
+		}
+		g_free (tryexec);
+	}
+
+	exec = NULL;
+	gdm_common_config_get_string (cfg, "Desktop Entry/Exec", &exec, NULL);
 
  out:
 
-   g_key_file_free (cfg);
+	ret = g_strdup (exec);
 
-   return ret;
+	g_key_file_free (cfg);
+
+	return ret;
 }
 
 /**
- * gdm_set_user_session_lang
- * gdm_get_user_session_lang
+ * gdm_daemon_config_get_user_session_lang
  *
  * These functions get and set the user's language and setting in their
  * $HOME/.dmrc file via vicious-extensions.
  */
 void
-gdm_set_user_session_lang (gboolean savesess,
-                           gboolean savelang,
-                           const char *home_dir,
-                           const char *save_session,
-                           const char *save_language)
-{
-   GKeyFile *dmrc;
-   gchar *cfgstr;
-
-   cfgstr = g_build_filename (home_dir, ".dmrc", NULL);
-
-   dmrc = gdm_common_config_load (cfgstr, NULL);
-   if (dmrc == NULL) {
-      return;
-   }
-
-   if (savesess) {
-      g_key_file_set_string (dmrc, "Desktop", "Session", ve_sure_string (save_session));
-   }
-
-   if (savelang) {
-      if (ve_string_empty (save_language)) {
-         /* we chose the system default language so wipe the
-          * lang key */
-         g_key_file_remove_key (dmrc, "Desktop", "Language", NULL);
-      } else {
-         g_key_file_set_string (dmrc, "Desktop", "Language", save_language);
-      }
-   }
-
-   if (dmrc != NULL) {
-      mode_t oldmode;
-      oldmode = umask (077);
-      gdm_common_config_save (dmrc, cfgstr, NULL);
-      umask (oldmode);
-   }
+gdm_daemon_config_set_user_session_lang (gboolean savesess,
+					 gboolean savelang,
+					 const char *home_dir,
+					 const char *save_session,
+					 const char *save_language)
+{
+	GKeyFile *dmrc;
+	gchar *cfgstr;
+
+	cfgstr = g_build_filename (home_dir, ".dmrc", NULL);
+
+	dmrc = gdm_common_config_load (cfgstr, NULL);
+	if (dmrc == NULL) {
+		return;
+	}
+
+	if (savesess) {
+		g_key_file_set_string (dmrc, "Desktop", "Session", ve_sure_string (save_session));
+	}
+
+	if (savelang) {
+		if (ve_string_empty (save_language)) {
+			/* we chose the system default language so wipe the
+			 * lang key */
+			g_key_file_remove_key (dmrc, "Desktop", "Language", NULL);
+		} else {
+			g_key_file_set_string (dmrc, "Desktop", "Language", save_language);
+		}
+	}
+
+	if (dmrc != NULL) {
+		mode_t oldmode;
+		oldmode = umask (077);
+		gdm_common_config_save (dmrc, cfgstr, NULL);
+		umask (oldmode);
+	}
 
-   g_free (cfgstr);
-   g_key_file_free (dmrc);
+	g_free (cfgstr);
+	g_key_file_free (dmrc);
 }
 
 void
-gdm_get_user_session_lang (char **usrsess,
-                           char **usrlang,
-                           const char *home_dir,
-                           gboolean *savesess)
-{
-   char *p;
-   char *cfgfile;
-   GKeyFile *cfg;
-   char *session;
-   char *lang;
-   gboolean save;
-
-   cfgfile = g_build_filename (home_dir, ".dmrc", NULL);
-   cfg = gdm_common_config_load (cfgfile, NULL);
-   g_free (cfgfile);
-
-   save = FALSE;
-   session = NULL;
-
-   gdm_common_config_get_string (cfg, "Desktop/Session", &session, NULL);
-   if (session == NULL) {
-      session = g_strdup ("");
-   }
-
-   /* this is just being truly anal about what users give us, and in case
-    * it looks like they may have included a path whack it. */
-   p = strrchr (session, '/');
-   if (p != NULL) {
-      char *tmp = g_strdup (p + 1);
-      g_free (session);
-      session = tmp;
-   }
-
-   /* ugly workaround for migration */
-   if ((strcmp (ve_sure_string (session), "Default.desktop") == 0 ||
-        strcmp (ve_sure_string (session), "Default") == 0) &&
-       ! ve_is_prog_in_path ("Default.desktop",
-            gdm_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR))) {
-           g_free (session);
-           session = g_strdup ("default");
-           save = TRUE;
-   }
-
-   gdm_common_config_get_string (cfg, "Desktop/Language", &lang, NULL);
-   if (lang == NULL) {
-           lang = g_strdup ("");
-   }
-
-   if (usrsess != NULL) {
-      *usrsess = g_strdup (session);
-   }
-   g_free (session);
-
-   if (savesess != NULL) {
-      *savesess = save;
-   }
-
-   if (usrlang != NULL) {
-      *usrlang = g_strdup (lang);
-   }
-   g_free (lang);
+gdm_daemon_config_get_user_session_lang (char      **usrsess,
+					 char      **usrlang,
+					 const char *home_dir,
+					 gboolean   *savesess)
+{
+	char *p;
+	char *cfgfile;
+	GKeyFile *cfg;
+	char *session;
+	char *lang;
+	gboolean save;
+
+	cfgfile = g_build_filename (home_dir, ".dmrc", NULL);
+	cfg = gdm_common_config_load (cfgfile, NULL);
+	g_free (cfgfile);
+
+	save = FALSE;
+	session = NULL;
+
+	gdm_common_config_get_string (cfg, "Desktop/Session", &session, NULL);
+	if (session == NULL) {
+		session = g_strdup ("");
+	}
+
+	/* this is just being truly anal about what users give us, and in case
+	 * it looks like they may have included a path whack it. */
+	p = strrchr (session, '/');
+	if (p != NULL) {
+		char *tmp = g_strdup (p + 1);
+		g_free (session);
+		session = tmp;
+	}
+
+	/* ugly workaround for migration */
+	if (strcmp (session, "Default") == 0 ||
+	    strcmp (session, "Default.desktop") == 0) {
+		g_free (session);
+		session = g_strdup ("default");
+		save = TRUE;
+	}
+
+	gdm_common_config_get_string (cfg, "Desktop/Language", &lang, NULL);
+	if (lang == NULL) {
+		lang = g_strdup ("");
+	}
+
+	if (usrsess != NULL) {
+		*usrsess = g_strdup (session);
+	}
+	g_free (session);
+
+	if (savesess != NULL) {
+		*savesess = save;
+	}
+
+	if (usrlang != NULL) {
+		*usrlang = g_strdup (lang);
+	}
+	g_free (lang);
 
-   g_key_file_free (cfg);
+	g_key_file_free (cfg);
 }
-
Index: daemon/choose.c
===================================================================
--- daemon/choose.c	(revision 4696)
+++ daemon/choose.c	(working copy)
@@ -42,7 +42,9 @@
 #include "misc.h"
 #include "choose.h"
 #include "xdmcp.h"
-#include "gdmconfig.h"
+
+#include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 static gint ipending = 0;
 static GSList *indirect = NULL;
@@ -148,7 +150,7 @@ gdm_choose_data (const char *data)
 		GdmIndirectDisplay *idisp = li->data;
 		if (idisp->id == id) {
 			/* whack the oldest if more then allowed */
-			while (ipending >= gdm_get_value_int (GDM_KEY_MAX_INDIRECT) &&
+			while (ipending >= gdm_daemon_config_get_value_int (GDM_KEY_MAX_INDIRECT) &&
 			       remove_oldest_pending ())
 				;
 
@@ -333,7 +335,7 @@ gdm_choose_indirect_lookup (struct socka
 		continue;
 
 	if (id->acctime > 0 &&
-	    curtime > id->acctime + gdm_get_value_int (GDM_KEY_MAX_WAIT_INDIRECT)) {
+	    curtime > id->acctime + gdm_daemon_config_get_value_int (GDM_KEY_MAX_WAIT_INDIRECT)) {
 #ifdef ENABLE_IPV6
 	    if (clnt_sa->ss_family == AF_INET6) {
 		char buffer6[INET6_ADDRSTRLEN];
Index: daemon/gdm-daemon-config.h
===================================================================
--- daemon/gdm-daemon-config.h	(revision 4696)
+++ daemon/gdm-daemon-config.h	(working copy)
@@ -19,75 +19,76 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifndef _GDM_CONFIG_H
-#define _GDM_CONFIG_H
+#ifndef _GDM_DAEMON_CONFIG_H
+#define _GDM_DAEMON_CONFIG_H
 
-#include "gdm.h"
+#include "gdm-daemon-config-entries.h"
 
 G_BEGIN_DECLS
 
+gchar*         gdm_daemon_config_get_display_custom_config_file (const gchar *display);
+gchar*         gdm_daemon_config_get_custom_config_file (void);
 
-gchar*         gdm_get_display_custom_config_file
-                                        (const gchar *display);
-gchar*         gdm_get_custom_config_file (void);
-gchar*         gdm_get_value_string     (const gchar *key);
-gboolean       gdm_get_value_bool       (const gchar *key);
-gint           gdm_get_value_int        (const gchar *key);
-gchar*         gdm_get_value_string_per_display (const gchar *display,
-                                                 const gchar *key);
-gboolean       gdm_get_value_bool_per_display   (const gchar *display,
-                                                 const gchar *key);
-gint           gdm_get_value_int_per_display    (const gchar *display,
-                                                 const gchar *key);
-void           gdm_set_value_string     (const gchar *key,
-                                         const gchar *value);
-void           gdm_set_value_bool       (const gchar *key,
-                                         gboolean value);
-void           gdm_set_value_int        (const gchar *key,
-                                         gint value);
-void           gdm_config_key_to_string_per_display
-                                        (const gchar *display,
-                                         const gchar *key,
-                                         gchar **retval);
-void           gdm_config_key_to_string (const gchar *file,
-                                         const gchar *key,
-                                         gchar **retval);
-void           gdm_config_to_string     (const gchar *key,
-                                         const gchar *display,
-                                         gchar **retval);
-gboolean       gdm_update_config        (const gchar *key);
-void           gdm_config_parse         (void);
-GdmXserver*    gdm_find_xserver         (const gchar *id);
-gchar*         gdm_get_xservers         (void);
-int            gdm_compare_displays     (gconstpointer a,
-                                         gconstpointer b);
-uid_t          gdm_get_gdmuid           (void);
-uid_t          gdm_get_gdmgid           (void);
-gint           gdm_get_high_display_num (void);
-void           gdm_set_high_display_num (gint val);
-gboolean       gdm_is_valid_key         (const gchar *key);
-gboolean       gdm_signal_terminthup_was_notified  (void);
-
-gchar*         gdm_get_facefile_from_home
-                                        (const char *homedir,
-                                         guint uid);
-gchar*         gdm_get_facefile_from_global
-                                        (const char *username,
-                                         guint uid);
-void           gdm_get_user_session_lang
-                                        (char **usrsess,
-                                         char **usrlang,
-                                         const char *homedir,
-                                         gboolean *savesess);
-void		gdm_set_user_session_lang (gboolean savesess,
-					 gboolean savelang,
-					 const char *home_dir,
-					 const char *save_session,
-					 const char *save_language);
-char*          gdm_get_session_exec     (const char *session_name,
-                                         gboolean check_try_exec);
+const char*    gdm_daemon_config_get_value_string     (const gchar *key);
+gboolean       gdm_daemon_config_get_value_bool       (const gchar *key);
+gint           gdm_daemon_config_get_value_int        (const gchar *key);
+gchar*         gdm_daemon_config_get_value_string_per_display (const gchar *display,
+                                                               const gchar *key);
+gboolean       gdm_daemon_config_get_value_bool_per_display   (const gchar *display,
+                                                               const gchar *key);
+gint           gdm_daemon_config_get_value_int_per_display    (const gchar *display,
+                                                               const gchar *key);
+
+
+void           gdm_daemon_config_set_value_string     (const gchar *key,
+                                                       const gchar *value);
+void           gdm_daemon_config_set_value_bool       (const gchar *key,
+                                                       gboolean value);
+void           gdm_daemon_config_set_value_int        (const gchar *key,
+                                                       gint value);
+
+
+void           gdm_daemon_config_key_to_string_per_display (const gchar *display,
+                                                                   const gchar *key,
+                                                                   gchar **retval);
+void           gdm_daemon_config_key_to_string        (const gchar *file,
+                                                       const gchar *key,
+                                                       gchar **retval);
+void           gdm_daemon_config_to_string            (const gchar *key,
+                                                       const gchar *display,
+                                                       gchar **retval);
+gboolean       gdm_daemon_config_update_key           (const gchar *key);
+
+
+void           gdm_daemon_config_parse                (const char *config_file);
+GdmXserver *   gdm_daemon_config_find_xserver         (const gchar *id);
+gchar *        gdm_daemon_config_get_xservers         (void);
+int            gdm_daemon_config_compare_displays     (gconstpointer a,
+                                                       gconstpointer b);
+uid_t          gdm_daemon_config_get_gdmuid           (void);
+uid_t          gdm_daemon_config_get_gdmgid           (void);
+gint           gdm_daemon_config_get_high_display_num (void);
+void           gdm_daemon_config_set_high_display_num (gint val);
+gboolean       gdm_daemon_config_is_valid_key         (const gchar *key);
+gboolean       gdm_daemon_config_signal_terminthup_was_notified  (void);
+
+gchar *        gdm_daemon_config_get_facefile_from_home (const char *homedir,
+                                                         guint uid);
+gchar *        gdm_daemon_config_get_facefile_from_global (const char *username,
+                                                           guint uid);
+void           gdm_daemon_config_get_user_session_lang (char **usrsess,
+                                                        char **usrlang,
+                                                        const char *homedir,
+                                                        gboolean *savesess);
+void		gdm_daemon_config_set_user_session_lang (gboolean savesess,
+                                                         gboolean savelang,
+                                                         const char *home_dir,
+                                                         const char *save_session,
+                                                         const char *save_language);
+char *          gdm_daemon_config_get_session_exec     (const char *session_name,
+                                                        gboolean check_try_exec);
 
 
 G_END_DECLS
 
-#endif /* _GDM_CONFIG_H */
+#endif /* _GDM_DAEMON_CONFIG_H */
Index: daemon/Makefile.am
===================================================================
--- daemon/Makefile.am	(revision 4696)
+++ daemon/Makefile.am	(working copy)
@@ -40,8 +40,9 @@ sbin_PROGRAMS = gdm-binary
 gdm_binary_SOURCES = \
 	gdm.c \
 	gdm.h \
-	gdmconfig.c \
-	gdmconfig.h \
+	gdm-daemon-config.c \
+	gdm-daemon-config.h \
+	gdm-daemon-config-entries.h \
 	display.c \
 	display.h \
 	fstype.c \
Index: daemon/misc.c
===================================================================
--- daemon/misc.c	(revision 4696)
+++ daemon/misc.c	(working copy)
@@ -55,9 +55,9 @@
 #include "misc.h"
 #include "xdmcp.h"
 #include "slave.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 extern char **environ;
 
@@ -301,7 +301,7 @@ gdm_debug (const gchar *format, ...)
     va_list args;
     char *s;
 
-    if G_LIKELY (! gdm_get_value_bool (GDM_KEY_DEBUG)) 
+    if G_LIKELY (! gdm_daemon_config_get_value_bool (GDM_KEY_DEBUG))
 	return;
 
     va_start (args, format);
@@ -314,7 +314,7 @@ gdm_debug (const gchar *format, ...)
     g_free (s);
 }
 
-void 
+void
 gdm_fdprintf (int fd, const gchar *format, ...)
 {
 	va_list args;
@@ -346,37 +346,6 @@ gdm_fdprintf (int fd, const gchar *forma
 }
 
 /*
- * Clear environment, but keep the i18n ones,
- * note that this leaks memory so only use before exec
- * (keep LD_* if preserve_ld_vars is true)
- */
-void
-gdm_clearenv_no_lang (void)
-{
-	int i;
-	GList *li, *envs = NULL;
-
-	for (i = 0; environ[i] != NULL; i++) {
-		char *env = environ[i];
-		if (strncmp (env, "LC_", 3) == 0 ||
-		    strncmp (env, "LANG", 4) == 0 ||
-		    strncmp (env, "LINGUAS", 7) == 0)
-			envs = g_list_prepend (envs, g_strdup (env));
-		if (preserve_ld_vars &&
-		    strncmp (env, "LD_", 3) == 0)
-			envs = g_list_prepend (envs, g_strdup (env));
-	}
-
-	ve_clearenv ();
-
-	for (li = envs; li != NULL; li = li->next) {
-		putenv (li->data);
-	}
-
-	g_list_free (envs);
-}
-
-/*
  * Clear environment completely
  * note that this leaks memory so only use before exec
  * (keep LD_* if preserve_ld_vars is true)
@@ -580,7 +549,7 @@ gdm_text_message_dialog (const char *msg
 	char *dialog; /* do we have dialog? */
 	char *msg_quoted;
 
-    if ( ! gdm_get_value_bool (GDM_KEY_CONSOLE_NOTIFY))
+    if ( ! gdm_daemon_config_get_value_bool (GDM_KEY_CONSOLE_NOTIFY))
 		return FALSE;
 
 	if (g_access (LIBEXECDIR "/gdmopen", X_OK) != 0)
@@ -658,7 +627,7 @@ gdm_text_yesno_dialog (const char *msg, 
 	char *dialog; /* do we have dialog? */
 	char *msg_quoted;
 
-    if ( ! gdm_get_value_bool (GDM_KEY_CONSOLE_NOTIFY))
+    if ( ! gdm_daemon_config_get_value_bool (GDM_KEY_CONSOLE_NOTIFY))
 		return FALSE;
 	
 	if (g_access (LIBEXECDIR "/gdmopen", X_OK) != 0)
@@ -959,7 +928,7 @@ gdm_fork_extra (void)
 		/* Harmless in children, but in case we'd run
 		   extra processes from main daemon would fix
 		   problems ... */
-		if (gdm_get_value_bool (GDM_KEY_XDMCP))
+		if (gdm_daemon_config_get_value_bool (GDM_KEY_XDMCP))
 			gdm_xdmcp_close ();
 	}
 
@@ -2552,7 +2521,7 @@ gdm_ok_console_language (void)
 	static gboolean cached = FALSE;
 	static gboolean is_ok;
 	const char *loc;
-	char *consolecannothandle = gdm_get_value_string (GDM_KEY_CONSOLE_CANNOT_HANDLE);
+	const char *consolecannothandle = gdm_daemon_config_get_value_string (GDM_KEY_CONSOLE_CANNOT_HANDLE);
 
 	if (cached)
 		return is_ok;
Index: daemon/gdm-net.c
===================================================================
--- daemon/gdm-net.c	(revision 4696)
+++ daemon/gdm-net.c	(working copy)
@@ -35,9 +35,9 @@
 #include "gdm.h"
 #include "misc.h"
 #include "gdm-net.h"
-#include "gdmconfig.h"
 
 #include "gdm-common.h"
+#include "gdm-daemon-config.h"
 
 /*
  * Kind of a weird setup, new connections whack old connections.
Index: daemon/gdmconfig.c
===================================================================
--- daemon/gdmconfig.c	(revision 4696)
+++ daemon/gdmconfig.c	(working copy)
@@ -1,2932 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 3 -*-
- *
- * GDM - The GNOME Display Manager
- * Copyright (C) 1998, 1999, 2000 Martin K. Petersen <mkp@mkp.net>
- * Copyright (C) 2005 Brian Cameron <brian.cameron@sun.com>
- *
- * 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
- */
-
-/*
- * gdmconfig.c isolates most logic that interacts with GDM configuration
- * into a single file and provides a mechanism for interacting with GDM
- * configuration optins via access functions for getting/setting values.
- * This logic also ensures that the same configuration validation happens
- * when loading the values initially or setting them via the
- * GDM_UPDATE_CONFIG socket command.
- *
- * When adding a new configuration option, simply add the new option to
- * gdm.h and to the val_hash and type_hash hashes in the gdm_config_init
- * function.  Any validation for the configuration option should be
- * placed in the _gdm_set_value_string, _gdm_set_value_int, or
- * _gdm_set_value_bool functions.
- */
-#include "config.h"
-
-#include <stdlib.h>
-#include <unistd.h>
-#include <ctype.h>
-#include <fcntl.h>
-#include <sys/types.h>
-#include <sys/resource.h>
-#include <sys/stat.h>
-#include <sys/resource.h>
-#include <signal.h>
-#include <pwd.h>
-#include <grp.h>
-
-#include <glib.h>
-#include <glib/gi18n.h>
-
-#include "gdm-common.h"
-
-#include "gdm.h"
-#include "gdmconfig.h"
-#include "verify.h"
-#include "gdm-net.h"
-#include "misc.h"
-#include "server.h"
-#include "filecheck.h"
-#include "slave.h"
-
-gchar *config_file                     = NULL;
-gchar *custom_config_file              = NULL;
-static time_t config_file_mtime        = 0;
-static time_t custom_config_file_mtime = 0;
-
-extern gboolean no_console;
-extern gboolean gdm_emergency_server;
-
-GSList *displays          = NULL;
-GSList *displays_inactive = NULL;
-GSList *xservers          = NULL;
-
-gint high_display_num = 0;
-
-typedef enum {
-        CONFIG_BOOL,
-        CONFIG_INT,
-        CONFIG_STRING
-} GdmConfigType;
-
-static GHashTable    *type_hash       = NULL;
-static GHashTable    *val_hash        = NULL;
-static GHashTable    *translated_hash = NULL;
-static GHashTable    *realkey_hash    = NULL;
-static GdmConfigType  bool_type       = CONFIG_BOOL;
-static GdmConfigType  int_type        = CONFIG_INT;
-static GdmConfigType  string_type     = CONFIG_STRING;
-
-static uid_t GdmUserId;   /* Userid  under which gdm should run */
-static gid_t GdmGroupId;  /* Gruopid under which gdm should run */
-
-/* Config options used by daemon */
-/* ----------------------------- */
-static gchar *GdmUser = NULL;
-static gchar *GdmGroup = NULL;
-static gchar *GdmGtkRC = NULL;
-static gchar *GdmGtkTheme = NULL;
-static gchar *GdmSessDir = NULL;
-static gchar *GdmBaseXsession = NULL;
-static gchar *GdmDefaultSession = NULL;
-static gchar *GdmAutomaticLogin = NULL;
-static gchar *GdmConfigurator = NULL;
-static gchar *GdmGlobalFaceDir = NULL;
-static gchar *GdmGreeter = NULL;
-static gchar *GdmRemoteGreeter = NULL;
-static gchar *GdmGtkModulesList = NULL;
-static gchar *GdmChooser = NULL;
-static gchar *GdmLogDir = NULL;
-static gchar *GdmDisplayInitDir = NULL;
-static gchar *GdmPostLogin = NULL;
-static gchar *GdmPreSession = NULL;
-static gchar *GdmPostSession = NULL;
-static gchar *GdmFailsafeXserver = NULL;
-static gchar *GdmXKeepsCrashing = NULL;
-static gchar *GdmHalt = NULL;
-static gchar *GdmReboot = NULL;
-static GdmCustomCmd *GdmCustomCommands = NULL;
-static gchar *GdmSuspend = NULL;
-static gchar *GdmServAuthDir = NULL;
-static gchar *GdmMulticastAddr;
-static gchar *GdmUserAuthDir = NULL;
-static gchar *GdmUserAuthFile = NULL;
-static gchar *GdmUserAuthFallback = NULL;
-static gchar *GdmPidFile = NULL;
-static gchar *GdmPath = NULL;
-static gchar *GdmRootPath = NULL;
-static gchar *GdmWilling = NULL;
-static gchar *GdmXdmcpProxyXserver = NULL;
-static gchar *GdmXdmcpProxyReconnect = NULL;
-static gchar *GdmTimedLogin = NULL;
-static gchar *GdmStandardXserver = NULL;
-static gchar *GdmXnest = NULL;
-static gchar *GdmSoundProgram = NULL;
-static gchar *GdmSoundOnLoginFile = NULL;
-static gchar *GdmSoundOnLoginSuccessFile = NULL;
-static gchar *GdmSoundOnLoginFailureFile = NULL;
-static gchar *GdmConsoleCannotHandle = NULL;
-static gchar *GdmPamStack = NULL;
-
-static gint GdmXineramaScreen = 0;
-static gint GdmUserMaxFile = 0;
-static gint GdmDisplaysPerHost = 0;
-static gint GdmMaxPending = 0;
-static gint GdmMaxSessions = 0;
-static gint GdmUdpPort = 0;
-static gint GdmMaxIndirect = 0;
-static gint GdmMaxWaitIndirect = 0;
-static gint GdmPingInterval = 0;
-static gint GdmRelaxPerm = 0;
-static gint GdmRetryDelay = 0;
-static gint GdmTimedLoginDelay = 0;
-static gint GdmFlexibleXservers = 5;
-static gint GdmFirstVt = 7;
-static gint GdmXserverTimeout = 10;
-
-gboolean GdmAlwaysRestartServer;
-static gboolean GdmAutomaticLoginEnable;
-static gboolean GdmConfigAvailable;
-static gboolean GdmSystemMenu;
-static gboolean GdmChooserButton;
-static gboolean GdmBrowser;
-static gboolean GdmAddGtkModules;
-static gboolean GdmDoubleLoginWarning;
-static gboolean GdmAlwaysLoginCurrentSession;
-static gboolean GdmDisplayLastLogin;
-static gboolean GdmMulticast;
-static gboolean GdmNeverPlaceCookiesOnNfs;
-static gboolean GdmPasswordRequired;
-static gboolean GdmKillInitClients;
-static gboolean GdmXdmcp;
-static gboolean GdmIndirect;
-static gboolean GdmXdmcpProxy;
-static gboolean GdmDebug;
-static gboolean GdmDebugGestures;
-static gboolean GdmAllowRoot;
-static gboolean GdmAllowRemoteRoot;
-static gboolean GdmAllowRemoteAutoLogin;
-static gboolean GdmCheckDirOwner;
-static gboolean GdmSupportAutomount;
-static gboolean GdmTimedLoginEnable;
-static gboolean GdmDynamicXservers;
-static gboolean GdmVTAllocation;
-static gboolean GdmDisallowTcp;
-static gboolean GdmSoundOnLogin;
-static gboolean GdmSoundOnLoginSuccess;
-static gboolean GdmSoundOnLoginFailure;
-static gboolean GdmConsoleNotify;
-static gboolean GdmXnestUnscaledFontPath;
-
-/* Config options used by slave */
-/* ---------------------------- */
-static gchar *GdmGtkThemesToAllow = NULL;
-static gchar *GdmInclude = NULL;
-static gchar *GdmExclude = NULL;
-static gchar *GdmDefaultFace = NULL;
-static gchar *GdmLocaleFile = NULL;
-static gchar *GdmLogo = NULL;
-static gchar *GdmChooserButtonLogo = NULL;
-static gchar *GdmWelcome = NULL;
-static gchar *GdmRemoteWelcome = NULL;
-static gchar *GdmBackgroundProgram = NULL;
-static gchar *GdmBackgroundImage = NULL;
-static gchar *GdmBackgroundColor = NULL;
-static gchar *GdmGraphicalTheme = NULL;
-static gchar *GdmInfoMsgFile = NULL;
-static gchar *GdmInfoMsgFont = NULL;
-static gchar *GdmHost = NULL;
-static gchar *GdmHostImageDir = NULL;
-static gchar *GdmHosts = NULL;
-static gchar *GdmGraphicalThemeColor = NULL;
-static gchar *GdmGraphicalThemeDir = NULL;
-static gchar *GdmGraphicalThemes = NULL;
-static gchar *GdmPreFetchProgram = NULL;
-static gchar *GdmUse24Clock = NULL;
-
-static gint GdmPositionX;
-static gint GdmPositionY;
-static gint GdmMinimalUid;
-static gint GdmMaxIconWidth;
-static gint GdmMaxIconHeight;
-static gint GdmBackgroundType;
-static gint GdmScanTime;
-static gint GdmMaxWait;
-static gint GdmFlexiReapDelayMinutes;
-static gint GdmBackgroundProgramInitialDelay = 30;
-static gint GdmBackgroundProgramRestartDelay = 30;
-
-static gboolean GdmAllowGtkThemeChange;
-static gboolean GdmTitleBar;
-static gboolean GdmIncludeAll;
-static gboolean GdmDefaultWelcome;
-static gboolean GdmDefaultRemoteWelcome;
-static gboolean GdmLockPosition;
-static gboolean GdmBackgroundScaleToFit;
-static gboolean GdmBackgroundRemoteOnlyColor;
-static gboolean GdmRunBackgroundProgramAlways;
-static gboolean GdmSetPosition;
-static gboolean GdmQuiver;
-static gboolean GdmShowGnomeFailsafe;
-static gboolean GdmShowXtermFailsafe;
-static gboolean GdmShowLastSession;
-static gboolean GdmEntryCircles;
-static gboolean GdmEntryInvisible;
-static gboolean GdmGraphicalThemeRand;
-static gboolean GdmBroadcast;
-static gboolean GdmAllowAdd;
-static gboolean GdmRestartBackgroundProgram;
-
-/**
- * gdm_config_add_hash
- *
- * Add config value to the val_hash and type_hash.  Strip the key so
- * it doesn't contain a default value.  This function assumes the
- * val_hash, type_hash, and realkey_hash have been initialized.
- */
-static void
-gdm_config_add_hash (gchar *key, gpointer value, GdmConfigType *type)
-{
-   gchar *p;
-   gchar *newkey = g_strdup (key);
-
-   g_strstrip (newkey);
-   p = strchr (newkey, '=');
-   if (p != NULL)
-      *p = '\0';
-
-   g_hash_table_insert (val_hash, newkey, value);
-   g_hash_table_insert (type_hash, newkey, type);
-   g_hash_table_insert (realkey_hash, newkey, key);
-}
-
-/**
- * gdm_config_hash_lookup
- *
- * Accesses hash with key, stripping it so it doesn't contain a default
- * value.
- */
-static gpointer
-gdm_config_hash_lookup (GHashTable *hash,
-                        const gchar *key)
-{
-   gchar *p;
-   gpointer *ret;
-   gchar *newkey = g_strdup (key);
-
-   g_strstrip (newkey);
-   p = strchr (newkey, '=');
-   if (p != NULL)
-      *p = '\0';
-
-   ret = g_hash_table_lookup (hash, newkey);
-   g_free (newkey);
-   return (ret);
-}
-
-/**
- * is_key
- *
- * Since GDM keys sometimes have default values defined in the gdm.h header
- * file (e.g. key=value), this function strips off the "=value" from both 
- * keys passed and compares them, returning TRUE if they are the same, 
- * FALSE otherwise.
- */
-static gboolean
-is_key (const gchar *key1, const gchar *key2)
-{
-   gchar *key1d, *key2d, *p;
-
-   key1d = g_strdup (key1);
-   key2d = g_strdup (key2);
-
-   g_strstrip (key1d);
-   p = strchr (key1d, '=');
-   if (p != NULL)
-      *p = '\0';
-
-   g_strstrip (key2d);
-   p = strchr (key2d, '=');
-   if (p != NULL)
-      *p = '\0';
-
-   if (strcmp (ve_sure_string (key1d), ve_sure_string (key2d)) == 0) {
-      g_free (key1d);
-      g_free (key2d);
-      return TRUE;
-   } else {
-      g_free (key1d);
-      g_free (key2d);
-      return FALSE;
-   }
-}
-
-/**
- * gdm_config_init
- * 
- * Sets up initial hashes used by configuration routines.
- */ 
-static void 
-gdm_config_init (void)
-{
-   gint i;
-   gchar *key_string = NULL; 
-
-   type_hash    = g_hash_table_new (g_str_hash, g_str_equal);
-   val_hash     = g_hash_table_new (g_str_hash, g_str_equal);
-   realkey_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
-   /* boolean values */
-   gdm_config_add_hash (GDM_KEY_ALLOW_REMOTE_ROOT, &GdmAllowRemoteRoot, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALLOW_ROOT, &GdmAllowRoot, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN,
-      &GdmAllowRemoteAutoLogin, &bool_type);
-   gdm_config_add_hash (GDM_KEY_PASSWORD_REQUIRED, &GdmPasswordRequired, &bool_type);
-   gdm_config_add_hash (GDM_KEY_AUTOMATIC_LOGIN_ENABLE,
-      &GdmAutomaticLoginEnable, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALWAYS_RESTART_SERVER,
-      &GdmAlwaysRestartServer, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ADD_GTK_MODULES, &GdmAddGtkModules, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DOUBLE_LOGIN_WARNING,
-      &GdmDoubleLoginWarning, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALWAYS_LOGIN_CURRENT_SESSION,
-      &GdmAlwaysLoginCurrentSession, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DISPLAY_LAST_LOGIN, &GdmDisplayLastLogin, &bool_type);
-   gdm_config_add_hash (GDM_KEY_KILL_INIT_CLIENTS, &GdmKillInitClients, &bool_type);
-   gdm_config_add_hash (GDM_KEY_CONFIG_AVAILABLE, &GdmConfigAvailable, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SYSTEM_MENU, &GdmSystemMenu, &bool_type);
-   gdm_config_add_hash (GDM_KEY_CHOOSER_BUTTON, &GdmChooserButton, &bool_type);
-   gdm_config_add_hash (GDM_KEY_BROWSER, &GdmBrowser, &bool_type);
-   gdm_config_add_hash (GDM_KEY_MULTICAST, &GdmMulticast, &bool_type);
-   gdm_config_add_hash (GDM_KEY_NEVER_PLACE_COOKIES_ON_NFS,
-      &GdmNeverPlaceCookiesOnNfs, &bool_type);
-   gdm_config_add_hash (GDM_KEY_CONSOLE_NOTIFY, &GdmConsoleNotify, &bool_type);
-   gdm_config_add_hash (GDM_KEY_TIMED_LOGIN_ENABLE, &GdmTimedLoginEnable, &bool_type);
-   gdm_config_add_hash (GDM_KEY_CHECK_DIR_OWNER, &GdmCheckDirOwner, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SUPPORT_AUTOMOUNT, &GdmSupportAutomount, &bool_type);
-   gdm_config_add_hash (GDM_KEY_XDMCP, &GdmXdmcp, &bool_type);
-   gdm_config_add_hash (GDM_KEY_INDIRECT, &GdmIndirect, &bool_type);
-   gdm_config_add_hash (GDM_KEY_XDMCP_PROXY, &GdmXdmcpProxy, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DYNAMIC_XSERVERS, &GdmDynamicXservers, &bool_type);
-   gdm_config_add_hash (GDM_KEY_VT_ALLOCATION, &GdmVTAllocation, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DISALLOW_TCP, &GdmDisallowTcp, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_SUCCESS,
-      &GdmSoundOnLoginSuccess, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_FAILURE,
-      &GdmSoundOnLoginFailure, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DEBUG, &GdmDebug, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DEBUG_GESTURES, &GdmDebugGestures, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALLOW_GTK_THEME_CHANGE,
-      &GdmAllowGtkThemeChange, &bool_type);
-   gdm_config_add_hash (GDM_KEY_TITLE_BAR, &GdmTitleBar, &bool_type);
-   gdm_config_add_hash (GDM_KEY_INCLUDE_ALL, &GdmIncludeAll, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_WELCOME, &GdmDefaultWelcome, &bool_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_REMOTE_WELCOME,
-      &GdmDefaultRemoteWelcome, &bool_type);
-   gdm_config_add_hash (GDM_KEY_LOCK_POSITION, &GdmLockPosition, &bool_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_SCALE_TO_FIT,
-      &GdmBackgroundScaleToFit, &bool_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_REMOTE_ONLY_COLOR,
-      &GdmBackgroundRemoteOnlyColor, &bool_type);
-   gdm_config_add_hash (GDM_KEY_RUN_BACKGROUND_PROGRAM_ALWAYS,
-      &GdmRunBackgroundProgramAlways, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SET_POSITION, &GdmSetPosition, &bool_type);
-   gdm_config_add_hash (GDM_KEY_QUIVER, &GdmQuiver, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SHOW_GNOME_FAILSAFE,
-      &GdmShowGnomeFailsafe, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SHOW_XTERM_FAILSAFE,
-      &GdmShowXtermFailsafe, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SHOW_LAST_SESSION,
-      &GdmShowLastSession, &bool_type);
-   gdm_config_add_hash (GDM_KEY_USE_24_CLOCK, &GdmUse24Clock, &string_type);
-   gdm_config_add_hash (GDM_KEY_ENTRY_CIRCLES, &GdmEntryCircles, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ENTRY_INVISIBLE, &GdmEntryInvisible, &bool_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEME_RAND,
-      &GdmGraphicalThemeRand, &bool_type);
-   gdm_config_add_hash (GDM_KEY_BROADCAST, &GdmBroadcast, &bool_type);
-   gdm_config_add_hash (GDM_KEY_ALLOW_ADD, &GdmAllowAdd, &bool_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN, &GdmSoundOnLogin, &bool_type);
-   gdm_config_add_hash (GDM_KEY_RESTART_BACKGROUND_PROGRAM,
-      &GdmRestartBackgroundProgram, &bool_type);
-   gdm_config_add_hash (GDM_KEY_XNEST_UNSCALED_FONT_PATH,
-      &GdmXnestUnscaledFontPath, &bool_type);
-
-   /* string values */
-   gdm_config_add_hash (GDM_KEY_PATH, &GdmPath, &string_type);
-   gdm_config_add_hash (GDM_KEY_ROOT_PATH, &GdmRootPath, &string_type);
-   gdm_config_add_hash (GDM_KEY_CONSOLE_CANNOT_HANDLE,
-      &GdmConsoleCannotHandle, &string_type);
-   gdm_config_add_hash (GDM_KEY_CHOOSER, &GdmChooser, &string_type);
-   gdm_config_add_hash (GDM_KEY_GREETER, &GdmGreeter, &string_type);
-   gdm_config_add_hash (GDM_KEY_CONFIGURATOR, &GdmConfigurator, &string_type);
-   gdm_config_add_hash (GDM_KEY_POSTLOGIN, &GdmPostLogin, &string_type);
-   gdm_config_add_hash (GDM_KEY_PRESESSION, &GdmPreSession, &string_type);
-   gdm_config_add_hash (GDM_KEY_POSTSESSION, &GdmPostSession, &string_type);
-   gdm_config_add_hash (GDM_KEY_FAILSAFE_XSERVER, &GdmFailsafeXserver, &string_type);
-   gdm_config_add_hash (GDM_KEY_X_KEEPS_CRASHING, &GdmXKeepsCrashing, &string_type);
-   gdm_config_add_hash (GDM_KEY_BASE_XSESSION, &GdmBaseXsession, &string_type);
-   gdm_config_add_hash (GDM_KEY_REMOTE_GREETER, &GdmRemoteGreeter, &string_type);
-   gdm_config_add_hash (GDM_KEY_DISPLAY_INIT_DIR, &GdmDisplayInitDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_AUTOMATIC_LOGIN, &GdmAutomaticLogin, &string_type);
-   gdm_config_add_hash (GDM_KEY_GTK_MODULES_LIST, &GdmGtkModulesList, &string_type);
-   gdm_config_add_hash (GDM_KEY_REBOOT, &GdmReboot, &string_type);
-   gdm_config_add_hash (GDM_KEY_HALT, &GdmHalt, &string_type);
-   gdm_config_add_hash (GDM_KEY_SUSPEND, &GdmSuspend, &string_type);
-   gdm_config_add_hash (GDM_KEY_LOG_DIR, &GdmLogDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_PID_FILE, &GdmPidFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_GLOBAL_FACE_DIR, &GdmGlobalFaceDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_SERV_AUTHDIR, &GdmServAuthDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_USER_AUTHDIR, &GdmUserAuthDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_USER_AUTHFILE, &GdmUserAuthFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_USER_AUTHDIR_FALLBACK,
-      &GdmUserAuthFallback, &string_type);
-   gdm_config_add_hash (GDM_KEY_SESSION_DESKTOP_DIR, &GdmSessDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_SESSION, &GdmDefaultSession, &string_type);
-   gdm_config_add_hash (GDM_KEY_MULTICAST_ADDR, &GdmMulticastAddr, &string_type);
-   gdm_config_add_hash (GDM_KEY_USER, &GdmUser, &string_type);
-   gdm_config_add_hash (GDM_KEY_GROUP, &GdmGroup, &string_type);
-   gdm_config_add_hash (GDM_KEY_GTKRC, &GdmGtkRC, &string_type);
-   gdm_config_add_hash (GDM_KEY_GTK_THEME, &GdmGtkTheme, &string_type);
-   gdm_config_add_hash (GDM_KEY_TIMED_LOGIN, &GdmTimedLogin, &string_type);
-   gdm_config_add_hash (GDM_KEY_WILLING, &GdmWilling, &string_type);
-   gdm_config_add_hash (GDM_KEY_XDMCP_PROXY_XSERVER,
-      &GdmXdmcpProxyXserver, &string_type);
-   gdm_config_add_hash (GDM_KEY_XDMCP_PROXY_RECONNECT,
-      &GdmXdmcpProxyReconnect, &string_type);
-   gdm_config_add_hash (GDM_KEY_STANDARD_XSERVER, &GdmStandardXserver, &string_type);
-   gdm_config_add_hash (GDM_KEY_XNEST, &GdmXnest, &string_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_PROGRAM, &GdmSoundProgram, &string_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_FILE,
-      &GdmSoundOnLoginFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE,
-      &GdmSoundOnLoginSuccessFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE,
-      &GdmSoundOnLoginFailureFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_GTK_THEMES_TO_ALLOW,
-      &GdmGtkThemesToAllow, &string_type);
-   gdm_config_add_hash (GDM_KEY_INCLUDE, &GdmInclude, &string_type);
-   gdm_config_add_hash (GDM_KEY_EXCLUDE, &GdmExclude, &string_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_FACE, &GdmDefaultFace, &string_type);
-   gdm_config_add_hash (GDM_KEY_LOCALE_FILE, &GdmLocaleFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_LOGO, &GdmLogo, &string_type);
-   gdm_config_add_hash (GDM_KEY_CHOOSER_BUTTON_LOGO,
-      &GdmChooserButtonLogo, &string_type);
-   gdm_config_add_hash (GDM_KEY_WELCOME, &GdmWelcome, &string_type);
-   gdm_config_add_hash (GDM_KEY_REMOTE_WELCOME, &GdmRemoteWelcome, &string_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_PROGRAM,
-      &GdmBackgroundProgram, &string_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_IMAGE,
-      &GdmBackgroundImage, &string_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_COLOR,
-      &GdmBackgroundColor, &string_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEME,
-      &GdmGraphicalTheme, &string_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEME_DIR,
-      &GdmGraphicalThemeDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEMES,
-      &GdmGraphicalThemes, &string_type);
-   gdm_config_add_hash (GDM_KEY_GRAPHICAL_THEMED_COLOR,
-      &GdmGraphicalThemeColor, &string_type);
-   gdm_config_add_hash (GDM_KEY_INFO_MSG_FILE, &GdmInfoMsgFile, &string_type);
-   gdm_config_add_hash (GDM_KEY_INFO_MSG_FONT, &GdmInfoMsgFont, &string_type);
-   gdm_config_add_hash (GDM_KEY_DEFAULT_HOST_IMG, &GdmHost, &string_type);
-   gdm_config_add_hash (GDM_KEY_HOST_IMAGE_DIR, &GdmHostImageDir, &string_type);
-   gdm_config_add_hash (GDM_KEY_HOSTS, &GdmHosts, &string_type);
-   gdm_config_add_hash (GDM_KEY_PRE_FETCH_PROGRAM,
-      &GdmPreFetchProgram, &string_type);
-   gdm_config_add_hash (GDM_KEY_PAM_STACK, &GdmPamStack, &string_type);
-
-   /* custom command string values */
-   GdmCustomCommands = g_new0 (GdmCustomCmd, GDM_CUSTOM_COMMAND_MAX);   
-   for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
-	   /* For each possible custom command */      
-	   key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i); 
-	   GdmCustomCommands[i].command = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=Custom_%d"), GDM_KEY_CUSTOM_CMD_LABEL_TEMPLATE, i, i); 
-	   GdmCustomCommands[i].command_label = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_label, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=Execute custom command _%d"), GDM_KEY_CUSTOM_CMD_LR_LABEL_TEMPLATE, i, i);
-	   GdmCustomCommands[i].command_lr_label = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_lr_label, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=Are you sure?"), GDM_KEY_CUSTOM_CMD_TEXT_TEMPLATE, i);
-	   GdmCustomCommands[i].command_text = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_text, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=Execute custom command %d"), GDM_KEY_CUSTOM_CMD_TOOLTIP_TEMPLATE, i, i);
-	   GdmCustomCommands[i].command_tooltip = NULL;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_tooltip, &string_type);
-	   
-	   key_string = g_strdup_printf (_("%s%d=false"), GDM_KEY_CUSTOM_CMD_NO_RESTART_TEMPLATE, i);
-	   GdmCustomCommands[i].command_no_restart = FALSE;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_no_restart, &bool_type);  
-
-	   key_string = g_strdup_printf(_("%s%d=false"), GDM_KEY_CUSTOM_CMD_IS_PERSISTENT_TEMPLATE, i);
-	   GdmCustomCommands[i].command_is_persistent = FALSE;
-	   gdm_config_add_hash (key_string, &GdmCustomCommands[i].command_is_persistent, &bool_type); 
-   }   
-
-   /* int values */
-   gdm_config_add_hash (GDM_KEY_XINERAMA_SCREEN, &GdmXineramaScreen, &int_type);
-   gdm_config_add_hash (GDM_KEY_RETRY_DELAY, &GdmRetryDelay, &int_type);
-   gdm_config_add_hash (GDM_KEY_TIMED_LOGIN_DELAY, &GdmTimedLoginDelay, &int_type);
-   gdm_config_add_hash (GDM_KEY_RELAX_PERM, &GdmRelaxPerm, &int_type);
-   gdm_config_add_hash (GDM_KEY_USER_MAX_FILE, &GdmUserMaxFile, &int_type);
-   gdm_config_add_hash (GDM_KEY_DISPLAYS_PER_HOST, &GdmDisplaysPerHost, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_PENDING, &GdmMaxPending, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_WAIT, &GdmMaxWait, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_SESSIONS, &GdmMaxSessions, &int_type);
-   gdm_config_add_hash (GDM_KEY_UDP_PORT, &GdmUdpPort, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_INDIRECT, &GdmMaxIndirect, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_WAIT_INDIRECT, &GdmMaxWaitIndirect, &int_type);
-   gdm_config_add_hash (GDM_KEY_PING_INTERVAL, &GdmPingInterval, &int_type);
-   gdm_config_add_hash (GDM_KEY_FLEXIBLE_XSERVERS, &GdmFlexibleXservers, &int_type);
-   gdm_config_add_hash (GDM_KEY_FIRST_VT, &GdmFirstVt, &int_type);
-   gdm_config_add_hash (GDM_KEY_POSITION_X, &GdmPositionX, &int_type);
-   gdm_config_add_hash (GDM_KEY_POSITION_Y, &GdmPositionY, &int_type);
-   gdm_config_add_hash (GDM_KEY_MINIMAL_UID, &GdmMinimalUid, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_ICON_WIDTH, &GdmMaxIconWidth, &int_type);
-   gdm_config_add_hash (GDM_KEY_MAX_ICON_HEIGHT, &GdmMaxIconHeight, &int_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_TYPE, &GdmBackgroundType, &int_type);
-   gdm_config_add_hash (GDM_KEY_SCAN_TIME, &GdmScanTime, &int_type);
-   gdm_config_add_hash (GDM_KEY_FLEXI_REAP_DELAY_MINUTES,
-      &GdmFlexiReapDelayMinutes, &int_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_PROGRAM_INITIAL_DELAY,
-      &GdmBackgroundProgramInitialDelay, &int_type);
-   gdm_config_add_hash (GDM_KEY_BACKGROUND_PROGRAM_RESTART_DELAY,
-      &GdmBackgroundProgramRestartDelay, &int_type);
-   gdm_config_add_hash (GDM_KEY_XSERVER_TIMEOUT, &GdmXserverTimeout, &int_type);
-}
-
-/**
- * gdm_get_config:
- *
- * Get config file.
- */
-static GKeyFile *
-gdm_get_default_config (void)
-{
-   GKeyFile   *config;
-   GError     *error;
-   struct stat statbuf;
-   int         r;
-
-   /* Not NULL if config_file was set by command-line option. */
-   if (config_file == NULL) {
-      config_file = GDM_DEFAULTS_CONF;
-   }
-
-   error = NULL;
-   config = gdm_common_config_load (config_file, &error);
-
-   if (config == NULL) {
-      gdm_error (_("%s: Unable to load configuration from %s: %s"),
-                 "gdm_config_parse",
-                 config_file,
-                 error->message);
-      g_error_free (error);
-      return NULL;
-   }
-
-   VE_IGNORE_EINTR (r = g_stat (config_file, &statbuf));
-   if (r >= 0) {
-      config_file_mtime = statbuf.st_mtime;
-   }
-
-   return config;
-}
-
-/**
- * gdm_get_custom_config:
- *
- * Get the custom config file where gdmsetup saves its changes and
- * where users are encouraged to make modifications.
- */
-static GKeyFile *
-gdm_get_custom_config (void)
-{
-   GKeyFile   *config;
-   GError     *error;
-   struct stat statbuf;
-   int         r;
-
-   /*
-    * First check to see if the old configuration file name is on
-    * the system.  If so, use that as the custom configuration
-    * file.  "make install" will move this file aside, and 
-    * distros probably can also manage moving this file on
-    * upgrade.
-    *
-    * In case this file is on the system, then use it as
-    * the custom configuration file until the user moves it
-    * aside.  This will likely mean all the defaults in
-    * defaults.conf will not get used since the old gdm.conf
-    * file has all the keys in it (except new ones).  But
-    * that would be what the user wants.
-    */
-
-   error = NULL;
-   config = gdm_common_config_load (GDM_OLD_CONF, &error);
-   if (config != NULL) {
-      custom_config_file = g_strdup (GDM_OLD_CONF);
-   } else {
-      g_error_free (error);
-      error = NULL;
-      config = gdm_common_config_load (GDM_CUSTOM_CONF, &error);
-      if (config != NULL) {
-         custom_config_file = g_strdup (GDM_CUSTOM_CONF);
-      } else {
-         g_error_free (error);
-      }
-   }
-
-   VE_IGNORE_EINTR (r = g_stat (custom_config_file, &statbuf));
-   if (r >= 0) {
-      custom_config_file_mtime = statbuf.st_mtime;
-   }
-
-   return config;
-}
-
-/**
- * gdm_get_per_display_custom_config_file
- *
- * Returns the per-display config file for a given display
- * This is always the custom config file name with the display
- * appended, and never gdm.conf.
- */
-static gchar *
-gdm_get_per_display_custom_config_file (const gchar *display)
-{
-  return g_strdup_printf ("%s%s", custom_config_file, display);
-}
- 
-/**
- * gdm_get_custom_config_file
- *
- * Returns the custom config file being used.
- */
-gchar *
-gdm_get_custom_config_file (void)
-{
-   return custom_config_file;
-}
-
-/**
- * gdm_get_value_int
- *
- * Gets an integer configuration option by key.  The option must
- * first be loaded, say, by calling gdm_config_parse.
- */
-gint
-gdm_get_value_int (const char *key)
-{
-   GdmConfigType *type = gdm_config_hash_lookup (type_hash, key);
-   gpointer val        = gdm_config_hash_lookup (val_hash, key);
-
-   if (type == NULL || val == NULL) {
-      gdm_error ("Request for invalid configuration key %s", key);
-   } else if (*type != CONFIG_INT) {
-      gdm_error ("Request for configuration key %s, but not type INT", key);
-   } else {
-      gint *intval = (int *)val;
-      return *intval;
-   }
-
-   return 0;
-}
-
-/**
- * gdm_get_value_string
- *
- * Gets a string configuration option by key.  The option must
- * first be loaded, say, by calling gdm_config_parse.
- */
-gchar *
-gdm_get_value_string (const char *key)
-{
-   GdmConfigType *type;
-   gpointer val;
-
-   /* First look in translated_hash */
-   if (translated_hash != NULL) {
-      val = gdm_config_hash_lookup (translated_hash, key);
-      if (val) {
-         gchar **charval = (char **)val;
-         return *charval;
-      }
-   }
-
-   type = gdm_config_hash_lookup (type_hash, key);
-   val  = gdm_config_hash_lookup (val_hash, key);
-
-   if (type == NULL || val == NULL) {
-      gdm_error ("Request for invalid configuration key %s", key);
-   } else if (*type != CONFIG_STRING) {
-      gdm_error ("Request for configuration key %s, but not type STRING", key);
-   } else {
-      gchar **charval = (char **)val;
-      return *charval;
-   }
-
-   return NULL;
-}
-
-/**
- * gdm_get_value_bool
- * 
- * Gets a boolean configuration option by key.  The option must
- * first be loaded, say, by calling gdm_config_parse.
- */
-gboolean
-gdm_get_value_bool (const char *key)
-{
-   GdmConfigType *type = gdm_config_hash_lookup (type_hash, key);
-   gpointer val        = gdm_config_hash_lookup (val_hash, key);
-
-   if (type == NULL || val == NULL) {
-      gdm_error ("Request for invalid configuration key %s", key);
-   } else if (*type != CONFIG_BOOL) {
-      gdm_error ("Request for configuration key %s, but not type BOOL", key);
-   } else {
-      gboolean *boolval = (gboolean *)val;
-      return *boolval;
-   }
-
-   return FALSE;
-}
-
-/**
- * Note that some GUI configuration parameters are read by the daemon,
- * and in order for them to work, it is necessary for the daemon to 
- * access a few keys in a per-display fashion.  These access functions
- * allow the daemon to access these keys properly.
- */
-
-/**
- * gdm_get_value_int_per_display
- *
- * Gets the per-display version  of the configuration, or the default
- * value if none exists.
- */
-gint gdm_get_value_int_per_display (const gchar *display,
-                                    const gchar *key)
-{
-   gchar *perdispval;
-
-   gdm_config_key_to_string_per_display (display, key, &perdispval);
-
-   if (perdispval != NULL) {
-      gint val = atoi (perdispval);
-      g_free (perdispval);
-      return val;
-   } else {
-      return (gdm_get_value_int (key));
-   }
-}
- 
-/**
- * gdm_get_value_bool_per_display
- *
- * Gets the per-display version  of the configuration, or the default
- * value if none exists.
- */
-gboolean gdm_get_value_bool_per_display (const gchar *display,
-                                         const gchar *key)
-{
-   gchar *perdispval;
-
-   gdm_config_key_to_string_per_display (display, key, &perdispval);
-
-   if (perdispval != NULL) {
-      if (perdispval[0] == 'T' ||
-          perdispval[0] == 't' ||
-          perdispval[0] == 'Y' ||
-          perdispval[0] == 'y' ||
-          atoi (perdispval) != 0) {
-		g_free (perdispval);
-		return TRUE;
-       } else {
-		return FALSE;
-       }
-   } else {
-      return (gdm_get_value_bool (key));
-   }
-}
- 
-/**
- * gdm_get_value_string_per_display
- *
- * Gets the per-display version  of the configuration, or the default
- * value if none exists.  Note that this value needs to be freed,
- * unlike the non-per-display version.
- */
-gchar * gdm_get_value_string_per_display (const gchar *display,
-                                          const gchar *key)
-{
-   gchar *perdispval;
-
-   gdm_config_key_to_string_per_display (display, key, &perdispval);
-
-   if (perdispval != NULL) {
-      return perdispval;
-   } else {
-      return (g_strdup (gdm_get_value_string (key)));
-   }
-}
-
-/**
- * gdm_config_key_to_string_per_display
- *
- * If the key makes sense to be per-display, return the value,
- * otherwise return NULL.  Keys that only apply to the daemon
- * process do not make sense for per-display configuration  
- * Valid keys include any key in the greeter or gui categories,
- * and the GDM_KEY_PAM_STACK key.
- *
- * If additional keys make sense for per-display usage, make
- * sure they are added to the if-test below.
- */
-void
-gdm_config_key_to_string_per_display (const gchar *display,
-                                      const gchar *key,
-                                      gchar **retval)
-{
-   gchar *file;
-   gchar **splitstr = g_strsplit (key, "/", 2);
-
-   *retval = NULL;
-
-   if (display == NULL)
-      return;
-
-   file = gdm_get_per_display_custom_config_file (display);
-
-   if (strcmp (ve_sure_string (splitstr[0]), "greeter") == 0 ||
-       strcmp (ve_sure_string (splitstr[0]), "gui") == 0 ||
-       is_key (key, GDM_KEY_PAM_STACK)) {
-      gdm_config_key_to_string (file, key, retval);
-   }
-
-   g_free (file);
-
-   return;
-}
-
-/**
- * gdm_config_key_to_string
- *
- * Returns a specific key from the config file, or NULL if not found.
- * Note this returns the value in string form, so the caller needs
- * to parse it properly if it is a bool or int.
- */
-void
-gdm_config_key_to_string (const gchar *file,
-                          const gchar *keystring,
-                          gchar **retval)
-{
-   GKeyFile *config;
-   GdmConfigType *type;
-
-   if (retval != NULL) {
-      *retval = NULL;
-   }
-
-   config = gdm_common_config_load (file, NULL);
-   /* If file doesn't exist, then just return */
-   if (config == NULL)
-      return;
-
-   type = gdm_config_hash_lookup (type_hash, keystring);
-
-   gdm_debug ("Returning value for key <%s>\n", keystring);
-
-   switch (*type) {
-   case CONFIG_BOOL:
-      {
-         gboolean value;
-         gdm_common_config_get_boolean (config, keystring, &value, NULL);
-         if (value)
-            *retval = g_strdup ("true");
-         else
-            *retval = g_strdup ("false");
-      }
-      break;
-   case CONFIG_INT:
-      {
-         gint value;
-         gdm_common_config_get_int (config, keystring, &value, NULL);
-         *retval = g_strdup_printf ("%d", value);
-      }
-      break;
-   case CONFIG_STRING:
-      {
-         gchar *value;
-         gdm_common_config_get_string (config, keystring, &value, NULL);
-         *retval = value;
-      }
-      break;
-   default:
-      break;
-   }
-
-   g_key_file_free (config);
-
-   return;
-}
-
-/**
- * gdm_config_to_string
- *
- * Returns a configuration option as a string.  Used by GDM's
- * GET_CONFIG socket command.
- */
-void
-gdm_config_to_string (const gchar *key,
-                      const gchar *display,
-                      gchar **retval)
-{
-   GdmConfigType *type = gdm_config_hash_lookup (type_hash, key);
-   *retval = NULL;
-
-   /*
-    * See if there is a per-display config file, returning that value
-    * if it exists.
-    */
-   if (display) {
-      gdm_config_key_to_string_per_display (display, key, retval);
-      if (*retval != NULL)
-         return;
-   }
-
-   /* First look in translated_hash */
-   if (translated_hash != NULL) {
-      gpointer val = gdm_config_hash_lookup (translated_hash, key);
-      if (val) {
-         *retval = g_strdup (val);
-         return;
-      }
-   }
-
-   if (type != NULL) {
-      if (*type == CONFIG_BOOL) {
-         gboolean value = gdm_get_value_bool (key);
-         if (value)
-            *retval = g_strdup ("true");
-         else
-            *retval = g_strdup ("false");
-         return;
-      } else if (*type == CONFIG_INT) {
-         gint value = gdm_get_value_int (key);
-         *retval = g_strdup_printf ("%d", value);
-         return;
-      } else if (*type == CONFIG_STRING) {
-         gchar *value = gdm_get_value_string (key);
-         if (value != NULL)
-            *retval = g_strdup (value);
-         return;
-      }
-   }
-
-   gdm_debug ("Error returning config key %s\n", key);
-   return;
-}
-
-/**
- * gdm_compare_displays
- * 
- * Support function for loading displays from the configuration
- * file
- */
-int
-gdm_compare_displays (gconstpointer a, gconstpointer b)
-{
-   const GdmDisplay *d1 = a;
-   const GdmDisplay *d2 = b;
-   if (d1->dispnum < d2->dispnum)
-      return -1;
-   else if (d1->dispnum > d2->dispnum)
-      return 1;
-   else
-      return 0;
-}
-
-/**
- * notify_displays_int
- * notify_displays_string
- *
- * The following two functions will notify the slave programs
- * (gdmgreeter, gdmlogin, etc.) that a configuration option has
- * been changed so the slave can update with the new option
- * value.  GDM does this notify when it receives a
- * GDM_CONFIG_UPDATE socket command from gdmsetup or from the
- * gdmflexiserver --command option.   notify_displays_int
- * is also used for notifying for boolean values.
- */
-static void
-notify_displays_int (const gchar *key, int val)
-{
-   GSList *li;
-   for (li = displays; li != NULL; li = li->next) {
-       GdmDisplay *disp = li->data;
-       if (disp->master_notify_fd >= 0) {
-          gdm_fdprintf (disp->master_notify_fd, "%c%s %d\n",
-                        GDM_SLAVE_NOTIFY_KEY, key, val);
-
-          if (disp != NULL && disp->slavepid > 1)
-             kill (disp->slavepid, SIGUSR2);
-      }
-   }
-}
-
-static void
-notify_displays_string (const gchar *key, const gchar *val)
-{
-   GSList *li;
-   for (li = displays; li != NULL; li = li->next) {
-      GdmDisplay *disp = li->data;
-      if (disp->master_notify_fd >= 0) {
-         if (val == NULL) {
-            gdm_fdprintf (disp->master_notify_fd, "%c%s \n",
-                          GDM_SLAVE_NOTIFY_KEY, key);
-         } else {
-            gdm_fdprintf (disp->master_notify_fd, "%c%s %s\n",
-                          GDM_SLAVE_NOTIFY_KEY, key, val);
-         }
-         if (disp != NULL && disp->slavepid > 1)
-            kill (disp->slavepid, SIGUSR2);
-      }
-   }
-}
-
-/**
- * _gdm_set_value_string
- * _gdm_set_value_bool
- * _gdm_set_value_int
- *
- * The following interfaces are used to set values.  The "doing_update"
- * boolean argument which is only set when GDM_UPDATE_CONFIG is called.
- * If doing_update is TRUE, then a notify is sent to slaves.  When
- * loading values at other times (such as when first loading
- * configuration options) there is no need to notify the slaves.  If
- * there is a desire to send a notify to the slaves, the
- * gdm_update_config function should be used instead of calling these
- * functions directly.
- */
-static void
-_gdm_set_value_string (const gchar *key,
-                       const gchar *value_in,
-                       gboolean doing_update)
-{
-   gchar **setting = gdm_config_hash_lookup (val_hash, key);
-   gchar *setting_copy = NULL;
-   gchar *temp_string;
-   const gchar *value;
-   gint i;
-
-   if (! ve_string_empty (value_in))
-      value = value_in;
-   else
-      value = NULL;
-
-   if (setting == NULL) {
-      gdm_error ("Failure setting key %s to %s", key, value);
-      return;
-   }
-
-   if (*setting != NULL) {
-      /* Free old value */
-      setting_copy = g_strdup (*setting);
-      g_free (*setting);
-   }
-
-   /* User PATH */
-   if (is_key (key, GDM_KEY_PATH)) {
-
-      temp_string = gdm_read_default ("PATH=");
-      if (temp_string != NULL)
-         *setting = temp_string;
-      else if (value != NULL)
-         *setting = g_strdup (value);
-      else
-         *setting = NULL;
-
-   /* Root user PATH */
-   } else if (is_key (key, GDM_KEY_ROOT_PATH)) {
-
-      temp_string = gdm_read_default ("SUPATH=");
-      if (temp_string != NULL)
-         *setting = temp_string;
-      else if (value != NULL)
-         *setting = g_strdup (value);
-      else
-         *setting = NULL;
-
-    /* Location of Xsession script */
-    } else if (is_key (key, GDM_KEY_BASE_XSESSION)) {
-       if (value != NULL) {
-          *setting = g_strdup (value);
-       } else {
-          gdm_info (_("%s: BaseXsession empty; using %s/gdm/Xsession"),
-                      "gdm_config_parse",
-                      GDMCONFDIR);
-          *setting = g_build_filename (GDMCONFDIR,
-                                       "gdm", "Xsession", NULL);
-       }
-
-   /* Halt, Reboot, and Suspend commands */
-   } else if (is_key (key, GDM_KEY_HALT) ||
-              is_key (key, GDM_KEY_REBOOT) ||
-              is_key (key, GDM_KEY_SUSPEND)) {
-       if (value != NULL)
-          *setting = ve_get_first_working_command (value, FALSE);
-       else
-          *setting = NULL;
-
-   /* Console cannot handle these languages */
-   } else if (is_key (key, GDM_KEY_CONSOLE_CANNOT_HANDLE)) {
-       if (value != NULL)
-          *setting = g_strdup (value);
-       else
-          *setting = "";
-       gdm_ok_console_language ();
-
-   /* Location of Xserver */
-   } else if (is_key (key, GDM_KEY_STANDARD_XSERVER)) {
-      gchar *bin = NULL;
-
-      if (value != NULL)
-         bin = ve_first_word (value);
-
-      if G_UNLIKELY (ve_string_empty (bin) ||
-                     g_access (bin, X_OK) != 0) {
-         gdm_info (_("%s: Standard X server not found; trying alternatives"),
-                     "gdm_config_parse");
-         if (g_access ("/usr/X11R6/bin/X", X_OK) == 0) {
-            *setting = g_strdup ("/usr/X11R6/bin/X");
-         } else if (g_access ("/opt/X11R6/bin/X", X_OK) == 0) {
-            *setting = g_strdup ("/opt/X11R6/bin/X");
-         } else if (g_access ("/usr/bin/X11/X", X_OK) == 0) {
-            *setting = g_strdup ("/usr/bin/X11/X");
-         } else
-            *setting = g_strdup (value);
-      } else {
-         *setting = g_strdup (value);
-      }
-
-   /* Graphical Theme Directory */
-   } else if (is_key (key, GDM_KEY_GRAPHICAL_THEME_DIR)) {
-      if (value == NULL ||
-          ! g_file_test (value, G_FILE_TEST_IS_DIR))
-      {
-         *setting = g_strdup (GREETERTHEMEDIR);
-      } else {
-         *setting = g_strdup (value);
-      }
-
-   /* Graphical Theme */
-   } else if (is_key (key, GDM_KEY_GRAPHICAL_THEME)) {
-     if (value == NULL)
-        *setting = g_strdup ("circles");
-     else
-        *setting = g_strdup (value);
-
-   /*
-    * Default Welcome Message.  Don't translate here since the
-    * GDM user may not be running with the same language as the user.
-    * The slave programs will translate the string.
-    */
-   } else if (is_key (key, GDM_KEY_WELCOME)) {
-      if (value != NULL)
-         *setting = g_strdup (value);
-      else
-         *setting = g_strdup (GDM_DEFAULT_WELCOME_MSG);
-
-   /*
-    * Default Remote Welcome Message.  Don't translate here since the 
-    * GDM user may not be running with the same language as the user.
-    * The slave programs will translate the string.
-    */
-   } else if (is_key (key, GDM_KEY_REMOTE_WELCOME)) {
-      if (value != NULL)
-         *setting = g_strdup (value);
-      else
-         *setting = g_strdup (GDM_DEFAULT_REMOTE_WELCOME_MSG);
-
-   /* All others */
-   } else {
-       for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {
-	       gchar * key_string = NULL;
-	       /* For each possible custom command */
-	       key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i);
-	       if (is_key (key, key_string)) {
-		       if (value != NULL)
-			       *setting = ve_get_first_working_command (value, FALSE);
-		       else
-			       *setting = NULL;
-		       break;
-	       }
-	       g_free(key_string);
-       }
-
-       if (value != NULL)
-          *setting = g_strdup (value);
-       else {
-          if (is_key (key, GDM_KEY_GREETER))
-             gdm_error (_("%s: No greeter specified."), "gdm_config_parse");
-          else if (is_key (key, GDM_KEY_REMOTE_GREETER))
-             gdm_error (_("%s: No remote greeter specified."), "gdm_config_parse");
-          else if (is_key (key, GDM_KEY_SESSION_DESKTOP_DIR))
-             gdm_error (_("%s: No sessions directory specified."), "gdm_config_parse");
-
-          *setting = NULL;
-       }
-   }
-
-   /* Handle update */
-   if (doing_update == TRUE && 
-       strcmp (ve_sure_string (*setting),
-               ve_sure_string (setting_copy)) != 0) {
-
-      if (is_key (key, GDM_KEY_GREETER))
-         notify_displays_string (GDM_NOTIFY_GREETER, *setting);
-      else if (is_key (key, GDM_KEY_REMOTE_GREETER))
-         notify_displays_string (GDM_NOTIFY_REMOTE_GREETER, *setting);
-      else if (is_key (key, GDM_KEY_SOUND_ON_LOGIN_FILE))
-         notify_displays_string (GDM_NOTIFY_SOUND_ON_LOGIN_FILE, *setting);
-      else if (is_key (key, GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE))
-         notify_displays_string (GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE, *setting);
-      else if (is_key (key, GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE))
-         notify_displays_string (GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE, *setting);
-      else if (is_key (key, GDM_KEY_GTK_MODULES_LIST))
-         notify_displays_string (GDM_NOTIFY_GTK_MODULES_LIST, *setting);
-      else if (is_key (key, GDM_KEY_TIMED_LOGIN))
-         notify_displays_string (GDM_NOTIFY_TIMED_LOGIN, *setting);
-
-      for (i = 0; i < GDM_CUSTOM_COMMAND_MAX; i++) {	   	   
-	      gchar * key_string = NULL;
-	      /* For each possible custom command */     
-	      key_string = g_strdup_printf (_("%s%d="), GDM_KEY_CUSTOM_CMD_TEMPLATE, i); 
-	      if (is_key (key, key_string)) {
-		      g_free(key_string);
-		      key_string = g_strdup_printf (_("%s%d"), GDM_NOTIFY_CUSTOM_CMD_TEMPLATE, i);
-		      notify_displays_string (key_string, *setting);
-		      break;
-	      }
-	      g_free(key_string);
-      }       
-   }
-
-   if (setting_copy != NULL)
-      g_free (setting_copy);
-
-   if (*setting == NULL)
-      gdm_debug ("set config key %s to string <NULL>", key);
-   else
-      gdm_debug ("set config key %s to string %s", key, *setting);
-}
-
-void
-gdm_set_value_string (const gchar *key,
-                      const gchar *value_in)
-{
-   _gdm_set_value_string (key, value_in, TRUE);
-}
-
-static void
-_gdm_set_value_bool (const gchar *key,
-                     gboolean value,
-                     gboolean doing_update)
-{
-   gboolean *setting     = gdm_config_hash_lookup (val_hash, key);
-   gboolean setting_copy = *setting;
-   gchar *temp_string;
-
-   if (setting == NULL) {
-      if (value)
-         gdm_error ("Failure setting key %s to true", key);
-      else
-         gdm_error ("Failure setting key %s to false", key);
-      return;
-   }
-
-   /* Password Required */
-   if (is_key (key, GDM_KEY_PASSWORD_REQUIRED)) {
-      temp_string = gdm_read_default ("PASSREQ=");
-      if (temp_string == NULL)
-         *setting = value;
-      else if (g_ascii_strcasecmp (temp_string, "YES") == 0)
-         *setting = TRUE;
-      else
-         *setting = FALSE;
-      g_free (temp_string);
-
-   /* Allow root login */
-   } else if (is_key (key, GDM_KEY_ALLOW_REMOTE_ROOT)) {
-      temp_string = gdm_read_default ("CONSOLE=");
-
-      if (temp_string == NULL)
-         *setting = value;
-      else if (g_ascii_strcasecmp (temp_string, "/dev/console") != 0)
-         *setting = TRUE;
-      else
-         *setting = FALSE;
-      g_free (temp_string);
-
-   /* XDMCP */
-#ifndef HAVE_LIBXDMCP
-   } else if (is_key (key, GDM_KEY_XDMCP)) {
-      if (value) {
-         gdm_info (_("%s: XDMCP was enabled while there is no XDMCP support; turning it off"), "gdm_config_parse");
-      }
-      *setting = FALSE;
-#endif
-   } else {
-      *setting = value;
-   }
-
-   /* Handle update */
-   if (doing_update == TRUE && *setting != setting_copy) {
-     if (is_key (key, GDM_KEY_ALLOW_ROOT))
-        notify_displays_int (GDM_NOTIFY_ALLOW_ROOT, *setting);
-     else if (is_key (key, GDM_KEY_ALLOW_REMOTE_ROOT))
-        notify_displays_int (GDM_NOTIFY_ALLOW_REMOTE_ROOT, *setting);
-     else if (is_key (key, GDM_KEY_ALLOW_REMOTE_AUTOLOGIN))
-        notify_displays_int (GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN, *setting);
-     else if (is_key (key, GDM_KEY_SYSTEM_MENU))
-        notify_displays_int (GDM_NOTIFY_SYSTEM_MENU, *setting);
-     else if (is_key (key, GDM_KEY_CONFIG_AVAILABLE))
-        notify_displays_int (GDM_NOTIFY_CONFIG_AVAILABLE, *setting);
-     else if (is_key (key, GDM_KEY_CHOOSER_BUTTON))
-        notify_displays_int (GDM_NOTIFY_CHOOSER_BUTTON, *setting); 
-     else if (is_key (key, GDM_KEY_DISALLOW_TCP))
-        notify_displays_int (GDM_NOTIFY_DISALLOW_TCP, *setting);
-     else if (is_key (key, GDM_KEY_ADD_GTK_MODULES))
-        notify_displays_int (GDM_NOTIFY_ADD_GTK_MODULES, *setting);
-     else if (is_key (key, GDM_KEY_TIMED_LOGIN_ENABLE))
-        notify_displays_int (GDM_NOTIFY_TIMED_LOGIN_ENABLE, *setting);
-   }
-
-   if (*setting)
-      gdm_debug ("set config key %s to boolean true", key);
-   else
-      gdm_debug ("set config key %s to boolean false", key);
-}
-
-void
-gdm_set_value_bool (const gchar *key,
-                    gboolean value)
-{
-   _gdm_set_value_bool (key, value, TRUE);
-}
-
-static void
-_gdm_set_value_int (const gchar *key,
-                    gint value,
-                    gboolean doing_update)
-{
-   gint *setting     = gdm_config_hash_lookup (val_hash, key);
-   gint setting_copy = *setting;
-
-   if (setting == NULL) {
-      gdm_error ("Failure setting key %s to %d", key, value);
-      return;
-   }
-
-   if (is_key (key, GDM_KEY_MAX_INDIRECT) ||
-       is_key (key, GDM_KEY_XINERAMA_SCREEN)) {
-      if (value < 0)
-         *setting = 0;
-      else
-         *setting = value;
-   } else if (is_key (key, GDM_KEY_TIMED_LOGIN_DELAY)) {
-      if (value < 5) {
-         gdm_info (_("%s: TimedLoginDelay is less than 5, defaulting to 5."), "gdm_config_parse");
-         *setting = 5;
-      } else
-         *setting = value;
-   } else if (is_key (key, GDM_KEY_MAX_ICON_WIDTH) ||
-              is_key (key, GDM_KEY_MAX_ICON_HEIGHT)) {
-      if (value < 0)
-         *setting = 128;
-      else
-         *setting = value;
-   } else if (is_key (key, GDM_KEY_SCAN_TIME)) {
-      if (value < 1)
-         *setting = 1;
-      else
-         *setting = value;
-   }
- else {
-      *setting = value;
-   }
- 
-   /* Handle update */
-   if (doing_update == TRUE && *setting != setting_copy) {
-      if (is_key (key, GDM_KEY_RETRY_DELAY))
-         notify_displays_int (GDM_NOTIFY_RETRY_DELAY, *setting);
-      else if (is_key (key, GDM_KEY_TIMED_LOGIN_DELAY))
-         notify_displays_int (GDM_NOTIFY_TIMED_LOGIN_DELAY, *setting);
-   }
-
-   gdm_debug ("set config key %s to integer %d", key, *setting);
-}
-
-void
-gdm_set_value_int (const gchar *key,
-                   gint value)
-{
-   _gdm_set_value_int (key, value, TRUE);
-}
-
-
-
-/**
- * gdm_set_value
- *
- * This functon is used to set the config values in the hash.  This is called
- * at initial config load time or when gdm_update_config is called to reload
- * them.   It adds translated strings to the hash with their proper keys
- * (greeter/Welcome[cs] for example).
- */
-static gboolean
-gdm_set_value (GKeyFile      *config,
-               GdmConfigType *type,
-               const gchar   *fullkey,
-               gboolean       doing_update)
-{
-   gchar * realkey;
-   gchar *value;
-
-   realkey = gdm_config_hash_lookup (realkey_hash, fullkey);
-
-   if (realkey == NULL) {
-      return FALSE;
-   }
-
-   if (*type == CONFIG_BOOL) {
-      gboolean value;
-      gdm_common_config_get_boolean (config, realkey, &value, NULL);
-      _gdm_set_value_bool (fullkey, value, doing_update);
-      return TRUE;
-   } else if (*type == CONFIG_INT) {
-      gint value;
-      gdm_common_config_get_int (config, realkey, &value, NULL);
-      _gdm_set_value_int (fullkey, value, doing_update);
-      return TRUE;
-   } else if (*type == CONFIG_STRING) {
-
-      /* Process translated strings */
-      if (is_key (fullkey, GDM_KEY_WELCOME) ||
-          is_key (fullkey, GDM_KEY_REMOTE_WELCOME)) {
-         gchar **keys;
-         gsize   length;
-         gchar  *prefix, *basekey;
-         int     i;
-
-         keys = g_key_file_get_keys (config, "greeter", &length, NULL);
-
-         if (is_key (fullkey, GDM_KEY_WELCOME)) {
-            basekey = g_strdup ("Welcome");
-            prefix  = g_strdup ("Welcome[");
-         } else {
-            basekey = g_strdup ("RemoteWelcome");
-            prefix  = g_strdup ("RemoteWelcome[");
-         }
-
-          /*
-           * Loop over translated keys and put all values into the hash
-           * Probably should loop through the hashs and delete any old values,
-           * but this just means that if a translation is deleted from the
-           * config, GDM won't forget about it until restart.  I don't think
-           * this will happen, or be a real problem if it does.
-           */
-         for (i = 0; i < length; i++) {
-            gchar *key;
-
-            key = keys[i];
-
-            if (g_str_has_prefix (key, prefix) &&
-                g_str_has_suffix (key, "]")) {
-               gchar *transkey, *transvalue;
-
-               if (translated_hash == NULL)
-                  translated_hash = g_hash_table_new (g_str_hash, g_str_equal);
-
-               transkey = g_strdup_printf ("greeter/%s", key);
-               gdm_common_config_get_string (config, transkey, &transvalue, NULL);
-
-               g_hash_table_remove (translated_hash, transkey);
-
-               /*
-                * Store translated values in a separate hash.  Note that we load
-                * the initial values via a g_hash_table_foreach function, so if
-                * we add these to the same hash, we would end up loading these
-                * values in again a second time.
-                */
-               g_hash_table_insert (translated_hash, transkey, transvalue);
-            }
-         }
-
-         g_strfreev (keys);
-         g_free (basekey);
-         g_free (prefix);
-      }
-
-      /* Handle non-translated strings as normal */
-      gdm_common_config_get_string (config, realkey, &value, NULL);
-      _gdm_set_value_string (fullkey, value, doing_update);
-      return TRUE;
-   }
-
-   return FALSE;
-}
-
-/**
- * gdm_find_xserver
- *
- * Return an xserver with a given ID, or NULL if not found.
- */
-GdmXserver *
-gdm_find_xserver (const gchar *id)
-{
-   GSList *li;
-
-   if (xservers == NULL)
-      return NULL;
-
-   if (id == NULL)
-      return xservers->data;
-
-   for (li = xservers; li != NULL; li = li->next) {
-      GdmXserver *svr = li->data;
-      if (strcmp (ve_sure_string (svr->id), ve_sure_string (id)) == 0)
-         return svr;
-   }
-   return NULL;
-}
-
-/**
- * gdm_get_xservers
- *
- * Prepare a string to be returned for the GET_SERVER_LIST
- * sockets command.
- */
-gchar *
-gdm_get_xservers (void)
-{
-   GSList *li;
-   gchar *retval = NULL;
-
-   if (xservers == NULL)
-      return NULL;
-
-   for (li = xservers; li != NULL; li = li->next) {
-      GdmXserver *svr = li->data;
-      if (retval != NULL)
-         retval = g_strconcat (retval, ";", svr->id, NULL);
-      else
-         retval = g_strdup (svr->id);
-   }
-
-   return retval;
-}
-
-/* PRIO_MIN and PRIO_MAX are not defined on Solaris, but are -20 and 20 */
-#if sun
-#ifndef PRIO_MIN
-#define PRIO_MIN -20
-#endif
-#ifndef PRIO_MAX
-#define PRIO_MAX 20
-#endif
-#endif
-
-/**
- * gdm_load_xservers
- *
- * Load [server-foo] sections from a configuration file.
- */
-static void
-gdm_load_xservers (GKeyFile *config)
-{
-   int i;
-   gsize length;
-   char **groups;
-
-   /* Find server definitions */
-   groups = g_key_file_get_groups (config, &length);
-
-   for (i = 0; i < length; i++) {
-      gchar *id;
-      const char *sec = groups [i];
-
-      if (strncmp (sec, "server-", strlen ("server-")) != 0) {
-         continue;
-      }
-
-      id = g_strdup (sec + strlen ("server-"));
-
-      /*
-       * See if we already loaded a server with this id, skip if
-       * one already exists.
-       */
-      if (gdm_find_xserver (id) != NULL) {
-         g_free (id);
-      } else {
-         GdmXserver *svr = g_new0 (GdmXserver, 1);
-         gchar buf[256];
-         int n;
-
-         svr->id = id;
-
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_NAME, sec);
-         gdm_common_config_get_string (config, buf, &svr->name, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_COMMAND, sec);
-         gdm_common_config_get_string (config, buf, &svr->command, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_FLEXIBLE, sec);
-         gdm_common_config_get_boolean (config, buf, &svr->flexible, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_CHOOSABLE, sec);
-         gdm_common_config_get_boolean (config, buf, &svr->choosable, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_HANDLED, sec);
-         gdm_common_config_get_boolean (config, buf, &svr->handled, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_CHOOSER, sec);
-         gdm_common_config_get_boolean (config, buf, &svr->chooser, NULL);
-         g_snprintf (buf, sizeof (buf), "%s/" GDM_KEY_SERVER_PRIORITY, sec);
-         gdm_common_config_get_int (config, buf, &svr->priority, NULL);
-
-         /* do some bounds checking */
-         n = svr->priority;
-         if (n < PRIO_MIN)
-            n = PRIO_MIN;
-         else if (n > PRIO_MAX)
-            n = PRIO_MAX;
-         if (n != svr->priority) {
-            gdm_error (_("%s: Priority out of bounds; changed to %d"),
-                       "gdm_config_parse", n);
-            svr->priority = n;
-         }
-
-         if (ve_string_empty (svr->command)) {
-            gdm_error (_("%s: Empty server command; "
-                         "using standard command."), "gdm_config_parse");
-            g_free (svr->command);
-            svr->command = g_strdup (GdmStandardXserver);
-         }
-
-         xservers = g_slist_append (xservers, svr);
-      }
-   }
-
-   g_strfreev (groups);
-}
-
-/**
- * gdm_update_xservers
- *
- * Reload [server-foo] sections from the configuration files.
- */
-static void
-gdm_update_xservers (GKeyFile *cfg,
-                     GKeyFile *custom_cfg)
-{
-   GSList *xli;
-
-   /* Free list if already loaded */
-   if (xservers != NULL) {
-      for (xli = xservers; xli != NULL; xli = xli->next) {
-         GdmXserver *xsvr = xli->data;
-
-         g_free (xsvr->id);
-         g_free (xsvr->name);
-         g_free (xsvr->command);
-      }
-      g_slist_free (xservers);
-      xservers = NULL;
-   }
-
-   /* Reload first from custom_cfg then from cfg. */
-   if (custom_cfg != NULL)
-      gdm_load_xservers (custom_cfg);
-
-   if (cfg != NULL)
-      gdm_load_xservers (cfg);
-
-   /* If no "Standard" server was created, then add it */
-   if (xservers == NULL || gdm_find_xserver (GDM_STANDARD) == NULL) {
-      GdmXserver *svr = g_new0 (GdmXserver, 1);
-
-      svr->id        = g_strdup (GDM_STANDARD);
-      svr->name      = g_strdup ("Standard server");
-      svr->command   = g_strdup (GdmStandardXserver);
-      svr->flexible  = TRUE;
-      svr->choosable = TRUE;
-      svr->handled   = TRUE;
-      svr->priority  = 0;
-      xservers       = g_slist_append (xservers, svr);
-   }
-}
-
-/**
- * gdm_update_config
- *
- * Will cause a the GDM daemon to re-read the key from the configuration
- * file and cause notify signal to be sent to the slaves for the 
- * specified key, if appropriate.  Only specific keys defined in the
- * gdm_set_value functions above are associated with such notification.
- * Obviously notification is not needed for configuration options only
- * used by the daemon.  This function is called when the UPDDATE_CONFIG
- * sockets command is called.
- *
- * To add a new notification, a GDM_NOTIFY_* argument will need to be
- * defined in gdm.h, supporting logic placed in the gdm_set_value
- * functions and in the gdm_slave_handle_notify function in slave.c.
- */
-gboolean
-gdm_update_config (const gchar *key)
-{
-   GdmConfigType *type;
-   struct stat statbuf, custom_statbuf;
-   GKeyFile *cfg;
-   GKeyFile *custom_cfg;
-   gboolean rc;
-
-   rc = FALSE;
-   cfg = NULL;
-   custom_cfg = NULL;
-
-   /*
-    * Do not allow these keys to be updated, since GDM would need
-    * additional work, or at least heavy testing, to make these keys
-    * flexible enough to be changed at runtime.
-    */
-   if (is_key (key, GDM_KEY_PID_FILE) ||
-       is_key (key, GDM_KEY_CONSOLE_NOTIFY) ||
-       is_key (key, GDM_KEY_USER) ||
-       is_key (key, GDM_KEY_GROUP) ||
-       is_key (key, GDM_KEY_LOG_DIR) ||
-       is_key (key, GDM_KEY_SERV_AUTHDIR) ||
-       is_key (key, GDM_KEY_USER_AUTHDIR) ||
-       is_key (key, GDM_KEY_USER_AUTHFILE) ||
-       is_key (key, GDM_KEY_USER_AUTHDIR_FALLBACK)) {
-      return FALSE;
-   }
-
-   /* See if custom file is now there */
-   if (custom_config_file == NULL) {
-      custom_cfg = gdm_get_custom_config ();
-   }
-
-   /* Don't bother re-reading configuration if files have not changed */
-   VE_IGNORE_EINTR (g_stat (config_file, &statbuf));
-   VE_IGNORE_EINTR (g_stat (custom_config_file, &custom_statbuf));
-
-  /*
-   * Do not reset mtime to the latest values since there is no
-   * guarantee that only one key was modified since last write.
-   * This check simply avoids re-reading the files if neither
-   * has changed since GDM was started.
-   */
-   if (config_file_mtime        == statbuf.st_mtime &&
-       custom_config_file_mtime == custom_statbuf.st_mtime) {
-      rc = TRUE;
-      goto out;
-   }
-
-   /* Shortcut for updating all XDMCP parameters */
-   if (is_key (key, "xdmcp/PARAMETERS")) {
-      gdm_update_config (GDM_KEY_DISPLAYS_PER_HOST);
-      gdm_update_config (GDM_KEY_MAX_PENDING);
-      gdm_update_config (GDM_KEY_MAX_WAIT);
-      gdm_update_config (GDM_KEY_MAX_SESSIONS);
-      gdm_update_config (GDM_KEY_INDIRECT);
-      gdm_update_config (GDM_KEY_MAX_INDIRECT);
-      gdm_update_config (GDM_KEY_MAX_WAIT_INDIRECT);
-      gdm_update_config (GDM_KEY_PING_INTERVAL);
-      rc = TRUE;
-      goto out;
-   }
-
-   if (custom_config_file != NULL) {
-      custom_cfg = gdm_common_config_load (custom_config_file, NULL);
-   }
-
-   if (is_key (key, "xservers/PARAMETERS")) {
-      cfg = gdm_common_config_load (config_file, NULL);
-
-      gdm_update_xservers (cfg, custom_cfg);
-
-      rc = TRUE;
-      goto out;
-   }
-
-   type = gdm_config_hash_lookup (type_hash, key);
-   if (type == NULL)
-      return FALSE;
-
-   /* First check the custom file */
-   if (custom_cfg != NULL) {
-      char *config_group;
-      char *config_key;
-      gboolean has_key;
-
-      config_group = config_key = NULL;
-      if (! gdm_common_config_parse_key_string (key, &config_group, &config_key, NULL)) {
-         rc = FALSE;
-         goto out;
-      }
-
-      has_key = g_key_file_has_key (custom_cfg, config_group, config_key, NULL);
-      g_free (config_group);
-      g_free (config_key);
-
-      if (has_key) {
-         rc = gdm_set_value (custom_cfg, type, key, TRUE);
-         goto out;
-      }
-   }
-
-   /* If not in the custom file, check main config file */
-   cfg = gdm_common_config_load (config_file, NULL);
-
-   rc = gdm_set_value (cfg, type, key, TRUE);
-
- out:
-   if (cfg != NULL)
-      g_key_file_free (cfg);
-
-   if (custom_cfg != NULL)
-      g_key_file_free (custom_cfg);
-
-   return rc;
-}
-
-/**
- * check_logdir
- * check_servauthdir
- *
- * Support functions for gdm_config_parse.
- */
-static void
-check_logdir (void)
-{
-        struct stat statbuf;
-        int r;
-
-        VE_IGNORE_EINTR (r = g_stat (GdmLogDir, &statbuf));
-        if (r < 0 ||
-            ! S_ISDIR (statbuf.st_mode))  {
-                gdm_error (_("%s: Logdir %s does not exist or isn't a directory.  Using ServAuthDir %s."), "gdm_config_parse",
-                           GdmLogDir, GdmServAuthDir);
-                g_free (GdmLogDir);
-                GdmLogDir = g_strdup (GdmServAuthDir);
-        }
-}
-
-static void
-check_servauthdir (struct stat *statbuf)
-{
-    int r;
-
-    /* Enter paranoia mode */
-    VE_IGNORE_EINTR (r = g_stat (GdmServAuthDir, statbuf));
-    if G_UNLIKELY (r < 0) {
-            if (GdmConsoleNotify) {
-               gchar *s = g_strdup_printf
-                       (C_(N_("Server Authorization directory "
-                              "(daemon/ServAuthDir) is set to %s "
-                              "but this does not exist. Please "
-                              "correct GDM configuration and "
-                              "restart GDM.")), GdmServAuthDir);
-
-               gdm_text_message_dialog (s);
-               g_free (s);
-            }
-
-            GdmPidFile = NULL;
-            gdm_fail (_("%s: Authdir %s does not exist. Aborting."), "gdm_config_parse", GdmServAuthDir);
-    }
-
-    if G_UNLIKELY (! S_ISDIR (statbuf->st_mode)) {
-            if (GdmConsoleNotify) {
-               gchar *s = g_strdup_printf
-                       (C_(N_("Server Authorization directory "
-                              "(daemon/ServAuthDir) is set to %s "
-                              "but this is not a directory. Please "
-                              "correct GDM configuration and "
-                              "restart GDM.")), GdmServAuthDir);
-
-                gdm_text_message_dialog (s);
-                g_free (s);
-            }
-
-            GdmPidFile = NULL;
-            gdm_fail (_("%s: Authdir %s is not a directory. Aborting."), "gdm_config_parse", GdmServAuthDir);
-    }
-}
-
-typedef struct _GdmConfigFiles {
-   GKeyFile *cfg;
-   GKeyFile *custom_cfg;
-} GdmConfigFiles;
-
-/**
- * gdm_load_displays
- *
- * Load the displays section of the config file
- */
-static void
-gdm_load_displays (GKeyFile *cfg,
-                   char    **keys)
-{
-   GSList *li2;
-   int i;
-
-   for (i = 0; keys[i] != NULL; i++) {
-      const gchar *key = keys[i];
-
-      gdm_debug ("Loading display for key '%s'", key);
-      if (isdigit (*key)) {
-         gchar *fullkey;
-         gchar *dispval;
-         int keynum = atoi (key);
-         gboolean skip_entry = FALSE;
-         GError *error;
-
-         fullkey = g_strdup_printf ("%s/%s", GDM_KEY_SECTION_SERVERS, key);
-         dispval = NULL;
-         error = NULL;
-         gdm_common_config_get_string (cfg, fullkey, &dispval, &error);
-         if (error != NULL) {
-            gdm_error ("Unable to get name for server '%s': %s", fullkey, error->message);
-         }
-         g_free (fullkey);
-
-         gdm_debug ("Got name for server: %s", dispval);
-         /* Do not add if already in the list */
-         for (li2 = displays; li2 != NULL; li2 = li2->next) {
-            GdmDisplay *disp = li2->data;
-            if (disp->dispnum == keynum) {
-               skip_entry = TRUE;
-               break;
-            }
-         }
-
-         /* Do not add if this display was marked as inactive already */
-         for (li2 = displays_inactive; li2 != NULL; li2 = li2->next) {
-            gchar *disp = li2->data;
-            if (atoi (disp) == keynum) {
-               skip_entry = TRUE;
-               break;
-            }
-         }
-
-         if (skip_entry == TRUE) {
-            g_free (dispval);
-            continue;
-         }
-
-         if (g_ascii_strcasecmp (ve_sure_string (dispval), "inactive") == 0) {
-            gdm_debug ("display %s is inactive", key);
-            displays_inactive = g_slist_append (displays_inactive, g_strdup (key));
-         } else {
-            GdmDisplay *disp = gdm_server_alloc (keynum, dispval);
-
-            if (disp == NULL)
-               continue;
-
-            displays = g_slist_insert_sorted (displays, disp, gdm_compare_displays);
-            if (keynum > high_display_num)
-               high_display_num = keynum;
-         }
-
-         g_free (dispval);
-
-      } else {
-        gdm_info (_("%s: Invalid server line in config file. Ignoring!"), "gdm_config_parse");
-      }
-   }
-}
-
-/**
- * gdm_load_config_option
- *
- * Called by gdm_config_parse in a loop to set each key.
- */
-static void
-gdm_load_config_option (gpointer key_in, gpointer value_in, gpointer data)
-{
-   gchar *key               = (gchar *)key_in;
-   GdmConfigType *type      = (GdmConfigType *)value_in;
-   GdmConfigFiles *cfgfiles = (GdmConfigFiles *)data;
-   gboolean custom_retval;
-
-   if (type != NULL) {
-      /* First check the custom file */
-      if (cfgfiles->custom_cfg != NULL) {
-         gchar *config_group;
-         gchar *config_key;
-         gboolean has_key;
-
-         config_group = config_key = NULL;
-         if (! gdm_common_config_parse_key_string (key_in, &config_group, &config_key, NULL)) {
-            return;
-         }
-
-         has_key = g_key_file_has_key (cfgfiles->custom_cfg, config_group, config_key, NULL);
-         g_free (config_group);
-         g_free (config_key);
-
-         if (has_key) {
-            custom_retval = gdm_set_value (cfgfiles->custom_cfg, type, key, FALSE);
-            return;
-         }
-      }
-
-      /* If not in the custom file, check main config file */
-      if (gdm_set_value (cfgfiles->cfg, type, key, FALSE))
-         return;
-   }
-
-   gdm_error ("Cannot set config option %s", key);
-}
-
-/**
- * gdm_config_parse
- *
- * Loads initial configuration settings.
- */
-void
-gdm_config_parse (void)
-{
-   GdmConfigFiles cfgfiles;
-   GKeyFile *cfg;
-   GKeyFile *custom_cfg;
-   struct passwd *pwent;
-   struct group *grent;
-   struct stat statbuf;
-   gchar *bin;
-
-   /* Init structures for configuration data */
-   gdm_config_init ();
-
-   displays          = NULL;
-   high_display_num  = 0;
-
-   /*
-    * It is okay if the custom_cfg file is missing, then just use
-    * main configuration file. However if main config file does 
-    * not exist we cannot continue and need to bail out.
-    */
-
-   cfg = gdm_get_default_config ();
-
-   if (cfg == NULL)
-	   gdm_fail (_("%s: Main config file (defaults.conf) is missing. Aborting!"), "gdm_config_parse");
-
-   custom_cfg = gdm_get_custom_config ();
-
-   cfgfiles.cfg = cfg;
-   cfgfiles.custom_cfg = custom_cfg;
-
-   /* Loop over all configuration options and load them */
-   g_hash_table_foreach (type_hash, gdm_load_config_option, &cfgfiles);
-
-   /* Load server-foo sections */
-   gdm_update_xservers (cfg, custom_cfg);
-
-   /* Only read the list if no_console is FALSE at this stage */
-   if (! no_console) {
-      char  **keys;
-      GError *error;
-      GSList *li2;
-      gsize   len;
-
-      /* Find static X server definitions */
-      if (custom_cfg != NULL) {
-         error = NULL;
-         keys = g_key_file_get_keys (custom_cfg, GDM_KEY_SECTION_SERVERS, &len, &error);
-         if (error != NULL) {
-            gdm_error ("Unable to load server list: %s", error->message);
-            g_error_free (error);
-         }
-         if (keys != NULL) {
-            gdm_load_displays (custom_cfg, keys);
-         }
-         g_strfreev (keys);
-      }
-
-      error = NULL;
-      keys = g_key_file_get_keys (cfg, GDM_KEY_SECTION_SERVERS, &len, &error);
-      if (error != NULL) {
-         gdm_error ("Unable to load server list: %s", error->message);
-         g_error_free (error);
-      }
-      if (keys != NULL) {
-         gdm_load_displays (cfg, keys);
-      }
-
-      g_strfreev (keys);
-
-      /* Free list of inactive, not needed anymore */
-      for (li2 = displays_inactive; li2 != NULL; li2 = li2->next) {
-         gchar *disp = li2->data;
-         g_free (disp);
-      }
-      g_slist_free (displays_inactive);
-   }
-
-   if G_UNLIKELY ((displays == NULL) && (! GdmXdmcp) && (!GdmDynamicXservers)) {
-      gchar *server = NULL;
-
-      /*
-       * If we requested no static servers (there is no console),
-       * then don't display errors in console messages
-       */
-      if (no_console) {
-         gdm_fail (_("%s: XDMCP disabled and no static servers defined. Aborting!"), "gdm_config_parse");
-      }
-
-      bin = ve_first_word (GdmStandardXserver);
-      if G_LIKELY (g_access (bin, X_OK) == 0) {
-         server = GdmStandardXserver;
-      } else if (g_access ("/usr/bin/X11/X", X_OK) == 0) {
-         server = "/usr/bin/X11/X";
-      } else if (g_access ("/usr/X11R6/bin/X", X_OK) == 0) {
-         server = "/usr/X11R6/bin/X";
-      } else if (g_access ("/opt/X11R6/bin/X", X_OK) == 0) {
-         server = "/opt/X11R6/bin/X";
-      }
-      g_free (bin);
-
-      /* yay, we can add a backup emergency server */
-      if (server != NULL) {
-         int num = gdm_get_free_display (0 /* start */, 0 /* server uid */);
-         gdm_error (_("%s: XDMCP disabled and no static servers defined. Adding %s on :%d to allow configuration!"),
-                      "gdm_config_parse", server, num);
-
-         gdm_emergency_server = TRUE;
-         displays = g_slist_append (displays, gdm_server_alloc (num, server));
-         /* ALWAYS run the greeter and don't log anyone in,
-          * this is just an emergency session */
-         g_free (GdmAutomaticLogin);
-         g_free (GdmTimedLogin);
-         GdmAutomaticLogin = NULL;
-         GdmTimedLogin     = NULL;
-      } else {
-         if (GdmConsoleNotify) {
-            gchar *s = g_strdup_printf (C_(N_("XDMCP is disabled and GDM "
-                                      "cannot find any static server "
-                                      "to start.  Aborting!  Please "
-                                      "correct the configuration "
-                                      "and restart GDM.")));
-            gdm_text_message_dialog (s);
-            g_free (s);
-         }
-
-         GdmPidFile = NULL;
-         gdm_fail (_("%s: XDMCP disabled and no static servers defined. Aborting!"), "gdm_config_parse");
-      }
-   }
-
-   /* If no displays were found, then obviously
-      we're in a no console mode */
-   if (displays == NULL)
-      no_console = TRUE;
-
-   if (no_console)
-      GdmConsoleNotify = FALSE;
-
-   /* Lookup user and groupid for the GDM user */
-   pwent = getpwnam (GdmUser);
-
-   /* Set GdmUserId and GdmGroupId */
-   if G_UNLIKELY (pwent == NULL) {
-
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("The GDM user '%s' does not exist. "
-                                           "Please correct GDM configuration "
-                                           "and restart GDM.")), GdmUser);
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: Can't find the GDM user '%s'. Aborting!"), "gdm_config_parse", GdmUser);
-   } else {
-      GdmUserId = pwent->pw_uid;
-   }
-
-   if G_UNLIKELY (GdmUserId == 0) {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("The GDM user is set to be root, but "
-                                           "this is not allowed since it can "
-                                           "pose a security risk.  Please "
-                                           "correct GDM configuration and "
-                                           "restart GDM.")));
-
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: The GDM user should not be root. Aborting!"), "gdm_config_parse");
-   }
-
-   grent = getgrnam (GdmGroup);
-
-   if G_UNLIKELY (grent == NULL) {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("The GDM group '%s' does not exist. "
-                                           "Please correct GDM configuration "
-                                           "and restart GDM.")), GdmGroup);
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: Can't find the GDM group '%s'. Aborting!"), "gdm_config_parse", GdmGroup);
-   } else  {
-      GdmGroupId = grent->gr_gid;   
-   }
-
-   if G_UNLIKELY (GdmGroupId == 0) {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("The GDM group is set to be root, but "
-                                           "this is not allowed since it can "
-                                           "pose a security risk. Please "
-                                           "correct GDM configuration and "
-                                           "restart GDM.")));
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: The GDM group should not be root. Aborting!"), "gdm_config_parse");
-   }
-
-   /* gid remains `gdm' */
-   NEVER_FAILS_root_set_euid_egid (GdmUserId, GdmGroupId);
-
-   /* Check that the greeter can be executed */
-   bin = ve_first_word (GdmGreeter);
-   if G_UNLIKELY (ve_string_empty (bin) || g_access (bin, X_OK) != 0) {
-      gdm_error (_("%s: Greeter not found or can't be executed by the GDM user"), "gdm_config_parse");
-   }
-   g_free (bin);
-
-   bin = ve_first_word (GdmRemoteGreeter);
-   if G_UNLIKELY (ve_string_empty (bin) || g_access (bin, X_OK) != 0) {
-      gdm_error (_("%s: Remote greeter not found or can't be executed by the GDM user"), "gdm_config_parse");
-   }
-   g_free (bin);
-
-   /* Check that chooser can be executed */
-   bin = ve_first_word (GdmChooser);
-
-   if G_UNLIKELY (GdmIndirect && (ve_string_empty (bin) || g_access (bin, X_OK) != 0)) {
-      gdm_error (_("%s: Chooser not found or it can't be executed by the GDM user"), "gdm_config_parse");
-   }
-    
-   g_free (bin);
-
-   /* Check the serv auth and log dirs */
-   if G_UNLIKELY (ve_string_empty (GdmServAuthDir)) {
-       if (GdmConsoleNotify) {
-          gdm_text_message_dialog
-             (C_(N_("No daemon/ServAuthDir specified in the GDM configuration file")));
-       }
-       GdmPidFile = NULL;
-       gdm_fail (_("%s: No daemon/ServAuthDir specified."), "gdm_config_parse");
-   }
-
-   if (ve_string_empty (GdmLogDir)) {
-      g_free (GdmLogDir);
-      GdmLogDir = g_strdup (GdmServAuthDir);
-   }
-
-   /* Enter paranoia mode */
-   check_servauthdir (&statbuf);
-
-   NEVER_FAILS_root_set_euid_egid (0, 0);
-
-   /* Now set things up for us as  */
-   chown (GdmServAuthDir, 0, GdmGroupId);
-   g_chmod (GdmServAuthDir, (S_IRWXU|S_IRWXG|S_ISVTX));
-
-   NEVER_FAILS_root_set_euid_egid (GdmUserId, GdmGroupId);
-
-   /* Again paranoid */
-   check_servauthdir (&statbuf);
-
-   if G_UNLIKELY (statbuf.st_uid != 0 || statbuf.st_gid != GdmGroupId)  {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("Server Authorization directory "
-                                           "(daemon/ServAuthDir) is set to %s "
-                                           "but is not owned by user %s and group "
-                                           "%s. Please correct the ownership or "
-                                           "GDM configuration and restart "
-                                           "GDM.")), GdmServAuthDir,
-		   			gdm_root_user (), GdmGroup);
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: Authdir %s is not owned by user %s, group %s. Aborting."),
-                     "gdm_config_parse", GdmServAuthDir, gdm_root_user (), GdmGroup);
-   }
-
-   if G_UNLIKELY (statbuf.st_mode != (S_IFDIR|S_IRWXU|S_IRWXG|S_ISVTX))  {
-      if (GdmConsoleNotify) {
-         gchar *s = g_strdup_printf (C_(N_("Server Authorization directory "
-                                    "(daemon/ServAuthDir) is set to %s "
-                                    "but has the wrong permissions: it "
-                                    "should have permissions of %o. "
-                                    "Please correct the permissions or "
-                                    "the GDM configuration and "
-                                    "restart GDM.")), GdmServAuthDir,
-                                    (S_IRWXU|S_IRWXG|S_ISVTX));
-         gdm_text_message_dialog (s);
-         g_free (s);
-      }
-
-      GdmPidFile = NULL;
-      gdm_fail (_("%s: Authdir %s has wrong permissions %o. Should be %o. Aborting."), "gdm_config_parse", 
-                  GdmServAuthDir, statbuf.st_mode, (S_IRWXU|S_IRWXG|S_ISVTX));
-   }
-
-   NEVER_FAILS_root_set_euid_egid (0, 0);
-
-   check_logdir ();
-
-   /* Check that user authentication is properly configured */
-   gdm_verify_check ();
-
-   if (custom_cfg != NULL)
-      g_key_file_free (custom_cfg);
-   g_key_file_free (cfg);
-}
-
-/** 
- * gdm_get_gdmuid
- * gdm_get_gdmgid
- *
- * Access functions for getting the GDM user ID and group ID.
- */
-uid_t
-gdm_get_gdmuid (void)
-{
-   return GdmUserId;
-}
-
-gid_t
-gdm_get_gdmgid (void)
-{
-   return GdmGroupId;
-}
-
-/** 
- * gdm_get_high_display_num
- * gdm_get_high_display_num
- *
- * Access functions for getting the high display number.
- */
-gint
-gdm_get_high_display_num (void)
-{
-   return high_display_num;
-}
-
-void
-gdm_set_high_display_num (gint val)
-{
-   high_display_num = val;
-}
-
-/**
- * gdm_is_valid_key
- *
- * Returns TRUE if the key is a valid key, FALSE otherwise.
- */
-gboolean
-gdm_is_valid_key (const gchar *key)
-{
-   GdmConfigType *type = gdm_config_hash_lookup (type_hash, key);
-   if (type == NULL)
-      return FALSE;
-
-   return TRUE;
-}
-
-/**
- * gdm_signal_terminthup_was_notified
- *
- * returns TRUE if signal SIGTERM, SIGINT, or SIGHUP was received.
- * This just hides these vicious-extensions functions from the
- * other files
- */
-gboolean
-gdm_signal_terminthup_was_notified (void)
-{
-   if (ve_signal_was_notified (SIGTERM) ||
-       ve_signal_was_notified (SIGINT) ||
-       ve_signal_was_notified (SIGHUP)) {
-      return TRUE;
-   } else {
-      return FALSE;
-   }
-}
-
-/**
- * check_user_file
- * check_global_file
- * is_in_trusted_pic_dir
- * get_facefile_from_gnome2_dir_config 
- * path_is_local
- * gdm_get_facefile_from_home
- * gdm_get_facefile_from_global
- *
- * These functions are used for accessing the user's face image from their
- * home directory via vicious-extensions.
- */
-static gboolean
-check_user_file (const char *path,
-                 guint       uid)
-{
-        char    *dir;
-        char    *file;
-        gboolean is_ok;
-
-        if (path == NULL)
-                return FALSE;
-
-        if (g_access (path, R_OK) != 0)
-                return FALSE;
-
-        dir = g_path_get_dirname (path);
-        file = g_path_get_basename (path);
-
-        is_ok = gdm_file_check ("run_pictures",
-                                uid,
-                                dir,
-                                file,
-                                TRUE, TRUE,
-                                gdm_get_value_int (GDM_KEY_USER_MAX_FILE),
-                                gdm_get_value_int (GDM_KEY_RELAX_PERM));
-        g_free (dir);
-        g_free (file);
-
-        return is_ok;
-}
-
-static gboolean
-check_global_file (const char *path,
-                   guint       uid)
-{
-        if (path == NULL)
-                return FALSE;
-
-        if (g_access (path, R_OK) != 0)
-                return FALSE;
-
-        return TRUE;
-}
-
-/* If path starts with a "trusted" directory, don't sanity check things */
-/* This is really somewhat "outdated" as we now really want things in
- * the picture dir or in ~/.gnome2/photo */
-static gboolean
-is_in_trusted_pic_dir (const char *path)
-{
-        /* our own pixmap dir is trusted */
-        if (strncmp (path, PIXMAPDIR, sizeof (PIXMAPDIR)) == 0)
-                return TRUE;
-
-        return FALSE;
-}
-
-static gchar *
-get_facefile_from_gnome2_dir_config (const char *homedir,
-                                     guint       uid)
-{
-   char *picfile = NULL;
-   char *cfgdir;
-
-   /* Sanity check on ~user/.gnome2/gdm */
-   cfgdir = g_build_filename (homedir, ".gnome2", "gdm", NULL);
-   if (G_LIKELY (check_user_file (cfgdir, uid))) {
-      GKeyFile *cfg;
-      char *cfgfile;
-
-      cfgfile = g_build_filename (homedir, ".gnome2", "gdm", NULL);
-      cfg = gdm_common_config_load (cfgfile, NULL);
-      g_free (cfgfile);
-
-      if (cfg != NULL) {
-         gdm_common_config_get_string (cfg, "face/picture=", &picfile, NULL);
-         g_key_file_free (cfg);
-      }
-
-      /* must exist and be absolute (note that this check
-       * catches empty strings)*/
-      /* Note that these days we just set ~/.face */
-      if G_UNLIKELY (picfile != NULL &&
-                     (picfile[0] != '/' ||
-                      /* this catches readability by user */
-                      g_access (picfile, R_OK) != 0)) {
-         g_free (picfile);
-         picfile = NULL;
-      }
-
-      if (picfile != NULL) {
-         char buf[PATH_MAX];
-         if (realpath (picfile, buf) == NULL) {
-            g_free (picfile);
-            picfile = NULL;
-         } else {
-            g_free (picfile);
-            picfile = g_strdup (buf);
-         }
-      }
-
-      if G_UNLIKELY (picfile != NULL) {
-         if (! is_in_trusted_pic_dir (picfile)) {
-            /* if not in trusted dir, check it out */
-
-            /* Note that strict permissions checking is done
-             * on this file.  Even if it may not even be owned by the
-             * user.  This setting should ONLY point to pics in trusted
-             * dirs. */
-            if (! check_user_file (picfile, uid)) {
-               g_free (picfile);
-               picfile = NULL;
-            }
-         }
-      }
-   }
-   g_free (cfgdir);
-
-   return picfile;
-}
-
-static GHashTable *fstype_hash = NULL;
-extern char *filesystem_type (char *path, char *relpath, struct stat *statp);
-
-static gboolean
-path_is_local (const char *path)
-{
-        gpointer local = NULL;
-
-        if (path == NULL)
-                return FALSE;
-
-        if (fstype_hash == NULL)
-                fstype_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
-        else
-                local = g_hash_table_lookup (fstype_hash, path);
-
-        if (local == NULL) {
-                struct stat statbuf;
-
-                if (g_stat (path, &statbuf) == 0) {
-                        char *type = filesystem_type ((char *)path, (char *)path, &statbuf);
-                        gboolean is_local = ((strcmp (ve_sure_string (type), "nfs") != 0) &&
-                                             (strcmp (ve_sure_string (type), "afs") != 0) &&
-                                             (strcmp (ve_sure_string (type), "autofs") != 0) &&
-                                             (strcmp (ve_sure_string (type), "unknown") != 0) &&
-                                             (strcmp (ve_sure_string (type), "ncpfs") != 0));
-                        local = GINT_TO_POINTER (is_local ? 1 : -1);
-                        g_hash_table_insert (fstype_hash, g_strdup (path), local);
-                }
-        }
-
-        return GPOINTER_TO_INT (local) > 0;
-}
-
-gchar *
-gdm_get_facefile_from_home (const char *homedir,
-                            guint       uid)
-{
-   char    *picfile = NULL;
-   char    *path;
-   gboolean is_local;
-
-   /* special case: look at parent of home to detect autofs
-      this is so we don't try to trigger an automount */
-   path = g_path_get_dirname (homedir);
-   is_local = path_is_local (path);
-   g_free (path);
-
-   /* now check that home dir itself is local */
-   if (is_local) {
-      is_local = path_is_local (homedir);
-   }
-
-   /* Only look at local home directories so we don't try to
-      read from remote (e.g. NFS) volumes */
-   if (! is_local)
-      return NULL;
-
-   picfile = g_build_filename (homedir, ".face", NULL);
-
-   if (check_user_file (picfile, uid))
-      return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   picfile = g_build_filename (homedir, ".face.icon", NULL);
-
-   if (check_user_file (picfile, uid))
-           return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   picfile = get_facefile_from_gnome2_dir_config (homedir, uid);
-   if (check_user_file (picfile, uid))
-      return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   /* Nothing found yet, try the old locations */
-
-   picfile = g_build_filename (homedir, ".gnome2", "photo", NULL);
-   if (check_user_file (picfile, uid))
-      return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   picfile = g_build_filename (homedir, ".gnome", "photo", NULL);
-   if (check_user_file (picfile, uid))
-      return picfile;
-   else {
-      g_free (picfile);
-      picfile = NULL;
-   }
-
-   return NULL;
-}
-
-gchar *
-gdm_get_facefile_from_global (const char *username,
-                              guint       uid)
-{
-   char *picfile = NULL;
-   char *facedir = gdm_get_value_string (GDM_KEY_GLOBAL_FACE_DIR);
-
-   /* Try the global face directory */
-
-   picfile = g_build_filename (facedir, username, NULL);
-
-   if (check_global_file (picfile, uid))
-      return picfile;
-
-   g_free (picfile);
-   picfile = gdm_make_filename (facedir, username, ".png");
-
-   if (check_global_file (picfile, uid))
-      return picfile;
-
-   g_free (picfile);
-   return NULL;
-}
-
-/**
- * gdm_get_session_exec
- *
- * This function accesses the GDM session desktop file, via vicious
- * extensions and returns the execution command for starting the
- * session.
- */
-char *
-gdm_get_session_exec (const char *session_name, gboolean check_try_exec)
-{
-   char *file;
-   char *full = NULL;
-   GKeyFile *cfg;
-   static char *exec;
-   static char *cached = NULL;
-   gboolean hidden;
-   char *ret;
-
-   cfg = NULL;
-
-   /* clear cache */
-   if (session_name == NULL) {
-      g_free (exec);
-      exec = NULL;
-      g_free (cached);
-      cached = NULL;
-      return NULL;
-   }
-
-   if (cached != NULL && strcmp (ve_sure_string (session_name), ve_sure_string (cached)) == 0)
-      return g_strdup (exec);
-
-   g_free (exec);
-   exec = NULL;
-   g_free (cached);
-   cached = g_strdup (session_name);
-
-   /* Some ugly special casing for legacy "Default.desktop", oh well,
-    * we changed to "default.desktop" */
-   if (g_ascii_strcasecmp (session_name, "default") == 0 ||
-       g_ascii_strcasecmp (session_name, "default.desktop") == 0) {
-      full = ve_find_prog_in_path ("default.desktop",
-         gdm_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR));
-   }
-
-   if (full == NULL) {
-      file = gdm_ensure_extension (session_name, ".desktop");
-      full = ve_find_prog_in_path (file,
-         gdm_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR));
-      g_free (file);
-   }
-
-   if (ve_string_empty (full) || g_access (full, R_OK) != 0) {
-      g_free (full);
-      if (gdm_is_session_magic (session_name)) {
-         exec = g_strdup (session_name);
-         return g_strdup (exec);
-      } else {
-         return NULL;
-      }
-   }
-
-   cfg = gdm_common_config_load (full, NULL);
-   g_free (full);
-   if (cfg == NULL) {
-      ret = NULL;
-      goto out;
-   }
-
-   hidden = FALSE;
-   gdm_common_config_get_boolean (cfg, "Desktop Entry/Hidden=false", &hidden, NULL);
-   if (hidden) {
-      ret = NULL;
-      goto out;
-   }
-
-   if (check_try_exec) {
-      char *tryexec;
-      tryexec = NULL;
-      gdm_common_config_get_string (cfg, "Desktop Entry/TryExec", &tryexec, NULL);
-      if ( ! ve_string_empty (tryexec) &&
-           ! ve_is_prog_in_path (tryexec, gdm_get_value_string (GDM_KEY_PATH)) &&
-           ! ve_is_prog_in_path (tryexec, gdm_saved_getenv ("PATH"))) {
-         g_free (tryexec);
-         ret = NULL;
-         goto out;
-      }
-      g_free (tryexec);
-   }
-
-   exec = NULL;
-   gdm_common_config_get_string (cfg, "Desktop Entry/Exec", &exec, NULL);
-   ret = g_strdup (exec);
-
- out:
-
-   g_key_file_free (cfg);
-
-   return ret;
-}
-
-/**
- * gdm_set_user_session_lang
- * gdm_get_user_session_lang
- *
- * These functions get and set the user's language and setting in their
- * $HOME/.dmrc file via vicious-extensions.
- */
-void
-gdm_set_user_session_lang (gboolean savesess,
-                           gboolean savelang,
-                           const char *home_dir,
-                           const char *save_session,
-                           const char *save_language)
-{
-   GKeyFile *dmrc;
-   gchar *cfgstr;
-
-   cfgstr = g_build_filename (home_dir, ".dmrc", NULL);
-
-   dmrc = gdm_common_config_load (cfgstr, NULL);
-   if (dmrc == NULL) {
-      return;
-   }
-
-   if (savesess) {
-      g_key_file_set_string (dmrc, "Desktop", "Session", ve_sure_string (save_session));
-   }
-
-   if (savelang) {
-      if (ve_string_empty (save_language)) {
-         /* we chose the system default language so wipe the
-          * lang key */
-         g_key_file_remove_key (dmrc, "Desktop", "Language", NULL);
-      } else {
-         g_key_file_set_string (dmrc, "Desktop", "Language", save_language);
-      }
-   }
-
-   if (dmrc != NULL) {
-      mode_t oldmode;
-      oldmode = umask (077);
-      gdm_common_config_save (dmrc, cfgstr, NULL);
-      umask (oldmode);
-   }
-
-   g_free (cfgstr);
-   g_key_file_free (dmrc);
-}
-
-void
-gdm_get_user_session_lang (char **usrsess,
-                           char **usrlang,
-                           const char *home_dir,
-                           gboolean *savesess)
-{
-   char *p;
-   char *cfgfile;
-   GKeyFile *cfg;
-   char *session;
-   char *lang;
-   gboolean save;
-
-   cfgfile = g_build_filename (home_dir, ".dmrc", NULL);
-   cfg = gdm_common_config_load (cfgfile, NULL);
-   g_free (cfgfile);
-
-   save = FALSE;
-   session = NULL;
-
-   gdm_common_config_get_string (cfg, "Desktop/Session", &session, NULL);
-   if (session == NULL) {
-      session = g_strdup ("");
-   }
-
-   /* this is just being truly anal about what users give us, and in case
-    * it looks like they may have included a path whack it. */
-   p = strrchr (session, '/');
-   if (p != NULL) {
-      char *tmp = g_strdup (p + 1);
-      g_free (session);
-      session = tmp;
-   }
-
-   /* ugly workaround for migration */
-   if ((strcmp (ve_sure_string (session), "Default.desktop") == 0 ||
-        strcmp (ve_sure_string (session), "Default") == 0) &&
-       ! ve_is_prog_in_path ("Default.desktop",
-            gdm_get_value_string (GDM_KEY_SESSION_DESKTOP_DIR))) {
-           g_free (session);
-           session = g_strdup ("default");
-           save = TRUE;
-   }
-
-   gdm_common_config_get_string (cfg, "Desktop/Language", &lang, NULL);
-   if (lang == NULL) {
-           lang = g_strdup ("");
-   }
-
-   if (usrsess != NULL) {
-      *usrsess = g_strdup (session);
-   }
-   g_free (session);
-
-   if (savesess != NULL) {
-      *savesess = save;
-   }
-
-   if (usrlang != NULL) {
-      *usrlang = g_strdup (lang);
-   }
-   g_free (lang);
-
-   g_key_file_free (cfg);
-}
-
