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

# User Rev Content
1 pippijn 1.1 /*
2     * main.C: Initialisation routine.
3 pippijn 1.2 * Rights to this code are documented in doc/pod/license.pod.
4 pippijn 1.1 */
5    
6 pippijn 1.8 static char const rcsid[] = "$Id: main.C,v 1.7 2007-08-30 19:56:26 pippijn Exp $";
7 pippijn 1.1
8     #include "atheme.h"
9 pippijn 1.8 #include "servers.h"
10 pippijn 1.5 #include <ermyth/database.h>
11     #include <ermyth/module.h>
12 pippijn 1.1 #include <account/kline.h>
13 pippijn 1.5 #include <account/myuser.h>
14     #include <account/mynick.h>
15     #include <account/mychan.h>
16     #include "account.h" // XXX: expire_check
17 pippijn 1.1 #include "uplink.h"
18     #include "internal.h"
19     #include "datastream.h"
20     #include "authcookie.h"
21     #include "connection.h"
22     #include "confparse.h"
23 pippijn 1.5 #include <ermyth/shstr.h>
24     #include <common/random.h>
25    
26 pippijn 1.1 /* *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 pippijn 1.2 "Rights to this code are documented in doc/pod/license.pod.\n",
48 pippijn 1.1 version, creation, generation);
49     }
50     /* *INDENT-ON* */
51    
52     static void
53 pippijn 1.5 db_save (void *)
54 pippijn 1.1 {
55 pippijn 1.5 backend->save ();
56 pippijn 1.1 }
57    
58     int
59 pippijn 1.4 main (int argc, char *argv[], char *envp[])
60 pippijn 1.1 {
61     bool have_conf = false;
62     bool have_log = false;
63     char buf[32];
64     int i, pid, r;
65     FILE *pid_file;
66 pippijn 1.5 char const *pidfilename = RUNDIR "/" PACKAGE_NAME ".pid";
67 pippijn 1.1 #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 pippijn 1.5 // set up shstr buckets
83     std::vector<shentry *> *shstr_buckets = new std::vector<shentry *> [shstr::bucketcnt ()];
84     shstr::initbuckets (shstr_buckets);
85    
86 pippijn 1.1 /* 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 pippijn 1.5 me.start = time_t (now ());
152 pippijn 1.1 NOW = me.start;
153 pippijn 1.5 init_gen_rand (NOW);
154     srand (gen_rand32 ());
155 pippijn 1.1 me.execname = argv[0];
156    
157     /* set signal handlers */
158     init_signal_handlers ();
159    
160     /* open log */
161     log_open ();
162 pippijn 1.5
163 pippijn 1.1 printf ("%s: version " PACKAGE_NAME "-%s\n", me.execname, version);
164 pippijn 1.5
165 pippijn 1.1 /* check for pid file */
166     if ((pid_file = fopen (pidfilename, "r")))
167     {
168     if (fgets (buf, 32, pid_file))
169 pippijn 1.5 {
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 pippijn 1.1 fclose (pid_file);
180     }
181 pippijn 1.5
182 pippijn 1.1 #if HAVE_UMASK
183     /* file creation mask */
184     umask (077);
185     #endif
186 pippijn 1.5
187 pippijn 1.1 event_init ();
188     init_dlink_nodes ();
189     init_netio ();
190     init_socket_queues ();
191 pippijn 1.5
192 pippijn 1.1 init_nodes ();
193     init_newconf ();
194     servtree_init ();
195     init_ircpacket ();
196 pippijn 1.5
197 pippijn 1.1 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 pippijn 1.5
204 pippijn 1.1 authcookie_init ();
205     common_ctcp_init ();
206     update_chanacs_flags ();
207 pippijn 1.5
208     if (!database::handler::loaded)
209 pippijn 1.1 {
210 pippijn 1.5 fprintf (stderr, "%s: no backend loaded, see your configuration file.\n", me.execname);
211 pippijn 1.1 exit (EXIT_FAILURE);
212     }
213 pippijn 1.5
214 pippijn 1.1 /* check our config file */
215     if (!conf_check ())
216     exit (EXIT_FAILURE);
217 pippijn 1.5
218 pippijn 1.1 /* we've done the critical startup steps now */
219     cold_start = false;
220 pippijn 1.5
221 pippijn 1.1 /* load our db */
222 pippijn 1.5 if (database::handler::loaded)
223     backend->load ();
224 pippijn 1.1 else
225     {
226     /* XXX: We should have bailed by now! --nenolod */
227 pippijn 1.5 fprintf (stderr, "%s: no backend loaded, see your configuration file.\n", me.execname);
228 pippijn 1.1 exit (EXIT_FAILURE);
229     }
230     db_check ();
231 pippijn 1.5
232 pippijn 1.1 #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 pippijn 1.5 {
239     fprintf (stderr, "%s: unable to open /dev/null??\n", me.execname);
240     exit (EXIT_FAILURE);
241     }
242 pippijn 1.1 if ((i = fork ()) < 0)
243 pippijn 1.5 {
244     fprintf (stderr, "%s: can't fork into the background\n", me.execname);
245     exit (EXIT_FAILURE);
246     }
247    
248 pippijn 1.1 /* parent */
249     else if (i != 0)
250 pippijn 1.5 {
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 pippijn 1.1 /* parent is gone, just us now */
257     if (setsid () < 0)
258 pippijn 1.5 {
259     fprintf (stderr, "%s: unable to create new session\n", me.execname);
260     exit (EXIT_FAILURE);
261     }
262 pippijn 1.1 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 pippijn 1.5
274 pippijn 1.1 #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 pippijn 1.5
290 pippijn 1.1 /* we probably have a few open already... */
291     me.maxfd = 3;
292 pippijn 1.5
293 pippijn 1.1 /* DB commit interval is configurable */
294     event_add ("db_save", db_save, NULL, config_options.commit_interval);
295 pippijn 1.5
296 pippijn 1.1 /* check expires every hour */
297     event_add ("expire_check", expire_check, NULL, 3600);
298 pippijn 1.5
299 pippijn 1.1 /* check kline expires every minute */
300 pippijn 1.8 event_add ("kline_t::expire", kline_t::expire, NULL, 60);
301 pippijn 1.5
302 pippijn 1.1 /* check authcookie expires every ten minutes */
303     event_add ("authcookie_expire", authcookie_expire, NULL, 600);
304 pippijn 1.5
305 pippijn 1.1 me.connected = false;
306     uplink_connect ();
307    
308     /* main loop */
309     io_loop ();
310 pippijn 1.5
311 pippijn 1.1 /* we're shutting down */
312 pippijn 1.5 backend->save ();
313 pippijn 1.1 if (chansvs.me != NULL && chansvs.me->me != NULL)
314 pippijn 1.5 phandler->quit_sts (chansvs.me->me, "shutting down");
315    
316 pippijn 1.1 remove (pidfilename);
317     errno = 0;
318     if (curr_uplink != NULL && curr_uplink->conn != NULL)
319     sendq_flush (curr_uplink->conn);
320 pippijn 1.7 connection_t::close_all ();
321 pippijn 1.1
322     me.connected = false;
323 pippijn 1.5
324 pippijn 1.1 /* should we restart? */
325     if (runflags & RF_RESTART)
326     {
327     slog (LG_INFO, "main(): restarting");
328    
329     #ifdef HAVE_EXECVE
330 pippijn 1.4 execve (me.execname, argv, envp);
331 pippijn 1.1 #endif
332     }
333 pippijn 1.5
334 pippijn 1.1 slog (LG_INFO, "main(): shutting down");
335    
336 pippijn 1.5 /* free used memory */
337     shstr::cleanup ();
338     modules::cleanup ();
339 pippijn 1.6 myuser_t::cleanup (); // XXX: this currently breaks and I don't know why
340 pippijn 1.8 mynick_t::cleanup ();
341 pippijn 1.7 mychan_t::cleanup ();
342 pippijn 1.5 delete phandler;
343 pippijn 1.8 deinit_conf ();
344     server_delete (me.me, true);
345 pippijn 1.5
346 pippijn 1.1 log_shutdown ();
347    
348     return 0;
349     }