1 | /* |
1 | /* |
2 | * main.C: Initialisation routine. |
2 | * main.C: Initialisation routine. |
3 | * Rights to this code are documented in doc/pod/license.pod. |
3 | * Rights to this code are documented in doc/pod/license.pod. |
4 | */ |
4 | */ |
5 | |
5 | |
6 | static char const rcsid[] = "$Id: main.C,v 1.4 2007/07/21 15:55:13 pippijn Exp $"; |
6 | static char const rcsid[] = "$Id: main.C,v 1.5 2007/08/28 17:08:12 pippijn Exp $"; |
7 | |
7 | |
8 | #include "atheme.h" |
8 | #include "atheme.h" |
|
|
9 | #include <ermyth/database.h> |
|
|
10 | #include <ermyth/module.h> |
9 | #include <account/kline.h> |
11 | #include <account/kline.h> |
10 | #include "account.h" // XXX: backend_loaded / db_load / db_check / expire_check |
12 | #include <account/myuser.h> |
|
|
13 | #include <account/mynick.h> |
|
|
14 | #include <account/mychan.h> |
|
|
15 | #include "account.h" // XXX: expire_check |
11 | #include "uplink.h" |
16 | #include "uplink.h" |
12 | #include "pmodule.h" /* pcommand_init */ |
|
|
13 | #include "internal.h" |
17 | #include "internal.h" |
14 | #include "datastream.h" |
18 | #include "datastream.h" |
15 | #include "authcookie.h" |
19 | #include "authcookie.h" |
16 | #include "connection.h" |
20 | #include "connection.h" |
17 | #include "confparse.h" |
21 | #include "confparse.h" |
|
|
22 | #include <ermyth/shstr.h> |
|
|
23 | #include <common/random.h> |
|
|
24 | |
|
|
25 | extern char **environ; |
18 | |
26 | |
19 | /* *INDENT-OFF* */ |
27 | /* *INDENT-OFF* */ |
20 | static void |
28 | static void |
21 | print_help (void) |
29 | print_help (void) |
22 | { |
30 | { |
… | |
… | |
41 | version, creation, generation); |
49 | version, creation, generation); |
42 | } |
50 | } |
43 | /* *INDENT-ON* */ |
51 | /* *INDENT-ON* */ |
44 | |
52 | |
45 | static void |
53 | static void |
46 | rng_reseed (void *unused) |
54 | db_save (void *) |
47 | { |
55 | { |
48 | arc4random_addrandom ((uint8_t *) & cnt, sizeof cnt); |
56 | backend->save (); |
49 | } |
57 | } |
50 | |
58 | |
51 | int |
59 | int |
52 | main (int argc, char *argv[], char *envp[]) |
60 | main (int argc, char *argv[], char *envp[]) |
53 | { |
61 | { |
54 | bool have_conf = false; |
62 | bool have_conf = false; |
55 | bool have_log = false; |
63 | bool have_log = false; |
56 | char buf[32]; |
64 | char buf[32]; |
57 | int i, pid, r; |
65 | int i, pid, r; |
58 | FILE *pid_file; |
66 | FILE *pid_file; |
59 | char *pidfilename = RUNDIR "/" PACKAGE_NAME ".pid"; |
67 | char const *pidfilename = RUNDIR "/" PACKAGE_NAME ".pid"; |
60 | #ifdef HAVE_GETRLIMIT |
68 | #ifdef HAVE_GETRLIMIT |
61 | struct rlimit rlim; |
69 | struct rlimit rlim; |
62 | #endif |
70 | #endif |
63 | curr_uplink = NULL; |
71 | curr_uplink = NULL; |
64 | me.argc = argc; |
72 | me.argc = argc; |
… | |
… | |
70 | setlocale (LC_ALL, ""); |
78 | setlocale (LC_ALL, ""); |
71 | bindtextdomain (PACKAGE_NAME, LOCALEDIR); |
79 | bindtextdomain (PACKAGE_NAME, LOCALEDIR); |
72 | textdomain (PACKAGE_NAME); |
80 | textdomain (PACKAGE_NAME); |
73 | #endif |
81 | #endif |
74 | |
82 | |
|
|
83 | // set up shstr buckets |
|
|
84 | std::vector<shentry *> *shstr_buckets = new std::vector<shentry *> [shstr::bucketcnt ()]; |
|
|
85 | shstr::initbuckets (shstr_buckets); |
|
|
86 | |
75 | /* change to our local directory */ |
87 | /* change to our local directory */ |
76 | if (chdir (PREFIX) < 0) |
88 | if (chdir (PREFIX) < 0) |
77 | { |
89 | { |
78 | perror (PREFIX); |
90 | perror (PREFIX); |
79 | return 20; |
91 | return 20; |
… | |
… | |
135 | |
147 | |
136 | cold_start = true; |
148 | cold_start = true; |
137 | |
149 | |
138 | runflags |= RF_STARTING; |
150 | runflags |= RF_STARTING; |
139 | |
151 | |
140 | me.start = time (NULL); |
152 | me.start = time_t (now ()); |
141 | NOW = me.start; |
153 | NOW = me.start; |
|
|
154 | init_gen_rand (NOW); |
142 | srand (arc4random ()); |
155 | srand (gen_rand32 ()); |
143 | me.execname = argv[0]; |
156 | me.execname = argv[0]; |
144 | |
157 | |
145 | /* set signal handlers */ |
158 | /* set signal handlers */ |
146 | init_signal_handlers (); |
159 | init_signal_handlers (); |
147 | |
160 | |
148 | /* open log */ |
161 | /* open log */ |
149 | log_open (); |
162 | log_open (); |
150 | |
163 | |
151 | printf ("%s: version " PACKAGE_NAME "-%s\n", me.execname, version); |
164 | printf ("%s: version " PACKAGE_NAME "-%s\n", me.execname, version); |
152 | |
165 | |
153 | /* check for pid file */ |
166 | /* check for pid file */ |
154 | if ((pid_file = fopen (pidfilename, "r"))) |
167 | if ((pid_file = fopen (pidfilename, "r"))) |
155 | { |
168 | { |
156 | if (fgets (buf, 32, pid_file)) |
169 | if (fgets (buf, 32, pid_file)) |
157 | { |
170 | { |
158 | pid = atoi (buf); |
171 | pid = atoi (buf); |
159 | |
172 | |
160 | if (!kill (pid, 0)) |
173 | if (!kill (pid, 0)) |
161 | { |
174 | { |
162 | fprintf (stderr, "%s: daemon is already running\n", me.execname); |
175 | fprintf (stderr, "%s: daemon is already running\n", me.execname); |
163 | exit (EXIT_FAILURE); |
176 | exit (EXIT_FAILURE); |
164 | } |
177 | } |
165 | } |
178 | } |
166 | |
179 | |
167 | fclose (pid_file); |
180 | fclose (pid_file); |
168 | } |
181 | } |
169 | |
182 | |
170 | #if HAVE_UMASK |
183 | #if HAVE_UMASK |
171 | /* file creation mask */ |
184 | /* file creation mask */ |
172 | umask (077); |
185 | umask (077); |
173 | #endif |
186 | #endif |
174 | |
187 | |
175 | event_init (); |
188 | event_init (); |
176 | initBlockHeap (); |
|
|
177 | init_dlink_nodes (); |
189 | init_dlink_nodes (); |
178 | hooks_init (); |
|
|
179 | init_netio (); |
190 | init_netio (); |
180 | init_socket_queues (); |
191 | init_socket_queues (); |
181 | |
192 | |
182 | init_nodes (); |
193 | init_nodes (); |
183 | init_newconf (); |
194 | init_newconf (); |
184 | servtree_init (); |
195 | servtree_init (); |
185 | init_ircpacket (); |
196 | init_ircpacket (); |
186 | |
197 | |
187 | modules_init (); |
|
|
188 | pcommand_init (); |
|
|
189 | |
|
|
190 | conf_init (); |
198 | conf_init (); |
191 | if (!conf_parse (config_file)) |
199 | if (!conf_parse (config_file)) |
192 | { |
200 | { |
193 | slog (LG_ERROR, "Error loading config file %s, aborting", config_file); |
201 | slog (LG_ERROR, "Error loading config file %s, aborting", config_file); |
194 | exit (EXIT_FAILURE); |
202 | exit (EXIT_FAILURE); |
195 | } |
203 | } |
196 | |
204 | |
197 | authcookie_init (); |
205 | authcookie_init (); |
198 | common_ctcp_init (); |
206 | common_ctcp_init (); |
199 | update_chanacs_flags (); |
207 | update_chanacs_flags (); |
200 | |
208 | |
201 | if (!backend_loaded) |
209 | if (!database::handler::loaded) |
202 | { |
210 | { |
203 | fprintf (stderr, "%s: no backend modules loaded, see your configuration file.\n", me.execname); |
211 | fprintf (stderr, "%s: no backend loaded, see your configuration file.\n", me.execname); |
204 | exit (EXIT_FAILURE); |
212 | exit (EXIT_FAILURE); |
205 | } |
213 | } |
206 | |
214 | |
207 | /* check our config file */ |
215 | /* check our config file */ |
208 | if (!conf_check ()) |
216 | if (!conf_check ()) |
209 | exit (EXIT_FAILURE); |
217 | exit (EXIT_FAILURE); |
210 | |
218 | |
211 | /* we've done the critical startup steps now */ |
219 | /* we've done the critical startup steps now */ |
212 | cold_start = false; |
220 | cold_start = false; |
213 | |
221 | |
214 | /* load our db */ |
222 | /* load our db */ |
215 | if (db_load) |
223 | if (database::handler::loaded) |
216 | db_load (); |
224 | backend->load (); |
217 | else |
225 | else |
218 | { |
226 | { |
219 | /* XXX: We should have bailed by now! --nenolod */ |
227 | /* XXX: We should have bailed by now! --nenolod */ |
220 | fprintf (stderr, "%s: no backend modules loaded, see your configuration file.\n", me.execname); |
228 | fprintf (stderr, "%s: no backend loaded, see your configuration file.\n", me.execname); |
221 | exit (EXIT_FAILURE); |
229 | exit (EXIT_FAILURE); |
222 | } |
230 | } |
223 | db_check (); |
231 | db_check (); |
224 | |
232 | |
225 | #ifdef HAVE_FORK |
233 | #ifdef HAVE_FORK |
226 | /* fork into the background */ |
234 | /* fork into the background */ |
227 | if (!(runflags & RF_LIVE)) |
235 | if (!(runflags & RF_LIVE)) |
228 | { |
236 | { |
229 | close (0); |
237 | close (0); |
230 | if (open ("/dev/null", O_RDWR) != 0) |
238 | if (open ("/dev/null", O_RDWR) != 0) |
231 | { |
239 | { |
232 | fprintf (stderr, "%s: unable to open /dev/null??\n", me.execname); |
240 | fprintf (stderr, "%s: unable to open /dev/null??\n", me.execname); |
233 | exit (EXIT_FAILURE); |
241 | exit (EXIT_FAILURE); |
234 | } |
242 | } |
235 | if ((i = fork ()) < 0) |
243 | if ((i = fork ()) < 0) |
236 | { |
244 | { |
237 | fprintf (stderr, "%s: can't fork into the background\n", me.execname); |
245 | fprintf (stderr, "%s: can't fork into the background\n", me.execname); |
238 | exit (EXIT_FAILURE); |
246 | exit (EXIT_FAILURE); |
239 | } |
247 | } |
240 | |
248 | |
241 | /* parent */ |
249 | /* parent */ |
242 | else if (i != 0) |
250 | else if (i != 0) |
243 | { |
251 | { |
244 | printf ("%s: pid %d\n", me.execname, i); |
252 | printf ("%s: pid %d\n", me.execname, i); |
245 | printf ("%s: running in background mode from " PREFIX "\n", me.execname); |
253 | printf ("%s: running in background mode from " PREFIX "\n", me.execname); |
246 | exit (EXIT_SUCCESS); |
254 | exit (EXIT_SUCCESS); |
247 | } |
255 | } |
248 | |
256 | |
249 | /* parent is gone, just us now */ |
257 | /* parent is gone, just us now */ |
250 | if (setsid () < 0) |
258 | if (setsid () < 0) |
251 | { |
259 | { |
252 | fprintf (stderr, "%s: unable to create new session\n", me.execname); |
260 | fprintf (stderr, "%s: unable to create new session\n", me.execname); |
253 | exit (EXIT_FAILURE); |
261 | exit (EXIT_FAILURE); |
254 | } |
262 | } |
255 | dup2 (0, 1); |
263 | dup2 (0, 1); |
256 | dup2 (0, 2); |
264 | dup2 (0, 2); |
257 | } |
265 | } |
258 | else |
266 | else |
259 | { |
267 | { |
… | |
… | |
261 | printf ("%s: running in foreground mode from %s\n", me.execname, PREFIX); |
269 | printf ("%s: running in foreground mode from %s\n", me.execname, PREFIX); |
262 | } |
270 | } |
263 | #else |
271 | #else |
264 | printf ("%s: running in foreground mode from %s\n", me.execname, PREFIX); |
272 | printf ("%s: running in foreground mode from %s\n", me.execname, PREFIX); |
265 | #endif |
273 | #endif |
266 | |
274 | |
267 | #ifdef HAVE_GETPID |
275 | #ifdef HAVE_GETPID |
268 | /* write pid */ |
276 | /* write pid */ |
269 | if ((pid_file = fopen (pidfilename, "w"))) |
277 | if ((pid_file = fopen (pidfilename, "w"))) |
270 | { |
278 | { |
271 | fprintf (pid_file, "%d\n", getpid ()); |
279 | fprintf (pid_file, "%d\n", getpid ()); |
… | |
… | |
277 | exit (EXIT_FAILURE); |
285 | exit (EXIT_FAILURE); |
278 | } |
286 | } |
279 | #endif |
287 | #endif |
280 | /* no longer starting */ |
288 | /* no longer starting */ |
281 | runflags &= ~RF_STARTING; |
289 | runflags &= ~RF_STARTING; |
282 | |
290 | |
283 | /* we probably have a few open already... */ |
291 | /* we probably have a few open already... */ |
284 | me.maxfd = 3; |
292 | me.maxfd = 3; |
285 | |
293 | |
286 | /* DB commit interval is configurable */ |
294 | /* DB commit interval is configurable */ |
287 | event_add ("db_save", db_save, NULL, config_options.commit_interval); |
295 | event_add ("db_save", db_save, NULL, config_options.commit_interval); |
288 | |
296 | |
289 | /* check expires every hour */ |
297 | /* check expires every hour */ |
290 | event_add ("expire_check", expire_check, NULL, 3600); |
298 | event_add ("expire_check", expire_check, NULL, 3600); |
291 | |
299 | |
292 | /* check kline expires every minute */ |
300 | /* check kline expires every minute */ |
293 | event_add ("kline_expire", kline_expire, NULL, 60); |
301 | event_add ("kline_expire", kline_expire, NULL, 60); |
294 | |
302 | |
295 | /* check authcookie expires every ten minutes */ |
303 | /* check authcookie expires every ten minutes */ |
296 | event_add ("authcookie_expire", authcookie_expire, NULL, 600); |
304 | event_add ("authcookie_expire", authcookie_expire, NULL, 600); |
297 | |
305 | |
298 | /* reseed rng a little every five minutes */ |
|
|
299 | event_add ("rng_reseed", rng_reseed, NULL, 293); |
|
|
300 | |
|
|
301 | me.connected = false; |
306 | me.connected = false; |
302 | uplink_connect (); |
307 | uplink_connect (); |
303 | |
308 | |
304 | /* main loop */ |
309 | /* main loop */ |
305 | io_loop (); |
310 | io_loop (); |
306 | |
311 | |
307 | /* we're shutting down */ |
312 | /* we're shutting down */ |
308 | db_save (NULL); |
313 | backend->save (); |
309 | if (chansvs.me != NULL && chansvs.me->me != NULL) |
314 | if (chansvs.me != NULL && chansvs.me->me != NULL) |
310 | quit_sts (chansvs.me->me, "shutting down"); |
315 | phandler->quit_sts (chansvs.me->me, "shutting down"); |
311 | |
316 | |
312 | remove (pidfilename); |
317 | remove (pidfilename); |
313 | errno = 0; |
318 | errno = 0; |
314 | if (curr_uplink != NULL && curr_uplink->conn != NULL) |
319 | if (curr_uplink != NULL && curr_uplink->conn != NULL) |
315 | sendq_flush (curr_uplink->conn); |
320 | sendq_flush (curr_uplink->conn); |
316 | connection_close_all (); |
321 | connection_close_all (); |
317 | |
322 | |
318 | me.connected = false; |
323 | me.connected = false; |
319 | |
324 | |
320 | /* should we restart? */ |
325 | /* should we restart? */ |
321 | if (runflags & RF_RESTART) |
326 | if (runflags & RF_RESTART) |
322 | { |
327 | { |
323 | slog (LG_INFO, "main(): restarting"); |
328 | slog (LG_INFO, "main(): restarting"); |
324 | |
329 | |
325 | #ifdef HAVE_EXECVE |
330 | #ifdef HAVE_EXECVE |
326 | execve (me.execname, argv, envp); |
331 | execve (me.execname, argv, envp); |
327 | #endif |
332 | #endif |
328 | } |
333 | } |
329 | |
334 | |
330 | slog (LG_INFO, "main(): shutting down"); |
335 | slog (LG_INFO, "main(): shutting down"); |
331 | |
336 | |
332 | // unload all modules |
337 | /* free used memory */ |
|
|
338 | shstr::cleanup (); |
|
|
339 | modules::cleanup (); |
|
|
340 | mychan_cleanup (); |
|
|
341 | mynick_cleanup (); |
|
|
342 | myuser_cleanup (); |
|
|
343 | delete phandler; |
333 | { |
344 | |
334 | node_t *n; |
|
|
335 | extern list_t modules; |
|
|
336 | LIST_FOREACH (n, modules.head) |
|
|
337 | { |
|
|
338 | module_t *m = static_cast<module_t *> (n->data); |
|
|
339 | if (!m->header->norestart) |
|
|
340 | module_unload (m); |
|
|
341 | } |
|
|
342 | } |
|
|
343 | |
|
|
344 | log_shutdown (); |
345 | log_shutdown (); |
345 | |
346 | |
346 | return 0; |
347 | return 0; |
347 | } |
348 | } |