Example #1
0
/** Report all F-lines to a user.
 * @param[in] to Client requesting statistics.
 * @param[in] sd Stats descriptor for request (ignored).
 * @param[in] param Extra parameter from user (ignored).
 */
void
feature_report(struct Client* to, const struct StatDesc* sd, char* param)
{
  char changed;
  int report;
  int i;

  /* send header so the client knows what we are showing */
  send_reply(to, SND_EXPLICIT | RPL_STATSHEADER,
    "F Feature/Log Value");

  for (i = 0; features[i].type; i++) {
    if ((features[i].flags & FEAT_NODISP) ||
	(features[i].flags & FEAT_MYOPER && !MyOper(to)) ||
	(features[i].flags & FEAT_OPER && !IsAnOper(to)))
      continue; /* skip this one */

 
    changed = (features[i].flags & FEAT_MARK) ? 'F' : 'f';
    report = (features[i].flags & FEAT_MARK) || sd->sd_funcdata;

    switch (features[i].flags & FEAT_MASK) {
    case FEAT_NONE:
      if (features[i].report) /* let the callback handle this */
	(*features[i].report)(to, report);
      break;


    case FEAT_INT: /* Report an F-line with integer values */
      if (features[i].flags & FEAT_MARK) /* it's been changed */
	send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "F %s %d",
		   features[i].type, features[i].v_int);
      break;

    case FEAT_BOOL: /* Report an F-line with boolean values */
      if (report) /* it's been changed */
	send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "%c %s %s",
		   changed, features[i].type, features[i].v_int ? "TRUE" : "FALSE");
      break;

    case FEAT_STR: /* Report an F-line with string values */
      if (report) { /* it's been changed */
	if (features[i].v_str)
	  send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "%c %s %s",
		     changed, features[i].type, features[i].v_str);
	else /* Actually, F:<type> would reset it; you want F:<type>: */
	  send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "%c %s",
		     changed, features[i].type);
      }
      break;
    }
  }
}
Example #2
0
/** Gets the value of a specific feature and reports it to the user.
 * @param[in] from Client trying to get the feature.
 * @param[in] fields Parameters to set, starting with feature name.
 * @param[in] count Number of fields in \a fields.
 * @return Zero (or, theoretically, CPTR_KILLED).
 */
int
feature_get(struct Client* from, const char* const* fields, int count)
{
  struct FeatureDesc *feat;

  assert(0 != from);

  if (count < 1) /* check parameters */
    need_more_params(from, "GET");
  else if ((feat = feature_desc(from, fields[0]))) {
    if ((feat->flags & FEAT_NODISP) ||
	(feat->flags & FEAT_MYOPER && !MyOper(from)) ||
	(feat->flags & FEAT_OPER && !IsAnOper(from))) /* check privs */
      return send_reply(from, ERR_NOPRIVILEGES);

    switch (feat_type(feat)) {
    case FEAT_NONE: /* none, call the callback... */
      if (feat->get) /* if there's a callback, use it */
	(*feat->get)(from, fields + 1, count - 1);
      break;

    case FEAT_INT: /* integer, report integer value */
      send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		 ":Integer value of %s: %d", feat->type, feat->v_int);
      break;

    case FEAT_UINT: /* unsigned integer, report its value */
      send_reply(from, SND_EXPLICIT | RPL_FEATURE,
                 ":Unsigned value of %s: %u", feat->type, feat->v_int);
      break;

    case FEAT_BOOL: /* boolean, report boolean value */
      send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		 ":Boolean value of %s: %s", feat->type,
		 feat->v_int ? "TRUE" : "FALSE");
      break;

    case FEAT_STR: /* string, report string value */
      if (feat->v_str) /* deal with null case */
	send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		   ":String value of %s: %s", feat->type, feat->v_str);
      else
	send_reply(from, SND_EXPLICIT | RPL_FEATURE,
		   ":String value for %s not set", feat->type);
      break;
    }
  }

  return 0;
}
Example #3
0
/** Report all F-lines to a user.
 * @param[in] to Client requesting statistics.
 * @param[in] sd Stats descriptor for request (ignored).
 * @param[in] param Extra parameter from user (ignored).
 */
