2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
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.
12 * $Id: irc.c,v 1.84 2002/03/03 17:15:11 alex Exp $
17 * Revision 1.84 2002/03/03 17:15:11 alex
18 * - Source in weitere Module fuer IRC-Befehle aufgesplitted.
20 * Revision 1.83 2002/02/28 00:48:26 alex
21 * - Forwarding von TOPIC an andere Server gefixed. Hoffentlich ;-)
23 * Revision 1.82 2002/02/27 23:26:36 alex
24 * - einige Funktionen in irc-xxx-Module ausgegliedert.
26 * Revision 1.81 2002/02/27 20:55:44 alex
27 * - Channel-Topics werden nun auch korrekt von anderen Server angenommen.
29 * Revision 1.80 2002/02/27 20:33:13 alex
30 * - Channel-Topics implementiert.
32 * Revision 1.79 2002/02/27 18:57:21 alex
33 * - PRIVMSG zeugt nun bei Texten an User an, wenn diese "away" sind.
35 * Revision 1.78 2002/02/27 18:23:45 alex
36 * - IRC-Befehl "AWAY" implementert.
38 * Revision 1.77 2002/02/27 17:05:41 alex
39 * - PRIVMSG beachtet nun die Channel-Modes "n" und "m".
41 * Revision 1.76 2002/02/27 16:04:14 alex
42 * - Bug bei belegtem Nickname bei User-Registrierung (NICK-Befehl) behoben.
44 * Revision 1.75 2002/02/27 15:23:27 alex
45 * - NAMES beachtet nun das "invisible" Flag ("i") von Usern.
47 * Revision 1.74 2002/02/27 03:44:53 alex
48 * - gerade eben in SQUIT eingefuehrten Bug behoben: entfernte Server werden nun
49 * nur noch geloescht, die Verbindung, von der SQUIT kam, bleibt wieder offen.
51 * Revision 1.73 2002/02/27 03:08:05 alex
52 * - Log-Meldungen bei SQUIT erneut ueberarbeitet ...
54 * Revision 1.72 2002/02/27 02:26:58 alex
55 * - SQUIT wird auf jeden Fall geforwarded, zudem besseres Logging.
57 * Revision 1.71 2002/02/27 00:50:05 alex
58 * - einige unnoetige Client_NextHop()-Aufrufe entfernt.
59 * - NAMES korrigiert und komplett implementiert.
61 * Revision 1.70 2002/02/26 22:06:40 alex
62 * - Nick-Aenderungen werden nun wieder korrekt ins Logfile geschrieben.
81 #include "irc-write.h"
90 GLOBAL BOOLEAN IRC_MOTD( CLIENT *Client, REQUEST *Req )
92 assert( Client != NULL );
93 assert( Req != NULL );
95 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
97 /* Falsche Anzahl Parameter? */
98 if( Req->argc != 0 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
100 return IRC_Show_MOTD( Client );
104 GLOBAL BOOLEAN IRC_PRIVMSG( CLIENT *Client, REQUEST *Req )
106 BOOLEAN is_member, has_voice, is_op, ok;
110 assert( Client != NULL );
111 assert( Req != NULL );
113 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
115 /* Falsche Anzahl Parameter? */
116 if( Req->argc == 0 ) return IRC_WriteStrClient( Client, ERR_NORECIPIENT_MSG, Client_ID( Client ), Req->command );
117 if( Req->argc == 1 ) return IRC_WriteStrClient( Client, ERR_NOTEXTTOSEND_MSG, Client_ID( Client ));
118 if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
120 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
122 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
124 cl = Client_Search( Req->argv[0] );
127 /* Okay, Ziel ist ein User */
128 if(( Client_Type( Client ) != CLIENT_SERVER ) && ( strchr( Client_Modes( cl ), 'a' )))
130 /* Ziel-User ist AWAY: Meldung verschicken */
131 if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( cl ), Client_Away( cl ))) return DISCONNECTED;
135 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
136 return IRC_WriteStrClientPrefix( cl, from, "PRIVMSG %s :%s", Client_ID( cl ), Req->argv[1] );
139 chan = Channel_Search( Req->argv[0] );
142 /* Okay, Ziel ist ein Channel */
143 is_member = has_voice = is_op = FALSE;
144 if( Channel_IsMemberOf( chan, from ))
147 if( strchr( Channel_UserModes( chan, from ), 'v' )) has_voice = TRUE;
148 if( strchr( Channel_UserModes( chan, from ), 'o' )) is_op = TRUE;
151 /* pruefen, ob Client in Channel schreiben darf */
153 if( strchr( Channel_Modes( chan ), 'n' ) && ( ! is_member )) ok = FALSE;
154 if( strchr( Channel_Modes( chan ), 'm' ) && ( ! is_op ) && ( ! has_voice )) ok = FALSE;
156 if( ! ok ) return IRC_WriteStrClient( from, ERR_CANNOTSENDTOCHAN_MSG, Client_ID( from ), Req->argv[0] );
159 if( Client_Conn( from ) > NONE ) Conn_UpdateIdle( Client_Conn( from ));
160 return IRC_WriteStrChannelPrefix( Client, chan, from, TRUE, "PRIVMSG %s :%s", Req->argv[0], Req->argv[1] );
163 return IRC_WriteStrClient( from, ERR_NOSUCHNICK_MSG, Client_ID( from ), Req->argv[0] );
167 GLOBAL BOOLEAN IRC_NOTICE( CLIENT *Client, REQUEST *Req )
171 assert( Client != NULL );
172 assert( Req != NULL );
174 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
176 /* Falsche Anzahl Parameter? */
177 if( Req->argc != 2 ) return CONNECTED;
179 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
181 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
183 to = Client_Search( Req->argv[0] );
186 /* Okay, Ziel ist ein User */
187 return IRC_WriteStrClientPrefix( to, from, "NOTICE %s :%s", Client_ID( to ), Req->argv[1] );
189 else return CONNECTED;
193 GLOBAL BOOLEAN IRC_NAMES( CLIENT *Client, REQUEST *Req )
195 CHAR rpl[COMMAND_LEN], *ptr;
196 CLIENT *target, *from, *c;
199 assert( Client != NULL );
200 assert( Req != NULL );
202 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
204 /* Falsche Anzahl Parameter? */
205 if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
207 /* From aus Prefix ermitteln */
208 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
210 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
214 /* an anderen Server forwarden */
215 target = Client_GetFromID( Req->argv[1] );
216 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
218 if( target != Client_ThisServer( ))
220 /* Ok, anderer Server ist das Ziel: forwarden */
221 return IRC_WriteStrClientPrefix( target, from, "NAMES %s :%s", Req->argv[0], Req->argv[1] );
227 /* bestimmte Channels durchgehen */
228 ptr = strtok( Req->argv[0], "," );
231 chan = Channel_Search( ptr );
235 if( ! IRC_Send_NAMES( from, chan )) return DISCONNECTED;
237 if( ! IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), ptr )) return DISCONNECTED;
239 /* naechsten Namen ermitteln */
240 ptr = strtok( NULL, "," );
245 /* alle Channels durchgehen */
246 chan = Channel_First( );
250 if( ! IRC_Send_NAMES( from, chan )) return DISCONNECTED;
252 /* naechster Channel */
253 chan = Channel_Next( chan );
256 /* Nun noch alle Clients ausgeben, die in keinem Channel sind */
258 sprintf( rpl, RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" );
261 if(( Client_Type( c ) == CLIENT_USER ) && ( Channel_FirstChannelOf( c ) == NULL ) && ( ! strchr( Client_Modes( c ), 'i' )))
263 /* Okay, das ist ein User: anhaengen */
264 if( rpl[strlen( rpl ) - 1] != ':' ) strcat( rpl, " " );
265 strcat( rpl, Client_ID( c ));
267 if( strlen( rpl ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
269 /* Zeile wird zu lang: senden! */
270 if( ! IRC_WriteStrClient( from, rpl )) return DISCONNECTED;
271 sprintf( rpl, RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" );
275 /* naechster Client */
276 c = Client_Next( c );
278 if( rpl[strlen( rpl ) - 1] != ':')
280 /* es wurden User gefunden */
281 if( ! IRC_WriteStrClient( from, rpl )) return DISCONNECTED;
284 return IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), "*" );
288 GLOBAL BOOLEAN IRC_ISON( CLIENT *Client, REQUEST *Req )
290 CHAR rpl[COMMAND_LEN];
295 assert( Client != NULL );
296 assert( Req != NULL );
298 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
300 /* Falsche Anzahl Parameter? */
301 if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
303 strcpy( rpl, RPL_ISON_MSG );
304 for( i = 0; i < Req->argc; i++ )
306 ptr = strtok( Req->argv[i], " " );
310 c = Client_GetFromID( ptr );
311 if( c && ( Client_Type( c ) == CLIENT_USER ))
313 /* Dieser Nick ist "online" */
317 ptr = strtok( NULL, " " );
320 if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
322 return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
326 GLOBAL BOOLEAN IRC_WHOIS( CLIENT *Client, REQUEST *Req )
328 CLIENT *from, *target, *c;
329 CHAR str[LINE_LEN + 1], *ptr = NULL;
333 assert( Client != NULL );
334 assert( Req != NULL );
336 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
338 /* Falsche Anzahl Parameter? */
339 if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
342 c = Client_GetFromID( Req->argv[Req->argc - 1] );
343 if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] );
345 /* Empfaenger des WHOIS suchen */
346 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
348 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
350 /* Forwarden an anderen Server? */
353 /* angegebenen Ziel-Server suchen */
354 target = Client_GetFromID( Req->argv[1] );
355 if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
358 else target = Client_ThisServer( );
360 assert( target != NULL );
362 if(( Client_NextHop( target ) != Client_ThisServer( )) && ( Client_Type( Client_NextHop( target )) == CLIENT_SERVER )) return IRC_WriteStrClientPrefix( target, from, "WHOIS %s :%s", Req->argv[0], ptr );
364 /* Nick, User und Name */
365 if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
368 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;
371 sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
372 cl2chan = Channel_FirstChannelOf( c );
375 chan = Channel_GetChannel( cl2chan );
376 assert( chan != NULL );
378 /* Channel-Name anhaengen */
379 if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
380 if( strchr( Channel_UserModes( chan, c ), 'v' )) strcat( str, "+" );
381 if( strchr( Channel_UserModes( chan, c ), 'o' )) strcat( str, "@" );
382 strcat( str, Channel_Name( chan ));
384 if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ))
386 /* Zeile wird zu lang: senden! */
387 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
388 sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
391 /* naechstes Mitglied suchen */
392 cl2chan = Channel_NextChannelOf( c, cl2chan );
394 if( str[strlen( str ) - 1] != ':')
396 /* Es sind noch Daten da, die gesendet werden muessen */
397 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
401 if( Client_HasMode( c, 'o' ))
403 if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
406 /* Idle (nur lokale Clients) */
407 if( Client_Conn( c ) > NONE )
409 if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
413 if( Client_HasMode( c, 'a' ))
415 if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( c ), Client_Away( c ))) return DISCONNECTED;
419 return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
423 GLOBAL BOOLEAN IRC_WHO( CLIENT *Client, REQUEST *Req )
425 assert( Client != NULL );
426 assert( Req != NULL );
428 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
430 /* Falsche Anzahl Parameter? */
431 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
437 GLOBAL BOOLEAN IRC_USERHOST( CLIENT *Client, REQUEST *Req )
439 CHAR rpl[COMMAND_LEN];
443 assert( Client != NULL );
444 assert( Req != NULL );
446 if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
448 /* Falsche Anzahl Parameter? */
449 if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
451 if( Req->argc > 5 ) max = 5;
452 else max = Req->argc;
454 strcpy( rpl, RPL_USERHOST_MSG );
455 for( i = 0; i < max; i++ )
457 c = Client_GetFromID( Req->argv[i] );
458 if( c && ( Client_Type( c ) == CLIENT_USER ))
460 /* Dieser Nick ist "online" */
461 strcat( rpl, Client_ID( c ));
462 if( Client_HasMode( c, 'o' )) strcat( rpl, "*" );
464 if( Client_HasMode( c, 'a' )) strcat( rpl, "-" );
465 else strcat( rpl, "+" );
466 strcat( rpl, Client_User( c ));
468 strcat( rpl, Client_Hostname( c ));
472 if( rpl[strlen( rpl ) - 1] == ' ' ) rpl[strlen( rpl ) - 1] = '\0';
474 return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
478 GLOBAL BOOLEAN IRC_ERROR( CLIENT *Client, REQUEST *Req )
480 assert( Client != NULL );
481 assert( Req != NULL );
483 if( Req->argc < 1 ) Log( LOG_NOTICE, "Got ERROR from \"%s\"!", Client_Mask( Client ));
484 else Log( LOG_NOTICE, "Got ERROR from \"%s\": %s!", Client_Mask( Client ), Req->argv[0] );
490 GLOBAL BOOLEAN IRC_LUSERS( CLIENT *Client, REQUEST *Req )
492 CLIENT *target, *from;
494 assert( Client != NULL );
495 assert( Req != NULL );
497 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
499 /* Falsche Anzahl Parameter? */
500 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
502 /* Absender ermitteln */
503 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
505 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
507 /* An anderen Server forwarden? */
510 target = Client_GetFromID( Req->argv[1] );
511 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[1] );
512 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LUSERS %s %s", Req->argv[0], Req->argv[1] );
515 /* Wer ist der Absender? */
516 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
517 else target = Client;
518 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
520 IRC_Send_LUSERS( target );
526 GLOBAL BOOLEAN IRC_LINKS( CLIENT *Client, REQUEST *Req )
528 CLIENT *target, *from, *c;
531 assert( Client != NULL );
532 assert( Req != NULL );
534 if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
536 /* Falsche Anzahl Parameter? */
537 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
539 /* Server-Mask ermitteln */
540 if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
543 /* Absender ermitteln */
544 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_GetFromID( Req->prefix );
546 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
548 /* An anderen Server forwarden? */
551 target = Client_GetFromID( Req->argv[0] );
552 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
553 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
556 /* Wer ist der Absender? */
557 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_GetFromID( Req->prefix );
558 else target = Client;
559 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
564 if( Client_Type( c ) == CLIENT_SERVER )
566 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;
568 c = Client_Next( c );
571 return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
575 GLOBAL BOOLEAN IRC_VERSION( CLIENT *Client, REQUEST *Req )
577 CLIENT *target, *prefix;
579 assert( Client != NULL );
580 assert( Req != NULL );
582 /* Falsche Anzahl Parameter? */
583 if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
586 if( Req->argc == 1 ) target = Client_GetFromID( Req->argv[0] );
587 else target = Client_ThisServer( );
589 /* Prefix ermitteln */
590 if( Client_Type( Client ) == CLIENT_SERVER ) prefix = Client_GetFromID( Req->prefix );
591 else prefix = Client;
592 if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->prefix );
594 /* An anderen Server weiterleiten? */
595 if( target != Client_ThisServer( ))
597 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
600 IRC_WriteStrClientPrefix( target, prefix, "VERSION %s", Req->argv[0] );
604 /* mit Versionsinfo antworten */
605 return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition( ));
609 GLOBAL BOOLEAN IRC_KILL( CLIENT *Client, REQUEST *Req )
613 assert( Client != NULL );
614 assert( Req != NULL );
616 if( Client_Type( Client ) != CLIENT_SERVER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
618 /* Falsche Anzahl Parameter? */
619 if(( Req->argc != 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
621 prefix = Client_GetFromID( Req->prefix );
624 Log( LOG_WARNING, "Got KILL with invalid prefix: \"%s\"!", Req->prefix );
625 prefix = Client_ThisServer( );
628 Log( LOG_NOTICE, "Got KILL command from \"%s\" for \"%s\": %s", Client_Mask( prefix ), Req->argv[0], Req->argv[1] );
630 /* andere Server benachrichtigen */
631 IRC_WriteStrServersPrefix( Client, prefix, "KILL %s :%s", Req->argv[0], Req->argv[1] );
633 /* haben wir selber einen solchen Client? */
634 c = Client_GetFromID( Req->argv[0] );
635 if( c && ( Client_Conn( c ) != NONE )) Conn_Close( Client_Conn( c ), NULL, Req->argv[1], TRUE );
641 GLOBAL BOOLEAN IRC_Show_MOTD( CLIENT *Client )
647 assert( Client != NULL );
649 fd = fopen( Conf_MotdFile, "r" );
652 Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno ));
653 return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
656 IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )));
659 if( ! fgets( line, 126, fd )) break;
660 if( line[strlen( line ) - 1] == '\n' ) line[strlen( line ) - 1] = '\0';
661 if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), line ))
667 ok = IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ) );
672 } /* IRC_Show_MOTD */
675 GLOBAL BOOLEAN IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan )
677 BOOLEAN is_visible, is_member;
678 CHAR str[LINE_LEN + 1];
682 assert( Client != NULL );
683 assert( Chan != NULL );
685 if( Channel_IsMemberOf( Chan, Client )) is_member = TRUE;
686 else is_member = FALSE;
688 /* Alle Mitglieder suchen */
689 sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
690 cl2chan = Channel_FirstMember( Chan );
693 cl = Channel_GetClient( cl2chan );
695 if( strchr( Client_Modes( cl ), 'i' )) is_visible = FALSE;
696 else is_visible = TRUE;
698 if( is_member || is_visible )
701 if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
702 if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strcat( str, "+" );
703 if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strcat( str, "@" );
704 strcat( str, Client_ID( cl ));
706 if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
708 /* Zeile wird zu lang: senden! */
709 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
710 sprintf( str, RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
714 /* naechstes Mitglied suchen */
715 cl2chan = Channel_NextMember( Chan, cl2chan );
717 if( str[strlen( str ) - 1] != ':')
719 /* Es sind noch Daten da, die gesendet werden muessen */
720 if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
724 } /* IRC_Send_NAMES */
727 GLOBAL BOOLEAN IRC_Send_LUSERS( CLIENT *Client )
731 assert( Client != NULL );
733 /* Users, Services und Serevr im Netz */
734 if( ! IRC_WriteStrClient( Client, RPL_LUSERCLIENT_MSG, Client_ID( Client ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
736 /* IRC-Operatoren im Netz */
737 cnt = Client_OperCount( );
740 if( ! IRC_WriteStrClient( Client, RPL_LUSEROP_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
743 /* Unbekannt Verbindungen */
744 cnt = Client_UnknownCount( );
747 if( ! IRC_WriteStrClient( Client, RPL_LUSERUNKNOWN_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
750 /* Channels im Netz */
751 if( ! IRC_WriteStrClient( Client, RPL_LUSERCHANNELS_MSG, Client_ID( Client ), Channel_Count( ))) return DISCONNECTED;
753 /* Channels im Netz */
754 if( ! IRC_WriteStrClient( Client, RPL_LUSERME_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
757 } /* IRC_Send_LUSERS */