Index: ChangeLog =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/ChangeLog,v retrieving revision 1.87.2.17 retrieving revision 1.147.2.3 diff -u -r1.87.2.17 -r1.147.2.3 --- ChangeLog 2002/11/24 15:33:14 1.87.2.17 +++ ChangeLog 2002/12/24 13:53:54 1.147.2.3 @@ -10,6 +10,63 @@ -- ChangeLog / Aenderungen -- +ngIRCd 0.6.0, 2002-12-24 + + ngIRCd 0.6.0-pre2, 2002-12-23 + - neuer Numeric 005 ("Features") beim Connect. + - LUSERS erweitert: nun wird die maximale Anzahl der lokalen und globalen + Clients, die dem Server bzw. im Netzwerk seit dem letzten (Re-)Start + dem Server gleichzeitig bekannt waren, angezeigt. + + ngIRCd 0.6.0-pre1, 2002-12-18 + - beim Schliessen einer Verbindung zeigt der Server nun vor dem ERROR + noch eine Statistik ueber die empfangene und gesendete Datenmenge an. + - der Server wartet bei einer eingehenden Verbindung nun laenger auf den + Resolver (4 Sekunden), wenn das Ergebnis eintrifft setzt er aber den + Login sofort fort (bisher wurde immer mind. 1 Sekunde gewartet). + - Connection-Strukturen werden nun "pool-weise" verwaltet; der Pool wird + bei Bedarf bis zu einem konfigurierten Limit vergroessert. + - Mit der neuen Konfigurationsvariable "MaxConnections" (Sektion "Global") + kann die maximale Anzahl gleichzeitiger Verbindungen begrenzt werden. + Der Default ist -1, "unlimitiert". + - der Server erkennt nun, ob bereits eine eingehende Verbindung von einem + Peer-Server besteht und versucht dann nicht mehr, selber eine eigene + ausgehende Verbindung zu diesem auufzubauen. Dadurch kann nun auf beiden + Servern in der Konfiguration ein Port fuer den Connect konfiguriert + werden (beide Server versuchen sich dann gegenseitig zu connectieren). + - Test-Suite und Dokumentation an A/UX angepasst. + - unter HP-UX definiert das configure-Script nun _XOPEN_SOURCE_EXTENDED. + - Server identifizieren sich nun mit asyncronen Passwoertern, d.h. das + Passwort, welches A an B schickt, kann ein anderes sein als das, welches + B als Antwort an A sendet. In der Konfig.-Datei, Abschnitt "Server", + wurde "Password" dazu durch "MyPassword" und "PeerPassword" ersetzt. + - Der Server kann nun zur Laufzeit die Konfiguration neu einlesen: dies + macht er nach dem Befehl REHASH oder wenn ein HUP-Signal empfangen wird. + - Channel-Mode "P" ("persistent") kann nur noch von IRC-Operatoren gesetzt + werden. Grund: User koennen den Server sonst leicht "Channel-Flooden". + - MOTD kann nun an andere Server geforwarded werden. + - IRC-Befehl "TIME" implementiert. + - Server-Server-Links koennen nun komprimiert werden, dazu wird die zlib + (www.zlib.org) benoetigt. Unterstuetzt die Gegenseite die Komprimierung + nicht, wird automatisch unkomprimiert kommuniziert. Das Verfahren ist + kompatibel mit dem Original-ircd 2.10.3, d.h. beide Server koennen + miteinander ueber komprimiert Links kommunizieren. + - Handling der Schreibpuffer umgestellt: Server sollte schneller arbeiten. + - Prefix-Fehler werden besser protokolliert (mit verursachendem Befehl). + - SQUIT wird nicht mehr doppelt an andere Server weitergeleitet. + - Der Server versucht nun vor dem Schliessen einer Verbindung Daten, die + noch im Schreibpuffer stehen, zu senden. + - Source in weiteres Modul "irc-info" aufgespalten. + - Konfigurationsvariablen werden besser validiert: Laengen, Zahlen, ... + - neuen Befehl STATS begonnen: bisher unterstuetzt wird "l" und "m". + - bei ISON und USERHOST fehlte im Ergebnis-String der korrekte Absender. + - IRC Operatoren koennen nun mit KILL User toeten. Achtung: ein Grund muss + zwingend als zweiter Parameter angegeben werden! + - neue Konfigurations-Variable "MaxJoins": Hiermit kann die maximale Zahl + der Channels, in denen ein User Mitglied sein kann, begrent werden. + - neuer, deutlich flexiblerer Parser fuer den MODE Befehl. + - neue Channel-Modes l (User-Limit) und k (Channel-Key) implementiert. + ngIRCd 0.5.4, 24.11.2002 - Fehler-Handling von connect() gefixed: der Server kann sich nun auch @@ -266,7 +323,6 @@ - Clients werden nun korrekt sowohl nur ueber den Nickname als auch die komplette "Host Mask" erkannt. - ngIRCd 0.0.3, 16.01.2002 - Server-Links vollstaendig implementiert: der ngIRCd kann nun auch @@ -313,4 +369,4 @@ -- -$Id: ChangeLog,v 1.87.2.17 2002/11/24 15:33:14 alex Exp $ +$Id: ChangeLog,v 1.147.2.3 2002/12/24 13:53:54 alex Exp $ Index: INSTALL =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/INSTALL,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- INSTALL 2002/09/16 11:03:05 1.8 +++ INSTALL 2002/12/18 12:19:07 1.9 @@ -18,6 +18,20 @@ +-----------------------------------------------------------------------+ +0. Update von frueheren Versionen +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Unterschiede zu Version 0.5.x + +- Ab Version 0.6.0 werden asyncrone Passwoerter zur Identifikation anderer + Server, die Variable "Password" in [Server]-Abschnitten wird nicht mehr + unterstuetzt. Passwoerter fuer Server-Server-Links werden nun mit den + Variablen "MyPassword" und "PeerPassword" angegeben. + +- Neue Konfigurationsvariablen, Sektion [Global]: MaxConnections, MaxJoins + (vgl. auch Beispiel-Konfiguration "doc/sample-ngircd.conf"!) + + I. Standard-Installation ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -145,4 +159,4 @@ -- -$Id: INSTALL,v 1.8 2002/09/16 11:03:05 alex Exp $ +$Id: INSTALL,v 1.9 2002/12/18 12:19:07 alex Exp $ Index: Makefile.am =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/Makefile.am,v retrieving revision 1.9.2.1 retrieving revision 1.10 diff -u -r1.9.2.1 -r1.10 --- Makefile.am 2002/10/03 16:13:38 1.9.2.1 +++ Makefile.am 2002/10/01 09:57:08 1.10 @@ -9,7 +9,7 @@ # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. # -# $Id: Makefile.am,v 1.9.2.1 2002/10/03 16:13:38 alex Exp $ +# $Id: Makefile.am,v 1.10 2002/10/01 09:57:08 alex Exp $ # AUTOMAKE_OPTIONS = gnu Index: NEWS =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/NEWS,v retrieving revision 1.38.2.4 retrieving revision 1.45.2.2 diff -u -r1.38.2.4 -r1.45.2.2 --- NEWS 2002/10/03 16:09:50 1.38.2.4 +++ NEWS 2002/12/24 13:53:54 1.45.2.2 @@ -10,6 +10,35 @@ -- NEWS / Neuigkeiten -- +ngIRCd 0.6.0, 2002-12-24 + + - beim Schliessen einer Verbindung zeigt der Server nun vor dem ERROR + noch eine Statistik ueber die empfangene und gesendete Datenmenge an. + - Connection-Strukturen werden nun "pool-weise" verwaltet; der Pool wird + bei Bedarf bis zu einem konfigurierten Limit vergroessert. + - Mit der neuen Konfigurationsvariable "MaxConnections" (Sekion "Global") + kann die maximale Anzahl gleichzeitiger Verbindungen begrenzt werden. + Der Default ist -1, "unlimitiert". + - der Server erkennt nun, ob bereits eine eingehende Verbindung von einem + Peer-Server besteht und versucht dann nicht mehr, selber eine eigene + ausgehende Verbindung zu diesem auufzubauen. Dadurch kann nun auf beiden + Servern in der Konfiguration ein Port fuer den Connect konfiguriert + werden (beide Server versuchen sich dann gegenseitig zu connectieren). + - Server identifizieren sich nun mit asyncronen Passwoertern, d.h. das + Passwort, welches A an B schickt, kann ein anderes sein als das, welches + B als Antwort an A sendet. In der Konfig.-Datei, Abschnitt "Server", + wurde "Password" dazu durch "MyPassword" und "PeerPassword" ersetzt. + - Der Server kann nun zur Laufzeit die Konfiguration neu einlesen: dies + macht er nach dem Befehl REHASH oder wenn ein HUP-Signal empfangen wird. + - Server-Server-Links koennen nun komprimiert werden, dazu wird die zlib + (www.zlib.org) benoetigt. Unterstuetzt die Gegenseite die Komprimierung + nicht, wird automatisch unkomprimiert kommuniziert. Das Verfahren ist + kompatibel mit dem Original-ircd 2.10.3, d.h. beide Server koennen + miteinander ueber komprimiert Links kommunizieren. + - neue Konfigurations-Variable "MaxJoins": Hiermit kann die maximale Zahl + der Channels, in denen ein User Mitglied sein kann, begrent werden. + - neue Channel-Modes l (User-Limit) und k (Channel-Key) implementiert. + ngIRCd 0.5.0, 20.09.2002 - AIX (3.2.5), HP-UX (10.20), IRIX (6.5), NetBSD (1.5.3/m68k) und Solaris @@ -18,15 +47,15 @@ dem "nativen" (ggf. pre-ANSI) Compiler. - "persistente Channels" (Mode 'P') implementiert: diese koennen in der Konfigurationsdatei definiert werden (Sektion "Channel", vgl. Beispiel- - Konfiguration "sample-ngircd.conf") und bleiben auch dann bestehen, + Konfiguration "sample-ngircd.conf") und bleiben auch dann bestehen, wenn kein User mehr im Channel ist. - - neue IRC-Befehle: KICK, INVITE, ADMIN, CHANINFO; LIST wurde erweitert. - Mit dem neuen Befehl CHANINFO syncronisieren Server, die das IRC+- + - neue IRC-Befehle: KICK, INVITE, ADMIN, CHANINFO; LIST wurde erweitert. + Mit dem neuen Befehl CHANINFO syncronisieren Server, die das IRC+- Protokoll unterstuetzen, Channel-Modes und Topics. Fuer den ADMIN-Befehl gibt es neue Konfigurationsoptionen (Sektion "Global"): "AdminInfo1", "AdminInfo2" und "AdminEMail". - - Invite- und Ban-Lists implementiert. - - neue Konfigurationsoption "OperCanUseMode" (Sektion "Global"): + - Invite- und Ban-Lists implementiert. + - neue Konfigurationsoption "OperCanUseMode" (Sektion "Global"): ist sie aktiv, koennen IRC-Operatoren immer Channel-Modes setzen. - "Test-Suite" begonnen: mit "make check" wird sie durchlaufen. @@ -110,4 +139,4 @@ -- -$Id: NEWS,v 1.38.2.4 2002/10/03 16:09:50 alex Exp $ +$Id: NEWS,v 1.45.2.2 2002/12/24 13:53:54 alex Exp $ Index: README =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/README,v retrieving revision 1.13 retrieving revision 1.14 diff -u -r1.13 -r1.14 --- README 2002/09/16 11:03:05 1.13 +++ README 2002/11/24 18:48:59 1.14 @@ -38,8 +38,8 @@ ADMIN, AWAY, CHANINFO, CONNECT, DIE, ERROR, INVITE, ISON, JOIN, KICK, KILL, LINKS, LIST, LUSERS, MODE, MOTD, NAMES, NICK, NJOIN, NOTICE, OPER, PART, -PASS, PING, PONG, PRIVMSG, QUIT, RESTART, SERVER, SQUIT, TOPIC, USERHOST, -USER, VERSION, WHO, WHOIS. +PASS, PING, PONG, PRIVMSG, QUIT, RESTART, SERVER, SQUIT, TIME, TOPIC, +USERHOST, USER, VERSION, WHO, WHOIS. III. Features (oder: warum gerade ngIRCd?) @@ -102,4 +102,4 @@ -- -$Id: README,v 1.13 2002/09/16 11:03:05 alex Exp $ +$Id: README,v 1.14 2002/11/24 18:48:59 alex Exp $ Index: configure.in =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/configure.in,v retrieving revision 1.58.2.10 retrieving revision 1.69.2.3 diff -u -r1.58.2.10 -r1.69.2.3 --- configure.in 2002/11/24 15:33:26 1.58.2.10 +++ configure.in 2002/12/24 13:54:09 1.69.2.3 @@ -9,7 +9,7 @@ # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. # -# $Id: configure.in,v 1.58.2.10 2002/11/24 15:33:26 alex Exp $ +# $Id: configure.in,v 1.69.2.3 2002/12/24 13:54:09 alex Exp $ # # -- Initialisierung -- @@ -18,7 +18,7 @@ AC_PREREQ(2.50) AC_CANONICAL_TARGET AC_CONFIG_SRCDIR(src/config.h.in) -AM_INIT_AUTOMAKE(ngircd,0.5.4) +AM_INIT_AUTOMAKE(ngircd,0.6.0) AM_CONFIG_HEADER(src/config.h) # -- Templates fuer config.h -- @@ -28,6 +28,7 @@ AH_TEMPLATE([SNIFFER], [Define if IRC sniffer should be enabled]) AH_TEMPLATE([STRICT_RFC], [Define if ngIRCd should behave strict RFC compliant]) AH_TEMPLATE([USE_SYSLOG], [Define if syslog should be used for logging]) +AH_TEMPLATE([USE_ZLIB], [Define if zlib compression should be enabled]) AH_TEMPLATE([IRCPLUS], [Define if IRC+ protocol should be used]) AH_TEMPLATE([TARGET_OS], [Target operating system name]) @@ -53,6 +54,20 @@ AM_C_PROTOTYPES AC_C_CONST +# -- Defines -- + +if test `uname` = "A/UX"; then + # unter A/UX sollte _POSIX_SOURCE definiert sein. + AC_MSG_RESULT([detected A/UX, defining _POSIX_SOURCE]) + CFLAGS="$CFLAGS -D_POSIX_SOURCE" +fi + +if test `uname` = "HP-UX"; then + # unter HP-UX 11.11 muss _XOPEN_SOURCE_EXTENDED definiert sein. + AC_MSG_RESULT([detected HP-UX, defining _XOPEN_SOURCE_EXTENDED]) + CFLAGS="$CFLAGS -D_XOPEN_SOURCE_EXTENDED" +fi + # -- Header -- AC_HEADER_STDC @@ -66,7 +81,7 @@ strings.h sys/socket.h sys/time.h unistd.h \ ],,AC_MSG_ERROR([required C header missing!])) -AC_CHECK_HEADERS(arpa/inet.h malloc.h stdint.h sys/select.h varargs.h) +AC_CHECK_HEADERS(arpa/inet.h ctype.h malloc.h stdint.h sys/select.h varargs.h) # -- Datentypen -- @@ -107,7 +122,7 @@ strstr waitpid \ ],,AC_MSG_ERROR([required function missing!])) -AC_CHECK_FUNCS(inet_aton sigaction snprintf vsnprintf) +AC_CHECK_FUNCS(inet_aton isdigit sigaction snprintf vsnprintf) # -- Konfigurationsoptionen -- @@ -127,6 +142,22 @@ AC_CHECK_LIB(be,syslog) fi +x_zlib_on=no +AC_ARG_ENABLE(zlib, + [ --disable-zlib disable zlib compression (autodetected by default)], + [ if test "$enableval" = "yes"; then + AC_CHECK_HEADER(zlib.h, x_zlib_on=yes, + AC_MSG_ERROR([Can't enable zlib: zlib.h not found!]) + ) + fi + ], + [ AC_CHECK_HEADER(zlib.h, x_zlib_on=yes) ] +) +if test "$x_zlib_on" = "yes"; then + AC_DEFINE(USE_ZLIB, 1) + AC_CHECK_LIB(z,deflate) +fi + x_ircplus_on=yes AC_ARG_ENABLE(ircplus, [ --disable-ircplus disable IRC+ protocol], @@ -167,18 +198,14 @@ AC_DEFINE_UNQUOTED(TARGET_VENDOR, "$target_vendor" ) AC_DEFINE_UNQUOTED(TARGET_OS, "$target_os" ) -if test `uname` = "A/UX"; then - # unter A/UX sollte _POSIX_SOURCE definiert sein. - AC_MSG_RESULT([detected A/UX, defining _POSIX_SOURCE]) - CFLAGS="$CFLAGS -D_POSIX_SOURCE" -fi - # -- Variablen -- if test "$GCC" = "yes"; then CFLAGS="-Wall $CFLAGS" fi +the_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -DSYSCONFDIR='\"\$(sysconfdir)\"'" # -- Ausgabe der Dateien -- @@ -209,12 +236,11 @@ echo " host: ${host}" echo " compiler: ${CC}" -echo " compiler flags: ${CFLAGS}" +echo " compiler flags: ${the_CFLAGS}" echo " preprocessor flags: ${CPPFLAGS}" echo " linker flags: ${LDFLAGS}" echo " libraries: ${LIBS}" echo - echo " 'ngircd' binary: $S" echo " configuration file: $C" echo " manual pages: $M" @@ -222,6 +248,7 @@ echo $ECHO_N " active options: $ECHO_C" test "$x_syslog_on" = "yes" && echo $ECHO_N "Syslog $ECHO_C" +test "$x_zlib_on" = "yes" && echo $ECHO_N "zLib $ECHO_C" test "$x_debug_on" = "yes" && echo $ECHO_N "Debug $ECHO_C" test "$x_sniffer_on" = "yes" && echo $ECHO_N "Sniffer $ECHO_C" test "$x_strict_rfc_on" = "yes" && echo $ECHO_N "Strict-RFC $ECHO_C" Index: MacOSX/ngircd.pbproj/project.pbxproj =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/MacOSX/ngircd.pbproj/project.pbxproj,v retrieving revision 1.21 retrieving revision 1.24 diff -u -r1.21 -r1.24 --- MacOSX/ngircd.pbproj/project.pbxproj 2002/09/16 11:03:30 1.21 +++ MacOSX/ngircd.pbproj/project.pbxproj 2002/11/30 17:39:56 1.24 @@ -66,9 +66,10 @@ 08FB7794FE84155DC02AAC07 = { children = ( 1AB674ADFE9D54B511CA2CBB, + F56D8B9E01E0BFA00155ADA7, + F5D3536103892A8A01A85B04, F51F791401DFD0DE01D13771, F520AF150335F1B801A85B04, - F56D8B9E01E0BFA00155ADA7, F52162B301C7B904012300F4, F52162C301C7B904012300F4, F52162C401C7B904012300F4, @@ -93,11 +94,13 @@ ); buildSettings = { FRAMEWORK_SEARCH_PATHS = ""; + GCC_TREAT_WARNINGS_AS_ERRORS = YES; HEADER_SEARCH_PATHS = ""; INSTALL_PATH = "$(HOME)/bin"; LIBRARY_SEARCH_PATHS = ""; - OTHER_CFLAGS = "-DLOCALSTATEDIR=\\\\\\\"/usr/local/var\\\\\\\" -DSYSCONFDIR=\\\\\\\"/usr/local/etc\\\\\\\""; - OTHER_LDFLAGS = ""; + OPTIMIZATION_CFLAGS = "-O2"; + OTHER_CFLAGS = "-DSYSCONFDIR=\\\\\\\"/usr/local/etc\\\\\\\""; + OTHER_LDFLAGS = "-lz"; OTHER_REZFLAGS = ""; PRODUCT_NAME = ngircd; REZ_EXECUTABLE = YES; @@ -143,6 +146,7 @@ F5BEF12E02A1169C01A85B03, F5BEF13302A12AFE01A85B03, F5E9448502C9F49D01A85B04, + F5D5CC9403990FED0155B873, ); isa = PBXHeadersBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -171,6 +175,7 @@ F5BEF12F02A1169C01A85B03, F5BEF13502A24F1001A85B03, F5E9448602C9F49D01A85B04, + F5D5CC9603990FFA0155B873, ); isa = PBXSourcesBuildPhase; runOnlyForDeploymentPostprocessing = 0; @@ -579,6 +584,8 @@ F51D180301C8FDD001E11C2E, F57C888D02328D7201A85B04, F57C888E02328D7201A85B04, + F5D5CC9503990FFA0155B873, + F5D5CC9303990FED0155B873, F51DBB1B022D9D8F01A85B04, F51DBB1C022D9D8F01A85B04, F51DBB17022D995501A85B04, @@ -820,6 +827,8 @@ F5382426024F89BC01A85B04, ); buildSettings = { + GCC_TREAT_WARNINGS_AS_ERRORS = YES; + OPTIMIZATION_CFLAGS = "-O2"; OTHER_CFLAGS = ""; OTHER_LDFLAGS = ""; OTHER_REZFLAGS = ""; @@ -1140,11 +1149,61 @@ settings = { }; }; + F5D3536103892A8A01A85B04 = { + children = ( + F5D3536203892AD201A85B04, + F5D3536303892AD201A85B04, + ); + isa = PBXGroup; + name = contrib; + refType = 4; + }; + F5D3536203892AD201A85B04 = { + isa = PBXFileReference; + name = Makefile.am; + path = /Users/alex/Develop/ngircd/contrib/Makefile.am; + refType = 0; + }; + F5D3536303892AD201A85B04 = { + isa = PBXFileReference; + name = ngircd.spec; + path = /Users/alex/Develop/ngircd/contrib/ngircd.spec; + refType = 0; + }; + F5D3536403892AFE01A85B04 = { + isa = PBXFileReference; + name = "sample-ngircd.conf"; + path = "en/sample-ngircd.conf"; + refType = 4; + }; + F5D5CC9303990FED0155B873 = { + isa = PBXFileReference; + path = "irc-info.h"; + refType = 4; + }; + F5D5CC9403990FED0155B873 = { + fileRef = F5D5CC9303990FED0155B873; + isa = PBXBuildFile; + settings = { + }; + }; + F5D5CC9503990FFA0155B873 = { + isa = PBXFileReference; + path = "irc-info.c"; + refType = 4; + }; + F5D5CC9603990FFA0155B873 = { + fileRef = F5D5CC9503990FFA0155B873; + isa = PBXBuildFile; + settings = { + }; + }; F5E9447B02C9EE0E01A85B04 = { children = ( F5E9448002C9EE4901A85B04, F5E9448202C9EE4901A85B04, F5E9448102C9EE4901A85B04, + F5D3536403892AFE01A85B04, ); isa = PBXGroup; name = en; Index: contrib/Makefile.am =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/contrib/Makefile.am,v retrieving revision 1.1.2.1 retrieving revision 1.1 diff -u -r1.1.2.1 -r1.1 --- contrib/Makefile.am 2002/10/03 16:13:38 1.1.2.1 +++ contrib/Makefile.am 2002/10/01 09:57:08 1.1 @@ -9,7 +9,7 @@ # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. # -# $Id: Makefile.am,v 1.1.2.1 2002/10/03 16:13:38 alex Exp $ +# $Id: Makefile.am,v 1.1 2002/10/01 09:57:08 alex Exp $ # EXTRA_DIST = ngircd.spec Index: contrib/ngircd.spec =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/contrib/ngircd.spec,v retrieving revision 1.1.2.7 retrieving revision 1.2.2.3 diff -u -r1.1.2.7 -r1.2.2.3 --- contrib/ngircd.spec 2002/11/24 15:33:26 1.1.2.7 +++ contrib/ngircd.spec 2002/12/24 13:54:09 1.2.2.3 @@ -1,5 +1,5 @@ %define name ngircd -%define version 0.5.4 +%define version 0.6.0 %define release 1 %define prefix %{_prefix} Index: doc/README-AUX.txt =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/doc/README-AUX.txt,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- doc/README-AUX.txt 2002/04/29 14:19:48 1.3 +++ doc/README-AUX.txt 2002/11/11 00:59:11 1.4 @@ -11,37 +11,33 @@ Seit Version 0.2.2-pre gehoert Apple A/UX zu den offiziell unterstuetzten -Platformen. Er ist im vollen Funktionsumfang nutzbar. +Plattformen. Er ist im vollen Funktionsumfang nutzbar. -Folgende Software wird jedoch benoetigt: - - - GNU C Compiler (gcc) - Bezugsquellen: - http://www.rezepte-im-web.de/appleux/gcc281.tar.gz - ftp://arthur.ath.cx/pub/AUX/Software/Development/gcc-2.8.1-auxbin.tar.gz +Ab Version 0.5.0 compiliert zudem der ngIRCd mit dem nativen A/UX-Compiler, +d.h. GNU C wird nicht mehr zwingend vorausgesetzt. - - GNU make - Bezugsquellen: - http://www.rezepte-im-web.de/appleux/make-3.79.tar.gz - ftp://arthur.ath.cx/pub/AUX/Software/Development/make-3.79.tar.gz +Folgende Software wird jedoch benoetigt: - GNU sed Bezugsquellen: http://www.rezepte-im-web.de/appleux/sed-3.02.tar.gz ftp://arthur.ath.cx/pub/AUX/Software/Tools/sed-3.02.tar.gz - - install (z.B. aus den GNU fileutils) - Ein install, welches entweder so "broken" ist, dass configure das eigene - Shell-Script waehlt, oder eines, das funktioniert. Leider ist mindestens - ein Binary im Umlauf, das Probleme macht. - Bezugsquelle: - ftp://arthur.ath.cx/pub/UNIX/AUX/Software/Tools/fileutils-4.0.tar.gz + A/UX beinhaltet ein /bin/sed, dieses unterstuetzt jedoch leider nicht + alle Funktionen, die GNU automake/autoconf nutzen. + Achtung: bitte bei der Installation von GNU sed sicherstellen, dass + immer dieses und nie das von A/UX verwendet wird (also $PATH entsprechend + anpassen bzw. die A/UX-Version komplett ersetzen)! - libUTIL.a Bezugsquellen: http://ftp.mayn.de/pub/apple/apple_unix/Sys_stuff/libUTIL-2.1.tar.gz ftp://arthur.ath.cx/pub/AUX/Software/Libraries/libUTIL-2.1.tar.gz + Diese Library beinhaltet Systemfunktionen, die auf UNIXoiden Systemen + gaengig, unter A/UX jedoch leider nicht verfuegbar sind. Dazu gehoert + u.a. memmove(), strerror() und strdup(). + Nachdem diese Pakete entsprechend installiert sind, reicht ein ganz normales "./configure" und "make" aus, um den ngIRCd unter A/UX zu compilieren. @@ -59,13 +55,14 @@ unbedingt ausserhalb von /bin (z.B. unter /usr/local/bin) installiert werden. Ansonsten waehlt es das configure-Script als Shell aus, leider funktioniert das aber nicht. - Das config.status-Script sollte mit der ksh als Interpreter erstellt - worden sein (siehe erste Zeile davon!). - -Hier die Zeiten von Alex System (Macintosh SE/30, 32 MB, A/UX 3.0.1): -configure: 7:33, make: 12:02 + - da die /bin/sh von A/UX recht limitiert ist, kann sie u.a. nicht zum + Erzeugen des "config.status"-Scripts verwendet werden. + Abhilfe: /bin/sh umbenennen (z.B. in "/bin/sh.AUX") und durch einen (am + besten symbolischen) Link auf /bin/ksh ersetzen. + Dieser Schritt sollte keine Probleme nach sich ziehen und ist daher immer, + auch unabhaengig vom ngIRCd, empfehlenswert. -- -$Id: README-AUX.txt,v 1.3 2002/04/29 14:19:48 alex Exp $ +$Id: README-AUX.txt,v 1.4 2002/11/11 00:59:11 alex Exp $ Index: doc/sample-ngircd.conf =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/doc/sample-ngircd.conf,v retrieving revision 1.11 retrieving revision 1.17 diff -u -r1.11 -r1.17 --- doc/sample-ngircd.conf 2002/09/16 10:33:09 1.11 +++ doc/sample-ngircd.conf 2002/12/18 12:19:07 1.17 @@ -1,4 +1,4 @@ -# $Id: sample-ngircd.conf,v 1.11 2002/09/16 10:33:09 alex Exp $ +# $Id: sample-ngircd.conf,v 1.17 2002/12/18 12:19:07 alex Exp $ # # Das ist eine Beispiel-Konfiguration fuer den ngIRCd, die an die @@ -6,6 +6,11 @@ # # Kommentare werden mit "#" oder ";" eingeleitet. # +# +-----------------------------------------------------------------------+ +# | Please note: English translations of some of the german documentation | +# | files can be found in the directory "doc/en" -- please have a look! | +# +-----------------------------------------------------------------------+ +# # Autor: Alexander Barton, # Erweiterungen von Ilja Osthoff, # @@ -42,14 +47,16 @@ ;MotdFile = /usr/local/etc/ngircd.motd # User-ID, unter der der Daemon laufen soll (dazu muss der Server - # jedoch mit root-Rechten gestartet werden). + # jedoch mit root-Rechten gestartet werden). Es kann der Name oder + # die numerische ID angegeben werden. # ACHTUNG: Die Konfigurations- und MOTD-Datei muessen fuer diesen # Benutzer lesbar sein, ansonsten schlaegt ein RESTART fehl! - ;ServerUID = 65534 + ;ServerUID = ircd # Group-ID, zu der der Daemon wechseln soll (hierzu muss der Server - # jedoch mit root-Rechten gestartet werden) - ;ServerGID = 65534 + # jedoch mit root-Rechten gestartet werden). Es kann der Name oder + # die numerische ID angegeben werden. + ;ServerGID = daemon # Nach Sekunden verschickt der Server bei Inaktivitaet # von einem Client diesem ein PING. @@ -67,6 +74,14 @@ # koennen, auch wenn sie kein(!) Channel-Operator sind? ;OperCanUseMode = no + # Maximale Anzahl von gleichzeitigen Verbindungen, die dieser + # Server annehmen darf (<=0: unlimitiert). + ;MaxConnections = -1 + + # Maximale Anzahl von Channels, in denen ein User zeitgleich + # Mitglied sein kann (<=0: unlimitiert). + ;MaxJoins = 10 + [Operator] # @@ -104,19 +119,24 @@ # die Gegenseite angegeben hat! # - # Hostname des Servers - ;Host = connect-to-host.the.net - # IRC-Name des Servers ;Name = irc2.the.net + # DNS-Hostname des Servers + ;Host = connect-to-host.the.net + # Port, zu dem dieser Server eine Verbindung herstellen soll. Wird # kein Port angegeben, so wird auf eine Verbindung der Gegenseite # gewartet. ;Port = 6666 - # Passwort fuer diese Verbindung - ;Password = ThePwd1 + # Eigenes Passwort fuer diese Verbindung. Dieses Passwort muss auf + # dem anderen Server als "PeerPassword" konfiguriert werden. + ;MyPassword = MySecret + + # Passwort des Peer-Servers fuer diese Verbindung. Dieses Passwort + # muss auf dem anderen Server als "MyPassword" konfiguriert sein. + ;PeerPassword = PeerSecret # Gruppe, zu der dieser Server gehoert (optional). ;Group = 123 Index: doc/en/INSTALL =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/doc/en/INSTALL,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- doc/en/INSTALL 2002/05/20 12:02:58 1.2 +++ doc/en/INSTALL 2002/12/18 12:19:07 1.3 @@ -11,6 +11,19 @@ +0. Upgrade Information +~~~~~~~~~~~~~~~~~~~~~~ + +Differences to version 0.5.x + +- Starting with version 0.6.0, other servers are identified using asyncronous + passwords: therefore the variable "Password" in [Server]-sections has been + replaced by "MyPassword" and "PeerPassword". + +- New configuration variables, section [Global]: MaxConnections, MaxJoins + (see example configuration file "doc/en/sample-ngircd.conf"!). + + I. Standard-Installation ~~~~~~~~~~~~~~~~~~~~~~~~ @@ -123,4 +136,4 @@ -- -$Id: INSTALL,v 1.2 2002/05/20 12:02:58 alex Exp $ +$Id: INSTALL,v 1.3 2002/12/18 12:19:07 alex Exp $ Index: doc/en/Makefile.am =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/doc/en/Makefile.am,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- doc/en/Makefile.am 2002/05/09 10:17:05 1.1 +++ doc/en/Makefile.am 2002/11/18 14:06:29 1.2 @@ -9,10 +9,10 @@ # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. # -# $Id: Makefile.am,v 1.1 2002/05/09 10:17:05 alex Exp $ +# $Id: Makefile.am,v 1.2 2002/11/18 14:06:29 alex Exp $ # -EXTRA_DIST = INSTALL README +EXTRA_DIST = INSTALL README sample-ngircd.conf maintainer-clean-local: rm -f Makefile Makefile.in Index: doc/en/README =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/doc/en/README,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- doc/en/README 2002/09/16 11:03:05 1.6 +++ doc/en/README 2002/11/24 18:48:59 1.7 @@ -32,8 +32,8 @@ ADMIN, AWAY, CHANINFO, CONNECT, DIE, ERROR, INVITE, ISON, JOIN, KICK, KILL, LINKS, LIST, LUSERS, MODE, MOTD, NAMES, NICK, NJOIN, NOTICE, OPER, PART, -PASS, PING, PONG, PRIVMSG, QUIT, RESTART, SERVER, SQUIT, TOPIC, USERHOST, -USER, VERSION, WHO, WHOIS. +PASS, PING, PONG, PRIVMSG, QUIT, RESTART, SERVER, SQUIT, TIME, TOPIC, +USERHOST, USER, VERSION, WHO, WHOIS. III. Features (or: why use ngIRCd?) @@ -98,4 +98,4 @@ -- -$Id: README,v 1.6 2002/09/16 11:03:05 alex Exp $ +$Id: README,v 1.7 2002/11/24 18:48:59 alex Exp $ Index: man/ngircd.8 =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/man/ngircd.8,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- man/ngircd.8 2002/09/16 11:11:21 1.4 +++ man/ngircd.8 2002/11/18 18:49:34 1.5 @@ -1,5 +1,5 @@ .\" -.\" $Id: ngircd.8,v 1.4 2002/09/16 11:11:21 alex Exp $ +.\" $Id: ngircd.8,v 1.5 2002/11/18 18:49:34 alex Exp $ .\" .TH ngircd 8 "September 2002" ngircd "ngIRCd Manual" .SH NAME @@ -24,7 +24,7 @@ .I file as configuration file. .IP "-n, --nodaemon" -don't fork and don't detatch from controlling terminal. +don't fork and don't detach from controlling terminal. .IP "-p, --passive" disable automatic connections to other servers. .IP --version Index: src/ngircd/Makefile.am =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/Makefile.am,v retrieving revision 1.27 retrieving revision 1.31 diff -u -r1.27 -r1.31 --- src/ngircd/Makefile.am 2002/09/07 18:06:29 1.27 +++ src/ngircd/Makefile.am 2002/12/12 12:36:41 1.31 @@ -9,7 +9,7 @@ # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. # -# $Id: Makefile.am,v 1.27 2002/09/07 18:06:29 alex Exp $ +# $Id: Makefile.am,v 1.31 2002/12/12 12:36:41 alex Exp $ # AUTOMAKE_OPTIONS = ../portab/ansi2knr @@ -21,20 +21,20 @@ sbin_PROGRAMS = ngircd ngircd_SOURCES = ngircd.c channel.c client.c conf.c conn.c hash.c irc.c \ - irc-channel.c irc-login.c irc-mode.c irc-op.c irc-oper.c irc-server.c \ - irc-write.c lists.c log.c match.c parse.c resolve.c tool.c + irc-channel.c irc-info.c irc-login.c irc-mode.c irc-op.c irc-oper.c \ + irc-server.c irc-write.c lists.c log.c match.c parse.c resolve.c tool.c ngircd_LDFLAGS = -L../portab ngircd_LDADD = -lngportab noinst_HEADERS = ngircd.h channel.h client.h conf.h conn.h hash.h irc.h \ - irc-channel.h irc-login.h irc-mode.h irc-op.h irc-oper.h irc-server.h \ - irc-write.h lists.h log.h match.h parse.h resolve.h tool.h \ + irc-channel.h irc-info.h irc-login.h irc-mode.h irc-op.h irc-oper.h \ + irc-server.h irc-write.h lists.h log.h match.h parse.h resolve.h tool.h \ messages.h defines.h clean-local: - rm -f check-version check-help lint.out + rm -f check-version check-help lint.out cvs-version.* maintainer-clean-local: rm -f Makefile Makefile.in @@ -59,6 +59,15 @@ echo; cat lint.out; echo; \ fi; \ done; + +ngircd.c: cvs-date cvs-version.h + +cvs-date: + grep VERSION ../config.h | grep "CVS" \ + && echo "#define CVSDATE \"$$( grep "\$$Id" $(srcdir)/*.c \ + | awk "{ print \$$9 }" | sort | tail -n 1 )\"" > cvs-version.new \ + || echo "" > cvs-version.new + diff cvs-version.h cvs-version.new || cp cvs-version.new cvs-version.h TESTS = check-version check-help Index: src/ngircd/channel.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/channel.c,v retrieving revision 1.32.2.1 retrieving revision 1.38 diff -u -r1.32.2.1 -r1.38 --- src/ngircd/channel.c 2002/11/04 19:18:39 1.32.2.1 +++ src/ngircd/channel.c 2002/12/16 23:05:24 1.38 @@ -2,16 +2,13 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: channel.c,v 1.32.2.1 2002/11/04 19:18:39 alex Exp $ - * - * channel.c: Management der Channels + * Channel management */ @@ -20,6 +17,8 @@ #include "portab.h" +static char UNUSED id[] = "$Id: channel.c,v 1.38 2002/12/16 23:05:24 alex Exp $"; + #include "imp.h" #include #include @@ -88,6 +87,14 @@ Log( LOG_ERR, "Can't create pre-defined channel: invalid name: \"%s\"!", Conf_Channel[i].name ); continue; } + + /* Gibt es den Channel bereits? */ + chan = Channel_Search( Conf_Channel[i].name ); + if( chan ) + { + Log( LOG_INFO, "Can't create pre-defined channel \"%s\": name already in use.", Conf_Channel[i].name ); + continue; + } /* Channel anlegen */ chan = Channel_Create( Conf_Channel[i].name ); @@ -285,6 +292,48 @@ } /* Channel_MemberCount */ +GLOBAL INT +Channel_CountForUser( CLIENT *Client ) +{ + /* Count number of channels a user is member of. */ + + CL2CHAN *cl2chan; + INT count; + + assert( Client != NULL ); + + count = 0; + cl2chan = My_Cl2Chan; + while( cl2chan ) + { + if( cl2chan->client == Client ) count++; + cl2chan = cl2chan->next; + } + + return count; +} /* Channel_CountForUser */ + + +GLOBAL INT +Channel_PCount( VOID ) +{ + /* Count the number of persistent (mode 'P') channels */ + + CHANNEL *chan; + INT count; + + 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 ) { @@ -301,6 +350,22 @@ } /* Channel_Modes */ +GLOBAL CHAR * +Channel_Key( CHANNEL *Chan ) +{ + assert( Chan != NULL ); + return Chan->key; +} /* Channel_Key */ + + +GLOBAL LONG +Channel_MaxUsers( CHANNEL *Chan ) +{ + assert( Chan != NULL ); + return Chan->maxusers; +} /* Channel_MaxUsers */ + + GLOBAL CHANNEL * Channel_First( VOID ) { @@ -580,6 +645,27 @@ } /* Channel_SetModes */ +GLOBAL VOID +Channel_SetKey( CHANNEL *Chan, CHAR *Key ) +{ + assert( Chan != NULL ); + assert( Key != NULL ); + + strncpy( Chan->key, Key, CLIENT_PASS_LEN - 1 ); + Chan->key[CLIENT_PASS_LEN - 1] = '\0'; + Log( LOG_DEBUG, "Channel %s: Key is now \"%s\".", Chan->name, Chan->key ); +} /* Channel_SetKey */ + + +GLOBAL VOID +Channel_SetMaxUsers( CHANNEL *Chan, LONG Count ) +{ + assert( Chan != NULL ); + + Chan->maxusers = Count; + Log( LOG_DEBUG, "Channel %s: Member limit is now %ld.", Chan->name, Chan->maxusers ); +} /* Channel_SetMaxUsers */ + GLOBAL BOOLEAN Channel_Write( CHANNEL *Chan, CLIENT *From, CLIENT *Client, CHAR *Text ) @@ -629,6 +715,8 @@ strcpy( c->modes, "" ); strcpy( c->topic, "" ); c->hash = Hash( c->name ); + strcpy( c->key, "" ); + c->maxusers = 0; /* Verketten */ c->next = My_Channels; Index: src/ngircd/channel.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/channel.h,v retrieving revision 1.21.2.1 retrieving revision 1.26 diff -u -r1.21.2.1 -r1.26 --- src/ngircd/channel.h 2002/11/04 19:18:39 1.21.2.1 +++ src/ngircd/channel.h 2002/12/16 23:05:24 1.26 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: channel.h,v 1.21.2.1 2002/11/04 19:18:39 alex Exp $ + * $Id: channel.h,v 1.26 2002/12/16 23:05:24 alex Exp $ * - * channel.h: Management der Channels (Header) + * Channel management (header) */ @@ -26,10 +25,12 @@ typedef struct _CHANNEL { struct _CHANNEL *next; - CHAR name[CHANNEL_NAME_LEN]; /* Name des Channel */ - UINT32 hash; /* Hash ueber (kleingeschrieben) Namen */ - CHAR modes[CHANNEL_MODE_LEN]; /* Channel-Modes */ - CHAR topic[CHANNEL_TOPIC_LEN]; /* Topic des Channels */ + CHAR name[CHANNEL_NAME_LEN]; /* Name of the channel */ + UINT32 hash; /* Hash of the (lowecase!) name */ + CHAR modes[CHANNEL_MODE_LEN]; /* Channel modes */ + CHAR topic[CHANNEL_TOPIC_LEN]; /* Topic of the channel */ + CHAR key[CLIENT_PASS_LEN]; /* Channel key ("password", mode "k" ) */ + LONG maxusers; /* Maximum number of members (mode "l") */ } CHANNEL; typedef struct _CLIENT2CHAN @@ -48,54 +49,60 @@ #endif -GLOBAL VOID Channel_Init PARAMS((VOID )); -GLOBAL VOID Channel_InitPredefined PARAMS(( VOID )); -GLOBAL VOID Channel_Exit PARAMS((VOID )); +GLOBAL VOID Channel_Init PARAMS(( VOID )); +GLOBAL VOID Channel_InitPredefined PARAMS(( VOID )); +GLOBAL VOID Channel_Exit PARAMS(( VOID )); -GLOBAL BOOLEAN Channel_Join PARAMS((CLIENT *Client, CHAR *Name )); -GLOBAL BOOLEAN Channel_Part PARAMS((CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason )); +GLOBAL BOOLEAN Channel_Join PARAMS(( CLIENT *Client, CHAR *Name )); +GLOBAL BOOLEAN Channel_Part PARAMS(( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason )); -GLOBAL VOID Channel_Quit PARAMS((CLIENT *Client, CHAR *Reason )); +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 LONG Channel_Count PARAMS(( VOID )); +GLOBAL LONG Channel_MemberCount PARAMS(( CHANNEL *Chan )); +GLOBAL INT Channel_CountForUser PARAMS(( CLIENT *Client )); +GLOBAL INT Channel_PCount PARAMS(( VOID )); -GLOBAL CHAR *Channel_Name PARAMS((CHANNEL *Chan )); -GLOBAL CHAR *Channel_Modes PARAMS((CHANNEL *Chan )); -GLOBAL CHAR *Channel_Topic PARAMS((CHANNEL *Chan )); +GLOBAL CHAR *Channel_Name PARAMS(( CHANNEL *Chan )); +GLOBAL CHAR *Channel_Modes PARAMS(( CHANNEL *Chan )); +GLOBAL CHAR *Channel_Topic PARAMS(( CHANNEL *Chan )); +GLOBAL CHAR *Channel_Key PARAMS(( CHANNEL *Chan )); +GLOBAL LONG Channel_MaxUsers PARAMS(( CHANNEL *Chan )); -GLOBAL VOID Channel_SetTopic PARAMS((CHANNEL *Chan, CHAR *Topic )); -GLOBAL VOID Channel_SetModes PARAMS((CHANNEL *Chan, CHAR *Modes )); +GLOBAL VOID Channel_SetTopic PARAMS(( CHANNEL *Chan, CHAR *Topic )); +GLOBAL VOID Channel_SetModes PARAMS(( CHANNEL *Chan, CHAR *Modes )); +GLOBAL VOID Channel_SetKey PARAMS(( CHANNEL *Chan, CHAR *Key )); +GLOBAL VOID Channel_SetMaxUsers PARAMS(( CHANNEL *Chan, LONG Count )); -GLOBAL CHANNEL *Channel_Search PARAMS((CHAR *Name )); +GLOBAL CHANNEL *Channel_Search PARAMS(( CHAR *Name )); -GLOBAL CHANNEL *Channel_First PARAMS((VOID )); -GLOBAL CHANNEL *Channel_Next PARAMS((CHANNEL *Chan )); +GLOBAL CHANNEL *Channel_First PARAMS(( VOID )); +GLOBAL CHANNEL *Channel_Next PARAMS(( CHANNEL *Chan )); -GLOBAL CL2CHAN *Channel_FirstMember PARAMS((CHANNEL *Chan )); -GLOBAL CL2CHAN *Channel_NextMember PARAMS((CHANNEL *Chan, CL2CHAN *Cl2Chan )); -GLOBAL CL2CHAN *Channel_FirstChannelOf PARAMS((CLIENT *Client )); -GLOBAL CL2CHAN *Channel_NextChannelOf PARAMS((CLIENT *Client, CL2CHAN *Cl2Chan )); +GLOBAL CL2CHAN *Channel_FirstMember PARAMS(( CHANNEL *Chan )); +GLOBAL CL2CHAN *Channel_NextMember PARAMS(( CHANNEL *Chan, CL2CHAN *Cl2Chan )); +GLOBAL CL2CHAN *Channel_FirstChannelOf PARAMS(( CLIENT *Client )); +GLOBAL CL2CHAN *Channel_NextChannelOf PARAMS(( CLIENT *Client, CL2CHAN *Cl2Chan )); -GLOBAL CLIENT *Channel_GetClient PARAMS((CL2CHAN *Cl2Chan )); -GLOBAL CHANNEL *Channel_GetChannel PARAMS((CL2CHAN *Cl2Chan )); +GLOBAL CLIENT *Channel_GetClient PARAMS(( CL2CHAN *Cl2Chan )); +GLOBAL CHANNEL *Channel_GetChannel PARAMS(( CL2CHAN *Cl2Chan )); -GLOBAL BOOLEAN Channel_IsValidName PARAMS((CHAR *Name )); +GLOBAL BOOLEAN Channel_IsValidName PARAMS(( CHAR *Name )); -GLOBAL BOOLEAN Channel_ModeAdd PARAMS((CHANNEL *Chan, CHAR Mode )); -GLOBAL BOOLEAN Channel_ModeDel PARAMS((CHANNEL *Chan, CHAR Mode )); +GLOBAL BOOLEAN Channel_ModeAdd PARAMS(( CHANNEL *Chan, CHAR Mode )); +GLOBAL BOOLEAN Channel_ModeDel PARAMS(( CHANNEL *Chan, CHAR Mode )); -GLOBAL BOOLEAN Channel_UserModeAdd PARAMS((CHANNEL *Chan, CLIENT *Client, CHAR Mode )); -GLOBAL BOOLEAN Channel_UserModeDel PARAMS((CHANNEL *Chan, CLIENT *Client, CHAR Mode )); -GLOBAL CHAR *Channel_UserModes PARAMS((CHANNEL *Chan, CLIENT *Client )); +GLOBAL BOOLEAN Channel_UserModeAdd PARAMS(( CHANNEL *Chan, CLIENT *Client, CHAR Mode )); +GLOBAL BOOLEAN Channel_UserModeDel PARAMS(( CHANNEL *Chan, CLIENT *Client, CHAR Mode )); +GLOBAL CHAR *Channel_UserModes PARAMS(( CHANNEL *Chan, CLIENT *Client )); -GLOBAL BOOLEAN Channel_IsMemberOf PARAMS((CHANNEL *Chan, CLIENT *Client )); +GLOBAL BOOLEAN Channel_IsMemberOf PARAMS(( CHANNEL *Chan, CLIENT *Client )); -GLOBAL BOOLEAN Channel_Write PARAMS((CHANNEL *Chan, CLIENT *From, CLIENT *Client, CHAR *Text )); +GLOBAL BOOLEAN Channel_Write PARAMS(( CHANNEL *Chan, CLIENT *From, CLIENT *Client, CHAR *Text )); -GLOBAL CHANNEL *Channel_Create PARAMS((CHAR *Name )); +GLOBAL CHANNEL *Channel_Create PARAMS(( CHAR *Name )); #endif Index: src/ngircd/client.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/client.c,v retrieving revision 1.60.2.2 retrieving revision 1.65.2.1 diff -u -r1.60.2.2 -r1.65.2.1 --- src/ngircd/client.c 2002/11/04 19:18:39 1.60.2.2 +++ src/ngircd/client.c 2002/12/22 23:42:28 1.65.2.1 @@ -2,23 +2,13 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: client.c,v 1.60.2.2 2002/11/04 19:18:39 alex Exp $ - * - * client.c: Management aller Clients - * - * Der Begriff "Client" ist in diesem Fall evtl. etwas verwirrend: Clients sind - * alle Verbindungen, die im gesamten(!) IRC-Netzwerk bekannt sind. Das sind IRC- - * Clients (User), andere Server und IRC-Services. - * Ueber welchen IRC-Server die Verbindung nun tatsaechlich in das Netzwerk her- - * gestellt wurde, muss der jeweiligen Struktur entnommen werden. Ist es dieser - * Server gewesen, so existiert eine entsprechende CONNECTION-Struktur. + * Client management. */ @@ -27,6 +17,8 @@ #include "portab.h" +static char UNUSED id[] = "$Id: client.c,v 1.65.2.1 2002/12/22 23:42:28 alex Exp $"; + #include "imp.h" #include #include @@ -65,8 +57,12 @@ LOCAL CLIENT *New_Client_Struct PARAMS(( VOID )); LOCAL VOID Generate_MyToken PARAMS(( CLIENT *Client )); +LOCAL VOID Adjust_Counters PARAMS(( CLIENT *Client )); +LONG Max_Users = 0, My_Max_Users = 0; + + GLOBAL VOID Client_Init( VOID ) { @@ -185,6 +181,9 @@ client->next = (POINTER *)My_Clients; My_Clients = client; + /* Adjust counters */ + Adjust_Counters( client ); + return client; } /* Client_New */ @@ -375,7 +374,7 @@ assert( Flags != NULL ); strncpy( Client->flags, Flags, CLIENT_FLAGS_LEN - 1 ); - Client->modes[CLIENT_FLAGS_LEN - 1] = '\0'; + Client->flags[CLIENT_FLAGS_LEN - 1] = '\0'; } /* Client_SetFlags */ @@ -422,6 +421,7 @@ assert( Client != NULL ); Client->type = Type; if( Type == CLIENT_SERVER ) Generate_MyToken( Client ); + Adjust_Counters( Client ); } /* Client_SetType */ @@ -808,8 +808,9 @@ if( strcasecmp( c->id, ID ) == 0 ) { /* die Server-ID gibt es bereits */ - sprintf( str, "ID \"%s\" already registered!", ID ); - Log( LOG_ERR, "%s (on connection %d)", str, Client->conn_id ); + sprintf( str, "ID \"%s\" already registered", ID ); + if( Client->conn_id != c->conn_id ) Log( LOG_ERR, "%s (on connection %d)!", str, c->conn_id ); + else Log( LOG_ERR, "%s (via network)!", str ); Conn_Close( Client->conn_id, str, str, TRUE ); return FALSE; } @@ -926,6 +927,20 @@ } /* Client_UnknownCount */ +GLOBAL LONG +Client_MaxUserCount( VOID ) +{ + return Max_Users; +} /* Client_MaxUserCount */ + + +GLOBAL LONG +Client_MyMaxUserCount( VOID ) +{ + return My_Max_Users; +} /* Client_MyMaxUserCount */ + + GLOBAL BOOLEAN Client_IsValidNick( CHAR *Nick ) { @@ -1046,6 +1061,26 @@ Client->mytoken = token; Log( LOG_DEBUG, "Assigned token %d to server \"%s\".", token, Client->id ); } /* Generate_MyToken */ + + +LOCAL VOID +Adjust_Counters( CLIENT *Client ) +{ + LONG count; + + assert( Client != NULL ); + + if( Client->type != CLIENT_USER ) return; + + if( Client->conn_id != NONE ) + { + /* Local connection */ + count = Client_MyUserCount( ); + if( count > My_Max_Users ) My_Max_Users = count; + } + count = Client_UserCount( ); + if( count > Max_Users ) Max_Users = count; +} /* Adjust_Counters */ /* -eof- */ Index: src/ngircd/client.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/client.h,v retrieving revision 1.29.2.1 retrieving revision 1.32.2.1 diff -u -r1.29.2.1 -r1.32.2.1 --- src/ngircd/client.h 2002/11/04 19:18:39 1.29.2.1 +++ src/ngircd/client.h 2002/12/22 23:42:28 1.32.2.1 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: client.h,v 1.29.2.1 2002/11/04 19:18:39 alex Exp $ + * $Id: client.h,v 1.32.2.1 2002/12/22 23:42:28 alex Exp $ * - * client.h: Konfiguration des ngircd (Header) + * Client management (header) */ @@ -19,18 +18,17 @@ #define __client_h__ -typedef enum -{ - CLIENT_UNKNOWN, /* Verbindung mit (noch) unbekanntem Typ */ - CLIENT_GOTPASS, /* Client hat PASS gesendet */ - CLIENT_GOTNICK, /* Client hat NICK gesendet */ - CLIENT_GOTUSER, /* Client hat USER gesendet */ - CLIENT_USER, /* Client ist ein Benutzer (USER wurde gesendet) */ - CLIENT_UNKNOWNSERVER, /* unregistrierte Server-Verbindung */ - CLIENT_GOTPASSSERVER, /* Client hat PASS nach "Server-Art" gesendet */ - CLIENT_SERVER, /* Client ist ein Server */ - CLIENT_SERVICE /* Client ist ein Service */ -} CLIENT_TYPE; +#define CLIENT_UNKNOWN 1 /* connection of unknown type */ +#define CLIENT_GOTPASS 2 /* client did send PASS */ +#define CLIENT_GOTNICK 4 /* client did send NICK */ +#define CLIENT_GOTUSER 8 /* client did send USER */ +#define CLIENT_USER 16 /* client is an IRC user */ +#define CLIENT_UNKNOWNSERVER 32 /* unregistered server connection */ +#define CLIENT_GOTPASSSERVER 64 /* client did send PASS in "server style" */ +#define CLIENT_SERVER 128 /* client is a server */ +#define CLIENT_SERVICE 256 /* client is a service */ + +#define CLIENT_TYPE INT #if defined(__client_c__) | defined(S_SPLINT_S) @@ -39,22 +37,22 @@ typedef struct _CLIENT { - CHAR id[CLIENT_ID_LEN]; /* Nick (User) bzw. ID (Server) */ - UINT32 hash; /* Hash ueber die (kleingeschriebene) ID */ - POINTER *next; /* Zeiger auf naechste Client-Struktur */ - CLIENT_TYPE type; /* Typ des Client, vgl. CLIENT_TYPE */ - CONN_ID conn_id; /* ID der Connection (wenn lokal) bzw. NONE (remote) */ - struct _CLIENT *introducer; /* ID des Servers, der die Verbindung hat */ - struct _CLIENT *topserver; /* Toplevel-Servers (nur gueltig, wenn Client ein Server ist) */ - CHAR pwd[CLIENT_PASS_LEN]; /* Passwort, welches der Client angegeben hat */ - CHAR host[CLIENT_HOST_LEN]; /* Hostname des Client */ - CHAR user[CLIENT_USER_LEN]; /* Benutzername ("Login") */ - CHAR info[CLIENT_INFO_LEN]; /* Langer Benutzername (User) bzw. Infotext (Server) */ - CHAR modes[CLIENT_MODE_LEN]; /* Client Modes */ - INT hops, token, mytoken; /* "Hops" und "Token" (-> SERVER-Befehl) */ - BOOLEAN oper_by_me; /* IRC-Operator-Status durch diesen Server? */ - CHAR away[CLIENT_AWAY_LEN]; /* AWAY-Text, wenn Mode 'a' gesetzt */ - CHAR flags[CLIENT_FLAGS_LEN]; /* Flags des Client (aktuell nur bei Servern) */ + CHAR id[CLIENT_ID_LEN]; /* nick (user) / ID (server) */ + UINT32 hash; /* hash of lower-case ID */ + POINTER *next; /* pointer to next client structure */ + CLIENT_TYPE type; /* type of client, see CLIENT_xxx */ + CONN_ID conn_id; /* ID of the connection (if local) or NONE (remote) */ + struct _CLIENT *introducer; /* ID of the servers which the client is connected to */ + struct _CLIENT *topserver; /* toplevel servers (only valid if client is a server) */ + CHAR pwd[CLIENT_PASS_LEN]; /* password received of the client */ + CHAR host[CLIENT_HOST_LEN]; /* hostname of the client */ + CHAR user[CLIENT_USER_LEN]; /* user name ("login") */ + CHAR info[CLIENT_INFO_LEN]; /* long user name (user) / info text (server) */ + CHAR modes[CLIENT_MODE_LEN]; /* client modes */ + INT hops, token, mytoken; /* "hops" and "Token" (see SERVER command) */ + BOOLEAN oper_by_me; /* client is local IRC operator on this server? */ + CHAR away[CLIENT_AWAY_LEN]; /* AWAY text (valid if mode 'a' is set) */ + CHAR flags[CLIENT_FLAGS_LEN]; /* flags of the client */ } CLIENT; #else @@ -132,6 +130,8 @@ GLOBAL LONG Client_MyUserCount PARAMS((VOID )); GLOBAL LONG Client_MyServiceCount PARAMS((VOID )); GLOBAL LONG Client_MyServerCount PARAMS((VOID )); +GLOBAL LONG Client_MaxUserCount PARAMS(( VOID )); +GLOBAL LONG Client_MyMaxUserCount PARAMS(( VOID )); GLOBAL BOOLEAN Client_IsValidNick PARAMS((CHAR *Nick )); Index: src/ngircd/conf.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/conf.c,v retrieving revision 1.29.2.5 retrieving revision 1.47 diff -u -r1.29.2.5 -r1.47 --- src/ngircd/conf.c 2002/11/24 15:25:25 1.29.2.5 +++ src/ngircd/conf.c 2002/12/18 02:53:36 1.47 @@ -1,22 +1,21 @@ /* * ngIRCd -- The Next Generation IRC Daemon - * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) + * Copyright (c)2001,2002 Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: conf.c,v 1.29.2.5 2002/11/24 15:25:25 alex Exp $ - * - * conf.h: Konfiguration des ngircd + * Configuration management (reading, parsing & validation) */ #include "portab.h" +static char UNUSED id[] = "$Id: conf.c,v 1.47 2002/12/18 02:53:36 alex Exp $"; + #include "imp.h" #include #include @@ -28,7 +27,12 @@ #include #include #include +#include +#ifdef HAVE_CTYPE_H +# include +#endif + #include "ngircd.h" #include "conn.h" #include "client.h" @@ -46,7 +50,7 @@ LOCAL VOID Set_Defaults PARAMS(( VOID )); LOCAL VOID Read_Config PARAMS(( VOID )); -LOCAL VOID Validate_Config PARAMS(( VOID )); +LOCAL VOID Validate_Config PARAMS(( BOOLEAN TestOnly )); LOCAL VOID Handle_GLOBAL PARAMS(( INT Line, CHAR *Var, CHAR *Arg )); LOCAL VOID Handle_OPERATOR PARAMS(( INT Line, CHAR *Var, CHAR *Arg )); @@ -61,14 +65,14 @@ { Set_Defaults( ); Read_Config( ); - Validate_Config( ); + Validate_Config( FALSE ); } /* Config_Init */ GLOBAL INT Conf_Test( VOID ) { - /* Konfiguration einlesen, ueberpruefen und ausgeben. */ + /* Read configuration, validate and output it. */ struct passwd *pwd; struct group *grp; @@ -77,10 +81,10 @@ Use_Log = FALSE; Set_Defaults( ); - printf( "Using \"%s\" as configuration file ...\n", NGIRCd_ConfFile ); Read_Config( ); + Validate_Config( TRUE ); - /* Wenn stdin ein ein TTY ist: auf Taste warten */ + /* If stdin is a valid tty wait for a key: */ if( isatty( fileno( stdout ))) { puts( "OK, press enter to see a dump of your service configuration ..." ); @@ -113,13 +117,17 @@ printf( " PongTimeout = %d\n", Conf_PongTimeout ); printf( " ConnectRetry = %d\n", Conf_ConnectRetry ); printf( " OperCanUseMode = %s\n", Conf_OperCanMode == TRUE ? "yes" : "no" ); + if( Conf_MaxConnections > 0 ) printf( " MaxConnections = %ld\n", Conf_MaxConnections ); + else printf( " MaxConnections = -1\n" ); + if( Conf_MaxJoins > 0 ) printf( " MaxJoins = %d\n", Conf_MaxJoins ); + else printf( " MaxJoins = -1\n" ); puts( "" ); for( i = 0; i < Conf_Oper_Count; i++ ) { if( ! Conf_Oper[i].name[0] ) continue; - /* gueltiger Operator-Block: ausgeben */ + /* Valid "Operator" section */ puts( "[OPERATOR]" ); printf( " Name = %s\n", Conf_Oper[i].name ); printf( " Password = %s\n", Conf_Oper[i].pwd ); @@ -129,14 +137,14 @@ for( i = 0; i < Conf_Server_Count; i++ ) { if( ! Conf_Server[i].name[0] ) continue; - if( ! Conf_Server[i].host[0] ) continue; - /* gueltiger Server-Block: ausgeben */ + /* Valid "Server" section */ puts( "[SERVER]" ); printf( " Name = %s\n", Conf_Server[i].name ); printf( " Host = %s\n", Conf_Server[i].host ); printf( " Port = %d\n", Conf_Server[i].port ); - printf( " Password = %s\n", Conf_Server[i].pwd ); + printf( " MyPassword = %s\n", Conf_Server[i].pwd_in ); + printf( " PeerPassword = %s\n", Conf_Server[i].pwd_out ); printf( " Group = %d\n", Conf_Server[i].group ); puts( "" ); } @@ -145,7 +153,7 @@ { if( ! Conf_Channel[i].name[0] ) continue; - /* gueltiger Channel-Block: ausgeben */ + /* Valid "Channel" section */ puts( "[CHANNEL]" ); printf( " Name = %s\n", Conf_Channel[i].name ); printf( " Modes = %s\n", Conf_Channel[i].modes ); @@ -160,7 +168,7 @@ LOCAL VOID Set_Defaults( VOID ) { - /* Konfigurationsvariablen initialisieren, d.h. auf Default-Werte setzen. */ + /* Initialize configuration variables with default values. */ strcpy( Conf_ServerName, "" ); sprintf( Conf_ServerInfo, "%s %s", PACKAGE, VERSION ); @@ -186,13 +194,16 @@ Conf_Channel_Count = 0; Conf_OperCanMode = FALSE; + + Conf_MaxConnections = -1; + Conf_MaxJoins = 10; } /* Set_Defaults */ LOCAL VOID Read_Config( VOID ) { - /* Konfigurationsdatei einlesen. */ + /* Read configuration file. */ CHAR section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr; INT line; @@ -201,12 +212,14 @@ fd = fopen( NGIRCd_ConfFile, "r" ); if( ! fd ) { - /* Keine Konfigurationsdatei gefunden */ + /* No configuration file found! */ Config_Error( LOG_ALERT, "Can't read configuration \"%s\": %s", NGIRCd_ConfFile, strerror( errno )); Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); exit( 1 ); } + Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile ); + line = 0; strcpy( section, "" ); while( TRUE ) @@ -215,10 +228,10 @@ ngt_TrimStr( str ); line++; - /* Kommentarzeilen und leere Zeilen ueberspringen */ + /* Skip comments and empty lines */ if( str[0] == ';' || str[0] == '#' || str[0] == '\0' ) continue; - /* Anfang eines Abschnittes? */ + /* Is this the beginning of a new section? */ if(( str[0] == '[' ) && ( str[strlen( str ) - 1] == ']' )) { strcpy( section, str ); @@ -228,7 +241,7 @@ if( Conf_Oper_Count + 1 > MAX_OPERATORS ) Config_Error( LOG_ERR, "Too many operators configured." ); else { - /* neuen Operator initialisieren */ + /* Initialize new operator structure */ strcpy( Conf_Oper[Conf_Oper_Count].name, "" ); strcpy( Conf_Oper[Conf_Oper_Count].pwd, "" ); Conf_Oper_Count++; @@ -240,11 +253,12 @@ if( Conf_Server_Count + 1 > MAX_SERVERS ) Config_Error( LOG_ERR, "Too many servers configured." ); else { - /* neuen Server ("Peer") initialisieren */ + /* Initialize new server structure */ strcpy( Conf_Server[Conf_Server_Count].host, "" ); strcpy( Conf_Server[Conf_Server_Count].ip, "" ); strcpy( Conf_Server[Conf_Server_Count].name, "" ); - strcpy( Conf_Server[Conf_Server_Count].pwd, "" ); + strcpy( Conf_Server[Conf_Server_Count].pwd_in, "" ); + strcpy( Conf_Server[Conf_Server_Count].pwd_out, "" ); Conf_Server[Conf_Server_Count].port = 0; Conf_Server[Conf_Server_Count].group = -1; Conf_Server[Conf_Server_Count].lasttry = time( NULL ) - Conf_ConnectRetry + STARTUP_DELAY; @@ -258,7 +272,7 @@ if( Conf_Channel_Count + 1 > MAX_DEFCHANNELS ) Config_Error( LOG_ERR, "Too many pre-defined channels configured." ); else { - /* neuen vordefinierten Channel initialisieren */ + /* Initialize new channel structure */ strcpy( Conf_Channel[Conf_Channel_Count].name, "" ); strcpy( Conf_Channel[Conf_Channel_Count].modes, "" ); strcpy( Conf_Channel[Conf_Channel_Count].topic, "" ); @@ -271,7 +285,7 @@ } if( section[0] == 0x1 ) continue; - /* In Variable und Argument zerlegen */ + /* Split line into variable name and parameters */ ptr = strchr( str, '=' ); if( ! ptr ) { @@ -291,7 +305,7 @@ fclose( fd ); - /* Wenn kein Port definiert wurde, Port 6667 als Default benutzen */ + /* If there are no ports configured use the default: 6667 */ if( Conf_ListenPorts_Count < 1 ) { Conf_ListenPorts_Count = 1; @@ -314,50 +328,56 @@ if( strcasecmp( Var, "Name" ) == 0 ) { - /* Der Server-Name */ + /* Server name */ strncpy( Conf_ServerName, Arg, CLIENT_ID_LEN - 1 ); Conf_ServerName[CLIENT_ID_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_ID_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Info" ) == 0 ) { - /* Server-Info-Text */ + /* Info text of server */ strncpy( Conf_ServerInfo, Arg, CLIENT_INFO_LEN - 1 ); Conf_ServerInfo[CLIENT_INFO_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_INFO_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Info\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Password" ) == 0 ) { - /* Server-Passwort */ + /* Global server password */ strncpy( Conf_ServerPwd, Arg, CLIENT_PASS_LEN - 1 ); Conf_ServerPwd[CLIENT_PASS_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Password\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "AdminInfo1" ) == 0 ) { - /* Server-Info-Text */ + /* Administrative info #1 */ strncpy( Conf_ServerAdmin1, Arg, CLIENT_INFO_LEN - 1 ); Conf_ServerAdmin1[CLIENT_INFO_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_INFO_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"AdminInfo1\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "AdminInfo2" ) == 0 ) { - /* Server-Info-Text */ + /* Administrative info #2 */ strncpy( Conf_ServerAdmin2, Arg, CLIENT_INFO_LEN - 1 ); Conf_ServerAdmin2[CLIENT_INFO_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_INFO_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"AdminInfo2\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "AdminEMail" ) == 0 ) { - /* Server-Info-Text */ + /* Administrative email contact */ strncpy( Conf_ServerAdminMail, Arg, CLIENT_INFO_LEN - 1 ); Conf_ServerAdminMail[CLIENT_INFO_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_INFO_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"AdminEMail\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Ports" ) == 0 ) { - /* Ports, durch "," getrennt, auf denen der Server - * Verbindungen annehmen soll */ + /* Ports on that the server should listen. More port numbers + * must be separated by "," */ ptr = strtok( Arg, "," ); while( ptr ) { @@ -375,58 +395,105 @@ } if( strcasecmp( Var, "MotdFile" ) == 0 ) { - /* Datei mit der "message of the day" (MOTD) */ + /* "Message of the day" (MOTD) file */ strncpy( Conf_MotdFile, Arg, FNAME_LEN - 1 ); Conf_MotdFile[FNAME_LEN - 1] = '\0'; + if( strlen( Arg ) > FNAME_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MotdFile\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "ServerUID" ) == 0 ) { - /* UID, mit der der Daemon laufen soll */ + /* UID the daemon should switch to */ pwd = getpwnam( Arg ); if( pwd ) Conf_UID = pwd->pw_uid; - else Conf_UID = (UINT)atoi( Arg ); + else + { +#ifdef HAVE_ISDIGIT + if( ! isdigit( *Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"ServerUID\" is not a number!", NGIRCd_ConfFile, Line ); + else +#endif + Conf_UID = (UINT)atoi( Arg ); + } return; } if( strcasecmp( Var, "ServerGID" ) == 0 ) { - /* GID, mit der der Daemon laufen soll */ + /* GID the daemon should use */ grp = getgrnam( Arg ); if( grp ) Conf_GID = grp->gr_gid; - else Conf_GID = (UINT)atoi( Arg ); + else + { +#ifdef HAVE_ISDIGIT + if( ! isdigit( *Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"ServerGID\" is not a number!", NGIRCd_ConfFile, Line ); + else +#endif + Conf_GID = (UINT)atoi( Arg ); + } return; } if( strcasecmp( Var, "PingTimeout" ) == 0 ) { - /* PING-Timeout */ + /* PING timeout */ Conf_PingTimeout = atoi( Arg ); - if(( Conf_PingTimeout ) < 5 ) Conf_PingTimeout = 5; + if( Conf_PingTimeout < 5 ) + { + Config_Error( LOG_WARNING, "%s, line %d: Value of \"PingTimeout\" too low!", NGIRCd_ConfFile, Line ); + Conf_PingTimeout = 5; + } return; } if( strcasecmp( Var, "PongTimeout" ) == 0 ) { - /* PONG-Timeout */ + /* PONG timeout */ Conf_PongTimeout = atoi( Arg ); - if(( Conf_PongTimeout ) < 5 ) Conf_PongTimeout = 5; + if( Conf_PongTimeout < 5 ) + { + Config_Error( LOG_WARNING, "%s, line %d: Value of \"PongTimeout\" too low!", NGIRCd_ConfFile, Line ); + Conf_PongTimeout = 5; + } return; } if( strcasecmp( Var, "ConnectRetry" ) == 0 ) { - /* Sekunden zwischen Verbindungsversuchen zu anderen Servern */ + /* Seconds between connection attempts to other servers */ Conf_ConnectRetry = atoi( Arg ); - if(( Conf_ConnectRetry ) < 5 ) Conf_ConnectRetry = 5; + if( Conf_ConnectRetry < 5 ) + { + Config_Error( LOG_WARNING, "%s, line %d: Value of \"ConnectRetry\" too low!", NGIRCd_ConfFile, Line ); + Conf_ConnectRetry = 5; + } return; } if( strcasecmp( Var, "OperCanUseMode" ) == 0 ) { - /* Koennen IRC-Operatoren immer MODE benutzen? */ + /* Are IRC operators allowed to use MODE in channels they aren't Op in? */ if( strcasecmp( Arg, "yes" ) == 0 ) Conf_OperCanMode = TRUE; else if( strcasecmp( Arg, "true" ) == 0 ) Conf_OperCanMode = TRUE; else if( atoi( Arg ) != 0 ) Conf_OperCanMode = TRUE; else Conf_OperCanMode = FALSE; return; } - + if( strcasecmp( Var, "MaxConnections" ) == 0 ) + { + /* Maximum number of connections. Values <= 0 are equal to "no limit". */ +#ifdef HAVE_ISDIGIT + if( ! isdigit( *Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MaxConnections\" is not a number!", NGIRCd_ConfFile, Line ); + else +#endif + Conf_MaxConnections = atol( Arg ); + return; + } + if( strcasecmp( Var, "MaxJoins" ) == 0 ) + { + /* Maximum number of channels a user can join. Values <= 0 are equal to "no limit". */ +#ifdef HAVE_ISDIGIT + if( ! isdigit( *Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MaxJoins\" is not a number!", NGIRCd_ConfFile, Line ); + else +#endif + Conf_MaxJoins = atoi( Arg ); + return; + } + Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!", NGIRCd_ConfFile, Line, Var ); } /* Handle_GLOBAL */ @@ -441,16 +508,18 @@ if( strcasecmp( Var, "Name" ) == 0 ) { - /* Name des IRC Operator */ + /* Name of IRC operator */ strncpy( Conf_Oper[Conf_Oper_Count - 1].name, Arg, CLIENT_PASS_LEN - 1 ); Conf_Oper[Conf_Oper_Count - 1].name[CLIENT_PASS_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Password" ) == 0 ) { - /* Passwort des IRC Operator */ + /* Password of IRC operator */ strncpy( Conf_Oper[Conf_Oper_Count - 1].pwd, Arg, CLIENT_PASS_LEN - 1 ); Conf_Oper[Conf_Oper_Count - 1].pwd[CLIENT_PASS_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Password\" too long!", NGIRCd_ConfFile, Line ); return; } @@ -469,28 +538,39 @@ if( strcasecmp( Var, "Host" ) == 0 ) { - /* Hostname des Servers */ + /* Hostname of the server */ strncpy( Conf_Server[Conf_Server_Count - 1].host, Arg, HOST_LEN - 1 ); Conf_Server[Conf_Server_Count - 1].host[HOST_LEN - 1] = '\0'; + if( strlen( Arg ) > HOST_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Host\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Name" ) == 0 ) { - /* Name des Servers ("Nick") */ + /* Name of the server ("Nick"/"ID") */ strncpy( Conf_Server[Conf_Server_Count - 1].name, Arg, CLIENT_ID_LEN - 1 ); Conf_Server[Conf_Server_Count - 1].name[CLIENT_ID_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_ID_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line ); return; } - if( strcasecmp( Var, "Password" ) == 0 ) + if( strcasecmp( Var, "MyPassword" ) == 0 ) { - /* Passwort des Servers */ - strncpy( Conf_Server[Conf_Server_Count - 1].pwd, Arg, CLIENT_PASS_LEN - 1 ); - Conf_Server[Conf_Server_Count - 1].pwd[CLIENT_PASS_LEN - 1] = '\0'; + /* Password of this server which is sent to the peer */ + strncpy( Conf_Server[Conf_Server_Count - 1].pwd_in, Arg, CLIENT_PASS_LEN - 1 ); + Conf_Server[Conf_Server_Count - 1].pwd_in[CLIENT_PASS_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MyPassword\" too long!", NGIRCd_ConfFile, Line ); return; } + if( strcasecmp( Var, "PeerPassword" ) == 0 ) + { + /* Passwort of the peer which must be received */ + strncpy( Conf_Server[Conf_Server_Count - 1].pwd_out, Arg, CLIENT_PASS_LEN - 1 ); + Conf_Server[Conf_Server_Count - 1].pwd_out[CLIENT_PASS_LEN - 1] = '\0'; + if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"PeerPassword\" too long!", NGIRCd_ConfFile, Line ); + return; + } if( strcasecmp( Var, "Port" ) == 0 ) { - /* Port, zu dem Verbunden werden soll */ + /* Port to which this server should connect */ port = atol( Arg ); if( port > 0 && port < 0xFFFF ) Conf_Server[Conf_Server_Count - 1].port = (INT)port; else Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Illegal port number %ld!", NGIRCd_ConfFile, Line, port ); @@ -498,7 +578,11 @@ } if( strcasecmp( Var, "Group" ) == 0 ) { - /* Server-Gruppe */ + /* Server group */ +#ifdef HAVE_ISDIGIT + if( ! isdigit( *Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Group\" is not a number!", NGIRCd_ConfFile, Line ); + else +#endif Conf_Server[Conf_Server_Count - 1].group = atoi( Arg ); return; } @@ -516,23 +600,26 @@ if( strcasecmp( Var, "Name" ) == 0 ) { - /* Hostname des Servers */ + /* Name of the channel */ strncpy( Conf_Channel[Conf_Channel_Count - 1].name, Arg, CHANNEL_NAME_LEN - 1 ); Conf_Channel[Conf_Channel_Count - 1].name[CHANNEL_NAME_LEN - 1] = '\0'; + if( strlen( Arg ) > CHANNEL_NAME_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Modes" ) == 0 ) { - /* Name des Servers ("Nick") */ + /* Initial modes */ strncpy( Conf_Channel[Conf_Channel_Count - 1].modes, Arg, CHANNEL_MODE_LEN - 1 ); Conf_Channel[Conf_Channel_Count - 1].modes[CHANNEL_MODE_LEN - 1] = '\0'; + if( strlen( Arg ) > CHANNEL_MODE_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Modes\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Topic" ) == 0 ) { - /* Passwort des Servers */ + /* Initial topic */ strncpy( Conf_Channel[Conf_Channel_Count - 1].topic, Arg, CHANNEL_TOPIC_LEN - 1 ); Conf_Channel[Conf_Channel_Count - 1].topic[CHANNEL_TOPIC_LEN - 1] = '\0'; + if( strlen( Arg ) > CHANNEL_TOPIC_LEN - 1 ) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Topic\" too long!", NGIRCd_ConfFile, Line ); return; } @@ -541,33 +628,48 @@ LOCAL VOID -Validate_Config( VOID ) +Validate_Config( BOOLEAN Configtest ) { - /* Konfiguration ueberpruefen */ + /* Validate configuration settings. */ if( ! Conf_ServerName[0] ) { - /* Kein Servername konfiguriert */ + /* No server name configured! */ Config_Error( LOG_ALERT, "No server name configured in \"%s\" ('ServerName')!", NGIRCd_ConfFile ); - Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); - exit( 1 ); + if( ! Configtest ) + { + Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); + exit( 1 ); + } } #ifdef STRICT_RFC if( ! Conf_ServerAdminMail[0] ) { - /* Keine Server-Information konfiguriert */ + /* No administrative contact configured! */ Config_Error( LOG_ALERT, "No administrator email address configured in \"%s\" ('AdminEMail')!", NGIRCd_ConfFile ); - Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); - exit( 1 ); + if( ! Configtest ) + { + Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); + exit( 1 ); + } } #endif if( ! Conf_ServerAdmin1[0] && ! Conf_ServerAdmin2[0] && ! Conf_ServerAdminMail[0] ) { - /* Keine Server-Information konfiguriert */ - Log( LOG_WARNING, "No server information configured but required by RFC!" ); + /* No administrative information configured! */ + Config_Error( LOG_WARNING, "No administrative information configured but required by RFC!" ); } +#ifdef FD_SETSIZE + if(( Conf_MaxConnections > (LONG)FD_SETSIZE ) || ( Conf_MaxConnections < 1 )) + { + Conf_MaxConnections = (LONG)FD_SETSIZE; + Config_Error( LOG_ERR, "Setting MaxConnections to %ld, select() can't handle more file descriptors!", Conf_MaxConnections ); + } +#else + Config_Error( LOG_WARN, "Don't know how many file descriptors select() can handle on this system, don't set MaxConnections too high!" ); +#endif } /* Validate_Config */ @@ -580,14 +682,13 @@ va_dcl #endif { - /* Fehler! Auf Console und/oder ins Log schreiben */ + /* Error! Write to console and/or logfile. */ CHAR msg[MAX_LOG_MSG_LEN]; va_list ap; assert( Format != NULL ); - /* String mit variablen Argumenten zusammenbauen ... */ #ifdef PROTOTYPES va_start( ap, Format ); #else @@ -595,10 +696,10 @@ #endif vsnprintf( msg, MAX_LOG_MSG_LEN, Format, ap ); va_end( ap ); - - /* Im "normalen Betrieb" soll der Log-Mechanismus des ngIRCd verwendet - * werden, beim Testen der Konfiguration jedoch nicht, hier sollen alle - * Meldungen direkt auf die Konsole ausgegeben werden: */ + + /* During "normal operations" the log functions of the daemon should + * be used, but during testing of the configuration file, all messages + * should go directly to the console: */ if( Use_Log ) Log( Level, "%s", msg ); else puts( msg ); } /* Config_Error */ Index: src/ngircd/conf.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/conf.h,v retrieving revision 1.19 retrieving revision 1.24 diff -u -r1.19 -r1.24 --- src/ngircd/conf.h 2002/09/16 09:13:40 1.19 +++ src/ngircd/conf.h 2002/12/14 13:36:19 1.24 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: conf.h,v 1.19 2002/09/16 09:13:40 alex Exp $ + * $Id: conf.h,v 1.24 2002/12/14 13:36:19 alex Exp $ * - * conf.h: Konfiguration des ngircd (Header) + * Configuration management (header) */ @@ -25,76 +24,84 @@ typedef struct _Conf_Oper { - CHAR name[CLIENT_PASS_LEN]; /* Name (ID) des IRC-OPs */ - CHAR pwd[CLIENT_PASS_LEN]; /* Passwort */ + CHAR name[CLIENT_PASS_LEN]; /* Name (ID) of IRC operator */ + CHAR pwd[CLIENT_PASS_LEN]; /* Password */ } CONF_OPER; typedef struct _Conf_Server { CHAR host[HOST_LEN]; /* Hostname */ - CHAR ip[16]; /* IP-Adresse (von Resolver) */ + CHAR ip[16]; /* IP address (Resolver) */ CHAR name[CLIENT_ID_LEN]; /* IRC-Client-ID */ - CHAR pwd[CLIENT_PASS_LEN]; /* Passwort */ - INT port; /* Server-Port */ - INT group; /* Gruppe des Servers */ - time_t lasttry; /* Letzter Connect-Versuch */ - RES_STAT *res_stat; /* Status des Resolver */ + CHAR pwd_in[CLIENT_PASS_LEN]; /* Password which must be received */ + CHAR pwd_out[CLIENT_PASS_LEN]; /* Password to send to peer */ + INT port; /* Server port */ + INT group; /* Group of server */ + time_t lasttry; /* Last connect attempt */ + RES_STAT *res_stat; /* Status of the resolver */ } CONF_SERVER; typedef struct _Conf_Channel { - CHAR name[CHANNEL_NAME_LEN]; /* Name des Channel */ - CHAR modes[CHANNEL_MODE_LEN]; /* Channel-Modes */ - CHAR topic[CHANNEL_TOPIC_LEN]; /* Topic des Channels */ + CHAR name[CHANNEL_NAME_LEN]; /* Name of the channel */ + CHAR modes[CHANNEL_MODE_LEN]; /* Initial channel modes */ + CHAR topic[CHANNEL_TOPIC_LEN]; /* Initial topic */ } CONF_CHANNEL; -/* Name ("Nick") des Servers */ +/* Name ("Nick") of the servers */ GLOBAL CHAR Conf_ServerName[CLIENT_ID_LEN]; -/* Server-Info-Text */ +/* Server info text */ GLOBAL CHAR Conf_ServerInfo[CLIENT_INFO_LEN]; -/* Server-Passwort */ +/* Global server passwort */ GLOBAL CHAR Conf_ServerPwd[CLIENT_PASS_LEN]; -/* Admin-Info-Texte */ +/* Administrative information */ GLOBAL CHAR Conf_ServerAdmin1[CLIENT_INFO_LEN]; GLOBAL CHAR Conf_ServerAdmin2[CLIENT_INFO_LEN]; GLOBAL CHAR Conf_ServerAdminMail[CLIENT_INFO_LEN]; -/* Datei mit MOTD-Text */ +/* File with MOTD text */ GLOBAL CHAR Conf_MotdFile[FNAME_LEN]; -/* Ports, auf denen der Server Verbindungen entgegen nimmt */ +/* Ports the server should listen on */ GLOBAL UINT Conf_ListenPorts[MAX_LISTEN_PORTS]; GLOBAL INT Conf_ListenPorts_Count; -/* User- und Group-ID, zu denen der Daemon wechseln soll */ +/* User and group ID the server should run with */ GLOBAL UINT Conf_UID; GLOBAL UINT Conf_GID; -/* Timeouts fuer PING und PONG */ +/* Timeouts for PING and PONG */ GLOBAL INT Conf_PingTimeout; GLOBAL INT Conf_PongTimeout; -/* Sekunden zwischen Verbindungsversuchen zu anderen Servern */ +/* Seconds between connect attempts to other servers */ GLOBAL INT Conf_ConnectRetry; -/* Operatoren */ +/* Operators */ GLOBAL CONF_OPER Conf_Oper[MAX_OPERATORS]; GLOBAL INT Conf_Oper_Count; -/* Server */ +/* Servers */ GLOBAL CONF_SERVER Conf_Server[MAX_SERVERS]; GLOBAL INT Conf_Server_Count; -/* Vorkonfigurierte Channels */ +/* Pre-defined channels */ GLOBAL CONF_CHANNEL Conf_Channel[MAX_DEFCHANNELS]; GLOBAL INT Conf_Channel_Count; -/* Koennen IRC OPs immer Modes setzen? */ +/* Are IRC operators allowed to always use MODE? */ GLOBAL BOOLEAN Conf_OperCanMode; + +/* Maximum number of connections to this server */ +GLOBAL LONG Conf_MaxConnections; + +/* Maximum number of channels a user can join */ +GLOBAL INT Conf_MaxJoins; + GLOBAL VOID Conf_Init PARAMS((VOID )); GLOBAL INT Conf_Test PARAMS((VOID )); Index: src/ngircd/conn.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/conn.c,v retrieving revision 1.72.2.8 retrieving revision 1.106 diff -u -r1.72.2.8 -r1.106 --- src/ngircd/conn.c 2002/11/24 15:32:14 1.72.2.8 +++ src/ngircd/conn.c 2002/12/18 13:50:22 1.106 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: conn.c,v 1.72.2.8 2002/11/24 15:32:14 alex Exp $ - * - * connect.h: Verwaltung aller Netz-Verbindungen ("connections") + * Connection management */ #include "portab.h" +static char UNUSED id[] = "$Id: conn.c,v 1.106 2002/12/18 13:50:22 alex Exp $"; + #include "imp.h" #include #include @@ -42,6 +41,10 @@ #include /* u.a. fuer Mac OS X */ #endif +#ifdef USE_ZLIB +#include +#endif + #include "exp.h" #include "conn.h" @@ -60,6 +63,20 @@ #define SERVER_WAIT (NONE - 1) +#ifdef USE_ZLIB +typedef struct _ZipData +{ + z_stream in; /* "Handle" fuer Input-Stream */ + z_stream out; /* "Handle" fuer Output-Stream */ + CHAR rbuf[READBUFFER_LEN]; /* Lesepuffer */ + INT rdatalen; /* Laenge der Daten im Lesepuffer (komprimiert) */ + CHAR wbuf[WRITEBUFFER_LEN]; /* Schreibpuffer */ + INT wdatalen; /* Laenge der Daten im Schreibpuffer (unkomprimiert) */ + LONG bytes_in, bytes_out; /* Counter fuer Statistik (unkomprimiert!) */ +} ZIPDATA; +#endif + + typedef struct _Connection { INT sock; /* Socket Handle */ @@ -71,10 +88,18 @@ CHAR wbuf[WRITEBUFFER_LEN]; /* Schreibpuffer */ INT wdatalen; /* Laenge der Daten im Schreibpuffer */ INT our_server; /* wenn von uns zu connectender Server: ID */ + time_t starttime; /* Startzeit des Links */ time_t lastdata; /* Letzte Aktivitaet */ time_t lastping; /* Letzter PING */ time_t lastprivmsg; /* Letzte PRIVMSG */ time_t delaytime; /* Nicht beachten bis ("penalty") */ + LONG bytes_in, bytes_out; /* Empfangene uns gesendete Bytes */ + LONG msg_in, msg_out; /* Empfangene uns gesendete Nachtichten */ + INT flag; /* "Markierungs-Flag" (vgl. "irc-write"-Modul) */ + INT options; /* Link-Optionen */ +#ifdef USE_ZLIB + ZIPDATA zip; /* Kompressionsinformationen */ +#endif } CONNECTION; @@ -87,17 +112,24 @@ LOCAL BOOLEAN Handle_Buffer PARAMS(( CONN_ID Idx )); LOCAL VOID Check_Connections PARAMS(( VOID )); LOCAL VOID Check_Servers PARAMS(( VOID )); -LOCAL VOID Init_Conn_Struct PARAMS(( INT Idx )); +LOCAL VOID Init_Conn_Struct PARAMS(( LONG Idx )); LOCAL BOOLEAN Init_Socket PARAMS(( INT Sock )); LOCAL VOID New_Server PARAMS(( INT Server, CONN_ID Idx )); LOCAL VOID Read_Resolver_Result PARAMS(( INT r_fd )); +#ifdef USE_ZLIB +LOCAL BOOLEAN Zip_Buffer PARAMS(( CONN_ID Idx, CHAR *Data, INT Len )); +LOCAL BOOLEAN Zip_Flush PARAMS(( CONN_ID Idx )); +LOCAL BOOLEAN Unzip_Buffer PARAMS(( CONN_ID Idx )); +#endif + LOCAL fd_set My_Listeners; LOCAL fd_set My_Sockets; LOCAL fd_set My_Connects; -LOCAL CONNECTION My_Connections[MAX_CONNECTIONS]; +LOCAL CONNECTION *My_Connections; +LOCAL LONG Pool_Size, WCounter; GLOBAL VOID @@ -107,15 +139,35 @@ CONN_ID i; + /* Speicher fuer Verbindungs-Pool anfordern */ + Pool_Size = CONNECTION_POOL; + if( Conf_MaxConnections > 0 ) + { + /* konfiguriertes Limit beachten */ + if( Pool_Size > Conf_MaxConnections ) Pool_Size = Conf_MaxConnections; + } + My_Connections = malloc( sizeof( CONNECTION ) * Pool_Size ); + if( ! My_Connections ) + { + /* Speicher konnte nicht alloziert werden! */ + Log( LOG_EMERG, "Can't allocate memory! [Conn_Init]" ); + exit( 1 ); + } + Log( LOG_DEBUG, "Allocted connection pool for %ld items (%ld bytes).", Pool_Size, sizeof( CONNECTION ) * Pool_Size ); + /* zu Beginn haben wir keine Verbindungen */ FD_ZERO( &My_Listeners ); FD_ZERO( &My_Sockets ); FD_ZERO( &My_Connects ); + /* Groesster File-Descriptor fuer select() */ Conn_MaxFD = 0; /* Connection-Struktur initialisieren */ - for( i = 0; i < MAX_CONNECTIONS; i++ ) Init_Conn_Struct( i ); + for( i = 0; i < Pool_Size; i++ ) Init_Conn_Struct( i ); + + /* Global write counter */ + WCounter = 0; } /* Conn_Init */ @@ -134,7 +186,7 @@ { if( FD_ISSET( i, &My_Sockets )) { - for( idx = 0; idx < MAX_CONNECTIONS; idx++ ) + for( idx = 0; idx < Pool_Size; idx++ ) { if( My_Connections[idx].sock == i ) break; } @@ -148,7 +200,7 @@ close( i ); Log( LOG_DEBUG, "Connection %d closed during creation (socket %d).", idx, i ); } - else if( idx < MAX_CONNECTIONS ) + else if( idx < Pool_Size ) { if( NGIRCd_Restart ) Conn_Close( idx, NULL, "Server going down (restarting)", TRUE ); else Conn_Close( idx, NULL, "Server going down", TRUE ); @@ -160,9 +212,50 @@ } } } + + free( My_Connections ); + My_Connections = NULL; + Pool_Size = 0; } /* Conn_Exit */ +GLOBAL INT +Conn_InitListeners( VOID ) +{ + /* Ports, auf denen der Server Verbindungen entgegennehmen + * soll, initialisieren */ + + INT created, i; + + created = 0; + for( i = 0; i < Conf_ListenPorts_Count; i++ ) + { + if( Conn_NewListener( Conf_ListenPorts[i] )) created++; + else Log( LOG_ERR, "Can't listen on port %u!", Conf_ListenPorts[i] ); + } + return created; +} /* Conn_InitListeners */ + + +GLOBAL VOID +Conn_ExitListeners( VOID ) +{ + /* Alle "Listen-Sockets" schliessen */ + + INT i; + + Log( LOG_INFO, "Shutting down all listening sockets ..." ); + for( i = 0; i < Conn_MaxFD + 1; i++ ) + { + if( FD_ISSET( i, &My_Sockets ) && FD_ISSET( i, &My_Listeners )) + { + close( i ); + Log( LOG_DEBUG, "Listening socket %d closed.", i ); + } + } +} /* Conn_ExitListeners */ + + GLOBAL BOOLEAN Conn_NewListener( CONST UINT Port ) { @@ -235,20 +328,20 @@ fd_set read_sockets, write_sockets; struct timeval tv; time_t start, t; - INT i, idx; + LONG i, idx; BOOLEAN timeout; start = time( NULL ); while(( ! NGIRCd_Quit ) && ( ! NGIRCd_Restart )) { timeout = TRUE; - + Check_Servers( ); Check_Connections( ); /* noch volle Lese-Buffer suchen */ - for( i = 0; i < MAX_CONNECTIONS; i++ ) + for( i = 0; i < Pool_Size; i++ ) { if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].rdatalen > 0 )) { @@ -259,16 +352,20 @@ /* noch volle Schreib-Puffer suchen */ FD_ZERO( &write_sockets ); - for( i = 0; i < MAX_CONNECTIONS; i++ ) + for( i = 0; i < Pool_Size; i++ ) { +#ifdef USE_ZLIB + if(( My_Connections[i].sock > NONE ) && (( My_Connections[i].wdatalen > 0 ) || ( My_Connections[i].zip.wdatalen > 0 ))) +#else if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].wdatalen > 0 )) +#endif { /* Socket der Verbindung in Set aufnehmen */ FD_SET( My_Connections[i].sock, &write_sockets ); } } /* Sockets mit im Aufbau befindlichen ausgehenden Verbindungen suchen */ - for( i = 0; i < MAX_CONNECTIONS; i++ ) + for( i = 0; i < Pool_Size; i++ ) { if(( My_Connections[i].sock > NONE ) && ( FD_ISSET( My_Connections[i].sock, &My_Connects ))) FD_SET( My_Connections[i].sock, &write_sockets ); } @@ -276,7 +373,7 @@ /* von welchen Sockets koennte gelesen werden? */ t = time( NULL ); read_sockets = My_Sockets; - for( i = 0; i < MAX_CONNECTIONS; i++ ) + for( i = 0; i < Pool_Size; i++ ) { if(( My_Connections[i].sock > NONE ) && ( My_Connections[i].host[0] == '\0' )) { @@ -373,7 +470,7 @@ BOOLEAN ok; va_list ap; - assert( Idx >= 0 ); + assert( Idx > NONE ); assert( Format != NULL ); #ifdef PROTOTYPES @@ -394,6 +491,7 @@ strcat( buffer, "\r\n" ); ok = Conn_Write( Idx, buffer, strlen( buffer )); + My_Connections[Idx].msg_out++; va_end( ap ); return ok; @@ -406,47 +504,56 @@ /* Daten in Socket schreiben. Bei "fatalen" Fehlern wird * der Client disconnectiert und FALSE geliefert. */ - assert( Idx >= 0 ); + assert( Idx > NONE ); assert( Data != NULL ); assert( Len > 0 ); - /* Ist der entsprechende Socket ueberhaupt noch offen? - * In einem "Handler-Durchlauf" kann es passieren, dass - * dem nicht mehr so ist, wenn einer von mehreren - * Conn_Write()'s fehlgeschlagen ist. In diesem Fall - * wird hier einfach ein Fehler geliefert. */ + /* 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. */ if( My_Connections[Idx].sock <= NONE ) { Log( LOG_DEBUG, "Skipped write on closed socket (connection %d).", Idx ); return FALSE; } - /* pruefen, ob Daten im Schreibpuffer sind. Wenn ja, zunaechst - * pruefen, ob diese gesendet werden koennen */ - if( My_Connections[Idx].wdatalen > 0 ) + /* 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( WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - Len <= 0 ) { + /* Der Puffer ist dummerweise voll. Jetzt versuchen, den Puffer + * zu schreiben, wenn das nicht klappt, haben wir ein Problem ... */ if( ! Try_Write( Idx )) return FALSE; + + /* nun neu pruefen: */ + if( WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - Len <= 0 ) + { + Log( LOG_NOTICE, "Write buffer overflow (connection %d)!", Idx ); + Conn_Close( Idx, "Write buffer overflow!", NULL, FALSE ); + return FALSE; + } } - /* pruefen, ob im Schreibpuffer genuegend Platz ist */ - if( WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - Len <= 0 ) +#ifdef USE_ZLIB + if( My_Connections[Idx].options & CONN_ZIP ) { - /* der Puffer ist dummerweise voll ... */ - Log( LOG_NOTICE, "Write buffer overflow (connection %d)!", Idx ); - Conn_Close( Idx, "Write buffer overflow!", NULL, FALSE ); - return FALSE; + /* Daten komprimieren und in Puffer kopieren */ + if( ! Zip_Buffer( Idx, Data, Len )) return FALSE; } - - /* Daten in Puffer kopieren */ - memcpy( My_Connections[Idx].wbuf + My_Connections[Idx].wdatalen, Data, Len ); - My_Connections[Idx].wdatalen += Len; - - /* pruefen, on Daten vorhanden sind und geschrieben werden koennen */ - if( My_Connections[Idx].wdatalen > 0 ) + else +#endif { - if( ! Try_Write( Idx )) return FALSE; + /* Daten in Puffer kopieren */ + memcpy( My_Connections[Idx].wbuf + My_Connections[Idx].wdatalen, Data, Len ); + My_Connections[Idx].wdatalen += Len; + My_Connections[Idx].bytes_out += Len; } + /* Adjust global write counter */ + WCounter += Len; + return TRUE; } /* Conn_Write */ @@ -458,24 +565,59 @@ * Sub-Prozessen offene Pipes werden geschlossen. */ CLIENT *c; + DOUBLE in_k, out_k; +#ifdef USE_ZLIB + DOUBLE in_z_k, out_z_k; + INT in_p, out_p; +#endif - assert( Idx >= 0 ); + assert( Idx > NONE ); assert( My_Connections[Idx].sock > NONE ); + c = Client_GetFromConn( Idx ); + if( InformClient ) { +#ifndef STRICT_RFC + /* Statistik an Client melden, wenn User */ + if(( c != NULL ) && ( Client_Type( c ) == CLIENT_USER )) + { + Conn_WriteStr( Idx, "NOTICE %s :%sConnection statistics: client %.1f kb, server %.1f kb.", Client_ThisServer( ), NOTICE_TXTPREFIX, (DOUBLE)My_Connections[Idx].bytes_in / 1024, (DOUBLE)My_Connections[Idx].bytes_out / 1024 ); + } +#endif + + /* ERROR an Client schicken (von RFC so vorgesehen!) */ if( FwdMsg ) Conn_WriteStr( Idx, "ERROR :%s", FwdMsg ); else Conn_WriteStr( Idx, "ERROR :Closing connection." ); if( My_Connections[Idx].sock == NONE ) return; } + /* zunaechst versuchen, noch im Schreibpuffer vorhandene + * Daten auf den Socket zu schreiben ... */ + Try_Write( Idx ); + if( close( My_Connections[Idx].sock ) != 0 ) { - Log( LOG_ERR, "Error closing connection %d (socket %d) with %s:%d - %s!", Idx, My_Connections[Idx].sock, inet_ntoa( My_Connections[Idx].addr.sin_addr ), ntohs( My_Connections[Idx].addr.sin_port), strerror( errno )); + Log( LOG_ERR, "Error closing connection %d (socket %d) with %s:%d - %s!", Idx, My_Connections[Idx].sock, My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port), strerror( errno )); } else { - Log( LOG_INFO, "Connection %d (socket %d) with %s:%d closed.", Idx, My_Connections[Idx].sock, inet_ntoa( My_Connections[Idx].addr.sin_addr ), ntohs( My_Connections[Idx].addr.sin_port )); + in_k = (DOUBLE)My_Connections[Idx].bytes_in / 1024; + out_k = (DOUBLE)My_Connections[Idx].bytes_out / 1024; +#ifdef USE_ZLIB + if( My_Connections[Idx].options & CONN_ZIP ) + { + in_z_k = (DOUBLE)My_Connections[Idx].zip.bytes_in / 1024; + out_z_k = (DOUBLE)My_Connections[Idx].zip.bytes_out / 1024; + in_p = (INT)(( in_k * 100 ) / in_z_k ); + out_p = (INT)(( out_k * 100 ) / out_z_k ); + Log( LOG_INFO, "Connection %d with %s:%d closed (in: %.1fk/%.1fk/%d%%, out: %.1fk/%.1fk/%d%%).", Idx, My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port ), in_k, in_z_k, in_p, out_k, out_z_k, out_p ); + } + else +#endif + { + Log( LOG_INFO, "Connection %d with %s:%d closed (in: %.1fk, out: %.1fk).", Idx, My_Connections[Idx].host, ntohs( My_Connections[Idx].addr.sin_port ), in_k, out_k ); + } } /* Socket als "ungueltig" markieren */ @@ -483,7 +625,6 @@ FD_CLR( My_Connections[Idx].sock, &My_Connects ); My_Connections[Idx].sock = NONE; - c = Client_GetFromConn( Idx ); if( c ) Client_Destroy( c, LogMsg, FwdMsg, TRUE ); if( My_Connections[Idx].res_stat ) @@ -496,7 +637,7 @@ } /* Startzeit des naechsten Connect-Versuchs modifizieren? */ - if(( My_Connections[Idx].our_server >= 0 ) && ( Conf_Server[My_Connections[Idx].our_server].lasttry < time( NULL ) - Conf_ConnectRetry )) + if(( My_Connections[Idx].our_server > NONE ) && ( Conf_Server[My_Connections[Idx].our_server].lasttry < time( NULL ) - Conf_ConnectRetry )) { /* Okay, die Verbindung stand schon "genuegend lange": * lasttry-Zeitpunkt so setzen, dass der naechste @@ -505,6 +646,15 @@ Conf_Server[My_Connections[Idx].our_server].lasttry = time( NULL ) - Conf_ConnectRetry + RECONNECT_DELAY; } +#ifdef USE_ZLIB + /* Ggf. zlib abmelden */ + if( Conn_Options( Idx ) & CONN_ZIP ) + { + inflateEnd( &My_Connections[Idx].zip.in ); + deflateEnd( &My_Connections[Idx].zip.out ); + } +#endif + /* Connection-Struktur loeschen (=freigeben) */ Init_Conn_Struct( Idx ); } /* Conn_Close */ @@ -515,7 +665,7 @@ { /* Idle-Timer zuruecksetzen */ - assert( Idx >= 0 ); + assert( Idx > NONE ); My_Connections[Idx].lastprivmsg = time( NULL ); } @@ -525,7 +675,7 @@ { /* Idle-Time einer Verbindung liefern (in Sekunden) */ - assert( Idx >= 0 ); + assert( Idx > NONE ); return time( NULL ) - My_Connections[Idx].lastprivmsg; } /* Conn_GetIdle */ @@ -535,7 +685,7 @@ { /* Zeitpunkt des letzten PING liefern */ - assert( Idx >= 0 ); + assert( Idx > NONE ); return My_Connections[Idx].lastping; } /* Conn_LastPing */ @@ -550,7 +700,7 @@ time_t t; - assert( Idx >= 0 ); + assert( Idx > NONE ); assert( Seconds >= 0 ); t = time( NULL ) + Seconds; @@ -558,18 +708,306 @@ } /* Conn_SetPenalty */ +GLOBAL VOID +Conn_ResetPenalty( CONN_ID Idx ) +{ + assert( Idx > NONE ); + My_Connections[Idx].delaytime = 0; +} /* Conn_ResetPenalty */ + + +GLOBAL VOID +Conn_ClearFlags( VOID ) +{ + /* Alle Connection auf "nicht-markiert" setzen */ + + LONG i; + + for( i = 0; i < Pool_Size; i++ ) My_Connections[i].flag = 0; +} /* Conn_ClearFlags */ + + +GLOBAL INT +Conn_Flag( CONN_ID Idx ) +{ + /* Ist eine Connection markiert (TRUE) oder nicht? */ + + assert( Idx > NONE ); + return My_Connections[Idx].flag; +} /* Conn_Flag */ + + +GLOBAL VOID +Conn_SetFlag( CONN_ID Idx, INT Flag ) +{ + /* Connection markieren */ + + assert( Idx > NONE ); + My_Connections[Idx].flag = Flag; +} /* Conn_SetFlag */ + + +GLOBAL CONN_ID +Conn_First( VOID ) +{ + /* Connection-Struktur der ersten Verbindung liefern; + * Ist keine Verbindung vorhanden, wird NONE geliefert. */ + + LONG i; + + for( i = 0; i < Pool_Size; i++ ) + { + if( My_Connections[i].sock != NONE ) return i; + } + return NONE; +} /* Conn_First */ + + +GLOBAL CONN_ID +Conn_Next( CONN_ID Idx ) +{ + /* Naechste Verbindungs-Struktur liefern; existiert keine + * weitere, so wird NONE geliefert. */ + + LONG i = NONE; + + assert( Idx > NONE ); + + for( i = Idx + 1; i < Pool_Size; i++ ) + { + if( My_Connections[i].sock != NONE ) return i; + } + return NONE; +} /* Conn_Next */ + + +GLOBAL VOID +Conn_SetServer( CONN_ID Idx, INT ConfServer ) +{ + /* Connection als Server markieren: Index des konfigurierten + * Servers speichern. Verbindung muss bereits bestehen! */ + + assert( Idx > NONE ); + assert( My_Connections[Idx].sock > NONE ); + + My_Connections[Idx].our_server = ConfServer; +} /* Conn_SetServer */ + + +GLOBAL VOID +Conn_SetOption( CONN_ID Idx, INT Option ) +{ + /* Option fuer Verbindung setzen. + * Initial sind alle Optionen _nicht_ gesetzt. */ + + assert( Idx > NONE ); + assert( Option != 0 ); + + My_Connections[Idx].options |= Option; +} /* Conn_SetOption */ + + +GLOBAL VOID +Conn_UnsetOption( CONN_ID Idx, INT Option ) +{ + /* Option fuer Verbindung loeschen */ + + assert( Idx > NONE ); + assert( Option != 0 ); + + My_Connections[Idx].options &= ~Option; +} /* Conn_UnsetOption */ + + +GLOBAL INT +Conn_Options( CONN_ID Idx ) +{ + assert( Idx > NONE ); + return My_Connections[Idx].options; +} /* Conn_Options */ + + +#ifdef USE_ZLIB + +GLOBAL BOOLEAN +Conn_InitZip( CONN_ID Idx ) +{ + /* Kompression fuer Link initialisieren */ + + assert( Idx > NONE ); + + My_Connections[Idx].zip.in.avail_in = 0; + My_Connections[Idx].zip.in.total_in = 0; + My_Connections[Idx].zip.in.total_out = 0; + My_Connections[Idx].zip.in.zalloc = NULL; + My_Connections[Idx].zip.in.zfree = NULL; + My_Connections[Idx].zip.in.data_type = Z_ASCII; + + if( inflateInit( &My_Connections[Idx].zip.in ) != Z_OK ) + { + /* Fehler! */ + Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib inflate)!", Idx ); + return FALSE; + } + + My_Connections[Idx].zip.out.total_in = 0; + My_Connections[Idx].zip.out.total_in = 0; + My_Connections[Idx].zip.out.zalloc = NULL; + My_Connections[Idx].zip.out.zfree = NULL; + My_Connections[Idx].zip.out.data_type = Z_ASCII; + + if( deflateInit( &My_Connections[Idx].zip.out, Z_DEFAULT_COMPRESSION ) != Z_OK ) + { + /* Fehler! */ + Log( LOG_ALERT, "Can't initialize compression on connection %d (zlib deflate)!", Idx ); + return FALSE; + } + + My_Connections[Idx].zip.bytes_in = My_Connections[Idx].bytes_in; + My_Connections[Idx].zip.bytes_out = My_Connections[Idx].bytes_out; + + Log( LOG_INFO, "Enabled link compression (zlib) on connection %d.", Idx ); + Conn_SetOption( Idx, CONN_ZIP ); + + return TRUE; +} /* Conn_InitZip */ + + +GLOBAL LONG +Conn_SendBytesZip( CONN_ID Idx ) +{ + /* Anzahl gesendeter Bytes (komprimiert!) liefern */ + + assert( Idx > NONE ); + return My_Connections[Idx].zip.bytes_out; +} /* Conn_SendBytesZip */ + + +GLOBAL LONG +Conn_RecvBytesZip( CONN_ID Idx ) +{ + /* Anzahl gesendeter Bytes (komprimiert!) liefern */ + + assert( Idx > NONE ); + return My_Connections[Idx].zip.bytes_in; +} /* Conn_RecvBytesZip */ + +#endif + + +GLOBAL time_t +Conn_StartTime( CONN_ID Idx ) +{ + /* Zeitpunkt des Link-Starts liefern (in Sekunden) */ + + assert( Idx > NONE ); + return My_Connections[Idx].starttime; +} /* Conn_Uptime */ + + +GLOBAL INT +Conn_SendQ( CONN_ID Idx ) +{ + /* Laenge der Daten im Schreibbuffer liefern */ + + assert( Idx > NONE ); +#ifdef USE_ZLIB + if( My_Connections[Idx].options & CONN_ZIP ) return My_Connections[Idx].zip.wdatalen; + else +#endif + return My_Connections[Idx].wdatalen; +} /* Conn_SendQ */ + + +GLOBAL LONG +Conn_SendMsg( CONN_ID Idx ) +{ + /* Anzahl gesendeter Nachrichten liefern */ + + assert( Idx > NONE ); + return My_Connections[Idx].msg_out; +} /* Conn_SendMsg */ + + +GLOBAL LONG +Conn_SendBytes( CONN_ID Idx ) +{ + /* Anzahl gesendeter Bytes (unkomprimiert) liefern */ + + assert( Idx > NONE ); + return My_Connections[Idx].bytes_out; +} /* Conn_SendBytes */ + + +GLOBAL INT +Conn_RecvQ( CONN_ID Idx ) +{ + /* Laenge der Daten im Lesebuffer liefern */ + + assert( Idx > NONE ); +#ifdef USE_ZLIB + if( My_Connections[Idx].options & CONN_ZIP ) return My_Connections[Idx].zip.rdatalen; + else +#endif + return My_Connections[Idx].rdatalen; +} /* Conn_RecvQ */ + + +GLOBAL LONG +Conn_RecvMsg( CONN_ID Idx ) +{ + /* Anzahl empfangener Nachrichten liefern */ + + assert( Idx > NONE ); + return My_Connections[Idx].msg_in; +} /* Conn_RecvMsg */ + + +GLOBAL LONG +Conn_RecvBytes( CONN_ID Idx ) +{ + /* Anzahl empfangener Bytes (unkomprimiert) liefern */ + + assert( Idx > NONE ); + return My_Connections[Idx].bytes_in; +} /* Conn_RecvBytes */ + + +GLOBAL VOID +Conn_ResetWCounter( VOID ) +{ + WCounter = 0; +} /* Conn_ResetWCounter */ + + +GLOBAL LONG +Conn_WCounter( VOID ) +{ + return WCounter; +} /* Conn_WCounter */ + + LOCAL BOOLEAN Try_Write( CONN_ID Idx ) { - /* Versuchen, Daten aus dem Schreib-Puffer in den - * Socket zu schreiben. */ + /* Versuchen, Daten aus dem Schreib-Puffer in den Socket zu + * schreiben. TRUE wird geliefert, wenn entweder keine Daten + * zum Versenden vorhanden sind oder erfolgreich bearbeitet + * werden konnten. Im Fehlerfall wird FALSE geliefert und + * die Verbindung geschlossen. */ fd_set write_socket; struct timeval tv; - assert( Idx >= 0 ); + assert( Idx > NONE ); assert( My_Connections[Idx].sock > NONE ); - assert( My_Connections[Idx].wdatalen > 0 ); + + /* sind ueberhaupt Daten vorhanden? */ +#ifdef USE_ZLIB + if(( ! My_Connections[Idx].wdatalen > 0 ) && ( ! My_Connections[Idx].zip.wdatalen )) return TRUE; +#else + if( ! My_Connections[Idx].wdatalen > 0 ) return TRUE; +#endif /* Timeout initialisieren: 0 Sekunden, also nicht blockieren */ tv.tv_sec = 0; tv.tv_usec = 0; @@ -602,7 +1040,7 @@ CONN_ID idx; - assert( Sock >= 0 ); + assert( Sock > NONE ); if( FD_ISSET( Sock, &My_Listeners )) { @@ -669,10 +1107,16 @@ Log( LOG_DEBUG, "Connection %d with \"%s:%d\" established, now sendig PASS and SERVER ...", Idx, My_Connections[Idx].host, Conf_Server[My_Connections[Idx].our_server].port ); /* PASS und SERVER verschicken */ - Conn_WriteStr( Idx, "PASS %s %s", Conf_Server[My_Connections[Idx].our_server].pwd, NGIRCd_ProtoID ); + Conn_WriteStr( Idx, "PASS %s %s", Conf_Server[My_Connections[Idx].our_server].pwd_out, NGIRCd_ProtoID ); return Conn_WriteStr( Idx, "SERVER %s :%s", Conf_ServerName, Conf_ServerInfo ); } +#ifdef USE_ZLIB + /* Schreibpuffer leer, aber noch Daten im Kompressionsbuffer? + * Dann muss dieser nun geflushed werden! */ + if( My_Connections[Idx].wdatalen == 0 ) Zip_Flush( Idx ); +#endif + assert( My_Connections[Idx].wdatalen > 0 ); /* Daten schreiben */ @@ -707,8 +1151,10 @@ RES_STAT *s; CONN_ID idx; CLIENT *c; + POINTER *ptr; + LONG new_size; - assert( Sock >= 0 ); + assert( Sock > NONE ); /* Connection auf Listen-Socket annehmen */ new_sock_len = sizeof( new_addr ); @@ -723,12 +1169,59 @@ Init_Socket( new_sock ); /* Freie Connection-Struktur suchen */ - for( idx = 0; idx < MAX_CONNECTIONS; idx++ ) if( My_Connections[idx].sock == NONE ) break; - if( idx >= MAX_CONNECTIONS ) + for( idx = 0; idx < Pool_Size; idx++ ) if( My_Connections[idx].sock == NONE ) break; + if( idx >= Pool_Size ) { - Log( LOG_ALERT, "Can't accept connection: limit reached (%d)!", MAX_CONNECTIONS ); - close( new_sock ); - return; + new_size = Pool_Size + CONNECTION_POOL; + + /* Im bisherigen Pool wurde keine freie Connection-Struktur mehr gefunden. + * Wenn erlaubt und moeglich muss nun der Pool vergroessert werden: */ + + if( Conf_MaxConnections > 0 ) + { + /* Es ist ein Limit konfiguriert */ + if( Pool_Size >= Conf_MaxConnections ) + { + /* Mehr Verbindungen duerfen wir leider nicht mehr annehmen ... */ + Log( LOG_ALERT, "Can't accept connection: limit (%d) reached!", Pool_Size ); + close( new_sock ); + return; + } + if( new_size > Conf_MaxConnections ) new_size = Conf_MaxConnections; + } + + /* zunaechst realloc() versuchen; wenn das scheitert, malloc() versuchen + * und Daten ggf. "haendisch" umkopieren. (Haesslich! Eine wirklich + * dynamische Verwaltung waere wohl _deutlich_ besser ...) */ + ptr = realloc( My_Connections, sizeof( CONNECTION ) * new_size ); + if( ! ptr ) + { + /* realloc() ist fehlgeschlagen. Nun malloc() probieren: */ + ptr = malloc( sizeof( CONNECTION ) * new_size ); + if( ! ptr ) + { + /* Offenbar steht kein weiterer Sepeicher zur Verfuegung :-( */ + Log( LOG_EMERG, "Can't allocate memory! [New_Connection]" ); + close( new_sock ); + return; + } + + /* Struktur umkopieren ... */ + memcpy( ptr, My_Connections, sizeof( CONNECTION ) * Pool_Size ); + + Log( LOG_DEBUG, "Allocated new connection pool for %ld items (%ld bytes). [malloc()/memcpy()]", new_size, sizeof( CONNECTION ) * new_size ); + } + else Log( LOG_DEBUG, "Allocated new connection pool for %ld items (%ld bytes). [realloc()]", new_size, sizeof( CONNECTION ) * new_size ); + + /* Adjust pointer to new block */ + My_Connections = ptr; + + /* Initialize new items */ + for( idx = Pool_Size; idx < new_size; idx++ ) Init_Conn_Struct( idx ); + idx = Pool_Size; + + /* Adjust new pool size */ + Pool_Size = new_size; } /* Client-Struktur initialisieren */ @@ -752,21 +1245,17 @@ Log( LOG_INFO, "Accepted connection %d from %s:%d on socket %d.", idx, inet_ntoa( new_addr.sin_addr ), ntohs( new_addr.sin_port), Sock ); /* Hostnamen ermitteln */ + strcpy( My_Connections[idx].host, inet_ntoa( new_addr.sin_addr )); + Client_SetHostname( c, My_Connections[idx].host ); s = Resolve_Addr( &new_addr ); if( s ) { /* Sub-Prozess wurde asyncron gestartet */ My_Connections[idx].res_stat = s; } - else - { - /* kann Namen nicht aufloesen, daher wird die IP-Adresse verwendet */ - strcpy( My_Connections[idx].host, inet_ntoa( new_addr.sin_addr )); - Client_SetHostname( c, My_Connections[idx].host ); - } /* Penalty-Zeit setzen */ - Conn_SetPenalty( idx, 1 ); + Conn_SetPenalty( idx, 4 ); } /* New_Connection */ @@ -777,11 +1266,11 @@ CONN_ID idx; - assert( Sock >= 0 ); + assert( Sock > NONE ); - for( idx = 0; idx < MAX_CONNECTIONS; idx++ ) if( My_Connections[idx].sock == Sock ) break; + for( idx = 0; idx < Pool_Size; idx++ ) if( My_Connections[idx].sock == Sock ) break; - if( idx >= MAX_CONNECTIONS ) + if( idx >= Pool_Size ) { /* die Connection wurde vermutlich (wegen eines * Fehlers) bereits wieder abgebaut ... */ @@ -798,12 +1287,27 @@ /* Daten von Socket einlesen und entsprechend behandeln. * Tritt ein Fehler auf, so wird der Socket geschlossen. */ - INT len; + INT len, bsize; +#ifdef USE_ZLIB + CLIENT *c; +#endif - assert( Idx >= 0 ); + assert( Idx > NONE ); assert( My_Connections[Idx].sock > NONE ); + + /* wenn noch nicht registriert: maximal mit ZREADBUFFER_LEN arbeiten, + * ansonsten koennen Daten ggf. nicht umkopiert werden. */ + bsize = READBUFFER_LEN; +#ifdef USE_ZLIB + c = Client_GetFromConn( Idx ); + if(( Client_Type( c ) != CLIENT_USER ) && ( Client_Type( c ) != CLIENT_SERVER ) && ( Client_Type( c ) != CLIENT_SERVICE ) && ( bsize > ZREADBUFFER_LEN )) bsize = ZREADBUFFER_LEN; +#endif - if( READBUFFER_LEN - My_Connections[Idx].rdatalen - 2 < 0 ) +#ifdef USE_ZLIB + if(( bsize - My_Connections[Idx].rdatalen - 1 < 1 ) || ( ZREADBUFFER_LEN - My_Connections[Idx].zip.rdatalen < 1 )) +#else + if( bsize - My_Connections[Idx].rdatalen - 1 < 1 ) +#endif { /* Der Lesepuffer ist voll */ Log( LOG_ERR, "Read buffer overflow (connection %d): %d bytes!", Idx, My_Connections[Idx].rdatalen ); @@ -811,12 +1315,23 @@ return; } - len = recv( My_Connections[Idx].sock, My_Connections[Idx].rbuf + My_Connections[Idx].rdatalen, READBUFFER_LEN - My_Connections[Idx].rdatalen - 2, 0 ); +#ifdef USE_ZLIB + if( My_Connections[Idx].options & CONN_ZIP ) + { + len = recv( My_Connections[Idx].sock, My_Connections[Idx].zip.rbuf + My_Connections[Idx].zip.rdatalen, ( ZREADBUFFER_LEN - My_Connections[Idx].zip.rdatalen ), 0 ); + if( len > 0 ) My_Connections[Idx].zip.rdatalen += len; + } + else +#endif + { + len = recv( My_Connections[Idx].sock, My_Connections[Idx].rbuf + My_Connections[Idx].rdatalen, bsize - My_Connections[Idx].rdatalen - 1, 0 ); + if( len > 0 ) My_Connections[Idx].rdatalen += len; + } if( len == 0 ) { /* Socket wurde geschlossen */ - Log( LOG_INFO, "%s:%d is closing the connection ...", inet_ntoa( My_Connections[Idx].addr.sin_addr ), ntohs( My_Connections[Idx].addr.sin_port)); + 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; } @@ -832,10 +1347,8 @@ return; } - /* Lesebuffer updaten */ - My_Connections[Idx].rdatalen += len; - assert( My_Connections[Idx].rdatalen < READBUFFER_LEN ); - My_Connections[Idx].rbuf[My_Connections[Idx].rdatalen] = '\0'; + /* Connection-Statistik aktualisieren */ + My_Connections[Idx].bytes_in += len; /* Timestamp aktualisieren */ My_Connections[Idx].lastdata = time( NULL ); @@ -856,56 +1369,103 @@ #endif CHAR *ptr; INT len, delta; - BOOLEAN action; - - /* Eine komplette Anfrage muss mit CR+LF enden, vgl. - * RFC 2812. Haben wir eine? */ - ptr = strstr( My_Connections[Idx].rbuf, "\r\n" ); - - if( ptr ) delta = 2; -#ifndef STRICT_RFC - else - { - /* Nicht RFC-konforme Anfrage mit nur CR oder LF? Leider - * machen soetwas viele Clients, u.a. "mIRC" :-( */ - ptr1 = strchr( My_Connections[Idx].rbuf, '\r' ); - ptr2 = strchr( My_Connections[Idx].rbuf, '\n' ); - delta = 1; - if( ptr1 && ptr2 ) ptr = ptr1 > ptr2 ? ptr2 : ptr1; - else if( ptr1 ) ptr = ptr1; - else if( ptr2 ) ptr = ptr2; - } + BOOLEAN action, result; +#ifdef USE_ZLIB + BOOLEAN old_z; #endif - action = FALSE; - if( ptr ) - { - /* Ende der Anfrage wurde gefunden */ - *ptr = '\0'; - len = ( ptr - My_Connections[Idx].rbuf ) + delta; - if( len > ( COMMAND_LEN - 1 )) - { - /* Eine Anfrage darf(!) nicht laenger als 512 Zeichen - * (incl. CR+LF!) werden; vgl. RFC 2812. Wenn soetwas - * empfangen wird, wird der Client disconnectiert. */ - Log( LOG_ERR, "Request too long (connection %d): %d bytes (max. %d expected)!", Idx, My_Connections[Idx].rdatalen, COMMAND_LEN - 1 ); - Conn_Close( Idx, NULL, "Request too long", TRUE ); - return FALSE; + result = FALSE; + do + { +#ifdef USE_ZLIB + /* ggf. noch unkomprimiete Daten weiter entpacken */ + if( My_Connections[Idx].options & CONN_ZIP ) + { + if( ! Unzip_Buffer( Idx )) return FALSE; } +#endif + + if( My_Connections[Idx].rdatalen < 1 ) break; - if( len > delta ) + /* Eine komplette Anfrage muss mit CR+LF enden, vgl. + * RFC 2812. Haben wir eine? */ + My_Connections[Idx].rbuf[My_Connections[Idx].rdatalen] = '\0'; + ptr = strstr( My_Connections[Idx].rbuf, "\r\n" ); + + if( ptr ) delta = 2; +#ifndef STRICT_RFC + else { - /* Es wurde ein Request gelesen */ - if( ! Parse_Request( Idx, My_Connections[Idx].rbuf )) return FALSE; - else action = TRUE; + /* Nicht RFC-konforme Anfrage mit nur CR oder LF? Leider + * machen soetwas viele Clients, u.a. "mIRC" :-( */ + ptr1 = strchr( My_Connections[Idx].rbuf, '\r' ); + ptr2 = strchr( My_Connections[Idx].rbuf, '\n' ); + delta = 1; + if( ptr1 && ptr2 ) ptr = ptr1 > ptr2 ? ptr2 : ptr1; + else if( ptr1 ) ptr = ptr1; + else if( ptr2 ) ptr = ptr2; } +#endif + + action = FALSE; + if( ptr ) + { + /* Ende der Anfrage wurde gefunden */ + *ptr = '\0'; + len = ( ptr - My_Connections[Idx].rbuf ) + delta; + if( len > ( COMMAND_LEN - 1 )) + { + /* Eine Anfrage darf(!) nicht laenger als 512 Zeichen + * (incl. CR+LF!) werden; vgl. RFC 2812. Wenn soetwas + * empfangen wird, wird der Client disconnectiert. */ + Log( LOG_ERR, "Request too long (connection %d): %d bytes (max. %d expected)!", Idx, My_Connections[Idx].rdatalen, COMMAND_LEN - 1 ); + Conn_Close( Idx, NULL, "Request too long", TRUE ); + return FALSE; + } - /* Puffer anpassen */ - My_Connections[Idx].rdatalen -= len; - memmove( My_Connections[Idx].rbuf, My_Connections[Idx].rbuf + len, My_Connections[Idx].rdatalen ); - } +#ifdef USE_ZLIB + /* merken, ob Stream bereits komprimiert wird */ + old_z = My_Connections[Idx].options & CONN_ZIP; +#endif + + if( len > delta ) + { + /* Es wurde ein Request gelesen */ + My_Connections[Idx].msg_in++; + if( ! Parse_Request( Idx, My_Connections[Idx].rbuf )) return FALSE; + else action = TRUE; + } + + /* Puffer anpassen */ + My_Connections[Idx].rdatalen -= len; + memmove( My_Connections[Idx].rbuf, My_Connections[Idx].rbuf + len, My_Connections[Idx].rdatalen ); + +#ifdef USE_ZLIB + if(( ! old_z ) && ( My_Connections[Idx].options & CONN_ZIP ) && ( My_Connections[Idx].rdatalen > 0 )) + { + /* Mit dem letzten Befehl wurde Socket-Kompression aktiviert. + * Evtl. schon vom Socket gelesene Daten in den Unzip-Puffer + * umkopieren, damit diese nun zunaechst entkomprimiert werden */ + { + if( My_Connections[Idx].rdatalen > ZREADBUFFER_LEN ) + { + /* Hupsa! Soviel Platz haben wir aber gar nicht! */ + Log( LOG_ALERT, "Can't move read buffer: No space left in unzip buffer (need %d bytes)!", My_Connections[Idx].rdatalen ); + return FALSE; + } + memcpy( My_Connections[Idx].zip.rbuf, My_Connections[Idx].rbuf, My_Connections[Idx].rdatalen ); + My_Connections[Idx].zip.rdatalen = My_Connections[Idx].rdatalen; + My_Connections[Idx].rdatalen = 0; + Log( LOG_DEBUG, "Moved already received data (%d bytes) to uncompression buffer.", My_Connections[Idx].zip.rdatalen ); + } + } +#endif + } + + if( action ) result = TRUE; + } while( action ); - return action; + return result; } /* Handle_Buffer */ @@ -917,9 +1477,9 @@ * auch das nicht "hilft", Client disconnectieren. */ CLIENT *c; - INT i; + LONG i; - for( i = 0; i < MAX_CONNECTIONS; i++ ) + for( i = 0; i < Pool_Size; i++ ) { if( My_Connections[i].sock == NONE ) continue; @@ -965,8 +1525,9 @@ /* Pruefen, ob Server-Verbindungen aufgebaut werden * muessen bzw. koennen */ - INT idx, i, n; RES_STAT *s; + LONG idx, n; + INT i; /* Wenn "Passive-Mode" aktiv: nicht verbinden */ if( NGIRCd_Passive ) return; @@ -977,7 +1538,7 @@ if(( ! Conf_Server[i].host[0] ) || ( ! Conf_Server[i].port > 0 )) continue; /* Haben wir schon eine Verbindung? */ - for( n = 0; n < MAX_CONNECTIONS; n++ ) + for( n = 0; n < Pool_Size; n++ ) { if( My_Connections[n].sock == NONE ) continue; @@ -997,7 +1558,7 @@ if( Conf_Server[My_Connections[n].our_server].group == Conf_Server[i].group ) break; } } - if( n < MAX_CONNECTIONS ) continue; + if( n < Pool_Size ) continue; /* Wann war der letzte Connect-Versuch? */ if( Conf_Server[i].lasttry > time( NULL ) - Conf_ConnectRetry ) continue; @@ -1006,10 +1567,10 @@ Conf_Server[i].lasttry = time( NULL ); /* Freie Connection-Struktur suschen */ - for( idx = 0; idx < MAX_CONNECTIONS; idx++ ) if( My_Connections[idx].sock == NONE ) break; - if( idx >= MAX_CONNECTIONS ) + for( idx = 0; idx < Pool_Size; idx++ ) if( My_Connections[idx].sock == NONE ) break; + if( idx >= Pool_Size ) { - Log( LOG_ALERT, "Can't establist server connection: connection limit reached (%d)!", MAX_CONNECTIONS ); + Log( LOG_ALERT, "Can't establist server connection: connection limit reached (%d)!", Pool_Size ); return; } Log( LOG_DEBUG, "Preparing connection %d for \"%s\" ...", idx, Conf_Server[i].host ); @@ -1019,19 +1580,16 @@ My_Connections[idx].sock = SERVER_WAIT; My_Connections[idx].our_server = i; - /* Hostnamen in IP aufloesen */ + /* Hostnamen in IP aufloesen (Default bzw. im Fehlerfall: versuchen, den + * konfigurierten Text direkt als IP-Adresse zu verwenden ... */ + strcpy( Conf_Server[My_Connections[idx].our_server].ip, Conf_Server[i].host ); + strcpy( My_Connections[idx].host, Conf_Server[i].host ); s = Resolve_Name( Conf_Server[i].host ); if( s ) { /* Sub-Prozess wurde asyncron gestartet */ My_Connections[idx].res_stat = s; } - else - { - /* kann Namen nicht aufloesen: nun versuchen wir einfach, - * den "Text" direkt als IP-Adresse zu verwenden ... */ - strcpy( Conf_Server[My_Connections[idx].our_server].ip, Conf_Server[i].host ); - } } } /* Check_Servers */ @@ -1046,8 +1604,8 @@ INT res, new_sock; CLIENT *c; - assert( Server >= 0 ); - assert( Idx >= 0 ); + assert( Server > NONE ); + assert( Idx > NONE ); /* Wurde eine gueltige IP-Adresse gefunden? */ if( ! Conf_Server[Server].ip[0] ) @@ -1125,7 +1683,7 @@ LOCAL VOID -Init_Conn_Struct( INT Idx ) +Init_Conn_Struct( LONG Idx ) { /* Connection-Struktur initialisieren */ @@ -1137,10 +1695,26 @@ My_Connections[Idx].wbuf[0] = '\0'; My_Connections[Idx].wdatalen = 0; My_Connections[Idx].our_server = NONE; + My_Connections[Idx].starttime = time( NULL ); My_Connections[Idx].lastdata = time( NULL ); My_Connections[Idx].lastping = 0; My_Connections[Idx].lastprivmsg = time( NULL ); My_Connections[Idx].delaytime = 0; + My_Connections[Idx].bytes_in = 0; + My_Connections[Idx].bytes_out = 0; + My_Connections[Idx].msg_in = 0; + My_Connections[Idx].msg_out = 0; + My_Connections[Idx].flag = 0; + My_Connections[Idx].options = 0; + +#ifdef USE_ZLIB + My_Connections[Idx].zip.rbuf[0] = '\0'; + My_Connections[Idx].zip.rdatalen = 0; + My_Connections[Idx].zip.wbuf[0] = '\0'; + My_Connections[Idx].zip.wdatalen = 0; + My_Connections[Idx].zip.bytes_in = 0; + My_Connections[Idx].zip.bytes_out = 0; +#endif } /* Init_Conn_Struct */ @@ -1193,11 +1767,11 @@ result[len] = '\0'; /* zugehoerige Connection suchen */ - for( i = 0; i < MAX_CONNECTIONS; i++ ) + for( i = 0; i < Pool_Size; i++ ) { if(( My_Connections[i].sock != NONE ) && ( My_Connections[i].res_stat ) && ( My_Connections[i].res_stat->pipe[0] == r_fd )) break; } - if( i >= MAX_CONNECTIONS ) + if( i >= Pool_Size ) { /* Opsa! Keine passende Connection gefunden!? Vermutlich * wurde sie schon wieder geschlossen. */ @@ -1206,6 +1780,8 @@ return; } + Log( LOG_DEBUG, "Resolver: %s is \"%s\".", My_Connections[i].host, result ); + /* Aufraeumen */ close( My_Connections[i].res_stat->pipe[0] ); close( My_Connections[i].res_stat->pipe[1] ); @@ -1223,10 +1799,124 @@ else { /* Ausgehende Verbindung (=Server): IP setzen */ - assert( My_Connections[i].our_server >= 0 ); + assert( My_Connections[i].our_server > NONE ); strcpy( Conf_Server[My_Connections[i].our_server].ip, result ); } + + /* Penalty-Zeit zurueck setzen */ + Conn_ResetPenalty( i ); } /* Read_Resolver_Result */ + + +#ifdef USE_ZLIB + +LOCAL BOOLEAN +Zip_Buffer( CONN_ID Idx, CHAR *Data, INT Len ) +{ + /* Daten zum Komprimieren im "Kompressions-Puffer" sammeln. + * Es wird TRUE bei Erfolg, sonst FALSE geliefert. */ + + assert( Idx > NONE ); + assert( Data != NULL ); + assert( Len > 0 ); + + /* Ist noch Platz im Kompressions-Puffer? */ + if( ZWRITEBUFFER_LEN - My_Connections[Idx].zip.wdatalen < Len + 50 ) + { + /* Nein! Puffer zunaechst leeren ...*/ + if( ! Zip_Flush( Idx )) return FALSE; + } + + /* Daten kopieren */ + memmove( My_Connections[Idx].zip.wbuf + My_Connections[Idx].zip.wdatalen, Data, Len ); + My_Connections[Idx].zip.wdatalen += Len; + + return TRUE; +} /* Zip_Buffer */ + + +LOCAL BOOLEAN +Zip_Flush( CONN_ID Idx ) +{ + /* Daten komprimieren und in Schreibpuffer kopieren. + * Es wird TRUE bei Erfolg, sonst FALSE geliefert. */ + + INT result, out_len; + z_stream *out; + + out = &My_Connections[Idx].zip.out; + + out->next_in = My_Connections[Idx].zip.wbuf; + out->avail_in = My_Connections[Idx].zip.wdatalen; + out->next_out = My_Connections[Idx].wbuf + My_Connections[Idx].wdatalen; + out->avail_out = WRITEBUFFER_LEN - My_Connections[Idx].wdatalen; + + result = deflate( out, Z_SYNC_FLUSH ); + if(( result != Z_OK ) || ( out->avail_in > 0 )) + { + Log( LOG_ALERT, "Compression error: code %d!?", result ); + Conn_Close( Idx, "Compression error!", NULL, FALSE ); + return FALSE; + } + + out_len = WRITEBUFFER_LEN - My_Connections[Idx].wdatalen - out->avail_out; + My_Connections[Idx].wdatalen += out_len; + My_Connections[Idx].bytes_out += out_len; + My_Connections[Idx].zip.bytes_out += My_Connections[Idx].zip.wdatalen; + My_Connections[Idx].zip.wdatalen = 0; + + return TRUE; +} /* Zip_Flush */ + + +LOCAL BOOLEAN +Unzip_Buffer( CONN_ID Idx ) +{ + /* Daten entpacken und in Lesepuffer kopieren. Bei Fehlern + * wird FALSE geliefert, ansonsten TRUE. Der Fall, dass keine + * Daten mehr zu entpacken sind, ist _kein_ Fehler! */ + + INT result, in_len, out_len; + z_stream *in; + + assert( Idx > NONE ); + + if( My_Connections[Idx].zip.rdatalen <= 0 ) return TRUE; + + in = &My_Connections[Idx].zip.in; + + in->next_in = My_Connections[Idx].zip.rbuf; + in->avail_in = My_Connections[Idx].zip.rdatalen; + in->next_out = My_Connections[Idx].rbuf + My_Connections[Idx].rdatalen; + in->avail_out = READBUFFER_LEN - My_Connections[Idx].rdatalen - 1; + + result = inflate( in, Z_SYNC_FLUSH ); + if( result != Z_OK ) + { + Log( LOG_ALERT, "Decompression error: code %d (ni=%d, ai=%d, no=%d, ao=%d)!?", result, in->next_in, in->avail_in, in->next_out, in->avail_out ); + Conn_Close( Idx, "Decompression error!", NULL, FALSE ); + return FALSE; + } + + in_len = My_Connections[Idx].zip.rdatalen - in->avail_in; + out_len = READBUFFER_LEN - My_Connections[Idx].rdatalen - 1 - in->avail_out; + My_Connections[Idx].rdatalen += out_len; + + if( in->avail_in > 0 ) + { + /* es konnten nicht alle Daten entpackt werden, vermutlich war + * im Ziel-Puffer kein Platz mehr. Umkopieren ... */ + My_Connections[Idx].zip.rdatalen -= in_len; + memmove( My_Connections[Idx].zip.rbuf, My_Connections[Idx].zip.rbuf + in_len, My_Connections[Idx].zip.rdatalen ); + } + else My_Connections[Idx].zip.rdatalen = 0; + My_Connections[Idx].zip.bytes_in += out_len; + + return TRUE; +} /* Unzip_Buffer */ + + +#endif /* -eof- */ Index: src/ngircd/conn.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/conn.h,v retrieving revision 1.17 retrieving revision 1.26 diff -u -r1.17 -r1.26 --- src/ngircd/conn.h 2002/08/26 00:03:15 1.17 +++ src/ngircd/conn.h 2002/12/18 13:50:22 1.26 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: conn.h,v 1.17 2002/08/26 00:03:15 alex Exp $ + * $Id: conn.h,v 1.26 2002/12/18 13:50:22 alex Exp $ * - * conn.h: Verwaltung aller Netz-Verbindungen ("connections") (Header) + * Connection management (header) */ @@ -19,15 +18,23 @@ #define __conn_h__ -#include +#include /* wg. time_t, s.u. */ +#ifdef USE_ZLIB +#define CONN_ZIP 4 /* Kompression mit zlib */ +#endif + + typedef INT CONN_ID; GLOBAL VOID Conn_Init PARAMS((VOID )); GLOBAL VOID Conn_Exit PARAMS(( VOID )); +GLOBAL INT Conn_InitListeners PARAMS(( VOID )); +GLOBAL VOID Conn_ExitListeners PARAMS(( VOID )); + GLOBAL BOOLEAN Conn_NewListener PARAMS(( CONST UINT Port )); GLOBAL VOID Conn_Handler PARAMS(( VOID )); @@ -40,8 +47,38 @@ GLOBAL VOID Conn_UpdateIdle PARAMS(( CONN_ID Idx )); GLOBAL time_t Conn_GetIdle PARAMS(( CONN_ID Idx )); GLOBAL time_t Conn_LastPing PARAMS(( CONN_ID Idx )); +GLOBAL time_t Conn_StartTime PARAMS(( CONN_ID Idx )); +GLOBAL INT Conn_SendQ PARAMS(( CONN_ID Idx )); +GLOBAL INT Conn_RecvQ PARAMS(( CONN_ID Idx )); +GLOBAL LONG Conn_SendMsg PARAMS(( CONN_ID Idx )); +GLOBAL LONG Conn_RecvMsg PARAMS(( CONN_ID Idx )); +GLOBAL LONG Conn_SendBytes PARAMS(( CONN_ID Idx )); +GLOBAL LONG Conn_RecvBytes PARAMS(( CONN_ID Idx )); GLOBAL VOID Conn_SetPenalty PARAMS(( CONN_ID Idx, time_t Seconds )); +GLOBAL VOID Conn_ResetPenalty PARAMS(( CONN_ID Idx )); + +GLOBAL VOID Conn_ClearFlags PARAMS(( VOID )); +GLOBAL INT Conn_Flag PARAMS(( CONN_ID Idx )); +GLOBAL VOID Conn_SetFlag PARAMS(( CONN_ID Idx, INT Flag )); + +GLOBAL VOID Conn_SetServer PARAMS(( CONN_ID Idx, INT ConfServer )); + +GLOBAL CONN_ID Conn_First PARAMS(( VOID )); +GLOBAL CONN_ID Conn_Next PARAMS(( CONN_ID Idx )); + +GLOBAL VOID Conn_SetOption PARAMS(( CONN_ID Idx, INT Option )); +GLOBAL VOID Conn_UnsetOption PARAMS(( CONN_ID Idx, INT Option )); +GLOBAL INT Conn_Options PARAMS(( CONN_ID Idx )); + +#ifdef USE_ZLIB +GLOBAL BOOLEAN Conn_InitZip PARAMS(( CONN_ID Idx )); +GLOBAL LONG Conn_SendBytesZip PARAMS(( CONN_ID Idx )); +GLOBAL LONG Conn_RecvBytesZip PARAMS(( CONN_ID Idx )); +#endif + +GLOBAL VOID Conn_ResetWCounter PARAMS(( VOID )); +GLOBAL LONG Conn_WCounter PARAMS(( VOID )); GLOBAL INT Conn_MaxFD; Index: src/ngircd/defines.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/defines.h,v retrieving revision 1.33.2.1 retrieving revision 1.40 diff -u -r1.33.2.1 -r1.40 --- src/ngircd/defines.h 2002/11/23 16:20:25 1.33.2.1 +++ src/ngircd/defines.h 2002/12/16 23:10:56 1.40 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: defines.h,v 1.33.2.1 2002/11/23 16:20:25 alex Exp $ + * $Id: defines.h,v 1.40 2002/12/16 23:10:56 alex Exp $ * - * defines.h: (globale) Konstanten + * Global defines of ngIRCd. */ #ifndef __defines_h__ @@ -36,8 +35,10 @@ #define MAX_DEFCHANNELS 16 /* max. Anzahl vorkonfigurierbarerr Channels */ -#define MAX_CONNECTIONS 100 /* max. Anzahl von Verbindungen an diesem Server */ +#define MAX_SERVICES 8 /* maximum number of configurable services */ +#define CONNECTION_POOL 100 /* Anzahl Verbindungs-Strukturen, die blockweise alloziert werden */ + #define CLIENT_ID_LEN 64 /* max. ID-Laenge; vgl. RFC 2812, 1.1 und 1.2.1 */ #define CLIENT_NICK_LEN 10 /* max. Nick-Laenge; vgl. RFC 2812, 1.2.1 */ #define CLIENT_PASS_LEN 9 /* max. Laenge des Passwortes */ @@ -55,9 +56,14 @@ #define COMMAND_LEN 513 /* max. Laenge eines Befehls, vgl. RFC 2812, 3.2 */ -#define READBUFFER_LEN 2 * COMMAND_LEN /* Laenge des Lesepuffers je Verbindung (Bytes) */ +#define READBUFFER_LEN 2048 /* Laenge des Lesepuffers je Verbindung (Bytes) */ #define WRITEBUFFER_LEN 4096 /* Laenge des Schreibpuffers je Verbindung (Bytes) */ +#ifdef USE_ZLIB +#define ZREADBUFFER_LEN 1024 /* Laenge des Lesepuffers je Verbindung (Bytes) */ +#define ZWRITEBUFFER_LEN 4096 /* Laenge des Schreibpuffers fuer Kompression (Bytes) */ +#endif + #define PROTOVER "0210" /* implementierte Protokoll-Version (RFC 2813, 4.1.1) */ #define PROTOIRC "-IRC" /* Protokoll-Suffix (RFC 2813, 4.1.1) */ #define PROTOIRCPLUS "-IRC+" /* Protokoll-Suffix fŸr IRC+-Protokoll */ @@ -70,7 +76,7 @@ #define RECONNECT_DELAY 3 /* Server-Links erst nach 3 Sekunden versuchen, wieder aufzubauen */ #define USERMODES "aios" /* unterstuetzte User-Modes */ -#define CHANMODES "biImnoPtv" /* unterstuetzte Channel-Modes */ +#define CHANMODES "biklImnoPtv" /* unterstuetzte Channel-Modes */ #define CONNECTED TRUE /* fuer die irc-xxx-Module */ #define DISCONNECTED FALSE @@ -89,6 +95,8 @@ #define MAX_LOG_MSG_LEN 256 /* max. Laenge einer Log-Meldung */ #define TOKEN_OUTBOUND -2 /* Kennzeichnung fuer ausgehende Server-Links im Aufbau */ + +#define NOTICE_TXTPREFIX "" /* Kennzeichnung fuer Server-NOTICEs an User */ #endif Index: src/ngircd/hash.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/hash.c,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- src/ngircd/hash.c 2002/05/27 12:54:07 1.5 +++ src/ngircd/hash.c 2002/12/12 12:24:18 1.6 @@ -2,20 +2,19 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: hash.c,v 1.5 2002/05/27 12:54:07 alex Exp $ - * - * hash.c: Hash-Werte berechnen + * Hash calculation */ #include "portab.h" + +static char UNUSED id[] = "$Id: hash.c,v 1.6 2002/12/12 12:24:18 alex Exp $"; #include "imp.h" #include Index: src/ngircd/hash.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/hash.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- src/ngircd/hash.h 2002/05/27 12:54:07 1.3 +++ src/ngircd/hash.h 2002/12/12 12:23:43 1.4 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: hash.h,v 1.3 2002/05/27 12:54:07 alex Exp $ + * $Id: hash.h,v 1.4 2002/12/12 12:23:43 alex Exp $ * - * hash.h: Hash-Werte berechnen (Header) + * Hash calculation (header) */ Index: src/ngircd/irc-channel.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-channel.c,v retrieving revision 1.15 retrieving revision 1.21 diff -u -r1.15 -r1.21 --- src/ngircd/irc-channel.c 2002/09/16 09:16:17 1.15 +++ src/ngircd/irc-channel.c 2002/12/16 23:06:46 1.21 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-channel.c,v 1.15 2002/09/16 09:16:17 alex Exp $ - * - * irc-channel.c: IRC-Channel-Befehle + * IRC channel commands */ #include "portab.h" +static char UNUSED id[] = "$Id: irc-channel.c,v 1.21 2002/12/16 23:06:46 alex Exp $"; + #include "imp.h" #include #include @@ -30,8 +29,10 @@ #include "match.h" #include "messages.h" #include "parse.h" -#include "irc.h" +#include "irc-info.h" #include "irc-write.h" +#include "resolve.h" +#include "conf.h" #include "exp.h" #include "irc-channel.h" @@ -40,7 +41,7 @@ GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req ) { - CHAR *channame, *flags, *topic, modes[8]; + CHAR *channame, *key, *flags, *topic, modes[8]; BOOLEAN is_new_chan, is_invited, is_banned; CLIENT *target; CHANNEL *chan; @@ -48,16 +49,18 @@ assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); + /* Bad number of arguments? */ + if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - /* Wer ist der Absender? */ + /* Who is the sender? */ if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix ); else target = Client; if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); + /* Are channel keys given? */ + if( Req->argc > 1 ) key = Req->argv[1]; + else key = NULL; + /* Channel-Namen durchgehen */ chan = NULL; channame = strtok( Req->argv[0], "," ); @@ -84,6 +87,16 @@ /* Lokaler Client? */ if( Client_Type( Client ) == CLIENT_USER ) { + /* Test if the user has reached his maximum channel count */ + if( Client_Type( Client ) == CLIENT_USER ) + { + if(( Conf_MaxJoins > 0 ) && ( Channel_CountForUser( Client ) >= Conf_MaxJoins )) + { + IRC_WriteStrClient( Client, ERR_TOOMANYCHANNELS_MSG, Client_ID( Client ), channame ); + return CONNECTED; + } + } + /* Existiert der Channel bereits, oder wird er im Moment neu erzeugt? */ if( is_new_chan ) { @@ -105,18 +118,40 @@ /* Client ist gebanned (und nicht invited): */ IRC_WriteStrClient( Client, ERR_BANNEDFROMCHAN_MSG, Client_ID( Client ), channame ); - /* naechsten Namen ermitteln */ + /* Try next name, if any */ channame = strtok( NULL, "," ); continue; } /* Ist der Channel "invite-only"? */ - if(( strchr( Channel_Modes( chan ), 'i' ) != NULL ) && ( is_invited == FALSE )) + if(( strchr( Channel_Modes( chan ), 'i' )) && ( is_invited == FALSE )) { /* Channel ist "invite-only" und Client wurde nicht invited: */ IRC_WriteStrClient( Client, ERR_INVITEONLYCHAN_MSG, Client_ID( Client ), channame ); + + /* Try next name, if any */ + channame = strtok( NULL, "," ); + continue; + } + + /* Is the channel protected by a key? */ + if(( strchr( Channel_Modes( chan ), 'k' )) && ( strcmp( Channel_Key( chan ), key ? key : "" ) != 0 )) + { + /* Bad channel key! */ + IRC_WriteStrClient( Client, ERR_BADCHANNELKEY_MSG, Client_ID( Client ), channame ); + + /* Try next name, if any */ + channame = strtok( NULL, "," ); + continue; + } + + /* Are there already too many members? */ + if(( strchr( Channel_Modes( chan ), 'l' )) && ( Channel_MaxUsers( chan ) <= Channel_MemberCount( chan ))) + { + /* Bad channel key! */ + IRC_WriteStrClient( Client, ERR_CHANNELISFULL_MSG, Client_ID( Client ), channame ); - /* naechsten Namen ermitteln */ + /* Try next name, if any */ channame = strtok( NULL, "," ); continue; } @@ -189,8 +224,6 @@ assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -227,8 +260,6 @@ assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -280,8 +311,6 @@ assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -339,8 +368,6 @@ assert( Client != NULL ); assert( Req != NULL ); - - if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); /* Falsche Anzahl Parameter? */ if(( Req->argc < 1 ) || ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); Index: src/ngircd/irc-channel.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-channel.h,v retrieving revision 1.5 retrieving revision 1.6 diff -u -r1.5 -r1.6 --- src/ngircd/irc-channel.h 2002/09/03 23:56:55 1.5 +++ src/ngircd/irc-channel.h 2002/12/12 12:23:43 1.6 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-channel.h,v 1.5 2002/09/03 23:56:55 alex Exp $ + * $Id: irc-channel.h,v 1.6 2002/12/12 12:23:43 alex Exp $ * - * irc-channel.h: IRC-Channel-Befehle (Header) + * IRC channel commands (header) */ Index: src/ngircd/irc-login.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-login.c,v retrieving revision 1.21.2.1 retrieving revision 1.27.2.1 diff -u -r1.21.2.1 -r1.27.2.1 --- src/ngircd/irc-login.c 2002/09/22 21:37:06 1.21.2.1 +++ src/ngircd/irc-login.c 2002/12/22 23:42:28 1.27.2.1 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-login.c,v 1.21.2.1 2002/09/22 21:37:06 alex Exp $ - * - * irc-login.c: Anmeldung und Abmeldung im IRC + * Login and logout */ #include "portab.h" +static char UNUSED id[] = "$Id: irc-login.c,v 1.27.2.1 2002/12/22 23:42:28 alex Exp $"; + #include "imp.h" #include #include @@ -32,7 +31,7 @@ #include "log.h" #include "messages.h" #include "parse.h" -#include "irc.h" +#include "irc-info.h" #include "irc-write.h" #include "exp.h" @@ -65,7 +64,7 @@ } 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; + CHAR c2, c4, *type, *impl, *serverver, *flags, *ptr, *ircflags; INT protohigh, protolow; /* noch nicht registrierte Server-Verbindung */ @@ -94,6 +93,10 @@ if( strlen( Req->argv[1] ) > 4 ) type = &Req->argv[1][4]; else type = NULL; + /* IRC-Flags (nach RFC 2813) */ + if( Req->argc >= 4 ) ircflags = Req->argv[3]; + else ircflags = ""; + /* Implementation, Version und ngIRCd-Flags */ impl = Req->argv[2]; ptr = strchr( impl, '|' ); @@ -111,12 +114,16 @@ flags++; } else flags = ""; - Log( LOG_INFO, "Connection %d: Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", Client_Conn( Client ), impl, serverver, protohigh, protolow, flags ); + Log( LOG_INFO, "Peer announces itself as %s-%s using protocol %d.%d/IRC+ (flags: \"%s\").", impl, serverver, protohigh, protolow, flags ); } else { - serverver = flags = ""; - Log( LOG_INFO, "Connection %d: Peer announces itself as \"%s\" using protocol %d.%d.", Client_Conn( Client ), impl, protohigh, protolow ); + /* auf der anderen Seite laeuft ein Server, der + * nur das Originalprotokoll unterstuetzt */ + 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 ); } Client_SetType( Client, CLIENT_GOTPASSSERVER ); @@ -354,8 +361,6 @@ assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client )); #ifdef STRICT_RFC @@ -390,8 +395,6 @@ assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client )); if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -444,6 +447,9 @@ if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), VERSION, TARGET_CPU, TARGET_VENDOR, TARGET_OS )) return FALSE; if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return FALSE; if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )), VERSION, USERMODES, CHANMODES )) return FALSE; + + /* Features */ + if( ! IRC_WriteStrClient( Client, RPL_FEATURE_MSG, Client_ID( Client ), CLIENT_NICK_LEN - 1, CHANNEL_TOPIC_LEN - 1, CLIENT_AWAY_LEN - 1, Conf_MaxJoins )) return DISCONNECTED; Client_SetType( Client, CLIENT_USER ); Index: src/ngircd/irc-login.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-login.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- src/ngircd/irc-login.h 2002/05/27 13:09:27 1.4 +++ src/ngircd/irc-login.h 2002/12/12 12:23:43 1.5 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-login.h,v 1.4 2002/05/27 13:09:27 alex Exp $ + * $Id: irc-login.h,v 1.5 2002/12/12 12:23:43 alex Exp $ * - * irc-login.h: Anmeldung und Abmeldung im IRC (Header) + * Login and logout (header) */ Index: src/ngircd/irc-mode.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-mode.c,v retrieving revision 1.14 retrieving revision 1.24 diff -u -r1.14 -r1.24 --- src/ngircd/irc-mode.c 2002/09/08 17:07:14 1.14 +++ src/ngircd/irc-mode.c 2002/12/18 14:16:21 1.24 @@ -2,23 +2,24 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-mode.c,v 1.14 2002/09/08 17:07:14 alex Exp $ - * - * irc-mode.c: IRC-Befehle zur Mode-Aenderung (MODE, AWAY, ...) + * IRC commands for mode changes (MODE, AWAY, ...) */ #include "portab.h" +static char UNUSED id[] = "$Id: irc-mode.c,v 1.24 2002/12/18 14:16:21 alex Exp $"; + #include "imp.h" #include +#include +#include #include #include "conn.h" @@ -37,6 +38,9 @@ #include "irc-mode.h" +LOCAL BOOLEAN Client_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target )); +LOCAL BOOLEAN Channel_Mode PARAMS(( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel )); + LOCAL BOOLEAN Add_Invite PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )); LOCAL BOOLEAN Add_Ban PARAMS(( CLIENT *Prefix, CLIENT *Client, CHANNEL *Channel, CHAR *Pattern )); @@ -49,383 +53,507 @@ GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req ) { - CHAR *mode_ptr, the_modes[CLIENT_MODE_LEN], x[2]; - CLIENT *cl, *chan_cl, *prefix; - BOOLEAN set, ok, modeok; + CLIENT *cl, *origin; CHANNEL *chan; - + assert( Client != NULL ); assert( Req != NULL ); - cl = chan_cl = prefix = NULL; - chan = NULL; - - /* Valider Client? */ - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Keine Parameter? */ + /* No parameters? */ if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - /* Ziel suchen: Client bzw. Channel */ + /* Origin for answers */ + if( Client_Type( Client ) == CLIENT_SERVER ) + { + origin = Client_Search( Req->prefix ); + if( ! origin ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); + } + else origin = Client; + + /* Channel or user mode? */ + cl = chan = NULL; if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] ); if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] ); - /* Kein Ziel gefunden? */ - if(( ! cl ) && ( ! chan )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] ); + if( cl ) return Client_Mode( Client, Req, origin, cl ); + if( chan ) return Channel_Mode( Client, Req, origin, chan ); - assert(( cl && chan ) != TRUE ); + /* No target found! */ + return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] ); +} /* IRC_MODE */ - /* Falsche Anzahl Parameter? */ - if(( cl ) && ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - if(( chan ) && ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - /* Prefix fuer Antworten etc. ermitteln */ - if( Client_Type( Client ) == CLIENT_SERVER ) +LOCAL BOOLEAN +Client_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CLIENT *Target ) +{ + /* Handle client mode requests */ + + CHAR the_modes[COMMAND_LEN], x[2], *mode_ptr; + BOOLEAN ok, set; + INT mode_arg; + + /* Is the client allowed to request or change the modes? */ + if( Client_Type( Client ) == CLIENT_USER ) { - prefix = Client_Search( Req->prefix ); - if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); + /* Users are only allowed to manipulate their own modes! */ + if( Target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client )); } - else prefix = Client; - - if(( chan ) && (( Req->argc == 2 ) || ( Req->argc == 3 ))) + + /* Mode request: let's answer it :-) */ + if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_UMODEIS_MSG, Client_ID( Origin ), Client_Modes( Target )); + + mode_arg = 1; + mode_ptr = Req->argv[mode_arg]; + + /* Initial state: set or unset modes? */ + if( *mode_ptr == '+' ) set = TRUE; + else if( *mode_ptr == '-' ) set = FALSE; + else return IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Origin )); + + /* Prepare reply string */ + if( set ) strcpy( the_modes, "+" ); + else strcpy( the_modes, "-" ); + + x[1] = '\0'; + ok = CONNECTED; + while( mode_ptr ) { - /* pruefen, ob "Listen-Operation": Invite, Ban */ - if(( Req->argv[1][0] == '-' ) || ( Req->argv[1][0] == '+' )) mode_ptr = &Req->argv[1][1]; - else mode_ptr = &Req->argv[1][0]; - - if( Req->argc == 2 ) - { - /* Liste anzeigen */ - if( *mode_ptr == 'I' ) return Lists_ShowInvites( prefix, chan ); - if( *mode_ptr == 'b' ) return Lists_ShowBans( prefix, chan ); + mode_ptr++; + if( ! *mode_ptr ) + { + /* Try next argument if there's any */ + mode_arg++; + if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg]; + else break; } - else + + switch( *mode_ptr ) { - /* Listen veraendern */ - - if( Client_Type( Client ) == CLIENT_USER ) - { - /* Ist der User Channel-Operator? */ - modeok = FALSE; - if( strchr( Channel_UserModes( chan, Client ), 'o' )) modeok = TRUE; - if( Conf_OperCanMode ) - { - /* auch IRC-Operatoren duerfen MODE verwenden */ - if( Client_OperByMe( Client )) modeok = TRUE; - } - - if( ! modeok ) + case '+': + case '-': + if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set ))) { - Log( LOG_DEBUG, "Can't change modes: \"%s\" is not operator on %s!", Client_ID( Client ), Channel_Name( chan )); - return IRC_WriteStrClient( Client, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Client ), Channel_Name( chan )); + /* Action modifier ("+"/"-") must be changed ... */ + if(( the_modes[strlen( the_modes ) - 1] == '+' ) || ( the_modes[strlen( the_modes ) - 1] == '-' )) + { + /* Adjust last action modifier in result */ + the_modes[strlen( the_modes ) - 1] = *mode_ptr; + } + else + { + /* Append modifier character to result string */ + x[0] = *mode_ptr; strcat( the_modes, x ); + } + if( *mode_ptr == '+' ) set = TRUE; + else set = FALSE; } - } - - if( Req->argv[1][0] == '+' ) - { - /* Listen-Eintrag hinzufuegen */ - if( *mode_ptr == 'I' ) return Add_Invite( prefix, Client, chan, Req->argv[2] ); - if( *mode_ptr == 'b' ) return Add_Ban( prefix, Client, chan, Req->argv[2] ); - } - else if( Req->argv[1][0] == '-' ) - { - /* Listen-Eintrag loeschen */ - if( *mode_ptr == 'I' ) return Del_Invite( prefix, Client, chan, Req->argv[2] ); - if( *mode_ptr == 'b' ) return Del_Ban( prefix, Client, chan, Req->argv[2] ); - } + continue; } - } + + /* Validate modes */ + x[0] = '\0'; + switch( *mode_ptr ) + { + case 'a': + /* Away */ + if( Client_Type( Client ) == CLIENT_SERVER ) x[0] = 'a'; + else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin )); + break; + case 'i': + /* Invisible */ + x[0] = 'i'; + break; + case 'o': + /* IRC operator (only unsetable!) */ + if(( ! set ) || ( Client_Type( Client ) == CLIENT_SERVER )) + { + Client_SetOperByMe( Target, FALSE ); + x[0] = 'o'; + } + else ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin )); + break; + case 'r': + /* Restricted (only setable) */ + if(( set ) || ( Client_Type( Client ) == CLIENT_SERVER )) x[0] = 'r'; + else ok = IRC_WriteStrClient( Origin, ERR_RESTRICTED_MSG, Client_ID( Origin )); + break; + case 's': + /* Server messages */ + x[0] = 's'; + break; + default: + Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin )); + if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr ); + x[0] = '\0'; + goto client_exit; + } + if( ! ok ) break; - /* Client ermitteln, wenn bei Channel-Modes mit 3 Parametern */ - if(( chan ) && (Req->argc == 3 )) - { - chan_cl = Client_Search( Req->argv[2] ); - if( ! chan_cl ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] ); + /* Is there a valid mode change? */ + if( ! x[0] ) continue; + + if( set ) + { + /* Set mode */ + if( Client_ModeAdd( Target, x[0] )) strcat( the_modes, x ); + + } + else + { + /* Unset mode */ + if( Client_ModeDel( Target, x[0] )) strcat( the_modes, x ); + } } +client_exit: - /* Wenn Anfragender ein User ist: Zugriff erlaubt? */ - if( Client_Type( Client ) == CLIENT_USER ) + /* Are there changed modes? */ + if( the_modes[1] ) { - if( cl ) + /* Remoce needless action modifier characters */ + if(( the_modes[strlen( the_modes ) - 1] == '+' ) || ( the_modes[strlen( the_modes ) - 1] == '-' )) the_modes[strlen( the_modes ) - 1] = '\0'; + + if( Client_Type( Client ) == CLIENT_SERVER ) { - /* MODE ist nur fuer sich selber zulaessig! */ - if( cl != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client )); + /* Forward modes to other servers */ + IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes ); } - if( chan ) + else { - /* Darf der User die Channel-Modes ermitteln? */ + /* Send reply to client and inform other servers */ + ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s", Client_ID( Target ), the_modes ); + IRC_WriteStrServersPrefix( Client, Origin, "MODE %s :%s", Client_ID( Target ), the_modes ); } + Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( Target ), Client_Modes( Target )); } + + return ok; +} /* Client_Mode */ - /* Werden die Modes "nur" erfragt? */ - if(( cl ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( cl )); - if(( chan ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_CHANNELMODEIS_MSG, Client_ID( Client ), Channel_Name( chan ), Channel_Modes( chan )); - mode_ptr = Req->argv[1]; +LOCAL BOOLEAN +Channel_Mode( CLIENT *Client, REQUEST *Req, CLIENT *Origin, CHANNEL *Channel ) +{ + /* Handle channel and channel-user modes */ - /* Sollen Modes gesetzt oder geloescht werden? */ - if( cl ) - { - if( *mode_ptr == '+' ) set = TRUE; - else if( *mode_ptr == '-' ) set = FALSE; - else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client )); - mode_ptr++; - } - else + CHAR the_modes[COMMAND_LEN], the_args[COMMAND_LEN], x[2], argadd[CLIENT_PASS_LEN], *mode_ptr; + BOOLEAN ok, set, modeok, skiponce; + INT mode_arg, arg_arg; + CLIENT *client; + LONG l; + + /* Mode request: let's answer it :-) */ + if( Req->argc == 1 ) return IRC_WriteStrClient( Origin, RPL_CHANNELMODEIS_MSG, Client_ID( Origin ), Channel_Name( Channel ), Channel_Modes( Channel )); + + /* Is the user allowed to change modes? */ + if( Client_Type( Client ) == CLIENT_USER ) { - if( *mode_ptr == '-' ) set = FALSE; - else set = TRUE; - if(( *mode_ptr == '-' ) || ( *mode_ptr == '+' )) mode_ptr++; + if( strchr( Channel_UserModes( Channel, Origin ), 'o' )) modeok = TRUE; + else modeok = FALSE; + if( Conf_OperCanMode ) + { + /* auch IRC-Operatoren duerfen MODE verwenden */ + if( Client_OperByMe( Origin )) modeok = TRUE; + } } + else modeok = TRUE; + + mode_arg = 1; + mode_ptr = Req->argv[mode_arg]; + if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1; + else arg_arg = -1; + + /* Initial state: set or unset modes? */ + skiponce = FALSE; + if( *mode_ptr == '-' ) set = FALSE; + else if( *mode_ptr == '+' ) set = TRUE; + else set = skiponce = TRUE; - /* Reply-String mit Aenderungen vorbereiten */ + /* Prepare reply string */ if( set ) strcpy( the_modes, "+" ); else strcpy( the_modes, "-" ); + strcpy( the_args, " " ); - ok = TRUE; x[1] = '\0'; - while( *mode_ptr ) + ok = CONNECTED; + while( mode_ptr ) { - x[0] = '\0'; - if( Client_Type( Client ) == CLIENT_SERVER ) + if( ! skiponce ) mode_ptr++; + if( ! *mode_ptr ) { - /* Befehl kommt von einem Server, daher - * trauen wir ihm "unbesehen" ... */ - x[0] = *mode_ptr; + /* Try next argument if there's any */ + if( arg_arg > mode_arg ) mode_arg = arg_arg; + else mode_arg++; + if( mode_arg < Req->argc ) mode_ptr = Req->argv[mode_arg]; + else break; + if( Req->argc > mode_arg + 1 ) arg_arg = mode_arg + 1; + else arg_arg = -1; } - else + skiponce = FALSE; + + switch( *mode_ptr ) { - /* Modes validieren */ - if( cl ) - { - /* User-Modes */ - switch( *mode_ptr ) + case '+': + case '-': + if((( *mode_ptr == '+' ) && ( ! set )) || (( *mode_ptr == '-' ) && ( set ))) { - case 'i': - /* invisible */ - x[0] = 'i'; - break; - case 'o': - /* operator (kann nur geloescht werden) */ - if( ! set ) - { - Client_SetOperByMe( Client, FALSE ); - x[0] = 'o'; - } - else ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client )); - break; - case 'r': - /* restricted (kann nur gesetzt werden) */ - if( set ) x[0] = 'r'; - else ok = IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client )); - break; - case 's': - /* server messages */ - x[0] = 's'; - break; - default: - Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Client )); - ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr ); - x[0] = '\0'; + /* Action modifier ("+"/"-") must be changed ... */ + if(( the_modes[strlen( the_modes ) - 1] == '+' ) || ( the_modes[strlen( the_modes ) - 1] == '-' )) + { + /* Adjust last action modifier in result */ + the_modes[strlen( the_modes ) - 1] = *mode_ptr; + } + else + { + /* Append modifier character to result string */ + x[0] = *mode_ptr; strcat( the_modes, x ); + } + if( *mode_ptr == '+' ) set = TRUE; + else set = FALSE; } - } - if( chan ) - { - /* Ist der User ein Channel Operator? */ - modeok = FALSE; - if( strchr( Channel_UserModes( chan, Client ), 'o' )) modeok = TRUE; - if( Conf_OperCanMode ) + continue; + } + + /* Are there arguments left? */ + if( arg_arg >= Req->argc ) arg_arg = -1; + + /* Validate modes */ + x[0] = '\0'; + argadd[0] = '\0'; + client = NULL; + switch( *mode_ptr ) + { + /* Channel modes */ + case 'i': + /* Invite-Only */ + if( modeok ) x[0] = 'i'; + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + break; + case 'm': + /* Moderated */ + if( modeok ) x[0] = 'm'; + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + break; + case 'n': + /* kein Schreiben in den Channel von aussen */ + if( modeok ) x[0] = 'n'; + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + break; + case 't': + /* Topic Lock */ + if( modeok ) x[0] = 't'; + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + break; + case 'P': + /* Persistent channel */ + if( modeok ) { - /* auch IRC-Operatoren duerfen MODE verwenden */ - if( Client_OperByMe( Client )) modeok = TRUE; + if( set && ( ! Client_OperByMe( Client ))) + { + /* Only IRC operators are allowed to set P mode */ + ok = IRC_WriteStrClient( Origin, ERR_NOPRIVILEGES_MSG, Client_ID( Origin )); + } + else x[0] = 'P'; } + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + break; - if( ! modeok ) + /* Channel user modes */ + case 'o': + /* Channel operator */ + case 'v': + /* Voice */ + if( arg_arg > mode_arg ) { - Log( LOG_DEBUG, "Can't change modes: \"%s\" is not operator on %s!", Client_ID( Client ), Channel_Name( chan )); - ok = IRC_WriteStrClient( Client, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Client ), Channel_Name( chan )); + if( modeok ) + { + client = Client_Search( Req->argv[arg_arg] ); + if( client ) x[0] = *mode_ptr; + else ok = IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[arg_arg] ); + } + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + Req->argv[arg_arg][0] = '\0'; + arg_arg++; + } + else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); + break; + case 'k': + /* Channel key */ + if( ! set ) + { + if( modeok ) x[0] = *mode_ptr; + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); break; } - - /* Channel-Modes oder Channel-User-Modes */ - if( chan_cl ) + if( arg_arg > mode_arg ) { - /* Channel-User-Modes */ - switch( *mode_ptr ) + if( modeok ) { - case 'o': - /* Channel Operator */ - x[0] = 'o'; - break; - case 'v': - /* Voice */ - x[0] = 'v'; - break; - default: - Log( LOG_DEBUG, "Unknown channel-user-mode \"%c%c\" from \"%s\" on \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Client_ID( chan_cl ), Channel_Name( chan )); - ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr ); - x[0] = '\0'; + Channel_ModeDel( Channel, 'k' ); + Channel_SetKey( Channel, Req->argv[arg_arg] ); + strcpy( argadd, Channel_Key( Channel )); + x[0] = *mode_ptr; } + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + Req->argv[arg_arg][0] = '\0'; + arg_arg++; + } + else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); + break; + case 'l': + /* Member limit */ + if( ! set ) + { + if( modeok ) x[0] = *mode_ptr; + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + break; } - else + if( arg_arg > mode_arg ) { - /* Channel-Modes */ - switch( *mode_ptr ) + if( modeok ) { - case 'i': - /* Invite-Only */ - x[0] = 'i'; - break; - case 'm': - /* Moderated */ - x[0] = 'm'; - break; - case 'n': - /* kein Schreiben in den Channel von aussen */ - x[0] = 'n'; - break; - case 't': - /* Topic Lock */ - x[0] = 't'; - break; - case 'P': - /* Persistent */ - x[0] = 'P'; - break; - default: - Log( LOG_DEBUG, "Unknown channel-mode \"%c%c\" from \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Channel_Name( chan )); - ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Client ), set ? '+' : '-', *mode_ptr ); - x[0] = '\0'; + l = atol( Req->argv[arg_arg] ); + if( l > 0 && l < 0xFFFF ) + { + Channel_ModeDel( Channel, 'l' ); + Channel_SetMaxUsers( Channel, l ); + sprintf( argadd, "%ld", l ); + x[0] = *mode_ptr; + } } - } - } + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + Req->argv[arg_arg][0] = '\0'; + arg_arg++; + } + else ok = IRC_WriteStrClient( Origin, ERR_NEEDMOREPARAMS_MSG, Client_ID( Origin ), Req->command ); + break; + + /* Channel lists */ + case 'I': + /* Invite lists */ + if( arg_arg > mode_arg ) + { + /* modify list */ + if( modeok ) + { + if( set ) Add_Invite( Origin, Client, Channel, Req->argv[arg_arg] ); + else Del_Invite( Origin, Client, Channel, Req->argv[arg_arg] ); + } + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + Req->argv[arg_arg][0] = '\0'; + arg_arg++; + } + else Lists_ShowInvites( Origin, Channel ); + break; + case 'b': + /* Ban lists */ + if( arg_arg > mode_arg ) + { + /* modify list */ + if( modeok ) + { + if( set ) Add_Ban( Origin, Client, Channel, Req->argv[arg_arg] ); + else Del_Ban( Origin, Client, Channel, Req->argv[arg_arg] ); + } + else ok = IRC_WriteStrClient( Origin, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Origin ), Channel_Name( Channel )); + Req->argv[arg_arg][0] = '\0'; + arg_arg++; + } + else Lists_ShowBans( Origin, Channel ); + break; + + default: + Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\" on %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Origin ), Channel_Name( Channel )); + if( Client_Type( Client ) != CLIENT_SERVER ) ok = IRC_WriteStrClient( Origin, ERR_UMODEUNKNOWNFLAG2_MSG, Client_ID( Origin ), set ? '+' : '-', *mode_ptr ); + x[0] = '\0'; + goto chan_exit; } if( ! ok ) break; - - mode_ptr++; + + /* Is there a valid mode change? */ if( ! x[0] ) continue; - /* Okay, gueltigen Mode gefunden */ - if( cl ) + if( set ) { - /* Es geht um User-Modes */ - if( set ) + /* Set mode */ + if( client ) { - /* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */ - if( Client_ModeAdd( cl, x[0] )) strcat( the_modes, x ); - + /* Channel-User-Mode */ + if( Channel_UserModeAdd( Channel, client, x[0] )) + { + strcat( the_args, Client_ID( client )); + strcat( the_args, " " ); strcat( the_modes, x ); + Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client )); + } } else - { - /* Modes geloescht. Wenn der Client ihn hatte: merken */ - if( Client_ModeDel( cl, x[0] )) strcat( the_modes, x ); - } - - /* "nachbearbeiten" */ - if( x[0] == 'a' ) { - /* away */ - if( set ) Client_SetAway( cl, DEFAULT_AWAY_MSG ); - else Client_SetAway( cl, NULL ); + /* Channel-Mode */ + if( Channel_ModeAdd( Channel, x[0] )) + { + strcat( the_modes, x ); + Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel )); + } } } - if( chan ) + else { - /* Es geht um Channel-Modes oder Channel-User-Modes */ - if( chan_cl ) + /* Unset mode */ + if( client ) { - /* Channel-User-Modes */ - if( set ) - { - /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */ - if( Channel_UserModeAdd( chan, chan_cl, x[0] )) strcat( the_modes, x ); - } - else + /* Channel-User-Mode */ + if( Channel_UserModeDel( Channel, client, x[0] )) { - /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */ - if( Channel_UserModeDel( chan, chan_cl, x[0] )) strcat( the_modes, x ); + strcat( the_args, Client_ID( client )); + strcat( the_args, " " ); strcat( the_modes, x ); + Log( LOG_DEBUG, "User \"%s\": Mode change on %s, now \"%s\"", Client_Mask( client ), Channel_Name( Channel ), Channel_UserModes( Channel, client )); } } else { /* Channel-Mode */ - if( set ) + if( Channel_ModeDel( Channel, x[0] )) { - /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */ - if( Channel_ModeAdd( chan, x[0] )) strcat( the_modes, x ); + strcat( the_modes, x ); + Log( LOG_DEBUG, "Channel %s: Mode change, now \"%s\".", Channel_Name( Channel ), Channel_Modes( Channel )); } - else - { - /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */ - if( Channel_ModeDel( chan, x[0] )) strcat( the_modes, x ); - } } } + + /* Are there additional arguments to add? */ + if( argadd[0] ) + { + if( the_args[strlen( the_args ) - 1] != ' ' ) strcat( the_args, " " ); + strcat( the_args, argadd ); + } } +chan_exit: - /* Wurden Modes geaendert? */ + /* Are there changed modes? */ if( the_modes[1] ) { - if( cl ) + /* Clean up mode string */ + if(( the_modes[strlen( the_modes ) - 1] == '+' ) || ( the_modes[strlen( the_modes ) - 1] == '-' )) the_modes[strlen( the_modes ) - 1] = '\0'; + + /* Clean up argument string if there are none */ + if( ! the_args[1] ) the_args[0] = '\0'; + + if( Client_Type( Client ) == CLIENT_SERVER ) { - /* Client-Mode */ - if( Client_Type( Client ) == CLIENT_SERVER ) - { - /* Modes an andere Server forwarden */ - IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes ); - } - else - { - /* Bestaetigung an Client schicken & andere Server informieren */ - ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Client_ID( cl ), the_modes ); - IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes ); - } - Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( cl ), Client_Modes( cl )); + /* Forward mode changes to channel users and other servers */ + IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); + IRC_WriteStrChannelPrefix( Client, Channel, Origin, FALSE, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); } - if( chan ) + else { - /* Channel-Modes oder Channel-User-Mode */ - if( chan_cl ) - { - /* Channel-User-Mode */ - if( Client_Type( Client ) == CLIENT_SERVER ) - { - /* Modes an andere Server und Channel-User forwarden */ - IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl)); - IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl)); - } - else - { - /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */ - ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl)); - IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl)); - IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl)); - } - Log( LOG_DEBUG, "User \"%s\" on %s: Mode change, now \"%s\".", Client_Mask( chan_cl), Channel_Name( chan ), Channel_UserModes( chan, chan_cl )); - } - else - { - /* Channel-Mode */ - if( Client_Type( Client ) == CLIENT_SERVER ) - { - /* Modes an andere Server und Channel-User forwarden */ - IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes ); - IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes ); - } - else - { - /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */ - ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Channel_Name( chan ), the_modes ); - IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes ); - IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes ); - } - Log( LOG_DEBUG, "Channel \"%s\": Mode change, now \"%s\".", Channel_Name( chan ), Channel_Modes( chan )); - } + /* Send reply to client and inform other servers and channel users */ + ok = IRC_WriteStrClientPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); + IRC_WriteStrServersPrefix( Client, Origin, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); + IRC_WriteStrChannelPrefix( Client, Channel, Origin, FALSE, "MODE %s %s%s", Channel_Name( Channel ), the_modes, the_args ); } } - return ok; -} /* IRC_MODE */ + return CONNECTED; +} /* Channel_Mode */ GLOBAL BOOLEAN @@ -433,8 +561,6 @@ { assert( Client != NULL ); assert( Req != NULL ); - - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); /* Falsche Anzahl Parameter? */ if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); Index: src/ngircd/irc-mode.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-mode.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- src/ngircd/irc-mode.h 2002/05/27 13:09:27 1.4 +++ src/ngircd/irc-mode.h 2002/12/12 12:23:43 1.5 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-mode.h,v 1.4 2002/05/27 13:09:27 alex Exp $ + * $Id: irc-mode.h,v 1.5 2002/12/12 12:23:43 alex Exp $ * - * irc-mode.h: IRC-Befehle zur Mode-Aenderung (MODE, AWAY, ...) (Header) + * IRC commands for mode changes (header) */ Index: src/ngircd/irc-op.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-op.c,v retrieving revision 1.9 retrieving revision 1.11 diff -u -r1.9 -r1.11 --- src/ngircd/irc-op.c 2002/09/08 17:06:54 1.9 +++ src/ngircd/irc-op.c 2002/12/12 12:24:18 1.11 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-op.c,v 1.9 2002/09/08 17:06:54 alex Exp $ - * - * irc-op.c: Befehle zur Channel-Verwaltung + * Channel operator commands */ #include "portab.h" +static char UNUSED id[] = "$Id: irc-op.c,v 1.11 2002/12/12 12:24:18 alex Exp $"; + #include "imp.h" #include #include @@ -44,9 +43,6 @@ assert( Client != NULL ); assert( Req != NULL ); - /* Valider Client? */ - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if(( Req->argc < 2) || ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -72,9 +68,6 @@ assert( Client != NULL ); assert( Req != NULL ); - - /* Valider Client? */ - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); /* Falsche Anzahl Parameter? */ if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); Index: src/ngircd/irc-op.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-op.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- src/ngircd/irc-op.h 2002/09/08 00:52:55 1.2 +++ src/ngircd/irc-op.h 2002/12/12 12:23:43 1.3 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-op.h,v 1.2 2002/09/08 00:52:55 alex Exp $ + * $Id: irc-op.h,v 1.3 2002/12/12 12:23:43 alex Exp $ * - * irc-op.h: Befehle zur Channel-Verwaltung (Header) + * Channel operator commands (header) */ Index: src/ngircd/irc-oper.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-oper.c,v retrieving revision 1.8 retrieving revision 1.13 diff -u -r1.8 -r1.13 --- src/ngircd/irc-oper.c 2002/09/03 23:54:59 1.8 +++ src/ngircd/irc-oper.c 2002/12/12 12:33:14 1.13 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-oper.c,v 1.8 2002/09/03 23:54:59 alex Exp $ - * - * irc-oper.c: IRC-Operator-Befehle + * IRC operator commands */ #include "portab.h" +static char UNUSED id[] = "$Id: irc-oper.c,v 1.13 2002/12/12 12:33:14 alex Exp $"; + #include "imp.h" #include #include @@ -44,8 +43,6 @@ assert( Client != NULL ); assert( Req != NULL ); - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -88,8 +85,6 @@ assert( Client != NULL ); assert( Req != NULL ); - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -102,13 +97,29 @@ GLOBAL BOOLEAN -IRC_RESTART( CLIENT *Client, REQUEST *Req ) +IRC_REHASH( CLIENT *Client, REQUEST *Req ) { assert( Client != NULL ); assert( Req != NULL ); - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); + /* Falsche Anzahl Parameter? */ + if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); + if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client )); + + Log( LOG_NOTICE|LOG_snotice, "Got REHASH command from \"%s\", re-reading configuration ...", Client_Mask( Client )); + NGIRCd_Rehash( ); + + return CONNECTED; +} /* IRC_REHASH */ + + +GLOBAL BOOLEAN +IRC_RESTART( CLIENT *Client, REQUEST *Req ) +{ + assert( Client != NULL ); + assert( Req != NULL ); + /* Falsche Anzahl Parameter? */ if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -128,8 +139,6 @@ assert( Client != NULL ); assert( Req != NULL ); - - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); /* Falsche Anzahl Parameter? */ if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); Index: src/ngircd/irc-oper.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-oper.h,v retrieving revision 1.6 retrieving revision 1.9 diff -u -r1.6 -r1.9 --- src/ngircd/irc-oper.h 2002/09/03 23:54:59 1.6 +++ src/ngircd/irc-oper.h 2002/12/12 12:23:43 1.9 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-oper.h,v 1.6 2002/09/03 23:54:59 alex Exp $ + * $Id: irc-oper.h,v 1.9 2002/12/12 12:23:43 alex Exp $ * - * irc-oper.h: IRC-Operator-Befehle (Header) + * IRC operator commands (header) */ @@ -21,6 +20,7 @@ GLOBAL BOOLEAN IRC_OPER PARAMS((CLIENT *Client, REQUEST *Req )); GLOBAL BOOLEAN IRC_DIE PARAMS((CLIENT *Client, REQUEST *Req )); +GLOBAL BOOLEAN IRC_REHASH PARAMS((CLIENT *Client, REQUEST *Req )); GLOBAL BOOLEAN IRC_RESTART PARAMS((CLIENT *Client, REQUEST *Req )); GLOBAL BOOLEAN IRC_CONNECT PARAMS((CLIENT *Client, REQUEST *Req )); Index: src/ngircd/irc-server.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-server.c,v retrieving revision 1.17.2.2 retrieving revision 1.24 diff -u -r1.17.2.2 -r1.24 --- src/ngircd/irc-server.c 2002/10/04 13:12:46 1.17.2.2 +++ src/ngircd/irc-server.c 2002/12/12 12:24:18 1.24 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-server.c,v 1.17.2.2 2002/10/04 13:12:46 alex Exp $ - * - * irc-server.c: IRC-Befehle fuer Server-Links + * IRC commands for server links */ #include "portab.h" +static char UNUSED id[] = "$Id: irc-server.c,v 1.24 2002/12/12 12:24:18 alex Exp $"; + #include "imp.h" #include #include @@ -47,6 +46,7 @@ INT max_hops, i; CHANNEL *chan; BOOLEAN ok; + CONN_ID con; assert( Client != NULL ); assert( Req != NULL ); @@ -71,10 +71,10 @@ Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", TRUE ); return DISCONNECTED; } - if( strcmp( Client_Password( Client ), Conf_Server[i].pwd ) != 0 ) + if( strcmp( Client_Password( Client ), Conf_Server[i].pwd_in ) != 0 ) { /* Falsches Passwort */ - Log( LOG_ERR, "Connection %d: Bad password for server \"%s\"!", Client_Conn( Client ), Req->argv[0] ); + Log( LOG_ERR, "Connection %d: Got bad password from server \"%s\"!", Client_Conn( Client ), Req->argv[0] ); Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE ); return DISCONNECTED; } @@ -86,18 +86,19 @@ Client_SetID( Client, Req->argv[0] ); Client_SetHops( Client, 1 ); Client_SetInfo( Client, Req->argv[Req->argc - 1] ); - + /* Meldet sich der Server bei uns an (d.h., bauen nicht wir * selber die Verbindung zu einem anderen Server auf)? */ + con = Client_Conn( Client ); if( Client_Token( Client ) != TOKEN_OUTBOUND ) { /* Eingehende Verbindung: Unseren SERVER- und PASS-Befehl senden */ ok = TRUE; - if( ! IRC_WriteStrClient( Client, "PASS %s %s", Conf_Server[i].pwd, NGIRCd_ProtoID )) ok = FALSE; + if( ! IRC_WriteStrClient( Client, "PASS %s %s", Conf_Server[i].pwd_out, NGIRCd_ProtoID )) ok = FALSE; else ok = IRC_WriteStrClient( Client, "SERVER %s 1 :%s", Conf_ServerName, Conf_ServerInfo ); if( ! ok ) { - Conn_Close( Client_Conn( Client ), "Unexpected server behavior!", NULL, FALSE ); + Conn_Close( con, "Unexpected server behavior!", NULL, FALSE ); return DISCONNECTED; } Client_SetIntroducer( Client, Client ); @@ -110,9 +111,23 @@ Client_SetToken( Client, atoi( Req->argv[1] )); } - Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), Client_Conn( Client )); + Log( LOG_NOTICE|LOG_snotice, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), con ); Client_SetType( Client, CLIENT_SERVER ); + Conn_SetServer( con, i ); + +#ifdef USE_ZLIB + /* Kompression initialisieren, wenn erforderlich */ + if( strchr( Client_Flags( Client ), 'Z' )) + { + if( ! Conn_InitZip( con )) + { + /* Fehler! */ + Conn_Close( con, "Can't inizialize compression (zlib)!", NULL, FALSE ); + return DISCONNECTED; + } + } +#endif /* maximalen Hop Count ermitteln */ max_hops = 0; @@ -266,8 +281,6 @@ assert( Client != NULL ); assert( Req != NULL ); - if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTEREDSERVER_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); @@ -331,16 +344,10 @@ assert( Client != NULL ); assert( Req != NULL ); - /* SQUIT ist nur fuer Server erlaubt */ - if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - /* Falsche Anzahl Parameter? */ if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); Log( LOG_DEBUG, "Got SQUIT from %s for \"%s\": \"%s\" ...", Client_ID( Client ), Req->argv[0], Req->argv[1] ); - - /* SQUIT an alle Server weiterleiten */ - IRC_WriteStrServers( Client, "SQUIT %s :%s", Req->argv[0], Req->argv[1] ); target = Client_Search( Req->argv[0] ); if( ! target ) Index: src/ngircd/irc-server.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-server.h,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- src/ngircd/irc-server.h 2002/05/27 13:09:27 1.3 +++ src/ngircd/irc-server.h 2002/12/12 12:23:43 1.4 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-server.h,v 1.3 2002/05/27 13:09:27 alex Exp $ + * $Id: irc-server.h,v 1.4 2002/12/12 12:23:43 alex Exp $ * - * irc-server.h: IRC-Befehle fuer Server-Links (Header) + * IRC commands for server links (header) */ Index: src/ngircd/irc-write.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-write.c,v retrieving revision 1.7.2.3 retrieving revision 1.13 diff -u -r1.7.2.3 -r1.13 --- src/ngircd/irc-write.c 2002/10/04 13:12:46 1.7.2.3 +++ src/ngircd/irc-write.c 2002/12/12 12:24:18 1.13 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-write.c,v 1.7.2.3 2002/10/04 13:12:46 alex Exp $ - * - * irc-write.c: IRC-Texte und Befehle ueber Netzwerk versenden + * Sending IRC commands over the network */ #include "portab.h" +static char UNUSED id[] = "$Id: irc-write.c,v 1.13 2002/12/12 12:24:18 alex Exp $"; + #include "imp.h" #include #include @@ -32,6 +31,10 @@ #include "irc-write.h" +#define SEND_TO_USER 1 +#define SEND_TO_SERVER 2 + + LOCAL CHAR *Get_Prefix PARAMS(( CLIENT *Target, CLIENT *Client )); @@ -146,11 +149,11 @@ va_dcl #endif { - BOOLEAN sock[MAX_CONNECTIONS], is_server[MAX_CONNECTIONS], ok = CONNECTED; + BOOLEAN ok = CONNECTED; CHAR buffer[1000]; CL2CHAN *cl2chan; + CONN_ID conn; CLIENT *c; - INT s, i; va_list ap; assert( Client != NULL ); @@ -166,7 +169,7 @@ vsnprintf( buffer, 1000, Format, ap ); va_end( ap ); - for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE; + Conn_ClearFlags( ); /* An alle Clients, die in den selben Channels sind. * Dabei aber nur einmal je Remote-Server */ @@ -184,26 +187,26 @@ if( c && ( c != Client )) { /* Ok, anderer Client */ - s = Client_Conn( c ); - assert( s >= 0 ); - assert( s < MAX_CONNECTIONS ); - sock[s] = TRUE; - if( Client_Type( c ) == CLIENT_SERVER ) is_server[s] = TRUE; - else is_server[s] = FALSE; + conn = Client_Conn( c ); + if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER ); + else Conn_SetFlag( conn, SEND_TO_USER ); } cl2chan = Channel_NextMember( Chan, cl2chan ); } - /* Senden ... */ - for( i = 0; i < MAX_CONNECTIONS; i++ ) + /* Senden: alle Verbindungen durchgehen ... */ + conn = Conn_First( ); + while( conn != NONE ) { - if( sock[i] ) - { - if( is_server[i] ) ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer ); - else ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer ); - if( ! ok ) break; - } + /* muessen Daten ueber diese Verbindung verschickt werden? */ + if( Conn_Flag( conn ) == SEND_TO_SERVER) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer ); + else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer ); + if( ! ok ) break; + + /* naechste Verbindung testen */ + conn = Conn_Next( conn ); } + return ok; } /* IRC_WriteStrChannelPrefix */ @@ -321,13 +324,13 @@ va_dcl #endif { - BOOLEAN sock[MAX_CONNECTIONS], is_server[MAX_CONNECTIONS], ok = CONNECTED; + BOOLEAN ok = CONNECTED; CL2CHAN *chan_cl2chan, *cl2chan; CHAR buffer[1000]; CHANNEL *chan; + CONN_ID conn; va_list ap; CLIENT *c; - INT i, s; assert( Client != NULL ); assert( Prefix != NULL ); @@ -342,7 +345,7 @@ va_end( ap ); /* initialisieren */ - for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE; + Conn_ClearFlags( ); /* An alle Clients, die in einem Channel mit dem "Ausloeser" sind, * den Text schicken. An Remote-Server aber jeweils nur einmal. */ @@ -365,12 +368,9 @@ if( c && ( c != Client )) { /* Ok, anderer Client */ - s = Client_Conn( c ); - assert( s >= 0 ); - assert( s < MAX_CONNECTIONS ); - sock[s] = TRUE; - if( Client_Type( c ) == CLIENT_SERVER ) is_server[s] = TRUE; - else is_server[s] = FALSE; + conn = Client_Conn( c ); + if( Client_Type( c ) == CLIENT_SERVER ) Conn_SetFlag( conn, SEND_TO_SERVER ); + else Conn_SetFlag( conn, SEND_TO_USER ); } cl2chan = Channel_NextMember( chan, cl2chan ); } @@ -379,15 +379,17 @@ chan_cl2chan = Channel_NextChannelOf( Client, chan_cl2chan ); } - /* Senden ... */ - for( i = 0; i < MAX_CONNECTIONS; i++ ) + /* Senden: alle Verbindungen durchgehen ... */ + conn = Conn_First( ); + while( conn != NONE ) { - if( sock[i] ) - { - if( is_server[i] ) ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer ); - else ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer ); - if( ! ok ) break; - } + /* muessen ueber diese Verbindung Daten gesendet werden? */ + if( Conn_Flag( conn ) == SEND_TO_SERVER ) ok = Conn_WriteStr( conn, ":%s %s", Client_ID( Prefix ), buffer ); + else if( Conn_Flag( conn ) == SEND_TO_USER ) ok = Conn_WriteStr( conn, ":%s %s", Client_Mask( Prefix ), buffer ); + if( ! ok ) break; + + /* naechste Verbindung testen */ + conn = Conn_Next( conn ); } return ok; } /* IRC_WriteStrRelatedPrefix */ Index: src/ngircd/irc-write.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc-write.h,v retrieving revision 1.4 retrieving revision 1.5 diff -u -r1.4 -r1.5 --- src/ngircd/irc-write.h 2002/09/03 23:56:06 1.4 +++ src/ngircd/irc-write.h 2002/12/12 12:23:43 1.5 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc-write.h,v 1.4 2002/09/03 23:56:06 alex Exp $ + * $Id: irc-write.h,v 1.5 2002/12/12 12:23:43 alex Exp $ * - * irc-write.h: IRC-Texte und Befehle ueber Netzwerk versenden (Header) + * Sending IRC commands over the network (header) */ Index: src/ngircd/irc.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc.c,v retrieving revision 1.95.2.3 retrieving revision 1.107 diff -u -r1.95.2.3 -r1.107 --- src/ngircd/irc.c 2002/11/04 19:18:39 1.95.2.3 +++ src/ngircd/irc.c 2002/12/12 12:24:18 1.107 @@ -2,486 +2,39 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc.c,v 1.95.2.3 2002/11/04 19:18:39 alex Exp $ - * - * irc.c: IRC-Befehle + * IRC commands */ #include "portab.h" +static char UNUSED id[] = "$Id: irc.c,v 1.107 2002/12/12 12:24:18 alex Exp $"; + #include "imp.h" #include -#include #include -#include #include -#include "ngircd.h" #include "conn.h" #include "client.h" #include "channel.h" -#include "resolve.h" -#include "conf.h" -#include "conn.h" +#include "defines.h" #include "irc-write.h" #include "log.h" #include "messages.h" #include "parse.h" -#include "tool.h" #include "exp.h" #include "irc.h" GLOBAL BOOLEAN -IRC_MOTD( CLIENT *Client, REQUEST *Req ) -{ - assert( Client != NULL ); - assert( Req != NULL ); - - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - return IRC_Show_MOTD( Client ); -} /* IRC_MOTD */ - - -GLOBAL BOOLEAN -IRC_PRIVMSG( CLIENT *Client, REQUEST *Req ) -{ - CLIENT *cl, *from; - CHANNEL *chan; - - assert( Client != NULL ); - assert( Req != NULL ); - - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command ); - if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client )); - if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); - else from = Client; - if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - - cl = Client_Search( Req->argv[0] ); - if( cl ) - { - /* Okay, Ziel ist ein Client. Aber ist es auch ein User? */ - if( Client_Type( cl ) != CLIENT_USER ) return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] ); - - /* Okay, Ziel ist ein User */ - if(( Client_Type( Client ) != CLIENT_SERVER ) && ( strchr( Client_Modes( cl ), 'a' ))) - { - /* Ziel-User ist AWAY: Meldung verschicken */ - if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( cl ), Client_Away( cl ))) return DISCONNECTED; - } - - /* Text senden */ - if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from )); - return IRC_WriteStrClientPrefix( cl, from, "PRIVMSG %s :%s", Client_ID( cl ), Req->argv[1] ); - } - - chan = Channel_Search( Req->argv[0] ); - if( chan ) return Channel_Write( chan, from, Client, Req->argv[1] ); - - return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] ); -} /* IRC_PRIVMSG */ - - -GLOBAL BOOLEAN -IRC_NOTICE( CLIENT *Client, REQUEST *Req ) -{ - CLIENT *to, *from; - - assert( Client != NULL ); - assert( Req != NULL ); - - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return CONNECTED; - - /* Falsche Anzahl Parameter? */ - if( Req->argc != 2 ) return CONNECTED; - - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); - else from = Client; - if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - - to = Client_Search( Req->argv[0] ); - if(( to ) && ( Client_Type( to ) == CLIENT_USER )) - { - /* Okay, Ziel ist ein User */ - return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] ); - } - else return CONNECTED; -} /* IRC_NOTICE */ - - -GLOBAL BOOLEAN -IRC_NAMES( CLIENT *Client, REQUEST *Req ) -{ - CHAR rpl[COMMAND_LEN], *ptr; - CLIENT *target, *from, *c; - CHANNEL *chan; - - assert( Client != NULL ); - assert( Req != NULL ); - - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - /* From aus Prefix ermitteln */ - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); - else from = Client; - if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix ); - - if( Req->argc == 2 ) - { - /* an anderen Server forwarden */ - target = Client_Search( Req->argv[1] ); - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] ); - - if( target != Client_ThisServer( )) - { - /* Ok, anderer Server ist das Ziel: forwarden */ - return IRC_WriteStrClientPrefix( target, from, "NAMES %s :%s", Req->argv[0], Req->argv[1] ); - } - } - - if( Req->argc > 0 ) - { - /* bestimmte Channels durchgehen */ - ptr = strtok( Req->argv[0], "," ); - while( ptr ) - { - chan = Channel_Search( ptr ); - if( chan ) - { - /* Namen ausgeben */ - if( ! IRC_Send_NAMES( from, chan )) return DISCONNECTED; - } - if( ! IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), ptr )) return DISCONNECTED; - - /* naechsten Namen ermitteln */ - ptr = strtok( NULL, "," ); - } - return CONNECTED; - } - - /* alle Channels durchgehen */ - chan = Channel_First( ); - while( chan ) - { - /* Namen ausgeben */ - if( ! IRC_Send_NAMES( from, chan )) return DISCONNECTED; - - /* naechster Channel */ - chan = Channel_Next( chan ); - } - - /* Nun noch alle Clients ausgeben, die in keinem Channel sind */ - c = Client_First( ); - sprintf( rpl, RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" ); - while( c ) - { - if(( Client_Type( c ) == CLIENT_USER ) && ( Channel_FirstChannelOf( c ) == NULL ) && ( ! strchr( Client_Modes( c ), 'i' ))) - { - /* Okay, das ist ein User: anhaengen */ - if( rpl[strlen( rpl ) - 1] != ':' ) strcat( rpl, " " ); - strcat( rpl, Client_ID( c )); - - if( strlen( rpl ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 )) - { - /* Zeile wird zu lang: senden! */ - if( ! IRC_WriteStrClient( from, "%s", rpl )) return DISCONNECTED; - sprintf( rpl, RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" ); - } - } - - /* naechster Client */ - c = Client_Next( c ); - } - if( rpl[strlen( rpl ) - 1] != ':') - { - /* es wurden User gefunden */ - if( ! IRC_WriteStrClient( from, "%s", rpl )) return DISCONNECTED; - } - - return IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), "*" ); -} /* IRC_NAMES */ - - -GLOBAL BOOLEAN -IRC_ISON( CLIENT *Client, REQUEST *Req ) -{ - CHAR rpl[COMMAND_LEN]; - CLIENT *c; - CHAR *ptr; - INT i; - - assert( Client != NULL ); - assert( Req != NULL ); - - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - strcpy( rpl, RPL_ISON_MSG ); - for( i = 0; i < Req->argc; i++ ) - { - ptr = strtok( Req->argv[i], " " ); - while( ptr ) - { - ngt_TrimStr( ptr ); - c = Client_Search( ptr ); - if( c && ( Client_Type( c ) == CLIENT_USER )) - { - /* Dieser Nick ist "online" */ - strcat( rpl, ptr ); - strcat( rpl, " " ); - } - ptr = strtok( NULL, " " ); - } - } - if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0'; - - return IRC_WriteStrClient( Client, "%s", rpl, Client_ID( Client ) ); -} /* IRC_ISON */ - - -GLOBAL BOOLEAN -IRC_WHOIS( CLIENT *Client, REQUEST *Req ) -{ - CLIENT *from, *target, *c; - CHAR str[LINE_LEN + 1], *ptr = NULL; - CL2CHAN *cl2chan; - CHANNEL *chan; - - assert( Client != NULL ); - assert( Req != NULL ); - - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - /* Client suchen */ - c = Client_Search( Req->argv[Req->argc - 1] ); - if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] ); - - /* Empfaenger des WHOIS suchen */ - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); - else from = Client; - if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - - /* Forwarden an anderen Server? */ - if( Req->argc > 1 ) - { - /* angegebenen Ziel-Server suchen */ - target = Client_Search( Req->argv[1] ); - if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] ); - ptr = Req->argv[1]; - } - else target = Client_ThisServer( ); - - assert( target != NULL ); - - if(( Client_NextHop( target ) != Client_ThisServer( )) && ( Client_Type( Client_NextHop( target )) == CLIENT_SERVER )) return IRC_WriteStrClientPrefix( target, from, "WHOIS %s :%s", Req->argv[0], ptr ); - - /* Nick, User und Name */ - if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED; - - /* Server */ - if( ! IRC_WriteStrClient( from, RPL_WHOISSERVER_MSG, Client_ID( from ), Client_ID( c ), Client_ID( Client_Introducer( c )), Client_Info( Client_Introducer( c )))) return DISCONNECTED; - - /* Channels */ - sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c )); - cl2chan = Channel_FirstChannelOf( c ); - while( cl2chan ) - { - chan = Channel_GetChannel( cl2chan ); - assert( chan != NULL ); - - /* Channel-Name anhaengen */ - if( str[strlen( str ) - 1] != ':' ) strcat( str, " " ); - if( strchr( Channel_UserModes( chan, c ), 'o' )) strcat( str, "@" ); - else if( strchr( Channel_UserModes( chan, c ), 'v' )) strcat( str, "+" ); - strcat( str, Channel_Name( chan )); - - if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 )) - { - /* Zeile wird zu lang: senden! */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; - sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c )); - } - - /* naechstes Mitglied suchen */ - cl2chan = Channel_NextChannelOf( c, cl2chan ); - } - if( str[strlen( str ) - 1] != ':') - { - /* Es sind noch Daten da, die gesendet werden muessen */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; - } - - /* IRC-Operator? */ - if( Client_HasMode( c, 'o' )) - { - if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED; - } - - /* Idle (nur lokale Clients) */ - if( Client_Conn( c ) > NONE ) - { - if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED; - } - - /* Away? */ - if( Client_HasMode( c, 'a' )) - { - if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( c ), Client_Away( c ))) return DISCONNECTED; - } - - /* End of Whois */ - return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c )); -} /* IRC_WHOIS */ - - -GLOBAL BOOLEAN -IRC_WHO( CLIENT *Client, REQUEST *Req ) -{ - BOOLEAN ok, only_ops; - CHAR flags[8], *ptr; - CL2CHAN *cl2chan; - CHANNEL *chan; - CLIENT *c; - - assert( Client != NULL ); - assert( Req != NULL ); - - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - only_ops = FALSE; - chan = NULL; - - if( Req->argc == 2 ) - { - /* Nur OPs anzeigen? */ - if( strcmp( Req->argv[1], "o" ) == 0 ) only_ops = TRUE; -#ifdef STRICT_RFC - else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); -#endif - } - - if( Req->argc >= 1 ) - { - /* wurde ein Channel oder Nick-Mask angegeben? */ - chan = Channel_Search( Req->argv[0] ); - } - - if( chan ) - { - /* User eines Channels ausgeben */ - if( ! IRC_Send_WHO( Client, chan, only_ops )) return DISCONNECTED; - } - - c = Client_First( ); - while( c ) - { - if(( Client_Type( c ) == CLIENT_USER ) && ( ! strchr( Client_Modes( c ), 'i' ))) - { - ok = FALSE; - if( Req->argc == 0 ) ok = TRUE; - else - { - if( strcasecmp( Req->argv[0], Client_ID( c )) == 0 ) ok = TRUE; - else if( strcmp( Req->argv[0], "0" ) == 0 ) ok = TRUE; - } - - if( ok && (( ! only_ops ) || ( strchr( Client_Modes( c ), 'o' )))) - { - /* Flags zusammenbasteln */ - strcpy( flags, "H" ); - if( strchr( Client_Modes( c ), 'o' )) strcat( flags, "*" ); - - /* ausgeben */ - cl2chan = Channel_FirstChannelOf( c ); - if( cl2chan ) ptr = Channel_Name( Channel_GetChannel( cl2chan )); - else ptr = "*"; - if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), ptr, Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED; - } - } - - /* naechster Client */ - c = Client_Next( c ); - } - - if( chan ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Channel_Name( chan )); - else if( Req->argc == 0 ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), "*" ); - else return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Req->argv[0] ); -} /* IRC_WHO */ - - -GLOBAL BOOLEAN -IRC_USERHOST( CLIENT *Client, REQUEST *Req ) -{ - CHAR rpl[COMMAND_LEN]; - CLIENT *c; - INT max, i; - - assert( Client != NULL ); - assert( Req != NULL ); - - if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - if( Req->argc > 5 ) max = 5; - else max = Req->argc; - - strcpy( rpl, RPL_USERHOST_MSG ); - for( i = 0; i < max; i++ ) - { - c = Client_Search( Req->argv[i] ); - if( c && ( Client_Type( c ) == CLIENT_USER )) - { - /* Dieser Nick ist "online" */ - strcat( rpl, Client_ID( c )); - if( Client_HasMode( c, 'o' )) strcat( rpl, "*" ); - strcat( rpl, "=" ); - if( Client_HasMode( c, 'a' )) strcat( rpl, "-" ); - else strcat( rpl, "+" ); - strcat( rpl, Client_User( c )); - strcat( rpl, "@" ); - strcat( rpl, Client_Hostname( c )); - strcat( rpl, " " ); - } - } - if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0'; - - return IRC_WriteStrClient( Client, "%s", rpl, Client_ID( Client ) ); -} /* IRC_USERHOST */ - - -GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req ) { assert( Client != NULL ); @@ -495,159 +48,44 @@ GLOBAL BOOLEAN -IRC_LUSERS( CLIENT *Client, REQUEST *Req ) -{ - CLIENT *target, *from; - - assert( Client != NULL ); - assert( Req != NULL ); - - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - /* Absender ermitteln */ - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); - else from = Client; - if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - - /* An anderen Server forwarden? */ - if( Req->argc == 2 ) - { - target = Client_Search( Req->argv[1] ); - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] ); - else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LUSERS %s %s", Req->argv[0], Req->argv[1] ); - } - - /* Wer ist der Absender? */ - if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix ); - else target = Client; - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - - IRC_Send_LUSERS( target ); - - return CONNECTED; -} /* IRC_LUSERS */ - - -GLOBAL BOOLEAN -IRC_LINKS( CLIENT *Client, REQUEST *Req ) -{ - CLIENT *target, *from, *c; - CHAR *mask; - - assert( Client != NULL ); - assert( Req != NULL ); - - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); - - /* Falsche Anzahl Parameter? */ - if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - /* Server-Mask ermitteln */ - if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1]; - else mask = "*"; - - /* Absender ermitteln */ - if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); - else from = Client; - if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - - /* An anderen Server forwarden? */ - if( Req->argc == 2 ) - { - target = Client_Search( Req->argv[0] ); - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] ); - else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] ); - } - - /* Wer ist der Absender? */ - if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix ); - else target = Client; - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - - c = Client_First( ); - while( c ) - { - if( Client_Type( c ) == CLIENT_SERVER ) - { - if( ! IRC_WriteStrClient( target, RPL_LINKS_MSG, Client_ID( target ), Client_ID( c ), Client_ID( Client_TopServer( c ) ? Client_TopServer( c ) : Client_ThisServer( )), Client_Hops( c ), Client_Info( c ))) return DISCONNECTED; - } - c = Client_Next( c ); - } - - return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask ); -} /* IRC_LINKS */ - - -GLOBAL BOOLEAN -IRC_VERSION( CLIENT *Client, REQUEST *Req ) -{ - CLIENT *target, *prefix; - - assert( Client != NULL ); - assert( Req != NULL ); - - /* Falsche Anzahl Parameter? */ - if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - /* Ziel suchen */ - if( Req->argc == 1 ) target = Client_Search( Req->argv[0] ); - else target = Client_ThisServer( ); - - /* Prefix ermitteln */ - if( Client_Type( Client ) == CLIENT_SERVER ) prefix = Client_Search( Req->prefix ); - else prefix = Client; - if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix ); - - /* An anderen Server weiterleiten? */ - if( target != Client_ThisServer( )) - { - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] ); - - /* forwarden */ - IRC_WriteStrClientPrefix( target, prefix, "VERSION %s", Req->argv[0] ); - return CONNECTED; - } - - /* mit Versionsinfo antworten */ - return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), PACKAGE, VERSION, NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition( )); -} /* IRC_VERSION */ - - -GLOBAL BOOLEAN IRC_KILL( CLIENT *Client, REQUEST *Req ) { CLIENT *prefix, *c; - + CHAR reason[COMMAND_LEN]; + assert( Client != NULL ); assert( Req != NULL ); - if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); + /* is the user an IRC operator? */ + if(( Client_Type( Client ) != CLIENT_SERVER ) && ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client )); /* Falsche Anzahl Parameter? */ if(( Req->argc != 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - prefix = Client_Search( Req->prefix ); + if( Req->prefix ) prefix = Client_Search( Req->prefix ); + else prefix = Client; if( ! prefix ) { Log( LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!", Req->prefix ); prefix = Client_ThisServer( ); } - - Log( LOG_NOTICE, "Got KILL command from \"%s\" for \"%s\": %s", Client_Mask( prefix ), Req->argv[0], Req->argv[1] ); - + + Log( LOG_NOTICE|LOG_snotice, "Got KILL command from \"%s\" for \"%s\": %s", Client_Mask( prefix ), Req->argv[0], Req->argv[1] ); + + /* build reason string */ + if( Client_Type( Client ) == CLIENT_USER ) sprintf( reason, "KILLed by %s: %s", Client_ID( Client ), Req->argv[1] ); + else strcpy( reason, Req->argv[1] ); + /* andere Server benachrichtigen */ - IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s", Req->argv[0], Req->argv[1] ); + IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s", Req->argv[0], reason ); /* haben wir selber einen solchen Client? */ c = Client_Search( Req->argv[0] ); if( c ) { /* Ja, wir haben einen solchen Client */ - if( Client_Conn( c ) != NONE ) Conn_Close( Client_Conn( c ), NULL, Req->argv[1], TRUE ); - else Client_Destroy( c, NULL, Req->argv[1], TRUE ); + if( Client_Conn( c ) != NONE ) Conn_Close( Client_Conn( c ), NULL, reason, TRUE ); + else Client_Destroy( c, NULL, reason, TRUE ); } else Log( LOG_NOTICE, "Client with nick \"%s\" is unknown here.", Req->argv[0] ); @@ -656,213 +94,73 @@ GLOBAL BOOLEAN -IRC_ADMIN(CLIENT *Client, REQUEST *Req ) +IRC_NOTICE( CLIENT *Client, REQUEST *Req ) { - CLIENT *target, *prefix; + CLIENT *to, *from; assert( Client != NULL ); assert( Req != NULL ); - if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client )); + if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return CONNECTED; /* Falsche Anzahl Parameter? */ - if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - - /* Ziel suchen */ - if( Req->argc == 1 ) target = Client_Search( Req->argv[0] ); - else target = Client_ThisServer( ); - - /* Prefix ermitteln */ - if( Client_Type( Client ) == CLIENT_SERVER ) prefix = Client_Search( Req->prefix ); - else prefix = Client; - if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix ); - - /* An anderen Server weiterleiten? */ - if( target != Client_ThisServer( )) - { - if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] ); - - /* forwarden */ - IRC_WriteStrClientPrefix( target, prefix, "ADMIN %s", Req->argv[0] ); - return CONNECTED; - } - - /* mit Versionsinfo antworten */ - if( ! IRC_WriteStrClient( Client, RPL_ADMINME_MSG, Client_ID( prefix ), Conf_ServerName )) return DISCONNECTED; - if( ! IRC_WriteStrClient( Client, RPL_ADMINLOC1_MSG, Client_ID( prefix ), Conf_ServerAdmin1 )) return DISCONNECTED; - if( ! IRC_WriteStrClient( Client, RPL_ADMINLOC2_MSG, Client_ID( prefix ), Conf_ServerAdmin2 )) return DISCONNECTED; - if( ! IRC_WriteStrClient( Client, RPL_ADMINEMAIL_MSG, Client_ID( prefix ), Conf_ServerAdminMail )) return DISCONNECTED; - - return CONNECTED; -} /* IRC_ADMIN */ - - + if( Req->argc != 2 ) return CONNECTED; -GLOBAL BOOLEAN -IRC_Show_MOTD( CLIENT *Client ) -{ - BOOLEAN ok; - CHAR line[127]; - FILE *fd; - - assert( Client != NULL ); + if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); + else from = Client; + if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - fd = fopen( Conf_MotdFile, "r" ); - if( ! fd ) - { - Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno )); - return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) ); - } - - IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( ))); - while( TRUE ) + to = Client_Search( Req->argv[0] ); + if(( to ) && ( Client_Type( to ) == CLIENT_USER )) { - if( ! fgets( line, 126, fd )) break; - if( line[strlen( line ) - 1] == '\n' ) line[strlen( line ) - 1] = '\0'; - if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), line )) - { - fclose( fd ); - return FALSE; - } + /* Okay, Ziel ist ein User */ + return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] ); } - ok = IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ) ); - - fclose( fd ); - - return ok; -} /* IRC_Show_MOTD */ + else return CONNECTED; +} /* IRC_NOTICE */ GLOBAL BOOLEAN -IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan ) +IRC_PRIVMSG( CLIENT *Client, REQUEST *Req ) { - BOOLEAN is_visible, is_member; - CHAR str[LINE_LEN + 1]; - CL2CHAN *cl2chan; - CLIENT *cl; + CLIENT *cl, *from; + CHANNEL *chan; assert( Client != NULL ); - assert( Chan != NULL ); - - if( Channel_IsMemberOf( Chan, Client )) is_member = TRUE; - else is_member = FALSE; - - /* Alle Mitglieder suchen */ - sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan )); - cl2chan = Channel_FirstMember( Chan ); - while( cl2chan ) - { - cl = Channel_GetClient( cl2chan ); - - if( strchr( Client_Modes( cl ), 'i' )) is_visible = FALSE; - else is_visible = TRUE; - - if( is_member || is_visible ) - { - /* Nick anhaengen */ - if( str[strlen( str ) - 1] != ':' ) strcat( str, " " ); - if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strcat( str, "@" ); - else if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strcat( str, "+" ); - strcat( str, Client_ID( cl )); - - if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 )) - { - /* Zeile wird zu lang: senden! */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; - sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan )); - } - } - - /* naechstes Mitglied suchen */ - cl2chan = Channel_NextMember( Chan, cl2chan ); - } - if( str[strlen( str ) - 1] != ':') - { - /* Es sind noch Daten da, die gesendet werden muessen */ - if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED; - } - - return CONNECTED; -} /* IRC_Send_NAMES */ - - -GLOBAL BOOLEAN -IRC_Send_WHO( CLIENT *Client, CHANNEL *Chan, BOOLEAN OnlyOps ) -{ - BOOLEAN is_visible, is_member; - CL2CHAN *cl2chan; - CHAR flags[8]; - CLIENT *c; + assert( Req != NULL ); - assert( Client != NULL ); - assert( Chan != NULL ); + /* Falsche Anzahl Parameter? */ + if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command ); + if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client )); + if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command ); - if( Channel_IsMemberOf( Chan, Client )) is_member = TRUE; - else is_member = FALSE; + if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix ); + else from = Client; + if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix ); - /* Alle Mitglieder suchen */ - cl2chan = Channel_FirstMember( Chan ); - while( cl2chan ) + cl = Client_Search( Req->argv[0] ); + if( cl ) { - c = Channel_GetClient( cl2chan ); - - if( strchr( Client_Modes( c ), 'i' )) is_visible = FALSE; - else is_visible = TRUE; + /* Okay, Ziel ist ein Client. Aber ist es auch ein User? */ + if( Client_Type( cl ) != CLIENT_USER ) return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] ); - if( is_member || is_visible ) + /* Okay, Ziel ist ein User */ + if(( Client_Type( Client ) != CLIENT_SERVER ) && ( strchr( Client_Modes( cl ), 'a' ))) { - /* Flags zusammenbasteln */ - strcpy( flags, "H" ); - if( strchr( Client_Modes( c ), 'o' )) strcat( flags, "*" ); - if( strchr( Channel_UserModes( Chan, c ), 'o' )) strcat( flags, "@" ); - else if( strchr( Channel_UserModes( Chan, c ), 'v' )) strcat( flags, "+" ); - - /* ausgeben */ - if(( ! OnlyOps ) || ( strchr( Client_Modes( c ), 'o' ))) - { - if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), Channel_Name( Chan ), Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED; - } + /* Ziel-User ist AWAY: Meldung verschicken */ + if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( cl ), Client_Away( cl ))) return DISCONNECTED; } - - /* naechstes Mitglied suchen */ - cl2chan = Channel_NextMember( Chan, cl2chan ); - } - return CONNECTED; -} /* IRC_Send_WHO */ - - -GLOBAL BOOLEAN -IRC_Send_LUSERS( CLIENT *Client ) -{ - LONG cnt; - - assert( Client != NULL ); - - /* Users, Services und Serevr im Netz */ - if( ! IRC_WriteStrClient( Client, RPL_LUSERCLIENT_MSG, Client_ID( Client ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED; - - /* IRC-Operatoren im Netz */ - cnt = Client_OperCount( ); - if( cnt > 0 ) - { - if( ! IRC_WriteStrClient( Client, RPL_LUSEROP_MSG, Client_ID( Client ), cnt )) return DISCONNECTED; - } - /* Unbekannt Verbindungen */ - cnt = Client_UnknownCount( ); - if( cnt > 0 ) - { - if( ! IRC_WriteStrClient( Client, RPL_LUSERUNKNOWN_MSG, Client_ID( Client ), cnt )) return DISCONNECTED; + /* Text senden */ + if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from )); + return IRC_WriteStrClientPrefix( cl, from, "PRIVMSG %s :%s", Client_ID( cl ), Req->argv[1] ); } - /* Channels im Netz */ - if( ! IRC_WriteStrClient( Client, RPL_LUSERCHANNELS_MSG, Client_ID( Client ), Channel_Count( ))) return DISCONNECTED; + chan = Channel_Search( Req->argv[0] ); + if( chan ) return Channel_Write( chan, from, Client, Req->argv[1] ); - /* Channels im Netz */ - if( ! IRC_WriteStrClient( Client, RPL_LUSERME_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED; - - return CONNECTED; -} /* IRC_Send_LUSERS */ + return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] ); +} /* IRC_PRIVMSG */ /* -eof- */ Index: src/ngircd/irc.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/irc.h,v retrieving revision 1.32 retrieving revision 1.36 diff -u -r1.32 -r1.36 --- src/ngircd/irc.h 2002/09/16 09:14:45 1.32 +++ src/ngircd/irc.h 2002/12/12 12:23:43 1.36 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: irc.h,v 1.32 2002/09/16 09:14:45 alex Exp $ + * $Id: irc.h,v 1.36 2002/12/12 12:23:43 alex Exp $ * - * irc.h: IRC-Befehle (Header) + * IRC commands (header) */ @@ -19,28 +18,10 @@ #define __irc_h__ -GLOBAL BOOLEAN IRC_MOTD PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_LUSERS PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_LINKS PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_VERSION PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_ADMIN PARAMS((CLIENT *Client, REQUEST *Req )); - -GLOBAL BOOLEAN IRC_PRIVMSG PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_NOTICE PARAMS((CLIENT *Client, REQUEST *Req )); - -GLOBAL BOOLEAN IRC_NAMES PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_ISON PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_WHOIS PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_USERHOST PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_WHO PARAMS((CLIENT *Client, REQUEST *Req )); - -GLOBAL BOOLEAN IRC_ERROR PARAMS((CLIENT *Client, REQUEST *Req )); -GLOBAL BOOLEAN IRC_KILL PARAMS((CLIENT *Client, REQUEST *Req )); - -GLOBAL BOOLEAN IRC_Send_NAMES PARAMS((CLIENT *Client, CHANNEL *Chan )); -GLOBAL BOOLEAN IRC_Send_LUSERS PARAMS((CLIENT *Client )); -GLOBAL BOOLEAN IRC_Show_MOTD PARAMS((CLIENT *Client )); -GLOBAL BOOLEAN IRC_Send_WHO PARAMS((CLIENT *Client, CHANNEL *Chan, BOOLEAN OnlyOps )); +GLOBAL BOOLEAN IRC_ERROR PARAMS(( CLIENT *Client, REQUEST *Req )); +GLOBAL BOOLEAN IRC_KILL PARAMS(( CLIENT *Client, REQUEST *Req )); +GLOBAL BOOLEAN IRC_NOTICE PARAMS(( CLIENT *Client, REQUEST *Req )); +GLOBAL BOOLEAN IRC_PRIVMSG PARAMS(( CLIENT *Client, REQUEST *Req )); #endif Index: src/ngircd/lists.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/lists.c,v retrieving revision 1.8.2.2 retrieving revision 1.10 diff -u -r1.8.2.2 -r1.10 --- src/ngircd/lists.c 2002/10/04 13:12:46 1.8.2.2 +++ src/ngircd/lists.c 2002/12/12 12:24:18 1.10 @@ -2,20 +2,19 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: lists.c,v 1.8.2.2 2002/10/04 13:12:46 alex Exp $ - * - * lists.c: Verwaltung der "IRC-Listen": Ban, Invite, ... + * Management of IRC lists: ban, invite, ... */ #include "portab.h" + +static char UNUSED id[] = "$Id: lists.c,v 1.10 2002/12/12 12:24:18 alex Exp $"; #include "imp.h" #include Index: src/ngircd/lists.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/lists.h,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- src/ngircd/lists.h 2002/09/08 17:05:25 1.8 +++ src/ngircd/lists.h 2002/12/12 12:23:43 1.9 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: lists.h,v 1.8 2002/09/08 17:05:25 alex Exp $ + * $Id: lists.h,v 1.9 2002/12/12 12:23:43 alex Exp $ * - * lists.h: Verwaltung der "IRC-Listen": Ban, Invite, ... (Header) + * Management of IRC lists: ban, invite, ... (header) */ Index: src/ngircd/log.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/log.c,v retrieving revision 1.37.2.3 retrieving revision 1.41 diff -u -r1.37.2.3 -r1.41 --- src/ngircd/log.c 2002/11/04 19:18:39 1.37.2.3 +++ src/ngircd/log.c 2002/12/12 12:24:18 1.41 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: log.c,v 1.37.2.3 2002/11/04 19:18:39 alex Exp $ - * - * log.c: Logging-Funktionen + * Logging functions */ #include "portab.h" +static char UNUSED id[] = "$Id: log.c,v 1.41 2002/12/12 12:24:18 alex Exp $"; + #include "imp.h" #include #include @@ -280,7 +279,7 @@ c = Client_First( ); while( c ) { - if(( Client_Conn( c ) > NONE ) && ( Client_HasMode( c, 's' ))) IRC_WriteStrClient( c, "NOTICE %s :%s", Client_ThisServer( ), Msg ); + if(( Client_Conn( c ) > NONE ) && ( Client_HasMode( c, 's' ))) IRC_WriteStrClient( c, "NOTICE %s :%s%s", Client_ThisServer( ), NOTICE_TXTPREFIX, Msg ); c = Client_Next( c ); } } /* Wall_ServerNotice */ Index: src/ngircd/log.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/log.h,v retrieving revision 1.12 retrieving revision 1.13 diff -u -r1.12 -r1.13 --- src/ngircd/log.h 2002/05/27 13:09:27 1.12 +++ src/ngircd/log.h 2002/12/12 12:23:43 1.13 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: log.h,v 1.12 2002/05/27 13:09:27 alex Exp $ + * $Id: log.h,v 1.13 2002/12/12 12:23:43 alex Exp $ * - * log.h: Logging-Funktionen (Header) + * Logging functions (header) */ Index: src/ngircd/match.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/match.c,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- src/ngircd/match.c 2002/06/26 15:42:58 1.1 +++ src/ngircd/match.c 2002/12/12 12:24:18 1.2 @@ -2,20 +2,19 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: match.c,v 1.1 2002/06/26 15:42:58 alex Exp $ - * - * match.c: Wildcard Pattern Matching + * Wildcard pattern matching */ #include "portab.h" + +static char UNUSED id[] = "$Id: match.c,v 1.2 2002/12/12 12:24:18 alex Exp $"; #include "imp.h" #include Index: src/ngircd/match.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/match.h,v retrieving revision 1.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- src/ngircd/match.h 2002/06/26 15:42:58 1.1 +++ src/ngircd/match.h 2002/12/12 12:23:43 1.2 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: match.h,v 1.1 2002/06/26 15:42:58 alex Exp $ + * $Id: match.h,v 1.2 2002/12/12 12:23:43 alex Exp $ * - * match.h: Wildcard Pattern Matching (Header) + * Wildcard pattern matching (header) */ Index: src/ngircd/messages.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/messages.h,v retrieving revision 1.46.2.4 retrieving revision 1.59.2.1 diff -u -r1.46.2.4 -r1.59.2.1 --- src/ngircd/messages.h 2002/11/22 22:55:05 1.46.2.4 +++ src/ngircd/messages.h 2002/12/22 23:42:28 1.59.2.1 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: messages.h,v 1.46.2.4 2002/11/22 22:55:05 alex Exp $ + * $Id: messages.h,v 1.59.2.1 2002/12/22 23:42:28 alex Exp $ * - * irc.h: IRC-Befehle (Header) + * IRC numerics (Header) */ @@ -23,6 +22,10 @@ #define RPL_YOURHOST_MSG "002 %s :Your host is %s, running version ngircd-%s (%s/%s/%s)" #define RPL_CREATED_MSG "003 %s :This server has been started %s" #define RPL_MYINFO_MSG "004 %s %s ngircd-%s %s %s" +#define RPL_FEATURE_MSG "005 %s NICKLEN=%d TOPICLEN=%d AWAYLEN=%d MAXCHANNELS=%d :are supported on this server" +#define RPL_STATSLINKINFO_MSG "211 %s %s %d %ld %ld %ld %ld :%ld" +#define RPL_STATSCOMMANDS_MSG "212 %s %s %ld %ld %ld" +#define RPL_ENDOFSTATS_MSG "219 %s %c :End of STATS report" #define RPL_UMODEIS_MSG "221 %s +%s" #define RPL_LUSERCLIENT_MSG "251 %s :There are %ld users and %ld services on %ld servers" #define RPL_LUSEROP_MSG "252 %s %ld :operator(s) online" @@ -33,6 +36,8 @@ #define RPL_ADMINLOC1_MSG "257 %s :%s" #define RPL_ADMINLOC2_MSG "258 %s :%s" #define RPL_ADMINEMAIL_MSG "259 %s :%s" +#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_AWAY_MSG "301 %s %s :%s" #define RPL_USERHOST_MSG "302 %s :" @@ -42,6 +47,7 @@ #define RPL_WHOISUSER_MSG "311 %s %s %s %s * :%s" #define RPL_WHOISSERVER_MSG "312 %s %s %s :%s" #define RPL_WHOISOPERATOR_MSG "313 %s %s :is an IRC operator" +#define RPL_WHOWASUSER_MSG "314 %s %s %s %s * :%s" #define RPL_ENDOFWHO_MSG "315 %s %s :End of WHO list" #define RPL_WHOISIDLE_MSG "317 %s %s %ld :seconds idle" #define RPL_ENDOFWHOIS_MSG "318 %s %s :End of WHOIS list" @@ -62,15 +68,20 @@ #define RPL_ENDOFNAMES_MSG "366 %s %s :End of NAMES list" #define RPL_BANLIST_MSG "367 %s %s %s" #define RPL_ENDOFBANLIST_MSG "368 %s %s :End of channel ban list" +#define RPL_ENDOFWHOWAS_MSG "369 %s %s :End of WHOWAS list" #define RPL_MOTD_MSG "372 %s :- %s" #define RPL_MOTDSTART_MSG "375 %s :- %s message of the day" #define RPL_ENDOFMOTD_MSG "376 %s :End of MOTD command" #define RPL_YOUREOPER_MSG "381 %s :You are now an IRC Operator" +#define RPL_YOURESERVICE_MSG "383 %s :You are service %s" +#define RPL_TIME_MSG "391 %s %s :%s" #define ERR_NOSUCHNICK_MSG "401 %s %s :No such nick or channel name" #define ERR_NOSUCHSERVER_MSG "402 %s %s :No such server" #define ERR_NOSUCHCHANNEL_MSG "403 %s %s :No such channel" #define ERR_CANNOTSENDTOCHAN_MSG "404 %s %s :Cannot send to channel" +#define ERR_TOOMANYCHANNELS_MSG "405 %s %s :You have joined too many channels" +#define ERR_WASNOSUCHNICK_MSG "406 %s %s :There was no such nickname" #define ERR_NOORIGIN_MSG "409 %s :No origin specified" #define ERR_NORECIPIENT_MSG "411 %s :No receipient given (%s)" #define ERR_NOTEXTTOSEND_MSG "412 %s :No text to send" @@ -85,10 +96,12 @@ #define ERR_NOTREGISTEREDSERVER_MSG "451 %s :Connection not registered as server link" #define ERR_NEEDMOREPARAMS_MSG "461 %s %s :Syntax error" #define ERR_ALREADYREGISTRED_MSG "462 %s :Connection already registered" -#define ERR_PASSWDMISMATCH_MSG "464 %s: Invalid password" +#define ERR_PASSWDMISMATCH_MSG "464 %s :Invalid password" +#define ERR_CHANNELISFULL_MSG "471 %s %s :Cannot join channel (+l)" #define ERR_UNKNOWNMODE_MSG "472 %s: %c :is unknown mode char for %s" #define ERR_INVITEONLYCHAN_MSG "473 %s %s :Cannot join channel (+i)" #define ERR_BANNEDFROMCHAN_MSG "474 %s %s :Cannot join channel (+b)" +#define ERR_BADCHANNELKEY_MSG "475 %s %s :Cannot join channel (+k)" #define ERR_NOPRIVILEGES_MSG "481 %s :Permission denied" #define ERR_CHANOPRIVSNEEDED_MSG "482 %s %s :You are not channel operator" #define ERR_RESTRICTED_MSG "484 %s :Your connection is restricted" @@ -97,6 +110,10 @@ #define ERR_UMODEUNKNOWNFLAG_MSG "501 %s :Unknown mode" #define ERR_UMODEUNKNOWNFLAG2_MSG "501 %s :Unknown mode \"%c%c\"" #define ERR_USERSDONTMATCH_MSG "502 %s :Can't set/get mode for other users" + +#ifdef USE_ZLIB +#define RPL_STATSLINKINFOZIP_MSG "211 %s %s %d %ld %ld/%ld %ld %ld/%ld :%ld" +#endif #endif Index: src/ngircd/ngircd.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/ngircd.c,v retrieving revision 1.54.2.4 retrieving revision 1.64 diff -u -r1.54.2.4 -r1.64 --- src/ngircd/ngircd.c 2002/11/24 15:25:25 1.54.2.4 +++ src/ngircd/ngircd.c 2002/12/12 11:31:21 1.64 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: ngircd.c,v 1.54.2.4 2002/11/24 15:25:25 alex Exp $ - * - * ngircd.c: Hier beginnt alles ;-) + * Main program -- main() */ #include "portab.h" +static char UNUSED id[] = "$Id: ngircd.c,v 1.64 2002/12/12 11:31:21 alex Exp $"; + #include "imp.h" #include #include @@ -37,6 +36,7 @@ #include "client.h" #include "channel.h" #include "conf.h" +#include "cvs-version.h" #include "defines.h" #include "lists.h" #include "log.h" @@ -50,8 +50,6 @@ LOCAL VOID Initialize_Signal_Handler PARAMS(( VOID )); LOCAL VOID Signal_Handler PARAMS(( INT Signal )); -LOCAL VOID Initialize_Listen_Ports PARAMS(( VOID )); - LOCAL VOID Show_Version PARAMS(( VOID )); LOCAL VOID Show_Help PARAMS(( VOID )); @@ -295,19 +293,30 @@ * sind in doc/Protocol.txt beschrieben. */ #ifdef IRCPLUS sprintf( NGIRCd_ProtoID, "%s%s %s|%s:%s", PROTOVER, PROTOIRCPLUS, PACKAGE, VERSION, IRCPLUSFLAGS ); +#ifdef USE_ZLIB + strcat( NGIRCd_ProtoID, "Z" ); +#endif if( Conf_OperCanMode ) strcat( NGIRCd_ProtoID, "o" ); #else sprintf( NGIRCd_ProtoID, "%s%s %s|%s", PROTOVER, PROTOIRC, PACKAGE, VERSION ); #endif strcat( NGIRCd_ProtoID, " P" ); +#ifdef USE_ZLIB + strcat( NGIRCd_ProtoID, "Z" ); +#endif Log( LOG_DEBUG, "Protocol and server ID is \"%s\".", NGIRCd_ProtoID ); /* Vordefinierte Channels anlegen */ Channel_InitPredefined( ); /* Listen-Ports initialisieren */ - Initialize_Listen_Ports( ); - + if( Conn_InitListeners( ) < 1 ) + { + Log( LOG_ALERT, "Server isn't listening on a single port!" ); + Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); + exit( 1 ); + } + /* Hauptschleife */ Conn_Handler( ); @@ -327,8 +336,12 @@ NGIRCd_Version( VOID ) { STATIC CHAR version[126]; - + +#ifdef CVSDATE + sprintf( version, "%s %s(%s)-%s", PACKAGE, VERSION, CVSDATE, NGIRCd_VersionAddition( )); +#else sprintf( version, "%s %s-%s", PACKAGE, VERSION, NGIRCd_VersionAddition( )); +#endif return version; } /* NGIRCd_Version */ @@ -344,6 +357,10 @@ if( txt[0] ) strcat( txt, "+" ); strcat( txt, "SYSLOG" ); #endif +#ifdef USE_ZLIB + if( txt[0] ) strcat( txt, "+" ); + strcat( txt, "ZLIB" ); +#endif #ifdef DEBUG if( txt[0] ) strcat( txt, "+" ); strcat( txt, "DEBUG" ); @@ -372,6 +389,38 @@ } /* NGIRCd_VersionAddition */ +GLOBAL VOID +NGIRCd_Rehash( VOID ) +{ + CHAR old_name[CLIENT_ID_LEN]; + + /* Alle Listen-Sockets schliessen */ + Conn_ExitListeners( ); + + /* Alten Server-Namen merken */ + strcpy( old_name, Conf_ServerName ); + + /* Konfiguration neu lesen ... */ + Conf_Init( ); + + /* Alten Server-Namen wiederherstellen: dieser + * kann nicht zur Laufzeit geaendert werden ... */ + if( strcmp( old_name, Conf_ServerName ) != 0 ) + { + strcpy( Conf_ServerName, old_name ); + Log( LOG_ERR, "Can't change \"ServerName\" on runtime! Ignored new name." ); + } + + /* neue pre-defined Channel anlegen: */ + Channel_InitPredefined( ); + + /* Listen-Sockets neu anlegen: */ + Conn_InitListeners( ); + + Log( LOG_INFO, "Re-reading of configuration done." ); +} /* NGIRCd_Rehash */ + + LOCAL VOID Initialize_Signal_Handler( VOID ) { @@ -432,15 +481,15 @@ case SIGINT: case SIGQUIT: /* wir soll(t)en uns wohl beenden ... */ - if( Signal == SIGTERM ) Log( LOG_WARNING, "Got TERM signal, terminating now ..." ); - else if( Signal == SIGINT ) Log( LOG_WARNING, "Got INT signal, terminating now ..." ); - else if( Signal == SIGQUIT ) Log( LOG_WARNING, "Got QUIT signal, terminating now ..." ); + if( Signal == SIGTERM ) Log( LOG_WARNING|LOG_snotice, "Got TERM signal, terminating now ..." ); + else if( Signal == SIGINT ) Log( LOG_WARNING|LOG_snotice, "Got INT signal, terminating now ..." ); + else if( Signal == SIGQUIT ) Log( LOG_WARNING|LOG_snotice, "Got QUIT signal, terminating now ..." ); NGIRCd_Quit = TRUE; break; case SIGHUP: - /* neu starten */ - Log( LOG_WARNING, "Got HUP signal, restarting now ..." ); - NGIRCd_Restart = TRUE; + /* Konfiguration neu einlesen: */ + Log( LOG_WARNING|LOG_snotice, "Got HUP signal, re-reading configuration ..." ); + NGIRCd_Rehash( ); break; case SIGCHLD: /* Child-Prozess wurde beendet. Zombies vermeiden: */ @@ -454,30 +503,6 @@ LOCAL VOID -Initialize_Listen_Ports( VOID ) -{ - /* Ports, auf denen der Server Verbindungen entgegennehmen - * soll, initialisieren */ - - INT created, i; - - created = 0; - for( i = 0; i < Conf_ListenPorts_Count; i++ ) - { - if( Conn_NewListener( Conf_ListenPorts[i] )) created++; - else Log( LOG_ERR, "Can't listen on port %u!", Conf_ListenPorts[i] ); - } - - if( created < 1 ) - { - Log( LOG_ALERT, "Server isn't listening on a single port!" ); - Log( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); - exit( 1 ); - } -} /* Initialize_Listen_Ports */ - - -LOCAL VOID Show_Version( VOID ) { puts( NGIRCd_Version( )); @@ -495,7 +520,7 @@ puts( " -d, --debug log extra debug messages" ); #endif puts( " -f, --config use file as configuration file" ); - puts( " -n, --nodaemon don't fork and don't detatch from controlling terminal" ); + puts( " -n, --nodaemon don't fork and don't detach from controlling terminal" ); puts( " -p, --passive disable automatic connections to other servers" ); #ifdef SNIFFER puts( " -s, --sniffer enable network sniffer and display all IRC traffic" ); Index: src/ngircd/ngircd.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/ngircd.h,v retrieving revision 1.14 retrieving revision 1.17 diff -u -r1.14 -r1.17 --- src/ngircd/ngircd.h 2002/09/02 19:01:11 1.14 +++ src/ngircd/ngircd.h 2002/12/12 11:30:23 1.17 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: ngircd.h,v 1.14 2002/09/02 19:01:11 alex Exp $ + * $Id: ngircd.h,v 1.17 2002/12/12 11:30:23 alex Exp $ * - * ngircd.h: Prototypen aus dem "Haupt-Modul" + * Prototypes of the "main module". */ @@ -47,8 +46,11 @@ GLOBAL CHAR NGIRCd_ProtoID[1024]; /* Protokoll- und Server-Identifikation */ + GLOBAL CHAR *NGIRCd_Version PARAMS((VOID )); GLOBAL CHAR *NGIRCd_VersionAddition PARAMS((VOID )); + +GLOBAL VOID NGIRCd_Rehash PARAMS(( VOID )); #endif Index: src/ngircd/parse.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/parse.c,v retrieving revision 1.41.2.3 retrieving revision 1.52 diff -u -r1.41.2.3 -r1.52 --- src/ngircd/parse.c 2002/11/20 11:11:19 1.41.2.3 +++ src/ngircd/parse.c 2002/12/18 13:53:20 1.52 @@ -2,21 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: parse.c,v 1.41.2.3 2002/11/20 11:11:19 alex Exp $ - * - * parse.c: Parsen der Client-Anfragen + * IRC command parser and validator */ #include "portab.h" +static char UNUSED id[] = "$Id: parse.c,v 1.52 2002/12/18 13:53:20 alex Exp $"; + #include "imp.h" #include #include @@ -38,6 +37,7 @@ #include "imp.h" #include "irc.h" #include "irc-channel.h" +#include "irc-info.h" #include "irc-login.h" #include "irc-mode.h" #include "irc-op.h" @@ -48,6 +48,54 @@ #include "exp.h" +COMMAND My_Commands[] = +{ + { "ADMIN", IRC_ADMIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "AWAY", IRC_AWAY, CLIENT_USER, 0, 0, 0 }, + { "CONNECT", IRC_CONNECT, CLIENT_USER, 0, 0, 0 }, + { "DIE", IRC_DIE, CLIENT_USER, 0, 0, 0 }, + { "ERROR", IRC_ERROR, 0xFFFF, 0, 0, 0 }, + { "INVITE", IRC_INVITE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "ISON", IRC_ISON, CLIENT_USER, 0, 0, 0 }, + { "JOIN", IRC_JOIN, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "KICK", IRC_KICK, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "KILL", IRC_KILL, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "LINKS", IRC_LINKS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "LIST", IRC_LIST, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "LUSERS", IRC_LUSERS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "MODE", IRC_MODE, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "MOTD", IRC_MOTD, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "NAMES", IRC_NAMES, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "NICK", IRC_NICK, 0xFFFF, 0, 0, 0 }, + { "NJOIN", IRC_NJOIN, CLIENT_SERVER, 0, 0, 0 }, + { "NOTICE", IRC_NOTICE, 0xFFFF, 0, 0, 0 }, + { "OPER", IRC_OPER, CLIENT_USER, 0, 0, 0 }, + { "PART", IRC_PART, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "PASS", IRC_PASS, 0xFFFF, 0, 0, 0 }, + { "PING", IRC_PING, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "PONG", IRC_PONG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "PRIVMSG", IRC_PRIVMSG, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "QUIT", IRC_QUIT, 0xFFFF, 0, 0, 0 }, + { "REHASH", IRC_REHASH, CLIENT_USER, 0, 0, 0 }, + { "RESTART", IRC_RESTART, CLIENT_USER, 0, 0, 0 }, + { "SERVER", IRC_SERVER, 0xFFFF, 0, 0, 0 }, + { "SQUIT", IRC_SQUIT, CLIENT_SERVER, 0, 0, 0 }, + { "STATS", IRC_STATS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "TIME", IRC_TIME, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "TOPIC", IRC_TOPIC, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "USER", IRC_USER, 0xFFFF, 0, 0, 0 }, + { "USERHOST", IRC_USERHOST, CLIENT_USER, 0, 0, 0 }, + { "VERSION", IRC_VERSION, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "WHO", IRC_WHO, CLIENT_USER, 0, 0, 0 }, + { "WHOIS", IRC_WHOIS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, + { "WHOWAS", IRC_WHOWAS, CLIENT_USER|CLIENT_SERVER, 0, 0, 0 }, +#ifdef IRCPLUS + { "CHANINFO", IRC_CHANINFO, CLIENT_SERVER, 0, 0, 0 }, +#endif + { NULL, NULL, 0x0, 0, 0, 0 } /* Ende-Marke */ +}; + + LOCAL VOID Init_Request PARAMS(( REQUEST *Req )); LOCAL BOOLEAN Validate_Prefix PARAMS(( CONN_ID Idx, REQUEST *Req, BOOLEAN *Closed )); @@ -57,6 +105,13 @@ LOCAL BOOLEAN Handle_Request PARAMS(( CONN_ID Idx, REQUEST *Req )); +GLOBAL COMMAND * +Parse_GetCommandStruct( VOID ) +{ + return My_Commands; +} /* Parse_GetCommandStruct */ + + GLOBAL BOOLEAN Parse_Request( CONN_ID Idx, CHAR *Request ) { @@ -101,8 +156,6 @@ } else start = Request; - if( ! Validate_Prefix( Idx, &req, &closed )) return ! closed; - /* Befehl */ ptr = strchr( start, ' ' ); if( ptr ) @@ -116,8 +169,6 @@ } req.command = start; - if( ! Validate_Command( Idx, &req, &closed )) return ! closed; - /* Argumente, Parameter */ if( ptr ) { @@ -156,6 +207,9 @@ } } + /* Daten validieren */ + if( ! Validate_Prefix( Idx, &req, &closed )) return ! closed; + if( ! Validate_Command( Idx, &req, &closed )) return ! closed; if( ! Validate_Args( Idx, &req, &closed )) return ! closed; return Handle_Request( Idx, &req ); @@ -209,7 +263,7 @@ if( ! c ) { /* im Prefix angegebener Client ist nicht bekannt */ - Log( LOG_ERR, "Invalid prefix \"%s\", client not known (connection %d)!?", Req->prefix, Idx ); + Log( LOG_ERR, "Invalid prefix \"%s\", client not known (connection %d, command %s)!?", Req->prefix, Idx, Req->command ); if( ! Conn_WriteStr( Idx, "ERROR :Invalid prefix \"%s\", client not known!?", Req->prefix )) *Closed = TRUE; return FALSE; } @@ -221,7 +275,7 @@ { /* das angegebene Prefix ist aus dieser Richtung, also * aus der gegebenen Connection, ungueltig! */ - Log( LOG_ERR, "Spoofed prefix \"%s\" from \"%s\" (connection %d)!", Req->prefix, Client_Mask( Client_GetFromConn( Idx )), Idx ); + Log( LOG_ERR, "Spoofed prefix \"%s\" from \"%s\" (connection %d, command %s)!", Req->prefix, Client_Mask( Client_GetFromConn( Idx )), Idx, Req->command ); Conn_Close( Idx, NULL, "Spoofed prefix", TRUE ); *Closed = TRUE; return FALSE; @@ -261,6 +315,8 @@ CLIENT *client, *target, *prefix; CHAR str[LINE_LEN]; + BOOLEAN result; + COMMAND *cmd; INT i; assert( Idx >= 0 ); @@ -314,50 +370,39 @@ return IRC_WriteStrClientPrefix( target, prefix, "%s", str ); } - if( strcasecmp( Req->command, "PASS" ) == 0 ) return IRC_PASS( client, Req ); - else if( strcasecmp( Req->command, "NICK" ) == 0 ) return IRC_NICK( client, Req ); - else if( strcasecmp( Req->command, "USER" ) == 0 ) return IRC_USER( client, Req ); - else if( strcasecmp( Req->command, "SERVER" ) == 0 ) return IRC_SERVER( client, Req ); - else if( strcasecmp( Req->command, "NJOIN" ) == 0 ) return IRC_NJOIN( client, Req ); - else if( strcasecmp( Req->command, "QUIT" ) == 0 ) return IRC_QUIT( client, Req ); - else if( strcasecmp( Req->command, "SQUIT" ) == 0 ) return IRC_SQUIT( client, Req ); - else if( strcasecmp( Req->command, "PING" ) == 0 ) return IRC_PING( client, Req ); - else if( strcasecmp( Req->command, "PONG" ) == 0 ) return IRC_PONG( client, Req ); - else if( strcasecmp( Req->command, "MOTD" ) == 0 ) return IRC_MOTD( client, Req ); - else if( strcasecmp( Req->command, "PRIVMSG" ) == 0 ) return IRC_PRIVMSG( client, Req ); - else if( strcasecmp( Req->command, "NOTICE" ) == 0 ) return IRC_NOTICE( client, Req ); - else if( strcasecmp( Req->command, "MODE" ) == 0 ) return IRC_MODE( client, Req ); - else if( strcasecmp( Req->command, "NAMES" ) == 0 ) return IRC_NAMES( client, Req ); - else if( strcasecmp( Req->command, "ISON" ) == 0 ) return IRC_ISON( client, Req ); - else if( strcasecmp( Req->command, "WHOIS" ) == 0 ) return IRC_WHOIS( client, Req ); - else if( strcasecmp( Req->command, "USERHOST" ) == 0 ) return IRC_USERHOST( client, Req ); - else if( strcasecmp( Req->command, "OPER" ) == 0 ) return IRC_OPER( client, Req ); - else if( strcasecmp( Req->command, "DIE" ) == 0 ) return IRC_DIE( client, Req ); - else if( strcasecmp( Req->command, "RESTART" ) == 0 ) return IRC_RESTART( client, Req ); - else if( strcasecmp( Req->command, "ERROR" ) == 0 ) return IRC_ERROR( client, Req ); - else if( strcasecmp( Req->command, "LUSERS" ) == 0 ) return IRC_LUSERS( client, Req ); - else if( strcasecmp( Req->command, "LINKS" ) == 0 ) return IRC_LINKS( client, Req ); - else if( strcasecmp( Req->command, "JOIN" ) == 0 ) return IRC_JOIN( client, Req ); - else if( strcasecmp( Req->command, "PART" ) == 0 ) return IRC_PART( client, Req ); - else if( strcasecmp( Req->command, "VERSION" ) == 0 ) return IRC_VERSION( client, Req ); - else if( strcasecmp( Req->command, "KILL" ) == 0 ) return IRC_KILL( client, Req ); - else if( strcasecmp( Req->command, "AWAY" ) == 0 ) return IRC_AWAY( client, Req ); - else if( strcasecmp( Req->command, "TOPIC" ) == 0 ) return IRC_TOPIC( client, Req ); - else if( strcasecmp( Req->command, "WHO" ) == 0 ) return IRC_WHO( client, Req ); - else if( strcasecmp( Req->command, "LIST" ) == 0 ) return IRC_LIST( client, Req ); - else if( strcasecmp( Req->command, "INVITE" ) == 0 ) return IRC_INVITE( client, Req ); - else if( strcasecmp( Req->command, "KICK" ) == 0 ) return IRC_KICK( client, Req ); - else if( strcasecmp( Req->command, "CONNECT" ) == 0 ) return IRC_CONNECT( client, Req ); - else if( strcasecmp( Req->command, "ADMIN" ) == 0 ) return IRC_ADMIN( client, Req ); -#ifdef IRCPLUS - else if( strcasecmp( Req->command, "CHANINFO" ) == 0 ) return IRC_CHANINFO( client, Req ); -#endif + cmd = My_Commands; + while( cmd->name ) + { + /* Befehl suchen */ + if( strcasecmp( Req->command, cmd->name ) != 0 ) + { + cmd++; continue; + } + + if( Client_Type( client ) & cmd->type ) + { + /* Command is allowed for this client: call it and count produced bytes */ + Conn_ResetWCounter( ); + result = (cmd->function)( client, Req ); + cmd->bytes += Conn_WCounter( ); + + /* Adjust counters */ + if( Client_Type( client ) != CLIENT_SERVER ) cmd->lcount++; + else cmd->rcount++; + + return result; + } + else + { + /* Befehl ist fuer diesen Client-Typ nicht erlaubt! */ + return IRC_WriteStrClient( client, ERR_NOTREGISTERED_MSG, Client_ID( client )); + } + } /* Unbekannter Befehl */ - if( Client_Type( client ) != CLIENT_SERVER ) IRC_WriteStrClient( client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( client ), Req->command ); Log( LOG_DEBUG, "Connection %d: Unknown command \"%s\", %d %s,%s prefix.", Client_Conn( client ), Req->command, Req->argc, Req->argc == 1 ? "parameter" : "parameters", Req->prefix ? "" : " no" ); - - return TRUE; + if( Client_Type( client ) != CLIENT_SERVER ) return IRC_WriteStrClient( client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( client ), Req->command ); + else return TRUE; } /* Handle_Request */ Index: src/ngircd/parse.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/parse.h,v retrieving revision 1.7 retrieving revision 1.9 diff -u -r1.7 -r1.9 --- src/ngircd/parse.h 2002/05/27 13:09:27 1.7 +++ src/ngircd/parse.h 2002/12/18 13:53:20 1.9 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: parse.h,v 1.7 2002/05/27 13:09:27 alex Exp $ + * $Id: parse.h,v 1.9 2002/12/18 13:53:20 alex Exp $ * - * parse.h: Parsen der Client-Anfragen (Header) + * IRC command parser and validator (header) */ @@ -28,7 +27,19 @@ } REQUEST; +typedef struct _COMMAND +{ + CHAR *name; /* command name */ + BOOLEAN (*function)( CLIENT *Client, REQUEST *Request ); + CLIENT_TYPE type; /* valid client types (bit mask) */ + LONG lcount, rcount; /* number of local and remote calls */ + LONG bytes; /* number of bytes created */ +} COMMAND; + + GLOBAL BOOLEAN Parse_Request PARAMS((CONN_ID Idx, CHAR *Request )); + +GLOBAL COMMAND *Parse_GetCommandStruct PARAMS(( VOID )); #endif Index: src/ngircd/resolve.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/resolve.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- src/ngircd/resolve.c 2002/06/09 13:19:08 1.3 +++ src/ngircd/resolve.c 2002/12/12 12:24:18 1.4 @@ -2,20 +2,19 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: resolve.c,v 1.3 2002/06/09 13:19:08 alex Exp $ - * - * resolve.c: asyncroner Resolver + * Asynchronous resolver */ #include "portab.h" + +static char UNUSED id[] = "$Id: resolve.c,v 1.4 2002/12/12 12:24:18 alex Exp $"; #include "imp.h" #include Index: src/ngircd/resolve.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/resolve.h,v retrieving revision 1.2 retrieving revision 1.3 diff -u -r1.2 -r1.3 --- src/ngircd/resolve.h 2002/09/16 09:22:41 1.2 +++ src/ngircd/resolve.h 2002/12/12 12:23:43 1.3 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: resolve.h,v 1.2 2002/09/16 09:22:41 alex Exp $ + * $Id: resolve.h,v 1.3 2002/12/12 12:23:43 alex Exp $ * - * resolve.h: asyncroner Resolver (Header) + * Asynchronous resolver (header) */ Index: src/ngircd/tool.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/tool.c,v retrieving revision 1.9 retrieving revision 1.10 diff -u -r1.9 -r1.10 --- src/ngircd/tool.c 2002/05/27 13:09:27 1.9 +++ src/ngircd/tool.c 2002/12/12 12:24:18 1.10 @@ -2,20 +2,19 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: tool.c,v 1.9 2002/05/27 13:09:27 alex Exp $ - * - * tool.c: Hilfsfunktionen, ggf. Platformabhaengig + * Tool functions */ #include "portab.h" + +static char UNUSED id[] = "$Id: tool.c,v 1.10 2002/12/12 12:24:18 alex Exp $"; #include "imp.h" #include Index: src/ngircd/tool.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/ngircd/tool.h,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- src/ngircd/tool.h 2002/05/27 13:09:27 1.8 +++ src/ngircd/tool.h 2002/12/12 12:23:43 1.9 @@ -2,16 +2,15 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: tool.h,v 1.8 2002/05/27 13:09:27 alex Exp $ + * $Id: tool.h,v 1.9 2002/12/12 12:23:43 alex Exp $ * - * log.h: Hilfsfunktionen (Header) + * Tool functions (Header) */ Index: src/portab/portab.h =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/portab/portab.h,v retrieving revision 1.7.2.1 retrieving revision 1.9 diff -u -r1.7.2.1 -r1.9 --- src/portab/portab.h 2002/11/04 19:18:39 1.7.2.1 +++ src/portab/portab.h 2002/12/12 11:26:08 1.9 @@ -9,7 +9,7 @@ * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. * - * $Id: portab.h,v 1.7.2.1 2002/11/04 19:18:39 alex Exp $ + * $Id: portab.h,v 1.9 2002/12/12 11:26:08 alex Exp $ * * portab.h: "Portabilitaets-Definitionen" */ @@ -24,6 +24,13 @@ /* Compiler Features */ +#ifdef __GNUC__ +# define PUNUSED(x) __attribute__ ((unused)) x +# define UNUSED __attribute__ ((unused)) +#else +# define PUNUSED(x) x +# define UNUSED +#endif #ifndef PARAMS # if PROTOTYPES Index: src/portab/portabtest.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/portab/portabtest.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -r1.8 -r1.9 --- src/portab/portabtest.c 2002/09/09 10:05:10 1.8 +++ src/portab/portabtest.c 2002/12/12 11:38:46 1.9 @@ -2,20 +2,19 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: portabtest.c,v 1.8 2002/09/09 10:05:10 alex Exp $ - * - * portabtest.c: Testprogramm fuer portab.h + * test program for portab.h and friends ;-) */ #include "portab.h" + +static char UNUSED id[] = "$Id: portabtest.c,v 1.9 2002/12/12 11:38:46 alex Exp $"; #include "imp.h" #include Index: src/portab/vsnprintf.c =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/portab/vsnprintf.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -r1.3 -r1.4 --- src/portab/vsnprintf.c 2002/05/27 13:01:04 1.3 +++ src/portab/vsnprintf.c 2002/12/12 11:37:11 1.4 @@ -2,20 +2,20 @@ * ngIRCd -- The Next Generation IRC Daemon * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de) * - * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen - * der GNU General Public License (GPL), wie von der Free Software Foundation - * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2 - * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version. - * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste - * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * Please read the file COPYING, README and AUTHORS for more information. * - * $Id: vsnprintf.c,v 1.3 2002/05/27 13:01:04 alex Exp $ - * - * vsnprintf.c: u.a. Ersatz fuer vsnprintf() + * snprintf() and vsnprintf() replacement functions */ #include "portab.h" + +static char UNUSED id[] = "$Id: vsnprintf.c,v 1.4 2002/12/12 11:37:11 alex Exp $"; + #include "imp.h" #include "exp.h" Index: src/testsuite/Makefile.am =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/testsuite/Makefile.am,v retrieving revision 1.3.2.2 retrieving revision 1.9 diff -u -r1.3.2.2 -r1.9 --- src/testsuite/Makefile.am 2002/09/20 15:39:55 1.3.2.2 +++ src/testsuite/Makefile.am 2002/11/10 14:28:06 1.9 @@ -9,7 +9,7 @@ # Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste # der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS. # -# $Id: Makefile.am,v 1.3.2.2 2002/09/20 15:39:55 alex Exp $ +# $Id: Makefile.am,v 1.9 2002/11/10 14:28:06 alex Exp $ # AUTOMAKE_OPTIONS = ../portab/ansi2knr @@ -25,7 +25,7 @@ clean-local: rm -rf logs tests *-test ngircd-test.log ngircd-test.motd \ - ngircd-TEST* procs.tmp + T-ngircd procs.tmp maintainer-clean-local: rm -f Makefile Makefile.in @@ -33,7 +33,7 @@ check_SCRIPTS = ngircd-TEST-Binary tests.sh ngircd-TEST-Binary: - cp ../ngircd/ngircd ngircd-TEST + cp ../ngircd/ngircd T-ngircd [ -f getpid.sh ] || ln -s $(srcdir)/getpid.sh . connect-test: tests.sh Index: src/testsuite/getpid.sh =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/testsuite/getpid.sh,v retrieving revision 1.1.2.1 retrieving revision 1.2 diff -u -r1.1.2.1 -r1.2 --- src/testsuite/getpid.sh 2002/09/20 15:19:55 1.1.2.1 +++ src/testsuite/getpid.sh 2002/11/10 14:28:06 1.2 @@ -1,22 +1,24 @@ #!/bin/sh # ngIRCd Test Suite -# $Id: getpid.sh,v 1.1.2.1 2002/09/20 15:19:55 alex Exp $ +# $Id: getpid.sh,v 1.2 2002/11/10 14:28:06 alex Exp $ # wurde ein Name uebergeben? [ $# -ne 1 ] && exit 1 # Flags fuer "ps" ermitteln if [ `uname` = "FreeBSD" ]; then - PS_FLAGS=-a; PS_PIDCOL=1 + PS_FLAGS="-a"; PS_PIDCOL="1"; HEAD_FLAGS="-n 1" +elif [ `uname` = "A/UX" ]; then + PS_FLAGS="-ae"; PS_PIDCOL="1"; HEAD_FLAGS="-1" else - PS_FLAGS=-f; PS_PIDCOL=2 + PS_FLAGS="-f"; PS_PIDCOL="2"; HEAD_FLAGS="-n 1" ps $PS_FLAGS > /dev/null 2>&1 - if [ $? -ne 0 ]; then PS_FLAGS=a; PS_PIDCOL=1; fi + if [ $? -ne 0 ]; then PS_FLAGS="a"; PS_PIDCOL="1"; fi fi # PID ermitteln ps $PS_FLAGS > procs.tmp -pid=`cat procs.tmp | grep "$1" | awk "{ print \\\$$PS_PIDCOL }" | sort -n | head -n 1` +pid=$( cat procs.tmp | grep "$1" | awk "{print \$$PS_PIDCOL}" | sort -n | head $HEAD_FLAGS ) # ermittelte PID validieren [ "$pid" -gt 1 ] > /dev/null 2>&1 Index: src/testsuite/mode-test.e =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/testsuite/mode-test.e,v retrieving revision 1.2.2.1 retrieving revision 1.4 diff -u -r1.2.2.1 -r1.4 --- src/testsuite/mode-test.e 2002/11/22 23:46:09 1.2.2.1 +++ src/testsuite/mode-test.e 2002/12/15 15:52:34 1.4 @@ -1,4 +1,4 @@ -# $Id: mode-test.e,v 1.2.2.1 2002/11/22 23:46:09 alex Exp $ +# $Id: mode-test.e,v 1.4 2002/12/15 15:52:34 alex Exp $ spawn telnet localhost 6789 expect { @@ -93,10 +93,10 @@ ":nick!~user@* MODE #channel +I nick3!user@*" } -send "mode #channel -vo nick\r" +send "mode #channel -vo nick nick\r" expect { timeout { exit 1 } - ":nick!~user@* MODE #channel -vo nick" + ":nick!~user@* MODE #channel -vo nick nick" } send "quit\r" Index: src/testsuite/ngircd-test.conf =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/testsuite/ngircd-test.conf,v retrieving revision 1.2.2.1 retrieving revision 1.3 diff -u -r1.2.2.1 -r1.3 --- src/testsuite/ngircd-test.conf 2002/11/04 19:18:39 1.2.2.1 +++ src/testsuite/ngircd-test.conf 2002/10/21 13:45:23 1.3 @@ -1,4 +1,4 @@ -# $Id: ngircd-test.conf,v 1.2.2.1 2002/11/04 19:18:39 alex Exp $ +# $Id: ngircd-test.conf,v 1.3 2002/10/21 13:45:23 alex Exp $ [Global] Name = ngircd.test.server Index: src/testsuite/start-server.sh =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/testsuite/start-server.sh,v retrieving revision 1.5.2.4 retrieving revision 1.10 diff -u -r1.5.2.4 -r1.10 --- src/testsuite/start-server.sh 2002/10/03 16:13:38 1.5.2.4 +++ src/testsuite/start-server.sh 2002/11/10 14:28:06 1.10 @@ -1,6 +1,6 @@ #!/bin/sh # ngIRCd Test Suite -# $Id: start-server.sh,v 1.5.2.4 2002/10/03 16:13:38 alex Exp $ +# $Id: start-server.sh,v 1.10 2002/11/10 14:28:06 alex Exp $ [ -z "$srcdir" ] && srcdir=`dirname $0` @@ -12,7 +12,7 @@ # pruefen, ob getpid.sh gueltige PID's liefert. Wenn dem nicht so ist, # wird kein ngIRCd gestartet, da dieser ansonsten nicht mehr am Ende # des Testlaufs beendet werden koennte! -./getpid.sh make > /dev/null 2>&1 +./getpid.sh sh > /dev/null 2>&1 if [ $? -ne 0 ]; then echo " error: getpid.sh FAILED!" exit 1 @@ -22,11 +22,11 @@ echo "This is an ngIRCd Test Server" > ngircd-test.motd # Test-Server starten ... -./ngircd-TEST -np -f ${srcdir}/ngircd-test.conf > ngircd-test.log 2>&1 & +./T-ngircd -np -f ${srcdir}/ngircd-test.conf > ngircd-test.log 2>&1 & sleep 1 # validieren, dass Server laeuft -pid=`./getpid.sh ngircd-TEST` +pid=`./getpid.sh T-ngircd` [ -n "$pid" ] && kill -0 $pid > /dev/null 2>&1 || exit 1 # -eof- Index: src/testsuite/stop-server.sh =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/testsuite/stop-server.sh,v retrieving revision 1.4.2.4 retrieving revision 1.9 diff -u -r1.4.2.4 -r1.9 --- src/testsuite/stop-server.sh 2002/10/03 16:13:38 1.4.2.4 +++ src/testsuite/stop-server.sh 2002/11/10 14:28:06 1.9 @@ -1,13 +1,13 @@ #!/bin/sh # ngIRCd Test Suite -# $Id: stop-server.sh,v 1.4.2.4 2002/10/03 16:13:38 alex Exp $ +# $Id: stop-server.sh,v 1.9 2002/11/10 14:28:06 alex Exp $ [ -z "$srcdir" ] && srcdir=`dirname $0` echo " stopping server ..." # Test-Server stoppen ... -pid=`./getpid.sh ngircd-TEST` +pid=`./getpid.sh T-ngircd` [ -n "$pid" ] && kill $pid > /dev/null 2>&1 || exit 1 sleep 1 Index: src/testsuite/stress-server.sh =================================================================== RCS file: /usr/local/CVS/ngircd/ngircd/src/testsuite/stress-server.sh,v retrieving revision 1.4.2.2 retrieving revision 1.6 diff -u -r1.4.2.2 -r1.6 --- src/testsuite/stress-server.sh 2002/10/03 16:13:38 1.4.2.2 +++ src/testsuite/stress-server.sh 2002/09/23 22:07:43 1.6 @@ -1,6 +1,6 @@ #!/bin/sh # ngIRCd Test Suite -# $Id: stress-server.sh,v 1.4.2.2 2002/10/03 16:13:38 alex Exp $ +# $Id: stress-server.sh,v 1.6 2002/09/23 22:07:43 alex Exp $ [ -z "$srcdir" ] && srcdir=`dirname $0`