/[cvs]/eggdrop1.4/src/misc.c
ViewVC logotype

Annotation of /eggdrop1.4/src/misc.c

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.3 - (hide annotations) (download) (as text)
Thu Jun 24 20:41:06 1999 UTC (20 years, 3 months ago) by segfault
Branch: MAIN
Changes since 1.2: +10 -4 lines
File MIME type: text/x-chdr
Small fixes to bugs in Fabian's telnet-banner patch

1 segfault 1.1 /*
2     * misc.c -- handles:
3     * split() maskhost() copyfile() movefile() fixfrom()
4     * dumplots() daysago() days() daysdur()
5     * logging things
6     * queueing output for the bot (msg and help)
7     * resync buffers for sharebots
8     * help system
9     * motd display and %var substitution
10     *
11     * dprintf'ized, 12dec1995
12     */
13     /*
14     * This file is part of the eggdrop source code
15     * copyright (c) 1997 Robey Pointer
16     * and is distributed according to the GNU general public license.
17     * For full details, read the top of 'main.c' or the file called
18     * COPYING that was distributed with this code.
19     */
20    
21     #include "main.h"
22     #include <sys/stat.h>
23     #include <unistd.h>
24     #include <fcntl.h>
25     #include "chan.h"
26     #ifdef HAVE_UNAME
27     #include <sys/utsname.h>
28     #endif
29    
30     extern int dcc_total;
31     extern struct dcc_t *dcc;
32     extern char helpdir[];
33     extern char version[];
34     extern char origbotname[];
35     extern char admin[];
36     extern int backgrd;
37     extern int con_chan;
38     extern int term_z;
39     extern int use_stderr;
40     extern char motdfile[];
41     extern char ver[];
42     extern int keep_all_logs;
43     extern char botnetnick[];
44     extern struct chanset_t *chanset;
45     extern time_t now;
46 segfault 1.2 extern char bannerfile[];
47 segfault 1.1
48     int shtime = 1; /* whether or not to display the time
49     * with console output */
50     log_t *logs = 0; /* logfiles */
51     int max_logs = 5; /* current maximum log files */
52     int max_logsize = 0; /* maximum logfile size, 0 for no limit */
53     int conmask = LOG_MODES | LOG_CMDS | LOG_MISC; /* console mask */
54     int debug_output = 0; /* disply output to server to LOG_SERVEROUT */
55    
56     struct help_list {
57     struct help_list *next;
58     char *name;
59     int type;
60     };
61    
62     static struct help_ref {
63     char *name;
64     struct help_list *first;
65     struct help_ref *next;
66     } *help_list = NULL;
67    
68     /* expected memory usage */
69     int expmem_misc()
70     {
71     struct help_ref *current;
72     struct help_list *item;
73     int tot = 0;
74    
75     for (current = help_list; current; current = current->next) {
76     tot += sizeof(struct help_ref) + strlen(current->name) + 1;
77    
78     for (item = current->first; item; item = item->next)
79     tot += sizeof(struct help_list) + strlen(item->name) + 1;
80     }
81     return tot + (max_logs * sizeof(log_t));
82     }
83    
84     void init_misc()
85     {
86     static int last = 0;
87    
88     if (max_logs < 1)
89     max_logs = 1;
90     if (logs)
91     logs = nrealloc(logs, max_logs * sizeof(log_t));
92     else
93     logs = nmalloc(max_logs * sizeof(log_t));
94     for (; last < max_logs; last++) {
95     logs[last].filename = logs[last].chname = NULL;
96     logs[last].mask = 0;
97     logs[last].f = NULL;
98     /* Added by cybah */
99     logs[last].szLast[0] = 0;
100     logs[last].Repeats = 0;
101     }
102     }
103    
104     /***** MISC FUNCTIONS *****/
105    
106     /* low-level stuff for other modules */
107     static int is_file(char *s)
108     {
109     struct stat ss;
110     int i = stat(s, &ss);
111    
112     if (i < 0)
113     return 0;
114     if ((ss.st_mode & S_IFREG) || (ss.st_mode & S_IFLNK))
115     return 1;
116     return 0;
117     }
118    
119     /* unixware has no strcasecmp() without linking in a hefty library */
120     #if !HAVE_STRCASECMP
121     #define upcase(c) (((c)>='a' && (c)<='z') ? (c)-'a'+'A' : (c))
122    
123     int strcasecmp(char *s1, char *s2)
124     {
125     while ((*s1) && (*s2) && (upcase(*s1) == upcase(*s2))) {
126     s1++;
127     s2++;
128     }
129     return upcase(*s1) - upcase(*s2);
130     }
131     #endif
132    
133     int my_strcpy(char *a, char *b)
134     {
135     char *c = b;
136    
137     while (*b)
138     *a++ = *b++;
139     *a = *b;
140     return b - c;
141     }
142    
143     /* split first word off of rest and put it in first */
144     void splitc(char *first, char *rest, char divider)
145     {
146     char *p;
147    
148     p = strchr(rest, divider);
149     if (p == NULL) {
150     if ((first != rest) && (first != NULL))
151     first[0] = 0;
152     return;
153     }
154     *p = 0;
155     if (first != NULL)
156     strcpy(first, rest);
157     if (first != rest)
158     strcpy(rest, p + 1);
159     }
160    
161     char *splitnick(char **blah)
162     {
163     char *p = strchr(*blah, '!'), *q = *blah;
164    
165     if (p) {
166     *p = 0;
167     *blah = p + 1;
168     return q;
169     }
170     return "";
171     }
172    
173     char *newsplit(char **rest)
174     {
175     register char *o, *r;
176    
177     if (!rest)
178     return *rest = "";
179     o = *rest;
180     while (*o == ' ')
181     o++;
182     r = o;
183     while (*o && (*o != ' '))
184     o++;
185     if (*o)
186     *o++ = 0;
187     *rest = o;
188     return r;
189     }
190    
191     /* convert "abc!user@a.b.host" into "*!user@*.b.host"
192     * or "abc!user@1.2.3.4" into "*!user@1.2.3.*" */
193     void maskhost(char *s, char *nw)
194     {
195     char *p, *q, *e, *f;
196     int i;
197    
198     *nw++ = '*';
199     *nw++ = '!';
200     p = (q = strchr(s, '!')) ? q + 1 : s;
201     /* strip of any nick, if a username is found, use last 8 chars */
202     if ((q = strchr(p, '@'))) {
203     if ((q - p) > 9) {
204     nw[0] = '*';
205     p = q - 7;
206     i = 1;
207     } else
208     i = 0;
209     while (*p != '@') {
210     if ((*p == '~') || (*p == '+') || (*p == '-'))
211     nw[i] = '?';
212     else
213     nw[i] = *p;
214     p++;
215     i++;
216     }
217     nw[i++] = '@';
218     q++;
219     } else {
220     nw[0] = '*';
221     nw[1] = '@';
222     i = 2;
223     q = s;
224     }
225     nw += i;
226     /* now q points to the hostname, i point to where to put the mask */
227     if (!(p = strchr(q, '.')) || !(e = strchr(p + 1, '.')))
228     /* TLD or 2 part host */
229     strcpy(nw, q);
230     else {
231     for (f = e; *f; f++);
232     f--;
233     if ((*f >= '0') && (*f <= '9')) { /* numeric IP address */
234     while (*f != '.')
235     f--;
236     strncpy(nw, q, f - q);
237     nw += (f - q);
238     strcpy(nw, ".*");
239     } else { /* normal host >= 3 parts */
240     /* ok, people whined at me...how about this? ..
241     * a.b.c -> *.b.c
242     * a.b.c.d -> *.b.c.d if tld is a country (2 chars)
243     * OR *.c.d if tld is com/edu/etc (3 chars)
244     * a.b.c.d.e -> *.c.d.e etc
245     */
246     char *x = strchr(e + 1, '.');
247    
248     if (!x)
249     x = p;
250     else if (strchr(x + 1, '.'))
251     x = e;
252     else if (strlen(x) == 3)
253     x = p;
254     else
255     x = e;
256     sprintf(nw, "*%s", x);
257     }
258     }
259     }
260    
261     /* copy a file from one place to another (possibly erasing old copy) */
262     /* returns 0 if OK, 1 if can't open original file, 2 if can't open new */
263     /* file, 3 if original file isn't normal, 4 if ran out of disk space */
264     int copyfile(char *oldpath, char *newpath)
265     {
266     int fi, fo, x;
267     char buf[512];
268     struct stat st;
269    
270     fi = open(oldpath, O_RDONLY, 0);
271     if (fi < 0)
272     return 1;
273     fstat(fi, &st);
274     if (!(st.st_mode & S_IFREG))
275     return 3;
276     fo = creat(newpath, (int) (st.st_mode & 0777));
277     if (fo < 0) {
278     close(fi);
279     return 2;
280     }
281     for (x = 1; x > 0;) {
282     x = read(fi, buf, 512);
283     if (x > 0) {
284     if (write(fo, buf, x) < x) { /* couldn't write */
285     close(fo);
286     close(fi);
287     unlink(newpath);
288     return 4;
289     }
290     }
291     }
292     close(fo);
293     close(fi);
294     return 0;
295     }
296    
297     int movefile(char *oldpath, char *newpath)
298     {
299     int x = copyfile(oldpath, newpath);
300    
301     if (x == 0)
302     unlink(oldpath);
303     return x;
304     }
305    
306     /* dump a potentially super-long string of text */
307     /* assume prefix 20 chars or less */
308     void dumplots(int idx, char *prefix, char *data)
309     {
310     char *p = data, *q, *n, c;
311    
312     if (!(*data)) {
313     dprintf(idx, "%s\n", prefix);
314     return;
315     }
316     while (strlen(p) > 480) {
317     q = p + 480;
318     /* search for embedded linefeed first */
319     n = strchr(p, '\n');
320     if ((n != NULL) && (n < q)) {
321     /* great! dump that first line then start over */
322     *n = 0;
323     dprintf(idx, "%s%s\n", prefix, p);
324     *n = '\n';
325     p = n + 1;
326     } else {
327     /* search backwards for the last space */
328     while ((*q != ' ') && (q != p))
329     q--;
330     if (q == p)
331     q = p + 480;
332     /* ^ 1 char will get squashed cos there was no space -- too bad */
333     c = *q;
334     *q = 0;
335     dprintf(idx, "%s%s\n", prefix, p);
336     *q = c;
337     p = q + 1;
338     }
339     }
340     /* last trailing bit: split by linefeeds if possible */
341     n = strchr(p, '\n');
342     while (n != NULL) {
343     *n = 0;
344     dprintf(idx, "%s%s\n", prefix, p);
345     *n = '\n';
346     p = n + 1;
347     n = strchr(p, '\n');
348     }
349     if (*p)
350     dprintf(idx, "%s%s\n", prefix, p); /* last trailing bit */
351     }
352    
353     /* convert an interval (in seconds) to one of:
354     * "19 days ago", "1 day ago", "18:12" */
355     void daysago(time_t now, time_t then, char *out)
356     {
357     char s[81];
358    
359     if (now - then > 86400) {
360     int days = (now - then) / 86400;
361    
362     sprintf(out, "%d day%s ago", days, (days == 1) ? "" : "s");
363     return;
364     }
365     strcpy(s, ctime(&then));
366     s[16] = 0;
367     strcpy(out, &s[11]);
368     }
369    
370     /* convert an interval (in seconds) to one of:
371     * "in 19 days", "in 1 day", "at 18:12" */
372     void days(time_t now, time_t then, char *out)
373     {
374     char s[81];
375    
376     if (now - then > 86400) {
377     int days = (now - then) / 86400;
378    
379     sprintf(out, "in %d day%s", days, (days == 1) ? "" : "s");
380     return;
381     }
382     strcpy(out, "at ");
383     strcpy(s, ctime(&now));
384     s[16] = 0;
385     strcpy(&out[3], &s[11]);
386     }
387    
388     /* convert an interval (in seconds) to one of:
389     * "for 19 days", "for 1 day", "for 09:10" */
390     void daysdur(time_t now, time_t then, char *out)
391     {
392     char s[81];
393     int hrs, mins;
394    
395     if (now - then > 86400) {
396     int days = (now - then) / 86400;
397    
398     sprintf(out, "for %d day%s", days, (days == 1) ? "" : "s");
399     return;
400     }
401     strcpy(out, "for ");
402     now -= then;
403     hrs = (int) (now / 3600);
404     mins = (int) ((now - (hrs * 3600)) / 60);
405     sprintf(s, "%02d:%02d", hrs, mins);
406     strcat(out, s);
407     }
408    
409     /***** LOGGING *****/
410    
411     /* log something */
412     /* putlog(level,channel_name,format,...); */
413     void putlog VARARGS_DEF(int, arg1)
414     {
415     int i, type;
416     char *format, *chname, s[MAX_LOG_LINE + 1], s1[256], *out;
417     time_t tt;
418     char ct[81];
419     struct tm *T = localtime(&now);
420    
421     va_list va;
422     type = VARARGS_START(int, arg1, va);
423     chname = va_arg(va, char *);
424     format = va_arg(va, char *);
425    
426     /* format log entry at offset 8, then i can prepend the timestamp */
427     out = &s[8];
428     #ifdef HAVE_VSNPRINTF
429     /* no need to check if out should be null-terminated here,
430     * just do it! <cybah> */
431     vsnprintf(out, MAX_LOG_LINE - 8, format, va);
432     out[MAX_LOG_LINE - 8] = 0;
433     #else
434     vsprintf(out, format, va);
435     #endif
436     tt = now;
437     if (keep_all_logs) {
438     strcpy(ct, ctime(&tt));
439     ct[10] = 0;
440     strcpy(ct, &ct[8]);
441     ct[7] = 0;
442     strcpy(&ct[2], &ct[4]);
443     ct[24] = 0;
444     strcpy(&ct[5], &ct[22]);
445     if (ct[0] == ' ')
446     ct[0] = '0';
447     }
448     if ((out[0]) && (shtime)) {
449     strcpy(s1, ctime(&tt));
450     strcpy(s1, &s1[11]);
451     s1[5] = 0;
452     out = s;
453     s[0] = '[';
454     strncpy(&s[1], s1, 5);
455     s[6] = ']';
456     s[7] = ' ';
457     }
458     strcat(out, "\n");
459     if (!use_stderr) {
460     for (i = 0; i < max_logs; i++) {
461     if ((logs[i].filename != NULL) && (logs[i].mask & type) &&
462     ((chname[0] == '*') || (logs[i].chname[0] == '*') ||
463     (!rfc_casecmp(chname, logs[i].chname)))) {
464     if (logs[i].f == NULL) {
465     /* open this logfile */
466     if (keep_all_logs) {
467     sprintf(s1, "%s.%s", logs[i].filename, ct);
468     logs[i].f = fopen(s1, "a+");
469     } else
470     logs[i].f = fopen(logs[i].filename, "a+");
471     }
472     if (logs[i].f != NULL) {
473     /* Check if this is the same as the last line added to
474     * the log. <cybah> */
475     if (!strcasecmp(out + 8, logs[i].szLast)) {
476     /* It is a repeat, so increment Repeats */
477     logs[i].Repeats++;
478     } else {
479     /* Not a repeat, check if there were any repeat
480     * lines previously... */
481     if (logs[i].Repeats > 0) {
482     /* Yep.. so display 'last message repeated x times'
483     * then reset repeats. We want the current time here,
484     * so put that in the file first. */
485     if (T)
486     fprintf(logs[i].f, "[%2.2d:%2.2d] last message repeated %d times\n",
487     T->tm_hour, T->tm_min, logs[i].Repeats);
488     else
489     fprintf(logs[i].f, "[??:??] last message repeated %d times\n",
490     logs[i].Repeats);
491     logs[i].Repeats = 0;
492     /* no need to reset logs[i].szLast here
493     * because we update it later on... */
494     }
495     fputs(out, logs[i].f);
496     strncpy(logs[i].szLast, out + 8, MAX_LOG_LINE);
497     logs[i].szLast[MAX_LOG_LINE] = 0;
498     }
499     }
500     }
501     }
502     }
503     if ((!backgrd) && (!con_chan) && (!term_z))
504     printf("%s", out);
505     for (i = 0; i < dcc_total; i++)
506     if ((dcc[i].type == &DCC_CHAT) && (dcc[i].u.chat->con_flags & type)) {
507     if ((chname[0] == '*') || (dcc[i].u.chat->con_chan[0] == '*') ||
508     (!rfc_casecmp(chname, dcc[i].u.chat->con_chan)))
509     dprintf(i, "%s", out);
510     }
511     if ((type & LOG_MISC) && use_stderr) {
512     if (shtime)
513     out += 8;
514     dprintf(DP_STDERR, "%s", s);
515     }
516     va_end(va);
517     }
518    
519     void check_logsize()
520     {
521     struct stat ss;
522     int i;
523    
524     /* int x=1; */
525     char buf[1024]; /* should be plenty */
526    
527     context;
528     if ((keep_all_logs == 0) && (max_logsize != 0)) {
529     for (i = 0; i < max_logs; i++) {
530     if (logs[i].filename) {
531     if (stat(logs[i].filename, &ss) != 0) {
532     break;
533     }
534     if ((ss.st_size >> 10) > max_logsize) {
535     context;
536     if (logs[i].f) {
537     /* write to the log before closing it huh.. */
538     putlog(LOG_MISC, "*", MISC_CLOGS, logs[i].filename, ss.st_size);
539     fflush(logs[i].f);
540     fclose(logs[i].f);
541     logs[i].f = NULL;
542     context;
543     }
544     context;
545    
546     simple_sprintf(buf, "%s.yesterday", logs[i].filename);
547     buf[1023] = 0;
548     unlink(buf);
549     /* x++;
550     * This is an alternate method i was considering, i want to leave
551     * this in here and commented.. in case someone wants it like this
552     * it really depends on feedback from the users. - poptix
553     * feel free to ask me, if you have questions on this..
554     *
555     * while (x > 0) {
556     * x++;
557     * * only YOU can prevent buffer overflows! *
558     * simple_sprintf(buf,"%s.%d",logs[i].filename,x);
559     * buf[1023] = 0;
560     * if (stat(buf,&ss) == -1) {
561     * * file doesnt exist, lets use it *
562     */
563     #ifdef RENAME
564     rename(logs[i].filename, buf);
565     #else
566     movefile(logs[i].filename, buf);
567     #endif
568     /* x=0;
569     * }
570     * } */
571     }
572     }
573     }
574     }
575     context;
576     }
577    
578     /* flush the logfiles to disk */
579     void flushlogs()
580     {
581     int i;
582     struct tm *T = localtime(&now);
583    
584     context;
585     /* Now also checks to see if there's a repeat message and
586     * displays the 'last message repeated...' stuff too <cybah> */
587     for (i = 0; i < max_logs; i++) {
588     if (logs[i].f != NULL) {
589     if (logs[i].Repeats > 0) {
590     /* Repeat.. so display 'last message
591     * repeated x times' then reset Repeats. */
592     if (T) {
593     fprintf(logs[i].f, "[%2.2d:%2.2d] last message repeated %d times\n",
594     T->tm_hour, T->tm_min, logs[i].Repeats);
595     } else {
596     fprintf(logs[i].f, "[??:??] last message repeated %d times\n",
597     logs[i].Repeats);
598     }
599     /* Reset repeats */
600     logs[i].Repeats = 0;
601     }
602     fflush(logs[i].f);
603     }
604     }
605     context;
606     }
607    
608     /********** STRING SUBSTITUTION **********/
609    
610     static int cols = 0;
611     static int colsofar = 0;
612     static int blind = 0;
613     static int subwidth = 70;
614     static char *colstr = NULL;
615    
616     /* add string to colstr */
617     static void subst_addcol(char *s, char *newcol)
618     {
619     char *p, *q;
620     int i, colwidth;
621    
622     if ((newcol[0]) && (newcol[0] != '\377'))
623     colsofar++;
624     colstr = nrealloc(colstr, strlen(colstr) + strlen(newcol) +
625     (colstr[0] ? 2 : 1));
626     if ((newcol[0]) && (newcol[0] != '\377')) {
627     if (colstr[0])
628     strcat(colstr, "\377");
629     strcat(colstr, newcol);
630     }
631     if ((colsofar == cols) || ((newcol[0] == '\377') && (colstr[0]))) {
632     colsofar = 0;
633     strcpy(s, " ");
634     colwidth = (subwidth - 5) / cols;
635     q = colstr;
636     p = strchr(colstr, '\377');
637     while (p != NULL) {
638     *p = 0;
639     strcat(s, q);
640     for (i = strlen(q); i < colwidth; i++)
641     strcat(s, " ");
642     q = p + 1;
643     p = strchr(q, '\377');
644     }
645     strcat(s, q);
646     nfree(colstr);
647     colstr = (char *) nmalloc(1);
648     colstr[0] = 0;
649     }
650     }
651    
652     /* substitute %x codes in help files
653     * %B = bot nickname
654     * %V = version
655     * %C = list of channels i monitor
656     * %E = eggdrop banner
657     * %A = admin line
658     * %T = current time ("14:15")
659     * %N = user's nickname
660     * %U = display system name if possible
661     * %{+xy} require flags to read this section
662     * %{-} turn of required flag matching only
663     * %{center} center this line
664     * %{cols=N} start of columnated section (indented)
665     * %{help=TOPIC} start a section for a particular command
666     * %{end} end of section
667     */
668     #define HELP_BUF_LEN 256
669     #define HELP_BOLD 1
670     #define HELP_REV 2
671     #define HELP_UNDER 4
672     #define HELP_FLASH 8
673    
674     void help_subst(char *s, char *nick, struct flag_record *flags,
675     int isdcc, char *topic)
676     {
677     char xx[HELP_BUF_LEN + 1], sub[161], *current, *q, chr, *writeidx,
678     *readidx, *towrite;
679     struct chanset_t *chan;
680     int i, j, center = 0;
681     static int help_flags;
682    
683     #ifdef HAVE_UNAME
684     struct utsname uname_info;
685    
686     #endif
687    
688     if (s == NULL) {
689     /* used to reset substitutions */
690     blind = 0;
691     cols = 0;
692     subwidth = 70;
693     if (colstr != NULL) {
694     nfree(colstr);
695     colstr = NULL;
696     }
697     help_flags = isdcc;
698     return;
699     }
700     strncpy(xx, s, HELP_BUF_LEN);
701     xx[HELP_BUF_LEN] = 0;
702     readidx = xx;
703     writeidx = s;
704     current = strchr(readidx, '%');
705     while (current) {
706     /* are we about to copy a chuck to the end of the buffer?
707     * if so return */
708     if ((writeidx + (current - readidx)) >= (s + HELP_BUF_LEN)) {
709     strncpy(writeidx, readidx, (s + HELP_BUF_LEN) - writeidx);
710     s[HELP_BUF_LEN] = 0;
711     return;
712     }
713     chr = *(current + 1);
714     *current = 0;
715     if (!blind)
716     writeidx += my_strcpy(writeidx, readidx);
717     towrite = NULL;
718     switch (chr) {
719     case 'b':
720     if (glob_hilite(*flags)) {
721     if (help_flags & HELP_IRC) {
722     towrite = "\002";
723     } else if (help_flags & HELP_BOLD) {
724     help_flags &= ~HELP_BOLD;
725     towrite = "\033[0m";
726     } else {
727     help_flags |= HELP_BOLD;
728     towrite = "\033[1m";
729     }
730     }
731     break;
732     case 'v':
733     if (glob_hilite(*flags)) {
734     if (help_flags & HELP_IRC) {
735     towrite = "\026";
736     } else if (help_flags & HELP_REV) {
737     help_flags &= ~HELP_REV;
738     towrite = "\033[0m";
739     } else {
740     help_flags |= HELP_REV;
741     towrite = "\033[7m";
742     }
743     }
744     break;
745     case '_':
746     if (glob_hilite(*flags)) {
747     if (help_flags & HELP_IRC) {
748     towrite = "\037";
749     } else if (help_flags & HELP_UNDER) {
750     help_flags &= ~HELP_UNDER;
751     towrite = "\033[0m";
752     } else {
753     help_flags |= HELP_UNDER;
754     towrite = "\033[4m";
755     }
756     }
757     break;
758     case 'f':
759     if (glob_hilite(*flags)) {
760     if (help_flags & HELP_FLASH) {
761     if (help_flags & HELP_IRC) {
762     towrite = "\002\037";
763     } else {
764     towrite = "\033[0m";
765     }
766     help_flags &= ~HELP_FLASH;
767     } else {
768     help_flags |= HELP_FLASH;
769     if (help_flags & HELP_IRC) {
770     towrite = "\037\002";
771     } else {
772     towrite = "\033[5m";
773     }
774     }
775     }
776     break;
777     case 'U':
778     #ifdef HAVE_UNAME
779     if (!uname(&uname_info)) {
780     simple_sprintf(sub, "%s %s", uname_info.sysname,
781     uname_info.release);
782     towrite = sub;
783     } else
784     #endif
785     towrite = "*UNKNOWN*";
786     break;
787     case 'B':
788     towrite = (isdcc ? botnetnick : origbotname);
789     break;
790     case 'V':
791     towrite = ver;
792     break;
793     case 'E':
794     towrite = version;
795     break;
796     case 'A':
797     towrite = admin;
798     break;
799     case 'T':
800     strcpy(sub, ctime(&now));
801     sub[16] = 0;
802     towrite = sub + 11;
803     break;
804     case 'N':
805     towrite = strchr(nick, ':');
806     if (towrite)
807     towrite++;
808     else
809     towrite = nick;
810     break;
811     case 'C':
812     if (!blind)
813     for (chan = chanset; chan; chan = chan->next) {
814     if ((strlen(chan->name) + writeidx + 2) >=
815     (s + HELP_BUF_LEN)) {
816     strncpy(writeidx, chan->name, (s + HELP_BUF_LEN) - writeidx);
817     s[HELP_BUF_LEN] = 0;
818     return;
819     }
820     writeidx += my_strcpy(writeidx, chan->name);
821     if (chan->next) {
822     *writeidx++ = ',';
823     *writeidx++ = ' ';
824     }
825     }
826     break;
827     case '{':
828     q = current;
829     current++;
830     while ((*current != '}') && (*current))
831     current++;
832     if (*current) {
833     *current = 0;
834     current--;
835     q += 2;
836     /* now q is the string and p is where the rest of the fcn expects */
837     if (!strncmp(q, "help=", 5)) {
838     if (topic && strcasecmp(q + 5, topic))
839     blind |= 2;
840     else
841     blind &= ~2;
842     } else if (!(blind & 2)) {
843     if (q[0] == '+') {
844     struct flag_record fr =
845     {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
846    
847     break_down_flags(q + 1, &fr, NULL);
848     if (!flagrec_ok(&fr, flags))
849     blind |= 1;
850     else
851     blind &= ~1;
852     } else if (q[0] == '-') {
853     blind &= ~1;
854     } else if (!strcasecmp(q, "end")) {
855     blind &= ~1;
856     subwidth = 70;
857     if (cols) {
858     subst_addcol(sub, "\377");
859     nfree(colstr);
860     colstr = NULL;
861     cols = 0;
862     towrite = sub;
863     }
864     } else if (!strcasecmp(q, "center"))
865     center = 1;
866     else if (!strncmp(q, "cols=", 5)) {
867     char *r;
868    
869     cols = atoi(q + 5);
870     colsofar = 0;
871     colstr = (char *) nmalloc(1);
872     colstr[0] = 0;
873     r = strchr(q + 5, '/');
874     if (r != NULL)
875     subwidth = atoi(r + 1);
876     }
877     }
878     } else
879     current = q; /* no } so ignore */
880     break;
881     default:
882     if (!blind) {
883     *writeidx++ = chr;
884     if (writeidx >= (s + HELP_BUF_LEN)) {
885     *writeidx = 0;
886     return;
887     }
888     }
889     }
890     if (towrite && !blind) {
891     if ((writeidx + strlen(towrite)) >= (s + HELP_BUF_LEN)) {
892     strncpy(writeidx, towrite, (s + HELP_BUF_LEN) - writeidx);
893     s[HELP_BUF_LEN] = 0;
894     return;
895     }
896     writeidx += my_strcpy(writeidx, towrite);
897     }
898     if (chr) {
899     readidx = current + 2;
900     current = strchr(readidx, '%');
901     } else {
902     readidx = current + 1;
903     current = NULL;
904     }
905     }
906     if (!blind) {
907     i = strlen(readidx);
908     if (i && ((writeidx + i) >= (s + HELP_BUF_LEN))) {
909     strncpy(writeidx, readidx, (s + HELP_BUF_LEN) - writeidx);
910     s[HELP_BUF_LEN] = 0;
911     return;
912     }
913     strcpy(writeidx, readidx);
914     } else
915     *writeidx = 0;
916     if (center) {
917     strcpy(xx, s);
918     i = 35 - (strlen(xx) / 2);
919     if (i > 0) {
920     s[0] = 0;
921     for (j = 0; j < i; j++)
922     s[j] = ' ';
923     strcpy(s + i, xx);
924     }
925     }
926     if (cols) {
927     strcpy(xx, s);
928     s[0] = 0;
929     subst_addcol(s, xx);
930     }
931     }
932    
933     static void scan_help_file(struct help_ref *current, char *filename, int type)
934     {
935     FILE *f;
936     char s[HELP_BUF_LEN + 1], *p, *q;
937     struct help_list *list;
938    
939     if (is_file(filename) && (f = fopen(filename, "r"))) {
940     while (!feof(f)) {
941     fgets(s, HELP_BUF_LEN, f);
942     if (!feof(f)) {
943     p = s;
944     while ((q = strstr(p, "%{help="))) {
945     q += 7;
946     if ((p = strchr(q, '}'))) {
947     *p = 0;
948     list = nmalloc(sizeof(struct help_list));
949    
950     list->name = nmalloc(p - q + 1);
951     strcpy(list->name, q);
952     list->next = current->first;
953     list->type = type;
954     current->first = list;
955     p++;
956     } else
957     p = "";
958     }
959     }
960     }
961     fclose(f);
962     }
963     }
964    
965     void add_help_reference(char *file)
966     {
967     char s[1024];
968     struct help_ref *current;
969    
970     for (current = help_list; current; current = current->next)
971     if (!strcmp(current->name, file))
972     return; /* already exists, can't re-add :P */
973     current = nmalloc(sizeof(struct help_ref));
974    
975     current->name = nmalloc(strlen(file) + 1);
976     strcpy(current->name, file);
977     current->next = help_list;
978     current->first = NULL;
979     help_list = current;
980     simple_sprintf(s, "%smsg/%s", helpdir, file);
981     scan_help_file(current, s, 0);
982     simple_sprintf(s, "%s%s", helpdir, file);
983     scan_help_file(current, s, 1);
984     simple_sprintf(s, "%sset/%s", helpdir, file);
985     scan_help_file(current, s, 2);
986     };
987    
988     void rem_help_reference(char *file)
989     {
990     struct help_ref *current, *last = NULL;
991     struct help_list *item;
992    
993     for (current = help_list; current; last = current, current = current->next)
994     if (!strcmp(current->name, file)) {
995     while ((item = current->first)) {
996     current->first = item->next;
997     nfree(item->name);
998     nfree(item);
999     }
1000     nfree(current->name);
1001     if (last)
1002     last->next = current->next;
1003     else
1004     help_list = current->next;
1005     nfree(current);
1006     return;
1007     }
1008     }
1009    
1010     void reload_help_data(void)
1011     {
1012     struct help_ref *current = help_list, *next;
1013     struct help_list *item;
1014    
1015     help_list = NULL;
1016     while (current) {
1017     while ((item = current->first)) {
1018     current->first = item->next;
1019     nfree(item->name);
1020     nfree(item);
1021     }
1022     add_help_reference(current->name);
1023     nfree(current->name);
1024     next = current->next;
1025     nfree(current);
1026     current = next;
1027     }
1028     }
1029    
1030     void debug_help(int idx)
1031     {
1032     struct help_ref *current;
1033     struct help_list *item;
1034    
1035     for (current = help_list; current; current = current->next) {
1036     dprintf(idx, "HELP FILE(S): %s\n", current->name);
1037     for (item = current->first; item; item = item->next) {
1038     dprintf(idx, " %s (%s)\n", item->name, (item->type == 0) ? "msg/" :
1039     (item->type == 1) ? "" : "set/");
1040     }
1041     }
1042     }
1043    
1044     FILE *resolve_help(int dcc, char *file)
1045     {
1046     char s[1024], *p;
1047     FILE *f;
1048     struct help_ref *current;
1049     struct help_list *item;
1050    
1051     /* somewhere here goes the eventual substituation */
1052     if (!(dcc & HELP_TEXT))
1053     for (current = help_list; current; current = current->next)
1054     for (item = current->first; item; item = item->next)
1055     if (!strcmp(item->name, file)) {
1056     if (!item->type && !dcc) {
1057     simple_sprintf(s, "%smsg/%s", helpdir, current->name);
1058     if ((f = fopen(s, "r")))
1059     return f;
1060     } else if (dcc && item->type) {
1061     if (item->type == 1)
1062     simple_sprintf(s, "%s%s", helpdir, current->name);
1063     else
1064     simple_sprintf(s, "%sset/%s", helpdir, current->name);
1065     if ((f = fopen(s, "r")))
1066     return f;
1067     }
1068     }
1069     for (p = s + simple_sprintf(s, "%s%s", helpdir, dcc ? "" : "msg/");
1070     *file && (p < s + 1023); file++, p++) {
1071     switch (*file) {
1072     case ' ':
1073     case '.':
1074     *p = '/';
1075     break;
1076     case '-':
1077     *p = '-';
1078     break;
1079     case '+':
1080     *p = 'P';
1081     break;
1082     default:
1083     *p = *file;
1084     }
1085     }
1086     *p = 0;
1087     if (!is_file(s)) {
1088     strcat(s, "/");
1089     strcat(s, file);
1090     if (!is_file(s))
1091     return NULL;
1092     }
1093     return fopen(s, "r");
1094     }
1095    
1096     void showhelp(char *who, char *file, struct flag_record *flags, int fl)
1097     {
1098     int lines = 0;
1099     char s[HELP_BUF_LEN + 1];
1100     FILE *f = resolve_help(fl, file);
1101    
1102     if (f) {
1103     help_subst(NULL, NULL, 0, HELP_IRC, NULL); /* clear flags */
1104     while (!feof(f)) {
1105     fgets(s, HELP_BUF_LEN, f);
1106     if (!feof(f)) {
1107     if (s[strlen(s) - 1] == '\n')
1108     s[strlen(s) - 1] = 0;
1109     if (!s[0])
1110     strcpy(s, " ");
1111     help_subst(s, who, flags, 0, file);
1112     if ((s[0]) && (strlen(s) > 1)) {
1113     dprintf(DP_HELP, "NOTICE %s :%s\n", who, s);
1114     lines++;
1115     }
1116     }
1117     }
1118     fclose(f);
1119     }
1120     if (!lines && !(fl & HELP_TEXT))
1121     dprintf(DP_HELP, "NOTICE %s :%s\n", who, IRC_NOHELP2);
1122     }
1123    
1124     void tellhelp(int idx, char *file, struct flag_record *flags, int fl)
1125     {
1126     char s[HELP_BUF_LEN + 1];
1127     int lines = 0;
1128     FILE *f = resolve_help(HELP_DCC | fl, file);
1129    
1130     if (f) {
1131     help_subst(NULL, NULL, 0,
1132     (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
1133     while (!feof(f)) {
1134     fgets(s, HELP_BUF_LEN, f);
1135     if (!feof(f)) {
1136     if (s[strlen(s) - 1] == '\n')
1137     s[strlen(s) - 1] = 0;
1138     if (!s[0])
1139     strcpy(s, " ");
1140     help_subst(s, dcc[idx].nick, flags, 1, file);
1141     if (s[0]) {
1142     dprintf(idx, "%s\n", s);
1143     lines++;
1144     }
1145     }
1146     }
1147     fclose(f);
1148     }
1149     if (!lines && !(fl & HELP_TEXT))
1150     dprintf(idx, "%s\n", IRC_NOHELP2);
1151     }
1152    
1153     /* substitute vars in a lang text to dcc chatter */
1154     void sub_lang(int idx, char *text)
1155     {
1156     char s[1024];
1157     struct flag_record fr =
1158     {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
1159    
1160     get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
1161     help_subst(NULL, NULL, 0,
1162     (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
1163     strncpy(s, text, 1024);
1164     if (s[strlen(s) - 1] == '\n')
1165     s[strlen(s) - 1] = 0;
1166     if (!s[0])
1167     strcpy(s, " ");
1168     help_subst(s, dcc[idx].nick, &fr, 1, botnetnick);
1169     if (s[0])
1170     dprintf(idx, "%s\n", s);
1171     }
1172    
1173     /* show motd to dcc chatter */
1174     void show_motd(int idx)
1175     {
1176     FILE *vv;
1177     char s[1024];
1178     struct flag_record fr =
1179     {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
1180    
1181     get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
1182     vv = fopen(motdfile, "r");
1183     if (vv != NULL) {
1184     if (!is_file(motdfile)) {
1185     fclose(vv);
1186     dprintf(idx, "### MOTD %s\n", IRC_NOTNORMFILE);
1187     return;
1188     }
1189     dprintf(idx, "\n");
1190     help_subst(NULL, NULL, 0,
1191     (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
1192     while (!feof(vv)) {
1193     fgets(s, 120, vv);
1194     if (!feof(vv)) {
1195     if (s[strlen(s) - 1] == '\n')
1196     s[strlen(s) - 1] = 0;
1197     if (!s[0])
1198     strcpy(s, " ");
1199     help_subst(s, dcc[idx].nick, &fr, 1, botnetnick);
1200     if (s[0])
1201     dprintf(idx, "%s\n", s);
1202     }
1203     }
1204     fclose(vv);
1205     dprintf(idx, "\n");
1206     }
1207     }
1208    
1209     /* remove :'s from ignores and bans */
1210     void remove_gunk(char *par)
1211     {
1212     char *q, *p;
1213     char WBUF[strlen(par) + 1];
1214    
1215     for (p = par, q = WBUF; *p; p++, q++) {
1216     if (*p == ':')
1217     q--;
1218     else
1219     *q = *p;
1220     }
1221     *q = *p;
1222     strcpy(par, WBUF);
1223     }
1224    
1225     /* This will return a pointer to the first character after the @ in the
1226     * string given it. Possibly it's time to think about a regexp library
1227     * for eggdrop... */
1228     char *extracthostname(char *hostmask)
1229     {
1230     char *ptr = strrchr(hostmask, '@');
1231    
1232     if (ptr) {
1233     ptr = ptr + 1;
1234     return ptr;
1235     }
1236     return "";
1237     }
1238 segfault 1.2
1239     /* show banner to telnet user, simialer to show_motd() - [seC] */
1240     void show_banner(int idx) {
1241     FILE *vv;
1242     char s[1024];
1243     struct flag_record fr = {FR_GLOBAL|FR_CHAN,0,0,0,0,0};
1244    
1245     get_user_flagrec(dcc[idx].user,&fr,dcc[idx].u.chat->con_chan);
1246     vv = fopen(bannerfile, "r");
1247     if (!vv || !is_file(bannerfile)) {
1248     dprintf(idx, "\r\n\r\n");
1249     sub_lang(idx, MISC_BANNER);
1250     return;
1251     }
1252     while(!feof(vv)) {
1253     fgets(s, 120, vv);
1254 segfault 1.3 if (!feof(vv)) {
1255     if (s[strlen(s) - 1] == '\n')
1256     s[strlen(s) - 1] = 0;
1257     if (!s[0])
1258     strcpy(s, " \n");
1259     help_subst(s, dcc[idx].nick, &fr, 1, botnetnick);
1260     if (s[0])
1261     dprintf(idx, "%s", s);
1262     }
1263 segfault 1.2 }
1264 segfault 1.3 dprintf(idx, "\r\nNickname.\r\n");
1265 segfault 1.2 }
1266    

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23