]> jfr.im git - irc/evilnet/x3.git/blame - src/main.c
Merged in srvx 1.4-RC1 changes. DNSBL parts are missing as it hasnt even been impleme...
[irc/evilnet/x3.git] / src / main.c
CommitLineData
7637f48f 1/* main.c - X3
d76ed9a9
AS
2 * Copyright 2000-2004 srvx Development Team
3 *
83ff05c3 4 * This file is part of x3.
d76ed9a9 5 *
d0f04f71 6 * x3 is free software; you can redistribute it and/or modify
d76ed9a9 7 * it under the terms of the GNU General Public License as published by
348683aa 8 * the Free Software Foundation; either version 3 of the License, or
d76ed9a9
AS
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
19 */
20
ceafd592 21#define PID_FILE "x3.pid"
d76ed9a9
AS
22
23#include "conf.h"
24#include "gline.h"
25#include "ioset.h"
26#include "modcmd.h"
27#include "saxdb.h"
ff3b058a 28#include "mail.h"
63c95a47 29#include "spamserv.h"
d914d1cb 30#include "shun.h"
d76ed9a9 31#include "timeq.h"
ff3b058a 32#include "sar.h"
d76ed9a9
AS
33
34#include "chanserv.h"
35#include "global.h"
36#include "modules.h"
37#include "opserv.h"
38
39#ifdef HAVE_GETOPT_H
40#include <getopt.h>
41#else
42#include "getopt.h"
43#endif
44#ifdef HAVE_SYS_RESOURCE_H
45#include <sys/resource.h>
46#endif
47#ifdef HAVE_NETINET_IN_H
48#include <netinet/in.h>
49#endif
50#ifdef HAVE_SYS_SOCKET_H
51#include <sys/socket.h>
52#endif
53#ifdef HAVE_SYS_WAIT_H
54#include <sys/wait.h>
55#endif
56
57#ifndef SIGCHLD
58#define SIGCHLD SIGCLD
59#endif
60
ff3b058a 61#include "main-common.c"
d76ed9a9
AS
62
63void sigaction_writedb(int x)
64{
65#ifndef HAVE_STRSIGNAL
66 log_module(MAIN_LOG, LOG_INFO, "Signal %d -- writing databases.", x);
67#else
68 log_module(MAIN_LOG, LOG_INFO, "%s -- writing databases.", strsignal(x));
69#endif
70 do_write_dbs = 1;
71}
72
73void sigaction_exit(int x)
74{
75#ifndef HAVE_STRSIGNAL
76 log_module(MAIN_LOG, LOG_INFO, "Signal %d -- exiting.", x);
77#else
78 log_module(MAIN_LOG, LOG_INFO, "%s -- exiting.", strsignal(x));
79#endif
80 irc_squit(self, "Exiting on signal from console.", NULL);
81 quit_services = 1;
82}
83
84void sigaction_wait(UNUSED_ARG(int x))
85{
86 int code;
87 wait4(-1, &code, WNOHANG, NULL);
88}
89
90void sigaction_rehash(int x)
91{
92#ifndef HAVE_STRSIGNAL
93 log_module(MAIN_LOG, LOG_INFO, "Signal %d -- rehashing.", x);
94#else
95 log_module(MAIN_LOG, LOG_INFO, "%s -- rehashing.", strsignal(x));
96#endif
97 do_reopen = 1;
98}
99
d76ed9a9
AS
100#if WITH_MALLOC_BOEHM_GC
101void
102gc_warn_proc(char *msg, GC_word arg)
103{
104 log_module(MAIN_LOG, LOG_ERROR, "GC(%p): %s", (void*)arg, msg);
105}
106#endif
107
108int main(int argc, char *argv[])
109{
110 int daemon, debug;
111 pid_t pid = 0;
112 FILE *file_out;
113 struct sigaction sv;
114
0d16e639 115#if WITH_MALLOC_BOEHM_GC
116 GC_find_leak = 1;
117 GC_set_warn_proc(gc_warn_proc);
118 GC_enable_incremental();
119#endif
120
d76ed9a9
AS
121 daemon = 1;
122 debug = 0;
123 tools_init();
124
125 /* set up some signal handlers */
126 memset(&sv, 0, sizeof(sv));
127 sigemptyset(&sv.sa_mask);
128 sv.sa_handler = SIG_IGN;
129 sigaction(SIGPIPE, &sv, NULL);
130 sv.sa_handler = sigaction_rehash;
131 sigaction(SIGHUP, &sv, NULL);
132 sv.sa_handler = sigaction_writedb;
133 sigaction(SIGINT, &sv, NULL);
134 sv.sa_handler = sigaction_exit;
135 sigaction(SIGQUIT, &sv, NULL);
136 sv.sa_handler = sigaction_wait;
137 sigaction(SIGCHLD, &sv, NULL);
138
139 if (argc > 1) { /* parse command line, if any */
140 int c;
141 struct option options[] =
142 {
143 {"config", 1, 0, 'c'},
144 {"debug", 0, 0, 'd'},
145 {"foreground", 0, 0, 'f'},
146 {"help", 0, 0, 'h'},
147 {"check", 0, 0, 'k'},
148 {"replay", 1, 0, 'r'},
149 {"version", 0, 0, 'v'},
d76ed9a9
AS
150 {0, 0, 0, 0}
151 };
152
ff3b058a 153 while ((c = getopt_long(argc, argv, "c:dfhkr:v", options, NULL)) != -1) {
154 switch (c) {
d76ed9a9
AS
155 case 'c':
156 services_config = optarg;
157 break;
158 case 'k':
159 if (conf_read(services_config)) {
160 printf("%s appears to be a valid configuration file.\n", services_config);
161 } else {
162 printf("%s is an invalid configuration file.\n", services_config);
163 }
164 exit(0);
165 case 'r':
166 replay_file = fopen(optarg, "r");
167 if (!replay_file) {
168 fprintf(stderr, "Could not open %s for reading: %s (%d)\n",
169 optarg, strerror(errno), errno);
170 exit(0);
171 }
172 break;
173 case 'd':
174 debug = 1;
175 break;
176 case 'f':
177 daemon = 0;
178 break;
179 case 'v':
180 version();
181 license();
182 exit(0);
183 case 'h':
184 default:
185 usage(argv[0]);
186 exit(0);
187 }
188 }
189 }
190
191 version();
192
193 if (replay_file) {
194 /* We read a line here to "prime" the replay file parser, but
195 * mostly to get the right value of "now" for when we do the
196 * irc_introduce. */
197 replay_read_line();
198 boot_time = now;
199 } else {
200 boot_time = time(&now);
201 }
202
ff3b058a 203 fprintf(stdout, "Initializing daemon...\n");
d76ed9a9 204 if (!conf_read(services_config)) {
ff3b058a 205 fprintf(stderr, "Unable to read %s.\n", services_config);
206 exit(1);
d76ed9a9
AS
207 }
208
209 conf_register_reload(uplink_compile);
210
211 if (daemon) {
212 /* Attempt to fork into the background if daemon mode is on. */
213 pid = fork();
214 if (pid < 0) {
ff3b058a 215 fprintf(stderr, "Unable to fork: %s\n", strerror(errno));
d76ed9a9 216 } else if (pid > 0) {
ff3b058a 217 fprintf(stdout, "Forking into the background (pid: %d)...\n", pid);
d76ed9a9
AS
218 exit(0);
219 }
220 setsid();
d76ed9a9
AS
221 }
222
ff3b058a 223
224 file_out = fopen(PID_FILE, "w");
225 if (file_out == NULL) {
d76ed9a9 226 /* Create the main process' pid file */
ff3b058a 227 fprintf(stderr, "Unable to create PID file: %s", strerror(errno));
d76ed9a9
AS
228 } else {
229 fprintf(file_out, "%i\n", (int)getpid());
230 fclose(file_out);
231 }
232
ff3b058a 233 if (daemon) {
234 /* Close these since we should not use them from now on. */
235 fclose(stdin);
236 fclose(stdout);
237 fclose(stderr);
238 }
239
d76ed9a9
AS
240 services_argc = argc;
241 services_argv = argv;
242
243 atexit(call_exit_funcs);
244 reg_exit_func(main_shutdown);
245
246 log_init();
ceafd592 247 MAIN_LOG = log_register_type("x3", "file:main.log");
d76ed9a9
AS
248 if (debug)
249 log_debug();
ff3b058a 250 ioset_init();
d76ed9a9
AS
251 init_structs();
252 init_parse();
253 modcmd_init();
254 saxdb_init();
ff3b058a 255 sar_init();
d76ed9a9 256 gline_init();
d914d1cb 257 shun_init();
ff3b058a 258 mail_init();
d76ed9a9
AS
259 helpfile_init();
260 conf_globals(); /* initializes the core services */
261 conf_rlimits();
262 modules_init();
263 message_register_table(msgtab);
264 modcmd_finalize();
265 saxdb_finalize();
266 helpfile_finalize();
267 modules_finalize();
268
269 /* The first exit func to be called *should* be saxdb_write_all(). */
270 reg_exit_func(saxdb_write_all);
271 if (replay_file) {
272 char *msg;
273 log_module(MAIN_LOG, LOG_INFO, "Beginning replay...");
274 srand(now);
275 replay_event_loop();
276 if ((msg = dict_sanity_check(clients))) {
277 log_module(MAIN_LOG, LOG_ERROR, "Clients insanity: %s", msg);
278 free(msg);
279 }
280 if ((msg = dict_sanity_check(channels))) {
281 log_module(MAIN_LOG, LOG_ERROR, "Channels insanity: %s", msg);
282 free(msg);
283 }
284 if ((msg = dict_sanity_check(servers))) {
285 log_module(MAIN_LOG, LOG_ERROR, "Servers insanity: %s", msg);
286 free(msg);
287 }
288 } else {
289 srand(time(&now));
290 ioset_run();
291 }
292 return 0;
293}