/[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.12 - (hide annotations) (download) (as text)
Wed Dec 15 17:20:37 1999 UTC (19 years, 8 months ago) by fabian
Branch: MAIN
Changes since 1.11: +2 -2 lines
File MIME type: text/x-chdr
the share_botoverride patch...

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23