ソースを参照

Import upstream version 0.10.3

Alexander Barton 17 年 前
コミット
88b8fe8f93

+ 35 - 2
ChangeLog

@@ -1,7 +1,7 @@
 
 
                      ngIRCd - Next Generation IRC Server
                      ngIRCd - Next Generation IRC Server
 
 
-                        (c)2001-2006 Alexander Barton,
+                        (c)2001-2007 Alexander Barton,
                     alex@barton.de, http://www.barton.de/
                     alex@barton.de, http://www.barton.de/
 
 
                ngIRCd is free software and published under the
                ngIRCd is free software and published under the
@@ -10,6 +10,39 @@
                                -- ChangeLog --
                                -- 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)
 ngIRCd 0.10.0 (2006-10-01)
 
 
   - Fixed file handle leak when daemon is not able to send MOTD to a client.
   - 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.
   The Z compression library ("libz") is required for this option.
   
   
 * IO Backend (autodetected by default):
 * 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-epoll[=<path>] / --without-epoll
   --with-kqueue[=<path>] / --without-kqueue  
   --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
   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"
   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:
 * IDENT-Support:
   --with-ident[=<path>]
   --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
                      ngIRCd - Next Generation IRC Server
 
 
-                        (c)2001-2006 Alexander Barton,
+                        (c)2001-2007 Alexander Barton,
                     alex@barton.de, http://www.barton.de/
                     alex@barton.de, http://www.barton.de/
 
 
                ngIRCd is free software and published under the
                ngIRCd is free software and published under the
@@ -10,6 +10,20 @@
                                   -- NEWS --
                                   -- 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 (2006-10-01)
 
 
   ngIRCd 0.10.0-pre1 (2006-08-02)
   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
                      ngIRCd - Next Generation IRC Server
 
 
-                        (c)2001-2006 Alexander Barton,
+                        (c)2001-2007 Alexander Barton,
                     alex@barton.de, http://www.barton.de/
                     alex@barton.de, http://www.barton.de/
 
 
                ngIRCd is free software and published under the
                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
 generation IRC daemon", it's written from scratch and not deduced from the
 "grandfather of IRC daemons", the daemon of the IRCNet.
 "grandfather of IRC daemons", the daemon of the IRCNet.
 
 
+Please see the INSTALL document for installation and upgrade information!
+
 
 
 II. Status
 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
 #! /bin/sh
 # Attempt to guess a canonical system name.
 # Attempt to guess a canonical system name.
 #   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
 #   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
 # 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
 # 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 ;;
 	    arm*) machine=arm-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3el) machine=shl-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
 	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
 	esac
 	esac
 	# The Operating System including object format, if it has switched
 	# 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}
 	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
 	exit ;;
 	exit ;;
     macppc:MirBSD:*:*)
     macppc:MirBSD:*:*)
-	echo powerppc-unknown-mirbsd${UNAME_RELEASE}
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
 	exit ;;
 	exit ;;
     *:MirBSD:*:*)
     *:MirBSD:*:*)
 	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
 	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
@@ -770,6 +772,8 @@ EOF
 	case ${UNAME_MACHINE} in
 	case ${UNAME_MACHINE} in
 	    pc98)
 	    pc98)
 		echo i386-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 		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/[-(].*//'` ;;
 		echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'` ;;
 	esac
 	esac
@@ -777,10 +781,7 @@ EOF
     i*:CYGWIN*:*)
     i*:CYGWIN*:*)
 	echo ${UNAME_MACHINE}-pc-cygwin
 	echo ${UNAME_MACHINE}-pc-cygwin
 	exit ;;
 	exit ;;
-    i*:MINGW*:*)
-	echo ${UNAME_MACHINE}-pc-mingw32
-	exit ;;
-    i*:MSYS_NT-*:*:*)
+    *:MINGW*:*)
 	echo ${UNAME_MACHINE}-pc-mingw32
 	echo ${UNAME_MACHINE}-pc-mingw32
 	exit ;;
 	exit ;;
     i*:windows32*:*)
     i*:windows32*:*)
@@ -790,12 +791,15 @@ EOF
     i*:PW*:*)
     i*:PW*:*)
 	echo ${UNAME_MACHINE}-pc-pw32
 	echo ${UNAME_MACHINE}-pc-pw32
 	exit ;;
 	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:*)
     [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
 	echo i${UNAME_MACHINE}-pc-mks
 	echo i${UNAME_MACHINE}-pc-mks
 	exit ;;
 	exit ;;
@@ -831,6 +835,9 @@ EOF
     arm*:Linux:*:*)
     arm*:Linux:*:*)
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	echo ${UNAME_MACHINE}-unknown-linux-gnu
 	exit ;;
 	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-gnu
+	exit ;;
     cris:Linux:*:*)
     cris:Linux:*:*)
 	echo cris-axis-linux-gnu
 	echo cris-axis-linux-gnu
 	exit ;;
 	exit ;;
@@ -947,6 +954,9 @@ EOF
     x86_64:Linux:*:*)
     x86_64:Linux:*:*)
 	echo x86_64-unknown-linux-gnu
 	echo x86_64-unknown-linux-gnu
 	exit ;;
 	exit ;;
+    xtensa:Linux:*:*)
+    	echo xtensa-unknown-linux-gnu
+	exit ;;
     i*86:Linux:*:*)
     i*86:Linux:*:*)
 	# The BFD linker knows what the default object file format is, so
 	# 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
 	# first see if it will tell us. cd to the root directory to prevent
@@ -989,7 +999,7 @@ EOF
 	LIBC=gnulibc1
 	LIBC=gnulibc1
 	# endif
 	# endif
 	#else
 	#else
-	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__sun)
+	#if defined(__INTEL_COMPILER) || defined(__PGI) || defined(__SUNPRO_C) || defined(__SUNPRO_CC)
 	LIBC=gnu
 	LIBC=gnu
 	#else
 	#else
 	LIBC=gnuaout
 	LIBC=gnuaout
@@ -1205,6 +1215,15 @@ EOF
     SX-6:SUPER-UX:*:*)
     SX-6:SUPER-UX:*:*)
 	echo sx6-nec-superux${UNAME_RELEASE}
 	echo sx6-nec-superux${UNAME_RELEASE}
 	exit ;;
 	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:*:*)
     Power*:Rhapsody:*:*)
 	echo powerpc-apple-rhapsody${UNAME_RELEASE}
 	echo powerpc-apple-rhapsody${UNAME_RELEASE}
 	exit ;;
 	exit ;;

+ 41 - 27
config.sub

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

ファイルの差分が大きいため隠しています
+ 858 - 227
configure


+ 107 - 18
configure.in

@@ -1,6 +1,6 @@
 #
 #
 # ngIRCd -- The Next Generation IRC Daemon
 # 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
 # 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
 # it under the terms of the GNU General Public License as published by
@@ -8,13 +8,13 @@
 # (at your option) any later version.
 # (at your option) any later version.
 # Please read the file COPYING, README and AUTHORS for more information.
 # 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 --
 # -- Initialisation --
 
 
 AC_PREREQ(2.50)
 AC_PREREQ(2.50)
-AC_INIT(ngircd, 0.10.0)
+AC_INIT(ngircd, 0.10.3)
 AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
 AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
 AC_CANONICAL_TARGET
 AC_CANONICAL_TARGET
 AM_INIT_AUTOMAKE(1.6)
 AM_INIT_AUTOMAKE(1.6)
@@ -53,6 +53,7 @@ AC_PROG_RANLIB
 
 
 AM_C_PROTOTYPES
 AM_C_PROTOTYPES
 AC_C_CONST
 AC_C_CONST
+AC_C_INLINE
 
 
 # -- Hard coded system and compiler dependencies/features/options ... --
 # -- Hard coded system and compiler dependencies/features/options ... --
 
 
@@ -137,17 +138,15 @@ AC_FUNC_STRFTIME
 
 
 AC_CHECK_FUNCS([ \
 AC_CHECK_FUNCS([ \
 	bind gethostbyaddr gethostbyname gethostname inet_ntoa malloc memmove \
 	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!]))
 	strstr waitpid],,AC_MSG_ERROR([required function missing!]))
 
 
 AC_CHECK_FUNCS(inet_aton isdigit sigaction snprintf vsnprintf strdup strlcpy strlcat)
 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 --
 # -- Configuration options --
 
 
+# use syslog?
+
 x_syslog_on=no
 x_syslog_on=no
 AC_ARG_WITH(syslog,
 AC_ARG_WITH(syslog,
 	[  --without-syslog        disable syslog (autodetected by default)],
 	[  --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!]))
 	AC_CHECK_HEADERS(syslog.h,,AC_MSG_ERROR([required C header missing!]))
 fi
 fi
 
 
+# use zlib compression?
+
 x_zlib_on=no
 x_zlib_on=no
 AC_ARG_WITH(zlib,
 AC_ARG_WITH(zlib,
 	[  --without-zlib          disable zlib compression (autodetected by default)],
 	[  --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!]))
 	AC_CHECK_HEADERS(zlib.h,,AC_MSG_ERROR([required C header missing!]))
 fi
 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,
 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" != "no"; then
 			if test "$withval" != "yes"; then
 			if test "$withval" != "yes"; then
 				CFLAGS="-I$withval/include $CFLAGS"
 				CFLAGS="-I$withval/include $CFLAGS"
 				CPPFLAGS="-I$withval/include $CPPFLAGS"
 				CPPFLAGS="-I$withval/include $CPPFLAGS"
 				LDFLAGS="-L$withval/lib $LDFLAGS"
 				LDFLAGS="-L$withval/lib $LDFLAGS"
 			fi
 			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
 		fi
 	],
 	],
 	[
 	[
-		AC_CHECK_FUNCS(epoll_create, x_io_backend=epoll)
+		AC_CHECK_FUNCS(epoll_create, x_io_epoll=yes)
 	]
 	]
 )
 )
 
 
 AC_ARG_WITH(kqueue,
 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" != "no"; then
 			if test "$withval" != "yes"; then
 			if test "$withval" != "yes"; then
 				CFLAGS="-I$withval/include $CFLAGS"
 				CFLAGS="-I$withval/include $CFLAGS"
 				CPPFLAGS="-I$withval/include $CPPFLAGS"
 				CPPFLAGS="-I$withval/include $CPPFLAGS"
 				LDFLAGS="-L$withval/lib $LDFLAGS"
 				LDFLAGS="-L$withval/lib $LDFLAGS"
 			fi
 			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
 		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
 x_tcpwrap_on=no
 AC_ARG_WITH(tcp-wrappers,
 AC_ARG_WITH(tcp-wrappers,
@@ -265,6 +342,8 @@ int deny_severity = 0;
 	]
 	]
 )
 )
 
 
