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