#include "../nick/nick.h"
#include "../core/hooks.h"
#include "../lib/strlfunc.h"
+#include "../lib/version.h"
#include <string.h>
#include <stdio.h>
+MODULE_VERSION("")
+
#define ALLOCUNIT 100
#define authnamehash(x) ((x)%AUTHNAMEHASHSIZE)
/* internal access only */
static authname *authnametablebyname[AUTHNAMEHASHSIZE];
-sstring *authnameextnames[MAXAUTHNAMEEXTS];
+static struct {
+ sstring *name;
+ int persistant;
+} authnameexts[MAXAUTHNAMEEXTS];
static void authextstats(int hooknum, void *arg);
freeauthnames=anp;
}
-int registerauthnameext(const char *name) {
+int registerauthnameext(const char *name, int persistant) {
int i;
if (findauthnameext(name)!=-1) {
}
for (i=0;i<MAXAUTHNAMEEXTS;i++) {
- if (authnameextnames[i]==NULL) {
- authnameextnames[i]=getsstring(name,100);
+ if (authnameexts[i].name==NULL) {
+ authnameexts[i].name=getsstring(name,100);
+ authnameexts[i].persistant=persistant;
return i;
}
}
int i;
for (i=0;i<MAXAUTHNAMEEXTS;i++) {
- if (authnameextnames[i]!=NULL && !ircd_strcmp(name,authnameextnames[i]->content)) {
+ if (authnameexts[i].name!=NULL && !ircd_strcmp(name,authnameexts[i].name->content)) {
return i;
}
}
int i;
authname *anp;
- freesstring(authnameextnames[index]);
- authnameextnames[index]=NULL;
+ freesstring(authnameexts[index].name);
+ authnameexts[index].name=NULL;
for (i=0;i<AUTHNAMEHASHSIZE;i++) {
for (anp=authnametable[i];anp;anp=anp->next) {
anp->nicks = NULL;
for(i=0;i<MAXAUTHNAMEEXTS;i++)
- if(anp->exts[i]!=NULL)
+ if(authnameexts[i].persistant && anp->exts[i]!=NULL)
return;
+ triggerhook(HOOK_AUTH_LOSTAUTHNAME, (void *)anp);
found = 0;
for(manp=&(authnametable[authnamehash(anp->userid)]);*manp;manp=(authname **)&((*manp)->next)) {
if ((*manp)==anp) {
void freeauthname (authname *hp);
/* EXT management */
-int registerauthnameext(const char *name);
+int registerauthnameext(const char *name, int persistant);
int findauthnameext(const char *name);
void releaseauthnameext(int index);
#include "../irc/irc_config.h"
#include "../core/nsmalloc.h"
#include "../lib/flags.h"
+#include "../lib/version.h"
+
+MODULE_VERSION("")
#define ALLOCUNIT 100
#include "../lib/irc_string.h"
#include "../core/error.h"
#include "../core/nsmalloc.h"
+#include "../lib/version.h"
#include <stdio.h>
#include <string.h>
+MODULE_VERSION("")
+
#define ALLOCUNIT 1000
#define channelhash(x) (crc32i(x)%CHANNELHASHSIZE)
void _init() {
chanservext=registerchanext("chanserv");
- chanservaext=registerauthnameext("chanserv");
+ chanservaext=registerauthnameext("chanserv",1);
/* Set up the allocators and hashes */
chanservallocinit();
int controlreload(void *sender, int cargc, char **cargv);
int controlhelpcmd(void *sender, int cargc, char **cargv);
void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...);
-void handlerehash(int hooknum, void *arg);
+void handlesignal(int hooknum, void *arg);
void _init() {
controlcmds=newcommandtree();
registercontrolhelpcmd("reload",NO_DEVELOPER,1,&controlreload,"Usage: reload <module>\nReloads specified module.");
registercontrolhelpcmd("help",NO_ANYONE,1,&controlhelpcmd,"Usage: help <command>\nShows help for specified command.");
- registerhook(HOOK_CORE_REHASH, &handlerehash);
+ registerhook(HOOK_CORE_REHASH, &handlesignal);
+ registerhook(HOOK_CORE_SIGINT, &handlesignal);
scheduleoneshot(time(NULL)+1,&controlconnect,NULL);
}
destroycommandtree(controlcmds);
- deregisterhook(HOOK_CORE_REHASH, &handlerehash);
+ deregisterhook(HOOK_CORE_REHASH, &handlesignal);
+ deregisterhook(HOOK_CORE_SIGINT, &handlesignal);
}
void registercontrolhelpcmd(const char *name, int level, int maxparams, CommandHandler handler, char *help) {
/* someone killed me? Bastards */
scheduleoneshot(time(NULL)+1,&controlconnect,NULL);
mynick=NULL;
+ triggerhook(HOOK_CONTROL_REGISTERED, NULL);
break;
default:
controlwall(NO_OPER, noticelevel, "%s", broadcast);
}
-void handlerehash(int hooknum, void *arg) {
- long hupped = (long)arg;
- if(hupped)
- controlwall(NO_OPER, NL_OPERATIONS, "SIGHUP received, rehashing...");
-}
+void handlesignal(int hooknum, void *arg) {
+ char *signal, *action;
+
+ if(hooknum == HOOK_CORE_SIGINT) {
+ signal = "INT";
+ action = "terminating";
+ } else {
+ long hupped = (long)arg;
+ if(!hupped)
+ return;
+ signal = "HUP";
+ action = "rehashing";
+ }
+
+ controlwall(NO_OPER, NL_OPERATIONS, "SIG%s received, %s...", signal, action);
+}
#define HOOK_CORE_STOPERROR 4
#define HOOK_CORE_ERROR 5 /* Argument is a struct error_event * */
#define HOOK_CORE_SIGUSR1 6
+#define HOOK_CORE_SIGINT 7
#define HOOK_IRC_CONNECTED 100 /* Located in server.c now to fix burst bug */
#define HOOK_IRC_DISCON 101
#define HOOK_SHADOW_SERVER 701 /* Argument is char* */
#define HOOK_AUTH_FLAGSUPDATED 801 /* Argument is void*[2] (authname*, u_int64_t*) */
+#define HOOK_AUTH_LOSTAUTHNAME 802 /* Argument is authname* */
typedef void (*HookCallback)(int, void *);
void handlesignals(void);
int newserv_shutdown_pending;
-static int newserv_sigusr1_pending, newserv_sighup_pending;
+static int newserv_sigint_pending, newserv_sigusr1_pending, newserv_sighup_pending;
static void (*oldsegv)(int);
int main(int argc, char **argv) {
triggerhook(HOOK_CORE_REHASH, (void *)1);
newserv_sighup_pending=0;
}
+
+ if (newserv_sigint_pending) {
+ Error("core", ERR_INFO, "SIGINT received, terminating.");
+ triggerhook(HOOK_CORE_SIGINT, NULL);
+ newserv_sigint_pending=0;
+ newserv_shutdown_pending=1;
+ }
}
/*
}
void siginthandler(int sig) {
- newserv_shutdown_pending = 1;
+ newserv_sigint_pending = 1;
}
void sigusr1handler(int sig) {
int insmod(char *modulename) {
int i;
module *mods;
- char buf[1024];
+ char buf[1024], modulebuf[1024];
const char *(*verinfo)(const char **);
struct module_dep *mdp;
- delchars(modulename,"./\\;");
+ strlcpy(modulebuf, modulename, sizeof(modulebuf));
+ delchars(modulebuf,"./\\;");
- if (isloaded(modulename)) {
- Error("core",ERR_DEBUG,"Tried to load already loaded module: %s",modulename);
+ if (isloaded(modulebuf)) {
+ Error("core",ERR_DEBUG,"Tried to load already loaded module: %s",modulebuf);
return 1;
}
- if (strlen(modulename)>100) {
- Error("core",ERR_WARNING,"Module name too long: %s",modulename);
+ if (strlen(modulebuf)>100) {
+ Error("core",ERR_WARNING,"Module name too long: %s",modulebuf);
return 1;
}
- if ((mdp=getmoduledep(modulename))) {
+ if ((mdp=getmoduledep(modulebuf))) {
for (i=0;i<mdp->numparents;i++) {
if (!isloaded(mdp->parents[i]->name->content)) {
if (insmod(mdp->parents[i]->name->content)) {
Error("core",ERR_WARNING,"Error loading dependant module %s (needed by %s)",
- mdp->parents[i]->name->content,modulename);
+ mdp->parents[i]->name->content,modulebuf);
return 1;
}
}
}
} else {
- Error("core",ERR_WARNING,"Loading module %s without dependency information.",modulename);
+ Error("core",ERR_WARNING,"Loading module %s without dependency information.",modulebuf);
}
i=array_getfreeslot(&modules);
mods=(module *)(modules.content);
- sprintf(buf,"%s/%s%s",moddir->content,modulename,modsuffix->content);
+ sprintf(buf,"%s/%s%s",moddir->content,modulebuf,modsuffix->content);
mods[i].handle=dlopen(buf,RTLD_NOW|RTLD_GLOBAL);
if(mods[i].handle==NULL) {
- Error("core",ERR_ERROR,"Loading module %s failed: %s",modulename,dlerror());
+ Error("core",ERR_ERROR,"Loading module %s failed: %s",modulebuf,dlerror());
array_delslot(&modules,i);
return -1;
}
- mods[i].name=getsstring(modulename,MODULENAMELEN);
+ mods[i].name=getsstring(modulebuf,MODULENAMELEN);
verinfo=dlsym(mods[i].handle,"_version");
if(verinfo) {
}
mods[i].loadedsince = time(NULL);
- Error("core",ERR_INFO,"Loaded module %s OK.",modulename);
+ Error("core",ERR_INFO,"Loaded module %s OK.",modulebuf);
return 0;
}
int i,j;
module *mods;
struct module_dep *mdp;
+ char modulebuf[1024];
+
+ strlcpy(modulebuf, modulename, sizeof(modulebuf));
+ delchars(modulebuf,"./\\;");
- delchars(modulename,"./\\;");
-
- i=getindex(modulename);
+ i=getindex(modulebuf);
if (i<0)
return 1;
- if ((mdp=getmoduledep(modulename))) {
+ if ((mdp=getmoduledep(modulebuf))) {
for (j=0;j<mdp->numchildren;j++) {
if (isloaded(mdp->children[j]->name->content)) {
if (rmmod(mdp->children[j]->name->content)) {
Error("core",ERR_WARNING,"Unable to remove child module %s (depends on %s)",
- mdp->children[j]->name->content, modulename);
+ mdp->children[j]->name->content, modulebuf);
return 1;
}
}
}
/* We may have removed other modules - reaquire the index number in case it has changed. */
- i=getindex(modulename);
+ i=getindex(modulebuf);
if (i<0)
return 1;
} else {
- Error("core",ERR_WARNING,"Removing module %s without dependency information",modulename);
+ Error("core",ERR_WARNING,"Removing module %s without dependency information",modulebuf);
}
mods=(module *)(modules.content);
freesstring(mods[i].name);
array_delslot(&modules,i);
- Error("core",ERR_INFO,"Removed module %s.",modulename);
+ Error("core",ERR_INFO,"Removed module %s.",modulebuf);
return 0;
}
+++ /dev/null
-@include@ @includel@../build.mk@includel@
-
-.PHONY: all
-all: graphing.so nterfacer_graphing.so dump
-
-graphing.so: graphing.o fsample.o
-
-nterfacer_graphing.so: nterfacer_graphing.o
-
-dump: dump.o fsample.o
- $(CC) $(CFLAGS) -o $@ @srcs@
+++ /dev/null
-#include "graphing.h"
-#include <stdio.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-
-int dump(fsample_m *f, fsample_t start, fsample_t stop) {
- int i, j;
-
- for(i=start;i<stop;i++) {
- printf("%2d ", i);
- for(j=0;j<f->pos;j++) {
- fsample_t t;
- int moo = fsget_m(f, j, i, &t);
-
- if(!moo) {
- int moo2 = fsget_mr(f, j, i, &t);
- printf("X%2d(%2d) ", t, moo2);
- } else {
- printf(" %2d(%2d) ", t, moo);
- }
- }
- printf("\n");
- }
-
- return 0;
-}
-
-
-int main(int cargc, char **cargv) {
- fsample_m *f;
- int stop = time(NULL) / GRAPHING_RESOLUTION;
- struct stat sb;
-
- if(cargc < 2) {
- puts("insufficient args");
- return 1;
- }
-
- if(stat(cargv[1], &sb) == -1) {
- puts("file doesn't exist");
- return 2;
- }
-
- f = fsopen_m(0, cargv[1], SAMPLES, NULL, NULL);
- if(!f)
- return 3;
-
- dump(f, stop - 100, stop);
-
- fsclose_m(f);
-
- return 0;
-}
-
+++ /dev/null
-#include "fsample.h"
-
-#include <sys/types.h>
-#include <sys/uio.h>
-#include <unistd.h>
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <string.h>
-
-static fsample_t version = 1;
-
-static void fscorefree(void *arg) {
- fsample *f = (fsample *)arg;
- munmap(f->header, f->len);
-}
-
-fsample *fsopen(char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn) {
- int flags = 0;
- int new = 0;
- fsample *f = (fsample *)malloc(sizeof(fsample));
- if(!f)
- return NULL;
-
- f->len = samples * sizeof(struct fsample_p) + sizeof(struct fsample_header);
- f->fd = open(filename, O_RDWR|O_CREAT, 0600);
-
- if(!lseek(f->fd, 0, SEEK_END))
- new = 1;
-
- if((f->fd == -1) || (lseek(f->fd, f->len - 1, SEEK_SET) == -1)) {
- free(f);
- return NULL;
- }
- write(f->fd, "", 1);
-
- flags = MAP_SHARED;
-#ifdef MAP_NOCORE
- flags|=MAP_NOCORE;
-#endif
-
- f->header = mmap(NULL, f->len, PROT_READ|PROT_WRITE, flags, f->fd, 0);
- if(f->header == MAP_FAILED) {
- close(f->fd);
- free(f);
- return NULL;
- }
-
- if(!new && (memcmp(f->header->magic, "FSAMP", sizeof(f->header->magic)) || (version != f->header->version))) {
- munmap(f->header, f->len);
- close(f->fd);
- free(f);
- return NULL;
- }
-
- if(chafn && chdfn) {
- f->corehandler = chafn(fscorefree, f);
- f->corehandlerdel = chdfn;
- } else {
- f->corehandler = NULL;
- f->corehandlerdel = NULL;
- }
-
- memcpy(f->header->magic, "FSAMP", sizeof(f->header->magic));
- f->header->version = version;
-
- f->m = (struct fsample_p *)(f->header + 1);
- f->samples = samples;
-
- if(f->header->iteration == 0)
- f->header->iteration = 1;
-
- return f;
-}
-
-void fsclose(fsample *f) {
- munmap(f->header, f->len);
- close(f->fd);
-
- if(f->corehandlerdel && f->corehandler)
- (f->corehandlerdel)(f->corehandler);
-
- free(f);
-}
-
-int fsadd_m(fsample_m *f, char *filename, size_t freq, DeriveValueFn derive, void *tag) {
- fsample_m_entry *p = &f->entry[f->pos];
-
- p->f = fsopen(filename, f->samples / freq, f->chafn, f->chdfn);
- if(!p->f)
- return 0;
-
- p->freq = freq;
- p->derive = derive;
- p->tag = tag;
- f->pos++;
- return 1;
-}
-
-fsample_m *fsopen_m(size_t count, char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn) {
- fsample_m *n = (fsample_m *)malloc(sizeof(fsample_m) + (count + 1) * sizeof(fsample_m_entry));
- if(!n)
- return NULL;
-
- n->samples = samples;
- n->pos = 0;
- n->chafn = chafn;
- n->chdfn = chdfn;
-
- if(!fsadd_m(n, filename, 1, NULL, 0)) {
- free(n);
- return NULL;
- }
-
- return n;
-}
-
-void fsset_m(fsample_m *f, fsample_t pos, fsample_t value) {
- int i;
-
- for(i=0;i<f->pos;i++) {
- fsample_t v;
-
- if((pos + 1) % f->entry[i].freq != 0)
- continue;
-
- if(f->entry[i].derive) {
- v = (f->entry[i].derive)(f, i, pos, f->entry[i].tag);
- } else {
- v = value;
- }
-
- fsset(f->entry[i].f, pos / f->entry[i].freq, v);
- }
-}
-
-void fsclose_m(fsample_m *f) {
- int i;
-
- for(i=0;i<f->pos;i++)
- fsclose(f->entry[i].f);
- free(f);
-}
-
-fsample_t fsamean(fsample_m *f, int entry, fsample_t pos, void *tag) {
- fsample_t c = 0;
- long samples = (long)tag;
- int count = 0;
- int rpos = pos / f->entry[0].freq;
- int i;
- fsample_t t;
-
- for(i=0;i<samples;i++) {
- if(__fsget_m(f, 0, rpos - i, &t)) {
- c+=t;
- count++;
- } else {
-/* printf("bad :(\n");*/
- }
- }
-
- if(count == 0)
- return 0;
-
- return c / count;
-}
-
-fsample_t fsapmean(fsample_m *f, int entry, fsample_t pos, void *tag) {
- fsample_t c = 0;
- long samples = (long)tag;
- int count = 0;
- int rpos = pos / f->entry[entry - 1].freq;
- int i;
- fsample_t t;
-
- for(i=0;i<=samples;i++) {
- if(__fsget(f->entry[entry - 1].f, rpos - i, &t)) {
- c+=t;
- count++;
- } else {
- /*printf("bad :(\n");*/
- }
- }
-
- if(count == 0)
- return 0;
-
- return c / count;
-}
+++ /dev/null
-#ifndef __FSAMPLE_H
-#define __FSAMPLE_H
-
-#include <sys/types.h>
-
-typedef u_int32_t fsample_t;
-
-typedef struct fsample fsample;
-
-/* nice loss of type safety here... */
-typedef void *(*CoreHandlerAddFn)(void *handler, void *arg);
-typedef void (*CoreHandlerDelFn)(void *);
-
-/* single sample functions */
-fsample *fsopen(char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn);
-void fsclose(fsample *f);
-
-struct fsample_m;
-typedef fsample_t (*DeriveValueFn)(struct fsample_m *v, int entry, fsample_t pos, void *tag);
-
-typedef struct fsample_m_entry {
- size_t freq;
- fsample *f;
- void *tag;
- DeriveValueFn derive;
-} fsample_m_entry;
-
-typedef struct fsample_m {
- size_t pos, samples;
- CoreHandlerAddFn chafn;
- CoreHandlerDelFn chdfn;
- struct fsample_m_entry entry[];
-} fsample_m;
-
-/* multiple sample functions */
-fsample_m *fsopen_m(size_t count, char *filename, size_t samples, CoreHandlerAddFn chafn, CoreHandlerDelFn chdfn);
-void fsclose_m(fsample_m *f);
-int fsadd_m(fsample_m *f, char *filename, size_t freq, DeriveValueFn derive, void *tag);
-void fsset_m(fsample_m *f, fsample_t pos, fsample_t value);
-
-/* aggregates */
-fsample_t fsamean(fsample_m *f, int entry, fsample_t pos, void *tag);
-fsample_t fsapmean(fsample_m *f, int entry, fsample_t pos, void *tag);
-
-struct fsample_p {
- fsample_t v;
- unsigned char iteration;
-};
-
-struct fsample_header {
- char magic[4];
- fsample_t version;
- unsigned char iteration;
- fsample_t lastpos;
-};
-
-struct fsample {
- struct fsample_p *m;
- int fd;
- size_t samples, len;
- struct fsample_header *header;
- void *corehandler;
- CoreHandlerDelFn corehandlerdel;
-};
-
-static inline unsigned char previteration(fsample *f) {
- unsigned char p = f->header->iteration - 1;
- if(p == 0)
- p = 255;
- return p;
-}
-
-/* doesn't support writing to negative numbers... */
-static inline void fsset(fsample *f, fsample_t pos, fsample_t value) {
- fsample_t actualpos = pos % f->samples;
- struct fsample_p *p = &f->m[actualpos];
-
- if(f->header->lastpos > actualpos) {
- f->header->iteration++;
- if(f->header->iteration == 0)
- f->header->iteration = 1;
- }
-
- f->header->lastpos = actualpos;
-
- p->iteration = f->header->iteration;
- p->v = value;
-}
-
-static inline fsample_t mmod(int x, int y) {
-#if -5 % 3 == -2
- int v = x % y;
- if(v < 0)
- v = v + y;
- return v;
-#else
-#error Unknown modulo operator function.
-#endif
-}
-
-/* API functions only have access to positive indicies */
-static inline fsample_t __fsget(fsample *f, int pos, fsample_t *t) {
- struct fsample_p *p = &f->m[mmod(pos, f->samples)];
-
- if(p->iteration != f->header->iteration) {
- unsigned char prev = previteration(f);
-
- if(prev != p->iteration || (pos <= f->header->lastpos)) {
- /*printf("bad: prev: %d p->iteration: %d, pos: %d lastpos: %d\n", prev, p->iteration, pos, f->header->lastpos);*/
- return 0;
- }
- }
-
- *t = p->v;
- return p->iteration;
-}
-
-static inline fsample_t fsget_r(fsample *f, fsample_t pos, fsample_t *t) {
- struct fsample_p *p = &f->m[mmod(pos, f->samples)];
-
- *t = p->v;
- return p->iteration;
-}
-
-static inline fsample_t fsget(fsample *f, fsample_t pos, fsample_t *t) {
- return __fsget(f, pos, t);
-}
-
-static inline fsample_t __fsget_m(fsample_m *f, int entry, int pos, fsample_t *t) {
- return __fsget(f->entry[entry].f, pos / f->entry[entry].freq, t);
-}
-
-static inline fsample_t fsget_m(fsample_m *f, int entry, fsample_t pos, fsample_t *t) {
- return fsget(f->entry[entry].f, pos / f->entry[entry].freq, t);
-}
-
-static inline fsample_t fsget_mr(fsample_m *f, int entry, fsample_t pos, fsample_t *t) {
- return fsget_r(f->entry[entry].f, pos / f->entry[entry].freq, t);
-}
-
-#endif
+++ /dev/null
-#include <string.h>
-#include <stdio.h>
-
-#include "../core/hooks.h"
-#include "../core/config.h"
-#include "../usercount/usercount.h"
-#include "../lib/sstring.h"
-#include "../core/schedule.h"
-#include "../core/error.h"
-#include "../lib/sha1.h"
-#include "../lib/hmac.h"
-
-#include "graphing.h"
-
-static void gr_newserver(int hook, void *arg);
-static void gr_lostserver(int hook, void *arg);
-static void tick(void *arg);
-static void openserver(int servernum);
-static void closeserver(int servernum);
-
-fsample_m *servergraphs[MAXSERVERS];
-static void *sched;
-
-static sstring *path;
-
-void _init(void) {
- int i;
-
- memset(servergraphs, 0, sizeof(servergraphs));
-
- path = getcopyconfigitem("graphing", "path", "", 100);
- if(!path || !path->content || !path->content[0]) {
- Error("graphing", ERR_WARNING, "Path not set, not loaded.");
- return;
- }
-
- for(i=0;i<MAXSERVERS;i++)
- openserver(i);
-
- registerhook(HOOK_SERVER_NEWSERVER, gr_newserver);
- registerhook(HOOK_SERVER_LOSTSERVER, gr_lostserver);
-
- sched = schedulerecurring(time(NULL), 0, 1, tick, NULL);
-}
-
-void _fini(void) {
- int i;
- if(sched)
- deleteschedule(sched, tick, NULL);
-
- for(i=0;i<MAXSERVERS;i++)
- if(servermonitored(i))
- closeserver(i);
-
- freesstring(path);
-
- deregisterhook(HOOK_SERVER_NEWSERVER, gr_newserver);
- deregisterhook(HOOK_SERVER_LOSTSERVER, gr_lostserver);
-}
-
-int servermonitored(int servernum) {
- return servergraphs[servernum] != NULL;
-}
-
-static char *appendsuffix(char *prefix, char *suffix) {
- static char buf[1024];
-
- snprintf(buf, sizeof(buf), "%s%s", prefix, suffix);
-
- return buf;
-}
-
-static void openserver(int servernum) {
- unsigned char digest[SHA1_DIGESTSIZE];
- char filename[512], hexdigest[sizeof(digest)*2 + 1];
- FILE *f;
- SHA1_CTX sha;
- fsample_m *m;
-
- if(servermonitored(servernum))
- return;
-
- if(serverlist[servernum].linkstate == LS_INVALID)
- return;
-
- SHA1Init(&sha);
- SHA1Update(&sha, (unsigned char *)serverlist[servernum].name->content, serverlist[servernum].name->length);
- SHA1Final(digest, &sha);
-
- snprintf(filename, sizeof(filename), "%s/%s", path->content, hmac_printhex(digest, hexdigest, sizeof(digest)));
-
- f = fopen(appendsuffix(filename, ".name"), "w");
- if(!f) {
- Error("graphing", ERR_WARNING, "Unable to create name file for %s (%s.name)", serverlist[servernum].name->content, filename);
- return;
- }
-
- fprintf(f, "%s\n", serverlist[servernum].name->content);
- fclose(f);
-
- /* 0: seconds
- 1: minutes
- 2: hours
- 3: days
- 4: weeks
- 5: months
- */
-
- m = fsopen_m(GRAPHING_DATASETS, appendsuffix(filename, ".0"), SAMPLES, (CoreHandlerAddFn)registercorehandler, (CoreHandlerDelFn)deregistercorehandler);
- if(!m) {
- Error("graphing", ERR_WARNING, "Unable to create main backing store for %s (%s.0)", serverlist[servernum].name->content, filename);
- return;
- }
-/*
- if(!fsadd_m(m, appendsuffix(filename, ".1"), PERMINUTE, fsapmean, (void *)PERMINUTE) ||
- !fsadd_m(m, appendsuffix(filename, ".2"), PERMINUTE * 24, fsapmean, (void *)(PERMINUTE * 24)) ||
- !fsadd_m(m, appendsuffix(filename, ".3"), PERMINUTE * 24 * 7, fsapmean, (void *)(PERMINUTE * 24 * 7)) ||
- !fsadd_m(m, appendsuffix(filename, ".4"), PERMINUTE * 24 * 7 * 4, fsapmean, (void *)(PERMINUTE * 24 * 7 * 4)) ||
- !fsadd_m(m, appendsuffix(filename, ".5"), PERMINUTE * 24 * 7 * 4 * 12, fsapmean, (void *)(PERMINUTE * 24 * 7 * 4 * 12)))
- {
- Error("graphing", ERR_WARNING, "Unable to create main side store for %s (%s.X)", serverlist[servernum].name->content, filename);
- fsclose_m(m);
- return;
- }
-*/
- servergraphs[servernum] = m;
-}
-
-static void closeserver(int servernum) {
- if(!servermonitored(servernum))
- return;
-
- fsclose_m(servergraphs[servernum]);
- servergraphs[servernum] = NULL;
-}
-
-static void gr_newserver(int hook, void *arg) {
- long num = (long)arg;
-
- openserver(num);
-}
-
-static void gr_lostserver(int hook, void *arg) {
- long num = (long)arg;
-
- closeserver(num);
-}
-
-static void tick(void *arg) {
- time_t t = time(NULL);
- int i;
-
- if(t % GRAPHING_RESOLUTION != 0)
- return;
-
- for(i=0;i<MAXSERVERS;i++)
- if(servermonitored(i))
- fsset_m(servergraphs[i], t / GRAPHING_RESOLUTION, servercount[i]);
-}
-
-
+++ /dev/null
-#ifndef __GRAPHING_H
-#define __GRAPHING_H
-
-#include "../server/server.h"
-#include "../graphing/fsample.h"
-
-extern fsample_m *servergraphs[MAXSERVERS];
-int servermonitored(int servernum);
-
-#define GRAPHING_DATASETS 5
-#define GRAPHING_RESOLUTION 5
-
-#define PERMINUTE (60 / GRAPHING_RESOLUTION)
-#define SAMPLES PERMINUTE * 60 * 24 * 7 * 4 * 12
-
-#endif
+++ /dev/null
-#include "../nterfacer/library.h"
-#include "../nterfacer/nterfacer.h"
-
-#include "graphing.h"
-
-#include <time.h>
-
-#define ERR_SERVER_NOT_MONITORED 0x01
-#define ERR_BAD_PARAMETERS 0x02
-#define ERR_BAD_ENTRY 0x03
-
-int handle_servernames(struct rline *li, int argc, char **argv);
-int handle_serverdata(struct rline *li, int argc, char **argv);
-
-static struct service_node *g_node;
-
-void _init(void) {
- g_node = register_service("graphing");
- if(!g_node)
- return;
-
- register_handler(g_node, "servernames", 0, handle_servernames);
- register_handler(g_node, "serverdata", 3, handle_serverdata);
-}
-
-void _fini(void) {
- if(g_node)
- deregister_service(g_node);
-}
-
-int handle_servernames(struct rline *li, int argc, char **argv) {
- int i;
-
- for(i=0;i<MAXSERVERS;i++) {
- if((serverlist[i].linkstate != LS_INVALID) && servermonitored(i)) {
- if(ri_append(li, "%d:%s", i, serverlist[i].name->content) == BF_OVER)
- return ri_error(li, BF_OVER, "Buffer overflow");
- }
- }
-
- return ri_final(li);
-}
-
-int handle_serverdata(struct rline *li, int argc, char **argv) {
- int servernum = atoi(argv[0]);
- unsigned int entry = atoi(argv[1]);
- fsample_t count = atoi(argv[2]);
- time_t t = time(NULL) / GRAPHING_RESOLUTION;
- int i, ret;
- fsample_m *m;
-
- if(!servermonitored(servernum))
- return ri_error(li, ERR_SERVER_NOT_MONITORED, "Server not monitored");
-
- m = servergraphs[servernum];
-
- if(entry > m->pos) /* not inclusive as 0 is used for for the base index */
- return ri_error(li, ERR_BAD_PARAMETERS, "Bad parameters");
-
- for(i=0;i<count;i++) {
- fsample_t v;
- if(fsget_m(m, entry, t - m->entry[entry].freq * i, &v)) {
- ret = ri_append(li, "%d", v);
- } else {
- ret = ri_append(li, "-1", v);
- }
- if(ret == BF_OVER)
- return ri_error(li, BF_OVER, "Buffer overflow");
- }
-
- return ri_final(li);
-}
-
/*
* longtoduration:
* Converts a specified number of seconds into a duration string.
- * format: 0 for the "/stats u" compatible output, 1 for more human-friendly output, 2 for a different human-friendly output.
+ * format: 0 for the "/stats u" compatible output, 1 for more
+ * human-friendly output (that is sometimes format 0), and
+ * 2 for a different human-friendly output.
*/
const char *longtoduration(unsigned long interval, int format) {
hours=(interval%(3600*24))/3600;
days=interval/(3600*24);
- if (format==0) {
- sprintf(outstring,"%d day%s, %02d:%02d:%02d",
- days,(days==1)?"":"s",hours,minutes,seconds);
- } else if (format == 1) {
- if (days>0) {
+ if(format<2) {
+ if (format==0 || (days>0 && (hours||minutes||seconds))) {
+ sprintf(outstring,"%d day%s, %02d:%02d:%02d",
+ days,(days==1)?"":"s",hours,minutes,seconds);
+ } else if (days>0) {
sprintf(outstring, "%d day%s",days,(days==1)?"":"s");
} else {
if (hours>0) {
static int freecalls;
static int allocs;
-/* Internal function */
+/* Internal functions */
static void sstringstats(int hooknum, void *arg);
+static void salloc(void);
+
+#ifndef USE_VALGRIND
+
+#define sunprotect(x)
+#define sunprotectb(x)
+#define sprotect(x)
+
+#else
+
+#define __USE_MISC
+
+#include <sys/mman.h>
+static void *mblock;
+struct mblock_list {
+ void *block;
+ struct mblock_list *next;
+};
+
+static void *mblock_head;
+
+#define sunprotectb(x) mprotect(x, SSTRING_ALLOC, PROT_READ|PROT_WRITE);
+#define sunprotect(x) sunprotectb((x)->block);
+#define sprotect(x) mprotect((x)->block, SSTRING_ALLOC, PROT_READ);
+
+#ifndef MAP_ANON
+#define MAP_ANON MAP_ANONYMOUS
+#endif
+
+#endif /* USE_VALGRIND */
void initsstring() {
int i;
registerhook(HOOK_CORE_STATSREQUEST,&sstringstats);
}
+#ifndef USE_VALGRIND
void finisstring() {
nsfreeall(POOL_SSTRING);
}
+static void salloc(void) {
+ ssmem=(char *)nsmalloc(POOL_SSTRING, SSTRING_ALLOC);
+ ssmemfree=SSTRING_ALLOC;
+}
+#endif /* USE_VALGRIND */
+
sstring *findsstring(const char *str) {
unsigned int hash=crc32(str)%SSTRING_HASHSIZE;
sstring *ss;
void sstring_dehash(sstring *ss) {
unsigned int hash=crc32(ss->content)%SSTRING_HASHSIZE;
- sstring **ssh;
+ sstring *ssh, *ssp;
- for (ssh=&(sshash[hash]); *ssh; ssh=&((*ssh)->next)) {
- if (*ssh==ss) {
- *ssh=ss->next;
+ for (ssh=sshash[hash],ssp=NULL; ssh; ssp=ssh,ssh=ssh->next) {
+ if (ssh==ss) {
+ if (!ssp) {
+ sshash[hash]=ss->next;
+ } else {
+#ifndef USE_VALGRIND
+ ssp->next=ss->next;
+#else
+ if (ssp->block!=ss->block) {
+ sunprotect(ssp) {
+ ssp->next=ss->next;
+ } sprotect(ssp);
+ } else {
+ ssp->next=ss->next;
+ }
+ }
+#endif
return;
}
}
sstring *getsstring(const char *inputstr, int maxlen) {
int i;
sstring *retval=NULL;
- int length;
+ int length, foreignblock;
char strbuf[SSTRING_MAXLEN];
/* getsstring() on a NULL pointer returns a NULL sstring.. */
/* If it's hashed this is easy */
if ((retval=findsstring(strbuf))) {
- retval->refcount++;
+ sunprotect(retval) {
+ retval->refcount++;
+ } sprotect(retval);
+
return retval;
}
-
+
+ foreignblock=0;
/* Check to see if an approximately correct
* sized string is available */
for(i=0;i<SSTRING_SLACK;i++) {
if (freelist[length+i]!=NULL) {
retval=freelist[length+i];
freelist[length+i]=retval->next;
+ sunprotect(retval);
+ foreignblock=1;
+
retval->alloc=(length+i);
break;
}
/* Not enough for us - turn the remaining memory into a free string for later */
if (ssmemfree>sizeof(sstring)) {
retval=(sstring *)ssmem;
+ sunprotectb(mblock);
+ retval->block=mblock;
retval->alloc=(ssmemfree-sizeof(sstring));
retval->refcount=0;
freesstring(retval);
}
- allocs++;
- ssmem=(char *)nsmalloc(POOL_SSTRING, SSTRING_ALLOC);
- ssmemfree=SSTRING_ALLOC;
+ allocs++;
+ salloc();
+ } else {
+ sunprotectb(mblock);
}
retval=(sstring *)ssmem;
strcpy(retval->content,strbuf);
retval->refcount=1;
+#ifdef USE_VALGRIND
+ if(!foreignblock)
+ retval->block = mblock;
+#endif
+
sstring_enhash(retval);
-
+ sprotect(retval);
+
return retval;
}
/* Only count calls that actually did something */
freecalls++;
+ if (inval->refcount)
+ sunprotect(inval);
+
if (inval->refcount > 1) {
inval->refcount--;
+ sprotect(inval);
return;
}
- /* If refcount==0 it wasn't hashed */
+ /* If refcount==0 it wasn't hashed, or protected */
if (inval->refcount)
sstring_dehash(inval);
-
+
alloc=inval->alloc;
assert(alloc<=SSTRING_MAXLEN);
inval->next=freelist[alloc];
freelist[alloc]=inval;
+ sprotect(inval);
}
void sstringstats(int hooknum, void *arg) {
return strncmp(ss1->content, ss2->content, ss1->length);
}
+#ifdef USE_VALGRIND
+void finisstring() {
+ struct mblock_list *c, *n;
+ for (c=mblock_head;c;c=n) {
+ n=c->next;
+ munmap(c->block, SSTRING_ALLOC);
+ }
+}
+
+static void salloc(void) {
+ struct mblock_list *n;
+ mblock=mmap((void *)0, SSTRING_ALLOC, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANON, -1, 0);
+
+ n=(struct mblock_list *)mblock;
+ n->block = mblock;
+ n->next = mblock_head;
+ mblock_head = n;
+
+ ssmem=(char *)mblock + sizeof(struct mblock_list);
+ ssmemfree=SSTRING_ALLOC-sizeof(struct mblock_list);
+}
+#endif /* USE_VALGRIND */
/* Externally visibly max string length */
#define SSTRING_MAX 512
+/* you can actually change USE_VALGRIND here without recompiling! */
typedef struct sstring {
short length;
short alloc;
struct sstring *next;
+#ifdef USE_VALGRIND
+ void *block;
+#endif
+ unsigned long refcount;
char content[];
} sstring;
#else /* USE_VALGRIND */
+#define __USE_MISC
+#include <sys/mman.h>
+
+#ifndef MAP_ANON
+#define MAP_ANON MAP_ANONYMOUS
+#endif
+
+#define MModify(x) mprotect(x, x->s->u.l.alloc, PROT_READ|PROT_WRITE)
+#define MUnmodify(x) mprotect(x, x->s->u.l.alloc, PROT_READ)
+
typedef struct sstringlist {
struct sstringlist *prev;
struct sstringlist *next;
for(s=head;s;s=sn) {
sn = s->next;
+
+ MModify(s);
s->next = NULL;
s->prev = NULL;
sstringlist *s;
size_t len;
char *p;
+ void *m;
if(!inputstr)
return NULL;
; /* empty */
len = p - inputstr;
- s=(sstringlist *)malloc(sizeof(sstringlist) + sizeof(sstring));
-
+ m=mmap((void *)0, sizeof(sstringlist) + sizeof(sstring) + len + 1, PROT_WRITE|PROT_READ, MAP_PRIVATE|MAP_ANON, -1, 0);
+ s=(sstringlist *)m;
+
+ if(m == MAP_FAILED)
+ s->s->u.l.length = 0;
+
s->s->u.l.length = len;
- s->s->content=(char *)malloc(len + 1);
+ s->s->u.l.alloc = sizeof(sstringlist) + sizeof(sstring) + len + 1;
+ s->s->content=(char *)m + sizeof(sstringlist) + sizeof(sstring);
memcpy(s->s->content, inputstr, len);
s->s->content[len] = '\0';
s->next = head;
s->prev = NULL;
- if(head)
+ if(head) {
+ MModify(head);
head->prev = s;
+ MUnmodify(head);
+ }
head = s;
+ MUnmodify(s);
return s->s;
}
s = (sstringlist *)inval - 1;
+ MModify(s);
if(s->prev) {
+ MModify(s->prev);
s->prev->next = s->next;
- if(s->next)
+ MUnmodify(s->prev);
+ if(s->next) {
+ MModify(s->next);
s->next->prev = s->prev;
+ MUnmodify(s->prev);
+ }
} else {
head = s->next;
- if(head)
+ if(head) {
+ MModify(head);
head->prev = NULL;
+ MUnmodify(head);
+ }
}
- free(inval->content);
- free(s);
+ munmap(s, s->s->u.l.alloc);
}
#endif
#include "../nick/nick.h"
#include "../irc/irc.h"
#include "../core/error.h"
+#include "../lib/version.h"
#include <stdarg.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
+MODULE_VERSION("")
+
int handleserverstats(void *source, int cargc, char **cargv);
int handleserverstatsend(void *source, int cargc, char **cargv);
firsttime = 0;
}
- if(oldhandler)
+ if(oldhandler && mynick)
hooklocaluserhandler(mynick, oldhandler);
controlwall = oldwall;
}
void noperserv_trap_registration(int hooknum, void *arg) {
+ nick *np = (nick *)arg;
+ if(!np)
+ return;
+
oldhandler = hooklocaluserhandler((nick *)arg, &noperserv_handle_messages);
if(!oldhandler)
return;
#include "../localuser/localuserchannel.h"
#include "../control/control.h"
#include "../usercount/usercount.h"
+#include "../lib/version.h"
+
+MODULE_VERSION("")
#include <stdlib.h>
#include <string.h>
#include "../nick/nick.h"
#include "../core/hooks.h"
+#include "../lib/version.h"
#include "usercount.h"
+MODULE_VERSION("")
+
int servercount[MAXSERVERS];
static void uc_newserver(int hook, void *arg);
+/* TODO: catch control messages */
+
#include <string.h>
#include <stdio.h>
#include <stdarg.h>
#include "../irc/irc.h"
#include "../lib/array.h"
#include "../lib/base64.h"
+#include "../lib/irc_string.h"
#include "../core/error.h"
-#include "../server/server.h"
-#include "../control/control.h"
+#include "../localuser/localuser.h"
+#include "../lib/strlfunc.h"
#include "xsb.h"
+#undef XSB_DEBUG
+
static const char *DEFAULT_SERVICE_MASKS[] = { "services*.*.quakenet.org", (char *)0 };
+
static array defaultservicemasks_a;
static sstring **defaultservicemasks;
static void handlemaskprivmsg(int, void *);
+static void handlecontrolregistered(int, void *);
static CommandTree *cmds;
-#define DEBUG
+static char controlnum[6];
+
+struct messagequeue {
+ struct messagequeue *next;
+ char buf[];
+};
+
+struct messagequeue *head, *tail;
void _init(void) {
const char **p;
array *servicemasks;
+ controlnum[0] = '\0';
+
cmds = newcommandtree();
- if(cmds)
- registerhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg);
-
+ if(!cmds)
+ return;
+
+ registerhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg);
+ registerhook(HOOK_CONTROL_REGISTERED, &handlecontrolregistered);
+
array_init(&defaultservicemasks_a, sizeof(sstring *));
for(p=DEFAULT_SERVICE_MASKS;*p;p++) {
void _fini(void) {
int i;
+ struct messagequeue *q, *nq;
+
+ if(!cmds)
+ return;
+
+ destroycommandtree(cmds);
+
+ deregisterhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg);
+ deregisterhook(HOOK_CONTROL_REGISTERED, &handlecontrolregistered);
for(i=0;i<defaultservicemasks_a.cursi;i++)
freesstring(defaultservicemasks[i]);
array_free(&defaultservicemasks_a);
- if(!cmds)
- return;
+ for(q=head;q;q=nq) {
+ nq = q->next;
+ free(q);
+ }
+
+ head = NULL;
+ tail = NULL;
+}
- deregisterhook(HOOK_NICK_MASKPRIVMSG, &handlemaskprivmsg);
+void xsb_addcommand(const char *name, const int maxparams, CommandHandler handler) {
+ addcommandtotree(cmds, name, 0, maxparams, handler);
+}
- destroycommandtree(cmds);
+void xsb_delcommand(const char *name, CommandHandler handler) {
+ deletecommandfromtree(cmds, name, handler);
}
static void handlemaskprivmsg(int hooknum, void *args) {
return;
}
-#ifndef DEBUG
+#ifndef XSB_DEBUG
if(!(s->flags & SMODE_SERVICE)) {
Error("xsb", ERR_WARNING, "Got XSB message from non-service server (%s): %s", s->name->content, source->nick);
return;
(cmd->handler)(source, cargc - 2, &cargv[2]);
}
-void xsb_addcommand(const char *name, const int maxparams, CommandHandler handler) {
- addcommandtotree(cmds, name, 0, maxparams, handler);
+static void directsend(char *buf) {
+ irc_send("%s P %s", controlnum, buf);
}
-void xsb_delcommand(const char *name, CommandHandler handler) {
- deletecommandfromtree(cmds, name, handler);
+static void handlecontrolregistered(int hooknum, void *args) {
+ nick *np = (nick *)args;
+
+ if(np) {
+ struct messagequeue *q, *nq;
+
+ longtonumeric2(np->numeric, 5, controlnum);
+
+ for(q=head;q;q=nq) {
+ nq = q->next;
+
+ directsend(q->buf);
+ free(q);
+ }
+ head = NULL;
+ tail = NULL;
+ } else {
+ controlnum[0] = '\0';
+ }
}
-void xsb_command(const char *command, const char *format, ...) {
+static int getservicemasks(sstring ***masks) {
+ array *aservicemasks = getconfigitems("xsb", "servicemask");
+ if(!aservicemasks || !aservicemasks->cursi)
+ aservicemasks = &defaultservicemasks_a;
+
+ *masks = (sstring **)aservicemasks->content;
+
+ return aservicemasks->cursi;
+}
+
+static void xsb_send(const char *format, ...) {
+ char buf[512];
+ va_list va;
+ size_t len;
+
+ va_start(va, format);
+ len = vsnprintf(buf, sizeof(buf), format, va);
+ va_end(va);
+ if(len >= sizeof(buf))
+ len = sizeof(buf);
+
+ if(controlnum[0]) {
+ directsend(buf);
+ } else {
+ struct messagequeue *q = (struct messagequeue *)malloc(sizeof(struct messagequeue) + len);
+
+ strlcpy(q->buf, buf, len + 1);
+ q->next = NULL;
+ if(tail) {
+ tail->next = q;
+ } else {
+ head = q;
+ }
+ tail = q;
+ }
+}
+
+void xsb_broadcast(const char *command, server *service, const char *format, ...) {
char buf[512];
va_list va;
sstring **servicemasks;
- array *aservicemasks;
int i;
- char *controlnum;
va_start(va, format);
vsnprintf(buf, sizeof(buf), format, va);
va_end(va);
- aservicemasks = getconfigitems("xsb", "servicemask");
- if(!aservicemasks || !aservicemasks->cursi)
- aservicemasks = &defaultservicemasks_a;
+ if(service) {
+ xsb_send("$%s :XSB1 %s %s", service->name->content, command, buf);
+ return;
+ }
- servicemasks = (sstring **)aservicemasks->content;
+ for(i=getservicemasks(&servicemasks)-1;i>=0;i--)
+ xsb_send("$%s :XSB1 %s %s", servicemasks[i]->content, command, buf);
+}
- controlnum = longtonumeric(mynick->numeric, 5);
+void xsb_unicast(const char *command, nick *np, const char *format, ...) {
+ char buf[512];
+ va_list va;
+
+ va_start(va, format);
+ vsnprintf(buf, sizeof(buf), format, va);
+ va_end(va);
- for(i=0;i<aservicemasks->cursi;i++)
- irc_send("%s P $%s :XSB1 %s %s", controlnum, servicemasks[i]->content, command, buf);
+ /* TODO */
+ xsb_send("$%s :XSB1 %s %s", serverlist[homeserver(np->numeric)].name, command, buf);
+ /* xsb_send("%s :XSB1 %s %s", longtonumeric(np->numeric, 5), command, buf);*/
+
}
+
+int xsb_isservice(server *service) {
+ int i;
+ sstring **servicemasks;
+ char *name = service->name->content;
+
+ if(!(service->flags & SMODE_SERVICE))
+ return 0;
+
+ for(i=getservicemasks(&servicemasks)-1;i>=0;i--)
+ if(match2strings(servicemasks[i]->content, name))
+ return 1;
+
+ return 0;
+}
+
#define __XSB_H
#include "../parser/parser.h"
+#include "../nick/nick.h"
+#include "../server/server.h"
void xsb_addcommand(const char *name, const int maxparams, CommandHandler handler);
void xsb_delcommand(const char *name, CommandHandler handler);
-void xsb_command(const char *command, const char *format, ...);
+void xsb_broadcast(const char *command, server *service, const char *format, ...);
+void xsb_unicast(const char *command, nick *np, const char *format, ...);
+int xsb_isservice(server *service);
#endif