+# include support for "zeroconf"?
+
 x_zeroconf_on=no
 x_zeroconf_on=no
 AC_ARG_WITH(zeroconf,
 AC_ARG_WITH(zeroconf,
 	[  --with-zeroconf         enable support for "Zeroconf"],
 	[  --with-zeroconf         enable support for "Zeroconf"],
@@ -313,6 +392,8 @@ if test "$x_zeroconf_on" = "howl"; then
 	AC_DEFINE(ZEROCONF, 1)
 	AC_DEFINE(ZEROCONF, 1)
 fi
 fi
 
 
+# do IDENT requests using libident?
+
 x_identauth_on=no
 x_identauth_on=no
 AC_ARG_WITH(ident,
 AC_ARG_WITH(ident,
 	[  --with-ident            enable "IDENT" ("AUTH") protocol support],
 	[  --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!]))
 	AC_CHECK_HEADERS(ident.h,,AC_MSG_ERROR([required C header missing!]))
 fi
 fi
 
 
+# compile in IRC+ protocol support?
+
 x_ircplus_on=yes
 x_ircplus_on=yes
 AC_ARG_ENABLE(ircplus,
 AC_ARG_ENABLE(ircplus,
 	[  --disable-ircplus       disable IRC+ protocol],
 	[  --disable-ircplus       disable IRC+ protocol],
@@ -343,6 +426,8 @@ if test "$x_ircplus_on" = "yes"; then
 	AC_DEFINE(IRCPLUS, 1)
 	AC_DEFINE(IRCPLUS, 1)
 fi
 fi
 
 
+# compile in IRC "sniffer"?
+
 x_sniffer_on=no; x_debug_on=no
 x_sniffer_on=no; x_debug_on=no
 AC_ARG_ENABLE(sniffer,
 AC_ARG_ENABLE(sniffer,
 	[  --enable-sniffer        enable IRC traffic sniffer (enables debug mode)],
 	[  --enable-sniffer        enable IRC traffic sniffer (enables debug mode)],
@@ -352,6 +437,8 @@ AC_ARG_ENABLE(sniffer,
 	fi
 	fi
 )
 )
 
 
+# enable additional debugging code?
+
 AC_ARG_ENABLE(debug,
 AC_ARG_ENABLE(debug,
 	[  --enable-debug          show additional debug output],
 	[  --enable-debug          show additional debug output],
 	if test "$enableval" = "yes"; then x_debug_on=yes; fi
 	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"
 	test "$GCC" = "yes" && CFLAGS="-pedantic $CFLAGS"
 fi
 fi
 
 
+# enable "strict RFC rules"?
+
 x_strict_rfc_on=no
 x_strict_rfc_on=no
 AC_ARG_ENABLE(strict-rfc,
 AC_ARG_ENABLE(strict-rfc,
 	[  --enable-strict-rfc     strict RFC conformance -- may break clients!],
 	[  --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 "yes   $ECHO_C" \
 	|| echo $ECHO_N "no    $ECHO_C"
 	|| echo $ECHO_N "no    $ECHO_C"
 echo $ECHO_N "        I/O backend: $ECHO_C"
 echo $ECHO_N "        I/O backend: $ECHO_C"
-	echo "\"$x_io_backend()\""
+	echo "\"$x_io_backend\""
 
 
 echo
 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
 ngircd (0.10.0-0ab1) unstable; urgency=low
 
 
   * New "upstream" release: 0.10.0
   * 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
 # 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
 PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
 DAEMON=/usr/sbin/ngircd
 DAEMON=/usr/sbin/ngircd
 NAME=ngIRCd
 NAME=ngIRCd

+ 1 - 1
contrib/ngircd.spec

@@ -1,5 +1,5 @@
 %define name    ngircd
 %define name    ngircd
-%define version 0.10.0
+%define version 0.10.3
 %define release 1
 %define release 1
 %define prefix  %{_prefix}
 %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/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/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/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.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/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
 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.
 (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
 # 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)
 	# server? (This is a compatibility hack for ircd-irc2 servers)
 	;OperServerMode = no
 	;OperServerMode = no
 
 
+	# Allow Pre-Defined Channels only (see Section [Channels])
+	;PredefChannelsOnly = no
+
 	# Maximum number of simultaneous connection the server is allowed
 	# Maximum number of simultaneous connection the server is allowed
 	# to accept (<=0: unlimited):
 	# to accept (<=0: unlimited):
 	;MaxConnections = -1
 	;MaxConnections = -1
@@ -175,7 +178,13 @@
 	;Topic = a great topic
 	;Topic = a great topic
 
 
 	# Initial channel modes
 	# Initial channel modes
-	;Modes = tn
+	;Modes = tnk
+
+	# initial channel password (mode k)
+	;Key = Secret
+
+	# maximum users per channel (mode l)
+	;MaxUsers = 23
 
 
 [Channel]
 [Channel]
 	# More [Channel] sections, if you like ...
 	# More [Channel] sections, if you like ...

+ 2 - 2
doc/src/Makefile.am

@@ -8,14 +8,14 @@
 # (at your option) any later version.
 # (at your option) any later version.
 # Please read the file COPYING, README and AUTHORS for more information.
 # 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:
 maintainer-clean-local:
 	rm -f Makefile Makefile.in
 	rm -f Makefile Makefile.in
 
 
 distclean-local:
 distclean-local:
-	rm -f html
+	rm -rf html
 
 
 srcdoc:
 srcdoc:
 	@doxygen --version >/dev/null 2>&1 \
 	@doxygen --version >/dev/null 2>&1 \

+ 2 - 2
doc/src/Makefile.in

@@ -24,7 +24,7 @@
 # (at your option) any later version.
 # (at your option) any later version.
 # Please read the file COPYING, README and AUTHORS for more information.
 # 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@
 srcdir = @srcdir@
 top_srcdir = @top_srcdir@
 top_srcdir = @top_srcdir@
@@ -305,7 +305,7 @@ maintainer-clean-local:
 	rm -f Makefile Makefile.in
 	rm -f Makefile Makefile.in
 
 
 distclean-local:
 distclean-local:
-	rm -f html
+	rm -rf html
 
 
 srcdoc:
 srcdoc:
 	@doxygen --version >/dev/null 2>&1 \
 	@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"
 .TH ngircd.conf 5 "August 2005" ngircd "ngIRCd Manual"
 .SH NAME
 .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
 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.
 by non-chanops as if they were coming from the server. Default: no.
 .TP
 .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
 \fBMaxConnections\fR
 Maximum number of simultaneous connection the server is allowed to accept
 Maximum number of simultaneous connection the server is allowed to accept
 (<=0: unlimited). Default: -1.
 (<=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. */
 /* Define to 1 if you have the <netinet/in.h> header file. */
 #undef HAVE_NETINET_IN_H
 #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. */
 /* Define to 1 if you have the `realloc' function. */
 #undef HAVE_REALLOC
 #undef HAVE_REALLOC
 
 
@@ -157,6 +160,9 @@
 /* Define to 1 if you have the `strchr' function. */
 /* Define to 1 if you have the `strchr' function. */
 #undef HAVE_STRCHR
 #undef HAVE_STRCHR
 
 
+/* Define to 1 if you have the `strcspn' function. */
+#undef HAVE_STRCSPN
+
 /* Define to 1 if you have the `strdup' function. */
 /* Define to 1 if you have the `strdup' function. */
 #undef HAVE_STRDUP
 #undef HAVE_STRDUP
 
 
@@ -190,8 +196,8 @@
 /* Define to 1 if you have the <syslog.h> header file. */
 /* Define to 1 if you have the <syslog.h> header file. */
 #undef HAVE_SYSLOG_H
 #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. */
 /* Define to 1 if you have the <sys/socket.h> header file. */
 #undef HAVE_SYS_SOCKET_H
 #undef HAVE_SYS_SOCKET_H
@@ -310,6 +316,12 @@
 /* Define to empty if `const' does not conform to ANSI C. */
 /* Define to empty if `const' does not conform to ANSI C. */
 #undef const
 #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. */
 /* Define to `int' if <sys/types.h> does not define. */
 #undef pid_t
 #undef pid_t
 
 

+ 8 - 22
src/ngircd/array.c

@@ -12,7 +12,7 @@
 
 
 #include "array.h"
 #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>
 #include <assert.h>
 
 
@@ -66,10 +66,7 @@ array_alloc(array * a, size_t size, size_t pos)
 
 
 	assert(size > 0);
 	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;
 		return NULL;
 
 
 	if (a->allocated < alloc) {
 	if (a->allocated < alloc) {
@@ -250,20 +247,22 @@ void *
 array_get(array * a, size_t membersize, size_t pos)
 array_get(array * a, size_t membersize, size_t pos)
 {
 {
 	size_t totalsize;
 	size_t totalsize;
+	size_t posplus1 = pos + 1;
 
 
 	assert(membersize > 0);
 	assert(membersize > 0);
 	assert(a != NULL);
 	assert(a != NULL);
 
 
-	if (array_UNUSABLE(a))
+	if (!posplus1 || array_UNUSABLE(a))
 		return NULL;
 		return NULL;
 
 
-	if (!safemult_sizet(pos, membersize, &totalsize))
+	if (!safemult_sizet(posplus1, membersize, &totalsize))
 		return NULL;
 		return NULL;
 
 
 	if (a->allocated < totalsize)
 	if (a->allocated < totalsize)
 		return NULL;
 		return NULL;
 
 
-	return a->mem + pos * membersize;
+	totalsize = pos * membersize;
+	return a->mem + totalsize;
 }
 }
 
 
 
 
@@ -271,7 +270,7 @@ void
 array_free(array * a)
 array_free(array * a)
 {
 {
 	assert(a != NULL);
 	assert(a != NULL);
-#ifdef DEBUG
+#ifdef DEBUG_ARRAY
 	Log(LOG_DEBUG,
 	Log(LOG_DEBUG,
 	    "array_free(): %u bytes free'd (%u bytes still used at time of free()).",
 	    "array_free(): %u bytes free'd (%u bytes still used at time of free()).",
 	    a->allocated, a->used);
 	    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 *
 void *
 array_start(const array * const a)
 array_start(const array * const a)
 {
 {
@@ -331,9 +320,6 @@ array_moveleft(array * a, size_t membersize, size_t pos)
 	assert(a != NULL);
 	assert(a != NULL);
 	assert(membersize > 0);
 	assert(membersize > 0);
 
 
-	if (!pos)
-		return;
-
 	if (!safemult_sizet(membersize, pos, &bytepos)) {
 	if (!safemult_sizet(membersize, pos, &bytepos)) {
 		a->used = 0;
 		a->used = 0;
 		return;
 		return;

+ 141 - 80
src/ngircd/channel.c

@@ -17,7 +17,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -70,6 +70,22 @@ Channel_Init( void )
 } /* Channel_Init */
 } /* 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
 GLOBAL void
 Channel_InitPredefined( void )
 Channel_InitPredefined( void )
 {
 {
@@ -114,7 +130,10 @@ Channel_InitPredefined( void )
 			c = Conf_Channel[i].modes;
 			c = Conf_Channel[i].modes;
 			while (*c)
 			while (*c)
 				Channel_ModeAdd(chan, *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\".",
 			Log(LOG_INFO, "Created pre-defined channel \"%s\".",
 							Conf_Channel[i].name );
 							Conf_Channel[i].name );
 		}
 		}
@@ -129,7 +148,7 @@ Channel_Exit( void )
 {
 {
 	CHANNEL *c, *c_next;
 	CHANNEL *c, *c_next;
 	CL2CHAN *cl2chan, *cl2chan_next;
 	CL2CHAN *cl2chan, *cl2chan_next;
-	
+
 	/* Channel-Strukturen freigeben */
 	/* Channel-Strukturen freigeben */
 	c = My_Channels;
 	c = My_Channels;
 	while( c )
 	while( c )
@@ -173,7 +192,7 @@ Channel_Join( CLIENT *Client, char *Name )
 	{
 	{
 		/* Gibt es noch nicht? Dann neu anlegen: */
 		/* Gibt es noch nicht? Dann neu anlegen: */
 		chan = Channel_Create( Name );
 		chan = Channel_Create( Name );
-		if( ! chan ) return false;
+		if (!chan) return false;
 	}
 	}
 
 
 	/* User dem Channel hinzufuegen */
 	/* User dem Channel hinzufuegen */
@@ -214,7 +233,6 @@ Channel_Kick( CLIENT *Client, CLIENT *Origin, char *Name, char *Reason )
 	assert( Name != NULL );
 	assert( Name != NULL );
 	assert( Reason != NULL );
 	assert( Reason != NULL );
 
 
-	/* Channel suchen */
 	chan = Channel_Search( Name );
 	chan = Channel_Search( Name );
 	if( ! chan )
 	if( ! chan )
 	{
 	{
@@ -266,11 +284,11 @@ Channel_Quit( CLIENT *Client, char *Reason )
 } /* Channel_Quit */
 } /* Channel_Quit */
 
 
 
 
-GLOBAL long
+GLOBAL unsigned long
 Channel_Count( void )
 Channel_Count( void )
 {
 {
 	CHANNEL *c;
 	CHANNEL *c;
-	long count = 0;
+	unsigned long count = 0;
 	
 	
 	c = My_Channels;
 	c = My_Channels;
 	while( c )
 	while( c )
@@ -282,11 +300,11 @@ Channel_Count( void )
 } /* Channel_Count */
 } /* Channel_Count */
 
 
 
 
-GLOBAL long
+GLOBAL unsigned long
 Channel_MemberCount( CHANNEL *Chan )
 Channel_MemberCount( CHANNEL *Chan )
 {
 {
 	CL2CHAN *cl2chan;
 	CL2CHAN *cl2chan;
-	long count = 0;
+	unsigned long count = 0;
 
 
 	assert( Chan != NULL );
 	assert( Chan != NULL );
 
 
@@ -321,27 +339,9 @@ Channel_CountForUser( CLIENT *Client )
 } /* Channel_CountForUser */
 } /* 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 );
 	assert( Chan != NULL );
 	return Chan->name;
 	return Chan->name;
@@ -364,7 +364,7 @@ Channel_Key( CHANNEL *Chan )
 } /* Channel_Key */
 } /* Channel_Key */
 
 
 
 
-GLOBAL long
+GLOBAL unsigned long
 Channel_MaxUsers( CHANNEL *Chan )
 Channel_MaxUsers( CHANNEL *Chan )
 {
 {
 	assert( Chan != NULL );
 	assert( Chan != NULL );
@@ -463,25 +463,13 @@ Channel_GetChannel( CL2CHAN *Cl2Chan )
 
 
 
 
 GLOBAL bool
 GLOBAL bool
-Channel_IsValidName( char *Name )
+Channel_IsValidName( const char *Name )
 {
 {
-	/* Pruefen, ob Name als Channelname gueltig */
-
-	char *ptr, badchars[10];
-	
 	assert( Name != NULL );
 	assert( Name != NULL );
 
 
 	if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN )) return false;
 	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 */
 } /* Channel_IsValidName */
 
 
 
 
@@ -548,7 +536,7 @@ Channel_UserModeAdd( CHANNEL *Chan, CLIENT *Client, char Mode )
 
 
 	cl2chan = Get_Cl2Chan( Chan, Client );
 	cl2chan = Get_Cl2Chan( Chan, Client );
 	assert( cl2chan != NULL );
 	assert( cl2chan != NULL );
-	
+
 	x[0] = Mode; x[1] = '\0';
 	x[0] = Mode; x[1] = '\0';
 	if( ! strchr( cl2chan->modes, x[0] ))
 	if( ! strchr( cl2chan->modes, x[0] ))
 	{
 	{
@@ -594,7 +582,7 @@ GLOBAL char *
 Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
 Channel_UserModes( CHANNEL *Chan, CLIENT *Client )
 {
 {
 	/* return Users' Channel-Modes */
 	/* return Users' Channel-Modes */
-	
+
 	CL2CHAN *cl2chan;
 	CL2CHAN *cl2chan;
 
 
 	assert( Chan != NULL );
 	assert( Chan != NULL );
@@ -614,9 +602,7 @@ Channel_IsMemberOf( CHANNEL *Chan, CLIENT *Client )
 
 
 	assert( Chan != NULL );
 	assert( Chan != NULL );
 	assert( Client != NULL );
 	assert( Client != NULL );
-
-	if( Get_Cl2Chan( Chan, Client )) return true;
-	else return false;
+	return Get_Cl2Chan(Chan, Client);
 } /* Channel_IsMemberOf */
 } /* Channel_IsMemberOf */
 
 
 
 
@@ -661,12 +647,9 @@ Channel_SetTopic(CHANNEL *Chan, CLIENT *Client, char *Topic)
 	if (len < array_bytes(&Chan->topic))
 	if (len < array_bytes(&Chan->topic))
 		array_free(&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",
 		Log(LOG_WARNING, "could not set new Topic \"%s\" on %s: %s",
 					Topic, Chan->name, strerror(errno));
 					Topic, Chan->name, strerror(errno));
-
-	array_cat0(&Chan->topic);
-
 #ifndef STRICT_RFC
 #ifndef STRICT_RFC
 	Chan->topic_time = time(NULL);
 	Chan->topic_time = time(NULL);
 	if (Client != NULL && Client_Type(Client) != CLIENT_SERVER)
 	if (Client != NULL && Client_Type(Client) != CLIENT_SERVER)
@@ -698,17 +681,17 @@ Channel_SetKey( CHANNEL *Chan, char *Key )
 	assert( Key != NULL );
 	assert( Key != NULL );
 
 
 	strlcpy( Chan->key, Key, sizeof( Chan->key ));
 	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 */
 } /* Channel_SetKey */
 
 
 
 
 GLOBAL void
 GLOBAL void
-Channel_SetMaxUsers( CHANNEL *Chan, long Count )
+Channel_SetMaxUsers(CHANNEL *Chan, unsigned long Count)
 {
 {
 	assert( Chan != NULL );
 	assert( Chan != NULL );
 
 
 	Chan->maxusers = Count;
 	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 */
 } /* Channel_SetMaxUsers */
 
 
 
 
@@ -730,9 +713,9 @@ Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, char *Text )
 	ok = true;
 	ok = true;
 	if( strchr( Channel_Modes( Chan ), 'n' ) && ( ! is_member )) ok = false;
 	if( strchr( Channel_Modes( Chan ), 'n' ) && ( ! is_member )) ok = false;
 	if( strchr( Channel_Modes( Chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = false;
 	if( strchr( Channel_Modes( Chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = false;
-	
+
 	/* Is the client banned? */
 	/* 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? */
 		/* Client is banned, but is he channel operator or has voice? */
 		if(( ! has_voice ) && ( ! is_op )) ok = false;
 		if(( ! has_voice ) && ( ! is_op )) ok = false;
@@ -753,7 +736,7 @@ Channel_Create( char *Name )
 	CHANNEL *c;
 	CHANNEL *c;
 
 
 	assert( Name != NULL );
 	assert( Name != NULL );
-	
+
 	c = (CHANNEL *)malloc( sizeof( CHANNEL ));
 	c = (CHANNEL *)malloc( sizeof( CHANNEL ));
 	if( ! c )
 	if( ! c )
 	{
 	{
@@ -765,9 +748,7 @@ Channel_Create( char *Name )
 	c->hash = Hash( c->name );
 	c->hash = Hash( c->name );
 	c->next = My_Channels;
 	c->next = My_Channels;
 	My_Channels = c;
 	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;
 	return c;
 } /* Channel_Create */
 } /* Channel_Create */
 
 
@@ -851,25 +832,42 @@ Remove_Client( int Type, CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, char *Re
 	switch( Type )
 	switch( Type )
 	{
 	{
 		case REMOVE_QUIT:
 		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 );
 			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;
 			break;
 		case REMOVE_KICK:
 		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;
 			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 */
 	/* 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 */
 } /* 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 *
 static CL2CHAN *
 Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
 Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
 {
 {
@@ -911,7 +971,7 @@ static bool
 Delete_Channel( CHANNEL *Chan )
 Delete_Channel( CHANNEL *Chan )
 {
 {
 	/* Channel-Struktur loeschen */
 	/* Channel-Struktur loeschen */
-	
+
 	CHANNEL *chan, *last_chan;
 	CHANNEL *chan, *last_chan;
 
 
 	last_chan = NULL;
 	last_chan = NULL;
@@ -927,13 +987,14 @@ Delete_Channel( CHANNEL *Chan )
 	Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
 	Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
 
 
 	/* Invite- und Ban-Lists aufraeumen */
 	/* Invite- und Ban-Lists aufraeumen */
-	Lists_DeleteChannel( chan );
+	Lists_Free( &chan->list_bans );
+	Lists_Free( &chan->list_invites );
 
 
 	/* Neu verketten und freigeben */
 	/* Neu verketten und freigeben */
 	if( last_chan ) last_chan->next = chan->next;
 	if( last_chan ) last_chan->next = chan->next;
 	else My_Channels = chan->next;
 	else My_Channels = chan->next;
 	free( chan );
 	free( chan );
-		
+
 	return true;
 	return true;
 } /* Delete_Channel */
 } /* Delete_Channel */
 
 

+ 17 - 11
src/ngircd/channel.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Channel management (header)
  */
  */
@@ -20,6 +20,7 @@
 
 
 #if defined(__channel_c__) | defined(S_SPLINT_S)
 #if defined(__channel_c__) | defined(S_SPLINT_S)
 
 
+#include "lists.h"
 #include "defines.h"
 #include "defines.h"
 #include "array.h"
 #include "array.h"
 
 
@@ -35,7 +36,9 @@ typedef struct _CHANNEL
 	char topic_who[CLIENT_NICK_LEN];/* Nickname of user that set topic */
 	char topic_who[CLIENT_NICK_LEN];/* Nickname of user that set topic */
 #endif
 #endif
 	char key[CLIENT_PASS_LEN];	/* Channel key ("password", mode "k" ) */
 	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;
 } CHANNEL;
 
 
 typedef struct _CLIENT2CHAN
 typedef struct _CLIENT2CHAN
@@ -53,6 +56,8 @@ typedef POINTER CL2CHAN;
 
 
 #endif
 #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_Init PARAMS(( void ));
 GLOBAL void Channel_InitPredefined 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 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_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_Modes PARAMS(( CHANNEL *Chan ));
 GLOBAL char *Channel_Topic PARAMS(( CHANNEL *Chan ));
 GLOBAL char *Channel_Topic PARAMS(( CHANNEL *Chan ));
 GLOBAL char *Channel_Key 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_SetTopic PARAMS(( CHANNEL *Chan, CLIENT *Client, char *Topic ));
 GLOBAL void Channel_SetModes PARAMS(( CHANNEL *Chan, char *Modes ));
 GLOBAL void Channel_SetModes PARAMS(( CHANNEL *Chan, char *Modes ));
 GLOBAL void Channel_SetKey PARAMS(( CHANNEL *Chan, char *Key ));
 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 ));
 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 CLIENT *Channel_GetClient PARAMS(( CL2CHAN *Cl2Chan ));
 GLOBAL CHANNEL *Channel_GetChannel 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_ModeAdd PARAMS(( CHANNEL *Chan, char Mode ));
 GLOBAL bool Channel_ModeDel 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 ));
 GLOBAL char *Channel_TopicWho PARAMS(( CHANNEL *Chan ));
 #endif
 #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
 #endif
-
-
 /* -eof- */
 /* -eof- */

+ 41 - 83
src/ngircd/client.c

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

+ 8 - 12
src/ngircd/client.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Client management (header)
  */
  */
@@ -23,10 +23,9 @@
 #define CLIENT_GOTNICK 4		/* client did send NICK */
 #define CLIENT_GOTNICK 4		/* client did send NICK */
 #define CLIENT_GOTUSER 8		/* client did send USER */
 #define CLIENT_GOTUSER 8		/* client did send USER */
 #define CLIENT_USER 16			/* client is an IRC 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
 #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 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 ));
 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 ));
 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_UserCount PARAMS(( void ));
 GLOBAL long Client_ServiceCount PARAMS(( void ));
 GLOBAL long Client_ServiceCount PARAMS(( void ));
 GLOBAL long Client_ServerCount 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_MyUserCount PARAMS(( void ));
 GLOBAL long Client_MyServiceCount 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_MaxUserCount PARAMS((  void ));
 GLOBAL long Client_MyMaxUserCount 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 WHOWAS *Client_GetWhowas PARAMS(( void ));
 GLOBAL int Client_GetLastWhowasIndex PARAMS(( void ));
 GLOBAL int Client_GetLastWhowasIndex PARAMS(( void ));

+ 66 - 23
src/ngircd/conf.c

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -146,6 +146,9 @@ Conf_Rehash( void )
 	Set_Defaults( false );
 	Set_Defaults( false );
 	Read_Config( );
 	Read_Config( );
 	Validate_Config(false, true);
 	Validate_Config(false, true);
+
+	/* Update CLIENT structure of local server */
+	Client_SetInfo(Client_ThisServer(), Conf_ServerInfo);
 } /* Config_Rehash */
 } /* Config_Rehash */
 
 
 
 
@@ -199,15 +202,16 @@ Conf_Test( void )
 	printf( "  PingTimeout = %d\n", Conf_PingTimeout );
 	printf( "  PingTimeout = %d\n", Conf_PingTimeout );
 	printf( "  PongTimeout = %d\n", Conf_PongTimeout );
 	printf( "  PongTimeout = %d\n", Conf_PongTimeout );
 	printf( "  ConnectRetry = %d\n", Conf_ConnectRetry );
 	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( "  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( "  MaxConnections = %ld\n", Conf_MaxConnections>0 ? Conf_MaxConnections : -1);
 	printf( "  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP>0 ? Conf_MaxConnectionsIP : -1);
 	printf( "  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP>0 ? Conf_MaxConnectionsIP : -1);
 	printf( "  MaxJoins = %d\n\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1);
 	printf( "  MaxJoins = %d\n\n", Conf_MaxJoins>0 ? Conf_MaxJoins : -1);
 
 
 	for( i = 0; i < Conf_Oper_Count; i++ ) {
 	for( i = 0; i < Conf_Oper_Count; i++ ) {
 		if( ! Conf_Oper[i].name[0] ) continue;
 		if( ! Conf_Oper[i].name[0] ) continue;
-		
+
 		/* Valid "Operator" section */
 		/* Valid "Operator" section */
 		puts( "[OPERATOR]" );
 		puts( "[OPERATOR]" );
 		printf( "  Name = %s\n", Conf_Oper[i].name );
 		printf( "  Name = %s\n", Conf_Oper[i].name );
@@ -218,7 +222,7 @@ Conf_Test( void )
 
 
 	for( i = 0; i < MAX_SERVERS; i++ ) {
 	for( i = 0; i < MAX_SERVERS; i++ ) {
 		if( ! Conf_Server[i].name[0] ) continue;
 		if( ! Conf_Server[i].name[0] ) continue;
-		
+
 		/* Valid "Server" section */
 		/* Valid "Server" section */
 		puts( "[SERVER]" );
 		puts( "[SERVER]" );
 		printf( "  Name = %s\n", Conf_Server[i].name );
 		printf( "  Name = %s\n", Conf_Server[i].name );
@@ -231,16 +235,18 @@ Conf_Test( void )
 
 
 	for( i = 0; i < Conf_Channel_Count; i++ ) {
 	for( i = 0; i < Conf_Channel_Count; i++ ) {
 		if( ! Conf_Channel[i].name[0] ) continue;
 		if( ! Conf_Channel[i].name[0] ) continue;
-		
+
 		/* Valid "Channel" section */
 		/* Valid "Channel" section */
 		puts( "[CHANNEL]" );
 		puts( "[CHANNEL]" );
 		printf( "  Name = %s\n", Conf_Channel[i].name );
 		printf( "  Name = %s\n", Conf_Channel[i].name );
 		printf( "  Modes = %s\n", Conf_Channel[i].modes );
 		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);
 		topic = (char*)array_start(&Conf_Channel[i].topic);
 		printf( "  Topic = %s\n\n", topic ? topic : "");
 		printf( "  Topic = %s\n\n", topic ? topic : "");
 	}
 	}
-	
+
 	return 0;
 	return 0;
 } /* Conf_Test */
 } /* Conf_Test */
 
 
@@ -268,14 +274,14 @@ Conf_UnsetServer( CONN_ID Idx )
 			Init_Server_Struct( &Conf_Server[i] );
 			Init_Server_Struct( &Conf_Server[i] );
 		} else {
 		} else {
 			/* Set time for next connect attempt */
 			/* 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 */
 } /* Conf_UnsetServer */
@@ -297,9 +303,9 @@ GLOBAL int
 Conf_GetServer( CONN_ID Idx )
 Conf_GetServer( CONN_ID Idx )
 {
 {
 	/* Get index of server in configuration structure */
 	/* Get index of server in configuration structure */
-	
+
 	int i = 0;
 	int i = 0;
-	
+
 	assert( Idx > NONE );
 	assert( Idx > NONE );
 
 
 	for( i = 0; i < MAX_SERVERS; i++ ) {
 	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 ));
 	strlcpy( Conf_Server[i].pwd_in, PeerPwd, sizeof( Conf_Server[i].pwd_in ));
 	Conf_Server[i].port = Port;
 	Conf_Server[i].port = Port;
 	Conf_Server[i].flags = CONF_SFLAG_ONCE;
 	Conf_Server[i].flags = CONF_SFLAG_ONCE;
-	
+
 	return true;
 	return true;
 } /* Conf_AddServer */
 } /* Conf_AddServer */
 
 
@@ -409,7 +415,7 @@ Set_Defaults( bool InitServers )
 	strcpy( Conf_ListenAddress, "" );
 	strcpy( Conf_ListenAddress, "" );
 
 
 	Conf_UID = Conf_GID = 0;
 	Conf_UID = Conf_GID = 0;
-	
+
 	Conf_PingTimeout = 120;
 	Conf_PingTimeout = 120;
 	Conf_PongTimeout = 20;
 	Conf_PongTimeout = 20;
 
 
@@ -419,8 +425,9 @@ Set_Defaults( bool InitServers )
 	Conf_Channel_Count = 0;
 	Conf_Channel_Count = 0;
 
 
 	Conf_OperCanMode = false;
 	Conf_OperCanMode = false;
+	Conf_PredefChannelsOnly = false;
 	Conf_OperServerMode = false;
 	Conf_OperServerMode = false;
-	
+
 	Conf_MaxConnections = -1;
 	Conf_MaxConnections = -1;
 	Conf_MaxConnectionsIP = 5;
 	Conf_MaxConnectionsIP = 5;
 	Conf_MaxJoins = 10;
 	Conf_MaxJoins = 10;
@@ -550,6 +557,8 @@ Read_Config( void )
 					/* Initialize new channel structure */
 					/* Initialize new channel structure */
 					strcpy( Conf_Channel[Conf_Channel_Count].name, "" );
 					strcpy( Conf_Channel[Conf_Channel_Count].name, "" );
 					strcpy( Conf_Channel[Conf_Channel_Count].modes, "" );
 					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);
 					array_free(&Conf_Channel[Conf_Channel_Count].topic);
 					Conf_Channel_Count++;
 					Conf_Channel_Count++;
 				}
 				}
@@ -750,6 +759,11 @@ Handle_GLOBAL( int Line, char *Var, char *Arg )
 		}
 		}
 		return;
 		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 ) {
 	if( strcasecmp( Var, "OperCanUseMode" ) == 0 ) {
 		/* Are IRC operators allowed to use MODE in channels they aren't Op in? */
 		/* Are IRC operators allowed to use MODE in channels they aren't Op in? */
 		Conf_OperCanMode = Check_ArgIsTrue( Arg );
 		Conf_OperCanMode = Check_ArgIsTrue( Arg );
@@ -912,6 +926,21 @@ Handle_SERVER( int Line, char *Var, char *Arg )
 } /* Handle_SERVER */
 } /* 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
 static void
 Handle_CHANNEL( int Line, char *Var, char *Arg )
 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;
 		chancount = Conf_Channel_Count - 1;
 
 
 	if( strcasecmp( Var, "Name" ) == 0 ) {
 	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 );
 			Config_Error_TooLong( Line, Var );
 		return;
 		return;
 	}
 	}
@@ -945,6 +972,22 @@ Handle_CHANNEL( int Line, char *Var, char *Arg )
 		return;
 		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\"!",
 	Config_Error( LOG_ERR, "%s, line %d (section \"Channel\"): Unknown variable \"%s\"!",
 								NGIRCd_ConfFile, Line, Var );
 								NGIRCd_ConfFile, Line, Var );
 } /* Handle_CHANNEL */
 } /* Handle_CHANNEL */
@@ -965,7 +1008,7 @@ Validate_Config(bool Configtest, bool Rehash)
 	do {
 	do {
 		if (*ptr >= 'a' && *ptr <= 'z') continue;
 		if (*ptr >= 'a' && *ptr <= 'z') continue;
 		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 > Conf_ServerName) {
 			if (*ptr == '.' || *ptr == '-')
 			if (*ptr == '.' || *ptr == '-')
 				continue;
 				continue;

+ 5 - 1
src/ngircd/conf.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Configuration management (header)
  */
  */
@@ -49,6 +49,8 @@ typedef struct _Conf_Channel
 {
 {
 	char name[CHANNEL_NAME_LEN];	/* Name of the channel */
 	char name[CHANNEL_NAME_LEN];	/* Name of the channel */
 	char modes[CHANNEL_MODE_LEN];	/* Initial channel modes */
 	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 */
 	array topic;			/* Initial topic */
 } CONF_CHANNEL;
 } CONF_CHANNEL;
 
 
@@ -110,6 +112,8 @@ GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS];
 /* Pre-defined channels */
 /* Pre-defined channels */
 GLOBAL CONF_CHANNEL Conf_Channel[MAX_DEFCHANNELS];
 GLOBAL CONF_CHANNEL Conf_Channel[MAX_DEFCHANNELS];
 GLOBAL unsigned int Conf_Channel_Count;
 GLOBAL unsigned int Conf_Channel_Count;
+/* Pre-defined channels only */
+GLOBAL bool Conf_PredefChannelsOnly;
 
 
 /* Are IRC operators allowed to always use MODE? */
 /* Are IRC operators allowed to always use MODE? */
 GLOBAL bool Conf_OperCanMode;
 GLOBAL bool Conf_OperCanMode;

+ 4 - 4
src/ngircd/conn-func.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Connection management: Global functions (header)
  */
  */
@@ -52,9 +52,9 @@ GLOBAL UINT16 Conn_Options PARAMS(( CONN_ID Idx ));
 GLOBAL void Conn_ResetWCounter PARAMS(( void ));
 GLOBAL void Conn_ResetWCounter PARAMS(( void ));
 GLOBAL long Conn_WCounter 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
 #endif
 
 

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

@@ -1,6 +1,6 @@
 /*
 /*
  * ngIRCd -- The Next Generation IRC Daemon
  * 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
  * 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
  * it under the terms of the GNU General Public License as published by
@@ -22,7 +22,7 @@
 /* enable more zlib related debug messages: */
 /* enable more zlib related debug messages: */
 /* #define DEBUG_ZLIB */
 /* #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -82,47 +82,63 @@ Zip_InitConn( CONN_ID Idx )
 } /* Zip_InitConn */
 } /* 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
 GLOBAL bool
 Zip_Buffer( CONN_ID Idx, char *Data, size_t Len )
 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( Idx > NONE );
 	assert( Data != NULL );
 	assert( Data != NULL );
 	assert( Len > 0 );
 	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 */
 		/* compression buffer is full, flush */
 		if( ! Zip_Flush( Idx )) return false;
 		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);
 	return array_catb(&My_Connections[Idx].zip.wbuf, Data, Len);
 } /* Zip_Buffer */
 } /* 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
 GLOBAL bool
 Zip_Flush( CONN_ID Idx )
 Zip_Flush( CONN_ID Idx )
 {
 {
-	/* Daten komprimieren und in Schreibpuffer kopieren.
-	* Es wird true bei Erfolg, sonst false geliefert. */
-
 	int result;
 	int result;
-	unsigned char zipbuf[WRITEBUFFER_LEN];
+	unsigned char zipbuf[WRITEBUFFER_SLINK_LEN];
 	int zipbuf_used = 0;
 	int zipbuf_used = 0;
 	z_stream *out;
 	z_stream *out;
 
 
 	out = &My_Connections[Idx].zip.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);
 	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->next_out = zipbuf;
 	out->avail_out = (uInt)sizeof zipbuf;
 	out->avail_out = (uInt)sizeof zipbuf;
@@ -139,14 +155,26 @@ Zip_Flush( CONN_ID Idx )
 		return false;
 		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
 #ifdef DEBUG_ZIP
 	Log(LOG_DEBUG, "zipbuf_used: %d", zipbuf_used);
 	Log(LOG_DEBUG, "zipbuf_used: %d", zipbuf_used);
 #endif
 #endif
 	if (!array_catb(&My_Connections[Idx].wbuf,
 	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;
 		return false;
+	}
 
 
 	My_Connections[Idx].bytes_out += zipbuf_used;
 	My_Connections[Idx].bytes_out += zipbuf_used;
 	My_Connections[Idx].zip.bytes_out += array_bytes(&My_Connections[Idx].zip.wbuf); 
 	My_Connections[Idx].zip.bytes_out += array_bytes(&My_Connections[Idx].zip.wbuf); 
@@ -178,10 +206,9 @@ Unzip_Buffer( CONN_ID Idx )
 		return true;
 		return true;
 
 
 	in = &My_Connections[Idx].zip.in;
 	in = &My_Connections[Idx].zip.in;
-	
+
 	in->next_in = array_start(&My_Connections[Idx].zip.rbuf);
 	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->avail_in = z_rdatalen;
 	in->next_out = unzipbuf;
 	in->next_out = unzipbuf;

+ 108 - 94
src/ngircd/conn.c

@@ -1,6 +1,6 @@
 /*
 /*
  * ngIRCd -- The Next Generation IRC Daemon
  * 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
  * 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
  * it under the terms of the GNU General Public License as published by
@@ -17,7 +17,7 @@
 #include "portab.h"
 #include "portab.h"
 #include "io.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 "imp.h"
 #include <assert.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 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 int New_Connection PARAMS(( int Sock ));
 static CONN_ID Socket2Index PARAMS(( int Sock ));
 static CONN_ID Socket2Index PARAMS(( int Sock ));
 static void Read_Request PARAMS(( CONN_ID Idx ));
 static void Read_Request PARAMS(( CONN_ID Idx ));
@@ -123,7 +124,6 @@ cb_connserver(int sock, UNUSED short what)
 {
 {
 	int res, err;
 	int res, err;
 	socklen_t sock_len;
 	socklen_t sock_len;
-	CLIENT *c;
 	CONN_ID idx = Socket2Index( sock );
 	CONN_ID idx = Socket2Index( sock );
 	if (idx <= NONE) {
 	if (idx <= NONE) {
 		LogDebug("cb_connserver wants to write on unknown socket?!");
 		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,
  			    Conf_Server[Conf_GetServer(idx)].port,
  			    idx, strerror(err));
  			    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;
 		return;
 	}
 	}
 
 
@@ -384,7 +377,7 @@ NewListener( const UINT16 Port )
 	if( ! Init_Socket( sock )) return -1;
 	if( ! Init_Socket( sock )) return -1;
 
 
 	if (bind(sock, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) != 0) {
 	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 );
 		close( sock );
 		return -1;
 		return -1;
 	}
 	}
@@ -615,51 +608,74 @@ va_dcl
 } /* Conn_WriteStr */
 } /* 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 )
 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( Idx > NONE );
 	assert( Data != NULL );
 	assert( Data != NULL );
 	assert( Len > 0 );
 	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 ) {
 	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;
 		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
 #ifdef ZLIB
 	if ( Conn_OPTION_ISSET( &My_Connections[Idx], CONN_ZIP )) {
 	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
 	else
 #endif
 #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;
 			return false;
 
 
 		My_Connections[Idx].bytes_out += Len;
 		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" */
 	/* Mark link as "closing" */
 	Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING );
 	Conn_OPTION_ADD( &My_Connections[Idx], CONN_ISCLOSING );
-		
+
 	if (LogMsg)
 	if (LogMsg)
 		txt = LogMsg;
 		txt = LogMsg;
 	else
 	else
@@ -728,7 +744,6 @@ Conn_Close( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient )
 			 (double)My_Connections[Idx].bytes_out / 1024);
 			 (double)My_Connections[Idx].bytes_out / 1024);
 		}
 		}
 #endif
 #endif
-
 		/* Send ERROR to client (see RFC!) */
 		/* Send ERROR to client (see RFC!) */
 		if (FwdMsg)
 		if (FwdMsg)
 			Conn_WriteStr(Idx, "ERROR :%s", FwdMsg);
 			Conn_WriteStr(Idx, "ERROR :%s", FwdMsg);
@@ -872,24 +887,23 @@ Handle_Write( CONN_ID Idx )
 	wdatalen = array_bytes(&My_Connections[Idx].wbuf );
 	wdatalen = array_bytes(&My_Connections[Idx].wbuf );
 
 
 #ifdef ZLIB
 #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) {
 	if (wdatalen == 0) {
+		/* Still no data, fine. */
 		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE );
 		io_event_del(My_Connections[Idx].sock, IO_WANTWRITE );
 		return true;
 		return true;
 	}
 	}
-#endif
 
 
-	/* Zip_Flush() may have changed the write buffer ... */
-	wdatalen = array_bytes(&My_Connections[Idx].wbuf);
 	LogDebug
 	LogDebug
 	    ("Handle_Write() called for connection %d, %ld bytes pending ...",
 	    ("Handle_Write() called for connection %d, %ld bytes pending ...",
 	     Idx, wdatalen);
 	     Idx, wdatalen);
@@ -995,11 +1009,19 @@ New_Connection( int Sock )
 			Init_Conn_Struct(Pool_Size++);
 			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 );
 	c = Client_NewLocal( new_sock, inet_ntoa( new_addr.sin_addr ), CLIENT_UNKNOWN, false );
 	if( ! c ) {
 	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;
 		return -1;
 	}
 	}
 
 
