2 * ngIRCd -- The Next Generation IRC Daemon
3 * Copyright (c)2001,2002 by Alexander Barton (alex@barton.de)
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 * Please read the file COPYING, README and AUTHORS for more information.
17 static char UNUSED id[] = "$Id: irc-info.c,v 1.28 2005/03/19 18:43:48 fw Exp $";
27 #include "cvs-version.h"
28 #include "conn-func.h"
39 #include "irc-write.h"
46 IRC_ADMIN(CLIENT *Client, REQUEST *Req )
48 CLIENT *target, *prefix;
50 assert( Client != NULL );
51 assert( Req != NULL );
53 /* Falsche Anzahl Parameter? */
54 if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
57 if( Req->argc == 1 ) target = Client_Search( Req->argv[0] );
58 else target = Client_ThisServer( );
60 /* Prefix ermitteln */
61 if( Client_Type( Client ) == CLIENT_SERVER ) prefix = Client_Search( Req->prefix );
63 if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
65 /* An anderen Server weiterleiten? */
66 if( target != Client_ThisServer( ))
68 if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( prefix, ERR_NOSUCHSERVER_MSG, Client_ID( prefix ), Req->argv[0] );
71 IRC_WriteStrClientPrefix( target, prefix, "ADMIN %s", Req->argv[0] );
75 /* mit Versionsinfo antworten */
76 if( ! IRC_WriteStrClient( Client, RPL_ADMINME_MSG, Client_ID( prefix ), Conf_ServerName )) return DISCONNECTED;
77 if( ! IRC_WriteStrClient( Client, RPL_ADMINLOC1_MSG, Client_ID( prefix ), Conf_ServerAdmin1 )) return DISCONNECTED;
78 if( ! IRC_WriteStrClient( Client, RPL_ADMINLOC2_MSG, Client_ID( prefix ), Conf_ServerAdmin2 )) return DISCONNECTED;
79 if( ! IRC_WriteStrClient( Client, RPL_ADMINEMAIL_MSG, Client_ID( prefix ), Conf_ServerAdminMail )) return DISCONNECTED;
81 IRC_SetPenalty( Client, 1 );
87 IRC_ISON( CLIENT *Client, REQUEST *Req )
89 char rpl[COMMAND_LEN];
94 assert( Client != NULL );
95 assert( Req != NULL );
97 /* Falsche Anzahl Parameter? */
98 if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
100 strcpy( rpl, RPL_ISON_MSG );
101 for( i = 0; i < Req->argc; i++ )
103 ptr = strtok( Req->argv[i], " " );
107 c = Client_Search( ptr );
108 if( c && ( Client_Type( c ) == CLIENT_USER ))
110 /* Dieser Nick ist "online" */
111 strlcat( rpl, ptr, sizeof( rpl ));
112 strlcat( rpl, " ", sizeof( rpl ));
114 ptr = strtok( NULL, " " );
117 ngt_TrimLastChr(rpl, ' ');
119 return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
124 IRC_LINKS( CLIENT *Client, REQUEST *Req )
126 CLIENT *target, *from, *c;
129 assert( Client != NULL );
130 assert( Req != NULL );
132 /* Falsche Anzahl Parameter? */
133 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
135 /* Server-Mask ermitteln */
136 if( Req->argc > 0 ) mask = Req->argv[Req->argc - 1];
139 /* Absender ermitteln */
140 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
142 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
144 /* An anderen Server forwarden? */
147 target = Client_Search( Req->argv[0] );
148 if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] );
149 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LINKS %s %s", Req->argv[0], Req->argv[1] );
152 /* Wer ist der Absender? */
153 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
154 else target = Client;
155 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
160 if( Client_Type( c ) == CLIENT_SERVER )
162 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;
164 c = Client_Next( c );
167 IRC_SetPenalty( target, 1 );
168 return IRC_WriteStrClient( target, RPL_ENDOFLINKS_MSG, Client_ID( target ), mask );
173 IRC_LUSERS( CLIENT *Client, REQUEST *Req )
175 CLIENT *target, *from;
177 assert( Client != NULL );
178 assert( Req != NULL );
180 /* Falsche Anzahl Parameter? */
181 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
183 /* Absender ermitteln */
184 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
186 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
188 /* An anderen Server forwarden? */
191 target = Client_Search( Req->argv[1] );
192 if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
193 else if( target != Client_ThisServer( )) return IRC_WriteStrClientPrefix( target, from, "LUSERS %s %s", Req->argv[0], Req->argv[1] );
196 /* Wer ist der Absender? */
197 if( Client_Type( Client ) == CLIENT_SERVER ) target = Client_Search( Req->prefix );
198 else target = Client;
199 if( ! target ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
201 IRC_Send_LUSERS( target );
203 IRC_SetPenalty( target, 1 );
209 IRC_MOTD( CLIENT *Client, REQUEST *Req )
211 CLIENT *from, *target;
213 assert( Client != NULL );
214 assert( Req != NULL );
216 /* Falsche Anzahl Parameter? */
217 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
219 /* From aus Prefix ermitteln */
220 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
222 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
226 /* an anderen Server forwarden */
227 target = Client_Search( Req->argv[0] );
228 if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] );
230 if( target != Client_ThisServer( ))
232 /* Ok, anderer Server ist das Ziel: forwarden */
233 return IRC_WriteStrClientPrefix( target, from, "MOTD %s", Req->argv[0] );
237 IRC_SetPenalty( from, 3 );
238 return IRC_Show_MOTD( from );
243 IRC_NAMES( CLIENT *Client, REQUEST *Req )
245 char rpl[COMMAND_LEN], *ptr;
246 CLIENT *target, *from, *c;
249 assert( Client != NULL );
250 assert( Req != NULL );
252 /* Falsche Anzahl Parameter? */
253 if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
255 /* From aus Prefix ermitteln */
256 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
258 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
262 /* an anderen Server forwarden */
263 target = Client_Search( Req->argv[1] );
264 if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
266 if( target != Client_ThisServer( ))
268 /* Ok, anderer Server ist das Ziel: forwarden */
269 return IRC_WriteStrClientPrefix( target, from, "NAMES %s :%s", Req->argv[0], Req->argv[1] );
275 /* bestimmte Channels durchgehen */
276 ptr = strtok( Req->argv[0], "," );
279 chan = Channel_Search( ptr );
283 if( ! IRC_Send_NAMES( from, chan )) return DISCONNECTED;
285 if( ! IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), ptr )) return DISCONNECTED;
287 /* naechsten Namen ermitteln */
288 ptr = strtok( NULL, "," );
293 /* alle Channels durchgehen */
294 chan = Channel_First( );
298 if( ! IRC_Send_NAMES( from, chan )) return DISCONNECTED;
300 /* naechster Channel */
301 chan = Channel_Next( chan );
304 /* Nun noch alle Clients ausgeben, die in keinem Channel sind */
306 snprintf( rpl, sizeof( rpl ), RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" );
309 if(( Client_Type( c ) == CLIENT_USER ) && ( Channel_FirstChannelOf( c ) == NULL ) && ( ! strchr( Client_Modes( c ), 'i' )))
311 /* Okay, das ist ein User: anhaengen */
312 if( rpl[strlen( rpl ) - 1] != ':' ) strlcat( rpl, " ", sizeof( rpl ));
313 strlcat( rpl, Client_ID( c ), sizeof( rpl ));
315 if( strlen( rpl ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
317 /* Zeile wird zu lang: senden! */
318 if( ! IRC_WriteStrClient( from, "%s", rpl )) return DISCONNECTED;
319 snprintf( rpl, sizeof( rpl ), RPL_NAMREPLY_MSG, Client_ID( from ), "*", "*" );
323 /* naechster Client */
324 c = Client_Next( c );
326 if( rpl[strlen( rpl ) - 1] != ':')
328 /* es wurden User gefunden */
329 if( ! IRC_WriteStrClient( from, "%s", rpl )) return DISCONNECTED;
332 IRC_SetPenalty( from, 1 );
333 return IRC_WriteStrClient( from, RPL_ENDOFNAMES_MSG, Client_ID( from ), "*" );
338 IRC_STATS( CLIENT *Client, REQUEST *Req )
340 CLIENT *from, *target, *cl;
345 assert( Client != NULL );
346 assert( Req != NULL );
348 /* Falsche Anzahl Parameter? */
349 if( Req->argc > 2 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
351 /* From aus Prefix ermitteln */
352 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
354 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
358 /* an anderen Server forwarden */
359 target = Client_Search( Req->argv[1] );
360 if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
362 if( target != Client_ThisServer( ))
364 /* Ok, anderer Server ist das Ziel: forwarden */
365 return IRC_WriteStrClientPrefix( target, from, "STATS %s %s", Req->argv[0], Req->argv[1] );
369 if( Req->argc > 0 ) query = Req->argv[0][0] ? Req->argv[0][0] : '*';
374 case 'l': /* Links */
379 cl = Client_GetFromConn( con );
380 if( cl && (( Client_Type( cl ) == CLIENT_SERVER ) || ( cl == Client )))
382 /* Server link or our own connection */
384 if( Conn_Options( con ) & CONN_ZIP )
386 if( ! IRC_WriteStrClient( from, RPL_STATSLINKINFOZIP_MSG, Client_ID( from ), Client_Mask( cl ), Conn_SendQ( con ), Conn_SendMsg( con ), Zip_SendBytes( con ), Conn_SendBytes( con ), Conn_RecvMsg( con ), Zip_RecvBytes( con ), Conn_RecvBytes( con ), (long)( time( NULL ) - Conn_StartTime( con )))) return DISCONNECTED;
391 if( ! IRC_WriteStrClient( from, RPL_STATSLINKINFO_MSG, Client_ID( from ), Client_Mask( cl ), Conn_SendQ( con ), Conn_SendMsg( con ), Conn_SendBytes( con ), Conn_RecvMsg( con ), Conn_RecvBytes( con ), (long)( time( NULL ) - Conn_StartTime( con )))) return DISCONNECTED;
394 con = Conn_Next( con );
397 case 'm': /* IRC-Befehle */
399 cmd = Parse_GetCommandStruct( );
402 if( cmd->lcount > 0 || cmd->rcount > 0 )
404 if( ! IRC_WriteStrClient( from, RPL_STATSCOMMANDS_MSG, Client_ID( from ), cmd->name, cmd->lcount, cmd->bytes, cmd->rcount )) return DISCONNECTED;
411 IRC_SetPenalty( from, 2 );
412 return IRC_WriteStrClient( from, RPL_ENDOFSTATS_MSG, Client_ID( from ), query );
417 IRC_TIME( CLIENT *Client, REQUEST *Req )
419 CLIENT *from, *target;
423 assert( Client != NULL );
424 assert( Req != NULL );
426 /* Falsche Anzahl Parameter? */
427 if( Req->argc > 1 ) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
429 /* From aus Prefix ermitteln */
430 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
432 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
436 /* an anderen Server forwarden */
437 target = Client_Search( Req->argv[0] );
438 if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOSUCHSERVER_MSG, Client_ID( Client ), Req->argv[0] );
440 if( target != Client_ThisServer( ))
442 /* Ok, anderer Server ist das Ziel: forwarden */
443 return IRC_WriteStrClientPrefix( target, from, "TIME %s", Req->argv[0] );
448 (void)strftime( t_str, 60, "%A %B %d %Y -- %H:%M %Z", localtime( &t ));
449 return IRC_WriteStrClient( from, RPL_TIME_MSG, Client_ID( from ), Client_ID( Client_ThisServer( )), t_str );
454 IRC_USERHOST( CLIENT *Client, REQUEST *Req )
456 char rpl[COMMAND_LEN];
460 assert( Client != NULL );
461 assert( Req != NULL );
463 /* Falsche Anzahl Parameter? */
464 if(( Req->argc < 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
466 if( Req->argc > 5 ) max = 5;
467 else max = Req->argc;
469 strcpy( rpl, RPL_USERHOST_MSG );
470 for( i = 0; i < max; i++ )
472 c = Client_Search( Req->argv[i] );
473 if( c && ( Client_Type( c ) == CLIENT_USER ))
475 /* Dieser Nick ist "online" */
476 strlcat( rpl, Client_ID( c ), sizeof( rpl ));
477 if( Client_HasMode( c, 'o' )) strlcat( rpl, "*", sizeof( rpl ));
478 strlcat( rpl, "=", sizeof( rpl ));
479 if( Client_HasMode( c, 'a' )) strlcat( rpl, "-", sizeof( rpl ));
480 else strlcat( rpl, "+", sizeof( rpl ));
481 strlcat( rpl, Client_User( c ), sizeof( rpl ));
482 strlcat( rpl, "@", sizeof( rpl ));
483 strlcat( rpl, Client_Hostname( c ), sizeof( rpl ));
484 strlcat( rpl, " ", sizeof( rpl ));
487 ngt_TrimLastChr( rpl, ' ');
489 return IRC_WriteStrClient( Client, rpl, Client_ID( Client ) );
494 IRC_VERSION( CLIENT *Client, REQUEST *Req )
496 CLIENT *target, *prefix;
498 char ver[12], vertxt[30];
501 assert( Client != NULL );
502 assert( Req != NULL );
504 /* Falsche Anzahl Parameter? */
505 if(( Req->argc > 1 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
508 if( Req->argc == 1 ) target = Client_Search( Req->argv[0] );
509 else target = Client_ThisServer( );
511 /* Prefix ermitteln */
512 if( Client_Type( Client ) == CLIENT_SERVER ) prefix = Client_Search( Req->prefix );
513 else prefix = Client;
514 if( ! prefix ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
516 /* An anderen Server weiterleiten? */
517 if( target != Client_ThisServer( ))
519 if(( ! target ) || ( Client_Type( target ) != CLIENT_SERVER )) return IRC_WriteStrClient( prefix, ERR_NOSUCHSERVER_MSG, Client_ID( prefix ), Req->argv[0] );
522 IRC_WriteStrClientPrefix( target, prefix, "VERSION %s", Req->argv[0] );
526 /* mit Versionsinfo antworten */
527 IRC_SetPenalty( Client, 1 );
529 strlcpy( ver, CVSDATE, sizeof( ver ));
530 strncpy( ver + 4, ver + 5, 2 );
531 strncpy( ver + 6, ver + 8, 3 );
532 snprintf( vertxt, sizeof( vertxt ), "%s(%s)", PACKAGE_VERSION, ver );
533 return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), PACKAGE_NAME, vertxt, NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition );
535 return IRC_WriteStrClient( Client, RPL_VERSION_MSG, Client_ID( prefix ), PACKAGE_NAME, PACKAGE_VERSION, NGIRCd_DebugLevel, Conf_ServerName, NGIRCd_VersionAddition );
541 IRC_WHO( CLIENT *Client, REQUEST *Req )
549 assert( Client != NULL );
550 assert( Req != NULL );
552 /* Falsche Anzahl Parameter? */
553 if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
560 /* Nur OPs anzeigen? */
561 if( strcmp( Req->argv[1], "o" ) == 0 ) only_ops = true;
563 else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
569 /* wurde ein Channel oder Nick-Mask angegeben? */
570 chan = Channel_Search( Req->argv[0] );
575 /* User eines Channels ausgeben */
576 if( ! IRC_Send_WHO( Client, chan, only_ops )) return DISCONNECTED;
582 if(( Client_Type( c ) == CLIENT_USER ) && ( ! strchr( Client_Modes( c ), 'i' )))
585 if( Req->argc == 0 ) ok = true;
588 if( strcasecmp( Req->argv[0], Client_ID( c )) == 0 ) ok = true;
589 else if( strcmp( Req->argv[0], "0" ) == 0 ) ok = true;
592 if( ok && (( ! only_ops ) || ( strchr( Client_Modes( c ), 'o' ))))
595 strcpy( flags, "H" );
596 if( strchr( Client_Modes( c ), 'o' )) strlcat( flags, "*", sizeof( flags ));
598 /* Search suitable channel */
599 cl2chan = Channel_FirstChannelOf( c );
602 cn = Channel_GetChannel( cl2chan );
603 if( Channel_IsMemberOf( cn, Client ) ||
604 ! strchr( Channel_Modes( cn ), 's' ))
606 ptr = Channel_Name( cn );
609 cl2chan = Channel_NextChannelOf( c, cl2chan );
611 if( ! cl2chan ) ptr = "*";
613 if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), ptr, Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
617 /* naechster Client */
618 c = Client_Next( c );
621 if( chan ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Channel_Name( chan ));
622 else if( Req->argc == 0 ) return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), "*" );
623 else return IRC_WriteStrClient( Client, RPL_ENDOFWHO_MSG, Client_ID( Client ), Req->argv[0] );
628 IRC_WHOIS( CLIENT *Client, REQUEST *Req )
630 CLIENT *from, *target, *c;
631 char str[LINE_LEN + 1];
635 assert( Client != NULL );
636 assert( Req != NULL );
638 /* Bad number of parameters? */
639 if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
642 c = Client_Search( Req->argv[Req->argc - 1] );
643 if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] );
645 /* Search sender of the WHOIS */
646 if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
648 if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
650 /* Forward to other server? */
653 /* Search target server (can be specified as nick of that server!) */
654 target = Client_Search( Req->argv[0] );
655 if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[0] );
657 else target = Client_ThisServer( );
659 assert( target != NULL );
661 if(( Client_NextHop( target ) != Client_ThisServer( )) && ( Client_Type( Client_NextHop( target )) == CLIENT_SERVER )) return IRC_WriteStrClientPrefix( target, from, "WHOIS %s :%s", Req->argv[0], Req->argv[1] );
663 /* Nick, user and name */
664 if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
667 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;
670 snprintf( str, sizeof( str ), RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
671 cl2chan = Channel_FirstChannelOf( c );
674 chan = Channel_GetChannel( cl2chan );
675 assert( chan != NULL );
678 cl2chan = Channel_NextChannelOf( c, cl2chan );
680 /* Secret channel? */
681 if( strchr( Channel_Modes( chan ), 's' ) && ! Channel_IsMemberOf( chan, Client )) continue;
683 /* Concatenate channel names */
684 if( str[strlen( str ) - 1] != ':' ) strlcat( str, " ", sizeof( str ));
685 if( strchr( Channel_UserModes( chan, c ), 'o' )) strlcat( str, "@", sizeof( str ));
686 else if( strchr( Channel_UserModes( chan, c ), 'v' )) strlcat( str, "+", sizeof( str ));
687 strlcat( str, Channel_Name( chan ), sizeof( str ));
689 if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ))
691 /* Line becomes too long: send it! */
692 if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
693 snprintf( str, sizeof( str ), RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
696 if( str[strlen( str ) - 1] != ':')
698 /* There is data left to send: */
699 if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
703 if( Client_HasMode( c, 'o' ))
705 if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
708 /* Idle (only local clients) */
709 if( Client_Conn( c ) > NONE )
711 if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
715 if( Client_HasMode( c, 'a' ))
717 if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( c ), Client_Away( c ))) return DISCONNECTED;
721 return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
726 IRC_WHOWAS( CLIENT *Client, REQUEST *Req )
728 assert( Client != NULL );
729 assert( Req != NULL );
731 /* Falsche Anzahl Parameter? */
732 if(( Req->argc < 1 ) || ( Req->argc > 3 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
741 IRC_Send_LUSERS( CLIENT *Client )
745 assert( Client != NULL );
747 /* Users, services and serevers in the network */
748 if( ! IRC_WriteStrClient( Client, RPL_LUSERCLIENT_MSG, Client_ID( Client ), Client_UserCount( ), Client_ServiceCount( ), Client_ServerCount( ))) return DISCONNECTED;
750 /* Number of IRC operators */
751 cnt = Client_OperCount( );
754 if( ! IRC_WriteStrClient( Client, RPL_LUSEROP_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
757 /* Unknown connections */
758 cnt = Client_UnknownCount( );
761 if( ! IRC_WriteStrClient( Client, RPL_LUSERUNKNOWN_MSG, Client_ID( Client ), cnt )) return DISCONNECTED;
764 /* Number of created channels */
765 if( ! IRC_WriteStrClient( Client, RPL_LUSERCHANNELS_MSG, Client_ID( Client ), Channel_Count( ))) return DISCONNECTED;
767 /* Number of local users, services and servers */
768 if( ! IRC_WriteStrClient( Client, RPL_LUSERME_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyServiceCount( ), Client_MyServerCount( ))) return DISCONNECTED;
771 /* Maximum number of local users */
772 if( ! IRC_WriteStrClient( Client, RPL_LOCALUSERS_MSG, Client_ID( Client ), Client_MyUserCount( ), Client_MyMaxUserCount( ))) return DISCONNECTED;
773 /* Maximum number of users in the network */
774 if( ! IRC_WriteStrClient( Client, RPL_NETUSERS_MSG, Client_ID( Client ), Client_UserCount( ), Client_MaxUserCount( ))) return DISCONNECTED;
778 } /* IRC_Send_LUSERS */
782 IRC_Show_MOTD( CLIENT *Client )
788 assert( Client != NULL );
790 if( Conf_MotdPhrase[0] )
792 if( ! IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return DISCONNECTED;
793 if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), Conf_MotdPhrase )) return DISCONNECTED;
794 return IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ));
797 fd = fopen( Conf_MotdFile, "r" );
800 Log( LOG_WARNING, "Can't read MOTD file \"%s\": %s", Conf_MotdFile, strerror( errno ));
801 return IRC_WriteStrClient( Client, ERR_NOMOTD_MSG, Client_ID( Client ) );
804 if( ! IRC_WriteStrClient( Client, RPL_MOTDSTART_MSG, Client_ID( Client ), Client_ID( Client_ThisServer( )))) return DISCONNECTED;
807 if( ! fgets( line, sizeof( line ), fd )) break;
809 ngt_TrimLastChr( line, '\n');
811 if( ! IRC_WriteStrClient( Client, RPL_MOTD_MSG, Client_ID( Client ), line ))
817 ok = IRC_WriteStrClient( Client, RPL_ENDOFMOTD_MSG, Client_ID( Client ) );
822 } /* IRC_Show_MOTD */
826 IRC_Send_NAMES( CLIENT *Client, CHANNEL *Chan )
828 bool is_visible, is_member;
829 char str[LINE_LEN + 1];
833 assert( Client != NULL );
834 assert( Chan != NULL );
836 if( Channel_IsMemberOf( Chan, Client )) is_member = true;
837 else is_member = false;
839 /* Secret channel? */
840 if( ! is_member && strchr( Channel_Modes( Chan ), 's' )) return CONNECTED;
842 /* Alle Mitglieder suchen */
843 snprintf( str, sizeof( str ), RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
844 cl2chan = Channel_FirstMember( Chan );
847 cl = Channel_GetClient( cl2chan );
849 if( strchr( Client_Modes( cl ), 'i' )) is_visible = false;
850 else is_visible = true;
852 if( is_member || is_visible )
855 if( str[strlen( str ) - 1] != ':' ) strlcat( str, " ", sizeof( str ));
856 if( strchr( Channel_UserModes( Chan, cl ), 'o' )) strlcat( str, "@", sizeof( str ));
857 else if( strchr( Channel_UserModes( Chan, cl ), 'v' )) strlcat( str, "+", sizeof( str ));
858 strlcat( str, Client_ID( cl ), sizeof( str ));
860 if( strlen( str ) > ( LINE_LEN - CLIENT_NICK_LEN - 4 ))
862 /* Zeile wird zu lang: senden! */
863 if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
864 snprintf( str, sizeof( str ), RPL_NAMREPLY_MSG, Client_ID( Client ), "=", Channel_Name( Chan ));
868 /* naechstes Mitglied suchen */
869 cl2chan = Channel_NextMember( Chan, cl2chan );
871 if( str[strlen( str ) - 1] != ':')
873 /* Es sind noch Daten da, die gesendet werden muessen */
874 if( ! IRC_WriteStrClient( Client, "%s", str )) return DISCONNECTED;
878 } /* IRC_Send_NAMES */
882 IRC_Send_WHO( CLIENT *Client, CHANNEL *Chan, bool OnlyOps )
884 bool is_visible, is_member;
889 assert( Client != NULL );
890 assert( Chan != NULL );
892 if( Channel_IsMemberOf( Chan, Client )) is_member = true;
893 else is_member = false;
895 /* Secret channel? */
896 if( ! is_member && strchr( Channel_Modes( Chan ), 's' )) return CONNECTED;
898 /* Alle Mitglieder suchen */
899 cl2chan = Channel_FirstMember( Chan );
902 c = Channel_GetClient( cl2chan );
904 if( strchr( Client_Modes( c ), 'i' )) is_visible = false;
905 else is_visible = true;
907 if( is_member || is_visible )
909 /* Flags zusammenbasteln */
910 strcpy( flags, "H" );
911 if( strchr( Client_Modes( c ), 'o' )) strlcat( flags, "*", sizeof( flags ));
912 if( strchr( Channel_UserModes( Chan, c ), 'o' )) strlcat( flags, "@", sizeof( flags ));
913 else if( strchr( Channel_UserModes( Chan, c ), 'v' )) strlcat( flags, "+", sizeof( flags ));
916 if(( ! OnlyOps ) || ( strchr( Client_Modes( c ), 'o' )))
918 if( ! IRC_WriteStrClient( Client, RPL_WHOREPLY_MSG, Client_ID( Client ), Channel_Name( Chan ), Client_User( c ), Client_Hostname( c ), Client_ID( Client_Introducer( c )), Client_ID( c ), flags, Client_Hops( c ), Client_Info( c ))) return DISCONNECTED;
922 /* naechstes Mitglied suchen */
923 cl2chan = Channel_NextMember( Chan, cl2chan );