+ bool ok, configtest = false;
+ bool NGIRCd_NoDaemon = false;
+ int i;
+ size_t n;
+
+#if defined(DEBUG) && defined(HAVE_MTRACE)
+ /* enable GNU libc memory tracing when running in debug mode
+ * and functionality available */
+ mtrace();
+#endif
+
+ umask(0077);
+
+ NGIRCd_SignalQuit = NGIRCd_SignalRestart = false;
+ NGIRCd_Passive = false;
+#ifdef DEBUG
+ NGIRCd_Debug = false;
+#endif
+#ifdef SNIFFER
+ NGIRCd_Sniffer = false;
+#endif
+ strlcpy(NGIRCd_ConfFile, SYSCONFDIR, sizeof(NGIRCd_ConfFile));
+ strlcat(NGIRCd_ConfFile, CONFIG_FILE, sizeof(NGIRCd_ConfFile));
+
+ Fill_Version();
+
+ /* parse conmmand line */
+ for (i = 1; i < argc; i++) {
+ ok = false;
+ if (argv[i][0] == '-' && argv[i][1] == '-') {
+ /* long option */
+ if (strcmp(argv[i], "--config") == 0) {
+ if (i + 1 < argc) {
+ /* Ok, there's an parameter left */
+ strlcpy(NGIRCd_ConfFile, argv[i+1],
+ sizeof(NGIRCd_ConfFile));
+ /* next parameter */
+ i++; ok = true;
+ }
+ }
+ if (strcmp(argv[i], "--configtest") == 0) {
+ configtest = true;
+ ok = true;
+ }
+#ifdef DEBUG
+ if (strcmp(argv[i], "--debug") == 0) {
+ NGIRCd_Debug = true;
+ ok = true;
+ }
+#endif
+ if (strcmp(argv[i], "--help") == 0) {
+ Show_Version();
+ puts(""); Show_Help( ); puts( "" );
+ exit(1);
+ }
+ if (strcmp(argv[i], "--nodaemon") == 0) {
+ NGIRCd_NoDaemon = true;
+ ok = true;
+ }
+ if (strcmp(argv[i], "--passive") == 0) {
+ NGIRCd_Passive = true;
+ ok = true;
+ }
+#ifdef SNIFFER
+ if (strcmp(argv[i], "--sniffer") == 0) {
+ NGIRCd_Sniffer = true;
+ ok = true;
+ }
+#endif
+ if (strcmp(argv[i], "--version") == 0) {
+ Show_Version();
+ exit(1);
+ }
+ }
+ else if(argv[i][0] == '-' && argv[i][1] != '-') {
+ /* short option */
+ for (n = 1; n < strlen(argv[i]); n++) {
+ ok = false;
+#ifdef DEBUG
+ if (argv[i][n] == 'd') {
+ NGIRCd_Debug = true;
+ ok = true;
+ }
+#endif
+ if (argv[i][n] == 'f') {
+ if (!argv[i][n+1] && i+1 < argc) {
+ /* Ok, next character is a blank */
+ strlcpy(NGIRCd_ConfFile, argv[i+1],
+ sizeof(NGIRCd_ConfFile));
+
+ /* go to the following parameter */
+ i++;
+ n = strlen(argv[i]);
+ ok = true;
+ }
+ }
+
+ if (argv[i][n] == 'h') {
+ Show_Version();
+ puts(""); Show_Help(); puts("");
+ exit(1);
+ }
+
+ if (argv[i][n] == 'n') {
+ NGIRCd_NoDaemon = true;
+ ok = true;
+ }
+ if (argv[i][n] == 'p') {
+ NGIRCd_Passive = true;
+ ok = true;
+ }
+#ifdef SNIFFER
+ if (argv[i][n] == 's') {
+ NGIRCd_Sniffer = true;
+ ok = true;
+ }
+#endif
+ if (argv[i][n] == 't') {
+ configtest = true;
+ ok = true;
+ }
+
+ if (argv[i][n] == 'V') {
+ Show_Version();
+ exit(1);
+ }
+
+ if (!ok) {
+ printf("%s: invalid option \"-%c\"!\n",
+ PACKAGE_NAME, argv[i][n]);
+ printf("Try \"%s --help\" for more information.\n",
+ PACKAGE_NAME);
+ exit(1);
+ }
+ }
+
+ }
+ if (!ok) {
+ printf("%s: invalid option \"%s\"!\n",
+ PACKAGE_NAME, argv[i]);
+ printf("Try \"%s --help\" for more information.\n",
+ PACKAGE_NAME);
+ exit(1);
+ }
+ }
+
+ /* Debug level for "VERSION" command */
+ NGIRCd_DebugLevel[0] = '\0';
+#ifdef DEBUG
+ if (NGIRCd_Debug)
+ strcpy(NGIRCd_DebugLevel, "1");
+#endif
+#ifdef SNIFFER
+ if (NGIRCd_Sniffer) {
+ NGIRCd_Debug = true;
+ strcpy(NGIRCd_DebugLevel, "2");
+ }
+#endif
+
+ if (configtest) {
+ Show_Version(); puts("");
+ exit(Conf_Test());
+ }
+
+ while (!NGIRCd_SignalQuit) {
+ /* Initialize global variables */
+ NGIRCd_Start = time(NULL);
+ (void)strftime(NGIRCd_StartStr, 64,
+ "%a %b %d %Y at %H:%M:%S (%Z)",
+ localtime(&NGIRCd_Start));
+
+ NGIRCd_SignalRestart = false;
+ NGIRCd_SignalQuit = false;
+
+ Log_Init(!NGIRCd_NoDaemon);
+ Random_Init();
+ Conf_Init();
+ Log_ReInit();
+
+ /* Initialize the "main program":
+ * chroot environment, user and group ID, ... */
+ if (!NGIRCd_Init(NGIRCd_NoDaemon)) {
+ Log(LOG_ALERT, "Fatal: Initialization failed, exiting!");
+ exit(1);
+ }
+
+ if (!io_library_init(CONNECTION_POOL)) {
+ Log(LOG_ALERT,
+ "Fatal: Could not initialize IO routines: %s",
+ strerror(errno));
+ exit(1);
+ }
+
+ if (!Signals_Init()) {
+ Log(LOG_ALERT,
+ "Fatal: Could not set up signal handlers: %s",
+ strerror(errno));
+ exit(1);
+ }
+
+ Channel_Init();
+ Conn_Init();
+ Class_Init();
+ Client_Init();
+
+ /* Create protocol and server identification. The syntax
+ * used by ngIRCd in PASS commands and the known "extended
+ * flags" are described in doc/Protocol.txt. */
+#ifdef IRCPLUS
+ snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s:%s",
+ PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION,
+ IRCPLUSFLAGS);
+#ifdef ZLIB
+ strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID);
+#endif
+ if (Conf_OperCanMode)
+ strlcat(NGIRCd_ProtoID, "o", sizeof NGIRCd_ProtoID);
+#else /* IRCPLUS */
+ snprintf(NGIRCd_ProtoID, sizeof NGIRCd_ProtoID, "%s%s %s|%s",
+ PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION);
+#endif /* IRCPLUS */
+ strlcat(NGIRCd_ProtoID, " P", sizeof NGIRCd_ProtoID);
+#ifdef ZLIB
+ strlcat(NGIRCd_ProtoID, "Z", sizeof NGIRCd_ProtoID);
+#endif
+ LogDebug("Protocol and server ID is \"%s\".", NGIRCd_ProtoID);
+
+ Channel_InitPredefined();
+
+ if (Conn_InitListeners() < 1) {
+ Log(LOG_ALERT,
+ "Server isn't listening on a single port!" );
+ Log(LOG_ALERT,
+ "%s exiting due to fatal errors!", PACKAGE_NAME);
+ Pidfile_Delete();
+ exit(1);
+ }
+
+ /* Main Run Loop */
+ Conn_Handler();
+
+ Conn_Exit();
+ Client_Exit();
+ Channel_Exit();
+ Class_Exit();
+ Log_Exit();
+ Signals_Exit();
+ }
+ Pidfile_Delete();
+