00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031 #include "main.h"
00032 #include <sys/stat.h>
00033 #include <unistd.h>
00034 #include <fcntl.h>
00035 #include <ctype.h>
00036 #include "chan.h"
00037 #include "tandem.h"
00038 #include "modules.h"
00039
00040 #ifdef HAVE_UNAME
00041 # include <sys/utsname.h>
00042 #endif
00043
00044 #include "stat.h"
00045
00046 extern struct dcc_t *dcc;
00047 extern struct chanset_t *chanset;
00048
00049 extern char helpdir[], version[], origbotname[], botname[], admin[], network[],
00050 motdfile[], ver[], botnetnick[], bannerfile[], logfile_suffix[],
00051 textdir[];
00052 extern int backgrd, con_chan, term_z, use_stderr, dcc_total, keep_all_logs,
00053 quick_logs, strict_host;
00054
00055 extern time_t now;
00056 extern Tcl_Interp *interp;
00057
00058 char log_ts[32] = "[%H:%M:%S]";
00059
00060 int shtime = 1;
00061 log_t *logs = 0;
00062 int max_logs = 5;
00063 int max_logsize = 0;
00064 int raw_log = 0;
00065
00066 int conmask = LOG_MODES | LOG_CMDS | LOG_MISC;
00067
00068 struct help_list_t {
00069 struct help_list_t *next;
00070 char *name;
00071 int type;
00072 };
00073
00074 static struct help_ref {
00075 char *name;
00076 struct help_list_t *first;
00077 struct help_ref *next;
00078 } *help_list = NULL;
00079
00080
00081
00082
00083 int expmem_misc()
00084 {
00085 struct help_ref *current;
00086 struct help_list_t *item;
00087 int tot = 0;
00088
00089 for (current = help_list; current; current = current->next) {
00090 tot += sizeof(struct help_ref) + strlen(current->name) + 1;
00091
00092 for (item = current->first; item; item = item->next)
00093 tot += sizeof(struct help_list_t) + strlen(item->name) + 1;
00094 }
00095 return tot + (max_logs * sizeof(log_t));
00096 }
00097
00098 void init_misc()
00099 {
00100 static int last = 0;
00101
00102 if (max_logs < 1)
00103 max_logs = 1;
00104 if (logs)
00105 logs = nrealloc(logs, max_logs * sizeof(log_t));
00106 else
00107 logs = nmalloc(max_logs * sizeof(log_t));
00108 for (; last < max_logs; last++) {
00109 logs[last].filename = logs[last].chname = NULL;
00110 logs[last].mask = 0;
00111 logs[last].f = NULL;
00112
00113 logs[last].szlast[0] = 0;
00114 logs[last].repeats = 0;
00115
00116 logs[last].flags = 0;
00117 }
00118 }
00119
00120
00121
00122
00123
00124
00125
00126
00127 int is_file(const char *s)
00128 {
00129 struct stat ss;
00130 int i = stat(s, &ss);
00131
00132 if (i < 0)
00133 return 0;
00134 if ((ss.st_mode & S_IFREG) || (ss.st_mode & S_IFLNK))
00135 return 1;
00136 return 0;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158 int egg_strcatn(char *dst, const char *src, size_t max)
00159 {
00160 size_t tmpmax = 0;
00161
00162
00163 while (*dst && max > 0) {
00164 dst++;
00165 max--;
00166 }
00167
00168
00169
00170
00171 tmpmax = max;
00172
00173
00174 while (*src && max > 1) {
00175 *dst++ = *src++;
00176 max--;
00177 }
00178
00179
00180 *dst = 0;
00181
00182
00183
00184
00185 return tmpmax - max;
00186 }
00187
00188 int my_strcpy(register char *a, register char *b)
00189 {
00190 register char *c = b;
00191
00192 while (*b)
00193 *a++ = *b++;
00194 *a = *b;
00195 return b - c;
00196 }
00197
00198
00199
00200 void splitc(char *first, char *rest, char divider)
00201 {
00202 char *p = strchr(rest, divider);
00203
00204 if (p == NULL) {
00205 if (first != rest && first)
00206 first[0] = 0;
00207 return;
00208 }
00209 *p = 0;
00210 if (first != NULL)
00211 strcpy(first, rest);
00212 if (first != rest)
00213
00214
00215
00216
00217 strcpy(rest, p + 1);
00218 }
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231 void splitcn(char *first, char *rest, char divider, size_t max)
00232 {
00233 char *p = strchr(rest, divider);
00234
00235 if (p == NULL) {
00236 if (first != rest && first)
00237 first[0] = 0;
00238 return;
00239 }
00240 *p = 0;
00241 if (first != NULL)
00242 strncpyz(first, rest, max);
00243 if (first != rest)
00244
00245
00246
00247
00248 strcpy(rest, p + 1);
00249 }
00250
00251 char *splitnick(char **blah)
00252 {
00253 char *p = strchr(*blah, '!'), *q = *blah;
00254
00255 if (p) {
00256 *p = 0;
00257 *blah = p + 1;
00258 return q;
00259 }
00260 return "";
00261 }
00262
00263 void remove_crlf(char **line)
00264 {
00265 char *p;
00266
00267 p = strchr(*line, '\n');
00268 if (p != NULL)
00269 *p = 0;
00270 p = strchr(*line, '\r');
00271 if (p != NULL)
00272 *p = 0;
00273 }
00274
00275 char *newsplit(char **rest)
00276 {
00277 register char *o, *r;
00278
00279 if (!rest)
00280 return "";
00281 o = *rest;
00282 while (*o == ' ')
00283 o++;
00284 r = o;
00285 while (*o && (*o != ' '))
00286 o++;
00287 if (*o)
00288 *o++ = 0;
00289 *rest = o;
00290 return r;
00291 }
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321
00322 void maskaddr(const char *s, char *nw, int type)
00323 {
00324 int d = type % 5, num = 1;
00325 register char *p, *u = 0, *h = 0, *ss;
00326
00327
00328 ss = (char *)s;
00329 u = strchr(s, '!');
00330 if (u)
00331 h = strchr(u, '@');
00332 if (!h){
00333 h = strchr(s, '@');
00334 u = 0;
00335 }
00336
00337
00338 if (!u || (type % 10) < 5)
00339 *nw++ = '*';
00340 else {
00341 strncpy(nw, s, u - s);
00342 nw += u - s;
00343 }
00344 *nw++ = '!';
00345
00346
00347 u = (u ? u + 1 : ss);
00348 if (!h || (d == 2) || (d == 4))
00349 *nw++ = '*';
00350 else {
00351 if (d) {
00352 *nw++ = '*';
00353 if (strchr("~+-^=", *u))
00354 u++;
00355 }
00356 strncpy(nw, u, h - u);
00357 nw += h - u;
00358 }
00359 *nw++ = '@';
00360
00361
00362 h = (h ? h + 1 : ss);
00363 for (p = h; *p; p++)
00364 if ((*p > '9' || *p < '0') && *p != '.') {
00365 num = 0;
00366 break;
00367 }
00368 p = strrchr(h, ':');
00369
00370 if (p && d > 2) {
00371 if ((u = strrchr(p, '.')))
00372 p = u;
00373 strncpy(nw, h, ++p - h);
00374 nw += p - h;
00375 strcpy(nw, "*");
00376 } else if (!p && !num && type >= 10) {
00377
00378
00379 num = 0;
00380 for (p = h; *p; p++) {
00381 if (*p < '0' || *p > '9') {
00382 *nw++ = *p;
00383 num = 0;
00384 } else {
00385 if (type < 20)
00386 *nw++ = '?';
00387 else if (!num) {
00388 *nw++ = '*';
00389 num = 1;
00390
00391 }
00392 }
00393 }
00394 *nw = 0;
00395 } else if (d > 2 && (p = strrchr(h, '.'))) {
00396 if (num) {
00397 strncpy(nw, h, p - h);
00398 nw += p - h;
00399 strcpy(nw, ".*");
00400 return;
00401 }
00402 for (u = h, d = 0; (u = strchr(++u, '.')); d++);
00403 if (d < 2) {
00404 strcpy(nw, h);
00405 return;
00406 }
00407 u = strchr(h, '.');
00408 if (d > 3 || (d == 3 && strlen(p) > 3))
00409 u = strchr(++u, '.');
00410 sprintf(nw, "*%s", u);
00411 } else if (!*h)
00412
00413 strcpy(nw, "*");
00414 else
00415 strcpy(nw, h);
00416 }
00417
00418
00419
00420 void dumplots(int idx, const char *prefix, const char *data)
00421 {
00422 const char *p = data, *q, *n;
00423 const int max_data_len = 500 - strlen(prefix);
00424
00425 if (!*data) {
00426 dprintf(idx, "%s\n", prefix);
00427 return;
00428 }
00429 while (strlen(p) > max_data_len) {
00430 q = p + max_data_len;
00431
00432 n = strchr(p, '\n');
00433 if (n && n < q) {
00434
00435 dprintf(idx, "%s%.*s\n", prefix, n - p, p);
00436 p = n + 1;
00437 } else {
00438
00439 while (*q != ' ' && q != p)
00440 q--;
00441 if (q == p)
00442 q = p + max_data_len;
00443 dprintf(idx, "%s%.*s\n", prefix, q - p, p);
00444 p = q;
00445 if (*q == ' ')
00446 p++;
00447 }
00448 }
00449
00450 n = strchr(p, '\n');
00451 while (n) {
00452 dprintf(idx, "%s%.*s\n", prefix, n - p, p);
00453 p = n + 1;
00454 n = strchr(p, '\n');
00455 }
00456 if (*p)
00457 dprintf(idx, "%s%s\n", prefix, p);
00458 }
00459
00460
00461
00462
00463 void daysago(time_t now, time_t then, char *out)
00464 {
00465 if (now - then > 86400) {
00466 int days = (now - then) / 86400;
00467
00468 sprintf(out, "%d day%s ago", days, (days == 1) ? "" : "s");
00469 return;
00470 }
00471 egg_strftime(out, 6, "%H:%M", localtime(&then));
00472 }
00473
00474
00475
00476
00477 void days(time_t now, time_t then, char *out)
00478 {
00479 if (now - then > 86400) {
00480 int days = (now - then) / 86400;
00481
00482 sprintf(out, "in %d day%s", days, (days == 1) ? "" : "s");
00483 return;
00484 }
00485 egg_strftime(out, 9, "at %H:%M", localtime(&now));
00486 }
00487
00488
00489
00490
00491 void daysdur(time_t now, time_t then, char *out)
00492 {
00493 char s[81];
00494 int hrs, mins;
00495
00496 if (now - then > 86400) {
00497 int days = (now - then) / 86400;
00498
00499 sprintf(out, "for %d day%s", days, (days == 1) ? "" : "s");
00500 return;
00501 }
00502 strcpy(out, "for ");
00503 now -= then;
00504 hrs = (int) (now / 3600);
00505 mins = (int) ((now - (hrs * 3600)) / 60);
00506 sprintf(s, "%02d:%02d", hrs, mins);
00507 strcat(out, s);
00508 }
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518 void putlog EGG_VARARGS_DEF(int, arg1)
00519 {
00520 static int inhere = 0;
00521 int i, type, tsl = 0;
00522 char *format, *chname, s[LOGLINELEN], s1[256], *out, ct[81], *s2, stamp[34];
00523 va_list va;
00524 time_t now2 = time(NULL);
00525 struct tm *t = localtime(&now2);
00526
00527 type = EGG_VARARGS_START(int, arg1, va);
00528 chname = va_arg(va, char *);
00529 format = va_arg(va, char *);
00530
00531
00532 t = localtime(&now2);
00533 if (shtime) {
00534 egg_strftime(stamp, sizeof(stamp) - 2, log_ts, t);
00535 strcat(stamp, " ");
00536 tsl = strlen(stamp);
00537 }
00538 else
00539 *stamp = '\0';
00540
00541
00542 out = s + tsl;
00543
00544
00545
00546 egg_vsnprintf(out, LOGLINEMAX - tsl, format, va);
00547 out[LOGLINEMAX - tsl] = 0;
00548 if (keep_all_logs) {
00549 if (!logfile_suffix[0])
00550 egg_strftime(ct, 12, ".%d%b%Y", t);
00551 else {
00552 egg_strftime(ct, 80, logfile_suffix, t);
00553 ct[80] = 0;
00554 s2 = ct;
00555
00556 while (s2[0]) {
00557 if (s2[0] == ' ')
00558 s2[0] = '_';
00559 s2++;
00560 }
00561 }
00562 }
00563
00564 if (!inhere && H_log) {
00565 inhere = 1;
00566 check_tcl_log(type, chname, out);
00567 inhere = 0;
00568 }
00569
00570 if (out[0] && shtime) {
00571 strncpy(s, stamp, tsl);
00572 out = s;
00573 }
00574 strcat(out, "\n");
00575 if (!use_stderr) {
00576 for (i = 0; i < max_logs; i++) {
00577 if ((logs[i].filename != NULL) && (logs[i].mask & type) &&
00578 ((chname[0] == '*') || (logs[i].chname[0] == '*') ||
00579 (!rfc_casecmp(chname, logs[i].chname)))) {
00580 if (logs[i].f == NULL) {
00581
00582 if (keep_all_logs) {
00583 egg_snprintf(s1, 256, "%s%s", logs[i].filename, ct);
00584 logs[i].f = fopen(s1, "a+");
00585 } else
00586 logs[i].f = fopen(logs[i].filename, "a+");
00587 }
00588 if (logs[i].f != NULL) {
00589
00590
00591
00592 if (!egg_strcasecmp(out + tsl, logs[i].szlast))
00593
00594 logs[i].repeats++;
00595 else {
00596
00597
00598
00599 if (logs[i].repeats > 0) {
00600
00601
00602
00603
00604 fprintf(logs[i].f, stamp);
00605 fprintf(logs[i].f, MISC_LOGREPEAT, logs[i].repeats);
00606 logs[i].repeats = 0;
00607
00608
00609
00610 }
00611 fputs(out, logs[i].f);
00612 strncpyz(logs[i].szlast, out + tsl, LOGLINEMAX);
00613 }
00614 }
00615 }
00616 }
00617 }
00618 for (i = 0; i < dcc_total; i++) {
00619 if ((dcc[i].type == &DCC_CHAT) && (dcc[i].u.chat->con_flags & type)) {
00620 if ((chname[0] == '*') || (dcc[i].u.chat->con_chan[0] == '*') ||
00621 !rfc_casecmp(chname, dcc[i].u.chat->con_chan)) {
00622 dprintf(i, "%s", out);
00623 }
00624 }
00625 }
00626 if (!backgrd && !con_chan && !term_z)
00627 dprintf(DP_STDOUT, "%s", out);
00628 else if ((type & LOG_MISC) && use_stderr) {
00629 if (shtime)
00630 out += tsl;
00631 dprintf(DP_STDERR, "%s", s);
00632 }
00633 va_end(va);
00634 }
00635
00636
00637
00638
00639 void logsuffix_change(char *s)
00640 {
00641 int i;
00642 char *s2 = logfile_suffix;
00643
00644
00645 if (s && s2 && !strcmp(s, s2))
00646 return;
00647
00648 debug0("Logfile suffix changed. Closing all open logs.");
00649 strcpy(logfile_suffix, s);
00650 while (s2[0]) {
00651 if (s2[0] == ' ')
00652 s2[0] = '_';
00653 s2++;
00654 }
00655 for (i = 0; i < max_logs; i++) {
00656 if (logs[i].f) {
00657 fflush(logs[i].f);
00658 fclose(logs[i].f);
00659 logs[i].f = NULL;
00660 }
00661 }
00662 }
00663
00664 void check_logsize()
00665 {
00666 struct stat ss;
00667 int i;
00668
00669
00670 char buf[1024];
00671
00672 if (!keep_all_logs && max_logsize > 0) {
00673 for (i = 0; i < max_logs; i++) {
00674 if (logs[i].filename) {
00675 if (stat(logs[i].filename, &ss) != 0) {
00676 break;
00677 }
00678 if ((ss.st_size >> 10) > max_logsize) {
00679 if (logs[i].f) {
00680
00681 putlog(LOG_MISC, "*", MISC_CLOGS, logs[i].filename, ss.st_size);
00682 fflush(logs[i].f);
00683 fclose(logs[i].f);
00684 logs[i].f = NULL;
00685 }
00686
00687 egg_snprintf(buf, sizeof buf, "%s.yesterday", logs[i].filename);
00688 buf[1023] = 0;
00689 unlink(buf);
00690 movefile(logs[i].filename, buf);
00691 }
00692 }
00693 }
00694 }
00695 }
00696
00697
00698
00699 void flushlogs()
00700 {
00701 int i;
00702
00703
00704 if (!logs)
00705 return;
00706
00707
00708
00709
00710 for (i = 0; i < max_logs; i++) {
00711 if (logs[i].f != NULL) {
00712 if ((logs[i].repeats > 0) && quick_logs) {
00713
00714
00715
00716 char stamp[33];
00717
00718 egg_strftime(stamp, sizeof(stamp) - 1, log_ts, localtime(&now));
00719 fprintf(logs[i].f, "%s ", stamp);
00720 fprintf(logs[i].f, MISC_LOGREPEAT, logs[i].repeats);
00721
00722 logs[i].repeats = 0;
00723 }
00724 fflush(logs[i].f);
00725 }
00726 }
00727 }
00728
00729
00730
00731
00732
00733
00734 static int cols = 0;
00735 static int colsofar = 0;
00736 static int blind = 0;
00737 static int subwidth = 70;
00738 static char *colstr = NULL;
00739
00740
00741
00742
00743 static void subst_addcol(char *s, char *newcol)
00744 {
00745 char *p, *q;
00746 int i, colwidth;
00747
00748 if ((newcol[0]) && (newcol[0] != '\377'))
00749 colsofar++;
00750 colstr = nrealloc(colstr, strlen(colstr) + strlen(newcol) +
00751 (colstr[0] ? 2 : 1));
00752 if ((newcol[0]) && (newcol[0] != '\377')) {
00753 if (colstr[0])
00754 strcat(colstr, "\377");
00755 strcat(colstr, newcol);
00756 }
00757 if ((colsofar == cols) || ((newcol[0] == '\377') && (colstr[0]))) {
00758 colsofar = 0;
00759 strcpy(s, " ");
00760 colwidth = (subwidth - 5) / cols;
00761 q = colstr;
00762 p = strchr(colstr, '\377');
00763 while (p != NULL) {
00764 *p = 0;
00765 strcat(s, q);
00766 for (i = strlen(q); i < colwidth; i++)
00767 strcat(s, " ");
00768 q = p + 1;
00769 p = strchr(q, '\377');
00770 }
00771 strcat(s, q);
00772 nfree(colstr);
00773 colstr = nmalloc(1);
00774 colstr[0] = 0;
00775 }
00776 }
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796 #define HELP_BUF_LEN 256
00797 #define HELP_BOLD 1
00798 #define HELP_REV 2
00799 #define HELP_UNDER 4
00800 #define HELP_FLASH 8
00801
00802 void help_subst(char *s, char *nick, struct flag_record *flags,
00803 int isdcc, char *topic)
00804 {
00805 char xx[HELP_BUF_LEN + 1], sub[161], *current, *q, chr, *writeidx,
00806 *readidx, *towrite;
00807 struct chanset_t *chan;
00808 int i, j, center = 0;
00809 static int help_flags;
00810
00811 #ifdef HAVE_UNAME
00812 struct utsname uname_info;
00813 #endif
00814
00815 if (s == NULL) {
00816
00817 blind = 0;
00818 cols = 0;
00819 subwidth = 70;
00820 if (colstr != NULL) {
00821 nfree(colstr);
00822 colstr = NULL;
00823 }
00824 help_flags = isdcc;
00825 return;
00826 }
00827 strncpyz(xx, s, sizeof xx);
00828 readidx = xx;
00829 writeidx = s;
00830 current = strchr(readidx, '%');
00831 while (current) {
00832
00833
00834
00835 if ((writeidx + (current - readidx)) >= (s + HELP_BUF_LEN)) {
00836 strncpy(writeidx, readidx, (s + HELP_BUF_LEN) - writeidx);
00837 s[HELP_BUF_LEN] = 0;
00838 return;
00839 }
00840 chr = *(current + 1);
00841 *current = 0;
00842 if (!blind)
00843 writeidx += my_strcpy(writeidx, readidx);
00844 towrite = NULL;
00845 switch (chr) {
00846 case 'b':
00847 if (glob_hilite(*flags)) {
00848 if (help_flags & HELP_IRC) {
00849 towrite = "\002";
00850 } else if (help_flags & HELP_BOLD) {
00851 help_flags &= ~HELP_BOLD;
00852 towrite = "\033[0m";
00853 } else {
00854 help_flags |= HELP_BOLD;
00855 towrite = "\033[1m";
00856 }
00857 }
00858 break;
00859 case 'v':
00860 if (glob_hilite(*flags)) {
00861 if (help_flags & HELP_IRC) {
00862 towrite = "\026";
00863 } else if (help_flags & HELP_REV) {
00864 help_flags &= ~HELP_REV;
00865 towrite = "\033[0m";
00866 } else {
00867 help_flags |= HELP_REV;
00868 towrite = "\033[7m";
00869 }
00870 }
00871 break;
00872 case '_':
00873 if (glob_hilite(*flags)) {
00874 if (help_flags & HELP_IRC) {
00875 towrite = "\037";
00876 } else if (help_flags & HELP_UNDER) {
00877 help_flags &= ~HELP_UNDER;
00878 towrite = "\033[0m";
00879 } else {
00880 help_flags |= HELP_UNDER;
00881 towrite = "\033[4m";
00882 }
00883 }
00884 break;
00885 case 'f':
00886 if (glob_hilite(*flags)) {
00887 if (help_flags & HELP_FLASH) {
00888 if (help_flags & HELP_IRC)
00889 towrite = "\002\037";
00890 else
00891 towrite = "\033[0m";
00892 help_flags &= ~HELP_FLASH;
00893 } else {
00894 help_flags |= HELP_FLASH;
00895 if (help_flags & HELP_IRC)
00896 towrite = "\037\002";
00897 else
00898 towrite = "\033[5m";
00899 }
00900 }
00901 break;
00902 case 'U':
00903 #ifdef HAVE_UNAME
00904 if (uname(&uname_info) >= 0) {
00905 egg_snprintf(sub, sizeof sub, "%s %s", uname_info.sysname,
00906 uname_info.release);
00907 towrite = sub;
00908 } else
00909 #endif
00910 towrite = "*UNKNOWN*";
00911 break;
00912 case 'B':
00913 towrite = (isdcc ? botnetnick : botname);
00914 break;
00915 case 'V':
00916 towrite = ver;
00917 break;
00918 case 'E':
00919 towrite = version;
00920 break;
00921 case 'A':
00922 towrite = admin;
00923 break;
00924 case 'n':
00925 towrite = network;
00926 break;
00927 case 'T':
00928 egg_strftime(sub, 6, "%H:%M", localtime(&now));
00929 towrite = sub;
00930 break;
00931 case 'N':
00932 towrite = strchr(nick, ':');
00933 if (towrite)
00934 towrite++;
00935 else
00936 towrite = nick;
00937 break;
00938 case 'C':
00939 if (!blind)
00940 for (chan = chanset; chan; chan = chan->next) {
00941 if ((strlen(chan->dname) + writeidx + 2) >= (s + HELP_BUF_LEN)) {
00942 strncpy(writeidx, chan->dname, (s + HELP_BUF_LEN) - writeidx);
00943 s[HELP_BUF_LEN] = 0;
00944 return;
00945 }
00946 writeidx += my_strcpy(writeidx, chan->dname);
00947 if (chan->next) {
00948 *writeidx++ = ',';
00949 *writeidx++ = ' ';
00950 }
00951 }
00952 break;
00953 case '{':
00954 q = current;
00955 current++;
00956 while ((*current != '}') && (*current))
00957 current++;
00958 if (*current) {
00959 *current = 0;
00960 current--;
00961 q += 2;
00962
00963 if (!strncmp(q, "help=", 5)) {
00964 if (topic && egg_strcasecmp(q + 5, topic))
00965 blind |= 2;
00966 else
00967 blind &= ~2;
00968 } else if (!(blind & 2)) {
00969 if (q[0] == '+') {
00970 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
00971
00972 break_down_flags(q + 1, &fr, NULL);
00973
00974
00975
00976
00977 if (!flagrec_eq(&fr, flags))
00978 blind |= 1;
00979 else
00980 blind &= ~1;
00981 } else if (q[0] == '-')
00982 blind &= ~1;
00983 else if (!egg_strcasecmp(q, "end")) {
00984 blind &= ~1;
00985 subwidth = 70;
00986 if (cols) {
00987 sub[0] = 0;
00988 subst_addcol(sub, "\377");
00989 nfree(colstr);
00990 colstr = NULL;
00991 cols = 0;
00992 towrite = sub;
00993 }
00994 } else if (!egg_strcasecmp(q, "center"))
00995 center = 1;
00996 else if (!strncmp(q, "cols=", 5)) {
00997 char *r;
00998
00999 cols = atoi(q + 5);
01000 colsofar = 0;
01001 colstr = nmalloc(1);
01002 colstr[0] = 0;
01003 r = strchr(q + 5, '/');
01004 if (r != NULL)
01005 subwidth = atoi(r + 1);
01006 }
01007 }
01008 } else
01009 current = q;
01010 break;
01011 default:
01012 if (!blind) {
01013 *writeidx++ = chr;
01014 if (writeidx >= (s + HELP_BUF_LEN)) {
01015 *writeidx = 0;
01016 return;
01017 }
01018 }
01019 }
01020 if (towrite && !blind) {
01021 if ((writeidx + strlen(towrite)) >= (s + HELP_BUF_LEN)) {
01022 strncpy(writeidx, towrite, (s + HELP_BUF_LEN) - writeidx);
01023 s[HELP_BUF_LEN] = 0;
01024 return;
01025 }
01026 writeidx += my_strcpy(writeidx, towrite);
01027 }
01028 if (chr) {
01029 readidx = current + 2;
01030 current = strchr(readidx, '%');
01031 } else {
01032 readidx = current + 1;
01033 current = NULL;
01034 }
01035 }
01036 if (!blind) {
01037 i = strlen(readidx);
01038 if (i && ((writeidx + i) >= (s + HELP_BUF_LEN))) {
01039 strncpy(writeidx, readidx, (s + HELP_BUF_LEN) - writeidx);
01040 s[HELP_BUF_LEN] = 0;
01041 return;
01042 }
01043 strcpy(writeidx, readidx);
01044 } else
01045 *writeidx = 0;
01046 if (center) {
01047 strcpy(xx, s);
01048 i = 35 - (strlen(xx) / 2);
01049 if (i > 0) {
01050 s[0] = 0;
01051 for (j = 0; j < i; j++)
01052 s[j] = ' ';
01053 strcpy(s + i, xx);
01054 }
01055 }
01056 if (cols) {
01057 strcpy(xx, s);
01058 s[0] = 0;
01059 subst_addcol(s, xx);
01060 }
01061 }
01062
01063 static void scan_help_file(struct help_ref *current, char *filename, int type)
01064 {
01065 FILE *f;
01066 char s[HELP_BUF_LEN + 1], *p, *q;
01067 struct help_list_t *list;
01068
01069 if (is_file(filename) && (f = fopen(filename, "r"))) {
01070 while (!feof(f)) {
01071 fgets(s, HELP_BUF_LEN, f);
01072 if (!feof(f)) {
01073 p = s;
01074 while ((q = strstr(p, "%{help="))) {
01075 q += 7;
01076 if ((p = strchr(q, '}'))) {
01077 *p = 0;
01078 list = nmalloc(sizeof *list);
01079
01080 list->name = nmalloc(p - q + 1);
01081 strcpy(list->name, q);
01082 list->next = current->first;
01083 list->type = type;
01084 current->first = list;
01085 p++;
01086 } else
01087 p = "";
01088 }
01089 }
01090 }
01091 fclose(f);
01092 }
01093 }
01094
01095 void add_help_reference(char *file)
01096 {
01097 char s[1024];
01098 struct help_ref *current;
01099
01100 for (current = help_list; current; current = current->next)
01101 if (!strcmp(current->name, file))
01102 return;
01103 current = nmalloc(sizeof *current);
01104
01105 current->name = nmalloc(strlen(file) + 1);
01106 strcpy(current->name, file);
01107 current->next = help_list;
01108 current->first = NULL;
01109 help_list = current;
01110 egg_snprintf(s, sizeof s, "%smsg/%s", helpdir, file);
01111 scan_help_file(current, s, 0);
01112 egg_snprintf(s, sizeof s, "%s%s", helpdir, file);
01113 scan_help_file(current, s, 1);
01114 egg_snprintf(s, sizeof s, "%sset/%s", helpdir, file);
01115 scan_help_file(current, s, 2);
01116 }
01117
01118 void rem_help_reference(char *file)
01119 {
01120 struct help_ref *current, *last = NULL;
01121 struct help_list_t *item;
01122
01123 for (current = help_list; current; last = current, current = current->next)
01124 if (!strcmp(current->name, file)) {
01125 while ((item = current->first)) {
01126 current->first = item->next;
01127 nfree(item->name);
01128 nfree(item);
01129 }
01130 nfree(current->name);
01131 if (last)
01132 last->next = current->next;
01133 else
01134 help_list = current->next;
01135 nfree(current);
01136 return;
01137 }
01138 }
01139
01140 void reload_help_data(void)
01141 {
01142 struct help_ref *current = help_list, *next;
01143 struct help_list_t *item;
01144
01145 help_list = NULL;
01146 while (current) {
01147 while ((item = current->first)) {
01148 current->first = item->next;
01149 nfree(item->name);
01150 nfree(item);
01151 }
01152 add_help_reference(current->name);
01153 nfree(current->name);
01154 next = current->next;
01155 nfree(current);
01156 current = next;
01157 }
01158 }
01159
01160 void debug_help(int idx)
01161 {
01162 struct help_ref *current;
01163 struct help_list_t *item;
01164
01165 for (current = help_list; current; current = current->next) {
01166 dprintf(idx, "HELP FILE(S): %s\n", current->name);
01167 for (item = current->first; item; item = item->next) {
01168 dprintf(idx, " %s (%s)\n", item->name, (item->type == 0) ? "msg/" :
01169 (item->type == 1) ? "" : "set/");
01170 }
01171 }
01172 }
01173
01174 FILE *resolve_help(int dcc, char *file)
01175 {
01176
01177 char s[1024];
01178 FILE *f;
01179 struct help_ref *current;
01180 struct help_list_t *item;
01181
01182
01183 if (!(dcc & HELP_TEXT)) {
01184 for (current = help_list; current; current = current->next)
01185 for (item = current->first; item; item = item->next)
01186 if (!strcmp(item->name, file)) {
01187 if (!item->type && !dcc) {
01188 egg_snprintf(s, sizeof s, "%smsg/%s", helpdir, current->name);
01189 if ((f = fopen(s, "r")))
01190 return f;
01191 } else if (dcc && item->type) {
01192 if (item->type == 1)
01193 egg_snprintf(s, sizeof s, "%s%s", helpdir, current->name);
01194 else
01195 egg_snprintf(s, sizeof s, "%sset/%s", helpdir, current->name);
01196 if ((f = fopen(s, "r")))
01197 return f;
01198 }
01199 }
01200
01201 return NULL;
01202 }
01203
01204 simple_sprintf(s, "%s%s", textdir, file);
01205 if (is_file(s))
01206 return fopen(s, "r");
01207 else
01208 return NULL;
01209 }
01210
01211 void showhelp(char *who, char *file, struct flag_record *flags, int fl)
01212 {
01213 int lines = 0;
01214 char s[HELP_BUF_LEN + 1];
01215 FILE *f = resolve_help(fl, file);
01216
01217 if (f) {
01218 help_subst(NULL, NULL, 0, HELP_IRC, NULL);
01219 while (!feof(f)) {
01220 fgets(s, HELP_BUF_LEN, f);
01221 if (!feof(f)) {
01222 if (s[strlen(s) - 1] == '\n')
01223 s[strlen(s) - 1] = 0;
01224 if (!s[0])
01225 strcpy(s, " ");
01226 help_subst(s, who, flags, 0, file);
01227 if ((s[0]) && (strlen(s) > 1)) {
01228 dprintf(DP_HELP, "NOTICE %s :%s\n", who, s);
01229 lines++;
01230 }
01231 }
01232 }
01233 fclose(f);
01234 }
01235 if (!lines && !(fl & HELP_TEXT))
01236 dprintf(DP_HELP, "NOTICE %s :%s\n", who, IRC_NOHELP2);
01237 }
01238
01239 static int display_tellhelp(int idx, char *file, FILE *f,
01240 struct flag_record *flags)
01241 {
01242 char s[HELP_BUF_LEN + 1];
01243 int lines = 0;
01244
01245 if (f) {
01246 help_subst(NULL, NULL, 0,
01247 (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
01248 while (!feof(f)) {
01249 fgets(s, HELP_BUF_LEN, f);
01250 if (!feof(f)) {
01251 if (s[strlen(s) - 1] == '\n')
01252 s[strlen(s) - 1] = 0;
01253 if (!s[0])
01254 strcpy(s, " ");
01255 help_subst(s, dcc[idx].nick, flags, 1, file);
01256 if (s[0]) {
01257 dprintf(idx, "%s\n", s);
01258 lines++;
01259 }
01260 }
01261 }
01262 fclose(f);
01263 }
01264 return lines;
01265 }
01266
01267 void tellhelp(int idx, char *file, struct flag_record *flags, int fl)
01268 {
01269 int lines = 0;
01270 FILE *f = resolve_help(HELP_DCC | fl, file);
01271
01272 if (f)
01273 lines = display_tellhelp(idx, file, f, flags);
01274 if (!lines && !(fl & HELP_TEXT))
01275 dprintf(idx, "%s\n", IRC_NOHELP2);
01276 }
01277
01278
01279
01280 void tellwildhelp(int idx, char *match, struct flag_record *flags)
01281 {
01282 struct help_ref *current;
01283 struct help_list_t *item;
01284 FILE *f;
01285 char s[1024];
01286
01287 s[0] = '\0';
01288 for (current = help_list; current; current = current->next)
01289 for (item = current->first; item; item = item->next)
01290 if (wild_match(match, item->name) && item->type) {
01291 if (item->type == 1)
01292 egg_snprintf(s, sizeof s, "%s%s", helpdir, current->name);
01293 else
01294 egg_snprintf(s, sizeof s, "%sset/%s", helpdir, current->name);
01295 if ((f = fopen(s, "r")))
01296 display_tellhelp(idx, item->name, f, flags);
01297 }
01298 if (!s[0])
01299 dprintf(idx, "%s\n", IRC_NOHELP2);
01300 }
01301
01302
01303
01304 void tellallhelp(int idx, char *match, struct flag_record *flags)
01305 {
01306 struct help_ref *current;
01307 struct help_list_t *item;
01308 FILE *f;
01309 char s[1024];
01310
01311 s[0] = '\0';
01312 for (current = help_list; current; current = current->next)
01313 for (item = current->first; item; item = item->next)
01314 if (!strcmp(match, item->name) && item->type) {
01315
01316 if (item->type == 1)
01317 egg_snprintf(s, sizeof s, "%s%s", helpdir, current->name);
01318 else
01319 egg_snprintf(s, sizeof s, "%sset/%s", helpdir, current->name);
01320 if ((f = fopen(s, "r")))
01321 display_tellhelp(idx, item->name, f, flags);
01322 }
01323 if (!s[0])
01324 dprintf(idx, "%s\n", IRC_NOHELP2);
01325 }
01326
01327
01328
01329 void sub_lang(int idx, char *text)
01330 {
01331 char s[1024];
01332 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
01333
01334 get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
01335 help_subst(NULL, NULL, 0,
01336 (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
01337 strncpyz(s, text, sizeof s);
01338 if (s[strlen(s) - 1] == '\n')
01339 s[strlen(s) - 1] = 0;
01340 if (!s[0])
01341 strcpy(s, " ");
01342 help_subst(s, dcc[idx].nick, &fr, 1, botnetnick);
01343 if (s[0])
01344 dprintf(idx, "%s\n", s);
01345 }
01346
01347
01348
01349
01350
01351 char *extracthostname(char *hostmask)
01352 {
01353 char *p = strrchr(hostmask, '@');
01354
01355 return p ? p + 1 : "";
01356 }
01357
01358
01359
01360 void show_motd(int idx)
01361 {
01362 FILE *vv;
01363 char s[1024];
01364 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
01365
01366 if (!is_file(motdfile))
01367 return;
01368
01369 vv = fopen(motdfile, "r");
01370 if (!vv)
01371 return;
01372
01373 get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
01374 dprintf(idx, "\n");
01375
01376 help_subst(NULL, NULL, 0,
01377 (dcc[idx].status & STAT_TELNET) ? 0 : HELP_IRC, NULL);
01378 while (!feof(vv)) {
01379 fgets(s, 120, vv);
01380 if (!feof(vv)) {
01381 if (s[strlen(s) - 1] == '\n')
01382 s[strlen(s) - 1] = 0;
01383 if (!s[0])
01384 strcpy(s, " ");
01385 help_subst(s, dcc[idx].nick, &fr, 1, botnetnick);
01386 if (s[0])
01387 dprintf(idx, "%s\n", s);
01388 }
01389 }
01390 fclose(vv);
01391 dprintf(idx, "\n");
01392 }
01393
01394
01395
01396 void show_banner(int idx)
01397 {
01398 FILE *vv;
01399 char s[1024];
01400 struct flag_record fr = { FR_GLOBAL | FR_CHAN, 0, 0, 0, 0, 0 };
01401
01402 if (!is_file(bannerfile))
01403 return;
01404
01405 vv = fopen(bannerfile, "r");
01406 if (!vv)
01407 return;
01408
01409 get_user_flagrec(dcc[idx].user, &fr, dcc[idx].u.chat->con_chan);
01410
01411 help_subst(NULL, NULL, 0, 0, NULL);
01412 while (!feof(vv)) {
01413 fgets(s, 120, vv);
01414 if (!feof(vv)) {
01415 if (!s[0])
01416 strcpy(s, " \n");
01417 help_subst(s, dcc[idx].nick, &fr, 0, botnetnick);
01418 dprintf(idx, "%s", s);
01419 }
01420 }
01421 fclose(vv);
01422 }
01423
01424
01425
01426 void make_rand_str(char *s, int len)
01427 {
01428 int j;
01429
01430 for (j = 0; j < len; j++) {
01431 if (!randint(3))
01432 s[j] = '0' + randint(10);
01433 else
01434 s[j] = 'a' + randint(26);
01435 }
01436 s[len] = 0;
01437 }
01438
01439
01440
01441
01442 int oatoi(const char *octal)
01443 {
01444 register int i;
01445
01446 if (!*octal)
01447 return -1;
01448 for (i = 0; ((*octal >= '0') && (*octal <= '7')); octal++)
01449 i = (i * 8) + (*octal - '0');
01450 if (*octal)
01451 return -1;
01452 return i;
01453 }
01454
01455
01456
01457
01458
01459
01460
01461 char *str_escape(const char *str, const char div, const char mask)
01462 {
01463 const int len = strlen(str);
01464 int buflen = (2 * len), blen = 0;
01465 char *buf = nmalloc(buflen + 1), *b = buf;
01466 const char *s;
01467
01468 if (!buf)
01469 return NULL;
01470 for (s = str; *s; s++) {
01471
01472 if ((buflen - blen) <= 3) {
01473 buflen = (buflen * 2);
01474 buf = nrealloc(buf, buflen + 1);
01475 if (!buf)
01476 return NULL;
01477 b = buf + blen;
01478 }
01479
01480 if (*s == div || *s == mask) {
01481 sprintf(b, "%c%02x", mask, *s);
01482 b += 3;
01483 blen += 3;
01484 } else {
01485 *(b++) = *s;
01486 blen++;
01487 }
01488 }
01489 *b = 0;
01490 return buf;
01491 }
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510 char *strchr_unescape(char *str, const char div, register const char esc_char)
01511 {
01512 char buf[3];
01513 register char *s, *p;
01514
01515 buf[2] = 0;
01516 for (s = p = str; *s; s++, p++) {
01517 if (*s == esc_char) {
01518
01519 buf[0] = s[1], buf[1] = s[2];
01520 *p = (unsigned char) strtol(buf, NULL, 16);
01521 s += 2;
01522 } else if (*s == div) {
01523 *p = *s = 0;
01524 return (s + 1);
01525 } else
01526 *p = *s;
01527 }
01528 *p = 0;
01529 return NULL;
01530 }
01531
01532
01533 int str_isdigit(const char *str)
01534 {
01535 if (!*str)
01536 return 0;
01537
01538 for (; *str; ++str) {
01539 if (!egg_isdigit(*str))
01540 return 0;
01541 }
01542 return 1;
01543 }
01544
01545
01546
01547
01548 void str_unescape(char *str, register const char esc_char)
01549 {
01550 (void) strchr_unescape(str, 0, esc_char);
01551 }
01552
01553 char *str_dup(const char *s)
01554 {
01555 char *d = nmalloc(strlen(s)+1);
01556 strcpy(d, s);
01557 return d;
01558 }
01559
01560
01561
01562
01563 void kill_bot(char *s1, char *s2)
01564 {
01565 call_hook(HOOK_DIE);
01566 chatout("*** %s\n", s1);
01567 botnet_send_chat(-1, botnetnick, s1);
01568 botnet_send_bye();
01569 write_userfile(-1);
01570 fatal(s2, 0);
01571 }