- CHAR str[LINE_LEN + 1], *ptr = NULL;
- CL2CHAN *cl2chan;
- CHANNEL *chan;
-
- assert( Client != NULL );
- assert( Req != NULL );
-
- if(( Client_Type( Client ) != CLIENT_USER ) && ( Client_Type( Client ) != CLIENT_SERVER )) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
-
- /* Falsche Anzahl Parameter? */
- if(( Req->argc < 1 ) || ( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
-
- /* Client suchen */
- c = Client_Search( Req->argv[Req->argc - 1] );
- if(( ! c ) || ( Client_Type( c ) != CLIENT_USER )) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->argv[Req->argc - 1] );
-
- /* Empfaenger des WHOIS suchen */
- if( Client_Type( Client ) == CLIENT_SERVER ) from = Client_Search( Req->prefix );
- else from = Client;
- if( ! from ) return IRC_WriteStrClient( Client, ERR_NOSUCHNICK_MSG, Client_ID( Client ), Req->prefix );
-
- /* Forwarden an anderen Server? */
- if( Req->argc > 1 )
- {
- /* angegebenen Ziel-Server suchen */
- target = Client_Search( Req->argv[1] );
- if( ! target ) return IRC_WriteStrClient( from, ERR_NOSUCHSERVER_MSG, Client_ID( from ), Req->argv[1] );
- ptr = Req->argv[1];
- }
- else target = Client_ThisServer( );
-
- assert( target != NULL );
-
- 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 );
-
- /* Nick, User und Name */
- if( ! IRC_WriteStrClient( from, RPL_WHOISUSER_MSG, Client_ID( from ), Client_ID( c ), Client_User( c ), Client_Hostname( c ), Client_Info( c ))) return DISCONNECTED;
-
- /* Server */
- 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;
-
- /* Channels */
- sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
- cl2chan = Channel_FirstChannelOf( c );
- while( cl2chan )
- {
- chan = Channel_GetChannel( cl2chan );
- assert( chan != NULL );
-
- /* Channel-Name anhaengen */
- if( str[strlen( str ) - 1] != ':' ) strcat( str, " " );
- if( strchr( Channel_UserModes( chan, c ), 'o' )) strcat( str, "@" );
- else if( strchr( Channel_UserModes( chan, c ), 'v' )) strcat( str, "+" );
- strcat( str, Channel_Name( chan ));
-
- if( strlen( str ) > ( LINE_LEN - CHANNEL_NAME_LEN - 4 ))
- {
- /* Zeile wird zu lang: senden! */
- if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
- sprintf( str, RPL_WHOISCHANNELS_MSG, Client_ID( from ), Client_ID( c ));
- }
-
- /* naechstes Mitglied suchen */
- cl2chan = Channel_NextChannelOf( c, cl2chan );
- }
- if( str[strlen( str ) - 1] != ':')
- {
- /* Es sind noch Daten da, die gesendet werden muessen */
- if( ! IRC_WriteStrClient( Client, str )) return DISCONNECTED;
- }
-
- /* IRC-Operator? */
- if( Client_HasMode( c, 'o' ))
- {
- if( ! IRC_WriteStrClient( from, RPL_WHOISOPERATOR_MSG, Client_ID( from ), Client_ID( c ))) return DISCONNECTED;
- }
-
- /* Idle (nur lokale Clients) */
- if( Client_Conn( c ) > NONE )
- {
- if( ! IRC_WriteStrClient( from, RPL_WHOISIDLE_MSG, Client_ID( from ), Client_ID( c ), Conn_GetIdle( Client_Conn ( c )))) return DISCONNECTED;
- }
-
- /* Away? */
- if( Client_HasMode( c, 'a' ))
- {
- if( ! IRC_WriteStrClient( from, RPL_AWAY_MSG, Client_ID( from ), Client_ID( c ), Client_Away( c ))) return DISCONNECTED;
- }
-
- /* End of Whois */
- return IRC_WriteStrClient( from, RPL_ENDOFWHOIS_MSG, Client_ID( from ), Client_ID( c ));
-} /* IRC_WHOIS */
-
-
-GLOBAL BOOLEAN
-IRC_WHO( CLIENT *Client, REQUEST *Req )
-{
- BOOLEAN ok, only_ops;
- CHAR flags[8], *ptr;
- CL2CHAN *cl2chan;
- CHANNEL *chan;
- CLIENT *c;
-
- assert( Client != NULL );
- assert( Req != NULL );
-
- if( Client_Type( Client ) != CLIENT_USER ) return IRC_WriteStrClient( Client, ERR_NOTREGISTERED_MSG, Client_ID( Client ));
-
- /* Falsche Anzahl Parameter? */
- if(( Req->argc > 2 )) return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
-
- only_ops = FALSE;
- chan = NULL;
-
- if( Req->argc == 2 )
- {
- /* Nur OPs anzeigen? */
- if( strcmp( Req->argv[1], "o" ) == 0 ) only_ops = TRUE;
-#ifdef STRICT_RFC
- else return IRC_WriteStrClient( Client, ERR_NEEDMOREPARAMS_MSG, Client_ID( Client ), Req->command );
-#endif
- }
-
- if( Req->argc >= 1 )
- {
- /* wurde ein Channel oder Nick-Mask angegeben? */
- chan = Channel_Search( Req->argv[0] );
- }
-
- if( chan )
- {
- /* User eines Channels ausgeben */
- if( ! IRC_Send_WHO( Client, chan, only_ops )) return DISCONNECTED;
+ CONN_ID idx, idx2;
+ char user[CLIENT_USER_LEN];
+
+ assert(Client != NULL);
+ assert(Req != NULL);
+
+ _IRC_GET_SENDER_OR_RETURN_(from, Req, Client)
+ _IRC_GET_TARGET_SERVER_OR_RETURN_(target, Req, 0, from)
+
+ /* Forward command to other server? */
+ if (target != Client_ThisServer()) {
+ /* Send RPL_TRACELINK back to initiator */
+ idx = Client_Conn(Client);
+ assert(idx > NONE);
+ idx2 = Client_Conn(Client_NextHop(target));
+ assert(idx2 > NONE);
+
+ if (!IRC_WriteStrClient(from, RPL_TRACELINK_MSG,
+ Client_ID(from), PACKAGE_NAME,
+ PACKAGE_VERSION, Client_ID(target),
+ Client_ID(Client_NextHop(target)),
+ Option_String(idx2),
+ time(NULL) - Conn_StartTime(idx2),
+ Conn_SendQ(idx), Conn_SendQ(idx2)))
+ return DISCONNECTED;
+
+ /* Forward command */
+ IRC_WriteStrClientPrefix(target, from, "TRACE %s", Req->argv[0]);
+ return CONNECTED;