@@ -1008,13 +1030,6 @@ New_Connection( int Sock )
 	My_Connections[new_sock].addr = new_addr;
 	My_Connections[new_sock].addr = new_addr;
 	My_Connections[new_sock].client = c;
 	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,
 	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 );
 			inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock );
 
 
@@ -1050,47 +1065,52 @@ Socket2Index( int Sock )
 } /* Socket2Index */
 } /* 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
 static void
 Read_Request( CONN_ID Idx )
 Read_Request( CONN_ID Idx )
 {
 {
-	/* Daten von Socket einlesen und entsprechend behandeln.
-	 * Tritt ein Fehler auf, so wird der Socket geschlossen. */
-
 	ssize_t len;
 	ssize_t len;
-	char readbuf[1024];
+	char readbuf[READBUFFER_LEN];
 	CLIENT *c;
 	CLIENT *c;
-
 	assert( Idx > NONE );
 	assert( Idx > NONE );
 	assert( My_Connections[Idx].sock > NONE );
 	assert( My_Connections[Idx].sock > NONE );
 
 
 #ifdef ZLIB
 #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
 #else
-	if ( array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN )
+	if (array_bytes(&My_Connections[Idx].rbuf) >= READBUFFER_LEN)
 #endif
 #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 );
 		Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
 		return;
 		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;
 		return;
 	}
 	}
 
 
