Index: Makefile
===================================================================
--- Makefile	(revision c2295f7eeac263dbcc19f84e9a61abbe778aa9f8)
+++ Makefile	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -10,5 +10,5 @@
 
 # Program variables
-objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o irc.o log.o nick.o query.o set.o unix.o url.o user.o
+objects = account.o bitlbee.o commands.o conf.o crypting.o help.o ini.o irc.o log.o nick.o query.o set.o unix.o url.o user.o storage_text.o storage.o
 subdirs = protocols
 
Index: bitlbee.c
===================================================================
--- bitlbee.c	(revision c2295f7eeac263dbcc19f84e9a61abbe778aa9f8)
+++ bitlbee.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -27,5 +27,4 @@
 #include "bitlbee.h"
 #include "commands.h"
-#include "crypting.h"
 #include "protocols/nogaim.h"
 #include "help.h"
@@ -244,222 +243,4 @@
 }
 
-int bitlbee_load( irc_t *irc, const char* password )
-{
-	char s[512];
-	char *line;
-	int proto;
-	char nick[MAX_NICK_LENGTH+1];
-	FILE *fp;
-	user_t *ru = user_find( irc, ROOT_NICK );
-	
-	if( irc->status == USTATUS_IDENTIFIED )
-		return( 1 );
-	
-	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
-   	fp = fopen( s, "r" );
-   	if( !fp ) return( 0 );
-	
-	fscanf( fp, "%32[^\n]s", s );
-	if( setpass( irc, password, s ) < 0 )
-	{
-		fclose( fp );
-		return( -1 );
-	}
-	
-	/* Do this now. If the user runs with AuthMode = Registered, the
-	   account command will not work otherwise. */
-	irc->status = USTATUS_IDENTIFIED;
-	
-	while( fscanf( fp, "%511[^\n]s", s ) > 0 )
-	{
-		fgetc( fp );
-		line = deobfucrypt( irc, s );
-		root_command_string( irc, ru, line, 0 );
-		g_free( line );
-	}
-	fclose( fp );
-	
-	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
-	fp = fopen( s, "r" );
-	if( !fp ) return( 0 );
-	while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 )
-	{
-		http_decode( s );
-		nick_set( irc, s, proto, nick );
-	}
-	fclose( fp );
-	
-	if( set_getint( irc, "auto_connect" ) )
-	{
-		strcpy( s, "account on" );	/* Can't do this directly because r_c_s alters the string */
-		root_command_string( irc, ru, s, 0 );
-	}
-	
-	return( 1 );
-}
-
-int bitlbee_save( irc_t *irc )
-{
-	char s[512];
-	char path[512], new_path[512];
-	char *line;
-	nick_t *n;
-	set_t *set;
-	mode_t ou = umask( 0077 );
-	account_t *a;
-	FILE *fp;
-	char *hash;
-	
-	/*\
-	 *  [SH] Nothing should be saved if no password is set, because the
-	 *  password is not set if it was wrong, or if one is not identified
-	 *  yet. This means that a malicious user could easily overwrite
-	 *  files owned by someone else:
-	 *  a Bad Thing, methinks
-	\*/
-
-	/* [WVG] No? Really? */
-
-	/*\
-	 *  [SH] Okay, okay, it wasn't really Wilmer who said that, it was
-	 *  me. I just thought it was funny.
-	\*/
-	
-	hash = hashpass( irc );
-	if( hash == NULL )
-	{
-		irc_usermsg( irc, "Please register yourself if you want to save your settings." );
-		return( 0 );
-	}
-	
-	g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" );
-	fp = fopen( path, "w" );
-	if( !fp ) return( 0 );
-	for( n = irc->nicks; n; n = n->next )
-	{
-		strcpy( s, n->handle );
-		s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */
-		http_encode( s );
-		g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", n->proto, n->nick );
-		if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 )
-		{
-			irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
-			fclose( fp );
-			return( 0 );
-		}
-	}
-	if( fclose( fp ) != 0 )
-	{
-		irc_usermsg( irc, "fclose() reported an error. Disk full?" );
-		return( 0 );
-	}
-  
-	g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
-	if( unlink( new_path ) != 0 )
-	{
-		if( errno != ENOENT )
-		{
-			irc_usermsg( irc, "Error while removing old .nicks file" );
-			return( 0 );
-		}
-	}
-	if( rename( path, new_path ) != 0 )
-	{
-		irc_usermsg( irc, "Error while renaming new .nicks file" );
-		return( 0 );
-	}
-	
-	g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" );
-	fp = fopen( path, "w" );
-	if( !fp ) return( 0 );
-	if( fprintf( fp, "%s", hash ) != strlen( hash ) )
-	{
-		irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
-		fclose( fp );
-		return( 0 );
-	}
-	g_free( hash );
-
-	for( a = irc->accounts; a; a = a->next )
-	{
-		if( a->protocol == PROTO_OSCAR || a->protocol == PROTO_ICQ || a->protocol == PROTO_TOC )
-			g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server );
-		else
-			g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"",
-			            proto_name[a->protocol], a->user, a->pass, a->server ? a->server : "" );
-		
-		line = obfucrypt( irc, s );
-		if( *line )
-		{
-			if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
-			{
-				irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
-				fclose( fp );
-				return( 0 );
-			}
-		}
-		g_free( line );
-	}
-	
-	for( set = irc->set; set; set = set->next )
-	{
-		if( set->value && set->def )
-		{
-			g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value );
-			line = obfucrypt( irc, s );
-			if( *line )
-			{
-				if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
-				{
-					irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
-					fclose( fp );
-					return( 0 );
-				}
-			}
-			g_free( line );
-		}
-	}
-	
-	if( strcmp( irc->mynick, ROOT_NICK ) != 0 )
-	{
-		g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick );
-		line = obfucrypt( irc, s );
-		if( *line )
-		{
-			if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
-			{
-				irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
-				fclose( fp );
-				return( 0 );
-			}
-		}
-		g_free( line );
-	}
-	if( fclose( fp ) != 0 )
-	{
-		irc_usermsg( irc, "fclose() reported an error. Disk full?" );
-		return( 0 );
-	}
-	
- 	g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
- 	if( unlink( new_path ) != 0 )
-	{
-		if( errno != ENOENT )
-		{
-			irc_usermsg( irc, "Error while removing old .accounts file" );
-			return( 0 );
-		}
-	}
-	if( rename( path, new_path ) != 0 )
-	{
-		irc_usermsg( irc, "Error while renaming new .accounts file" );
-		return( 0 );
-	}
-	
-	umask( ou );
-	
-	return( 1 );
-}
-
 void bitlbee_shutdown( gpointer data )
 {
Index: bitlbee.h
===================================================================
--- bitlbee.h	(revision c2295f7eeac263dbcc19f84e9a61abbe778aa9f8)
+++ bitlbee.h	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -100,4 +100,5 @@
 
 #include "irc.h"
+#include "storage.h"
 #include "set.h"
 #include "protocols/nogaim.h"
@@ -115,4 +116,5 @@
 	help_t *help;
 	conf_t *conf;
+	storage_t *storage;
 	char *helpfile;
 	GMainLoop *loop;
@@ -127,6 +129,4 @@
 int root_command_string( irc_t *irc, user_t *u, char *command, int flags );
 int root_command( irc_t *irc, char *command[] );
-int bitlbee_load( irc_t *irc, const char *password );
-int bitlbee_save( irc_t *irc );
 void bitlbee_shutdown( gpointer data );
 double gettime( void );
Index: commands.c
===================================================================
--- commands.c	(revision c2295f7eeac263dbcc19f84e9a61abbe778aa9f8)
+++ commands.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -86,5 +86,5 @@
 int cmd_identify( irc_t *irc, char **cmd )
 {
-	int checkie = bitlbee_load( irc, cmd[1] );
+	int checkie = global.storage->load( irc->nick, cmd[1], irc );
 	
 	if( checkie == -1 )
@@ -110,7 +110,4 @@
 int cmd_register( irc_t *irc, char **cmd )
 {
-	int checkie;
-	char path[512];
-	
 	if( global.conf->authmode == AUTHMODE_REGISTERED )
 	{
@@ -118,20 +115,18 @@
 		return( 0 );
 	}
-	
-	g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
-	checkie = access( path, F_OK );
-	
-	g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
-	checkie += access( path, F_OK );
-	
-	if( checkie == -2 )
-	{
-		setpassnc( irc, cmd[1] );
-		root_command_string( irc, user_find( irc, irc->mynick ), "save", 0 );
-		irc->status = USTATUS_IDENTIFIED;
-	}
-	else
-	{
-		irc_usermsg( irc, "Nick is already registered" );
+
+	setpassnc( irc, cmd[1] );
+	switch( global.storage->save( irc, FALSE )) {
+		case STORAGE_ALREADY_EXISTS:
+			irc_usermsg( irc, "Nick is already registered" );
+			break;
+			
+		case STORAGE_OK:
+			irc->status = USTATUS_IDENTIFIED;
+			break;
+
+		default:
+			irc_usermsg( irc, "Error registering" );
+			break;
 	}
 	
@@ -141,33 +136,22 @@
 int cmd_drop( irc_t *irc, char **cmd )
 {
-	char s[512];
-	FILE *fp;
-	
-	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
-	fp = fopen( s, "r" );
-	if( !fp )
-	{
+	storage_status_t status;
+	
+	status = global.storage->remove (irc->nick, cmd[1]);
+	switch (status) {
+	case STORAGE_NO_SUCH_USER:
 		irc_usermsg( irc, "That account does not exist" );
 		return( 0 );
-	}
-	
-	fscanf( fp, "%32[^\n]s", s );
-	fclose( fp );
-	if( setpass( irc, cmd[1], s ) < 0 )
-	{
-		irc_usermsg( irc, "Incorrect password" );
-		return( 0 );
-	}
-	
-	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
-	unlink( s );
-	
-	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
-	unlink( s );
-	
-	setpassnc( irc, NULL );
-	irc_usermsg( irc, "Files belonging to account `%s' removed", irc->nick );
-	
-	return( 0 );
+	case STORAGE_INVALID_PASSWORD:
+		irc_usermsg( irc, "Password invalid" );
+		return( 0 );
+	case STORAGE_OK:
+		setpassnc( irc, NULL );
+		irc_usermsg( irc, "Account `%s' removed", irc->nick );
+		return( 0 );
+	default:
+		irc_usermsg( irc, "Error: '%d'", status );
+		return( 0 );
+	}
 }
 
@@ -634,5 +618,5 @@
 int cmd_save( irc_t *irc, char **cmd )
 {
-	if( bitlbee_save( irc ) )
+	if( global.storage->save( irc, TRUE ) )
 		irc_usermsg( irc, "Configuration saved" );
 	else
Index: conf.c
===================================================================
--- conf.c	(revision c2295f7eeac263dbcc19f84e9a61abbe778aa9f8)
+++ conf.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -50,4 +50,5 @@
 	conf->nofork = 0;
 	conf->verbose = 0;
+	conf->storage = "text";
 	conf->runmode = RUNMODE_INETD;
 	conf->authmode = AUTHMODE_OPEN;
@@ -198,4 +199,9 @@
 				conf->motdfile = g_strdup( ini->value );
 			}
+			else if( g_strcasecmp( ini->key, "storage" ) == 0 )
+			{
+				g_free( conf->storage );
+				conf->storage = g_strdup( ini->value );
+			}
 			else if( g_strcasecmp( ini->key, "pinginterval" ) == 0 )
 			{
Index: conf.h
===================================================================
--- conf.h	(revision c2295f7eeac263dbcc19f84e9a61abbe778aa9f8)
+++ conf.h	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -42,4 +42,5 @@
 	char *configdir;
 	char *motdfile;
+	char *storage;
 	int ping_interval;
 	int ping_timeout;
Index: irc.c
===================================================================
--- irc.c	(revision c2295f7eeac263dbcc19f84e9a61abbe778aa9f8)
+++ irc.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -161,5 +161,5 @@
 	
 	if( irc->status >= USTATUS_IDENTIFIED && set_getint( irc, "save_on_quit" ) ) 
-		if( !bitlbee_save( irc ) )
+		if( !global.storage->save( irc, TRUE ) )
 			irc_usermsg( irc, "Error while saving settings!" );
 	
Index: storage.c
===================================================================
--- storage.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
+++ storage.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -0,0 +1,58 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* Support for multiple storage backends */
+
+/*
+  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
+*/
+
+#define BITLBEE_CORE
+#include "bitlbee.h"
+#include "crypting.h"
+
+extern storage_t storage_text;
+
+static GList text_entry = { &storage_text, NULL, NULL };
+static GList *storage_backends = &text_entry;
+
+void register_storage_backend(storage_t *backend)
+{
+	storage_backends = g_list_append(storage_backends, backend);
+}
+
+storage_t *storage_init(const char *name)
+{
+	GList *gl;
+	storage_t *st;
+
+	for (gl = storage_backends; gl; gl = gl->next) {
+		st = gl->data;
+		if (strcmp(st->name, name) == 0)
+			break;
+	}
+
+	if (gl == NULL) 
+		return NULL;
+
+	if (st->init)
+		st->init();
+
+	return st;
+}
Index: storage.h
===================================================================
--- storage.h	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
+++ storage.h	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -0,0 +1,58 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* Layer for retrieving and storing buddy information */
+
+/*
+  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
+*/
+
+#ifndef __STORAGE_H__
+#define __STORAGE_H__
+
+typedef enum {
+	STORAGE_OK = 0,
+	STORAGE_NO_SUCH_USER,
+	STORAGE_INVALID_PASSWORD,
+	STORAGE_ALREADY_EXISTS,
+	STORAGE_OTHER_ERROR /* Error that isn't caused by user input, such as 
+						   a database that is unreachable. log() will be 
+						   used for the exact error message */
+} storage_status_t;
+
+typedef struct {
+	const char *name;
+	
+	/* May be set to NULL if not required */
+	void (*init) (void);
+
+	storage_status_t (*check_pass) (const char *nick, const char *password);
+
+	storage_status_t (*load) (const char *nick, const char *password, irc_t * irc);
+	storage_status_t (*save) (irc_t *irc, int overwrite);
+	storage_status_t (*remove) (const char *nick, const char *password);
+
+	/* May be NULL if not supported by backend */
+	storage_status_t (*rename) (const char *onick, const char *nnick, const char *password);
+} storage_t;
+
+void register_storage_backend(storage_t *);
+storage_t *storage_init(const char *name);
+
+#endif /* __STORAGE_H__ */
Index: storage_text.c
===================================================================
--- storage_text.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
+++ storage_text.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -0,0 +1,311 @@
+  /********************************************************************\
+  * BitlBee -- An IRC to other IM-networks gateway                     *
+  *                                                                    *
+  * Copyright 2002-2004 Wilmer van der Gaast and others                *
+  \********************************************************************/
+
+/* Storage backend that uses the same file format as <=1.0 */
+
+/*
+  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
+*/
+
+#define BITLBEE_CORE
+#include "bitlbee.h"
+#include "crypting.h"
+
+static void text_init (void)
+{
+	if( access( global.conf->configdir, F_OK ) != 0 )
+		log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", CONFIG );
+	else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 )
+		log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir );
+}
+
+static storage_status_t text_load ( const char *my_nick, const char* password, irc_t *irc )
+{
+	char s[512];
+	char *line;
+	int proto;
+	char nick[MAX_NICK_LENGTH+1];
+	FILE *fp;
+	user_t *ru = user_find( irc, ROOT_NICK );
+	
+	if( irc->status == USTATUS_IDENTIFIED )
+		return( 1 );
+	
+	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".accounts" );
+   	fp = fopen( s, "r" );
+   	if( !fp ) return STORAGE_NO_SUCH_USER;
+	
+	fscanf( fp, "%32[^\n]s", s );
+	if( setpass( irc, password, s ) < 0 )
+	{
+		fclose( fp );
+		return STORAGE_INVALID_PASSWORD;
+	}
+	
+	/* Do this now. If the user runs with AuthMode = Registered, the
+	   account command will not work otherwise. */
+	irc->status = USTATUS_IDENTIFIED;
+	
+	while( fscanf( fp, "%511[^\n]s", s ) > 0 )
+	{
+		fgetc( fp );
+		line = deobfucrypt( irc, s );
+		root_command_string( irc, ru, line, 0 );
+		g_free( line );
+	}
+	fclose( fp );
+	
+	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, my_nick, ".nicks" );
+	fp = fopen( s, "r" );
+	if( !fp ) return STORAGE_NO_SUCH_USER;
+	while( fscanf( fp, "%s %d %s", s, &proto, nick ) > 0 )
+	{
+		http_decode( s );
+		nick_set( irc, s, proto, nick );
+	}
+	fclose( fp );
+	
+	if( set_getint( irc, "auto_connect" ) )
+	{
+		strcpy( s, "account on" );	/* Can't do this directly because r_c_s alters the string */
+		root_command_string( irc, ru, s, 0 );
+	}
+	
+	return STORAGE_OK;
+}
+
+static storage_status_t text_save( irc_t *irc, int overwrite )
+{
+	char s[512];
+	char path[512], new_path[512];
+	char *line;
+	nick_t *n;
+	set_t *set;
+	mode_t ou = umask( 0077 );
+	account_t *a;
+	FILE *fp;
+	char *hash;
+
+	if (!overwrite) {
+		g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
+		if (access( path, F_OK ) != -1)
+			return STORAGE_ALREADY_EXISTS;
+	
+		g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
+		if (access( path, F_OK ) != -1)
+			return STORAGE_ALREADY_EXISTS;
+	}
+	
+	/*\
+	 *  [SH] Nothing should be saved if no password is set, because the
+	 *  password is not set if it was wrong, or if one is not identified
+	 *  yet. This means that a malicious user could easily overwrite
+	 *  files owned by someone else:
+	 *  a Bad Thing, methinks
+	\*/
+
+	/* [WVG] No? Really? */
+
+	/*\
+	 *  [SH] Okay, okay, it wasn't really Wilmer who said that, it was
+	 *  me. I just thought it was funny.
+	\*/
+	
+	hash = hashpass( irc );
+	if( hash == NULL )
+	{
+		irc_usermsg( irc, "Please register yourself if you want to save your settings." );
+		return( 0 );
+	}
+	
+	g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".nicks~" );
+	fp = fopen( path, "w" );
+	if( !fp ) return STORAGE_OTHER_ERROR;
+	for( n = irc->nicks; n; n = n->next )
+	{
+		strcpy( s, n->handle );
+		s[169] = 0; /* Prevent any overflow (169 ~ 512 / 3) */
+		http_encode( s );
+		g_snprintf( s + strlen( s ), 510 - strlen( s ), " %d %s", n->proto, n->nick );
+		if( fprintf( fp, "%s\n", s ) != strlen( s ) + 1 )
+		{
+			irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+			fclose( fp );
+			return STORAGE_OTHER_ERROR;
+		}
+	}
+	if( fclose( fp ) != 0 )
+	{
+		irc_usermsg( irc, "fclose() reported an error. Disk full?" );
+		return STORAGE_OTHER_ERROR;
+	}
+  
+	g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".nicks" );
+	if( unlink( new_path ) != 0 )
+	{
+		if( errno != ENOENT )
+		{
+			irc_usermsg( irc, "Error while removing old .nicks file" );
+			return STORAGE_OTHER_ERROR;
+		}
+	}
+	if( rename( path, new_path ) != 0 )
+	{
+		irc_usermsg( irc, "Error while renaming new .nicks file" );
+		return STORAGE_OTHER_ERROR;
+	}
+	
+	g_snprintf( path, 511, "%s%s%s", global.conf->configdir, irc->nick, ".accounts~" );
+	fp = fopen( path, "w" );
+	if( !fp ) return STORAGE_OTHER_ERROR;
+	if( fprintf( fp, "%s", hash ) != strlen( hash ) )
+	{
+		irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+		fclose( fp );
+		return STORAGE_OTHER_ERROR;
+	}
+	g_free( hash );
+
+	for( a = irc->accounts; a; a = a->next )
+	{
+		if( a->protocol == PROTO_OSCAR || a->protocol == PROTO_ICQ || a->protocol == PROTO_TOC )
+			g_snprintf( s, sizeof( s ), "account add oscar \"%s\" \"%s\" %s", a->user, a->pass, a->server );
+		else
+			g_snprintf( s, sizeof( s ), "account add %s \"%s\" \"%s\" \"%s\"",
+			            proto_name[a->protocol], a->user, a->pass, a->server ? a->server : "" );
+		
+		line = obfucrypt( irc, s );
+		if( *line )
+		{
+			if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
+			{
+				irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+				fclose( fp );
+				return STORAGE_OTHER_ERROR;
+			}
+		}
+		g_free( line );
+	}
+	
+	for( set = irc->set; set; set = set->next )
+	{
+		if( set->value && set->def )
+		{
+			g_snprintf( s, sizeof( s ), "set %s \"%s\"", set->key, set->value );
+			line = obfucrypt( irc, s );
+			if( *line )
+			{
+				if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
+				{
+					irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+					fclose( fp );
+					return STORAGE_OTHER_ERROR;
+				}
+			}
+			g_free( line );
+		}
+	}
+	
+	if( strcmp( irc->mynick, ROOT_NICK ) != 0 )
+	{
+		g_snprintf( s, sizeof( s ), "rename %s %s", ROOT_NICK, irc->mynick );
+		line = obfucrypt( irc, s );
+		if( *line )
+		{
+			if( fprintf( fp, "%s\n", line ) != strlen( line ) + 1 )
+			{
+				irc_usermsg( irc, "fprintf() wrote too little. Disk full?" );
+				fclose( fp );
+				return STORAGE_OTHER_ERROR;
+			}
+		}
+		g_free( line );
+	}
+	if( fclose( fp ) != 0 )
+	{
+		irc_usermsg( irc, "fclose() reported an error. Disk full?" );
+		return STORAGE_OTHER_ERROR;
+	}
+	
+ 	g_snprintf( new_path, 512, "%s%s%s", global.conf->configdir, irc->nick, ".accounts" );
+ 	if( unlink( new_path ) != 0 )
+	{
+		if( errno != ENOENT )
+		{
+			irc_usermsg( irc, "Error while removing old .accounts file" );
+			return STORAGE_OTHER_ERROR;
+		}
+	}
+	if( rename( path, new_path ) != 0 )
+	{
+		irc_usermsg( irc, "Error while renaming new .accounts file" );
+		return STORAGE_OTHER_ERROR;
+	}
+	
+	umask( ou );
+	
+	return STORAGE_OK;
+}
+
+static storage_status_t text_check_pass( const char *nick, const char *password )
+{
+	char s[512];
+	FILE *fp;
+	
+	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
+	fp = fopen( s, "r" );
+	if (!fp)
+		return STORAGE_NO_SUCH_USER;
+
+	fscanf( fp, "%32[^\n]s", s );
+	fclose( fp );
+
+	/*FIXME Test if password is correct */
+
+	return STORAGE_OK;
+}
+
+static storage_status_t text_remove( const char *nick, const char *password )
+{
+	char s[512];
+	storage_status_t status;
+
+	status = text_check_pass( nick, password );
+	if (status != STORAGE_OK)
+		return status;
+
+	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".accounts" );
+	if (unlink( s ) == -1)
+		return STORAGE_OTHER_ERROR;
+	
+	g_snprintf( s, 511, "%s%s%s", global.conf->configdir, nick, ".nicks" );
+	if (unlink( s ) == -1)
+		return STORAGE_OTHER_ERROR;
+
+	return STORAGE_OK;
+}
+
+storage_t storage_text = {
+	.name = "text",
+	.init = text_init,
+	.check_pass = text_check_pass,
+	.remove = text_remove,
+	.load = text_load,
+	.save = text_save
+};
Index: unix.c
===================================================================
--- unix.c	(revision c2295f7eeac263dbcc19f84e9a61abbe778aa9f8)
+++ unix.c	(revision 8efa2f49816aaac986137a5da1f6c35425282195)
@@ -52,9 +52,10 @@
 	
 	global.helpfile = g_strdup( HELP_FILE );
