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

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

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


Revision 1.2 - (show annotations) (download) (as text)
Sat Oct 9 15:46:34 1999 UTC (19 years, 9 months ago) by fabian
Branch: MAIN
Changes since 1.1: +24 -22 lines
File MIME type: text/x-chdr
all changes to the 1.3 tree merged with 1.4

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23