Browse Source

Import upstream version 0.10.3

Alexander Barton 16 years ago
parent
commit
88b8fe8f93

+ 35 - 2
ChangeLog

@@ -1,7 +1,7 @@
 
                      ngIRCd - Next Generation IRC Server
 
-                        (c)2001-2006 Alexander Barton,
+                        (c)2001-2007 Alexander Barton,
                     alex@barton.de, http://www.barton.de/
 
                ngIRCd is free software and published under the
@@ -10,6 +10,39 @@
                                -- ChangeLog --
 
 
+ngIRCd 0.10.3 (2007-07-31)
+
+  - SECURITY: Fixed a severe bug in handling JOIN commands, which could
+    cause the server to crash. Thanks to Sebastian Vesper, <net@veoson.net>.
+
+ngIRCd 0.10.2 (2007-06-08)
+
+  ngIRCd 0.10.2-pre2 (2007-05-19)
+  - Server links are allowed to use larger write buffers now (up to 50 KB).
+
+  ngIRCd 0.10.2-pre1 (2007-05-05)
+  - Fix compressed server links (broken since 0.10.0).
+  - 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)
+
+  - Fixed validation of server names containing digits.
+  - Update the "info text" of the local server after re-reading configuration.
+  - Changed Numerics 265 and 266 to follow ircd 2.11.x "standards".
+  - Allow PASS syntax defined in RFC 1459 for server links, too.
+  - Enhanced ISUPPORT message (005 numeric).
+  - New configuration option "PredefChannelsOnly": if set, clients can only
+    join predefined channels.
+  - Code cleanups: use "LogDebug(...)" instead of "Log(LOG_DEBUG, ...)", use
+    "strcspn()", unsigned vs. signed, use "const", fix whitespaces, ...
+
 ngIRCd 0.10.0 (2006-10-01)
 
   - Fixed file handle leak when daemon is not able to send MOTD to a client.
@@ -661,4 +694,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: ChangeLog,v 1.302.2.4 2006/10/01 16:21:55 alex Exp $
+$Id: ChangeLog,v 1.302.2.19 2007/07/31 19:33:51 alex Exp $

+ 10 - 4
INSTALL

@@ -149,14 +149,20 @@ standard locations.
   The Z compression library ("libz") is required for this option.
   
 * IO Backend (autodetected by default):
+  --with-select[=<path>] / --without-select
+  --with-poll[=<path>] / --without-poll
+  --with-devpoll[=<path>] / --without-devpoll
   --with-epoll[=<path>] / --without-epoll
   --with-kqueue[=<path>] / --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[=<path>]
@@ -241,4 +247,4 @@ number. In both cases the server exits after the output.
 
 
 -- 
-$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 $

+ 16 - 2
NEWS

@@ -1,7 +1,7 @@
 
                      ngIRCd - Next Generation IRC Server
 
-                        (c)2001-2006 Alexander Barton,
+                        (c)2001-2007 Alexander Barton,
                     alex@barton.de, http://www.barton.de/
 
                ngIRCd is free software and published under the
@@ -10,6 +10,20 @@
                                   -- NEWS --
 
 
+ngIRCd 0.10.2 (2007-06-08)
+
+  - Predefined channel configuration now allows specification of channel key
+    (mode k) and maximum user count (mode l): variables "Key" and "MaxUsers".
+  - When using the epoll() IO interface, compile in the select() interface as
+    well and fall back to it when epoll() isn't available on runtime.
+  - Added support for IO APIs "poll()" and "/dev/poll".
+
+ngIRCd 0.10.1 (2006-12-17)
+
+  - Allow PASS syntax defined in RFC 1459 for server links, too.
+  - New configuration option "PredefChannelsOnly": if set, clients can only
+    join predefined channels.
+
 ngIRCd 0.10.0 (2006-10-01)
 
   ngIRCd 0.10.0-pre1 (2006-08-02)
@@ -223,4 +237,4 @@ ngIRCd 0.0.1, 31.12.2001
 
 
 -- 
-$Id: NEWS,v 1.75.2.3 2006/10/01 16:21:55 alex Exp $
+$Id: NEWS,v 1.75.2.7 2007/06/08 09:05:23 alex Exp $

+ 4 - 2
README

@@ -1,7 +1,7 @@
 
                      ngIRCd - Next Generation IRC Server
 
-                        (c)2001-2006 Alexander Barton,
+                        (c)2001-2007 Alexander Barton,
                     alex@barton.de, http://www.barton.de/
 
                ngIRCd is free software and published under the
@@ -19,6 +19,8 @@ Licence (URL: http://www.gnu.org/licenses/gpl.html). ngIRCd means "next
 generation IRC daemon", it's written from scratch and not deduced from the
 "grandfather of IRC daemons", the daemon of the IRCNet.
 
+Please see the INSTALL document for installation and upgrade information!
+
 
 II. Status
 ~~~~~~~~~~~
@@ -84,4 +86,4 @@ mail to <alex@barton.de>.
 
 
 -- 
-$Id: README,v 1.21.2.1 2006/08/02 08:19:38 alex Exp $
+$Id: README,v 1.21.2.2 2007/05/05 20:25:20 alex Exp $

+ 33 - 14
config.guess

@@ -1,9 +1,10 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
 
-timestamp='2006-02-23'
+timestamp='2007-03-06'
 
 # This file is free software; you can redistribute it and/or modify it
 # under the terms of the GNU General Public License as published by
@@ -160,6 +161,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 	esac
 	# The Operating System including object format, if it has switched
@@ -210,7 +212,7 @@ case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
 	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
 	exit ;;
     macppc:MirBSD:*:*)
-	echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
 	exit ;;
     *:MirBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
@@ -770,6 +772,8 @@ EOF
 	case ${UNAME_MACHINE} in
 	    pc98)
 		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
+	    amd64)
+		echo x86_64-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	    *)
 		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	esac
@@ -777,10 +781,7 @@ EOF
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
-    i*:MINGW*:*)
-	echo ${UNAME_MACHINE}-pc-mingw32
-	exit ;;
-    i*:MSYS_NT-*:*:*)
+    *:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
     i*:windows32*:*)
@@ -790,12 +791,15 @@ EOF
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit ;;
-    x86:Interix*:[345]*)
-	echo i586-pc-interix${UNAME_RELEASE}
-	exit ;;
-    EM64T:Interix*:[345]*)
-	echo x86_64-unknown-interix${UNAME_RELEASE}
-	exit ;;
+    *:Interix*:[3456]*)
+    	case ${UNAME_MACHINE} in
+	    x86) 
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    EM64T | authenticamd)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
 	echo i${UNAME_MACHINE}-pc-mks
 	exit ;;
@@ -831,6 +835,9 @@ EOF
     arm*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
     cris:Linux:*:*)
 	echo cris-axis-linux-gnu
 	exit ;;
@@ -947,6 +954,9 @@ EOF
     x86_64:Linux:*:*)
 	echo x86_64-unknown-linux-gnu
 	exit ;;
+    xtensa:Linux:*:*)
+    	echo xtensa-unknown-linux-gnu
+	exit ;;
     i*86:Linux:*:*)
 	# The BFD linker knows what the default object file format is, so
 	# first see if it will tell us. cd to the root directory to prevent
@@ -989,7 +999,7 @@ EOF
 	LIBC=gnulibc1
 	# endif
 	#else
-	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__sun)
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
 	LIBC=gnu
 	#else
 	LIBC=gnuaout
@@ -1205,6 +1215,15 @@ EOF
     SX-6:SUPER-UX:*:*)
 	echo sx6-nec-superux${UNAME_RELEASE}
 	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
     Power*:Rhapsody:*:*)
 	echo powerpc-apple-rhapsody${UNAME_RELEASE}
 	exit ;;

+ 41 - 27
config.sub

@@ -1,9 +1,10 @@
 #! /bin/sh
 # Configuration validation subroutine script.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
-#   2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
+#   2000, 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation,
+#   Inc.
 
-timestamp='2006-02-23'
+timestamp='2007-01-18'
 
 # This file is (in principle) common to ALL GNU software.
 # The presence of a machine in this file suggests that SOME GNU software
@@ -240,15 +241,16 @@ case $basic_machine in
 	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
 	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
 	| am33_2.0 \
-	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \
+	| arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr | avr32 \
 	| bfin \
 	| c4x | clipper \
 	| d10v | d30v | dlx | dsp16xx \
-	| fr30 | frv \
+	| fido | fr30 | frv \
 	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
 	| i370 | i860 | i960 | ia64 \
 	| ip2k | iq2000 \
-	| m32r | m32rle | m68000 | m68k | m88k | maxq | mb | microblaze | mcore \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | mcore | mep \
 	| mips | mipsbe | mipseb | mipsel | mipsle \
 	| mips16 \
 	| mips64 | mips64el \
@@ -274,21 +276,19 @@ case $basic_machine in
 	| pdp10 | pdp11 | pj | pjl \
 	| powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \
 	| pyramid \
-	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[23]e | sh[34]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
 	| sh64 | sh64le \
-	| sparc | sparc64 | sparc64b | sparc86x | sparclet | sparclite \
-	| sparcv8 | sparcv9 | sparcv9b \
-	| strongarm \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu | strongarm \
 	| tahoe | thumb | tic4x | tic80 | tron \
 	| v850 | v850e \
 	| we32k \
-	| x86 | xscale | xscalee[bl] | xstormy16 | xtensa \
+	| x86 | xc16x | xscale | xscalee[bl] | xstormy16 | xtensa \
 	| z8k)
 		basic_machine=$basic_machine-unknown
 		;;
-	m32c)
-		basic_machine=$basic_machine-unknown
-		;;
 	m6811 | m68hc11 | m6812 | m68hc12)
 		# Motorola 68HC11/12.
 		basic_machine=$basic_machine-unknown
@@ -318,18 +318,18 @@ case $basic_machine in
 	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
 	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* \
 	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
-	| avr-* \
+	| avr-* | avr32-* \
 	| bfin-* | bs2000-* \
 	| c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* | c55x-* | c6x-* \
 	| clipper-* | craynv-* | cydra-* \
 	| d10v-* | d30v-* | dlx-* \
 	| elxsi-* \
-	| f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
 	| h8300-* | h8500-* \
 	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
 	| i*86-* | i860-* | i960-* | ia64-* \
 	| ip2k-* | iq2000-* \
-	| m32r-* | m32rle-* \
+	| m32c-* | m32r-* | m32rle-* \
 	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
 	| m88110-* | m88k-* | maxq-* | mcore-* \
 	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
@@ -358,23 +358,21 @@ case $basic_machine in
 	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \
 	| pyramid-* \
 	| romp-* | rs6000-* \
-	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | shbe-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
 	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
-	| sparc-* | sparc64-* | sparc64b-* | sparc86x-* | sparclet-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
 	| sparclite-* \
-	| sparcv8-* | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | strongarm-* | sv1-* | sx?-* \
 	| tahoe-* | thumb-* \
 	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
 	| tron-* \
 	| v850-* | v850e-* | vax-* \
 	| we32k-* \
-	| x86-* | x86_64-* | xps100-* | xscale-* | xscalee[bl]-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* | xscale-* | xscalee[bl]-* \
 	| xstormy16-* | xtensa-* \
 	| ymp-* \
 	| z8k-*)
 		;;
-	m32c-*)
-		;;
 	# Recognize the various machine names and aliases which stand
 	# for a CPU type and a company and sometimes even an OS.
 	386bsd)
@@ -912,6 +910,10 @@ case $basic_machine in
 	sb1el)
 		basic_machine=mipsisa64sb1el-unknown
 		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
 	sei)
 		basic_machine=mips-sei
 		os=-seiux
@@ -923,6 +925,9 @@ case $basic_machine in
 		basic_machine=sh-hitachi
 		os=-hms
 		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
 	sh64)
 		basic_machine=sh64-unknown
 		;;
@@ -1128,7 +1133,7 @@ case $basic_machine in
 	sh[1234] | sh[24]a | sh[34]eb | sh[1234]le | sh[23]ele)
 		basic_machine=sh-unknown
 		;;
-	sparc | sparcv8 | sparcv9 | sparcv9b)
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
 		basic_machine=sparc-sun
 		;;
 	cydra)
@@ -1217,7 +1222,7 @@ case $os in
 	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
 	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
 	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
-	      | -skyos* | -haiku* | -rdos*)
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops*)
 	# Remember, each alternative MUST END IN *, to match a version number.
 		;;
 	-qnx*)
@@ -1369,6 +1374,12 @@ else
 # system, and we'll never get to this point.
 
 case $basic_machine in
+        score-*)
+		os=-elf
+		;;
+        spu-*)
+		os=-elf
+		;;
 	*-acorn)
 		os=-riscix1.2
 		;;
@@ -1378,9 +1389,9 @@ case $basic_machine in
 	arm*-semi)
 		os=-aout
 		;;
-    c4x-* | tic4x-*)
-        os=-coff
-        ;;
+        c4x-* | tic4x-*)
+        	os=-coff
+		;;
 	# This must come before the *-dec entry.
 	pdp10-*)
 		os=-tops20
@@ -1406,6 +1417,9 @@ case $basic_machine in
 	m68*-cisco)
 		os=-aout
 		;;
+        mep-*)
+		os=-elf
+		;;
 	mips*-cisco)
 		os=-elf
 		;;

File diff suppressed because it is too large
+ 858 - 227
configure


+ 107 - 18
configure.in

@@ -1,6 +1,6 @@
 #
 # ngIRCd -- The Next Generation IRC Daemon
-# Copyright (c)2001-2006 Alexander Barton <alex@barton.de>
+# Copyright (c)2001-2007 Alexander Barton <alex@barton.de>
 #
 # 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.6 2006/10/01 16:21:56 alex Exp $
+# $Id: configure.in,v 1.118.2.13 2007/07/31 19:07:59 alex Exp $
 #
 
 # -- Initialisation --
 
 AC_PREREQ(2.50)
-AC_INIT(ngircd, 0.10.0)
+AC_INIT(ngircd, 0.10.3)
 AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
 AC_CANONICAL_TARGET
 AM_INIT_AUTOMAKE(1.6)
@@ -53,6 +53,7 @@ AC_PROG_RANLIB
 
 AM_C_PROTOTYPES
 AC_C_CONST
+AC_C_INLINE
 
 # -- Hard coded system and compiler dependencies/features/options ... --
 
@@ -137,17 +138,15 @@ AC_FUNC_STRFTIME
 
 AC_CHECK_FUNCS([ \
 	bind gethostbyaddr gethostbyname gethostname inet_ntoa malloc memmove \
-	memset realloc setsid setsockopt socket strcasecmp strchr strerror \
+	memset realloc setsid setsockopt socket strcasecmp strchr strcspn strerror \
 	strstr waitpid],,AC_MSG_ERROR([required function missing!]))
 
 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)],
@@ -173,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)],
@@ -197,44 +198,120 @@ 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=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(select, x_io_select=yes,
+				AC_MSG_ERROR([Can't enable select IO support!])
+			)
+		fi
+	],
+	[
+		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)
+	]
+)
 
