/[LeafOK_CVS]/pvpgn-1.7.4/src/bnetd/alias_command.c
ViewVC logotype

Contents of /pvpgn-1.7.4/src/bnetd/alias_command.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (show annotations)
Tue Jun 6 03:41:37 2006 UTC (19 years, 9 months ago) by sysadm
Branch point for: GNU, MAIN
Content type: text/x-csrc
Initial revision

1 /*
2 * Copyright (C) 2000 Onlyer (onlyer@263.net)
3 * Copyright (C) 2002 Ross Combs (rocombs@cs.nmsu.edu)
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #define ALIAS_COMMAND_INTERNAL_ACCESS
20 #include "common/setup_before.h"
21 #ifdef HAVE_STDDEF_H
22 # include <stddef.h>
23 #else
24 # ifndef NULL
25 # define NULL ((void *)0)
26 # endif
27 #endif
28 #ifdef STDC_HEADERS
29 # include <stdlib.h>
30 #else
31 # ifdef HAVE_MALLOC_H
32 # include <malloc.h>
33 # endif
34 #endif
35 #ifdef HAVE_STRING_H
36 # include <string.h>
37 #else
38 # ifdef HAVE_STRINGS_H
39 # include <strings.h>
40 # endif
41 #endif
42 #include "compat/strcasecmp.h"
43 #include <ctype.h>
44 #include <errno.h>
45 #include "compat/strerror.h"
46 #include "common/field_sizes.h"
47 #include "common/util.h"
48 #include "common/eventlog.h"
49 #include "common/list.h"
50 #include "common/xalloc.h"
51 #include "message.h"
52 #include "connection.h"
53 #include "alias_command.h"
54 #include "common/setup_after.h"
55
56
57 static t_list * aliaslist_head=NULL;
58
59 #define MAX_ALIAS_LEN 32
60
61
62 static int list_aliases(t_connection * c);
63 static char * replace_args(char const * in, unsigned int * offsets, int numargs, char const * text);
64 static int do_alias(t_connection * c, char const * cmd, char const * args);
65
66
67 static int list_aliases(t_connection * c)
68 {
69 t_elem const * elem1;
70 t_elem const * elem2;
71 t_alias const * alias;
72 t_output * output;
73 char temp[MAX_MESSAGE_LEN];
74
75 message_send_text(c,message_type_info,c,"Alias list:");
76 LIST_TRAVERSE_CONST(aliaslist_head,elem1)
77 {
78 if (!(alias = elem_get_data(elem1)))
79 continue;
80
81 sprintf(temp,"@%.128s",alias->alias);
82 message_send_text(c,message_type_info,c,temp);
83 LIST_TRAVERSE_CONST(alias->output,elem2)
84 {
85 if (!(output = elem_get_data(elem2)))
86 continue;
87
88 /*
89 * FIXME: need a more user-friendly way to express this... maybe
90 * add a help line to the file format?
91 */
92 if (output->min==-1)
93 sprintf(temp,"[*]%.128s",output->line);
94 else if (output->max==-1)
95 sprintf(temp,"[%d+]%.128s",output->min,output->line);
96 else if (output->min == output->max)
97 sprintf(temp,"[%d]%.128s",output->min,output->line);
98 else
99 sprintf(temp,"[%d-%d]%.128s",output->min,output->max,output->line);
100 message_send_text(c,message_type_info,c,temp);
101 }
102 }
103 return 0;
104 }
105
106
107 static char * replace_args(char const * in, unsigned int * offsets, int numargs, char const * text)
108 {
109 char * out;
110 unsigned int inpos;
111 unsigned int outpos;
112 unsigned int off1;
113 unsigned int off2;
114 unsigned int size;
115
116 off1 = off2 = 0;
117
118 out = xstrdup(in);
119 size = strlen(out);
120
121 for (inpos=outpos=0; inpos<strlen(in); inpos++)
122 {
123 if (in[inpos]!='$')
124 {
125 out[outpos] = in[inpos];
126 outpos++;
127 continue;
128 }
129
130 inpos++;
131
132 if (in[inpos]=='*')
133 {
134 off1 = offsets[0];
135 off2 = strlen(text);
136 }
137 else if (in[inpos]=='{')
138 {
139 int arg1, arg2;
140 char symbol;
141
142 if (sscanf(&in[inpos],"{%u-%u}",&arg1,&arg2)!=2)
143 {
144 if (sscanf(&in[inpos],"{%d%c",&arg2,&symbol)!=2)
145 {
146 while (in[inpos]!='\0' && in[inpos]!='}')
147 inpos++;
148 continue;
149 }
150 else
151 {
152 if (symbol=='}')
153 {
154 if (arg2<0)
155 {
156 arg1 = 0;
157 arg2 = -arg2;
158 }
159 else
160 {
161 arg1 = arg2;
162 }
163 }
164 else if (symbol=='-')
165 {
166 arg1 = arg2;
167 arg2 = numargs-1;
168 }
169 else
170 {
171 while (in[inpos]!='\0' && in[inpos]!='}') inpos++;
172 continue;
173 }
174
175 }
176 }
177
178 if (arg2>=numargs)
179 arg2 = numargs-1;
180 if (arg1>arg2)
181 {
182 while (in[inpos]!='\0' && in[inpos]!='}')
183 inpos++;
184 continue;
185 }
186 off1 = offsets[arg1];
187 if (arg2+1==numargs)
188 off2 = strlen(text);
189 else
190 off2 = offsets[arg2+1]-1;
191
192 while (in[inpos]!='\0' && in[inpos]!='}')
193 inpos++;
194 }
195 else if (isdigit((int)in[inpos]))
196 {
197 int arg;
198
199 if (in[inpos]=='0') arg = 0;
200 else if (in[inpos]=='1') arg = 1;
201 else if (in[inpos]=='2') arg = 2;
202 else if (in[inpos]=='3') arg = 3;
203 else if (in[inpos]=='4') arg = 4;
204 else if (in[inpos]=='5') arg = 5;
205 else if (in[inpos]=='6') arg = 6;
206 else if (in[inpos]=='7') arg = 7;
207 else if (in[inpos]=='8') arg = 8;
208 else arg = 9;
209
210 if (arg>=numargs)
211 continue;
212 for (off1=off2=offsets[arg]; text[off2]!='\0' && text[off2]!=' ' && text[off2]!='\t'; off2++);
213 }
214
215 {
216 char * newout;
217
218 newout = xmalloc(size+(off2-off1)+1); /* curr + new + nul */
219 size = size+(off2-off1)+1;
220 memmove(newout,out,outpos);
221 xfree(out);
222 out = newout;
223
224 while (off1<off2)
225 out[outpos++] = text[off1++];
226 }
227 }
228 out[outpos] = '\0';
229
230 return out;
231 }
232
233 int count_args(char const * text)
234 {
235 int args = 1;
236 char * pointer = (char *)text;
237 int not_ws = 1;
238
239 for (;*pointer!='\0';pointer++)
240 {
241 if ((not_ws) && (*pointer==' ')) not_ws = 0;
242 if ((not_ws == 0) && (*pointer!=' ')) { not_ws = 1; args++; }
243 }
244
245 return args;
246 }
247
248 void get_offsets(char const * text, unsigned int * offsets)
249 {
250 char * pointer = (char *)text;
251 int counter = 1;
252 int not_ws = 1;
253
254 offsets[0]=0;
255 for (;*pointer!='\0';pointer++)
256 {
257 if ((not_ws) && (*pointer==' ')) not_ws = 0;
258 if ((not_ws == 0) && (*pointer!=' '))
259 {
260 not_ws = 1;
261 offsets[counter]=(unsigned int)(pointer-text);
262 counter++;
263 }
264 }
265
266 }
267
268 static int do_alias(t_connection * c, char const * cmd, char const * text)
269 {
270 t_elem const * elem1;
271 t_elem const * elem2;
272 t_alias const * alias;
273 t_output * output;
274 unsigned int * offsets;
275 int numargs;
276 int match = -1;
277
278 numargs = count_args(text)-1;
279 offsets=xmalloc(sizeof(unsigned int *)*(numargs+1));
280 get_offsets(text,offsets);
281
282 LIST_TRAVERSE_CONST(aliaslist_head,elem1)
283 {
284 if (!(alias = elem_get_data(elem1)))
285 continue;
286
287 if (strstr(alias->alias,cmd)==NULL)
288 continue;
289
290 LIST_TRAVERSE_CONST(alias->output,elem2)
291 {
292 if (!(output = elem_get_data(elem2)))
293 continue;
294
295 if (!output->line)
296 continue;
297
298 if ((output->min==-1) ||
299 ((output->min<=numargs) && (output->max==-1)) ||
300 ((output->min<=numargs) && (output->max>=numargs)))
301
302 //TODO: initialize offsets
303
304 {
305 char * msgtmp;
306 char * tmp2;
307 char * cmd = "%C";
308 match = 1;
309
310 if ((msgtmp = replace_args(output->line,offsets,numargs+1,text)))
311 {
312 if (msgtmp[0]!='\0')
313 {
314 if ((msgtmp[0]=='/')&&(msgtmp[1]!='/')) // to make sure we don't get endless aliasing loop
315 {
316 tmp2 = xmalloc(strlen(msgtmp)+3);
317 sprintf(tmp2,"%s%s",cmd,msgtmp);
318 xfree((void *)msgtmp);
319 msgtmp=tmp2;
320
321 }
322 if (strlen(msgtmp)>MAX_MESSAGE_LEN)
323 {
324 msgtmp[MAX_MESSAGE_LEN]='\0';
325 eventlog(eventlog_level_info,__FUNCTION__,"message line after alias expansion was too long, truncating it");
326 }
327 message_send_formatted(c,msgtmp);
328 }
329 xfree((void *)msgtmp); /* avoid warning */
330 }
331 else
332 eventlog(eventlog_level_error,__FUNCTION__,"could not perform argument replacement");
333 }
334 }
335 }
336 xfree(offsets);
337 return match;
338 }
339
340
341 extern int aliasfile_load(char const * filename)
342 {
343 FILE * afp;
344 char * buff;
345 char * temp;
346 unsigned int line;
347 unsigned int pos;
348 int inalias;
349 t_alias * alias = NULL;
350
351
352 if (!filename)
353 {
354 eventlog(eventlog_level_error,__FUNCTION__,"got NULL filename");
355 return -1;
356 }
357 if (!(afp = fopen(filename,"r")))
358 {
359 eventlog(eventlog_level_error,__FUNCTION__,"unable to open alias file \"%s\" for reading (fopen: %s)",filename,pstrerror(errno));
360 return -1;
361 }
362
363 aliaslist_head = list_create();
364
365 inalias = 0;
366 for (line=1; (buff = file_get_line(afp)); line++)
367 {
368 for (pos=0; buff[pos]=='\t' || buff[pos]==' '; pos++);
369 if (buff[pos]=='\0' || buff[pos]=='#')
370 {
371 continue;
372 }
373 if (!(temp = strrchr(buff,'"'))) /* FIXME: assumes comments don't contain " */
374 temp = buff;
375 if ((temp = strrchr(temp,'#')))
376 {
377 unsigned int len;
378 unsigned int endpos;
379
380 *temp = '\0';
381 len = strlen(buff)+1;
382 for (endpos=len-1; buff[endpos]=='\t' || buff[endpos]==' '; endpos--);
383 buff[endpos+1] = '\0';
384 }
385
386 switch (inalias)
387 {
388 case 0:
389 if (buff[pos]!='@') /* not start of alias */
390 {
391 eventlog(eventlog_level_error,__FUNCTION__,"expected start of alias stanza on line %u of alias file \"%s\" but found \"%s\"",line,filename,&buff[pos]);
392 break;
393 }
394 inalias = 1;
395 break;
396
397 case 1:
398 {
399 if (buff[pos]=='\0') break;
400
401 inalias = 2;
402 alias = xmalloc(sizeof(t_alias));
403 alias->output=0;
404 alias->alias=xstrdup(&buff[pos]);
405 }
406 break;
407
408 case 2:
409 {
410 char * dummy;
411 char * out = NULL;
412 int min, max;
413 t_output * output;
414
415 min = max = 0;
416 if (buff[pos]!='[')
417 {
418 eventlog(eventlog_level_error,__FUNCTION__,"expected output entry on line %u of alias file \"%s\" but found \"%s\"",line,filename,&buff[pos]);
419 break;
420 }
421
422 if ((dummy=strchr(&buff[pos],']')))
423 {
424 if (dummy[1]!='\0') out = xstrdup(&dummy[1]);
425 }
426
427 if (buff[pos+1]=='*')
428 {
429 min = max = -1;
430 }
431 else if (buff[pos+1]=='+')
432 {
433 min = 1;
434 max = -1;
435 }
436 else if (sscanf(&buff[pos],"[%u",&min)==1)
437 {
438 if (*(dummy-1)=='+')
439 max = -1;
440 else max = min;
441 }
442 else
443 {
444 eventlog(eventlog_level_error,__FUNCTION__,"error parsing min/max value for alias output");
445 }
446
447 if (out!=NULL)
448 {
449 output = xmalloc(sizeof(t_output));
450 output->min=min;
451 output->max=max;
452 output->line = out;
453 alias->output = list_create();
454 list_append_data(alias->output,output);
455 inalias = 3;
456 }
457 }
458 break;
459 case 3:
460 {
461 if (buff[pos]=='@')
462 {
463 inalias = 1;
464 if (alias!=NULL) list_append_data(aliaslist_head,alias);
465 alias=NULL;
466 break;
467 }
468 else if (buff[pos]=='[')
469 {
470 char * dummy;
471 char * out = NULL;
472 int min, max;
473 t_output * output;
474
475 min = max = 0;
476 if ((dummy=strchr(&buff[pos],']')))
477 {
478 if (dummy[1]!='\0') out = xstrdup(&dummy[1]);
479 }
480
481
482 if (buff[pos+1]=='*')
483 {
484 min = max = -1;
485 }
486 else if (buff[pos+1]=='+')
487 {
488 min = 1;
489 max = -1;
490 }
491 else if (sscanf(&buff[pos],"[%u",&min)==1)
492 {
493 if (*(dummy-1)=='+')
494 max = -1;
495 else max = min;
496 }
497 else
498 {
499 eventlog(eventlog_level_error,__FUNCTION__,"error parsing min/max value for alias output");
500 }
501
502 if (out!=NULL)
503 {
504 output = xmalloc(sizeof(t_output));
505 output->min=min;
506 output->max=max;
507 output->line = out;
508
509 list_append_data(alias->output,output);
510 }
511 }
512 else
513 eventlog(eventlog_level_error,__FUNCTION__,"expected output entry or next alias stanza on line %u of file \"%s\"i but found \"%s\"",line,filename,&buff[pos]);
514 break;
515 }
516 }
517 }
518 if (alias!=NULL) list_append_data(aliaslist_head,alias);
519
520 file_get_line(NULL); // clear file_get_line buffer
521 fclose(afp);
522 eventlog(eventlog_level_info,__FUNCTION__,"done loading aliases");
523 return 0;
524 }
525
526
527 extern int aliasfile_unload(void)
528 {
529 t_elem * elem1;
530 t_elem * elem2;
531 t_alias const * alias;
532 t_output * output;
533
534 if (aliaslist_head)
535 {
536 LIST_TRAVERSE(aliaslist_head,elem1)
537 {
538 if (!(alias = elem_get_data(elem1))) /* should not happen */
539 {
540 eventlog(eventlog_level_error,__FUNCTION__,"alias list contains NULL item");
541 continue;
542 }
543
544 if (list_remove_elem(aliaslist_head,&elem1)<0)
545 {
546 eventlog(eventlog_level_error,__FUNCTION__,"could not remove alias");
547 continue;
548 }
549 if (alias->output)
550 {
551 LIST_TRAVERSE(alias->output,elem2)
552 {
553 if (!(output = elem_get_data(elem2)))
554 {
555 eventlog(eventlog_level_error,__FUNCTION__,"output list contains NULL item");
556 continue;
557 }
558
559 if (list_remove_elem(alias->output,&elem2)<0)
560 {
561 eventlog(eventlog_level_error,__FUNCTION__,"could not remove output");
562 continue;
563 }
564 xfree((void *)output->line); /* avoid warning */
565 xfree((void *)output);
566 }
567 list_destroy(alias->output);
568 }
569 if (alias->alias) xfree((void *)alias->alias);
570 xfree((void *)alias);
571 }
572
573 if (list_destroy(aliaslist_head)<0)
574 return -1;
575 aliaslist_head = NULL;
576 }
577
578 return 0;
579 }
580
581
582 extern int handle_alias_command(t_connection * c, char const * text)
583 {
584 unsigned int i,j;
585 char cmd[MAX_COMMAND_LEN];
586
587 for (i=j=0; text[i]!=' ' && text[i]!='\0'; i++) /* get command */
588 if (j<sizeof(cmd)-1) cmd[j++] = text[i];
589 cmd[j] = '\0';
590
591 if (cmd[2]=='\0')
592 return list_aliases(c);
593
594 if (do_alias(c,cmd,text)<0)
595 {
596 message_send_text(c,message_type_info,c,"No such alias. Use // to show the list.");
597 return -1;
598 }
599 return 0;
600 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1