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

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

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


Revision 1.4 - (show annotations) (download) (as text)
Sun Jul 18 22:28:21 1999 UTC (20 years, 3 months ago) by segfault
Branch: MAIN
Changes since 1.3: +2 -1 lines
File MIME type: text/x-chdr
John's help bug, guppy's fix

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23