]> jfr.im git - irc/quakenet/newserv.git/blobdiff - control/control.c
longtoduration formats 0 and 1 back to how they were.
[irc/quakenet/newserv.git] / control / control.c
index aab494525d249f187ed88566838b46b1b71294a3..efeddfef51a0a697010aedb7840369414f34a94c 100644 (file)
@@ -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 <stdio.h>
@@ -49,6 +50,7 @@ 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, ...);
+void handlesignal(int hooknum, void *arg);
 
 void _init() {
   controlcmds=newcommandtree();
@@ -62,15 +64,42 @@ void _init() {
   registercontrolhelpcmd("die",NO_DEVELOPER,1,&die,"Usage: die <reason>\nTerminates the service.");
   registercontrolhelpcmd("insmod",NO_DEVELOPER,1,&controlinsmod,"Usage: insmod <module>\nAdds a module to the running instance.");
   registercontrolhelpcmd("rmmod",NO_DEVELOPER,1,&controlrmmod,"Usage: rmmod <module>\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 <module>\nReloads specified module.");
   registercontrolhelpcmd("help",NO_ANYONE,1,&controlhelpcmd,"Usage: help <command>\nShows help for specified command.");
-  
+  registerhook(HOOK_CORE_REHASH, &handlesignal);
+  registerhook(HOOK_CORE_SIGINT, &handlesignal);
   scheduleoneshot(time(NULL)+1,&controlconnect,NULL);
 }
 
+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 *help) {
   addcommandhelptotree(controlcmds,name,level,maxparams,handler,help);
 }
@@ -89,7 +118,7 @@ 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) {
@@ -111,15 +140,15 @@ void handlestats(int hooknum, void *arg) {
 }
 
 int controlstatus(void *sender, int cargc, char **cargv) {
-  unsigned int level=5;
-
+  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;
@@ -176,10 +205,17 @@ int controlwhois(void *sender, int cargc, char **cargv) {
   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)  {
+      controlreply((nick *)sender,"UserID    : %ld",target->auth->userid);
+      if (target->auth->flags) 
+        controlreply((nick *)sender,"AccFlags  : %s",printflags(target->auth->flags,accountflags));
+    }
   }
 
   hooknick=(nick *)sender;
@@ -260,15 +296,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;
@@ -277,14 +316,13 @@ int controllsmod(void *sender, int cargc, char **cargv) {
 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]);
   
-  preparereload(cargv[0]);
-  controlrmmod(sender, cargc, cargv);
-  controlinsmod(sender, cargc, cargv);
-  reloadmarked();
+  safereload(cargv[0]);
   
   return CMD_OK;
-}
+}  
 
 int relink(void *sender, int cargc, char **cargv) {
   if (cargc<1) {
@@ -299,15 +337,16 @@ 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;
   }
+
+  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) {
@@ -316,8 +355,9 @@ 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)
     return CMD_USAGE;
   
@@ -331,9 +371,14 @@ int controlchannel(void *sender, int cargc, char **cargv) {
   }
   
   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) {
     controlreply((nick *)sender,"Topic   : %s",cp->topic->content);
-    controlreply((nick *)sender,"T-time  : %ld [%s]",cp->topictime,ctime(&(cp->topictime)));
+    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:"");
@@ -354,6 +399,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!");
@@ -362,7 +411,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));
   }
@@ -436,6 +485,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:
@@ -490,9 +540,9 @@ 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);
   freesstring(froo);
@@ -500,22 +550,20 @@ void controlspecialrmmod(void *arg) {
 
 void controlspecialreloadmod(void *arg) {
   struct specialsched *a = (struct specialsched *)arg;
+  sstring *froo = a->modulename;
 
   a->schedule = NULL;
-  sstring *froo = a->modulename;
 
-  preparereload(free->content);
-  rmmod(froo->content);
-  insmod(froo->content);
-  reloadmarked();
+  safereload(froo->content);
   freesstring(froo);
 }
 
 void controlhelp(nick *np, Command *cmd) {
-  char *cp = cmd->help, *sp = cp;
-  if(!cp || !*cp) {
+  sstring *scp = cmd->help;
+  if(!scp) {
     controlreply(np, "Sorry, no help for this command.");
   } else {
+    char *cp = scp->content, *sp = cp;
     int finished = 0;
     for(;;cp++) {
       if(*cp == '\0' || *cp == '\n') {
@@ -571,3 +619,32 @@ void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, 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);
+}
+
+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);
+}