]> jfr.im git - irc/quakenet/newserv.git/commitdiff
Merge
authorsplidge <redacted>
Wed, 26 Mar 2008 00:22:05 +0000 (00:22 +0000)
committersplidge <redacted>
Wed, 26 Mar 2008 00:22:05 +0000 (00:22 +0000)
24 files changed:
chanserv/newsearch/Makefile.in
chanserv/newsearch/chanserv_newsearch.c
chanserv/newsearch/chanserv_newsearch.h [new file with mode: 0644]
chanserv/newsearch/csns-qemail.c [new file with mode: 0644]
chanserv/newsearch/csns-qlasthost.c [new file with mode: 0644]
chanserv/newsearch/csns-qsuspendreason.c [new file with mode: 0644]
chanserv/newsearch/csns-qusername.c [new file with mode: 0644]
chanserv/newsearch/formats.c
chanserv/newsearch/interface.c
chanserv/q9snprintf.c
control/control.c
control/control.h
lib/Makefile.in
lib/stringbuf.c [new file with mode: 0644]
lib/stringbuf.h [new file with mode: 0644]
newsearch/Makefile.in
newsearch/formats.c
newsearch/newsearch.c
newsearch/newsearch.h
newsearch/newsearch_ast.c [new file with mode: 0644]
noperserv/noperserv_commands.c
parser/parser.c
parser/parser.h
trojanscan/trojanscan.c

index e96f6bcc49dfa8ba32fe8b9b9e57df0e0a74e7d1..85f2014ea6c7bac1259cdcd4a84bdf7c34368f0b 100644 (file)
@@ -5,4 +5,4 @@ INCPATH=../../
 .PHONY: all
 all: chanserv_newsearch.so
 
-chanserv_newsearch.so: chanserv_newsearch.o formats.o csns-qusers.o interface.o
+chanserv_newsearch.so: chanserv_newsearch.o formats.o csns-qusers.o interface.o csns-qlasthost.o csns-qemail.o csns-qsuspendreason.o csns-qusername.o
index b3392e1bbfab5acf728d6981e5ce6fc668c65878..5b6a6ff5f817e36ec75faf38f2ef5868f58d3009 100644 (file)
@@ -1,32 +1,53 @@
-#include "../../newsearch/newsearch.h"
 #include "../chanserv.h"
-
-/* formats.c */
-void printnick_auth(searchCtx *, nick *, nick *);
-void printnick_authchans(searchCtx *, nick *, nick *);
-void printchannel_qusers(searchCtx *, nick *, chanindex *);
-
-struct searchNode *qusers_parse(searchCtx *, int type, int argc, char **argv);
+#include "chanserv_newsearch.h"
 
 int cs_donicksearch(void *source, int cargc, char **cargv);
 int cs_dochansearch(void *source, int cargc, char **cargv);
+int cs_dousersearch(void *source, int cargc, char **cargv);
+int cs_dospewemailtwo(void *source, int cargc, char **cargv);
+int cs_dospewdbtwo(void *source, int cargc, char **cargv);
+
+UserDisplayFunc previousdefault;
 
 void _init() {
   regnickdisp("auth", printnick_auth);
   regnickdisp("authchans", printnick_authchans);
   regchandisp("qusers", printchannel_qusers);
+  reguserdisp("auth", printauth);
+
   registersearchterm("qusers", qusers_parse);
+  registersearchterm("qlasthost", qlasthost_parse);
+  registersearchterm("qemail", qemail_parse);
+  registersearchterm("qsuspendreason", qsuspendreason_parse);
+  registersearchterm("qusername", qusername_parse);
 
   chanservaddcommand("nicksearch", QCMD_OPER, 5, cs_donicksearch, "Wrapper for standard newserv nicksearch command.", "");
   chanservaddcommand("chansearch", QCMD_OPER, 5, cs_dochansearch, "Wrapper for standard newserv chansearch command.", "");
+  chanservaddcommand("usersearch", QCMD_OPER, 5, cs_dousersearch, "Wrapper for standard newserv usersearch command.", "");
+  chanservaddcommand("spewemailtwo", QCMD_OPER, 1, cs_dospewemailtwo, "Spews email...", "");
+  chanservaddcommand("spewdbtwo", QCMD_OPER, 1, cs_dospewdbtwo, "Spews db...", "");
+
+  previousdefault = defaultuserfn;
+  defaultuserfn = printauth;
 }
 
 void _fini() {
   unregnickdisp("auth", printnick_auth);
   unregnickdisp("authchans", printnick_authchans);
   unregchandisp("qusers", printchannel_qusers);
+  unreguserdisp("auth", printauth);
+
   deregistersearchterm("qusers", qusers_parse);
+  deregistersearchterm("qlasthost", qlasthost_parse);
+  deregistersearchterm("qemail", qemail_parse);
+  deregistersearchterm("qsuspendreason", qsuspendreason_parse);
+  deregistersearchterm("qusername", qusername_parse);
 
   chanservremovecommand("nicksearch", cs_donicksearch);
   chanservremovecommand("chansearch", cs_dochansearch);
+  chanservremovecommand("usersearch", cs_dousersearch);
+  chanservremovecommand("spewemailtwo", cs_dospewemailtwo);
+  chanservremovecommand("spewdbtwo", cs_dospewdbtwo);
+
+  defaultuserfn = previousdefault;
 }
