ircd: import modified version of ratbox 3.1 whowas code

This commit is contained in:
William Pitcock 2016-01-23 11:16:34 -05:00
parent 3de2266243
commit b47f8a4fda
12 changed files with 205 additions and 195 deletions

View file

@ -117,7 +117,8 @@ struct Client
struct Client *servptr; /* Points to server this Client is on */ struct Client *servptr; /* Points to server this Client is on */
struct Client *from; /* == self, if Local Client, *NEVER* NULL! */ struct Client *from; /* == self, if Local Client, *NEVER* NULL! */
struct Whowas *whowas; /* Pointers to whowas structs */ rb_dlink_list whowas_clist;
time_t tsinfo; /* TS on the nick, SVINFO on server */ time_t tsinfo; /* TS on the nick, SVINFO on server */
unsigned int umodes; /* opers, normal users subset */ unsigned int umodes; /* opers, normal users subset */
unsigned int flags; /* client flags */ unsigned int flags; /* client flags */

View file

@ -131,7 +131,7 @@
#define NUMERIC_STR_366 ":%s 366 %s %s :End of /NAMES list." #define NUMERIC_STR_366 ":%s 366 %s %s :End of /NAMES list."
#define NUMERIC_STR_367 ":%s 367 %s %s %s %s %lu" #define NUMERIC_STR_367 ":%s 367 %s %s %s %s %lu"
#define NUMERIC_STR_368 ":%s 368 %s %s :End of Channel Ban List" #define NUMERIC_STR_368 ":%s 368 %s %s :End of Channel Ban List"
#define NUMERIC_STR_369 ":%s 369 %s %s :End of WHOWAS" #define NUMERIC_STR_369 "%s :End of WHOWAS"
#define NUMERIC_STR_371 ":%s" #define NUMERIC_STR_371 ":%s"
#define NUMERIC_STR_372 ":%s 372 %s :- %s" #define NUMERIC_STR_372 ":%s 372 %s :- %s"
#define NUMERIC_STR_374 ":End of /INFO list." #define NUMERIC_STR_374 ":End of /INFO list."
@ -147,7 +147,7 @@
#define NUMERIC_STR_403 "%s :No such channel" #define NUMERIC_STR_403 "%s :No such channel"
#define NUMERIC_STR_404 "%s :Cannot send to channel" #define NUMERIC_STR_404 "%s :Cannot send to channel"
#define NUMERIC_STR_405 ":%s 405 %s %s :You have joined too many channels" #define NUMERIC_STR_405 ":%s 405 %s %s :You have joined too many channels"
#define NUMERIC_STR_406 ":%s 406 %s %s :There was no such nickname" #define NUMERIC_STR_406 ":%s :There was no such nickname"
#define NUMERIC_STR_407 ":%s 407 %s %s :Too many recipients." #define NUMERIC_STR_407 ":%s 407 %s %s :Too many recipients."
#define NUMERIC_STR_409 ":%s 409 %s :No origin specified" #define NUMERIC_STR_409 ":%s 409 %s :No origin specified"
#define NUMERIC_STR_410 ":%s 410 %s %s :Invalid CAP subcommand" #define NUMERIC_STR_410 ":%s 410 %s %s :Invalid CAP subcommand"

View file

