]>
Commit | Line | Data |
---|---|---|
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 | |
63 | void 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 | ||
73 | void 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 | ||
84 | void sigaction_wait(UNUSED_ARG(int x)) | |
85 | { | |
86 | int code; | |
87 | wait4(-1, &code, WNOHANG, NULL); | |
88 | } | |
89 | ||
90 | void 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 |
101 | void | |
102 | gc_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 | ||
108 | int 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 | } |