diff --git a/chanserv/newsearch/chanserv_newsearch.h b/chanserv/newsearch/chanserv_newsearch.h
new file mode 100644 (file)
index 0000000..3a958d9
--- /dev/null
@@ -0,0 +1,17 @@
+#ifndef __CHANSERV_NEWSEARCH_H
+#define __CHANSERV_NEWSEARCH_H
+
+#include "../../newsearch/newsearch.h"
+
+void printnick_auth(searchCtx *, nick *, nick *);
+void printnick_authchans(searchCtx *, nick *, nick *);
+void printchannel_qusers(searchCtx *, nick *, chanindex *);
+void printauth(searchCtx *, nick *, authname *);
+
+struct searchNode *qusers_parse(searchCtx *, int type, int argc, char **argv);
+struct searchNode *qlasthost_parse(searchCtx *, int type, int argc, char **argv);
+struct searchNode *qemail_parse(searchCtx *, int type, int argc, char **argv);
+struct searchNode *qsuspendreason_parse(searchCtx *, int type, int argc, char **argv);
+struct searchNode *qusername_parse(searchCtx *, int type, int argc, char **argv);
+
+#endif
diff --git a/chanserv/newsearch/csns-qemail.c b/chanserv/newsearch/csns-qemail.c
new file mode 100644 (file)
index 0000000..6db9fea
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * qemail functionality 
+ */
+
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+#include <stdlib.h>
+
+void *qemail_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void qemail_free(searchCtx *ctx, struct searchNode *thenode);
+
+struct searchNode *qemail_parse(searchCtx *ctx, int type, int argc, char **argv) {
+  struct searchNode *thenode;
+
+  if (type != SEARCHTYPE_USER) {
+    parseError = "qemail: this function is only valid for user searches.";
+    return NULL;
+  }
+
+  if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+    parseError = "malloc: could not allocate memory for this search.";
+    return NULL;
+  }
+
+  thenode->returntype = RETURNTYPE_STRING;
+  thenode->exe = qemail_exe;
+  thenode->free = qemail_free;
+
+  return thenode;
+}
+
+void *qemail_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
+  authname *ap = (authname *)theinput;
+  reguser *rup = ap->exts[chanservext];
+  if(!rup || !rup->email)
+    return "";
+
+  return rup->email->content;
+}
+
+void qemail_free(searchCtx *ctx, struct searchNode *thenode) {
+  free(thenode);
+}
+
diff --git a/chanserv/newsearch/csns-qlasthost.c b/chanserv/newsearch/csns-qlasthost.c
new file mode 100644 (file)
index 0000000..0aba845
--- /dev/null
@@ -0,0 +1,44 @@
+/*
+ * qlasthost functionality 
+ */
+
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+#include <stdlib.h>
+
+void *qlasthost_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void qlasthost_free(searchCtx *ctx, struct searchNode *thenode);
+
+struct searchNode *qlasthost_parse(searchCtx *ctx, int type, int argc, char **argv) {
+  struct searchNode *thenode;
+
+  if (type != SEARCHTYPE_USER) {
+    parseError = "qlasthost: this function is only valid for user searches.";
+    return NULL;
+  }
+
+  if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+    parseError = "malloc: could not allocate memory for this search.";
+    return NULL;
+  }
+
+  thenode->returntype = RETURNTYPE_STRING;
+  thenode->exe = qlasthost_exe;
+  thenode->free = qlasthost_free;
+
+  return thenode;
+}
+
+void *qlasthost_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
+  authname *ap = (authname *)theinput;
+  reguser *rup = ap->exts[chanservext];
+  if(!rup || !rup->lastuserhost)
+    return "";
+
+  return rup->lastuserhost->content;
+}
+
+void qlasthost_free(searchCtx *ctx, struct searchNode *thenode) {
+  free(thenode);
+}
diff --git a/chanserv/newsearch/csns-qsuspendreason.c b/chanserv/newsearch/csns-qsuspendreason.c
new file mode 100644 (file)
index 0000000..127d147
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * qsuspendreason functionality 
+ */
+
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+#include <stdlib.h>
+
+void *qsuspendreason_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void qsuspendreason_free(searchCtx *ctx, struct searchNode *thenode);
+
+struct searchNode *qsuspendreason_parse(searchCtx *ctx, int type, int argc, char **argv) {
+  struct searchNode *thenode;
+
+  if (type != SEARCHTYPE_USER) {
+    parseError = "qsuspendreason: this function is only valid for user searches.";
+    return NULL;
+  }
+
+  if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+    parseError = "malloc: could not allocate memory for this search.";
+    return NULL;
+  }
+
+  thenode->returntype = RETURNTYPE_STRING;
+  thenode->exe = qsuspendreason_exe;
+  thenode->free = qsuspendreason_free;
+
+  return thenode;
+}
+
+void *qsuspendreason_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
+  authname *ap = (authname *)theinput;
+  reguser *rup = ap->exts[chanservext];
+  if(!rup || !UHasSuspension(rup) || !rup->suspendreason)
+    return "";
+
+  return rup->suspendreason->content;
+}
+
+void qsuspendreason_free(searchCtx *ctx, struct searchNode *thenode) {
+  free(thenode);
+}
+
diff --git a/chanserv/newsearch/csns-qusername.c b/chanserv/newsearch/csns-qusername.c
new file mode 100644 (file)
index 0000000..83f0f8e
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * qusername functionality 
+ */
+
+#include "../../newsearch/newsearch.h"
+#include "../chanserv.h"
+
+#include <stdlib.h>
+
+void *qusername_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void qusername_free(searchCtx *ctx, struct searchNode *thenode);
+
+struct searchNode *qusername_parse(searchCtx *ctx, int type, int argc, char **argv) {
+  struct searchNode *thenode;
+
+  if (type != SEARCHTYPE_USER) {
+    parseError = "qusername: this function is only valid for user searches.";
+    return NULL;
+  }
+
+  if (!(thenode=(struct searchNode *)malloc(sizeof (struct searchNode)))) {
+    parseError = "malloc: could not allocate memory for this search.";
+    return NULL;
+  }
+
+  thenode->returntype = RETURNTYPE_STRING;
+  thenode->exe = qusername_exe;
+  thenode->free = qusername_free;
+
+  return thenode;
+}
+
+void *qusername_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput) {
+  authname *ap = (authname *)theinput;
+  reguser *rup = ap->exts[chanservext];
+  if(!rup)
+    return "";
+
+  return rup->username;
+}
+
+void qusername_free(searchCtx *ctx, struct searchNode *thenode) {
+  free(thenode);
+}
+
index ae6553dd3f9ab81e7898790715739ad5f9b009bd..84aaa9e2f503bc2639b00856a329df6656793ed3 100644 (file)
@@ -3,6 +3,7 @@
 #include "../chanserv.h"
 #include "../../newsearch/newsearch.h"
 #include "../../control/control.h"
+#include "../../lib/stringbuf.h"
 
 void printchannel_qusers(searchCtx *ctx, nick *sender, chanindex *cip) {
   regchanuser *rcup;
@@ -87,3 +88,31 @@ void printnick_authchans(searchCtx *ctx, nick *sender, nick *np) {
       ctx->reply(sender," %s", thebuf);
   }
 }
+
+void printauth(searchCtx *ctx, nick *sender, authname *anp) {
+  reguser *rup;
+  StringBuf b;
+  char output[1024];
+  nick *tnp;
+  int space = 0;
+
+  if (!(rup=anp->exts[chanservaext]))
+    return;
+
+  output[0] = '\0';
+
+  b.capacity = sizeof(output);
+  b.len = 0;
+  b.buf = output;
+
+  for(tnp=anp->nicks;tnp;tnp=tnp->next) {
+    if(space)
+      sbaddchar(&b, ' ');
+    space = 1;
+    sbaddstr(&b, tnp->nick);
+  }
+  sbterminate(&b);
+
+  ctx->reply(sender, " %s%s%s%s", rup->username, *output?" (":"", output, *output?")":"");
+  ctx->reply(sender, "  %-10s %-30s %s", UHasSuspension(rup)?"yes":"no", rup->email?rup->email->content:"(no email)", rup->lastuserhost?rup->lastuserhost->content:"(no last host)");
+}
index 5478ff41924e657b0f882c0325e8a1dec8a1994f..93f386e71371a52763800b441f060ce05071c821 100644 (file)
@@ -1,5 +1,5 @@
 #include "../chanserv.h"
