1
0
mirror of https://github.com/osmarks/ngircd.git synced 2025-11-02 15:03:00 +00:00

Compare commits

..

65 Commits

Author SHA1 Message Date
Alexander Barton
1e56fb35ab - Version 0.0.1 2002-01-29 00:24:17 +00:00
Alexander Barton
408793c2ca - README, NEWS und ChangeLog aktualisiert. 2002-01-29 00:17:39 +00:00
Alexander Barton
1ab92bb9cb - neue Funktion Client_TopServer(), Client_NewXXX() angepasst. 2002-01-29 00:14:49 +00:00
Alexander Barton
5a0f118df0 - RPL_WHOISCHANNELS_MSG korrigiert. 2002-01-29 00:14:05 +00:00
Alexander Barton
eab20beefc - WHOIS zeigt nun auch die Channels an, in denen der jeweilige User Mitglied ist.
- zu jedem Server wird nun der "Top-Server" gespeichert, somit funktioniert
  LINKS wieder korrekt.
2002-01-29 00:13:45 +00:00
Alexander Barton
0bb9db1aa0 - neue Funktionen Channel_FirstChannelOf() und Channel_NextChannelOf(). 2002-01-29 00:11:10 +00:00
Alexander Barton
8316d98b16 - RPL_NAMREPLY_MSG an tatsaechliche Implementierung angepasst ;-) 2002-01-28 13:06:19 +00:00
Alexander Barton
a0123e424c - nach einem JOIN wird die Liste der Mitglieder an den Client geschickt.
- MODE fuer Channels wird nun komplett ignoriert (keine Fehlermeldung mehr).
2002-01-28 13:05:48 +00:00
Alexander Barton
ff25b7291f - SERVER-Meldungen an neue Server sind nun in der richtigen Reihenfolge. 2002-01-28 01:45:43 +00:00
Alexander Barton
eba8d4d553 - connectierenden Servern werden Channels nun mit NJOIN bekannt gemacht. 2002-01-28 01:18:14 +00:00
Alexander Barton
71c7a6fcc0 - neue Funktionen Channel_Name(), Channel_First() und Channel_Next(). 2002-01-28 01:16:15 +00:00
Alexander Barton
3b38d3ca0d - ein neu connectierender Server wird nun korrekt im Netz bekannt gemacht. 2002-01-28 00:55:08 +00:00
Alexander Barton
6491b9843f - PART wird nicht mehr an den Server verschickt, von dem es empfangen wurde. 2002-01-27 22:47:11 +00:00
Alexander Barton
40c9fd26d6 - Client_GetFromID() besser dokumentiert, kleinere Aenderungen. 2002-01-27 22:07:36 +00:00
Alexander Barton
b5ee4552c1 - weitere Anpassungen an Chennals, v.a. ueber Server-Links. 2002-01-27 21:56:54 +00:00
Alexander Barton
8f521aa8bf - IRC_WriteStrServersPrefixID() und IRC_WriteStrClientPrefixID() wieder entfernt.
- einige kleinere Fixes bezueglich Channels ...
2002-01-27 21:56:39 +00:00
Alexander Barton
b28dab3632 - IRC_WriteStrServersPrefixID() und IRC_WriteStrClientPrefixID() wieder entfernt. 2002-01-27 21:53:57 +00:00
Alexander Barton
9f9e9a496f - bei NICK wurde das falsche Prefix an andere Server weitergegeben. 2002-01-27 18:28:01 +00:00
Alexander Barton
d17748e978 - Client_GetFromID() kommt nun auch mit Host-Masken zurecht. 2002-01-27 18:27:12 +00:00
Alexander Barton
d14588f368 - anderungen an den Funktions-Prototypen von IRC_WriteStrChannel() und
IRC_WriteStrChannelPrefix(),
- neue: IRC_WriteStrClientPrefixID() und IRC_WriteStrServersPrefixID().
2002-01-27 17:15:49 +00:00
Alexander Barton
d569c9246e - diverse Aenderungen fuer Channels ueber mehrere Server. 2002-01-27 17:14:33 +00:00
Alexander Barton
791301dc7d - neue Defines fuer RPL_TOPIC und RPL_NOTOPIC. 2002-01-27 17:13:37 +00:00
Alexander Barton
92fb409fe2 - neue Funktionen IRC_WriteStrChannelPrefix() und IRC_WriteStrChannel(),
die IRC_Write_xxx_Related() sind dafuer entfallen.
- IRC_PRIVMSG() kann nun auch mit Channels als Ziel umgehen.
2002-01-26 18:43:11 +00:00
Alexander Barton
8a324b6d9c - CHANNEL- und CL2CHAN-Strukturen in Header verlegt,
- einige neue Funktionen (Channel_GetChannel(), Channel_FirstMember(), ...)
2002-01-26 18:41:55 +00:00
Alexander Barton
7709acf754 - CVS-ID's ergaenzt ... 2002-01-23 18:20:04 +00:00
Alexander Barton
077b610eb0 - FAQ begonnen. 2002-01-23 14:05:20 +00:00
Alexander Barton
23253edb54 - die Fehlermeldung "interrupted system call" sollte nicht mehr auftreten. 2002-01-22 17:15:39 +00:00
Alexander Barton
bb19cfda95 - begonnen, Channels zu implementieren :-) 2002-01-21 00:12:29 +00:00
Alexander Barton
4b0c9849d6 - Definition der CHANNEL-Struktur aus Header entfernt,
- neue Funktionen Channel_Join(), Channel_Part() und Channel_RemoveClient().
2002-01-21 00:11:59 +00:00
Alexander Barton
fc3c82f7df - wird ein Client entfernt, so wird er auch aus allen Channels geloescht. 2002-01-21 00:08:50 +00:00
Alexander Barton
5999fcea4e - Channel-Pointer aus Client-Struktur entfernt. Wird nun dynamisch verwaltet :-) 2002-01-21 00:06:49 +00:00
Alexander Barton
87fc9566b0 - neue Funktionen IRC_JOIN und IRC_PART begonnen, ebenso die Funktionen
IRC_WriteStrRelatedPrefix und IRC_WriteStrRelatedChannelPrefix().
- diverse Aenderungen im Zusammenhang mit Channels.
2002-01-21 00:05:11 +00:00
Alexander Barton
85ac414908 - neue Funktionen IRC_JOIN, IRC_PART, IRC_WriteStrRelatedPrefix und
IRC_WriteStrRelatedChannelPrefix().
2002-01-21 00:04:13 +00:00
Alexander Barton
01999cfdb1 - neue Konstante CHANNEL_MODE_LEN. 2002-01-21 00:03:16 +00:00
Alexander Barton
4c32a6cebd - ERR_NOSUCHCHANNEL hinzugefuegt. 2002-01-21 00:02:34 +00:00
Alexander Barton
9951e13510 - Hilfetexte korrigiert und ergaenzt (Sniffer). 2002-01-21 00:02:11 +00:00
Alexander Barton
d3e0d78d4d - neue Befehle JOIN und PART. 2002-01-21 00:01:37 +00:00
Alexander Barton
20640e1a90 *** empty log message *** 2002-01-21 00:00:54 +00:00
Alexander Barton
6debfc3123 - Server-Verbinungen werden beim Start erst nach kurzer Pause aufgebaut. 2002-01-18 15:51:44 +00:00
Alexander Barton
49ed223c1b - bei Client_SetModes() wurde das NULL-Byte falsch gesetzt. Opsa. 2002-01-18 15:32:01 +00:00
Alexander Barton
00f86465ef - die User-Modes bei einem NICK von einem Server wurden falsch uebernommen. 2002-01-18 15:31:32 +00:00
Alexander Barton
d79a7d287a - der Sniffer wird nun nur noch aktiviert, wenn auf Kommandozeile angegeben. 2002-01-18 11:12:11 +00:00
Alexander Barton
5829be2944 - Version auf 0.0.4-pre im CVS angehoben. 2002-01-16 23:06:16 +00:00
Alexander Barton
bd923fc757 - Version 0.0.3 2002-01-16 22:55:45 +00:00
Alexander Barton
6600c90890 *** empty log message *** 2002-01-16 22:35:28 +00:00
Alexander Barton
b9d701dbeb - neue Funktionen Client_xxxCount(). 2002-01-16 22:10:35 +00:00
Alexander Barton
b3ccaa76b6 - IRC_LUSERS() implementiert. 2002-01-16 22:10:18 +00:00
Alexander Barton
8d48f07de1 - RPL_LUSERME_MSG erweitert, kleinere Aenderungen. 2002-01-16 22:09:52 +00:00
Alexander Barton
568239244f - neue Funktion Channel_Count(). 2002-01-16 22:09:07 +00:00
Alexander Barton
22cf0c5def - ngIRCd wandelt sich nun selber in einen Daemon (Hintergrundprozess) um. 2002-01-12 00:17:28 +00:00
Alexander Barton
c2ee5437da - LINKS implementiert, LUSERS begonnen. 2002-01-11 23:50:55 +00:00
Alexander Barton
4fe7e9d6f1 - Hop-Count fuer den Server selber (0) wird korrekt initialisiert. 2002-01-11 23:50:40 +00:00
Alexander Barton
006c0328b4 - Anpassungen an neue Kommandozeilen-Optionen "--debug" und "--nodaemon". 2002-01-11 14:45:37 +00:00
Alexander Barton
52424b49cb - Kommandozeilen-Parser implementiert: Debug- und No-Daemon-Modus, Hilfe. 2002-01-11 14:45:18 +00:00
Alexander Barton
baf845ddeb - WHOIS wurde faelschlicherweise an User geforwarded statt vom Server beantwortet. 2002-01-09 21:30:45 +00:00
Alexander Barton
428cc6258f - WHOIS wird im "Strict-RFC-Mode" nicht mehr automatisch geforwarded,
- andere Server werden nun ueber bisherige Server und User informiert.
2002-01-09 01:09:58 +00:00
Alexander Barton
3543c2220a - Parses handhabt Leerzeichen zw. Parametern nun etwas "lockerer". 2002-01-09 01:08:42 +00:00
Alexander Barton
8f7e7d666a - wird ein Server abgemeldet, so wird anderen Server ein SQUIT geschickt. 2002-01-09 01:08:08 +00:00
Alexander Barton
a53857b4c7 - Es werden fuer alle Server eigene Token generiert,
- QUIT von einem Server fuer einen User wird an andere Server geforwarded,
- ebenso NICK-Befehle, die "fremde" User einfuehren.
2002-01-07 23:42:12 +00:00
Alexander Barton
2714a94f43 - Loglevel von Remote-Mode-Aenderungen angepasst (nun Debug).
- Im Debug-Mode werden nun auch PING's protokolliert.
2002-01-07 16:02:36 +00:00
Alexander Barton
6359ec48f0 - Server nimmt nun Server-Links an: PASS und SERVER entsprechend angepasst.
- MODE und NICK melden nun die Aenderungen an andere Server.
2002-01-07 15:39:46 +00:00
Alexander Barton
b89c310891 - Bei Log-Meldungen ueber Clients wird nun immer die "Client Mask" verwendet. 2002-01-07 15:31:00 +00:00
Alexander Barton
bf92db85a6 - PASSSERVERADD definiert, wird beim PASS-Befehl an Server verwendet. 2002-01-07 15:29:52 +00:00
Alexander Barton
9e18ec30ff - Status-Codes an den Server selber werden ignoriert, besseres Logging. 2002-01-07 15:29:11 +00:00
Alexander Barton
a56776892b - die Fehlermeldung "unbekannter Befehl" hatte ein falsches Format. 2002-01-06 17:41:44 +00:00
21 changed files with 1887 additions and 138 deletions

View File

@@ -10,6 +10,49 @@
-- ChangeLog / Aenderungen --
ngIRCd 0.1.0, 29.01.2002
- User-Modes bei User-Registrierungen von andere Servern (NICK-Befehl)
wurden falsch uebernommen. Zudem wurden die Modes falsch gekuerzt.
- Server-Verbindungen werden nun nach dem Start erst nach einer kurzen
Pause aufgebaut (zur Zeit drei Sekunden).
- Hilfetext korrigiert: --help und --version waren vertauscht, die
Option --sniffer wurde gar nicht erwaehnt.
- FAQ.txt in doc/ begonnen.
- der IRC-Sniffer wird nur noch aktiviert, wenn die Option auf der
Kommandozeile angegeben wurde (bei entsprechend compiliertem Server).
- Channels implementiert, bisher jedoch noch ohne Channel-Modes, d.h.
es gibt keine Channel-Ops, kein Topic, kein "topic lock" etc. pp.
Chatten in Channels ist aber natuerlich moeglich ;-)
- neue Befehle fuer Channles: JOIN, PART und NJOIN.
- durch die Channels einige Aenderungen an PRIVMSG, WHOIS, MODE etc.
- neu connectierenden Servern werden nun Channels mit NJOIN angekuendigt.
- Signal-Hander geaendert: die Fehlermeldung "interrupted system call"
sollte so nicht mehr auftreten.
- "spaeter" neu connectierende Server werden nun im Netz angekuendigt.
- SERVER-Meldungen an andere Server sind nun korrekt sortiert.
- 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
"Sub-Server" haben, also sowohl als Leaf-Node als auch Hub in einem
IRC-Netzwerk arbeiten.
- MODE und NICK melden nun die Aenderungen an andere Server, ebenso
die Befehle QUIT und SQUIT.
- WHOIS wird nun immer an den "Original-Server" weitergeleitet.
- Parses handhabt Leerzeichen zw. Parametern nun etwas "lockerer".
- Status-Codes an den Server selber werden ignorier.
- Log-Meldungen und Log-Level ueberarbeitet und korrigiert.
- Kommandozeilen-Parser: Debug- und No-Daemon-Modus, Hilfe.
- ngIRCd wandelt sich nun in einen Daemon (Hintergrundprozess) um.
- WHOIS korrigiert: Anfrage wurde u.U. an User geforwarded anstatt vom
Server beantwortet zu werden.
- neue Befehle: LUSERS, LINKS
- Client-Modes von Remote-Servern wurden nicht korrekt uerbernommen.
ngIRCd 0.0.2, 06.01.2002
- Struktur der Konfigurationsdatei geaendert: sie ist nun "Samba like",
@@ -38,4 +81,4 @@ ngIRCd 0.0.1, 31.12.2001
--
$Id: ChangeLog,v 1.7 2002/01/06 15:40:01 alex Exp $
$Id: ChangeLog,v 1.13 2002/01/29 00:17:39 alex Exp $

