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

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

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


Revision 1.4 - (hide annotations) (download) (as text)
Mon Oct 11 07:59:57 1999 UTC (19 years, 10 months ago) by fabian
Branch: MAIN
Changes since 1.3: +3 -3 lines
File MIME type: text/x-chdr
dns patches, textdir patch, sync 939496415-939574072

1 segfault 1.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 fabian 1.4 char configfile[121] = "eggdrop.conf"; /* name of the config file */
96 segfault 1.1 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 fabian 1.2 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 segfault 1.1 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 fabian 1.2 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 segfault 1.1 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 fabian 1.4 putlog(LOG_ALL, "*", "--- %.11s%s", s, s + 20);
443 segfault 1.1 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 fabian 1.2 movefile(logs[i].filename, s);
473 segfault 1.1 }
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 fabian 1.2 sprintf(&egg_version[strlen(egg_version)], " %u", egg_numver);
551 segfault 1.1 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 fabian 1.4 putlog(LOG_MISC, "*", "=== %s: %d channels, %d users.",
628 segfault 1.1 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 fabian 1.3 #if ((TCL_MAJOR_VERSION == 7) && (TCL_MINOR_VERSION >= 5)) || (TCL_MAJOR_VERSION >= 8)
754 segfault 1.1 /* process a single tcl event */
755     Tcl_DoOneEvent(TCL_ALL_EVENTS | TCL_DONT_WAIT);
756 fabian 1.3 #endif /* TCL */
757 segfault 1.1 /* lets move some of this here, reducing the numer of actual
758     * calls to periodic_timers */
759     now = time(NULL);
760     random(); /* woop, lets really jumble things */
761     if (now != then) { /* once a second */
762     call_hook(HOOK_SECONDLY);
763     then = now;
764     }
765     context;
766     /* only do this every so often */
767     if (!socket_cleanup) {
768     /* clean up sockets that were just left for dead */
769     for (i = 0; i < dcc_total; i++) {
770     if (dcc[i].type == &DCC_LOST) {
771     dcc[i].type = (struct dcc_table *) (dcc[i].sock);
772     lostdcc(i);
773     i--;
774     }
775     }
776     /* check for server or dcc activity */
777     dequeue_sockets();
778     socket_cleanup = 5;
779     } else
780     socket_cleanup--;
781     /* new net routines: help me mary! */
782     xx = sockgets(buf, &i);
783     if (xx >= 0) { /* non-error */
784     int idx;
785    
786     context;
787     for (idx = 0; idx < dcc_total; idx++)
788     if (dcc[idx].sock == xx) {
789     if (dcc[idx].type && dcc[idx].type->activity)
790     dcc[idx].type->activity(idx, buf, i);
791     else
792     putlog(LOG_MISC, "*",
793     "!!! untrapped dcc activity: type %s, sock %d",
794     dcc[idx].type->name, dcc[idx].sock);
795     break;
796     }
797     } else if (xx == -1) { /* EOF from someone */
798     int idx;
799    
800     if ((i == STDOUT) && !backgrd)
801     fatal("END OF FILE ON TERMINAL", 0);
802     context;
803     for (idx = 0; idx < dcc_total; idx++)
804     if (dcc[idx].sock == i) {
805     if (dcc[idx].type && dcc[idx].type->eof)
806     dcc[idx].type->eof(idx);
807     else {
808     putlog(LOG_MISC, "*",
809     "*** ATTENTION: DEAD SOCKET (%d) OF TYPE %s UNTRAPPED",
810 fabian 1.2 i, dcc[idx].type ? dcc[idx].type->name : "*UNKNOWN*");
811     killsock(i);
812 segfault 1.1 lostdcc(idx);
813     }
814     idx = dcc_total + 1;
815     }
816     if (idx == dcc_total) {
817     putlog(LOG_MISC, "*",
818 fabian 1.2 "(@) EOF socket %d, not a dcc socket, not anything.", i);
819     close(i);
820     killsock(i);
821 segfault 1.1 }
822     } else if ((xx == -2) && (errno != EINTR)) { /* select() error */
823     context;
824     putlog(LOG_MISC, "*", "* Socket error #%d; recovering.", errno);
825     for (i = 0; i < dcc_total; i++) {
826     if ((fcntl(dcc[i].sock, F_GETFD, 0) == -1) && (errno = EBADF)) {
827     if (dcc[i].type == &DCC_LOST)
828     dcc[i].type = (struct dcc_table *) (dcc[i].sock);
829     putlog(LOG_MISC, "*",
830     "DCC socket %d (type %d, name '%s') expired -- pfft",
831     dcc[i].sock, dcc[i].type, dcc[i].nick);
832     killsock(dcc[i].sock);
833     lostdcc(i);
834     i--;
835     }
836     }
837     } else if (xx == (-3)) {
838     call_hook(HOOK_IDLE);
839     socket_cleanup = 0; /* if we've been idle, cleanup & flush */
840     }
841     if (do_restart) {
842     if (do_restart == -2)
843     rehash();
844     else {
845     /* unload as many modules as possible */
846     int f = 1;
847     module_entry *p;
848     Function x;
849     char xx[256];
850    
851     while (f) {
852     f = 0;
853     for (p = module_list; p != NULL; p = p->next) {
854     dependancy *d = dependancy_list;
855     int ok = 1;
856    
857     while (ok && d) {
858     if (d->needed == p)
859     ok = 0;
860     d = d->next;
861     }
862     if (ok) {
863     strcpy(xx, p->name);
864     if (module_unload(xx, origbotname) == NULL) {
865     f = 1;
866     break;
867     }
868     }
869     }
870     }
871     p = module_list;
872     if (p && p->next && p->next->next)
873     /* should be only 2 modules now -
874     * blowfish & eggdrop */
875     putlog(LOG_MISC, "*", MOD_STAGNANT);
876     context;
877     flushlogs();
878     context;
879     kill_tcl();
880     init_tcl();
881     init_language(0);
882     x = p->funcs[MODCALL_START];
883     x(0);
884     rehash();
885     restart_chons();
886     }
887     do_restart = 0;
888     }
889     }
890     }

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23