Index: irc.c
===================================================================
--- irc.c	(revision 3ddb7477f51d3cf1632e2a8b6f7da4c0609a52cb)
+++ irc.c	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
@@ -124,5 +124,5 @@
 	irc->user->host = g_strdup( host );
 	
-	conf_loaddefaults( b );
+	conf_loaddefaults( irc );
 	
 	/* Evaluator sets the iconv/oconv structures. */
@@ -130,4 +130,7 @@
 	
 	irc_write( irc, ":%s NOTICE AUTH :%s", irc->root->host, "BitlBee-IRCd initialized, please go on" );
+	
+	g_free( myhost );
+	g_free( host );
 	
 	return irc;
@@ -203,5 +206,8 @@
 	
 	while( irc->users )
-		irc_user_free( irc, irc->users->data );
+	{
+		irc_user_t *iu = irc->users->data;
+		irc_user_free( irc, iu->nick );
+	}
 	
 	if( irc->ping_source_id > 0 )
Index: irc.h
===================================================================
--- irc.h	(revision 3ddb7477f51d3cf1632e2a8b6f7da4c0609a52cb)
+++ irc.h	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
@@ -139,4 +139,5 @@
 irc_user_t *irc_user_find( irc_t *irc, const char *nick );
 int irc_user_rename( irc_t *irc, const char *old, const char *new );
+gint irc_user_cmp( gconstpointer a_, gconstpointer b_ );
 
 #endif
Index: irc_commands.c
===================================================================
--- irc_commands.c	(revision 3ddb7477f51d3cf1632e2a8b6f7da4c0609a52cb)
+++ irc_commands.c	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
@@ -94,5 +94,4 @@
 }
 
