/************************************************************************
 *   IRC - Internet Relay Chat, server/s_query.c
 *
 *   Copyright (C) 2000-2003 TR-IRCD Development
 *
 *   Copyright (C) 1990 Jarkko Oikarinen and
 *                      University of Oulu, Co Center
 *
 *   See file AUTHORS in IRC package for additional names of
 *   the programmers.
 *
 *   This program is free software; you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation; either version 2, or (at your option)
 *   any later version.
 *
 *   This program is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with this program; if not, write to the Free Software
 *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

/*
 * $Id: s_query.c,v 1.3 2003/06/14 13:55:52 tr-ircd Exp $ 
 */

#include "struct.h"
#include "common.h"
#include "sys.h"
#include "numeric.h"
#include "msg.h"
#include "channel.h"
#include "h.h"
#include "zlink.h"
#include "s_conf.h"

extern struct Token tok1_msgtab[];

/* 
 * * hunt_server *
 * 
 *      Do the basic thing in delivering the message (command) *
 * across the relays to the specific server (server) for *
 * actions. *
 * 
 *      Note:   The command is a format string and *MUST* be *  
 * f prefixed style (e.g. ":%s COMMAND %s ..."). *              Command
 * can have only max 8 parameters. *
 * 
 *      server  parv[server] is the parameter identifying the *
 * arget server. *
 *
 *      *WARNING* *             parv[server] is replaced with the
 * pointer to the *             real servername from the matched client
 * (I'm lazy *          now --msa). *
 *
 */

int hunt_server(aClient *cptr, aClient *sptr, char *command, char *token,
		int server, int parc, char *parv[])
{
    aClient *acptr;
    int wilds;
    if (parc <= server || BadPtr(parv[server]) ||
	match(me.name, parv[server]) == 0 || match(parv[server], me.name) == 0)
	return (HUNTED_ISME);
    /*
     * * These are to pickup matches that would cause the following *
     * message to go in the wrong direction while doing quick fast * 
     * non-matching lookups.
     */

    if ((acptr = find_client(parv[server])))
	if (acptr->from == sptr->from && !MyConnect(acptr))
	    acptr = NULL;
    if (!acptr && (acptr = find_server(parv[server])))
	if (acptr->from == sptr->from && !MyConnect(acptr))
	    acptr = NULL;

    (void) collapse(parv[server]);
    wilds = (strchr(parv[server], '?') || strchr(parv[server], '*'));
    /*
     * Again, if there are no wild cards involved in the server name,
     * use the hash lookup - Dianora
     */

    if (!acptr) {
	if (!wilds) {
	    acptr = find_server(parv[server]);
	    if (!acptr || !IsRegistered(acptr) || !IsServer(acptr)) {
		send_me_numeric(sptr, ERR_NOSUCHSERVER, parv[server]);
		return (HUNTED_NOSUCH);
	    }
	} else {
	    for (acptr = GlobalClientList;
		 (acptr = next_client(acptr, parv[server])); acptr = acptr->next) {
		if (acptr->from == sptr->from && !MyConnect(acptr))
		    continue;
		/*
		 * Fix to prevent looping in case the parameter for some
		 * reason happens to match someone from the from link --jto
		 */
		if (IsRegistered(acptr) && (acptr != cptr))
		    break;
	    }
	}
    }

    if (acptr) {
	if (IsMe(acptr) || MyClient(acptr))
	    return HUNTED_ISME;
	if (match(acptr->name, parv[server]))
	    parv[server] = acptr->name;

	/* Please note that the following line REQUIRES the usage of
	 * hunt_server with token elements.
	 * -TimeMr14C
	 */

	sendto_one(acptr, command, parv[0],
		   (IsToken1(acptr->from) ? token :
		    tok1_msgtab[(u_char) *token].cmd), parv[1], parv[2],
		   parv[3], parv[4], parv[5], parv[6], parv[7], parv[8]);
	return (HUNTED_PASS);
    }
    send_me_numeric(sptr, ERR_NOSUCHSERVER, parv[server]);
    return (HUNTED_NOSUCH);
}

#define LUSERS_CACHE_TIME 180

    /*
     * send_lusers
     *     parv[0] = sender
     *     parv[1] = host/server mask.
     *     parv[2] = server to query
     */
int send_lusers(aClient *cptr, aClient *sptr, int parc, char *parv[])
{
    send_me_numeric(sptr, RPL_LUSERCLIENT, Count.total, Count.invisi, Count.server);
    if (Count.service && Count.myservice)
	sendto_one(sptr,
		   ":%C %N %s :There are %d services online, I have %d services.",
		   &me, RPL_SERVICE, sptr->name, Count.service, Count.myservice);
    else if (Count.service)
	sendto_one(sptr, ":%C %N %s :There are %d services online.",
		   &me, RPL_SERVICE, sptr->name, Count.service);
    if (Count.oper)
	send_me_numeric(sptr, RPL_LUSEROP, Count.oper);
    if (Count.unknown)
	send_me_numeric(sptr, RPL_LUSERUNKNOWN, Count.unknown);
    if (Count.chan)
	send_me_numeric(sptr, RPL_LUSERCHANNELS, Count.chan);
    send_me_numeric(sptr, RPL_LUSERME, Count.local,
		    (ServicesConf.hide_ulined_servers && IsSeeHidden(sptr)) ?
		    Count.myserver : Count.myserver - Count.myulined);
    send_me_numeric(sptr, RPL_LOCALUSERS, Count.local, Count.max_loc);
    send_me_numeric(sptr, RPL_GLOBALUSERS, Count.total, Count.max_tot);
    return 0;
}



syntax highlighted by Code2HTML, v. 0.9.1