This repository has been archived on 2025-02-12. You can view files and clone it, but cannot push or open issues or pull requests.
NeoStats-services/hash.c

418 lines
9.4 KiB
C

/* NetStats - IRC Statistical Services
** Copyright (c) 1999 Adam Rutter, Justin Hammond
** http://codeworks.kamserve.com
*
** Based from GeoStats 1.1.0 by Johnathan George net@lite.net
*
** NetStats CVS Identification
** $Id: hash.c,v 1.4 2002/06/05 15:41:10 fishwaldo Exp $
*/
#include <fnmatch.h>
#include "services.h"
void del_svs_dead_timers();
void sync_changed_nicks_to_db() {
NS_User *tmp;
hnode_t *nsn;
hscan_t nss;
int j = 0;
int starttime;
starttime = time(NULL);
hash_scan_begin(&nss, nsuserlist);
while ((nsn = hash_scan_next(&nss))) {
tmp = hnode_get(nsn);
if (tmp->lastchange > last_db_sync) {
tmp->lastchange = time(NULL);
#ifdef DEBUG
log("Syncing Nick %s", tmp->nick);
#endif
sync_nick_to_db(tmp);
j++;
}
}
last_db_sync = time(NULL);
/* we always sync anyway, in case other gets/puts have happened outside this timer */
dbp->sync(dbp, 0);
/* this checks how long it took to sync the databaes
** if it took too long, then it warns the opers
** and asks them to decrease the database sync time
** to stop lag of NeoStats
*/
if ((time(NULL) - starttime) > 5) {
notice(s_NickServ, "\002Warning, Database Sync is exceeding threasholds, NeoStats is Lagging out\002");
notice(s_NickServ, "\002Suggest you Change the Database Sync interval to something smaller\002");
notice(s_NickServ, "\002We Synced %d Records in %d Secs...\002", j, time(NULL) - starttime);
}
}
void sync_nick_to_db(NS_User *tmp) {
DBT key, data;
int i;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = (void *)tmp->nick;
key.size = strlen(tmp->nick);
data.data = (void *)tmp;
data.size = sizeof(*tmp);
i = dbp->put(dbp, NULL, &key, &data, 0);
if (i != 0) {
log("Database Sync Error for %s: %s", tmp->nick, db_strerror(i));
notice(s_NickServ, "\002Database Sync Error\002 for %s: %s", tmp->nick, db_strerror(i));
return;
}
}
void del_nick_from_db(char *nick) {
DBT key;
int i;
memset(&key, 0, sizeof(key));
key.data = (void *)nick;
key.size = strlen(nick);
i = dbp->del(dbp, NULL, &key, 0);
if (i != 0) {
log("Database Sync Error for dropping nick %s: %s", nick, db_strerror(i));
notice(s_NickServ, "\002Database Sync error for dropping nick %s: %s", nick, db_strerror(i));
return;
}
}
void init_nick_forbid_list()
{
DBT key, data;
int i;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
/* we store the forbidden lists in a key called ns_forbid_list - Hopefully no user tries to use this nick */
key.data = "ns_forbid_list";
key.size = strlen(key.data);
i = dbp->get(dbp, NULL, &key, &data, 0);
if (i == DB_NOTFOUND) {
log("Warning: No Forbidden Nick list found in Database!");
return;
} else if (i != 0) {
log("Error: Forbidden Nick list retrival from database %s", db_strerror(i));
return;
} else {
strcpy(ns_forbid_list, data.data);
}
}
void save_nick_forbid_list()
{
DBT key, data;
int i;
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = "ns_forbid_list";
key.size = strlen(key.data);
data.data = ns_forbid_list;
data.size = strlen(ns_forbid_list);
i = dbp->put(dbp, NULL, &key, &data, 0);
if (i != 0) {
log("Error: Forbidden Nick list save to database: %s", db_strerror(i));
return;
} else {
notice(s_NickServ, "Saved Forbidden Nick List to database");
}
}
int is_forbidden(char *nick) {
char *tmp, *tmp2;
tmp = malloc(strlen(ns_forbid_list));
strcpy(tmp, ns_forbid_list);
tmp2 = strtok(tmp, " ");
while (tmp2) {
if (fnmatch(tmp2, nick, 0)) {
/* its a match */
free(tmp);
return 1;
}
tmp2 = strtok(NULL, " ");
}
free(tmp);
return 0;
}
void init_regnick_hash()
{
nsuserlist = hash_create(NS_USER_LIST, 0, 0);
}
NS_User *lookup_regnick(char *name)
{
NS_User *ns2;
DBT key, data;
int i;
ns2 = malloc(sizeof(NS_User));
bzero(ns2, sizeof(NS_User));
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = (char *)name;
key.size = strlen(key.data);
i = dbp->get(dbp, NULL, &key, &data, 0);
if (i == DB_NOTFOUND) {
free(ns2);
return NULL;
}
if (i == 0) {
#ifdef DEBUG
log("Getting RegNick From Database");
#endif
ns2 = data.data;
return ns2;
} else {
notice(s_NickServ, "DataBase Error %s", db_strerror(i));
log("Database Error: %s", db_strerror(i));
}
return NULL;
}
NS_User *new_regnick(char *name, int create)
{
NS_User *ns, *ns2;
hnode_t *nsn;
DBT key, data;
int i;
ns = malloc(sizeof(NS_User));
ns2 = malloc(sizeof(NS_User));
bzero(ns, sizeof(NS_User));
bzero(ns2, sizeof(NS_User));
memset(&key, 0, sizeof(key));
memset(&data, 0, sizeof(data));
key.data = name;
key.size = strlen(key.data);
i = dbp->get(dbp, NULL, &key, &data, 0);
if ((i == DB_NOTFOUND) && (create == 0)) {
free(ns);
free(ns2);
return NULL;
}
if ((i == 0) && (create ==0)) {
#ifdef DEBUG
log("Getting RegNick From Database");
#endif
ns2 = data.data;
strcpy(ns->pass, ns2->pass);
strcpy(ns->url, ns2->url);
strcpy(ns->email, ns2->email);
strcpy(ns->acl, ns2->acl);
strcpy(ns->last_mask, ns2->last_mask);
strcpy(ns->last_quit, ns2->last_quit);
strcpy(ns->aim, ns2->aim);
strcpy(ns->info, ns2->info);
strcpy(ns->greet, ns2->greet);
strcpy(ns->vhost, ns2->vhost);
ns->icq = ns2->icq;
ns->language = ns2->language;
ns->kill = ns2->kill;
ns->secure = ns2->secure;
ns->private = ns2->private;
ns->onlineflags = 0;
ns->lastchange = 0;
ns->registered_at = ns2->registered_at;
ns->flags = ns2->flags;
ns->last_seen_at = ns2->last_seen_at;
/* free(ns2); */
}
strncpy(ns->nick, name, strlen(name));
nsn = hnode_create(ns);
if (!hash_isfull(nsuserlist)) {
hash_insert(nsuserlist, nsn, ns->nick);
} else {
log("eeek, NickServ User list hash is full");
}
return ns;
}
NS_User *findregnick(char *name)
{
NS_User *ns = NULL;
hnode_t *nsn;
nsn = hash_lookup(nsuserlist, name);
if (nsn) {
ns = hnode_get(nsn);
}
#ifdef DEBUG
log("findregnick(%s) -> %s", name, (ns) ? ns->nick : "NOTFOUND");
#endif
return ns;
}
void del_regnick(char *name)
{
NS_User *ns;
hnode_t *nsn = hash_lookup(nsuserlist, name);
#ifdef DEBUG
log("DelRegnick(%s)", name);
#endif
if (!nsn) {
log("Delregnick(%s) failed!", name);
return;
}
ns = hnode_get(nsn);
hash_delete(nsuserlist, nsn);
hnode_destroy(nsn);
free(ns);
}
/* this is the Timer Hash setting... Things can be added to the services timer, which get called again (Consider them a timer within a timer!) */
static void add_svstimer_to_hash_table(char *name, Svs_Timers *svstmr)
{
svstmr->hash = HASH(name, MAX_SVS_TIMERS);
svstmr->next = serv_timers[svstmr->hash];
serv_timers[svstmr->hash] = (void *)svstmr;
}
static void del_svstimer_from_hash_table(char *name, Svs_Timers *svstmr)
{
Svs_Timers *tmp, *prev = NULL;
for (tmp = serv_timers[svstmr->hash]; tmp; tmp = tmp->next) {
if (tmp == svstmr) {
if (prev)
prev->next = tmp->next;
else
serv_timers[svstmr->hash] = tmp->next;
tmp->next = NULL;
return;
}
prev = tmp;
}
}
void init_svstimer_hash()
{
int i;
Svs_Timers *svstmr, *prev;
for (i = 0; i < MAX_SVS_TIMERS; i++) {
svstmr = serv_timers[i];
while (svstmr) {
prev = svstmr->next;
free(svstmr);
svstmr = prev;
}
serv_timers[i] = NULL;
}
bzero((char *)serv_timers, sizeof(serv_timers));
}
int runsvstimers()
{
Svs_Timers *svstmr;
time_t current = time(NULL);
int i, ret = 0;
int startime, count = 0;
startime = time(NULL);
for (i = 0; i < MAX_SVS_TIMERS; i++) {
svstmr = serv_timers[i];
while (svstmr) {
if (current - svstmr->lastrun >= svstmr->interval) {
#ifdef DEBUG
log("runsvstimers(%s)", svstmr->timername);
#endif
svstmr->lastrun = time(NULL);
ret = svstmr->function(svstmr->varibles);
/* if ret = 1 then delete the timer */
if (ret == 1) {
svstmr->interval = 0;
}
count++;
}
svstmr = svstmr->next;
}
}
/* only run garbage cleanup if there is something to clean up */
if (ret == 1) del_svs_dead_timers();
if ((time(NULL) - startime) > 5) {
notice(s_NickServ, "\002Warning, Timers are taking a long time to run\002");
notice(s_NickServ, "\002This is Lagging out NeoStats\002");
notice(s_NickServ, "\002Suggest you Change your Timer Settings (Such a EnforcerTime, Identtime) to something smaller\002");
notice(s_NickServ, "\002If this message keeps re-occuring. (it might be normal when a split server rejoins)\002");
notice(s_NickServ, "\002We Ran %d timers and it took %d Sec...\002", count, time(NULL) - startime);
}
return 1;
}
void del_svs_dead_timers()
{
Svs_Timers *svstmr;
int i;
#ifdef DEBUG
log("Services Timer Garbage Cleanup");
#endif
for (i = 0; i < MAX_SVS_TIMERS; i++) {
svstmr = serv_timers[i];
while (svstmr) {
if (svstmr->interval == 0) {
del_svstimer_from_hash_table(svstmr->timername, svstmr);
}
svstmr = svstmr->next;
}
}
}
void del_svs_timers(char *name)
{
Svs_Timers *svstmr;
#ifdef DEBUG
log("Delsvstimer(%s)", name);
#endif
svstmr = serv_timers[HASH(name, MAX_SVS_TIMERS)];
while (svstmr && strcasecmp(svstmr->timername, name) != 0)
svstmr = svstmr->next;
if (!svstmr) {
log("Delsvstimer(%s) failed!", name);
return;
}
del_svstimer_from_hash_table(name, svstmr);
}
Svs_Timers *new_svs_timers(char *name)
{
Svs_Timers *svstmr;
svstmr = malloc(sizeof(Svs_Timers));
bzero(svstmr, sizeof(Svs_Timers));
#ifdef DEBUG
log("New Services Timer: %s", name);
#endif
memcpy(svstmr->timername, name, strlen(name));
add_svstimer_to_hash_table(name, svstmr);
return svstmr;
}