ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/main.C
Revision: 1.3
Committed: Sat Jul 21 13:23:22 2007 UTC (16 years, 10 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.2: +1 -1 lines
Log Message:
- added rcsid to some files
- more documentation tweaks
- made most protocol commands local to phandler.C
- added ircd metadata (inspircd only for now)
- added inspircd swhois support

File Contents

# Content
1 /*
2 * main.C: Initialisation routine.
3 * Rights to this code are documented in doc/pod/license.pod.
4 */
5
6 static char const rcsid[] = "$Id$";
7
8 #include "atheme.h"
9 #include <account/kline.h>
10 #include "account.h" // XXX: backend_loaded / db_load / db_check / expire_check
11 #include "uplink.h"
12 #include "pmodule.h" /* pcommand_init */
13 #include "internal.h"
14 #include "datastream.h"
15 #include "authcookie.h"
16 #include "connection.h"
17 #include "confparse.h"
18
19 /* *INDENT-OFF* */
20 static void
21 print_help (void)
22 {
23 printf ("usage: %s [-dhnv] [-c conf] [-l logfile] [-p pidfile]\n\n"
24 "-c <file> Specify the config file\n"
25 "-d Start in debugging mode\n"
26 "-h Print this message and exit\n"
27 "-l <file> Specify the log file\n"
28 "-n Don't fork into the background (log screen + log file)\n"
29 "-p <file> Specify the pid file (will be overwritten)\n"
30 "-v Print version information and exit\n", me.execname);
31 }
32
33 static void
34 print_version (void)
35 {
36 printf ("Ermyth IRC Services (" PACKAGE_NAME "-%s)\n"
37 "Compiled %s, build %s\n\n"
38 "Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team\n"
39 "Copyright © 2005-2007 Atheme Development Group\n"
40 "Rights to this code are documented in doc/pod/license.pod.\n",
41 version, creation, generation);
42 }
43 /* *INDENT-ON* */
44
45 static void
46 rng_reseed (void *unused)
47 {
48 arc4random_addrandom ((uint8_t *) & cnt, sizeof cnt);
49 }
50
51 int
52 main (int argc, char *argv[])
53 {
54 bool have_conf = false;
55 bool have_log = false;
56 char buf[32];
57 int i, pid, r;
58 FILE *pid_file;
59 char *pidfilename = RUNDIR "/" PACKAGE_NAME ".pid";
60 #ifdef HAVE_GETRLIMIT
61 struct rlimit rlim;
62 #endif
63 curr_uplink = NULL;
64 me.argc = argc;
65 me.argv = argv;
66 me.execname = argv[0];
67
68 /* Prepare gettext */
69 #ifdef ENABLE_NLS
70 setlocale (LC_ALL, "");
71 bindtextdomain (PACKAGE_NAME, LOCALEDIR);
72 textdomain (PACKAGE_NAME);
73 #endif
74
75 /* change to our local directory */
76 if (chdir (PREFIX) < 0)
77 {
78 perror (PREFIX);
79 return 20;
80 }
81
82 #ifdef HAVE_GETRLIMIT
83 /* it appears certian systems *ahem*linux*ahem*
84 * don't dump cores by default, so we do this here.
85 */
86 if (!getrlimit (RLIMIT_CORE, &rlim))
87 {
88 rlim.rlim_cur = rlim.rlim_max;
89 setrlimit (RLIMIT_CORE, &rlim);
90 }
91 #endif
92
93 /* do command-line options */
94 while ((r = getopt (argc, argv, "c:dhl:np:v")) != -1)
95 {
96 switch (r)
97 {
98 case 'c':
99 config_file = sstrdup (optarg);
100 have_conf = true;
101 break;
102 case 'd':
103 log_force = true;
104 break;
105 case 'h':
106 print_help ();
107 exit (EXIT_SUCCESS);
108 break;
109 case 'l':
110 log_path = sstrdup (optarg);
111 have_log = true;
112 break;
113 case 'n':
114 runflags |= RF_LIVE;
115 break;
116 case 'p':
117 pidfilename = optarg;
118 break;
119 case 'v':
120 print_version ();
121 exit (EXIT_SUCCESS);
122 break;
123 default:
124 printf ("usage: %s [-dhnv] [-c conf] [-l logfile] [-p pidfile]\n", me.execname);
125 exit (EXIT_SUCCESS);
126 break;
127 }
128 }
129
130 if (have_conf == false)
131 config_file = sstrdup (SYSCONFDIR "/" PACKAGE_NAME ".conf");
132
133 if (have_log == false)
134 log_path = sstrdup (LOGDIR "/" PACKAGE_NAME ".log");
135
136 cold_start = true;
137
138 runflags |= RF_STARTING;
139
140 me.start = time (NULL);
141 NOW = me.start;
142 srand (arc4random ());
143 me.execname = argv[0];
144
145 /* set signal handlers */
146 init_signal_handlers ();
147
148 /* open log */
149 log_open ();
150
151 printf ("%s: version " PACKAGE_NAME "-%s\n", me.execname, version);
152
153 /* check for pid file */
154 if ((pid_file = fopen (pidfilename, "r")))
155 {
156 if (fgets (buf, 32, pid_file))
157 {
158 pid = atoi (buf);
159
160 if (!kill (pid, 0))
161 {
162 fprintf (stderr, "%s: daemon is already running\n", me.execname);
163 exit (EXIT_FAILURE);
164 }
165 }
166
167 fclose (pid_file);
168 }
169
170 #if HAVE_UMASK
171 /* file creation mask */
172 umask (077);
173 #endif
174
175 event_init ();
176 initBlockHeap ();
177 init_dlink_nodes ();
178 hooks_init ();
179 init_netio ();
180 init_socket_queues ();
181
182 init_nodes ();
183 init_newconf ();
184 servtree_init ();
185 init_ircpacket ();
186
187 modules_init ();
188 pcommand_init ();
189
190 conf_init ();
191 if (!conf_parse (config_file))
192 {
193 slog (LG_ERROR, "Error loading config file %s, aborting", config_file);
194 exit (EXIT_FAILURE);
195 }
196
197 authcookie_init ();
198 common_ctcp_init ();
199 update_chanacs_flags ();
200
201 if (!backend_loaded)
202 {
203 fprintf (stderr, "%s: no backend modules loaded, see your configuration file.\n", me.execname);
204 exit (EXIT_FAILURE);
205 }
206
207 /* check our config file */
208 if (!conf_check ())
209 exit (EXIT_FAILURE);
210
211 /* we've done the critical startup steps now */
212 cold_start = false;
213
214 /* load our db */
215 if (db_load)
216 db_load ();
217 else
218 {
219 /* XXX: We should have bailed by now! --nenolod */
220 fprintf (stderr, "%s: no backend modules loaded, see your configuration file.\n", me.execname);
221 exit (EXIT_FAILURE);
222 }
223 db_check ();
224
225 #ifdef HAVE_FORK
226 /* fork into the background */
227 if (!(runflags & RF_LIVE))
228 {
229 close (0);
230 if (open ("/dev/null", O_RDWR) != 0)
231 {
232 fprintf (stderr, "%s: unable to open /dev/null??\n", me.execname);
233 exit (EXIT_FAILURE);
234 }
235 if ((i = fork ()) < 0)
236 {
237 fprintf (stderr, "%s: can't fork into the background\n", me.execname);
238 exit (EXIT_FAILURE);
239 }
240
241 /* parent */
242 else if (i != 0)
243 {
244 printf ("%s: pid %d\n", me.execname, i);
245 printf ("%s: running in background mode from " PREFIX "\n", me.execname);
246 exit (EXIT_SUCCESS);
247 }
248
249 /* parent is gone, just us now */
250 if (setsid () < 0)
251 {
252 fprintf (stderr, "%s: unable to create new session\n", me.execname);
253 exit (EXIT_FAILURE);
254 }
255 dup2 (0, 1);
256 dup2 (0, 2);
257 }
258 else
259 {
260 printf ("%s: pid %d\n", me.execname, getpid ());
261 printf ("%s: running in foreground mode from %s\n", me.execname, PREFIX);
262 }
263 #else
264 printf ("%s: running in foreground mode from %s\n", me.execname, PREFIX);
265 #endif
266
267 #ifdef HAVE_GETPID
268 /* write pid */
269 if ((pid_file = fopen (pidfilename, "w")))
270 {
271 fprintf (pid_file, "%d\n", getpid ());
272 fclose (pid_file);
273 }
274 else
275 {
276 fprintf (stderr, "%s: unable to write pid file\n", me.execname);
277 exit (EXIT_FAILURE);
278 }
279 #endif
280 /* no longer starting */
281 runflags &= ~RF_STARTING;
282
283 /* we probably have a few open already... */
284 me.maxfd = 3;
285
286 /* DB commit interval is configurable */
287 event_add ("db_save", db_save, NULL, config_options.commit_interval);
288
289 /* check expires every hour */
290 event_add ("expire_check", expire_check, NULL, 3600);
291
292 /* check kline expires every minute */
293 event_add ("kline_expire", kline_expire, NULL, 60);
294
295 /* check authcookie expires every ten minutes */
296 event_add ("authcookie_expire", authcookie_expire, NULL, 600);
297
298 /* reseed rng a little every five minutes */
299 event_add ("rng_reseed", rng_reseed, NULL, 293);
300
301 me.connected = false;
302 uplink_connect ();
303
304 /* main loop */
305 io_loop ();
306
307 /* we're shutting down */
308 db_save (NULL);
309 if (chansvs.me != NULL && chansvs.me->me != NULL)
310 quit_sts (chansvs.me->me, "shutting down");
311
312 remove (pidfilename);
313 errno = 0;
314 if (curr_uplink != NULL && curr_uplink->conn != NULL)
315 sendq_flush (curr_uplink->conn);
316 connection_close_all ();
317
318 me.connected = false;
319
320 /* should we restart? */
321 if (runflags & RF_RESTART)
322 {
323 slog (LG_INFO, "main(): restarting");
324
325 #ifdef HAVE_EXECVE
326 execve (me.execname, argv, environ);
327 #endif
328 }
329
330 slog (LG_INFO, "main(): shutting down");
331
332 // unload all modules
333 {
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
346 return 0;
347 }