ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/main.C
Revision: 1.6
Committed: Tue Aug 28 22:18:31 2007 UTC (16 years, 9 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.5: +3 -3 lines
Log Message:
added type traits

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