-	
+
 	global.conf = conf_load( argc, argv );
 	if( global.conf == NULL )
 		return( 1 );
-	
+
+
 	if( global.conf->runmode == RUNMODE_INETD )
 	{
@@ -70,4 +71,11 @@
 	if( i != 0 )
 		return( i );
+
+	global.storage = storage_init( global.conf->storage );
+	if ( global.storage == NULL) {
+		log_message( LOGLVL_ERROR, "No such storage backend '%s'", global.conf->storage );
+		return( 1 );
+	}
+	
  	
 	/* Catch some signals to tell the user what's happening before quitting */
@@ -87,8 +95,4 @@
 	if( !getuid() || !geteuid() )
 		log_message( LOGLVL_WARNING, "BitlBee is running with root privileges. Why?" );
-	if( access( global.conf->configdir, F_OK ) != 0 )
-		log_message( LOGLVL_WARNING, "The configuration directory %s does not exist. Configuration won't be saved.", CONFIG );
-	else if( access( global.conf->configdir, R_OK ) != 0 || access( global.conf->configdir, W_OK ) != 0 )
-		log_message( LOGLVL_WARNING, "Permission problem: Can't read/write from/to %s.", global.conf->configdir );
 	if( help_init( &(global.help) ) == NULL )
 		log_message( LOGLVL_WARNING, "Error opening helpfile %s.", HELP_FILE );
