/[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.22 - (hide annotations) (download) (as text)
Thu Jan 6 19:45:02 2000 UTC (19 years, 7 months ago) by fabian
Branch: MAIN
Changes since 1.21: +9 -9 lines
File MIME type: text/x-chdr
errors_fix, simialer to 1.4

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23