--- gdm2/ChangeLog.org	2007-05-09 12:15:48.000000000 +0100
+++ gdm2/ChangeLog	2007-05-11 08:34:33.000000000 +0100
@@ -0,0 +1,20 @@
+2007-05-11  Lukasz Zalewski <lukas@dcs.qmul.ac.uk>
+
+	* daemon/gdm-daemon-config-keys.h:
+	* daemon/gdm-daemon-config.[ch]:
+	* daemon/slave.c:
+	* common/gdm-config.[ch]:
+	  First part of the fix for bug #404891. Removed all GDM_NOTIFY_*
+	  keys used in the notification process and substituted them with
+	  group/key pairs of the actual keys (All the GDM_NOTIFY_* keys 
+	  represented was manually defined key part without the group). 
+	  Added all/PARAMETERS option to the gdm_daemon_config_update_key 
+	  function which perfroms bulk update of most available keys 
+	  (forbidden keys + xserver sections excluded) and notifies 
+	  the slaves if appropriate. This option can be used with 
+	  flexiserver --command "UPDATE_CONFIG ..". Also simplified
+	  gdm_slave_handle_notify such that the config is re-read and 
+	  updated entirely keeping all the configs in sync and all the keys
+	  of interest are grouped wrt the following action rather than the
+	  type of value they going to set.
+	  	
--- gdm2/daemon/gdm-daemon-config.h.org	2007-05-09 12:15:48.000000000 +0100
+++ gdm2/daemon/gdm-daemon-config.h	2007-05-11 08:45:06.000000000 +0100
@@ -44,6 +44,8 @@
 gint           gdm_daemon_config_get_high_display_num (void);
 void           gdm_daemon_config_set_high_display_num (gint val);
 
+gboolean       gdm_daemon_config_update_all_no_notify (void);
+
 /* deprecated */
 char *         gdm_daemon_config_get_display_custom_config_file (const char *display);
 char *         gdm_daemon_config_get_custom_config_file (void);
@@ -101,6 +103,7 @@
 char *         gdm_daemon_config_get_session_exec     (const char *session_name,
                                                        gboolean check_try_exec);
 char *         gdm_daemon_config_get_session_xserver_args (const char *session_name);
+gboolean       is_key (const gchar *key1, const gchar *key2);
 
 
 G_END_DECLS
--- gdm2/daemon/gdm-socket-protocol.h.org	2007-05-11 08:45:18.000000000 +0100
+++ gdm2/daemon/gdm-socket-protocol.h	2007-05-11 08:46:06.000000000 +0100
@@ -174,6 +174,15 @@
 /* send the question dialog response */
 #define GDM_SLAVE_NOTIFY_QUESTION_RESPONSE 'Q'
 