-x_io_backend=select
 AC_ARG_WITH(epoll,
-	[  --without-epoll         disable epoll support (autodetected by default)],
+	[  --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_backend=epoll,
-				AC_MSG_ERROR([Can't enable epoll support!])
+			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_backend=epoll)
+		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"
 				CPPFLAGS="-I$withval/include $CPPFLAGS"
 				LDFLAGS="-L$withval/lib $LDFLAGS"
 			fi
-			AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue,
-				AC_MSG_ERROR([Can't enable kqueue support!])
+			AC_CHECK_FUNCS(kqueue, x_io_backend=kqueue\(\),
+				AC_MSG_ERROR([Can't enable kqueue IO support!])
 			)
 		fi
 	],
 	[
-		AC_CHECK_FUNCS(kqueue, x_io_backend=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,
@@ -265,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"],
@@ -313,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],
@@ -334,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],
@@ -343,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)],
@@ -352,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
@@ -361,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!],
@@ -481,7 +570,7 @@ test "$x_identauth_on" = "yes" \
 	&& echo $ECHO_N "yes   $ECHO_C" \
 	|| echo $ECHO_N "no    $ECHO_C"
 echo $ECHO_N "        I/O backend: $ECHO_C"
-	echo "\"$x_io_backend()\""
+	echo "\"$x_io_backend\""
 
 echo
 

+ 18 - 0
contrib/Debian/changelog

@@ -1,3 +1,21 @@
+ngircd (0.10.3-0ab1) unstable; urgency=high
+
+  * New "upstream" release: 0.10.3 - fixing a security bug.
+
+ -- Alexander Barton <alex@barton.de>  Tue, 31 Jul 2007 21:02:52 +0200
+
+ngircd (0.10.2-0ab1) unstable; urgency=low
+
+  * New "upstream" release: 0.10.2
+
+ -- Alexander Barton <alex@barton.de>  Fri,  8 Jun 2007 10:49:36 +0200
+
+ngircd (0.10.1-0ab1) unstable; urgency=low
+
+  * New "upstream" release: 0.10.1
+
+ -- Alexander Barton <alex@barton.de>  Sun, 17 Dec 2006 14:52:06 +0100
+
 ngircd (0.10.0-0ab1) unstable; urgency=low
 
   * New "upstream" release: 0.10.0

+ 12 - 1
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

+ 1 - 1
contrib/ngircd.spec

@@ -1,5 +1,5 @@
 %define name    ngircd
-%define version 0.10.0
+%define version 0.10.3
 %define release 1
 %define prefix  %{_prefix}
 

+ 2 - 1
doc/Platforms.txt

@@ -51,6 +51,7 @@ powerpc/apple/darwin7.4.0   gcc 3.3      0.8.0      04-05-30 alex   Y Y Y Y
 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 $

+ 11 - 2
doc/sample-ngircd.conf

@@ -1,4 +1,4 @@
-# $Id: sample-ngircd.conf,v 1.37 2006/04/09 12:27:23 alex 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
@@ -93,6 +93,9 @@
 	# server? (This is a compatibility hack for ircd-irc2 servers)
 	;OperServerMode = no
 
+	# Allow Pre-Defined Channels only (see Section [Channels])
+	;PredefChannelsOnly = no
+
 	# Maximum number of simultaneous connection the server is allowed
 	# to accept (<=0: unlimited):
 	;MaxConnections = -1
@@ -175,7 +178,13 @@
 	;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 ...

+ 2 - 2
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 \

+ 2 - 2
doc/src/Makefile.in

@@ -24,7 +24,7 @@
 # (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 $
 #
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
@@ -305,7 +305,7 @@ maintainer-clean-local:
 	rm -f Makefile Makefile.in
 
 distclean-local:
-	rm -f html
+	rm -rf html
 
 srcdoc:
 	@doxygen --version >/dev/null 2>&1 \

+ 6 - 1
man/ngircd.conf.5

@@ -1,5 +1,5 @@
 .\"
-.\" $Id: ngircd.conf.5,v 1.20 2005/09/02 14:39:00 fw Exp $
+.\" $Id: ngircd.conf.5,v 1.20.2.1 2006/12/11 22:08:14 fw Exp $
 .\"
 .TH ngircd.conf 5 "August 2005" ngircd "ngIRCd Manual"
 .SH NAME
@@ -146,6 +146,11 @@ If OperCanUseMode is enabled, this may lead the compatibility problems with
 Servers that run the ircd-irc2 Software. This Option "masks" mode requests
 by non-chanops as if they were coming from the server. Default: no.
 .TP
+\fBPredefChannelsOnly\fR
+If enabled, no new channels can be created. Useful if
+you do not want to have channels other than those defined in
+the config file.
+.TP
 \fBMaxConnections\fR
 Maximum number of simultaneous connection the server is allowed to accept
 (<=0: unlimited). Default: -1.

+ 14 - 2
src/config.h.in

@@ -115,6 +115,9 @@
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #undef HAVE_NETINET_IN_H
 
+/* Define to 1 if you have the `poll' function. */
+#undef HAVE_POLL
+
 /* Define to 1 if you have the `realloc' function. */
 #undef HAVE_REALLOC
 
@@ -157,6 +160,9 @@
 /* Define to 1 if you have the `strchr' function. */
 #undef HAVE_STRCHR
 
+/* Define to 1 if you have the `strcspn' function. */
+#undef HAVE_STRCSPN
+
 /* Define to 1 if you have the `strdup' function. */
 #undef HAVE_STRDUP
 
@@ -190,8 +196,8 @@
 /* Define to 1 if you have the <syslog.h> header file. */
 #undef HAVE_SYSLOG_H
 
-/* Define to 1 if you have the <sys/select.h> header file. */
-#undef HAVE_SYS_SELECT_H
+/* Define to 1 if you have the <sys/devpoll.h> header file. */
+#undef HAVE_SYS_DEVPOLL_H
 
 /* Define to 1 if you have the <sys/socket.h> header file. */
 #undef HAVE_SYS_SOCKET_H
@@ -310,6 +316,12 @@
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const
 
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+   calls it, or to nothing if 'inline' is not supported under any name.  */
+#ifndef __cplusplus
+#undef inline
+#endif
+
 /* Define to `int' if <sys/types.h> does not define. */
 #undef pid_t
 

+ 8 - 22
src/ngircd/array.c

@@ -12,7 +12,7 @@
 
 #include "array.h"
 
-static char UNUSED id[] = "$Id: array.c,v 1.11 2006/07/01 22:11:48 fw Exp $";
+static char UNUSED id[] = "$Id: array.c,v 1.11.2.3 2007/04/03 22:08:52 fw Exp $";
 
 #include <assert.h>
 
@@ -66,10 +66,7 @@ array_alloc(array * a, size_t size, size_t pos)
 
 	assert(size > 0);
 
-	if (pos_plus1 < pos)
-		return NULL;
-
-	if (!safemult_sizet(size, pos_plus1, &alloc))
+	if (pos_plus1 == 0 || !safemult_sizet(size, pos_plus1, &alloc))
 		return NULL;
 
 	if (a->allocated < alloc) {
@@ -250,20 +247,22 @@ void *
 array_get(array * a, size_t membersize, size_t pos)
 {
 	size_t totalsize;
+	size_t posplus1 = pos + 1;
 
 	assert(membersize > 0);
 	assert(a != NULL);
 
-	if (array_UNUSABLE(a))
+	if (!posplus1 || array_UNUSABLE(a))
 		return NULL;
 
-	if (!safemult_sizet(pos, membersize, &totalsize))
+	if (!safemult_sizet(posplus1, membersize, &totalsize))
 		return NULL;
 
 	if (a->allocated < totalsize)
 		return NULL;
 
-	return a->mem + pos * membersize;
+	totalsize = pos * membersize;
+	return a->mem + totalsize;
 }
 
 
@@ -271,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);
@@ -283,16 +282,6 @@ array_free(array * a)
 }
 
 
-void
-array_free_wipe(array * a)
-{
-	if (!array_UNUSABLE(a))
-		memset(a->mem, 0, a->allocated);
-
-	array_free(a);
-}
-
-
 void *
 array_start(const array * const a)
 {
@@ -331,9 +320,6 @@ array_moveleft(array * a, size_t membersize, size_t pos)
 	assert(a != NULL);
 	assert(membersize > 0);
 
-	if (!pos)
-		return;
-
 	if (!safemult_sizet(membersize, pos, &bytepos)) {
 		a->used = 0;
 		return;

+ 141 - 80
src/ngircd/channel.c

@@ -17,7 +17,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: channel.c,v 1.56 2006/07/24 22:54:09 alex 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 <assert.h>
@@ -70,6 +70,22 @@ Channel_Init( void )
 } /* Channel_Init */
 
 
+GLOBAL struct list_head *
+Channel_GetListBans(CHANNEL *c)
+{
+	assert(c != NULL);
+	return &c->list_bans;
+}
+
+
+GLOBAL struct list_head *
+Channel_GetListInvites(CHANNEL *c)
+{
+	assert(c != NULL);
+	return &c->list_invites;
+}
+
+
 GLOBAL void
 Channel_InitPredefined( void )
 {
@@ -114,7 +130,10 @@ Channel_InitPredefined( void )
 			c = Conf_Channel[i].modes;
 			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 );
 		}
@@ -129,7 +148,7 @@ Channel_Exit( void )
 {
 	CHANNEL *c, *c_next;
 	CL2CHAN *cl2chan, *cl2chan_next;
-	
+
 	/* Channel-Strukturen freigeben */
 	c = My_Channels;
 	while( c )
@@ -173,7 +192,7 @@ Channel_Join( CLIENT *Client, char *Name )
 	{
 		/* Gibt es noch nicht? Dann neu anlegen: */
 		chan = Channel_Create( Name );
-		if( ! chan ) return false;
+		if (!chan) return false;
 	}
 
 	/* User dem Channel hinzufuegen */
@@ -214,7 +233,6 @@ Channel_Kick( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason )
 	assert( Name != NULL );
 	assert( Reason != NULL );
 
-	/* Channel suchen */
 	chan = Channel_Search( Name );
 	if( ! chan )
 	{
@@ -266,11 +284,11 @@ Channel_Quit( CLIENT *Client, char *Reason )
 } /* Channel_Quit */
 
 
-GLOBAL long
+GLOBAL unsigned long
 Channel_Count( void )
 {
 	CHANNEL *c;
-	long count = 0;
+	unsigned long count = 0;
 	
 	c = My_Channels;
 	while( c )
@@ -282,11 +300,11 @@ Channel_Count( void )
 } /* Channel_Count */
 
 
-GLOBAL long
+GLOBAL unsigned long
 Channel_MemberCount( CHANNEL *Chan )
 {
 	CL2CHAN *cl2chan;
-	long count = 0;
+	unsigned long count = 0;
 
 	assert( Chan != NULL );
 
@@ -321,27 +339,9 @@ Channel_CountForUser( CLIENT *Client )
 } /* Channel_CountForUser */
 
 
-GLOBAL int
-Channel_PCount( void )
-{
-	/* Count the number of persistent (mode 'P') channels */
-
-	CHANNEL *chan;
-	int count = 0;
-
-	chan = My_Channels;
-	while( chan )
-	{
-		if( strchr( chan->modes, 'P' )) count++;
-		chan = chan->next;
-	}
-
-	return count;
-} /* Channel_PCount */
-
 
-GLOBAL char *
-Channel_Name( CHANNEL *Chan )
+GLOBAL const char *
+Channel_Name( const CHANNEL *Chan )
 {
 	assert( Chan != NULL );
 	return Chan->name;
@@ -364,7 +364,7 @@ Channel_Key( CHANNEL *Chan )
 } /* Channel_Key */
 
 
-GLOBAL long
+GLOBAL unsigned long
 Channel_MaxUsers( CHANNEL *Chan )
 {
 	assert( Chan != NULL );
@@ -463,25 +463,13 @@ Channel_GetChannel( CL2CHAN *Cl2Chan )
 
 
 GLOBAL bool
-Channel_IsValidName( char *Name )
+Channel_IsValidName( const char *Name )
 {
-	/* Pruefen, ob Name als Channelname gueltig */
-
-	char *ptr, badchars[10];
-	
 	assert( Name != NULL );
 
 	if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return false;
 
-	ptr = Name;
-	strcpy( badchars, " ,:\007" );
-	while( *ptr )
-	{
-		if( strchr( badchars, *ptr )) return false;
-		ptr++;
-	}
-	
-	return true;
+	return Name[strcspn(Name, " ,:\007")] == 0;
 } /* Channel_IsValidName */
 
 
@@ -548,7 +536,7 @@ Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, char Mode )
 
 	cl2chan = Get_Cl2Chan( Chan, Client );
 	assert( cl2chan != NULL );
-	
+
 	x[0] = Mode; x[1] = '\0';
 	if( ! strchr( cl2chan->modes, x[0] ))
 	{
@@ -594,7 +582,7 @@ GLOBAL char *
 Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
 {
 	/* return Users' Channel-Modes */
-	
+
 	CL2CHAN *cl2chan;
 
 	assert( Chan != NULL );
@@ -614,9 +602,7 @@ Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client )
 
 	assert( Chan != NULL );
 	assert( Client != NULL );
-
-	if( Get_Cl2Chan( Chan, Client )) return true;
-	else return false;
+	return Get_Cl2Chan(Chan, Client);
 } /* Channel_IsMemberOf */
 
 
@@ -661,12 +647,9 @@ Channel_SetTopic(CHANNEL *Chan, CLIENT *Client, char *Topic)
 	if (len < array_bytes(&Chan->topic))
 		array_free(&Chan->topic);
 
-	if (!array_copyb(&Chan->topic, Topic, len))
+	if (len >= COMMAND_LEN || !array_copyb(&Chan->topic, Topic, len+1))
 		Log(LOG_WARNING, "could not set new Topic \"%s\" on %s: %s",
 					Topic, Chan->name, strerror(errno));
-
-	array_cat0(&Chan->topic);
-
 #ifndef STRICT_RFC
 	Chan->topic_time = time(NULL);
 	if (Client != NULL && Client_Type(Client) != CLIENT_SERVER)
@@ -698,17 +681,17 @@ Channel_SetKey( CHANNEL *Chan, char *Key )
 	assert( Key != NULL );
 
 	strlcpy( Chan->key, Key, sizeof( Chan->key ));
-	Log( LOG_DEBUG, "Channel %s: Key is now \"%s\".", Chan->name, Chan->key );
+	LogDebug("Channel %s: Key is now \"%s\".", Chan->name, Chan->key );
 } /* Channel_SetKey */
 
 
 GLOBAL void
-Channel_SetMaxUsers( CHANNEL *Chan, long Count )
+Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count)
 {
 	assert( Chan != NULL );
 
 	Chan->maxusers = Count;
-	Log( LOG_DEBUG, "Channel %s: Member limit is now %ld.", Chan->name, Chan->maxusers );
+	LogDebug("Channel %s: Member limit is now %lu.", Chan->name, Chan->maxusers );
 } /* Channel_SetMaxUsers */
 
 
@@ -730,9 +713,9 @@ Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, char *Text )
 	ok = true;
 	if( strchr( Channel_Modes( Chan ), 'n' ) && ( ! is_member )) ok = false;
 	if( strchr( Channel_Modes( Chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = false;
-	
+
 	/* Is the client banned? */
-	if( Lists_CheckBanned( From, Chan ))
+	if( Lists_Check(&Chan->list_bans, From))
 	{
 		/* Client is banned, but is he channel operator or has voice? */
 		if(( ! has_voice ) && ( ! is_op )) ok = false;
@@ -753,7 +736,7 @@ Channel_Create( char *Name )
 	CHANNEL *c;
 
 	assert( Name != NULL );
-	
+
 	c = (CHANNEL *)malloc( sizeof( CHANNEL ));
 	if( ! c )
 	{
@@ -765,9 +748,7 @@ Channel_Create( char *Name )
 	c->hash = Hash( c->name );
 	c->next = My_Channels;
 	My_Channels = c;
-#ifdef DEBUG	
-	Log( LOG_DEBUG, "Created new channel structure for \"%s\".", Name );
-#endif
+	LogDebug("Created new channel structure for \"%s\".", Name);
 	return c;
 } /* Channel_Create */
 
@@ -851,25 +832,42 @@ Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Re
 	switch( Type )
 	{
 		case REMOVE_QUIT:
-			/* QUIT: andere Server wurden bereits informiert, vgl. Client_Destroy();
-			 * hier also "nur" noch alle User in betroffenen Channeln infomieren */
+			/* QUIT: other servers have already been notified, see Client_Destroy();
+			 * so only inform other clients in same channel. */
 			assert( InformServer == false );
-			Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason );
+			LogDebug("User \"%s\" left channel \"%s\" (%s).",
+					Client_Mask( Client ), c->name, Reason );
 			break;
 		case REMOVE_KICK:
-			/* User wurde geKICKed: ggf. andere Server sowie alle betroffenen User
-			 * im entsprechenden Channel informieren */
-			if( InformServer ) IRC_WriteStrServersPrefix( Client_NextHop( Origin ), Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason );
-			IRC_WriteStrChannelPrefix( Client, c, Origin, false, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason );
-			if(( Client_Conn( Client ) > NONE ) && ( Client_Type( Client ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Client, Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason );
-			Log( LOG_DEBUG, "User \"%s\" has been kicked of \"%s\" by \"%s\": %s.", Client_Mask( Client ), c->name, Client_ID( Origin ), Reason );
+			/* User was KICKed: inform other servers and all users in channel */
+			if( InformServer )
+				IRC_WriteStrServersPrefix( Client_NextHop( Origin ),
+					Origin, "KICK %s %s :%s", c->name, Client_ID( Client ), Reason);
+			IRC_WriteStrChannelPrefix(Client, c, Origin, false, "KICK %s %s :%s",
+							c->name, Client_ID( Client ), Reason );
+			if ((Client_Conn(Client) > NONE) &&
+					(Client_Type(Client) == CLIENT_USER))
+			{
+				IRC_WriteStrClientPrefix(Client, Origin, "KICK %s %s :%s",
+								c->name, Client_ID( Client ), Reason);
+			}
+			LogDebug("User \"%s\" has been kicked of \"%s\" by \"%s\": %s.",
+				Client_Mask( Client ), c->name, Client_ID(Origin), Reason);
 			break;
-		default:
-			/* PART */
-			if( InformServer ) IRC_WriteStrServersPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
-			IRC_WriteStrChannelPrefix( Origin, c, Client, false, "PART %s :%s", c->name, Reason );
-			if(( Client_Conn( Origin ) > NONE ) && ( Client_Type( Origin ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
-			Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason );
+		default: /* PART */
+			if (InformServer)
+				IRC_WriteStrServersPrefix(Origin, Client, "PART %s :%s", c->name, Reason);
+
+			IRC_WriteStrChannelPrefix(Origin, c, Client, false, "PART %s :%s",
+									c->name, Reason);
+
+			if ((Client_Conn(Origin) > NONE) &&
+					(Client_Type(Origin) == CLIENT_USER))
+			{
+				IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason);
+				LogDebug("User \"%s\" left channel \"%s\" (%s).",
+					Client_Mask(Client), c->name, Reason);
+			}
 	}
 
 	/* Wenn Channel nun leer und nicht pre-defined: loeschen */
@@ -882,6 +880,68 @@ Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Re
 } /* Remove_Client */
 
 
+GLOBAL bool
+Channel_AddBan(CHANNEL *c, const char *mask )
+{
+	struct list_head *h = Channel_GetListBans(c);
+	return Lists_Add(h, mask, false);
+}
+
+
+GLOBAL bool
+Channel_AddInvite(CHANNEL *c, const char *mask, bool onlyonce)
+{
+	struct list_head *h = Channel_GetListInvites(c);
+	return Lists_Add(h, mask, onlyonce);
+}
+
+
+static bool
+ShowInvitesBans(struct list_head *head, CLIENT *Client, CHANNEL *Channel, bool invite)
+{
+	struct list_elem *e;
+	char *msg = invite ? RPL_INVITELIST_MSG : RPL_BANLIST_MSG;
+	char *msg_end;
+
+	assert( Client != NULL );
+	assert( Channel != NULL );
+
+	e = Lists_GetFirst(head);
+	while (e) {
+		if( ! IRC_WriteStrClient( Client, msg, Client_ID( Client ),
+				Channel_Name( Channel ), Lists_GetMask(e) )) return DISCONNECTED;
+		e = Lists_GetNext(e);
+	}
+
+	msg_end = invite ? RPL_ENDOFINVITELIST_MSG : RPL_ENDOFBANLIST_MSG;
+	return IRC_WriteStrClient( Client, msg_end, Client_ID( Client ), Channel_Name( Channel ));
+}
+
+
+GLOBAL bool
+Channel_ShowBans( CLIENT *Client, CHANNEL *Channel )
+{
+	struct list_head *h;
+
+	assert( Channel != NULL );
+
+	h = Channel_GetListBans(Channel);
+	return ShowInvitesBans(h, Client, Channel, false);
+}
+
+
+GLOBAL bool
+Channel_ShowInvites( CLIENT *Client, CHANNEL *Channel )
+{
+	struct list_head *h;
+
+	assert( Channel != NULL );
+
+	h = Channel_GetListInvites(Channel);
+	return ShowInvitesBans(h, Client, Channel, true);
+}
+
+
 static CL2CHAN *
 Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
 {
@@ -911,7 +971,7 @@ static bool
 Delete_Channel( CHANNEL *Chan )
 {
 	/* Channel-Struktur loeschen */
-	
+
 	CHANNEL *chan, *last_chan;
 
 	last_chan = NULL;
@@ -927,13 +987,14 @@ Delete_Channel( CHANNEL *Chan )
 	Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
 
 	/* Invite- und Ban-Lists aufraeumen */
-	Lists_DeleteChannel( chan );
+	Lists_Free( &chan->list_bans );
+	Lists_Free( &chan->list_invites );
 
 	/* Neu verketten und freigeben */
 	if( last_chan ) last_chan->next = chan->next;
 	else My_Channels = chan->next;
 	free( chan );
-		
+
 	return true;
 } /* Delete_Channel */
 

+ 17 - 11
src/ngircd/channel.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: channel.h,v 1.29 2005/09/02 12:50:25 alex Exp $
+ * $Id: channel.h,v 1.29.2.2 2007/04/03 20:23:31 fw Exp $
  *
  * Channel management (header)
  */
@@ -20,6 +20,7 @@
 
 #if defined(__channel_c__) | defined(S_SPLINT_S)
 
+#include "lists.h"
 #include "defines.h"
 #include "array.h"
 
@@ -35,7 +36,9 @@ typedef struct _CHANNEL
 	char topic_who[CLIENT_NICK_LEN];/* Nickname of user that set topic */
 #endif
 	char key[CLIENT_PASS_LEN];	/* Channel key ("password", mode "k" ) */
-	long maxusers;			/* Maximum number of members (mode "l") */
+	unsigned long maxusers;		/* Maximum number of members (mode "l") */
+	struct list_head list_bans;	/* list head of banned users */
+	struct list_head list_invites;	/* list head of invited users */
 } CHANNEL;
 
 typedef struct _CLIENT2CHAN
@@ -53,6 +56,8 @@ typedef POINTER CL2CHAN;
 
 #endif
 
+GLOBAL struct list_head *Channel_GetListBans PARAMS((CHANNEL *c));
+GLOBAL struct list_head *Channel_GetListInvites PARAMS((CHANNEL *c));
 
 GLOBAL void Channel_Init PARAMS(( void ));
 GLOBAL void Channel_InitPredefined PARAMS((  void ));
@@ -65,21 +70,20 @@ GLOBAL void Channel_Quit PARAMS(( CLIENT *Client, char *Reason ));
 
 GLOBAL void Channel_Kick PARAMS((  CLIENT *Client, CLIENT *Origin, char *Name, char *Reason ));
 
-GLOBAL long Channel_Count PARAMS(( void ));
-GLOBAL long Channel_MemberCount PARAMS(( CHANNEL *Chan ));
+GLOBAL unsigned long Channel_Count PARAMS(( void ));
+GLOBAL unsigned long Channel_MemberCount PARAMS(( CHANNEL *Chan ));
 GLOBAL int Channel_CountForUser PARAMS(( CLIENT *Client ));
-GLOBAL int Channel_PCount PARAMS(( void ));
 
-GLOBAL char *Channel_Name PARAMS(( CHANNEL *Chan ));
+GLOBAL const char *Channel_Name PARAMS(( const CHANNEL *Chan ));
 GLOBAL char *Channel_Modes PARAMS(( CHANNEL *Chan ));
 GLOBAL char *Channel_Topic PARAMS(( CHANNEL *Chan ));
 GLOBAL char *Channel_Key PARAMS(( CHANNEL *Chan ));
-GLOBAL long Channel_MaxUsers PARAMS(( CHANNEL *Chan ));
+GLOBAL unsigned long Channel_MaxUsers PARAMS(( CHANNEL *Chan ));
 
 GLOBAL void Channel_SetTopic PARAMS(( CHANNEL *Chan, CLIENT *Client, char *Topic ));
 GLOBAL void Channel_SetModes PARAMS(( CHANNEL *Chan, char *Modes ));
 GLOBAL void Channel_SetKey PARAMS(( CHANNEL *Chan, char *Key ));
-GLOBAL void Channel_SetMaxUsers PARAMS(( CHANNEL *Chan, long Count ));
+GLOBAL void Channel_SetMaxUsers PARAMS(( CHANNEL *Chan, unsigned long Count ));
 
 GLOBAL CHANNEL *Channel_Search PARAMS(( char *Name ));
 
@@ -94,7 +98,7 @@ GLOBAL CL2CHAN *Channel_NextChannelOf PARAMS(( CLIENT *Client, CL2CHAN *Cl2Chan
 GLOBAL CLIENT *Channel_GetClient PARAMS(( CL2CHAN *Cl2Chan ));
 GLOBAL CHANNEL *Channel_GetChannel PARAMS(( CL2CHAN *Cl2Chan ));
 
-GLOBAL bool Channel_IsValidName PARAMS(( char *Name ));
+GLOBAL bool Channel_IsValidName PARAMS(( const char *Name ));
 
 GLOBAL bool Channel_ModeAdd PARAMS(( CHANNEL *Chan, char Mode ));
 GLOBAL bool Channel_ModeDel PARAMS(( CHANNEL *Chan, char Mode ));
@@ -114,8 +118,10 @@ GLOBAL unsigned int Channel_TopicTime PARAMS(( CHANNEL *Chan ));
 GLOBAL char *Channel_TopicWho PARAMS(( CHANNEL *Chan ));
 #endif
 
+GLOBAL bool Channel_AddInvite PARAMS((CHANNEL *c, const char *Mask, bool OnlyOnce ));
+GLOBAL bool Channel_AddBan PARAMS((CHANNEL *c, const char *Mask ));
 
+GLOBAL bool Channel_ShowBans PARAMS((CLIENT *client, CHANNEL *c));
+GLOBAL bool Channel_ShowInvites PARAMS((CLIENT *client, CHANNEL *c));
 #endif
-
-
 /* -eof- */

+ 41 - 83
src/ngircd/client.c

@@ -17,7 +17,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: client.c,v 1.91 2006/04/23 10:37:27 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 <assert.h>
@@ -57,8 +57,8 @@ static WHOWAS My_Whowas[MAX_WHOWAS];
 static int Last_Whowas = -1;
 
 
-static long Count PARAMS(( CLIENT_TYPE Type ));
-static long MyCount PARAMS(( CLIENT_TYPE Type ));
+static unsigned long Count PARAMS(( CLIENT_TYPE Type ));
+static unsigned long MyCount PARAMS(( CLIENT_TYPE Type ));
 
 static CLIENT *New_Client_Struct PARAMS(( void ));
 static void Generate_MyToken PARAMS(( CLIENT *Client ));
@@ -68,10 +68,6 @@ 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;
 
@@ -211,8 +207,8 @@ Init_New_Client(CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer,
 	if( Modes ) Client_SetModes( client, Modes );
 	if( Type == CLIENT_SERVER ) Generate_MyToken( client );
 
-	/* ist der User away? */
-	if( strchr( client->modes, 'a' )) strlcpy( client->away, DEFAULT_AWAY_MSG, sizeof( client->away ));
+	if( strchr( client->modes, 'a' ))
+		strlcpy( client->away, DEFAULT_AWAY_MSG, sizeof( client->away ));
 
 	/* Verketten */
 	client->next = (POINTER *)My_Clients;
@@ -337,42 +333,13 @@ Client_Destroy( CLIENT *Client, char *LogMsg, char *FwdMsg, bool SendQuit )
 
 
 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 */
 
@@ -399,7 +366,7 @@ Client_SetUser( CLIENT *Client, char *User, bool Idented )
 
 	assert( Client != NULL );
 	assert( User != NULL );
-	
+
 	if( Idented ) strlcpy( Client->user, User, sizeof( Client->user ));
 	else
 	{
@@ -416,7 +383,7 @@ Client_SetInfo( CLIENT *Client, char *Info )
 
 	assert( Client != NULL );
 	assert( Info != NULL );
-	
+
 	strlcpy( Client->info, Info, sizeof( Client->info ));
 } /* Client_SetInfo */
 
@@ -452,7 +419,7 @@ Client_SetPassword( CLIENT *Client, char *Pwd )
 
 	assert( Client != NULL );
 	assert( Pwd != NULL );
-	
+
 	strlcpy( Client->pwd, Pwd, sizeof( Client->pwd ));
 } /* Client_SetPassword */
 
@@ -522,7 +489,7 @@ Client_ModeAdd( CLIENT *Client, char Mode )
 	 */
 
 	char x[2];
-	
+
 	assert( Client != NULL );
 
 	x[0] = Mode; x[1] = '\0';
@@ -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 */
 
 
@@ -734,11 +700,13 @@ GLOBAL CLIENT *
 Client_NextHop( CLIENT *Client )
 {
 	CLIENT *c;
-	
+
 	assert( Client != NULL );
 
 	c = Client;
-	while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server )) c = c->introducer;
+	while( c->introducer && ( c->introducer != c ) && ( c->introducer != This_Server ))
+		c = c->introducer;
+
 	return c;
 } /* Client_NextHop */
 
@@ -750,7 +718,7 @@ Client_Mask( CLIENT *Client )
 	 * Prefixe benoetigt wird. */
 
 	assert( Client != NULL );
-	
+
 	if( Client->type == CLIENT_SERVER ) return Client->id;
 
 	snprintf( GetID_Buffer, GETID_LEN, "%s!%s@%s", Client->id, Client->user, Client->host );
@@ -795,12 +763,9 @@ Client_Away( CLIENT *Client )
 GLOBAL bool
 Client_CheckNick( CLIENT *Client, char *Nick )
 {
-	/* Nick ueberpruefen */
-
 	assert( Client != NULL );
 	assert( Nick != NULL );
-	
-	/* Nick ungueltig? */
+
 	if( ! Client_IsValidNick( Nick ))
 	{
 		IRC_WriteStrClient( Client, ERR_ERRONEUSNICKNAME_MSG, Client_ID( Client ), Nick );
@@ -913,13 +878,12 @@ Client_MyServiceCount( void )
 } /* Client_MyServiceCount */
 
 
-GLOBAL long
+GLOBAL unsigned long
 Client_MyServerCount( void )
 {
 	CLIENT *c;
-	long cnt;
+	unsigned long cnt = 0;
 
-	cnt = 0;
 	c = My_Clients;
 	while( c )
 	{
@@ -930,13 +894,12 @@ Client_MyServerCount( void )
 } /* Client_MyServerCount */
 
 
-GLOBAL long
+GLOBAL unsigned long
 Client_OperCount( void )
 {
 	CLIENT *c;
-	long cnt;
+	unsigned long cnt = 0;
 
-	cnt = 0;
 	c = My_Clients;
 	while( c )
 	{
@@ -947,19 +910,19 @@ Client_OperCount( void )
 } /* Client_OperCount */
 
 
-GLOBAL long
+GLOBAL unsigned long
 Client_UnknownCount( void )
 {
 	CLIENT *c;
-	long cnt;
+	unsigned long cnt = 0;
 
-	cnt = 0;
 	c = My_Clients;
 	while( c )
 	{
 		if( c && ( c->type != CLIENT_USER ) && ( c->type != CLIENT_SERVICE ) && ( c->type != CLIENT_SERVER )) cnt++;
 		c = (CLIENT *)c->next;
 	}
+
 	return cnt;
 } /* Client_UnknownCount */
 
@@ -979,16 +942,13 @@ Client_MyMaxUserCount( void )
 
 
 GLOBAL bool
-Client_IsValidNick( char *Nick )
+Client_IsValidNick( const char *Nick )
 {
-	/* Ist der Nick gueltig? */
+	const char *ptr;
+	static const char goodchars[] = ";0123456789-";
 
-	char *ptr, goodchars[20];
-	
 	assert( Nick != NULL );
 
-	strcpy( goodchars, ";0123456789-" );
-
 	if( Nick[0] == '#' ) return false;
 	if( strchr( goodchars, Nick[0] )) return false;
 	if( strlen( Nick ) >= CLIENT_NICK_LEN ) return false;
@@ -996,11 +956,11 @@ Client_IsValidNick( char *Nick )
 	ptr = Nick;
 	while( *ptr )
 	{
-		if(( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return false;
-		if(( *ptr > '}' ) && ( ! strchr( goodchars, *ptr ))) return false;
+		if (( *ptr < 'A' ) && ( ! strchr( goodchars, *ptr ))) return false;
+		if ( *ptr > '}' ) return false;
 		ptr++;
 	}
-	
+
 	return true;
 } /* Client_IsValidNick */
 
@@ -1037,13 +997,12 @@ Client_StartTime(CLIENT *Client)
 } /* Client_Uptime */
 
 
-static long
+static unsigned long
 Count( CLIENT_TYPE Type )
 {
 	CLIENT *c;
-	long cnt;
+	unsigned long cnt = 0;
 
-	cnt = 0;
 	c = My_Clients;
 	while( c )
 	{
@@ -1054,13 +1013,12 @@ Count( CLIENT_TYPE Type )
 } /* Count */
 
 
-static long
+static unsigned long
 MyCount( CLIENT_TYPE Type )
 {
 	CLIENT *c;
-	long cnt;
+	unsigned long cnt = 0;
 
-	cnt = 0;
 	c = My_Clients;
 	while( c )
 	{
@@ -1075,9 +1033,9 @@ static CLIENT *
 New_Client_Struct( void )
 {
 	/* Neue CLIENT-Struktur pre-initialisieren */
-	
+
 	CLIENT *c;
-	
+
 	c = (CLIENT *)malloc( sizeof( CLIENT ));
 	if( ! c )
 	{
@@ -1130,7 +1088,7 @@ Adjust_Counters( CLIENT *Client )
 	assert( Client != NULL );
 
 	if( Client->type != CLIENT_USER ) return;
-	
+
 	if( Client->conn_id != NONE )
 	{
 		/* Local connection */
@@ -1153,7 +1111,7 @@ Client_RegisterWhowas( CLIENT *Client )
 {
 	int slot;
 	time_t now;
-	
+
 	assert( Client != NULL );
 
 	now = time(NULL);
@@ -1167,7 +1125,7 @@ Client_RegisterWhowas( CLIENT *Client )
 #ifdef DEBUG
 	Log( LOG_DEBUG, "Saving WHOWAS information to slot %d ...", slot );
 #endif
-	
+
 	My_Whowas[slot].time = now;
 	strlcpy( My_Whowas[slot].id, Client_ID( Client ),
 		 sizeof( My_Whowas[slot].id ));
@@ -1179,7 +1137,7 @@ Client_RegisterWhowas( CLIENT *Client )
 		 sizeof( My_Whowas[slot].info ));
 	strlcpy( My_Whowas[slot].server, Client_ID( Client_Introducer( Client )),
 		 sizeof( My_Whowas[slot].server ));
-	
+
 	Last_Whowas = slot;
 } /* Client_RegisterWhowas */
 

+ 8 - 12
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 2006/04/23 10:37:27 fw Exp $
+ * $Id: client.h,v 1.42.2.3 2007/04/03 22:08:52 fw Exp $
  *
  * Client management (header)
  */
@@ -23,10 +23,9 @@
 #define CLIENT_GOTNICK 4		/* client did send NICK */
 #define CLIENT_GOTUSER 8		/* client did send USER */
 #define CLIENT_USER 16			/* client is an IRC user */
-#define CLIENT_UNKNOWNSERVER 32		/* unregistered server connection */
-#define CLIENT_GOTPASSSERVER 64		/* client did send PASS in "server style" */
-#define CLIENT_SERVER 128		/* client is a server */
-#define CLIENT_SERVICE 256		/* client is a service */
+#define CLIENT_SERVER 32		/* client is a server */
+#define CLIENT_SERVICE 64		/* client is a service */
+#define CLIENT_UNKNOWNSERVER 128	/* unregistered server connection */
 
 #define CLIENT_TYPE int
 
@@ -81,9 +80,6 @@ GLOBAL CLIENT *Client_NewRemoteServer PARAMS(( CLIENT *Introducer, char *Hostnam
 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 ));
 
@@ -138,15 +134,15 @@ GLOBAL bool Client_CheckID PARAMS(( CLIENT *Client, char *ID ));
 GLOBAL long Client_UserCount PARAMS(( void ));
 GLOBAL long Client_ServiceCount PARAMS(( void ));
 GLOBAL long Client_ServerCount PARAMS(( void ));
-GLOBAL long Client_OperCount PARAMS(( void ));
-GLOBAL long Client_UnknownCount PARAMS(( void ));
+GLOBAL unsigned long Client_OperCount PARAMS(( void ));
+GLOBAL unsigned long Client_UnknownCount PARAMS(( void ));
 GLOBAL long Client_MyUserCount PARAMS(( void ));
 GLOBAL long Client_MyServiceCount PARAMS(( void ));
-GLOBAL long Client_MyServerCount PARAMS(( void ));
+GLOBAL unsigned long Client_MyServerCount PARAMS(( void ));
 GLOBAL long Client_MaxUserCount PARAMS((  void ));
 GLOBAL long Client_MyMaxUserCount PARAMS((  void ));
 
-GLOBAL bool Client_IsValidNick PARAMS(( char *Nick ));
+GLOBAL bool Client_IsValidNick PARAMS(( const char *Nick ));
 
 GLOBAL WHOWAS *Client_GetWhowas PARAMS(( void ));
 GLOBAL int Client_GetLastWhowasIndex PARAMS(( void ));

+ 66 - 23
src/ngircd/conf.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: conf.c,v 1.92 2006/07/23 16:42:45 alex 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 <assert.h>
@@ -146,6 +146,9 @@ Conf_Rehash( void )
 	Set_Defaults( false );
 	Read_Config( );
 	Validate_Config(false, true);
+
+	/* Update CLIENT structure of local server */
+	Client_SetInfo(Client_ThisServer(), Conf_ServerInfo);
 } /* Config_Rehash */
 
 
@@ -199,15 +202,16 @@ Conf_Test( void )
 	printf( "  PingTimeout = %d\n", Conf_PingTimeout );
 	printf( "  PongTimeout = %d\n", Conf_PongTimeout );
 	printf( "  ConnectRetry = %d\n", Conf_ConnectRetry );
-	printf( "  OperCanUseMode = %s\n", Conf_OperCanMode == true? "yes" : "no" );
+	printf( "  OperCanUseMode = %s\n", Conf_OperCanMode == true ? "yes" : "no" );
 	printf( "  OperServerMode = %s\n", Conf_OperServerMode == true? "yes" : "no" );
+	printf( "  PredefChannelsOnly = %s\n", Conf_PredefChannelsOnly == true ? "yes" : "no" );
 	printf( "  MaxConnections = %ld\n", Conf_MaxConnections>0 ? Conf_MaxConnections : -1);
 	printf( "  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP>0 ? Conf_MaxConnectionsIP : -1);
 	printf( "  MaxJoins = %d\n\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1);
 
 	for( i = 0; i < Conf_Oper_Count; i++ ) {
 		if( ! Conf_Oper[i].name[0] ) continue;
-		
+
 		/* Valid "Operator" section */
 		puts( "[OPERATOR]" );
 		printf( "  Name = %s\n", Conf_Oper[i].name );
@@ -218,7 +222,7 @@ Conf_Test( void )
 
 	for( i = 0; i < MAX_SERVERS; i++ ) {
 		if( ! Conf_Server[i].name[0] ) continue;
-		
+
 		/* Valid "Server" section */
 		puts( "[SERVER]" );
 		printf( "  Name = %s\n", Conf_Server[i].name );
@@ -231,16 +235,18 @@ Conf_Test( void )
 
 	for( i = 0; i < Conf_Channel_Count; i++ ) {
 		if( ! Conf_Channel[i].name[0] ) continue;
-		
+
 		/* Valid "Channel" section */
 		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 : "");
 	}
-	
+
 	return 0;
 } /* Conf_Test */
 
@@ -268,14 +274,14 @@ Conf_UnsetServer( CONN_ID Idx )
 			Init_Server_Struct( &Conf_Server[i] );
 		} else {
 			/* Set time for next connect attempt */
- 			t = time(NULL);
- 			if (Conf_Server[i].lasttry < t - Conf_ConnectRetry) {
- 				/* The connection has been "long", so we don't
- 				 * require the next attempt to be delayed. */
- 				Conf_Server[i].lasttry =
- 					t - Conf_ConnectRetry + RECONNECT_DELAY;
- 			} else
- 				Conf_Server[i].lasttry = t;
+			t = time(NULL);
+			if (Conf_Server[i].lasttry < t - Conf_ConnectRetry) {
+				/* The connection has been "long", so we don't
+				 * require the next attempt to be delayed. */
+				Conf_Server[i].lasttry =
+					t - Conf_ConnectRetry + RECONNECT_DELAY;
+			} else
+				Conf_Server[i].lasttry = t;
 		}
 	}
 } /* Conf_UnsetServer */
@@ -297,9 +303,9 @@ GLOBAL int
 Conf_GetServer( CONN_ID Idx )
 {
 	/* Get index of server in configuration structure */
-	
+
 	int i = 0;
-	
+
 	assert( Idx > NONE );
 
 	for( i = 0; i < MAX_SERVERS; i++ ) {
@@ -377,7 +383,7 @@ Conf_AddServer( char *Name, UINT16 Port, char *Host, char *MyPwd, char *PeerPwd
 	strlcpy( Conf_Server[i].pwd_in, PeerPwd, sizeof( Conf_Server[i].pwd_in ));
 	Conf_Server[i].port = Port;
 	Conf_Server[i].flags = CONF_SFLAG_ONCE;
-	
+
 	return true;
 } /* Conf_AddServer */
 
@@ -409,7 +415,7 @@ Set_Defaults( bool InitServers )
 	strcpy( Conf_ListenAddress, "" );
 
 	Conf_UID = Conf_GID = 0;
-	
+
 	Conf_PingTimeout = 120;
 	Conf_PongTimeout = 20;
 
@@ -419,8 +425,9 @@ Set_Defaults( bool InitServers )
 	Conf_Channel_Count = 0;
 
 	Conf_OperCanMode = false;
+	Conf_PredefChannelsOnly = false;
 	Conf_OperServerMode = false;
-	
+
 	Conf_MaxConnections = -1;
 	Conf_MaxConnectionsIP = 5;
 	Conf_MaxJoins = 10;
@@ -550,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++;
 				}
@@ -750,6 +759,11 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
 		}
 		return;
 	}
+	if( strcasecmp( Var, "PredefChannelsOnly" ) == 0 ) {
+		/* Should we only allow pre-defined-channels? (i.e. users cannot create their own channels) */
+		Conf_PredefChannelsOnly = Check_ArgIsTrue( Arg );
+		return;
+	}
 	if( strcasecmp( Var, "OperCanUseMode" ) == 0 ) {
 		/* Are IRC operators allowed to use MODE in channels they aren't Op in? */
 		Conf_OperCanMode = Check_ArgIsTrue( Arg );
@@ -912,6 +926,21 @@ Handle_SERVER( int Line, char *Var, char *Arg )
 } /* Handle_SERVER */
 
 
+static bool
+Handle_Channelname(size_t chancount, const char *name)
+{
+	size_t size = sizeof( Conf_Channel[chancount].name );
+	char *dest = Conf_Channel[chancount].name;
+
+	if (*name && *name != '#') {
+		*dest = '#';
+		--size;
+		++dest;
+	}
+	return size > strlcpy(dest, name, size);
+}
+
+
 static void
 Handle_CHANNEL( int Line, char *Var, char *Arg )
 {
@@ -925,9 +954,7 @@ Handle_CHANNEL( int Line, char *Var, char *Arg )
 		chancount = Conf_Channel_Count - 1;
 
 	if( strcasecmp( Var, "Name" ) == 0 ) {
-		/* Name of the channel */
-		len = strlcpy( Conf_Channel[chancount].name, Arg, sizeof( Conf_Channel[chancount].name ));
-		if (len >= sizeof( Conf_Channel[chancount].name ))
+		if (!Handle_Channelname(chancount, Arg))
 			Config_Error_TooLong( Line, Var );
 		return;
 	}
@@ -945,6 +972,22 @@ Handle_CHANNEL( int Line, char *Var, char *Arg )
 		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 */
@@ -965,7 +1008,7 @@ Validate_Config(bool Configtest, bool Rehash)
 	do {
 		if (*ptr >= 'a' && *ptr <= 'z') continue;
 		if (*ptr >= 'A' && *ptr <= 'Z') continue;
-		if (*ptr >= '1' && *ptr <= '0') continue;
+		if (*ptr >= '0' && *ptr <= '9') continue;
 		if (ptr > Conf_ServerName) {
 			if (*ptr == '.' || *ptr == '-')
 				continue;

+ 5 - 1
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 2006/05/10 21:24:01 alex 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;
 
@@ -110,6 +112,8 @@ GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS];
 /* Pre-defined channels */
 GLOBAL CONF_CHANNEL Conf_Channel[MAX_DEFCHANNELS];
 GLOBAL unsigned int Conf_Channel_Count;
+/* Pre-defined channels only */
+GLOBAL bool Conf_PredefChannelsOnly;
 
 /* Are IRC operators allowed to always use MODE? */
 GLOBAL bool Conf_OperCanMode;

+ 4 - 4
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
 

+ 50 - 23
src/ngircd/conn-zip.c

@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2006 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
  *
  * 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
@@ -22,7 +22,7 @@
 /* enable more zlib related debug messages: */
 /* #define DEBUG_ZLIB */
 
-static char UNUSED id[] = "$Id: conn-zip.c,v 1.11 2006/07/23 15:19:20 alex Exp $";
+static char UNUSED id[] = "$Id: conn-zip.c,v 1.11.2.1 2007/05/18 22:11:19 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -82,47 +82,63 @@ Zip_InitConn( CONN_ID Idx )
 } /* Zip_InitConn */
 
 
+/**
+ * Copy data to the compression buffer of a connection. We do collect
+ * some data there until it's full so that we can achieve better
+ * compression ratios.
+ * If the (pre-)compression buffer is full, we try to flush it ("actually
+ * compress some data") and to add the new (uncompressed) data afterwards.
+ * @param Idx Connection handle.
+ * @param Data Pointer to the data.
+ * @param Len Length of the data to add.
+ * @return true on success, false otherwise. */
 GLOBAL bool
 Zip_Buffer( CONN_ID Idx, char *Data, size_t Len )
 {
-	/* Daten zum Komprimieren im "Kompressions-Puffer" sammeln.
-	* Es wird true bei Erfolg, sonst false geliefert. */
+	size_t buflen;
 
 	assert( Idx > NONE );
 	assert( Data != NULL );
 	assert( Len > 0 );
-	assert( Len <= ZWRITEBUFFER_LEN );
 
-	if (Len > ZWRITEBUFFER_LEN)
-		return false;
-
-	if ( array_bytes( &My_Connections[Idx].zip.wbuf ) >= ZWRITEBUFFER_LEN ) {
+	buflen = array_bytes(&My_Connections[Idx].zip.wbuf);
+	if (buflen + Len >= WRITEBUFFER_SLINK_LEN) {
 		/* compression buffer is full, flush */
 		if( ! Zip_Flush( Idx )) return false;
 	}
 
+	/* check again; if zip buf is still too large do not append data:
+	 * otherwise the zip wbuf would grow too large */
+	buflen = array_bytes(&My_Connections[Idx].zip.wbuf);
+	if (buflen + Len >= WRITEBUFFER_SLINK_LEN)
+		return false;
+
 	return array_catb(&My_Connections[Idx].zip.wbuf, Data, Len);
 } /* Zip_Buffer */
 
 
+/**
+ * Compress data in ZIP buffer and move result to the write buffer of
+ * the connection.
+ * @param Idx Connection handle.
+ * @retrun true on success, false otherwise.
+ */
 GLOBAL bool
 Zip_Flush( CONN_ID Idx )
 {
-	/* Daten komprimieren und in Schreibpuffer kopieren.
-	* Es wird true bei Erfolg, sonst false geliefert. */
-
 	int result;
-	unsigned char zipbuf[WRITEBUFFER_LEN];
+	unsigned char zipbuf[WRITEBUFFER_SLINK_LEN];
 	int zipbuf_used = 0;
 	z_stream *out;
 
 	out = &My_Connections[Idx].zip.out;
 
-	out->next_in = array_start(&My_Connections[Idx].zip.wbuf);
-	if (!out->next_in)
-		return false;
-
 	out->avail_in = (uInt)array_bytes(&My_Connections[Idx].zip.wbuf);
+	if (!out->avail_in)
+		return true;	/* nothing to do. */
+
+	out->next_in = array_start(&My_Connections[Idx].zip.wbuf);
+	assert(out->next_in != NULL);
 
 	out->next_out = zipbuf;
 	out->avail_out = (uInt)sizeof zipbuf;
@@ -139,14 +155,26 @@ Zip_Flush( CONN_ID Idx )
 		return false;
 	}
 
-	assert(out->avail_out <= WRITEBUFFER_LEN);
-	zipbuf_used = WRITEBUFFER_LEN - out->avail_out;
+	if (out->avail_out <= 0) {
+		/* Not all data was compressed, because data became
+		 * bigger while compressing it. */
+		Log (LOG_ALERT, "Compression error: buffer overvlow!?");
+		Conn_Close(Idx, "Compression error!", NULL, false);
+		return false;
+	}
+
+	assert(out->avail_out <= WRITEBUFFER_SLINK_LEN);
+
+	zipbuf_used = WRITEBUFFER_SLINK_LEN - out->avail_out;
 #ifdef DEBUG_ZIP
 	Log(LOG_DEBUG, "zipbuf_used: %d", zipbuf_used);
 #endif
 	if (!array_catb(&My_Connections[Idx].wbuf,
-			(char *)zipbuf, (size_t) zipbuf_used))
+			(char *)zipbuf, (size_t) zipbuf_used)) {
+		Log (LOG_ALERT, "Compression error: can't copy data!?");
+		Conn_Close(Idx, "Compression error!", NULL, false);
 		return false;
+	}
 
 	My_Connections[Idx].bytes_out += zipbuf_used;
 	My_Connections[Idx].zip.bytes_out += array_bytes(&My_Connections[Idx].zip.wbuf); 
@@ -178,10 +206,9 @@ Unzip_Buffer( CONN_ID Idx )
 		return true;
 
 	in = &My_Connections[Idx].zip.in;
-	
+
 	in->next_in = array_start(&My_Connections[Idx].zip.rbuf);
-	if (!in->next_in)
-		return false;
+	assert(in->next_in != NULL);
 
 	in->avail_in = z_rdatalen;
 	in->next_out = unzipbuf;

+ 108 - 94
src/ngircd/conn.c

@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2005 Alexander Barton <alex@barton.de>
+ * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
  *
  * 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
@@ -17,7 +17,7 @@
 #include "portab.h"
 #include "io.h"
 
-static char UNUSED id[] = "$Id: conn.c,v 1.198 2006/07/23 23:05:20 alex Exp $";
+static char UNUSED id[] = "$Id: conn.c,v 1.198.2.6 2007/05/18 22:11:19 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -83,6 +83,7 @@ static char UNUSED id[] = "$Id: conn.c,v 1.198 2006/07/23 23:05:20 alex Exp $";
 
 
 static bool Handle_Write PARAMS(( CONN_ID Idx ));
+static bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
 static int New_Connection PARAMS(( int Sock ));
 static CONN_ID Socket2Index PARAMS(( int Sock ));
 static void Read_Request PARAMS(( CONN_ID Idx ));
@@ -123,7 +124,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 +150,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 +377,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;
 	}
@@ -615,51 +608,74 @@ va_dcl
 } /* Conn_WriteStr */
 
 
-GLOBAL bool
+/**
+ * Append Data to the outbound write buffer of a connection.
+ * @param Idx Index of the connection.
+ * @param Data pointer to the data.
+ * @param Len length of Data.
+ * @return true on success, false otherwise.
+ */
+static bool
 Conn_Write( CONN_ID Idx, char *Data, size_t Len )
 {
-	/* Daten in Socket schreiben. Bei "fatalen" Fehlern wird
-	 * der Client disconnectiert und false geliefert. */
-
+	CLIENT *c;
+	size_t writebuf_limit = WRITEBUFFER_LEN;
 	assert( Idx > NONE );
 	assert( Data != NULL );
 	assert( Len > 0 );
 
-	/* Ist der entsprechende Socket ueberhaupt noch offen? In einem
-	 * "Handler-Durchlauf" kann es passieren, dass dem nicht mehr so
-	 * ist, wenn einer von mehreren Conn_Write()'s fehlgeschlagen ist.
-	 * In diesem Fall wird hier einfach ein Fehler geliefert. */
+	c = Conn_GetClient(Idx);
+	assert( c != NULL);
+
+	/* Servers do get special write buffer limits, so they can generate
+	 * all the messages that are required while peering. */
+	if (Client_Type(c) == CLIENT_SERVER)
+		writebuf_limit = WRITEBUFFER_SLINK_LEN;
+
+	/* Is the socket still open? A previous call to Conn_Write()
+	 * may have closed the connection due to a fatal error.
+	 * In this case it is sufficient to return an error, as well. */
 	if( My_Connections[Idx].sock <= NONE ) {
-		LogDebug("Skipped write on closed socket (connection %d).", Idx );
+		LogDebug("Skipped write on closed socket (connection %d).", Idx);
 		return false;
 	}
 
-	/* Pruefen, ob im Schreibpuffer genuegend Platz ist. Ziel ist es,
-	 * moeglichts viel im Puffer zu haben und _nicht_ gleich alles auf den
-	 * Socket zu schreiben (u.a. wg. Komprimierung). */
-	if( array_bytes(&My_Connections[Idx].wbuf) >= WRITEBUFFER_LEN) {
-		/* Der Puffer ist dummerweise voll. Jetzt versuchen, den Puffer
-		 * zu schreiben, wenn das nicht klappt, haben wir ein Problem ... */
-		if( ! Handle_Write( Idx )) return false;
-
-		/* check again: if our writebuf is twice als large as the initial limit: Kill connection */
-		if( array_bytes(&My_Connections[Idx].wbuf) >= (WRITEBUFFER_LEN*2)) {
-			Log( LOG_NOTICE, "Write buffer overflow (connection %d)!", Idx );
-			Conn_Close( Idx, "Write buffer overflow!", NULL, false );
-			return false;
-		}
-	}
-
 #ifdef ZLIB
 	if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
-		/* Daten komprimieren und in Puffer kopieren */
-		if( ! Zip_Buffer( Idx, Data, Len )) return false;
+		/* Compressed link:
+		 * Zip_Buffer() does all the dirty work for us: it flushes
+		 * the (pre-)compression buffers if required and handles
+		 * all error conditions. */
+		if (!Zip_Buffer(Idx, Data, Len))
+			return false;
 	}
 	else
 #endif
 	{
-		/* Daten in Puffer kopieren */
-		if (!array_catb( &My_Connections[Idx].wbuf, Data, Len ))
+		/* Uncompressed link:
+		 * Check if outbound buffer has enough space for the data. */
+		if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
+		    writebuf_limit) {
+			/* Buffer is full, flush it. Handle_Write deals with
+			 * low-level errors, if any. */
+			if (!Handle_Write(Idx))
+				return false;
+		}
+
+		/* When the write buffer is still too big after flushing it,
+		 * the connection will be killed. */
+		if (array_bytes(&My_Connections[Idx].wbuf) + Len >=
+		    writebuf_limit) {
+			Log(LOG_NOTICE,
+			    "Write buffer overflow (connection %d, size %lu byte)!",
+			    Idx,
+			    (unsigned long)array_bytes(&My_Connections[Idx].wbuf));
+			Conn_Close(Idx, "Write buffer overflow!", NULL, false);
+			return false;
+		}
+
+		/* Copy data to write buffer */
+		if (!array_catb(&My_Connections[Idx].wbuf, Data, Len))
 			return false;
 
 		My_Connections[Idx].bytes_out += Len;
@@ -700,7 +716,7 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
 
 	/* Mark link as "closing" */
 	Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING );
-		
+
 	if (LogMsg)
 		txt = LogMsg;
 	else
@@ -728,7 +744,6 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
 			 (double)My_Connections[Idx].bytes_out / 1024);
 		}
 #endif
-
 		/* Send ERROR to client (see RFC!) */
 		if (FwdMsg)
 			Conn_WriteStr(Idx, "ERROR :%s", FwdMsg);
@@ -872,24 +887,23 @@ Handle_Write( CONN_ID Idx )
 	wdatalen = array_bytes(&My_Connections[Idx].wbuf );
 
 #ifdef ZLIB
-	if (wdatalen == 0 && !array_bytes(&My_Connections[Idx].zip.wbuf)) {
-		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE );
-		return true;
+	if (wdatalen == 0) {
+		/* Write buffer is empty, so we try to flush the compression
+		 * buffer and get some data to work with from there :-) */
+		if (!Zip_Flush(Idx))
+			return false;
+
+		/* Now the write buffer most probably has changed: */
+		wdatalen = array_bytes(&My_Connections[Idx].wbuf);
 	}
+#endif
 
-	/* write buffer empty, but not compression buffer?
-         * -> flush compression buffer! */
-	if (wdatalen == 0)
-		Zip_Flush(Idx);
-#else
 	if (wdatalen == 0) {
+		/* Still no data, fine. */
 		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE );
 		return true;
 	}
-#endif
 
-	/* Zip_Flush() may have changed the write buffer ... */
-	wdatalen = array_bytes(&My_Connections[Idx].wbuf);
 	LogDebug
 	    ("Handle_Write() called for connection %d, %ld bytes pending ...",
 	     Idx, wdatalen);
@@ -995,11 +1009,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;
 	}
 
@@ -1008,13 +1030,6 @@ New_Connection( int 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 );
 
@@ -1050,47 +1065,52 @@ Socket2Index( int Sock )
 } /* Socket2Index */
 
 
+/**
+ * Read data from the network to the read buffer. If an error occures,
+ * the socket of this connection will be shut down.
+ */
 static void
 Read_Request( CONN_ID Idx )
 {
-	/* Daten von Socket einlesen und entsprechend behandeln.
-	 * Tritt ein Fehler auf, so wird der Socket geschlossen. */
-
 	ssize_t len;
-	char readbuf[1024];
+	char readbuf[READBUFFER_LEN];
 	CLIENT *c;
-
 	assert( Idx > NONE );
 	assert( My_Connections[Idx].sock > NONE );
 
 #ifdef ZLIB
-	if (( array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN ) ||
-		( array_bytes(&My_Connections[Idx].zip.rbuf) >= ZREADBUFFER_LEN ))
+	if ((array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN) ||
+		(array_bytes(&My_Connections[Idx].zip.rbuf) >= READBUFFER_LEN))
 #else
-	if ( array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN )
+	if (array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN)
 #endif
 	{
-		/* Der Lesepuffer ist voll */
-		Log( LOG_ERR, "Receive buffer overflow (connection %d): %d bytes!", Idx,
-						array_bytes(&My_Connections[Idx].rbuf));
+		/* Read buffer is full */
+		Log(LOG_ERR,
+		    "Receive buffer overflow (connection %d): %d bytes!",
+		    Idx, array_bytes(&My_Connections[Idx].rbuf));
 		Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
 		return;
 	}
 
-	len = read( My_Connections[Idx].sock, readbuf, sizeof readbuf -1 );
-	if( len == 0 ) {
-		Log( LOG_INFO, "%s:%d (%s) is closing the connection ...",
-			My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port),
-					inet_ntoa( My_Connections[Idx].addr.sin_addr ));
-		Conn_Close( Idx, "Socket closed!", "Client closed connection", false );
+	len = read(My_Connections[Idx].sock, readbuf, sizeof(readbuf));
+	if (len == 0) {
+		Log(LOG_INFO, "%s:%d (%s) is closing the connection ...",
+		    My_Connections[Idx].host,
+		    ntohs(My_Connections[Idx].addr.sin_port),
+		    inet_ntoa( My_Connections[Idx].addr.sin_addr));
+		Conn_Close(Idx,
+			   "Socket closed!", "Client closed connection",
+			   false);
 		return;
 	}
 
-	if( len < 0 ) {
+	if (len < 0) {
 		if( errno == EAGAIN ) return;
-		Log( LOG_ERR, "Read error on connection %d (socket %d): %s!", Idx,
-					My_Connections[Idx].sock, strerror( errno ));
-		Conn_Close( Idx, "Read error!", "Client closed connection", false );
+		Log(LOG_ERR, "Read error on connection %d (socket %d): %s!",
+		    Idx, My_Connections[Idx].sock, strerror(errno));
+		Conn_Close(Idx, "Read error!", "Client closed connection",
+			   false);
 		return;
 	}
 #ifdef ZLIB
@@ -1107,8 +1127,7 @@ Read_Request( CONN_ID Idx )
 	} else
 #endif
 	{
-		readbuf[len] = 0;
-		if (!array_cats( &My_Connections[Idx].rbuf, readbuf )) {
+		if (!array_catb( &My_Connections[Idx].rbuf, readbuf, len)) {
 			Log( LOG_ERR, "Could not append recieved data to input buffer (connn %d): %d bytes!", Idx, len );
 			Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
 		}
@@ -1227,11 +1246,6 @@ Handle_Buffer( CONN_ID Idx )
 			/* The last Command activated Socket-Compression.
 			 * Data that was read after that needs to be copied to Unzip-buf
 			 * for decompression */
-			if( array_bytes(&My_Connections[Idx].rbuf)> ZREADBUFFER_LEN ) {
-				Log( LOG_ALERT, "Connection %d: No space left in unzip buf (need %u bytes)!",
-								Idx, array_bytes(&My_Connections[Idx].rbuf ));
-				return false;
-			}
 			if (!array_copy( &My_Connections[Idx].zip.rbuf, &My_Connections[Idx].rbuf ))
 				return false;
 
@@ -1639,9 +1653,9 @@ Conn_GetClient( CONN_ID Idx )
 	assert( Idx >= 0 );
 
 	c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx);
-	
+
 	assert(c != NULL);
-	
+
 	return c ? c->client : NULL;
 }
 

+ 1 - 2
src/ngircd/conn.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: conn.h,v 1.42 2006/05/10 21:24:01 alex Exp $
+ * $Id: conn.h,v 1.42.2.1 2007/05/09 13:21:38 fw Exp $
  *
  * Connection management (header)
  */
@@ -88,7 +88,6 @@ GLOBAL void Conn_ExitListeners PARAMS(( void ));
 
 GLOBAL void Conn_Handler PARAMS(( void ));
 
-GLOBAL bool Conn_Write PARAMS(( CONN_ID Idx, char *Data, size_t Len ));
 GLOBAL bool Conn_WriteStr PARAMS(( CONN_ID Idx, char *Format, ... ));
 
 GLOBAL void Conn_Close PARAMS(( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ));

+ 4 - 9
src/ngircd/defines.h

@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2005 Alexander Barton (alex@barton.de)
+ * Copyright (c)2001-2007 Alexander Barton (alex@barton.de)
  *
  * 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,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: defines.h,v 1.58 2006/06/15 20:28:15 alex Exp $
+ * $Id: defines.h,v 1.58.2.1 2007/05/18 22:11:19 alex Exp $
  */
 
 
@@ -70,13 +70,8 @@
 					   connection in bytes. */
 #define WRITEBUFFER_LEN 4096		/* Size of the write buffer of a
 					   connection in bytes. */
-
-#ifdef ZLIB
-#define ZREADBUFFER_LEN 1024		/* Size of the compressed read buffer
-					   of a connection in bytes. */
-#define ZWRITEBUFFER_LEN 4096		/* Size of the compressed write buffer
-					   of a connection in bytes. */
-#endif
+#define WRITEBUFFER_SLINK_LEN 51200	/* Size of the write buffer of a
+					   server link connection in bytes. */
 
 #define PROTOVER "0210"			/* Implemented IRC protocol version,
 					   see RFC 2813 section 4.1.1. */

+ 2 - 2
src/ngircd/hash.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: hash.c,v 1.12 2005/07/31 20:13:08 alex Exp $";
+static char UNUSED id[] = "$Id: hash.c,v 1.12.2.1 2006/12/02 13:18:22 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -31,7 +31,7 @@ static UINT32 jenkins_hash PARAMS(( register UINT8 *k, register UINT32 length, r
 
 
 GLOBAL UINT32
-Hash( char *String )
+Hash( const char *String )
 {
 	/* Hash-Wert ueber String berechnen */
 

+ 2 - 3
src/ngircd/hash.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: hash.h,v 1.5 2005/03/19 18:43:48 fw Exp $
+ * $Id: hash.h,v 1.5.4.1 2006/12/02 13:18:22 fw Exp $
  *
  * Hash calculation (header)
  */
@@ -17,8 +17,7 @@
 #ifndef __hash_h__
 #define __hash_h__
 
-
-GLOBAL UINT32 Hash PARAMS((char *String ));
+GLOBAL UINT32 Hash PARAMS((const char *String ));
 
 
 #endif

+ 393 - 77
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 <assert.h>
 #include <stdlib.h>
@@ -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
-
-static bool library_initialized;
+#  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 = false;
 
 #ifdef IO_USE_EPOLL
 #include <sys/epoll.h>
 
-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 <poll.h>
+
+static array pollfds;
+static int poll_maxfd;
+
+static bool io_event_change_poll(int fd, short what);
+#endif
+
+#ifdef IO_USE_DEVPOLL
+#include <sys/devpoll.h>
+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;
-#endif
-#ifdef IO_USE_EPOLL
-	int ecreate_hint = (int)eventsize;
-	if (ecreate_hint <= 0)
-		ecreate_hint = 128;
+	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
-	if (library_initialized)
-		return true;
 
-#ifdef IO_USE_SELECT
-#ifdef FD_SETSIZE
-	if (eventsize >= FD_SETSIZE)
-		eventsize = FD_SETSIZE - 1;
-#endif
+
+#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;
+
+		library_initialized = true;
+	}
+}
 #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;
 
-	return ret;
-#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) (int, short))
 	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) (int, short))
 
 	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) (int, short))
 	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 action)
 		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,14 +884,21 @@ 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 */
 }

