]>
Commit | Line | Data |
---|---|---|
7637f48f | 1 | /* main.c - X3 |
1136f709 | 2 | * Copyright 2000-2006 srvx Development Team |
d76ed9a9 | 3 | * |
1136f709 | 4 | * This file is part of X3. |
d76ed9a9 | 5 | * |
1136f709 | 6 | * srvx 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 |
be2c97a5 | 8 | * the Free Software Foundation; either version 3 of the License, or |
d76ed9a9 | 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 | 22 | |
23 | #include "conf.h" | |
24 | #include "gline.h" | |
25 | #include "ioset.h" | |
26 | #include "modcmd.h" | |
27 | #include "saxdb.h" | |
1136f709 | 28 | #include "mail.h" |
d76ed9a9 | 29 | #include "timeq.h" |
1136f709 | 30 | #include "sar.h" |
31 | #include "shun.h" | |
d76ed9a9 | 32 | |
33 | #include "chanserv.h" | |
34 | #include "global.h" | |
35 | #include "modules.h" | |
36 | #include "opserv.h" | |
37c8e812 | 37 | #include "spamserv.h" |
d76ed9a9 | 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 | ||
1136f709 | 57 | #include "main-common.c" |
d76ed9a9 | 58 | |
59 | void sigaction_writedb(int x) | |
60 | { | |
61 | #ifndef HAVE_STRSIGNAL | |
62 | log_module(MAIN_LOG, LOG_INFO, "Signal %d -- writing databases.", x); | |
63 | #else | |
64 | log_module(MAIN_LOG, LOG_INFO, "%s -- writing databases.", strsignal(x)); | |
65 | #endif | |
66 | do_write_dbs = 1; | |
67 | } | |
68 | ||
69 | void sigaction_exit(int x) | |
70 | { | |
71 | #ifndef HAVE_STRSIGNAL | |
72 | log_module(MAIN_LOG, LOG_INFO, "Signal %d -- exiting.", x); | |
73 | #else | |
74 | log_module(MAIN_LOG, LOG_INFO, "%s -- exiting.", strsignal(x)); | |
75 | #endif | |
76 | irc_squit(self, "Exiting on signal from console.", NULL); | |
77 | quit_services = 1; | |
78 | } | |
79 | ||
80 | void sigaction_wait(UNUSED_ARG(int x)) | |
81 | { | |
82 | int code; | |
83 | wait4(-1, &code, WNOHANG, NULL); | |
84 | } | |
85 | ||
86 | void sigaction_rehash(int x) | |
87 | { | |
88 | #ifndef HAVE_STRSIGNAL | |
89 | log_module(MAIN_LOG, LOG_INFO, "Signal %d -- rehashing.", x); | |
90 | #else | |
91 | log_module(MAIN_LOG, LOG_INFO, "%s -- rehashing.", strsignal(x)); | |
92 | #endif | |
93 | do_reopen = 1; | |
94 | } | |
95 | ||
d76ed9a9 | 96 | #if WITH_MALLOC_BOEHM_GC |
97 | void | |
98 | gc_warn_proc(char *msg, GC_word arg) | |
99 | { | |
100 | log_module(MAIN_LOG, LOG_ERROR, "GC(%p): %s", (void*)arg, msg); | |
101 | } | |
102 | #endif | |
103 | ||
104 | int main(int argc, char *argv[]) | |
105 | { | |
1136f709 | 106 | int run_as_daemon; |
107 | int debug; | |
d76ed9a9 | 108 | pid_t pid = 0; |
109 | FILE *file_out; | |
110 | struct sigaction sv; | |
111 | ||
0d16e639 | 112 | #if WITH_MALLOC_BOEHM_GC |
113 | GC_find_leak = 1; | |
114 | GC_set_warn_proc(gc_warn_proc); | |
115 | GC_enable_incremental(); | |
116 | #endif | |
117 | ||
c3211b62 AS |
118 | chdir(PREFIX); |
119 | log_module(MAIN_LOG, LOG_INFO, "changed to %s\n", PREFIX); | |
1136f709 | 120 | run_as_daemon = 1; |
d76ed9a9 | 121 | debug = 0; |
122 | tools_init(); | |
123 | ||
124 | /* set up some signal handlers */ | |
125 | memset(&sv, 0, sizeof(sv)); | |
126 | sigemptyset(&sv.sa_mask); | |
127 | sv.sa_handler = SIG_IGN; | |
128 | sigaction(SIGPIPE, &sv, NULL); | |
129 | sv.sa_handler = sigaction_rehash; | |
130 | sigaction(SIGHUP, &sv, NULL); | |
131 | sv.sa_handler = sigaction_writedb; | |
132 | sigaction(SIGINT, &sv, NULL); | |
133 | sv.sa_handler = sigaction_exit; | |
134 | sigaction(SIGQUIT, &sv, NULL); | |
135 | sv.sa_handler = sigaction_wait; | |
136 | sigaction(SIGCHLD, &sv, NULL); | |
137 | ||
138 | if (argc > 1) { /* parse command line, if any */ | |
1136f709 | 139 | int c; |
140 | struct option options[] = | |
141 | { | |
142 | {"config", 1, 0, 'c'}, | |
d76ed9a9 | 143 | {"debug", 0, 0, 'd'}, |
1136f709 | 144 | {"foreground", 0, 0, 'f'}, |
145 | {"help", 0, 0, 'h'}, | |
146 | {"check", 0, 0, 'k'}, | |
d76ed9a9 | 147 | {"replay", 1, 0, 'r'}, |
1136f709 | 148 | {"version", 0, 0, 'v'}, |
149 | {0, 0, 0, 0} | |
150 | }; | |
151 | ||
152 | while ((c = getopt_long(argc, argv, "c:dfhkr:v", options, NULL)) != -1) { | |
153 | switch (c) { | |
154 | case 'c': | |
155 | services_config = optarg; | |
156 | break; | |
157 | case 'k': | |
158 | if (conf_read(services_config)) { | |
159 | printf("%s appears to be a valid configuration file.\n", services_config); | |
160 | } else { | |
161 | printf("%s is an invalid configuration file.\n", services_config); | |
162 | } | |
163 | exit(0); | |
d76ed9a9 | 164 | case 'r': |
165 | replay_file = fopen(optarg, "r"); | |
166 | if (!replay_file) { | |
167 | fprintf(stderr, "Could not open %s for reading: %s (%d)\n", | |
168 | optarg, strerror(errno), errno); | |
169 | exit(0); | |
170 | } | |
171 | break; | |
172 | case 'd': | |
173 | debug = 1; | |
174 | break; | |
1136f709 | 175 | case 'f': |
176 | run_as_daemon = 0; | |
177 | break; | |
178 | case 'v': | |
179 | version(); | |
180 | license(); | |
181 | exit(0); | |
182 | case 'h': | |
183 | default: | |
184 | usage(argv[0]); | |
185 | exit(0); | |
186 | } | |
187 | } | |
d76ed9a9 | 188 | } |
189 | ||
190 | version(); | |
191 | ||
192 | if (replay_file) { | |
193 | /* We read a line here to "prime" the replay file parser, but | |
194 | * mostly to get the right value of "now" for when we do the | |
195 | * irc_introduce. */ | |
196 | replay_read_line(); | |
d76ed9a9 | 197 | } else { |
1136f709 | 198 | now = time(NULL); |
d76ed9a9 | 199 | } |
1136f709 | 200 | boot_time = now; |
d76ed9a9 | 201 | |
1136f709 | 202 | fprintf(stdout, "Initializing daemon...\n"); |
d76ed9a9 | 203 | if (!conf_read(services_config)) { |
1136f709 | 204 | fprintf(stderr, "Unable to read %s.\n", services_config); |
205 | exit(1); | |
d76ed9a9 | 206 | } |
207 | ||
208 | conf_register_reload(uplink_compile); | |
209 | ||
1136f709 | 210 | if (run_as_daemon) { |
211 | /* Attempt to fork into the background if daemon mode is on. */ | |
212 | pid = fork(); | |
213 | if (pid < 0) { | |
214 | fprintf(stderr, "Unable to fork: %s\n", strerror(errno)); | |
d76ed9a9 | 215 | } else if (pid > 0) { |
1136f709 | 216 | fprintf(stdout, "Forking into the background (pid: %d)...\n", pid); |
217 | exit(0); | |
218 | } | |
219 | setsid(); | |
220 | } | |
221 | ||
222 | file_out = fopen(PID_FILE, "w"); | |
223 | if (file_out == NULL) { | |
224 | /* Create the main process' pid file */ | |
225 | fprintf(stderr, "Unable to create PID file: %s", strerror(errno)); | |
226 | } else { | |
227 | fprintf(file_out, "%i\n", (int)getpid()); | |
228 | fclose(file_out); | |
229 | } | |
230 | ||
231 | if (run_as_daemon) { | |
0f6fe38c | 232 | /* Close these since we should not use them from now on. */ |
233 | fclose(stdin); | |
234 | fclose(stdout); | |
235 | fclose(stderr); | |
d76ed9a9 | 236 | } |
237 | ||
d76ed9a9 | 238 | services_argc = argc; |
239 | services_argv = argv; | |
240 | ||
241 | atexit(call_exit_funcs); | |
30874d66 | 242 | reg_exit_func(main_shutdown, NULL); |
d76ed9a9 | 243 | |
244 | log_init(); | |
ceafd592 | 245 | MAIN_LOG = log_register_type("x3", "file:main.log"); |
d76ed9a9 | 246 | if (debug) |
247 | log_debug(); | |
1136f709 | 248 | ioset_init(); |
d76ed9a9 | 249 | init_structs(); |
250 | init_parse(); | |
251 | modcmd_init(); | |
252 | saxdb_init(); | |
1136f709 | 253 | sar_init(); |
d76ed9a9 | 254 | gline_init(); |
d914d1cb | 255 | shun_init(); |
1136f709 | 256 | mail_init(); |
d76ed9a9 | 257 | helpfile_init(); |
258 | conf_globals(); /* initializes the core services */ | |
259 | conf_rlimits(); | |
260 | modules_init(); | |
261 | message_register_table(msgtab); | |
262 | modcmd_finalize(); | |
263 | saxdb_finalize(); | |
264 | helpfile_finalize(); | |
265 | modules_finalize(); | |
266 | ||
267 | /* The first exit func to be called *should* be saxdb_write_all(). */ | |
30874d66 | 268 | reg_exit_func(saxdb_write_all, NULL); |
d76ed9a9 | 269 | if (replay_file) { |
270 | char *msg; | |
271 | log_module(MAIN_LOG, LOG_INFO, "Beginning replay..."); | |
272 | srand(now); | |
273 | replay_event_loop(); | |
274 | if ((msg = dict_sanity_check(clients))) { | |
275 | log_module(MAIN_LOG, LOG_ERROR, "Clients insanity: %s", msg); | |
276 | free(msg); | |
277 | } | |
278 | if ((msg = dict_sanity_check(channels))) { | |
279 | log_module(MAIN_LOG, LOG_ERROR, "Channels insanity: %s", msg); | |
280 | free(msg); | |
281 | } | |
282 | if ((msg = dict_sanity_check(servers))) { | |
283 | log_module(MAIN_LOG, LOG_ERROR, "Servers insanity: %s", msg); | |
284 | free(msg); | |
285 | } | |
286 | } else { | |
1136f709 | 287 | now = time(NULL); |
288 | srand(now); | |
d76ed9a9 | 289 | ioset_run(); |
290 | } | |
291 | return 0; | |
292 | } |