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