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

# 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.3 static char const rcsid[] = "$Id$";
7 pippijn 1.1
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 pippijn 1.2 "Rights to this code are documented in doc/pod/license.pod.\n",
41 pippijn 1.1 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     }