+/* Update flags used in conjunction with GDM_SLAVE_NOTIFY_KEY */
+typedef enum {
+	GDM_NOTIFY_FLAG_DO_NOTHING           = 0x0,
+	GDM_NOTIFY_FLAG_NO_RESTART           = 0x1,
+	GDM_NOTIFY_FLAG_RESTART_STATIC       = 0x2,
+	GDM_NOTIFY_FLAG_RESTART_XMDCP        = 0x4,
+	GDM_NOTIFY_FLAG_RESTART_STATIC_XMDCP = 0x6,
+} GdmNotifyStatus;
+
 /*
  * Maximum number of messages allowed over the sockets protocol.  This
  * is set to 80 since the gdmlogin/gdmgreeter programs have ~60 config
--- gdm2/daemon/slave.c.org	2007-05-09 12:15:48.000000000 +0100
+++ gdm2/daemon/slave.c	2007-05-09 12:15:48.000000000 +0100
@@ -4947,6 +4947,7 @@
 			unhandled_notifies =
 				g_list_append (unhandled_notifies,
 					       g_strdup (&s[1]));
+			check_notifies_now ();
 		} else if (s[0] == GDM_SLAVE_NOTIFY_COMMAND) {
 			if (strcmp (&s[1], GDM_NOTIFY_DIRTY_SERVERS) == 0) {
 				/* never restart flexi servers
@@ -5719,164 +5720,91 @@
 }
 
 static void
+gdm_terminate_slave (gint type_to_terminate) 
+{
+	do_restart_greeter = TRUE;
+	if (restart_greeter_now) {
+		; /* will get restarted later */
+	} else if (d->type == type_to_terminate) {
+		/* FIXME: can't handle flexi servers like this
+		 * without going all cranky */
+		if ( ! d->logged_in) {
+			gdm_slave_quick_exit (DISPLAY_REMANAGE);
+		} else {
+			remanage_asap = TRUE;
+		}
+	}	
+}
+
+static void
 gdm_slave_handle_notify (const char *msg)
 {
 	int val;
 
 	gdm_debug ("Handling slave notify: '%s'", msg);
 
-	if (sscanf (msg, GDM_NOTIFY_ALLOW_ROOT " %d", &val) == 1) {
-		gdm_daemon_config_set_value_bool (GDM_KEY_ALLOW_ROOT, val);
-	} else if (sscanf (msg, GDM_NOTIFY_ALLOW_REMOTE_ROOT " %d", &val) == 1) {
-		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_daemon_config_set_value_bool (GDM_KEY_ALLOW_REMOTE_AUTOLOGIN, val);
-	} else if (sscanf (msg, GDM_NOTIFY_SYSTEM_MENU " %d", &val) == 1) {
-		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_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_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_daemon_config_set_value_int (GDM_KEY_RETRY_DELAY, val);
-	} else if (sscanf (msg, GDM_NOTIFY_DISALLOW_TCP " %d", &val) == 1) {
-		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_daemon_config_set_value_string (GDM_KEY_GREETER, ((gchar *)&msg[strlen (GDM_NOTIFY_GREETER) + 1]));
-
-		if (d->attached) {
-			do_restart_greeter = TRUE;
-			if (restart_greeter_now) {
-				; /* will get restarted later */
-			} else if (d->type == TYPE_STATIC) {
-				/* FIXME: can't handle flexi servers like this
-				 * without going all cranky */
-				if ( ! d->logged_in) {
-					gdm_slave_quick_exit (DISPLAY_REMANAGE);
-				} else {
-					remanage_asap = TRUE;
-				}
-			}
-		}
-	} else if (strncmp (msg, GDM_NOTIFY_CUSTOM_CMD_TEMPLATE,
-			    strlen (GDM_NOTIFY_CUSTOM_CMD_TEMPLATE)) == 0) {
-    	        if (sscanf (msg, GDM_NOTIFY_CUSTOM_CMD_TEMPLATE "%d", &val) == 1) {
-			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_daemon_config_set_value_string (key_string, ((gchar *)&msg[strlen (GDM_NOTIFY_CUSTOM_CMD_TEMPLATE) + 2]));
-			g_free(key_string);
-
-			if (d->attached) {
+	gchar **splitstr = g_strsplit (msg, " ", 2);
+	if (splitstr[0] != NULL) {
+		if (splitstr[1] != NULL) {			
+			if (gdm_daemon_config_update_all_no_notify () == FALSE)
+				return;
+			
+			if (is_key (splitstr[0], GDM_KEY_SYSTEM_MENU) ||
+			    is_key (splitstr[0], GDM_KEY_CONFIG_AVAILABLE) ||
+			    is_key (splitstr[0], GDM_KEY_CHOOSER_BUTTON) ||
+			    is_key (splitstr[0], GDM_KEY_SOUND_ON_LOGIN_FILE) ||
+			    is_key (splitstr[0], GDM_KEY_SOUND_ON_LOGIN_SUCCESS_FILE) ||
+			    is_key (splitstr[0], GDM_KEY_SOUND_ON_LOGIN_FAILURE_FILE)) {
+				if (d->greetpid > 1)
+					kill (d->greetpid, SIGHUP);
+				
+			} else if (is_key (splitstr[0], GDM_KEY_DISALLOW_TCP)) {
+				remanage_asap = TRUE;
+				
+			} else if (is_key (splitstr[0], GDM_KEY_GREETER) ||
+				   is_key (splitstr[0],GDM_KEY_ADD_GTK_MODULES) ||
+				   is_key (splitstr[0], GDM_KEY_GTK_MODULES_LIST)) {
+				if (d->attached) 
+					gdm_terminate_slave (TYPE_STATIC);
+
+			} else if (is_key (splitstr[0], GDM_KEY_REMOTE_GREETER)) {
+				if (!d->attached) 
+					gdm_terminate_slave (TYPE_XDMCP);			
+		
+			} else if (is_key (splitstr[0], GDM_KEY_TIMED_LOGIN) ||
+				   is_key (splitstr[0], GDM_KEY_TIMED_LOGIN_ENABLE) ||
+				   is_key (splitstr[0], GDM_KEY_TIMED_LOGIN_DELAY)) {
 				do_restart_greeter = TRUE;
-				if (restart_greeter_now) {
-					; /* will get restarted later */
-				} else if (d->type == TYPE_STATIC) {
-					/* FIXME: can't handle flexi servers like this
-					 * without going all cranky */
+				/* FIXME: this is fairly nasty, we should handle this nicer   */
+				/* FIXME: can't handle flexi servers without going all cranky */
+				if (d->type == TYPE_STATIC || d->type == TYPE_XDMCP) {
 					if ( ! d->logged_in) {
 						gdm_slave_quick_exit (DISPLAY_REMANAGE);
 					} else {
 						remanage_asap = TRUE;
 					}
+				}				
+			
+			} else if (is_key (splitstr[0], GDM_NOTIFY_UPDATE_ALL_GREETERS)) {				
+				if (sscanf (splitstr[1], "%d", &val) == 1) {					
+					if (d->attached && 
+					    (val & GDM_NOTIFY_FLAG_RESTART_STATIC) == GDM_NOTIFY_FLAG_RESTART_STATIC) {
+						gdm_terminate_slave (TYPE_STATIC);
+
+					} else if (!d->attached && 
+						   (val & GDM_NOTIFY_FLAG_RESTART_XMDCP) == GDM_NOTIFY_FLAG_RESTART_XMDCP) {
+						gdm_terminate_slave (TYPE_XDMCP);
+
+					} else if ((val & GDM_NOTIFY_FLAG_NO_RESTART) == GDM_NOTIFY_FLAG_NO_RESTART) {
+						if (d->greetpid > 1)
+							kill (d->greetpid, SIGHUP);
+					}
 				}
 			}
 		}
-	} else if (strncmp (msg, GDM_NOTIFY_REMOTE_GREETER " ",
-			    strlen (GDM_NOTIFY_REMOTE_GREETER) + 1) == 0) {
-		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;
-			if (restart_greeter_now) {
-				; /* will get restarted later */
-			} else if (d->type == TYPE_XDMCP) {
-				/* FIXME: can't handle flexi servers like this
-				 * without going all cranky */
-				if ( ! d->logged_in) {
-					gdm_slave_quick_exit (DISPLAY_REMANAGE);
-				} else {
-					remanage_asap = TRUE;
-				}
-			}
-		}
-	} else if ((strncmp (msg, GDM_NOTIFY_TIMED_LOGIN " ",
-			     strlen (GDM_NOTIFY_TIMED_LOGIN) + 1) == 0) ||
-	           (strncmp (msg, GDM_NOTIFY_TIMED_LOGIN_DELAY " ",
-			     strlen (GDM_NOTIFY_TIMED_LOGIN_DELAY) + 1) == 0) ||
-	           (strncmp (msg, GDM_NOTIFY_TIMED_LOGIN_ENABLE " ",
-			     strlen (GDM_NOTIFY_TIMED_LOGIN_ENABLE) + 1) == 0)) {
-		do_restart_greeter = TRUE;
-		/* FIXME: this is fairly nasty, we should handle this nicer   */
-		/* FIXME: can't handle flexi servers without going all cranky */
-		if (d->type == TYPE_STATIC || d->type == TYPE_XDMCP) {
-			if ( ! d->logged_in) {
-				gdm_slave_quick_exit (DISPLAY_REMANAGE);
-			} else {
-				remanage_asap = TRUE;
-			}
-		}
-	} else if (strncmp (msg, GDM_NOTIFY_SOUND_ON_LOGIN_FILE " ",
-			    strlen (GDM_NOTIFY_SOUND_ON_LOGIN_FILE) + 1) == 0) {
-		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_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_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_daemon_config_set_value_string (GDM_KEY_GTK_MODULES_LIST,
-						    (gchar *)(&msg[strlen (GDM_NOTIFY_GTK_MODULES_LIST) + 1]));
-
-		if (gdm_daemon_config_get_value_bool (GDM_KEY_ADD_GTK_MODULES)) {
-			do_restart_greeter = TRUE;
-			if (restart_greeter_now) {
-				; /* will get restarted later */
-			} else if (d->type == TYPE_STATIC) {
-				/* FIXME: can't handle flexi servers like this
-				 * without going all cranky */
-				if ( ! d->logged_in) {
-					gdm_slave_quick_exit (DISPLAY_REMANAGE);
-				} else {
-					remanage_asap = TRUE;
-				}
-			}
-		}
-	} else if (sscanf (msg, GDM_NOTIFY_ADD_GTK_MODULES " %d", &val) == 1) {
-		gdm_daemon_config_set_value_bool (GDM_KEY_ADD_GTK_MODULES, val);
-
-		do_restart_greeter = TRUE;
-		if (restart_greeter_now) {
-			; /* will get restarted later */
-		} else if (d->type == TYPE_STATIC) {
-			/* FIXME: can't handle flexi servers like this
-			 * without going all cranky */
-			if ( ! d->logged_in) {
-				gdm_slave_quick_exit (DISPLAY_REMANAGE);
-			} else {
-				remanage_asap = TRUE;
-			}
-		}
-	}
+		
+	}	   
+	g_strfreev (splitstr);		
 }
 
 /* do cleanup but only if we are a slave, if we're not a slave, just
--- gdm2/daemon/gdm-daemon-config.c.org	2007-05-09 12:15:48.000000000 +0100
+++ gdm2/daemon/gdm-daemon-config.c	2007-05-09 12:15:48.000000000 +0100
@@ -67,6 +67,8 @@
 
 static GdmConfig *daemon_config = NULL;
 
+static GdmNotifyStatus notify_status = GDM_NOTIFY_FLAG_DO_NOTHING;
+
 static GSList *displays = NULL;
 static GSList *xservers = NULL;
 
@@ -84,7 +86,7 @@
  * keys passed and compares them, returning TRUE if they are the same, 
  * FALSE otherwise.
  */
-static gboolean
+gboolean
 is_key (const gchar *key1, const gchar *key2)
 {
 	gchar *key1d, *key2d, *p;
@@ -794,66 +796,15 @@
 }
 
 static char *
-lookup_notify_key (GdmConfig  *config,
-		   const char *group,
-		   const char *key)
+get_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;
+	
+	return keystring;
 }
 
 /**
@@ -876,7 +827,7 @@
 	char   *valstr;
 	char   *keystr;
 
-	keystr = lookup_notify_key (config, group, key);
+	keystr = get_notify_key (config, group, key);
 
 	/* unfortunately, can't always gdm_config_value_to_string()
 	 * here because booleans need to be sent as ints
@@ -1217,7 +1168,7 @@
                 entry.id = GDM_CONFIG_INVALID_ID;
 
                 gdm_config_add_entry (config, &entry);
-                gdm_config_process_entry (config, &entry, NULL);
+                gdm_config_process_entry (config, &entry, NULL, TRUE, FALSE);
 
                 res = gdm_config_get_value (config, entry.group, entry.key, &value);
                 if (! res) {
@@ -1245,7 +1196,7 @@
                         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_process_entry (config, srv_entry, NULL, TRUE, FALSE);
                         gdm_config_entry_free (srv_entry);
                 }
 		g_free (new_group);
@@ -1265,6 +1216,27 @@
 	gdm_daemon_config_ensure_one_xserver (config);
 }
 
+gboolean
+gdm_daemon_config_update_all_no_notify ()
+{
+	GError          *error;
+	gboolean         res;
+	GdmConfigStatus  reload_status;
+	
+	error = NULL;
+	/* reload backend files if necessary */
+	reload_status = gdm_config_load (daemon_config, NULL);
+	if (reload_status == GDM_CONFIG_FILE_UNCHANGED)
+		return FALSE;
+	
+	res = gdm_config_process_all (daemon_config, &error, FALSE, TRUE);
+	if (error != NULL) {
+		gdm_error ("Unable to update configuration: %s", error->message);
+		g_error_free (error);
+	}		
+	return res;
+}
+
 /**
  * gdm_daemon_config_update_key
  *
@@ -1275,10 +1247,9 @@
  * 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-daemon-config-keys.h, supporting logic placed in the
- * notify_cb function and in the gdm_slave_handle_notify function
- * in slave.c.
+ * To add a new notification, notify_status_cb will have to be modified
+ * such that it supports logic placed in the notify_status_cb function 
+ * and in the gdm_slave_handle_notify function in slave.c.
  */
 gboolean
 gdm_daemon_config_update_key (const char *keystring)