+ 2 - 2
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"

+ 24 - 13
src/ngircd/irc-channel.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-channel.c,v 1.35 2006/03/16 20:14:16 fw Exp $";
+static char UNUSED id[] = "$Id: irc-channel.c,v 1.35.2.4 2007/07/31 18:54:30 alex Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -52,7 +52,9 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 	assert( Req != NULL );
 
 	/* Bad number of arguments? */
-	if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+	if (Req->argc < 1 || Req->argc > 2)
+		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
+					  Client_ID(Client), Req->command);
 
 	/* Who is the sender? */
 	if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
@@ -78,8 +80,17 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 		chan = NULL; flags = NULL;
 
 		/* wird der Channel neu angelegt? */
-		if( Channel_Search( channame )) is_new_chan = false;
-		else is_new_chan = true;
+		if( Channel_Search( channame )) {
+			is_new_chan = false;
+		} else {
+			if (Conf_PredefChannelsOnly) { /* this server does not allow creation of channels */
+				IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
+				/* Try next name, if any */
+				channame = strchr(channame, ',');
+				continue;
+			}
+			is_new_chan = true;
+		}
 
 		/* Hat ein Server Channel-User-Modes uebergeben? */
 		if( Client_Type( Client ) == CLIENT_SERVER )
@@ -113,8 +124,8 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 				chan = Channel_Search( channame );
 				assert( chan != NULL );
 