22
NEWS
View File

@@ -10,6 +10,26 @@
-- NEWS / Neuigkeiten --
ngIRCd 0.1.0, 29.01.2002
- Channels implementiert, bisher jedoch noch ohne Channel-Modes, d.h.
es gibt keine Channel-Ops, kein Topic, kein "topic lock" etc. pp.
Chatten in Channels ist aber natuerlich moeglich ;-)
Dadurch zum Teil groessere Aenderungen an bisherigen Funktionen.
- neue Befehle fuer Channles: JOIN, PART und NJOIN.
- FAQ.txt in doc/ begonnen.
ngIRCd 0.0.3, 16.01.2002
- Server-Links vollstaendig implementiert: der ngIRCd kann nun auch
"Sub-Server" haben, also sowohl als Leaf-Node als auch Hub in einem
IRC-Netzwerk arbeiten.
- WHOIS wird nun immer an den "Original-Server" weitergeleitet.
- Parser handhabt Leerzeichen zw. Parametern nun etwas "lockerer".
- Kommandozeilen-Parser: Debug- und No-Daemon-Modus, Hilfe.
- ngIRCd wandelt sich nun in einen Daemon (Hintergrundprozess) um.
- neue Befehle: LUSERS, LINKS.
ngIRCd 0.0.2, 06.01.2002
- neuer Aufbau der Konfigurationsdatei,
@@ -23,4 +43,4 @@ ngIRCd 0.0.1, 31.12.2001
--
$Id: NEWS,v 1.4 2002/01/06 15:40:01 alex Exp $
$Id: NEWS,v 1.6 2002/01/29 00:17:39 alex Exp $

11
README
View File

@@ -20,12 +20,11 @@ wenig wie Server-Links. Das private Chatten (PRIVMSG) mit den Client-Befehlen
/msg und /query sollte hingegen funktionieren, ein wenig praktische Funk-
tionalitaet ist also tatsaechlich schon vorhanden ;-)
Diese Version ist aber auf jeden Fall als "Preview" anzusehen!
Bisher (mehr oder wenig vollstaendig) implementierte IRC-Befehle:
DIE, ISON, MODE, MOTD, NAMES, NICK, NOTICE, OPER, PASS, PING, PONG, PRIVMSG,
QUIT, RESTART, USER, USERHOST, WHOIS.
DIE, ERROR, ISON, JOIN, LINKS, LUSERS, MODE, MOTD, NAMES, NICK, NOTICE, NJOIN,
OPER, PART, PASS, PING, PONG, PRIVMSG, QUIT, RESTART, SERVER, SQUIT, USER,
USERHOST, WHOIS.
Ueber Rueckmeldungen, Bug-Reports und Patches freue ich mich! Also los, haut
in die Tasten! :-))
@@ -40,3 +39,7 @@ Hinweise zur Installation findest du in der Datei INSTALL.
Alle Autoren von ngIRCd sind in AUTHORS aufgefuehrt.
In der Datei COPYING steht die GNU General Public License.
Das README liest du gerade ,-)
--
$Id: README,v 1.4 2002/01/29 00:17:39 alex Exp $

View File

@@ -9,9 +9,18 @@
# 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.19 2002/01/06 16:21:09 alex Exp $
# $Id: configure.in,v 1.22 2002/01/29 00:24:17 alex Exp $
#
# $Log: configure.in,v $
# Revision 1.22 2002/01/29 00:24:17 alex
# - Version 0.0.1
#
# Revision 1.21 2002/01/16 23:06:16 alex
# - Version auf 0.0.4-pre im CVS angehoben.
#
# Revision 1.20 2002/01/16 22:55:45 alex
# - Version 0.0.3
#
# Revision 1.19 2002/01/06 16:21:09 alex
# - CVS-Version auf "0.0.3-pre" angehoben.
#
@@ -74,7 +83,7 @@
AC_INIT
AC_CONFIG_SRCDIR(src/ngircd/ngircd.c)
AM_INIT_AUTOMAKE(ngircd,0.0.3-pre)
AM_INIT_AUTOMAKE(ngircd,0.1.0)
AM_CONFIG_HEADER(src/config.h)
# -- Variablen --

View File

@@ -19,3 +19,7 @@ noch nicht, also frage einfach Alex direkt (siehe AUTHORS-Text), wenn du
daran interessiert bist, Zugriff auf den Quellcode via CVS zu bekommen!
[ ... more to come ... ]
--
$Id: CVS.txt,v 1.4 2002/01/23 18:20:04 alex Exp $

46
doc/FAQ.txt Normal file
View File

@@ -0,0 +1,46 @@
ngIRCd - Next Generation IRC Server
(c)2001,2002 by Alexander Barton,
alex@barton.de, http://www.barton.de/
ngIRCd ist freie Software und steht unter
der GNU General Public License.
-- FAQ: Frequently Asked Questions --
I. Allgemein
~~~~~~~~~~~~
Q: Kann der ngIRCd im Netz zusammen mit "normalen" Servern betrieben werden?
A: Ja. ngIRCd ist zum Original kompatibel, getestet wird dies zur Zeit mit
der Version 2.10.3p3 des ircd.
Q: Gibt es eine Homepage mit Informationen und Downloads?
A: Ja. Die URL ist <http://arthur.ath.cx/~alex/ngircd/>.
II. Compilieren
~~~~~~~~~~~~~~~
Q: Ich habe die Sourcen von ngIRCd ueber CVS installiert. Nun kann ich
./configure nicht ausfuehren, da es nicht existiert!?
A: Bei Builds direkt aus dem CVS-Tree muss das configure-Script zunaechst
durch GNU autoconf sowie die Makefile.in's durch GNU automake generiert
werden. Um dies zu vereinfachen existiert das Script "./autogen.sh".
GNU automake und GNU autoconf werden -- im Gegensatz zu Builds aus den
Sourcen eines .tar.gz-Archivs -- hierbei benoetigt!
Q: ./autogen.sh bricht mit der Meldung "autoheader: command not found" ab.
A: GNU autoconf ist nicht installiert, wird jedoch bei Builds direkt aus
dem CVS-Tree benoetigt.
Q: ./autogen.sh bricht mit der Meldung "autoconf: Undefined macros:
AC_FUNC_MALLOC" bzw. "AC_CONFIG_SRCDIR" ab.
A: Auf dem System ist eine zu alte Version von GNU autoconf installiert.
Ein Update auf z.B. Version 2.52 loest dieses Problem (eine installiete
alte Version sollte ggf. zunaechst entfernt werden, bei RPM-Paketen z.B.
mit dem Befehl "rpm -e autoconf").
--
$Id: FAQ.txt,v 1.1 2002/01/23 14:05:20 alex Exp $

View File

@@ -27,3 +27,6 @@ Das IRC-Protokoll ist in diesen RFC's (Request For Comments) dokumentiert:
2813 Kalt, C., "Internet Relay Chat: Server Protocol",
April 2000, [IRC-SERVER].
--
$Id: RFC.txt,v 1.4 2002/01/23 18:20:04 alex Exp $

View File

@@ -9,11 +9,36 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: channel.c,v 1.3 2002/01/02 02:42:58 alex Exp $
* $Id: channel.c,v 1.11 2002/01/29 00:11:10 alex Exp $
*
* channel.c: Management der Channels
*
* $Log: channel.c,v $
* Revision 1.11 2002/01/29 00:11:10 alex
* - neue Funktionen Channel_FirstChannelOf() und Channel_NextChannelOf().
*
* Revision 1.10 2002/01/28 01:16:15 alex
* - neue Funktionen Channel_Name(), Channel_First() und Channel_Next().
*
* Revision 1.9 2002/01/27 22:47:11 alex
* - PART wird nicht mehr an den Server verschickt, von dem es empfangen wurde.
*
* Revision 1.8 2002/01/27 21:56:54 alex
* - weitere Anpassungen an Chennals, v.a. ueber Server-Links.
*
* Revision 1.7 2002/01/27 17:14:33 alex
* - diverse Aenderungen fuer Channels ueber mehrere Server.
*
* Revision 1.6 2002/01/26 18:41:55 alex
* - CHANNEL- und CL2CHAN-Strukturen in Header verlegt,
* - einige neue Funktionen (Channel_GetChannel(), Channel_FirstMember(), ...)
*
* Revision 1.5 2002/01/21 00:12:29 alex
* - begonnen, Channels zu implementieren :-)
*
* Revision 1.4 2002/01/16 22:09:07 alex
* - neue Funktion Channel_Count().
*
* Revision 1.3 2002/01/02 02:42:58 alex
* - Copyright-Texte aktualisiert.
*
@@ -24,32 +49,403 @@
*
* Revision 1.1 2001/12/14 08:13:43 alex
* - neues Modul begonnen :-)
*
*/
#define __channel_c__
#include <portab.h>
#include "global.h"
#include <imp.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "client.h"
#include "irc.h"
#include "log.h"
#include "messages.h"
#include <exp.h>
#include "channel.h"
LOCAL CHANNEL *My_Channels;
LOCAL CL2CHAN *My_Cl2Chan;
LOCAL CHANNEL *New_Chan( CHAR *Name );
LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client );
LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client );
LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN ServerPART );
LOCAL CL2CHAN *Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan );
LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Chan );
LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan );
GLOBAL VOID Channel_Init( VOID )
{
My_Channels = NULL;
My_Cl2Chan = NULL;
} /* Channel_Init */
GLOBAL VOID Channel_Exit( VOID )
{
CHANNEL *c, *c_next;
CL2CHAN *cl2chan, *cl2chan_next;
/* Channel-Strukturen freigeben */
c = My_Channels;
while( c )
{
c_next = c->next;
free( c );
c = c_next;
}
/* Channel-Zuordnungstabelle freigeben */
cl2chan = My_Cl2Chan;
while( c )
{
cl2chan_next = cl2chan->next;
free( cl2chan );
cl2chan = cl2chan_next;
}
} /* Channel_Exit */
GLOBAL BOOLEAN Channel_Join( CLIENT *Client, CHAR *Name )
{
CHANNEL *chan;
assert( Client != NULL );
assert( Name != NULL );
/* Valider Channel-Name? */
if(( Name[0] != '#' ) || ( strlen( Name ) >= CHANNEL_NAME_LEN ))
{
IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
return FALSE;
}
/* Channel suchen */
chan = Channel_Search( Name );
if( chan )
{
/* Ist der Client bereits Mitglied? */
if( Get_Cl2Chan( chan, Client )) return FALSE;
}
else
{
/* Gibt es noch nicht? Dann neu anlegen: */
chan = New_Chan( Name );
if( ! chan ) return FALSE;
/* Verketten */
chan->next = My_Channels;
My_Channels = chan;
}
/* User dem Channel hinzufuegen */
if( ! Add_Client( chan, Client )) return FALSE;
else return TRUE;
} /* Channel_Join */
GLOBAL BOOLEAN Channel_Part( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason )
{
CHANNEL *chan;
assert( Client != NULL );
assert( Name != NULL );
/* Channel suchen */
chan = Channel_Search( Name );
if(( ! chan ) || ( ! Get_Cl2Chan( chan, Client )))
{
IRC_WriteStrClient( Client, ERR_NOSUCHCHANNEL_MSG, Client_ID( Client ), Name );
return FALSE;
}
/* User aus Channel entfernen */
if( ! Remove_Client( chan, Client, Origin, Reason, TRUE )) return FALSE;
else return TRUE;
} /* Channel_Part */
GLOBAL VOID Channel_RemoveClient( CLIENT *Client, CHAR *Reason )
{
CHANNEL *c, *next_c;
assert( Client != NULL );
c = My_Channels;
while( c )
{
next_c = c->next;
Remove_Client( c, Client, Client_ThisServer( ), Reason, FALSE );
c = next_c;
}
} /* Channel_RemoveClient */
GLOBAL INT Channel_Count( VOID )
{
CHANNEL *c;
INT count;
count = 0;
c = My_Channels;
while( c )
{
count++;
c = c->next;
}
return count;
} /* Channel_Count */
GLOBAL CHAR *Channel_Name( CHANNEL *Chan )
{
assert( Chan != NULL );
return Chan->name;
} /* Channel_Name */
GLOBAL CHANNEL *Channel_First( VOID )
{
return My_Channels;
} /* Channel_First */
GLOBAL CHANNEL *Channel_Next( CHANNEL *Chan )
{
assert( Chan != NULL );
return Chan->next;
} /* Channel_Next */
GLOBAL CHANNEL *Channel_Search( CHAR *Name )
{
/* Channel-Struktur suchen */
CHANNEL *c;
assert( Name != NULL );
c = My_Channels;
while( c )
{
if( strcasecmp( Name, c->name ) == 0 ) return c;
c = c->next;
}
return NULL;
} /* Channel_Search */
GLOBAL CL2CHAN *Channel_FirstMember( CHANNEL *Chan )
{
assert( Chan != NULL );
return Get_First_Cl2Chan( NULL, Chan );
} /* Channel_FirstMember */
GLOBAL CL2CHAN *Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan )
{
assert( Chan != NULL );
assert( Cl2Chan != NULL );
return Get_Next_Cl2Chan( Cl2Chan->next, NULL, Chan );
} /* Channel_NextMember */
GLOBAL CL2CHAN *Channel_FirstChannelOf( CLIENT *Client )
{
assert( Client != NULL );
return Get_First_Cl2Chan( Client, NULL );
} /* Channel_FirstChannelOf */
GLOBAL CL2CHAN *Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan )
{
assert( Client != NULL );
assert( Cl2Chan != NULL );
return Get_Next_Cl2Chan( Cl2Chan->next, Client, NULL );
} /* Channel_NextChannelOf */
GLOBAL CLIENT *Channel_GetClient( CL2CHAN *Cl2Chan )
{
assert( Cl2Chan != NULL );
return Cl2Chan->client;
} /* Channel_GetClient */
GLOBAL CHANNEL *Channel_GetChannel( CL2CHAN *Cl2Chan )
{
assert( Cl2Chan != NULL );
return Cl2Chan->channel;
} /* Channel_GetChannel */
LOCAL CHANNEL *New_Chan( CHAR *Name )
{
/* Neue Channel-Struktur anlegen */
CHANNEL *c;
assert( Name != NULL );
c = malloc( sizeof( CHANNEL ));
if( ! c )
{
Log( LOG_EMERG, "Can't allocate memory!" );
return NULL;
}
c->next = NULL;
strncpy( c->name, Name, CHANNEL_NAME_LEN );
c->name[CHANNEL_NAME_LEN - 1] = '\0';
strcpy( c->modes, "" );
Log( LOG_DEBUG, "Created new channel structure for \"%s\".", Name );
return c;
} /* New_Chan */
LOCAL CL2CHAN *Get_Cl2Chan( CHANNEL *Chan, CLIENT *Client )
{
CL2CHAN *cl2chan;
assert( Chan != NULL );
assert( Client != NULL );
cl2chan = My_Cl2Chan;
while( cl2chan )
{
if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) return cl2chan;
cl2chan = cl2chan->next;
}
return NULL;
} /* Get_Cl2Chan */
LOCAL CL2CHAN *Add_Client( CHANNEL *Chan, CLIENT *Client )
{
CL2CHAN *cl2chan;
assert( Chan != NULL );
assert( Client != NULL );
cl2chan = malloc( sizeof( CL2CHAN ));
if( ! cl2chan )
{
Log( LOG_EMERG, "Can't allocate memory!" );
return NULL;
}
cl2chan->channel = Chan;
cl2chan->client = Client;
/* Verketten */
cl2chan->next = My_Cl2Chan;
My_Cl2Chan = cl2chan;
Log( LOG_DEBUG, "User \"%s\" joined channel \"%s\".", Client_Mask( Client ), Chan->name );
return cl2chan;
} /* Add_Client */
LOCAL BOOLEAN Remove_Client( CHANNEL *Chan, CLIENT *Client, CLIENT *Origin, CHAR *Reason, BOOLEAN ServerPART )
{
CL2CHAN *cl2chan, *last_cl2chan;
CHANNEL *c;
assert( Chan != NULL );
assert( Client != NULL );
assert( Origin != NULL );
assert( Reason != NULL );
last_cl2chan = NULL;
cl2chan = My_Cl2Chan;
while( cl2chan )
{
if(( cl2chan->channel == Chan ) && ( cl2chan->client == Client )) break;
last_cl2chan = cl2chan;
cl2chan = cl2chan->next;
}
if( ! cl2chan ) return FALSE;
c = cl2chan->channel;
assert( c != NULL );
/* Aus Verkettung loesen und freigeben */
if( last_cl2chan ) last_cl2chan->next = cl2chan->next;
else My_Cl2Chan = cl2chan->next;
free( cl2chan );
if( ServerPART ) IRC_WriteStrServersPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
IRC_WriteStrChannelPrefix( Origin, c, Client, FALSE, "PART %s :%s", c->name, Reason );
if(( Client_Conn( Origin ) > NONE ) && ( Client_Type( Origin ) == CLIENT_USER )) IRC_WriteStrClientPrefix( Origin, Client, "PART %s :%s", c->name, Reason );
Log( LOG_DEBUG, "User \"%s\" left channel \"%s\" (%s).", Client_Mask( Client ), c->name, Reason );
/* Wenn Channel nun leer: loeschen */
if( ! Get_First_Cl2Chan( NULL, Chan )) Delete_Channel( Chan );
return TRUE;
} /* Remove_Client */
LOCAL CL2CHAN *Get_First_Cl2Chan( CLIENT *Client, CHANNEL *Chan )
{
return Get_Next_Cl2Chan( My_Cl2Chan, Client, Chan );
} /* Get_First_Cl2Chan */
LOCAL CL2CHAN *Get_Next_Cl2Chan( CL2CHAN *Start, CLIENT *Client, CHANNEL *Channel )
{
CL2CHAN *cl2chan;
assert( Client != NULL || Channel != NULL );
cl2chan = Start;
while( cl2chan )
{
if(( Client ) && ( cl2chan->client == Client )) return cl2chan;
if(( Channel ) && ( cl2chan->channel == Channel )) return cl2chan;
cl2chan = cl2chan->next;
}
return NULL;
} /* Get_Next_Cl2Chan */
LOCAL BOOLEAN Delete_Channel( CHANNEL *Chan )
{
/* Channel-Struktur loeschen */
CHANNEL *chan, *last_chan;
last_chan = NULL;
chan = My_Channels;
while( chan )
{
if( chan == Chan ) break;
last_chan = chan;
chan = chan->next;
}
if( ! chan ) return FALSE;
Log( LOG_DEBUG, "Freed channel structure for \"%s\".", Chan->name );
/* Neu verketten und freigeben */
if( last_chan ) last_chan->next = chan->next;
else My_Channels = chan->next;
free( chan );
return TRUE;
} /* Delete_Channel */
/* -eof- */

