]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc.c
- weitere Anpassungen an Channel-Modes und Channel-User-Modes.
[ngircd-alex.git] / src / ngircd / irc.c
1 /*
2  * ngIRCd -- The Next Generation IRC Daemon
3  * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
4  *
5  * Dieses Programm ist freie Software. Sie koennen es unter den Bedingungen
6  * der GNU General Public License (GPL), wie von der Free Software Foundation
7  * herausgegeben, weitergeben und/oder modifizieren, entweder unter Version 2
8  * der Lizenz oder (wenn Sie es wuenschen) jeder spaeteren Version.
9  * Naehere Informationen entnehmen Sie bitter der Datei COPYING. Eine Liste
10  * der an ngIRCd beteiligten Autoren finden Sie in der Datei AUTHORS.
11  *
12  * $Id: irc.c,v 1.54 2002/02/11 23:33:35 alex Exp $
13  *
14  * irc.c: IRC-Befehle
15  *
16  * $Log: irc.c,v $
17  * Revision 1.54  2002/02/11 23:33:35  alex
18  * - weitere Anpassungen an Channel-Modes und Channel-User-Modes.
19  *
20  * Revision 1.53  2002/02/11 16:06:21  alex
21  * - Die Quelle von MODE-Aenderungen wird nun korrekt weitergegeben.
22  *
23  * Revision 1.52  2002/02/11 15:52:21  alex
24  * - PONG an den Server selber wurde faelschlicherweise versucht zu forwarden.
25  * - Channel-Modes wurden falsch geliefert (als User-Modes).
26  *
27  * Revision 1.51  2002/02/11 15:15:53  alex
28  * - PING und PONG werden nun auch korrekt an andere Server geforwarded.
29  * - bei MODE-Meldungen wird der letzte Parameter nicht mehr mit ":" getrennt.
30  *
31  * Revision 1.50  2002/02/11 01:03:20  alex
32  * - Aenderungen und Anpassungen an Channel-Modes und Channel-User-Modes:
33  *   Modes werden besser geforwarded, lokale User, fuer die ein Channel
34  *   angelegt wird, werden Channel-Operator, etc. pp. ...
35  * - NJOIN's von Servern werden nun korrekt an andere Server weitergeleitet.
36  *
37  * Revision 1.49  2002/02/06 16:51:22  alex
38  * - neue Funktion zur MODE-Behandlung, fuer Channel-Modes vorbereitet.
39  *
40  * Revision 1.48  2002/01/29 00:13:45  alex
41  * - WHOIS zeigt nun auch die Channels an, in denen der jeweilige User Mitglied ist.
42  * - zu jedem Server wird nun der "Top-Server" gespeichert, somit funktioniert
43  *   LINKS wieder korrekt.
44  *
45  * Revision 1.47  2002/01/28 13:05:48  alex
46  * - nach einem JOIN wird die Liste der Mitglieder an den Client geschickt.
47  * - MODE fuer Channels wird nun komplett ignoriert (keine Fehlermeldung mehr).
48  *
49  * Revision 1.46  2002/01/28 01:45:43  alex
50  * - SERVER-Meldungen an neue Server sind nun in der richtigen Reihenfolge.
51  *
52  * Revision 1.45  2002/01/28 01:18:14  alex
53  * - connectierenden Servern werden Channels nun mit NJOIN bekannt gemacht.
54  *
55  * Revision 1.44  2002/01/28 00:55:08  alex
56  * - ein neu connectierender Server wird nun korrekt im Netz bekannt gemacht.
57  *
58  * Revision 1.43  2002/01/27 21:56:39  alex
59  * - IRC_WriteStrServersPrefixID() und IRC_WriteStrClientPrefixID() wieder entfernt.
60  * - einige kleinere Fixes bezueglich Channels ...
61  *
62  * Revision 1.42  2002/01/27 18:28:01  alex
63  * - bei NICK wurde das falsche Prefix an andere Server weitergegeben.
64  *
65  * Revision 1.41  2002/01/27 17:15:49  alex
66  * - anderungen an den Funktions-Prototypen von IRC_WriteStrChannel() und
67  *   IRC_WriteStrChannelPrefix(),
68  * - neue: IRC_WriteStrClientPrefixID() und IRC_WriteStrServersPrefixID().
69  *
70  * Revision 1.40  2002/01/26 18:43:11  alex
71  * - neue Funktionen IRC_WriteStrChannelPrefix() und IRC_WriteStrChannel(),
72  *   die IRC_Write_xxx_Related() sind dafuer entfallen.
73  * - IRC_PRIVMSG() kann nun auch mit Channels als Ziel umgehen.
74  *
75  * Revision 1.39  2002/01/21 00:05:11  alex
76  * - neue Funktionen IRC_JOIN und IRC_PART begonnen, ebenso die Funktionen
77  *   IRC_WriteStrRelatedPrefix und IRC_WriteStrRelatedChannelPrefix().
78  * - diverse Aenderungen im Zusammenhang mit Channels.
79  *
80  * Revision 1.38  2002/01/18 15:31:32  alex
81  * - die User-Modes bei einem NICK von einem Server wurden falsch uebernommen.
82  *
83  * Revision 1.37  2002/01/16 22:10:18  alex
84  * - IRC_LUSERS() implementiert.
85  *
86  * Revision 1.36  2002/01/11 23:50:55  alex
87  * - LINKS implementiert, LUSERS begonnen.
88  *
89  * Revision 1.35  2002/01/09 21:30:45  alex
90  * - WHOIS wurde faelschlicherweise an User geforwarded statt vom Server beantwortet.
91  *
92  * Revision 1.34  2002/01/09 01:09:58  alex
93  * - WHOIS wird im "Strict-RFC-Mode" nicht mehr automatisch geforwarded,
94  * - andere Server werden nun ueber bisherige Server und User informiert.
95  *
96  * Revision 1.33  2002/01/07 23:42:12  alex
97  * - Es werden fuer alle Server eigene Token generiert,
98  * - QUIT von einem Server fuer einen User wird an andere Server geforwarded,
99  * - ebenso NICK-Befehle, die "fremde" User einfuehren.
100  *
101  * Revision 1.32  2002/01/07 16:02:36  alex
102  * - Loglevel von Remote-Mode-Aenderungen angepasst (nun Debug).
103  * - Im Debug-Mode werden nun auch PING's protokolliert.
104  *
105  * Revision 1.31  2002/01/07 15:39:46  alex
106  * - Server nimmt nun Server-Links an: PASS und SERVER entsprechend angepasst.
107  * - MODE und NICK melden nun die Aenderungen an andere Server.
108  *
109  * Revision 1.30  2002/01/06 15:21:29  alex
110  * - Loglevel und Meldungen nochmals ueberarbeitet.
111  * - QUIT und SQUIT forwarden nun den Grund der Trennung,
112  * - WHOIS wird nun immer an den "Original-Server" weitergeleitet.
113  *
114  * Revision 1.29  2002/01/05 23:24:54  alex
115  * - WHOIS erweitert: Anfragen koennen an andere Server weitergeleitet werden.
116  * - Vorbereitungen fuer Ident-Abfragen bei neuen Client-Strukturen.
117  *
118  * Revision 1.28  2002/01/05 20:08:02  alex
119  * - Div. Aenderungen fuer die Server-Links (u.a. WHOIS, QUIT, NICK angepasst).
120  * - Neue Funktionen IRC_WriteStrServer() und IRC_WriteStrServerPrefix().
121  *
122  * Revision 1.27  2002/01/05 19:15:03  alex
123  * - Fehlerpruefung bei select() in der "Hauptschleife" korrigiert.
124  *
125  * Revision 1.26  2002/01/05 16:51:18  alex
126  * - das Passwort von Servern wird nun ueberprueft (PASS- und SERVER-Befehl).
127  *
128  * Revision 1.25  2002/01/05 00:48:33  alex
129  * - bei SQUIT wurde immer die Verbindung getrennt, auch bei Remote-Servern.
130  *
131  * Revision 1.24  2002/01/04 17:58:44  alex
132  * - IRC_WriteStrXXX()-Funktionen eingefuehrt, groessere Anpassungen daran.
133  * - neuer Befehl SQUIT, QUIT an Server-Links angepasst.
134  *
135  * Revision 1.23  2002/01/04 01:36:40  alex
136  * - Loglevel ein wenig angepasst.
137  *
138  * Revision 1.22  2002/01/04 01:21:47  alex
139  * - Client-Strukruren werden nur noch ueber Funktionen angesprochen.
140  * - Weitere Anpassungen und Erweiterungen der Server-Links.
141  *
142  * Revision 1.21  2002/01/03 02:26:51  alex
143  * - neue Befehle SERVER und NJOIN begonnen,
144  * - begonnen, diverse IRC-Befehle an Server-Links anzupassen.
145  *
146  * Revision 1.20  2002/01/02 12:46:41  alex
147  * - die Gross- und Kleinschreibung des Nicks kann mit NICK nun geaendert werden.
148  *
149  * Revision 1.19  2002/01/02 02:51:39  alex
150  * - Copyright-Texte angepasst.
151  * - neuer Befehl "ERROR".
152  *
153  * Revision 1.17  2001/12/31 15:33:13  alex
154  * - neuer Befehl NAMES, kleinere Bugfixes.
155  * - Bug bei PING behoben: war zu restriktiv implementiert :-)
156  *
157  * Revision 1.16  2001/12/31 02:18:51  alex
158  * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART),
159  * - neuen Header "defines.h" mit (fast) allen Konstanten.
160  * - Code Cleanups und viele "kleine" Aenderungen & Bugfixes.
161  *
162  * Revision 1.15  2001/12/30 19:26:11  alex
163  * - Unterstuetzung fuer die Konfigurationsdatei eingebaut.
164  *
165  * Revision 1.14  2001/12/30 11:42:00  alex
166  * - der Server meldet nun eine ordentliche "Start-Zeit".
167  *
168  * Revision 1.13  2001/12/29 03:10:06  alex
169  * - Neue Funktion IRC_MODE() implementiert, div. Aenderungen.
170  * - neue configure-Optione "--enable-strict-rfc".
171  *
172  * Revision 1.12  2001/12/27 19:17:26  alex
173  * - neue Befehle PRIVMSG, NOTICE, PING.
174  *
175  * Revision 1.11  2001/12/27 16:55:41  alex
176  * - neu: IRC_WriteStrRelated(), Aenderungen auch in IRC_WriteStrClient().
177  *
178  * Revision 1.10  2001/12/26 22:48:53  alex
179  * - MOTD-Datei ist nun konfigurierbar und wird gelesen.
180  *
181  * Revision 1.9  2001/12/26 14:45:37  alex
182  * - "Code Cleanups".
183  *
184  * Revision 1.8  2001/12/26 03:21:46  alex
185  * - PING/PONG-Befehle implementiert,
186  * - Meldungen ueberarbeitet: enthalten nun (fast) immer den Nick.
187  *
188  * Revision 1.7  2001/12/25 23:25:18  alex
189  * - und nochmal Aenderungen am Logging ;-)
190  *
191  * Revision 1.6  2001/12/25 23:13:33  alex
192  * - Debug-Meldungen angepasst.
193  *
194  * Revision 1.5  2001/12/25 22:02:42  alex
195  * - neuer IRC-Befehl "/QUIT". Verbessertes Logging & Debug-Ausgaben.
196  *
197  * Revision 1.4  2001/12/25 19:19:30  alex
198  * - bessere Fehler-Abfragen, diverse Bugfixes.
199  * - Nicks werden nur einmal vergeben :-)
200  * - /MOTD wird unterstuetzt.
201  *
202  * Revision 1.3  2001/12/24 01:34:06  alex
203  * - USER und NICK wird nun in beliebiger Reihenfolge akzeptiert (wg. BitchX)
204  * - MOTD-Ausgabe begonnen zu implementieren.
205  *
206  * Revision 1.2  2001/12/23 21:57:16  alex
207  * - erste IRC-Befehle zu implementieren begonnen.
208  *
209  * Revision 1.1  2001/12/14 08:13:43  alex
210  * - neues Modul begonnen :-)
211  */
212
213
214 #include <portab.h>
215 #include "global.h"
216
217 #include <imp.h>
218 #include <assert.h>
219 #include <errno.h>
220 #include <stdarg.h>
221 #include <stdio.h>
222 #include <stdlib.h>
223 #include <string.h>
224
225 #include "ngircd.h"
226 #include "channel.h"
227 #include "client.h"
228 #include "conf.h"
229 #include "conn.h"
230 #include "log.h"
231 #include "messages.h"
232 #include "parse.h"
233 #include "tool.h"
234
235 #include <exp.h>
236 #include "irc.h"
237
238
239 #define CONNECTED TRUE
240 #define DISCONNECTED FALSE
241
242
243 LOCAL BOOLEAN Hello_User( CLIENT *Client );
244 LOCAL BOOLEAN Show_MOTD( CLIENT *Client );
245
246 LOCAL VOID Kill_Nick( CHAR *Nick );
247
248 LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan );
249
250
251 GLOBAL VOID IRC_Init( VOID )
252 {
253 } /* IRC_Init */
254
255
256 GLOBAL VOID IRC_Exit( VOID )
257 {
258 } /* IRC_Exit */
259
260
261 GLOBAL BOOLEAN IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... )
262 {
263         CHAR buffer[1000];
264         BOOLEAN ok = CONNECTED;
265         va_list ap;
266
267         assert( Client != NULL );
268         assert( Format != NULL );
269
270         va_start( ap, Format );
271         vsnprintf( buffer, 1000, Format, ap );
272         va_end( ap );
273
274         /* an den Client selber */
275         ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), buffer );
276
277         return ok;
278 } /* IRC_WriteStrClient */
279
280
281 GLOBAL BOOLEAN IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
282 {
283         /* Text an Clients, lokal bzw. remote, senden. */
284
285         CHAR buffer[1000];
286         va_list ap;
287
288         assert( Client != NULL );
289         assert( Format != NULL );
290         assert( Prefix != NULL );
291
292         va_start( ap, Format );
293         vsnprintf( buffer, 1000, Format, ap );
294         va_end( ap );
295
296         return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Client_ID( Prefix ), buffer );
297 } /* IRC_WriteStrClientPrefix */
298
299
300 GLOBAL BOOLEAN IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, BOOLEAN Remote, CHAR *Format, ... )
301 {
302         CHAR buffer[1000];
303         va_list ap;
304
305         assert( Client != NULL );
306         assert( Format != NULL );
307
308         va_start( ap, Format );
309         vsnprintf( buffer, 1000, Format, ap );
310         va_end( ap );
311
312         return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), Remote, buffer );
313 } /* IRC_WriteStrChannel */
314
315
316 GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, BOOLEAN Remote, CHAR *Format, ... )
317 {
318         CHAR buffer[1000];
319         BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED, i;
320         CL2CHAN *cl2chan;
321         CLIENT *c;
322         INT s;
323         va_list ap;
324
325         assert( Client != NULL );
326         assert( Chan != NULL );
327         assert( Prefix != NULL );
328         assert( Format != NULL );
329
330         va_start( ap, Format );
331         vsnprintf( buffer, 1000, Format, ap );
332         va_end( ap );
333
334         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
335
336         /* An alle Clients, die in den selben Channels sind.
337          * Dabei aber nur einmal je Remote-Server */
338         cl2chan = Channel_FirstMember( Chan );
339         while( cl2chan )
340         {
341                 c = Channel_GetClient( cl2chan );
342                 if( ! Remote )
343                 {
344                         if( Client_Conn( c ) <= NONE ) c = NULL;
345                         else if( Client_Type( c ) == CLIENT_SERVER ) c = NULL;
346                 }
347                 if( c ) c = Client_NextHop( c );
348                         
349                 if( c && ( c != Client ))
350                 {
351                         /* Ok, anderer Client */
352                         s = Client_Conn( c );
353                         assert( s >= 0 );
354                         assert( s < MAX_CONNECTIONS );
355                         sock[s] = TRUE;
356                 }
357                 cl2chan = Channel_NextMember( Chan, cl2chan );
358         }
359
360         /* Senden ... */
361         for( i = 0; i < MAX_CONNECTIONS; i++ )
362         {
363                 if( sock[i] )
364                 {
365                         ok = Conn_WriteStr( i, ":%s %s", Client_ID( Prefix ), buffer );
366                         if( ! ok ) break;
367                 }
368         }
369         return ok;
370 } /* IRC_WriteStrChannelPrefix */
371
372
373 GLOBAL VOID IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
374 {
375         CHAR buffer[1000];
376         va_list ap;
377
378         assert( Format != NULL );
379
380         va_start( ap, Format );
381         vsnprintf( buffer, 1000, Format, ap );
382         va_end( ap );
383
384         /* an den Client selber */
385         return IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), buffer );
386 } /* IRC_WriteStrServers */
387
388
389 GLOBAL VOID IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )
390 {
391         CHAR buffer[1000];
392         CLIENT *c;
393         va_list ap;
394         
395         assert( Format != NULL );
396         assert( Prefix != NULL );
397
398         va_start( ap, Format );
399         vsnprintf( buffer, 1000, Format, ap );
400         va_end( ap );
401         
402         c = Client_First( );
403         while( c )
404         {
405                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
406                 {
407                         /* Ziel-Server gefunden */
408                         IRC_WriteStrClientPrefix( c, Prefix, buffer );
409                 }
410                 c = Client_Next( c );
411         }
412 } /* IRC_WriteStrServersPrefix */
413
414
415 GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req )
416 {
417         assert( Client != NULL );
418         assert( Req != NULL );
419
420         /* Fehler liefern, wenn kein lokaler Client */
421         if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
422         
423         if(( Client_Type( Client ) == CLIENT_UNKNOWN ) && ( Req->argc == 1))
424         {
425                 /* noch nicht registrierte unbekannte Verbindung */
426                 Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client_Conn( Client ));
427
428                 /* Passwort speichern */
429                 Client_SetPassword( Client, Req->argv[0] );
430
431                 Client_SetType( Client, CLIENT_GOTPASS );
432                 return CONNECTED;
433         }
434         else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 )))
435         {
436                 /* noch nicht registrierte Server-Verbindung */
437                 Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client ));
438
439                 /* Passwort speichern */
440                 Client_SetPassword( Client, Req->argv[0] );
441
442                 Client_SetType( Client, CLIENT_GOTPASSSERVER );
443                 return CONNECTED;
444         }
445         else if(( Client_Type( Client ) == CLIENT_UNKNOWN  ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER ))
446         {
447                 /* Falsche Anzahl Parameter? */
448                 return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
449         }
450         else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
451 } /* IRC_PASS */
452
453
454 GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
455 {
456         CHAR str[LINE_LEN], *ptr;
457         CLIENT *from, *c, *cl;
458         CL2CHAN *cl2chan;
459         INT max_hops, i;
460         CHANNEL *chan;
461         BOOLEAN ok;
462         
463         assert( Client != NULL );
464         assert( Req != NULL );
465
466         /* Fehler liefern, wenn kein lokaler Client */
467         if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
468
469         if( Client_Type( Client ) == CLIENT_GOTPASSSERVER )
470         {
471                 /* Verbindung soll als Server-Server-Verbindung registriert werden */
472                 Log( LOG_DEBUG, "Connection %d: got SERVER command (new server link) ...", Client_Conn( Client ));
473
474                 /* Falsche Anzahl Parameter? */
475                 if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
476
477                 /* Ist dieser Server bei uns konfiguriert? */
478                 for( i = 0; i < Conf_Server_Count; i++ ) if( strcasecmp( Req->argv[0], Conf_Server[i].name ) == 0 ) break;
479                 if( i >= Conf_Server_Count )
480                 {
481                         /* Server ist nicht konfiguriert! */
482                         Log( LOG_ERR, "Connection %d: Server \"%s\" not configured here!", Client_Conn( Client ), Req->argv[0] );
483                         Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", TRUE );
484                         return DISCONNECTED;
485                 }
486                 if( strcmp( Client_Password( Client ), Conf_Server[i].pwd ) != 0 )
487                 {
488                         /* Falsches Passwort */
489                         Log( LOG_ERR, "Connection %d: Bad password for server \"%s\"!", Client_Conn( Client ), Req->argv[0] );
490                         Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE );
491                         return DISCONNECTED;
492                 }
493                 
494                 /* Ist ein Server mit dieser ID bereits registriert? */
495                 if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
496
497                 /* Server-Strukturen fuellen ;-) */
498                 Client_SetID( Client, Req->argv[0] );
499                 Client_SetHops( Client, 1 );
500                 Client_SetInfo( Client, Req->argv[Req->argc - 1] );
501                 
502                 /* Meldet sich der Server bei uns an? */
503                 if( Req->argc == 2 )
504                 {
505                         /* Unseren SERVER- und PASS-Befehl senden */
506                         ok = TRUE;
507                         if( ! IRC_WriteStrClient( Client, "PASS %s "PASSSERVERADD, Conf_Server[i].pwd )) ok = FALSE;
508                         else ok = IRC_WriteStrClient( Client, "SERVER %s 1 :%s", Conf_ServerName, Conf_ServerInfo );
509                         if( ! ok )
510                         {
511                                 Conn_Close( Client_Conn( Client ), "Unexpected server behavior!", NULL, FALSE );
512                                 return DISCONNECTED;
513                         }
514                         Client_SetIntroducer( Client, Client );
515                         Client_SetToken( Client, 1 );
516                 }
517                 else  Client_SetToken( Client, atoi( Req->argv[1] ));
518
519                 Log( LOG_NOTICE, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), Client_Conn( Client ));
520
521                 Client_SetType( Client, CLIENT_SERVER );
522
523                 /* maximalen Hop Count ermitteln */
524                 max_hops = 0;
525                 c = Client_First( );
526                 while( c )
527                 {
528                         if( Client_Hops( c ) > max_hops ) max_hops = Client_Hops( c );
529                         c = Client_Next( c );
530                 }
531                 
532                 /* Alle bisherigen Server dem neuen Server bekannt machen,
533                  * die bisherigen Server ueber den neuen informierenn */
534                 for( i = 0; i < ( max_hops + 1 ); i++ )
535                 {
536                         c = Client_First( );
537                         while( c )
538                         {
539                                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )) && ( Client_Hops( c ) == i ))
540                                 {
541                                         if( Client_Conn( c ) > NONE )
542                                         {
543                                                 /* Dem gefundenen Server gleich den neuen
544                                                 * Server bekannt machen */
545                                                 if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED;
546                                         }
547                                         
548                                         /* Den neuen Server ueber den alten informieren */
549                                         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;
550                                 }
551                                 c = Client_Next( c );
552                         }
553                 }
554
555                 /* alle User dem neuen Server bekannt machen */
556                 c = Client_First( );
557                 while( c )
558                 {
559                         if( Client_Type( c ) == CLIENT_USER )
560                         {
561                                 /* User an neuen Server melden */
562                                 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;
563                         }
564                         c = Client_Next( c );
565                 }
566
567                 /* Channels dem neuen Server bekannt machen */
568                 chan = Channel_First( );
569                 while( chan )
570                 {
571                         sprintf( str, "NJOIN %s :", Channel_Name( chan ));
572
573                         /* alle Member suchen */
574                         cl2chan = Channel_FirstMember( chan );
575                         while( cl2chan )
576                         {
577                                 cl = Channel_GetClient( cl2chan );
578                                 assert( cl != NULL );
579
580                                 /* Nick, ggf. mit Modes, anhaengen */
581                                 if( str[strlen( str ) - 1] != ':' ) strcat( str, "," );
582                                 if( strchr( Channel_UserModes( chan, cl ), 'v' )) strcat( str, "+" );
583                                 if( strchr( Channel_UserModes( chan, cl ), 'o' )) strcat( str, "@" );
584                                 strcat( str, Client_ID( cl ));
585
586                                 if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
587                                 {
588                                         /* Zeile senden */
589                                         if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
590                                         sprintf( str, "NJOIN %s :", Channel_Name( chan ));
591                                 }
592                                 
593                                 cl2chan = Channel_NextMember( chan, cl2chan );
594                         }
595
596                         /* noch Daten da? */
597                         if( str[strlen( str ) - 1] != ':')
598                         {
599                                 /* Ja; Also senden ... */
600                                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
601                         }
602
603                         /* naechsten Channel suchen */
604                         chan = Channel_Next( chan );
605                 }
606                 
607                 return CONNECTED;
608         }
609         else if( Client_Type( Client ) == CLIENT_SERVER )
610         {
611                 /* Neuer Server wird im Netz angekuendigt */
612
613                 /* Falsche Anzahl Parameter? */
614                 if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
615
616                 /* Ist ein Server mit dieser ID bereits registriert? */
617                 if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
618
619                 /* Ueberfluessige Hostnamen aus Info-Text entfernen */
620                 ptr = strchr( Req->argv[3] + 2, '[' );
621                 if( ! ptr ) ptr = Req->argv[3];
622
623                 from = Client_GetFromID( Req->prefix );
624                 if( ! from )
625                 {
626                         /* Hm, Server, der diesen einfuehrt, ist nicht bekannt!? */
627                         Log( LOG_ALERT, "Unknown ID in prefix of SERVER: \"%s\"! (on connection %d)", Req->prefix, Client_Conn( Client ));
628                         Conn_Close( Client_Conn( Client ), NULL, "Unknown ID in prefix of SERVER", TRUE );
629                         return DISCONNECTED;
630                 }
631
632                 /* Neue Client-Struktur anlegen */
633                 c = Client_NewRemoteServer( Client, Req->argv[0], from, atoi( Req->argv[1] ), atoi( Req->argv[2] ), ptr, TRUE );
634                 if( ! c )
635                 {
636                         /* Neue Client-Struktur konnte nicht angelegt werden */
637                         Log( LOG_ALERT, "Can't create client structure for server! (on connection %d)", Client_Conn( Client ));
638                         Conn_Close( Client_Conn( Client ), NULL, "Can't allocate client structure for remote server", TRUE );
639                         return DISCONNECTED;
640                 }
641
642                 /* Log-Meldung zusammenbauen und ausgeben */
643                 if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) sprintf( str, "connected to %s, ", Client_ID( from ));
644                 else strcpy( str, "" );
645                 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": "" );
646
647                 /* Andere Server informieren */
648                 IRC_WriteStrServersPrefix( Client, from, "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ));
649
650                 return CONNECTED;
651         }
652         else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
653 } /* IRC_SERVER */
654
655
656 GLOBAL BOOLEAN IRC_NJOIN( CLIENT *Client, REQUEST *Req )
657 {
658         BOOLEAN is_op, is_voiced;
659         CHAR *channame, *ptr;
660         CHANNEL *chan;
661         CLIENT *c;
662         
663         assert( Client != NULL );
664         assert( Req != NULL );
665
666         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTEREDSERVER_MSG, Client_ID( Client ));
667
668         /* Falsche Anzahl Parameter? */
669         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
670
671         channame = Req->argv[0];
672         ptr = strtok( Req->argv[1], "," );
673         while( ptr )
674         {
675                 is_op = is_voiced = FALSE;
676                 
677                 /* Prefixe abschneiden */
678                 while(( *ptr == '@' ) || ( *ptr == '+' ))
679                 {
680                         if( *ptr == '@' ) is_op = TRUE;
681                         if( *ptr == '+' ) is_voiced = TRUE;
682                         ptr++;
683                 }
684
685                 c = Client_GetFromID( ptr );
686                 if( c )
687                 {
688                         Channel_Join( c, channame );
689                         chan = Channel_Search( channame );
690                         assert( chan != NULL );
691                         
692                         if( is_op ) Channel_UserModeAdd( chan, c, 'o' );
693                         if( is_voiced ) Channel_UserModeAdd( chan, c, 'v' );
694                 }
695                 else Log( LOG_ERR, "Got NJOIN for unknown nick \"%s\" for channel \"%s\"!", ptr, channame );
696                 
697                 /* naechsten Nick suchen */
698                 ptr = strtok( NULL, "," );
699         }
700
701         /* an andere Server weiterleiten */
702         IRC_WriteStrServersPrefix( Client, Client_ThisServer( ), "NJOIN %s :%s", Req->argv[0], Req->argv[1] );
703
704         return CONNECTED;
705 } /* IRC_NJOIN */
706
707
708 GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
709 {
710         CLIENT *intr_c, *target, *c;
711         CHAR *modes;
712
713         assert( Client != NULL );
714         assert( Req != NULL );
715
716         /* Zumindest BitchX sendet NICK-USER in der falschen Reihenfolge. */
717 #ifndef STRICT_RFC
718         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 ))
719 #else
720         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 ))
721 #endif
722         {
723                 /* User-Registrierung bzw. Nick-Aenderung */
724
725                 /* Falsche Anzahl Parameter? */
726                 if( Req->argc != 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
727
728                 /* "Ziel-Client" ermitteln */
729                 if( Client_Type( Client ) == CLIENT_SERVER )
730                 {
731                         target = Client_GetFromID( Req->prefix );
732                         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
733                 }
734                 else
735                 {
736                         /* Ist der Client "restricted"? */
737                         if( Client_HasMode( Client, 'r' )) return IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
738                         target = Client;
739                 }
740
741                 /* Wenn der Client zu seinem eigenen Nick wechseln will, so machen
742                  * wir nichts. So macht es das Original und mind. Snak hat probleme,
743                  * wenn wir es nicht so machen. Ob es so okay ist? Hm ... */
744 #ifndef STRICT_RFC
745                 if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 ) return CONNECTED;
746 #endif
747                 
748                 /* pruefen, ob Nick bereits vergeben. Speziallfall: der Client
749                  * will nur die Gross- und Kleinschreibung aendern. Das darf
750                  * er natuerlich machen :-) */
751                 if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
752                 {
753                         if( ! Client_CheckNick( target, Req->argv[0] )) return CONNECTED;
754                 }
755
756                 if( Client_Type( Client ) == CLIENT_USER )
757                 {
758                         /* Nick-Aenderung: allen mitteilen! */
759                         Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
760                         IRC_WriteStrClient( Client, "NICK :%s", Req->argv[0] );
761                         IRC_WriteStrServersPrefix( NULL, Client, "NICK :%s", Req->argv[0] );
762                 }
763                 else if( Client_Type( Client ) == CLIENT_SERVER )
764                 {
765                         /* Nick-Aenderung: allen mitteilen! */
766                         Log( LOG_DEBUG, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
767                         IRC_WriteStrServersPrefix( Client, target, "NICK :%s", Req->argv[0] );
768                 }
769         
770                 /* Client-Nick registrieren */
771                 Client_SetID( target, Req->argv[0] );
772
773                 if(( Client_Type( target ) != CLIENT_USER ) && ( Client_Type( target ) != CLIENT_SERVER ))
774                 {
775                         /* Neuer Client */
776                         Log( LOG_DEBUG, "Connection %d: got NICK command ...", Client_Conn( Client ));
777                         if( Client_Type( Client ) == CLIENT_GOTUSER ) return Hello_User( Client );
778                         else Client_SetType( Client, CLIENT_GOTNICK );
779                 }
780                 return CONNECTED;
781         }
782         else if( Client_Type( Client ) == CLIENT_SERVER )
783         {
784                 /* Server fuehrt neuen Client ein */
785
786                 /* Falsche Anzahl Parameter? */
787                 if( Req->argc != 7 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
788
789                 /* Nick ueberpruefen */
790                 c = Client_GetFromID( Req->argv[0] );
791                 if( c )
792                 {
793                         /* Der neue Nick ist auf diesem Server bereits registriert:
794                          * sowohl der neue, als auch der alte Client muessen nun
795                          * disconnectiert werden. */
796                         Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
797                         Kill_Nick( Req->argv[0] );
798                         return CONNECTED;
799                 }
800
801                 /* Server, zu dem der Client connectiert ist, suchen */
802                 intr_c = Client_GetFromToken( Client, atoi( Req->argv[4] ));
803                 if( ! intr_c )
804                 {
805                         Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
806                         Kill_Nick( Req->argv[0] );
807                         return CONNECTED;
808                 }
809
810                 /* Neue Client-Struktur anlegen */
811                 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 );
812                 if( ! c )
813                 {
814                         /* Eine neue Client-Struktur konnte nicht angelegt werden.
815                          * Der Client muss disconnectiert werden, damit der Netz-
816                          * status konsistent bleibt. */
817                         Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
818                         Kill_Nick( Req->argv[0] );
819                         return CONNECTED;
820                 }
821
822                 modes = Client_Modes( c );
823                 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": "" );
824                 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": "" );
825
826                 /* Andere Server, ausser dem Introducer, informieren */
827                 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] );
828
829                 return CONNECTED;
830         }
831         else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
832 } /* IRC_NICK */
833
834
835 GLOBAL BOOLEAN IRC_USER( CLIENT *Client, REQUEST *Req )
836 {
837         assert( Client != NULL );
838         assert( Req != NULL );
839
840 #ifndef STRICT_RFC
841         if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_UNKNOWN )
842 #else
843         if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS )
844 #endif
845         {
846                 /* Falsche Anzahl Parameter? */
847                 if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
848
849                 Client_SetUser( Client, Req->argv[0], FALSE );
850                 Client_SetInfo( Client, Req->argv[3] );
851
852                 Log( LOG_DEBUG, "Connection %d: got USER command ...", Client_Conn( Client ));
853                 if( Client_Type( Client ) == CLIENT_GOTNICK ) return Hello_User( Client );
854                 else Client_SetType( Client, CLIENT_GOTUSER );
855                 return CONNECTED;
856         }
857         else if( Client_Type( Client ) == CLIENT_USER || Client_Type( Client ) == CLIENT_SERVER || Client_Type( Client ) == CLIENT_SERVICE )
858         {
859                 return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
860         }
861         else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
862 } /* IRC_USER */
863
864
865 GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req )
866 {
867         CLIENT *target;
868         
869         assert( Client != NULL );
870         assert( Req != NULL );
871
872         if(( Client_Type( Client ) == CLIENT_USER ) || ( Client_Type( Client ) == CLIENT_SERVICE ))
873         {
874                 /* User / Service */
875                 
876                 /* Falsche Anzahl Parameter? */
877                 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
878
879                 if( Req->argc == 0 ) Conn_Close( Client_Conn( Client ), "Got QUIT command.", NULL, TRUE );
880                 else Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argv[0], TRUE );
881                 
882                 return DISCONNECTED;
883         }
884         else if ( Client_Type( Client ) == CLIENT_SERVER )
885         {
886                 /* Server */
887
888                 /* Falsche Anzahl Parameter? */
889                 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
890
891                 target = Client_Search( Req->prefix );
892                 if( ! target )
893                 {
894                         Log( LOG_ERR, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
895                         return CONNECTED;
896                 }
897
898                 if( Req->argc == 0 ) Client_Destroy( target, "Got QUIT command.", NULL );
899                 else Client_Destroy( target, "Got QUIT command.", Req->argv[0] );
900
901                 return CONNECTED;
902         }
903         else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
904 } /* IRC_QUIT */
905
906
907 GLOBAL BOOLEAN IRC_SQUIT( CLIENT *Client, REQUEST *Req )
908 {
909         CLIENT *target;
910         
911         assert( Client != NULL );
912         assert( Req != NULL );
913
914         /* SQUIT ist nur fuer Server erlaubt */
915         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
916
917         /* Falsche Anzahl Parameter? */
918         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
919
920         target = Client_GetFromID( Req->argv[0] );
921         if( ! target )
922         {
923                 Log( LOG_ERR, "Got SQUIT from %s for unknown server \%s\"!?", Client_ID( Client ), Req->argv[0] );
924                 return CONNECTED;
925         }
926
927         if( target == Client ) Log( LOG_DEBUG, "Got SQUIT from %s: %s", Client_ID( Client ), Req->argv[1] );
928         else Log( LOG_DEBUG, "Got SQUIT from %s for %s: %s", Client_ID( Client ), Client_ID( target ), Req->argv[1] );
929
930         /* SQUIT an alle Server weiterleiten */
931         IRC_WriteStrServers( Client, "SQUIT %s :%s", Req->argv[0], Req->argv[1] );
932
933         if( Client_Conn( target ) > NONE )
934         {
935                 if( Req->argv[1][0] ) Conn_Close( Client_Conn( target ), "Got SQUIT command.", Req->argv[1], TRUE );
936                 else Conn_Close( Client_Conn( target ), "Got SQUIT command.", NULL, TRUE );
937                 return DISCONNECTED;
938         }
939         else
940         {
941                 Client_Destroy( target, "Got SQUIT command.", Req->argv[1] );
942                 return CONNECTED;
943         }
944 } /* IRC_SQUIT */
945
946
947 GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
948 {
949         CLIENT *target, *from;
950         
951         assert( Client != NULL );
952         assert( Req != NULL );
953
954         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
955
956         /* Falsche Anzahl Parameter? */
957         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
958         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
959         
960         if( Req->argc == 2 )
961         {
962                 /* es wurde ein Ziel-Client angegeben */
963                 target = Client_GetFromID( Req->argv[1] );
964                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
965                 if( target != Client_ThisServer( ))
966                 {
967                         /* ok, forwarden */
968                         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
969                         else from = Client;
970                         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
971                         return IRC_WriteStrClientPrefix( Client_NextHop( target ), from, "PING %s :%s", Client_ID( from ), Req->argv[1] );
972                 }
973         }
974
975         Log( LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Client_Conn( Client ));
976         return IRC_WriteStrClient( Client, "PONG %s :%s", Client_ID( Client_ThisServer( )), Client_ID( Client ));
977 } /* IRC_PING */
978
979
980 GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req )
981 {
982         CLIENT *target, *from;
983
984         assert( Client != NULL );
985         assert( Req != NULL );
986
987         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
988
989         /* Falsche Anzahl Parameter? */
990         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
991         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
992
993         /* forwarden? */
994         if( Req->argc == 2 )
995         {
996                 target = Client_GetFromID( Req->argv[1] );
997                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
998                 if( target != Client_ThisServer( ))
999                 {
1000                         /* ok, forwarden */
1001                         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1002                         else from = Client;
1003                         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
1004                         return IRC_WriteStrClientPrefix( Client_NextHop( target ), from, "PONG %s :%s", Client_ID( from ), Req->argv[1] );
1005                 }
1006         }
1007
1008         /* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
1009          * aktualisiert, daher muss das hier nicht mehr gemacht werden. */
1010
1011         if( Client_Conn( Client ) > NONE ) Log( LOG_DEBUG, "Connection %d: received PONG. Lag: %d seconds.", Client_Conn( Client ), time( NULL ) - Conn_LastPing( Client_Conn( Client )));
1012         else Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
1013
1014         return CONNECTED;
1015 } /* IRC_PONG */
1016
1017
1018 GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req )
1019 {
1020         assert( Client != NULL );
1021         assert( Req != NULL );
1022
1023         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1024
1025         /* Falsche Anzahl Parameter? */
1026         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1027
1028         return Show_MOTD( Client );
1029 } /* IRC_MOTD */
1030
1031
1032 GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
1033 {
1034         CLIENT *to, *from;
1035         CHANNEL *chan;
1036         
1037         assert( Client != NULL );
1038         assert( Req != NULL );
1039
1040         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1041
1042         /* Falsche Anzahl Parameter? */
1043         if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
1044         if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client ));
1045         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1046
1047         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1048         else from = Client;
1049         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1050
1051         to = Client_Search( Req->argv[0] );
1052         if( to )
1053         {
1054                 /* Okay, Ziel ist ein User */
1055                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
1056                 return IRC_WriteStrClientPrefix( to, from, "PRIVMSG %s :%s", Client_ID( to ), Req->argv[1] );
1057         }
1058
1059         chan = Channel_Search( Req->argv[0] );
1060         if( chan )
1061         {
1062                 /* Okay, Ziel ist ein Channel */
1063                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
1064                 return IRC_WriteStrChannelPrefix( Client, chan, from, TRUE, "PRIVMSG %s :%s", Req->argv[0], Req->argv[1] );
1065         }
1066
1067         return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
1068 } /* IRC_PRIVMSG */
1069
1070
1071 GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req )
1072 {
1073         CLIENT *to, *from;
1074
1075         assert( Client != NULL );
1076         assert( Req != NULL );
1077
1078         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1079
1080         /* Falsche Anzahl Parameter? */
1081         if( Req->argc != 2 ) return CONNECTED;
1082
1083         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1084         else from = Client;
1085         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1086
1087         to = Client_Search( Req->argv[0] );
1088         if( to )
1089         {
1090                 /* Okay, Ziel ist ein User */
1091                 return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] );
1092         }
1093         else return CONNECTED;
1094 } /* IRC_NOTICE */
1095
1096
1097 GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
1098 {
1099         CHAR *mode_ptr, the_modes[CLIENT_MODE_LEN], x[2];
1100         CLIENT *cl, *chan_cl, *prefix;
1101         BOOLEAN set, ok;
1102         CHANNEL *chan;
1103         
1104         assert( Client != NULL );
1105         assert( Req != NULL );
1106
1107         cl = chan_cl = prefix = NULL;
1108         chan = NULL;
1109
1110         /* Valider Client? */
1111         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1112
1113         /* Keine Parameter? */
1114         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1115
1116         /* Ziel suchen: Client bzw. Channel */
1117         if( Client_IsValidNick( Req->argv[0] )) cl = Client_Search( Req->argv[0] );
1118         if( Channel_IsValidName( Req->argv[0] )) chan = Channel_Search( Req->argv[0] );
1119
1120         /* Kein Ziel gefunden? */
1121         if(( ! cl ) && ( ! chan )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
1122
1123         assert(( cl && chan ) != TRUE );
1124
1125         /* Falsche Anzahl Parameter? */
1126         if(( cl ) && ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1127         if(( chan ) && ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1128
1129         /* Client ermitteln, wenn bei Channel-Modes mit 3 Parametern */
1130         if(( chan ) && (Req->argc == 3 ))
1131         {
1132                 chan_cl = Client_Search( Req->argv[2] );
1133                 if( ! chan_cl ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
1134         }
1135         
1136         /* Wenn Anfragender ein User ist: Zugriff erlaubt? */
1137         if( Client_Type( Client ) == CLIENT_USER )
1138         {
1139                 if( cl )
1140                 {
1141                         /* MODE ist nur fuer sich selber zulaessig! */
1142                         if( cl != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
1143                 }
1144                 if( chan )
1145                 {
1146                         /* Darf der User die Channel-Modes ermitteln? */
1147                 }
1148         }
1149
1150         /* Werden die Modes "nur" erfragt? */
1151         if(( cl ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( cl ));
1152         if(( chan ) && ( Req->argc == 1 )) return IRC_WriteStrClient( Client, RPL_CHANNELMODEIS_MSG, Client_ID( Client ), Channel_Name( chan ), Channel_Modes( chan ));
1153
1154         mode_ptr = Req->argv[1];
1155
1156         /* Sollen Modes gesetzt oder geloescht werden? */
1157         if( cl )
1158         {
1159                 if( *mode_ptr == '+' ) set = TRUE;
1160                 else if( *mode_ptr == '-' ) set = FALSE;
1161                 else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1162                 mode_ptr++;
1163         }
1164         else
1165         {
1166                 if( *mode_ptr == '-' ) set = FALSE;
1167                 else set = TRUE;
1168                 if(( *mode_ptr == '-' ) || ( *mode_ptr == '+' )) mode_ptr++;
1169         }
1170         
1171         /* Prefix fuer Antworten etc. ermitteln */
1172         if( Client_Type( Client ) == CLIENT_SERVER )
1173         {
1174                 prefix = Client_GetFromID( Req->prefix );
1175                 if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1176         }
1177         else prefix = Client;
1178
1179         /* Reply-String mit Aenderungen vorbereiten */
1180         if( set ) strcpy( the_modes, "+" );
1181         else strcpy( the_modes, "-" );
1182
1183         ok = TRUE;
1184         x[1] = '\0';
1185         while( *mode_ptr )
1186         {
1187                 x[0] = '\0';
1188                 if( Client_Type( Client ) == CLIENT_SERVER )
1189                 {
1190                         /* Befehl kommt von einem Server, daher
1191                          * trauen wir ihm "unbesehen" ... */
1192                         x[0] = *mode_ptr;
1193                 }
1194                 else
1195                 {
1196                         /* Modes validieren */
1197                         if( cl )
1198                         {
1199                                 /* User-Modes */
1200                                 switch( *mode_ptr )
1201                                 {
1202                                         case 'i':
1203                                                 /* invisible */
1204                                                 x[0] = 'i';
1205                                                 break;
1206                                         case 'r':
1207                                                 /* restricted (kann nur gesetzt werden) */
1208                                                 if( set ) x[0] = 'r';
1209                                                 else ok = IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
1210                                                 break;
1211                                         case 'o':
1212                                                 /* operator (kann nur geloescht werden) */
1213                                                 if( ! set )
1214                                                 {
1215                                                         Client_SetOperByMe( Client, FALSE );
1216                                                         x[0] = 'o';
1217                                                 }
1218                                                 else ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1219                                                 break;
1220                                         default:
1221                                                 Log( LOG_DEBUG, "Unknown mode \"%c%c\" from \"%s\"!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ));
1222                                                 ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1223                                                 x[0] = '\0';
1224                                 }
1225                         }
1226                         if( chan )
1227                         {
1228                                 /* Ist der User ein Channel Operator? */
1229                                 if( ! strchr( Channel_UserModes( chan, Client ), 'o' ))
1230                                 {
1231                                         Log( LOG_DEBUG, "Can't change modes: \"%s\" is not operator on %s!", Client_ID( Client ), Channel_Name( chan ));
1232                                         ok = IRC_WriteStrClient( Client, ERR_CHANOPRIVSNEEDED_MSG, Client_ID( Client ), Channel_Name( chan ));
1233                                         break;
1234                                 }
1235                                 
1236                                 /* Channel-Modes oder Channel-User-Modes */
1237                                 if( chan_cl )
1238                                 {
1239                                         /* Channel-User-Modes */
1240                                         switch( *mode_ptr )
1241                                         {
1242                                                 default:
1243                                                         Log( LOG_DEBUG, "Unknown channel-user-mode \"%c%c\" from \"%s\" on \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Client_ID( chan_cl ), Channel_Name( chan ));
1244                                                         ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1245                                                         x[0] = '\0';
1246                                         }
1247                                 }
1248                                 else
1249                                 {
1250                                         /* Channel-Modes */
1251                                         switch( *mode_ptr )
1252                                         {
1253                                                 default:
1254                                                         Log( LOG_DEBUG, "Unknown channel-mode \"%c%c\" from \"%s\" at %s!?", set ? '+' : '-', *mode_ptr, Client_ID( Client ), Channel_Name( chan ));
1255                                                         ok = IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
1256                                                         x[0] = '\0';
1257                                         }
1258                                 }
1259                         }
1260                 }
1261                 if( ! ok ) break;
1262                 
1263                 mode_ptr++;
1264                 if( ! x[0] ) continue;
1265
1266                 /* Okay, gueltigen Mode gefunden */
1267                 if( cl )
1268                 {
1269                         /* Es geht um User-Modes */
1270                         if( set )
1271                         {
1272                                 /* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
1273                                 if( Client_ModeAdd( cl, x[0] )) strcat( the_modes, x );
1274                         }
1275                         else
1276                         {
1277                                 /* Modes geloescht. Wenn der Client ihn hatte: merken */
1278                                 if( Client_ModeDel( cl, x[0] )) strcat( the_modes, x );
1279                         }
1280                 }
1281                 if( chan )
1282                 {
1283                         /* Es geht um Channel-Modes oder Channel-User-Modes */
1284                         if( chan_cl )
1285                         {
1286                                 /* Channel-User-Modes */
1287                                 if( set )
1288                                 {
1289                                         /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
1290                                         if( Channel_UserModeAdd( chan, chan_cl, x[0] )) strcat( the_modes, x );
1291                                 }
1292                                 else
1293                                 {
1294                                         /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
1295                                         if( Channel_UserModeDel( chan, chan_cl, x[0] )) strcat( the_modes, x );
1296                                 }
1297                         }
1298                         else
1299                         {
1300                                 /* Channel-Mode */
1301                                 if( set )
1302                                 {
1303                                         /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
1304                                         if( Channel_ModeAdd( chan, x[0] )) strcat( the_modes, x );
1305                                 }
1306                                 else
1307                                 {
1308                                         /* Mode setzen. Wenn der Channel ihn noch nicht hatte: merken */
1309                                         if( Channel_ModeDel( chan, x[0] )) strcat( the_modes, x );
1310                                 }
1311                         }
1312                 }
1313         }
1314
1315         /* Wurden Modes geaendert? */
1316         if( the_modes[1] )
1317         {
1318                 if( cl )
1319                 {
1320                         /* Client-Mode */
1321                         if( Client_Type( Client ) == CLIENT_SERVER )
1322                         {
1323                                 /* Modes an andere Server forwarden */
1324                                 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
1325                         }
1326                         else
1327                         {
1328                                 /* Bestaetigung an Client schicken & andere Server informieren */
1329                                 ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Client_ID( cl ), the_modes );
1330                                 IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Client_ID( cl ), the_modes );
1331                         }
1332                         Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( cl ), Client_Modes( cl ));
1333                 }
1334                 if( chan )
1335                 {
1336                         /* Channel-Modes oder Channel-User-Mode */
1337                         if( chan_cl )
1338                         {
1339                                 /* Channel-User-Mode */
1340                                 if( Client_Type( Client ) == CLIENT_SERVER )
1341                                 {
1342                                         /* Modes an andere Server und Channel-User forwarden */
1343                                         IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1344                                         IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1345                                 }
1346                                 else
1347                                 {
1348                                         /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
1349                                         ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1350                                         IRC_WriteStrServersPrefix( Client, prefix, "MODE %s %s :%s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1351                                         IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s %s", Channel_Name( chan ), the_modes, Client_ID( chan_cl));
1352                                 }
1353                                 Log( LOG_DEBUG, "User \"%s\" on %s: Mode change, now \"%s\".", Client_Mask( chan_cl), Channel_Name( chan ), Channel_UserModes( chan, chan_cl ));
1354                         }
1355                         else
1356                         {
1357                                 /* Channel-Mode */
1358                                 if( Client_Type( Client ) == CLIENT_SERVER )
1359                                 {
1360                                         /* Modes an andere Server und Channel-User forwarden */
1361                                         IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
1362                                         IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
1363                                 }
1364                                 else
1365                                 {
1366                                         /* Bestaetigung an Client schicken & andere Server sowie Channel-User informieren */
1367                                         ok = IRC_WriteStrClientPrefix( Client, prefix, "MODE %s %s", Channel_Name( chan ), the_modes );
1368                                         IRC_WriteStrServersPrefix( Client, prefix, "MODE %s :%s", Channel_Name( chan ), the_modes );
1369                                         IRC_WriteStrChannelPrefix( Client, chan, prefix, FALSE, "MODE %s %s", Channel_Name( chan ), the_modes );
1370                                 }
1371                                 Log( LOG_DEBUG, "Channel \"%s\": Mode change, now \"%s\".", Channel_Name( chan ), Channel_Modes( chan ));
1372                         }
1373                 }
1374         }
1375
1376         return ok;
1377 } /* IRC_MODE */
1378
1379
1380 GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req )
1381 {
1382         INT i;
1383         
1384         assert( Client != NULL );
1385         assert( Req != NULL );
1386
1387         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1388         
1389         /* Falsche Anzahl Parameter? */
1390         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1391
1392         /* Operator suchen */
1393         for( i = 0; i < Conf_Oper_Count; i++)
1394         {
1395                 if( Conf_Oper[i].name[0] && Conf_Oper[i].pwd[0] && ( strcmp( Conf_Oper[i].name, Req->argv[0] ) == 0 )) break;
1396         }
1397         if( i >= Conf_Oper_Count )
1398         {
1399                 Log( LOG_WARNING, "Got invalid OPER from \"%s\": Name \"%s\" not configured!", Client_Mask( Client ), Req->argv[0] );
1400                 return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
1401         }
1402
1403         /* Stimmt das Passwort? */
1404         if( strcmp( Conf_Oper[i].pwd, Req->argv[1] ) != 0 )
1405         {
1406                 Log( LOG_WARNING, "Got invalid OPER from \"%s\": Bad password for \"%s\"!", Client_Mask( Client ), Conf_Oper[i].name );
1407                 return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
1408         }
1409         
1410         if( ! Client_HasMode( Client, 'o' ))
1411         {
1412                 /* noch kein o-Mode gesetzt */
1413                 Client_ModeAdd( Client, 'o' );
1414                 if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
1415                 IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
1416         }
1417
1418         if( ! Client_OperByMe( Client )) Log( LOG_NOTICE, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
1419
1420         Client_SetOperByMe( Client, TRUE );
1421         return IRC_WriteStrClient( Client, RPL_YOUREOPER_MSG, Client_ID( Client ));
1422 } /* IRC_OPER */
1423
1424
1425 GLOBAL BOOLEAN IRC_DIE( CLIENT *Client, REQUEST *Req )
1426 {
1427         assert( Client != NULL );
1428         assert( Req != NULL );
1429
1430         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1431
1432         /* Falsche Anzahl Parameter? */
1433         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1434
1435         if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
1436
1437         Log( LOG_NOTICE, "Got DIE command from \"%s\", going down!", Client_Mask( Client ));
1438         NGIRCd_Quit = TRUE;
1439         return CONNECTED;
1440 } /* IRC_DIE */
1441
1442
1443 GLOBAL BOOLEAN IRC_RESTART( CLIENT *Client, REQUEST *Req )
1444 {
1445         assert( Client != NULL );
1446         assert( Req != NULL );
1447
1448         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1449
1450         /* Falsche Anzahl Parameter? */
1451         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1452
1453         if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
1454
1455         Log( LOG_NOTICE, "Got RESTART command from \"%s\", going down!", Client_Mask( Client ));
1456         NGIRCd_Restart = TRUE;
1457         return CONNECTED;
1458 } /* IRC_RESTART */
1459
1460
1461 GLOBAL BOOLEAN IRC_NAMES( CLIENT *Client, REQUEST *Req )
1462 {
1463         CHAR rpl[COMMAND_LEN];
1464         CLIENT *c;
1465         
1466         assert( Client != NULL );
1467         assert( Req != NULL );
1468
1469         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1470
1471         /* Falsche Anzahl Parameter? */
1472         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1473
1474         /* Noch alle User ausgeben, die in keinem Channel sind */
1475         rpl[0] = '\0';
1476         c = Client_First( );
1477         while( c )
1478         {
1479                 if( Client_Type( c ) == CLIENT_USER )
1480                 {
1481                         /* Okay, das ist ein User */
1482                         strcat( rpl, Client_ID( c ));
1483                         strcat( rpl, " " );
1484                 }
1485
1486                 /* Antwort zu lang? Splitten. */
1487                 if( strlen( rpl ) > 480 )
1488                 {
1489                         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1490                         if( ! IRC_WriteStrClient( Client, RPL_NAMREPLY_MSG, Client_ID( Client ), "*", "*", rpl )) return DISCONNECTED;
1491                         rpl[0] = '\0';
1492                 }
1493                 
1494                 c = Client_Next( c );
1495         }
1496         if( rpl[0] )
1497         {
1498                 /* es wurden User gefunden */
1499                 if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1500                 if( ! IRC_WriteStrClient( Client, RPL_NAMREPLY_MSG, Client_ID( Client ), "*", "*", rpl )) return DISCONNECTED;
1501         }
1502         return IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), "*" );
1503 } /* IRC_NAMES */
1504
1505
1506 GLOBAL BOOLEAN IRC_ISON( CLIENT *Client, REQUEST *Req )
1507 {
1508         CHAR rpl[COMMAND_LEN];
1509         CLIENT *c;
1510         CHAR *ptr;
1511         INT i;
1512         
1513         assert( Client != NULL );
1514         assert( Req != NULL );
1515
1516         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1517
1518         /* Falsche Anzahl Parameter? */
1519         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1520
1521         strcpy( rpl, RPL_ISON_MSG );
1522         for( i = 0; i < Req->argc; i++ )
1523         {
1524                 ptr = strtok( Req->argv[i], " " );
1525                 while( ptr )
1526                 {
1527                         ngt_TrimStr( ptr );
1528                         c = Client_GetFromID( ptr );
1529                         if( c && ( Client_Type( c ) == CLIENT_USER ))
1530                         {
1531                                 /* Dieser Nick ist "online" */
1532                                 strcat( rpl, ptr );
1533                                 strcat( rpl, " " );
1534                         }
1535                         ptr = strtok( NULL, " " );
1536                 }
1537         }
1538         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1539
1540         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
1541 } /* IRC_ISON */
1542
1543
1544 GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
1545 {
1546         CLIENT *from, *target, *c;
1547         CHAR str[LINE_LEN + 1], *ptr = NULL;
1548         CL2CHAN *cl2chan;
1549         CHANNEL *chan;
1550         
1551         assert( Client != NULL );
1552         assert( Req != NULL );
1553
1554         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1555
1556         /* Falsche Anzahl Parameter? */
1557         if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1558
1559         /* Client suchen */
1560         c = Client_GetFromID( Req->argv[Req->argc - 1] );
1561         if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] );
1562
1563         /* Empfaenger des WHOIS suchen */
1564         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1565         else from = Client;
1566         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1567         
1568         /* Forwarden an anderen Server? */
1569         if( Req->argc > 1 )
1570         {
1571                 /* angegebenen Ziel-Server suchen */
1572                 target = Client_GetFromID( Req->argv[1] );
1573                 if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
1574                 ptr = Req->argv[1];
1575         }
1576 #ifndef STRICT_RFC
1577         else if( Client_Conn( c ) == NONE )
1578         {
1579                 /* Client ist nicht von uns. Ziel-Server suchen */
1580                 target = c;
1581                 ptr = Req->argv[0];
1582         }
1583 #endif
1584         else target = NULL;
1585         
1586         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 );
1587         
1588         /* Nick, User und Name */
1589         if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
1590
1591         /* Server */
1592         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;
1593
1594         /* Channels */
1595         sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
1596         cl2chan = Channel_FirstChannelOf( c );
1597         while( cl2chan )
1598         {
1599                 chan = Channel_GetChannel( cl2chan );
1600                 assert( chan != NULL );
1601                 
1602                 /* Channel-Name anhaengen */
1603                 if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
1604                 if( strchr( Channel_UserModes( chan, c ), 'v' )) strcat( str, "+" );
1605                 if( strchr( Channel_UserModes( chan, c ), 'o' )) strcat( str, "@" );
1606                 strcat( str, Channel_Name( chan ));
1607
1608                 if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ))
1609                 {
1610                         /* Zeile wird zu lang: senden! */
1611                         if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
1612                         sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
1613                 }
1614
1615                 /* naechstes Mitglied suchen */
1616                 cl2chan = Channel_NextChannelOf( c, cl2chan );
1617         }
1618         if( str[strlen( str ) - 1] != ':')
1619         {
1620                 /* Es sind noch Daten da, die gesendet werden muessen */
1621                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
1622         }
1623         
1624         /* IRC-Operator? */
1625         if( Client_HasMode( c, 'o' ))
1626         {
1627                 if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
1628         }
1629
1630         /* Idle (nur lokale Clients) */
1631         if( Client_Conn( c ) > NONE )
1632         {
1633                 if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
1634         }
1635
1636         /* End of Whois */
1637         return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
1638 } /* IRC_WHOIS */
1639
1640
1641 GLOBAL BOOLEAN IRC_USERHOST( CLIENT *Client, REQUEST *Req )
1642 {
1643         CHAR rpl[COMMAND_LEN];
1644         CLIENT *c;
1645         INT max, i;
1646
1647         assert( Client != NULL );
1648         assert( Req != NULL );
1649
1650         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1651
1652         /* Falsche Anzahl Parameter? */
1653         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1654
1655         if( Req->argc > 5 ) max = 5;
1656         else max = Req->argc;
1657         
1658         strcpy( rpl, RPL_USERHOST_MSG );
1659         for( i = 0; i < max; i++ )
1660         {
1661                 c = Client_GetFromID( Req->argv[i] );
1662                 if( c && ( Client_Type( c ) == CLIENT_USER ))
1663                 {
1664                         /* Dieser Nick ist "online" */
1665                         strcat( rpl, Client_ID( c ));
1666                         if( Client_HasMode( c, 'o' )) strcat( rpl, "*" );
1667                         strcat( rpl, "=" );
1668                         if( Client_HasMode( c, 'a' )) strcat( rpl, "-" );
1669                         else strcat( rpl, "+" );
1670                         strcat( rpl, Client_User( c ));
1671                         strcat( rpl, "@" );
1672                         strcat( rpl, Client_Hostname( c ));
1673                         strcat( rpl, " " );
1674                 }
1675         }
1676         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1677
1678         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
1679 } /* IRC_USERHOST */
1680
1681
1682 GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req )
1683 {
1684         assert( Client != NULL );
1685         assert( Req != NULL );
1686
1687         if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client ));
1688         else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] );
1689
1690         return CONNECTED;
1691 } /* IRC_ERROR */
1692
1693
1694 GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
1695 {
1696         CLIENT *target, *from;
1697         INT cnt;
1698         
1699         assert( Client != NULL );
1700         assert( Req != NULL );
1701
1702         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1703
1704         /* Falsche Anzahl Parameter? */
1705         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1706
1707         /* Absender ermitteln */
1708         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1709         else from = Client;
1710         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1711
1712         /* An anderen Server forwarden? */
1713         if( Req->argc == 2 )
1714         {
1715                 target = Client_GetFromID( Req->argv[1] );
1716                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
1717                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LUSERS %s %s", Req->argv[0], Req->argv[1] );
1718         }
1719
1720         /* Wer ist der Absender? */
1721         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1722         else target = Client;
1723         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1724         
1725         /* Users, Services und Serevr im Netz */
1726         if( ! IRC_WriteStrClient( target, RPL_LUSERCLIENT_MSG, Client_ID( target ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
1727
1728         /* IRC-Operatoren im Netz */
1729         cnt = Client_OperCount( );
1730         if( cnt > 0 )
1731         {
1732                 if( ! IRC_WriteStrClient( target, RPL_LUSEROP_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
1733         }
1734
1735         /* Unbekannt Verbindungen */
1736         cnt = Client_UnknownCount( );
1737         if( cnt > 0 )
1738         {
1739                 if( ! IRC_WriteStrClient( target, RPL_LUSERUNKNOWN_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
1740         }
1741
1742         /* Channels im Netz */
1743         if( ! IRC_WriteStrClient( target, RPL_LUSERCHANNELS_MSG, Client_ID( target ), Channel_Count( ))) return DISCONNECTED;
1744
1745         /* Channels im Netz */
1746         if( ! IRC_WriteStrClient( target, RPL_LUSERME_MSG, Client_ID( target ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
1747
1748         return CONNECTED;
1749 } /* IRC_LUSERS */
1750
1751
1752 GLOBAL BOOLEAN IRC_LINKS( CLIENT *Client, REQUEST *Req )
1753 {
1754         CLIENT *target, *from, *c;
1755         CHAR *mask;
1756         
1757         assert( Client != NULL );
1758         assert( Req != NULL );
1759
1760         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1761
1762         /* Falsche Anzahl Parameter? */
1763         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1764
1765         /* Server-Mask ermitteln */
1766         if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
1767         else mask = "*";
1768
1769         /* Absender ermitteln */
1770         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1771         else from = Client;
1772         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1773         
1774         /* An anderen Server forwarden? */
1775         if( Req->argc == 2 )
1776         {
1777                 target = Client_GetFromID( Req->argv[0] );
1778                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
1779                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
1780         }
1781
1782         /* Wer ist der Absender? */
1783         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1784         else target = Client;
1785         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1786         
1787         c = Client_First( );
1788         while( c )
1789         {
1790                 if( Client_Type( c ) == CLIENT_SERVER )
1791                 {
1792                         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;
1793                 }
1794                 c = Client_Next( c );
1795         }
1796         
1797         return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
1798 } /* IRC_LINKS */
1799
1800
1801 GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req )
1802 {
1803         CHAR *channame, *flags, modes[8];
1804         BOOLEAN is_new_chan;
1805         CLIENT *target;
1806         CHANNEL *chan;
1807         
1808         assert( Client != NULL );
1809         assert( Req != NULL );
1810
1811         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1812
1813         /* Falsche Anzahl Parameter? */
1814         if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1815
1816         /* Wer ist der Absender? */
1817         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1818         else target = Client;
1819         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1820         
1821         /* Channel-Namen durchgehen */
1822         channame = strtok( Req->argv[0], "," );
1823         while( channame )
1824         {
1825                 /* wird der Channel neu angelegt? */
1826                 flags = NULL;
1827
1828                 if( Channel_Search( channame )) is_new_chan = FALSE;
1829                 else is_new_chan = TRUE;
1830
1831                 /* Hat ein Server Channel-User-Modes uebergeben? */
1832                 if( Client_Type( Client ) == CLIENT_SERVER )
1833                 {
1834                         /* Channel-Flags extrahieren */
1835                         flags = strchr( channame, 0x7 );
1836                         if( flags ) *flags++ = '\0';
1837                 }
1838
1839                 /* neuer Channel udn lokaler Client? */
1840                 if( is_new_chan && ( Client_Type( Client ) == CLIENT_USER ))
1841                 {
1842                         /* Dann soll der Client Channel-Operator werden! */
1843                         flags = "o";
1844                 }
1845
1846                 /* Channel joinen (und ggf. anlegen) */
1847                 if( ! Channel_Join( target, channame ))
1848                 {
1849                         /* naechsten Namen ermitteln */
1850                         channame = strtok( NULL, "," );
1851                         continue;
1852                 }
1853                 chan = Channel_Search( channame );
1854                 assert( chan != NULL );
1855
1856                 /* Modes setzen (wenn vorhanden) */
1857                 while( flags && *flags )
1858                 {
1859                         Channel_UserModeAdd( chan, target, *flags );
1860                         flags++;
1861                 }
1862
1863                 /* Muessen Modes an andere Server gemeldet werden? */
1864                 strcpy( &modes[1], Channel_UserModes( chan, target ));
1865                 if( modes[1] ) modes[0] = 0x7;
1866                 else modes[0] = '\0';
1867
1868                 /* An andere Server weiterleiten */
1869                 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s%s", channame, modes );
1870
1871                 /* im Channel bekannt machen */
1872                 IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "JOIN :%s", channame );
1873                 if( modes[1] )
1874                 {
1875                         /* Modes im Channel bekannt machen */
1876                         IRC_WriteStrChannelPrefix( Client, chan, target, FALSE, "MODE %s %s :%s", channame, modes, Client_ID( target ));
1877                 }
1878
1879                 if( Client_Type( Client ) == CLIENT_USER )
1880                 {
1881                         /* an Client bestaetigen */
1882                         IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", channame );
1883                         /* Topic an Client schicken */
1884                         IRC_WriteStrClient( Client, RPL_TOPIC_MSG, Client_ID( Client ), channame, "What a wonderful channel!" );
1885                         /* Mitglieder an Client Melden */
1886                         Send_NAMES( Client, chan );
1887                 }
1888                 
1889                 /* naechsten Namen ermitteln */
1890                 channame = strtok( NULL, "," );
1891         }
1892         return CONNECTED;
1893 } /* IRC_JOIN */
1894
1895
1896 GLOBAL BOOLEAN IRC_PART( CLIENT *Client, REQUEST *Req )
1897 {
1898         CLIENT *target;
1899         CHAR *chan;
1900
1901         assert( Client != NULL );
1902         assert( Req != NULL );
1903
1904         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1905
1906         /* Falsche Anzahl Parameter? */
1907         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1908
1909         /* Wer ist der Absender? */
1910         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1911         else target = Client;
1912         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1913
1914         /* Channel-Namen durchgehen */
1915         chan = strtok( Req->argv[0], "," );
1916         while( chan )
1917         {
1918                 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
1919                 {
1920                         /* naechsten Namen ermitteln */
1921                         chan = strtok( NULL, "," );
1922                         continue;
1923                 }
1924
1925                 /* naechsten Namen ermitteln */
1926                 chan = strtok( NULL, "," );
1927         }
1928         return CONNECTED;
1929 } /* IRC_PART */
1930
1931
1932 LOCAL BOOLEAN Hello_User( CLIENT *Client )
1933 {
1934         assert( Client != NULL );
1935
1936         /* Passwort ueberpruefen */
1937         if( strcmp( Client_Password( Client ), Conf_ServerPwd ) != 0 )
1938         {
1939                 /* Falsches Passwort */
1940                 Log( LOG_ERR, "User \"%s\" rejected (connection %d): Bad password!", Client_Mask( Client ), Client_Conn( Client ));
1941                 Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE );
1942                 return DISCONNECTED;
1943         }
1944
1945         Log( LOG_NOTICE, "User \"%s\" registered (connection %d).", Client_Mask( Client ), Client_Conn( Client ));
1946
1947         /* Andere Server informieren */
1948         IRC_WriteStrServers( NULL, "NICK %s 1 %s %s 1 +%s :%s", Client_ID( Client ), Client_User( Client ), Client_Hostname( Client ), Client_Modes( Client ), Client_Info( Client ));
1949
1950         if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return FALSE;
1951         if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE;
1952         if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return FALSE;
1953         if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE;
1954
1955         Client_SetType( Client, CLIENT_USER );
1956
1957         return Show_MOTD( Client );
1958 } /* Hello_User */
1959
1960
1961 LOCAL BOOLEAN Show_MOTD( CLIENT *Client )
1962 {
1963         BOOLEAN ok;
1964         CHAR line[127];
1965         FILE *fd;
1966         
1967         assert( Client != NULL );
1968
1969         fd = fopen( Conf_MotdFile, "r" );
1970         if( ! fd )
1971         {
1972                 Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno ));
1973                 return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
1974         }
1975         
1976         IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )));
1977         while( TRUE )
1978         {
1979                 if( ! fgets( line, 126, fd )) break;
1980                 if( line[strlen( line ) - 1] == '\n' ) line[strlen( line ) - 1] = '\0';
1981                 if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), line ))
1982                 {
1983                         fclose( fd );
1984                         return FALSE;
1985                 }
1986         }
1987         ok = IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ) );
1988
1989         fclose( fd );
1990         
1991         return ok;
1992 } /* Show_MOTD */
1993
1994
1995 LOCAL VOID Kill_Nick( CHAR *Nick )
1996 {
1997         Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected!", Nick );
1998         /* FIXME */
1999         Log( LOG_ALERT, "[Kill_Nick() not implemented - OOOPS!]" );
2000 } /* Kill_Nick */
2001
2002
2003 LOCAL BOOLEAN Send_NAMES( CLIENT *Client, CHANNEL *Chan )
2004 {
2005         CHAR str[LINE_LEN + 1];
2006         CL2CHAN *cl2chan;
2007         CLIENT *cl;
2008         
2009         assert( Client != NULL );
2010         assert( Chan != NULL );
2011
2012         /* Alle Mitglieder suchen */
2013         sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
2014         cl2chan = Channel_FirstMember( Chan );
2015         while( cl2chan )
2016         {
2017                 cl = Channel_GetClient( cl2chan );
2018
2019                 /* Nick anhaengen */
2020                 if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
2021                 if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strcat( str, "+" );
2022                 if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strcat( str, "@" );
2023                 strcat( str, Client_ID( cl ));
2024
2025                 if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
2026                 {
2027                         /* Zeile wird zu lang: senden! */
2028                         if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
2029                         sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
2030                 }
2031
2032                 /* naechstes Mitglied suchen */
2033                 cl2chan = Channel_NextMember( Chan, cl2chan );
2034         }
2035         if( str[strlen( str ) - 1] != ':')
2036         {
2037                 /* Es sind noch Daten da, die gesendet werden muessen */
2038                 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
2039         }
2040
2041         /* Ende anzeigen */
2042         IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), Channel_Name( Chan ));
2043         
2044         return CONNECTED;
2045 } /* Send_NAMES */
2046
2047
2048 /* -eof- */