/[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.22 - (hide annotations) (download) (as text)
Tue Dec 28 01:46:26 1999 UTC (19 years, 9 months ago) by guppy
Branch: MAIN
Changes since 1.21: +4 -4 lines
File MIME type: text/x-chdr
stricthost

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23