コード例 #1
0
ファイル: zline.c プロジェクト: evilnet/nefarious2
/** Create a Zline structure.
 * @param[in] mask Mask.
 * @param[in] reason Reason for Z-line.
 * @param[in] expire Expiration timestamp.
 * @param[in] lastmod Last modification timestamp.
 * @param[in] flags Bitwise combination of ZLINE_* bits.
 * @return Newly allocated Z-line.
 */
static struct Zline *
make_zline(char *mask, char *reason, time_t expire, time_t lastmod,
	   time_t lifetime, unsigned int flags)
{
  struct Zline *zline;

  assert(0 != expire);

  zline = (struct Zline *)MyMalloc(sizeof(struct Zline)); /* alloc memory */
  assert(0 != zline);

  DupString(zline->zl_reason, reason); /* initialize zline... */
  zline->zl_expire = expire;
  zline->zl_lifetime = lifetime;
  zline->zl_lastmod = lastmod;
  zline->zl_flags = flags & ZLINE_MASK;
  zline->zl_state = ZLOCAL_GLOBAL; /* not locally modified */

  DupString(zline->zl_mask, mask);

  if (ipmask_parse(mask, &zline->zl_addr, &zline->zl_bits)) {
    zline->zl_flags |= ZLINE_IPMASK;
    zline->zl_addr = ipmask_clean(&zline->zl_addr, zline->zl_bits);
  }

  zline->zl_next = GlobalZlineList; /* then link it into list */
  zline->zl_prev_p = &GlobalZlineList;
  if (GlobalZlineList)
    GlobalZlineList->zl_prev_p = &zline->zl_next;
  GlobalZlineList = zline;

  return zline;
}
コード例 #2
0
ファイル: zline.c プロジェクト: evilnet/nefarious2
/** Count number of users who match \a mask.
 * @param[in] mask ip mask to check.
 * @param[in] flags Bitmask possibly containing the value ZLINE_LOCAL, to limit searches to this server.
 * @return Count of matching users.
 */
static int
count_users(char *mask, int flags)
{
  struct irc_in_addr ipmask;
  struct Client *acptr;
  int count = 0;
  int ipmask_valid;
  char ipbuf[SOCKIPLEN + 2];
  unsigned char ipmask_len;

  ipmask_valid = ipmask_parse(mask, &ipmask, &ipmask_len);
  for (acptr = GlobalClientList; acptr; acptr = cli_next(acptr)) {
    if (!IsUser(acptr))
      continue;
    if ((flags & ZLINE_LOCAL) && !MyConnect(acptr))
      continue;

    ircd_snprintf(0, ipbuf, sizeof(ipbuf), "%s", ircd_ntoa(&cli_ip(acptr)));

    if (!match(mask, ipbuf)
        || (ipmask_valid && ipmask_check(&cli_ip(acptr), &ipmask, ipmask_len)
            && (irc_in_addr_type_cmp(&cli_ip(acptr), &ipmask) && ipmask_len)))
      count++;
  }

  return count;
}
コード例 #3
0
ファイル: ns-cidr.c プロジェクト: quakenet/newserv
struct searchNode *cidr_parse(searchCtx *ctx, int argc, char **argv) {
  struct searchNode *thenode, *convsn;
  struct cidr_localdata *c;
  struct irc_in_addr ip;
  unsigned char bits;
  char *p;
  int ret;
  
  if(argc != 1) {
    parseError = "usage: cidr ip/mask";
    return NULL;
  }

  if (!(convsn=argtoconststr("cidr", ctx, argv[0], &p)))
    return NULL;
  
  ret = ipmask_parse(p, &ip, &bits);
  convsn->free(ctx, convsn);
  
  if(!ret) {
    parseError = "usage: cidr ip/mask";
    return NULL;
  }
  
