]> arthur.barton.de Git - ngircd-alex.git/blob - src/ngircd/irc.c
- neue Funktionen IRC_WriteStrChannelPrefix() und IRC_WriteStrChannel(),
[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.40 2002/01/26 18:43:11 alex Exp $
13  *
14  * irc.c: IRC-Befehle
15  *
16  * $Log: irc.c,v $
17  * Revision 1.40  2002/01/26 18:43:11  alex
18  * - neue Funktionen IRC_WriteStrChannelPrefix() und IRC_WriteStrChannel(),
19  *   die IRC_Write_xxx_Related() sind dafuer entfallen.
20  * - IRC_PRIVMSG() kann nun auch mit Channels als Ziel umgehen.
21  *
22  * Revision 1.39  2002/01/21 00:05:11  alex
23  * - neue Funktionen IRC_JOIN und IRC_PART begonnen, ebenso die Funktionen
24  *   IRC_WriteStrRelatedPrefix und IRC_WriteStrRelatedChannelPrefix().
25  * - diverse Aenderungen im Zusammenhang mit Channels.
26  *
27  * Revision 1.38  2002/01/18 15:31:32  alex
28  * - die User-Modes bei einem NICK von einem Server wurden falsch uebernommen.
29  *
30  * Revision 1.37  2002/01/16 22:10:18  alex
31  * - IRC_LUSERS() implementiert.
32  *
33  * Revision 1.36  2002/01/11 23:50:55  alex
34  * - LINKS implementiert, LUSERS begonnen.
35  *
36  * Revision 1.35  2002/01/09 21:30:45  alex
37  * - WHOIS wurde faelschlicherweise an User geforwarded statt vom Server beantwortet.
38  *
39  * Revision 1.34  2002/01/09 01:09:58  alex
40  * - WHOIS wird im "Strict-RFC-Mode" nicht mehr automatisch geforwarded,
41  * - andere Server werden nun ueber bisherige Server und User informiert.
42  *
43  * Revision 1.33  2002/01/07 23:42:12  alex
44  * - Es werden fuer alle Server eigene Token generiert,
45  * - QUIT von einem Server fuer einen User wird an andere Server geforwarded,
46  * - ebenso NICK-Befehle, die "fremde" User einfuehren.
47  *
48  * Revision 1.32  2002/01/07 16:02:36  alex
49  * - Loglevel von Remote-Mode-Aenderungen angepasst (nun Debug).
50  * - Im Debug-Mode werden nun auch PING's protokolliert.
51  *
52  * Revision 1.31  2002/01/07 15:39:46  alex
53  * - Server nimmt nun Server-Links an: PASS und SERVER entsprechend angepasst.
54  * - MODE und NICK melden nun die Aenderungen an andere Server.
55  *
56  * Revision 1.30  2002/01/06 15:21:29  alex
57  * - Loglevel und Meldungen nochmals ueberarbeitet.
58  * - QUIT und SQUIT forwarden nun den Grund der Trennung,
59  * - WHOIS wird nun immer an den "Original-Server" weitergeleitet.
60  *
61  * Revision 1.29  2002/01/05 23:24:54  alex
62  * - WHOIS erweitert: Anfragen koennen an andere Server weitergeleitet werden.
63  * - Vorbereitungen fuer Ident-Abfragen bei neuen Client-Strukturen.
64  *
65  * Revision 1.28  2002/01/05 20:08:02  alex
66  * - Div. Aenderungen fuer die Server-Links (u.a. WHOIS, QUIT, NICK angepasst).
67  * - Neue Funktionen IRC_WriteStrServer() und IRC_WriteStrServerPrefix().
68  *
69  * Revision 1.27  2002/01/05 19:15:03  alex
70  * - Fehlerpruefung bei select() in der "Hauptschleife" korrigiert.
71  *
72  * Revision 1.26  2002/01/05 16:51:18  alex
73  * - das Passwort von Servern wird nun ueberprueft (PASS- und SERVER-Befehl).
74  *
75  * Revision 1.25  2002/01/05 00:48:33  alex
76  * - bei SQUIT wurde immer die Verbindung getrennt, auch bei Remote-Servern.
77  *
78  * Revision 1.24  2002/01/04 17:58:44  alex
79  * - IRC_WriteStrXXX()-Funktionen eingefuehrt, groessere Anpassungen daran.
80  * - neuer Befehl SQUIT, QUIT an Server-Links angepasst.
81  *
82  * Revision 1.23  2002/01/04 01:36:40  alex
83  * - Loglevel ein wenig angepasst.
84  *
85  * Revision 1.22  2002/01/04 01:21:47  alex
86  * - Client-Strukruren werden nur noch ueber Funktionen angesprochen.
87  * - Weitere Anpassungen und Erweiterungen der Server-Links.
88  *
89  * Revision 1.21  2002/01/03 02:26:51  alex
90  * - neue Befehle SERVER und NJOIN begonnen,
91  * - begonnen, diverse IRC-Befehle an Server-Links anzupassen.
92  *
93  * Revision 1.20  2002/01/02 12:46:41  alex
94  * - die Gross- und Kleinschreibung des Nicks kann mit NICK nun geaendert werden.
95  *
96  * Revision 1.19  2002/01/02 02:51:39  alex
97  * - Copyright-Texte angepasst.
98  * - neuer Befehl "ERROR".
99  *
100  * Revision 1.17  2001/12/31 15:33:13  alex
101  * - neuer Befehl NAMES, kleinere Bugfixes.
102  * - Bug bei PING behoben: war zu restriktiv implementiert :-)
103  *
104  * Revision 1.16  2001/12/31 02:18:51  alex
105  * - viele neue Befehle (WHOIS, ISON, OPER, DIE, RESTART),
106  * - neuen Header "defines.h" mit (fast) allen Konstanten.
107  * - Code Cleanups und viele "kleine" Aenderungen & Bugfixes.
108  *
109  * Revision 1.15  2001/12/30 19:26:11  alex
110  * - Unterstuetzung fuer die Konfigurationsdatei eingebaut.
111  *
112  * Revision 1.14  2001/12/30 11:42:00  alex
113  * - der Server meldet nun eine ordentliche "Start-Zeit".
114  *
115  * Revision 1.13  2001/12/29 03:10:06  alex
116  * - Neue Funktion IRC_MODE() implementiert, div. Aenderungen.
117  * - neue configure-Optione "--enable-strict-rfc".
118  *
119  * Revision 1.12  2001/12/27 19:17:26  alex
120  * - neue Befehle PRIVMSG, NOTICE, PING.
121  *
122  * Revision 1.11  2001/12/27 16:55:41  alex
123  * - neu: IRC_WriteStrRelated(), Aenderungen auch in IRC_WriteStrClient().
124  *
125  * Revision 1.10  2001/12/26 22:48:53  alex
126  * - MOTD-Datei ist nun konfigurierbar und wird gelesen.
127  *
128  * Revision 1.9  2001/12/26 14:45:37  alex
129  * - "Code Cleanups".
130  *
131  * Revision 1.8  2001/12/26 03:21:46  alex
132  * - PING/PONG-Befehle implementiert,
133  * - Meldungen ueberarbeitet: enthalten nun (fast) immer den Nick.
134  *
135  * Revision 1.7  2001/12/25 23:25:18  alex
136  * - und nochmal Aenderungen am Logging ;-)
137  *
138  * Revision 1.6  2001/12/25 23:13:33  alex
139  * - Debug-Meldungen angepasst.
140  *
141  * Revision 1.5  2001/12/25 22:02:42  alex
142  * - neuer IRC-Befehl "/QUIT". Verbessertes Logging & Debug-Ausgaben.
143  *
144  * Revision 1.4  2001/12/25 19:19:30  alex
145  * - bessere Fehler-Abfragen, diverse Bugfixes.
146  * - Nicks werden nur einmal vergeben :-)
147  * - /MOTD wird unterstuetzt.
148  *
149  * Revision 1.3  2001/12/24 01:34:06  alex
150  * - USER und NICK wird nun in beliebiger Reihenfolge akzeptiert (wg. BitchX)
151  * - MOTD-Ausgabe begonnen zu implementieren.
152  *
153  * Revision 1.2  2001/12/23 21:57:16  alex
154  * - erste IRC-Befehle zu implementieren begonnen.
155  *
156  * Revision 1.1  2001/12/14 08:13:43  alex
157  * - neues Modul begonnen :-)
158  */
159
160
161 #include <portab.h>
162 #include "global.h"
163
164 #include <imp.h>
165 #include <assert.h>
166 #include <errno.h>
167 #include <stdarg.h>
168 #include <stdio.h>
169 #include <stdlib.h>
170 #include <string.h>
171
172 #include "ngircd.h"
173 #include "channel.h"
174 #include "client.h"
175 #include "conf.h"
176 #include "conn.h"
177 #include "log.h"
178 #include "messages.h"
179 #include "parse.h"
180 #include "tool.h"
181
182 #include <exp.h>
183 #include "irc.h"
184
185
186 #define CONNECTED TRUE
187 #define DISCONNECTED FALSE
188
189
190 LOCAL BOOLEAN Hello_User( CLIENT *Client );
191 LOCAL BOOLEAN Show_MOTD( CLIENT *Client );
192
193 LOCAL VOID Kill_Nick( CHAR *Nick );
194
195
196 GLOBAL VOID IRC_Init( VOID )
197 {
198 } /* IRC_Init */
199
200
201 GLOBAL VOID IRC_Exit( VOID )
202 {
203 } /* IRC_Exit */
204
205
206 GLOBAL BOOLEAN IRC_WriteStrClient( CLIENT *Client, CHAR *Format, ... )
207 {
208         CHAR buffer[1000];
209         BOOLEAN ok = CONNECTED;
210         va_list ap;
211
212         assert( Client != NULL );
213         assert( Format != NULL );
214
215         va_start( ap, Format );
216         vsnprintf( buffer, 1000, Format, ap );
217         va_end( ap );
218
219         /* an den Client selber */
220         ok = IRC_WriteStrClientPrefix( Client, Client_ThisServer( ), buffer );
221
222         return ok;
223 } /* IRC_WriteStrClient */
224
225
226 GLOBAL BOOLEAN IRC_WriteStrClientPrefix( CLIENT *Client, CLIENT *Prefix, CHAR *Format, ... )
227 {
228         /* Text an Clients, lokal bzw. remote, senden. */
229
230         CHAR buffer[1000];
231         va_list ap;
232
233         assert( Client != NULL );
234         assert( Format != NULL );
235         assert( Prefix != NULL );
236
237         va_start( ap, Format );
238         vsnprintf( buffer, 1000, Format, ap );
239         va_end( ap );
240
241         return Conn_WriteStr( Client_Conn( Client_NextHop( Client )), ":%s %s", Client_Mask( Prefix ), buffer );
242 } /* IRC_WriteStrClientPrefix */
243
244
245 GLOBAL BOOLEAN IRC_WriteStrChannel( CLIENT *Client, CHANNEL *Chan, CHAR *Format, ... )
246 {
247         CHAR buffer[1000];
248         va_list ap;
249
250         assert( Client != NULL );
251         assert( Format != NULL );
252
253         va_start( ap, Format );
254         vsnprintf( buffer, 1000, Format, ap );
255         va_end( ap );
256
257         return IRC_WriteStrChannelPrefix( Client, Chan, Client_ThisServer( ), buffer );
258 } /* IRC_WriteStrChannel */
259
260
261 GLOBAL BOOLEAN IRC_WriteStrChannelPrefix( CLIENT *Client, CHANNEL *Chan, CLIENT *Prefix, CHAR *Format, ... )
262 {
263         CHAR buffer[1000];
264         BOOLEAN sock[MAX_CONNECTIONS], ok = CONNECTED, i;
265         CL2CHAN *cl2chan;
266         CLIENT *c;
267         va_list ap;
268
269         assert( Client != NULL );
270         assert( Chan != NULL );
271         assert( Prefix != NULL );
272         assert( Format != NULL );
273
274         va_start( ap, Format );
275         vsnprintf( buffer, 1000, Format, ap );
276         va_end( ap );
277
278         for( i = 0; i < MAX_CONNECTIONS; i++ ) sock[i] = FALSE;
279
280         /* An alle Clients, die in den selben Channels sind.
281          * Dabei aber nur einmal je Remote-Server */
282         cl2chan = Channel_FirstMember( Chan );
283         while( cl2chan )
284         {
285                 c = Channel_GetClient( cl2chan );
286                 if( c != Client )
287                 {
288                         /* Ok, anderer Client */
289                         if( Client_Conn( c ) > NONE ) sock[Client_Conn( c )] = TRUE;
290                 }
291                 cl2chan = Channel_NextMember( Chan, cl2chan );
292         }
293
294         /* Senden ... */
295         for( i = 0; i < MAX_CONNECTIONS; i++ )
296         {
297                 if( sock[i] )
298                 {
299                         ok = Conn_WriteStr( i, ":%s %s", Client_Mask( Prefix ), buffer );
300                         if( ! ok ) break;
301                 }
302         }
303         return ok;
304 } /* IRC_WriteStrChannelPrefix */
305
306
307 GLOBAL VOID IRC_WriteStrServers( CLIENT *ExceptOf, CHAR *Format, ... )
308 {
309         CHAR buffer[1000];
310         va_list ap;
311
312         assert( Format != NULL );
313
314         va_start( ap, Format );
315         vsnprintf( buffer, 1000, Format, ap );
316         va_end( ap );
317
318         /* an den Client selber */
319         return IRC_WriteStrServersPrefix( ExceptOf, Client_ThisServer( ), buffer );
320 } /* IRC_WriteStrServers */
321
322
323 GLOBAL VOID IRC_WriteStrServersPrefix( CLIENT *ExceptOf, CLIENT *Prefix, CHAR *Format, ... )
324 {
325         CHAR buffer[1000];
326         CLIENT *c;
327         va_list ap;
328         
329         assert( Format != NULL );
330         assert( Prefix != NULL );
331
332         va_start( ap, Format );
333         vsnprintf( buffer, 1000, Format, ap );
334         va_end( ap );
335         
336         c = Client_First( );
337         while( c )
338         {
339                 if(( Client_Type( c ) == CLIENT_SERVER ) && ( Client_Conn( c ) > NONE ) && ( c != Client_ThisServer( )) && ( c != ExceptOf ))
340                 {
341                         /* Ziel-Server gefunden */
342                         IRC_WriteStrClientPrefix( c, Prefix, buffer );
343                 }
344                 c = Client_Next( c );
345         }
346 } /* IRC_WriteStrServersPrefix */
347
348
349 GLOBAL BOOLEAN IRC_PASS( CLIENT *Client, REQUEST *Req )
350 {
351         assert( Client != NULL );
352         assert( Req != NULL );
353
354         /* Fehler liefern, wenn kein lokaler Client */
355         if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
356         
357         if(( Client_Type( Client ) == CLIENT_UNKNOWN ) && ( Req->argc == 1))
358         {
359                 /* noch nicht registrierte unbekannte Verbindung */
360                 Log( LOG_DEBUG, "Connection %d: got PASS command ...", Client_Conn( Client ));
361
362                 /* Passwort speichern */
363                 Client_SetPassword( Client, Req->argv[0] );
364
365                 Client_SetType( Client, CLIENT_GOTPASS );
366                 return CONNECTED;
367         }
368         else if((( Client_Type( Client ) == CLIENT_UNKNOWN ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER )) && (( Req->argc == 3 ) || ( Req->argc == 4 )))
369         {
370                 /* noch nicht registrierte Server-Verbindung */
371                 Log( LOG_DEBUG, "Connection %d: got PASS command (new server link) ...", Client_Conn( Client ));
372
373                 /* Passwort speichern */
374                 Client_SetPassword( Client, Req->argv[0] );
375
376                 Client_SetType( Client, CLIENT_GOTPASSSERVER );
377                 return CONNECTED;
378         }
379         else if(( Client_Type( Client ) == CLIENT_UNKNOWN  ) || ( Client_Type( Client ) == CLIENT_UNKNOWNSERVER ))
380         {
381                 /* Falsche Anzahl Parameter? */
382                 return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
383         }
384         else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
385 } /* IRC_PASS */
386
387
388 GLOBAL BOOLEAN IRC_SERVER( CLIENT *Client, REQUEST *Req )
389 {
390         CHAR str[LINE_LEN], *ptr;
391         BOOLEAN ok;
392         CLIENT *c;
393         INT i;
394         
395         assert( Client != NULL );
396         assert( Req != NULL );
397
398         /* Fehler liefern, wenn kein lokaler Client */
399         if( Client_Conn( Client ) <= NONE ) return IRC_WriteStrClient( Client, ERR_UNKNOWNCOMMAND_MSG, Client_ID( Client ), Req->command );
400
401         if( Client_Type( Client ) == CLIENT_GOTPASSSERVER )
402         {
403                 /* Verbindung soll als Server-Server-Verbindung registriert werden */
404                 Log( LOG_DEBUG, "Connection %d: got SERVER command (new server link) ...", Client_Conn( Client ));
405
406                 /* Falsche Anzahl Parameter? */
407                 if(( Req->argc != 2 ) && ( Req->argc != 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
408
409                 /* Ist dieser Server bei uns konfiguriert? */
410                 for( i = 0; i < Conf_Server_Count; i++ ) if( strcasecmp( Req->argv[0], Conf_Server[i].name ) == 0 ) break;
411                 if( i >= Conf_Server_Count )
412                 {
413                         /* Server ist nicht konfiguriert! */
414                         Log( LOG_ERR, "Connection %d: Server \"%s\" not configured here!", Client_Conn( Client ), Req->argv[0] );
415                         Conn_Close( Client_Conn( Client ), NULL, "Server not configured here", TRUE );
416                         return DISCONNECTED;
417                 }
418                 if( strcmp( Client_Password( Client ), Conf_Server[i].pwd ) != 0 )
419                 {
420                         /* Falsches Passwort */
421                         Log( LOG_ERR, "Connection %d: Bad password for server \"%s\"!", Client_Conn( Client ), Req->argv[0] );
422                         Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE );
423                         return DISCONNECTED;
424                 }
425                 
426                 /* Ist ein Server mit dieser ID bereits registriert? */
427                 if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
428
429                 /* Server-Strukturen fuellen ;-) */
430                 Client_SetID( Client, Req->argv[0] );
431                 Client_SetHops( Client, 1 );
432                 Client_SetInfo( Client, Req->argv[Req->argc - 1] );
433                 
434                 /* Meldet sich der Server bei uns an? */
435                 if( Req->argc == 2 )
436                 {
437                         /* Unseren SERVER- und PASS-Befehl senden */
438                         ok = TRUE;
439                         if( ! IRC_WriteStrClient( Client, "PASS %s "PASSSERVERADD, Conf_Server[i].pwd )) ok = FALSE;
440                         else ok = IRC_WriteStrClient( Client, "SERVER %s 1 :%s", Conf_ServerName, Conf_ServerInfo );
441                         if( ! ok )
442                         {
443                                 Conn_Close( Client_Conn( Client ), "Unexpected server behavior!", NULL, FALSE );
444                                 return DISCONNECTED;
445                         }
446                         Client_SetIntroducer( Client, Client );
447                         Client_SetToken( Client, 1 );
448                 }
449                 else  Client_SetToken( Client, atoi( Req->argv[1] ));
450
451                 Log( LOG_NOTICE, "Server \"%s\" registered (connection %d, 1 hop - direct link).", Client_ID( Client ), Client_Conn( Client ));
452
453                 Client_SetType( Client, CLIENT_SERVER );
454
455                 /* Alle bisherigen Server dem neuen Server bekannt machen,
456                  * die bisherigen Server ueber den neuen informierenn */
457                 c = Client_First( );
458                 while( c )
459                 {
460                         if(( Client_Type( c ) == CLIENT_SERVER ) && ( c != Client ) && ( c != Client_ThisServer( )))
461                         {
462                                 if( Client_Conn( c ) > NONE )
463                                 {
464                                         /* Dem gefundenen Server gleich den neuen
465                                         * Server bekannt machen */
466                                         if( ! IRC_WriteStrClient( c, "SERVER %s %d %d :%s", Client_ID( Client ), Client_Hops( Client ) + 1, Client_MyToken( Client ), Client_Info( Client ))) return DISCONNECTED;
467                                 }
468                                 
469                                 /* Den neuen Server ueber den alten informieren */
470                                 if( ! IRC_WriteStrClientPrefix( Client, Client_Introducer( c ), "SERVER %s %d %d :%s", Client_ID( c ), Client_Hops( c ) + 1, Client_MyToken( c ), Client_Info( c ))) return DISCONNECTED;
471                         }
472                         c = Client_Next( c );
473                 }
474
475                 /* alle User dem neuen Server bekannt machen */
476                 c = Client_First( );
477                 while( c )
478                 {
479                         if( Client_Type( c ) == CLIENT_USER )
480                         {
481                                 /* User an neuen Server melden */
482                                 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;
483                         }
484                         c = Client_Next( c );
485                 }
486                 
487                 return CONNECTED;
488         }
489         else if( Client_Type( Client ) == CLIENT_SERVER )
490         {
491                 /* Neuer Server wird im Netz angekuendigt */
492
493                 /* Falsche Anzahl Parameter? */
494                 if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
495
496                 /* Ist ein Server mit dieser ID bereits registriert? */
497                 if( ! Client_CheckID( Client, Req->argv[0] )) return DISCONNECTED;
498
499                 /* Ueberfluessige Hostnamen aus Info-Text entfernen */
500                 ptr = strchr( Req->argv[3] + 2, '[' );
501                 if( ! ptr ) ptr = Req->argv[3];
502
503                 /* Neue Client-Struktur anlegen */
504                 c = Client_NewRemoteServer( Client, Req->argv[0], atoi( Req->argv[1] ), atoi( Req->argv[2] ), ptr, TRUE );
505                 if( ! c )
506                 {
507                         /* Neue Client-Struktur konnte nicht angelegt werden */
508                         Log( LOG_ALERT, "Can't create client structure for server! (on connection %d)", Client_Conn( Client ));
509                         Conn_Close( Client_Conn( Client ), NULL, "Can't allocate client structure for remote server", TRUE );
510                         return DISCONNECTED;
511                 }
512
513                 /* Log-Meldung zusammenbauen und ausgeben */
514                 if(( Client_Hops( c ) > 1 ) && ( Req->prefix[0] )) sprintf( str, "connected to %s, ", Req->prefix );
515                 else strcpy( str, "" );
516                 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": "" );
517                 
518                 return CONNECTED;
519         }
520         else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
521 } /* IRC_SERVER */
522
523
524 GLOBAL BOOLEAN IRC_NJOIN( CLIENT *Client, REQUEST *Req )
525 {
526         assert( Client != NULL );
527         assert( Req != NULL );
528
529         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTEREDSERVER_MSG, Client_ID( Client ));
530
531         return CONNECTED;
532 } /* IRC_NJOIN */
533
534
535 GLOBAL BOOLEAN IRC_NICK( CLIENT *Client, REQUEST *Req )
536 {
537         CLIENT *intr_c, *target, *c;
538         CHAR *modes;
539
540         assert( Client != NULL );
541         assert( Req != NULL );
542
543         /* Zumindest BitchX sendet NICK-USER in der falschen Reihenfolge. */
544 #ifndef STRICT_RFC
545         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 ))
546 #else
547         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 ))
548 #endif
549         {
550                 /* User-Registrierung bzw. Nick-Aenderung */
551
552                 /* Falsche Anzahl Parameter? */
553                 if( Req->argc != 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
554
555                 /* "Ziel-Client" ermitteln */
556                 if( Client_Type( Client ) == CLIENT_SERVER )
557                 {
558                         target = Client_GetFromID( Req->prefix );
559                         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
560                 }
561                 else
562                 {
563                         /* Ist der Client "restricted"? */
564                         if( Client_HasMode( Client, 'r' )) return IRC_WriteStrClient( Client, ERR_RESTRICTED_MSG, Client_ID( Client ));
565                         target = Client;
566                 }
567
568                 /* Wenn der Client zu seinem eigenen Nick wechseln will, so machen
569                  * wir nichts. So macht es das Original und mind. Snak hat probleme,
570                  * wenn wir es nicht so machen. Ob es so okay ist? Hm ... */
571 #ifndef STRICT_RFC
572                 if( strcmp( Client_ID( target ), Req->argv[0] ) == 0 ) return CONNECTED;
573 #endif
574                 
575                 /* pruefen, ob Nick bereits vergeben. Speziallfall: der Client
576                  * will nur die Gross- und Kleinschreibung aendern. Das darf
577                  * er natuerlich machen :-) */
578                 if( strcasecmp( Client_ID( target ), Req->argv[0] ) != 0 )
579                 {
580                         if( ! Client_CheckNick( target, Req->argv[0] )) return CONNECTED;
581                 }
582
583                 if( Client_Type( Client ) == CLIENT_USER )
584                 {
585                         /* Nick-Aenderung: allen mitteilen! */
586                         Log( LOG_INFO, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
587                         IRC_WriteStrClient( Client, "NICK :%s", Req->argv[0] );
588                         IRC_WriteStrServersPrefix( NULL, Client, "NICK :%s", Req->argv[0] );
589                 }
590                 else if( Client_Type( Client ) == CLIENT_SERVER )
591                 {
592                         /* Nick-Aenderung: allen mitteilen! */
593                         Log( LOG_DEBUG, "User \"%s\" changed nick: \"%s\" -> \"%s\".", Client_Mask( target ), Client_ID( target ), Req->argv[0] );
594                         IRC_WriteStrServersPrefix( Client, Client, "NICK :%s", Req->argv[0] );
595                 }
596         
597                 /* Client-Nick registrieren */
598                 Client_SetID( target, Req->argv[0] );
599
600                 if(( Client_Type( target ) != CLIENT_USER ) && ( Client_Type( target ) != CLIENT_SERVER ))
601                 {
602                         /* Neuer Client */
603                         Log( LOG_DEBUG, "Connection %d: got NICK command ...", Client_Conn( Client ));
604                         if( Client_Type( Client ) == CLIENT_GOTUSER ) return Hello_User( Client );
605                         else Client_SetType( Client, CLIENT_GOTNICK );
606                 }
607                 return CONNECTED;
608         }
609         else if( Client_Type( Client ) == CLIENT_SERVER )
610         {
611                 /* Server fuehrt neuen Client ein */
612
613                 /* Falsche Anzahl Parameter? */
614                 if( Req->argc != 7 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
615
616                 /* Nick ueberpruefen */
617                 c = Client_GetFromID( Req->argv[0] );
618                 if( c )
619                 {
620                         /* Der neue Nick ist auf diesem Server bereits registriert:
621                          * sowohl der neue, als auch der alte Client muessen nun
622                          * disconnectiert werden. */
623                         Log( LOG_ERR, "Server %s introduces already registered nick \"%s\"!", Client_ID( Client ), Req->argv[0] );
624                         Kill_Nick( Req->argv[0] );
625                         return CONNECTED;
626                 }
627
628                 /* Server, zu dem der Client connectiert ist, suchen */
629                 intr_c = Client_GetFromToken( Client, atoi( Req->argv[4] ));
630                 if( ! intr_c )
631                 {
632                         Log( LOG_ERR, "Server %s introduces nick \"%s\" on unknown server!?", Client_ID( Client ), Req->argv[0] );
633                         Kill_Nick( Req->argv[0] );
634                         return CONNECTED;
635                 }
636
637                 /* Neue Client-Struktur anlegen */
638                 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 );
639                 if( ! c )
640                 {
641                         /* Eine neue Client-Struktur konnte nicht angelegt werden.
642                          * Der Client muss disconnectiert werden, damit der Netz-
643                          * status konsistent bleibt. */
644                         Log( LOG_ALERT, "Can't create client structure! (on connection %d)", Client_Conn( Client ));
645                         Kill_Nick( Req->argv[0] );
646                         return CONNECTED;
647                 }
648
649                 modes = Client_Modes( c );
650                 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": "" );
651                 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": "" );
652
653                 /* Andere Server, ausser dem Introducer, informieren */
654                 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] );
655
656                 return CONNECTED;
657         }
658         else return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
659 } /* IRC_NICK */
660
661
662 GLOBAL BOOLEAN IRC_USER( CLIENT *Client, REQUEST *Req )
663 {
664         assert( Client != NULL );
665         assert( Req != NULL );
666
667 #ifndef STRICT_RFC
668         if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS || Client_Type( Client ) == CLIENT_UNKNOWN )
669 #else
670         if( Client_Type( Client ) == CLIENT_GOTNICK || Client_Type( Client ) == CLIENT_GOTPASS )
671 #endif
672         {
673                 /* Falsche Anzahl Parameter? */
674                 if( Req->argc != 4 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
675
676                 Client_SetUser( Client, Req->argv[0], FALSE );
677                 Client_SetInfo( Client, Req->argv[3] );
678
679                 Log( LOG_DEBUG, "Connection %d: got USER command ...", Client_Conn( Client ));
680                 if( Client_Type( Client ) == CLIENT_GOTNICK ) return Hello_User( Client );
681                 else Client_SetType( Client, CLIENT_GOTUSER );
682                 return CONNECTED;
683         }
684         else if( Client_Type( Client ) == CLIENT_USER || Client_Type( Client ) == CLIENT_SERVER || Client_Type( Client ) == CLIENT_SERVICE )
685         {
686                 return IRC_WriteStrClient( Client, ERR_ALREADYREGISTRED_MSG, Client_ID( Client ));
687         }
688         else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
689 } /* IRC_USER */
690
691
692 GLOBAL BOOLEAN IRC_QUIT( CLIENT *Client, REQUEST *Req )
693 {
694         CLIENT *target;
695         
696         assert( Client != NULL );
697         assert( Req != NULL );
698
699         if(( Client_Type( Client ) == CLIENT_USER ) || ( Client_Type( Client ) == CLIENT_SERVICE ))
700         {
701                 /* User / Service */
702                 
703                 /* Falsche Anzahl Parameter? */
704                 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
705
706                 if( Req->argc == 0 ) Conn_Close( Client_Conn( Client ), "Got QUIT command.", NULL, TRUE );
707                 else Conn_Close( Client_Conn( Client ), "Got QUIT command.", Req->argv[0], TRUE );
708                 
709                 return DISCONNECTED;
710         }
711         else if ( Client_Type( Client ) == CLIENT_SERVER )
712         {
713                 /* Server */
714
715                 /* Falsche Anzahl Parameter? */
716                 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
717
718                 target = Client_Search( Req->prefix );
719                 if( ! target )
720                 {
721                         Log( LOG_ERR, "Got QUIT from %s for unknown client!?", Client_ID( Client ));
722                         return CONNECTED;
723                 }
724
725                 if( Req->argc == 0 ) Client_Destroy( target, "Got QUIT command.", NULL );
726                 else Client_Destroy( target, "Got QUIT command.", Req->argv[0] );
727
728                 return CONNECTED;
729         }
730         else return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
731 } /* IRC_QUIT */
732
733
734 GLOBAL BOOLEAN IRC_SQUIT( CLIENT *Client, REQUEST *Req )
735 {
736         CLIENT *target;
737         
738         assert( Client != NULL );
739         assert( Req != NULL );
740
741         /* SQUIT ist nur fuer Server erlaubt */
742         if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
743
744         /* Falsche Anzahl Parameter? */
745         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
746
747         target = Client_GetFromID( Req->argv[0] );
748         if( ! target )
749         {
750                 Log( LOG_ERR, "Got SQUIT from %s for unknown server \%s\"!?", Client_ID( Client ), Req->argv[0] );
751                 return CONNECTED;
752         }
753
754         if( target == Client ) Log( LOG_DEBUG, "Got SQUIT from %s: %s", Client_ID( Client ), Req->argv[1] );
755         else Log( LOG_DEBUG, "Got SQUIT from %s for %s: %s", Client_ID( Client ), Client_ID( target ), Req->argv[1] );
756
757         /* SQUIT an alle Server weiterleiten */
758         IRC_WriteStrServers( Client, "SQUIT %s :%s", Req->argv[0], Req->argv[1] );
759
760         if( Client_Conn( target ) > NONE )
761         {
762                 if( Req->argv[1][0] ) Conn_Close( Client_Conn( target ), "Got SQUIT command.", Req->argv[1], TRUE );
763                 else Conn_Close( Client_Conn( target ), "Got SQUIT command.", NULL, TRUE );
764                 return DISCONNECTED;
765         }
766         else
767         {
768                 Client_Destroy( target, "Got SQUIT command.", Req->argv[1] );
769                 return CONNECTED;
770         }
771 } /* IRC_SQUIT */
772
773
774 GLOBAL BOOLEAN IRC_PING( CLIENT *Client, REQUEST *Req )
775 {
776         assert( Client != NULL );
777         assert( Req != NULL );
778
779         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
780
781         /* Falsche Anzahl Parameter? */
782         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
783         if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
784
785         Log( LOG_DEBUG, "Connection %d: got PING, sending PONG ...", Client_Conn( Client ));
786         return IRC_WriteStrClient( Client, "PONG %s :%s", Client_ID( Client_ThisServer( )), Client_ID( Client ));
787 } /* IRC_PING */
788
789
790 GLOBAL BOOLEAN IRC_PONG( CLIENT *Client, REQUEST *Req )
791 {
792         assert( Client != NULL );
793         assert( Req != NULL );
794
795         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
796
797         /* Falsche Anzahl Parameter? */
798         if( Req->argc < 1 ) return IRC_WriteStrClient( Client, ERR_NOORIGIN_MSG, Client_ID( Client ));
799         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
800
801         /* Der Connection-Timestamp wurde schon beim Lesen aus dem Socket
802          * aktualisiert, daher muss das hier nicht mehr gemacht werden. */
803
804         Log( LOG_DEBUG, "Connection %d: received PONG.", Client_Conn( Client ));
805         return CONNECTED;
806 } /* IRC_PONG */
807
808
809 GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req )
810 {
811         assert( Client != NULL );
812         assert( Req != NULL );
813
814         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
815
816         /* Falsche Anzahl Parameter? */
817         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
818
819         return Show_MOTD( Client );
820 } /* IRC_MOTD */
821
822
823 GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
824 {
825         CLIENT *to, *from;
826         CHANNEL *chan;
827         
828         assert( Client != NULL );
829         assert( Req != NULL );
830
831         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
832
833         /* Falsche Anzahl Parameter? */
834         if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
835         if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client ));
836         if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
837
838         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
839         else from = Client;
840         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
841
842         to = Client_Search( Req->argv[0] );
843         if( to )
844         {
845                 /* Okay, Ziel ist ein User */
846                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
847                 return IRC_WriteStrClientPrefix( to, from, "PRIVMSG %s :%s", Client_ID( to ), Req->argv[1] );
848         }
849
850         chan = Channel_Search( Req->argv[0] );
851         if( chan )
852         {
853                 /* Okay, Ziel ist ein Channel */
854                 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
855                 return IRC_WriteStrChannelPrefix( Client, chan, from, "PRIVMSG %s :%s", Req->argv[0], Req->argv[1] );
856         }
857
858         return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
859 } /* IRC_PRIVMSG */
860
861
862 GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req )
863 {
864         CLIENT *to, *from;
865
866         assert( Client != NULL );
867         assert( Req != NULL );
868
869         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
870
871         /* Falsche Anzahl Parameter? */
872         if( Req->argc != 2 ) return CONNECTED;
873
874         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
875         else from = Client;
876         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
877
878         to = Client_Search( Req->argv[0] );
879         if( to )
880         {
881                 /* Okay, Ziel ist ein User */
882                 return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] );
883         }
884         else return CONNECTED;
885 } /* IRC_NOTICE */
886
887
888 GLOBAL BOOLEAN IRC_MODE( CLIENT *Client, REQUEST *Req )
889 {
890         CHAR x[2], new_modes[CLIENT_MODE_LEN], *ptr;
891         BOOLEAN set, ok;
892         CLIENT *target;
893         
894         assert( Client != NULL );
895         assert( Req != NULL );
896
897         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
898
899         /* Falsche Anzahl Parameter? */
900         if(( Req->argc > 2 ) || ( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
901
902         /* "Ziel-Client" suchen */
903         target = Client_Search( Req->argv[0] );
904
905         /* Wer ist der Anfragende? */
906         if( Client_Type( Client ) == CLIENT_USER )
907         {
908                 /* User: MODE ist nur fuer sich selber zulaessig */
909                 if( target != Client ) return IRC_WriteStrClient( Client, ERR_USERSDONTMATCH_MSG, Client_ID( Client ));
910         }
911         else
912         {
913                 /* Server: gibt es den Client ueberhaupt? */
914                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[0] );
915         }
916
917         /* Werden die Modes erfragt? */
918         if( Req->argc == 1 ) return IRC_WriteStrClient( Client, RPL_UMODEIS_MSG, Client_ID( Client ), Client_Modes( Client ));
919
920         ptr = Req->argv[1];
921
922         /* Sollen Modes gesetzt oder geloescht werden? */
923         if( *ptr == '+' ) set = TRUE;
924         else if( *ptr == '-' ) set = FALSE;
925         else return IRC_WriteStrClient( Client, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( Client ));
926
927         /* Reply-String mit Aenderungen vorbereiten */
928         if( set ) strcpy( new_modes, "+" );
929         else strcpy( new_modes, "-" );
930
931         ptr++;
932         ok = TRUE;
933         x[1] = '\0';
934         while( *ptr )
935         {
936                 x[0] = '\0';
937                 if( Client_Type( Client ) == CLIENT_SERVER )
938                 {
939                         x[0] = *ptr;
940                         ok = TRUE;
941                 }
942                 else
943                 {
944                         switch( *ptr )
945                         {
946                                 case 'i':
947                                         /* invisible */
948                                         x[0] = 'i';
949                                         break;
950                                 case 'r':
951                                         /* restricted (kann nur gesetzt werden) */
952                                         if( set ) x[0] = 'r';
953                                         else ok = IRC_WriteStrClient( target, ERR_RESTRICTED_MSG, Client_ID( target ));
954                                         break;
955                                 case 'o':
956                                         /* operator (kann nur geloescht werden) */
957                                         if( ! set )
958                                         {
959                                                 Client_SetOperByMe( target, FALSE );
960                                                 x[0] = 'o';
961                                         }
962                                         else ok = IRC_WriteStrClient( target, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( target ));
963                                         break;
964                                 default:
965                                         ok = IRC_WriteStrClient( target, ERR_UMODEUNKNOWNFLAG_MSG, Client_ID( target ));
966                                         x[0] = '\0';
967                         }
968                 }
969                 if( ! ok ) break;
970
971                 ptr++;
972                 if( ! x[0] ) continue;
973
974                 /* Okay, gueltigen Mode gefunden */
975                 if( set )
976                 {
977                         /* Mode setzen. Wenn der Client ihn noch nicht hatte: merken */
978                         if( Client_ModeAdd( target, x[0] )) strcat( new_modes, x );
979                 }
980                 else
981                 {
982                         /* Modes geloescht. Wenn der Client ihn hatte: merken */
983                         if( Client_ModeDel( target, x[0] )) strcat( new_modes, x );
984                 }
985         }
986         
987         /* Geanderte Modes? */
988         if( new_modes[1] )
989         {
990                 if( Client_Type( Client ) == CLIENT_SERVER )
991                 {
992                         /* Modes an andere Server forwarden */
993                         IRC_WriteStrServersPrefix( Client, Client, "MODE %s :%s", Client_ID( target ), new_modes );
994                 }
995                 else
996                 {
997                         /* Bestaetigung an Client schicken & andere Server informieren */
998                         ok = IRC_WriteStrClient( Client, "MODE %s :%s", Client_ID( target ), new_modes );
999                         IRC_WriteStrServers( Client, "MODE %s :%s", Client_ID( target ), new_modes );
1000                 }
1001                 Log( LOG_DEBUG, "User \"%s\": Mode change, now \"%s\".", Client_Mask( target ), Client_Modes( target ));
1002         }
1003         return ok;
1004 } /* IRC_MODE */
1005
1006
1007 GLOBAL BOOLEAN IRC_OPER( CLIENT *Client, REQUEST *Req )
1008 {
1009         INT i;
1010         
1011         assert( Client != NULL );
1012         assert( Req != NULL );
1013
1014         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1015         
1016         /* Falsche Anzahl Parameter? */
1017         if( Req->argc != 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1018
1019         /* Operator suchen */
1020         for( i = 0; i < Conf_Oper_Count; i++)
1021         {
1022                 if( Conf_Oper[i].name[0] && Conf_Oper[i].pwd[0] && ( strcmp( Conf_Oper[i].name, Req->argv[0] ) == 0 )) break;
1023         }
1024         if( i >= Conf_Oper_Count )
1025         {
1026                 Log( LOG_WARNING, "Got invalid OPER from \"%s\": Name \"%s\" not configured!", Client_Mask( Client ), Req->argv[0] );
1027                 return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
1028         }
1029
1030         /* Stimmt das Passwort? */
1031         if( strcmp( Conf_Oper[i].pwd, Req->argv[1] ) != 0 )
1032         {
1033                 Log( LOG_WARNING, "Got invalid OPER from \"%s\": Bad password for \"%s\"!", Client_Mask( Client ), Conf_Oper[i].name );
1034                 return IRC_WriteStrClient( Client, ERR_PASSWDMISMATCH_MSG, Client_ID( Client ));
1035         }
1036         
1037         if( ! Client_HasMode( Client, 'o' ))
1038         {
1039                 /* noch kein o-Mode gesetzt */
1040                 Client_ModeAdd( Client, 'o' );
1041                 if( ! IRC_WriteStrClient( Client, "MODE %s :+o", Client_ID( Client ))) return DISCONNECTED;
1042                 IRC_WriteStrServersPrefix( NULL, Client, "MODE %s :+o", Client_ID( Client ));
1043         }
1044
1045         if( ! Client_OperByMe( Client )) Log( LOG_NOTICE, "Got valid OPER from \"%s\", user is an IRC operator now.", Client_Mask( Client ));
1046
1047         Client_SetOperByMe( Client, TRUE );
1048         return IRC_WriteStrClient( Client, RPL_YOUREOPER_MSG, Client_ID( Client ));
1049 } /* IRC_OPER */
1050
1051
1052 GLOBAL BOOLEAN IRC_DIE( CLIENT *Client, REQUEST *Req )
1053 {
1054         assert( Client != NULL );
1055         assert( Req != NULL );
1056
1057         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1058
1059         /* Falsche Anzahl Parameter? */
1060         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1061
1062         if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
1063
1064         Log( LOG_NOTICE, "Got DIE command from \"%s\", going down!", Client_Mask( Client ));
1065         NGIRCd_Quit = TRUE;
1066         return CONNECTED;
1067 } /* IRC_DIE */
1068
1069
1070 GLOBAL BOOLEAN IRC_RESTART( CLIENT *Client, REQUEST *Req )
1071 {
1072         assert( Client != NULL );
1073         assert( Req != NULL );
1074
1075         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1076
1077         /* Falsche Anzahl Parameter? */
1078         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1079
1080         if(( ! Client_HasMode( Client, 'o' )) || ( ! Client_OperByMe( Client ))) return IRC_WriteStrClient( Client, ERR_NOPRIVILEGES_MSG, Client_ID( Client ));
1081
1082         Log( LOG_NOTICE, "Got RESTART command from \"%s\", going down!", Client_Mask( Client ));
1083         NGIRCd_Restart = TRUE;
1084         return CONNECTED;
1085 } /* IRC_RESTART */
1086
1087
1088 GLOBAL BOOLEAN IRC_NAMES( CLIENT *Client, REQUEST *Req )
1089 {
1090         CHAR rpl[COMMAND_LEN];
1091         CLIENT *c;
1092         
1093         assert( Client != NULL );
1094         assert( Req != NULL );
1095
1096         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1097
1098         /* Falsche Anzahl Parameter? */
1099         if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1100
1101         /* Noch alle User ausgeben, die in keinem Channel sind */
1102         rpl[0] = '\0';
1103         c = Client_First( );
1104         while( c )
1105         {
1106                 if( Client_Type( c ) == CLIENT_USER )
1107                 {
1108                         /* Okay, das ist ein User */
1109                         strcat( rpl, Client_ID( c ));
1110                         strcat( rpl, " " );
1111                 }
1112
1113                 /* Antwort zu lang? Splitten. */
1114                 if( strlen( rpl ) > 480 )
1115                 {
1116                         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1117                         if( ! IRC_WriteStrClient( Client, RPL_NAMREPLY_MSG, Client_ID( Client ), "*", "*", rpl )) return DISCONNECTED;
1118                         rpl[0] = '\0';
1119                 }
1120                 
1121                 c = Client_Next( c );
1122         }
1123         if( rpl[0] )
1124         {
1125                 /* es wurden User gefunden */
1126                 if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1127                 if( ! IRC_WriteStrClient( Client, RPL_NAMREPLY_MSG, Client_ID( Client ), "*", "*", rpl )) return DISCONNECTED;
1128         }
1129         return IRC_WriteStrClient( Client, RPL_ENDOFNAMES_MSG, Client_ID( Client ), "*" );
1130 } /* IRC_NAMES */
1131
1132
1133 GLOBAL BOOLEAN IRC_ISON( CLIENT *Client, REQUEST *Req )
1134 {
1135         CHAR rpl[COMMAND_LEN];
1136         CLIENT *c;
1137         CHAR *ptr;
1138         INT i;
1139         
1140         assert( Client != NULL );
1141         assert( Req != NULL );
1142
1143         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1144
1145         /* Falsche Anzahl Parameter? */
1146         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1147
1148         strcpy( rpl, RPL_ISON_MSG );
1149         for( i = 0; i < Req->argc; i++ )
1150         {
1151                 ptr = strtok( Req->argv[i], " " );
1152                 while( ptr )
1153                 {
1154                         ngt_TrimStr( ptr );
1155                         c = Client_GetFromID( ptr );
1156                         if( c && ( Client_Type( c ) == CLIENT_USER ))
1157                         {
1158                                 /* Dieser Nick ist "online" */
1159                                 strcat( rpl, ptr );
1160                                 strcat( rpl, " " );
1161                         }
1162                         ptr = strtok( NULL, " " );
1163                 }
1164         }
1165         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1166
1167         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
1168 } /* IRC_ISON */
1169
1170
1171 GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
1172 {
1173         CLIENT *from, *target, *c;
1174         CHAR *ptr = NULL;
1175         
1176         assert( Client != NULL );
1177         assert( Req != NULL );
1178
1179         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1180
1181         /* Falsche Anzahl Parameter? */
1182         if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1183
1184         /* Client suchen */
1185         c = Client_GetFromID( Req->argv[Req->argc - 1] );
1186         if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] );
1187
1188         /* Empfaenger des WHOIS suchen */
1189         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1190         else from = Client;
1191         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1192         
1193         /* Forwarden an anderen Server? */
1194         if( Req->argc > 1 )
1195         {
1196                 /* angegebenen Ziel-Server suchen */
1197                 target = Client_GetFromID( Req->argv[1] );
1198                 if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
1199                 ptr = Req->argv[1];
1200         }
1201 #ifndef STRICT_RFC
1202         else if( Client_Conn( c ) == NONE )
1203         {
1204                 /* Client ist nicht von uns. Ziel-Server suchen */
1205                 target = c;
1206                 ptr = Req->argv[0];
1207         }
1208 #endif
1209         else target = NULL;
1210         
1211         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 );
1212         
1213         /* Nick, User und Name */
1214         if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
1215
1216         /* Server */
1217         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;
1218
1219         /* IRC-Operator? */
1220         if( Client_HasMode( c, 'o' ))
1221         {
1222                 if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
1223         }
1224
1225         /* Idle (nur lokale Clients) */
1226         if( Client_Conn( c ) > NONE )
1227         {
1228                 if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
1229         }
1230
1231         /* End of Whois */
1232         return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
1233 } /* IRC_WHOIS */
1234
1235
1236 GLOBAL BOOLEAN IRC_USERHOST( CLIENT *Client, REQUEST *Req )
1237 {
1238         CHAR rpl[COMMAND_LEN];
1239         CLIENT *c;
1240         INT max, i;
1241
1242         assert( Client != NULL );
1243         assert( Req != NULL );
1244
1245         if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1246
1247         /* Falsche Anzahl Parameter? */
1248         if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1249
1250         if( Req->argc > 5 ) max = 5;
1251         else max = Req->argc;
1252         
1253         strcpy( rpl, RPL_USERHOST_MSG );
1254         for( i = 0; i < max; i++ )
1255         {
1256                 c = Client_GetFromID( Req->argv[i] );
1257                 if( c && ( Client_Type( c ) == CLIENT_USER ))
1258                 {
1259                         /* Dieser Nick ist "online" */
1260                         strcat( rpl, Client_ID( c ));
1261                         if( Client_HasMode( c, 'o' )) strcat( rpl, "*" );
1262                         strcat( rpl, "=" );
1263                         if( Client_HasMode( c, 'a' )) strcat( rpl, "-" );
1264                         else strcat( rpl, "+" );
1265                         strcat( rpl, Client_User( c ));
1266                         strcat( rpl, "@" );
1267                         strcat( rpl, Client_Hostname( c ));
1268                         strcat( rpl, " " );
1269                 }
1270         }
1271         if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
1272
1273         return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
1274 } /* IRC_USERHOST */
1275
1276
1277 GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req )
1278 {
1279         assert( Client != NULL );
1280         assert( Req != NULL );
1281
1282         if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client ));
1283         else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] );
1284
1285         return CONNECTED;
1286 } /* IRC_ERROR */
1287
1288
1289 GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
1290 {
1291         CLIENT *target, *from;
1292         INT cnt;
1293         
1294         assert( Client != NULL );
1295         assert( Req != NULL );
1296
1297         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1298
1299         /* Falsche Anzahl Parameter? */
1300         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1301
1302         /* Absender ermitteln */
1303         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1304         else from = Client;
1305         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1306
1307         /* An anderen Server forwarden? */
1308         if( Req->argc == 2 )
1309         {
1310                 target = Client_GetFromID( Req->argv[1] );
1311                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
1312                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LUSERS %s %s", Req->argv[0], Req->argv[1] );
1313         }
1314
1315         /* Wer ist der Absender? */
1316         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1317         else target = Client;
1318         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1319         
1320         /* Users, Services und Serevr im Netz */
1321         if( ! IRC_WriteStrClient( target, RPL_LUSERCLIENT_MSG, Client_ID( target ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
1322
1323         /* IRC-Operatoren im Netz */
1324         cnt = Client_OperCount( );
1325         if( cnt > 0 )
1326         {
1327                 if( ! IRC_WriteStrClient( target, RPL_LUSEROP_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
1328         }
1329
1330         /* Unbekannt Verbindungen */
1331         cnt = Client_UnknownCount( );
1332         if( cnt > 0 )
1333         {
1334                 if( ! IRC_WriteStrClient( target, RPL_LUSERUNKNOWN_MSG, Client_ID( target ), cnt )) return DISCONNECTED;
1335         }
1336
1337         /* Channels im Netz */
1338         if( ! IRC_WriteStrClient( target, RPL_LUSERCHANNELS_MSG, Client_ID( target ), Channel_Count( ))) return DISCONNECTED;
1339
1340         /* Channels im Netz */
1341         if( ! IRC_WriteStrClient( target, RPL_LUSERME_MSG, Client_ID( target ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
1342
1343         return CONNECTED;
1344 } /* IRC_LUSERS */
1345
1346
1347 GLOBAL BOOLEAN IRC_LINKS( CLIENT *Client, REQUEST *Req )
1348 {
1349         CLIENT *target, *from, *c;
1350         CHAR *mask;
1351         
1352         assert( Client != NULL );
1353         assert( Req != NULL );
1354
1355         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1356
1357         /* Falsche Anzahl Parameter? */
1358         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1359
1360         /* Server-Mask ermitteln */
1361         if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
1362         else mask = "*";
1363
1364         /* Absender ermitteln */
1365         if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
1366         else from = Client;
1367         if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1368         
1369         /* An anderen Server forwarden? */
1370         if( Req->argc == 2 )
1371         {
1372                 target = Client_GetFromID( Req->argv[0] );
1373                 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
1374                 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
1375         }
1376
1377         /* Wer ist der Absender? */
1378         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1379         else target = Client;
1380         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1381         
1382         c = Client_First( );
1383         while( c )
1384         {
1385                 if( Client_Type( c ) == CLIENT_SERVER )
1386                 {
1387                         if( ! IRC_WriteStrClient( target, RPL_LINKS_MSG, Client_ID( target ), Client_ID( c ), Client_ID( Client_Introducer( c )), Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
1388                 }
1389                 c = Client_Next( c );
1390         }
1391         
1392         return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
1393 } /* IRC_LINKS */
1394
1395
1396 GLOBAL BOOLEAN IRC_JOIN( CLIENT *Client, REQUEST *Req )
1397 {
1398         CLIENT *target;
1399         CHAR *chan;
1400         
1401         assert( Client != NULL );
1402         assert( Req != NULL );
1403
1404         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1405
1406         /* Falsche Anzahl Parameter? */
1407         if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1408
1409         /* Wer ist der Absender? */
1410         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1411         else target = Client;
1412         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1413         
1414         /* Channel-Namen durchgehen */
1415         chan = strtok( Req->argv[0], "," );
1416         while( chan )
1417         {
1418                 if( ! Channel_Join( target, chan ))
1419                 {
1420                         /* naechsten Namen ermitteln */
1421                         chan = strtok( NULL, "," );
1422                         continue;
1423                 }
1424
1425                 /* An andere Server weiterleiten, an Client bestaetigen */
1426                 IRC_WriteStrServersPrefix( Client, target, "JOIN :%s", chan );
1427                 IRC_WriteStrClientPrefix( Client, target, "JOIN :%s", chan );
1428                 IRC_WriteStrChannelPrefix( Client, Channel_Search( chan ), target, "JOIN :%s", chan );
1429
1430                 Log( LOG_DEBUG, "User \"%s\" joined channel \"%s\".", Client_Mask( target ), Req->argv[0] );
1431                 
1432                 /* naechsten Namen ermitteln */
1433                 chan = strtok( NULL, "," );
1434         }
1435         return CONNECTED;
1436 } /* IRC_JOIN */
1437
1438
1439 GLOBAL BOOLEAN IRC_PART( CLIENT *Client, REQUEST *Req )
1440 {
1441         CLIENT *target;
1442         CHAR *chan;
1443
1444         assert( Client != NULL );
1445         assert( Req != NULL );
1446
1447         if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
1448
1449         /* Falsche Anzahl Parameter? */
1450         if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
1451
1452         /* Wer ist der Absender? */
1453         if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
1454         else target = Client;
1455         if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
1456
1457         /* Channel-Namen durchgehen */
1458         chan = strtok( Req->argv[0], "," );
1459         while( chan )
1460         {
1461                 if( ! Channel_Part( target, Client, chan, Req->argc > 1 ? Req->argv[1] : Client_ID( target )))
1462                 {
1463                         /* naechsten Namen ermitteln */
1464                         chan = strtok( NULL, "," );
1465                         continue;
1466                 }
1467
1468                 /* naechsten Namen ermitteln */
1469                 chan = strtok( NULL, "," );
1470         }
1471         return CONNECTED;
1472 } /* IRC_PART */
1473
1474
1475 LOCAL BOOLEAN Hello_User( CLIENT *Client )
1476 {
1477         assert( Client != NULL );
1478
1479         /* Passwort ueberpruefen */
1480         if( strcmp( Client_Password( Client ), Conf_ServerPwd ) != 0 )
1481         {
1482                 /* Falsches Passwort */
1483                 Log( LOG_ERR, "User \"%s\" rejected (connection %d): Bad password!", Client_Mask( Client ), Client_Conn( Client ));
1484                 Conn_Close( Client_Conn( Client ), NULL, "Bad password", TRUE );
1485                 return DISCONNECTED;
1486         }
1487
1488         Log( LOG_NOTICE, "User \"%s\" registered (connection %d).", Client_Mask( Client ), Client_Conn( Client ));
1489
1490         /* Andere Server informieren */
1491         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 ));
1492
1493         if( ! IRC_WriteStrClient( Client, RPL_WELCOME_MSG, Client_ID( Client ), Client_Mask( Client ))) return FALSE;
1494         if( ! IRC_WriteStrClient( Client, RPL_YOURHOST_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE;
1495         if( ! IRC_WriteStrClient( Client, RPL_CREATED_MSG, Client_ID( Client ), NGIRCd_StartStr )) return FALSE;
1496         if( ! IRC_WriteStrClient( Client, RPL_MYINFO_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return FALSE;
1497
1498         Client_SetType( Client, CLIENT_USER );
1499
1500         return Show_MOTD( Client );
1501 } /* Hello_User */
1502
1503
1504 LOCAL BOOLEAN Show_MOTD( CLIENT *Client )
1505 {
1506         BOOLEAN ok;
1507         CHAR line[127];
1508         FILE *fd;
1509         
1510         assert( Client != NULL );
1511
1512         fd = fopen( Conf_MotdFile, "r" );
1513         if( ! fd )
1514         {
1515                 Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno ));
1516                 return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
1517         }
1518         
1519         IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )));
1520         while( TRUE )
1521         {
1522                 if( ! fgets( line, 126, fd )) break;
1523                 if( line[strlen( line ) - 1] == '\n' ) line[strlen( line ) - 1] = '\0';
1524                 if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), line ))
1525                 {
1526                         fclose( fd );
1527                         return FALSE;
1528                 }
1529         }
1530         ok = IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ) );
1531
1532         fclose( fd );
1533         
1534         return ok;
1535 } /* Show_MOTD */
1536
1537
1538 LOCAL VOID Kill_Nick( CHAR *Nick )
1539 {
1540         Log( LOG_ERR, "User(s) with nick \"%s\" will be disconnected!", Nick );
1541         /* FIXME */
1542         Log( LOG_ALERT, "[Kill_Nick() not implemented - OOOPS!]" );
1543 } /* Kill_Nick */
1544
1545
1546 /* -eof- */