Index: lib/Makefile
===================================================================
--- lib/Makefile	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
+++ lib/Makefile	(revision 0d4a068823e4a205c465f10a05ab699f0cef8e06)
@@ -10,5 +10,5 @@
 
 # [SH] Program variables
-objects = arc.o base64.o $(EVENT_HANDLER) http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
+objects = arc.o base64.o $(EVENT_HANDLER) ftutil.o http_client.o ini.o md5.o misc.o oauth.o proxy.o sha1.o $(SSL_CLIENT) url.o xmltree.o
 
 CFLAGS += -Wall
Index: lib/ftutil.c
===================================================================
--- lib/ftutil.c	(revision 0d4a068823e4a205c465f10a05ab699f0cef8e06)
+++ lib/ftutil.c	(revision 0d4a068823e4a205c465f10a05ab699f0cef8e06)
@@ -0,0 +1,134 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Utility functions for file transfer                                      *
+*                                                                           *
+*  Copyright 2008 Uli Meis <a.sporto+bee@gmail.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.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#define BITLBEE_CORE
+#include "bitlbee.h"
+#include <poll.h>
+#include <netinet/tcp.h>
+#include "lib/ftutil.h"
+
+#define ASSERTSOCKOP(op, msg) \
+	if( (op) == -1 ) {\
+		g_snprintf( errmsg, sizeof( errmsg ), msg ": %s", strerror( errno ) ); \
+		return -1; }
+
+/*
+ * Creates a listening socket and returns it in saddr_ptr.
+ */
+int ft_listen( struct sockaddr_storage *saddr_ptr, char *host, char *port, int for_bitlbee_client, char **errptr )
+{
+	int fd, gret, saddrlen;
+	struct addrinfo hints, *rp;
+	socklen_t ssize = sizeof( struct sockaddr_storage );
+	struct sockaddr_storage saddrs, *saddr = &saddrs;
+	static char errmsg[1024];
+	char *ftlisten = global.conf->ft_listen;
+
+	if( errptr )
+		*errptr = errmsg;
+
+	strcpy( port, "0" );
+
+	/* Format is <IP-A>[:<Port-A>];<IP-B>[:<Port-B>] where
+	 * A is for connections with the bitlbee client (DCC)
+	 * and B is for connections with IM peers.
+	 */
+	if( ftlisten )
+	{
+		char *scolon = strchr( ftlisten, ';' );
+		char *colon;
+
+		if( scolon )
+		{
+			if( for_bitlbee_client )
+			{
+				*scolon = '\0';
+				strncpy( host, ftlisten, HOST_NAME_MAX );
+				*scolon = ';';
+			}
+			else
+			{
+				strncpy( host, scolon + 1, HOST_NAME_MAX );
+			}
+		}
+		else
+		{
+			strncpy( host, ftlisten, HOST_NAME_MAX );
+		}
+
+		if( ( colon = strchr( host, ':' ) ) )
+		{
+			*colon = '\0';
+			strncpy( port, colon + 1, 5 );
+		}
+	}
+	else
+	{
+		ASSERTSOCKOP( gethostname( host, HOST_NAME_MAX + 1 ), "gethostname()" );
+	}
+
+	memset( &hints, 0, sizeof( struct addrinfo ) );
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_flags = AI_NUMERICSERV;
+
+	if ( ( gret = getaddrinfo( host, port, &hints, &rp ) ) != 0 )
+	{
+		sprintf( errmsg, "getaddrinfo() failed: %s", gai_strerror( gret ) );
+		return -1;
+	}
+
+	saddrlen = rp->ai_addrlen;
+
+	memcpy( saddr, rp->ai_addr, saddrlen );
+
+	freeaddrinfo( rp );
+
+	ASSERTSOCKOP( fd = socket( saddr->ss_family, SOCK_STREAM, 0 ), "Opening socket" );
+	ASSERTSOCKOP( bind( fd, ( struct sockaddr *)saddr, saddrlen ), "Binding socket" );
+	ASSERTSOCKOP( listen( fd, 1 ), "Making socket listen" );
+
+	if ( !inet_ntop( saddr->ss_family, saddr->ss_family == AF_INET ?
+			( void * )&( ( struct sockaddr_in * ) saddr )->sin_addr.s_addr :
+			( void * )&( ( struct sockaddr_in6 * ) saddr )->sin6_addr.s6_addr,
+			host, HOST_NAME_MAX ) )
+	{
+		strcpy( errmsg, "inet_ntop failed on listening socket" );
+		return -1;
+	}
+
+	ASSERTSOCKOP( getsockname( fd, ( struct sockaddr *)saddr, &ssize ), "Getting socket name" );
+
+	if( saddr->ss_family == AF_INET )
+		g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in *) saddr )->sin_port ) );
+	else
+		g_snprintf( port, 6, "%d", ntohs( ( (struct sockaddr_in6 *) saddr )->sin6_port ) );
+
+	if( saddr_ptr )
+		memcpy( saddr_ptr, saddr, saddrlen );
+
+	/* I hate static-length strings.. */
+	host[HOST_NAME_MAX] = '\0';
+	port[5] = '\0';
+	
+	return fd;
+}
Index: lib/ftutil.h
===================================================================
--- lib/ftutil.h	(revision 0d4a068823e4a205c465f10a05ab699f0cef8e06)
+++ lib/ftutil.h	(revision 0d4a068823e4a205c465f10a05ab699f0cef8e06)
@@ -0,0 +1,40 @@
+/***************************************************************************\
+*                                                                           *
+*  BitlBee - An IRC to IM gateway                                           *
+*  Utility functions for file transfer                                      *
+*                                                                           *
+*  Copyright 2008 Uli Meis <a.sporto+bee@gmail.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.,  *
+*  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.              *
+*                                                                           *
+\***************************************************************************/
+
+#ifndef AI_NUMERICSERV
+#define AI_NUMERICSERV 0x0400   /* Don't use name resolution.  */
+#endif
+
+/* Some ifdefs for ulibc and apparently also BSD (Thanks to Whoopie) */
+#ifndef HOST_NAME_MAX
+#include <sys/param.h>
+#ifdef MAXHOSTNAMELEN
+#define HOST_NAME_MAX MAXHOSTNAMELEN
+#else
+#define HOST_NAME_MAX 255
+#endif
+#endif
+
+/* This function should be used with care. host should be AT LEAST a
+   char[HOST_NAME_MAX+1] and port AT LEAST a char[6]. */
+int ft_listen( struct sockaddr_storage *saddr_ptr, char *host, char *port, int for_bitlbee_client, char **errptr );
Index: lib/misc.c
===================================================================
--- lib/misc.c	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
+++ lib/misc.c	(revision 0d4a068823e4a205c465f10a05ab699f0cef8e06)
@@ -648,2 +648,50 @@
 	return ret;
 }