  if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
    parseError = "malloc: could not allocate memory for this search.";
    return NULL;
  }

  thenode->returntype = RETURNTYPE_BOOL;
  if (!(c = malloc(sizeof(struct cidr_localdata)))) {
    /* couldn't malloc() memory for thenode->localdata, so free thenode to avoid leakage */
    parseError = "malloc: could not allocate memory for this search.";
    free(thenode);
    return NULL;
  }

  memcpy(&c->ip, &ip, sizeof(struct irc_in_addr));
  c->bits = bits;

  thenode->localdata = (void *)c;
  thenode->free = cidr_free;
  thenode->exe = cidr_exe;

  return thenode;
}
コード例 #4
0
ファイル: trusts_commands.c プロジェクト: quakenet/newserv
static int trusts_cmdtrustglinesuggest(void *source, int cargc, char **cargv) {
  nick *sender = source;
  char mask[512];
  char *p, *user, *host;
  struct irc_in_addr ip;
  unsigned char bits;
  int count;
  glinebuf gbuf;
  char creator[32];

  if(cargc < 1)
    return CMD_USAGE;

  strncpy(mask, cargv[0], sizeof(mask));

  p = strchr(mask, '@');

  if(!p)
    return CMD_USAGE;

  user = mask;
  host = p + 1;
  *p = '\0';

  if(!ipmask_parse(host, &ip, &bits)) {
    controlreply(sender, "Invalid CIDR.");
    return CMD_ERROR;
  }

  snprintf(creator, sizeof(creator), "#%s", sender->authname);

  glinebufinit(&gbuf, 0);
  glinebufaddbyip(&gbuf, user, &ip, 128, 0, creator, "Simulate", getnettime(), getnettime(), getnettime());
  glinebufcounthits(&gbuf, &count, NULL);
  glinebufspew(&gbuf, sender);
  glinebufabort(&gbuf);

  controlreply(sender, "Total hits: %d", count);

  return CMD_OK;
}
コード例 #5
0
ファイル: motd.c プロジェクト: DamnIO/DamnIRCd
/** Create a struct Motd and initialize it.
 * @param[in] hostmask Hostmask (or connection class name) to filter on.
 * @param[in] path Path to MOTD file.
 * @param[in] maxcount Maximum number of lines permitted for MOTD.
 */
static struct Motd *
motd_create(const char *hostmask, const char *path, int maxcount, int type)
{
  struct Motd* tmp;

  assert(0 != path);

  /* allocate memory and initialize the structure */
  if (MotdList.freelist)
  {
    tmp = MotdList.freelist;
    MotdList.freelist = tmp->next;
  } else
    tmp = (struct Motd *)MyMalloc(sizeof(struct Motd));
  tmp->next = 0;

  if (hostmask == NULL)
    tmp->type = MOTD_UNIVERSAL;
  else if (type == MOTD_COUNTRY)
    tmp->type = MOTD_COUNTRY;
  else if (type == MOTD_CONTINENT)
    tmp->type = MOTD_CONTINENT;
  else if (find_class(hostmask))
    tmp->type = MOTD_CLASS;
  else if (ipmask_parse(hostmask, &tmp->address, &tmp->addrbits))
    tmp->type = MOTD_IPMASK;
  else
    tmp->type = MOTD_HOSTMASK;

  if (hostmask != NULL)
    DupString(tmp->hostmask, hostmask);
  else
    tmp->hostmask = NULL;

  DupString(tmp->path, path);
  tmp->maxcount = maxcount;
  tmp->cache = 0;

  return tmp;
}
コード例 #6
0
ファイル: s_conf.c プロジェクト: kisserlb/enet-1.0
/** Parse a user\@host mask into username and host or IP parts.
 * If \a host contains no username part, set \a aconf->username to
 * NULL.  If the host part of \a host looks like an IP mask, set \a
 * aconf->addrbits and \a aconf->address to match.  Otherwise, set
 * \a aconf->host, and set \a aconf->addrbits to -1.
 * @param[in,out] aconf Configuration item to set.
 * @param[in] host user\@host mask to parse.
 */
