/** 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; } } }
/** 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; }
/** 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; } } }
/* ** 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; }
/* * 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); }
/* ** 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; }