View File

@@ -9,11 +9,28 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: channel.h,v 1.4 2002/01/02 02:42:58 alex Exp $
* $Id: channel.h,v 1.9 2002/01/29 00:11:19 alex Exp $
*
* channel.h: Management der Channels (Header)
*
* $Log: channel.h,v $
* Revision 1.9 2002/01/29 00:11:19 alex
* - neue Funktionen Channel_FirstChannelOf() und Channel_NextChannelOf().
*
* Revision 1.8 2002/01/28 01:16:15 alex
* - neue Funktionen Channel_Name(), Channel_First() und Channel_Next().
*
* Revision 1.7 2002/01/26 18:41:55 alex
* - CHANNEL- und CL2CHAN-Strukturen in Header verlegt,
* - einige neue Funktionen (Channel_GetChannel(), Channel_FirstMember(), ...)
*
* Revision 1.6 2002/01/21 00:11:59 alex
* - Definition der CHANNEL-Struktur aus Header entfernt,
* - neue Funktionen Channel_Join(), Channel_Part() und Channel_RemoveClient().
*
* Revision 1.5 2002/01/16 22:09:07 alex
* - neue Funktion Channel_Count().
*
* Revision 1.4 2002/01/02 02:42:58 alex
* - Copyright-Texte aktualisiert.
*
@@ -27,23 +44,65 @@
*
* Revision 1.1 2001/12/14 08:13:43 alex
* - neues Modul begonnen :-)
*
*/
#ifndef __channel_h__
#define __channel_h__
#include "client.h"
#ifdef __channel_c__
typedef struct _CHANNEL
{
CHAR name[CHANNEL_NAME_LEN]; /* Name */
struct _CHANNEL *next;
CHAR name[CHANNEL_NAME_LEN]; /* Name des Channel */
CHAR modes[CHANNEL_MODE_LEN]; /* Channel-Modes */
} CHANNEL;
typedef struct _CLIENT2CHAN
{
struct _CLIENT2CHAN *next;
CLIENT *client;
CHANNEL *channel;
CHAR modes[CHANNEL_MODE_LEN]; /* User-Modes in dem Channel */
} CL2CHAN;
#else
typedef POINTER CHANNEL;
typedef POINTER CL2CHAN;
#endif
GLOBAL VOID Channel_Init( VOID );
GLOBAL VOID Channel_Exit( VOID );
GLOBAL BOOLEAN Channel_Join( CLIENT *Client, CHAR *Name );
GLOBAL BOOLEAN Channel_Part( CLIENT *Client, CLIENT *Origin, CHAR *Name, CHAR *Reason );
GLOBAL VOID Channel_RemoveClient( CLIENT *Client, CHAR *Reason );
GLOBAL INT Channel_Count( VOID );
GLOBAL CHAR *Channel_Name( CHANNEL *Chan );
GLOBAL CHANNEL *Channel_Search( CHAR *Name );
GLOBAL CHANNEL *Channel_First( VOID );
GLOBAL CHANNEL *Channel_Next( CHANNEL *Chan );
GLOBAL CL2CHAN *Channel_FirstMember( CHANNEL *Chan );
GLOBAL CL2CHAN *Channel_NextMember( CHANNEL *Chan, CL2CHAN *Cl2Chan );
GLOBAL CL2CHAN *Channel_FirstChannelOf( CLIENT *Client );
GLOBAL CL2CHAN *Channel_NextChannelOf( CLIENT *Client, CL2CHAN *Cl2Chan );
GLOBAL CLIENT *Channel_GetClient( CL2CHAN *Cl2Chan );
GLOBAL CHANNEL *Channel_GetChannel( CL2CHAN *Cl2Chan );
#endif

View File

