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

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

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


Revision 1.1.1.1 - (show annotations) (download) (as text) (vendor branch)
Wed Jun 23 19:51:29 1999 UTC (22 years, 4 months ago) by segfault
Branch: eggdev
CVS Tags: start
Changes since 1.1: +0 -0 lines
File MIME type: text/x-chdr
Eggdrop 1.3.28 CVS Code

1 /*
2 * main.c -- handles:
3 * changing nicknames when the desired nick is in use
4 * flood detection
5 * signal handling
6 * command line arguments
7 *
8 * dprintf'ized, 15nov1995
9 */
10 /*
11 * This file is part of the eggdrop source code
12 * copyright (c) 1997 Robey Pointer
13 * and is distributed according to the GNU general public license.
14 *
15 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
19 *
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 * GNU General Public License for more details.
24 *
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
28 *
29 * The author (Robey Pointer) can be reached at: robey@netcom.com
30 * NOTE: Robey is no long working on this code, there is a discussion
31 * list avaliable at eggheads@eggheads.org.
32 */
33
34 #include "main.h"
35 #include <time.h>
36 #include <fcntl.h>
37 #include <errno.h>
38 #include <signal.h>
39 #include <netdb.h>
40 #include <setjmp.h>
41 #ifdef STOP_UAC /* osf/1 complains a lot */
42 #include <sys/sysinfo.h>
43 #define UAC_NOPRINT 0x00000001 /* Don't report unaligned fixups */
44 #endif
45 /* some systems have a working sys/wait.h even though configure will
46 * decide it's not bsd compatable. oh well. */
47 #include "chan.h"
48 #include "modules.h"
49 #include "tandem.h"
50
51 #ifndef _POSIX_SOURCE
52 /* solaris needs this */
53 #define _POSIX_SOURCE 1
54 #endif
55
56 extern char origbotname[];
57 extern int dcc_total;
58 extern struct dcc_t *dcc;
59 extern int conmask;
60 extern struct userrec *userlist;
61 extern int cache_hit, cache_miss;
62 extern char userfile[];
63 extern struct chanset_t *chanset;
64 extern char botnetnick[];
65 extern log_t *logs;
66 extern Tcl_Interp *interp;
67 extern int max_logs;
68 extern tcl_timer_t *timer, *utimer;
69 extern jmp_buf alarmret;
70 extern int quick_logs; /* dw */
71
72 /*
73 * Please use the PATCH macro instead of directly altering the version
74 * string from now on (it makes it much easier to maintain patches).
75 * Also please read the README file regarding your rights to distribute
76 * modified versions of this bot.
77 */
78
79 char egg_version[1024] = "1.3.28";
80 int egg_numver = 1032800;
81
82 char notify_new[121] = ""; /* person to send a note to for new users */
83 int default_flags = 0; /* default user flags for people who say
84 * 'hello' */
85 int backgrd = 1; /* run in the background? */
86 int con_chan = 0; /* foreground: constantly display channel
87 * stats? */
88 int term_z = 0; /* foreground: use the terminal as a party
89 * line? */
90 char configfile[121] = "egg.config"; /* name of the config file */
91 char helpdir[121]; /* directory of help files (if used) */
92 char textdir[121] = ""; /* directory for text files that get dumped */
93 int keep_all_logs = 0; /* never erase logfiles, no matter how old
94 * they are? */
95 time_t online_since; /* unix-time that the bot loaded up */
96 int make_userfile = 0; /* using bot in make-userfile mode? (first
97 * user to 'hello' becomes master) */
98 char owner[121] = ""; /* permanent owner(s) of the bot */
99 char pid_file[40]; /* name of the file for the pid to be
100 * stored in */
101 int save_users_at = 0; /* how many minutes past the hour to
102 * save the userfile? */
103 int notify_users_at = 0; /* how many minutes past the hour to
104 * notify users of notes? */
105 int switch_logfiles_at = 300; /* when (military time) to switch logfiles */
106 char version[81]; /* version info (long form) */
107 char ver[41]; /* version info (short form) */
108 char egg_xtra[1024]; /* patch info */
109 int use_stderr = 1; /* send stuff to stderr instead of logfiles? */
110 int do_restart = 0; /* .restart has been called, restart asap */
111 int die_on_sighup = 0; /* die if bot receives SIGHUP */
112 int die_on_sigterm = 0; /* die if bot receives SIGTERM */
113 int resolve_timeout = 15; /* hostname/address lookup timeout */
114 time_t now; /* duh, now :) */
115
116 /* context storage for fatal crashes */
117 char cx_file[16][30];
118 char cx_note[16][256];
119 int cx_line[16];
120 int cx_ptr = 0;
121
122 void fatal(char *s, int recoverable)
123 {
124 int i;
125
126 putlog(LOG_MISC, "*", "* %s", s);
127 flushlogs();
128 for (i = 0; i < dcc_total; i++)
129 killsock(dcc[i].sock);
130 unlink(pid_file);
131 if (!recoverable)
132 exit(1);
133 }
134
135 int expmem_chanprog(), expmem_users(), expmem_misc(), expmem_dccutil(),
136 expmem_botnet(), expmem_tcl(), expmem_tclhash(), expmem_net(),
137 expmem_modules(int), expmem_language(), expmem_tcldcc();
138
139 /* for mem.c : calculate memory we SHOULD be using */
140 int expected_memory()
141 {
142 int tot;
143
144 context;
145 tot = expmem_chanprog() + expmem_users() + expmem_misc() +
146 expmem_dccutil() + expmem_botnet() + expmem_tcl() + expmem_tclhash() +
147 expmem_net() + expmem_modules(0) + expmem_language() + expmem_tcldcc();
148 return tot;
149 }
150
151 static void check_expired_dcc()
152 {
153 int i;
154
155 for (i = 0; i < dcc_total; i++)
156 if (dcc[i].type && dcc[i].type->timeout_val &&
157 ((now - dcc[i].timeval) > *(dcc[i].type->timeout_val))) {
158 if (dcc[i].type->timeout)
159 dcc[i].type->timeout(i);
160 else if (dcc[i].type->eof)
161 dcc[i].type->eof(i);
162 else
163 continue;
164 /* only timeout 1 socket per cycle, too risky for more */
165 return;
166 }
167 }
168
169 static int nested_debug = 0;
170
171 void write_debug()
172 {
173 int x;
174 char s[80];
175 int y;
176
177 if (nested_debug) {
178 /* yoicks, if we have this there's serious trouble */
179 /* all of these are pretty reliable, so we'll try these */
180 /* dont try and display context-notes in here, it's _not_ safe <cybah> */
181 x = creat("DEBUG.DEBUG", 0644);
182 setsock(x, SOCK_NONSOCK);
183 if (x >= 0) {
184 strcpy(s, ctime(&now));
185 dprintf(-x, "Debug (%s) written %s", ver, s);
186 dprintf(-x, "Please report problem to eggheads@eggheads.org");
187 dprintf(-x, "Full Patch List: %s\n", egg_xtra);
188 dprintf(-x, "Context: ");
189 cx_ptr = cx_ptr & 15;
190 for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
191 dprintf(-x, "%s/%d,\n ", cx_file[y], cx_line[y]);
192 dprintf(-x, "%s/%d\n\n", cx_file[y], cx_line[y]);
193 killsock(x);
194 close(x);
195 }
196 exit(1); /* dont even try & tell people about, that may
197 * have caused the fault last time */
198 } else
199 nested_debug = 1;
200 putlog(LOG_MISC, "*", "* Last context: %s/%d [%s]", cx_file[cx_ptr],
201 cx_line[cx_ptr], cx_note[cx_ptr][0] ? cx_note[cx_ptr] : "");
202 x = creat("DEBUG", 0644);
203 setsock(x, SOCK_NONSOCK);
204 if (x < 0) {
205 putlog(LOG_MISC, "*", "* Failed to write DEBUG");
206 } else {
207 strcpy(s, ctime(&now));
208 dprintf(-x, "Debug (%s) written %s", ver, s);
209 dprintf(-x, "Full Patch List: %s\n", egg_xtra);
210 #ifdef STATIC
211 dprintf(-x, "STATICALLY LINKED\n");
212 #endif
213 strcpy(s, "info library");
214 if (interp && (Tcl_Eval(interp, s) == TCL_OK))
215 dprintf(-x, "Using tcl library: %s (header version %s)\n",
216 interp->result, TCL_VERSION);
217 dprintf(-x, "Compile flags: %s\n", CCFLAGS);
218 dprintf(-x, "Link flags : %s\n", LDFLAGS);
219 dprintf(-x, "Strip flags : %s\n", STRIPFLAGS);
220 dprintf(-x, "Context: ");
221 cx_ptr = cx_ptr & 15;
222 for (y = ((cx_ptr + 1) & 15); y != cx_ptr; y = ((y + 1) & 15))
223 dprintf(-x, "%s/%d, [%s]\n ", cx_file[y], cx_line[y],
224 (cx_note[y][0]) ? cx_note[y] : "");
225 dprintf(-x, "%s/%d [%s]\n\n", cx_file[cx_ptr], cx_line[cx_ptr],
226 (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
227 tell_dcc(-x);
228 dprintf(-x, "\n");
229 debug_mem_to_dcc(-x);
230 killsock(x);
231 close(x);
232 putlog(LOG_MISC, "*", "* Wrote DEBUG");
233 }
234 }
235
236 static void got_bus(int z)
237 {
238 write_debug();
239 fatal("BUS ERROR -- CRASHING!", 1);
240 #ifdef SA_RESETHAND
241 kill(getpid(), SIGBUS);
242 #else
243 exit(1);
244 #endif
245 }
246
247 static void got_segv(int z)
248 {
249 write_debug();
250 fatal("SEGMENT VIOLATION -- CRASHING!", 1);
251 #ifdef SA_RESETHAND
252 kill(getpid(), SIGSEGV);
253 #else
254 exit(1);
255 #endif
256 }
257
258 static void got_fpe(int z)
259 {
260 write_debug();
261 fatal("FLOATING POINT ERROR -- CRASHING!", 0);
262 }
263
264 static void got_term(int z)
265 {
266 write_userfile(-1);
267 check_tcl_event("sigterm");
268 if (die_on_sigterm) {
269 botnet_send_chat(-1, botnetnick, "ACK, I've been terminated!");
270 fatal("TERMINATE SIGNAL -- SIGNING OFF", 0);
271 } else {
272 putlog(LOG_MISC, "*", "RECEIVED TERMINATE SIGNAL (IGNORING)");
273 }
274 }
275
276 static void got_quit(int z)
277 {
278 check_tcl_event("sigquit");
279 putlog(LOG_MISC, "*", "RECEIVED QUIT SIGNAL (IGNORING)");
280 return;
281 }
282
283 static void got_hup(int z)
284 {
285 write_userfile(-1);
286 check_tcl_event("sighup");
287 if (die_on_sighup) {
288 fatal("HANGUP SIGNAL -- SIGNING OFF", 0);
289 } else
290 putlog(LOG_MISC, "*", "Received HUP signal: rehashing...");
291 do_restart = -2;
292 return;
293 }
294
295 static void got_alarm(int z)
296 {
297 /* a call to resolver (gethostbyname, etc) timed out */
298 longjmp(alarmret, 1);
299 /* STUPID STUPID STUPID */
300 /* return; */
301 }
302
303 /* got ILL signal -- log context and continue */
304 static void got_ill(int z)
305 {
306 check_tcl_event("sigill");
307 putlog(LOG_MISC, "*", "* Context: %s/%d [%s]", cx_file[cx_ptr],
308 cx_line[cx_ptr], (cx_note[cx_ptr][0]) ? cx_note[cx_ptr] : "");
309 }
310
311 static void do_arg(char *s)
312 {
313 int i;
314
315 if (s[0] == '-')
316 for (i = 1; i < strlen(s); i++) {
317 if (s[i] == 'n')
318 backgrd = 0;
319 if (s[i] == 'c') {
320 con_chan = 1;
321 term_z = 0;
322 }
323 if (s[i] == 't') {
324 con_chan = 0;
325 term_z = 1;
326 }
327 if (s[i] == 'm')
328 make_userfile = 1;
329 if (s[i] == 'v') {
330 char x[256], *z = x;
331
332 strcpy(x, egg_version);
333 newsplit(&z);
334 newsplit(&z);
335 printf("%s\n", version);
336 if (z[0])
337 printf(" (patches: %s)\n", z);
338 exit(0);
339 }
340 if (s[i] == 'h') {
341 printf("\n%s\n\n", version);
342 printf(EGG_USAGE);
343 printf("\n");
344 exit(0);
345 }
346 } else
347 strcpy(configfile, s);
348 }
349
350 void backup_userfile()
351 {
352 char s[150];
353
354 putlog(LOG_MISC, "*", USERF_BACKUP);
355 strcpy(s, userfile);
356 strcat(s, "~bak");
357 copyfile(userfile, s);
358 }
359
360 /* timer info: */
361 static int lastmin = 99;
362 static time_t then;
363 static struct tm *nowtm;
364
365 /* rally BB, this is not QUITE as bad as it seems <G> */
366 /* ONCE A SECOND */
367 static void core_secondly()
368 {
369 static int cnt = 0;
370 int miltime;
371
372 do_check_timers(&utimer); /* secondly timers */
373 cnt++;
374 if (cnt >= 10) { /* every 10 seconds */
375 cnt = 0;
376 check_expired_dcc();
377 if (con_chan && !backgrd) {
378 dprintf(DP_STDOUT, "\033[2J\033[1;1H");
379 tell_verbose_status(DP_STDOUT, 0);
380 do_module_report(DP_STDOUT, 0, "server");
381 do_module_report(DP_STDOUT, 0, "channels");
382 tell_mem_status_dcc(DP_STDOUT);
383 }
384 }
385 context;
386 nowtm = localtime(&now);
387 if (nowtm->tm_min != lastmin) {
388 int i = 0;
389
390 /* once a minute */
391 lastmin = (lastmin + 1) % 60;
392 call_hook(HOOK_MINUTELY);
393 check_expired_ignores();
394 autolink_cycle(NULL); /* attempt autolinks */
395 /* in case for some reason more than 1 min has passed: */
396 while (nowtm->tm_min != lastmin) {
397 /* timer drift, dammit */
398 debug2("timer: drift (lastmin=%d, now=%d)", lastmin, nowtm->tm_min);
399 context;
400 i++;
401 lastmin = (lastmin + 1) % 60;
402 call_hook(HOOK_MINUTELY);
403 }
404 if (i > 1)
405 putlog(LOG_MISC, "*", "(!) timer drift -- spun %d minutes", i);
406 miltime = (nowtm->tm_hour * 100) + (nowtm->tm_min);
407 context;
408 if (((int) (nowtm->tm_min / 5) * 5) == (nowtm->tm_min)) { /* 5 min */
409 call_hook(HOOK_5MINUTELY);
410 check_botnet_pings();
411 context;
412 if (quick_logs == 0) {
413 flushlogs();
414 check_logsize();
415 }
416 if (miltime == 0) { /* at midnight */
417 char s[128];
418 int j;
419
420 s[my_strcpy(s, ctime(&now)) - 1] = 0;
421 putlog(LOG_MISC, "*", "--- %.11s%s", s, s + 20);
422 backup_userfile();
423 for (j = 0; j < max_logs; j++) {
424 if (logs[j].filename != NULL && logs[j].f != NULL) {
425 fclose(logs[j].f);
426 logs[j].f = NULL;
427 }
428 }
429 }
430 }
431 context;
432 if (nowtm->tm_min == notify_users_at)
433 call_hook(HOOK_HOURLY);
434 context; /* these no longer need checking since they are
435 * all check vs minutely settings and we only
436 * get this far on the minute */
437 if (miltime == switch_logfiles_at) {
438 call_hook(HOOK_DAILY);
439 if (!keep_all_logs) {
440 putlog(LOG_MISC, "*", MISC_LOGSWITCH);
441 for (i = 0; i < max_logs; i++)
442 if (logs[i].filename) {
443 char s[1024];
444
445 if (logs[i].f) {
446 fclose(logs[i].f);
447 logs[i].f = NULL;
448 }
449 simple_sprintf(s, "%s.yesterday", logs[i].filename);
450 unlink(s);
451 #ifdef RENAME
452 rename(logs[i].filename, s);
453 #else
454 movefile(logs[i].filename, s);
455 #endif
456 }
457 }
458 }
459 }
460 }
461
462 static void core_minutely()
463 {
464 context;
465 check_tcl_time(nowtm);
466 do_check_timers(&timer);
467 context;
468 if (quick_logs != 0) {
469 flushlogs();
470 check_logsize();
471 }
472 }
473
474 static void core_hourly()
475 {
476 context;
477 write_userfile(-1);
478 }
479
480 static void event_rehash()
481 {
482 context;
483 check_tcl_event("rehash");
484 }
485
486 static void event_prerehash()
487 {
488 context;
489 check_tcl_event("prerehash");
490 }
491
492 static void event_save()
493 {
494 context;
495 check_tcl_event("save");
496 }
497
498 static void event_logfile()
499 {
500 context;
501 check_tcl_event("logfile");
502 }
503
504 void kill_tcl();
505 extern module_entry *module_list;
506 void restart_chons();
507
508 #ifdef STATIC
509 void check_static(char *, char *(*)());
510
511 #include "mod/static.h"
512 #endif
513 int init_mem(), init_dcc_max(), init_userent(), init_misc(), init_bots(),
514 init_net(), init_modules(), init_tcl(), init_language(char *);
515
516 int main(int argc, char **argv)
517 {
518 int xx, i;
519 char buf[520], s[520];
520 FILE *f;
521 struct sigaction sv;
522 struct chanset_t *chan;
523
524 /* initialise context list */
525 for (i = 0; i < 16; i++) {
526 context;
527 }
528 #include "patch.h"
529 /* version info! */
530 sprintf(ver, "eggdrop v%s", egg_version);
531 sprintf(version, "Eggdrop v%s (c)1997 Robey Pointer", egg_version);
532 /* now add on the patchlevel (for Tcl) */
533 sprintf(&egg_version[strlen(egg_version)], " %08u", egg_numver);
534 strcat(egg_version, egg_xtra);
535 context;
536 #ifdef STOP_UAC
537 {
538 int nvpair[2];
539
540 nvpair[0] = SSIN_UACPROC;
541 nvpair[1] = UAC_NOPRINT;
542 setsysinfo(SSI_NVPAIRS, (char *) nvpair, 1, NULL, 0);
543 }
544 #endif
545 /* set up error traps: */
546 sv.sa_handler = got_bus;
547 sigemptyset(&sv.sa_mask);
548 #ifdef SA_RESETHAND
549 sv.sa_flags = SA_RESETHAND;
550 #else
551 sv.sa_flags = 0;
552 #endif
553 sigaction(SIGBUS, &sv, NULL);
554 sv.sa_handler = got_segv;
555 sigaction(SIGSEGV, &sv, NULL);
556 #ifdef SA_RESETHAND
557 sv.sa_flags = 0;
558 #endif
559 sv.sa_handler = got_fpe;
560 sigaction(SIGFPE, &sv, NULL);
561 sv.sa_handler = got_term;
562 sigaction(SIGTERM, &sv, NULL);
563 sv.sa_handler = got_hup;
564 sigaction(SIGHUP, &sv, NULL);
565 sv.sa_handler = got_quit;
566 sigaction(SIGQUIT, &sv, NULL);
567 sv.sa_handler = SIG_IGN;
568 sigaction(SIGPIPE, &sv, NULL);
569 sv.sa_handler = got_ill;
570 sigaction(SIGILL, &sv, NULL);
571 sv.sa_handler = got_alarm;
572 sigaction(SIGALRM, &sv, NULL);
573 /* initialize variables and stuff */
574 now = time(NULL);
575 chanset = NULL;
576 nowtm = localtime(&now);
577 lastmin = nowtm->tm_min;
578 srandom(now);
579 init_mem();
580 init_language("core.english");
581 if (argc > 1)
582 for (i = 1; i < argc; i++)
583 do_arg(argv[i]);
584 printf("\n%s\n", version);
585 init_dcc_max();
586 init_userent();
587 init_misc();
588 init_bots();
589 init_net();
590 init_modules();
591 init_tcl();
592 init_language(NULL);
593 #ifdef STATIC
594 link_statics();
595 #endif
596 context;
597 strcpy(s, ctime(&now));
598 s[strlen(s) - 1] = 0;
599 strcpy(&s[11], &s[20]);
600 putlog(LOG_ALL, "*", "--- Loading %s (%s)", ver, s);
601 chanprog();
602 context;
603 if (encrypt_pass == 0) {
604 printf(MOD_NOCRYPT);
605 exit(1);
606 }
607 i = 0;
608 for (chan = chanset; chan; chan = chan->next)
609 i++;
610 putlog(LOG_ALL, "*", "=== %s: %d channels, %d users.\n",
611 botnetnick, i, count_users(userlist));
612 cache_miss = 0;
613 cache_hit = 0;
614 context;
615 sprintf(pid_file, "pid.%s", botnetnick);
616 context;
617 /* check for pre-existing eggdrop! */
618 f = fopen(pid_file, "r");
619 if (f != NULL) {
620 fgets(s, 10, f);
621 xx = atoi(s);
622 kill(xx, SIGCHLD); /* meaningless kill to determine if pid
623 * is used */
624 if (errno != ESRCH) {
625 printf(EGG_RUNNING1, origbotname);
626 printf(EGG_RUNNING2, pid_file);
627 exit(1);
628 }
629 }
630 context;
631 /* move into background? */
632 if (backgrd) {
633 xx = fork();
634 if (xx == -1)
635 fatal("CANNOT FORK PROCESS.", 0);
636 if (xx != 0) {
637 FILE *fp;
638
639 /* need to attempt to write pid now, not later */
640 unlink(pid_file);
641 fp = fopen(pid_file, "w");
642 if (fp != NULL) {
643 fprintf(fp, "%u\n", xx);
644 if (fflush(fp)) {
645 /* kill bot incase a botchk is run from crond */
646 printf(EGG_NOWRITE, pid_file);
647 printf(" Try freeing some disk space\n");
648 fclose(fp);
649 unlink(pid_file);
650 exit(1);
651 }
652 fclose(fp);
653 } else
654 printf(EGG_NOWRITE, pid_file);
655 printf("Launched into the background (pid: %d)\n\n", xx);
656 #if HAVE_SETPGID
657 setpgid(xx, xx);
658 #endif
659 exit(0);
660 }
661 }
662 use_stderr = 0; /* stop writing to stderr now */
663 xx = getpid();
664 if ((xx != 0) && (!backgrd)) {
665 FILE *fp;
666
667 /* write pid to file */
668 unlink(pid_file);
669 fp = fopen(pid_file, "w");
670 if (fp != NULL) {
671 fprintf(fp, "%u\n", xx);
672 if (fflush(fp)) {
673 /* let the bot live since this doesn't appear to be a botchk */
674 printf(EGG_NOWRITE, pid_file);
675 fclose(fp);
676 unlink(pid_file);
677 }
678 fclose(fp);
679 } else
680 printf(EGG_NOWRITE, pid_file);
681 }
682 if (backgrd) {
683 /* ok, try to disassociate from controlling terminal */
684 /* (finger cross) */
685 #if HAVE_SETPGID
686 setpgid(0, 0);
687 #endif
688 /* close out stdin/out/err */
689 freopen("/dev/null", "r", stdin);
690 freopen("/dev/null", "w", stdout);
691 freopen("/dev/null", "w", stderr);
692 /* tcl wants those file handles kept open */
693 /* close(0); close(1); close(2); */
694 }
695 /* terminal emulating dcc chat */
696 if ((!backgrd) && (term_z)) {
697 int n = new_dcc(&DCC_CHAT, sizeof(struct chat_info));
698
699 dcc[n].addr = iptolong(getmyip());
700 dcc[n].sock = STDOUT;
701 dcc[n].timeval = now;
702 dcc[n].u.chat->con_flags = conmask;
703 dcc[n].u.chat->strip_flags = STRIP_ALL;
704 dcc[n].status = STAT_ECHO;
705 strcpy(dcc[n].nick, "HQ");
706 strcpy(dcc[n].host, "llama@console");
707 dcc[n].user = get_user_by_handle(userlist, "HQ");
708 /* make sure there's an innocuous HQ user if needed */
709 if (!dcc[n].user) {
710 adduser(userlist, "HQ", "none", "-", USER_PARTY);
711 dcc[n].user = get_user_by_handle(userlist, "HQ");
712 }
713 setsock(STDOUT, 0); /* entry in net table */
714 dprintf(n, "\n### ENTERING DCC CHAT SIMULATION ###\n\n");
715 dcc_chatter(n);
716 }
717 then = now;
718 online_since = now;
719 autolink_cycle(NULL); /* hurry and connect to tandem bots */
720 add_help_reference("cmds1.help");
721 add_help_reference("cmds2.help");
722 add_help_reference("core.help");
723 add_hook(HOOK_SECONDLY, core_secondly);
724 add_hook(HOOK_MINUTELY, core_minutely);
725 add_hook(HOOK_HOURLY, core_hourly);
726 add_hook(HOOK_REHASH, event_rehash);
727 add_hook(HOOK_PRE_REHASH, event_prerehash);
728 add_hook(HOOK_USERFILE, event_save);
729 add_hook(HOOK_DAILY, event_logfile);
730
731 debug0("main: entering loop");
732 while (1) {
733 int socket_cleanup = 0;
734
735 context;
736 /* process a single tcl event */
737 Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
738 /* lets move some of this here, reducing the numer of actual
739 * calls to periodic_timers */
740 now = time(NULL);
741 random(); /* woop, lets really jumble things */
742 if (now != then) { /* once a second */
743 call_hook(HOOK_SECONDLY);
744 then = now;
745 }
746 context;
747 /* only do this every so often */
748 if (!socket_cleanup) {
749 /* clean up sockets that were just left for dead */
750 for (i = 0; i < dcc_total; i++) {
751 if (dcc[i].type == &DCC_LOST) {
752 dcc[i].type = (struct dcc_table *) (dcc[i].sock);
753 lostdcc(i);
754 i--;
755 }
756 }
757 /* check for server or dcc activity */
758 dequeue_sockets();
759 socket_cleanup = 5;
760 } else
761 socket_cleanup--;
762 /* new net routines: help me mary! */
763 xx = sockgets(buf, &i);
764 if (xx >= 0) { /* non-error */
765 int idx;
766
767 context;
768 for (idx = 0; idx < dcc_total; idx++)
769 if (dcc[idx].sock == xx) {
770 if (dcc[idx].type && dcc[idx].type->activity)
771 dcc[idx].type->activity(idx, buf, i);
772 else
773 putlog(LOG_MISC, "*",
774 "!!! untrapped dcc activity: type %s, sock %d",
775 dcc[idx].type->name, dcc[idx].sock);
776 break;
777 }
778 } else if (xx == -1) { /* EOF from someone */
779 int idx;
780
781 if ((i == STDOUT) && !backgrd)
782 fatal("END OF FILE ON TERMINAL", 0);
783 context;
784 for (idx = 0; idx < dcc_total; idx++)
785 if (dcc[idx].sock == i) {
786 if (dcc[idx].type && dcc[idx].type->eof)
787 dcc[idx].type->eof(idx);
788 else {
789 putlog(LOG_MISC, "*",
790 "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED",
791 xx, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
792 killsock(xx);
793 lostdcc(idx);
794 }
795 idx = dcc_total + 1;
796 }
797 if (idx == dcc_total) {
798 putlog(LOG_MISC, "*",
799 "(@) EOF socket %d, not a dcc socket, not anything.",
800 xx);
801 close(xx);
802 killsock(xx);
803 }
804 } else if ((xx == -2) && (errno != EINTR)) { /* select() error */
805 context;
806 putlog(LOG_MISC, "*", "* Socket error #%d; recovering.", errno);
807 for (i = 0; i < dcc_total; i++) {
808 if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno = EBADF)) {
809 if (dcc[i].type == &DCC_LOST)
810 dcc[i].type = (struct dcc_table *) (dcc[i].sock);
811 putlog(LOG_MISC, "*",
812 "DCC socket %d (type %d, name '%s') expired -- pfft",
813 dcc[i].sock, dcc[i].type, dcc[i].nick);
814 killsock(dcc[i].sock);
815 lostdcc(i);
816 i--;
817 }
818 }
819 } else if (xx == (-3)) {
820 call_hook(HOOK_IDLE);
821 socket_cleanup = 0; /* if we've been idle, cleanup & flush */
822 }
823 if (do_restart) {
824 if (do_restart == -2)
825 rehash();
826 else {
827 /* unload as many modules as possible */
828 int f = 1;
829 module_entry *p;
830 Function x;
831 char xx[256];
832
833 while (f) {
834 f = 0;
835 for (p = module_list; p != NULL; p = p->next) {
836 dependancy *d = dependancy_list;
837 int ok = 1;
838
839 while (ok && d) {
840 if (d->needed == p)
841 ok = 0;
842 d = d->next;
843 }
844 if (ok) {
845 strcpy(xx, p->name);
846 if (module_unload(xx, origbotname) == NULL) {
847 f = 1;
848 break;
849 }
850 }
851 }
852 }
853 p = module_list;
854 if (p && p->next && p->next->next)
855 /* should be only 2 modules now -
856 * blowfish & eggdrop */
857 putlog(LOG_MISC, "*", MOD_STAGNANT);
858 context;
859 flushlogs();
860 context;
861 for (i = 0; i < max_logs; i++) {
862 if (logs[i].f != NULL) {
863 fclose(logs[i].f);
864 nfree(logs[i].filename);
865 nfree(logs[i].chname);
866 logs[i].filename = NULL;
867 logs[i].chname = NULL;
868 logs[i].mask = 0;
869 logs[i].f = NULL;
870 }
871 }
872 context;
873 kill_tcl();
874 init_tcl();
875 init_language(NULL);
876 x = p->funcs[MODCALL_START];
877 x(0);
878 rehash();
879 restart_chons();
880 }
881 do_restart = 0;
882 }
883 }
884 }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23