-				is_banned = Lists_CheckBanned( target, chan );
-				is_invited = Lists_CheckInvited( target, chan );
+				is_banned = Lists_Check(Channel_GetListBans(chan), target );
+				is_invited = Lists_Check(Channel_GetListInvites(chan), target );
 
 				/* Testen, ob Client gebanned ist */
 				if(( is_banned == true) &&  ( is_invited == false ))
@@ -123,7 +134,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 					IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
 
 					/* Try next name, if any */
-					channame = strtok( NULL, "," );
+					channame = strchr(channame, ',');
 					continue;
 				}
 
@@ -134,7 +145,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 					IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
 
 					/* Try next name, if any */
-					channame = strtok( NULL, "," );
+					channame = strchr(channame, ',');
 					continue;
 				}
 
@@ -145,7 +156,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 					IRC_WriteStrClient( Client, ERR_BADCHANNELKEY_MSG, Client_ID( Client ), channame );
 
 					/* Try next name, if any */
-					channame = strtok( NULL, "," );
+					channame = strchr(channame, ',');
 					continue;
 				}
 
@@ -156,7 +167,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 					IRC_WriteStrClient( Client, ERR_CHANNELISFULL_MSG, Client_ID( Client ), channame );
 
 					/* Try next name, if any */
-					channame = strtok( NULL, "," );
+					channame = strchr(channame, ',');
 					continue;
 				}
 			}
