commit f67ad15a36ca6c284e5d7f27ba6762eae9a5a3e5 from: Florian Westphal date: Tue Apr 03 22:08:50 2007 UTC sync with HEAD. commit - 5c3e02393b5d12c00f68d5216f45bb5281b0cea9 commit + f67ad15a36ca6c284e5d7f27ba6762eae9a5a3e5 blob - fbce09f68a8fd0fda303107ba4d8e0380ea428a9 blob + ab1191cf4ef7b95c0adfa0868bd2c65c636dc624 --- ChangeLog +++ ChangeLog @@ -11,6 +11,14 @@ ngIRCd 0.10.2 + + - Predefined Channel configuration now allows specification of channel key + (mode k) and maximum user count (mode l). + - When using epoll() IO interface, compile in the select() interface as + well and fall back to it when epoll() isn't available on runtime. + - New configure option "--without-select" to disable select() IO API + (even when using epoll(), see above). + - Added support for IO APIs "poll()" and "/dev/poll". - Reorganized internal handling of invite and ban lists. ngIRCd 0.10.1 (2006-12-17) @@ -676,4 +684,4 @@ ngIRCd 0.0.1, 31.12.2001 -- -$Id: ChangeLog,v 1.302.2.10 2007/04/03 20:23:30 fw Exp $ +$Id: ChangeLog,v 1.302.2.11 2007/04/03 22:08:50 fw Exp $ blob - 19b554242453fcc6095a7b3409bb34d7b778a1cc blob + fdf324471ff27613c6024293c2f8448012aefa5e --- INSTALL +++ INSTALL @@ -149,14 +149,20 @@ standard locations. The Z compression library ("libz") is required for this option. * IO Backend (autodetected by default): + --with-select[=] / --without-select + --with-poll[=] / --without-poll + --with-devpoll[=] / --without-devpoll --with-epoll[=] / --without-epoll --with-kqueue[=] / --without-kqueue - ngIRCd can use three different IO "backends": the "old school" select() + ngIRCd can use different IO "backends": the "old school" select() and poll() API which should be supported by most UNIX-like operating systems, or the - more efficient and flexible epoll() (Linux 2.6) or kqueue() (BSD) APIs. + more efficient and flexible epoll() (Linux >=2.6), kqueue() (BSD) and + /dev/poll APIs. By default the IO backend is autodetected, but you can use "--without-xxx" - to disable a more enhanced API and force the daemon to use select(). + to disable a more enhanced API. + When using the epoll() API, support for select() is compiled in as well by + default to enable the binary to run on older Linux kernels (<2.6), too. * IDENT-Support: --with-ident[=] @@ -241,4 +247,4 @@ number. In both cases the server exits after the outpu -- -$Id: INSTALL,v 1.23.2.1 2006/08/02 08:19:38 alex Exp $ +$Id: INSTALL,v 1.23.2.2 2007/04/03 22:08:50 fw Exp $ blob - b5c9cb7c653eda56b8d3b07e47ce78d718466a4d blob + 0391335fc3e48db443a59db75bd8bcc6a7b958d4 --- configure.in +++ configure.in @@ -1,6 +1,6 @@ # # ngIRCd -- The Next Generation IRC Daemon -# Copyright (c)2001-2006 Alexander Barton +# Copyright (c)2001-2005 Alexander Barton # # 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 @@ -8,13 +8,13 @@ # (at your option) any later version. # Please read the file COPYING, README and AUTHORS for more information. # -# $Id: configure.in,v 1.118.2.8 2006/12/17 14:06:19 alex Exp $ +# $Id: configure.in,v 1.118.2.9 2007/04/03 22:08:50 fw Exp $ # # -- Initialisation -- AC_PREREQ(2.50) -AC_INIT(ngircd, 0.10.1) +AC_INIT(ngircd, CVSHEAD) AC_CONFIG_SRCDIR(src/ngircd/ngircd.c) AC_CANONICAL_TARGET AM_INIT_AUTOMAKE(1.6) @@ -143,12 +143,10 @@ AC_CHECK_FUNCS([ \ AC_CHECK_FUNCS(inet_aton isdigit sigaction snprintf vsnprintf strdup strlcpy strlcat) -AC_CHECK_FUNCS(select,[AC_CHECK_HEADERS(sys/select.h)], - AC_MSG_ERROR([required function select() is missing!]) -) - # -- Configuration options -- +# use syslog? + x_syslog_on=no AC_ARG_WITH(syslog, [ --without-syslog disable syslog (autodetected by default)], @@ -174,6 +172,8 @@ if test "$x_syslog_on" = "yes"; then AC_CHECK_HEADERS(syslog.h,,AC_MSG_ERROR([required C header missing!])) fi +# use zlib compression? + x_zlib_on=no AC_ARG_WITH(zlib, [ --without-zlib disable zlib compression (autodetected by default)], @@ -198,29 +198,83 @@ if test "$x_zlib_on" = "yes"; then AC_CHECK_HEADERS(zlib.h,,AC_MSG_ERROR([required C header missing!])) fi +# detect which IO API to use: -x_io_backend=select\(\) -AC_ARG_WITH(epoll, - [ --without-epoll disable epoll support (autodetected by default)], +x_io_backend=none + +AC_ARG_WITH(select, + [ --without-select disable select IO support (autodetected by default)], [ if test "$withval" != "no"; then if test "$withval" != "yes"; then CFLAGS="-I$withval/include $CFLAGS" CPPFLAGS="-I$withval/include $CPPFLAGS" LDFLAGS="-L$withval/lib $LDFLAGS" fi - AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll\(\), - AC_MSG_ERROR([Can't enable epoll support!]) + AC_CHECK_FUNCS(select, x_io_select=yes, + AC_MSG_ERROR([Can't enable select IO support!]) ) fi ], [ - AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll\(\)) + AC_CHECK_FUNCS(select, x_io_select=yes) ] ) +AC_ARG_WITH(poll, + [ --without-poll disable poll support (autodetected by default)], + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_FUNCS(poll, x_io_backend=poll\(\), + AC_MSG_ERROR([Can't enable poll IO support!]) + ) + fi + ], + [ + AC_CHECK_FUNCS(poll, x_io_backend=poll\(\)) + ] +) +AC_ARG_WITH(devpoll, + [ --without-devpoll disable /dev/poll IO support (autodetected by default)], + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + + AC_CHECK_HEADERS(sys/devpoll.h,,AC_MSG_ERROR([required C header missing!])) + fi + ], + [ + AC_CHECK_HEADERS(sys/devpoll.h, x_io_backend=/dev/poll) + ] +) + +AC_ARG_WITH(epoll, + [ --without-epoll disable epoll IO support (autodetected by default)], + [ if test "$withval" != "no"; then + if test "$withval" != "yes"; then + CFLAGS="-I$withval/include $CFLAGS" + CPPFLAGS="-I$withval/include $CPPFLAGS" + LDFLAGS="-L$withval/lib $LDFLAGS" + fi + AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes, + AC_MSG_ERROR([Can't enable epoll IO support!]) + ) + fi + ], + [ + AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes) + ] +) + AC_ARG_WITH(kqueue, - [ --without-kqueue disable kqueue support (autodetected by default)], + [ --without-kqueue disable kqueue IO support (autodetected by default)], [ if test "$withval" != "no"; then if test "$withval" != "yes"; then CFLAGS="-I$withval/include $CFLAGS" @@ -228,7 +282,7 @@ AC_ARG_WITH(kqueue, LDFLAGS="-L$withval/lib $LDFLAGS" fi AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\), - AC_MSG_ERROR([Can't enable kqueue support!]) + AC_MSG_ERROR([Can't enable kqueue IO support!]) ) fi ], @@ -236,7 +290,28 @@ AC_ARG_WITH(kqueue, AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\)) ] ) + +if test "$x_io_epoll" = "yes" -a "$x_io_select" = "yes"; then + # when epoll() and select() are available, we'll use both! + x_io_backend="epoll(), select()" +else + if test "$x_io_epoll" = "yes"; then + # we prefere epoll() if it is available + x_io_backend="epoll()" + else + if test "$x_io_select" = "yes" -a "$x_io_backend" = "none"; then + # we'll use select, when available and no "better" + # interface has been detected ... + x_io_backend="select()" + fi + fi +fi + +if test "$x_io_backend" = "none"; then + AC_MSG_ERROR([No useabe IO API activated/found!?]) +fi +# use TCP wrappers? x_tcpwrap_on=no AC_ARG_WITH(tcp-wrappers, @@ -267,6 +342,8 @@ int deny_severity = 0; ] ) +# include support for "zeroconf"? + x_zeroconf_on=no AC_ARG_WITH(zeroconf, [ --with-zeroconf enable support for "Zeroconf"], @@ -315,6 +392,8 @@ if test "$x_zeroconf_on" = "howl"; then AC_DEFINE(ZEROCONF, 1) fi +# do IDENT requests using libident? + x_identauth_on=no AC_ARG_WITH(ident, [ --with-ident enable "IDENT" ("AUTH") protocol support], @@ -336,6 +415,8 @@ if test "$x_identauth_on" = "yes"; then AC_CHECK_HEADERS(ident.h,,AC_MSG_ERROR([required C header missing!])) fi +# compile in IRC+ protocol support? + x_ircplus_on=yes AC_ARG_ENABLE(ircplus, [ --disable-ircplus disable IRC+ protocol], @@ -345,6 +426,8 @@ if test "$x_ircplus_on" = "yes"; then AC_DEFINE(IRCPLUS, 1) fi +# compile in IRC "sniffer"? + x_sniffer_on=no; x_debug_on=no AC_ARG_ENABLE(sniffer, [ --enable-sniffer enable IRC traffic sniffer (enables debug mode)], @@ -354,6 +437,8 @@ AC_ARG_ENABLE(sniffer, fi ) +# enable additional debugging code? + AC_ARG_ENABLE(debug, [ --enable-debug show additional debug output], if test "$enableval" = "yes"; then x_debug_on=yes; fi @@ -363,6 +448,8 @@ if test "$x_debug_on" = "yes"; then test "$GCC" = "yes" && CFLAGS="-pedantic $CFLAGS" fi +# enable "strict RFC rules"? + x_strict_rfc_on=no AC_ARG_ENABLE(strict-rfc, [ --enable-strict-rfc strict RFC conformance -- may break clients!], blob - 62373868818b6882e72048481202b270959cdee9 blob + 74435aa8861eb31b788141269dc865cafd0549d1 --- contrib/Debian/ngircd.init +++ contrib/Debian/ngircd.init @@ -2,9 +2,20 @@ # # ngIRCd start and stop script for Debian-based systems # -# $Id: ngircd.init,v 1.6 2005/07/26 19:37:18 alex Exp $ +# $Id: ngircd.init,v 1.6.2.1 2007/04/03 22:08:50 fw Exp $ # +### BEGIN INIT INFO +# Provides: ircd +# Required-Start: $local_fs +# Required-Stop: $local_fs +# Should-Start: $syslog $network +# Should-Stop: $syslog $network +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Next Generation IRC Server +### END INIT INFO + PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin DAEMON=/usr/sbin/ngircd NAME=ngIRCd blob - 18e4d900cf7334a9b3b7f93f003cdbf5c3142e39 blob + 2b731aac22d96d08a96930fcba9319cfb04f6377 --- doc/Platforms.txt +++ doc/Platforms.txt @@ -51,6 +51,7 @@ powerpc/apple/darwin7.4.0 gcc 3.3 0.8.0 04 powerpc/apple/darwin7.9.0 gcc 3.3 CVSHEAD 06-05-07 fw Y Y Y Y (3) powerpc/apple/darwin8.1.0 gcc 4.0 0.9.x-CVS 05-06-27 alex Y Y Y Y powerpc/unknown/linux-gnu gcc 3.3.3 0.8.0 04-05-30 alex Y Y Y Y +powerpc/unknown/openbsd3.6 gcc 2.95.3 0.10.0 06-10-08 alex Y Y n Y sparc/sun/solaris2.6 gcc 2.95.3 0.7.x-CVS 03-04-22 alex Y Y Y Y sparc/sun/solaris2.7 gcc 3.3 0.8.0 04-05-30 alex Y Y Y Y sparc/unkn./netbsdelf1.6.1 gcc 2.95.3 0.8.0 04-05-30 alex Y Y Y Y @@ -73,4 +74,4 @@ Notes (3) Using the kqueue() IO interface. -- -$Id: Platforms.txt,v 1.14.2.1 2006/09/09 18:10:56 alex Exp $ +$Id: Platforms.txt,v 1.14.2.2 2007/04/03 22:08:51 fw Exp $ blob - 87dbe8bdae302ca7e52b44aedc5779d988113d09 blob + 5d5bc1cc0eccb7cef605af40fec047bcf287ca0d --- doc/sample-ngircd.conf +++ doc/sample-ngircd.conf @@ -1,4 +1,4 @@ -# $Id: sample-ngircd.conf,v 1.37.2.1 2006/12/02 13:10:43 fw Exp $ +# $Id: sample-ngircd.conf,v 1.37.2.2 2007/04/03 22:08:51 fw Exp $ # # This is a sample configuration file for the ngIRCd, which must be adepted @@ -178,8 +178,14 @@ ;Topic = a great topic # Initial channel modes - ;Modes = tn + ;Modes = tnk + # initial channel password (mode k) + ;Key = Secret + + # maximum users per channel (mode l) + ;MaxUsers = 23 + [Channel] # More [Channel] sections, if you like ... blob - 40a0c09d239db29a150c3e3f5ae84d72605097c7 blob + b2d0fb553b3be566b7de1da801e604e448eedd6f --- doc/src/Makefile.am +++ doc/src/Makefile.am @@ -8,14 +8,14 @@ # (at your option) any later version. # Please read the file COPYING, README and AUTHORS for more information. # -# $Id: Makefile.am,v 1.2 2006/04/08 16:35:03 alex Exp $ +# $Id: Makefile.am,v 1.2.2.1 2007/04/03 22:08:52 fw Exp $ # maintainer-clean-local: rm -f Makefile Makefile.in distclean-local: - rm -f html + rm -rf html srcdoc: @doxygen --version >/dev/null 2>&1 \ blob - bd18cd6f47ae2ceb43cce96869176484c5961686 blob + b523240694a2e965346c6feea58d942d5a3bb681 --- src/ngircd/array.c +++ src/ngircd/array.c @@ -12,7 +12,7 @@ #include "array.h" -static char UNUSED id[] = "$Id: array.c,v 1.11.2.2 2006/12/17 23:00:17 fw Exp $"; +static char UNUSED id[] = "$Id: array.c,v 1.11.2.3 2007/04/03 22:08:52 fw Exp $"; #include @@ -270,7 +270,7 @@ void array_free(array * a) { assert(a != NULL); -#ifdef DEBUG +#ifdef DEBUG_ARRAY Log(LOG_DEBUG, "array_free(): %u bytes free'd (%u bytes still used at time of free()).", a->allocated, a->used); blob - 294e90673326adb03fd7cdb0c21b65209b2adef6 blob + 94993d4c12578bf957ba0a6dabd1638cef048817 --- src/ngircd/channel.c +++ src/ngircd/channel.c @@ -17,7 +17,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: channel.c,v 1.56.2.2 2007/04/03 20:23:31 fw Exp $"; +static char UNUSED id[] = "$Id: channel.c,v 1.56.2.3 2007/04/03 22:08:52 fw Exp $"; #include "imp.h" #include @@ -131,6 +131,9 @@ Channel_InitPredefined( void ) while (*c) Channel_ModeAdd(chan, *c++); + Channel_SetKey(chan, Conf_Channel[i].key); + Channel_SetMaxUsers(chan, Conf_Channel[i].maxusers); + Log(LOG_INFO, "Created pre-defined channel \"%s\".", Conf_Channel[i].name ); } @@ -145,7 +148,7 @@ Channel_Exit( void ) { CHANNEL *c, *c_next; CL2CHAN *cl2chan, *cl2chan_next; - + /* Channel-Strukturen freigeben */ c = My_Channels; while( c ) blob - e92d7c3ae18b441667d80fc30b0becde862b061b blob + 3795b0e98c0bba13d29de6c400e15fb6f43bccd1 --- src/ngircd/client.c +++ src/ngircd/client.c @@ -17,7 +17,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: client.c,v 1.91.2.1 2006/12/02 14:00:00 fw Exp $"; +static char UNUSED id[] = "$Id: client.c,v 1.91.2.2 2007/04/03 22:08:52 fw Exp $"; #include "imp.h" #include @@ -67,10 +67,6 @@ static void Adjust_Counters PARAMS(( CLIENT *Client )) static CLIENT *Init_New_Client PARAMS((CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer, int Type, char *ID, char *User, char *Hostname, char *Info, int Hops, int Token, char *Modes, bool Idented)); - -#ifndef Client_DestroyNow -GLOBAL void Client_DestroyNow PARAMS((CLIENT *Client )); -#endif long Max_Users = 0, My_Max_Users = 0; @@ -334,45 +330,16 @@ Client_Destroy( CLIENT *Client, char *LogMsg, char *Fw c = (CLIENT *)c->next; } } /* Client_Destroy */ - - -GLOBAL void -Client_DestroyNow( CLIENT *Client ) -{ - /* Destroy client structure immediately. This function is only - * intended for the connection layer to remove client structures - * of connections that can't be established! */ - - CLIENT *last, *c; - - assert( Client != NULL ); - - last = NULL; - c = My_Clients; - while( c ) - { - if( c == Client ) - { - /* Wir haben den Client gefunden: entfernen */ - if( last ) last->next = c->next; - else My_Clients = (CLIENT *)c->next; - free( c ); - break; - } - last = c; - c = (CLIENT *)c->next; - } -} /* Client_DestroyNow */ GLOBAL void Client_SetHostname( CLIENT *Client, char *Hostname ) { /* Hostname eines Clients setzen */ - + assert( Client != NULL ); assert( Hostname != NULL ); - + strlcpy( Client->host, Hostname, sizeof( Client->host )); } /* Client_SetHostname */ @@ -661,8 +628,7 @@ GLOBAL char * Client_User( CLIENT *Client ) { assert( Client != NULL ); - if( Client->user[0] ) return Client->user; - else return "~"; + return Client->user[0] ? Client->user : "~"; } /* Client_User */ @@ -916,9 +882,8 @@ GLOBAL unsigned long Client_MyServerCount( void ) { CLIENT *c; - unsigned long cnt; + unsigned long cnt = 0; - cnt = 0; c = My_Clients; while( c ) { @@ -933,9 +898,8 @@ GLOBAL unsigned long Client_OperCount( void ) { CLIENT *c; - unsigned long cnt; + unsigned long cnt = 0; - cnt = 0; c = My_Clients; while( c ) { blob - 3e81a01faf7ae02a790c2ff9ece2626ba02d1f4d blob + 9c8013737018ad329cc09d3f718735fac58879ae --- src/ngircd/client.h +++ src/ngircd/client.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: client.h,v 1.42.2.2 2006/12/02 14:26:53 fw Exp $ + * $Id: client.h,v 1.42.2.3 2007/04/03 22:08:52 fw Exp $ * * Client management (header) */ @@ -80,9 +80,6 @@ GLOBAL CLIENT *Client_NewRemoteServer PARAMS(( CLIENT GLOBAL CLIENT *Client_NewRemoteUser PARAMS(( CLIENT *Introducer, char *Nick, int Hops, char *User, char *Hostname, int Token, char *Modes, char *Info, bool Idented )); GLOBAL void Client_Destroy PARAMS(( CLIENT *Client, char *LogMsg, char *FwdMsg, bool SendQuit )); -#ifdef CONN_MODULE -GLOBAL void Client_DestroyNow PARAMS(( CLIENT *Client )); -#endif GLOBAL CLIENT *Client_ThisServer PARAMS(( void )); blob - 10821292fd78f6d17bffd3151bb2079d6f240c35 blob + 6dc99772330d36ead686e9ab41b369b78d11f889 --- src/ngircd/conf.c +++ src/ngircd/conf.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: conf.c,v 1.92.2.3 2006/12/02 13:10:43 fw Exp $"; +static char UNUSED id[] = "$Id: conf.c,v 1.92.2.4 2007/04/03 22:08:52 fw Exp $"; #include "imp.h" #include @@ -240,6 +240,8 @@ Conf_Test( void ) puts( "[CHANNEL]" ); printf( " Name = %s\n", Conf_Channel[i].name ); printf( " Modes = %s\n", Conf_Channel[i].modes ); + printf( " Key = %s\n", Conf_Channel[i].key ); + printf( " MaxUsers = %lu\n", Conf_Channel[i].maxusers ); topic = (char*)array_start(&Conf_Channel[i].topic); printf( " Topic = %s\n\n", topic ? topic : ""); @@ -555,6 +557,8 @@ Read_Config( void ) /* Initialize new channel structure */ strcpy( Conf_Channel[Conf_Channel_Count].name, "" ); strcpy( Conf_Channel[Conf_Channel_Count].modes, "" ); + strcpy( Conf_Channel[Conf_Channel_Count].key, "" ); + Conf_Channel[Conf_Channel_Count].maxusers = 0; array_free(&Conf_Channel[Conf_Channel_Count].topic); Conf_Channel_Count++; } @@ -965,9 +969,25 @@ Handle_CHANNEL( int Line, char *Var, char *Arg ) /* Initial topic */ if (!array_copys( &Conf_Channel[chancount].topic, Arg)) Config_Error_TooLong( Line, Var ); + return; + } + + if( strcasecmp( Var, "Key" ) == 0 ) { + /* Initial Channel Key (mode k) */ + len = strlcpy(Conf_Channel[chancount].key, Arg, sizeof(Conf_Channel[chancount].key)); + if (len >= sizeof( Conf_Channel[chancount].key )) + Config_Error_TooLong(Line, Var); return; } + if( strcasecmp( Var, "MaxUsers" ) == 0 ) { + /* maximum user limit, mode l */ + Conf_Channel[chancount].maxusers = (unsigned long) atol(Arg); + if (Conf_Channel[chancount].maxusers == 0) + Config_Error_NaN(Line, Var); + return; + } + Config_Error( LOG_ERR, "%s, line %d (section \"Channel\"): Unknown variable \"%s\"!", NGIRCd_ConfFile, Line, Var ); } /* Handle_CHANNEL */ blob - 391adef3f70652a63f5c6d7ee4e13614830766ae blob + 5ef603c6e335bf0c634ecda3b850544a1c67610e --- src/ngircd/conf.h +++ src/ngircd/conf.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: conf.h,v 1.40.2.1 2006/12/02 13:10:43 fw Exp $ + * $Id: conf.h,v 1.40.2.2 2007/04/03 22:08:52 fw Exp $ * * Configuration management (header) */ @@ -49,6 +49,8 @@ typedef struct _Conf_Channel { char name[CHANNEL_NAME_LEN]; /* Name of the channel */ char modes[CHANNEL_MODE_LEN]; /* Initial channel modes */ + char key[CLIENT_PASS_LEN]; /* Channel key ("password", mode "k" ) */ + unsigned long maxusers; /* maximum usercount for this channel, mode "l" */ array topic; /* Initial topic */ } CONF_CHANNEL; blob - 9da3dfb80418591d247c39b3adff6d031177d0ae blob + 3259c3907e6be438d12e0f8a4b5fa53a4c374b2d --- src/ngircd/conn-func.h +++ src/ngircd/conn-func.h @@ -8,7 +8,7 @@ * (at your option) any later version. * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: conn-func.h,v 1.5 2006/05/10 21:24:01 alex Exp $ + * $Id: conn-func.h,v 1.5.2.1 2007/04/03 22:08:52 fw Exp $ * * Connection management: Global functions (header) */ @@ -52,9 +52,9 @@ GLOBAL UINT16 Conn_Options PARAMS(( CONN_ID Idx )); GLOBAL void Conn_ResetWCounter PARAMS(( void )); GLOBAL long Conn_WCounter PARAMS(( void )); -#define Conn_OPTION_ADD( x, opt ) ( (x)->options |= opt ) -#define Conn_OPTION_DEL( x, opt ) ( (x)->options &= ~opt ) -#define Conn_OPTION_ISSET( x, opt ) ( (x)->options & opt ) +#define Conn_OPTION_ADD( x, opt ) ( (x)->options |= (opt) ) +#define Conn_OPTION_DEL( x, opt ) ( (x)->options &= ~(opt) ) +#define Conn_OPTION_ISSET( x, opt ) ( ((x)->options & (opt)) != 0) #endif blob - f5799e7f041523cbe6abaeea3b8d3a7db97e6160 blob + 03163e5577bf7e4953693bde5cbdae7984b8dcef --- src/ngircd/conn.c +++ src/ngircd/conn.c @@ -17,7 +17,7 @@ #include "portab.h" #include "io.h" -static char UNUSED id[] = "$Id: conn.c,v 1.198.2.2 2006/12/17 23:06:29 fw Exp $"; +static char UNUSED id[] = "$Id: conn.c,v 1.198.2.3 2007/04/03 22:08:52 fw Exp $"; #include "imp.h" #include @@ -123,7 +123,6 @@ cb_connserver(int sock, UNUSED short what) { int res, err; socklen_t sock_len; - CLIENT *c; CONN_ID idx = Socket2Index( sock ); if (idx <= NONE) { LogDebug("cb_connserver wants to write on unknown socket?!"); @@ -150,14 +149,7 @@ cb_connserver(int sock, UNUSED short what) Conf_Server[Conf_GetServer(idx)].port, idx, strerror(err)); - /* Clean up the CLIENT structure (to avoid silly log - * messages) and call Conn_Close() to do the rest. */ - c = Conn_GetClient(idx); - if (c) - Client_DestroyNow(c); - - Conn_Close(idx, "Can't connect!", NULL, false); - + Conn_Close(idx, "Can't connect!", NULL, false); return; } @@ -384,7 +376,7 @@ NewListener( const UINT16 Port ) if( ! Init_Socket( sock )) return -1; if (bind(sock, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) != 0) { - Log( LOG_CRIT, "Can't bind socket: %s!", strerror( errno )); + Log( LOG_CRIT, "Can't bind socket (port %d) : %s!", Port, strerror( errno )); close( sock ); return -1; } @@ -995,11 +987,19 @@ New_Connection( int Sock ) Init_Conn_Struct(Pool_Size++); } + /* register callback */ + if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) { + Log(LOG_ALERT, "Can't accept connection: io_event_create failed!"); + Simple_Message(new_sock, "ERROR :Internal error"); + close(new_sock); + return -1; + } + c = Client_NewLocal( new_sock, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWN, false ); if( ! c ) { - Log( LOG_ALERT, "Can't accept connection: can't create client structure!" ); - Simple_Message( new_sock, "ERROR :Internal error" ); - close( new_sock ); + Log(LOG_ALERT, "Can't accept connection: can't create client structure!"); + Simple_Message(new_sock, "ERROR :Internal error"); + io_close(new_sock); return -1; } @@ -1007,13 +1007,6 @@ New_Connection( int Sock ) My_Connections[new_sock].sock = new_sock; My_Connections[new_sock].addr = new_addr; My_Connections[new_sock].client = c; - - /* register callback */ - if (!io_event_create( new_sock, IO_WANTREAD, cb_clientserver)) { - Simple_Message( new_sock, "ERROR :Internal error" ); - Conn_Close( new_sock, "io_event_create() failed", NULL, false ); - return -1; - } Log( LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", new_sock, inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock ); blob - dd9b05f89e074e34052d66f81d2e95bac063ed6c blob + 4733fd5240f0918ec5ace97affe2cc0e7aa29315 --- src/ngircd/io.c +++ src/ngircd/io.c @@ -12,7 +12,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: io.c,v 1.16 2006/07/23 23:11:44 alex Exp $"; +static char UNUSED id[] = "$Id: io.c,v 1.16.2.1 2007/04/03 22:08:52 fw Exp $"; #include #include @@ -34,25 +34,40 @@ typedef struct { short what; } io_event; -#define INIT_IOEVENT { NULL, -1, 0, NULL } -#define IO_ERROR 4 +#define INIT_IOEVENT { NULL, -1, 0, NULL } +#define IO_ERROR 4 #ifdef HAVE_EPOLL_CREATE -#define IO_USE_EPOLL 1 +# define IO_USE_EPOLL 1 +# ifdef HAVE_SELECT +# define IO_USE_SELECT 1 +# endif #else -# ifdef HAVE_KQUEUE -#define IO_USE_KQUEUE 1 -# else -#define IO_USE_SELECT 1 -#endif -#endif +# ifdef HAVE_KQUEUE +# define IO_USE_KQUEUE 1 +# else +# ifdef HAVE_SYS_DEVPOLL_H +# define IO_USE_DEVPOLL 1 +# else +# ifdef HAVE_POLL +# define IO_USE_POLL 1 +# else +# ifdef HAVE_SELECT +# define IO_USE_SELECT 1 +# else +# error "no IO API available!?" +# endif /* HAVE_SELECT */ +# endif /* HAVE_POLL */ +# endif /* HAVE_SYS_DEVPOLL_H */ +# endif /* HAVE_KQUEUE */ +#endif /* HAVE_EPOLL_CREATE */ -static bool library_initialized; +static bool library_initialized = false; #ifdef IO_USE_EPOLL #include -static int io_masterfd; +static int io_masterfd = -1; static bool io_event_change_epoll(int fd, short what, const int action); static int io_dispatch_epoll(struct timeval *tv); #endif @@ -67,6 +82,22 @@ static int io_dispatch_kqueue(struct timeval *tv); static bool io_event_change_kqueue(int, short, const int action); #endif +#ifdef IO_USE_POLL +#include + +static array pollfds; +static int poll_maxfd; + +static bool io_event_change_poll(int fd, short what); +#endif + +#ifdef IO_USE_DEVPOLL +#include +static int io_masterfd; + +static bool io_event_change_devpoll(int fd, short what); +#endif + #ifdef IO_USE_SELECT #include "defines.h" /* for conn.h */ #include "conn.h" /* for CONN_IDX (needed by resolve.h) */ @@ -77,7 +108,11 @@ static fd_set readers; static fd_set writers; static int select_maxfd; /* the select() interface sucks badly */ static int io_dispatch_select(struct timeval *tv); + +#ifndef IO_USE_EPOLL +#define io_masterfd -1 #endif +#endif /* IO_USE_SELECT */ static array io_events; @@ -98,40 +133,45 @@ io_event_get(int fd) } -bool -io_library_init(unsigned int eventsize) +#ifdef IO_USE_DEVPOLL +static void +io_library_init_devpoll(unsigned int eventsize) { -#if defined(IO_USE_EPOLL) || defined(IO_USE_KQUEUE) - bool ret; + io_masterfd = open("/dev/poll", O_RDWR); + if (io_masterfd >= 0) + library_initialized = true; + Log(LOG_INFO, "IO subsystem: /dev/poll (initial maxfd %u, masterfd %d).", + eventsize, io_masterfd); +} #endif -#ifdef IO_USE_EPOLL - int ecreate_hint = (int)eventsize; - if (ecreate_hint <= 0) - ecreate_hint = 128; -#endif - if (library_initialized) - return true; -#ifdef IO_USE_SELECT -#ifdef FD_SETSIZE - if (eventsize >= FD_SETSIZE) - eventsize = FD_SETSIZE - 1; -#endif -#endif - if ((eventsize > 0) && !array_alloc(&io_events, sizeof(io_event), (size_t)eventsize)) - eventsize = 0; -#ifdef IO_USE_EPOLL - io_masterfd = epoll_create(ecreate_hint); - Log(LOG_INFO, - "IO subsystem: epoll (hint size %d, initial maxfd %u, masterfd %d).", - ecreate_hint, eventsize, io_masterfd); - ret = io_masterfd >= 0; - if (ret) library_initialized = true; +#ifdef IO_USE_POLL +static void +io_library_init_poll(unsigned int eventsize) +{ + struct pollfd *p; + array_init(&pollfds); + poll_maxfd = 0; + Log(LOG_INFO, "IO subsystem: poll (initial maxfd %u).", + eventsize); + p = array_alloc(&pollfds, sizeof(struct pollfd), eventsize); + if (p) { + unsigned i; + p = array_start(&pollfds); + for (i = 0; i < eventsize; i++) + p[i].fd = -1; - return ret; + library_initialized = true; + } +} #endif + + #ifdef IO_USE_SELECT +static void +io_library_init_select(unsigned int eventsize) +{ Log(LOG_INFO, "IO subsystem: select (initial maxfd %u).", eventsize); FD_ZERO(&readers); @@ -144,24 +184,82 @@ io_library_init(unsigned int eventsize) Conf_MaxConnections = FD_SETSIZE - 1; } -#else - Log(LOG_WARNING, - "FD_SETSIZE undefined, don't know how many descriptors select() can handle on your platform ..."); #endif /* FD_SETSIZE */ library_initialized = true; - return true; +} #endif /* SELECT */ + + +#ifdef IO_USE_EPOLL +static void +io_library_init_epoll(unsigned int eventsize) +{ + int ecreate_hint = (int)eventsize; + if (ecreate_hint <= 0) + ecreate_hint = 128; + io_masterfd = epoll_create(ecreate_hint); + if (io_masterfd >= 0) { + library_initialized = true; + Log(LOG_INFO, + "IO subsystem: epoll (hint size %d, initial maxfd %u, masterfd %d).", + ecreate_hint, eventsize, io_masterfd); + } +} +#endif + + #ifdef IO_USE_KQUEUE +static void +io_library_init_kqueue(unsigned int eventsize) +{ io_masterfd = kqueue(); Log(LOG_INFO, "IO subsystem: kqueue (initial maxfd %u, masterfd %d)", eventsize, io_masterfd); - ret = io_masterfd >= 0; - if (ret) library_initialized = true; + if (io_masterfd >= 0) + library_initialized = true; +} +#endif - return ret; + +bool +io_library_init(unsigned int eventsize) +{ + if (library_initialized) + return true; +#ifdef IO_USE_SELECT +#ifndef FD_SETSIZE + Log(LOG_WARNING, + "FD_SETSIZE undefined, don't know how many descriptors select() can handle on your platform ..."); +#else + if (eventsize >= FD_SETSIZE) + eventsize = FD_SETSIZE - 1; +#endif /* FD_SETSIZE */ +#endif /* IO_USE_SELECT */ + if ((eventsize > 0) && !array_alloc(&io_events, sizeof(io_event), (size_t)eventsize)) + eventsize = 0; +#ifdef IO_USE_EPOLL + io_library_init_epoll(eventsize); +#ifdef IO_USE_SELECT + if (io_masterfd < 0) + Log(LOG_INFO, "Can't initialize epoll() IO interface, falling back to select() ..."); #endif +#endif +#ifdef IO_USE_KQUEUE + io_library_init_kqueue(eventsize); +#endif +#ifdef IO_USE_DEVPOLL + io_library_init_devpoll(eventsize); +#endif +#ifdef IO_USE_POLL + io_library_init_poll(eventsize); +#endif +#ifdef IO_USE_SELECT + if (! library_initialized) + io_library_init_select(eventsize); +#endif + return library_initialized; } @@ -171,11 +269,15 @@ io_library_shutdown(void) #ifdef IO_USE_SELECT FD_ZERO(&readers); FD_ZERO(&writers); -#else - close(io_masterfd); /* kqueue, epoll */ +#endif +#ifdef IO_USE_EPOLL + if (io_masterfd >= 0) + close(io_masterfd); io_masterfd = -1; #endif #ifdef IO_USE_KQUEUE + close(io_masterfd); + io_masterfd = -1; array_free(&io_evcache); #endif library_initialized = false; @@ -201,18 +303,14 @@ io_event_create(int fd, short what, void (*cbfunc) (in io_event *i; assert(fd >= 0); - -#ifdef IO_USE_SELECT -#ifdef FD_SETSIZE +#if defined(IO_USE_SELECT) && defined(FD_SETSIZE) if (fd >= FD_SETSIZE) { Log(LOG_ERR, "fd %d exceeds FD_SETSIZE (%u) (select can't handle more file descriptors)", fd, FD_SETSIZE); return false; } -#endif /* FD_SETSIZE */ -#endif /* IO_USE_SELECT */ - +#endif i = (io_event *) array_alloc(&io_events, sizeof(io_event), (size_t) fd); if (!i) { Log(LOG_WARNING, @@ -223,6 +321,12 @@ io_event_create(int fd, short what, void (*cbfunc) (in i->callback = cbfunc; i->what = 0; +#ifdef IO_USE_DEVPOLL + ret = io_event_change_devpoll(fd, what); +#endif +#ifdef IO_USE_POLL + ret = io_event_change_poll(fd, what); +#endif #ifdef IO_USE_EPOLL ret = io_event_change_epoll(fd, what, EPOLL_CTL_ADD); #endif @@ -230,13 +334,57 @@ io_event_create(int fd, short what, void (*cbfunc) (in ret = io_event_change_kqueue(fd, what, EV_ADD|EV_ENABLE); #endif #ifdef IO_USE_SELECT - ret = io_event_add(fd, what); + if (io_masterfd < 0) + ret = io_event_add(fd, what); #endif if (ret) i->what = what; return ret; } + + +#ifdef IO_USE_DEVPOLL +static bool +io_event_change_devpoll(int fd, short what) +{ + struct pollfd p; + + p.events = 0; + + if (what & IO_WANTREAD) + p.events = POLLIN | POLLPRI; + if (what & IO_WANTWRITE) + p.events |= POLLOUT; + + p.fd = fd; + return write(io_masterfd, &p, sizeof p) == (ssize_t)sizeof p; +} +#endif + + + +#ifdef IO_USE_POLL +static bool +io_event_change_poll(int fd, short what) +{ + struct pollfd *p; + short events = 0; + if (what & IO_WANTREAD) + events = POLLIN | POLLPRI; + if (what & IO_WANTWRITE) + events |= POLLOUT; + p = array_alloc(&pollfds, sizeof *p, fd); + if (p) { + p->events = events; + p->fd = fd; + if (fd > poll_maxfd) + poll_maxfd = fd; + } + return p != NULL; +} +#endif + #ifdef IO_USE_EPOLL static bool io_event_change_epoll(int fd, short what, const int action) @@ -260,7 +408,7 @@ io_event_kqueue_commit_cache(void) struct kevent *events; bool ret; int len = (int) array_length(&io_evcache, sizeof (struct kevent)); - + if (!len) /* nothing to do */ return true; @@ -293,7 +441,7 @@ io_event_change_kqueue(int fd, short what, const int a ret = array_catb(&io_evcache, (char*) &kev, sizeof (kev)); if (!ret) ret = kevent(io_masterfd, &kev,1, NULL, 0, NULL) == 0; - } + } if (ret && (what & IO_WANTWRITE)) { EV_SET(&kev, fd, EVFILT_WRITE, action, 0, 0, 0); @@ -315,19 +463,27 @@ io_event_add(int fd, short what) io_event *i = io_event_get(fd); if (!i) return false; - if (i->what == what) return true; + + if ((i->what & what) == what) /* event type is already registered */ + return true; #ifdef DEBUG_IO - Log(LOG_DEBUG, "io_event_add(): fd %d (arg: %d), what %d.", i->fd, fd, what); + Log(LOG_DEBUG, "io_event_add(): fd %d, what %d.", fd, what); #endif i->what |= what; #ifdef IO_USE_EPOLL - return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD); + if (io_masterfd >= 0) + return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD); #endif #ifdef IO_USE_KQUEUE return io_event_change_kqueue(fd, what, EV_ADD | EV_ENABLE); #endif - +#ifdef IO_USE_DEVPOLL + return io_event_change_devpoll(fd, i->what); +#endif +#ifdef IO_USE_POLL + return io_event_change_poll(fd, i->what); +#endif #ifdef IO_USE_SELECT if (fd > select_maxfd) select_maxfd = fd; @@ -358,22 +514,77 @@ io_setnonblock(int fd) } -bool -io_close(int fd) +#ifdef IO_USE_DEVPOLL +static void +io_close_devpoll(int fd) { - io_event *i; + struct pollfd p; + p.events = POLLREMOVE; + p.fd = fd; + write(io_masterfd, &p, sizeof p); +} +#else +static inline void io_close_devpoll(int UNUSED x) { /* NOTHING */ } +#endif + + + +#ifdef IO_USE_POLL +static void +io_close_poll(int fd) +{ + struct pollfd *p; + p = array_get(&pollfds, sizeof *p, fd); + if (!p) return; + + p->fd = -1; + if (fd == poll_maxfd) { + while (poll_maxfd > 0) { + --poll_maxfd; + p = array_get(&pollfds, sizeof *p, poll_maxfd); + if (p && p->fd >= 0) + break; + } + } +} +#else +static inline void io_close_poll(int UNUSED x) { /* NOTHING */ } +#endif + + #ifdef IO_USE_SELECT +static void +io_close_select(int fd) +{ + io_event *i; + + if (io_masterfd >= 0) /* Are we using epoll()? */ + return; + FD_CLR(fd, &writers); FD_CLR(fd, &readers); + i = io_event_get(fd); + if (!i) return; + if (fd == select_maxfd) { while (select_maxfd>0) { - --select_maxfd; /* find largest fd */ + --select_maxfd; /* find largest fd */ i = io_event_get(select_maxfd); if (i && i->callback) break; - } - } + } + } +} +#else +static inline void io_close_select(int UNUSED x) { /* NOTHING */ } #endif + + +bool +io_close(int fd) +{ + io_event *i; + i = io_event_get(fd); #ifdef IO_USE_KQUEUE if (array_length(&io_evcache, sizeof (struct kevent))) /* pending data in cache? */ @@ -385,8 +596,13 @@ io_close(int fd) if (i) { io_event_change_kqueue(fd, i->what, EV_DELETE); io_event_kqueue_commit_cache(); - } + } #endif + + io_close_devpoll(fd); + io_close_poll(fd); + io_close_select(fd); + #ifdef IO_USE_EPOLL io_event_change_epoll(fd, 0, EPOLL_CTL_DEL); #endif @@ -409,8 +625,15 @@ io_event_del(int fd, short what) i->what &= ~what; +#ifdef IO_USE_DEVPOLL + return io_event_change_devpoll(fd, i->what); +#endif +#ifdef IO_USE_POLL + return io_event_change_poll(fd, i->what); +#endif #ifdef IO_USE_EPOLL - return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD); + if (io_masterfd >= 0) + return io_event_change_epoll(fd, i->what, EPOLL_CTL_MOD); #endif #ifdef IO_USE_KQUEUE @@ -465,6 +688,92 @@ io_dispatch_select(struct timeval *tv) #endif +#ifdef IO_USE_DEVPOLL +static int +io_dispatch_devpoll(struct timeval *tv) +{ + struct dvpoll dvp; + time_t sec = tv->tv_sec * 1000; + int i, total, ret, timeout = tv->tv_usec + sec; + short what; + struct pollfd p[100]; + + if (timeout < 0) + timeout = 1000; + + total = 0; + do { + dvp.dp_timeout = timeout; + dvp.dp_nfds = 100; + dvp.dp_fds = p; + ret = ioctl(io_masterfd, DP_POLL, &dvp); + total += ret; + if (ret <= 0) + return total; + for (i=0; i < ret ; i++) { + what = 0; + if (p[i].revents & (POLLIN|POLLPRI)) + what = IO_WANTREAD; + + if (p[i].revents & POLLOUT) + what |= IO_WANTWRITE; + + if (p[i].revents && !what) { + /* other flag is set, probably POLLERR */ + what = IO_ERROR; + } + io_docallback(p[i].fd, what); + } + } while (ret == 100); + + return total; +} +#endif + + +#ifdef IO_USE_POLL +static int +io_dispatch_poll(struct timeval *tv) +{ + time_t sec = tv->tv_sec * 1000; + int i, ret, timeout = tv->tv_usec + sec; + int fds_ready; + short what; + struct pollfd *p = array_start(&pollfds); + + if (timeout < 0) + timeout = 1000; + + ret = poll(p, poll_maxfd + 1, timeout); + if (ret <= 0) + return ret; + + fds_ready = ret; + for (i=0; i <= poll_maxfd; i++) { + what = 0; + if (p[i].revents & (POLLIN|POLLPRI)) + what = IO_WANTREAD; + + if (p[i].revents & POLLOUT) + what |= IO_WANTWRITE; + + if (p[i].revents && !what) { + /* other flag is set, probably POLLERR */ + what = IO_ERROR; + } + if (what) { + fds_ready--; + io_docallback(i, what); + } + if (fds_ready <= 0) + break; + } + + return ret; +} +#endif + + #ifdef IO_USE_EPOLL static int io_dispatch_epoll(struct timeval *tv) @@ -516,7 +825,7 @@ io_dispatch_kqueue(struct timeval *tv) int newevents_len; ts.tv_sec = tv->tv_sec; ts.tv_nsec = tv->tv_usec * 1000; - + do { newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent)); newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL; @@ -541,10 +850,10 @@ io_dispatch_kqueue(struct timeval *tv) #ifdef DEBUG LogDebug("kev.flag has EV_EOF set, setting IO_ERROR", kev[i].filter, kev[i].ident); -#endif +#endif io_docallback((int)kev[i].ident, IO_ERROR); continue; - } + } switch (kev[i].filter) { case EVFILT_READ: @@ -575,15 +884,22 @@ io_dispatch_kqueue(struct timeval *tv) int io_dispatch(struct timeval *tv) { +#ifdef IO_USE_EPOLL + if (io_masterfd >= 0) + return io_dispatch_epoll(tv); +#endif #ifdef IO_USE_SELECT return io_dispatch_select(tv); #endif #ifdef IO_USE_KQUEUE return io_dispatch_kqueue(tv); #endif -#ifdef IO_USE_EPOLL - return io_dispatch_epoll(tv); +#ifdef IO_USE_DEVPOLL + return io_dispatch_devpoll(tv); #endif +#ifdef IO_USE_POLL + return io_dispatch_poll(tv); +#endif } @@ -597,9 +913,9 @@ io_docallback(int fd, short what) #endif i = io_event_get(fd); - if (i->callback) { /* callback might be NULL if a previous callback function + if (i->callback) { /* callback might be NULL if a previous callback function called io_close on this fd */ i->callback(fd, (what & IO_ERROR) ? i->what : what); - } + } /* if error indicator is set, we return the event(s) that were registered */ } blob - dfc27b076fe740f8008cfe1e45c32c56fe1fa15c blob + 150cc5186dbdc44cf44bd253b4d1ddf5bca0d189 --- src/ngircd/io.h +++ src/ngircd/io.h @@ -7,10 +7,10 @@ * * I/O abstraction interface header * - * $Id: io.h,v 1.3 2005/07/14 09:15:58 alex Exp $ + * $Id: io.h,v 1.3.2.1 2007/04/03 22:08:52 fw Exp $ */ -#ifndef io_H_inclucded +#ifndef io_H_included #define io_H_included #include "portab.h" blob - 217b79aa0bbdc9e4c3f3ed25e811a2fa29871c35 blob + 2f27687a61d04fbce2624807537c26b99726b611 --- src/ngircd/lists.c +++ src/ngircd/lists.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: lists.c,v 1.18.2.2 2007/04/03 20:23:31 fw Exp $"; +static char UNUSED id[] = "$Id: lists.c,v 1.18.2.3 2007/04/03 22:08:52 fw Exp $"; #include "imp.h" #include @@ -80,7 +80,7 @@ Lists_Add(struct list_head *header, const char *Mask, newelem = malloc(sizeof(struct list_elem)); if( ! newelem ) { Log( LOG_EMERG, "Can't allocate memory for new Ban/Invite entry!" ); - return NULL; + return false; } strlcpy( newelem->mask, Mask, sizeof( newelem->mask ));