2 * Copyright 2000-2006 srvx Development Team
4 * This file is part of srvx.
6 * srvx is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with srvx; if not, write to the Free Software Foundation,
18 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
21 #define PID_FILE "srvx.pid"
41 #ifdef HAVE_SYS_RESOURCE_H
42 #include <sys/resource.h>
44 #ifdef HAVE_NETINET_IN_H
45 #include <netinet/in.h>
47 #ifdef HAVE_SYS_SOCKET_H
48 #include <sys/socket.h>
50 #ifdef HAVE_SYS_WAIT_H
55 #define SIGCHLD SIGCLD
58 #include "main-common.c"
60 void sigaction_writedb(int x)
62 #ifndef HAVE_STRSIGNAL
63 log_module(MAIN_LOG, LOG_INFO, "Signal %d -- writing databases.", x);
65 log_module(MAIN_LOG, LOG_INFO, "%s -- writing databases.", strsignal(x));
70 void sigaction_exit(int x)
72 #ifndef HAVE_STRSIGNAL
73 log_module(MAIN_LOG, LOG_INFO, "Signal %d -- exiting.", x);
75 log_module(MAIN_LOG, LOG_INFO, "%s -- exiting.", strsignal(x));
77 irc_squit(self, "Exiting on signal from console.", NULL);
81 void sigaction_wait(UNUSED_ARG(int x))
84 wait4(-1, &code, WNOHANG, NULL);
87 void sigaction_rehash(int x)
89 #ifndef HAVE_STRSIGNAL
90 log_module(MAIN_LOG, LOG_INFO, "Signal %d -- rehashing.", x);
92 log_module(MAIN_LOG, LOG_INFO, "%s -- rehashing.", strsignal(x));
97 void usage(char *self) {
98 /* We can assume we have getopt_long(). */
99 printf("Usage: %s [-c config] [-r log] [-d] [-f] [-v|-h]\n"
100 "-c, --config selects a different configuration file.\n"
101 "-d, --debug enables debug mode.\n"
102 "-f, --foreground run srvx in the foreground.\n"
103 "-h, --help prints this usage message.\n"
104 "-k, --check checks the configuration file's syntax.\n"
105 "-r, --replay replay a log file (for debugging)\n"
106 "-v, --version prints this program's version.\n"
111 printf(" --------------------------------------------------\n"
112 " - "PACKAGE_STRING" ("CODENAME"), Built: " __DATE__ ", " __TIME__".\n"
113 " - Copyright (C) 2000 - 2005, srvx Development Team\n"
114 " --------------------------------------------------\n");
119 "This program is free software; you can redistribute it and/or modify\n"
120 "it under the terms of the GNU General Public License as published by\n"
121 "the Free Software Foundation; either version 2 of the License, or\n"
122 "(at your option) any later version.\n"
124 "This program is distributed in the hope that it will be useful,\n"
125 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
126 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
127 "GNU General Public License for more details.\n"
129 "You should have received a copy of the GNU General Public License\n"
130 "along with this program; if not, write to the Free Software\n"
131 "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n");
134 #if WITH_MALLOC_BOEHM_GC
136 gc_warn_proc(char *msg, GC_word arg)
138 log_module(MAIN_LOG, LOG_ERROR, "GC(%p): %s", (void*)arg, msg);
142 int main(int argc, char *argv[])
149 #if WITH_MALLOC_BOEHM_GC
151 GC_set_warn_proc(gc_warn_proc);
152 GC_enable_incremental();
159 /* set up some signal handlers */
160 memset(&sv, 0, sizeof(sv));
161 sigemptyset(&sv.sa_mask);
162 sv.sa_handler = SIG_IGN;
163 sigaction(SIGPIPE, &sv, NULL);
164 sv.sa_handler = sigaction_rehash;
165 sigaction(SIGHUP, &sv, NULL);
166 sv.sa_handler = sigaction_writedb;
167 sigaction(SIGINT, &sv, NULL);
168 sv.sa_handler = sigaction_exit;
169 sigaction(SIGQUIT, &sv, NULL);
170 sv.sa_handler = sigaction_wait;
171 sigaction(SIGCHLD, &sv, NULL);
173 if (argc > 1) { /* parse command line, if any */
175 struct option options[] =
177 {"config", 1, 0, 'c'},
178 {"debug", 0, 0, 'd'},
179 {"foreground", 0, 0, 'f'},
181 {"check", 0, 0, 'k'},
182 {"replay", 1, 0, 'r'},
183 {"version", 0, 0, 'v'},
184 {"verbose", 0, 0, 'V'},
188 while ((c = getopt_long(argc, argv, "c:kr:dfvVh", options, NULL)) != -1) {
191 services_config = optarg;
194 if (conf_read(services_config)) {
195 printf("%s appears to be a valid configuration file.\n", services_config);
197 printf("%s is an invalid configuration file.\n", services_config);
201 replay_file = fopen(optarg, "r");
203 fprintf(stderr, "Could not open %s for reading: %s (%d)\n",
204 optarg, strerror(errno), errno);
229 /* We read a line here to "prime" the replay file parser, but
230 * mostly to get the right value of "now" for when we do the
235 boot_time = time(&now);
238 fprintf(stdout, "Initializing daemon...\n");
239 if (!conf_read(services_config)) {
240 fprintf(stderr, "Unable to read %s.\n", services_config);
244 conf_register_reload(uplink_compile);
247 /* Attempt to fork into the background if daemon mode is on. */
250 fprintf(stderr, "Unable to fork: %s\n", strerror(errno));
251 } else if (pid > 0) {
252 fprintf(stdout, "Forking into the background (pid: %d)...", pid);
258 file_out = fopen(PID_FILE, "w");
259 if (file_out == NULL) {
260 /* Create the main process' pid file */
261 fprintf(stderr, "Unable to create PID file: %s", strerror(errno));
263 fprintf(file_out, "%i\n", (int)getpid());
268 /* Close these since we should not use them from now on. */
274 services_argc = argc;
275 services_argv = argv;
277 atexit(call_exit_funcs);
278 reg_exit_func(main_shutdown);
281 MAIN_LOG = log_register_type("srvx", "file:main.log");
292 conf_globals(); /* initializes the core services */
295 message_register_table(msgtab);
301 /* The first exit func to be called *should* be saxdb_write_all(). */
302 reg_exit_func(saxdb_write_all);
305 log_module(MAIN_LOG, LOG_INFO, "Beginning replay...");
308 if ((msg = dict_sanity_check(clients))) {
309 log_module(MAIN_LOG, LOG_ERROR, "Clients insanity: %s", msg);
312 if ((msg = dict_sanity_check(channels))) {
313 log_module(MAIN_LOG, LOG_ERROR, "Channels insanity: %s", msg);
316 if ((msg = dict_sanity_check(servers))) {
317 log_module(MAIN_LOG, LOG_ERROR, "Servers insanity: %s", msg);