@@ -1289,29 +1260,19 @@
 	char                 *key;
 	char                 *locale;
 	const GdmConfigEntry *entry;
-
+	GdmConfigStatus       reload_status;
+	GError               *error;
+	GdmConfigValue       *notify_value;
+	
 	rc = FALSE;
 	group = key = locale = 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 (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;
-	}
+	notify_value = NULL;
+	error = NULL;
 
 	/* reload backend files if necessary */
-	gdm_config_load (daemon_config, NULL);
+	reload_status = gdm_config_load (daemon_config, NULL);
+	if (reload_status == GDM_CONFIG_FILE_UNCHANGED)
+		return TRUE;
 
 	/* Shortcut for updating all XDMCP parameters */
 	if (is_key (keystring, "xdmcp/PARAMETERS")) {
@@ -1333,6 +1294,24 @@
 		goto out;
 	}
 
+	if (is_key (keystring, "all/PARAMETERS")) {
+		/* populate the database with all changed entries */
+		notify_status = GDM_NOTIFY_FLAG_DO_NOTHING;
+		gdm_config_process_all (daemon_config, &error, FALSE, TRUE);
+		if (error != NULL) {
+			gdm_error ("Unable to process configuration: %s", error->message);
+			g_error_free (error);
+		}		
+		if (notify_status != GDM_NOTIFY_FLAG_DO_NOTHING) {
+			notify_value = gdm_config_value_new (GDM_CONFIG_VALUE_INT);
+			gdm_config_value_set_int (notify_value, notify_status);
+			notify_displays_value (daemon_config, "all", "PARAMETERS", notify_value);
+			gdm_config_value_free (notify_value);
+		}
+		rc = TRUE;
+		goto out;
+	}
+
 	/* find the entry for the key */
 	res = gdm_common_config_parse_key_string (keystring,
 						  &group,
@@ -1350,7 +1329,7 @@
 		goto out;
 	}
 
