+ 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_SignalRehash = FALSE;
+ NGIRCd_SignalRestart = FALSE;
+ NGIRCd_SignalQuit = FALSE;
+
+ /* Initialize modules, part I */
+ Log_Init( );
+ Conf_Init( );
+
+ if( Conf_Chroot[0] )
+ {
+ /* Chroot */
+ if( chdir( Conf_Chroot ) != 0 ) Log( LOG_ERR, "Can't chdir() in ChrootDir (%s): %s", Conf_Chroot, strerror( errno ));
+
+ if( chroot( Conf_Chroot ) != 0 ) Log( LOG_ERR, "Can't change root directory to \"%s\": %s", Conf_Chroot, strerror( errno ));
+ else Log( LOG_INFO, "Changed root and working directory to \"%s\".", Conf_Chroot );
+ }
+
+ if( Conf_GID != 0 )
+ {
+ /* Set new group ID */
+ if( setgid( Conf_GID ) != 0 ) Log( LOG_ERR, "Can't change group ID to %u: %s", Conf_GID, strerror( errno ));
+ }
+ if( Conf_UID != 0 )
+ {
+ /* Set new user ID */
+ if( setuid( Conf_UID ) != 0 ) Log( LOG_ERR, "Can't change user ID to %u: %s", Conf_UID, strerror( errno ));
+ }
+
+ /* In der Regel wird ein Sub-Prozess ge-fork()'t, der
+ * nicht mehr mit dem Terminal verbunden ist. Mit der
+ * Option "--nodaemon" kann dies (z.B. zum Debuggen)
+ * verhindert werden. */
+ if( ! NGIRCd_NoDaemon )
+ {
+ /* Daemon im Hintergrund erzeugen */
+ pid = (LONG)fork( );
+ if( pid > 0 )
+ {
+ /* "alter" Prozess */
+ exit( 0 );
+ }
+ if( pid < 0 )
+ {
+ /* Fehler */
+ printf( "%s: Can't fork: %s!\nFatal error, exiting now ...\n", PACKAGE_NAME, strerror( errno ));
+ exit( 1 );
+ }
+
+ /* Child-Prozess initialisieren */
+ (VOID)setsid( );
+ chdir( "/" );
+ }
+
+ /* Initialize modules, part II: these functions are eventually
+ * called with already dropped privileges ... */
+ Resolve_Init( );
+ Lists_Init( );
+ Channel_Init( );
+ Client_Init( );
+#ifdef RENDEZVOUS
+ Rendezvous_Init( );
+#endif
+ Conn_Init( );
+
+ /* Show user, group, and PID of the running daemon */
+ pwd = getpwuid( getuid( )); grp = getgrgid( getgid( ));
+ Log( LOG_INFO, "Running as user %s(%ld), group %s(%ld), with PID %ld.", pwd ? pwd->pw_name : "unknown", (LONG)getuid( ), grp ? grp->gr_name : "unknown", (LONG)getgid( ), (LONG)getpid( ));
+
+ /* Redirect stderr handle to "error file" for debugging.
+ * But don't try to write in the chroot jail, since it's more
+ * secure to have a chroot dir not writable by the daemon.
+ */
+ if( ! Conf_Chroot[0] ) Log_InitErrorfile( );
+
+ /* Signal-Handler initialisieren */
+ Initialize_Signal_Handler( );
+
+ /* Protokoll- und Server-Identifikation erzeugen. Die vom ngIRCd
+ * beim PASS-Befehl verwendete Syntax sowie die erweiterten Flags
+ * sind in doc/Protocol.txt beschrieben. */
+#ifdef IRCPLUS
+ sprintf( NGIRCd_ProtoID, "%s%s %s|%s:%s", PROTOVER, PROTOIRCPLUS, PACKAGE_NAME, PACKAGE_VERSION, IRCPLUSFLAGS );
+#ifdef ZLIB
+ strcat( NGIRCd_ProtoID, "Z" );
+#endif
+ if( Conf_OperCanMode ) strcat( NGIRCd_ProtoID, "o" );
+#else
+ sprintf( NGIRCd_ProtoID, "%s%s %s|%s", PROTOVER, PROTOIRC, PACKAGE_NAME, PACKAGE_VERSION );
+#endif
+ strcat( NGIRCd_ProtoID, " P" );
+#ifdef ZLIB
+ strcat( NGIRCd_ProtoID, "Z" );
+#endif
+ Log( LOG_DEBUG, "Protocol and server ID is \"%s\".", NGIRCd_ProtoID );
+
+ /* Vordefinierte Channels anlegen */
+ Channel_InitPredefined( );
+
+ /* Listen-Ports initialisieren */
+ 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 );
+ exit( 1 );
+ }
+
+ /* Hauptschleife */
+ Conn_Handler( );
+
+ /* Alles abmelden */
+ Conn_Exit( );
+#ifdef RENDEZVOUS
+ Rendezvous_Exit( );
+#endif
+ Client_Exit( );
+ Channel_Exit( );
+ Lists_Exit( );
+ Log_Exit( );
+ }
+