]> jfr.im git - irc/quakenet/newserv.git/blame - newsearch/newsearch.c
Disable kill.
[irc/quakenet/newserv.git] / newsearch / newsearch.c
CommitLineData
c86edd1d
Q
1
2#include <stdio.h>
3#include "newsearch.h"
4
5#include "../irc/irc_config.h"
6#include "../nick/nick.h"
7#include "../lib/irc_string.h"
8#include "../parser/parser.h"
9#include "../control/control.h"
10#include "../lib/splitline.h"
11
12CommandTree *searchTree;
13
14int do_nicksearch(void *source, int cargc, char **cargv);
15struct searchNode *search_parse(int type, char *input);
16
17void registersearchterm(char *term, parseFunc parsefunc);
18void deregistersearchterm(char *term, parseFunc parsefunc);
19
20void *trueval(int type);
21void *falseval(int type);
22
23const char *parseError;
24
25void _init() {
26 searchTree=newcommandtree();
27
28 /* Boolean operations */
29 registersearchterm("and",and_parse);
30 registersearchterm("not",not_parse);
31 registersearchterm("or",or_parse);
f1903ace 32
c86edd1d 33 registersearchterm("eq",eq_parse);
f1903ace
CP
34
35 registersearchterm("lt",lt_parse);
36 registersearchterm("gt",gt_parse);
c86edd1d
Q
37
38 /* String operations */
39 registersearchterm("match",match_parse);
40 registersearchterm("regex",regex_parse);
41
42 /* Nickname operations */
43 registersearchterm("hostmask",hostmask_parse);
44 registersearchterm("realname",realname_parse);
45 registersearchterm("nick",nick_parse);
052247fa 46 registersearchterm("authname",authname_parse);
c86edd1d
Q
47 registersearchterm("ident",ident_parse);
48 registersearchterm("host",host_parse);
49 registersearchterm("channel",channel_parse);
f1903ace 50 registersearchterm("timestamp",timestamp_parse);
c433958f 51 registersearchterm("country",country_parse);
c86edd1d
Q
52
53 /* Nickname / channel operations */
54 registersearchterm("modes",modes_parse);
55
38cee035 56 registercontrolhelpcmd("nicksearch",NO_OPER,4,do_nicksearch, "Usage: nicksearch <criteria>\nSearches for nicknames with the given criteria.");
c86edd1d
Q
57}
58
59void _fini() {
60 destroycommandtree(searchTree);
61 deregistercontrolcmd("nicksearch", do_nicksearch);
62}
63
64void registersearchterm(char *term, parseFunc parsefunc) {
65 addcommandtotree(searchTree, term, 0, 0, (CommandHandler) parsefunc);
66}
67
68void deregistersearchterm(char *term, parseFunc parsefunc) {
69 deletecommandfromtree(searchTree, term, (CommandHandler) parsefunc);
70}
71
72void printnick(nick *sender, nick *np) {
73 char hostbuf[HOSTLEN+NICKLEN+USERLEN+4];
74
75 controlreply(sender,"%s [%s] (%s) (%s)",visiblehostmask(np,hostbuf),
76 IPtostr(np->ipaddress), printflags(np->umodes, umodeflags), np->realname->name->content);
77}
78
79int do_nicksearch(void *source, int cargc, char **cargv) {
80 nick *sender=source, *np;
81 int i;
82 struct searchNode *search;
83 int limit=500,matches=0;
84 char *ch;
85 int arg=0;
86
38cee035
CP
87 if (cargc<1)
88 return CMD_USAGE;
c86edd1d
Q
89
90 if (*cargv[0] == '-') {
91 /* options */
92 arg++;
93
94 for (ch=cargv[0]+1;*ch;ch++) {
95 switch(*ch) {
96 case 'l':
97 if (cargc<arg) {
98 controlreply(sender,"Error: -l switch requires an argument");
38cee035 99 return CMD_USAGE;
c86edd1d
Q
100 }
101 limit=strtoul(cargv[arg++],NULL,10);
102 break;
103
104 default:
105 controlreply(sender,"Unrecognised flag -%c.",*ch);
106 }
107 }
108 }
109
110 if (arg>=cargc) {
111 controlreply(sender,"No search terms - aborting.");
112 return CMD_ERROR;
113 }
114
115 if (arg<(cargc-1)) {
116 rejoinline(cargv[arg],cargc-arg);
117 }
118
119 if (!(search = search_parse(SEARCHTYPE_NICK, cargv[arg]))) {
120 controlreply(sender,"Parse error: %s",parseError);
121 return CMD_ERROR;
122 }
123
124 for (i=0;i<NICKHASHSIZE;i++) {
125 for (np=nicktable[i];np;np=np->next) {
126 if ((search->exe)(search, RETURNTYPE_BOOL, np)) {
127 if (matches<limit)
128 printnick(sender, np);
129 if (matches==limit)
130 controlreply(sender, "--- More than %d matches, skipping the rest",limit);
131 matches++;
132 }
133 }
134 }
135
136 (search->free)(search);
137
138 controlreply(sender,"--- End of list: %d matches", matches);
139
140 return CMD_OK;
141}
142
143void *trueval(int type) {
144 switch(type) {
145 default:
146 case RETURNTYPE_INT:
147 case RETURNTYPE_BOOL:
148 return (void *)1;
149
150 case RETURNTYPE_STRING:
151 return "1";
152 }
153}
154
155void *falseval(int type) {
156 switch (type) {
157 default:
158 case RETURNTYPE_INT:
159 case RETURNTYPE_BOOL:
160 return NULL;
161
162 case RETURNTYPE_STRING:
163 return "";
164 }
165}
166
167
168/*
169 * LITERAL node type: used by the top level parse function
170 */
171
172struct literal_localdata {
173 int intval;
174 int boolval;
175 sstring *stringval;
176};
177
178void literal_free(struct searchNode *thenode);
179void *literal_exe(struct searchNode *thenode, int type, void *theinput);
180
181/* search_parse:
182 * Given an input string, return a searchNode.
183 */
184
185struct searchNode *search_parse(int type, char *input) {
186 /* OK, we need to split the input into chunks on spaces and brackets.. */
187 char *argvector[100];
188 int i,j;
189 char *ch;
190 struct Command *cmd;
191 struct searchNode *thenode;
192 struct literal_localdata *localdata;
193
194 /* If it starts with a bracket, it's a function call.. */
195 if (*input=='(') {
196 /* Skip past string */
197 for (ch=input;*ch;ch++);
198 if (*(ch-1) != ')') {
199 parseError = "Bracket mismatch!";
200 return NULL;
201 }
202 input++;
203 *(ch-1)='\0';
204
205 /* Split further args */
206 i=-1; /* i = -1 BoW, 0 = inword, 1 = bracket nest depth */
207 j=0; /* j = current arg */
a33e0d2b 208 argvector[0]="";
c86edd1d
Q
209 for (ch=input;*ch;ch++) {
210 if (i==-1) {
211 argvector[j]=ch;
212 if (*ch=='(') {
213 i=1;
214 } else if (*ch != ' ') {
215 i=0;
216 }
217 } else if (i==0) {
218 if (*ch==' ') {
219 *ch='\0';
220 j++;
4cd6347c
P
221 if(j >= (sizeof(argvector) / sizeof(*argvector))) {
222 parseError = "Too many arguments";
223 return NULL;
224 }
c86edd1d
Q
225 i=-1;
226 }
227 } else {
228 if (*ch=='(') {
229 i++;
230 } else if (*ch==')') {
231 i--;
232 }
233 }
234 }
235
236 if (i>0) {
237 parseError = "Bracket mismatch!";
238 return NULL;
239 }
4cd6347c
P
240
241 if (*(ch-1) == 0) /* if the last character was a space */
242 j--; /* remove an argument */
c86edd1d
Q
243
244 if (!(cmd=findcommandintree(searchTree,argvector[0],1))) {
245 parseError = "Unknown command";
246 return NULL;
247 } else {
248 return ((parseFunc)cmd->handler)(type, j, argvector+1);
249 }
250 } else {
251 /* Literal */
252 thenode=(struct searchNode *)malloc(sizeof(struct searchNode));
253 localdata=(struct literal_localdata *)malloc(sizeof (struct literal_localdata));
254
255 localdata->stringval=getsstring(input,512);
256 localdata->intval=strtol(input,NULL,10);
257 if (input==NULL || *input=='\0') {
258 localdata->boolval = 0;
259 } else {
260 localdata->boolval = 1;
261 }
262
263 thenode->localdata = localdata;
264 thenode->returntype = RETURNTYPE_CONST | RETURNTYPE_STRING;
265 thenode->exe = literal_exe;
266 thenode->free = literal_free;
267
268 return thenode;
269 }
270}
271
272void *literal_exe(struct searchNode *thenode, int type, void *theinput) {
273 struct literal_localdata *localdata;
274
275 localdata=thenode->localdata;
276
277 switch (type) {
278 case RETURNTYPE_STRING:
279 return (void *)(localdata->stringval->content);
280
281 default:
282 case RETURNTYPE_BOOL:
283 return (void *)(localdata->boolval);
284
285 case RETURNTYPE_INT:
286 return (void *)(localdata->intval);
287 }
288}
289
290void literal_free(struct searchNode *thenode) {
291 struct literal_localdata *localdata;
292
293 localdata=thenode->localdata;
294
295 freesstring(localdata->stringval);
296 free(localdata);
297 free(thenode);
298}