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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.1 - (hide 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 sysadm 1.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