Index: account.c
===================================================================
--- account.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ account.c	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -77,5 +77,5 @@
 	/* Double-check: We refuse to edit on-line accounts. */
 	if( set->flags & ACC_SET_OFFLINE_ONLY && acc->ic )
-		return NULL;
+		return SET_INVALID;
 	
 	if( strcmp( set->key, "server" ) == 0 )
@@ -89,11 +89,7 @@
 		else
 		{
-			acc->server = NULL;
+			acc->server = g_strdup( set->def );
 			return g_strdup( set->def );
 		}
-	}
-	else if( value == NULL )
-	{
-		/* Noop, the other three can't be NULL. */
 	}
 	else if( strcmp( set->key, "username" ) == 0 )
@@ -105,12 +101,21 @@
 	else if( strcmp( set->key, "password" ) == 0 )
 	{
-		g_free( acc->pass );
-		acc->pass = g_strdup( value );
-		return NULL;	/* password shouldn't be visible in plaintext! */
+		if( value )
+		{
+			g_free( acc->pass );
+			acc->pass = g_strdup( value );
+			return NULL;	/* password shouldn't be visible in plaintext! */
+		}
+		else
+		{
+			/* NULL can (should) be stored in the set_t
+			   variable, but is otherwise not correct. */
+			return SET_INVALID;
+		}
 	}
 	else if( strcmp( set->key, "auto_connect" ) == 0 )
 	{
 		if( !is_bool( value ) )
-			return NULL;
+			return SET_INVALID;
 		
 		acc->auto_connect = bool2int( value );
@@ -118,5 +123,5 @@
 	}
 	
-	return NULL;
+	return SET_INVALID;
 }
 
@@ -258,5 +263,5 @@
 	
 	/* Sure, call me evil for implementing my own fscanf here, but it's
-	   dead simple and I'm immediately at the next part to parse. */
+	   dead simple and I immediately know where to continue parsing. */
 	
 	if( *value == 0 )
@@ -291,5 +296,5 @@
 	struct account_reconnect_delay p;
 	
-	return account_reconnect_delay_parse( value, &p ) ? value : NULL;
+	return account_reconnect_delay_parse( value, &p ) ? value : SET_INVALID;
 }
 
Index: account.h
===================================================================
--- account.h	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ account.h	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -56,7 +56,7 @@
 int account_reconnect_delay( account_t *a );
 
-#define ACC_SET_NOSAVE		1
-#define ACC_SET_OFFLINE_ONLY	2
-#define ACC_SET_ONLINE_ONLY	4
+#define ACC_SET_NOSAVE		0x01
+#define ACC_SET_OFFLINE_ONLY	0x02
+#define ACC_SET_ONLINE_ONLY	0x04
 
 #endif
Index: irc.c
===================================================================
--- irc.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ irc.c	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -77,4 +77,5 @@
 	struct sockaddr_storage sock;
 	socklen_t socklen = sizeof( sock );
+	set_t *s;
 	
 	irc = g_new0( irc_t, 1 );
@@ -136,26 +137,27 @@
 	irc_connection_list = g_slist_append( irc_connection_list, irc );
 	
-	set_add( &irc->set, "away_devoice", "true",  set_eval_away_devoice, irc );
-	set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
-	set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc );
-	set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc );
-	set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
-	set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
-	set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
-	set_add( &irc->set, "debug", "false", set_eval_bool, irc );
-	set_add( &irc->set, "default_target", "root", NULL, irc );
-	set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );
-	set_add( &irc->set, "handle_unknown", "root", NULL, irc );
-	set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc );
-	set_add( &irc->set, "ops", "both", set_eval_ops, irc );
-	set_add( &irc->set, "password", NULL, passchange, irc );
-	set_add( &irc->set, "private", "true", set_eval_bool, irc );
-	set_add( &irc->set, "query_order", "lifo", NULL, irc );
-	set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
-	set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
-	set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
-	set_add( &irc->set, "strip_html", "true", NULL, irc );
-	set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );
-	set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
+	s = set_add( &irc->set, "away_devoice", "true",  set_eval_away_devoice, irc );
+	s = set_add( &irc->set, "auto_connect", "true", set_eval_bool, irc );
+	s = set_add( &irc->set, "auto_reconnect", "false", set_eval_bool, irc );
+	s = set_add( &irc->set, "auto_reconnect_delay", "5*3<900", set_eval_account_reconnect_delay, irc );
+	s = set_add( &irc->set, "buddy_sendbuffer", "false", set_eval_bool, irc );
+	s = set_add( &irc->set, "buddy_sendbuffer_delay", "200", set_eval_int, irc );
+	s = set_add( &irc->set, "charset", "utf-8", set_eval_charset, irc );
+	s = set_add( &irc->set, "debug", "false", set_eval_bool, irc );
+	s = set_add( &irc->set, "default_target", "root", NULL, irc );
+	s = set_add( &irc->set, "display_namechanges", "false", set_eval_bool, irc );
+	s = set_add( &irc->set, "handle_unknown", "root", NULL, irc );
+	s = set_add( &irc->set, "lcnicks", "true", set_eval_bool, irc );
+	s = set_add( &irc->set, "ops", "both", set_eval_ops, irc );
+	s = set_add( &irc->set, "password", NULL, passchange, irc );
+	s->flags |= SET_NULL_OK;
+	s = set_add( &irc->set, "private", "true", set_eval_bool, irc );
+	s = set_add( &irc->set, "query_order", "lifo", NULL, irc );
+	s = set_add( &irc->set, "root_nick", irc->mynick, set_eval_root_nick, irc );
+	s = set_add( &irc->set, "save_on_quit", "true", set_eval_bool, irc );
+	s = set_add( &irc->set, "simulate_netsplit", "true", set_eval_bool, irc );
+	s = set_add( &irc->set, "strip_html", "true", NULL, irc );
+	s = set_add( &irc->set, "to_char", ": ", set_eval_to_char, irc );
+	s = set_add( &irc->set, "typing_notice", "false", set_eval_bool, irc );
 	
 	conf_loaddefaults( irc );