@ -31,13 +31,6 @@
#include "setup.h" #include "setup.h"
/*
* Whowas hash table size
*
*/
#define WW_MAX_BITS 16
#define WW_MAX 65536
struct User; struct User;
struct Client; struct Client;
@ -48,7 +41,10 @@ struct Client;
*/ */
struct Whowas struct Whowas
{ {
int hashv; struct whowas_top *wtop;
rb_dlink_node wnode; /* for the wtop linked list */
rb_dlink_node cnode; /* node for online clients */
rb_dlink_node whowas_node; /* node for the whowas linked list */
char name[NICKLEN + 1]; char name[NICKLEN + 1];
char username[USERLEN + 1]; char username[USERLEN + 1];
char hostname[HOSTLEN + 1]; char hostname[HOSTLEN + 1];
@ -59,10 +55,6 @@ struct Whowas
const char *servername; const char *servername;
time_t logoff; time_t logoff;
struct Client *online; /* Pointer to new nickname for chasing or NULL */ struct Client *online; /* Pointer to new nickname for chasing or NULL */
struct Whowas *next; /* for hash table... */
struct Whowas *prev; /* for hash table... */
struct Whowas *cnext; /* for client struct linked list */
struct Whowas *cprev; /* for client struct linked list */
}; };
/* Flags */ /* Flags */
@ -72,7 +64,7 @@ struct Whowas
/* /*
** initwhowas ** initwhowas
*/ */
extern void initwhowas(void); extern void whowas_init(void);
/* /*
** add_history ** add_history
@ -81,7 +73,7 @@ extern void initwhowas(void);
** Client must be a fully registered user (specifically, ** Client must be a fully registered user (specifically,
** the user structure must have been allocated). ** the user structure must have been allocated).
*/ */
void add_history(struct Client *, int); void whowas_add_history(struct Client *, int);
/* /*
** off_history ** off_history
@ -90,7 +82,7 @@ void add_history(struct Client *, int);
** structures and it must know when they cease to exist. This ** structures and it must know when they cease to exist. This
** also implicitly calls AddHistory. ** also implicitly calls AddHistory.
*/ */
void off_history(struct Client *); void whowas_off_history(struct Client *);
/* /*
** get_history ** get_history
@ -98,18 +90,12 @@ void off_history(struct Client *);
** nickname within the timelimit. Returns NULL, if no ** nickname within the timelimit. Returns NULL, if no
** one found... ** one found...
*/ */
struct Client *get_history(const char *, time_t); struct Client *whowas_get_history(const char *, time_t);
/* Nick name */ /* Nick name */
/* Time limit in seconds */ /* Time limit in seconds */
/* rb_dlink_list *whowas_get_list(const char *name);
** for debugging...counts related structures stored in whowas array. void whowas_set_size(int whowas_length);
*/ void whowas_memory_usage(size_t *count, size_t *memused);
void count_whowas_memory(size_t *, size_t *);
/* XXX m_whowas.c in modules needs these */
extern struct Whowas WHOWAS[];
extern struct Whowas *WHOWASHASH[];
extern unsigned int hash_whowas_name(const char *name);
#endif /* INCLUDED_whowas_h */ #endif /* INCLUDED_whowas_h */

View file