void
feature_report(struct Client* to, const struct StatDesc* sd, char* param)
{
  int i;

  for (i = 0; features[i].type; i++) {
    if ((features[i].flags & FEAT_NODISP) ||
	(features[i].flags & FEAT_MYOPER && !MyOper(to)) ||
	(features[i].flags & FEAT_OPER && !IsAnOper(to)))
      continue; /* skip this one */

    switch (features[i].flags & FEAT_MASK) {
    case FEAT_NONE:
      if (features[i].report) /* let the callback handle this */
	(*features[i].report)(to, features[i].flags & FEAT_MARK ? 1 : 0);
      break;


    case FEAT_INT: /* Report an F-line with integer values */
      if (features[i].flags & FEAT_MARK) /* it's been changed */
	send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "F %s %d",
		   features[i].type, features[i].v_int);
      break;

    case FEAT_BOOL: /* Report an F-line with boolean values */
      if (features[i].flags & FEAT_MARK) /* it's been changed */
	send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "F %s %s",
		   features[i].type, features[i].v_int ? "TRUE" : "FALSE");
      break;

    case FEAT_STR: /* Report an F-line with string values */
      if (features[i].flags & FEAT_MARK) { /* it's been changed */
	if (features[i].v_str)
	  send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "F %s %s",
		     features[i].type, features[i].v_str);
	else /* Actually, F:<type> would reset it; you want F:<type>: */
	  send_reply(to, SND_EXPLICIT | RPL_STATSFLINE, "F %s",
		     features[i].type);
      }
      break;
    }
  }
}
Example #4
0
/*
** m_whowas
**      parv[1] = nickname queried
*/
static int
m_whowas(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{	
	struct Whowas *temp;
	int cur = 0;
	int max = -1, found = 0;
	char *p;
	const char *nick;
	char tbuf[26];

	static time_t last_used = 0L;

	if(!IsOper(source_p))
	{
		if((last_used + ConfigFileEntry.pace_wait_simple) > rb_current_time())
		{
			sendto_one(source_p, form_str(RPL_LOAD2HI),
				   me.name, source_p->name, "WHOWAS");
			sendto_one(source_p, form_str(RPL_ENDOFWHOWAS),
				   me.name, source_p->name, parv[1]);
			return 0;
		}
		else
			last_used = rb_current_time();
	}


	if(parc > 2)
		max = atoi(parv[2]);

#if 0
	if(parc > 3)
		if(hunt_server(client_p, source_p, ":%s WHOWAS %s %s :%s", 3, parc, parv))
			return 0;
#endif

	if((p = strchr(parv[1], ',')))
		*p = '\0';

	nick = parv[1];

	temp = WHOWASHASH[hash_whowas_name(nick)];
	found = 0;
	for (; temp; temp = temp->next)
	{
		if(!irccmp(nick, temp->name))
		{
			sendto_one(source_p, form_str(RPL_WHOWASUSER),
				   me.name, source_p->name, temp->name,
				   temp->username, temp->hostname, temp->realname);
			if (MyOper(source_p) && !EmptyString(temp->sockhost))
#if 0
				sendto_one(source_p, form_str(RPL_WHOWASREAL),
					   me.name, source_p->name, temp->name,
					   "<untracked>", temp->sockhost);
#else
				sendto_one_numeric(source_p, RPL_WHOISACTUALLY,
						   form_str(RPL_WHOISACTUALLY),
						   temp->name, temp->sockhost);
#endif
			if (!EmptyString(temp->suser))
				sendto_one_numeric(source_p, RPL_WHOISLOGGEDIN,
						   "%s %s :was logged in as",
						   temp->name, temp->suser);
                        if(SeesServers(source_p))
			sendto_one_numeric(source_p, RPL_WHOISSERVER,
					   form_str(RPL_WHOISSERVER),
					   temp->name, temp->servername,
					   rb_ctime(temp->logoff, tbuf, sizeof(tbuf)));
			else
			sendto_one_numeric(source_p, RPL_WHOISSERVER,
					   form_str(RPL_WHOISSERVER),
					   temp->name, source_p->servptr->mname,
					   rb_ctime(temp->logoff, tbuf, sizeof(tbuf)));
			cur++;
			found++;
		}
		if(max > 0 && cur >= max)
			break;
	}

	if(!found)
		sendto_one(source_p, form_str(ERR_WASNOSUCHNICK), 
			   me.name, source_p->name, nick);

	sendto_one(source_p, form_str(RPL_ENDOFWHOWAS), 
		   me.name, source_p->name, parv[1]);
	return 0;
}
Example #5
0
/*
 * handle_opers
 *
 * inputs	- server pointer
 *		- client pointer
 *		- nick stuff to grok for opers
 *		- text to send if grok
 * output	- none
 * side effects	- all the traditional oper type messages are parsed here.
 *		  i.e. "/msg #some.host."
 *		  However, syntax has been changed.
 *		  previous syntax "/msg #some.host.mask"
 *		  now becomes     "/msg $#some.host.mask"
 *		  previous syntax of: "/msg $some.server.mask" remains
 *		  This disambiguates the syntax.
 */
static void
handle_opers(int p_or_n, char *command, struct Client *client_p,
             struct Client *source_p, char *nick, char *text)
{
  struct Client *target_p;
  char *host;
  char *server;
  char *s;
  int count;

  /*
   * the following two cases allow masks in NOTICEs
   * (for OPERs only)
   *
   * Armin, 8Jun90 ([email protected])
   */
  if(*nick == '$')
  {
    if((*(nick+1) == '$' || *(nick+1) == '#'))
      nick++;
    else if(MyOper(source_p))
    {
      sendto_one(source_p, 
                 ":%s NOTICE %s :The command %s %s is no longer supported, please use $%s",
		 me.name, source_p->name, command, nick, nick);
      return;
    }
      
    if ((s = strrchr(nick, '.')) == NULL)
    {
      sendto_one(source_p, form_str(source_p,ERR_NOTOPLEVEL),
                 me.name, source_p->name, nick);
      return;
    }
    while (*++s)
      if (*s == '.' || *s == '*' || *s == '?')
        break;
    if (*s == '*' || *s == '?')
    {
      sendto_one(source_p, form_str(source_p,ERR_WILDTOPLEVEL),
                 me.name, source_p->name, nick);
      return;
    }
    
    sendto_match_butone(IsServer(client_p) ? client_p : NULL, source_p,
                        nick + 1,
                        (*nick == '#') ? MATCH_HOST : MATCH_SERVER,
                        "%s $%s :%s", command, nick, text);

    if ((p_or_n != NOTICE) && source_p->user)
      source_p->user->last = CurrentTime;

    return;
  }

  /*
   * user[%host]@server addressed?
   */
  if ((server = strchr(nick, '@')) && (target_p = find_server(server + 1)))
  {
    count = 0;

    /*
     * Not destined for a user on me :-(
     */

    if (!IsMe(target_p))
    {
      sendto_one(target_p, ":%s %s %s :%s", source_p->name,
                 command, nick, text);
      if ((p_or_n != NOTICE) && source_p->user)
        source_p->user->last = CurrentTime;
      return;
    }

    *server = '\0';

    if ((host = strchr(nick, '%')) != NULL)
      *host++ = '\0';

    /* Check if someones msg'ing [email protected] */
    if (strcmp(nick, "opers") == 0)
    {
      sendto_realops_flags(FLAGS_ALL, L_ALL, "To opers: From: %s: %s",
                           source_p->name, text);
      return;
    }

    /*
     * Look for users which match the destination host
     * (no host == wildcard) and if one and one only is
     * found connected to me, deliver message!
     */
    target_p = find_userhost(nick, host, &count);

    if (target_p != NULL)
    {
      if (server != NULL)
	*server = '@';
      if (host != NULL)
	*--host = '%';

      if (count == 1)
      {
        sendto_anywhere(target_p, source_p, "%s %s :%s", command,
			nick, text);
        if ((p_or_n != NOTICE) && source_p->user)
          source_p->user->last = CurrentTime;
      }
      else
        sendto_one(source_p, form_str(source_p,ERR_TOOMANYTARGETS),
                   me.name, source_p->name, nick);
    }
  }
  else if (server && *(server+1) && (target_p == NULL))
    sendto_one(source_p, form_str(source_p,ERR_NOSUCHSERVER), me.name,
               source_p->name, server+1);
  else if (server && (target_p == NULL))
    sendto_one(source_p, form_str(source_p,ERR_NOSUCHNICK), me.name,
               source_p->name, nick);
}
Example #6
0
/*
** m_whois
**      parv[0] = sender prefix
**      parv[1] = nickname masklist
*/
int     m_whois(struct Client *cptr,
                struct Client *sptr,
                int parc,
                char *parv[])
{
  static anUser UnknownUser =
  {
    NULL,       /* next */
    NULL,       /* channel */
    NULL,       /* invited */
	NULL,		/* silence */
    NULL,       /* away */
    0,          /* last */
    1,          /* refcount */
    0,          /* joined */
    "<Unknown>"         /* server */
  };
  static char rpl_oper[] = "an IRC Operator";
  static char rpl_locop[] = "an IRC Operator - Local IRC Operator";
  static char rpl_sadmin[] = "an IRC Operator - Services Administrator";
  static char rpl_admin[] = "an IRC Operator - Server Administrator";   
  static char rpl_tadmin[] = "an IRC Operator - Technical Administrator";
  static char rpl_nadmin[] = "an IRC Operator - Network Administrator"; 
  
  Link  *lp;
  anUser        *user;
  struct Client *acptr, *a2cptr;
  aChannel *chptr;
  char  *nick, *name;
  /* char  *tmp; */
  char  *p = NULL;
  int   found, len, mlen;
  static time_t last_used=0L;
  char *nick_match=NULL, *user_match=NULL, *host_match=NULL, *server_match=NULL;
  char *name_match=NULL;
  int found_mode;
  int hits = 0;
  char *mename = me.name;

  if(sptr->user && sptr->user->vlink)
    mename = sptr->user->vlink->name;
  
  if (parc < 2)
    {
      sendto_one(sptr, form_str(ERR_NONICKNAMEGIVEN),
                 mename, parv[0]);
      return 0;
    }

  if(parc > 2)
    {
      if (hunt_server(cptr,sptr,":%s WHOIS %s :%s", 1,parc,parv) !=
          HUNTED_ISME)
        return 0;
      parv[1] = parv[2];
    }

  if(!IsAnOper(sptr) && !MyConnect(sptr)) /* pace non local requests */
    {
      if((last_used + WHOIS_WAIT) > CurrentTime)
        {
          /* Unfortunately, returning anything to a non local
           * request =might= increase sendq to be usable in a split hack
           * Sorry gang ;-( - Dianora
           */
          return 0;
        }
      else
        {
          last_used = CurrentTime;
        }
    }

  /* Multiple whois from remote hosts, can be used
   * to flood a server off. One could argue that multiple whois on
   * local server could remain. Lets think about that, for now
   * removing it totally. 
   * -Dianora 
   */

  /*  for (tmp = parv[1]; (nick = strtoken(&p, tmp, ",")); tmp = NULL) */
  nick = parv[1];
  p = strchr(parv[1],',');
  if(p)
    *p = '\0';

    {
      int       invis, member, wilds;
      found = 0;
      (void)collapse(nick);
      wilds = (nick[0]=='$' || strchr(nick, '?') || strchr(nick, '*'));
      /*
      ** We're no longer allowing remote users to generate
      ** requests with wildcards.
      */
      if (wilds && !IsAnOper(sptr))
        {
          sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                     mename, parv[0], nick);
          return 0;
        }
      /*        continue; */

      /* If the nick doesn't have any wild cards in it,
       * then just pick it up from the hash table
       * - Dianora 
       */

      if(!wilds)
        {
          acptr = hash_find_client(nick,(struct Client *)NULL);
          if(!acptr)
            {
              sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                         mename, parv[0], nick);

              sendto_one(sptr, form_str(RPL_ENDOFWHOIS),
                         mename, parv[0], parv[1]);
						 
              return 0;
              /*              continue; */
            }
          if(IsStealth(acptr)) { 
	    sendto_one(sptr, form_str(ERR_NOSUCHNICK), mename,
	     parv[0], nick);
	     return 0; // Add by ^Stinger^ after the idea of Soldier (:
	  } 
	  if(!IsPerson(acptr))
            {
              sendto_one(sptr, form_str(RPL_ENDOFWHOIS),
                         mename, parv[0], parv[1]);
              return 0;
            }
            /*      continue; */

          user = acptr->user ? acptr->user : &UnknownUser;
          name = (!*acptr->name) ? "?" : acptr->name;
          invis = IsInvisible(acptr);
          member = (user->channel) ? 1 : 0;

          a2cptr = find_server(user->server);
          
          sendto_one(sptr, form_str(RPL_WHOISUSER), mename,
        	    parv[0], name, acptr->username, acptr->host, acptr->info);

	  if((IsOper(sptr) || (acptr == sptr)) && WhoisExtension)
	  {
		sendto_one(sptr, form_str(RPL_WHOISREALHOST), mename,
		    parv[0], name, acptr->realhost);
	  }

          mlen = strlen(mename) + strlen(parv[0]) + 6 +
            strlen(name);
			
          *buf = '\0';			
          if (IsSsl(acptr))
          {
              sendto_one(sptr, form_str(RPL_WHOISSECURE), mename, parv[0], parv[1]);
          }

		  if(((!IsPrivate(acptr) || IsOper(sptr)) || (acptr==sptr))
		  && !IsStealth(acptr))
          for (len = 0, *buf = '\0', lp = user->channel; lp;
               lp = lp->next)
            {
              chptr = lp->value.chptr;
              if (ShowChannel(sptr, chptr))
                {
                  if (len + strlen(chptr->chname)
                      > (size_t) BUFSIZE - 4 - mlen)
                    {
                      sendto_one(sptr,
                                 ":%s %d %s %s :%s",
                                 mename,
                                 RPL_WHOISCHANNELS,
                                 parv[0], name, buf);
                      *buf = '\0';
                      len = 0;
                    }

		  found_mode = user_channel_mode(acptr, chptr);
#ifdef HIDE_OPS
		  if(is_chan_op(sptr,chptr))
#endif
		    {
		      if(found_mode & CHFL_CHANOP)
			*(buf + len++) = '@';
#ifdef HALFOPS
                     else if (found_mode & CHFL_HALFOP)
                       *(buf + len++) = '%';
#endif
		      else if (found_mode & CHFL_VOICE)
			*(buf + len++) = '+';
		    }
                  if (len)
                    *(buf + len) = '\0';
                  (void)strcpy(buf + len, chptr->chname);
                  len += strlen(chptr->chname);
                  (void)strcat(buf + len, " ");
                  len++;
                }
            }
          if (buf[0] != '\0')
            sendto_one(sptr, form_str(RPL_WHOISCHANNELS),
                       mename, parv[0], name, buf);
          if(IsAnOper(sptr) || !HideServerOnWhois)
            {
#ifdef SERVERHIDE
            if (!(IsAnOper(sptr) || acptr == sptr))
              sendto_one(sptr, form_str(RPL_WHOISSERVER),
                       mename, parv[0], name, NetworkName,
                       NetworkDesc);
            else
#endif
            if(acptr->user && acptr->user->vlink)
              sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->vlink->name,
                     user->vlink->passwd);
            else
              {
                if(!IsService(acptr) || IsAnOper(sptr) || !HideServicesServer)
                sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->server,
                     a2cptr?a2cptr->info:"*Not On This Net*");
              }
	    } /* if(IsAnOper(sptr) || HideServerOnWhois) */
	  if (IsIdentified(acptr))
            sendto_one(sptr, form_str(RPL_WHOISIDENTIFIED),
                       mename, parv[0], name);

          if (IsHelper(acptr))
        	sendto_one(sptr, form_str(RPL_WHOISHELPOP),
                           mename, parv[0], name);
					   
          if(IsOper(sptr) && WhoisExtension)
	  {
	    sendto_one(sptr, form_str(RPL_WHOISMODE),
		mename, parv[0], name, get_mode_string(acptr));
	  }
	  
	  if (user->away)
            sendto_one(sptr, form_str(RPL_AWAY), mename,
                       parv[0], name, user->away);
	if(!IsHideOper(acptr) || IsOper(sptr))
	  {	
	    if (IsNetAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_nadmin);
	    else if (IsTechAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_tadmin);						   
            else if (IsSAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                      mename, parv[0], name, rpl_sadmin);						   
            else if (IsAdmin(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),  
                      mename, parv[0], name, rpl_admin);
            else if (IsOper(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR), 
            	mename, parv[0], name, rpl_oper);
            else if (IsLocOp(acptr))
              sendto_one(sptr, form_str(RPL_WHOISOPERATOR),
            	mename, parv[0], name, rpl_locop);
	  }