-	if( len < 0 ) {
+	if (len < 0) {
 		if( errno == EAGAIN ) return;
 		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;
 		return;
 	}
 	}
 #ifdef ZLIB
 #ifdef ZLIB
@@ -1107,8 +1127,7 @@ Read_Request( CONN_ID Idx )
 	} else
 	} else
 #endif
 #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 );
 			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 );
 			Conn_Close( Idx, "Receive buffer overflow!", NULL, false );
 		}
 		}
@@ -1227,11 +1246,6 @@ Handle_Buffer( CONN_ID Idx )
 			/* The last Command activated Socket-Compression.
 			/* The last Command activated Socket-Compression.
 			 * Data that was read after that needs to be copied to Unzip-buf
 			 * Data that was read after that needs to be copied to Unzip-buf
 			 * for decompression */
 			 * 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 ))
 			if (!array_copy( &My_Connections[Idx].zip.rbuf, &My_Connections[Idx].rbuf ))
 				return false;
 				return false;
 
 
@@ -1639,9 +1653,9 @@ Conn_GetClient( CONN_ID Idx )
 	assert( Idx >= 0 );
 	assert( Idx >= 0 );
 
 
 	c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx);
 	c = array_get(&My_ConnArray, sizeof (CONNECTION), (size_t)Idx);