-	rc = gdm_config_process_entry (daemon_config, entry, NULL);
+	rc = gdm_config_process_entry (daemon_config, entry, NULL, TRUE, TRUE);
 
  out:
 	g_free (group);
@@ -1819,6 +1798,39 @@
 	return res;
 }
 
+/*
+ * 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.
+ */
+
+static gboolean
+updatable_value_cb (GdmConfig          *config,
+		    GdmConfigSourceType source,
+		    const char         *group,
+		    const char         *key,
+		    GdmConfigValue     *value,
+		    int                 id,
+		    gpointer            data)
+{
+	
+	switch (id) {
+	case GDM_ID_CONSOLE_NOTIFY:
+	case GDM_ID_USER:
+	case GDM_ID_GROUP:
+	case GDM_ID_LOG_DIR:
+	case GDM_ID_SERV_AUTHDIR:
+	case GDM_ID_USER_AUTHDIR:
+	case GDM_ID_USER_AUTHFILE:
+	case GDM_ID_USER_AUTHDIR_FALLBACK:
+		return FALSE;
+	default:
+		break;
+	}
+
+	return TRUE;
+}
+
 static const char *
 source_to_name (GdmConfigSourceType source)
 {
@@ -1911,6 +1923,50 @@
         return TRUE;
 }
 
