mirror of
https://github.com/osmarks/ngircd.git
synced 2025-11-02 15:03:00 +00:00
Compare commits
65 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e56fb35ab | ||
|
|
408793c2ca | ||
|
|
1ab92bb9cb | ||
|
|
5a0f118df0 | ||
|
|
eab20beefc | ||
|
|
0bb9db1aa0 | ||
|
|
8316d98b16 | ||
|
|
a0123e424c | ||
|
|
ff25b7291f | ||
|
|
eba8d4d553 | ||
|
|
71c7a6fcc0 | ||
|
|
3b38d3ca0d | ||
|
|
6491b9843f | ||
|
|
40c9fd26d6 | ||
|
|
b5ee4552c1 | ||
|
|
8f521aa8bf | ||
|
|
b28dab3632 | ||
|
|
9f9e9a496f | ||
|
|
d17748e978 | ||
|
|
d14588f368 | ||
|
|
d569c9246e | ||
|
|
791301dc7d | ||
|
|
92fb409fe2 | ||
|
|
8a324b6d9c | ||
|
|
7709acf754 | ||
|
|
077b610eb0 | ||
|
|
23253edb54 | ||
|
|
bb19cfda95 | ||
|
|
4b0c9849d6 | ||
|
|
fc3c82f7df | ||
|
|
5999fcea4e | ||
|
|
87fc9566b0 | ||
|
|
85ac414908 | ||
|
|
01999cfdb1 | ||
|
|
4c32a6cebd | ||
|
|
9951e13510 | ||
|
|
d3e0d78d4d | ||
|
|
20640e1a90 | ||
|
|
6debfc3123 | ||
|
|
49ed223c1b | ||
|
|
00f86465ef | ||
|
|
d79a7d287a | ||
|
|
5829be2944 | ||
|
|
bd923fc757 | ||
|
|
6600c90890 | ||
|
|
b9d701dbeb | ||
|
|
b3ccaa76b6 | ||
|
|
8d48f07de1 | ||
|
|
568239244f | ||
|
|
22cf0c5def | ||
|
|
c2ee5437da | ||
|
|
4fe7e9d6f1 | ||
|
|
006c0328b4 | ||
|
|
52424b49cb | ||
|
|
baf845ddeb | ||
|
|
428cc6258f | ||
|
|
3543c2220a | ||
|
|
8f7e7d666a | ||
|
|
a53857b4c7 | ||
|
|
2714a94f43 | ||
|
|
6359ec48f0 | ||
|
|
b89c310891 | ||
|
|
bf92db85a6 | ||
|
|
9e18ec30ff | ||
|
|
a56776892b |
45
ChangeLog
45
ChangeLog
@@ -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
22
NEWS
@@ -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
11
README
@@ -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 $
|
||||
|
||||
13
configure.in
13
configure.in
@@ -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 --
|
||||
|
||||
@@ -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
46
doc/FAQ.txt
Normal 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 $
|
||||
@@ -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 $
|
||||
|
||||
@@ -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- */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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- */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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 */
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
672
src/ngircd/irc.c
672
src/ngircd/irc.c
@@ -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- */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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- */
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user