X-Git-Url: https://jfr.im/git/irc/quakenet/newserv.git/blobdiff_plain/b015c3e91e9dfb1c4835f4be894727dc9660da91..3898f97325dbed800d4b424e68a0c2858b8d8be7:/control/control.c diff --git a/control/control.c b/control/control.c index b00c7db7..8c267645 100644 --- a/control/control.c +++ b/control/control.c @@ -19,18 +19,27 @@ #include "../core/schedule.h" #include "../lib/base64.h" #include "../core/modules.h" +#include "../lib/version.h" +#include "../lib/irc_string.h" #include "control.h" #include #include #include -nick *mynick; +MODULE_VERSION(""); + +nick *hooknick; -nick *statsnick; +nick *mynick; -CommandTree *controlcmds; +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); @@ -39,32 +48,111 @@ int controlchannel(void *sender, int cargc, char **cargv); int relink(void *sender, int cargc, char **cargv); int die(void *sender, int cargc, char **cargv); int controlinsmod(void *sender, int cargc, char **cargv); -int controlrmmod(void *sender, int cargc, char **cargv); +int controllsmod(void *sender, int cargc, char **cargv); int controlrehash(void *sender, int cargc, char **cargv); -int controlshowcommands(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(); - - addcommandtotree(controlcmds,"status",10,1,&controlstatus); - addcommandtotree(controlcmds,"whois",10,1,&controlwhois); - addcommandtotree(controlcmds,"channel",10,1,&controlchannel); - addcommandtotree(controlcmds,"relink",10,1,&relink); - addcommandtotree(controlcmds,"die",10,1,&die); - addcommandtotree(controlcmds,"insmod",10,1,&controlinsmod); - addcommandtotree(controlcmds,"rmmod",10,1,&controlrmmod); - addcommandtotree(controlcmds,"rehash",10,1,&controlrehash); - addcommandtotree(controlcmds,"showcommands",10,0,&controlshowcommands); - addcommandtotree(controlcmds,"reload",10,1,&controlreload); - + 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."); + registercontrolhelpcmd("channel",NO_OPER,1,&controlchannel,"Usage: channel <#channel>\nDisplays channel information."); + registercontrolhelpcmd("relink",NO_DEVELOPER,1,&relink,"Usage: relink\nRelinks service to the network."); + 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_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); } -void registercontrolcmd(const char *name, int level, int maxparams, CommandHandler handler) { - addcommandtotree(controlcmds,name,level,maxparams,handler); +void _fini() { + deleteallschedules(&controlconnect); + if (mynick) { + deregisterlocaluser(mynick,"Leaving"); + } + + deregistercontrolcmd("status",&controlstatus); + deregistercontrolcmd("whois",&controlwhois); + deregistercontrolcmd("channel",&controlchannel); + deregistercontrolcmd("relink",&relink); + deregistercontrolcmd("die",&die); + deregistercontrolcmd("insmod",&controlinsmod); + deregistercontrolcmd("rmmod",&controlrmmod); + deregistercontrolcmd("lsmod",&controllsmod); + deregistercontrolcmd("rehash",&controlrehash); + deregistercontrolcmd("showcommands",&controlshowcommands); + deregistercontrolcmd("reload",&controlreload); + 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 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); } @@ -79,7 +167,8 @@ void controlconnect(void *arg) { myrealname=getcopyconfigitem("control","realname","NewServ Control Service",REALLEN); myauthname=getcopyconfigitem("control","authname","C",ACCOUNTLEN); - mynick=registerlocaluser(cnick->content,myident->content,myhost->content,myrealname->content,myauthname->content,UMODE_SERVICE|UMODE_DEAF|UMODE_OPER|UMODE_ACCOUNT,&handlemessages); + mynick=registerlocaluser(cnick->content,myident->content,myhost->content,myrealname->content,myauthname->content,UMODE_SERVICE|UMODE_DEAF|UMODE_OPER|UMODE_ACCOUNT|UMODE_INV,&handlemessages); + triggerhook(HOOK_CONTROL_REGISTERED, mynick); cp=findchannel("#twilightzone"); if (!cp) { localcreatechannel(mynick,"#twilightzone"); @@ -96,19 +185,19 @@ void controlconnect(void *arg) { } void handlestats(int hooknum, void *arg) { - sendmessagetouser(mynick,statsnick,"%s",(char *)arg); + controlreply(hooknick,"%s",(char *)arg); } int controlstatus(void *sender, int cargc, char **cargv) { - unsigned int level=5; - - statsnick=(nick *)sender; + unsigned long level=999; + hooknick=(nick *)sender; if (cargc>0) { level=strtoul(cargv[0],NULL,10); } - + registerhook(HOOK_CORE_STATSREPLY,&handlestats); + triggerhook(HOOK_CORE_STATSREQUEST,(void *)level); deregisterhook(HOOK_CORE_STATSREPLY,&handlestats); return CMD_OK; @@ -123,55 +212,88 @@ int controlrehash(void *sender, int cargc, char **cargv) { triggerhook(HOOK_CORE_REHASH,(void *)0); return CMD_OK; } - + +void handlewhois(int hooknum, void *arg) { + controlreply(hooknick,"%s",(char *)arg); +} + int controlwhois(void *sender, int cargc, char **cargv) { nick *target; channel **channels; char buf[BUFSIZE]; int i; - if (cargc<1) { - sendmessagetouser(mynick,(nick *)sender,"Usage: whois "); - return CMD_ERROR; - } + if (cargc<1) + return CMD_USAGE; if (cargv[0][0]=='#') { if (!(target=getnickbynumericstr(cargv[0]+1))) { - sendmessagetouser(mynick,sender,"Sorry, couldn't find numeric %s",cargv[0]+1); + controlreply(sender,"Sorry, couldn't find numeric %s",cargv[0]+1); return CMD_ERROR; } } else { if ((target=getnickbynick(cargv[0]))==NULL) { - sendmessagetouser(mynick,(nick *)sender,"Sorry, couldn't find that user"); + controlreply((nick *)sender,"Sorry, couldn't find that user"); return CMD_ERROR; } } - sendmessagetouser(mynick,(nick *)sender,"Nick : %s",target->nick); - sendmessagetouser(mynick,(nick *)sender,"Numeric : %s",longtonumeric(target->numeric,5)); - sendmessagetouser(mynick,(nick *)sender,"User@Host : %s@%s (%d user(s) on this host)",target->ident,target->host->name->content,target->host->clonecount); + controlreply((nick *)sender,"Nick : %s",target->nick); + controlreply((nick *)sender,"Numeric : %s",longtonumeric(target->numeric,5)); + controlreply((nick *)sender,"User@Host : %s@%s (%d user(s) on this host)",target->ident,target->host->name->content,target->host->clonecount); if (IsSetHost(target)) { if (target->shident) { - sendmessagetouser(mynick,(nick *)sender,"Fakehost : %s@%s",target->shident->content, target->sethost->content); + controlreply((nick *)sender,"Fakehost : %s@%s",target->shident->content, target->sethost->content); } else { - sendmessagetouser(mynick,(nick *)sender,"Fakehost : %s",target->sethost->content); + controlreply((nick *)sender,"Fakehost : %s",target->sethost->content); } } - sendmessagetouser(mynick,(nick *)sender,"Timestamp : %lu",target->timestamp); - sendmessagetouser(mynick,(nick *)sender,"IP address: %d.%d.%d.%d",(target->ipaddress)>>24,(target->ipaddress>>16)&255, (target->ipaddress>>8)&255,target->ipaddress&255); - sendmessagetouser(mynick,(nick *)sender,"Realname : %s (%d user(s) have this realname)",target->realname->name->content,target->realname->usercount); + 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) { - sendmessagetouser(mynick,(nick *)sender,"Umode(s) : %s",printflags(target->umodes,umodeflags)); + 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)) { - sendmessagetouser(mynick,(nick *)sender,"Account : %s",target->authname); + controlreply((nick *)sender,"Account : %s",target->authname); if (target->accountts) - sendmessagetouser(mynick,(nick *)sender,"AccountTS : %ld",target->accountts); + controlreply((nick *)sender,"AccountTS : %ld",target->accountts); + if (target->auth) { + controlreply((nick *)sender,"UserID : %ld",target->auth->userid); + 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; + registerhook(HOOK_CONTROL_WHOISREPLY,&handlewhois); + triggerhook(HOOK_CONTROL_WHOISREQUEST,target); + deregisterhook(HOOK_CONTROL_WHOISREPLY,&handlewhois); + if (target->channels->cursi==0) { - sendmessagetouser(mynick,(nick *)sender,"Channels : none"); + controlreply((nick *)sender,"Channels : none"); } else if (target->channels->cursi>50) { - sendmessagetouser(mynick,(nick *)sender,"Channels : - (total: %d)",target->channels->cursi); + controlreply((nick *)sender,"Channels : - (total: %d)",target->channels->cursi); } else { buf[0]='\0'; channels=(channel **)target->channels->content; @@ -183,7 +305,7 @@ int controlwhois(void *sender, int cargc, char **cargv) { if (strlen(buf)==0) { break; } else { - sendmessagetouser(mynick,(nick *)sender,"Channels : %s",buf); + controlreply((nick *)sender,"Channels : %s",buf); buf[0]='\0'; i--; } @@ -195,65 +317,84 @@ int controlwhois(void *sender, int cargc, char **cargv) { } int controlinsmod(void *sender, int cargc, char **cargv) { - if (cargc<1) { - sendmessagetouser(mynick,(nick *)sender,"Usage: insmod "); - return CMD_ERROR; - } + if (cargc<1) + return CMD_USAGE; switch(insmod(cargv[0])) { case -1: - sendmessagetouser(mynick,(nick *)sender,"Unable to load module %s",cargv[0]); + controlreply((nick *)sender,"Unable to load module %s",cargv[0]); return CMD_ERROR; case 1: - sendmessagetouser(mynick,(nick *)sender,"Module %s already loaded, or name not valid",cargv[0]); + controlreply((nick *)sender,"Module %s already loaded, or name not valid",cargv[0]); return CMD_ERROR; case 0: - sendmessagetouser(mynick,(nick *)sender,"Module %s loaded.",cargv[0]); + controlreply((nick *)sender,"Module %s loaded.",cargv[0]); return CMD_OK; default: - sendmessagetouser(mynick,(nick *)sender,"An unknown error occured."); + controlreply((nick *)sender,"An unknown error occured."); return CMD_ERROR; } } int controlrmmod(void *sender, int cargc, char **cargv) { - if (cargc<1) { - sendmessagetouser(mynick,(nick *)sender,"Usage: insmod "); - return CMD_ERROR; - } + if (cargc<1) + return CMD_USAGE; - switch(rmmod(cargv[0])) { + switch(rmmod(cargv[0], 1)) { case 1: - sendmessagetouser(mynick,(nick *)sender,"Module %s is not loaded.",cargv[0]); + controlreply((nick *)sender,"Module %s is not loaded.",cargv[0]); return CMD_ERROR; case 0: - sendmessagetouser(mynick,(nick *)sender,"Module %s unloaded.",cargv[0]); + controlreply((nick *)sender,"Module %s unloaded.",cargv[0]); return CMD_OK; default: - sendmessagetouser(mynick,(nick *)sender,"An unknown error occured."); + controlreply((nick *)sender,"An unknown error occured."); return CMD_ERROR; } } -int controlreload(void *sender, int cargc, char **cargv) { - if (cargc<1) { - sendmessagetouser(mynick,(nick *)sender,"Usage: reload "); - return CMD_ERROR; +int controllsmod(void *sender, int cargc, char **cargv) { + int i=0; + char *ptr; + + if (cargc < 1) { /* list all loaded modules */ + 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) { + 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]), NULL, NULL, NULL); + controlreply((nick *)sender,"Module \"%s\" %s", cargv[0], (ptr ? "is loaded." : "is NOT loaded.")); } - - controlrmmod(sender, cargc, cargv); - return controlinsmod(sender, cargc, cargv); + return CMD_OK; } +int controlreload(void *sender, int cargc, char **cargv) { + if (cargc<1) + return CMD_USAGE; + + controlreply((nick *)sender,"Imma gonna try and reload %s",cargv[0]); + + safereload(cargv[0]); + + return CMD_OK; +} + int relink(void *sender, int cargc, char **cargv) { if (cargc<1) { - sendmessagetouser(mynick,(nick *)sender,"You must give a reason."); - return CMD_ERROR; + controlreply((nick *)sender,"You must give a reason."); + return CMD_USAGE; } irc_send("%s SQ %s 0 :%s",mynumeric->content,myserver->content,cargv[0]); @@ -263,15 +404,16 @@ int relink(void *sender, int cargc, char **cargv) { } int die(void *sender, int cargc, char **cargv) { - if (cargc<1) { - sendmessagetouser(mynick,(nick *)sender,"You must give a reason."); - return CMD_ERROR; + if (cargc<1 || (strlen(cargv[0]) < 10)) { + controlreply((nick *)sender,"You must give a reason."); + return CMD_USAGE; } + + controlwall(NO_OPER,NL_OPERATIONS,"DIE from %s: %s",((nick *)sender)->nick, cargv[0]); - irc_send("%s SQ %s 0 :%s",mynumeric->content,myserver->content,cargv[0]); - irc_disconnected(); + newserv_shutdown_pending=1; - exit(0); + return CMD_OK; } int controlchannel(void *sender, int cargc, char **cargv) { @@ -280,15 +422,14 @@ int controlchannel(void *sender, int cargc, char **cargv) { chanban *cbp; char buf[BUFSIZE]; char buf2[12]; - int i,j; - - if (cargc<1) { - sendmessagetouser(mynick,(nick *)sender,"Usage: channel #chan"); - return CMD_ERROR; - } + int i,j, ops=0, voice=0; + char timebuf[30]; + + if (cargc<1) + return CMD_USAGE; if ((cp=findchannel(cargv[0]))==NULL) { - sendmessagetouser(mynick,(nick *)sender,"Couldn't find channel: %s",cargv[0]); + controlreply((nick *)sender,"Couldn't find channel: %s",cargv[0]); return CMD_ERROR; } @@ -296,14 +437,19 @@ int controlchannel(void *sender, int cargc, char **cargv) { sprintf(buf2,"%d",cp->limit); } - sendmessagetouser(mynick,(nick *)sender,"Channel : %s",cp->index->name->content); + controlreply((nick *)sender,"Channel : %s",cp->index->name->content); + strftime(timebuf, 30, "%d/%m/%y %H:%M", localtime(&(cp->timestamp))); + controlreply((nick *)sender,"C-time : %ld [%s]",cp->timestamp,timebuf); if (cp->topic) { - sendmessagetouser(mynick,(nick *)sender,"Topic : %s",cp->topic->content); - sendmessagetouser(mynick,(nick *)sender,"T-time : %ld [%s]",cp->topictime,ctime(&(cp->topictime))); + 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)"); } - sendmessagetouser(mynick,(nick *)sender,"Mode(s) : %s %s%s%s",printflags(cp->flags,cmodeflags),IsLimit(cp)?buf2:"", + controlreply((nick *)sender,"Mode(s) : %s %s%s%s",printflags(cp->flags,cmodeflags),IsLimit(cp)?buf2:"", IsLimit(cp)?" ":"",IsKey(cp)?cp->key->content:""); - sendmessagetouser(mynick,(nick *)sender,"Users : %d (hash size %d, utilisation %.1f%%); %d unique hosts", + controlreply((nick *)sender,"Users : %d (hash size %d, utilisation %.1f%%); %d unique hosts", cp->users->totalusers,cp->users->hashsize,((float)(100*cp->users->totalusers)/cp->users->hashsize), countuniquehosts(cp)); i=0; @@ -312,7 +458,7 @@ int controlchannel(void *sender, int cargc, char **cargv) { for (j=0;j<=cp->users->hashsize;j++) { if (i==4 || j==cp->users->hashsize) { if(i>0) { - sendmessagetouser(mynick,(nick *)sender,"Users : %s",buf); + controlreply((nick *)sender,"Users : %s",buf); } i=0; memset(buf,' ',72); @@ -320,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!"); @@ -328,9 +478,9 @@ 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) { - sendmessagetouser(mynick,(nick *)sender,"Ban : %s",bantostringdebug(cbp)); + controlreply((nick *)sender,"Ban : %s",bantostringdebug(cbp)); } return CMD_OK; } @@ -345,7 +495,7 @@ int controlshowcommands(void *sender, int cargc, char **cargv) { controlreply(np,"The following commands are registered at present:"); for(i=0;icommand->content,cmdlist[i]->level); + controlreply(np,"%s",cmdlist[i]->command->content); } controlreply(np,"End of list."); @@ -376,12 +526,12 @@ void handlemessages(nick *target, int messagetype, void **args) { cmd=findcommandintree(controlcmds,cargv[0],1); if (cmd==NULL) { - sendmessagetouser(mynick,sender,"Unknown command."); + controlreply(sender,"Unknown command."); return; } - if (cmd->level>=10 && !IsOper(sender)) { - sendmessagetouser(mynick,sender,"You need to be opered to use this command."); + if (cmd->level>0 && !IsOper(sender)) { + controlreply(sender,"You need to be opered to use this command."); return; } @@ -394,13 +544,15 @@ void handlemessages(nick *target, int messagetype, void **args) { cargc=(cmd->maxparams)+1; } - (cmd->handler)((void *)sender,cargc-1,&(cargv[1])); + if((cmd->handler)((void *)sender,cargc-1,&(cargv[1])) == CMD_USAGE) + controlhelp(sender, cmd); break; case LU_KILLED: /* someone killed me? Bastards */ scheduleoneshot(time(NULL)+1,&controlconnect,NULL); mynick=NULL; + triggerhook(HOOK_CONTROL_REGISTERED, NULL); break; default: @@ -408,7 +560,7 @@ void handlemessages(nick *target, int messagetype, void **args) { } } -void controlreply(nick *target, char *message, ... ) { +void controlmessage(nick *target, char *message, ... ) { char buf[512]; va_list va; @@ -453,13 +605,91 @@ void controlnotice(nick *target, char *message, ... ) { sendnoticetouser(mynick,target,"%s",buf); } -/* Send a notice to all opers, O(n) and a notice otherwise we'll get infinite loops with services */ -void controlnoticeopers(char *format, ...) { +void controlspecialrmmod(void *arg) { + struct specialsched *a = (struct specialsched *)arg; + sstring *froo = a->modulename; + + a->schedule = NULL; + + rmmod(froo->content, 1); + freesstring(froo); +} + +void controlspecialreloadmod(void *arg) { + struct specialsched *a = (struct specialsched *)arg; + sstring *froo = a->modulename; + + a->schedule = NULL; + + safereload(froo->content); + freesstring(froo); +} + +void controlhelp(nick *np, Command *cmd) { + 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 { + 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; + } + } + } + } +} + +int controlhelpcmd(void *sender, int cargc, char **cargv) { + Command *cmd; + nick *np = (nick *)sender; + + if (cargc<1) + return CMD_USAGE; + + cmd=findcommandintree(controlcmds,cargv[0],1); + if (cmd==NULL) { + controlreply(np,"Unknown command."); + return CMD_ERROR; + } + + controlhelp(np, cmd); + return CMD_OK; +} + +void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format, ...) { int i; nick *np; - char broadcast[BUFSIZE]; + char broadcast[512]; va_list va; - + va_start(va, format); vsnprintf(broadcast, sizeof(broadcast), format, va); va_end(va); @@ -469,3 +699,51 @@ void controlnoticeopers(char *format, ...) { if (IsOper(np)) controlnotice(np, "%s", broadcast); } + +void controlnswall(int noticelevel, char *format, ...) { + char broadcast[512]; + va_list va; + + va_start(va, format); + vsnprintf(broadcast, sizeof(broadcast), format, va); + va_end(va); + + 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; +} +