+static gboolean
+notify_status_cb (GdmConfig          *config,
+		  GdmConfigSourceType source,
+		  const char         *group,
+		  const char         *key,
+		  GdmConfigValue     *value,
+		  int                 id,
+		  gpointer            data)
+{
+	GdmNotifyStatus *status;
+
+	if (data == NULL)
+		return FALSE;
+	
+	status = (GdmNotifyStatus*)data;
+
+        switch (id) {
+	case GDM_ID_GREETER:
+	case GDM_ID_GTK_MODULES_LIST:
+        case GDM_ID_ADD_GTK_MODULES:
+        case GDM_ID_DISALLOW_TCP:
+		*status |= GDM_NOTIFY_FLAG_RESTART_STATIC;
+		break;
+	case GDM_ID_REMOTE_GREETER:
+		*status |= GDM_NOTIFY_FLAG_RESTART_XMDCP;
+		break;
+        case GDM_ID_TIMED_LOGIN:
+	case GDM_ID_TIMED_LOGIN_ENABLE:
+	case GDM_ID_TIMED_LOGIN_DELAY:
+		*status |= GDM_NOTIFY_FLAG_RESTART_STATIC_XMDCP;
+		break;
+	default:
+		*status |= GDM_NOTIFY_FLAG_NO_RESTART;
+		break;
+	}
+	
+	gdm_debug ("Notification status for %s/%s is %d\n",
+		   group,
+		   key,
+		   *status);
+	
+        return TRUE;
+}
+
 static void
 handle_no_displays (GdmConfig *config,
 		    gboolean   no_console)
@@ -2180,6 +2236,8 @@
 
 	gdm_config_set_notify_func (daemon_config, notify_cb, NULL);
 	gdm_config_set_validate_func (daemon_config, validate_cb, NULL);
+	gdm_config_set_notify_status_func (daemon_config, notify_status_cb, (gpointer)&notify_status);
+	gdm_config_set_updatable_value_func (daemon_config, updatable_value_cb, NULL);
 
 	gdm_config_add_static_entries (daemon_config, gdm_daemon_config_entries);
 
@@ -2195,7 +2253,7 @@
 	}
 
 	/* populate the database with all specified entries */
-	gdm_config_process_all (daemon_config, &error);
+	gdm_config_process_all (daemon_config, &error, TRUE, FALSE);
 
 	gdm_daemon_config_load_xservers (daemon_config);
 
--- gdm2/daemon/gdm-daemon-config-keys.h.org	2007-05-09 12:15:48.000000000 +0100
+++ gdm2/daemon/gdm-daemon-config-keys.h	2007-05-09 12:15:48.000000000 +0100
@@ -201,25 +201,7 @@
 
 /* Notification protocol */
 /* keys */
