/[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.14 - (show annotations) (download) (as text)
Sun Sep 19 17:37:32 1999 UTC (20 years ago) by guppy
Branch: MAIN
Changes since 1.13: +13 -5 lines
File MIME type: text/x-chdr
bunch of patches

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23