ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/src/main.C
Revision: 1.8
Committed: Sun Sep 9 20:05:52 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.7: +6 -5 lines
Log Message:
- changed configurations to the c++ stdlib
- more #defines to enum
- removed getopt.h and link.h from the system as they were unused
- reworked logstreams
- added an itoa with old syntax
- made klines objects
- moved some global variables into appropriate classes
- fixed boost.foreach's compiler workaround #if's
- allow other files to add exceptions with ADD_EXCEPTION
- changed mynick_t to c++ object
- moved servers.h out of atheme.h
- corrected PING from inspircd 1.2

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