-#define GDM_NOTIFY_ALLOW_REMOTE_ROOT "AllowRemoteRoot" /* <true/false as int> */
-#define GDM_NOTIFY_ALLOW_ROOT "AllowRoot" /* <true/false as int> */
-#define GDM_NOTIFY_ALLOW_REMOTE_AUTOLOGIN "AllowRemoteAutoLogin" /* <true/false as int> */
-#define GDM_NOTIFY_SYSTEM_MENU "SystemMenu" /* <true/false as int> */
-#define GDM_NOTIFY_CONFIG_AVAILABLE "ConfigAvailable" /* <true/false as int> */
-#define GDM_NOTIFY_CHOOSER_BUTTON "ChooserButton" /* <true/false as int> */
-#define GDM_NOTIFY_RETRY_DELAY "RetryDelay" /* <seconds> */
-#define GDM_NOTIFY_GREETER "Greeter" /* <greeter binary> */
-#define GDM_NOTIFY_REMOTE_GREETER "RemoteGreeter" /* <greeter binary> */
-#define GDM_NOTIFY_TIMED_LOGIN "TimedLogin" /* <login> */
-#define GDM_NOTIFY_TIMED_LOGIN_DELAY "TimedLoginDelay" /* <seconds> */
-#define GDM_NOTIFY_TIMED_LOGIN_ENABLE "TimedLoginEnable" /* <true/false as int> */
-#define GDM_NOTIFY_DISALLOW_TCP "DisallowTCP" /* <true/false as int> */
-#define GDM_NOTIFY_SOUND_ON_LOGIN_FILE "SoundOnLoginFile" /* <sound file> */
-#define GDM_NOTIFY_SOUND_ON_LOGIN_SUCCESS_FILE "SoundOnLoginSuccessFile" /* <sound file> */
-#define GDM_NOTIFY_SOUND_ON_LOGIN_FAILURE_FILE "SoundOnLoginFailureFile" /* <sound file> */
-#define GDM_NOTIFY_ADD_GTK_MODULES "AddGtkModules" /* <true/false as int> */
-#define GDM_NOTIFY_GTK_MODULES_LIST "GtkModulesList" /* <modules list> */
-#define GDM_NOTIFY_CUSTOM_CMD_TEMPLATE "CustomCommand" /* <custom command path> */
+#define GDM_NOTIFY_UPDATE_ALL_GREETERS "all/PARAMETERS" /* <GdmNotifyStatus flag> */
 
 /* commands, seel GDM_SLAVE_NOTIFY_COMMAND */
 #define GDM_NOTIFY_DIRTY_SERVERS "DIRTY_SERVERS"
--- gdm2/common/test-config.c.org	2007-05-09 12:15:48.000000000 +0100
+++ gdm2/common/test-config.c	2007-05-09 12:15:48.000000000 +0100
@@ -180,7 +180,7 @@
                 entry.id = GDM_CONFIG_INVALID_ID;
 
                 gdm_config_add_entry (config, &entry);
-                gdm_config_process_entry (config, &entry, NULL);
+                gdm_config_process_entry (config, &entry, NULL, TRUE, FALSE);
 
                 res = gdm_config_get_value (config, entry.group, entry.key, &value);
                 if (! res) {
@@ -198,7 +198,7 @@
                         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_process_entry (config, srv_entry, NULL, TRUE, FALSE);
                         gdm_config_entry_free (srv_entry);
                 }
                 g_free (new_group);
@@ -232,7 +232,7 @@
                 g_error_free (error);
         } else {
                 /* populate the database with all specified entries */
-                gdm_config_process_all (config, &error);
+                gdm_config_process_all (config, &error, TRUE, FALSE);
         }
 
         g_message ("Getting all standard values");
@@ -284,7 +284,7 @@
                 g_error_free (error);
         } else {
                 /* populate the database with all specified entries */
-                gdm_config_process_all (config, &error);
+                gdm_config_process_all (config, &error, TRUE, FALSE);
         }
 
 
--- gdm2/common/gdm-config.h.org	2007-05-09 12:15:48.000000000 +0100
+++ gdm2/common/gdm-config.h	2007-05-11 08:26:55.000000000 +0100
@@ -25,7 +25,12 @@
 
 G_BEGIN_DECLS
 
-typedef struct _GdmConfig GdmConfig;
+/* Status flags for the loaded config files */
+typedef enum {
+    GDM_CONFIG_LOAD_FAILURE   = 0x0,
+    GDM_CONFIG_LOAD_SUCCESS   = 0x1,
+    GDM_CONFIG_FILE_UNCHANGED = 0x2,
+} GdmConfigStatus; 
 
 typedef enum {
         GDM_CONFIG_VALUE_INVALID,
@@ -55,6 +60,8 @@
 
 typedef struct _GdmConfigValue GdmConfigValue;
 
+typedef struct _GdmConfig GdmConfig;
+
 typedef gboolean (* GdmConfigFunc) (GdmConfig          *config,
 				    GdmConfigSourceType source,
 				    const char         *group,
@@ -63,6 +70,7 @@
 				    int                 id,
 				    gpointer            data);
 
+
 typedef struct {
 	char              *group;
 	char              *key;
@@ -92,6 +100,12 @@
 void                   gdm_config_set_notify_func        (GdmConfig       *config,
 							  GdmConfigFunc    func,
 							  gpointer         data);
+void                   gdm_config_set_notify_status_func (GdmConfig       *config,
+							  GdmConfigFunc    func,
+							  gpointer         data);
+void                   gdm_config_set_updatable_value_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,
@@ -108,17 +122,23 @@
 const GdmConfigEntry * gdm_config_lookup_entry_for_id    (GdmConfig            *config,
 							  int                   id);
 
-gboolean               gdm_config_load                   (GdmConfig             *config,
+GdmConfigStatus        gdm_config_load                   (GdmConfig             *config,
 							  GError               **error);
 gboolean               gdm_config_process_all            (GdmConfig             *config,
-							  GError               **error);
+							  GError               **error,
+							  gboolean               do_notify,
+							  gboolean               doing_update);
 gboolean               gdm_config_process_entry          (GdmConfig             *config,
 							  const GdmConfigEntry  *entry,
-							  GError               **error);
+							  GError               **error,
+							  gboolean               do_notify,
+							  gboolean               doing_update);
 gboolean               gdm_config_process_entries        (GdmConfig             *config,
 							  const GdmConfigEntry **entries,
 							  gsize                  n_entries,
-							  GError               **error);
+							  GError               **error,
+							  gboolean               do_notify,
+							  gboolean               doing_update);
 
 gboolean               gdm_config_save_custom_file       (GdmConfig       *config,
 							  GError         **error);