#ifdef WHOIS_NOTICE
          if ((IsOper(acptr)) && ((acptr)->umodes & UMODE_SPY) &&
              (MyConnect(sptr)) && (IsPerson(sptr)) && (acptr != sptr) && !is_silenced(sptr, acptr))
            sendto_one(acptr,
                       ":%s NOTICE %s :*** Notice -- %s (%s@%s) is doing a /whois on you.",
                       me.name, acptr->name, parv[0], sptr->username,
                       sptr->realhost);
#endif /* #ifdef WHOIS_NOTICE */


          if ((acptr->user
#ifdef SERVERHIDE
              && IsAnOper(sptr)
#endif
              && MyConnect(acptr)))
            sendto_one(sptr, form_str(RPL_WHOISIDLE),
                       mename, parv[0], name,
                       CurrentTime - user->last,
                       acptr->firsttime);
					   
          sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]);
          
          return 0;
          /*      continue; */
        }

      /* wild is true so here we go */
          if(nick[0]==':') /* real name match */
            {
              name_match =  &nick[1];
              nick_match = NULL;
            }
          else
	  if(nick[0]=='$') /* server name match */
	    {
	      server_match = &nick[1];
	      nick_match = NULL;
	    }
	  else
		{
		  host_match = strchr(nick,'@');
		  if(host_match)
			{
			  if(*host_match)
				*(host_match++) = '\0';						  
			  user_match=nick;		  		  
			  if(host_match=='\0')
				host_match="*";		  			
			  if(user_match=='\0')
			  user_match="*";		  
			}
		  else
			nick_match = nick;
		}
		
	  				
      for (acptr = GlobalClientList; acptr;
           acptr = acptr->next)
        {
          if (IsServer(acptr))
            continue;
          /*
           * I'm always last :-) and acptr->next == NULL!!
           */
          if (IsMe(acptr))
            break;
          /*
           * 'Rules' established for sending a WHOIS reply:
           *
           *
           * - if wildcards are being used dont send a reply if
           *   the querier isnt any common channels and the
           *   client in question is invisible and wildcards are
           *   in use (allow exact matches only);
           *
           * - only send replies about common or public channels
           *   the target user(s) are on;
           */

/* If its an unregistered client, ignore it, it can
   be "seen" on a /trace anyway  -Dianora */

          if(!IsRegistered(acptr))
            continue;

          user = acptr->user ? acptr->user : &UnknownUser;
          name = (!*acptr->name) ? "?" : acptr->name;
		  
		  if(  (server_match && !match(server_match, user->server))
		    || (nick_match && !match(nick, name)) 
			|| (host_match && !match(host_match, acptr->realhost)
			   && !match(host_match, acptr->host))
			|| (user_match && !match(user_match, acptr->username))
			|| (name_match &&  !match(name_match, acptr->info))
			)
        	  continue;
			  
		  ++hits;
			  
          a2cptr = find_server(user->server);
          
          sendto_one(sptr, form_str(RPL_WHOISUSER), mename,
                    parv[0], name,
                    acptr->username, 
					IsOper(sptr) ? acptr->realhost : acptr->host,					 
					acptr->info);
					
          found = 1;
          mlen = strlen(mename) + strlen(parv[0]) + 6 +
            strlen(name);
          for (len = 0, *buf = '\0', lp = user->channel; lp;
               lp = lp->next)
            {
              chptr = lp->value.chptr;
              if (ShowChannel(sptr, chptr))
                {
                  if (len + strlen(chptr->chname)
                      > (size_t) BUFSIZE - 4 - mlen)
                    {
                      sendto_one(sptr,
                                 ":%s %d %s %s :%s",
                                 mename,
                                 RPL_WHOISCHANNELS,
                                 parv[0], name, buf);
                      *buf = '\0';
                      len = 0;
                    }
		  found_mode = user_channel_mode(acptr, chptr);
#ifdef HIDE_OPS
                  if(is_chan_op(sptr,chptr))
#endif
		     {
		       if (found_mode & CHFL_CHANOP)
			 *(buf + len++) = '@';
#ifdef HALFOPS
                     else if (found_mode & CHFL_HALFOP)
                        *(buf + len++) = '%';
#endif                                            
		       else if (found_mode & CHFL_VOICE)
			 *(buf + len++) = '+';
		     }
                  if (len)
                    *(buf + len) = '\0';
                  (void)strcpy(buf + len, chptr->chname);
                  len += strlen(chptr->chname);
                  (void)strcat(buf + len, " ");
                  len++;
                }
            }
          if (buf[0] != '\0')
            sendto_one(sptr, form_str(RPL_WHOISCHANNELS),
                       mename, parv[0], name, buf);
         
#ifdef SERVERHIDE
          if (!(IsAnOper(sptr) || acptr == sptr))
            sendto_one(sptr, form_str(RPL_WHOISSERVER),
                       mename, parv[0], name, NetworkName,
                       NetworkDesc);
          else    
#endif
          sendto_one(sptr, form_str(RPL_WHOISSERVER),
                     mename, parv[0], name, user->server,
                     a2cptr?a2cptr->info:"*Not On This Net*");

          if (user->away)
            sendto_one(sptr, form_str(RPL_AWAY), mename,
                       parv[0], name, user->away);



  		  if (IsNetAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_nadmin);
		  else if (IsTechAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_tadmin);						   
          else if (IsSAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),   
                           mename, parv[0], name, rpl_sadmin);						   
          else if (IsAdmin(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR),  
                           mename, parv[0], name, rpl_admin);
          else if (IsAnOper(acptr))
                sendto_one(sptr, form_str(RPL_WHOISOPERATOR), 
                           mename, parv[0], name, rpl_oper);