-	
+
 	assert(c != NULL);
 	assert(c != NULL);
-	
+
 	return c ? c->client : NULL;
 	return c ? c->client : NULL;
 }
 }
 
 

+ 1 - 2
src/ngircd/conn.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Connection management (header)
  */
  */
@@ -88,7 +88,6 @@ GLOBAL void Conn_ExitListeners PARAMS(( void ));
 
 
 GLOBAL void Conn_Handler 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 bool Conn_WriteStr PARAMS(( CONN_ID Idx, char *Format, ... ));
 
 
 GLOBAL void Conn_Close PARAMS(( CONN_ID Idx, char *LogMsg, char *FwdMsg, bool InformClient ));
 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
  * 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
  * 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
  * it under the terms of the GNU General Public License as published by
@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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. */
 					   connection in bytes. */
 #define WRITEBUFFER_LEN 4096		/* Size of the write buffer of a
 #define WRITEBUFFER_LEN 4096		/* Size of the write buffer of a
 					   connection in bytes. */
 					   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,
 #define PROTOVER "0210"			/* Implemented IRC protocol version,
 					   see RFC 2813 section 4.1.1. */
 					   see RFC 2813 section 4.1.1. */

+ 2 - 2
src/ngircd/hash.c

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -31,7 +31,7 @@ static UINT32 jenkins_hash PARAMS(( register UINT8 *k, register UINT32 length, r
 
 
 
 
 GLOBAL UINT32
 GLOBAL UINT32
-Hash( char *String )
+Hash( const char *String )
 {
 {
 	/* Hash-Wert ueber String berechnen */
 	/* Hash-Wert ueber String berechnen */
 
 

+ 2 - 3
src/ngircd/hash.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Hash calculation (header)
  */
  */
@@ -17,8 +17,7 @@
 #ifndef __hash_h__
 #ifndef __hash_h__
 #define __hash_h__
 #define __hash_h__
 
 
-
-GLOBAL UINT32 Hash PARAMS((char *String ));
+GLOBAL UINT32 Hash PARAMS((const char *String ));
 
 
 
 
 #endif
 #endif

+ 393 - 77
src/ngircd/io.c

@@ -12,7 +12,7 @@
 
 
 #include "portab.h"
 #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 <assert.h>
 #include <stdlib.h>
 #include <stdlib.h>
@@ -34,25 +34,40 @@ typedef struct {
  short what;
  short what;
 } io_event;
 } 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
 #ifdef HAVE_EPOLL_CREATE
-#define IO_USE_EPOLL    1
+#  define IO_USE_EPOLL		1
+#  ifdef HAVE_SELECT
+#    define IO_USE_SELECT	1
+#  endif
 #else
 #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
 #ifdef IO_USE_EPOLL
 #include <sys/epoll.h>
 #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 bool io_event_change_epoll(int fd, short what, const int action);
 static int io_dispatch_epoll(struct timeval *tv);
 static int io_dispatch_epoll(struct timeval *tv);
 #endif
 #endif
@@ -67,6 +82,22 @@ static int io_dispatch_kqueue(struct timeval *tv);
 static bool io_event_change_kqueue(int, short, const int action);
 static bool io_event_change_kqueue(int, short, const int action);
 #endif
 #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
 #ifdef IO_USE_SELECT
 #include "defines.h"	/* for conn.h */
 #include "defines.h"	/* for conn.h */
 #include "conn.h"	/* for CONN_IDX (needed by resolve.h) */
 #include "conn.h"	/* for CONN_IDX (needed by resolve.h) */
@@ -77,7 +108,11 @@ static fd_set readers;
 static fd_set writers;
 static fd_set writers;
 static int select_maxfd;		/* the select() interface sucks badly */
 static int select_maxfd;		/* the select() interface sucks badly */
 static int io_dispatch_select(struct timeval *tv);
 static int io_dispatch_select(struct timeval *tv);
+
+#ifndef IO_USE_EPOLL
+#define io_masterfd -1
 #endif
 #endif
+#endif /* IO_USE_SELECT */
 
 
 static array io_events;
 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
 #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
 #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
 #ifdef IO_USE_SELECT
+static void
+io_library_init_select(unsigned int eventsize)
+{
 	Log(LOG_INFO, "IO subsystem: select (initial maxfd %u).",
 	Log(LOG_INFO, "IO subsystem: select (initial maxfd %u).",
 	    eventsize);
 	    eventsize);
 	FD_ZERO(&readers);
 	FD_ZERO(&readers);
@@ -144,24 +184,82 @@ io_library_init(unsigned int eventsize)
 
 
 		Conf_MaxConnections = FD_SETSIZE - 1;
 		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 */
 #endif /* FD_SETSIZE */
 	library_initialized = true;
 	library_initialized = true;
-	return true;
+}
 #endif /* SELECT */
 #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
 #ifdef IO_USE_KQUEUE
+static void
+io_library_init_kqueue(unsigned int eventsize)
+{
 	io_masterfd = kqueue();
 	io_masterfd = kqueue();
 
 
 	Log(LOG_INFO,
 	Log(LOG_INFO,
 	    "IO subsystem: kqueue (initial maxfd %u, masterfd %d)",
 	    "IO subsystem: kqueue (initial maxfd %u, masterfd %d)",
 	    eventsize, io_masterfd);
 	    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
 #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
 #ifdef IO_USE_SELECT
 	FD_ZERO(&readers);
 	FD_ZERO(&readers);
 	FD_ZERO(&writers);
 	FD_ZERO(&writers);
-#else
-	close(io_masterfd);	/* kqueue, epoll */
+#endif
+#ifdef IO_USE_EPOLL
+	if (io_masterfd >= 0)
+		close(io_masterfd);
 	io_masterfd = -1;
 	io_masterfd = -1;
 #endif
 #endif
 #ifdef IO_USE_KQUEUE
 #ifdef IO_USE_KQUEUE
+	close(io_masterfd);
+	io_masterfd = -1;
 	array_free(&io_evcache);
 	array_free(&io_evcache);
 #endif
 #endif
 	library_initialized = false;
 	library_initialized = false;
@@ -201,18 +303,14 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short))
 	io_event *i;
 	io_event *i;
 
 
 	assert(fd >= 0);
 	assert(fd >= 0);
-
-#ifdef IO_USE_SELECT
-#ifdef FD_SETSIZE
+#if defined(IO_USE_SELECT) && defined(FD_SETSIZE)
 	if (fd >= FD_SETSIZE) {
 	if (fd >= FD_SETSIZE) {
 		Log(LOG_ERR,
 		Log(LOG_ERR,
 		    "fd %d exceeds FD_SETSIZE (%u) (select can't handle more file descriptors)",
 		    "fd %d exceeds FD_SETSIZE (%u) (select can't handle more file descriptors)",
 		    fd, FD_SETSIZE);
 		    fd, FD_SETSIZE);
 		return false;
 		return false;
 	}
 	}
-#endif				/* FD_SETSIZE */
-#endif				/* IO_USE_SELECT */
-
+#endif
 	i = (io_event *) array_alloc(&io_events, sizeof(io_event), (size_t) fd);
 	i = (io_event *) array_alloc(&io_events, sizeof(io_event), (size_t) fd);
 	if (!i) {
 	if (!i) {
 		Log(LOG_WARNING,
 		Log(LOG_WARNING,
@@ -223,6 +321,12 @@ io_event_create(int fd, short what, void (*cbfunc) (int, short))
 
 
 	i->callback = cbfunc;
 	i->callback = cbfunc;
 	i->what = 0;
 	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
 #ifdef IO_USE_EPOLL
 	ret = io_event_change_epoll(fd, what, EPOLL_CTL_ADD);
 	ret = io_event_change_epoll(fd, what, EPOLL_CTL_ADD);
 #endif
 #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);
 	ret = io_event_change_kqueue(fd, what, EV_ADD|EV_ENABLE);
 #endif
 #endif
 #ifdef IO_USE_SELECT
 #ifdef IO_USE_SELECT
-	ret = io_event_add(fd, what);
+	if (io_masterfd < 0)
+		ret = io_event_add(fd, what);
 #endif
 #endif
 	if (ret) i->what = what;
 	if (ret) i->what = what;
 	return ret;
 	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
 #ifdef IO_USE_EPOLL
 static bool
 static bool
 io_event_change_epoll(int fd, short what, const int action)
 io_event_change_epoll(int fd, short what, const int action)
@@ -260,7 +408,7 @@ io_event_kqueue_commit_cache(void)
 	struct kevent *events;
 	struct kevent *events;
 	bool ret;
 	bool ret;
 	int len = (int) array_length(&io_evcache, sizeof (struct kevent));
 	int len = (int) array_length(&io_evcache, sizeof (struct kevent));
- 
+
 	if (!len) /* nothing to do */
 	if (!len) /* nothing to do */
 		return true;
 		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));
 		ret = array_catb(&io_evcache, (char*) &kev, sizeof (kev));
 		if (!ret)
 		if (!ret)
 			ret = kevent(io_masterfd, &kev,1, NULL, 0, NULL) == 0;
 			ret = kevent(io_masterfd, &kev,1, NULL, 0, NULL) == 0;
-	}	
+	}
 
 
 	if (ret && (what & IO_WANTWRITE)) {
 	if (ret && (what & IO_WANTWRITE)) {
 		EV_SET(&kev, fd, EVFILT_WRITE, action, 0, 0, 0);
 		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);
 	io_event *i = io_event_get(fd);
 
 
 	if (!i) return false;
 	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
 #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
 #endif
 	i->what |= what;
 	i->what |= what;
 #ifdef IO_USE_EPOLL
 #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
 #endif
 
 
 #ifdef IO_USE_KQUEUE
 #ifdef IO_USE_KQUEUE
 	return io_event_change_kqueue(fd, what, EV_ADD | EV_ENABLE);
 	return io_event_change_kqueue(fd, what, EV_ADD | EV_ENABLE);
 #endif
 #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
 #ifdef IO_USE_SELECT
 	if (fd > select_maxfd)
 	if (fd > select_maxfd)
 		select_maxfd = fd;
 		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
 #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, &writers);
 	FD_CLR(fd, &readers);
 	FD_CLR(fd, &readers);
 
 
+	i = io_event_get(fd);
+	if (!i) return;
+
 	if (fd == select_maxfd) {
 	if (fd == select_maxfd) {
 		while (select_maxfd>0) {
 		while (select_maxfd>0) {
-			--select_maxfd; /* find largest fd */  
+			--select_maxfd; /* find largest fd */
 			i = io_event_get(select_maxfd);
 			i = io_event_get(select_maxfd);
 			if (i && i->callback) break;
 			if (i && i->callback) break;
-		}	
-	}	
+		}
+	}
+}
+#else
+static inline void io_close_select(int UNUSED x) { /* NOTHING */ }
 #endif
 #endif
+
+
+bool
+io_close(int fd)
+{
+	io_event *i;
+
 	i = io_event_get(fd);
 	i = io_event_get(fd);
 #ifdef IO_USE_KQUEUE
 #ifdef IO_USE_KQUEUE
 	if (array_length(&io_evcache, sizeof (struct kevent)))	/* pending data in cache? */
 	if (array_length(&io_evcache, sizeof (struct kevent)))	/* pending data in cache? */
@@ -385,8 +596,13 @@ io_close(int fd)
 	if (i) {
 	if (i) {
 		io_event_change_kqueue(fd, i->what, EV_DELETE);
 		io_event_change_kqueue(fd, i->what, EV_DELETE);
 		io_event_kqueue_commit_cache();
 		io_event_kqueue_commit_cache();
-	}	
+	}
 #endif
 #endif
+
+	io_close_devpoll(fd);
+	io_close_poll(fd);
+	io_close_select(fd);
+
 #ifdef IO_USE_EPOLL
 #ifdef IO_USE_EPOLL
 	io_event_change_epoll(fd, 0, EPOLL_CTL_DEL);
 	io_event_change_epoll(fd, 0, EPOLL_CTL_DEL);
 #endif
 #endif
@@ -409,8 +625,15 @@ io_event_del(int fd, short what)
 
 
 	i->what &= ~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
 #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
 #endif
 
 
 #ifdef IO_USE_KQUEUE
 #ifdef IO_USE_KQUEUE
@@ -465,6 +688,92 @@ io_dispatch_select(struct timeval *tv)
 #endif
 #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
 #ifdef IO_USE_EPOLL
 static int
 static int
 io_dispatch_epoll(struct timeval *tv)
 io_dispatch_epoll(struct timeval *tv)
@@ -516,7 +825,7 @@ io_dispatch_kqueue(struct timeval *tv)
 	int newevents_len;
 	int newevents_len;
 	ts.tv_sec = tv->tv_sec;
 	ts.tv_sec = tv->tv_sec;
 	ts.tv_nsec = tv->tv_usec * 1000;
 	ts.tv_nsec = tv->tv_usec * 1000;
-	
+
 	do {
 	do {
 		newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent));
 		newevents_len = (int) array_length(&io_evcache, sizeof (struct kevent));
 		newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL;
 		newevents = (newevents_len > 0) ? array_start(&io_evcache) : NULL;
@@ -541,10 +850,10 @@ io_dispatch_kqueue(struct timeval *tv)
 #ifdef DEBUG
 #ifdef DEBUG
 				LogDebug("kev.flag has EV_EOF set, setting IO_ERROR",
 				LogDebug("kev.flag has EV_EOF set, setting IO_ERROR",
 					kev[i].filter, kev[i].ident);
 					kev[i].filter, kev[i].ident);
-#endif				
+#endif
 				io_docallback((int)kev[i].ident, IO_ERROR);
 				io_docallback((int)kev[i].ident, IO_ERROR);
 				continue;
 				continue;
-			}	
+			}
 
 
 			switch (kev[i].filter) {
 			switch (kev[i].filter) {
 				case EVFILT_READ:
 				case EVFILT_READ:
@@ -575,14 +884,21 @@ io_dispatch_kqueue(struct timeval *tv)
 int
 int
 io_dispatch(struct timeval *tv)
 io_dispatch(struct timeval *tv)
 {
 {
+#ifdef IO_USE_EPOLL
+	if (io_masterfd >= 0)
+		return io_dispatch_epoll(tv);
+#endif
 #ifdef IO_USE_SELECT
 #ifdef IO_USE_SELECT
 	return io_dispatch_select(tv);
 	return io_dispatch_select(tv);
 #endif
 #endif
 #ifdef IO_USE_KQUEUE
 #ifdef IO_USE_KQUEUE
 	return io_dispatch_kqueue(tv);
 	return io_dispatch_kqueue(tv);
 #endif
 #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
 #endif
 }
 }
 
 
@@ -597,9 +913,9 @@ io_docallback(int fd, short what)
 #endif
 #endif
 	i = io_event_get(fd);
 	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 */
 				   called io_close on this fd */
 		i->callback(fd, (what & IO_ERROR) ? i->what : what);
 		i->callback(fd, (what & IO_ERROR) ? i->what : what);
-	}	
+	}
 	/* if error indicator is set, we return the event(s) that were registered */
 	/* 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
  * 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
 #define io_H_included
 
 
 #include "portab.h"
 #include "portab.h"

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

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -52,7 +52,9 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 	assert( Req != NULL );
 	assert( Req != NULL );
 
 
 	/* Bad number of arguments? */
 	/* 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? */
 	/* Who is the sender? */
 	if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
 	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;
 		chan = NULL; flags = NULL;
 
 
 		/* wird der Channel neu angelegt? */
 		/* 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? */
 		/* Hat ein Server Channel-User-Modes uebergeben? */
 		if( Client_Type( Client ) == CLIENT_SERVER )
 		if( Client_Type( Client ) == CLIENT_SERVER )
@@ -113,8 +124,8 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 				chan = Channel_Search( channame );
 				chan = Channel_Search( channame );
 				assert( chan != NULL );
 				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 */
 				/* Testen, ob Client gebanned ist */
 				if(( is_banned == true) &&  ( is_invited == false ))
 				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 );
 					IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame );
 
 
 					/* Try next name, if any */
 					/* Try next name, if any */