-#if 0
 static void irc_cmd_quit( irc_t *irc, char **cmd )
 {
@@ -105,7 +104,9 @@
 static void irc_cmd_ping( irc_t *irc, char **cmd )
 {
-	irc_write( irc, ":%s PONG %s :%s", irc->myhost, irc->myhost, cmd[1]?cmd[1]:irc->myhost );
-}
-
+	irc_write( irc, ":%s PONG %s :%s", irc->root->host,
+	           irc->root->host, cmd[1]?cmd[1]:irc->root->host );
+}
+
+#if 0
 static void irc_cmd_oper( irc_t *irc, char **cmd )
 {
@@ -580,7 +581,7 @@
 	{ "user",        4, irc_cmd_user,        IRC_CMD_PRE_LOGIN },
 	{ "nick",        1, irc_cmd_nick,        0 },
-#if 0
 	{ "quit",        0, irc_cmd_quit,        0 },
 	{ "ping",        0, irc_cmd_ping,        0 },
+#if 0
 	{ "oper",        2, irc_cmd_oper,        IRC_CMD_LOGGED_IN },
 	{ "mode",        1, irc_cmd_mode,        IRC_CMD_LOGGED_IN },
Index: irc_send.c
===================================================================
--- irc_send.c	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
+++ irc_send.c	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
@@ -0,0 +1,153 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2010 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* The IRC-based UI - Sending responses to commands/etc.                */
+
+/*
+  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 with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "bitlbee.h"
+
+void irc_send_num( irc_t *irc, int code, char *format, ... )
+{
+	char text[IRC_MAX_LINE];
+	va_list params;
+	
+	va_start( params, format );
+	g_vsnprintf( text, IRC_MAX_LINE, format, params );
+	va_end( params );
+	irc_write( irc, ":%s %03d %s %s", irc->root->host, code, irc->user->nick ? : "*", text );
+	
+	return;
+}
+
+void irc_send_login( irc_t *irc )
+{
+	irc_user_t *iu = irc->user;
+	
+	irc->user = irc_user_new( irc, iu->nick );
+	irc->user->user = iu->user;
+	irc->user->fullname = iu->fullname;
+	g_free( iu->nick );
+	g_free( iu );
+	
+	irc_send_num( irc,   1, ":Welcome to the BitlBee gateway, %s", irc->user->nick );
+	irc_send_num( irc,   2, ":Host %s is running BitlBee " BITLBEE_VERSION " " ARCH "/" CPU ".", irc->root->host );
+	irc_send_num( irc,   3, ":%s", IRCD_INFO );
+	irc_send_num( irc,   4, "%s %s %s %s", irc->root->host, BITLBEE_VERSION, UMODES UMODES_PRIV, CMODES );
+	irc_send_num( irc,   5, "PREFIX=(ov)@+ CHANTYPES=%s CHANMODES=,,,%s NICKLEN=%d NETWORK=BitlBee "
+	                        "CASEMAPPING=rfc1459 MAXTARGETS=1 WATCH=128 :are supported by this server",
+	                        CTYPES, CMODES, MAX_NICK_LENGTH - 1 );
+	irc_send_motd( irc );
+	irc->umode[0] = '\0';
+	/*irc_umode_set( irc, "+" UMODE, 1 );*/
+	
+	irc_usermsg( irc, "Welcome to the BitlBee gateway!\n\n"
+	                  "If you've never used BitlBee before, please do read the help "
+	                  "information using the \x02help\x02 command. Lots of FAQs are "
+	                  "answered there.\n"
+	                  "If you already have an account on this server, just use the "
+	                  "\x02identify\x02 command to identify yourself." );
+	
+	if( global.conf->runmode == RUNMODE_FORKDAEMON || global.conf->runmode == RUNMODE_DAEMON )
+		ipc_to_master_str( "CLIENT %s %s :%s\r\n", irc->user->host, irc->user->nick, irc->user->fullname );
+	
+	irc->status |= USTATUS_LOGGED_IN;
+	
+	/* This is for bug #209 (use PASS to identify to NickServ). */
+	if( irc->password != NULL )
+	{
+		char *send_cmd[] = { "identify", g_strdup( irc->password ), NULL };
+		
+		/*irc_setpass( irc, NULL );*/
+		/*root_command( irc, send_cmd );*/
+		g_free( send_cmd[1] );
+	}
+}
+
+void irc_send_motd( irc_t *irc )
+{
+	int fd;
+	
+	fd = open( global.conf->motdfile, O_RDONLY );
+	if( fd == -1 )
+	{
+		irc_send_num( irc, 422, ":We don't need MOTDs." );
+	}
+	else
+	{
+		char linebuf[80];	/* Max. line length for MOTD's is 79 chars. It's what most IRC networks seem to do. */
+		char *add, max;
+		int len;
+		
+		linebuf[79] = len = 0;
+		max = sizeof( linebuf ) - 1;
+		
+		irc_send_num( irc, 375, ":- %s Message Of The Day - ", irc->root->host );
+		while( read( fd, linebuf + len, 1 ) == 1 )
+		{
+			if( linebuf[len] == '\n' || len == max )
+			{
+				linebuf[len] = 0;
+				irc_send_num( irc, 372, ":- %s", linebuf );
+				len = 0;
+			}
+			else if( linebuf[len] == '%' )
+			{
+				read( fd, linebuf + len, 1 );
+				if( linebuf[len] == 'h' )
+					add = irc->root->host;
+				else if( linebuf[len] == 'v' )
+					add = BITLBEE_VERSION;
+				else if( linebuf[len] == 'n' )
+					add = irc->user->nick;
+				else
+					add = "%";
+				
+				strncpy( linebuf + len, add, max - len );
+				while( linebuf[++len] );
+			}
+			else if( len < max )
+			{
+				len ++;
+			}
+		}
+		irc_send_num( irc, 376, ":End of MOTD" );
+		close( fd );
+	}
+}
+
+/* FIXME/REPLACEME */
+int irc_usermsg( irc_t *irc, char *format, ... )
+{
+	char text[1024];
+	va_list params;
+	//irc_user_t *iu;
+	
+	va_start( params, format );
+	g_vsnprintf( text, sizeof( text ), format, params );
+	va_end( params );
+	
+	fprintf( stderr, "%s\n", text );
+	
+	return 1;
+	
+	/*return( irc_msgfrom( irc, u->nick, text ) );*/
+}
Index: irc_user.c
===================================================================
--- irc_user.c	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
+++ irc_user.c	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
@@ -0,0 +1,113 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* Stuff to handle, save and search IRC buddies                         */
+
+/*
+  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 with
+  the Debian GNU/Linux distribution in /usr/share/common-licenses/GPL;
+  if not, write to the Free Software Foundation, Inc., 59 Temple Place,
+  Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "bitlbee.h"
+
+irc_user_t *irc_user_new( irc_t *irc, const char *nick )
+{
+	irc_user_t *iu = g_new0( irc_user_t, 1 );
+	
+	iu->nick = g_strdup( nick );
+	iu->user = iu->host = iu->fullname = iu->nick;
+	
+	iu->is_private = set_getbool( &irc->b->set, "private" );
+	
+	iu->key = g_strdup( nick );
+	nick_lc( iu->key );
+	/* Using the hash table for speed and irc->users for easy iteration
+	   through the list (since the GLib API doesn't have anything sane
+	   for that.) */
+	g_hash_table_insert( irc->nick_user_hash, iu->key, iu );
+	irc->users = g_slist_insert_sorted( irc->users, iu, irc_user_cmp );
+	
+	return iu;
+}
+
+int irc_user_free( irc_t *irc, const char *nick )
+{
+	irc_user_t *iu;
+	
+	if( !( iu = irc_user_find( irc, nick ) ) )
+		return 0;
+	
+	irc->users = g_slist_remove( irc->users, iu );
+	g_hash_table_remove( irc->nick_user_hash, iu->key );
+	
+	g_free( iu->nick );
+	if( iu->nick != iu->user ) g_free( iu->user );
+	if( iu->nick != iu->host ) g_free( iu->host );
+	if( iu->nick != iu->fullname ) g_free( iu->fullname );
+	g_free( iu->sendbuf );
+	if( iu->sendbuf_timer ) b_event_remove( iu->sendbuf_timer );
+	g_free( iu->key );
+	
+	return 1;
+}
+
+irc_user_t *irc_user_find( irc_t *irc, const char *nick )
+{
+	char key[strlen(nick)+1];
+	
+	strcpy( key, nick );
+	if( nick_lc( key ) )
+		return g_hash_table_lookup( irc->nick_user_hash, key );
+	else
+		return NULL;
+}
+
+int irc_user_rename( irc_t *irc, const char *old, const char *new )
+{
+	irc_user_t *iu = irc_user_find( irc, old );
+	char key[strlen(new)+1];
+	
+	strcpy( key, new );
+	if( iu == NULL || !nick_lc( key ) || irc_user_find( irc, new ) )
+		return 0;
+	
+	irc->users = g_slist_remove( irc->users, iu );
+	g_hash_table_remove( irc->nick_user_hash, iu->key );
+	
+	if( iu->nick == iu->user ) iu->user = NULL;
+	if( iu->nick == iu->host ) iu->host = NULL;
+	if( iu->nick == iu->fullname ) iu->fullname = NULL;
+	g_free( iu->nick );
+	iu->nick = g_strdup( new );
+	if( iu->user == NULL ) iu->user = g_strdup( iu->nick );
+	if( iu->host == NULL ) iu->host = g_strdup( iu->nick );
+	if( iu->fullname == NULL ) iu->fullname = g_strdup( iu->nick );
+	
+	iu->key = g_strdup( key );
+	g_hash_table_insert( irc->nick_user_hash, iu->key, iu );
+	irc->users = g_slist_insert_sorted( irc->users, iu, irc_user_cmp );
+	
+	return 1;
+}
+
+gint irc_user_cmp( gconstpointer a_, gconstpointer b_ )
+{
+	const irc_user_t *a = a_, *b = b_;
+	
+	return strcmp( a->key, b->key );
+}
Index: protocols/bee.c
===================================================================
--- protocols/bee.c	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
+++ protocols/bee.c	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
@@ -0,0 +1,47 @@
+#include "bitlbee.h"
+
+bee_t *bee_new()
+{
+	bee_t *b = g_new0( bee_t, 1 );
+	set_t *s;
+	
+	s = set_add( &b->set, "away", NULL, NULL/*set_eval_away_status*/, b );
+	s->flags |= SET_NULL_OK;
+	s = set_add( &b->set, "auto_connect", "true", set_eval_bool, b );
+	s = set_add( &b->set, "auto_reconnect", "true", set_eval_bool, b );
+	s = set_add( &b->set, "auto_reconnect_delay", "5*3<900", NULL/*set_eval_account_reconnect_delay*/, b );
+	s = set_add( &b->set, "debug", "false", set_eval_bool, b );
+	s = set_add( &b->set, "password", NULL, NULL/*set_eval_password*/, b );
+	s->flags |= SET_NULL_OK;
+	s = set_add( &b->set, "save_on_quit", "true", set_eval_bool, b );
+	s = set_add( &b->set, "status", NULL, NULL/*set_eval_away_status*/, b );
+	s->flags |= SET_NULL_OK;
+	s = set_add( &b->set, "strip_html", "true", NULL, b );
+	
+	return b;
+}
+
+void bee_free( bee_t *b )
+{
+	while( b->accounts )
+	{
+		account_t *acc = b->accounts->data;
+		
+		/*
+		if( acc->ic )
+			imc_logout( acc->ic, FALSE );
+		else if( acc->reconnect )
+			cancel_auto_reconnect( acc );
+		*/
+		
+		if( acc->ic == NULL )
+			{} //account_del( b, acc );
+		else
+			/* Nasty hack, but account_del() doesn't work in this
+			   case and we don't want infinite loops, do we? ;-) */
+			b->accounts = g_slist_remove( b->accounts, acc );
+	}
+	
+	while( b->set )
+		set_del( &b->set, b->set->key );
+}
Index: protocols/bee.h
===================================================================
--- protocols/bee.h	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
+++ protocols/bee.h	(revision ebaebfe35c82460581fa6db518d8848996c9a0f4)
@@ -0,0 +1,18 @@
+typedef struct bee_ui
+{
+	void *data;
+} bee_ui_t;
+
+typedef struct bee
+{
+	struct set *set;
+	
+	GSList *users;
+	GSList *accounts;
+	
+	//const bee_ui_funcs_t *ui;
+	void *ui_data;
+} bee_t;
+
+bee_t *bee_new();
+void bee_free( bee_t *b );