void conf_parse_userhost(struct ConfItem *aconf, char *host)
{
  char *host_part;
  unsigned char addrbits;

  MyFree(aconf->username);
  MyFree(aconf->host);
  host_part = strchr(host, '@');
  if (host_part) {
    *host_part = '\0';
    DupString(aconf->username, host);
    host_part++;
  } else {
    aconf->username = NULL;
    host_part = host;
  }
  DupString(aconf->host, host_part);
  if (ipmask_parse(aconf->host, &aconf->address.addr, &addrbits))
    aconf->addrbits = addrbits;
  else
    aconf->addrbits = -1;
}
コード例 #7
0
ファイル: trusts_commands.c プロジェクト: quakenet/newserv
static int trusts_cmdtrustlist(void *source, int cargc, char **cargv) {
  nick *sender = source;
  trustgroup *tg = NULL;
  int found = 0, remaining = 50;
  char *name;
  trusthost *th;
  struct irc_in_addr ip;
  unsigned char bits;
  int showchildren;
  char *cmpbuf;

  if(cargc < 1)
    return CMD_USAGE;

  if(strcmp(cargv[0], "-v") == 0) {
    if(cargc < 2)
      return CMD_USAGE;

    showchildren = 1;
    name = cargv[1];
  } else {
    showchildren = 0;
    name = cargv[0];
  }

  tg = tg_strtotg(name);

  if(tg) {
    displaygroup(sender, tg, showchildren);
    controlreply(sender, "End of list.");
    return CMD_OK;
  }

  if(ipmask_parse(name, &ip, &bits)) {
    th = th_getbyhost(&ip);

    if(!th) {
      controlreply(sender, "Specified IP address is not trusted.");
      return CMD_OK;
    }

    displaygroup(sender, th->group, showchildren);
    controlreply(sender, "End of list.");
    return CMD_OK;
  }

  if(name[0] == '&') {
    int size = strlen(name) + strlen("Qwhois") + 1;
    cmpbuf = alloca(size);
    snprintf(cmpbuf, size, "Qwhois%s", name);
  } else {
    cmpbuf = NULL;
  }

  for(tg=tglist;tg;tg=tg->next) {
    if(cmpbuf) {
      if(!tg->contact->content || strcasecmp(cmpbuf, tg->contact->content))
        continue;
    } else if(match(name, tg->name->content)) {
      continue;
    }

    displaygroup(sender, tg, showchildren);
    if(--remaining == 0) {
      controlreply(sender, "Maximum number of matches reached.");
      return CMD_OK;
    }
    found = 1;
  }

  if(found) {
    controlreply(sender, "End of list.");
  } else {
    controlreply(sender, "No matches found.");
  }

  return CMD_OK;
}
コード例 #8
0
ファイル: send.c プロジェクト: mojadita/ircd
/** Send a (prefixed) command to all users matching \a to as \a who.
 * @warning \a pattern must not contain %v.
 * @param[in] from Source of the command.
 * @param[in] cmd Long name of command.
 * @param[in] tok Short name of command.
 * @param[in] to Destination host/server mask.
 * @param[in] one Client direction to skip (or NULL).
 * @param[in] who Type of match for \a to (either MATCH_HOST or MATCH_SERVER).
 * @param[in] pattern Format string for command arguments.
 */
void sendcmdto_match(struct Client *from, const char *cmd,
                     const char *tok, const char *to,
                     struct Client *one, unsigned int who,
                     const char *pattern, ...)
{
  struct VarData vd;
  struct irc_in_addr addr;
  struct Client *cptr;
  struct MsgBuf *user_mb;
  struct MsgBuf *serv_mb;
  unsigned char nbits;

  vd.vd_format = pattern;

  /* See if destination looks like an IP mask. */
  if (!ipmask_parse(to, &addr, &nbits))
    nbits = 255;

  /* Build buffer to send to users */
  va_start(vd.vd_args, pattern);
/*
TODO-ZOLTAN: Revisar el tema de Globales
  if (IsUser(from) && IsService(cli_user(from)->server))
*/
  user_mb = msgq_make(0, "%:#C %s %v", from, cmd, &vd);
/*
  else
  {
    char *mask, *msg;
    mask = (char *)va_arg(vd.vd_args, char *);
    msg = (char *)va_arg(vd.vd_args, char *);

    user_mb = msgq_make(0, "%:#C %s :*** Global Message -> (%s): %s",
                        from, cmd, mask, msg);
  }
*/
  va_end(vd.vd_args);

  /* Build buffer to send to servers */
  va_start(vd.vd_args, pattern);
  serv_mb = msgq_make(&me, "%C %s %v", from, tok, &vd);
  va_end(vd.vd_args);

  /* send buffer along */
  bump_sentalong(one);
  for (cptr = GlobalClientList; cptr; cptr = cli_next(cptr)) {
    if (cli_sentalong(cptr) == sentalong_marker ||
        !IsRegistered(cptr) ||
        IsServer(cptr) ||
    !match_it(from, cptr, to, &addr, nbits, who) ||
        cli_fd(cli_from(cptr)) < 0)
      continue; /* skip it */
    cli_sentalong(cptr) = sentalong_marker;

    if (MyConnect(cptr)) /* send right buffer */
      send_buffer(cptr, user_mb, 0);
    else
      send_buffer(cptr, serv_mb, 0);
  }

  msgq_clean(user_mb);
  msgq_clean(serv_mb);
}
コード例 #9
0
ファイル: patrol.c プロジェクト: quakenet/newserv
int patrol_isip(char *host) {
  struct irc_in_addr ip;
  unsigned char bits;

  return (ipmask_parse(host, &ip, &bits));
}
コード例 #10
0
ファイル: m_who.c プロジェクト: Compy/Undernet-IRCU
/*
 * m_who - generic message handler
 *
 *  parv[0] = sender prefix
 *  parv[1] = nickname mask list
 *  parv[2] = additional selection flag, only 'o' for now.
 *            and %flags to specify what fields to output
 *            plus a ,querytype if the t flag is specified
 *            so the final thing will be like o%tnchu,777
 *  parv[3] = _optional_ parameter that overrides parv[1]
 *            This can be used as "/quote who foo % :The Black Hacker
 *            to find me, parv[3] _can_ contain spaces !.
 */
