ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/src/main.C
Revision: 1.9
Committed: Sun Sep 16 18:54:45 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.8: +8 -1 lines
Log Message:
#defines to enum

File Contents

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