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