@@ -169,14 +180,14 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 			 * commands) in this list become deleted when a user
 			 * joins a channel this way. */
 			chan = Channel_Search( channame );
-			if( chan != NULL ) (void)Lists_CheckInvited( target, chan );
+			if( chan != NULL ) (void)Lists_Check(Channel_GetListInvites(chan), target);
 		}
 
 		/* Channel joinen (und ggf. anlegen) */
 		if( ! Channel_Join( target, channame ))
 		{
 			/* naechsten Namen ermitteln */
-			channame = strtok( NULL, "," );
+			channame = strchr(channame, ',');
 			continue;
 		}
 		if( ! chan ) chan = Channel_Search( channame );
@@ -491,7 +502,7 @@ IRC_CHANINFO( CLIENT *Client, REQUEST *Req )
 			{
 				if( *ptr == 'l' )
 				{
-					snprintf( l, sizeof( l ), " %ld", Channel_MaxUsers( chan ));
+					snprintf( l, sizeof( l ), " %lu", Channel_MaxUsers( chan ));
 					strlcat( modes_add, l, sizeof( modes_add ));
 				}
 				if( *ptr == 'k' )

+ 17 - 5
src/ngircd/irc-info.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-info.c,v 1.33.2.1 2006/09/16 13:49:15 alex Exp $";
+static char UNUSED id[] = "$Id: irc-info.c,v 1.33.2.2 2006/12/02 14:26:53 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -542,7 +542,8 @@ GLOBAL bool
 IRC_WHO( CLIENT *Client, REQUEST *Req )
 {
 	bool ok, only_ops;
-	char flags[8], *ptr;
+	char flags[8];
+	const char *ptr;
 	CL2CHAN *cl2chan;
 	CHANNEL *chan, *cn;
 	CLIENT *c;
@@ -832,7 +833,10 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req )
 GLOBAL bool
 IRC_Send_LUSERS( CLIENT *Client )
 {
-	long cnt;
+	unsigned long cnt;
+#ifndef STRICT_RFC
+	unsigned long max;
+#endif
 
 	assert( Client != NULL );
 
@@ -861,9 +865,17 @@ IRC_Send_LUSERS( CLIENT *Client )
 
 #ifndef STRICT_RFC
 	/* Maximum number of local users */
-	if( ! IRC_WriteStrClient( Client, RPL_LOCALUSERS_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyMaxUserCount( ))) return DISCONNECTED;
+	cnt = Client_MyUserCount();
+	max = Client_MyMaxUserCount();
+	if (! IRC_WriteStrClient(Client, RPL_LOCALUSERS_MSG, Client_ID(Client),
+			cnt, max, cnt, max))
+		return DISCONNECTED;
 	/* Maximum number of users in the network */
-	if( ! IRC_WriteStrClient( Client, RPL_NETUSERS_MSG, Client_ID( Client ), Client_UserCount( ), Client_MaxUserCount( ))) return DISCONNECTED;
+	cnt = Client_UserCount();
+	max = Client_MaxUserCount();
+	if(! IRC_WriteStrClient(Client, RPL_NETUSERS_MSG, Client_ID(Client),
+			cnt, max, cnt, max))
+		return DISCONNECTED;
 #endif
 	
 	return CONNECTED;

+ 102 - 78
src/ngircd/irc-login.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-login.c,v 1.49 2005/09/01 10:51:24 alex Exp $";
+static char UNUSED id[] = "$Id: irc-login.c,v 1.49.2.2 2006/12/02 14:26:53 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -45,101 +45,119 @@ static bool Hello_User PARAMS(( CLIENT *Client ));
 static void Kill_Nick PARAMS(( char *Nick, char *Reason ));
 
 
+/**
+ * Handler for the IRC command "PASS".
+ * See RFC 2813 section 4.1.1, and RFC 2812 section 3.1.1.
+ */
 GLOBAL bool
 IRC_PASS( CLIENT *Client, REQUEST *Req )
 {
+	char *type, *orig_flags;
+	int protohigh, protolow;
+
 	assert( Client != NULL );
 	assert( Req != NULL );
 
-	/* Fehler liefern, wenn kein lokaler Client */
-	if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
+	/* Return an error if this is not a local client */
+	if (Client_Conn(Client) <= NONE)
+		return IRC_WriteStrClient(Client, ERR_UNKNOWNCOMMAND_MSG,
+					  Client_ID(Client), Req->command);
 	
-	if(( Client_Type( Client ) == CLIENT_UNKNOWN ) && ( Req->argc == 1))
-	{
-		/* noch nicht registrierte unbekannte Verbindung */
-		Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client_Conn( Client ));
-
-		/* Passwort speichern */
-		Client_SetPassword( Client, Req->argv[0] );
-
-		Client_SetType( Client, CLIENT_GOTPASS );
-		return CONNECTED;
+	if (Client_Type(Client) == CLIENT_UNKNOWN && Req->argc == 1) {
+		/* Not yet registered "unknown" connection, PASS with one
+		 * argument: either a regular client, service, or server
+		 * using the old RFC 1459 section 4.1.1 syntax. */
+		LogDebug("Connection %d: got PASS command ...",
+			 Client_Conn(Client));
+	} else if ((Client_Type(Client) == CLIENT_UNKNOWN ||
+		    Client_Type(Client) == CLIENT_UNKNOWNSERVER) &&
+		   (Req->argc == 3 || Req->argc == 4)) {
+		/* Not yet registered "unknown" connection or outgoing server
+		 * link, PASS with three or four argument: server using the
+		 * RFC 2813 section 4.1.1 syntax. */
+		LogDebug("Connection %d: got PASS command (new server link) ...",
+			 Client_Conn(Client));
+	} else if (Client_Type(Client) == CLIENT_UNKNOWN ||
+		   Client_Type(Client) == CLIENT_UNKNOWNSERVER) {
+		/* Unregistered connection, but wrong number of arguments: */
+		return IRC_WriteStrClient(Client, ERR_NEEDMOREPARAMS_MSG,
+					  Client_ID(Client), Req->command);
+	} else {
+		/* Registered connection, PASS command is not allowed! */
+		return IRC_WriteStrClient(Client, ERR_ALREADYREGISTRED_MSG,
+					  Client_ID(Client));
 	}
-	else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 )))
-	{
-		char c2, c4, *type, *impl, *serverver, *flags, *ptr, *ircflags;
-		int protohigh, protolow;
 
-		/* noch nicht registrierte Server-Verbindung */
-		Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client ));
+	Client_SetPassword(Client, Req->argv[0]);
+	Client_SetType(Client, CLIENT_GOTPASS);
 