-					channame = strtok( NULL, "," );
+					channame = strchr(channame, ',');
 					continue;
 					continue;
 				}
 				}
 
 
@@ -134,7 +145,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 					IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
 					IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame );
 
 
 					/* Try next name, if any */
 					/* Try next name, if any */
-					channame = strtok( NULL, "," );
+					channame = strchr(channame, ',');
 					continue;
 					continue;
 				}
 				}
 
 
@@ -145,7 +156,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 					IRC_WriteStrClient( Client, ERR_BADCHANNELKEY_MSG, Client_ID( Client ), channame );
 					IRC_WriteStrClient( Client, ERR_BADCHANNELKEY_MSG, Client_ID( Client ), channame );
 
 
 					/* Try next name, if any */
 					/* Try next name, if any */
-					channame = strtok( NULL, "," );
+					channame = strchr(channame, ',');
 					continue;
 					continue;
 				}
 				}
 
 
@@ -156,7 +167,7 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 					IRC_WriteStrClient( Client, ERR_CHANNELISFULL_MSG, Client_ID( Client ), channame );
 					IRC_WriteStrClient( Client, ERR_CHANNELISFULL_MSG, Client_ID( Client ), channame );
 
 
 					/* Try next name, if any */
 					/* Try next name, if any */
-					channame = strtok( NULL, "," );
+					channame = strchr(channame, ',');
 					continue;
 					continue;
 				}
 				}
 			}
 			}
