ircd: import modified version of ratbox 3.1 whowas code
This commit is contained in:
parent
3de2266243
commit
b47f8a4fda
12 changed files with 205 additions and 195 deletions
|
@ -117,7 +117,8 @@ struct Client
|
|||
struct Client *servptr; /* Points to server this Client is on */
|
||||
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 */
|
||||
unsigned int umodes; /* opers, normal users subset */
|
||||
unsigned int flags; /* client flags */
|
||||
|
|
|
@ -131,7 +131,7 @@
|
|||
#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_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_372 ":%s 372 %s :- %s"
|
||||
#define NUMERIC_STR_374 ":End of /INFO list."
|
||||
|
@ -147,7 +147,7 @@
|
|||
#define NUMERIC_STR_403 "%s :No such 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_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_409 ":%s 409 %s :No origin specified"
|
||||
#define NUMERIC_STR_410 ":%s 410 %s %s :Invalid CAP subcommand"
|
||||
|
|
|
@ -31,13 +31,6 @@
|
|||
|
||||
#include "setup.h"
|
||||
|
||||
/*
|
||||
* Whowas hash table size
|
||||
*
|
||||
*/
|
||||
#define WW_MAX_BITS 16
|
||||
#define WW_MAX 65536
|
||||
|
||||
struct User;
|
||||
struct Client;
|
||||
|
||||
|
@ -48,7 +41,10 @@ struct Client;
|
|||
*/
|
||||
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 username[USERLEN + 1];
|
||||
char hostname[HOSTLEN + 1];
|
||||
|
@ -59,10 +55,6 @@ struct Whowas
|
|||
const char *servername;
|
||||
time_t logoff;
|
||||
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 */
|
||||
|
@ -72,7 +64,7 @@ struct Whowas
|
|||
/*
|
||||
** initwhowas
|
||||
*/
|
||||
extern void initwhowas(void);
|
||||
extern void whowas_init(void);
|
||||
|
||||
/*
|
||||
** add_history
|
||||
|
@ -81,7 +73,7 @@ extern void initwhowas(void);
|
|||
** Client must be a fully registered user (specifically,
|
||||
** the user structure must have been allocated).
|
||||
*/
|
||||
void add_history(struct Client *, int);
|
||||
void whowas_add_history(struct Client *, int);
|
||||
|
||||
/*
|
||||
** off_history
|
||||
|
@ -90,7 +82,7 @@ void add_history(struct Client *, int);
|
|||
** structures and it must know when they cease to exist. This
|
||||
** also implicitly calls AddHistory.
|
||||
*/
|
||||
void off_history(struct Client *);
|
||||
void whowas_off_history(struct Client *);
|
||||
|
||||
/*
|
||||
** get_history
|
||||
|
@ -98,18 +90,12 @@ void off_history(struct Client *);
|
|||
** nickname within the timelimit. Returns NULL, if no
|
||||
** one found...
|
||||
*/
|
||||
struct Client *get_history(const char *, time_t);
|
||||
struct Client *whowas_get_history(const char *, time_t);
|
||||
/* Nick name */
|
||||
/* Time limit in seconds */
|
||||
|
||||
/*
|
||||
** for debugging...counts related structures stored in whowas array.
|
||||
*/
|
||||
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);
|
||||
rb_dlink_list *whowas_get_list(const char *name);
|
||||
void whowas_set_size(int whowas_length);
|
||||
void whowas_memory_usage(size_t *count, size_t *memused);
|
||||
|
||||
#endif /* INCLUDED_whowas_h */
|
||||
|
|
|
@ -672,7 +672,7 @@ resv_nick_fnc(const char *mask, const char *reason, int temp_time)
|
|||
|
||||
/* Do all of the nick-changing gymnastics. */
|
||||
client_p->tsinfo = rb_current_time();
|
||||
add_history(client_p, 1);
|
||||
whowas_add_history(client_p, 1);
|
||||
|
||||
monitor_signoff(client_p);
|
||||
|
||||
|
@ -872,7 +872,7 @@ find_chasing(struct Client *source_p, const char *user, int *chasing)
|
|||
if(who || IsDigit(*user))
|
||||
return who;
|
||||
|
||||
if(!(who = get_history(user, (long) KILLCHASETIMELIMIT)))
|
||||
if(!(who = whowas_get_history(user, (long) KILLCHASETIMELIMIT)))
|
||||
{
|
||||
sendto_one_numeric(source_p, ERR_NOSUCHNICK,
|
||||
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 */
|
||||
del_all_accepts(source_p);
|
||||
|
||||
add_history(source_p, 0);
|
||||
off_history(source_p);
|
||||
whowas_add_history(source_p, 0);
|
||||
whowas_off_history(source_p);
|
||||
|
||||
monitor_signoff(source_p);
|
||||
|
||||
|
|
|
@ -653,7 +653,7 @@ charybdis_main(int argc, char *argv[])
|
|||
init_hook();
|
||||
init_channels();
|
||||
initclass();
|
||||
initwhowas();
|
||||
whowas_init();
|
||||
init_reject();
|
||||
init_cache();
|
||||
init_monitor();
|
||||
|
|
|
@ -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);
|
||||
|
||||
if (changed)
|
||||
add_history(target_p, 1);
|
||||
whowas_add_history(target_p, 1);
|
||||
|
||||
del_from_client_hash(target_p->name, target_p);
|
||||
rb_strlcpy(target_p->name, nick, NICKLEN);
|
||||
|
|
246
ircd/whowas.c
246
ircd/whowas.c
|
@ -4,7 +4,8 @@
|
|||
*
|
||||
* Copyright (C) 1990 Jarkko Oikarinen and University of Oulu, Co Center
|
||||
* 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
|
||||
* 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
|
||||
* 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
|
||||
*
|
||||
* $Id: whowas.c 1717 2006-07-04 14:41:11Z jilles $
|
||||
*/
|
||||
|
||||
#include "stdinc.h"
|
||||
|
||||
#include "whowas.h"
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
#include "hash.h"
|
||||
#include "whowas.h"
|
||||
#include "match.h"
|
||||
#include "ircd.h"
|
||||
#include "ircd_defs.h"
|
||||
#include "numeric.h"
|
||||
#include "s_assert.h"
|
||||
#include "s_serv.h"
|
||||
#include "s_user.h"
|
||||
#include "send.h"
|
||||
#include "s_conf.h"
|
||||
#include "client.h"
|
||||
#include "send.h"
|
||||
#include "logger.h"
|
||||
#include "scache.h"
|
||||
#include "s_assert.h"
|
||||
#include "irc_radixtree.h"
|
||||
|
||||
/* internally defined function */
|
||||
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)
|
||||
struct whowas_top
|
||||
{
|
||||
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);
|
||||
|
||||
if(client_p == NULL)
|
||||
return;
|
||||
|
||||
if(who->hashv != -1)
|
||||
{
|
||||
if(who->online)
|
||||
del_whowas_from_clist(&(who->online->whowas), who);
|
||||
del_whowas_from_list(&WHOWASHASH[who->hashv], who);
|
||||
}
|
||||
who->hashv = hash_whowas_name(client_p->name);
|
||||
/* 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)
|
||||
whowas_trim(NULL);
|
||||
|
||||
wtop = whowas_get_top(client_p->name);
|
||||
who = rb_malloc(sizeof(struct Whowas));
|
||||
who->wtop = wtop;
|
||||
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));
|
||||
strcpy(who->username, client_p->username);
|
||||
strcpy(who->hostname, client_p->host);
|
||||
strcpy(who->realname, client_p->info);
|
||||
strcpy(who->suser, client_p->user->suser);
|
||||
strcpy(who->sockhost, client_p->sockhost);
|
||||
rb_strlcpy(who->username, client_p->username, sizeof(who->username));
|
||||
rb_strlcpy(who->hostname, client_p->host, sizeof(who->hostname));
|
||||
rb_strlcpy(who->realname, client_p->info, sizeof(who->realname));
|
||||
rb_strlcpy(who->sockhost, client_p->sockhost, sizeof(who->sockhost));
|
||||
|
||||
who->flags = (IsIPSpoof(client_p) ? WHOWAS_IP_SPOOFING : 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);
|
||||
|
||||
if(online)
|
||||
{
|
||||
who->online = client_p;
|
||||
add_whowas_to_clist(&(client_p->whowas), who);
|
||||
rb_dlinkAdd(who, &who->cnode, &client_p->whowas_clist);
|
||||
}
|
||||
else
|
||||
who->online = NULL;
|
||||
add_whowas_to_list(&WHOWASHASH[who->hashv], who);
|
||||
whowas_next++;
|
||||
if(whowas_next == NICKNAMEHISTORYLENGTH)
|
||||
whowas_next = 0;
|
||||
|
||||
rb_dlinkAdd(who, &who->wnode, &wtop->wwlist);
|
||||
rb_dlinkAdd(who, &who->whowas_node, &whowas_list);
|
||||
}
|
||||
|
||||
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;
|
||||
temp->online = NULL;
|
||||
del_whowas_from_clist(&(client_p->whowas), temp);
|
||||
rb_dlink_node *ptr, *next;
|
||||
|
||||
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;
|
||||
int blah;
|
||||
struct whowas_top *wtop;
|
||||
rb_dlink_node *ptr;
|
||||
|
||||
wtop = irc_radixtree_retrieve(whowas_tree, nick);
|
||||
if(wtop == NULL)
|
||||
return NULL;
|
||||
|
||||
timelimit = rb_current_time() - timelimit;
|
||||
blah = hash_whowas_name(nick);
|
||||
temp = WHOWASHASH[blah];
|
||||
for (; temp; temp = temp->next)
|
||||
|
||||
RB_DLINK_FOREACH_PREV(ptr, wtop->wwlist.tail)
|
||||
{
|
||||
if(irccmp(nick, temp->name))
|
||||
continue;
|
||||
if(temp->logoff < timelimit)
|
||||
continue;
|
||||
return temp->online;
|
||||
struct Whowas *who = ptr->data;
|
||||
if(who->logoff >= timelimit)
|
||||
{
|
||||
return who->online;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void count_whowas_memory(size_t * wwu, size_t * wwum)
|
||||
static void
|
||||
whowas_trim(void *unused)
|
||||
{
|
||||
*wwu = NICKNAMEHISTORYLENGTH;
|
||||
*wwum = NICKNAMEHISTORYLENGTH * sizeof(struct Whowas);
|
||||
long over;
|
||||
|
||||
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
|
||||
initwhowas()
|
||||
whowas_init(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < NICKNAMEHISTORYLENGTH; i++)
|
||||
whowas_tree = irc_radixtree_create("whowas", irc_radixtree_irccasecanon);
|
||||
if(whowas_list_length == 0)
|
||||
{
|
||||
memset((void *) &WHOWAS[i], 0, sizeof(struct Whowas));
|
||||
WHOWAS[i].hashv = -1;
|
||||
whowas_list_length = NICKNAMEHISTORYLENGTH;
|
||||
}
|
||||
for (i = 0; i < WW_MAX; i++)
|
||||
WHOWASHASH[i] = NULL;
|
||||
rb_event_add("whowas_trim", whowas_trim, NULL, 10);
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
add_whowas_to_clist(struct Whowas **bucket, struct Whowas *whowas)
|
||||
void
|
||||
whowas_set_size(int len)
|
||||
{
|
||||
whowas->cprev = NULL;
|
||||
if((whowas->cnext = *bucket) != NULL)
|
||||
whowas->cnext->cprev = whowas;
|
||||
*bucket = whowas;
|
||||
whowas_list_length = len;
|
||||
whowas_trim(NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
del_whowas_from_clist(struct Whowas **bucket, struct Whowas *whowas)
|
||||
void
|
||||
whowas_memory_usage(size_t * count, size_t * memused)
|
||||
{
|
||||
if(whowas->cprev)
|
||||
whowas->cprev->cnext = whowas->cnext;
|
||||
else
|
||||
*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;
|
||||
*count = rb_dlink_list_length(&whowas_list);
|
||||
*memused += *count * sizeof(struct Whowas);
|
||||
*memused += sizeof(struct whowas_top) * irc_radixtree_size(whowas_tree);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
** 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, '.'))
|
||||
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.
|
||||
* --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,
|
||||
form_str(ERR_NOSUCHNICK), IsDigit(*user) ? "*" : user);
|
||||
|
|
|
@ -685,7 +685,7 @@ change_local_nick(struct Client *client_p, struct Client *source_p,
|
|||
/* send the nick change to servers.. */
|
||||
if(source_p->user)
|
||||
{
|
||||
add_history(source_p, 1);
|
||||
whowas_add_history(source_p, 1);
|
||||
|
||||
if (dosend)
|
||||
{
|
||||
|
@ -745,7 +745,7 @@ change_remote_nick(struct Client *client_p, struct Client *source_p,
|
|||
|
||||
if(source_p->user)
|
||||
{
|
||||
add_history(source_p, 1);
|
||||
whowas_add_history(source_p, 1);
|
||||
if (dosend)
|
||||
{
|
||||
sendto_server(client_p, NULL, CAP_TS6, NOCAPS, ":%s NICK %s :%ld",
|
||||
|
|
|
@ -244,7 +244,7 @@ doit:
|
|||
target_p->name, target_p->username,
|
||||
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",
|
||||
use_id(target_p), parv[2], (long) target_p->tsinfo);
|
||||
|
||||
|
|
|
@ -1267,7 +1267,7 @@ stats_memory (struct Client *source_p)
|
|||
|
||||
size_t total_memory = 0;
|
||||
|
||||
count_whowas_memory(&ww, &wwm);
|
||||
whowas_memory_usage(&ww, &wwm);
|
||||
|
||||
RB_DLINK_FOREACH(ptr, global_client_list.head)
|
||||
{
|
||||
|
|
|
@ -58,9 +58,10 @@ DECLARE_MODULE_AV1(whowas, NULL, NULL, whowas_clist, NULL, NULL, "$Revision: 171
|
|||
static int
|
||||
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 max = -1, found = 0;
|
||||
int max = -1;
|
||||
char *p;
|
||||
const char *nick;
|
||||
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),
|
||||
me.name, source_p->name, "WHOWAS");
|
||||
sendto_one(source_p, form_str(RPL_ENDOFWHOWAS),
|
||||
me.name, source_p->name, parv[1]);
|
||||
sendto_one_numeric(source_p, RPL_ENDOFWHOWAS, form_str(RPL_ENDOFWHOWAS),
|
||||
parv[1]);
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
|
@ -101,54 +102,50 @@ m_whowas(struct Client *client_p, struct Client *source_p, int parc, const char
|
|||
nick = parv[1];
|
||||
|
||||
sendq_limit = get_sendq(client_p) * 9 / 10;
|
||||
whowas_list = whowas_get_list(nick);
|
||||
|
||||
temp = WHOWASHASH[hash_whowas_name(nick)];
|
||||
found = 0;
|
||||
for (; temp; temp = temp->next)
|
||||
if(whowas_list == NULL)
|
||||
{
|
||||
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)
|
||||
{
|
||||
sendto_one(source_p, form_str(ERR_TOOMANYMATCHES),
|
||||
me.name, source_p->name, "WHOWAS");
|
||||
break;
|
||||
}
|
||||
|
||||
sendto_one(source_p, form_str(RPL_WHOWASUSER),
|
||||
me.name, source_p->name, temp->name,
|
||||
temp->username, temp->hostname, temp->realname);
|
||||
if (!EmptyString(temp->sockhost) &&
|
||||
strcmp(temp->sockhost, "0") &&
|
||||
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,
|
||||
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);
|
||||
|
||||
sendto_one_numeric(source_p, RPL_WHOISSERVER,
|
||||
form_str(RPL_WHOISSERVER),
|
||||
temp->name, temp->servername,
|
||||
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]);
|
||||
sendto_one_numeric(source_p, RPL_ENDOFWHOWAS, form_str(RPL_ENDOFWHOWAS), parv[1]);
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue