/* * ircd-ratbox: A slightly useful ircd. * whowas.c: WHOWAS user cache. * * 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 * * 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 * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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 * 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 "match.h"#include "ircd.h"#include "ircd_defs.h"#include "numeric.h"#include "s_serv.h"#include "s_user.h"#include "send.h"#include "s_conf.h"#include "scache.h"/* internally defined function */staticvoidadd_whowas_to_clist(structWhowas**,structWhowas*);staticvoiddel_whowas_from_clist(structWhowas**,structWhowas*);staticvoidadd_whowas_to_list(structWhowas**,structWhowas*);staticvoiddel_whowas_from_list(structWhowas**,structWhowas*);structWhowasWHOWAS[NICKNAMEHISTORYLENGTH];structWhowas*WHOWASHASH[WW_MAX];staticintwhowas_next=0;unsignedinthash_whowas_name(constchar*name){returnfnv_hash_upper((constunsignedchar*)name,WW_MAX_BITS);}voidadd_history(structClient*client_p,intonline){structWhowas*who=&WHOWAS[whowas_next];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);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);if(!EmptyString(client_p->sockhost)&&strcmp(client_p->sockhost,"0")&&show_ip(NULL,client_p))strcpy(who->sockhost,client_p->sockhost);elsewho->sockhost[0]='\0';who->servername=scache_get_name(client_p->servptr->serv->nameinfo);if(online){who->online=client_p;add_whowas_to_clist(&(client_p->whowas),who);}elsewho->online=NULL;add_whowas_to_list(&WHOWASHASH[who->hashv],who);whowas_next++;if(whowas_next==NICKNAMEHISTORYLENGTH)whowas_next=0;}voidoff_history(structClient*client_p){structWhowas*temp,*next;for(temp=client_p->whowas;temp;temp=next){next=temp->cnext;temp->online=NULL;del_whowas_from_clist(&(client_p->whowas),temp);}}structClient*get_history(constchar*nick,time_ttimelimit){structWhowas*temp;intblah;timelimit=rb_current_time()-timelimit;blah=hash_whowas_name(nick);temp=WHOWASHASH[blah];for(;temp;temp=temp->next){if(irccmp(nick,temp->name))continue;if(temp->logoff<timelimit)continue;returntemp->online;}returnNULL;}voidcount_whowas_memory(size_t*wwu,size_t*wwum){*wwu=NICKNAMEHISTORYLENGTH;*wwum=NICKNAMEHISTORYLENGTH*sizeof(structWhowas);}voidinitwhowas(){inti;for(i=0;i<NICKNAMEHISTORYLENGTH;i++){memset((void*)&WHOWAS[i],0,sizeof(structWhowas));WHOWAS[i].hashv=-1;}for(i=0;i<WW_MAX;i++)WHOWASHASH[i]=NULL;}staticvoidadd_whowas_to_clist(structWhowas**bucket,structWhowas*whowas){whowas->cprev=NULL;if((whowas->cnext=*bucket)!=NULL)whowas->cnext->cprev=whowas;*bucket=whowas;}staticvoiddel_whowas_from_clist(structWhowas**bucket,structWhowas*whowas){if(whowas->cprev)whowas->cprev->cnext=whowas->cnext;else*bucket=whowas->cnext;if(whowas->cnext)whowas->cnext->cprev=whowas->cprev;}staticvoidadd_whowas_to_list(structWhowas**bucket,structWhowas*whowas){whowas->prev=NULL;if((whowas->next=*bucket)!=NULL)whowas->next->prev=whowas;*bucket=whowas;}staticvoiddel_whowas_from_list(structWhowas**bucket,structWhowas*whowas){if(whowas->prev)whowas->prev->next=whowas->next;else*bucket=whowas->next;if(whowas->next)whowas->next->prev=whowas->prev;}