]> jfr.im git - irc/quakenet/newserv.git/blobdiff - parser/parser.c
CHANSERV: tell user when they can't attempts to auth any more, and drop max attempts...
[irc/quakenet/newserv.git] / parser / parser.c
index 90111f40e949db543f24846daa464ebb44ac988e..2a8147616d3be08dfeda268673148f467363627a 100644 (file)
@@ -45,7 +45,14 @@ void destroycommandtree(CommandTree *ct) {
       destroycommandtree((CommandTree *)ct->next[i]);
     }
   }
-  
+
+  if(ct->cmd) {
+    if(ct->cmd->command)
+      freesstring(ct->cmd->command);
+    if(ct->cmd->ext && ct->cmd->destroyext)
+      (ct->cmd->destroyext)(ct->cmd->ext);
+    free(ct->cmd);
+  } 
   free(ct);
 }
 
@@ -73,6 +80,32 @@ int countcommandtree(CommandTree *ct) {
   return sum;
 }
 
+/* sanitisecommandname:
+ *
+ * Converts the given command name to uppercase and checks for bad chars.
+ * 
+ * Returns 1 if bad chars were found
+ */
+static int sanitisecommandname(const char *cmdname, char *cmdbuf) {
+  int len,i;
+
+  strncpy(cmdbuf,cmdname,MAX_COMMAND_LEN);
+  cmdbuf[MAX_COMMAND_LEN-1]='\0';
+  
+  len=strlen(cmdbuf);
+  
+  /* Sanity check the string */
+  for (i=0;i<len;i++) {
+    cmdbuf[i]=toupper(cmdbuf[i]);
+    if (cmdbuf[i]<'A' || cmdbuf[i]>'Z') {
+      /* Someone tried to register an invalid command name */
+      return 1;    
+    }
+  }
+  
+  return 0;
+}
+
 /* 
  * addcommandhelptotree:
  *
@@ -82,41 +115,23 @@ int countcommandtree(CommandTree *ct) {
  * installing it in the tree
  */
  
-Command *addcommandhelptotree(CommandTree *ct, const char *cmdname, int level, int maxparams, CommandHandler handler, const char *help) {
+Command *addcommandexttotree(CommandTree *ct, const char *cmdname, int level, int maxparams, CommandHandler handler, void *ext) {
   Command *nc, *c;
-  int i;
-  
+  char cmdbuf[MAX_COMMAND_LEN];
+
+  if (sanitisecommandname(cmdname, cmdbuf))
+    return NULL;
+
   /* Generate the struct.. */
   nc=(void *)malloc(sizeof(Command));
-  nc->command=getsstring(cmdname, MAX_COMMAND_LEN);
+  nc->command=getsstring(cmdbuf, MAX_COMMAND_LEN);
   nc->level=level;
   nc->maxparams=maxparams;
   nc->handler=handler;
   nc->ext=NULL;
   nc->next=NULL;
-  if (help) {
-    int len=strlen(help);
-    nc->help=(char *)malloc(len+1);
-    if(nc->help) {
-      strncpy(nc->help, help, len);
-      nc->help[len] = '\0';
-    }
-  } else {
-    nc->help=NULL;
-  }
-
-  /* Sanity check the string */
-  for (i=0;i<nc->command->length;i++) {
-    nc->command->content[i]=toupper(nc->command->content[i]);
-    if (nc->command->content[i]<'A' || nc->command->content[i]>'Z') {
-      /* Someone tried to register an invalid command name */
-      freesstring(nc->command);
-      if(nc->help)
-        free(nc->help);
-      free(nc);
-      return NULL;    
-    }
-  }
+  nc->calls=0;
+  nc->destroyext=NULL;
 
   if ((c=findcommandintree(ct,cmdname,1))!=NULL) {
     /* Found something already.  Append our entry to the end */
@@ -126,11 +141,12 @@ Command *addcommandhelptotree(CommandTree *ct, const char *cmdname, int level, i
   } else if (insertcommand(nc,ct,0)) {
     /* Erk, that didn't work.. */
     freesstring(nc->command);
-    if(nc->help)
-      free(nc->help);
     free(nc);
     return NULL;
   }
+
+  if (ext)
+    nc->ext=(void *)ext;
   
   return nc;
 }
@@ -160,7 +176,11 @@ int insertcommand(Command *c, CommandTree *ct, int depth) {
       insertcommand(ct->cmd,(CommandTree *)ct->next[oldcharindex],depth+1);
     }
     ct->cmd=c;
-    ct->final=&(c->command->content[depth]);
+    /* Use a static NUL string rather than the allocated one if possible. */
+    if (c->command->length > depth)
+      ct->final=&(c->command->content[depth]);
+    else
+      ct->final="";
     return 0;
   } else {
     if ((ct->cmd!=NULL) && (ct->final[0]!='\0')) {
@@ -186,21 +206,16 @@ int insertcommand(Command *c, CommandTree *ct, int depth) {
 
 int deletecommandfromtree(CommandTree *ct, const char *cmdname, CommandHandler handler) {
   int i;
+  char cmdbuf[MAX_COMMAND_LEN+1];
   sstring *tmpstr;
   
-  tmpstr=getsstring(cmdname,MAX_COMMAND_LEN);
+  if (sanitisecommandname(cmdname, cmdbuf))
+    return 1;
   
-  /* Sanity check input string */
-  for (i=0;i<tmpstr->length;i++) {
-    tmpstr->content[i]=toupper(tmpstr->content[i]);
-    if (tmpstr->content[i]<'A' || tmpstr->content[i]>'Z') {
-      /* Someone tried to delete an invalid command name */
-      freesstring(tmpstr);
-      return 1;
-    }
-  }
+  tmpstr=getsstring(cmdbuf, MAX_COMMAND_LEN);
   i=deletecommand(tmpstr,ct,0,handler);
   freesstring(tmpstr);
+
   return i;
 }
 
@@ -221,8 +236,8 @@ int deletecommand(sstring *cmdname, CommandTree *ct, int depth, CommandHandler h
         c=*ch;
         (*ch)=(Command *)((*ch)->next);
         freesstring(c->command);
-        if(c->help)
-          free(c->help);
+        if(c->ext && c->destroyext)
+          (c->destroyext)(c->ext);
         free(c);
         return 0;
       }
@@ -240,9 +255,18 @@ int deletecommand(sstring *cmdname, CommandTree *ct, int depth, CommandHandler h
         c=*ch;
         (*ch)=(Command *)((*ch)->next);
         freesstring(c->command);
-        if(c->help)
-          free(c->help);
+        if(c->ext && c->destroyext)
+          (c->destroyext)(c->ext);
         free(c);
+
+        /* We need to regenerate the final pointer if needed;
+         * if ct->cmd is still pointing to a command it has the same name.
+         * Otherwise we should clear it.*/
+        if (ct->cmd)
+          ct->final=&(ct->cmd->command->content[depth]);
+        else
+          ct->final="";
+
         return 0;
       }
     }
@@ -334,3 +358,23 @@ int getcommandlist(CommandTree *ct, Command **commandlist, int maxcommands) {
   
   return count;
 }
+
+/* Returns the command name given a handler */
+sstring *getcommandname(CommandTree *ct, CommandHandler handler) {
+  int i;
+  sstring *s;
+
+  if(ct->cmd && ct->cmd->handler == handler) {
+    return ct->cmd->command;
+  }
+
+  for (i=0;i<26;i++) {
+    if(ct->next[i]) {
+      s=getcommandname(ct->next[i], handler);
+      if(s)
+        return s;
+    }
+  }
+
+  return NULL;
+}