-		/* Passwort speichern */
-		Client_SetPassword( Client, Req->argv[0] );
+	/* Protocol version */
+	if (Req->argc >= 2 && strlen(Req->argv[1]) >= 4) {
+		int c2, c4;
 
-		/* Protokollversion ermitteln */
-		if( strlen( Req->argv[1] ) >= 4 )
-		{
-			c2 = Req->argv[1][2];
-			c4 = Req->argv[1][4];
+		c2 = Req->argv[1][2];
+		c4 = Req->argv[1][4];
 
-			Req->argv[1][4] = '\0';
-			protolow = atoi( &Req->argv[1][2] );
-			Req->argv[1][2] = '\0';
-			protohigh = atoi( Req->argv[1] );
+		Req->argv[1][4] = '\0';
+		protolow = atoi(&Req->argv[1][2]);
+		Req->argv[1][2] = '\0';
+		protohigh = atoi(Req->argv[1]);
 			
-			Req->argv[1][2] = c2;
-			Req->argv[1][4] = c4;
-		}			
-		else protohigh = protolow = 0;
+		Req->argv[1][2] = c2;
+		Req->argv[1][4] = c4;
+	} else
+		protohigh = protolow = 0;
 
-		/* Protokoll-Typ */
-		if( strlen( Req->argv[1] ) > 4 ) type = &Req->argv[1][4];
-		else type = NULL;
+	/* Protocol type, see doc/Protocol.txt */
+	if (Req->argc >= 2 && strlen(Req->argv[1]) > 4)
+		type = &Req->argv[1][4];
+	else
+		type = NULL;
+	
+	/* Protocol flags/options */
+	if (Req->argc >= 4)
+		orig_flags = Req->argv[3];
+	else
+		orig_flags = "";
 
-		/* IRC-Flags (nach RFC 2813) */
-		if( Req->argc >= 4 ) ircflags = Req->argv[3];
-		else ircflags = "";
+	/* Implementation, version and IRC+ flags */
+	if (Req->argc >= 3) {
+		char *impl, *ptr, *serverver, *flags;
 
-		/* Implementation, Version und ngIRCd-Flags */
 		impl = Req->argv[2];
-		ptr = strchr( impl, '|' );
-		if( ptr ) *ptr = '\0';
+		ptr = strchr(impl, '|');
+		if (ptr)
+			*ptr = '\0';
 
-		if( type && ( strcmp( type, PROTOIRCPLUS ) == 0 ))
-		{
-			/* auf der anderen Seite laeuft ein Server, der
-			 * ebenfalls das IRC+-Protokoll versteht */
+		if (type && strcmp(type, PROTOIRCPLUS) == 0) {
+			/* The peer seems to be a server which supports the
+			 * IRC+ protocol (see doc/Protocol.txt). */
 			serverver = ptr + 1;
-			flags = strchr( serverver, ':' );
-			if( flags )
-			{
+			flags = strchr(serverver, ':');
+			if (flags) {
 				*flags = '\0';
 				flags++;
-			}
-			else flags = "";
-			Log( LOG_INFO, "Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", impl, serverver, protohigh, protolow, flags );
-		}
-		else
-		{
-			/* auf der anderen Seite laeuft ein Server, der
-			 * nur das Originalprotokoll unterstuetzt */
+			} else
+				flags = "";
+			Log(LOG_INFO,
+			    "Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").",
+			    impl, serverver, protohigh, protolow, flags);
+		} else {
+			/* The peer seems to be a server supporting the
+			 * "original" IRC protocol (RFC 2813). */
 			serverver = "";
-			if( strchr( ircflags, 'Z' )) flags = "Z";
-			else flags = "";
-			Log( LOG_INFO, "Peer announces itself as \"%s\" using protocol %d.%d (flags: \"%s\").", impl, protohigh, protolow, flags );
+			if (strchr(orig_flags, 'Z'))
+				flags = "Z";
+			else
+				flags = "";
+			Log(LOG_INFO,
+			    "Peer announces itself as \"%s\" using protocol %d.%d (flags: \"%s\").",
+			    impl, protohigh, protolow, flags);
 		}
-
-		Client_SetType( Client, CLIENT_GOTPASSSERVER );
-		Client_SetFlags( Client, flags );
-
-		return CONNECTED;
-	}
-	else if(( Client_Type( Client ) == CLIENT_UNKNOWN  ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER ))
-	{
-		/* Falsche Anzahl Parameter? */
-		return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
+		Client_SetFlags(Client, flags);
 	}
-	else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
+
+	return CONNECTED;
 } /* IRC_PASS */
 
 
@@ -268,13 +286,13 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
 						   "NICK :%s", Req->argv[0] );
 			IRC_WriteStrRelatedPrefix( target, target, false,
 						   "NICK :%s", Req->argv[0] );
-			
+
 			/* Register old nickname for WHOWAS queries */
 			Client_RegisterWhowas( target );
-				
+
 			/* Save new nickname */
 			Client_SetID( target, Req->argv[0] );
-			
+
 			IRC_SetPenalty( target, 2 );
 		}
 
@@ -598,9 +616,15 @@ Hello_User( CLIENT *Client )
 	if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, USERMODES, CHANMODES )) return false;
 #endif
 
-	/* Features */
-	if( ! IRC_WriteStrClient( Client, RPL_ISUPPORT_MSG, Client_ID( Client ), CLIENT_NICK_LEN - 1,
-			COMMAND_LEN - 23, CLIENT_AWAY_LEN - 1, Conf_MaxJoins )) return DISCONNECTED;
+	/* Features supported by this server (005 numeric, ISUPPORT),
+	 * see <http://www.irc.org/tech_docs/005.html> for details. */
+	if (! IRC_WriteStrClient(Client, RPL_ISUPPORT1_MSG, Client_ID(Client),
+			Conf_MaxJoins))
+		return DISCONNECTED;
+	if (! IRC_WriteStrClient(Client, RPL_ISUPPORT2_MSG, Client_ID(Client),
+			CHANNEL_NAME_LEN-1, CLIENT_NICK_LEN-1, COMMAND_LEN-23,
+			CLIENT_AWAY_LEN-1, COMMAND_LEN-113))
+		return DISCONNECTED;
 
 	Client_SetType( Client, CLIENT_USER );
 

+ 21 - 17
src/ngircd/irc-mode.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-mode.c,v 1.45 2006/05/10 21:24:01 alex Exp $";
+static char UNUSED id[] = "$Id: irc-mode.c,v 1.45.2.2 2007/04/03 20:23:31 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -69,7 +69,7 @@ IRC_MODE( CLIENT *Client, REQUEST *Req )
 		if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
 	}
 	else origin = Client;
-	
+
 	/* Channel or user mode? */
 	cl = NULL; chan = NULL;
 	if (Client_IsValidNick(Req->argv[0]))
@@ -268,7 +268,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
 			switch( *mode_ptr )
 			{
 				case 'l':
-					snprintf( argadd, sizeof( argadd ), " %ld", Channel_MaxUsers( Channel ));
+					snprintf( argadd, sizeof( argadd ), " %lu", Channel_MaxUsers( Channel ));
 					strlcat( the_args, argadd, sizeof( the_args ));
 					break;
 				case 'k':
@@ -477,7 +477,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
 					Req->argv[arg_arg][0] = '\0';
 					arg_arg++;
 				}
-				else Lists_ShowInvites( Origin, Channel );
+				else Channel_ShowInvites( Origin, Channel );
 				break;
 
 			case 'b': /* Ban lists */
@@ -493,7 +493,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
 					Req->argv[arg_arg][0] = '\0';
 					arg_arg++;
 				}
-				else Lists_ShowBans( Origin, Channel );
+				else Channel_ShowBans( Origin, Channel );
 				break;
 
 			default:
@@ -644,11 +644,13 @@ Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
 
 	mask = Lists_MakeMask( Pattern );
 
-	already = Lists_IsInviteEntry( mask, Channel );
-	
-	if( ! Lists_AddInvited( mask, Channel, false )) return CONNECTED;
-	
-	if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED;
+	already = Lists_CheckDupeMask(Channel_GetListInvites(Channel), mask );
+	if (!already) {
+		if( ! Channel_AddInvite(Channel, mask, false ))
+			return CONNECTED;
+	}
+	if ( already && ( Client_Type( Prefix ) == CLIENT_SERVER ))
+		return CONNECTED;
 
 	return Send_ListChange( "+I", Prefix, Client, Channel, mask );
 } /* Add_Invite */
@@ -666,11 +668,13 @@ Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
 
 	mask = Lists_MakeMask( Pattern );
 
-	already = Lists_IsBanEntry( mask, Channel );
-
-	if( ! Lists_AddBanned( mask, Channel )) return CONNECTED;
-
-	if(( Client_Type( Prefix ) == CLIENT_SERVER ) && ( already == true)) return CONNECTED;
+	already = Lists_CheckDupeMask(Channel_GetListBans(Channel), mask );
+	if (!already) {
+		if( ! Channel_AddBan(Channel, mask))
+			return CONNECTED;
+	}
+	if ( already && ( Client_Type( Prefix ) == CLIENT_SERVER ))
+		return CONNECTED;
 
 	return Send_ListChange( "+b", Prefix, Client, Channel, mask );
 } /* Add_Ban */
@@ -686,7 +690,7 @@ Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
 	assert( Pattern != NULL );
 
 	mask = Lists_MakeMask( Pattern );
-	Lists_DelInvited( mask, Channel );
+	Lists_Del(Channel_GetListInvites(Channel), mask);
 	return Send_ListChange( "-I", Prefix, Client, Channel, mask );
 } /* Del_Invite */
 
@@ -701,7 +705,7 @@ Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
 	assert( Pattern != NULL );
 
 	mask = Lists_MakeMask( Pattern );
-	Lists_DelBanned( mask, Channel );
+	Lists_Del(Channel_GetListBans(Channel), mask);
 	return Send_ListChange( "-b", Prefix, Client, Channel, mask );
 } /* Del_Ban */
 

+ 8 - 8
src/ngircd/irc-op.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-op.c,v 1.15 2005/04/27 07:39:18 alex Exp $";
+static char UNUSED id[] = "$Id: irc-op.c,v 1.15.4.2 2007/04/03 20:23:31 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -99,17 +99,17 @@ IRC_INVITE( CLIENT *Client, REQUEST *Req )
 		if( Channel_IsMemberOf( chan, target )) return IRC_WriteStrClient( from, ERR_USERONCHANNEL_MSG, Client_ID( from ), Req->argv[0], Req->argv[1] );
 
 		/* If the target user is banned on that channel: remember invite */
-		if( Lists_CheckBanned( target, chan )) remember = true;
+		if( Lists_Check(Channel_GetListBans(chan), target )) remember = true;
 
-		if( remember )
-		{
-			/* We must memember this invite */
-			if( ! Lists_AddInvited( Client_Mask( target ), chan, true)) return CONNECTED;
+		if (remember) {
+			/* We must remember this invite */
+			if( ! Channel_AddInvite(chan, Client_Mask( target ), true))
+				return CONNECTED;
 		}
 	}
 