-#include "../../newsearch/newsearch.h"
+#include "chanserv_newsearch.h"
 #include <stdio.h>
 #include <stdarg.h>
 
@@ -53,3 +53,43 @@ int cs_dochansearch(void *source, int cargc, char **cargv) {
   return CMD_OK;
 }
 
+int cs_dousersearch(void *source, int cargc, char **cargv) {
+  nick *sender=source;
+  
+  if (cargc < 1) {
+    chanservstdmessage(sender, QM_NOTENOUGHPARAMS, "usersearch");
+    return CMD_ERROR;
+  }
+
+  do_usersearch_real(chanservmessagewrapper, chanservwallwrapper, source, cargc, cargv);
+
+  chanservstdmessage(sender, QM_DONE);  
+  return CMD_OK;
+}
+
+int cs_dospewemailtwo(void *source, int cargc, char **cargv) {
+  searchASTExpr *tree;
+
+  if(cargc < 1)
+    return CMD_USAGE;
+
+  tree = NSASTNode(match_parse, NSASTNode(qemail_parse), NSASTLiteral(cargv[0]));
+  return ast_usersearch(tree, chanservmessagewrapper, source, chanservwallwrapper, printauth, 500);
+}
+
+int cs_dospewdbtwo(void *source, int cargc, char **cargv) {
+  searchASTExpr *tree;
+
+  if(cargc < 1)
+    return CMD_USAGE;
+
+  tree =
+    NSASTNode(or_parse,
+      NSASTNode(match_parse, NSASTNode(qusername_parse), NSASTLiteral(cargv[0])),
+      NSASTNode(match_parse, NSASTNode(qsuspendreason_parse), NSASTLiteral(cargv[0])),
+      NSASTNode(match_parse, NSASTNode(qemail_parse), NSASTLiteral(cargv[0])),
+      NSASTNode(match_parse, NSASTNode(qlasthost_parse), NSASTLiteral(cargv[0])),
+    );
+  return ast_usersearch(tree, chanservmessagewrapper, source, chanservwallwrapper, printauth, 500);
+}
+
index 02d6bd7a7af51d8c5aca2b97576dc1c526a0dba2..c1e6ab8507d2626a044aa292ad6aa98df25f36cb 100644 (file)
@@ -3,42 +3,14 @@
 #include <stdarg.h>
 #include <string.h>
 #include "../lib/sstring.h"
+#include "../lib/stringbuf.h"
 #include "../core/error.h"
 
 #define MAXARGS 10
 #define CONVBUF 512
 
