X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/a31ef5d5d97a8318dacd81583be15aaf1cd6d7a7..1dc949be3f4212f866e489bf7f2604ab6c09f3c0:/control/control.c diff --git a/control/control.c b/control/control.c index 48c4a77f..8c267645 100644 --- a/control/control.c +++ b/control/control.c @@ -20,6 +20,7 @@ #include "../lib/base64.h" #include "../core/modules.h" #include "../lib/version.h" +#include "../lib/irc_string.h" #include "control.h" #include @@ -35,7 +36,10 @@ nick *mynick; CommandTree *controlcmds; ControlMsg controlreply; ControlWall controlwall; +ControlPermitted controlpermitted; +DestroyExt controldestroyext; +void controldestroycmdext(void *ext); void handlemessages(nick *target, int messagetype, void **args); int controlstatus(void *sender, int cargc, char **cargv); void controlconnect(void *arg); @@ -48,12 +52,17 @@ int controllsmod(void *sender, int cargc, char **cargv); int controlrehash(void *sender, int cargc, char **cargv); 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, ...) __attribute__ ((format (printf, 3, 4))); void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...); +int controlcheckpermitted(flag_t level, nick *user); +void handlesignal(int hooknum, void *arg); void _init() { controlcmds=newcommandtree(); controlreply=&controlmessage; controlwall=&controlnoticeopers; + controlpermitted=&controlcheckpermitted; + controldestroyext=&controldestroycmdext; registercontrolhelpcmd("status",NO_DEVELOPER,1,&controlstatus,"Usage: status ?level?\nDisplays status information, increasing level gives more verbose information."); registercontrolhelpcmd("whois",NO_OPERED,1,&controlwhois,"Usage: whois \nDisplays lots of information about the specified nickname or numeric."); @@ -62,12 +71,14 @@ void _init() { registercontrolhelpcmd("die",NO_DEVELOPER,1,&die,"Usage: die \nTerminates the service."); registercontrolhelpcmd("insmod",NO_DEVELOPER,1,&controlinsmod,"Usage: insmod \nAdds a module to the running instance."); registercontrolhelpcmd("rmmod",NO_DEVELOPER,1,&controlrmmod,"Usage: rmmod \nRemoves a module from the running instance."); - registercontrolhelpcmd("lsmod",NO_DEVELOPER,0,&controllsmod,"Usage: lsmod\nLists currently running modules."); + registercontrolhelpcmd("lsmod",NO_OPER,0,&controllsmod,"Usage: lsmod\nLists currently running modules."); registercontrolhelpcmd("rehash",NO_DEVELOPER,1,&controlrehash,"Usage: rehash\nReloads configuration file."); registercontrolhelpcmd("showcommands",NO_ACCOUNT,0,&controlshowcommands,"Usage: showcommands\nShows all registered commands."); registercontrolhelpcmd("reload",NO_DEVELOPER,1,&controlreload,"Usage: reload \nReloads specified module."); registercontrolhelpcmd("help",NO_ANYONE,1,&controlhelpcmd,"Usage: help \nShows help for specified command."); - + + registerhook(HOOK_CORE_REHASH, &handlesignal); + registerhook(HOOK_CORE_SIGINT, &handlesignal); scheduleoneshot(time(NULL)+1,&controlconnect,NULL); } @@ -91,12 +102,57 @@ void _fini() { deregistercontrolcmd("help",&controlhelpcmd); destroycommandtree(controlcmds); + + deregisterhook(HOOK_CORE_REHASH, &handlesignal); + deregisterhook(HOOK_CORE_SIGINT, &handlesignal); +} + +void registercontrolhelpcmd(const char *name, int level, int maxparams, CommandHandler handler, char *helpstr) { + cmdhelp *help; + Command *newcmd; + + newcmd = addcommandtotree(controlcmds,name,level,maxparams,handler); + + if (helpstr) { + /* Allocate a help record */ + help=(cmdhelp *)malloc(sizeof(cmdhelp)); + if(!help) { + Error("control",ERR_ERROR,"Malloc failed: registercontrolhelpcmd"); + return; + } + memset((void *)help,0,sizeof(cmdhelp)); + + /* this isn't an sstring atm, as sstring has a max length (512) */ + int len=strlen(helpstr); + help->helpstr=(char *)malloc(len+1); + if(help->helpstr) { + strncpy(help->helpstr, helpstr, len); + help->helpstr[len] = '\0'; + } + newcmd->ext=(void *)help; + newcmd->destroyext=controldestroyext; + } } -void registercontrolhelpcmd(const char *name, int level, int maxparams, CommandHandler handler, char *help) { - addcommandhelptotree(controlcmds,name,level,maxparams,handler,help); +void registercontrolhelpfunccmd(const char *name, int level, int maxparams, CommandHandler handler, CommandHelp helpcmd) { + cmdhelp *help; + Command *newcmd; + + /* Allocate a help record */ + help=(cmdhelp *)malloc(sizeof(cmdhelp)); + if (!help) { + Error("control",ERR_ERROR,"Malloc failed: registercontrolhelpfunccmd"); + return; + } + memset((void *)help,0,sizeof(cmdhelp)); + + help->helpcmd=helpcmd; + + newcmd = addcommandexttotree(controlcmds,name,level,maxparams,handler, (void *)help); + newcmd->destroyext=controldestroyext; } + int deregistercontrolcmd(const char *name, CommandHandler handler) { return deletecommandfromtree(controlcmds, name, handler); } @@ -133,7 +189,7 @@ void handlestats(int hooknum, void *arg) { } int controlstatus(void *sender, int cargc, char **cargv) { - unsigned long level=5; + unsigned long level=999; hooknick=(nick *)sender; if (cargc>0) { @@ -193,19 +249,40 @@ int controlwhois(void *sender, int cargc, char **cargv) { } } controlreply((nick *)sender,"Timestamp : %lu",target->timestamp); + + /* HACK */ + { + int ext = findnickext("signontracker"); + + if(ext >= 0) { + time_t signedon = (time_t)(target->exts[ext]); + if(signedon) { + controlreply((nick *)sender,"Signed on : %lu",signedon); + } else { + controlreply((nick *)sender,"Signed on : ???"); + } + } + } controlreply((nick *)sender,"IP address: %s",IPtostr(target->p_ipaddr)); controlreply((nick *)sender,"Realname : %s (%d user(s) have this realname)",target->realname->name->content,target->realname->usercount); if (target->umodes) { controlreply((nick *)sender,"Umode(s) : %s",printflags(target->umodes,umodeflags)); } + if (IsOper(target) && target->opername) + controlreply((nick *)sender,"Opered as : %s",target->opername->content); if (IsAccount(target)) { controlreply((nick *)sender,"Account : %s",target->authname); if (target->accountts) controlreply((nick *)sender,"AccountTS : %ld",target->accountts); - if (target->auth) + if (target->auth) { controlreply((nick *)sender,"UserID : %ld",target->auth->userid); - if (target->accountflags) - controlreply((nick *)sender,"AccFlags : %s",printflags(target->accountflags,accountflags)); + if (target->auth->flags) + controlreply((nick *)sender,"AccFlags : %s",printflags(target->auth->flags,accountflags)); + } + } + + if (target->away) { + controlreply((nick *)sender, "Away : %s",target->away->content); } hooknick=(nick *)sender; @@ -266,7 +343,7 @@ int controlrmmod(void *sender, int cargc, char **cargv) { if (cargc<1) return CMD_USAGE; - switch(rmmod(cargv[0])) { + switch(rmmod(cargv[0], 1)) { case 1: controlreply((nick *)sender,"Module %s is not loaded.",cargv[0]); return CMD_ERROR; @@ -286,15 +363,18 @@ int controllsmod(void *sender, int cargc, char **cargv) { char *ptr; if (cargc < 1) { /* list all loaded modules */ - ptr = lsmod(i); - controlreply((nick *)sender,"Module"); + const char *ver, *buildid; + time_t t, t2 = time(NULL); + ptr = lsmod(i, &ver, &buildid, &t); + + /* 9999d 24h 59m 59s fbf2a4a69ee1-tip */ + controlreply((nick *)sender,"Module Loaded for Version Build id"); while (ptr != NULL) { - const char *ver = lsmodver(i); - controlreply((nick *)sender,"%s%s%s%s", ptr, ver?" (":"", ver?ver:"", ver?")":""); - ptr = lsmod(++i); + controlreply((nick *)sender," %-40s %-17s %-30s %s", ptr, longtoduration(t2-t, 2), ver?ver:"", buildid?buildid:""); + ptr = lsmod(++i, &ver, &buildid, &t); } } else { - ptr = lsmod(getindex(cargv[0])); + ptr = lsmod(getindex(cargv[0]), NULL, NULL, NULL); controlreply((nick *)sender,"Module \"%s\" %s", cargv[0], (ptr ? "is loaded." : "is NOT loaded.")); } return CMD_OK; @@ -324,7 +404,7 @@ int relink(void *sender, int cargc, char **cargv) { } int die(void *sender, int cargc, char **cargv) { - if (cargc<1) { + if (cargc<1 || (strlen(cargv[0]) < 10)) { controlreply((nick *)sender,"You must give a reason."); return CMD_USAGE; } @@ -342,7 +422,7 @@ int controlchannel(void *sender, int cargc, char **cargv) { chanban *cbp; char buf[BUFSIZE]; char buf2[12]; - int i,j; + int i,j, ops=0, voice=0; char timebuf[30]; if (cargc<1) @@ -364,6 +444,8 @@ int controlchannel(void *sender, int cargc, char **cargv) { controlreply((nick *)sender,"Topic : %s",cp->topic->content); strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(cp->topictime))); controlreply((nick *)sender,"T-time : %ld [%s]",cp->topictime,timebuf); + } else { + controlreply((nick *)sender,"Topic : (none)"); } controlreply((nick *)sender,"Mode(s) : %s %s%s%s",printflags(cp->flags,cmodeflags),IsLimit(cp)?buf2:"", IsLimit(cp)?" ":"",IsKey(cp)?cp->key->content:""); @@ -384,6 +466,10 @@ int controlchannel(void *sender, int cargc, char **cargv) { break; } if (cp->users->content[j]!=nouser) { + if (cp->users->content[j]&CUMODE_OP) + ops++; + else if (cp->users->content[j]&CUMODE_VOICE) + voice++; np=getnickbynumeric(cp->users->content[j]); sprintf(&buf[i*18],"%c%c%-15s ",cp->users->content[j]&CUMODE_VOICE?'+':' ', cp->users->content[j]&CUMODE_OP?'@':' ', np?np->nick:"!BUG-NONICK!"); @@ -392,7 +478,7 @@ int controlchannel(void *sender, int cargc, char **cargv) { buf[i*18]=' '; } } - + controlreply((nick *)sender, "Users : Opped: %d, Voiced: %d", ops,voice); for (cbp=cp->bans;cbp;cbp=cbp->next) { controlreply((nick *)sender,"Ban : %s",bantostringdebug(cbp)); } @@ -466,6 +552,7 @@ void handlemessages(nick *target, int messagetype, void **args) { /* someone killed me? Bastards */ scheduleoneshot(time(NULL)+1,&controlconnect,NULL); mynick=NULL; + triggerhook(HOOK_CONTROL_REGISTERED, NULL); break; default: @@ -520,47 +607,61 @@ void controlnotice(nick *target, char *message, ... ) { void controlspecialrmmod(void *arg) { struct specialsched *a = (struct specialsched *)arg; + sstring *froo = a->modulename; a->schedule = NULL; - sstring *froo = a->modulename; - rmmod(froo->content); + rmmod(froo->content, 1); freesstring(froo); } void controlspecialreloadmod(void *arg) { struct specialsched *a = (struct specialsched *)arg; + sstring *froo = a->modulename; a->schedule = NULL; - sstring *froo = a->modulename; safereload(froo->content); freesstring(froo); } void controlhelp(nick *np, Command *cmd) { - char *cp = cmd->help, *sp = cp; - if(!cp || !*cp) { + char *cp, *sp; + char *scp; + cmdhelp *help=(cmdhelp *)cmd->ext; + + if (!help) { controlreply(np, "Sorry, no help for this command."); + return; + } + if ( help->helpcmd ) { + (help->helpcmd)(np, cmd); } else { - int finished = 0; - for(;;cp++) { - if(*cp == '\0' || *cp == '\n') { - if(*cp == '\0') { - finished = 1; - } else { - *cp = '\0'; + scp = help->helpstr; + if (!scp) { + controlreply(np, "Sorry, no help for this command."); + } else { + cp = scp; + sp = cp; + int finished = 0; + for(;;cp++) { + if(*cp == '\0' || *cp == '\n') { + if(*cp == '\0') { + finished = 1; + } else { + *cp = '\0'; + } + + if(sp != cp) + controlreply(np, "%s", sp); + + if(finished) + break; + + *cp = '\n'; + + sp = cp + 1; } - - if(sp != cp) - controlreply(np, "%s", sp); - - if(finished) - break; - - *cp = '\n'; - - sp = cp + 1; } } } @@ -610,3 +711,39 @@ void controlnswall(int noticelevel, char *format, ...) { controlwall(NO_OPER, noticelevel, "%s", broadcast); } +int controlcheckpermitted(flag_t level, nick *user) { + return 1; +} + +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); +} + +void controldestroycmdext(void *ext) { + if ( ((cmdhelp *)ext)->helpstr) + free( ((cmdhelp *)ext)->helpstr); + free(ext); +} + +char *controlid(nick *np) { + static char buf[512]; + + snprintf(buf, sizeof(buf), "%s!%s@%s/%s", np->nick, np->ident, np->host->name->content, np->authname); + + return buf; +} +