int m_who(struct Client* cptr, struct Client* sptr, int parc, char* parv[])
{
  char *mask;           /* The mask we are looking for              */
  char ch;                      /* Scratch char register                    */
  struct Channel *chptr;                /* Channel to show                          */
  struct Client *acptr;         /* Client to show                           */

  int bitsel;                   /* Mask of selectors to apply               */
  int matchsel;                 /* Which fields the match should apply on    */
  int counter;                  /* Query size counter,
                                   initially used to count fields           */
  int commas;                   /* Does our mask contain any comma ?
                                   If so is a list..                        */
  int fields;                   /* Mask of fields to show                   */
  int isthere = 0;              /* When this set the user is member of chptr */
  char *nick;                   /* Single element extracted from
                                   the mask list                            */
  char *p;                      /* Scratch char pointer                     */
  char *qrt;                    /* Pointer to the query type                */
  static char mymask[512];      /* To save the mask before corrupting it    */

  /* Let's find where is our mask, and if actually contains something */
  mask = ((parc > 1) ? parv[1] : 0);
  if (parc > 3 && parv[3])
    mask = parv[3];
  if (mask && ((mask[0] == '\0') ||
      (mask[1] == '\0' && ((mask[0] == '0') || (mask[0] == '*')))))
    mask = 0;

  /* Evaluate the flags now, we consider the second parameter 
     as "matchFlags%fieldsToInclude,querytype"           */
  bitsel = fields = counter = matchsel = 0;
  qrt = 0;
  if (parc > 2 && parv[2] && *parv[2])
  {
    p = parv[2];
    while (((ch = *(p++))) && (ch != '%') && (ch != ','))
      switch (ch)
      {
        case 'd':
        case 'D':
          bitsel |= WHOSELECT_DELAY;
          continue;
        case 'o':
        case 'O':
          bitsel |= WHOSELECT_OPER;
          continue;
        case 'x':
        case 'X':
          bitsel |= WHOSELECT_EXTRA;
          if (HasPriv(sptr, PRIV_WHOX))
	    log_write(LS_WHO, L_INFO, LOG_NOSNOTICE, "%#C WHO %s %s", sptr,
		      (BadPtr(parv[3]) ? parv[1] : parv[3]), parv[2]);
          continue;
        case 'n':
        case 'N':
          matchsel |= WHO_FIELD_NIC;
          continue;
        case 'u':
        case 'U':
          matchsel |= WHO_FIELD_UID;
          continue;
        case 'h':
        case 'H':
          matchsel |= WHO_FIELD_HOS;
          continue;
        case 'i':
        case 'I':
          matchsel |= WHO_FIELD_NIP;
          continue;
        case 's':
        case 'S':
          matchsel |= WHO_FIELD_SER;
          continue;
        case 'r':
        case 'R':
          matchsel |= WHO_FIELD_REN;
          continue;
        case 'a':
        case 'A':
          matchsel |= WHO_FIELD_ACC;
          continue;
      }
    if (ch == '%')
      while ((ch = *p++) && (ch != ','))
      {
        counter++;
        switch (ch)
        {
          case 'c':
          case 'C':
            fields |= WHO_FIELD_CHA;
            break;
          case 'd':
          case 'D':
            fields |= WHO_FIELD_DIS;
            break;
          case 'f':
          case 'F':
            fields |= WHO_FIELD_FLA;
            break;
          case 'h':
          case 'H':
            fields |= WHO_FIELD_HOS;
            break;
          case 'i':
          case 'I':
            fields |= WHO_FIELD_NIP;
            break;
          case 'l':
          case 'L':
            fields |= WHO_FIELD_IDL;
          case 'n':
          case 'N':
            fields |= WHO_FIELD_NIC;
            break;
          case 'r':
          case 'R':
            fields |= WHO_FIELD_REN;
            break;
          case 's':
          case 'S':
            fields |= WHO_FIELD_SER;
            break;
          case 't':
          case 'T':
            fields |= WHO_FIELD_QTY;
            break;
          case 'u':
          case 'U':
            fields |= WHO_FIELD_UID;
            break;
          case 'a':
          case 'A':
            fields |= WHO_FIELD_ACC;
            break;
          case 'o':
          case 'O':
            fields |= WHO_FIELD_OPL;
            break;
          default:
            break;
        }
      };
    if (ch)
      qrt = p;
  }

  if (!matchsel)
    matchsel = WHO_FIELD_DEF;
  if (!fields)
    counter = 7;

  if (feature_bool(FEAT_HIS_WHO_SERVERNAME) && !IsAnOper(sptr))
    matchsel &= ~WHO_FIELD_SER;

  if (qrt && (fields & WHO_FIELD_QTY))
  {
    p = qrt;
    if (!((*p > '9') || (*p < '0')))
      p++;
    if (!((*p > '9') || (*p < '0')))
      p++;
    if (!((*p > '9') || (*p < '0')))
      p++;
    *p = '\0';
  }
  else
    qrt = 0;

  /* I'd love to add also a check on the number of matches fields per time */
  counter = (2048 / (counter + 4));
  if (mask && (strlen(mask) > 510))
    mask[510] = '\0';
  move_marker();
  commas = (mask && strchr(mask, ','));

  /* First treat mask as a list of plain nicks/channels */
  if (mask)
  {
    strcpy(mymask, mask);
    for (p = 0, nick = ircd_strtok(&p, mymask, ","); nick;
        nick = ircd_strtok(&p, 0, ","))
    {
      if (IsChannelName(nick) && (chptr = FindChannel(nick)))
      {
        isthere = (find_channel_member(sptr, chptr) != 0);
        if (isthere || SEE_CHANNEL(sptr, chptr, bitsel))
        {
          struct Membership* member;
          for (member = chptr->members; member; member = member->next_member)
          {
            acptr = member->user;
            if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr))
              continue;
            if ((acptr != sptr)
                && ((member->status & CHFL_ZOMBIE)
                    || ((member->status & CHFL_DELAYED)
                        && !(bitsel & WHOSELECT_DELAY))))
              continue;
            if (!(isthere || (SEE_USER(sptr, acptr, bitsel))))
              continue;
            if (!Process(acptr))        /* This can't be moved before other checks */
              continue;
            if (!(isthere || (SHOW_MORE(sptr, counter))))
              break;
            do_who(sptr, acptr, chptr, fields, qrt);
          }
        }
      }
      else
      {
        if ((acptr = FindUser(nick)) &&
            ((!(bitsel & WHOSELECT_OPER)) || SeeOper(sptr,acptr)) &&
            Process(acptr) && SHOW_MORE(sptr, counter))
        {
          do_who(sptr, acptr, 0, fields, qrt);
        }
      }
    }
  }

  /* If we didn't have any comma in the mask treat it as a
     real mask and try to match all relevant fields */
  if (!(commas || (counter < 1)))
  {
    struct irc_in_addr imask;
    int minlen, cset;
    unsigned char ibits;

    if (mask)
    {
      matchcomp(mymask, &minlen, &cset, mask);
      if (!ipmask_parse(mask, &imask, &ibits))
        matchsel &= ~WHO_FIELD_NIP;
      if ((minlen > NICKLEN) || !(cset & NTL_IRCNK))
        matchsel &= ~WHO_FIELD_NIC;
      if ((matchsel & WHO_FIELD_SER) &&
          ((minlen > HOSTLEN) || (!(cset & NTL_IRCHN))
          || (!markMatchexServer(mymask, minlen))))
        matchsel &= ~WHO_FIELD_SER;
      if ((minlen > USERLEN) || !(cset & NTL_IRCUI))
        matchsel &= ~WHO_FIELD_UID;
      if ((minlen > HOSTLEN) || !(cset & NTL_IRCHN))
        matchsel &= ~WHO_FIELD_HOS;
      if ((minlen > ACCOUNTLEN))
        matchsel &= ~WHO_FIELD_ACC;
    }

    /* First of all loop through the clients in common channels */
    if ((!(counter < 1)) && matchsel) {
      struct Membership* member;
      struct Membership* chan;
      for (chan = cli_user(sptr)->channel; chan; chan = chan->next_channel) {
        chptr = chan->channel;
        for (member = chptr->members; member; member = member->next_member)
        {
          acptr = member->user;
          if (!(IsUser(acptr) && Process(acptr)))
            continue;           /* Now Process() is at the beginning, if we fail
                                   we'll never have to show this acptr in this query */
 	  if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr))
	    continue;
          if ((mask) &&
              ((!(matchsel & WHO_FIELD_NIC))
              || matchexec(cli_name(acptr), mymask, minlen))
              && ((!(matchsel & WHO_FIELD_UID))
              || matchexec(cli_user(acptr)->username, mymask, minlen))
              && ((!(matchsel & WHO_FIELD_SER))
              || (!(HasFlag(cli_user(acptr)->server, FLAG_MAP))))
              && ((!(matchsel & WHO_FIELD_HOS))
              || matchexec(cli_user(acptr)->host, mymask, minlen))
              && ((!(matchsel & WHO_FIELD_HOS))
	      || !HasHiddenHost(acptr)
	      || !IsAnOper(sptr)
              || matchexec(cli_user(acptr)->realhost, mymask, minlen))
              && ((!(matchsel & WHO_FIELD_REN))
              || matchexec(cli_info(acptr), mymask, minlen))
              && ((!(matchsel & WHO_FIELD_NIP))
	      || (HasHiddenHost(acptr) && !IsAnOper(sptr))
              || !ipmask_check(&cli_ip(acptr), &imask, ibits))
              && ((!(matchsel & WHO_FIELD_ACC))
              || matchexec(cli_user(acptr)->account, mymask, minlen)))
            continue;
          if (!SHOW_MORE(sptr, counter))
            break;
          do_who(sptr, acptr, chptr, fields, qrt);
        }
      }
    }
    /* Loop through all clients :-\, if we still have something to match to 
       and we can show more clients */
    if ((!(counter < 1)) && matchsel)
      for (acptr = cli_prev(&me); acptr; acptr = cli_prev(acptr))
      {
        if (!(IsUser(acptr) && Process(acptr)))
          continue;
	if ((bitsel & WHOSELECT_OPER) && !SeeOper(sptr,acptr))
	  continue;
        if (!(SEE_USER(sptr, acptr, bitsel)))
          continue;
        if ((mask) &&
            ((!(matchsel & WHO_FIELD_NIC))
            || matchexec(cli_name(acptr), mymask, minlen))
            && ((!(matchsel & WHO_FIELD_UID))
            || matchexec(cli_user(acptr)->username, mymask, minlen))
            && ((!(matchsel & WHO_FIELD_SER))
                || (!(HasFlag(cli_user(acptr)->server, FLAG_MAP))))
            && ((!(matchsel & WHO_FIELD_HOS))
            || matchexec(cli_user(acptr)->host, mymask, minlen))
            && ((!(matchsel & WHO_FIELD_HOS))
	    || !HasHiddenHost(acptr)
	    || !IsAnOper(sptr)
            || matchexec(cli_user(acptr)->realhost, mymask, minlen))
            && ((!(matchsel & WHO_FIELD_REN))
            || matchexec(cli_info(acptr), mymask, minlen))
            && ((!(matchsel & WHO_FIELD_NIP))
	    || (HasHiddenHost(acptr) && !IsAnOper(sptr))
            || !ipmask_check(&cli_ip(acptr), &imask, ibits))
            && ((!(matchsel & WHO_FIELD_ACC))
            || matchexec(cli_user(acptr)->account, mymask, minlen)))
          continue;
        if (!SHOW_MORE(sptr, counter))
          break;
        do_who(sptr, acptr, 0, fields, qrt);
      }
  }

  /* Make a clean mask suitable to be sent in the "end of" */
  if (mask && (p = strchr(mask, ' ')))
    *p = '\0';
  /* Notify the user if we decided that his query was too long */
  if (counter < 0)
    send_reply(sptr, ERR_QUERYTOOLONG, BadPtr(mask) ? "*" : mask);
  send_reply(sptr, RPL_ENDOFWHO, BadPtr(mask) ? "*" : mask);

  return 0;
}