--- gdm2/common/gdm-config.c.org	2007-05-09 12:15:48.000000000 +0100
+++ gdm2/common/gdm-config.c	2007-05-09 12:15:48.000000000 +0100
@@ -40,10 +40,10 @@
 	char            *default_filename;
 	char            *custom_filename;
 
-	gboolean         mandatory_loaded;
-	gboolean         default_loaded;
-	gboolean         custom_loaded;
-
+	GdmConfigStatus  mandatory_loaded;
+	GdmConfigStatus  default_loaded;
+	GdmConfigStatus  custom_loaded;
+	
 	GKeyFile        *mandatory_key_file;
 	GKeyFile        *default_key_file;
 	GKeyFile        *custom_key_file;
@@ -60,18 +60,21 @@
 	gpointer         validate_func_data;
 	GdmConfigFunc    notify_func;
 	gpointer         notify_func_data;
+	GdmConfigFunc    notify_status_func;
+	gpointer         notify_status_func_data;
+	GdmConfigFunc    updatable_value_func;
+	gpointer         updatable_value_func_data;
 };
 
-
 typedef struct _GdmConfigRealValue
 {
-	GdmConfigValueType type;
-	union {
-		gboolean bool;
-		int      integer;
-		char    *str;
-		char   **array;
-	} val;
+        GdmConfigValueType type;
+        union {
+                gboolean bool;
+                int      integer;
+                char    *str;
+                char   **array;
+        } val;
 } GdmConfigRealValue;
 
 #define REAL_VALUE(x) ((GdmConfigRealValue *)(x))
@@ -744,6 +747,28 @@
 	config->notify_func_data = data;
 }
 
+void
+gdm_config_set_notify_status_func (GdmConfig       *config,
+				   GdmConfigFunc    func,
+				   gpointer         data)
+{
+	g_return_if_fail (config != NULL);
+	
+	config->notify_status_func = func;
+	config->notify_status_func_data = data;
+}
+
+void
+gdm_config_set_updatable_value_func (GdmConfig       *config,
+				     GdmConfigFunc    func,
+				     gpointer         data)
+{
+	g_return_if_fail (config != NULL);
+
+	config->updatable_value_func = func;
+	config->updatable_value_func_data = data;
+}
+
 static gboolean
 key_file_get_value (GdmConfig            *config,
 		    GKeyFile             *key_file,
@@ -929,7 +954,8 @@
 		    GdmConfigSourceType source,
 		    const char         *group,
 		    const char         *key,
-		    GdmConfigValue     *value)
+		    GdmConfigValue     *value,
+		    gboolean            do_notify)
 {
 	char           *key_path;
 	int             id;
@@ -959,8 +985,15 @@
 
 	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);
+	if (do_notify) {
+		if (config->notify_func) {
+			(* config->notify_func) (config, source, group, key, value, id, config->notify_func_data);
+		}
+	}
+	else {
+		if (config->notify_status_func) {
+			(* config->notify_status_func) (config, source, group, key, value, id, config->notify_status_func_data);
+		}
 	}
  out:
 	g_free (key_path);
@@ -970,14 +1003,17 @@
 store_entry_value (GdmConfig            *config,
 		   const GdmConfigEntry *entry,
 		   GdmConfigSourceType   source,
-		   GdmConfigValue       *value)
+		   GdmConfigValue       *value,
+		   gboolean              do_notify)
 {
-	internal_set_value (config, source, entry->group, entry->key, value);
+	internal_set_value (config, source, entry->group, entry->key, value, do_notify);
 }
 
 static gboolean
 load_entry (GdmConfig            *config,
-	    const GdmConfigEntry *entry)
+	    const GdmConfigEntry *entry,
+	    gboolean              do_notify,
+	    gboolean              doing_update)
 {
 	GdmConfigValue     *value;
 	GdmConfigSourceType source;
@@ -992,16 +1028,21 @@
 	}
 
 	res = TRUE;
+	
 	if (config->validate_func) {
 		res = (* config->validate_func) (config, source, entry->group, entry->key, value, entry->id, config->validate_func_data);
 	}
 