Index: protocols/jabber/jabber.c
===================================================================
--- protocols/jabber/jabber.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ protocols/jabber/jabber.c	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -70,5 +70,5 @@
 	
 	s = set_add( &acc->set, "server", NULL, set_eval_account, acc );
-	s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY;
+	s->flags |= ACC_SET_NOSAVE | ACC_SET_OFFLINE_ONLY | SET_NULL_OK;
 	
 	s = set_add( &acc->set, "ssl", "false", set_eval_bool, acc );
Index: protocols/jabber/jabber_util.c
===================================================================
--- protocols/jabber/jabber_util.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ protocols/jabber/jabber_util.c	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -37,8 +37,8 @@
 		/* Priority is a signed 8-bit integer, according to RFC 3921. */
 		if( i < -128 || i > 127 )
-			return NULL;
+			return SET_INVALID;
 	}
 	else
-		return NULL;
+		return SET_INVALID;
 	
 	/* Only run this stuff if the account is online ATM,
Index: protocols/nogaim.c
===================================================================
--- protocols/nogaim.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ protocols/nogaim.c	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -928,12 +928,8 @@
 	int st;
 	
-	if( ( g_strcasecmp( value, "true" ) == 0 ) || ( g_strcasecmp( value, "yes" ) == 0 ) || ( g_strcasecmp( value, "on" ) == 0 ) )
-		st = 1;
-	else if( ( g_strcasecmp( value, "false" ) == 0 ) || ( g_strcasecmp( value, "no" ) == 0 ) || ( g_strcasecmp( value, "off" ) == 0 ) )
-		st = 0;
-	else if( sscanf( value, "%d", &st ) != 1 )
-		return( NULL );
-	
-	st = st != 0;
+	if( !is_bool( value ) )
+		return SET_INVALID;
+	
+	st = bool2int( value );
 	
 	/* Horror.... */
@@ -979,5 +975,5 @@
 	}
 	
-	return( set_eval_bool( set, value ) );
+	return value;
 }
 
Index: root_commands.c
===================================================================
--- root_commands.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ root_commands.c	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -610,4 +610,6 @@
 			irc->mynick = g_strdup( cmd[2] );
 			
+			/* If we're called internally (user did "set root_nick"),
+			   let's not go O(INF). :-) */
 			if( strcmp( cmd[0], "set_rename" ) != 0 )
 				set_setstr( &irc->set, "root_nick", cmd[2] );
@@ -633,5 +635,5 @@
 	}
 	
-	return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : NULL;
+	return strcmp( irc->mynick, new_nick ) == 0 ? new_nick : SET_INVALID;
 }
 
Index: set.c
===================================================================
--- set.c	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ set.c	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -25,4 +25,7 @@
 #define BITLBEE_CORE
 #include "bitlbee.h"
+
+/* Used to use NULL for this, but NULL is actually a "valid" value. */
+char *SET_INVALID = "nee";
 
 set_t *set_add( set_t **head, char *key, char *def, set_eval eval, void *data )
@@ -114,7 +117,18 @@
 	
 	if( !s )
+		/*
+		Used to do this, but it never really made sense.
 		s = set_add( head, key, NULL, NULL, NULL );
-	
-	if( s->eval && !( nv = s->eval( s, value ) ) )
+		*/
+		return 0;
+	
+	if( value == NULL && ( s->flags & SET_NULL_OK ) == 0 )
+		return 0;
+	
+	/* Call the evaluator. For invalid values, evaluators should now
+	   return SET_INVALID, but previously this was NULL. Try to handle
+	   that too if NULL is not an allowed value for this setting. */
+	if( s->eval && ( ( nv = s->eval( s, value ) ) == SET_INVALID ||
+	                 ( ( s->flags & SET_NULL_OK ) == 0 && nv == NULL ) ) )
 		return 0;
 	
@@ -187,5 +201,5 @@
 	for( ; *s; s ++ )
 		if( !isdigit( *s ) )
-			return NULL;
+			return SET_INVALID;
 	
 	return value;
@@ -194,5 +208,5 @@
 char *set_eval_bool( set_t *set, char *value )
 {
-	return is_bool( value ) ? value : NULL;
+	return is_bool( value ) ? value : SET_INVALID;
 }
 
@@ -226,5 +240,5 @@
 		                                              irc->channel, "-oo", irc->nick, irc->mynick );
 	else
-		return NULL;
+		return SET_INVALID;
 	
 	return value;
Index: set.h
===================================================================
--- set.h	(revision 934dddf3614eae2b4f305f42583b070bdbd5bc86)
+++ set.h	(revision 7125cb3775a0e384c0f2fc08fd56df9582199502)
@@ -44,4 +44,8 @@
 typedef char *(*set_eval) ( struct set *set, char *value );
 
+extern char *SET_INVALID;
+
+#define SET_NULL_OK        0x0100
+
 typedef struct set
 {
@@ -61,6 +65,6 @@
 	                   this (yet?). */
 	
-	/* Eval: Returns NULL if the value is incorrect or exactly the
-	   passed value variable. When returning a corrected value,
+	/* Eval: Returns SET_INVALID if the value is incorrect or exactly
+	   the passed value variable. When returning a corrected value,
 	   set_setstr() should be able to free() the returned string! */
 	set_eval eval;