@@ -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: client.c,v 1.24 2002/01/06 15:18:14 alex Exp $
* $Id: client.c,v 1.35 2002/01/29 00:14:49 alex Exp $
*
* client.c: Management aller Clients
*
@@ -21,6 +21,41 @@
* Server gewesen, so existiert eine entsprechende CONNECTION-Struktur.
*
* $Log: client.c,v $
* Revision 1.35 2002/01/29 00:14:49 alex
* - neue Funktion Client_TopServer(), Client_NewXXX() angepasst.
*
* Revision 1.34 2002/01/27 22:07:36 alex
* - Client_GetFromID() besser dokumentiert, kleinere Aenderungen.
*
* Revision 1.33 2002/01/27 21:56:54 alex
* - weitere Anpassungen an Chennals, v.a. ueber Server-Links.
*
* Revision 1.32 2002/01/27 18:27:12 alex
* - Client_GetFromID() kommt nun auch mit Host-Masken zurecht.
*
* Revision 1.31 2002/01/21 00:08:50 alex
* - wird ein Client entfernt, so wird er auch aus allen Channels geloescht.
*
* Revision 1.30 2002/01/18 15:32:01 alex
* - bei Client_SetModes() wurde das NULL-Byte falsch gesetzt. Opsa.
*
* Revision 1.29 2002/01/16 22:10:35 alex
* - neue Funktionen Client_xxxCount().
*
* Revision 1.28 2002/01/11 23:50:40 alex
* - Hop-Count fuer den Server selber (0) wird korrekt initialisiert.
*
* Revision 1.27 2002/01/09 01:08:08 alex
* - wird ein Server abgemeldet, so wird anderen Server ein SQUIT geschickt.
*
* Revision 1.26 2002/01/07 23:42:12 alex
* - Es werden fuer alle Server eigene Token generiert,
* - QUIT von einem Server fuer einen User wird an andere Server geforwarded,
* - ebenso NICK-Befehle, die "fremde" User einfuehren.
*
* Revision 1.25 2002/01/07 15:31:00 alex
* - Bei Log-Meldungen ueber Clients wird nun immer die "Client Mask" verwendet.
*
* Revision 1.24 2002/01/06 15:18:14 alex
* - Loglevel und Meldungen nochmals geaendert. Level passen nun besser.
*
@@ -133,7 +168,11 @@ LOCAL CLIENT *This_Server, *My_Clients;
LOCAL CHAR GetID_Buffer[CLIENT_ID_LEN];
LOCAL INT Count( CLIENT_TYPE Type );
LOCAL INT MyCount( CLIENT_TYPE Type );
LOCAL CLIENT *New_Client_Struct( VOID );
LOCAL VOID Generate_MyToken( CLIENT *Client );
GLOBAL VOID Client_Init( VOID )
@@ -153,6 +192,8 @@ GLOBAL VOID Client_Init( VOID )
This_Server->type = CLIENT_SERVER;
This_Server->conn_id = NONE;
This_Server->introducer = This_Server;
This_Server->mytoken = 1;
This_Server->hops = 0;
gethostname( This_Server->host, CLIENT_HOST_LEN );
h = gethostbyname( This_Server->host );
@@ -194,25 +235,25 @@ GLOBAL CLIENT *Client_ThisServer( VOID )
GLOBAL CLIENT *Client_NewLocal( CONN_ID Idx, CHAR *Hostname, INT Type, BOOLEAN Idented )
{
/* Neuen lokalen Client erzeugen: Wrapper-Funktion fuer Client_New(). */
return Client_New( Idx, This_Server, Type, NULL, NULL, Hostname, NULL, 0, 0, NULL, Idented );
return Client_New( Idx, This_Server, NULL, Type, NULL, NULL, Hostname, NULL, 0, 0, NULL, Idented );
} /* Client_NewLocal */
GLOBAL CLIENT *Client_NewRemoteServer( CLIENT *Introducer, CHAR *Hostname, INT Hops, INT Token, CHAR *Info, BOOLEAN Idented )
GLOBAL CLIENT *Client_NewRemoteServer( CLIENT *Introducer, CHAR *Hostname, CLIENT *TopServer, INT Hops, INT Token, CHAR *Info, BOOLEAN Idented )
{
/* Neuen Remote-Client erzeugen: Wrapper-Funktion fuer Client_New (). */
return Client_New( NONE, Introducer, CLIENT_SERVER, Hostname, NULL, Hostname, Info, Hops, Token, NULL, Idented );
return Client_New( NONE, Introducer, TopServer, CLIENT_SERVER, Hostname, NULL, Hostname, Info, Hops, Token, NULL, Idented );
} /* Client_NewRemoteServer */
GLOBAL CLIENT *Client_NewRemoteUser( CLIENT *Introducer, CHAR *Nick, INT Hops, CHAR *User, CHAR *Hostname, INT Token, CHAR *Modes, CHAR *Info, BOOLEAN Idented )
{
/* Neuen Remote-Client erzeugen: Wrapper-Funktion fuer Client_New (). */
return Client_New( NONE, Introducer, CLIENT_USER, Nick, User, Hostname, Info, Hops, Token, NULL, Idented );
return Client_New( NONE, Introducer, NULL, CLIENT_USER, Nick, User, Hostname, Info, Hops, Token, Modes, Idented );
} /* Client_NewRemoteUser */
GLOBAL CLIENT *Client_New( CONN_ID Idx, CLIENT *Introducer, INT Type, CHAR *ID, CHAR *User, CHAR *Hostname, CHAR *Info, INT Hops, INT Token, CHAR *Modes, BOOLEAN Idented )
GLOBAL CLIENT *Client_New( CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer, INT Type, CHAR *ID, CHAR *User, CHAR *Hostname, CHAR *Info, INT Hops, INT Token, CHAR *Modes, BOOLEAN Idented )
{
CLIENT *client;
@@ -226,6 +267,7 @@ GLOBAL CLIENT *Client_New( CONN_ID Idx, CLIENT *Introducer, INT Type, CHAR *ID,
/* Initialisieren */
client->conn_id = Idx;
client->introducer = Introducer;
client->topserver = TopServer;
client->type = Type;
if( ID ) Client_SetID( client, ID );
if( User ) Client_SetUser( client, User, Idented );
@@ -234,6 +276,7 @@ GLOBAL CLIENT *Client_New( CONN_ID Idx, CLIENT *Introducer, INT Type, CHAR *ID,
client->hops = Hops;
client->token = Token;
if( Modes ) Client_SetModes( client, Modes );
if( Type == CLIENT_SERVER ) Generate_MyToken( client );
/* Verketten */
client->next = My_Clients;
@@ -276,20 +319,34 @@ GLOBAL VOID Client_Destroy( CLIENT *Client, CHAR *LogMsg, CHAR *FwdMsg )
{
if( c->conn_id != NONE )
{
/* Ein lokaler User. Andere Server informieren! */
Log( LOG_NOTICE, "User \"%s\" unregistered (connection %d): %s", c->id, c->conn_id, txt );
/* Ein lokaler User. Alle andere Server informieren! */
Log( LOG_NOTICE, "User \"%s\" unregistered (connection %d): %s", Client_Mask( c ), c->conn_id, txt );
if( FwdMsg ) IRC_WriteStrServersPrefix( NULL, c, "QUIT :%s", FwdMsg );
else IRC_WriteStrServersPrefix( NULL, c, "QUIT :" );
}
else
{
Log( LOG_DEBUG, "User \"%s\" unregistered: %s", c->id, txt );
/* Remote User. Andere Server informieren, ausser denen,
* die "in Richtung dem liegen", auf dem der User registriert
* ist. Von denen haben wir das QUIT ja wohl bekommen. */
Log( LOG_DEBUG, "User \"%s\" unregistered: %s", Client_Mask( c ), txt );
if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "QUIT :%s", FwdMsg );
else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "QUIT :" );
}
Channel_RemoveClient( c, FwdMsg ? FwdMsg : c->id );
}
else if( c->type == CLIENT_SERVER )
{
if( c != This_Server ) Log( LOG_NOTICE, "Server \"%s\" unregistered: %s", c->id, txt );
/* andere Server informieren */
if( ! NGIRCd_Quit )
{
if( FwdMsg ) IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :%s", c->id, FwdMsg );
else IRC_WriteStrServersPrefix( Client_NextHop( c ), c, "SQUIT %s :", c->id );
}
}
else Log( LOG_NOTICE, "Unknown client \"%s\" unregistered: %s", c->id, txt );
@@ -353,7 +410,7 @@ GLOBAL VOID Client_SetModes( CLIENT *Client, CHAR *Modes )
assert( Client != NULL );
strncpy( Client->modes, Modes, CLIENT_MODE_LEN );
Client->info[CLIENT_MODE_LEN - 1] = '\0';
Client->modes[CLIENT_MODE_LEN - 1] = '\0';
} /* Client_SetModes */
@@ -371,6 +428,7 @@ GLOBAL VOID Client_SetType( CLIENT *Client, INT Type )
{
assert( Client != NULL );
Client->type = Type;
if( Type == CLIENT_SERVER ) Generate_MyToken( Client );
} /* Client_SetType */
@@ -470,16 +528,23 @@ GLOBAL CLIENT *Client_GetFromConn( CONN_ID Idx )
GLOBAL CLIENT *Client_GetFromID( CHAR *Nick )
{
/* Client-Struktur, die den entsprechenden Nick hat,
* liefern. Wird keine gefunden, so wird NULL geliefert. */
* liefern. Wird keine gefunden, so wird NULL geliefert. */
CLIENT *c;
CHAR n[CLIENT_ID_LEN + 1], *ptr;
CLIENT *c = NULL;
assert( Nick != NULL );
/* Nick kopieren und ggf. Host-Mask abschneiden */
strncpy( n, Nick, CLIENT_ID_LEN );
n[CLIENT_ID_LEN] = '\0';
ptr = strchr( n, '!' );
if( ptr ) *ptr = '\0';
c = My_Clients;
while( c )
{
if( strcasecmp( c->id, Nick ) == 0 ) return c;
if( strcasecmp( c->id, n ) == 0 ) return c;
c = c->next;
}
return NULL;
@@ -587,6 +652,13 @@ GLOBAL INT Client_Token( CLIENT *Client )
} /* Client_Token */
GLOBAL INT Client_MyToken( CLIENT *Client )
{
assert( Client != NULL );
return Client->mytoken;
} /* Client_MyToken */
GLOBAL CLIENT *Client_NextHop( CLIENT *Client )
{
CLIENT *c;
@@ -620,6 +692,13 @@ GLOBAL CLIENT *Client_Introducer( CLIENT *Client )
} /* Client_Introducer */
GLOBAL CLIENT *Client_TopServer( CLIENT *Client )
{
assert( Client != NULL );
return Client->topserver;
} /* Client_TopServer */
GLOBAL BOOLEAN Client_HasMode( CLIENT *Client, CHAR Mode )
{
assert( Client != NULL );
@@ -726,12 +805,111 @@ GLOBAL CLIENT *Client_Next( CLIENT *c )
} /* Client_Next */
GLOBAL INT Client_UserCount( VOID )
{
return Count( CLIENT_USER );
} /* Client_UserCount */
GLOBAL INT Client_ServiceCount( VOID )
{
return Count( CLIENT_SERVICE );;
} /* Client_ServiceCount */
GLOBAL INT Client_ServerCount( VOID )
{
return Count( CLIENT_SERVER );
} /* Client_ServerCount */
GLOBAL INT Client_MyUserCount( VOID )
{
return MyCount( CLIENT_USER );
} /* Client_MyUserCount */
GLOBAL INT Client_MyServiceCount( VOID )
{
return MyCount( CLIENT_SERVICE );
} /* Client_MyServiceCount */
GLOBAL INT Client_MyServerCount( VOID )
{
return MyCount( CLIENT_SERVER );
} /* Client_MyServerCount */
GLOBAL INT Client_OperCount( VOID )
{
CLIENT *c;
INT cnt;
cnt = 0;
c = My_Clients;
while( c )
{
if( c && ( c->type == CLIENT_USER ) && ( strchr( c->modes, 'o' ))) cnt++;
c = c->next;
}
return cnt;
} /* Client_OperCount */
GLOBAL INT Client_UnknownCount( VOID )
{
CLIENT *c;
INT cnt;
cnt = 0;
c = My_Clients;
while( c )
{
if( c && ( c->type != CLIENT_USER ) && ( c->type != CLIENT_SERVICE ) && ( c->type != CLIENT_SERVER )) cnt++;
c = c->next;
}
return cnt;
} /* Client_UnknownCount */
LOCAL INT Count( CLIENT_TYPE Type )
{
CLIENT *c;
INT cnt;
cnt = 0;
c = My_Clients;
while( c )
{
if( c && ( c->type == Type )) cnt++;
c = c->next;
}
return cnt;
} /* Count */
LOCAL INT MyCount( CLIENT_TYPE Type )
{
CLIENT *c;
INT cnt;
cnt = 0;
c = My_Clients;
while( c )
{
if( c && ( c->introducer == This_Server ) && ( c->type == Type )) cnt++;
c = c->next;
}
return cnt;
} /* MyCount */
LOCAL CLIENT *New_Client_Struct( VOID )
{
/* Neue CLIENT-Struktur pre-initialisieren */
CLIENT *c;
INT i;
c = malloc( sizeof( CLIENT ));
if( ! c )
@@ -744,19 +922,43 @@ LOCAL CLIENT *New_Client_Struct( VOID )
c->type = CLIENT_UNKNOWN;
c->conn_id = NONE;
c->introducer = NULL;
c->topserver = NULL;
strcpy( c->id, "" );
strcpy( c->pwd, "" );
strcpy( c->host, "" );
strcpy( c->user, "" );
strcpy( c->info, "" );
for( i = 0; i < MAX_CHANNELS; c->channels[i++] = NULL );
strcpy( c->modes, "" );
c->oper_by_me = FALSE;
c->hops = -1;
c->token = -1;
c->mytoken = -1;
return c;
} /* New_Client */
LOCAL VOID Generate_MyToken( CLIENT *Client )
{
CLIENT *c;
INT token;
c = My_Clients;
token = 2;
while( c )
{
if( c->mytoken == token )
{
/* Das Token wurde bereits vergeben */
token++;
c = My_Clients;
continue;
}
else c = c->next;
}
Client->mytoken = token;
Log( LOG_DEBUG, "Assigned token %d to server \"%s\".", token, Client->id );
} /* Generate_MyToken */
/* -eof- */

View File

@@ -9,11 +9,25 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: client.h,v 1.17 2002/01/06 15:18:14 alex Exp $
* $Id: client.h,v 1.21 2002/01/29 00:14:49 alex Exp $
*
* client.h: Konfiguration des ngircd (Header)
*
* $Log: client.h,v $
* Revision 1.21 2002/01/29 00:14:49 alex
* - neue Funktion Client_TopServer(), Client_NewXXX() angepasst.
*
* Revision 1.20 2002/01/21 00:06:49 alex
* - Channel-Pointer aus Client-Struktur entfernt. Wird nun dynamisch verwaltet :-)
*
* Revision 1.19 2002/01/16 22:10:35 alex
* - neue Funktionen Client_xxxCount().
*
* Revision 1.18 2002/01/07 23:42:12 alex
* - Es werden fuer alle Server eigene Token generiert,
* - QUIT von einem Server fuer einen User wird an andere Server geforwarded,
* - ebenso NICK-Befehle, die "fremde" User einfuehren.
*
* Revision 1.17 2002/01/06 15:18:14 alex
* - Loglevel und Meldungen nochmals geaendert. Level passen nun besser.
*
@@ -75,7 +89,6 @@
#ifndef __client_h__
#define __client_h__
#include "channel.h"
#include "conn.h"
@@ -101,13 +114,13 @@ typedef struct _CLIENT
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) */
CHANNEL *channels[MAX_CHANNELS];/* Channel, in denen der Client Mitglied ist */
CHAR modes[CLIENT_MODE_LEN]; /* Client Modes */
INT hops, token; /* "Hops" und "Token" (-> SERVER-Befehl) */
INT hops, token, mytoken; /* "Hops" und "Token" (-> SERVER-Befehl) */
BOOLEAN oper_by_me; /* IRC-Operator-Status durch diesen Server? */
} CLIENT;
#else
@@ -119,9 +132,9 @@ GLOBAL VOID Client_Init( VOID );
GLOBAL VOID Client_Exit( VOID );
GLOBAL CLIENT *Client_NewLocal( CONN_ID Idx, CHAR *Hostname, INT Type, BOOLEAN Idented );
GLOBAL CLIENT *Client_NewRemoteServer( CLIENT *Introducer, CHAR *Hostname, INT Hops, INT Token, CHAR *Info, BOOLEAN Idented );
GLOBAL CLIENT *Client_NewRemoteServer( CLIENT *Introducer, CHAR *Hostname, CLIENT *TopServer, INT Hops, INT Token, CHAR *Info, BOOLEAN Idented );
GLOBAL CLIENT *Client_NewRemoteUser( CLIENT *Introducer, CHAR *Nick, INT Hops, CHAR *User, CHAR *Hostname, INT Token, CHAR *Modes, CHAR *Info, BOOLEAN Idented );
GLOBAL CLIENT *Client_New( CONN_ID Idx, CLIENT *Introducer, INT Type, CHAR *ID, CHAR *User, CHAR *Hostname, CHAR *Info, INT Hops, INT Token, CHAR *Modes, BOOLEAN Idented );
GLOBAL CLIENT *Client_New( CONN_ID Idx, CLIENT *Introducer, CLIENT *TopServer, INT Type, CHAR *ID, CHAR *User, CHAR *Hostname, CHAR *Info, INT Hops, INT Token, CHAR *Modes, BOOLEAN Idented );
GLOBAL VOID Client_Destroy( CLIENT *Client, CHAR *LogMsg, CHAR *FwdMsg );
@@ -148,6 +161,8 @@ GLOBAL CLIENT *Client_Introducer( CLIENT *Client );
GLOBAL BOOLEAN Client_OperByMe( CLIENT *Client );
GLOBAL INT Client_Hops( CLIENT *Client );
GLOBAL INT Client_Token( CLIENT *Client );
GLOBAL INT Client_MyToken( CLIENT *Client );
GLOBAL CLIENT *Client_TopServer( CLIENT *Client );
GLOBAL CLIENT *Client_NextHop( CLIENT *Client );
GLOBAL BOOLEAN Client_HasMode( CLIENT *Client, CHAR Mode );
@@ -170,6 +185,16 @@ GLOBAL BOOLEAN Client_ModeDel( CLIENT *Client, CHAR Mode );
GLOBAL BOOLEAN Client_CheckNick( CLIENT *Client, CHAR *Nick );
GLOBAL BOOLEAN Client_CheckID( CLIENT *Client, CHAR *ID );
GLOBAL INT Client_UserCount( VOID );
GLOBAL INT Client_ServiceCount( VOID );
GLOBAL INT Client_ServerCount( VOID );
GLOBAL INT Client_OperCount( VOID );
GLOBAL INT Client_UnknownCount( VOID );
GLOBAL INT Client_MyUserCount( VOID );
GLOBAL INT Client_MyServiceCount( VOID );
GLOBAL INT Client_MyServerCount( VOID );
#endif

View File

@@ -9,11 +9,14 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: conf.c,v 1.12 2002/01/05 23:26:24 alex Exp $
* $Id: conf.c,v 1.13 2002/01/18 15:51:44 alex Exp $
*
* conf.h: Konfiguration des ngircd
*
* $Log: conf.c,v $
* Revision 1.13 2002/01/18 15:51:44 alex
* - Server-Verbinungen werden beim Start erst nach kurzer Pause aufgebaut.
*
* Revision 1.12 2002/01/05 23:26:24 alex
* - Fehlermeldungen korrigiert.
*
@@ -171,7 +174,7 @@ LOCAL VOID Read_Config( VOID )
strcpy( Conf_Server[Conf_Server_Count].name, "" );
strcpy( Conf_Server[Conf_Server_Count].pwd, "" );
Conf_Server[Conf_Server_Count].port = 0;
Conf_Server[Conf_Server_Count].lasttry = 0;
Conf_Server[Conf_Server_Count].lasttry = time( NULL ) - Conf_ConnectRetry + STARTUP_DELAY;
Conf_Server[Conf_Server_Count].res_stat = NULL;
Conf_Server_Count++;
}