+
+char **split_command_parts( char *command )
+{
+	static char *cmd[IRC_MAX_ARGS+1];
+	char *s, q = 0;
+	int k;
+	
+	memset( cmd, 0, sizeof( cmd ) );
+	cmd[0] = command;
+	k = 1;
+	for( s = command; *s && k < IRC_MAX_ARGS; s ++ )
+		if( *s == ' ' && !q )
+		{
+			*s = 0;
+			while( *++s == ' ' );
+			if( *s == '"' || *s == '\'' )
+			{
+				q = *s;
+				s ++;
+			}
+			if( *s )
+			{
+				cmd[k++] = s;
+				s --;
+			}
+			else
+			{
+				break;
+			}
+		}
+		else if( *s == '\\' && ( ( !q && s[1] ) || ( q && q == s[1] ) ) )
+		{
+			char *cpy;
+			
+			for( cpy = s; *cpy; cpy ++ )
+				cpy[0] = cpy[1];
+		}
+		else if( *s == q )
+		{
+			q = *s = 0;
+		}
+	
+	/* Full zero-padding for easier argc checking. */
+	while( k <= IRC_MAX_ARGS )
+		cmd[k++] = NULL;
+	
+	return cmd;
+}
Index: lib/misc.h
===================================================================
--- lib/misc.h	(revision 3b878a1c3d0888b0669c30433efab914061fa61d)
+++ lib/misc.h	(revision 0d4a068823e4a205c465f10a05ab699f0cef8e06)
@@ -69,3 +69,5 @@
 G_MODULE_EXPORT int md5_verify_password( char *password, char *hash );
 
+G_MODULE_EXPORT char **split_command_parts( char *command );
+
 #endif