+	if (doing_update && config->updatable_value_func) {
+		res = (* config->updatable_value_func) (config, source, entry->group, entry->key, value, entry->id, config->updatable_value_func_data);
+	}
+
 	if (res) {
 		/* store runs notify */
-		store_entry_value (config, entry, source, value);
+		store_entry_value (config, entry, source, value, do_notify);
 	}
 
-	return TRUE;
+	return res;
 }
 
 static void
@@ -1078,7 +1119,7 @@
 	return (char **)g_ptr_array_free (array, FALSE);
 }
 
-static gboolean
+static GdmConfigStatus
 load_backend (GdmConfig  *config,
 	      const char *filename,
 	      GKeyFile  **key_file,
@@ -1092,11 +1133,11 @@
 	time_t      lmtime;
 
 	if (filename == NULL) {
-		return FALSE;
+		return GDM_CONFIG_LOAD_FAILURE;
 	}
 
 	if (g_stat (filename, &statbuf) != 0) {
-		return FALSE;
+		return GDM_CONFIG_LOAD_FAILURE;
 	}
 	lmtime = statbuf.st_mtime;
 
@@ -1107,7 +1148,7 @@
 			g_key_file_free (*key_file);
 		} else {
 			/* no reload necessary so we're done */
-			return TRUE;
+			return GDM_CONFIG_FILE_UNCHANGED;
 		}
 	}
 
@@ -1123,9 +1164,9 @@
 		g_key_file_free (kf);
 		kf = NULL;
 		lmtime = 0;
-		ret = FALSE;
+		ret = GDM_CONFIG_LOAD_FAILURE;
 	} else {
-		ret = TRUE;
+		ret = GDM_CONFIG_LOAD_SUCCESS;
 	}
 
 	*key_file = kf;
@@ -1134,7 +1175,7 @@
 	return ret;
 }
 
-gboolean
+GdmConfigStatus
 gdm_config_load (GdmConfig *config,
 		 GError   **error)
 {
@@ -1153,14 +1194,27 @@
 					      &config->custom_key_file,
 					      &config->custom_mtime);
 
-	return TRUE;
+	
+	/*	 
+	  Atm config->mandatory_loaded is not used hence is not included
+	  in the return value. if that isn't the case anymore it will have to
+	  be included in the return value (if applicable)
+	*/
+	return (config->default_loaded | config->custom_loaded);
 }
 
+/* The key ID's should correspond to the ID's of the keys present in the 
+ * gdm_daemon_config_update_key function and marked not to be updated 
+ * during runtime. If you decide to add a key dont foret to update its
+ * value in the function mentined earlier, in this function and also
+ */
 static gboolean
 process_entries (GdmConfig             *config,
 		 const GdmConfigEntry **entries,
 		 gsize                  n_entries,
-		 GError               **error)
+		 GError               **error,
+		 gboolean               do_notify,
+		 gboolean               doing_update)
 {
 	gboolean ret;
 	int      i;
@@ -1168,23 +1222,25 @@
 	ret = TRUE;
 
 	for (i = 0; i < n_entries; i++) {
-		load_entry (config, entries[i]);
+		load_entry (config, entries[i], do_notify, doing_update);		
 	}
-
+	
 	return ret;
 }
 
 gboolean
 gdm_config_process_entry (GdmConfig            *config,
 			  const GdmConfigEntry *entry,
-			  GError              **error)
+			  GError              **error,
+			  gboolean              do_notify,
+			  gboolean              doing_update)
 {
 	gboolean  ret;
 
 	g_return_val_if_fail (config != NULL, FALSE);
-	g_return_val_if_fail (entry != NULL, FALSE);
+	g_return_val_if_fail (entry != NULL, FALSE);	
 
-	ret = load_entry (config, entry);
+	ret = load_entry (config, entry, do_notify, doing_update);
 
 	return ret;
 }
@@ -1193,7 +1249,9 @@
 gdm_config_process_entries (GdmConfig             *config,
 			    const GdmConfigEntry **entries,
 			    gsize                  n_entries,
-			    GError               **error)
+			    GError               **error,
+			    gboolean               do_notify,
+			    gboolean               doing_update)
 {
 	gboolean  ret;
 
@@ -1201,14 +1259,16 @@
 	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);
+	ret = process_entries (config, entries, n_entries, error, do_notify, doing_update);
 
 	return ret;
 }
 
 gboolean
 gdm_config_process_all (GdmConfig *config,
-			GError   **error)
+			GError   **error,
+			gboolean   do_notify,
+			gboolean   doing_update)
 {
 	gboolean  ret;
 
@@ -1217,7 +1277,9 @@
 	ret = process_entries (config,
 			       (const GdmConfigEntry **)config->entries->pdata,
 			       config->entries->len,
-			       error);
+			       error,
+		               do_notify,
+			       doing_update);
 
 	return ret;
 }
@@ -1281,7 +1343,7 @@
 	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);
+	internal_set_value (config, GDM_CONFIG_SOURCE_RUNTIME_USER, group, key, value, TRUE);
 
 	return TRUE;
 }