-struct bufs {
-  char *buf;
-  int capacity;
-  int len;
-};
-
-static int addchar(struct bufs *buf, char c) {
-  if(buf->len >= buf->capacity - 1)
-    return 0;
-
-  buf->buf[buf->len++] = c;
-
-  return 1;
-}
-
-static int addstr(struct bufs *buf, char *c) {
-  int remaining = buf->capacity - buf->len - 1;
-  char *p;
-
-  for(p=c;*p;p++) {
-    if(remaining-- <= 0)
-      return 0;
-
-    buf->buf[buf->len++] = *p;
-  }
-
-  return 1;
-}
-
 void q9vsnprintf(char *buf, size_t size, const char *format, const char *args, va_list ap) {
-  struct bufs b;
+  StringBuf b;
   const char *p;
   char *c;
   char convbuf[MAXARGS][CONVBUF];
@@ -90,7 +62,7 @@ void q9vsnprintf(char *buf, size_t size, const char *format, const char *args, v
 
   for(p=format;*p;p++) {
     if(*p != '$') {
-      if(!addchar(&b, *p))
+      if(!sbaddchar(&b, *p))
         break;
       continue;
     }
@@ -98,7 +70,7 @@ void q9vsnprintf(char *buf, size_t size, const char *format, const char *args, v
     if(*p == '\0')
       break;
     if(*p == '$') {
-      if(!addchar(&b, *p))
+      if(!sbaddchar(&b, *p))
         break;
       continue;
     }
@@ -126,11 +98,11 @@ void q9vsnprintf(char *buf, size_t size, const char *format, const char *args, v
         c = "(bad format specifier)";
     }
     if(c)
-      if(!addstr(&b, c))
+      if(!sbaddstr(&b, c))
         break;
   }
 
-  buf[b.len] = '\0';
+  sbterminate(&b);
 
   /* not required */
   /*
index faf877f5a759fbb58a1705e3509edf17528e86ea..48c4a77f7ba76803bda00efe152c8e5a1cc37efb 100644 (file)
@@ -599,3 +599,14 @@ void controlnoticeopers(flag_t permissionlevel, flag_t noticelevel, char *format
         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);
+}
+
index 65a414aa31401302a8b88362b381206612e35375..901cd53e78ff19f57cb4e2983686373b3d76f096 100644 (file)
@@ -16,6 +16,7 @@ int controlrmmod(void *sender, int cargc, char **cargv);
 void controlspecialrmmod(void *arg);
 void controlspecialreloadmod(void *arg);
 void controlhelp(nick *np, Command *cmd);
+void controlnswall(int noticelevel, char *format, ...);
 
 #define registercontrolcmd(a, b, c, d) registercontrolhelpcmd(a, b, c, d, NULL)
 
index d7507e7f924e43a62c413c844e95316fa46c7716..c611e92b3fd2f07f5216b311c000c3fe5817ab29 100644 (file)
@@ -1,4 +1,4 @@
 @include@ @includel@../build.mk@includel@
 
 .PHONY: all
-all: sstring.o array.o splitline.o base64.o flags.o irc_string.o strlfunc.o sha1.o irc_ipv6.o patricia.o rijndael.o sha2.o hmac.o prng.o md5.o
+all: sstring.o array.o splitline.o base64.o flags.o irc_string.o strlfunc.o sha1.o irc_ipv6.o patricia.o rijndael.o sha2.o hmac.o prng.o md5.o stringbuf.o
diff --git a/lib/stringbuf.c b/lib/stringbuf.c
new file mode 100644 (file)
index 0000000..a558073
--- /dev/null
@@ -0,0 +1,34 @@
+#include "stringbuf.h"
+
+int sbaddchar(StringBuf *buf, char c) {
+  if(buf->len >= buf->capacity - 1)
+    return 0;
+
+  buf->buf[buf->len++] = c;
+
+  return 1;
+}
+
+int sbaddstr(StringBuf *buf, char *c) {
+  int remaining = buf->capacity - buf->len - 1;
+  char *p;
+
+  for(p=c;*p;p++) {
+    if(remaining <= 0)
+      return 0;
+
+    remaining--;
+
+    buf->buf[buf->len++] = *p;
+  }
+
+  return 1;
+}
+
+int sbterminate(StringBuf *buf) {
+  if(buf->capacity - buf->len > 0) {
+    buf->buf[buf->len] = '\0';
+    return 1;
+  }
+  return 0;
+}
diff --git a/lib/stringbuf.h b/lib/stringbuf.h
new file mode 100644 (file)
index 0000000..4b1ca36
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef __STRINGBUF_H
+#define __STRINGBUF_H
+
+typedef struct StringBuf {
+  char *buf;
+  int capacity;
+  int len;
+} StringBuf;
+
+int sbaddchar(StringBuf *buf, char c);
+int sbaddstr(StringBuf *buf, char *c);
+int sbterminate(StringBuf *buf);
+
+#endif
index d6f7f577ae1b780f72262fe0a9ef4ab86973a03f..43f3a49114e3a89ac5a96974ae0343b2591da92a 100644 (file)
@@ -6,4 +6,4 @@ LDFLAGS+=$(LIBPCRE)
 .PHONY: all
 all: newsearch.so
 
-newsearch.so: newsearch.o formats.o ns-not.o ns-and.o ns-or.o ns-eq.o ns-match.o ns-hostmask.o ns-realname.o ns-modes.o ns-nick.o ns-ident.o ns-regex.o ns-host.o ns-channel.o ns-lt.o ns-gt.o ns-timestamp.o ns-country.o ns-authname.o ns-ip.o ns-kill.o ns-gline.o ns-exists.o ns-services.o ns-size.o ns-name.o ns-topic.o ns-oppct.o ns-hostpct.o ns-authedpct.o ns-length.o ns-kick.o ns-authts.o ns-channels.o ns-server.o ns-authid.o ns-notice.o
+newsearch.so: newsearch.o formats.o ns-not.o ns-and.o ns-or.o ns-eq.o ns-match.o ns-hostmask.o ns-realname.o ns-modes.o ns-nick.o ns-ident.o ns-regex.o ns-host.o ns-channel.o ns-lt.o ns-gt.o ns-timestamp.o ns-country.o ns-authname.o ns-ip.o ns-kill.o ns-gline.o ns-exists.o ns-services.o ns-size.o ns-name.o ns-topic.o ns-oppct.o ns-hostpct.o ns-authedpct.o ns-length.o ns-kick.o ns-authts.o ns-channels.o ns-server.o ns-authid.o ns-notice.o newsearch_ast.o
index 22c1e2ddb89d08c7d3fb2fe00b146d78cf7eb2f7..abb7bd06f9d664900d8de78cfa71ecb21cd2e8f0 100644 (file)
@@ -146,3 +146,7 @@ void printchannel_services(searchCtx *ctx, nick *sender, chanindex *cip) {
   }
 }
 
+void printuser(searchCtx *ctx, nick *sender, authname *aup) {
+  ctx->reply(sender,"%d", aup->userid);
+}
+
index f5bb203a7f409e2b34c958e0c8a77d773473dbc6..911df297993d791bd267f58c91a7ea57339f97d0 100644 (file)
@@ -8,21 +8,28 @@
 #include "../control/control.h"
 #include "../lib/splitline.h"
 #include "../lib/version.h"
+#include "../lib/stringbuf.h"
 
 MODULE_VERSION("");
 
 CommandTree *searchTree;
 CommandTree *chanOutputTree;
 CommandTree *nickOutputTree;
+CommandTree *userOutputTree;
 
 int do_nicksearch(void *source, int cargc, char **cargv);
 int do_chansearch(void *source, int cargc, char **cargv);
+int do_usersearch(void *source, int cargc, char **cargv);
 
 void printnick_channels(searchCtx *, nick *, nick *);
 void printchannel(searchCtx *, nick *, chanindex *);
 void printchannel_topic(searchCtx *, nick *, chanindex *);
 void printchannel_services(searchCtx *, nick *, chanindex *);
 
+UserDisplayFunc defaultuserfn = printuser;
+NickDisplayFunc defaultnickfn = printnick;
+ChanDisplayFunc defaultchanfn = printchannel;
+
 void registersearchterm(char *term, parseFunc parsefunc);
 void deregistersearchterm(char *term, parseFunc parsefunc);
 
@@ -42,6 +49,14 @@ void unregnickdisp(const char *name, NickDisplayFunc handler) {
   deletecommandfromtree(nickOutputTree, name, (CommandHandler)handler);
 }
 
+void reguserdisp(const char *name, UserDisplayFunc handler) {
+  addcommandtotree(userOutputTree, name, 0, 0, (CommandHandler)handler);
+}
+
+void unreguserdisp(const char *name, UserDisplayFunc handler) {
+  deletecommandfromtree(userOutputTree, name, (CommandHandler)handler);
+}
+
 const char *parseError;
 /* used for *_free functions that need to warn users of certain things
    i.e. hitting too many users in a (kill) or (gline) */
@@ -51,6 +66,7 @@ void _init() {
   searchTree=newcommandtree();
   chanOutputTree=newcommandtree();
   nickOutputTree=newcommandtree();
+  userOutputTree=newcommandtree();
 
   /* Boolean operations */
   registersearchterm("and",and_parse);
@@ -113,16 +129,22 @@ void _init() {
   regchandisp("topic",printchannel_topic);
   regchandisp("services",printchannel_services);
 
+  /* Nick output filters */
+  reguserdisp("default",printuser);
+    
   registercontrolhelpcmd("nicksearch",NO_OPER,4,do_nicksearch, "Usage: nicksearch <criteria>\nSearches for nicknames with the given criteria.");
   registercontrolhelpcmd("chansearch",NO_OPER,4,do_chansearch, "Usage: chansearch <criteria>\nSearches for channels with the given criteria.");
+  registercontrolhelpcmd("usersearch",NO_OPER,4,do_usersearch, "Usage: usersearch <criteria>\nSearches for users with the given criteria.");
 }
 
 void _fini() {
   destroycommandtree(searchTree);
   destroycommandtree(chanOutputTree);
   destroycommandtree(nickOutputTree);
+  destroycommandtree(userOutputTree);
   deregistercontrolcmd("nicksearch", do_nicksearch);
   deregistercontrolcmd("chansearch", do_chansearch);
+  deregistercontrolcmd("usersearch", do_usersearch);
 }
 
 void registersearchterm(char *term, parseFunc parsefunc) {
@@ -143,45 +165,36 @@ static void controlwallwrapper(int level, char *format, ...) {
   va_end(ap);
 }
 
-int do_nicksearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
-  nick *sender = senderNSExtern = source;
-  struct searchNode *search;
-  int limit=500;
+static int parseopts(int cargc, char **cargv, int *arg, int *limit, void **display, CommandTree *tree, replyFunc reply, void *sender) {
   char *ch;
-  int arg=0;
   struct Command *cmd;
-  NickDisplayFunc display=printnick;
-  searchCtx ctx;
 
-  if (cargc<1)
-    return CMD_USAGE;
-  
   if (*cargv[0] == '-') {
     /* options */
-    arg++;
+    (*arg)++;
     
     for (ch=cargv[0]+1;*ch;ch++) {
       switch(*ch) {
       case 'l':
-       if (cargc<arg) {
+       if (cargc<*arg) {
          reply(sender,"Error: -l switch requires an argument");
          return CMD_USAGE;
        }
-       limit=strtoul(cargv[arg++],NULL,10);
+       *limit=strtoul(cargv[(*arg)++],NULL,10);
        break;
        
       case 'd':
-        if (cargc<arg) {
+        if (cargc<*arg) {
           reply(sender,"Error: -d switch requires an argument");
           return CMD_USAGE;
         }
-        cmd=findcommandintree(nickOutputTree, cargv[arg], 1);
+        cmd=findcommandintree(tree, cargv[*arg], 1);
         if (!cmd) {
-          reply(sender,"Error: unknown output format %s",cargv[arg]);
+          reply(sender,"Error: unknown output format %s",cargv[*arg]);
           return CMD_USAGE;
         }
-        display=(NickDisplayFunc)cmd->handler;
-        arg++;
+        *display=(void *)cmd->handler;
+        (*arg)++;
         break;
         
       default:
@@ -190,6 +203,25 @@ int do_nicksearch_real(replyFunc reply, wallFunc wall, void *source, int cargc,
     }
   }
 
+  return CMD_OK;
+}
+
+int do_nicksearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
+  nick *sender = senderNSExtern = source;
+  struct searchNode *search;
+  int limit=500;
+  int arg=0;
+  NickDisplayFunc display=defaultnickfn;
+  searchCtx ctx;
+  int ret;
+
+  if (cargc<1)
+    return CMD_USAGE;
+  
+  ret = parseopts(cargc, cargv, &arg, &limit, (void **)&display, nickOutputTree, reply, sender);
+  if(ret != CMD_OK)
+    return ret;
+
   if (arg>=cargc) {
     reply(sender,"No search terms - aborting.");
     return CMD_ERROR;
@@ -266,48 +298,17 @@ int do_chansearch_real(replyFunc reply, wallFunc wall, void *source, int cargc,
   nick *sender = senderNSExtern = source;
   struct searchNode *search;
   int limit=500;
-  char *ch;
   int arg=0;
-  struct Command *cmd;
-  ChanDisplayFunc display=printchannel;
+  ChanDisplayFunc display=defaultchanfn;
   searchCtx ctx;
+  int ret;
 
   if (cargc<1)
     return CMD_USAGE;
   
-  if (*cargv[0] == '-') {
-    /* options */
-    arg++;
-    
-    for (ch=cargv[0]+1;*ch;ch++) {
-      switch(*ch) {
-      case 'l':
-       if (cargc<arg) {
-         reply(sender,"Error: -l switch requires an argument");
-         return CMD_USAGE;
-       }
-       limit=strtoul(cargv[arg++],NULL,10);
-       break;
-
-      case 'd':
-        if (cargc<arg) {
-          reply(sender,"Error: -d switch requires an argument");
-          return CMD_USAGE;
-        }
-        cmd=findcommandintree(chanOutputTree, cargv[arg], 1);
-        if (!cmd) {
-          reply(sender,"Error: unknown output format %s",cargv[arg]);
-          return CMD_USAGE;
-        }
-        display=(ChanDisplayFunc)cmd->handler;
-        arg++;
-        break;
-       
-      default:
-       reply(sender,"Unrecognised flag -%c.",*ch);
-      }
-    }
-  }
+  ret = parseopts(cargc, cargv, &arg, &limit, (void **)&display, chanOutputTree, reply, sender);
+  if(ret != CMD_OK)
+    return ret;
 
   if (arg>=cargc) {
     reply(sender,"No search terms - aborting.");
@@ -360,6 +361,73 @@ void chansearch_exe(struct searchNode *search, searchCtx *ctx, nick *sender, Cha
   ctx->reply(sender,"--- End of list: %d matches", matches);
 }
 
+int do_usersearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv) {
+  nick *sender = senderNSExtern = source;
+  struct searchNode *search;
+  int limit=500;
+  int arg=0;
+  UserDisplayFunc display=defaultuserfn;
+  searchCtx ctx;
+  int ret;
+
+  if (cargc<1)
+    return CMD_USAGE;
+  
+  ret = parseopts(cargc, cargv, &arg, &limit, (void **)&display, userOutputTree, reply, sender);
+  if(ret != CMD_OK)
+    return ret;
+
+  if (arg>=cargc) {
+    reply(sender,"No search terms - aborting.");
+    return CMD_ERROR;
+  }
+
+  if (arg<(cargc-1)) {
+    rejoinline(cargv[arg],cargc-arg);
+  }
+
+  ctx.parser = search_parse;
+  ctx.reply = reply;
+  ctx.wall = wall;
+
+  if (!(search = ctx.parser(&ctx, SEARCHTYPE_USER, cargv[arg]))) {
+    reply(sender,"Parse error: %s",parseError);
+    return CMD_ERROR;
+  }
+
+  usersearch_exe(search, &ctx, sender, display, limit);
+
+  (search->free)(&ctx, search);
+
+  return CMD_OK;
+}
+
+int do_usersearch(void *source, int cargc, char **cargv) {
+  return do_usersearch_real(controlreply, controlwallwrapper, source, cargc, cargv);
+}
+
+void usersearch_exe(struct searchNode *search, searchCtx *ctx, nick *sender, UserDisplayFunc display, int limit) {  
+  int i;
+  authname *aup;
+  int matches = 0;
+  
+  search=coerceNode(ctx, search, RETURNTYPE_BOOL);
+  
+  for (i=0;i<AUTHNAMEHASHSIZE;i++) {
+    for (aup=authnametable[i];aup;aup=aup->next) {
+      if ((search->exe)(ctx, search, aup)) {
+       if (matches<limit)
+         display(ctx, sender, aup);
+       if (matches==limit)
+         ctx->reply(sender, "--- More than %d matches, skipping the rest",limit);
+       matches++;
+      }
+    }
+  }
+
+  ctx->reply(sender,"--- End of list: %d matches", matches);
+}
+
 struct coercedata {
   struct searchNode *child;
   union {
@@ -723,37 +791,8 @@ struct searchNode *search_parse(searchCtx *ctx, int type, char *input) {
   }    
 }
 
-struct bufs {
-  char *buf;
-  int capacity;
-  int len;
-};
-
-static int addchar(struct bufs *buf, char c) {
-  if(buf->len >= buf->capacity - 1)
-    return 0;
-
-  buf->buf[buf->len++] = c;
-
-  return 1;
-}
-
-static int addstr(struct bufs *buf, char *c) {
-  int remaining = buf->capacity - buf->len - 1;
-  char *p;
-
-  for(p=c;*p;p++) {
-    if(remaining-- <= 0)
-      return 0;
-
-    buf->buf[buf->len++] = *p;
-  }
-
-  return 1;
-}
-
 void nssnprintf(char *buf, size_t size, const char *format, nick *np) {
-  struct bufs b;
+  StringBuf b;
   const char *p;
   char *c;
   char hostbuf[512];
@@ -767,7 +806,7 @@ void nssnprintf(char *buf, size_t size, const char *format, nick *np) {
 
   for(p=format;*p;p++) {
     if(*p != '%') {
-      if(!addchar(&b, *p))
+      if(!sbaddchar(&b, *p))
         break;
       continue;
     }
@@ -775,7 +814,7 @@ void nssnprintf(char *buf, size_t size, const char *format, nick *np) {
     if(*p == '\0')
       break;
     if(*p == '%') {
-      if(!addchar(&b, *p))
+      if(!sbaddchar(&b, *p))
         break;
       continue;
     }
@@ -800,11 +839,11 @@ void nssnprintf(char *buf, size_t size, const char *format, nick *np) {
         c = "(bad format specifier)";
     }
     if(c)
-      if(!addstr(&b, c))
+      if(!sbaddstr(&b, c))
         break;
   }
 
-  buf[b.len] = '\0';
+  sbterminate(&b);
 
   /* not required */
   /*
index 58f7a59577c27bcc5849fcadfdcebcc6382ba8f1..696b283457990bcf18f100beb3e4268b885a0bc7 100644 (file)
@@ -2,9 +2,11 @@
 #include "../parser/parser.h"
 #include "../channel/channel.h"
 #include "../lib/flags.h"
+#include "../authext/authext.h"
 
 #define    SEARCHTYPE_CHANNEL     1
 #define    SEARCHTYPE_NICK        2
+#define    SEARCHTYPE_USER        3
 
 
 #define    NSMAX_KILL_LIMIT       500
@@ -38,6 +40,7 @@ typedef struct searchCtx {
   searchParseFunc parser;
   replyFunc reply;
   wallFunc wall;
+  void *arg;
 } searchCtx;
 
 typedef struct searchNode *(*parseFunc)(searchCtx *, int, int, char **);
@@ -45,6 +48,7 @@ typedef void (*freeFunc)(searchCtx *, struct searchNode *);
 typedef void *(*exeFunc)(searchCtx *, struct searchNode *, void *);
 typedef void (*ChanDisplayFunc)(searchCtx *, nick *, chanindex *);
 typedef void (*NickDisplayFunc)(searchCtx *, nick *, nick *);
+typedef void (*UserDisplayFunc)(searchCtx *, nick *, authname *);
 
 /* Core functions */
 /* Logical  (BOOL -> BOOL)*/
@@ -114,6 +118,8 @@ void regchandisp(const char *name, ChanDisplayFunc handler);
 void unregchandisp(const char *name, ChanDisplayFunc handler);
 void regnickdisp(const char *name, NickDisplayFunc handler);
 void unregnickdisp(const char *name, NickDisplayFunc handler);
+void reguserdisp(const char *name, UserDisplayFunc handler);
+void unreguserdisp(const char *name, UserDisplayFunc handler);
 
 /* Special nick* printf */
 void nssnprintf(char *, size_t, const char *, nick *);
@@ -128,9 +134,69 @@ typedef struct searchNode {
 extern const char *parseError;
 
 void printnick(searchCtx *, nick *, nick *);
+void printuser(searchCtx *, nick *, authname *);
 
 void nicksearch_exe(struct searchNode *search, searchCtx *sctx, nick *sender, NickDisplayFunc display, int limit);
 void chansearch_exe(struct searchNode *search, searchCtx *sctx, nick *sender, ChanDisplayFunc display, int limit);
+void usersearch_exe(struct searchNode *search, searchCtx *ctx, nick *sender, UserDisplayFunc display, int limit);
 
 int do_nicksearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv);
 int do_chansearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv);
+int do_usersearch_real(replyFunc reply, wallFunc wall, void *source, int cargc, char **cargv);
+
+void *literal_exe(searchCtx *ctx, struct searchNode *thenode, void *theinput);
+void literal_free(searchCtx *ctx, struct searchNode *thenode);
+
+/* AST functions */
+
+struct searchASTNode;
+
+#define AST_NODE_CHILD 1
+#define AST_NODE_LITERAL 2
+
+/* items to store in the ast lookup cache */
+#define AST_RECENT 10
+
+typedef struct searchASTExpr {
+  int type;
+  union {
+    char *literal;
+    struct searchASTNode *child;
+  } u;
+} searchASTExpr;
+
+typedef struct searchASTNode {
+  parseFunc fn;
+  int argc;
+  struct searchASTExpr **argv;
+} searchASTNode;
+
+/*
+ *
+ * FEAR THE COMPOUND LITERALS
+ * MUHAHAHHAHAHAHAHAHAAH
+ *
+ */
+#define __NSASTExpr(x, y, ...) &(searchASTExpr){.type = x, .u.y = __VA_ARGS__}
+#define __NSASTList(...) (searchASTExpr *[]){__VA_ARGS__}
+#define __NSASTNode(x, ...) &(searchASTNode){.fn = x, .argc = sizeof(__NSASTList(__VA_ARGS__)) / sizeof(__NSASTList(__VA_ARGS__)[0]), .argv = __NSASTList(__VA_ARGS__)}
+#define __NSASTChild(...) __NSASTExpr(AST_NODE_CHILD, child, __VA_ARGS__)
+
+#define NSASTLiteral(data) __NSASTExpr(AST_NODE_LITERAL, literal, data)
+#define NSASTNode(fn, ...) __NSASTChild(__NSASTNode(fn, __VA_ARGS__))
+
+searchNode *search_astparse(searchCtx *, int, char *);
+
+int ast_nicksearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NickDisplayFunc display, int limit);
+int ast_chansearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, ChanDisplayFunc display, int limit);
+int ast_usersearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, UserDisplayFunc display, int limit);
+
+char *ast_printtree(char *buf, size_t bufsize, searchASTExpr *expr);
+
+/* erk */
+extern CommandTree *searchTree;
+
+extern UserDisplayFunc defaultuserfn;
+extern NickDisplayFunc defaultnickfn;
+extern ChanDisplayFunc defaultchanfn;
+
diff --git a/newsearch/newsearch_ast.c b/newsearch/newsearch_ast.c
new file mode 100644 (file)
index 0000000..9ddefc3
--- /dev/null
@@ -0,0 +1,265 @@
+#include "newsearch.h"
+#include "../lib/sstring.h"
+#include "../lib/strlfunc.h"
+#include "../lib/stringbuf.h"
+#include <stdarg.h>
+#include <string.h>
+
+/* at least we have some type safety... */
+typedef union exprunion {
+  searchASTExpr *expr;
+  char *literal;
+} exprunion;
+
+typedef struct searchASTCache {
+  searchASTExpr *tree;
+  searchASTExpr *cache[AST_RECENT];
+  int nextpos;
+} searchASTCache;
+
+/* comares either a string and a string or an expression and an expression */
+static searchASTExpr *compareloc(searchASTExpr *expr, exprunion *loc) {
+  if(expr->type == AST_NODE_LITERAL) {
+    if(expr->u.literal == loc->literal)
+      return expr;
+  } else if(expr->type == AST_NODE_CHILD) {
+    if(expr == loc->expr)
+      return expr;
+  } else {
+    parseError = "static_parse_compare: bad node type";
+    return NULL;
+  }
+  return NULL;
+}
+
+/* searches the abstract syntax tree for the supplied expression/string */
+static searchASTExpr *treesearch(searchASTExpr *expr, exprunion *loc) {
+  searchASTExpr *ret = compareloc(expr, loc);
+  if(ret)
+    return ret;
+  
+  if(expr->type == AST_NODE_CHILD) {
+    int i;
+    for(i=0;i<expr->u.child->argc;i++) {
+      searchASTExpr *d = treesearch(expr->u.child->argv[i], loc);
+      if(d)
+        return d;
+    }
+  }
+  return NULL;
+}
+
+/*
+ * searches the AST cache, if this fails it goes and searches the tree.
+ * the cache is hit most of the time and I guess makes it nearly O(1) amortised...
+ */
+searchASTExpr *cachesearch(searchASTCache *cache, exprunion *loc) {
+  searchASTExpr *ret = compareloc(cache->tree, loc);
+  int i;
+  if(ret)
+    return ret;
+
+  for(i=0;i<AST_RECENT;i++) {
+    if(!cache->cache[i])
+      continue;
+    ret = compareloc(cache->cache[i], loc);
+    if(ret)
+      return ret;
+  }
+
+  return treesearch(cache->tree, loc);
+}
+
+/* pushes an item into the cache */
+static void cachepush(searchASTCache *cache, searchASTExpr *expr) {
+  cache->cache[cache->nextpos] = expr;
+  cache->nextpos = (cache->nextpos + 1) % AST_RECENT;
+}
+
+/* ast parser, the way we pass context around is very very hacky... */
+searchNode *search_astparse(searchCtx *ctx, int type, char *loc) {
+  searchASTCache *cache = ctx->arg;
+  searchASTExpr *expr = cachesearch(cache, (exprunion *)&loc);
+  searchNode *node;
+  char **v;
+  int i;
+
+  if(!expr) {
+    parseError = "WARNING: AST parsing failed";
+    return NULL;
+  }
+
+  switch(expr->type) {
+    case AST_NODE_LITERAL:
+      if (!(node=(searchNode *)malloc(sizeof(searchNode)))) {
+        parseError = "malloc: could not allocate memory for this search.";
+        return NULL;
+      }
+      node->localdata  = getsstring(expr->u.literal,512);
+      node->returntype = RETURNTYPE_CONST | RETURNTYPE_STRING;
+      node->exe        = literal_exe;
+      node->free       = literal_free;
+      return node;
+    case AST_NODE_CHILD:
+      v = (char **)malloc(expr->u.child->argc * sizeof(char *));
+      if(!v) {
+        parseError = "malloc: could not allocate memory for this search.";
+        return NULL;
+      }
+      for(i=0;i<expr->u.child->argc;i++) {
+        searchASTExpr *child = expr->u.child->argv[i];
+
+        cachepush(cache, child);
+        switch(child->type) {
+          case AST_NODE_LITERAL:
+            v[i] = child->u.literal;
+            break;
+          case AST_NODE_CHILD:
+            v[i] = (char *)child;
+            break;
+          default:
+            parseError = "static_parse: bad child node type";
+            free(v);
+            return NULL;
+        }
+      }
+
+      node = expr->u.child->fn(ctx, type, expr->u.child->argc, v);
+      free(v);
+      return node;
+   default:
+      parseError = "static_parse: bad node type";
+      return NULL;
+  }
+}
+
+int ast_nicksearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, NickDisplayFunc display, int limit) {
+  searchCtx ctx;
+  searchASTCache cache;
+  searchNode *search;
+  char buf[1024];
+
+  memset(&cache, 0, sizeof(cache));
+  cache.tree = tree;
+
+  ctx.reply = reply;
+  ctx.wall = wall;
+  ctx.parser = search_astparse;
+  ctx.arg = (void *)&cache;
+
+  buf[0] = '\0';
+  reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree));
+  search = ctx.parser(&ctx, SEARCHTYPE_NICK, (char *)tree);
+  if(!search) {
+    reply(sender, "Parse error: %s", parseError);
+    return CMD_ERROR;
+  }
+
+  reply(sender, "Executing...");
+  nicksearch_exe(search, &ctx, sender, display, limit);
+
+  (search->free)(&ctx, search);
+
+  return CMD_OK;
+}
+
+int ast_chansearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, ChanDisplayFunc display, int limit) {
+  searchCtx ctx;
+  searchASTCache cache;
+  searchNode *search;
+  char buf[1024];
+
+  ctx.reply = reply;
+  ctx.wall = wall;
+  ctx.parser = search_astparse;
+  ctx.arg = (void *)&cache;
+
+  buf[0] = '\0';
+  reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree));
+  search = ctx.parser(&ctx, SEARCHTYPE_CHANNEL, (char *)tree);
+  if(!search) {
+    reply(sender, "Parse error: %s", parseError);
+    return CMD_ERROR;
+  }
+
+  reply(sender, "Executing...");
+  chansearch_exe(search, &ctx, sender, display, limit);
+
+  (search->free)(&ctx, search);
+
+  return CMD_OK;
+}
+
+int ast_usersearch(searchASTExpr *tree, replyFunc reply, void *sender, wallFunc wall, UserDisplayFunc display, int limit) {
+  searchCtx ctx;
+  searchASTCache cache;
+  searchNode *search;
+  char buf[1024];
+
+  memset(&cache, 0, sizeof(cache));
+  cache.tree = tree;
+
+  ctx.reply = reply;
+  ctx.wall = wall;
+  ctx.parser = search_astparse;
+  ctx.arg = (void *)&cache;
+
+  buf[0] = '\0';
+  reply(sender, "Parsing: %s", ast_printtree(buf, sizeof(buf), tree));
+  search = ctx.parser(&ctx, SEARCHTYPE_USER, (char *)tree);
+  if(!search) {
+    reply(sender, "Parse error: %s", parseError);
+    return CMD_ERROR;
+  }
+
+  reply(sender, "Executing...");
+  usersearch_exe(search, &ctx, sender, display, limit);
+
+  (search->free)(&ctx, search);
+
+  return CMD_OK;
+}
+
+
+/* horribly inefficient -- don't call me very often! */
+static char *ast_printtree_real(StringBuf *buf, searchASTExpr *expr) {
+  char lbuf[256];
+  if(expr->type == AST_NODE_CHILD) {    
+    int i;
+    sstring *command = getcommandname(searchTree, (void *)expr->u.child->fn);
+
+    if(command) {
+      snprintf(lbuf, sizeof(lbuf), "(%s", command->content);
+    } else {
+      snprintf(lbuf, sizeof(lbuf), "(%p", expr->u.child->fn);
+    }
+    sbaddstr(buf, lbuf);
+
+    for(i=0;i<expr->u.child->argc;i++) {
+      sbaddchar(buf, ' ');
+      ast_printtree_real(buf, expr->u.child->argv[i]);
+    }
+    sbaddchar(buf, ')');
+
+  } else if(expr->type == AST_NODE_LITERAL) {
+    sbaddstr(buf, expr->u.literal);
+  } else {
+    sbaddstr(buf, "???");
+  }
+
+  return buf->buf;
+}
+
+char *ast_printtree(char *buf, size_t bufsize, searchASTExpr *expr) {
+  StringBuf b;
+  char *p;
+
+  b.capacity = bufsize;
+  b.len = 0;
+  b.buf = buf;
+
+  p = ast_printtree_real(&b, expr);
+  sbterminate(&b);
+  return p;
+}
index 023457417395927da212c57800dffe931c0705a5..9a94b64160798d117a5fce9b0dc8e8268cecc165 100644 (file)
@@ -7,6 +7,7 @@
 
 #include "../control/control.h"
 #include "../nick/nick.h"
+#include "../newsearch/newsearch.h"
 #include "../lib/irc_string.h"
 #include "../lib/strlfunc.h"
 #include "../localuser/localuserchannel.h"
@@ -34,7 +35,7 @@ void _init() {
 
   registercontrolhelpcmd("spewchan", NO_OPER, 1, &controlspewchan, "Usage: spewchan <pattern>\nShows all channels which are matched by the given pattern");
 
-/*  registercontrolhelpcmd("spew", NO_OPER, 1, &controlspew, "Usage: spewchan <pattern>\nShows all userss which are matched by the given pattern"); */
+  registercontrolhelpcmd("spew", NO_OPER, 1, &controlspew, "Usage: spewchan <pattern>\nShows all userss which are matched by the given pattern");
 
   registercontrolhelpcmd("resync", NO_OPER, 1, &controlresync, "Usage: resync <channel>\nResyncs a desynched channel");
 
@@ -52,7 +53,7 @@ void _fini() {
   deregistercontrolcmd("broadcast", controlbroadcast);
 
   deregistercontrolcmd("resync", controlresync);
-/*   deregistercontrolcmd("spew", controlspew); */
+  deregistercontrolcmd("spew", controlspew);
   deregistercontrolcmd("spewchan", controlspewchan);
 
 /*  deregistercontrolcmd("kill", controlkill); */
@@ -150,11 +151,16 @@ int controlresync(void *sender, int cargc, char **cargv) {
 }
 
 int controlspew(void *sender, int cargc, char **cargv) {
-/*  nick *np = (nick *)sender; */
+  searchASTExpr *tree;
 
-  return CMD_OK;
+  if(cargc < 1)
+    return CMD_USAGE;
+
+  tree = NSASTNode(match_parse, NSASTNode(hostmask_parse), NSASTLiteral(cargv[0]));
+  return ast_nicksearch(tree, controlreply, sender, controlnswall, printnick, 500);
 }
 
+/* this function is the definition of horrible */
 int controlspewchan(void *sender, int cargc, char **cargv) {
   nick *np = (nick*)sender;
   nick *np2;
index eadae3c626b658539aed85fd767d02565c1d8093..476d6a87574bd1ce4d8258dbe92217303230ee51 100644 (file)
@@ -347,3 +347,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;
+}
index 1aa030548ea465acd18e788818e215f11a23af3d..e98e577dc088c2c3b263e2494cdb3abc70753b1f 100644 (file)
@@ -53,6 +53,7 @@ Command *addcommandhelptotree(CommandTree *ct, const char *cmdname, int level, i
 int deletecommandfromtree(CommandTree *ct, const char *cmdname, CommandHandler handler);
 Command *findcommandintree(CommandTree *ct, const char *cmdname, int strictcheck);
 int getcommandlist(CommandTree *ct, Command **commandlist, int maxcommands);
+sstring *getcommandname(CommandTree *ct, CommandHandler handler);
 
 #define addcommandtotree(a, b, c, d, e) addcommandhelptotree(a, b, c, d, e, NULL)
 
index 9fb2239580ac825125e23580f4ba460b7297f337..ae163bee9bb5363e7742bc8a689d451d84d43e7e 100644 (file)
@@ -2080,7 +2080,7 @@ void trojanscan_phrasematch(channel *chp, nick *sender, trojanscan_phrases *phra
     
     irc_send("%s GL * +%s %d :You (%s!%s@%s) are infected with a trojan (%s/%d), see %s%d for details - banned for %d hours\r\n", mynumeric->content, glinemask, glinetime * 3600, sender->nick, sender->ident, sender->host->name->content, worm->name->content, phrase->id, TROJANSCAN_URL_PREFIX, worm->id, glinetime);
 
-    trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s p: %d f: %d", glinemask, messagetype, sender->nick, sender->ident, sender->host->name->content, messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", usercount, worm->name->content, worm->epidemic?"(E)":"", phrase->id, frequency);
+    trojanscan_mainchanmsg("g: *!%s t: %c u: %s!%s@%s%s%s c: %d w: %s%s p: %d f: %d%s%s", glinemask, messagetype, sender->nick, sender->ident, sender->host->name->content, messagetype=='N'||messagetype=='M'||messagetype=='P'?" #: ":"", messagetype=='N'||messagetype=='M'||messagetype=='P'?chp->index->name->content:"", usercount, worm->name->content, worm->epidemic?"(E)":"", phrase->id, frequency, matchbuf[0]?" --: ":"", matchbuf[0]?matchbuf:"");
   }
 }