View File

@@ -9,11 +9,17 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: conn.c,v 1.33 2002/01/06 15:18:14 alex Exp $
* $Id: conn.c,v 1.35 2002/01/18 11:12:11 alex Exp $
*
* connect.h: Verwaltung aller Netz-Verbindungen ("connections")
*
* $Log: conn.c,v $
* Revision 1.35 2002/01/18 11:12:11 alex
* - der Sniffer wird nun nur noch aktiviert, wenn auf Kommandozeile angegeben.
*
* Revision 1.34 2002/01/07 15:29:52 alex
* - PASSSERVERADD definiert, wird beim PASS-Befehl an Server verwendet.
*
* Revision 1.33 2002/01/06 15:18:14 alex
* - Loglevel und Meldungen nochmals geaendert. Level passen nun besser.
*
@@ -449,7 +455,7 @@ GLOBAL BOOLEAN Conn_WriteStr( CONN_ID Idx, CHAR *Format, ... )
}
#ifdef SNIFFER
Log( LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer );
if( NGIRCd_Sniffer ) Log( LOG_DEBUG, " -> connection %d: '%s'.", Idx, buffer );
#endif
strcat( buffer, "\r\n" );
@@ -1019,7 +1025,7 @@ LOCAL VOID New_Server( INT Server, CONN_ID Idx )
if( new_sock > My_Max_Fd ) My_Max_Fd = new_sock;
/* PASS und SERVER verschicken */
Conn_WriteStr( Idx, "PASS %s "PROTOVER""PROTOSUFFIX" IRC|"PACKAGE"-"VERSION" P", Conf_Server[Server].pwd );
Conn_WriteStr( Idx, "PASS %s "PASSSERVERADD, Conf_Server[Server].pwd );
Conn_WriteStr( Idx, "SERVER %s :%s", Conf_ServerName, Conf_ServerInfo );
} /* New_Server */

View File

@@ -9,11 +9,23 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: defines.h,v 1.3 2002/01/03 02:24:00 alex Exp $
* $Id: defines.h,v 1.7 2002/01/22 17:15:39 alex Exp $
*
* defines.h: (globale) Konstanten
*
* $Log: defines.h,v $
* Revision 1.7 2002/01/22 17:15:39 alex
* - die Fehlermeldung "interrupted system call" sollte nicht mehr auftreten.
*
* Revision 1.6 2002/01/21 00:03:16 alex
* - neue Konstante CHANNEL_MODE_LEN.
*
* Revision 1.5 2002/01/18 15:51:44 alex
* - Server-Verbinungen werden beim Start erst nach kurzer Pause aufgebaut.
*
* Revision 1.4 2002/01/07 15:29:53 alex
* - PASSSERVERADD definiert, wird beim PASS-Befehl an Server verwendet.
*
* Revision 1.3 2002/01/03 02:24:00 alex
* - Protokollversion und Suffix definiert.
*
@@ -24,7 +36,6 @@
* - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART),
* - neuen Header "defines.h" mit (fast) allen Konstanten.
* - Code Cleanups und viele "kleine" Aenderungen & Bugfixes.
*
*/
#ifndef __defines_h__
@@ -47,8 +58,6 @@
#define MAX_CONNECTIONS 100 /* max. Anzahl von Verbindungen an diesem Server */
#define MAX_CHANNELS 32 /* max. Anzahl Channels pro Nick */
#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 */
@@ -58,9 +67,10 @@
#define CLIENT_MODE_LEN 8 /* max. Laenge der Client-Modes */
#define CLIENT_INFO_LEN 64 /* max. Infotext-Laenge (Server) */
#define COMMAND_LEN 513 /* max. Laenge eines Befehls, vgl. RFC 2812, 3.2 */
#define CHANNEL_NAME_LEN 51 /* max. Laenge eines Channel-Namens, vgl. RFC 2812, 1.3 */
#define CHANNEL_MODE_LEN 8 /* max. Laenge der Channel-Modes */
#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 WRITEBUFFER_LEN 4096 /* Laenge des Schreibpuffers je Verbindung (Bytes) */
@@ -68,6 +78,9 @@
#define PROTOVER "0210" /* implementierte Protokoll-Version (RFC 2813, 4.1.1) */
#define PROTOSUFFIX "-ngIRCd" /* Protokoll-Suffix (RFC 2813, 4.1.1) */
#define PASSSERVERADD PROTOVER""PROTOSUFFIX" IRC|"PACKAGE"-"VERSION" P"
#define STARTUP_DELAY 1 /* Erst n Sek. nach Start zu anderen Servern verbinden */
#endif

View File