-	Log( LOG_DEBUG, "User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask( from ), Req->argv[0], Req->argv[1] );
-	
+	LogDebug("User \"%s\" invites \"%s\" to \"%s\" ...", Client_Mask(from), Req->argv[0], Req->argv[1]);
+
 	/* Inform target client */
 	IRC_WriteStrClientPrefix( target, from, "INVITE %s %s", Req->argv[0], Req->argv[1] );
 

+ 66 - 11
src/ngircd/irc-server.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-server.c,v 1.39 2006/04/30 21:31:43 alex Exp $";
+static char UNUSED id[] = "$Id: irc-server.c,v 1.39.2.3 2007/04/03 20:23:31 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -41,6 +41,54 @@ static char UNUSED id[] = "$Id: irc-server.c,v 1.39 2006/04/30 21:31:43 alex Exp
 #include "irc-server.h"
 
 
+#ifdef IRCPLUS
+static bool
+Synchronize_Lists( CLIENT *Client )
+{
+	CHANNEL *c;
+	struct list_head *head;
+	struct list_elem *elem;
+
+	assert( Client != NULL );
+
+	c = Channel_First();
+
+	while (c) {
+		head = Channel_GetListBans(c);
+
+		elem = Lists_GetFirst(head);
+		while (elem) {
+			if( ! IRC_WriteStrClient( Client, "MODE %s +b %s",
+					Channel_Name(c), Lists_GetMask(elem)))
+			{
+				return false;
+			}
+			elem = Lists_GetNext(elem);
+		}
+
+		head = Channel_GetListInvites(c);
+		elem = Lists_GetFirst(head);
+		while (elem) {
+			if( ! IRC_WriteStrClient( Client, "MODE %s +I %s",
+					Channel_Name( c ), Lists_GetMask(elem)))
+			{
+				return false;
+			}
+			elem = Lists_GetNext(elem);
+		}
+		c = Channel_Next(c);
+	}
+	return true;
+}
+#endif
+
+
+
+
+/**
+ * Handler for the IRC command "SERVER".
+ * See RFC 2813 section 4.1.2.
+ */
 GLOBAL bool
 IRC_SERVER( CLIENT *Client, REQUEST *Req )
 {
@@ -55,13 +103,16 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
 	assert( Client != NULL );
 	assert( Req != NULL );
 
-	/* Fehler liefern, wenn kein lokaler Client */
-	if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
+	/* Return an error if this is not a local client */
+	if (Client_Conn(Client) <= NONE)
+		return IRC_WriteStrClient(Client, ERR_UNKNOWNCOMMAND_MSG,
+					  Client_ID(Client), Req->command);
 
-	if( Client_Type( Client ) == CLIENT_GOTPASSSERVER )
-	{
-		/* Verbindung soll als Server-Server-Verbindung registriert werden */
-		Log( LOG_DEBUG, "Connection %d: got SERVER command (new server link) ...", Client_Conn( Client ));
+	if (Client_Type(Client) == CLIENT_GOTPASS) {
+		/* We got a PASS command from the peer, and now a SERVER
+		 * command: the peer tries to register itself as a server. */
+		LogDebug("Connection %d: got SERVER command (new server link) ...",
+			Client_Conn(Client));
 
 		/* Falsche Anzahl Parameter? */
 		if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
@@ -207,7 +258,13 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
 					else
 					{
 						/* "CHANINFO <chan> +<modes> <key> <limit> :<topic>" */
-						if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s %s %ld :%s", Channel_Name( chan ), modes, strchr( Channel_Modes( chan ), 'k' ) ? Channel_Key( chan ) : "*", strchr( Channel_Modes( chan ), 'l' ) ? Channel_MaxUsers( chan ) : 0L, topic )) return DISCONNECTED;
+						if( ! IRC_WriteStrClient( Client, "CHANINFO %s +%s %s %lu :%s",
+							Channel_Name( chan ), modes,
+							strchr( Channel_Modes( chan ), 'k' ) ? Channel_Key( chan ) : "*",
+							strchr( Channel_Modes( chan ), 'l' ) ? Channel_MaxUsers( chan ) : 0UL, topic ))
+						{
+							return DISCONNECTED;
+						}
 					}
 				}
 			}
@@ -255,9 +312,7 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
 			    "Synchronizing INVITE- and BAN-lists ...");
 #endif
 			/* Synchronize INVITE- and BAN-lists */
-			if (! Lists_SendInvites(Client))
-				return DISCONNECTED;
-			if (! Lists_SendBans(Client))
+			if (!Synchronize_Lists(Client))
 				return DISCONNECTED;
 		}
 #endif

+ 5 - 5
src/ngircd/irc-write.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: irc-write.c,v 1.20 2006/05/10 21:24:01 alex Exp $";
+static char UNUSED id[] = "$Id: irc-write.c,v 1.20.2.1 2006/12/02 13:06:50 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -378,7 +378,7 @@ va_dcl
 			}
 			cl2chan = Channel_NextMember( chan, cl2chan );
 		}
-		
+
 		/* naechsten Channel */
 		chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
 	}
@@ -403,12 +403,12 @@ GLOBAL void
 IRC_SetPenalty( CLIENT *Client, time_t Seconds )
 {
 	CONN_ID c;
-	
+
 	assert( Client != NULL );
 	assert( Seconds > 0 );
-	
+
 	if( Client_Type( Client ) == CLIENT_SERVER ) return;
-	
+
 	c = Client_Conn( Client );
 	if (c > NONE)
 		Conn_SetPenalty(c, Seconds);

+ 91 - 338
src/ngircd/lists.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: lists.c,v 1.18 2005/07/31 20:13:08 alex 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 <assert.h>
@@ -35,326 +35,131 @@ static char UNUSED id[] = "$Id: lists.c,v 1.18 2005/07/31 20:13:08 alex Exp $";
 #include "exp.h"
 #include "lists.h"
 
+#define MASK_LEN	(2*CLIENT_HOST_LEN)
 
-#define MASK_LEN 2*CLIENT_HOST_LEN
-
-
-typedef struct _C2C
-{
-	struct _C2C *next;
+struct list_elem {
+	struct list_elem *next;
 	char mask[MASK_LEN];
-	CHANNEL *channel;
 	bool onlyonce;
-} C2C;
-
-
-static C2C *My_Invites, *My_Bans;
-
-
-static C2C *New_C2C PARAMS(( char *Mask, CHANNEL *Chan, bool OnlyOnce ));
+};
 
-static bool Check_List PARAMS(( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan ));
-static bool Already_Registered PARAMS(( C2C *Cl2Chan, char *Mask, CHANNEL *Chan ));
 
-
-
-GLOBAL void
-Lists_Init( void )
+GLOBAL const char *
+Lists_GetMask(const struct list_elem *e)
 {
-	/* Modul initialisieren */
-
-	My_Invites = My_Bans = NULL;
-} /* Lists_Init */
+	return e->mask;
+}
 
 
-GLOBAL void
-Lists_Exit( void )
+GLOBAL struct list_elem*
+Lists_GetFirst(const struct list_head *h)
 {
-	/* Modul abmelden */
-
-	C2C *c2c, *next;
-
-	/* Invite-Lists freigeben */
-	c2c = My_Invites;
-	while( c2c )
-	{
-		next = c2c->next;
-		free( c2c );
-		c2c = next;
-	}
+	return h->first;
+}
 
-	/* Ban-Lists freigeben */
-	c2c = My_Bans;
-	while( c2c )
-	{
-		next = c2c->next;
-		free( c2c );
-		c2c = next;
-	}
-} /* Lists_Exit */
 
-
-GLOBAL bool
-Lists_CheckInvited( CLIENT *Client, CHANNEL *Chan )
+GLOBAL struct list_elem*
+Lists_GetNext(const struct list_elem *e)
 {
-	return Check_List( &My_Invites, Client, Chan );
-} /* Lists_CheckInvited */
+	return e->next;
+}
 
 
-GLOBAL bool
-Lists_IsInviteEntry( char *Mask, CHANNEL *Chan )
+bool
+Lists_Add(struct list_head *header, const char *Mask, bool OnlyOnce )
 {
+	struct list_elem *e, *newelem;
+
+	assert( header != NULL );
 	assert( Mask != NULL );
-	assert( Chan != NULL );
-	
-	return Already_Registered( My_Invites, Mask, Chan );
-} /* Lists_IsInviteEntry */
 
+	if (Lists_CheckDupeMask(header, Mask )) return true;
 
-GLOBAL bool
-Lists_AddInvited( char *Mask, CHANNEL *Chan, bool OnlyOnce )
-{
-	C2C *c2c;
+	e = Lists_GetFirst(header);
 
-	assert( Mask != NULL );
-	assert( Chan != NULL );
-
-	if( Already_Registered( My_Invites, Mask, Chan )) return true;
-	
-	c2c = New_C2C( Mask, Chan, OnlyOnce );
-	if( ! c2c )
-	{
-		Log( LOG_ERR, "Can't add new invite list entry!" );
+	newelem = malloc(sizeof(struct list_elem));
+	if( ! newelem ) {
+		Log( LOG_EMERG, "Can't allocate memory for new Ban/Invite entry!" );
 		return false;
 	}
 
-	/* verketten */
-	c2c->next = My_Invites;
-	My_Invites = c2c;
+	strlcpy( newelem->mask, Mask, sizeof( newelem->mask ));
+	newelem->onlyonce = OnlyOnce;
+	newelem->next = e;
+	header->first = newelem;
 
-	Log( LOG_DEBUG, "Added \"%s\" to invite list for \"%s\".", Mask, Channel_Name( Chan ));
+	LogDebug("Added \"%s\" to invite list", Mask);
 	return true;
-} /* Lists_AddInvited */
-
-
-GLOBAL void
-Lists_DelInvited( char *Mask, CHANNEL *Chan )
-{
-	C2C *c2c, *last, *next;
-
-	assert( Mask != NULL );
-	assert( Chan != NULL );
-
-	last = NULL;
-	c2c = My_Invites;
-	while( c2c )
-	{
-		next = c2c->next;
-		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
-		{
-			/* dieser Eintrag muss geloescht werden */
-			Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
-			if( last ) last->next = next;
-			else My_Invites = next;
-			free( c2c );
-		}
-		else last = c2c;
-		c2c = next;
-	}
-} /* Lists_DelInvited */
-
-
-GLOBAL bool
-Lists_ShowInvites( CLIENT *Client, CHANNEL *Channel )
-{
-	C2C *c2c;
-
-	assert( Client != NULL );
-	assert( Channel != NULL );
-
-	c2c = My_Invites;
-	while( c2c )
-	{
-		if( c2c->channel == Channel )
-		{
-			/* Eintrag fuer Channel gefunden; ausgeben: */
-			if( ! IRC_WriteStrClient( Client, RPL_INVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
-		}
-		c2c = c2c->next;
-	}
-	return IRC_WriteStrClient( Client, RPL_ENDOFINVITELIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
-} /* Lists_ShowInvites */
-
-
-GLOBAL bool
-Lists_SendInvites( CLIENT *Client )
-{
-	C2C *c2c;
-	
-	assert( Client != NULL );
-	
-	c2c = My_Invites;
-	while( c2c )
-	{
-		if( ! IRC_WriteStrClient( Client, "MODE %s +I %s", Channel_Name( c2c->channel ), c2c->mask )) return DISCONNECTED;
-		c2c = c2c->next;
-	}
-	return CONNECTED;
-} /* Lists_SendInvites */
-
-
-GLOBAL bool
-Lists_SendBans( CLIENT *Client )
-{
-	C2C *c2c;
-	
-	assert( Client != NULL );
-	
-	c2c = My_Bans;
-	while( c2c )
-	{
-		if( ! IRC_WriteStrClient( Client, "MODE %s +b %s", Channel_Name( c2c->channel ), c2c->mask )) return DISCONNECTED;
-		c2c = c2c->next;
-	}
-	return CONNECTED;
-} /* Lists_SendBans */
-
-
-GLOBAL bool
-Lists_CheckBanned( CLIENT *Client, CHANNEL *Chan )
-{
-	return Check_List( &My_Bans, Client, Chan );
-} /* Lists_CheckBanned */
+}
 
 
-GLOBAL bool
-Lists_IsBanEntry( char *Mask, CHANNEL *Chan )
+static void
+Lists_Unlink(struct list_head *header, struct list_elem *p, struct list_elem *victim)
 {
-	assert( Mask != NULL );
-	assert( Chan != NULL );
-	
-	return Already_Registered( My_Bans, Mask, Chan );
-} /* Lists_IsBanEntry */
-
-
-GLOBAL bool
-Lists_AddBanned( char *Mask, CHANNEL *Chan )
-{
-	C2C *c2c;
-
-	assert( Mask != NULL );
-	assert( Chan != NULL );
+	assert(victim != NULL);
+	assert(header != NULL);
 
-	if( Already_Registered( My_Bans, Mask, Chan )) return true;
+	if (p) p->next = victim->next;
+	else header->first = victim->next;
 
-	c2c = New_C2C( Mask, Chan, false );
-	if( ! c2c )
-	{
-		Log( LOG_ERR, "Can't add new ban list entry!" );
-		return false;
-	}
-
-	/* verketten */
-	c2c->next = My_Bans;
-	My_Bans = c2c;
-
-	Log( LOG_DEBUG, "Added \"%s\" to ban list for \"%s\".", Mask, Channel_Name( Chan ));
-	return true;
-} /* Lists_AddBanned */
+	free(victim);
+}
 
 
 GLOBAL void
-Lists_DelBanned( char *Mask, CHANNEL *Chan )
+Lists_Del(struct list_head *header, const char *Mask)
 {
-	C2C *c2c, *last, *next;
+	struct list_elem *e, *last, *victim;
 
+	assert( header != NULL );
 	assert( Mask != NULL );
-	assert( Chan != NULL );
 
 	last = NULL;
-	c2c = My_Bans;
-	while( c2c )
-	{
-		next = c2c->next;
-		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 ))
-		{
-			/* dieser Eintrag muss geloescht werden */
-			Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
-			if( last ) last->next = next;
-			else My_Bans = next;
-			free( c2c );
+	e = Lists_GetFirst(header);
+	while( e ) {
+		if(strcasecmp( e->mask, Mask ) == 0 ) {
+			LogDebug("Deleted \"%s\" from list", e->mask);
+			victim = e;
+			e = victim->next;
+			Lists_Unlink(header, last, victim);
+			continue;
 		}
-		else last = c2c;
-		c2c = next;
+		last = e;
+		e = e->next;
 	}
-} /* Lists_DelBanned */
+}
 
 
-GLOBAL bool
-Lists_ShowBans( CLIENT *Client, CHANNEL *Channel )
+GLOBAL void
+Lists_Free(struct list_head *head)
 {
-	C2C *c2c;
+	struct list_elem *e, *victim;
 
-	assert( Client != NULL );
-	assert( Channel != NULL );
+	assert(head != NULL);
 
-	c2c = My_Bans;
-	while( c2c )
-	{
-		if( c2c->channel == Channel )
-		{
-			/* Eintrag fuer Channel gefunden; ausgeben: */
-			if( ! IRC_WriteStrClient( Client, RPL_BANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ), c2c->mask )) return DISCONNECTED;
-		}
-		c2c = c2c->next;
+	e = head->first;
+	head->first = NULL;
+	while (e) {
+		LogDebug("Deleted \"%s\" from invite list" , e->mask);
+		victim = e;
+		e = e->next;
+		free( victim );
 	}
-	return IRC_WriteStrClient( Client, RPL_ENDOFBANLIST_MSG, Client_ID( Client ), Channel_Name( Channel ));
-} /* Lists_ShowBans */
+}
 
 
-GLOBAL void
-Lists_DeleteChannel( CHANNEL *Chan )
+GLOBAL bool
+Lists_CheckDupeMask(const struct list_head *h, const char *Mask )
 {
-	/* Channel wurde geloescht, Invite- und Ban-Lists aufraeumen */
-
-	C2C *c2c, *last, *next;
-
-	/* Invite-List */
-	last = NULL;
-	c2c = My_Invites;
-	while( c2c )
-	{
-		next = c2c->next;
-		if( c2c->channel == Chan )
-		{
-			/* dieser Eintrag muss geloescht werden */
-			Log( LOG_DEBUG, "Deleted \"%s\" from invite list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
-			if( last ) last->next = next;
-			else My_Invites = next;
-			free( c2c );
-		}
-		else last = c2c;
-		c2c = next;
-	}
-
-	/* Ban-List */
-	last = NULL;
-	c2c = My_Bans;
-	while( c2c )
-	{
-		next = c2c->next;
-		if( c2c->channel == Chan )
-		{
-			/* dieser Eintrag muss geloescht werden */
-			Log( LOG_DEBUG, "Deleted \"%s\" from ban list for \"%s\"." , c2c->mask, Channel_Name( Chan ));
-			if( last ) last->next = next;
-			else My_Bans = next;
-			free( c2c );
-		}
-		else last = c2c;
-		c2c = next;
+	struct list_elem *e;
+	e = h->first;
+	while (e) {
+		if (strcasecmp( e->mask, Mask ) == 0 )
+			return true;
+		e = e->next;
 	}
-} /* Lists_DeleteChannel */
+	return false;
+}
 
 
 GLOBAL char *
@@ -407,82 +212,30 @@ Lists_MakeMask( char *Pattern )
 } /* Lists_MakeMask */
 
 
-static C2C *
-New_C2C( char *Mask, CHANNEL *Chan, bool OnlyOnce )
-{
-	C2C *c2c;
-	
-	assert( Mask != NULL );
-	assert( Chan != NULL );
-
-	/* Speicher fuer Eintrag anfordern */
-	c2c = (C2C *)malloc( sizeof( C2C ));
-	if( ! c2c )
-	{
-		Log( LOG_EMERG, "Can't allocate memory! [New_C2C]" );
-		return NULL;
-	}
-
-	strlcpy( c2c->mask, Mask, sizeof( c2c->mask ));
-	c2c->channel = Chan;
-	c2c->onlyonce = OnlyOnce;
-
-	return c2c;
-} /* New_C2C */
 