@ -672,7 +672,7 @@ resv_nick_fnc(const char *mask, const char *reason, int temp_time)
/* Do all of the nick-changing gymnastics. */ /* Do all of the nick-changing gymnastics. */
client_p->tsinfo = rb_current_time(); client_p->tsinfo = rb_current_time();
add_history(client_p, 1); whowas_add_history(client_p, 1);
monitor_signoff(client_p); monitor_signoff(client_p);
@ -872,7 +872,7 @@ find_chasing(struct Client *source_p, const char *user, int *chasing)
if(who || IsDigit(*user)) if(who || IsDigit(*user))
return who; return who;
if(!(who = get_history(user, (long) KILLCHASETIMELIMIT))) if(!(who = whowas_get_history(user, (long) KILLCHASETIMELIMIT)))
{ {
sendto_one_numeric(source_p, ERR_NOSUCHNICK, sendto_one_numeric(source_p, ERR_NOSUCHNICK,
form_str(ERR_NOSUCHNICK), user); form_str(ERR_NOSUCHNICK), user);
@ -1247,8 +1247,8 @@ exit_generic_client(struct Client *client_p, struct Client *source_p, struct Cli
/* Clean up allow lists */ /* Clean up allow lists */
del_all_accepts(source_p); del_all_accepts(source_p);
add_history(source_p, 0); whowas_add_history(source_p, 0);
off_history(source_p); whowas_off_history(source_p);
monitor_signoff(source_p); monitor_signoff(source_p);

View file

@ -653,7 +653,7 @@ charybdis_main(int argc, char *argv[])
init_hook(); init_hook();
init_channels(); init_channels();
initclass(); initclass();
initwhowas(); whowas_init();
init_reject(); init_reject();
init_cache(); init_cache();
init_monitor(); init_monitor();

View file

@ -1513,7 +1513,7 @@ change_nick_user_host(struct Client *target_p, const char *nick, const char *use
rb_strlcpy(target_p->host, host, sizeof target_p->host); rb_strlcpy(target_p->host, host, sizeof target_p->host);
if (changed) if (changed)
add_history(target_p, 1); whowas_add_history(target_p, 1);
del_from_client_hash(target_p->name, target_p); del_from_client_hash(target_p->name, target_p);
rb_strlcpy(target_p->name, nick, NICKLEN); rb_strlcpy(target_p->name, nick, NICKLEN);

View file

@ -4,7 +4,8 @@
* *
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center * Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
* Copyright (C) 1996-2002 Hybrid Development Team * Copyright (C) 1996-2002 Hybrid Development Team
* Copyright (C) 2002-2005 ircd-ratbox development team * Copyright (C) 2002-2012 ircd-ratbox development team
* Copyright (C) 2016 William Pitcock <nenolod@dereferenced.org>
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -18,178 +19,203 @@
* *
* You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA * USA
*
* $Id: whowas.c 1717 2006-07-04 14:41:11Z jilles $
*/ */
#include "stdinc.h" #include "stdinc.h"
#include "whowas.h"
#include "client.h"
#include "common.h"
#include "hash.h" #include "hash.h"
#include "whowas.h"
#include "match.h" #include "match.h"
#include "ircd.h" #include "ircd.h"
#include "ircd_defs.h"
#include "numeric.h" #include "numeric.h"
#include "s_assert.h"
#include "s_serv.h" #include "s_serv.h"
#include "s_user.h" #include "s_user.h"
#include "send.h" #include "send.h"
#include "s_conf.h" #include "s_conf.h"
#include "client.h"
#include "send.h"
#include "logger.h"
#include "scache.h" #include "scache.h"
#include "s_assert.h" #include "irc_radixtree.h"
/* internally defined function */ struct whowas_top
static void add_whowas_to_clist(struct Whowas **, struct Whowas *);
static void del_whowas_from_clist(struct Whowas **, struct Whowas *);
static void add_whowas_to_list(struct Whowas **, struct Whowas *);
static void del_whowas_from_list(struct Whowas **, struct Whowas *);
struct Whowas WHOWAS[NICKNAMEHISTORYLENGTH];
struct Whowas *WHOWASHASH[WW_MAX];
static int whowas_next = 0;
unsigned int hash_whowas_name(const char *name)
{ {
return fnv_hash_upper((const unsigned char *) name, WW_MAX_BITS); char *name;
rb_dlink_list wwlist;
};
static struct irc_radixtree *whowas_tree = NULL;
static rb_dlink_list whowas_list = {NULL, NULL, 0};
static unsigned int whowas_list_length = NICKNAMEHISTORYLENGTH;
static void whowas_trim(void *unused);
static void
whowas_free_wtop(struct whowas_top *wtop)
{
if(rb_dlink_list_length(&wtop->wwlist) == 0)
{
irc_radixtree_delete(whowas_tree, wtop->name);
rb_free(wtop->name);
rb_free(wtop);
}
} }
void add_history(struct Client *client_p, int online) static struct whowas_top *
whowas_get_top(const char *name)
{ {
struct Whowas *who = &WHOWAS[whowas_next]; struct whowas_top *wtop;
wtop = irc_radixtree_retrieve(whowas_tree, name);
if (wtop != NULL)
return wtop;
wtop = rb_malloc(sizeof(struct whowas_top));
wtop->name = rb_strdup(name);
irc_radixtree_add(whowas_tree, wtop->name, wtop);
return wtop;
}
rb_dlink_list *
whowas_get_list(const char *name)
{
struct whowas_top *wtop;
wtop = irc_radixtree_retrieve(whowas_tree, name);
if(wtop == NULL)
return NULL;
return &wtop->wwlist;
}
void
whowas_add_history(struct Client *client_p, int online)
{
struct whowas_top *wtop;
struct Whowas *who;
s_assert(NULL != client_p); s_assert(NULL != client_p);
if(client_p == NULL) if(client_p == NULL)
return; return;
if(who->hashv != -1) /* trim some of the entries if we're getting well over our history length */
{ if(rb_dlink_list_length(&whowas_list) > whowas_list_length + 100)
if(who->online) whowas_trim(NULL);
del_whowas_from_clist(&(who->online->whowas), who);
del_whowas_from_list(&WHOWASHASH[who->hashv], who); wtop = whowas_get_top(client_p->name);
} who = rb_malloc(sizeof(struct Whowas));
who->hashv = hash_whowas_name(client_p->name); who->wtop = wtop;
who->logoff = rb_current_time(); who->logoff = rb_current_time();
/*
* NOTE: strcpy ok here, the sizes in the client struct MUST
* match the sizes in the whowas struct
*/
rb_strlcpy(who->name, client_p->name, sizeof(who->name)); rb_strlcpy(who->name, client_p->name, sizeof(who->name));
strcpy(who->username, client_p->username); rb_strlcpy(who->username, client_p->username, sizeof(who->username));
strcpy(who->hostname, client_p->host); rb_strlcpy(who->hostname, client_p->host, sizeof(who->hostname));
strcpy(who->realname, client_p->info); rb_strlcpy(who->realname, client_p->info, sizeof(who->realname));
strcpy(who->suser, client_p->user->suser); rb_strlcpy(who->sockhost, client_p->sockhost, sizeof(who->sockhost));
strcpy(who->sockhost, client_p->sockhost);
who->flags = (IsIPSpoof(client_p) ? WHOWAS_IP_SPOOFING : 0) | who->flags = (IsIPSpoof(client_p) ? WHOWAS_IP_SPOOFING : 0) |
(IsDynSpoof(client_p) ? WHOWAS_DYNSPOOF : 0); (IsDynSpoof(client_p) ? WHOWAS_DYNSPOOF : 0);
/* this is safe do to with the servername cache */
who->servername = scache_get_name(client_p->servptr->serv->nameinfo); who->servername = scache_get_name(client_p->servptr->serv->nameinfo);
if(online) if(online)
{ {
who->online = client_p; who->online = client_p;
add_whowas_to_clist(&(client_p->whowas), who); rb_dlinkAdd(who, &who->cnode, &client_p->whowas_clist);
} }
else else
who->online = NULL; who->online = NULL;
add_whowas_to_list(&WHOWASHASH[who->hashv], who);
whowas_next++; rb_dlinkAdd(who, &who->wnode, &wtop->wwlist);
if(whowas_next == NICKNAMEHISTORYLENGTH) rb_dlinkAdd(who, &who->whowas_node, &whowas_list);
whowas_next = 0;
} }
void off_history(struct Client *client_p)
{
struct Whowas *temp, *next;
for (temp = client_p->whowas; temp; temp = next) void
whowas_off_history(struct Client *client_p)
{ {
next = temp->cnext; rb_dlink_node *ptr, *next;
temp->online = NULL;
del_whowas_from_clist(&(client_p->whowas), temp); RB_DLINK_FOREACH_SAFE(ptr, next, client_p->whowas_clist.head)
{
struct Whowas *who = ptr->data;
who->online = NULL;
rb_dlinkDelete(&who->cnode, &client_p->whowas_clist);
} }
} }
struct Client *get_history(const char *nick, time_t timelimit) struct Client *
whowas_get_history(const char *nick, time_t timelimit)
{ {
struct Whowas *temp; struct whowas_top *wtop;
int blah; rb_dlink_node *ptr;
wtop = irc_radixtree_retrieve(whowas_tree, nick);
if(wtop == NULL)
return NULL;
timelimit = rb_current_time() - timelimit; timelimit = rb_current_time() - timelimit;
blah = hash_whowas_name(nick);
temp = WHOWASHASH[blah]; RB_DLINK_FOREACH_PREV(ptr, wtop->wwlist.tail)
for (; temp; temp = temp->next)
{ {
if(irccmp(nick, temp->name)) struct Whowas *who = ptr->data;
continue; if(who->logoff >= timelimit)
if(temp->logoff < timelimit) {
continue; return who->online;
return temp->online;
} }
}
return NULL; return NULL;
} }
void count_whowas_memory(size_t * wwu, size_t * wwum) static void
whowas_trim(void *unused)
{ {
*wwu = NICKNAMEHISTORYLENGTH; long over;
*wwum = NICKNAMEHISTORYLENGTH * sizeof(struct Whowas);
if(rb_dlink_list_length(&whowas_list) < whowas_list_length)
return;
over = rb_dlink_list_length(&whowas_list) - whowas_list_length;
/* remove whowas entries over the configured length */
for(long i = 0; i < over; i++)
{
if(whowas_list.tail != NULL && whowas_list.tail->data != NULL)
{
struct Whowas *twho = whowas_list.tail->data;
if(twho->online != NULL)
rb_dlinkDelete(&twho->cnode, &twho->online->whowas_clist);
rb_dlinkDelete(&twho->wnode, &twho->wtop->wwlist);
rb_dlinkDelete(&twho->whowas_node, &whowas_list);
whowas_free_wtop(twho->wtop);
rb_free(twho);
}
}
} }
void void
initwhowas() whowas_init(void)
{ {
int i; whowas_tree = irc_radixtree_create("whowas", irc_radixtree_irccasecanon);
if(whowas_list_length == 0)
for (i = 0; i < NICKNAMEHISTORYLENGTH; i++)
{ {
memset((void *) &WHOWAS[i], 0, sizeof(struct Whowas)); whowas_list_length = NICKNAMEHISTORYLENGTH;
WHOWAS[i].hashv = -1;
} }
for (i = 0; i < WW_MAX; i++) rb_event_add("whowas_trim", whowas_trim, NULL, 10);
WHOWASHASH[i] = NULL;
} }
void
static void whowas_set_size(int len)
add_whowas_to_clist(struct Whowas **bucket, struct Whowas *whowas)
{ {
whowas->cprev = NULL; whowas_list_length = len;
if((whowas->cnext = *bucket) != NULL) whowas_trim(NULL);
whowas->cnext->cprev = whowas;
*bucket = whowas;
} }
static void void
del_whowas_from_clist(struct Whowas **bucket, struct Whowas *whowas) whowas_memory_usage(size_t * count, size_t * memused)
{ {
if(whowas->cprev) *count = rb_dlink_list_length(&whowas_list);
whowas->cprev->cnext = whowas->cnext; *memused += *count * sizeof(struct Whowas);
else *memused += sizeof(struct whowas_top) * irc_radixtree_size(whowas_tree);
*bucket = whowas->cnext;
if(whowas->cnext)
whowas->cnext->cprev = whowas->cprev;
}
static void
add_whowas_to_list(struct Whowas **bucket, struct Whowas *whowas)
{
whowas->prev = NULL;
if((whowas->next = *bucket) != NULL)
whowas->next->prev = whowas;
*bucket = whowas;
}
static void
del_whowas_from_list(struct Whowas **bucket, struct Whowas *whowas)
{
if(whowas->prev)
whowas->prev->next = whowas->next;
else
*bucket = whowas->next;
if(whowas->next)
whowas->next->prev = whowas->prev;
} }

View file

@ -102,7 +102,7 @@ mo_kill(struct Client *client_p, struct Client *source_p, int parc, const char *
** rewrite the KILL for this new nickname--this keeps ** rewrite the KILL for this new nickname--this keeps
** servers in synch when nick change and kill collide ** servers in synch when nick change and kill collide
*/ */
if((target_p = get_history(user, (long) KILLCHASETIMELIMIT)) == NULL) if((target_p = whowas_get_history(user, (long) KILLCHASETIMELIMIT)) == NULL)
{ {
if (strchr(user, '.')) if (strchr(user, '.'))
sendto_one_numeric(source_p, ERR_CANTKILLSERVER, form_str(ERR_CANTKILLSERVER)); sendto_one_numeric(source_p, ERR_CANTKILLSERVER, form_str(ERR_CANTKILLSERVER));
@ -221,7 +221,7 @@ ms_kill(struct Client *client_p, struct Client *source_p, int parc, const char *
* not an uid, automatically rewrite the KILL for this new nickname. * not an uid, automatically rewrite the KILL for this new nickname.
* --this keeps servers in synch when nick change and kill collide * --this keeps servers in synch when nick change and kill collide
*/ */
if(IsDigit(*user) || (!(target_p = get_history(user, (long) KILLCHASETIMELIMIT)))) if(IsDigit(*user) || (!(target_p = whowas_get_history(user, (long) KILLCHASETIMELIMIT))))
{ {
sendto_one_numeric(source_p, ERR_NOSUCHNICK, sendto_one_numeric(source_p, ERR_NOSUCHNICK,
form_str(ERR_NOSUCHNICK), IsDigit(*user) ? "*" : user); form_str(ERR_NOSUCHNICK), IsDigit(*user) ? "*" : user);

View file

@ -685,7 +685,7 @@ change_local_nick(struct Client *client_p, struct Client *source_p,
/* send the nick change to servers.. */ /* send the nick change to servers.. */
if(source_p->user) if(source_p->user)
{ {
add_history(source_p, 1); whowas_add_history(source_p, 1);
if (dosend) if (dosend)
{ {
@ -745,7 +745,7 @@ change_remote_nick(struct Client *client_p, struct Client *source_p,
if(source_p->user) if(source_p->user)
{ {
add_history(source_p, 1); whowas_add_history(source_p, 1);
if (dosend) if (dosend)
{ {
sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld", sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",

View file

@ -244,7 +244,7 @@ doit:
target_p->name, target_p->username, target_p->name, target_p->username,
target_p->host, parv[2]); target_p->host, parv[2]);
add_history(target_p, 1); whowas_add_history(target_p, 1);
sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld", sendto_server(NULL, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
use_id(target_p), parv[2], (long) target_p->tsinfo); use_id(target_p), parv[2], (long) target_p->tsinfo);

View file

@ -1267,7 +1267,7 @@ stats_memory (struct Client *source_p)
size_t total_memory = 0; size_t total_memory = 0;
count_whowas_memory(&ww, &wwm); whowas_memory_usage(&ww, &wwm);
RB_DLINK_FOREACH(ptr, global_client_list.head) RB_DLINK_FOREACH(ptr, global_client_list.head)
{ {

View file

@ -58,9 +58,10 @@ DECLARE_MODULE_AV1(whowas, NULL, NULL, whowas_clist, NULL, NULL, "$Revision: 171
static int static int
m_whowas(struct Client *client_p, struct Client *source_p, int parc, const char *parv[]) m_whowas(struct Client *client_p, struct Client *source_p, int parc, const char *parv[])
{ {
struct Whowas *temp; rb_dlink_list *whowas_list;
rb_dlink_node *ptr;
int cur = 0; int cur = 0;
int max = -1, found = 0; int max = -1;
char *p; char *p;
const char *nick; const char *nick;
char tbuf[26]; char tbuf[26];
@ -76,8 +77,8 @@ m_whowas(struct Client *client_p, struct Client *source_p, int parc, const char
{ {
sendto_one(source_p, form_str(RPL_LOAD2HI), sendto_one(source_p, form_str(RPL_LOAD2HI),
me.name, source_p->name, "WHOWAS"); me.name, source_p->name, "WHOWAS");
sendto_one(source_p, form_str(RPL_ENDOFWHOWAS), sendto_one_numeric(source_p, RPL_ENDOFWHOWAS, form_str(RPL_ENDOFWHOWAS),
me.name, source_p->name, parv[1]); parv[1]);
return 0; return 0;
} }
else else
@ -101,54 +102,50 @@ m_whowas(struct Client *client_p, struct Client *source_p, int parc, const char
nick = parv[1]; nick = parv[1];
sendq_limit = get_sendq(client_p) * 9 / 10; sendq_limit = get_sendq(client_p) * 9 / 10;
whowas_list = whowas_get_list(nick);
temp = WHOWASHASH[hash_whowas_name(nick)]; if(whowas_list == NULL)
found = 0;
for (; temp; temp = temp->next)
{ {
if(!irccmp(nick, temp->name)) sendto_one_numeric(source_p, ERR_WASNOSUCHNICK, form_str(ERR_WASNOSUCHNICK), nick);
sendto_one_numeric(source_p, RPL_ENDOFWHOWAS, form_str(RPL_ENDOFWHOWAS), parv[1]);
return 0;
}
RB_DLINK_FOREACH(ptr, whowas_list->head)
{ {
struct Whowas *temp = ptr->data;
if(cur > 0 && rb_linebuf_len(&client_p->localClient->buf_sendq) > sendq_limit) if(cur > 0 && rb_linebuf_len(&client_p->localClient->buf_sendq) > sendq_limit)
{ {
sendto_one(source_p, form_str(ERR_TOOMANYMATCHES), sendto_one(source_p, form_str(ERR_TOOMANYMATCHES),
me.name, source_p->name, "WHOWAS"); me.name, source_p->name, "WHOWAS");
break; break;
} }
sendto_one(source_p, form_str(RPL_WHOWASUSER), sendto_one(source_p, form_str(RPL_WHOWASUSER),
me.name, source_p->name, temp->name, me.name, source_p->name, temp->name,
temp->username, temp->hostname, temp->realname); temp->username, temp->hostname, temp->realname);
if (!EmptyString(temp->sockhost) && if (!EmptyString(temp->sockhost) &&
strcmp(temp->sockhost, "0") && strcmp(temp->sockhost, "0") &&
show_ip_whowas(temp, source_p)) show_ip_whowas(temp, source_p))
#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, sendto_one_numeric(source_p, RPL_WHOISACTUALLY,
form_str(RPL_WHOISACTUALLY), form_str(RPL_WHOISACTUALLY),
temp->name, temp->sockhost); temp->name, temp->sockhost);
#endif
if (!EmptyString(temp->suser)) if (!EmptyString(temp->suser))
sendto_one_numeric(source_p, RPL_WHOISLOGGEDIN, sendto_one_numeric(source_p, RPL_WHOISLOGGEDIN,
"%s %s :was logged in as", "%s %s :was logged in as",
temp->name, temp->suser); temp->name, temp->suser);
sendto_one_numeric(source_p, RPL_WHOISSERVER, sendto_one_numeric(source_p, RPL_WHOISSERVER,
form_str(RPL_WHOISSERVER), form_str(RPL_WHOISSERVER),
temp->name, temp->servername, temp->name, temp->servername,
rb_ctime(temp->logoff, tbuf, sizeof(tbuf))); rb_ctime(temp->logoff, tbuf, sizeof(tbuf)));
cur++; cur++;
found++;
}
if(max > 0 && cur >= max) if(max > 0 && cur >= max)
break; break;
} }
if(!found) sendto_one_numeric(source_p, RPL_ENDOFWHOWAS, form_str(RPL_ENDOFWHOWAS), parv[1]);
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; return 0;
} }