@@ -9,11 +9,80 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: irc.c,v 1.30 2002/01/06 15:21:29 alex Exp $
* $Id: irc.c,v 1.48 2002/01/29 00:13:45 alex Exp $
*
* irc.c: IRC-Befehle
*
* $Log: irc.c,v $
* Revision 1.48 2002/01/29 00:13:45 alex
* - WHOIS zeigt nun auch die Channels an, in denen der jeweilige User Mitglied ist.
* - zu jedem Server wird nun der "Top-Server" gespeichert, somit funktioniert
* LINKS wieder korrekt.
*
* Revision 1.47 2002/01/28 13:05:48 alex
* - nach einem JOIN wird die Liste der Mitglieder an den Client geschickt.
* - MODE fuer Channels wird nun komplett ignoriert (keine Fehlermeldung mehr).
*
* Revision 1.46 2002/01/28 01:45:43 alex
* - SERVER-Meldungen an neue Server sind nun in der richtigen Reihenfolge.
*
* Revision 1.45 2002/01/28 01:18:14 alex
* - connectierenden Servern werden Channels nun mit NJOIN bekannt gemacht.
*
* Revision 1.44 2002/01/28 00:55:08 alex
* - ein neu connectierender Server wird nun korrekt im Netz bekannt gemacht.
*
* Revision 1.43 2002/01/27 21:56:39 alex
* - IRC_WriteStrServersPrefixID() und IRC_WriteStrClientPrefixID() wieder entfernt.
* - einige kleinere Fixes bezueglich Channels ...
*
* Revision 1.42 2002/01/27 18:28:01 alex
* - bei NICK wurde das falsche Prefix an andere Server weitergegeben.
*
* Revision 1.41 2002/01/27 17:15:49 alex
* - anderungen an den Funktions-Prototypen von IRC_WriteStrChannel() und
* IRC_WriteStrChannelPrefix(),
* - neue: IRC_WriteStrClientPrefixID() und IRC_WriteStrServersPrefixID().
*
* Revision 1.40 2002/01/26 18:43:11 alex
* - neue Funktionen IRC_WriteStrChannelPrefix() und IRC_WriteStrChannel(),
* die IRC_Write_xxx_Related() sind dafuer entfallen.
* - IRC_PRIVMSG() kann nun auch mit Channels als Ziel umgehen.
*
* Revision 1.39 2002/01/21 00:05:11 alex
* - neue Funktionen IRC_JOIN und IRC_PART begonnen, ebenso die Funktionen
* IRC_WriteStrRelatedPrefix und IRC_WriteStrRelatedChannelPrefix().
* - diverse Aenderungen im Zusammenhang mit Channels.
*
* Revision 1.38 2002/01/18 15:31:32 alex
* - die User-Modes bei einem NICK von einem Server wurden falsch uebernommen.
*
* Revision 1.37 2002/01/16 22:10:18 alex
* - IRC_LUSERS() implementiert.
*
* Revision 1.36 2002/01/11 23:50:55 alex
* - LINKS implementiert, LUSERS begonnen.
*
* Revision 1.35 2002/01/09 21:30:45 alex
* - WHOIS wurde faelschlicherweise an User geforwarded statt vom Server beantwortet.
*
* Revision 1.34 2002/01/09 01:09:58 alex
* - WHOIS wird im "Strict-RFC-Mode" nicht mehr automatisch geforwarded,
* - andere Server werden nun ueber bisherige Server und User informiert.
*
* Revision 1.33 2002/01/07 23:42:12 alex
* - Es werden fuer alle Server eigene Token generiert,
* - QUIT von einem Server fuer einen User wird an andere Server geforwarded,
* - ebenso NICK-Befehle, die "fremde" User einfuehren.
*
* Revision 1.32 2002/01/07 16:02:36 alex
* - Loglevel von Remote-Mode-Aenderungen angepasst (nun Debug).
* - Im Debug-Mode werden nun auch PING's protokolliert.
*
* Revision 1.31 2002/01/07 15:39:46 alex
* - Server nimmt nun Server-Links an: PASS und SERVER entsprechend angepasst.
* - MODE und NICK melden nun die Aenderungen an andere Server.
*
* Revision 1.30 2002/01/06 15:21:29 alex
* - Loglevel und Meldungen nochmals ueberarbeitet.
* - QUIT und SQUIT forwarden nun den Grund der Trennung,
@@ -131,6 +200,7 @@
#include <string.h>
#include "ngircd.h"
#include "channel.h"
#include "client.h"
#include "conf.h"
#include "conn.h"
@@ -152,6 +222,8 @@ LOCAL BOOLEAN Show_MOTD( CLIENT *Client );
LOCAL VOID Kill_Nick( CHAR *Nick );
LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan );
GLOBAL VOID IRC_Init( VOID )
{
@@ -202,10 +274,9 @@ GLOBAL BOOLEAN IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *F
} /* IRC_WriteStrClientPrefix */
GLOBAL BOOLEAN IRC_WriteStrRelated( CLIENT *Client, CHAR *Format, ... )
GLOBAL BOOLEAN IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )
{
CHAR buffer[1000];
BOOLEAN ok = CONNECTED;
va_list ap;
assert( Client != NULL );
@@ -215,13 +286,65 @@ GLOBAL BOOLEAN IRC_WriteStrRelated( CLIENT *Client, CHAR *Format, ... )
vsnprintf( buffer, 1000, Format, ap );
va_end( ap );
/* an den Client selber */
ok = IRC_WriteStrClient( Client, buffer );
return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, buffer );
} /* IRC_WriteStrChannel */
/* FIXME */
GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
{
CHAR buffer[1000];
BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED, i;
CL2CHAN *cl2chan;
CLIENT *c;
INT s;
va_list ap;
assert( Client != NULL );
assert( Chan != NULL );
assert( Prefix != NULL );
assert( Format != NULL );
va_start( ap, Format );
vsnprintf( buffer, 1000, Format, ap );
va_end( ap );
for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
/* An alle Clients, die in den selben Channels sind.
* Dabei aber nur einmal je Remote-Server */
cl2chan = Channel_FirstMember( Chan );
while( cl2chan )
{
c = Channel_GetClient( cl2chan );
if( ! Remote )
{
if( Client_Conn( c ) <= NONE ) c = NULL;
else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
}
if( c ) c = Client_NextHop( c );
if( c && ( c != Client ))
{
/* Ok, anderer Client */
s = Client_Conn( c );
assert( s >= 0 );
assert( s < MAX_CONNECTIONS );
sock[s] = TRUE;
}
cl2chan = Channel_NextMember( Chan, cl2chan );
}
/* Senden ... */
for( i = 0; i < MAX_CONNECTIONS; i++ )
{
if( sock[i] )
{
ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
if( ! ok ) break;
}
}
return ok;
} /* IRC_WriteStrRelated */
} /* IRC_WriteStrChannelPrefix */
GLOBAL VOID IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
@@ -308,8 +431,11 @@ GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
{
CHAR str[LINE_LEN], *ptr;
CLIENT *c;
INT i;
BOOLEAN ok;
CLIENT *from, *c;
CHANNEL *chan;
CL2CHAN *cl2chan;
INT max_hops, i;
assert( Client != NULL );
assert( Req != NULL );
@@ -323,7 +449,7 @@ GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
Log( LOG_DEBUG, "Connection %d: got SERVER command (new server link) ...", Client_Conn( Client ));
/* Falsche Anzahl Parameter? */
if( Req->argc != 3 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
/* Ist dieser Server bei uns konfiguriert? */
for( i = 0; i < Conf_Server_Count; i++ ) if( strcasecmp( Req->argv[0], Conf_Server[i].name ) == 0 ) break;
@@ -347,13 +473,108 @@ GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
/* Server-Strukturen fuellen ;-) */
Client_SetID( Client, Req->argv[0] );
Client_SetToken( Client, atoi( Req->argv[1] ));
Client_SetInfo( Client, Req->argv[2] );
Client_SetHops( Client, 1 );
Client_SetInfo( Client, Req->argv[Req->argc - 1] );
/* Meldet sich der Server bei uns an? */
if( Req->argc == 2 )
{
/* Unseren SERVER- und PASS-Befehl senden */
ok = TRUE;
if( ! IRC_WriteStrClient( Client, "PASS %s "PASSSERVERADD, Conf_Server[i].pwd )) 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 );
return DISCONNECTED;
}
Client_SetIntroducer( Client, Client );
Client_SetToken( Client, 1 );
}
else Client_SetToken( Client, atoi( Req->argv[1] ));
Log( LOG_NOTICE, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), Client_Conn( Client ));
Client_SetType( Client, CLIENT_SERVER );
/* maximalen Hop Count ermitteln */
max_hops = 0;
c = Client_First( );
while( c )
{
if( Client_Hops( c ) > max_hops ) max_hops = Client_Hops( c );
c = Client_Next( c );
}
/* Alle bisherigen Server dem neuen Server bekannt machen,
* die bisherigen Server ueber den neuen informierenn */
for( i = 0; i < ( max_hops + 1 ); i++ )
{
c = Client_First( );
while( c )
{
if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )) && ( Client_Hops( c ) == i ))
{
if( Client_Conn( c ) > NONE )
{
/* Dem gefundenen Server gleich den neuen
* Server bekannt machen */
if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED;
}
/* Den neuen Server ueber den alten informieren */
if( ! IRC_WriteStrClientPrefix( Client, Client_Hops( c ) == 1 ? Client_ThisServer( ) : Client_Introducer( c ), "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ))) return DISCONNECTED;
}
c = Client_Next( c );
}
}
/* alle User dem neuen Server bekannt machen */
c = Client_First( );
while( c )
{
if( Client_Type( c ) == CLIENT_USER )
{
/* User an neuen Server melden */
if( ! IRC_WriteStrClient( Client, "NICK %s %d %s %s %d +%s :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_User( c ), Client_Hostname( c ), Client_MyToken( Client_Introducer( c )), Client_Modes( c ), Client_Info( c ))) return DISCONNECTED;
}
c = Client_Next( c );
}
/* Channels dem neuen Server bekannt machen */
chan = Channel_First( );
while( chan )
{
sprintf( str, "NJOIN %s :", Channel_Name( chan ));
/* alle Member suchen */
cl2chan = Channel_FirstMember( chan );
while( cl2chan )
{
if( str[strlen( str ) - 1] != ':' ) strcat( str, "," );
strcat( str, Client_ID( Channel_GetClient( cl2chan )));
if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
{
/* Zeile senden */
if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
sprintf( str, "NJOIN %s :", Channel_Name( chan ));
}
cl2chan = Channel_NextMember( chan, cl2chan );
}
/* noch Daten da? */
if( str[strlen( str ) - 1] != ':')
{
/* Ja; Also senden ... */
if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
}
/* naechsten Channel suchen */
chan = Channel_Next( chan );
}
return CONNECTED;
}
else if( Client_Type( Client ) == CLIENT_SERVER )
@@ -370,8 +591,17 @@ GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
ptr = strchr( Req->argv[3] + 2, '[' );
if( ! ptr ) ptr = Req->argv[3];
from = Client_GetFromID( Req->prefix );
if( ! from )
{
/* Hm, Server, der diesen einfuehrt, ist nicht bekannt!? */
Log( LOG_ALERT, "Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)", Req->prefix, Client_Conn( Client ));
Conn_Close( Client_Conn( Client ), NULL, "Unknown ID in prefix of SERVER", TRUE );
return DISCONNECTED;
}
/* Neue Client-Struktur anlegen */
c = Client_NewRemoteServer( Client, Req->argv[0], atoi( Req->argv[1] ), atoi( Req->argv[2] ), ptr, TRUE );
c = Client_NewRemoteServer( Client, Req->argv[0], from, atoi( Req->argv[1] ), atoi( Req->argv[2] ), ptr, TRUE );
if( ! c )
{
/* Neue Client-Struktur konnte nicht angelegt werden */
@@ -381,10 +611,13 @@ GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
}
/* Log-Meldung zusammenbauen und ausgeben */
if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) sprintf( str, "connected to %s, ", Req->prefix );
if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) sprintf( str, "connected to %s, ", Client_ID( from ));
else strcpy( str, "" );
Log( LOG_NOTICE, "Server \"%s\" registered (via %s, %s%d hop%s).", Client_ID( c ), Client_ID( Client ), str, Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
/* Andere Server informieren */
IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ));
return CONNECTED;
}
else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
@@ -393,27 +626,49 @@ GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_NJOIN( CLIENT *Client, REQUEST *Req )
{
CHAR *chan, *ptr;
CLIENT *c;
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 );
chan = Req->argv[0];
ptr = strtok( Req->argv[1], "," );
while( ptr )
{
/* Prefixe abschneiden */
while(( *ptr == '@' ) || ( *ptr == '+' )) ptr++;
c = Client_GetFromID( ptr );
if( c ) Channel_Join( c, chan );
else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, chan );
/* naechsten Nick suchen */
ptr = strtok( NULL, "," );
}
return CONNECTED;
} /* IRC_NJOIN */
GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
{
CLIENT *intr_c, *c;
CLIENT *intr_c, *target, *c;
CHAR *modes;
assert( Client != NULL );
assert( Req != NULL );
/* Zumindest BitchX sendet NICK-USER in der falschen Reihenfolge. */
#ifndef STRICT_RFC
if( Client_Type( Client ) == CLIENT_UNKNOWN || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTUSER || Client_Type( Client ) == CLIENT_USER )
if( Client_Type( Client ) == CLIENT_UNKNOWN || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTUSER || Client_Type( Client ) == CLIENT_USER || ( Client_Type( Client ) == CLIENT_SERVER && Req->argc == 1 ))
#else
if( Client_Type( Client ) == CLIENT_UNKNOWN || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_USER )
if( Client_Type( Client ) == CLIENT_UNKNOWN || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_USER || ( Client_Type( Client ) == CLIENT_SERVER && Req->argc == 1 ))
#endif
{
/* User-Registrierung bzw. Nick-Aenderung */
@@ -421,35 +676,52 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
/* Falsche Anzahl Parameter? */
if( Req->argc != 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
/* Ist der Client "restricted"? */
if( Client_HasMode( Client, 'r' )) return IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
/* "Ziel-Client" ermitteln */
if( Client_Type( Client ) == CLIENT_SERVER )
{
target = Client_GetFromID( Req->prefix );
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
}
else
{
/* Ist der Client "restricted"? */
if( Client_HasMode( Client, 'r' )) return IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
target = Client;
}
/* Wenn der Client zu seinem eigenen Nick wechseln will, so machen
* wir nichts. So macht es das Original und mind. Snak hat probleme,
* wenn wir es nicht so machen. Ob es so okay ist? Hm ... */
#ifndef STRICT_RFC
if( strcmp( Client_ID( Client ), Req->argv[0] ) == 0 ) return CONNECTED;
if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 ) return CONNECTED;
#endif
/* pruefen, ob Nick bereits vergeben. Speziallfall: der Client
* will nur die Gross- und Kleinschreibung aendern. Das darf
* er natuerlich machen :-) */
if( strcasecmp( Client_ID( Client ), Req->argv[0] ) != 0 )
if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
{
if( ! Client_CheckNick( Client, Req->argv[0] )) return CONNECTED;
if( ! Client_CheckNick( target, Req->argv[0] )) return CONNECTED;
}
if( Client_Type( Client ) == CLIENT_USER )
{
/* Nick-Aenderung: allen mitteilen! */
Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( Client ), Client_ID( Client ), Req->argv[0] );
IRC_WriteStrRelated( Client, "NICK :%s", Req->argv[0] );
Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
IRC_WriteStrClient( Client, "NICK :%s", Req->argv[0] );
IRC_WriteStrServersPrefix( NULL, Client, "NICK :%s", Req->argv[0] );
}
else if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Nick-Aenderung: allen mitteilen! */
Log( LOG_DEBUG, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
IRC_WriteStrServersPrefix( Client, target, "NICK :%s", Req->argv[0] );
}
/* Client-Nick registrieren */
Client_SetID( Client, Req->argv[0] );
Client_SetID( target, Req->argv[0] );
if( Client_Type( Client ) != CLIENT_USER )
if(( Client_Type( target ) != CLIENT_USER ) && ( Client_Type( target ) != CLIENT_SERVER ))
{
/* Neuer Client */
Log( LOG_DEBUG, "Connection %d: got NICK command ...", Client_Conn( Client ));
@@ -472,7 +744,7 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
/* Der neue Nick ist auf diesem Server bereits registriert:
* sowohl der neue, als auch der alte Client muessen nun
* disconnectiert werden. */
Log( LOG_ERR, "Server %s introduces already registered nick %s!", Client_ID( Client ), Req->argv[0] );
Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
Kill_Nick( Req->argv[0] );
return CONNECTED;
}
@@ -481,13 +753,13 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
intr_c = Client_GetFromToken( Client, atoi( Req->argv[4] ));
if( ! intr_c )
{
Log( LOG_ERR, "Server %s introduces nick %s with unknown host server!?", Client_ID( Client ), Req->argv[0] );
Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
Kill_Nick( Req->argv[0] );
return CONNECTED;
}
/* Neue Client-Struktur anlegen */
c = Client_NewRemoteUser( intr_c, Req->argv[0], atoi( Req->argv[1] ), Req->argv[2], Req->argv[3], atoi( Req->argv[4] ), Req->argv[5], Req->argv[6], TRUE );
c = Client_NewRemoteUser( intr_c, Req->argv[0], atoi( Req->argv[1] ), Req->argv[2], Req->argv[3], atoi( Req->argv[4] ), Req->argv[5] + 1, Req->argv[6], TRUE );
if( ! c )
{
/* Eine neue Client-Struktur konnte nicht angelegt werden.
@@ -498,7 +770,12 @@ GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
return CONNECTED;
}
Log( LOG_DEBUG, "User \"%s\" registered (via %s, on %s, %d hop%s).", Client_ID( c ), Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
modes = Client_Modes( c );
if( *modes ) Log( LOG_DEBUG, "User \"%s\" (+%s) registered (via %s, on %s, %d hop%s).", Client_Mask( c ), modes, Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
else Log( LOG_DEBUG, "User \"%s\" registered (via %s, on %s, %d hop%s).", Client_Mask( c ), Client_ID( Client ), Client_ID( intr_c ), Client_Hops( c ), Client_Hops( c ) > 1 ? "s": "" );
/* Andere Server, ausser dem Introducer, informieren */
IRC_WriteStrServersPrefix( Client, Client, "NICK %s %d %s %s %d %s :%s", Req->argv[0], atoi( Req->argv[1] ) + 1, Req->argv[2], Req->argv[3], Client_MyToken( intr_c ), Req->argv[5], Req->argv[6] );
return CONNECTED;
}
@@ -565,7 +842,7 @@ GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req )
target = Client_Search( Req->prefix );
if( ! target )
{
Log( LOG_ERR, "Got QUIT from %s for unknown server!?", Client_ID( Client ));
Log( LOG_ERR, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
return CONNECTED;
}
@@ -601,8 +878,8 @@ GLOBAL BOOLEAN IRC_SQUIT( CLIENT *Client, REQUEST *Req )
if( target == Client ) Log( LOG_DEBUG, "Got SQUIT from %s: %s", Client_ID( Client ), Req->argv[1] );
else Log( LOG_DEBUG, "Got SQUIT from %s for %s: %s", Client_ID( Client ), Client_ID( target ), Req->argv[1] );
/* FIXME: das SQUIT muss an alle Server weiter-
* geleitet werden ... */
/* SQUIT an alle Server weiterleiten */
IRC_WriteStrServers( Client, "SQUIT %s :%s", Req->argv[0], Req->argv[1] );
if( Client_Conn( target ) > NONE )
{
@@ -629,6 +906,7 @@ GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
Log( LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Client_Conn( Client ));
return IRC_WriteStrClient( Client, "PONG %s :%s", Client_ID( Client_ThisServer( )), Client_ID( Client ));
} /* IRC_PING */
@@ -669,6 +947,7 @@ GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
{
CLIENT *to, *from;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
@@ -682,15 +961,25 @@ GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( 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 )
{
/* Okay, Ziel ist ein User */
if( Client_Conn( from ) >= 0 ) Conn_UpdateIdle( Client_Conn( from ));
if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
return IRC_WriteStrClientPrefix( to, from, "PRIVMSG %s :%s", Client_ID( to ), Req->argv[1] );
}
else return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
chan = Channel_Search( Req->argv[0] );
if( chan )
{
/* Okay, Ziel ist ein Channel */
if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
return IRC_WriteStrChannelPrefix( Client, chan, from, TRUE, "PRIVMSG %s :%s", Req->argv[0], Req->argv[1] );
}
return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
} /* IRC_PRIVMSG */
@@ -708,6 +997,7 @@ GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req )
if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( 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 )
@@ -724,6 +1014,7 @@ GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
CHAR x[2], new_modes[CLIENT_MODE_LEN], *ptr;
BOOLEAN set, ok;
CLIENT *target;
CHANNEL *chan;
assert( Client != NULL );
assert( Req != NULL );
@@ -731,11 +1022,27 @@ GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
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 < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
/* "Ziel-Client" suchen */
/* "Ziel-Client" bzw. Channel suchen */
chan = NULL;
target = Client_Search( Req->argv[0] );
if( ! target )
{
chan = Channel_Search( Req->argv[0] );
}
/* Falsche Anzahl Parameter? */
if( target && ( 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 );
if( chan )
{
/* Channel Modes kennen wir noch nicht ... */
Log( LOG_DEBUG, "MODE for channel \"%s\" ignored ...", Channel_Name( chan ));
return CONNECTED;
}
/* Wer ist der Anfragende? */
if( Client_Type( Client ) == CLIENT_USER )
{
@@ -824,12 +1131,13 @@ GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Modes an andere Server forwarden */
/* FIXME */
IRC_WriteStrServersPrefix( Client, Client, "MODE %s :%s", Client_ID( target ), new_modes );
}
else
{
/* Bestaetigung an Client schicken */
ok = IRC_WriteStrRelated( Client, "MODE %s :%s", Client_ID( target ), new_modes );
/* Bestaetigung an Client schicken & andere Server informieren */
ok = IRC_WriteStrClient( Client, "MODE %s :%s", Client_ID( target ), new_modes );
IRC_WriteStrServers( Client, "MODE %s :%s", Client_ID( target ), new_modes );
}
Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( target ), Client_Modes( target ));
}
@@ -871,7 +1179,8 @@ GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req )
{
/* noch kein o-Mode gesetzt */
Client_ModeAdd( Client, 'o' );
if( ! IRC_WriteStrRelated( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
}
if( ! Client_OperByMe( Client )) Log( LOG_NOTICE, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
@@ -1003,7 +1312,8 @@ GLOBAL BOOLEAN IRC_ISON( CLIENT *Client, REQUEST *Req )
GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
{
CLIENT *from, *target, *c;
CHAR *ptr = NULL;
CHAR str[LINE_LEN + 1], *ptr = NULL;
CL2CHAN *cl2chan;
assert( Client != NULL );
assert( Req != NULL );
@@ -1030,15 +1340,17 @@ GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
ptr = Req->argv[1];
}
#ifndef STRICT_RFC
else if( Client_Conn( c ) == NONE )
{
/* Client ist nicht von uns. Ziel-Server suchen */
target = c;
ptr = Req->argv[0];
}
#endif
else target = NULL;
if( target && ( Client_NextHop( target ) != Client_ThisServer( ))) return IRC_WriteStrClientPrefix( target, from, "WHOIS %s :%s", Req->argv[0], ptr );
if( target && ( 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;
@@ -1046,6 +1358,31 @@ GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
/* 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 )
{
/* Channel-Name anhaengen */
if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
strcat( str, Channel_Name( Channel_GetChannel( cl2chan )));
if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ))
{
/* Zeile wird zu lang: senden! */
if( ! IRC_WriteStrClient( Client, 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, str )) return DISCONNECTED;
}
/* IRC-Operator? */
if( Client_HasMode( c, 'o' ))
{
@@ -1116,6 +1453,207 @@ GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req )
} /* IRC_ERROR */
GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
{
CLIENT *target, *from;
INT cnt;
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_GetFromID( 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_GetFromID( 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_GetFromID( Req->prefix );
else target = Client;
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Users, Services und Serevr im Netz */
if( ! IRC_WriteStrClient( target, RPL_LUSERCLIENT_MSG, Client_ID( target ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
/* IRC-Operatoren im Netz */
cnt = Client_OperCount( );
if( cnt > 0 )
{
if( ! IRC_WriteStrClient( target, RPL_LUSEROP_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
}
/* Unbekannt Verbindungen */
cnt = Client_UnknownCount( );
if( cnt > 0 )
{
if( ! IRC_WriteStrClient( target, RPL_LUSERUNKNOWN_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
}
/* Channels im Netz */
if( ! IRC_WriteStrClient( target, RPL_LUSERCHANNELS_MSG, Client_ID( target ), Channel_Count( ))) return DISCONNECTED;
/* Channels im Netz */
if( ! IRC_WriteStrClient( target, RPL_LUSERME_MSG, Client_ID( target ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
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_GetFromID( 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_GetFromID( 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_GetFromID( 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_JOIN( CLIENT *Client, REQUEST *Req )
{
CLIENT *target;
CHAR *chan, *flags;
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 );
/* Wer ist der Absender? */
if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
else target = Client;
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Channel-Namen durchgehen */
chan = strtok( Req->argv[0], "," );
while( chan )
{
if( Client_Type( Client ) == CLIENT_SERVER )
{
/* Channel-Flags extrahieren */
flags = strchr( chan, 0x7 );
if( flags ) *flags++ = '\0';
}
else flags = NULL;
if( ! Channel_Join( target, chan ))
{
/* naechsten Namen ermitteln */
chan = strtok( NULL, "," );
continue;
}
/* An andere Server weiterleiten */
IRC_WriteStrServersPrefix( Client, target, "JOIN :%s", chan );
IRC_WriteStrChannelPrefix( Client, Channel_Search( chan ), target, FALSE, "JOIN :%s", chan );
if( Client_Type( Client ) == CLIENT_USER )
{
/* an Client bestaetigen */
IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", chan );
/* Topic an Client schicken */
IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), chan, "What a wonderful channel!" );
/* Mitglieder an Client Melden */
Send_NAMES( Client, Channel_Search( chan ));
}
/* naechsten Namen ermitteln */
chan = strtok( NULL, "," );
}
return CONNECTED;
} /* IRC_JOIN */
GLOBAL BOOLEAN IRC_PART( CLIENT *Client, REQUEST *Req )
{
CLIENT *target;
CHAR *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 );
/* Wer ist der Absender? */
if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
else target = Client;
if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
/* Channel-Namen durchgehen */
chan = strtok( Req->argv[0], "," );
while( chan )
{
if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
{
/* naechsten Namen ermitteln */
chan = strtok( NULL, "," );
continue;
}
/* naechsten Namen ermitteln */
chan = strtok( NULL, "," );
}
return CONNECTED;
} /* IRC_PART */
LOCAL BOOLEAN Hello_User( CLIENT *Client )
{
assert( Client != NULL );
@@ -1187,4 +1725,44 @@ LOCAL VOID Kill_Nick( CHAR *Nick )
} /* Kill_Nick */
LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan )
{
CHAR str[LINE_LEN + 1];
CL2CHAN *cl2chan;
assert( Client != NULL );
assert( Chan != NULL );
/* Alle Mitglieder suchen */
sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
cl2chan = Channel_FirstMember( Chan );
while( cl2chan )
{
/* Nick anhaengen */
if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
strcat( str, Client_ID( Channel_GetClient( cl2chan )));
if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
{
/* Zeile wird zu lang: senden! */
if( ! IRC_WriteStrClient( Client, 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, str )) return DISCONNECTED;
}
/* Ende anzeigen */
IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( Chan ));
return CONNECTED;
} /* Send_NAMES */
/* -eof- */

View File

@@ -9,11 +9,31 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: irc.h,v 1.16 2002/01/05 19:15:03 alex Exp $
* $Id: irc.h,v 1.21 2002/01/27 21:53:57 alex Exp $
*
* irc.h: IRC-Befehle (Header)
*
* $Log: irc.h,v $
* Revision 1.21 2002/01/27 21:53:57 alex
* - IRC_WriteStrServersPrefixID() und IRC_WriteStrClientPrefixID() wieder entfernt.
*
* Revision 1.20 2002/01/27 17:15:49 alex
* - anderungen an den Funktions-Prototypen von IRC_WriteStrChannel() und
* IRC_WriteStrChannelPrefix(),
* - neue: IRC_WriteStrClientPrefixID() und IRC_WriteStrServersPrefixID().
*
* Revision 1.19 2002/01/26 18:43:11 alex
* - neue Funktionen IRC_WriteStrChannelPrefix() und IRC_WriteStrChannel(),
* die IRC_Write_xxx_Related() sind dafuer entfallen.
* - IRC_PRIVMSG() kann nun auch mit Channels als Ziel umgehen.
*
* Revision 1.18 2002/01/21 00:04:13 alex
* - neue Funktionen IRC_JOIN, IRC_PART, IRC_WriteStrRelatedPrefix und
* IRC_WriteStrRelatedChannelPrefix().
*
* Revision 1.17 2002/01/11 23:50:55 alex
* - LINKS implementiert, LUSERS begonnen.
*
* Revision 1.16 2002/01/05 19:15:03 alex
* - Fehlerpruefung bei select() in der "Hauptschleife" korrigiert.
*
@@ -72,6 +92,7 @@
#define __irc_h__
#include "parse.h"
#include "channel.h"
GLOBAL VOID IRC_Init( VOID );
@@ -79,7 +100,8 @@ GLOBAL VOID IRC_Exit( VOID );
GLOBAL BOOLEAN IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... );
GLOBAL BOOLEAN IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... );
GLOBAL BOOLEAN IRC_WriteStrRelated( CLIENT *Client, CHAR *Format, ... );
GLOBAL BOOLEAN IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... );
GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... );
GLOBAL VOID IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... );
GLOBAL VOID IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... );
@@ -94,6 +116,8 @@ GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_SQUIT( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_LINKS( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req );
@@ -111,6 +135,9 @@ GLOBAL BOOLEAN IRC_RESTART( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req );
GLOBAL BOOLEAN IRC_PART( CLIENT *Client, REQUEST *Req );
#endif

View File

@@ -9,11 +9,14 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: log.c,v 1.16 2002/01/05 15:54:40 alex Exp $
* $Id: log.c,v 1.17 2002/01/11 14:45:37 alex Exp $
*
* log.c: Logging-Funktionen
*
* $Log: log.c,v $
* Revision 1.17 2002/01/11 14:45:37 alex
* - Anpassungen an neue Kommandozeilen-Optionen "--debug" und "--nodaemon".
*
* Revision 1.16 2002/01/05 15:54:40 alex
* - syslog() etc. wurde verwendet, auch wenn USE_SYSLOG nicht definiert war.
*
@@ -82,41 +85,19 @@
#include <syslog.h>
#endif
#include "global.h"
#include "ngircd.h"
#include <exp.h>
#include "log.h"
GLOBAL VOID Log_Init( VOID )
{
CHAR txt[64];
strcpy( txt, "" );
#ifdef USE_SYSLOG
if( txt[0] ) strcat( txt, "+" );
else strcat( txt, "-" );
strcat( txt, "SYSLOG" );
#endif
#ifdef STRICT_RFC
if( txt[0] ) strcat( txt, "+" );
else strcat( txt, "-" );
strcat( txt, "RFC" );
#endif
#ifdef DEBUG
if( txt[0] ) strcat( txt, "+" );
else strcat( txt, "-" );
strcat( txt, "DEBUG" );
#endif
#ifdef SNIFFER
if( txt[0] ) strcat( txt, "+" );
else strcat( txt, "-" );
strcat( txt, "SNIFFER" );
#endif
#ifdef USE_SYSLOG
openlog( PACKAGE, LOG_CONS|LOG_PID, LOG_LOCAL5 );
#endif
Log( LOG_NOTICE, PACKAGE" version "VERSION"%s-"P_OSNAME"/"P_ARCHNAME" started.", txt );
Log( LOG_NOTICE, "%s started.", NGIRCd_Version( ));
} /* Log_Init */
@@ -138,7 +119,9 @@ GLOBAL VOID Log( CONST INT Level, CONST CHAR *Format, ... )
assert( Format != NULL );
#ifndef DEBUG
#ifdef DEBUG
if(( Level == LOG_DEBUG ) && ( ! NGIRCd_Debug )) return;
#else
if( Level == LOG_DEBUG ) return;
#endif
@@ -148,7 +131,7 @@ GLOBAL VOID Log( CONST INT Level, CONST CHAR *Format, ... )
msg[MAX_LOG_MSG_LEN - 1] = '\0';
/* ... und ausgeben */
printf( "[%d] %s\n", Level, msg );
if( NGIRCd_NoDaemon ) printf( "[%d] %s\n", Level, msg );
#ifdef USE_SYSLOG
syslog( Level, msg );
#endif
@@ -186,7 +169,9 @@ GLOBAL VOID Log_Resolver( CONST INT Level, CONST CHAR *Format, ... )
assert( Format != NULL );
#ifndef DEBUG
#ifdef DEBUG
if(( Level == LOG_DEBUG ) && ( ! NGIRCd_Debug )) return;
#else
if( Level == LOG_DEBUG ) return;
#endif

View File

@@ -9,11 +9,29 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: messages.h,v 1.17 2002/01/05 23:23:44 alex Exp $
* $Id: messages.h,v 1.23 2002/01/29 00:14:05 alex Exp $
*
* irc.h: IRC-Befehle (Header)
*
* $Log: messages.h,v $
* Revision 1.23 2002/01/29 00:14:05 alex
* - RPL_WHOISCHANNELS_MSG korrigiert.
*
* Revision 1.22 2002/01/28 13:06:19 alex
* - RPL_NAMREPLY_MSG an tatsaechliche Implementierung angepasst ;-)
*
* Revision 1.21 2002/01/27 17:13:37 alex
* - neue Defines fuer RPL_TOPIC und RPL_NOTOPIC.
*
* Revision 1.20 2002/01/21 00:02:34 alex
* - ERR_NOSUCHCHANNEL hinzugefuegt.
*
* Revision 1.19 2002/01/16 22:09:52 alex
* - RPL_LUSERME_MSG erweitert, kleinere Aenderungen.
*
* Revision 1.18 2002/01/11 23:50:55 alex
* - LINKS implementiert, LUSERS begonnen.
*
* Revision 1.17 2002/01/05 23:23:44 alex
* - neue Nachricht ERR_NOSUCHSERVER_MSG definiert.
*
@@ -89,6 +107,21 @@
#define RPL_MYINFO "004"
#define RPL_MYINFO_MSG RPL_MYINFO" %s %s ngircd-"VERSION" ior +"
#define RPL_LUSERCLIENT "251"
#define RPL_LUSERCLIENT_MSG RPL_LUSERCLIENT" %s :There are %d users and %d services on %d servers"
#define RPL_LUSEROP "252"
#define RPL_LUSEROP_MSG RPL_LUSEROP" %s %d :operator(s) online"
#define RPL_LUSERUNKNOWN "253"
#define RPL_LUSERUNKNOWN_MSG RPL_LUSERUNKNOWN" %s %d :unknown connection(s)"
#define RPL_LUSERCHANNELS "254"
#define RPL_LUSERCHANNELS_MSG RPL_LUSERCHANNELS" %s %d :channels formed"
#define RPL_LUSERME "255"
#define RPL_LUSERME_MSG RPL_LUSERME" %s :I have %d users, %d services and %d servers"
#define RPL_MOTDSTART "375"
#define RPL_MOTDSTART_MSG RPL_MOTDSTART" %s :- %s message of the day"
@@ -123,10 +156,22 @@
#define RPL_ENDOFWHOIS_MSG RPL_ENDOFWHOIS" %s %s :End of WHOIS list"
#define RPL_WHOISCHANNELS "319"
#define RPL_WHOISCHANNELS_MSG RPL_WHOISCHANNELS" %s :"
#define RPL_WHOISCHANNELS_MSG RPL_WHOISCHANNELS" %s %s :"
#define RPL_NOTOPIC "331"
#define RPL_NOTOPIC_MSG RPL_NOTOPIC" %s %s :No topic is set"
#define RPL_TOPIC "332"
#define RPL_TOPIC_MSG RPL_TOPIC" %s %s :%s"
#define RPL_NAMREPLY "353"
#define RPL_NAMREPLY_MSG RPL_NAMREPLY" %s %s %s :%s"
#define RPL_NAMREPLY_MSG RPL_NAMREPLY" %s %s %s :"
#define RPL_LINKS "364"
#define RPL_LINKS_MSG RPL_LINKS" %s %s %s :%d %s"
#define RPL_ENDOFLINKS "365"
#define RPL_ENDOFLINKS_MSG RPL_ENDOFLINKS" %s %s :End of LINKS list"
#define RPL_ENDOFNAMES "366"
#define RPL_ENDOFNAMES_MSG RPL_ENDOFNAMES" %s %s :End of NAMES list"
@@ -141,6 +186,9 @@
#define ERR_NOSUCHSERVER "402"
#define ERR_NOSUCHSERVER_MSG ERR_NOSUCHSERVER" %s %s :No such server"
#define ERR_NOSUCHCHANNEL "403"
#define ERR_NOSUCHCHANNEL_MSG ERR_NOSUCHCHANNEL" %s %s :No such channel"
#define ERR_NOORIGIN "409"
#define ERR_NOORIGIN_MSG ERR_NOORIGIN" %s :No origin specified"

View File

@@ -9,11 +9,26 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: ngircd.c,v 1.17 2002/01/02 02:51:16 alex Exp $
* $Id: ngircd.c,v 1.22 2002/01/22 17:15:39 alex Exp $
*
* ngircd.c: Hier beginnt alles ;-)
*
* $Log: ngircd.c,v $
* Revision 1.22 2002/01/22 17:15:39 alex
* - die Fehlermeldung "interrupted system call" sollte nicht mehr auftreten.
*
* Revision 1.21 2002/01/21 00:02:11 alex
* - Hilfetexte korrigiert und ergaenzt (Sniffer).
*
* Revision 1.20 2002/01/18 11:12:11 alex
* - der Sniffer wird nun nur noch aktiviert, wenn auf Kommandozeile angegeben.
*
* Revision 1.19 2002/01/12 00:17:28 alex
* - ngIRCd wandelt sich nun selber in einen Daemon (Hintergrundprozess) um.
*
* Revision 1.18 2002/01/11 14:45:18 alex
* - Kommandozeilen-Parser implementiert: Debug- und No-Daemon-Modus, Hilfe.
*
* Revision 1.17 2002/01/02 02:51:16 alex
* - Signal-Handler fuer SIGCHLD: so sollten Zombies nicht mehr vorkommen.
*
@@ -80,8 +95,11 @@
#include <imp.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
@@ -103,14 +121,136 @@ LOCAL VOID Signal_Handler( INT Signal );
LOCAL VOID Initialize_Listen_Ports( VOID );
LOCAL VOID Show_Version( VOID );
LOCAL VOID Show_Help( VOID );
GLOBAL INT main( INT argc, CONST CHAR *argv[] )
{
BOOLEAN ok;
INT pid, i, n;
/* Datentypen der portab-Library ueberpruefen */
portab_check_types( );
NGIRCd_Restart = FALSE;
NGIRCd_Quit = FALSE;
NGIRCd_NoDaemon = FALSE;
#ifdef DEBUG
NGIRCd_Debug = FALSE;
#endif
#ifdef SNIFFER
NGIRCd_Sniffer = FALSE;
#endif
/* Kommandozeile parsen */
for( i = 1; i < argc; i++ )
{
ok = FALSE;
if(( argv[i][0] == '-' ) && ( argv[i][1] == '-' ))
{
/* Lange Option */
if( strcmp( argv[i], "--help" ) == 0 )
{
Show_Version( ); puts( "" );
Show_Help( ); puts( "" );
exit( 1 );
}
if( strcmp( argv[i], "--version" ) == 0 )
{
Show_Version( );
exit( 1 );
}
#ifdef DEBUG
if( strcmp( argv[i], "--debug" ) == 0 )
{
NGIRCd_Debug = TRUE;
ok = TRUE;
}
#endif
#ifdef SNIFFER
if( strcmp( argv[i], "--sniffer" ) == 0 )
{
NGIRCd_Sniffer = TRUE;
ok = TRUE;
}
#endif
if( strcmp( argv[i], "--nodaemon" ) == 0 )
{
NGIRCd_NoDaemon = TRUE;
ok = TRUE;
}
}
else if(( argv[i][0] == '-' ) && ( argv[i][1] != '-' ))
{
/* Kurze Option */
for( n = 1; n < strlen( argv[i] ); n++ )
{
ok = FALSE;
#ifdef DEBUG
if( argv[i][n] == 'd' )
{
NGIRCd_Debug = TRUE;
ok = TRUE;
}
#endif
#ifdef SNIFFER
if( argv[i][n] == 's' )
{
NGIRCd_Sniffer = TRUE;
ok = TRUE;
}
#endif
if( argv[i][n] == 'n' )
{
NGIRCd_NoDaemon = TRUE;
ok = TRUE;
}
if( ! ok )
{
printf( PACKAGE": invalid option \"-%c\"!\n", argv[i][n] );
puts( "Try \""PACKAGE" --help\" for more information." );
exit( 1 );
}
}
}
if( ! ok )
{
printf( PACKAGE": invalid option \"%s\"!\n", argv[i] );
puts( "Try \""PACKAGE" --help\" for more information." );
exit( 1 );
}
}
while( ! NGIRCd_Quit )
{
/* In der Regel wird ein Sub-Prozess ge-fork()'t, der
* nicht mehr mit dem Terminal verbunden ist. Mit der
* Option "--nodaemon" kann dies (z.B. zum Debuggen)
* verhindert werden. */
if( ! NGIRCd_NoDaemon )
{
/* Daemon im Hintergrund erzeugen */
pid = fork( );
if( pid > 0 )
{
/* "alter" Prozess */
exit( 0 );
}
if( pid < 0 )
{
/* Fehler */
printf( PACKAGE": Can't fork: %s!\nFatal error, exiting now ...", strerror( errno ));
exit( 1 );
}
setsid( );
chdir( "/" );
}
/* Globale Variablen initialisieren */
NGIRCd_Start = time( NULL );
strftime( NGIRCd_StartStr, 64, "%a %b %d %Y at %H:%M:%S (%Z)", localtime( &NGIRCd_Start ));
@@ -152,6 +292,39 @@ GLOBAL INT main( INT argc, CONST CHAR *argv[] )
} /* main */
GLOBAL CHAR *NGIRCd_Version( VOID )
{
STATIC CHAR version[126];
CHAR txt[64];
strcpy( txt, "" );
#ifdef USE_SYSLOG
if( txt[0] ) strcat( txt, "+" );
else strcat( txt, "-" );
strcat( txt, "SYSLOG" );
#endif
#ifdef STRICT_RFC
if( txt[0] ) strcat( txt, "+" );
else strcat( txt, "-" );
strcat( txt, "RFC" );
#endif
#ifdef DEBUG
if( txt[0] ) strcat( txt, "+" );
else strcat( txt, "-" );
strcat( txt, "DEBUG" );
#endif
#ifdef SNIFFER
if( txt[0] ) strcat( txt, "+" );
else strcat( txt, "-" );
strcat( txt, "SNIFFER" );
#endif
sprintf( version, PACKAGE" version "VERSION"%s-"P_OSNAME"/"P_ARCHNAME, txt );
return version;
} /* NGIRCd_Version */
LOCAL VOID Initialize_Signal_Handler( VOID )
{
/* Signal-Handler initialisieren: einige Signale
@@ -161,9 +334,10 @@ LOCAL VOID Initialize_Signal_Handler( VOID )
/* Signal-Struktur initialisieren */
memset( &saction, 0, sizeof( saction ));
saction.sa_handler = Signal_Handler;
saction.sa_flags = SA_RESTART;
/* Signal-Handler einhaengen */
saction.sa_handler = Signal_Handler;
sigaction( SIGINT, &saction, NULL );
sigaction( SIGQUIT, &saction, NULL );
sigaction( SIGTERM, &saction, NULL);
@@ -223,4 +397,28 @@ LOCAL VOID Initialize_Listen_Ports( VOID )
}
} /* Initialize_Listen_Ports */
LOCAL VOID Show_Version( VOID )
{
puts( NGIRCd_Version( ));
puts( "Copyright (c)2001,2002 by Alexander Barton (alex@barton.de).\n" );
puts( "This is free software; see the source for copying conditions. There is NO" );
puts( "warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." );
} /* Show_Version */
LOCAL VOID Show_Help( VOID )
{
#ifdef DEBUG
puts( " -d, --debug log extra debug messages" );
#endif
puts( " -n, --nodaemon don't fork and don't detatch from controlling terminal" );
#ifdef SNIFFER
puts( " -s, --sniffer enable network sniffer and display all IRC traffic" );
#endif
puts( " --version output version information and exit" );
puts( " --help display this help and exit" );
} /* Show_Help */
/* -eof- */

View File

@@ -9,11 +9,17 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: ngircd.h,v 1.6 2002/01/02 02:44:37 alex Exp $
* $Id: ngircd.h,v 1.8 2002/01/18 11:12:11 alex Exp $
*
* ngircd.h: Prototypen aus dem "Haupt-Modul"
*
* $Log: ngircd.h,v $
* Revision 1.8 2002/01/18 11:12:11 alex
* - der Sniffer wird nun nur noch aktiviert, wenn auf Kommandozeile angegeben.
*
* Revision 1.7 2002/01/11 14:45:18 alex
* - Kommandozeilen-Parser implementiert: Debug- und No-Daemon-Modus, Hilfe.
*
* Revision 1.6 2002/01/02 02:44:37 alex
* - neue Defines fuer max. Anzahl Server und Operatoren.
*
@@ -45,10 +51,23 @@
GLOBAL time_t NGIRCd_Start; /* Startzeitpunkt des Daemon */
GLOBAL CHAR NGIRCd_StartStr[64];
#ifdef DEBUG
GLOBAL BOOLEAN NGIRCd_Debug; /* Debug-Modus aktivieren */
#endif
#ifdef SNIFFER
GLOBAL BOOLEAN NGIRCd_Sniffer; /* Sniffer aktivieren */
#endif
GLOBAL BOOLEAN NGIRCd_NoDaemon; /* nicht im Hintergrund laufen */
GLOBAL BOOLEAN NGIRCd_Quit; /* TRUE: ngIRCd beenden */
GLOBAL BOOLEAN NGIRCd_Restart; /* TRUE: neu starten */
GLOBAL CHAR *NGIRCd_Version( VOID );
#endif

View File

@@ -9,11 +9,29 @@
* Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
* der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
*
* $Id: parse.c,v 1.16 2002/01/05 23:23:20 alex Exp $
* $Id: parse.c,v 1.22 2002/01/21 00:01:37 alex Exp $
*
* parse.c: Parsen der Client-Anfragen
*
* $Log: parse.c,v $
* Revision 1.22 2002/01/21 00:01:37 alex
* - neue Befehle JOIN und PART.
*
* Revision 1.21 2002/01/18 11:12:11 alex
* - der Sniffer wird nun nur noch aktiviert, wenn auf Kommandozeile angegeben.
*
* Revision 1.20 2002/01/11 23:50:55 alex
* - LINKS implementiert, LUSERS begonnen.
*
* Revision 1.19 2002/01/09 01:08:42 alex
* - Parses handhabt Leerzeichen zw. Parametern nun etwas "lockerer".
*
* Revision 1.18 2002/01/07 15:29:11 alex
* - Status-Codes an den Server selber werden ignoriert, besseres Logging.
*
* Revision 1.17 2002/01/06 17:41:44 alex
* - die Fehlermeldung "unbekannter Befehl" hatte ein falsches Format.
*
* Revision 1.16 2002/01/05 23:23:20 alex
* - generisches Forwarding von Zahlen-Statuscodes implementiert.
*
@@ -82,6 +100,7 @@
#include <stdio.h>
#include <string.h>
#include "ngircd.h"
#include "client.h"
#include "conn.h"
#include "irc.h"
@@ -127,7 +146,7 @@ GLOBAL BOOLEAN Parse_Request( CONN_ID Idx, CHAR *Request )
assert( Request != NULL );
#ifdef SNIFFER
Log( LOG_DEBUG, " <- connection %d: '%s'.", Idx, Request );
if( NGIRCd_Sniffer ) Log( LOG_DEBUG, " <- connection %d: '%s'.", Idx, Request );
#endif
Init_Request( &req );
@@ -143,6 +162,11 @@ GLOBAL BOOLEAN Parse_Request( CONN_ID Idx, CHAR *Request )
ptr = strchr( Request, ' ' );
if( ! ptr ) return Parse_Error( Idx, "Prefix without command!?" );
*ptr = '\0';
#ifndef STRICT_RFC
/* multiple Leerzeichen als Trenner zwischen
* Prefix und Befehl ignorieren */
while( *(ptr + 1) == ' ' ) ptr++;
#endif
start = ptr + 1;
}
else start = Request;
@@ -151,7 +175,15 @@ GLOBAL BOOLEAN Parse_Request( CONN_ID Idx, CHAR *Request )
/* Befehl */
ptr = strchr( start, ' ' );
if( ptr ) *ptr = '\0';
if( ptr )
{
*ptr = '\0';
#ifndef STRICT_RFC
/* multiple Leerzeichen als Trenner vor
*Parametertrennern ignorieren */
while( *(ptr + 1) == ' ' ) ptr++;
#endif
}
req.command = start;
if( ! Validate_Command( &req )) return Parse_Error( Idx, "Invalid command" );
@@ -173,7 +205,15 @@ GLOBAL BOOLEAN Parse_Request( CONN_ID Idx, CHAR *Request )
{
req.argv[req.argc] = start;
ptr = strchr( start, ' ' );
if( ptr ) *ptr = '\0';
if( ptr )
{
*ptr = '\0';
#ifndef STRICT_RFC
/* multiple Leerzeichen als
* Parametertrenner ignorieren */
while( *(ptr + 1) == ' ' ) ptr++;
#endif
}
}
req.argc++;
@@ -266,12 +306,30 @@ LOCAL BOOLEAN Handle_Request( CONN_ID Idx, REQUEST *Req )
/* Zielserver ermitteln */
if(( Client_Type( client ) == CLIENT_SERVER ) && ( Req->argc > 0 )) target = Client_GetFromID( Req->argv[0] );
else target = NULL;
if( ! target ) return TRUE;
if( ! target )
{
if( target ) Log( LOG_WARNING, "Unknown target for status code: \"%s\"", Req->argv[0] );
else Log( LOG_WARNING, "Unknown target for status code!" );
return TRUE;
}
if( target == Client_ThisServer( ))
{
Log( LOG_DEBUG, "Ignored status code %s from \"%s\".", Req->command, Client_ID( client ));
return TRUE;
}
/* Quell-Client ermitteln */
if( ! Req->prefix[0] ) return TRUE;
if( ! Req->prefix[0] )
{
Log( LOG_WARNING, "Got status code without prefix!?" );
return TRUE;
}
else prefix = Client_GetFromID( Req->prefix );
if( ! prefix ) return TRUE;
if( ! prefix )
{
Log( LOG_WARNING, "Got status code from unknown source: \"%s\"", Req->prefix );
return TRUE;
}
/* Statuscode weiterleiten */
strcpy( str, Req->command );
@@ -305,9 +363,13 @@ LOCAL BOOLEAN Handle_Request( CONN_ID Idx, REQUEST *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 );
/* Unbekannter Befehl */
if( Client_Type( client ) != CLIENT_SERVER ) IRC_WriteStrClient( client, Client_ThisServer( ), ERR_UNKNOWNCOMMAND_MSG, Client_ID( client ), Req->command );
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;