@@ -169,14 +180,14 @@ IRC_JOIN( CLIENT *Client, REQUEST *Req )
 			 * commands) in this list become deleted when a user
 			 * commands) in this list become deleted when a user
 			 * joins a channel this way. */
 			 * joins a channel this way. */
 			chan = Channel_Search( channame );
 			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) */
 		/* Channel joinen (und ggf. anlegen) */
 		if( ! Channel_Join( target, channame ))
 		if( ! Channel_Join( target, channame ))
 		{
 		{
 			/* naechsten Namen ermitteln */
 			/* naechsten Namen ermitteln */
-			channame = strtok( NULL, "," );
+			channame = strchr(channame, ',');
 			continue;
 			continue;
 		}
 		}
 		if( ! chan ) chan = Channel_Search( channame );
 		if( ! chan ) chan = Channel_Search( channame );
@@ -491,7 +502,7 @@ IRC_CHANINFO( CLIENT *Client, REQUEST *Req )
 			{
 			{
 				if( *ptr == 'l' )
 				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 ));
 					strlcat( modes_add, l, sizeof( modes_add ));
 				}
 				}
 				if( *ptr == 'k' )
 				if( *ptr == 'k' )

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

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -542,7 +542,8 @@ GLOBAL bool
 IRC_WHO( CLIENT *Client, REQUEST *Req )
 IRC_WHO( CLIENT *Client, REQUEST *Req )
 {
 {
 	bool ok, only_ops;
 	bool ok, only_ops;
-	char flags[8], *ptr;
+	char flags[8];
+	const char *ptr;
 	CL2CHAN *cl2chan;
 	CL2CHAN *cl2chan;
 	CHANNEL *chan, *cn;
 	CHANNEL *chan, *cn;
 	CLIENT *c;
 	CLIENT *c;
@@ -832,7 +833,10 @@ IRC_WHOWAS( CLIENT *Client, REQUEST *Req )
 GLOBAL bool
 GLOBAL bool
 IRC_Send_LUSERS( CLIENT *Client )
 IRC_Send_LUSERS( CLIENT *Client )
 {
 {
-	long cnt;
+	unsigned long cnt;
+#ifndef STRICT_RFC
+	unsigned long max;
+#endif
 
 
 	assert( Client != NULL );
 	assert( Client != NULL );
 
 
@@ -861,9 +865,17 @@ IRC_Send_LUSERS( CLIENT *Client )
 
 
 #ifndef STRICT_RFC
 #ifndef STRICT_RFC
 	/* Maximum number of local users */
 	/* 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 */
 	/* 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
 #endif
 	
 	
 	return CONNECTED;
 	return CONNECTED;

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

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -45,101 +45,119 @@ static bool Hello_User PARAMS(( CLIENT *Client ));
 static void Kill_Nick PARAMS(( char *Nick, char *Reason ));
 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
 GLOBAL bool
 IRC_PASS( CLIENT *Client, REQUEST *Req )
 IRC_PASS( CLIENT *Client, REQUEST *Req )
 {
 {
+	char *type, *orig_flags;
+	int protohigh, protolow;
+
 	assert( Client != NULL );
 	assert( Client != NULL );
 	assert( Req != 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];
 		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;
 			serverver = ptr + 1;
-			flags = strchr( serverver, ':' );
-			if( flags )
-			{
+			flags = strchr(serverver, ':');
+			if (flags) {
 				*flags = '\0';
 				*flags = '\0';
 				flags++;
 				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 = "";
 			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 */
 } /* IRC_PASS */
 
 
 
 
@@ -268,13 +286,13 @@ IRC_NICK( CLIENT *Client, REQUEST *Req )
 						   "NICK :%s", Req->argv[0] );
 						   "NICK :%s", Req->argv[0] );
 			IRC_WriteStrRelatedPrefix( target, target, false,
 			IRC_WriteStrRelatedPrefix( target, target, false,
 						   "NICK :%s", Req->argv[0] );
 						   "NICK :%s", Req->argv[0] );
-			
+
 			/* Register old nickname for WHOWAS queries */
 			/* Register old nickname for WHOWAS queries */
 			Client_RegisterWhowas( target );
 			Client_RegisterWhowas( target );
-				
+
 			/* Save new nickname */
 			/* Save new nickname */
 			Client_SetID( target, Req->argv[0] );
 			Client_SetID( target, Req->argv[0] );
-			
+
 			IRC_SetPenalty( target, 2 );
 			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;
 	if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), PACKAGE_VERSION, USERMODES, CHANMODES )) return false;
 #endif
 #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 );
 	Client_SetType( Client, CLIENT_USER );
 
 

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

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.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 );
 		if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
 	}
 	}
 	else origin = Client;
 	else origin = Client;
-	
+
 	/* Channel or user mode? */
 	/* Channel or user mode? */
 	cl = NULL; chan = NULL;
 	cl = NULL; chan = NULL;
 	if (Client_IsValidNick(Req->argv[0]))
 	if (Client_IsValidNick(Req->argv[0]))
@@ -268,7 +268,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
 			switch( *mode_ptr )
 			switch( *mode_ptr )
 			{
 			{
 				case 'l':
 				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 ));
 					strlcat( the_args, argadd, sizeof( the_args ));
 					break;
 					break;
 				case 'k':
 				case 'k':
@@ -477,7 +477,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
 					Req->argv[arg_arg][0] = '\0';
 					Req->argv[arg_arg][0] = '\0';
 					arg_arg++;
 					arg_arg++;
 				}
 				}
-				else Lists_ShowInvites( Origin, Channel );
+				else Channel_ShowInvites( Origin, Channel );
 				break;
 				break;
 
 
 			case 'b': /* Ban lists */
 			case 'b': /* Ban lists */
@@ -493,7 +493,7 @@ Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )
 					Req->argv[arg_arg][0] = '\0';
 					Req->argv[arg_arg][0] = '\0';
 					arg_arg++;
 					arg_arg++;
 				}
 				}
-				else Lists_ShowBans( Origin, Channel );
+				else Channel_ShowBans( Origin, Channel );
 				break;
 				break;
 
 
 			default:
 			default:
@@ -644,11 +644,13 @@ Add_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
 
 
 	mask = Lists_MakeMask( 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 );
 	return Send_ListChange( "+I", Prefix, Client, Channel, mask );
 } /* Add_Invite */
 } /* Add_Invite */
@@ -666,11 +668,13 @@ Add_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
 
 
 	mask = Lists_MakeMask( 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 );
 	return Send_ListChange( "+b", Prefix, Client, Channel, mask );
 } /* Add_Ban */
 } /* Add_Ban */
@@ -686,7 +690,7 @@ Del_Invite( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
 	assert( Pattern != NULL );
 	assert( Pattern != NULL );
 
 
 	mask = Lists_MakeMask( Pattern );
 	mask = Lists_MakeMask( Pattern );
-	Lists_DelInvited( mask, Channel );
+	Lists_Del(Channel_GetListInvites(Channel), mask);
 	return Send_ListChange( "-I", Prefix, Client, Channel, mask );
 	return Send_ListChange( "-I", Prefix, Client, Channel, mask );
 } /* Del_Invite */
 } /* Del_Invite */
 
 
@@ -701,7 +705,7 @@ Del_Ban( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, char *Pattern )
 	assert( Pattern != NULL );
 	assert( Pattern != NULL );
 
 
 	mask = Lists_MakeMask( Pattern );
 	mask = Lists_MakeMask( Pattern );
-	Lists_DelBanned( mask, Channel );
+	Lists_Del(Channel_GetListBans(Channel), mask);
 	return Send_ListChange( "-b", Prefix, Client, Channel, mask );
 	return Send_ListChange( "-b", Prefix, Client, Channel, mask );
 } /* Del_Ban */
 } /* Del_Ban */
 
 

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

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.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( 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 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 */
 	/* Inform target client */
 	IRC_WriteStrClientPrefix( target, from, "INVITE %s %s", Req->argv[0], Req->argv[1] );
 	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"
 #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 "imp.h"
 #include <assert.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"
 #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
 GLOBAL bool
 IRC_SERVER( CLIENT *Client, REQUEST *Req )
 IRC_SERVER( CLIENT *Client, REQUEST *Req )
 {
 {
@@ -55,13 +103,16 @@ IRC_SERVER( CLIENT *Client, REQUEST *Req )
 	assert( Client != NULL );
 	assert( Client != NULL );
 	assert( Req != 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? */
 		/* Falsche Anzahl Parameter? */
 		if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
 		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
 					else
 					{
 					{
 						/* "CHANINFO <chan> +<modes> <key> <limit> :<topic>" */
 						/* "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 ...");
 			    "Synchronizing INVITE- and BAN-lists ...");
 #endif
 #endif
 			/* Synchronize INVITE- and BAN-lists */
 			/* Synchronize INVITE- and BAN-lists */
-			if (! Lists_SendInvites(Client))
-				return DISCONNECTED;
-			if (! Lists_SendBans(Client))
+			if (!Synchronize_Lists(Client))
 				return DISCONNECTED;
 				return DISCONNECTED;
 		}
 		}
 #endif
 #endif

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

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -378,7 +378,7 @@ va_dcl
 			}
 			}
 			cl2chan = Channel_NextMember( chan, cl2chan );
 			cl2chan = Channel_NextMember( chan, cl2chan );
 		}
 		}
-		
+
 		/* naechsten Channel */
 		/* naechsten Channel */
 		chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
 		chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan );
 	}
 	}