-
-static bool
-Check_List( C2C **Cl2Chan, CLIENT *Client, CHANNEL *Chan )
+bool
+Lists_Check( struct list_head *header, CLIENT *Client)
 {
-	C2C *c2c, *last;
+	struct list_elem *e, *last;
 
-	assert( Cl2Chan != NULL );
-	assert( Client != NULL );
-	assert( Chan != NULL );
+	assert( header != NULL );
 
-	c2c = *Cl2Chan;
+	e = header->first;
 	last = NULL;
 
-	while( c2c )
-	{
-		if( c2c->channel == Chan )
-		{
-			/* Ok, richtiger Channel. Passt die Maske? */
-			if( Match( c2c->mask, Client_Mask( Client )))
-			{
-				/* Treffer! */
-				if( c2c->onlyonce )
-				{
-					/* Eintrag loeschen */
-					Log( LOG_DEBUG, "Deleted \"%s\" from %s list for \"%s\".", c2c->mask, *Cl2Chan == My_Invites ? "invite" : "ban", Channel_Name( Chan ));
-					if( last ) last->next = c2c->next;
-					else *Cl2Chan = c2c->next;
-					free( c2c );
-				}
-				return true;
+	while( e ) {
+		if( Match( e->mask, Client_Mask( Client ))) {
+			if( e->onlyonce ) { /* delete entry */
+				LogDebug("Deleted \"%s\" from list", e->mask);
+				Lists_Unlink(header, last, e);
 			}
+			return true;
 		}
-		last = c2c;
-		c2c = c2c->next;
+		last = e;
+		e = e->next;
 	}
 
 	return false;
-} /* Check_List */
-
-
-static bool
-Already_Registered( C2C *List, char *Mask, CHANNEL *Chan )
-{
-	C2C *c2c;
-
-	c2c = List;
-	while( c2c )
-	{
-		if(( c2c->channel == Chan ) && ( strcasecmp( c2c->mask, Mask ) == 0 )) return true;
-		c2c = c2c->next;
-	}
-	return false;
-} /* Already_Registered */
-
+}
 
 /* -eof- */

+ 18 - 18
src/ngircd/lists.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: lists.h,v 1.12 2005/03/19 18:43:49 fw Exp $
+ * $Id: lists.h,v 1.12.4.1 2007/04/03 20:23:31 fw Exp $
  *
  * Management of IRC lists: ban, invite, ... (header)
  */
@@ -16,31 +16,31 @@
 
 #ifndef __lists_h__
 #define __lists_h__
+#include "portab.h"
+#include "client.h"
 
+struct list_elem;
 
-GLOBAL void Lists_Init PARAMS(( void ));
-GLOBAL void Lists_Exit PARAMS(( void ));
+struct list_head {
+	struct list_elem *first;
+};
 
-GLOBAL bool Lists_CheckInvited PARAMS(( CLIENT *Client, CHANNEL *Chan ));
-GLOBAL bool Lists_AddInvited PARAMS(( char *Mask, CHANNEL *Chan, bool OnlyOnce ));
-GLOBAL void Lists_DelInvited PARAMS(( char *Mask, CHANNEL *Chan ));
-GLOBAL bool Lists_ShowInvites PARAMS(( CLIENT *Client, CHANNEL *Channel ));
-GLOBAL bool Lists_SendInvites PARAMS(( CLIENT *Client ));
-GLOBAL bool Lists_IsInviteEntry PARAMS(( char *Mask, CHANNEL *Chan ));
 
-GLOBAL bool Lists_CheckBanned PARAMS(( CLIENT *Client, CHANNEL *Chan ));
-GLOBAL bool Lists_AddBanned PARAMS(( char *Mask, CHANNEL *Chan ));
-GLOBAL void Lists_DelBanned PARAMS(( char *Mask, CHANNEL *Chan ));
-GLOBAL bool Lists_ShowBans PARAMS(( CLIENT *Client, CHANNEL *Channel ));
-GLOBAL bool Lists_SendBans PARAMS(( CLIENT *Client ));
-GLOBAL bool Lists_IsBanEntry PARAMS(( char *Mask, CHANNEL *Chan ));
+GLOBAL struct list_elem *Lists_GetFirst PARAMS((const struct list_head *));
+GLOBAL struct list_elem *Lists_GetNext PARAMS((const struct list_elem *));
 
-GLOBAL void Lists_DeleteChannel PARAMS(( CHANNEL *Chan ));
+GLOBAL bool Lists_Check PARAMS((struct list_head *head, CLIENT *client ));
+GLOBAL bool Lists_CheckDupeMask PARAMS((const struct list_head *head, const char *mask ));
 
-GLOBAL char *Lists_MakeMask PARAMS(( char *Pattern ));
+GLOBAL bool Lists_Add PARAMS((struct list_head *header, const char *Mask, bool OnlyOnce ));
+GLOBAL void Lists_Del PARAMS((struct list_head *head, const char *Mask ));
 
+GLOBAL bool Lists_AlreadyRegistered PARAMS(( const struct list_head *head, const char *Mask));
 
-#endif
+GLOBAL void Lists_Free PARAMS(( struct list_head *head ));
 
+GLOBAL char *Lists_MakeMask PARAMS(( char *Pattern ));
+GLOBAL const char *Lists_GetMask PARAMS(( const struct list_elem *e ));
 
+#endif
 /* -eof- */

+ 5 - 14
src/ngircd/log.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: log.c,v 1.61 2006/07/23 23:23:45 alex Exp $";
+static char UNUSED id[] = "$Id: log.c,v 1.61.2.1 2006/12/02 13:02:07 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -166,25 +166,21 @@ Log_Exit( void )
  * Log function for debug messages.
  * This function is only functional when the program is compiled with debug
  * code enabled; otherwise it is an empty function which the compiler will
- * hopefully mangle down to "nothing". Therefore you should use LogDebug(...)
- * in favor to Log(LOG_DEBUG, ...).
+ * hopefully mangle down to "nothing" (see log.h). Therefore you should use
+ * LogDebug(...) in favor to Log(LOG_DEBUG, ...).
  * @param Format Format string like printf().
  * @param ... Further arguments.
  */
+#ifdef DEBUG
 # ifdef PROTOTYPES
 GLOBAL void
-#ifdef DEBUG
 LogDebug( const char *Format, ... )
-#else
-LogDebug( UNUSED const char *Format, ... )
-#endif /* DEBUG */
 # else
 GLOBAL void
 LogDebug( Format, va_alist )
 const char *Format;
 va_dcl
 # endif /* PROTOTYPES */
-#ifdef DEBUG
 {
 	char msg[MAX_LOG_MSG_LEN];
 	va_list ap;
@@ -199,14 +195,9 @@ va_dcl
 	va_end( ap );
 	Log(LOG_DEBUG, "%s", msg);
 }
-#else
-{
-	/* Do nothing.
-	 * The compiler should optimize this out, please ;-) */
-}
 #endif	/* DEBUG */
 
-	
+
 /**
  * Logging function of ngIRCd.
  * This function logs messages to the console and/or syslog, whichever is

+ 7 - 1
src/ngircd/log.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: log.h,v 1.19 2006/02/08 17:33:28 fw Exp $
+ * $Id: log.h,v 1.19.2.1 2006/12/02 13:02:07 fw Exp $
  *
  * Logging functions (header)
  */
@@ -39,7 +39,13 @@ GLOBAL void Log_Init PARAMS(( bool Daemon_Mode ));
 GLOBAL void Log_Exit PARAMS(( void ));
 
 GLOBAL void Log PARAMS(( int Level, const char *Format, ... ));
+
+#ifdef DEBUG
 GLOBAL void LogDebug PARAMS(( const char *Format, ... ));
+#else
+static inline void LogDebug PARAMS(( UNUSED const char *Format, ... )){/* Do nothing. The compiler should optimize this out, please ;-) */}
+#endif
+
 
 GLOBAL void Log_Init_Resolver PARAMS(( void ));
 GLOBAL void Log_Exit_Resolver PARAMS(( void ));

+ 6 - 6
src/ngircd/match.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: match.c,v 1.4 2005/07/31 20:13:08 alex Exp $";
+static char UNUSED id[] = "$Id: match.c,v 1.4.2.1 2006/12/02 13:01:11 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -32,8 +32,8 @@ static char UNUSED id[] = "$Id: match.c,v 1.4 2005/07/31 20:13:08 alex Exp $";
  */
 
 
-static int Matche PARAMS(( char *p, char *t ));
-static int Matche_After_Star PARAMS(( char *p, char *t ));
+static int Matche PARAMS(( const char *p, const char *t ));
+static int Matche_After_Star PARAMS(( const char *p, const char *t ));
 
 
 #define MATCH_PATTERN	6	/* bad pattern */
@@ -45,7 +45,7 @@ static int Matche_After_Star PARAMS(( char *p, char *t ));
 
 
 GLOBAL bool
-Match( char *Pattern, char *String )
+Match( const char *Pattern, const char *String )
 {
 	/* Pattern mit String vergleichen */
 	if( Matche( Pattern, String ) == MATCH_VALID ) return true;
@@ -54,7 +54,7 @@ Match( char *Pattern, char *String )
 
 
 static int
-Matche( char *p, char *t )
+Matche( const char *p, const char *t )
 {
 	register char range_start, range_end;
 	bool invert;
@@ -201,7 +201,7 @@ Matche( char *p, char *t )
 
 
 static int
-Matche_After_Star( char *p, char *t )
+Matche_After_Star( const char *p, const char *t )
 {
 	register int nextp, match = 0;
 

+ 2 - 2
src/ngircd/match.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: match.h,v 1.3 2005/03/19 18:43:49 fw Exp $
+ * $Id: match.h,v 1.3.4.1 2006/12/02 13:01:11 fw Exp $
  *
  * Wildcard pattern matching (header)
  */
@@ -18,7 +18,7 @@
 #define __match_h__
 
 
-GLOBAL bool Match PARAMS(( char *Pattern, char *String ));
+GLOBAL bool Match PARAMS(( const char *Pattern, const char *String ));
 
 
 #endif

+ 9 - 8
src/ngircd/messages.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  *
- * $Id: messages.h,v 1.67 2005/09/02 12:50:25 alex Exp $
+ * $Id: messages.h,v 1.67.2.2 2006/12/02 14:26:53 fw Exp $
  *
  * IRC numerics (Header)
  */
@@ -22,7 +22,8 @@
 #define RPL_YOURHOST_MSG		"002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)"
 #define RPL_CREATED_MSG			"003 %s :This server has been started %s"
 #define RPL_MYINFO_MSG			"004 %s %s ngircd-%s %s %s"
-#define RPL_ISUPPORT_MSG		"005 %s NICKLEN=%d TOPICLEN=%d AWAYLEN=%d MAXCHANNELS=%d :are supported on this server"
+#define RPL_ISUPPORT1_MSG		"005 %s RFC2812 CASEMAPPING=ascii PREFIX=(ov)@+ CHANTYPES=# CHANMODES=bI,k,l,imnPst CHANLIMIT=#:%d :are supported on this server"
+#define RPL_ISUPPORT2_MSG		"005 %s CHANNELLEN=%d NICKLEN=%d TOPICLEN=%d AWAYLEN=%d KICKLEN=%d PENALTY :are supported on this server"
 
 #define RPL_TRACELINK_MSG		"200 %s Link %s-%s %s %s V%s %ld %d %d"
 #define RPL_TRACEOPERATOR_MSG		"204 %s Oper 2 :%s"
@@ -32,17 +33,17 @@
 #define RPL_ENDOFSTATS_MSG		"219 %s %c :End of STATS report"
 #define RPL_UMODEIS_MSG			"221 %s +%s"
 #define RPL_LUSERCLIENT_MSG		"251 %s :There are %ld users and %ld services on %ld servers"
-#define RPL_LUSEROP_MSG			"252 %s %ld :operator(s) online"
-#define RPL_LUSERUNKNOWN_MSG		"253 %s %ld :unknown connection(s)"
-#define RPL_LUSERCHANNELS_MSG		"254 %s %ld :channels formed"
-#define RPL_LUSERME_MSG			"255 %s :I have %ld users, %ld services and %ld servers"
+#define RPL_LUSEROP_MSG			"252 %s %lu :operator(s) online"
+#define RPL_LUSERUNKNOWN_MSG		"253 %s %lu :unknown connection(s)"
+#define RPL_LUSERCHANNELS_MSG		"254 %s %lu :channels formed"
+#define RPL_LUSERME_MSG			"255 %s :I have %lu users, %lu services and %lu servers"
 #define RPL_ADMINME_MSG			"256 %s %s :Administrative info"
 #define RPL_ADMINLOC1_MSG		"257 %s :%s"
 #define RPL_ADMINLOC2_MSG		"258 %s :%s"
 #define RPL_ADMINEMAIL_MSG		"259 %s :%s"
 #define RPL_TRACEEND_MSG		"262 %s %s %s-%s.%s :End of TRACE"
-#define RPL_LOCALUSERS_MSG		"265 %s :Current local users: %ld, Max: %ld"
-#define RPL_NETUSERS_MSG		"266 %s :Current global users: %ld, Max: %ld"
+#define RPL_LOCALUSERS_MSG		"265 %s %lu %lu :Current local users: %lu, Max: %lu"
+#define RPL_NETUSERS_MSG		"266 %s %lu %lu :Current global users: %lu, Max: %lu"
 
 #define RPL_AWAY_MSG			"301 %s %s :%s"
 #define RPL_USERHOST_MSG		"302 %s :"

+ 3 - 5
src/ngircd/ngircd.c

@@ -1,6 +1,6 @@
 /*
  * ngIRCd -- The Next Generation IRC Daemon
- * Copyright (c)2001-2006 Alexander Barton (alex@barton.de).
+ * Copyright (c)2001-2007 Alexander Barton (alex@barton.de).
  *
  * 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
@@ -12,7 +12,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: ngircd.c,v 1.113 2006/07/23 12:07:33 alex Exp $";
+static char UNUSED id[] = "$Id: ngircd.c,v 1.113.2.2 2007/05/05 20:25:47 alex Exp $";
 
 /**
  * @file
@@ -271,7 +271,6 @@ main( int argc, const char *argv[] )
 
 		/* Initialize modules, part II: these functions are eventually
 		 * called with already dropped privileges ... */
-		Lists_Init( );
 		Channel_Init( );
 		Client_Init( );
 #ifdef ZEROCONF
@@ -328,7 +327,6 @@ main( int argc, const char *argv[] )
 #endif
 		Client_Exit( );
 		Channel_Exit( );
-		Lists_Exit( );
 		Log_Exit( );
 	}
 	Pidfile_Delete( );
@@ -548,7 +546,7 @@ static void
 Show_Version( void )
 {
 	puts( NGIRCd_Version );
-	puts( "Copyright (c)2001-2006 Alexander Barton (<alex@barton.de>) and Contributors." );
+	puts( "Copyright (c)2001-2007 Alexander Barton (<alex@barton.de>) and Contributors." );
 	puts( "Homepage: <http://ngircd.barton.de/>\n" );
 	puts( "This is free software; see the source for copying conditions. There is NO" );
 	puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." );

+ 10 - 18
src/ngircd/resolve.c

@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: resolve.c,v 1.24 2006/05/10 21:24:01 alex Exp $";
+static char UNUSED id[] = "$Id: resolve.c,v 1.24.2.2 2006/12/17 22:59:56 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -313,7 +313,8 @@ register_callback( RES_STAT *s, void (*cbfunc)(int, short))
 			return true;
 
 	Log( LOG_CRIT, "Resolver: Could not register callback function: %s!", strerror(errno));
-	Resolve_Shutdown(s);
+	close(s->resolver_fd);
+	Resolve_Init(s);
 	return false;
 }
 
@@ -333,40 +334,31 @@ Resolve_Shutdown( RES_STAT *s)
 	return ret;
 }
 
-                
+
 /**
  * Read result of resolver sub-process from pipe
  */
 GLOBAL size_t
 Resolve_Read( RES_STAT *s, void* readbuf, size_t buflen)
 {
-	int err;
 	ssize_t bytes_read;
 
 	assert(buflen > 0);
 
 	/* Read result from pipe */
-	errno = 0;
 	bytes_read = read(s->resolver_fd, readbuf, buflen);
 	if (bytes_read < 0) {
-		if (errno != EAGAIN) {
-			err = errno;
-			Log( LOG_CRIT, "Resolver: Can't read result: %s!", strerror(err));
-			Resolve_Shutdown(s);
-			errno = err;
+		if (errno == EAGAIN)
 			return 0;
-		}
-		return 0;
-	}
 
-	Resolve_Shutdown(s);
-	if (bytes_read == 0) {	/* EOF: lookup failed */
+		Log( LOG_CRIT, "Resolver: Can't read result: %s!", strerror(errno));
+		bytes_read = 0;
+	}
 #ifdef DEBUG
+	else if (bytes_read == 0)
 		Log( LOG_DEBUG, "Resolver: Can't read result: EOF");
 #endif
-		return 0;
-	}
-
+	Resolve_Shutdown(s);
 	return (size_t)bytes_read;
 }
 /* -eof- */

+ 10 - 5
src/testsuite/getpid.sh

@@ -1,16 +1,17 @@
 #!/bin/sh
 # ngIRCd Test Suite
-# $Id: getpid.sh,v 1.4 2003/08/22 11:31:18 alex Exp $
+# $Id: getpid.sh,v 1.4.6.1 2006/12/17 13:49:49 alex Exp $
 
 # did we get a name?
 [ $# -ne 1 ] && exit 1
 
 # detect flags for "ps" and "head"
-if [ `uname` = "FreeBSD" ]; then
+UNAME=`uname`
+if [ $UNAME = "FreeBSD" -o $UNAME = "SunOS" ]; then
   PS_FLAGS="-a"; PS_PIDCOL="1"; HEAD_FLAGS="-n 1"
-elif [ `uname` = "A/UX" ]; then
+elif [ $UNAME = "A/UX" ]; then
   PS_FLAGS="-ae"; PS_PIDCOL="1"; HEAD_FLAGS="-1"
-elif [ `uname` = "GNU" ]; then
+elif [ $UNAME = "GNU" ]; then
   PS_FLAGS="-ax"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
 else
   PS_FLAGS="-f"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
@@ -19,13 +20,17 @@ else
 fi
 
 # debug output
+#echo "$0: UNAME=$UNAME"
 #echo "$0: PS_FLAGS=$PS_FLAGS"
 #echo "$0: PS_PIDCOL=$PS_PIDCOL"
 #echo "$0: HEAD_FLAGS=$HEAD_FLAGS"
 
 # search PID
 ps $PS_FLAGS > procs.tmp
-cat procs.tmp | grep -v "$0" | grep "$1" | awk "{print \$$PS_PIDCOL}" | sort -n > pids.tmp
+cat procs.tmp | \
+  grep -v "$0" | grep "$1" | \
+  awk "{print \$$PS_PIDCOL}" | \
+  sort -n > pids.tmp
 pid=`head $HEAD_FLAGS pids.tmp`
 rm -rf procs.tmp pids.tmp