#ifdef WHOIS_NOTICE
          if ((MyOper(acptr)) && ((acptr)->umodes & UMODE_SPY) &&
              (MyConnect(sptr)) && (IsPerson(sptr)) && (acptr != sptr))
            sendto_one(acptr,
                       ":%s NOTICE %s :*** Notice -- %s (%s@%s) is doing a /whois on you.",
                       mename, acptr->name, parv[0], sptr->username,
                       sptr->realhost);
#endif /* #ifdef WHOIS_NOTICE */

          if ((acptr->user
#ifdef SERVERHIDE
              && IsAnOper(sptr) 
#endif                 
              && MyConnect(acptr)))
            sendto_one(sptr, form_str(RPL_WHOISIDLE),
                       mename, parv[0], name,
                       CurrentTime - user->last,
                       acptr->firsttime);

		if(hits>50)
		  {
  			sendto_one(sptr,":%s NOTICE %s :Aborting /whois output as flood prevention",
				mename, sptr->name);			  
			break;
		  }
        }
		
      if (!found)	  
        sendto_one(sptr, form_str(ERR_NOSUCHNICK),
                   mename, parv[0], nick);
	  else
		sendto_one(sptr,":%s NOTICE %s :This /whois matched \2%i\2 user(s)", 
			mename, sptr->name,hits);
      /*
      if (p)
        p[-1] = ',';
        */
    }

  sendto_one(sptr, form_str(RPL_ENDOFWHOIS), mename, parv[0], parv[1]);
  
  return 0;
}