/[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.78 - (hide annotations) (download) (as text)
Fri Sep 28 03:15:34 2001 UTC (17 years, 9 months ago) by stdarg
Branch: MAIN
Changes since 1.77: +4 -13 lines
File MIME type: text/x-chdr

This is a big patch!
Created several new bind tables (raw, msg, msgm, pub, pubm) to see how it
would work. Seems to work well so far, although there could be bugs.
Added most of the new important bind table functions to the global table.

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

webmaster@eggheads.org
ViewVC Help
Powered by ViewVC 1.1.23