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

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

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


Revision 1.81 - (show annotations) (download) (as text)
Tue Dec 16 03:13:51 2003 UTC (15 years, 10 months ago) by wcc
Branch: MAIN
CVS Tags: HEAD
Changes since 1.80: +1 -1 lines
File MIME type: text/x-chdr
FILE REMOVED
* main.c cleanups.
* Added pidfile and die_on_sigterm to config.
* Added 'act' party command.
* Started a 'status' party command.
* Removed config.tcl.
* General cleanups.

1 /*
2 * misc.c --
3 *
4 * maskhost() dumplots() daysago() days() daysdur()
5 * queueing output for the bot (msg and help)
6 * help system
7 * motd display and %var substitution
8 */
9 /*
10 * Copyright (C) 1997 Robey Pointer
11 * Copyright (C) 1999, 2000, 2001, 2002, 2003, 2004 Eggheads Development Team
12 *
13 * This program is free software; you can redistribute it and/or
14 * modify it under the terms of the GNU General Public License
15 * as published by the Free Software Foundation; either version 2
16 * of the License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
26 */
27
28 #ifndef lint
29 static const char rcsid[] = "$Id: misc.c,v 1.80 2003/12/11 00:49:11 wcc Exp $";
30 #endif
31
32 #include "main.h"
33 #include "misc.h"
34 #include <unistd.h>
35 #include <fcntl.h>
36 #include "chan.h"
37 #include "modules.h"
38 #include "logfile.h"
39 #include "dccutil.h" /* dprintf_eggdrop, chatout */
40 #include "userrec.h" /* write_userfile */
41
42 #ifdef HAVE_UNAME
43 # include <sys/utsname.h>
44 #endif
45
46 extern struct dcc_t *dcc;
47 extern struct chanset_t *chanset;
48 extern char helpdir[], version[], *botname, admin[], network[], motdfile[],
49 ver[], myname[], bannerfile[], textdir[];
50 extern int strict_host;
51 extern time_t now;
52
53 int conmask = LOG_MODES | LOG_CMDS | LOG_MISC; /* Console mask */
54 int raw_log = 0; /* Disply output to server to LOG_SERVEROUT */
55
56 struct help_list_t {
57 struct help_list_t *next;
58 char *name;
59 int type;
60 };
61
62 static struct help_ref {
63 char *name;
64 struct help_list_t *first;
65 struct help_ref *next;
66 } *help_list = NULL;
67
68
69 /*
70 * Misc functions
71 */
72
73 /* Convert "abc!user@a.b.host" into "*!user@*.b.host"
74 * or "abc!user@1.2.3.4" into "*!user@1.2.3.*"
75 * or "abc!user@0:0:0:0:0:ffff:1.2.3.4" into "*!user@0:0:0:0:0:ffff:1.2.3.*"
76 * or "abc!user@3ffe:604:2:b02e:6174:7265:6964:6573" into
77 * "*!user@3ffe:604:2:b02e:6174:7265:6964:*"
78 */
79 /* FIXME: Convert strncpy usage to strlcpy */
80 void _maskhost(const char *s, char *nw, int host)
81 {
82 register const char *p, *q, *e, *f;
83 int i;
84
85 *nw++ = '*';
86 *nw++ = '!';
87 p = (q = strchr(s, '!')) ? q + 1 : s;
88 /* Strip of any nick, if a username is found, use last 8 chars */
89 if ((q = strchr(p, '@'))) {
90 int fl = 0;
91
92 if ((q - p) > 9) {
93 nw[0] = '*';
94 p = q - 7;
95 i = 1;
96 } else
97 i = 0;
98 while (*p != '@') {
99 if (!fl && strchr("~+-^=", *p)) {
100 if (strict_host)
101 nw[i] = '?';
102 else if (!host)
103 nw[i] = '*';
104 else
105 i--;
106 } else
107 nw[i] = *p;
108 fl++;
109 p++;
110 i++;
111 }
112 nw[i++] = '@';
113 q++;
114 } else {
115 nw[0] = '*';
116 nw[1] = '@';
117 i = 2;
118 q = s;
119 }
120 nw += i;
121 e = NULL;
122 /* Now q points to the hostname, i point to where to put the mask */
123 if ((!(p = strchr(q, '.')) || !(e = strchr(p + 1, '.'))) && !strchr(q, ':'))
124 /* TLD or 2 part host */
125 strcpy(nw, q);
126 else {
127 if (e == NULL) { /* IPv6 address? */
128 const char *mask_str;
129
130 f = strrchr(q, ':');
131 if (strchr(f, '.')) { /* IPv4 wrapped in an IPv6? */
132 f = strrchr(f, '.');
133 mask_str = ".*";
134 } else /* ... no, true IPv6. */
135 mask_str = ":*";
136 strncpy(nw, q, f - q);
137 /* No need to nw[f-q] = 0 here, as the strcpy below will
138 * terminate the string for us.
139 */
140 nw += (f - q);
141 strcpy(nw, mask_str);
142 } else {
143 for (f = e; *f; f++);
144 f--;
145 if (*f >= '0' && *f <= '9') { /* Numeric IP address */
146 while (*f != '.')
147 f--;
148 strncpy(nw, q, f - q);
149 /* No need to nw[f-q] = 0 here, as the strcpy below will
150 * terminate the string for us.
151 */
152 nw += (f - q);
153 strcpy(nw, ".*");
154 } else { /* Normal host >= 3 parts */
155 /* a.b.c -> *.b.c
156 * a.b.c.d -> *.b.c.d if tld is a country (2 chars)
157 * OR *.c.d if tld is com/edu/etc (3 chars)
158 * a.b.c.d.e -> *.c.d.e etc
159 */
160 const char *x = strchr(e + 1, '.');
161
162 if (!x)
163 x = p;
164 else if (strchr(x + 1, '.'))
165 x = e;
166 else if (strlen(x) == 3)
167 x = p;
168 else
169 x = e;
170 sprintf(nw, "*%s", x);
171 }
172 }
173 }
174 }
175
176 /* Dump a potentially super-long string of text.
177 */
178 void dumplots(int idx, const char *prefix, char *data)
179 {
180 char *p = data, *q, *n, c;
181 const int max_data_len = 500 - strlen(prefix);
182
183 if (!*data) {
184 dprintf(idx, "%s\n", prefix);
185 return;
186 }
187 while (strlen(p) > max_data_len) {
188 q = p + max_data_len;
189 /* Search for embedded linefeed first */
190 n = strchr(p, '\n');
191 if (n && n < q) {
192 /* Great! dump that first line then start over */
193 *n = 0;
194 dprintf(idx, "%s%s\n", prefix, p);
195 *n = '\n';
196 p = n + 1;
197 } else {
198 /* Search backwards for the last space */
199 while (*q != ' ' && q != p)
200 q--;
201 if (q == p)
202 q = p + max_data_len;
203 c = *q;
204 *q = 0;
205 dprintf(idx, "%s%s\n", prefix, p);
206 *q = c;
207 p = q;
208 if (c == ' ')
209 p++;
210 }
211 }
212 /* Last trailing bit: split by linefeeds if possible */
213 n = strchr(p, '\n');
214 while (n) {
215 *n = 0;
216 dprintf(idx, "%s%s\n", prefix, p);
217 *n = '\n';
218 p = n + 1;
219 n = strchr(p, '\n');
220 }
221 if (*p)
222 dprintf(idx, "%s%s\n", prefix, p); /* Last trailing bit */
223 }
224
225 /* Convert an interval (in seconds) to one of:
226 * "19 days ago", "1 day ago", "18:12"
227 */
228 void daysago(time_t now, time_t then, char *out)
229 {
230 if (now - then > 86400) {
231 int days = (now - then) / 86400;
232
233 sprintf(out, "%d day%s ago", days, (days == 1) ? "" : "s");
234 return;
235 }
236 strftime(out, 6, "%H:%M", localtime(&then));
237 }
238
239 /* Convert an interval (in seconds) to one of:
240 * "in 19 days", "in 1 day", "at 18:12"
241 */
242 void days(time_t now, time_t then, char *out)
243 {
244 if (now - then > 86400) {
245 int days = (now - then) / 86400;
246
247 sprintf(out, "in %d day%s", days, (days == 1) ? "" : "s");
248 return;
249 }
250 strftime(out, 9, "at %H:%M", localtime(&now));
251 }
252
253 /* Convert an interval (in seconds) to one of:
254 * "for 19 days", "for 1 day", "for 09:10"
255 */
256 void daysdur(time_t now, time_t then, char *out)
257 {
258 char s[81];
259 int hrs, mins;
260
261 if (now - then > 86400) {
262 int days = (now - then) / 86400;
263
264 sprintf(out, "for %d day%s", days, (days == 1) ? "" : "s");
265 return;
266 }
267 strcpy(out, "for ");
268 now -= then;
269 hrs = (int) (now / 3600);
270 mins = (int) ((now - (hrs * 3600)) / 60);
271 sprintf(s, "%02d:%02d", hrs, mins);
272 strcat(out, s);
273 }
274
275
276 /*
277 * String substitution functions
278 */
279
280 static int cols = 0;
281 static int colsofar = 0;
282 static int blind = 0;
283 static int subwidth = 70;
284 static char *colstr = NULL;
285
286
287 /* Add string to colstr
288 */
289 static void subst_addcol(char *s, char *newcol)
290 {
291 char *p, *q;
292 int i, colwidth;
293
294 if ((newcol[0]) && (newcol[0] != '\377'))
295 colsofar++;
296 colstr = realloc(colstr, strlen(colstr) + strlen(newcol) +
297 (colstr[0] ? 2 : 1));
298 if ((newcol[0]) && (newcol[0] != '\377')) {
299 if (colstr[0])
300 strcat(colstr, "\377");
301 strcat(colstr, newcol);
302 }
303 if ((colsofar == cols) || ((newcol[0] == '\377') && (colstr[0]))) {
304 colsofar = 0;
305 strcpy(s, " ");
306 colwidth = (subwidth - 5) / cols;
307 q = colstr;
308 p = strchr(colstr, '\377');
309 while (p != NULL) {
310 *p = 0;
311 strcat(s, q);
312 for (i = strlen(q); i < colwidth; i++)
313 strcat(s, " ");
314 q = p + 1;
315 p = strchr(q, '\377');
316 }
317 strcat(s, q);
318 free(colstr);
319 colstr = calloc(1, 1);
320 }
321 }
322
323 /* Substitute %x codes in help files
324 *
325 * %B = bot nickname
326 * %V = version
327 * %C = list of channels i monitor
328 * %E = eggdrop banner
329 * %A = admin line
330 * %n = network name
331 * %T = current time ("14:15")
332 * %N = user's nickname
333 * %U = display system name if possible
334 * %{+xy} require flags to read this section
335 * %{-} turn of required flag matching only
336 * %{center} center this line
337 * %{cols=N} start of columnated section (indented)
338 * %{help=TOPIC} start a section for a particular command
339 * %{end} end of section
340 */
341 #define HELP_BUF_LEN 256
342 #define HELP_BOLD 1
343 #define HELP_REV 2
344 #define HELP_UNDER 4
345 #define HELP_FLASH 8
346
347 /* FIXME: Convert strncpy usage to strlcpy */
348 void help_subst(char *s, char *nick, struct flag_record *flags,
349 int isdcc, char *topic)
350 {
351 char xx[HELP_BUF_LEN + 1], sub[161], *current, *q, chr, *writeidx,
352 *readidx, *towrite;
353 struct chanset_t *chan;
354 int i, j, center = 0;
355 static int help_flags;
356 #ifdef HAVE_UNAME
357 struct utsname uname_info;
358 #endif
359
360 if (s == NULL) {
361 /* Used to reset substitutions */
362 blind = 0;
363 cols = 0;
364 subwidth = 70;
365 if (colstr != NULL)
366 free_null(colstr);
367 help_flags = isdcc;
368 return;
369 }
370 strlcpy(xx, s, sizeof xx);
371 readidx = xx;
372 writeidx = s;
373 current = strchr(readidx, '%');
374 while (current) {
375 /* Are we about to copy a chuck to the end of the buffer?
376 * if so return
377 */
378 if ((writeidx + (current - readidx)) >= (s + HELP_BUF_LEN)) {
379 strncpy(writeidx, readidx, (s + HELP_BUF_LEN) - writeidx);
380 s[HELP_BUF_LEN] = 0;
381 return;
382 }
383 chr = *(current + 1);
384 *current = 0;
385 if (!blind)
386 writeidx += my_strcpy(writeidx, readidx);
387 towrite = NULL;
388 switch (chr) {
389 case 'b':
390 if (help_flags & HELP_IRC) {
391 towrite = "\002";
392 } else if (help_flags & HELP_BOLD) {
393 help_flags &= ~HELP_BOLD;
394 towrite = "\033[0m";
395 } else {
396 help_flags |= HELP_BOLD;
397 towrite = "\033[1m";
398 }
399 break;
400 case 'v':
401 if (help_flags & HELP_IRC) {
402 towrite = "\026";
403 } else if (help_flags & HELP_REV) {
404 help_flags &= ~HELP_REV;
405 towrite = "\033[0m";
406 } else {
407 help_flags |= HELP_REV;
408 towrite = "\033[7m";
409 }
410 break;
411 case '_':
412 if (help_flags & HELP_IRC) {
413 towrite = "\037";
414 } else if (help_flags & HELP_UNDER) {
415 help_flags &= ~HELP_UNDER;
416 towrite = "\033[0m";
417 } else {
418 help_flags |= HELP_UNDER;
419 towrite = "\033[4m";
420 }
421 break;
422 case 'f':
423 if (help_flags & HELP_FLASH) {
424 if (help_flags & HELP_IRC) {
425 towrite = "\002\037";
426 } else {
427 towrite = "\033[0m";
428 }
429 help_flags &= ~HELP_FLASH;
430 } else {
431 help_flags |= HELP_FLASH;
432 if (help_flags & HELP_IRC) {
433 towrite = "\037\002";
434 } else {
435 towrite = "\033[5m";
436 }
437 }
438 break;
439 case 'U':
440 #ifdef HAVE_UNAME
441 if (uname(&uname_info) >= 0) {
442 snprintf(sub, sizeof sub, "%s %s", uname_info.sysname,
443 uname_info.release);
444 towrite = sub;
445 } else
446 #endif
447 towrite = "*UNKNOWN*";
448 break;
449 case 'B':
450 towrite = (isdcc ? myname : botname);
451 break;
452 case 'V':
453 towrite = ver;
454 break;
455 case 'E':
456 towrite = version;
457 break;
458 case 'A':
459 towrite = admin;
460 break;
461 case 'n':
462 towrite = network;
463 break;
464 case 'T':
465 strftime(sub, 6, "%H:%M", localtime(&now));
466 towrite = sub;
467 break;
468 case 'N':
469 towrite = strchr(nick, ':');
470 if (towrite)
471 towrite++;
472 else
473 towrite = nick;
474 break;
475 case 'C':
476 if (!blind)
477 for (chan = chanset; chan; chan = chan->next) {
478 if ((strlen(chan->dname) + writeidx + 2) >=
479 (s + HELP_BUF_LEN)) {
480 strncpy(writeidx, chan->dname, (s + HELP_BUF_LEN) - writeidx);
481 s[HELP_BUF_LEN] = 0;
482 return;
483 }
484 writeidx += my_strcpy(writeidx, chan->dname);
485 if (chan->next) {
486 *writeidx++ = ',';
487 *writeidx++ = ' ';
488 }
489 }
490 break;
491 case '{':
492 q = current;
493 current++;
494 while ((*current != '}') && (*current))
495 current++;
496 if (*current) {
497 *current = 0;
498 current--;
499 q += 2;
500 /* Now q is the string and p is where the rest of the fcn expects */
501 if (!strncmp(q, "help=", 5)) {
502 if (topic && strcasecmp(q + 5, topic))
503 blind |= 2;
504 else
505 blind &= ~2;
506 } else if (!(blind & 2)) {
507 if (q[0] == '+') {
508 struct flag_record fr =
509 {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
510
511 break_down_flags(q + 1, &fr, NULL);
512 if (!flagrec_ok(&fr, flags))
513 blind |= 1;
514 else
515 blind &= ~1;
516 } else if (q[0] == '-') {
517 blind &= ~1;
518 } else if (!strcasecmp(q, "end")) {
519 blind &= ~1;
520 subwidth = 70;
521 if (cols) {
522 sub[0] = 0;
523 subst_addcol(sub, "\377");
524 free_null(colstr);
525 cols = 0;
526 towrite = sub;
527 }
528 } else if (!strcasecmp(q, "center"))
529 center = 1;
530 else if (!strncmp(q, "cols=", 5)) {
531 char *r;
532
533 cols = atoi(q + 5);
534 colsofar = 0;
535 colstr = calloc(1, 1);
536 r = strchr(q + 5, '/');
537 if (r != NULL)
538 subwidth = atoi(r + 1);
539 }
540 }
541 } else
542 current = q; /* no } so ignore */
543 break;
544 default:
545 if (!blind) {
546 *writeidx++ = chr;
547 if (writeidx >= (s + HELP_BUF_LEN)) {
548 *writeidx = 0;
549 return;
550 }
551 }
552 }
553 if (towrite && !blind) {
554 if ((writeidx + strlen(towrite)) >= (s + HELP_BUF_LEN)) {
555 strncpy(writeidx, towrite, (s + HELP_BUF_LEN) - writeidx);
556 s[HELP_BUF_LEN] = 0;
557 return;
558 }
559 writeidx += my_strcpy(writeidx, towrite);
560 }
561 if (chr) {
562 readidx = current + 2;
563 current = strchr(readidx, '%');
564 } else {
565 readidx = current + 1;
566 current = NULL;
567 }
568 }
569 if (!blind) {
570 i = strlen(readidx);
571 if (i && ((writeidx + i) >= (s + HELP_BUF_LEN))) {
572 strncpy(writeidx, readidx, (s + HELP_BUF_LEN) - writeidx);
573 s[HELP_BUF_LEN] = 0;
574 return;
575 }
576 strcpy(writeidx, readidx);
577 } else
578 *writeidx = 0;
579 if (center) {
580 strcpy(xx, s);
581 i = 35 - (strlen(xx) / 2);
582 if (i > 0) {
583 s[0] = 0;
584 for (j = 0; j < i; j++)
585 s[j] = ' ';
586 strcpy(s + i, xx);
587 }
588 }
589 if (cols) {
590 strcpy(xx, s);
591 s[0] = 0;
592 subst_addcol(s, xx);
593 }
594 }
595
596 static void scan_help_file(struct help_ref *current, char *filename, int type)
597 {
598 FILE *f;
599 char s[HELP_BUF_LEN + 1], *p, *q;
600 struct help_list_t *list;
601
602 if (is_file(filename) && (f = fopen(filename, "r"))) {
603 while (!feof(f)) {
604 fgets(s, HELP_BUF_LEN, f);
605 if (!feof(f)) {
606 p = s;
607 while ((q = strstr(p, "%{help="))) {
608 q += 7;
609 if ((p = strchr(q, '}'))) {
610 *p = 0;
611 list = malloc(sizeof(struct help_list_t));
612
613 list->name = malloc(p - q + 1);
614 strcpy(list->name, q);
615 list->next = current->first;
616 list->type = type;
617 current->first = list;
618 p++;
619 } else
620 p = "";
621 }
622 }
623 }
624 fclose(f);
625 }
626 }
627
628 void add_help_reference(char *file)
629 {
630 char s[1024];
631 struct help_ref *current;
632
633 for (current = help_list; current; current = current->next)
634 if (!strcmp(current->name, file))
635 return; /* Already exists, can't re-add :P */
636 current = malloc(sizeof(struct help_ref));
637
638 current->name = strdup(file);
639 current->next = help_list;
640 current->first = NULL;
641 help_list = current;
642 snprintf(s, sizeof s, "%smsg/%s", helpdir, file);
643 scan_help_file(current, s, 0);
644 snprintf(s, sizeof s, "%s%s", helpdir, file);
645 scan_help_file(current, s, 1);
646 snprintf(s, sizeof s, "%sset/%s", helpdir, file);
647 scan_help_file(current, s, 2);
648 }
649
650 void rem_help_reference(char *file)
651 {
652 struct help_ref *current, *last = NULL;
653 struct help_list_t *item;
654
655 for (current = help_list; current; last = current, current = current->next)
656 if (!strcmp(current->name, file)) {
657 while ((item = current->first)) {
658 current->first = item->next;
659 free(item->name);
660 free(item);
661 }
662 free(current->name);
663 if (last)
664 last->next = current->next;
665 else
666 help_list = current->next;
667 free(current);
668 return;
669 }
670 }
671
672 void reload_help_data(void)
673 {
674 struct help_ref *current = help_list, *next;
675 struct help_list_t *item;
676
677 help_list = NULL;
678 while (current) {
679 while ((item = current->first)) {
680 current->first = item->next;
681 free(item->name);
682 free(item);
683 }
684 add_help_reference(current->name);
685 free(current->name);
686 next = current->next;
687 free(current);
688 current = next;
689 }
690 }
691
692 FILE *resolve_help(int dcc, char *file)
693 {
694
695 char s[1024];
696 FILE *f;
697 struct help_ref *current;
698 struct help_list_t *item;
699
700 /* Somewhere here goes the eventual substituation */
701 if (!(dcc & HELP_TEXT))
702 {
703 for (current = help_list; current; current = current->next)
704 for (item = current->first; item; item = item->next)
705 if (!strcmp(item->name, file)) {
706 if (!item->type && !dcc) {
707 snprintf(s, sizeof s, "%smsg/%s", helpdir, current->name);
708 if ((f = fopen(s, "r")))
709 return f;
710 } else if (dcc && item->type) {
711 if (item->type == 1)
712 snprintf(s, sizeof s, "%s%s", helpdir, current->name);
713 else
714 snprintf(s, sizeof s, "%sset/%s", helpdir, current->name);
715 if ((f = fopen(s, "r")))
716 return f;
717 }
718 }
719 /* No match was found, so we better return NULL */
720 return NULL;
721 }
722 /* Since we're not dealing with help files, we should just prepend the filename with textdir */
723 simple_sprintf(s, "%s%s", textdir, file);
724 if (is_file(s))
725 return fopen(s, "r");
726 else
727 return NULL;
728 }
729
730 void showhelp(char *who, char *file, struct flag_record *flags, int fl)
731 {
732 int lines = 0;
733 char s[HELP_BUF_LEN + 1];
734 FILE *f = resolve_help(fl, file);
735
736 if (f) {
737 help_subst(NULL, NULL, 0, HELP_IRC, NULL); /* Clear flags */
738 while (!feof(f)) {
739 fgets(s, HELP_BUF_LEN, f);
740 if (!feof(f)) {
741 if (s[strlen(s) - 1] == '\n')
742 s[strlen(s) - 1] = 0;
743 if (!s[0])
744 strcpy(s, " ");
745 help_subst(s, who, flags, 0, file);
746 if ((s[0]) && (strlen(s) > 1)) {
747 dprintf(DP_HELP, "NOTICE %s :%s\n", who, s);
748 lines++;
749 }
750 }
751 }
752 fclose(f);
753 }
754 if (!lines && !(fl & HELP_TEXT))
755 dprintf(DP_HELP, "NOTICE %s :%s\n", who, _("No help available on that."));
756 }
757
758 static int display_tellhelp(int idx, char *file, FILE *f,
759 struct flag_record *flags)
760 {
761 char s[HELP_BUF_LEN + 1];
762 int lines = 0;
763
764 if (f) {
765 help_subst(NULL, NULL, 0,
766 (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
767 while (!feof(f)) {
768 fgets(s, HELP_BUF_LEN, f);
769 if (!feof(f)) {
770 if (s[strlen(s) - 1] == '\n')
771 s[strlen(s) - 1] = 0;
772 if (!s[0])
773 strcpy(s, " ");
774 help_subst(s, dcc[idx].nick, flags, 1, file);
775 if (s[0]) {
776 dprintf(idx, "%s\n", s);
777 lines++;
778 }
779 }
780 }
781 fclose(f);
782 }
783 return lines;
784 }
785
786 void tellhelp(int idx, char *file, struct flag_record *flags, int fl)
787 {
788 int lines = 0;
789 FILE *f = resolve_help(HELP_DCC | fl, file);
790
791 if (f)
792 lines = display_tellhelp(idx, file, f, flags);
793 if (!lines && !(fl & HELP_TEXT))
794 dprintf(idx, "%s\n", _("No help available on that."));
795 }
796
797 /* Same as tellallhelp, just using wild_match instead of strcmp
798 */
799 void tellwildhelp(int idx, char *match, struct flag_record *flags)
800 {
801 struct help_ref *current;
802 struct help_list_t *item;
803 FILE *f;
804 char s[1024];
805
806 s[0] = '\0';
807 for (current = help_list; current; current = current->next)
808 for (item = current->first; item; item = item->next)
809 if (wild_match(match, item->name) && item->type) {
810 if (item->type == 1)
811 snprintf(s, sizeof s, "%s%s", helpdir, current->name);
812 else
813 snprintf(s, sizeof s, "%sset/%s", helpdir, current->name);
814 if ((f = fopen(s, "r")))
815 display_tellhelp(idx, item->name, f, flags);
816 }
817 if (!s[0])
818 dprintf(idx, _("No help available on that.\n"));
819 }
820
821 /* Same as tellwildhelp, just using strcmp instead of wild_match
822 */
823 void tellallhelp(int idx, char *match, struct flag_record *flags)
824 {
825 struct help_ref *current;
826 struct help_list_t *item;
827 FILE *f;
828 char s[1024];
829
830 s[0] = '\0';
831 for (current = help_list; current; current = current->next)
832 for (item = current->first; item; item = item->next)
833 if (!strcmp(match, item->name) && item->type) {
834
835 if (item->type == 1)
836 snprintf(s, sizeof s, "%s%s", helpdir, current->name);
837 else
838 snprintf(s, sizeof s, "%sset/%s", helpdir, current->name);
839 if ((f = fopen(s, "r")))
840 display_tellhelp(idx, item->name, f, flags);
841 }
842 if (!s[0])
843 dprintf(idx, _("No help available on that.\n"));
844 }
845
846 /* Substitute vars in a lang text to dcc chatter
847 */
848 void sub_lang(int idx, char *text)
849 {
850 char s[1024];
851 struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
852
853 get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
854 help_subst(NULL, NULL, 0,
855 (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
856 strlcpy(s, text, sizeof s);
857 if (s[strlen(s) - 1] == '\n')
858 s[strlen(s) - 1] = 0;
859 if (!s[0])
860 strcpy(s, " ");
861 help_subst(s, dcc[idx].nick, &fr, 1, myname);
862 if (s[0])
863 dprintf(idx, "%s\n", s);
864 }
865
866 /* Show motd to dcc chatter
867 */
868 void show_motd(int idx)
869 {
870 FILE *vv;
871 char s[1024];
872 struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
873
874 if (!is_file(motdfile))
875 return;
876
877 vv = fopen(motdfile, "r");
878 if (!vv)
879 return;
880
881 get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
882 dprintf(idx, "\n");
883 /* reset the help_subst variables to their defaults */
884 help_subst(NULL, NULL, 0,
885 (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
886 while (!feof(vv)) {
887 fgets(s, 120, vv);
888 if (!feof(vv)) {
889 if (s[strlen(s) - 1] == '\n')
890 s[strlen(s) - 1] = 0;
891 if (!s[0])
892 strcpy(s, " ");
893 help_subst(s, dcc[idx].nick, &fr, 1, myname);
894 if (s[0])
895 dprintf(idx, "%s\n", s);
896 }
897 }
898 fclose(vv);
899 dprintf(idx, "\n");
900 }
901
902 /* Show banner to telnet user (very simialer to show_motd)
903 */
904 void show_telnet_banner(int idx) {
905 FILE *vv;
906 char s[1024];
907 struct flag_record fr = {FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0};
908
909 if (!is_file(bannerfile))
910 return;
911
912 vv = fopen(bannerfile, "r");
913 if (!vv)
914 return;
915
916 get_user_flagrec(dcc[idx].user, &fr,dcc[idx].u.chat->con_chan);
917 /* reset the help_subst variables to their defaults */
918 help_subst(NULL, NULL, 0, 0, NULL);
919 while(!feof(vv)) {
920 fgets(s, 120, vv);
921 if (!feof(vv)) {
922 if (!s[0])
923 strcpy(s, " \n");
924 help_subst(s, dcc[idx].nick, &fr, 1, myname);
925 dprintf(idx, "%s", s);
926 }
927 }
928 fclose(vv);
929 }
930
931 /* This will return a pointer to the first character after the @ in the
932 * string given it. Possibly it's time to think about a regexp library
933 * for eggdrop...
934 */
935 char *extracthostname(char *hostmask)
936 {
937 char *p = strrchr(hostmask, '@');
938 return p ? p + 1 : "";
939 }
940
941 /* Create a string with random letters and digits
942 */
943 void make_rand_str(char *s, int len)
944 {
945 int j;
946
947 for (j = 0; j < len; j++) {
948 if (random() % 3 == 0)
949 s[j] = '0' + (random() % 10);
950 else
951 s[j] = 'a' + (random() % 26);
952 }
953 s[len] = 0;
954 }
955
956 /* Convert an octal string into a decimal integer value. If the string
957 * is empty or contains non-octal characters, -1 is returned.
958 */
959 int oatoi(const char *octal)
960 {
961 register int i;
962
963 if (!*octal)
964 return -1;
965 for (i = 0; ((*octal >= '0') && (*octal <= '7')); octal++)
966 i = (i * 8) + (*octal - '0');
967 if (*octal)
968 return -1;
969 return i;
970 }
971
972 /* Kills the bot. s1 is the reason shown to other bots,
973 * s2 the reason shown on the partyline. (Sup 25Jul2001)
974 */
975 void kill_bot(char *s1, char *s2)
976 {
977 call_hook(HOOK_DIE);
978 chatout("*** %s\n", s1);
979 write_userfile(-1);
980 fatal(s2, 0);
981 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23