@@ -403,12 +403,12 @@ GLOBAL void
 IRC_SetPenalty( CLIENT *Client, time_t Seconds )
 IRC_SetPenalty( CLIENT *Client, time_t Seconds )
 {
 {
 	CONN_ID c;
 	CONN_ID c;
-	
+
 	assert( Client != NULL );
 	assert( Client != NULL );
 	assert( Seconds > 0 );
 	assert( Seconds > 0 );
-	
+
 	if( Client_Type( Client ) == CLIENT_SERVER ) return;
 	if( Client_Type( Client ) == CLIENT_SERVER ) return;
-	
+
 	c = Client_Conn( Client );
 	c = Client_Conn( Client );
 	if (c > NONE)
 	if (c > NONE)
 		Conn_SetPenalty(c, Seconds);
 		Conn_SetPenalty(c, Seconds);

+ 91 - 338
src/ngircd/lists.c

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.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 "exp.h"
 #include "lists.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];
 	char mask[MASK_LEN];
-	CHANNEL *channel;
 	bool onlyonce;
 	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( 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;
 		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;
 	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
 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( Mask != NULL );
-	assert( Chan != NULL );
 
 
 	last = 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 *
 GLOBAL char *
@@ -407,82 +212,30 @@ Lists_MakeMask( char *Pattern )
 } /* Lists_MakeMask */
 } /* 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;
 	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;
 	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- */
 /* -eof- */

+ 18 - 18
src/ngircd/lists.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Management of IRC lists: ban, invite, ... (header)
  */
  */
@@ -16,31 +16,31 @@
 
 
 #ifndef __lists_h__
 #ifndef __lists_h__
 #define __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- */
 /* -eof- */

+ 5 - 14
src/ngircd/log.c

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -166,25 +166,21 @@ Log_Exit( void )
  * Log function for debug messages.
  * Log function for debug messages.
  * This function is only functional when the program is compiled with debug
  * This function is only functional when the program is compiled with debug
  * code enabled; otherwise it is an empty function which the compiler will
  * 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 Format Format string like printf().
  * @param ... Further arguments.
  * @param ... Further arguments.
  */
  */
+#ifdef DEBUG
 # ifdef PROTOTYPES
 # ifdef PROTOTYPES
 GLOBAL void
 GLOBAL void
-#ifdef DEBUG
 LogDebug( const char *Format, ... )
 LogDebug( const char *Format, ... )
-#else
-LogDebug( UNUSED const char *Format, ... )
-#endif /* DEBUG */
 # else
 # else
 GLOBAL void
 GLOBAL void
 LogDebug( Format, va_alist )
 LogDebug( Format, va_alist )
 const char *Format;
 const char *Format;
 va_dcl
 va_dcl
 # endif /* PROTOTYPES */
 # endif /* PROTOTYPES */
-#ifdef DEBUG
 {
 {
 	char msg[MAX_LOG_MSG_LEN];
 	char msg[MAX_LOG_MSG_LEN];
 	va_list ap;
 	va_list ap;
@@ -199,14 +195,9 @@ va_dcl
 	va_end( ap );
 	va_end( ap );
 	Log(LOG_DEBUG, "%s", msg);
 	Log(LOG_DEBUG, "%s", msg);
 }
 }
-#else
-{
-	/* Do nothing.
-	 * The compiler should optimize this out, please ;-) */
-}
 #endif	/* DEBUG */
 #endif	/* DEBUG */
 
 
-	
+
 /**
 /**
  * Logging function of ngIRCd.
  * Logging function of ngIRCd.
  * This function logs messages to the console and/or syslog, whichever is
  * 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.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Logging functions (header)
  */
  */
@@ -39,7 +39,13 @@ GLOBAL void Log_Init PARAMS(( bool Daemon_Mode ));
 GLOBAL void Log_Exit PARAMS(( void ));
 GLOBAL void Log_Exit PARAMS(( void ));
 
 
 GLOBAL void Log PARAMS(( int Level, const char *Format, ... ));
 GLOBAL void Log PARAMS(( int Level, const char *Format, ... ));
+
+#ifdef DEBUG
 GLOBAL void LogDebug PARAMS(( const char *Format, ... ));
 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_Init_Resolver PARAMS(( void ));
 GLOBAL void Log_Exit_Resolver PARAMS(( void ));
 GLOBAL void Log_Exit_Resolver PARAMS(( void ));

+ 6 - 6
src/ngircd/match.c

@@ -14,7 +14,7 @@
 
 
 #include "portab.h"
 #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 "imp.h"
 #include <assert.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 */
 #define MATCH_PATTERN	6	/* bad pattern */
@@ -45,7 +45,7 @@ static int Matche_After_Star PARAMS(( char *p, char *t ));
 
 
 
 
 GLOBAL bool
 GLOBAL bool
-Match( char *Pattern, char *String )
+Match( const char *Pattern, const char *String )
 {
 {
 	/* Pattern mit String vergleichen */
 	/* Pattern mit String vergleichen */
 	if( Matche( Pattern, String ) == MATCH_VALID ) return true;
 	if( Matche( Pattern, String ) == MATCH_VALID ) return true;
@@ -54,7 +54,7 @@ Match( char *Pattern, char *String )
 
 
 
 
 static int
 static int
-Matche( char *p, char *t )
+Matche( const char *p, const char *t )
 {
 {
 	register char range_start, range_end;
 	register char range_start, range_end;
 	bool invert;
 	bool invert;
@@ -201,7 +201,7 @@ Matche( char *p, char *t )
 
 
 
 
 static int
 static int
-Matche_After_Star( char *p, char *t )
+Matche_After_Star( const char *p, const char *t )
 {
 {
 	register int nextp, match = 0;
 	register int nextp, match = 0;
 
 

+ 2 - 2
src/ngircd/match.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * Wildcard pattern matching (header)
  */
  */
@@ -18,7 +18,7 @@
 #define __match_h__
 #define __match_h__
 
 
 
 
-GLOBAL bool Match PARAMS(( char *Pattern, char *String ));
+GLOBAL bool Match PARAMS(( const char *Pattern, const char *String ));
 
 
 
 
 #endif
 #endif

+ 9 - 8
src/ngircd/messages.h

@@ -8,7 +8,7 @@
  * (at your option) any later version.
  * (at your option) any later version.
  * Please read the file COPYING, README and AUTHORS for more information.
  * 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)
  * 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_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_CREATED_MSG			"003 %s :This server has been started %s"
 #define RPL_MYINFO_MSG			"004 %s %s ngircd-%s %s %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_TRACELINK_MSG		"200 %s Link %s-%s %s %s V%s %ld %d %d"
 #define RPL_TRACEOPERATOR_MSG		"204 %s Oper 2 :%s"
 #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_ENDOFSTATS_MSG		"219 %s %c :End of STATS report"
 #define RPL_UMODEIS_MSG			"221 %s +%s"
 #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_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_ADMINME_MSG			"256 %s %s :Administrative info"
 #define RPL_ADMINLOC1_MSG		"257 %s :%s"
 #define RPL_ADMINLOC1_MSG		"257 %s :%s"
 #define RPL_ADMINLOC2_MSG		"258 %s :%s"
 #define RPL_ADMINLOC2_MSG		"258 %s :%s"
 #define RPL_ADMINEMAIL_MSG		"259 %s :%s"
 #define RPL_ADMINEMAIL_MSG		"259 %s :%s"
 #define RPL_TRACEEND_MSG		"262 %s %s %s-%s.%s :End of TRACE"
 #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_AWAY_MSG			"301 %s %s :%s"
 #define RPL_USERHOST_MSG		"302 %s :"
 #define RPL_USERHOST_MSG		"302 %s :"

+ 3 - 5
src/ngircd/ngircd.c

@@ -1,6 +1,6 @@
 /*
 /*
  * ngIRCd -- The Next Generation IRC Daemon
  * 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
  * 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
  * it under the terms of the GNU General Public License as published by
@@ -12,7 +12,7 @@
 
 
 #include "portab.h"
 #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
  * @file
@@ -271,7 +271,6 @@ main( int argc, const char *argv[] )
 
 
 		/* Initialize modules, part II: these functions are eventually
 		/* Initialize modules, part II: these functions are eventually
 		 * called with already dropped privileges ... */
 		 * called with already dropped privileges ... */
-		Lists_Init( );
 		Channel_Init( );
 		Channel_Init( );
 		Client_Init( );
 		Client_Init( );
 #ifdef ZEROCONF
 #ifdef ZEROCONF
@@ -328,7 +327,6 @@ main( int argc, const char *argv[] )
 #endif
 #endif
 		Client_Exit( );
 		Client_Exit( );
 		Channel_Exit( );
 		Channel_Exit( );
-		Lists_Exit( );
 		Log_Exit( );
 		Log_Exit( );
 	}
 	}
 	Pidfile_Delete( );
 	Pidfile_Delete( );
@@ -548,7 +546,7 @@ static void
 Show_Version( void )
 Show_Version( void )
 {
 {
 	puts( NGIRCd_Version );
 	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( "Homepage: <http://ngircd.barton.de/>\n" );
 	puts( "This is free software; see the source for copying conditions. There is NO" );
 	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." );
 	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"
 #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 "imp.h"
 #include <assert.h>
 #include <assert.h>
@@ -313,7 +313,8 @@ register_callback( RES_STAT *s, void (*cbfunc)(int, short))
 			return true;
 			return true;
 
 
 	Log( LOG_CRIT, "Resolver: Could not register callback function: %s!", strerror(errno));
 	Log( LOG_CRIT, "Resolver: Could not register callback function: %s!", strerror(errno));
-	Resolve_Shutdown(s);
+	close(s->resolver_fd);
+	Resolve_Init(s);
 	return false;
 	return false;
 }
 }
 
 
@@ -333,40 +334,31 @@ Resolve_Shutdown( RES_STAT *s)
 	return ret;
 	return ret;
 }
 }
 
 
-                
+
 /**
 /**
  * Read result of resolver sub-process from pipe
  * Read result of resolver sub-process from pipe
  */
  */
 GLOBAL size_t
 GLOBAL size_t
 Resolve_Read( RES_STAT *s, void* readbuf, size_t buflen)
 Resolve_Read( RES_STAT *s, void* readbuf, size_t buflen)
 {
 {
-	int err;
 	ssize_t bytes_read;
 	ssize_t bytes_read;
 
 
 	assert(buflen > 0);
 	assert(buflen > 0);
 
 
 	/* Read result from pipe */
 	/* Read result from pipe */
-	errno = 0;
 	bytes_read = read(s->resolver_fd, readbuf, buflen);
 	bytes_read = read(s->resolver_fd, readbuf, buflen);
 	if (bytes_read < 0) {
 	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;
-		}
-		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
 #ifdef DEBUG
+	else if (bytes_read == 0)
 		Log( LOG_DEBUG, "Resolver: Can't read result: EOF");
 		Log( LOG_DEBUG, "Resolver: Can't read result: EOF");
 #endif
 #endif
-		return 0;
-	}
-
+	Resolve_Shutdown(s);
 	return (size_t)bytes_read;
 	return (size_t)bytes_read;
 }
 }
 /* -eof- */
 /* -eof- */

+ 10 - 5
src/testsuite/getpid.sh

@@ -1,16 +1,17 @@
 #!/bin/sh
 #!/bin/sh
 # ngIRCd Test Suite
 # 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?
 # did we get a name?
 [ $# -ne 1 ] && exit 1
 [ $# -ne 1 ] && exit 1
 
 
 # detect flags for "ps" and "head"
 # 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"
   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"
   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"
   PS_FLAGS="-ax"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
 else
 else
   PS_FLAGS="-f"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
   PS_FLAGS="-f"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1"
@@ -19,13 +20,17 @@ else
 fi
 fi
 
 
 # debug output
 # debug output
+#echo "$0: UNAME=$UNAME"
 #echo "$0: PS_FLAGS=$PS_FLAGS"
 #echo "$0: PS_FLAGS=$PS_FLAGS"
 #echo "$0: PS_PIDCOL=$PS_PIDCOL"
 #echo "$0: PS_PIDCOL=$PS_PIDCOL"
 #echo "$0: HEAD_FLAGS=$HEAD_FLAGS"
 #echo "$0: HEAD_FLAGS=$HEAD_FLAGS"
 
 
 # search PID
 # search PID
 ps $PS_FLAGS > procs.tmp
 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`
 pid=`head $HEAD_FLAGS pids.tmp`
 rm -rf procs.tmp pids.tmp
 rm -rf procs.tmp pids.tmp