]> arthur.barton.de Git - ngircd-alex.git/blobdiff - src/ngircd/conf.c
New defines MAX_WHOWAS and DEFAULT_WHOWAS.
[ngircd-alex.git] / src / ngircd / conf.c
index c87cf5902e1eef8763039f82ed79f4bd667c34e7..328bbff06324500dab8bb77cb7ba810f272572b6 100644 (file)
@@ -14,7 +14,7 @@
 
 #include "portab.h"
 
-static char UNUSED id[] = "$Id: conf.c,v 1.66 2004/10/20 13:47:32 alex Exp $";
+static char UNUSED id[] = "$Id: conf.c,v 1.76 2005/04/16 09:23:01 fw Exp $";
 
 #include "imp.h"
 #include <assert.h>
@@ -50,60 +50,64 @@ static char UNUSED id[] = "$Id: conf.c,v 1.66 2004/10/20 13:47:32 alex Exp $";
 #include "conf.h"
 
 
-LOCAL BOOLEAN Use_Log = TRUE;
+LOCAL bool Use_Log = true;
 LOCAL CONF_SERVER New_Server;
-LOCAL INT New_Server_Idx;
+LOCAL int New_Server_Idx;
 
 
-LOCAL VOID Set_Defaults PARAMS(( BOOLEAN InitServers ));
-LOCAL VOID Read_Config PARAMS(( VOID ));
-LOCAL VOID Validate_Config PARAMS(( BOOLEAN TestOnly ));
+LOCAL void Set_Defaults PARAMS(( bool InitServers ));
+LOCAL void Read_Config PARAMS(( void ));
+LOCAL void Validate_Config PARAMS(( bool TestOnly ));
 
-LOCAL VOID Handle_GLOBAL PARAMS(( INT Line, CHAR *Var, CHAR *Arg ));
-LOCAL VOID Handle_OPERATOR PARAMS(( INT Line, CHAR *Var, CHAR *Arg ));
-LOCAL VOID Handle_SERVER PARAMS(( INT Line, CHAR *Var, CHAR *Arg ));
-LOCAL VOID Handle_CHANNEL PARAMS(( INT Line, CHAR *Var, CHAR *Arg ));
+LOCAL void Handle_GLOBAL PARAMS(( int Line, char *Var, char *Arg ));
+LOCAL void Handle_OPERATOR PARAMS(( int Line, char *Var, char *Arg ));
+LOCAL void Handle_SERVER PARAMS(( int Line, char *Var, char *Arg ));
+LOCAL void Handle_CHANNEL PARAMS(( int Line, char *Var, char *Arg ));
 
-LOCAL VOID Config_Error PARAMS(( CONST INT Level, CONST CHAR *Format, ... ));
+LOCAL void Config_Error PARAMS(( const int Level, const char *Format, ... ));
 
-LOCAL VOID Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
+LOCAL void Config_Error_NaN PARAMS(( const int LINE, const char *Value ));
+LOCAL void Config_Error_TooLong PARAMS(( const int LINE, const char *Value ));
 
+LOCAL void Init_Server_Struct PARAMS(( CONF_SERVER *Server ));
 
-GLOBAL VOID
-Conf_Init( VOID )
+
+GLOBAL void
+Conf_Init( void )
 {
-       Set_Defaults( TRUE );
+       Set_Defaults( true );
        Read_Config( );
-       Validate_Config( FALSE );
+       Validate_Config( false );
 } /* Config_Init */
 
 
-GLOBAL VOID
-Conf_Rehash( VOID )
+GLOBAL void
+Conf_Rehash( void )
 {
-       Set_Defaults( FALSE );
+       Set_Defaults( false );
        Read_Config( );
-       Validate_Config( FALSE );
+       Validate_Config( false );
 } /* Config_Rehash */
 
 
-GLOBAL INT
-Conf_Test( VOID )
+GLOBAL int
+Conf_Test( void )
 {
        /* Read configuration, validate and output it. */
 
        struct passwd *pwd;
        struct group *grp;
-       INT i;
+       int i;
 
-       Use_Log = FALSE;
-       Set_Defaults( TRUE );
+       Use_Log = false;
+       Set_Defaults( true );
 
        Read_Config( );
-       Validate_Config( TRUE );
+       Validate_Config( true );
 
-       /* If stdin is a valid tty wait for a key: */
-       if( isatty( fileno( stdout )))
+       /* If stdin and stdout ("you can read our nice message and we can
+        * read in your keypress") are valid tty's, wait for a key: */
+       if( isatty( fileno( stdin )) && isatty( fileno( stdout )))
        {
                puts( "OK, press enter to see a dump of your service configuration ..." );
                getchar( );
@@ -119,25 +123,27 @@ Conf_Test( VOID )
        printf( "  AdminEMail = %s\n", Conf_ServerAdminMail );
        printf( "  MotdFile = %s\n", Conf_MotdFile );
        printf( "  MotdPhrase = %s\n", Conf_MotdPhrase );
-       printf( "  ChrootDir= %s\n", Conf_Chroot );
+       printf( "  ChrootDir = %s\n", Conf_Chroot );
+       printf( "  PidFile = %s\n", Conf_PidFile);
        printf( "  Ports = " );
        for( i = 0; i < Conf_ListenPorts_Count; i++ )
        {
                if( i != 0 ) printf( ", " );
-               printf( "%u", Conf_ListenPorts[i] );
+               printf( "%u", (unsigned int) Conf_ListenPorts[i] );
        }
        puts( "" );
        printf( "  Listen = %s\n", Conf_ListenAddress );
        pwd = getpwuid( Conf_UID );
        if( pwd ) printf( "  ServerUID = %s\n", pwd->pw_name );
-       else printf( "  ServerUID = %ld\n", (LONG)Conf_UID );
+       else printf( "  ServerUID = %ld\n", (long)Conf_UID );
        grp = getgrgid( Conf_GID );
        if( grp ) printf( "  ServerGID = %s\n", grp->gr_name );
-       else printf( "  ServerGID = %ld\n", (LONG)Conf_GID );
+       else printf( "  ServerGID = %ld\n", (long)Conf_GID );
        printf( "  PingTimeout = %d\n", Conf_PingTimeout );
        printf( "  PongTimeout = %d\n", Conf_PongTimeout );
        printf( "  ConnectRetry = %d\n", Conf_ConnectRetry );
-       printf( "  OperCanUseMode = %s\n", Conf_OperCanMode == TRUE ? "yes" : "no" );
+       printf( "  OperCanUseMode = %s\n", Conf_OperCanMode == true? "yes" : "no" );
+       printf( "  OperServerMode = %s\n", Conf_OperServerMode == true? "yes" : "no" );
        if( Conf_MaxConnections > 0 ) printf( "  MaxConnections = %ld\n", Conf_MaxConnections );
        else printf( "  MaxConnections = -1\n" );
        if( Conf_MaxConnectionsIP > 0 ) printf( "  MaxConnectionsIP = %d\n", Conf_MaxConnectionsIP );
@@ -154,6 +160,7 @@ Conf_Test( VOID )
                puts( "[OPERATOR]" );
                printf( "  Name = %s\n", Conf_Oper[i].name );
                printf( "  Password = %s\n", Conf_Oper[i].pwd );
+               if ( Conf_Oper[i].mask ) printf( "  Mask = %s\n", Conf_Oper[i].mask );
                puts( "" );
        }
 
@@ -188,7 +195,7 @@ Conf_Test( VOID )
 } /* Conf_Test */
 
 
-GLOBAL VOID
+GLOBAL void
 Conf_UnsetServer( CONN_ID Idx )
 {
        /* Set next time for next connection attempt, if this is a server
@@ -196,7 +203,7 @@ Conf_UnsetServer( CONN_ID Idx )
         * "once", delete it from our configuration.
         * Non-Server-Connections will be silently ignored. */
 
-       INT i;
+       int i;
 
        /* Check all our configured servers */
        for( i = 0; i < MAX_SERVERS; i++ )
@@ -224,8 +231,8 @@ Conf_UnsetServer( CONN_ID Idx )
 } /* Conf_UnsetServer */
 
 
-GLOBAL VOID
-Conf_SetServer( INT ConfServer, CONN_ID Idx )
+GLOBAL void
+Conf_SetServer( int ConfServer, CONN_ID Idx )
 {
        /* Set connection for specified configured server */
 
@@ -236,12 +243,12 @@ Conf_SetServer( INT ConfServer, CONN_ID Idx )
 } /* Conf_SetServer */
 
 
-GLOBAL INT
+GLOBAL int
 Conf_GetServer( CONN_ID Idx )
 {
        /* Get index of server in configuration structure */
        
-       INT i = 0;
+       int i = 0;
        
        assert( Idx > NONE );
 
@@ -253,12 +260,12 @@ Conf_GetServer( CONN_ID Idx )
 } /* Conf_GetServer */
 
 
-GLOBAL BOOLEAN
-Conf_EnableServer( CHAR *Name, INT Port )
+GLOBAL bool
+Conf_EnableServer( char *Name, UINT16 Port )
 {
        /* Enable specified server and adjust port */
 
-       INT i;
+       int i;
 
        assert( Name != NULL );
 
@@ -269,19 +276,19 @@ Conf_EnableServer( CHAR *Name, INT Port )
                        /* Gotcha! Set port and enable server: */
                        Conf_Server[i].port = Port;
                        Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED;
-                       return TRUE;
+                       return true;
                }
        }
-       return FALSE;
+       return false;
 } /* Conf_EnableServer */
 
 
-GLOBAL BOOLEAN
-Conf_DisableServer( CHAR *Name )
+GLOBAL bool
+Conf_DisableServer( char *Name )
 {
        /* Enable specified server and adjust port */
 
-       INT i;
+       int i;
 
        assert( Name != NULL );
 
@@ -291,20 +298,20 @@ Conf_DisableServer( CHAR *Name )
                {
                        /* Gotcha! Disable and disconnect server: */
                        Conf_Server[i].flags |= CONF_SFLAG_DISABLED;
-                       if( Conf_Server[i].conn_id > NONE ) Conn_Close( Conf_Server[i].conn_id, NULL, "Server link terminated on operator request", TRUE );
-                       return TRUE;
+                       if( Conf_Server[i].conn_id > NONE ) Conn_Close( Conf_Server[i].conn_id, NULL, "Server link terminated on operator request", true);
+                       return true;
                }
        }
-       return FALSE;
+       return false;
 } /* Conf_DisableServer */
 
 
-GLOBAL BOOLEAN
-Conf_AddServer( CHAR *Name, INT Port, CHAR *Host, CHAR *MyPwd, CHAR *PeerPwd )
+GLOBAL bool
+Conf_AddServer( char *Name, UINT16 Port, char *Host, char *MyPwd, char *PeerPwd )
 {
        /* Add new server to configuration */
 
-       INT i;
+       int i;
 
        assert( Name != NULL );
        assert( Host != NULL );
@@ -317,7 +324,7 @@ Conf_AddServer( CHAR *Name, INT Port, CHAR *Host, CHAR *MyPwd, CHAR *PeerPwd )
                /* Is this item used? */
                if( ! Conf_Server[i].name[0] ) break;
        }
-       if( i >= MAX_SERVERS ) return FALSE;
+       if( i >= MAX_SERVERS ) return false;
 
        Init_Server_Struct( &Conf_Server[i] );
        strlcpy( Conf_Server[i].name, Name, sizeof( Conf_Server[i].name ));
@@ -327,16 +334,16 @@ Conf_AddServer( CHAR *Name, INT Port, CHAR *Host, CHAR *MyPwd, CHAR *PeerPwd )
        Conf_Server[i].port = Port;
        Conf_Server[i].flags = CONF_SFLAG_ONCE;
        
-       return TRUE;
+       return true;
 } /* Conf_AddServer */
 
 
-LOCAL VOID
-Set_Defaults( BOOLEAN InitServers )
+LOCAL void
+Set_Defaults( bool InitServers )
 {
        /* Initialize configuration variables with default values. */
 
-       INT i;
+       int i;
 
        strcpy( Conf_ServerName, "" );
        sprintf( Conf_ServerInfo, "%s %s", PACKAGE_NAME, PACKAGE_VERSION );
@@ -353,6 +360,8 @@ Set_Defaults( BOOLEAN InitServers )
 
        strlcpy( Conf_Chroot, CHROOT_DIR, sizeof( Conf_Chroot ));
 
+       strlcpy( Conf_PidFile, PID_FILE, sizeof( Conf_PidFile ));
+
        Conf_ListenPorts_Count = 0;
        strcpy( Conf_ListenAddress, "" );
 
@@ -366,7 +375,8 @@ Set_Defaults( BOOLEAN InitServers )
        Conf_Oper_Count = 0;
        Conf_Channel_Count = 0;
 
-       Conf_OperCanMode = FALSE;
+       Conf_OperCanMode = false;
+       Conf_OperServerMode = false;
        
        Conf_MaxConnections = -1;
        Conf_MaxConnectionsIP = 5;
@@ -377,13 +387,13 @@ Set_Defaults( BOOLEAN InitServers )
 } /* Set_Defaults */
 
 
-LOCAL VOID
-Read_Config( VOID )
+LOCAL void
+Read_Config( void )
 {
        /* Read configuration file. */
 
-       CHAR section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
-       INT line, i, n;
+       char section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr;
+       int line, i, n;
        FILE *fd;
 
        /* Open configuration file */
@@ -440,7 +450,7 @@ Read_Config( VOID )
        New_Server_Idx = NONE;
 
        /* Read configuration file */
-       while( TRUE )
+       while( true )
        {
                if( ! fgets( str, LINE_LEN, fd )) break;
                ngt_TrimStr( str );
@@ -460,8 +470,12 @@ Read_Config( VOID )
                                else
                                {
                                        /* Initialize new operator structure */
-                                       strcpy( Conf_Oper[Conf_Oper_Count].name, "" );
-                                       strcpy( Conf_Oper[Conf_Oper_Count].pwd, "" );
+                                       Conf_Oper[Conf_Oper_Count].name[0] = '\0';
+                                       Conf_Oper[Conf_Oper_Count].pwd[0] = '\0';
+                                       if (Conf_Oper[Conf_Oper_Count].mask) {
+                                               free(Conf_Oper[Conf_Oper_Count].mask );
+                                               Conf_Oper[Conf_Oper_Count].mask = NULL;
+                                       }
                                        Conf_Oper_Count++;
                                }
                                continue;
@@ -550,13 +564,24 @@ Read_Config( VOID )
 } /* Read_Config */
 
 
-LOCAL VOID
-Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
+LOCAL bool
+Check_ArgIsTrue( const char *Arg )
+{
+       if( strcasecmp( Arg, "yes" ) == 0 ) return true;
+       if( strcasecmp( Arg, "true" ) == 0 ) return true;
+       if( atoi( Arg ) != 0 ) return true;
+
+       return false;
+} /* Check_ArgIsTrue */
+
+
+LOCAL void
+Handle_GLOBAL( int Line, char *Var, char *Arg )
 {
        struct passwd *pwd;
        struct group *grp;
-       CHAR *ptr;
-       LONG port;
+       char *ptr;
+       long port;
        
        assert( Line > 0 );
        assert( Var != NULL );
@@ -565,37 +590,43 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
        if( strcasecmp( Var, "Name" ) == 0 )
        {
                /* Server name */
-               if( strlcpy( Conf_ServerName, Arg, sizeof( Conf_ServerName )) >= sizeof( Conf_ServerName )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_ServerName, Arg, sizeof( Conf_ServerName )) >= sizeof( Conf_ServerName ))
+                       Config_Error_TooLong( Line, Var );
+
                return;
        }
        if( strcasecmp( Var, "Info" ) == 0 )
        {
                /* Info text of server */
-               if( strlcpy( Conf_ServerInfo, Arg, sizeof( Conf_ServerInfo )) >= sizeof( Conf_ServerInfo )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Info\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_ServerInfo, Arg, sizeof( Conf_ServerInfo )) >= sizeof( Conf_ServerInfo ))
+                       Config_Error_TooLong ( Line, Var );
+
                return;
        }
        if( strcasecmp( Var, "Password" ) == 0 )
        {
                /* Global server password */
-               if( strlcpy( Conf_ServerPwd, Arg, sizeof( Conf_ServerPwd )) >= sizeof( Conf_ServerPwd )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Password\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_ServerPwd, Arg, sizeof( Conf_ServerPwd )) >= sizeof( Conf_ServerPwd ))
+                       Config_Error_TooLong( Line, Var );
+
                return;
        }
        if( strcasecmp( Var, "AdminInfo1" ) == 0 )
        {
                /* Administrative info #1 */
-               if( strlcpy( Conf_ServerAdmin1, Arg, sizeof( Conf_ServerAdmin1 )) >= sizeof( Conf_ServerAdmin1 )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"AdminInfo1\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_ServerAdmin1, Arg, sizeof( Conf_ServerAdmin1 )) >= sizeof( Conf_ServerAdmin1 )) Config_Error_TooLong ( Line, Var );
                return;
        }
        if( strcasecmp( Var, "AdminInfo2" ) == 0 )
        {
                /* Administrative info #2 */
-               if( strlcpy( Conf_ServerAdmin2, Arg, sizeof( Conf_ServerAdmin2 )) >= sizeof( Conf_ServerAdmin2 )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"AdminInfo2\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_ServerAdmin2, Arg, sizeof( Conf_ServerAdmin2 )) >= sizeof( Conf_ServerAdmin2 )) Config_Error_TooLong ( Line, Var );
                return;
        }
        if( strcasecmp( Var, "AdminEMail" ) == 0 )
        {
                /* Administrative email contact */
-               if( strlcpy( Conf_ServerAdminMail, Arg, sizeof( Conf_ServerAdminMail )) >= sizeof( Conf_ServerAdminMail )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"AdminEMail\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_ServerAdminMail, Arg, sizeof( Conf_ServerAdminMail )) >= sizeof( Conf_ServerAdminMail )) Config_Error_TooLong( Line, Var );
                return;
        }
        if( strcasecmp( Var, "Ports" ) == 0 )
@@ -610,7 +641,7 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
                        if( Conf_ListenPorts_Count + 1 > MAX_LISTEN_PORTS ) Config_Error( LOG_ERR, "Too many listen ports configured. Port %ld ignored.", port );
                        else
                        {
-                               if( port > 0 && port < 0xFFFF ) Conf_ListenPorts[Conf_ListenPorts_Count++] = (UINT)port;
+                               if( port > 0 && port < 0xFFFF ) Conf_ListenPorts[Conf_ListenPorts_Count++] = (UINT16)port;
                                else Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Illegal port number %ld!", NGIRCd_ConfFile, Line, port );
                        }
                        ptr = strtok( NULL, "," );
@@ -620,21 +651,37 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
        if( strcasecmp( Var, "MotdFile" ) == 0 )
        {
                /* "Message of the day" (MOTD) file */
-               if( strlcpy( Conf_MotdFile, Arg, sizeof( Conf_MotdFile )) >= sizeof( Conf_MotdFile )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MotdFile\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_MotdFile, Arg, sizeof( Conf_MotdFile )) >= sizeof( Conf_MotdFile ))
+                       Config_Error_TooLong( Line, Var );
+
                return;
        }
        if( strcasecmp( Var, "MotdPhrase" ) == 0 )
        {
                /* "Message of the day" phrase (instead of file) */
-               if( strlcpy( Conf_MotdPhrase, Arg, sizeof( Conf_MotdPhrase )) >= sizeof( Conf_MotdPhrase )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MotdPhrase\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_MotdPhrase, Arg, sizeof( Conf_MotdPhrase )) >= sizeof( Conf_MotdPhrase ))
+                       Config_Error_TooLong( Line, Var );
+
                return;
        }
        if( strcasecmp( Var, "ChrootDir" ) == 0 )
        {
                /* directory for chroot() */
-               if( strlcpy( Conf_Chroot, Arg, sizeof( Conf_Chroot )) >= sizeof( Conf_Chroot )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"ChrootDir\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_Chroot, Arg, sizeof( Conf_Chroot )) >= sizeof( Conf_Chroot ))
+                       Config_Error_TooLong( Line, Var );
+
+               return;
+       }
+
+       if ( strcasecmp( Var, "PidFile" ) == 0 )
+       {
+               /* name of pidfile */
+               if( strlcpy( Conf_PidFile, Arg, sizeof( Conf_PidFile )) >= sizeof( Conf_PidFile ))
+                       Config_Error_TooLong( Line, Var );
+
                return;
        }
+
        if( strcasecmp( Var, "ServerUID" ) == 0 )
        {
                /* UID the daemon should switch to */
@@ -643,10 +690,10 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
                else
                {
 #ifdef HAVE_ISDIGIT
-                       if( ! isdigit( (INT)*Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"ServerUID\" is not a number!", NGIRCd_ConfFile, Line );
+                       if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
                        else
 #endif
-                       Conf_UID = (UINT)atoi( Arg );
+                       Conf_UID = (unsigned int)atoi( Arg );
                }
                return;
        }
@@ -658,10 +705,10 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
                else
                {
 #ifdef HAVE_ISDIGIT
-                       if( ! isdigit( (INT)*Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"ServerGID\" is not a number!", NGIRCd_ConfFile, Line );
+                       if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
                        else
 #endif
-                       Conf_GID = (UINT)atoi( Arg );
+                       Conf_GID = (unsigned int)atoi( Arg );
                }
                return;
        }
@@ -701,17 +748,20 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
        if( strcasecmp( Var, "OperCanUseMode" ) == 0 )
        {
                /* Are IRC operators allowed to use MODE in channels they aren't Op in? */
-               if( strcasecmp( Arg, "yes" ) == 0 ) Conf_OperCanMode = TRUE;
-               else if( strcasecmp( Arg, "true" ) == 0 ) Conf_OperCanMode = TRUE;
-               else if( atoi( Arg ) != 0 ) Conf_OperCanMode = TRUE;
-               else Conf_OperCanMode = FALSE;
+               Conf_OperCanMode = Check_ArgIsTrue( Arg );
+               return;
+       }
+       if( strcasecmp( Var, "OperServerMode" ) == 0 )
+       {
+               /* Mask IRC operator as if coming from the server? (ircd-irc2 compat hack) */
+               Conf_OperServerMode = Check_ArgIsTrue( Arg );
                return;
        }
        if( strcasecmp( Var, "MaxConnections" ) == 0 )
        {
                /* Maximum number of connections. Values <= 0 are equal to "no limit". */
 #ifdef HAVE_ISDIGIT
-               if( ! isdigit( (INT)*Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MaxConnections\" is not a number!", NGIRCd_ConfFile, Line );
+               if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var);
                else
 #endif
                Conf_MaxConnections = atol( Arg );
@@ -721,7 +771,7 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
        {
                /* Maximum number of simoultanous connections from one IP. Values <= 0 are equal to "no limit". */
 #ifdef HAVE_ISDIGIT
-               if( ! isdigit( (INT)*Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MaxConnectionsIP\" is not a number!", NGIRCd_ConfFile, Line );
+               if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
                else
 #endif
                Conf_MaxConnectionsIP = atoi( Arg );
@@ -731,7 +781,7 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
        {
                /* Maximum number of channels a user can join. Values <= 0 are equal to "no limit". */
 #ifdef HAVE_ISDIGIT
-               if( ! isdigit( (INT)*Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MaxJoins\" is not a number!", NGIRCd_ConfFile, Line );
+               if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
                else
 #endif
                Conf_MaxJoins = atoi( Arg );
@@ -742,7 +792,7 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
                /* IP-Address to bind sockets */
                if( strlcpy( Conf_ListenAddress, Arg, sizeof( Conf_ListenAddress )) >= sizeof( Conf_ListenAddress ))
                {
-                       Config_Error( LOG_WARNING, "%s, line %d: Value of \"Listen\" too long!", NGIRCd_ConfFile, Line );
+                       Config_Error_TooLong( Line, Var );
                }
                return;
        }
@@ -751,8 +801,8 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg )
 } /* Handle_GLOBAL */
 
 
-LOCAL VOID
-Handle_OPERATOR( INT Line, CHAR *Var, CHAR *Arg )
+LOCAL void
+Handle_OPERATOR( int Line, char *Var, char *Arg )
 {
        assert( Line > 0 );
        assert( Var != NULL );
@@ -762,24 +812,34 @@ Handle_OPERATOR( INT Line, CHAR *Var, CHAR *Arg )
        if( strcasecmp( Var, "Name" ) == 0 )
        {
                /* Name of IRC operator */
-               if( strlcpy( Conf_Oper[Conf_Oper_Count - 1].name, Arg, sizeof( Conf_Oper[Conf_Oper_Count - 1].name )) >= sizeof( Conf_Oper[Conf_Oper_Count - 1].name )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_Oper[Conf_Oper_Count - 1].name, Arg, sizeof( Conf_Oper[Conf_Oper_Count - 1].name )) >= sizeof( Conf_Oper[Conf_Oper_Count - 1].name )) Config_Error_TooLong( Line, Var );
                return;
        }
        if( strcasecmp( Var, "Password" ) == 0 )
        {
                /* Password of IRC operator */
-               if( strlcpy( Conf_Oper[Conf_Oper_Count - 1].pwd, Arg, sizeof( Conf_Oper[Conf_Oper_Count - 1].pwd )) >= sizeof( Conf_Oper[Conf_Oper_Count - 1].pwd )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Password\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_Oper[Conf_Oper_Count - 1].pwd, Arg, sizeof( Conf_Oper[Conf_Oper_Count - 1].pwd )) >= sizeof( Conf_Oper[Conf_Oper_Count - 1].pwd )) Config_Error_TooLong( Line, Var );
+               return;
+       }
+       if( strcasecmp( Var, "Mask" ) == 0 )
+       {
+               if (Conf_Oper[Conf_Oper_Count - 1].mask) return; /* Hostname already configured */
+               Conf_Oper[Conf_Oper_Count - 1].mask = strdup( Arg );
+               if (! Conf_Oper[Conf_Oper_Count - 1].mask) {
+                       Config_Error( LOG_ERR, "%s, line %d: Cannot allocate memory for operator mask: %s", NGIRCd_ConfFile, Line, strerror(errno) );
+                       return;
+               }
+
                return;
        }
-       
        Config_Error( LOG_ERR, "%s, line %d (section \"Operator\"): Unknown variable \"%s\"!", NGIRCd_ConfFile, Line, Var );
 } /* Handle_OPERATOR */
 
 
-LOCAL VOID
-Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg )
+LOCAL void
+Handle_SERVER( int Line, char *Var, char *Arg )
 {
-       LONG port;
+       long port;
        
        assert( Line > 0 );
        assert( Var != NULL );
@@ -791,32 +851,35 @@ Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg )
        if( strcasecmp( Var, "Host" ) == 0 )
        {
                /* Hostname of the server */
-               if( strlcpy( New_Server.host, Arg, sizeof( New_Server.host )) >= sizeof( New_Server.host )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Host\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( New_Server.host, Arg, sizeof( New_Server.host )) >= sizeof( New_Server.host ))
+                       Config_Error_TooLong ( Line, Var );
+
                return;
        }
        if( strcasecmp( Var, "Name" ) == 0 )
        {
                /* Name of the server ("Nick"/"ID") */
-               if( strlcpy( New_Server.name, Arg, sizeof( New_Server.name )) >= sizeof( New_Server.name )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( New_Server.name, Arg, sizeof( New_Server.name )) >= sizeof( New_Server.name ))
+                       Config_Error_TooLong( Line, Var );
                return;
        }
        if( strcasecmp( Var, "MyPassword" ) == 0 )
        {
                /* Password of this server which is sent to the peer */
-               if( strlcpy( New_Server.pwd_in, Arg, sizeof( New_Server.pwd_in )) >= sizeof( New_Server.pwd_in )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MyPassword\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( New_Server.pwd_in, Arg, sizeof( New_Server.pwd_in )) >= sizeof( New_Server.pwd_in )) Config_Error_TooLong( Line, Var );
                return;
        }
        if( strcasecmp( Var, "PeerPassword" ) == 0 )
        {
                /* Passwort of the peer which must be received */
-               if( strlcpy( New_Server.pwd_out, Arg, sizeof( New_Server.pwd_out )) >= sizeof( New_Server.pwd_out )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"PeerPassword\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( New_Server.pwd_out, Arg, sizeof( New_Server.pwd_out )) >= sizeof( New_Server.pwd_out )) Config_Error_TooLong( Line, Var );
                return;
        }
        if( strcasecmp( Var, "Port" ) == 0 )
        {
                /* Port to which this server should connect */
                port = atol( Arg );
-               if( port > 0 && port < 0xFFFF ) New_Server.port = (INT)port;
+               if( port > 0 && port < 0xFFFF ) New_Server.port = (UINT16)port;
                else Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Illegal port number %ld!", NGIRCd_ConfFile, Line, port );
                return;
        }
@@ -824,7 +887,7 @@ Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg )
        {
                /* Server group */
 #ifdef HAVE_ISDIGIT
-               if( ! isdigit( (INT)*Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Group\" is not a number!", NGIRCd_ConfFile, Line );
+               if( ! isdigit( (int)*Arg )) Config_Error_NaN( Line, Var );
                else
 #endif
                New_Server.group = atoi( Arg );
@@ -835,8 +898,8 @@ Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg )
 } /* Handle_SERVER */
 
 
-LOCAL VOID
-Handle_CHANNEL( INT Line, CHAR *Var, CHAR *Arg )
+LOCAL void
+Handle_CHANNEL( int Line, char *Var, char *Arg )
 {
        assert( Line > 0 );
        assert( Var != NULL );
@@ -845,19 +908,23 @@ Handle_CHANNEL( INT Line, CHAR *Var, CHAR *Arg )
        if( strcasecmp( Var, "Name" ) == 0 )
        {
                /* Name of the channel */
-               if( strlcpy( Conf_Channel[Conf_Channel_Count - 1].name, Arg, sizeof( Conf_Channel[Conf_Channel_Count - 1].name )) >= sizeof( Conf_Channel[Conf_Channel_Count - 1].name )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_Channel[Conf_Channel_Count - 1].name, Arg, sizeof( Conf_Channel[Conf_Channel_Count - 1].name )) >= sizeof( Conf_Channel[Conf_Channel_Count - 1].name ))
+                       Config_Error_TooLong( Line, Var );
                return;
        }
        if( strcasecmp( Var, "Modes" ) == 0 )
        {
                /* Initial modes */
-               if( strlcpy( Conf_Channel[Conf_Channel_Count - 1].modes, Arg, sizeof( Conf_Channel[Conf_Channel_Count - 1].modes )) >= sizeof( Conf_Channel[Conf_Channel_Count - 1].modes )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Modes\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_Channel[Conf_Channel_Count - 1].modes, Arg, sizeof( Conf_Channel[Conf_Channel_Count - 1].modes )) >= sizeof( Conf_Channel[Conf_Channel_Count - 1].modes ))
+                       Config_Error_TooLong( Line, Var );
                return;
        }
        if( strcasecmp( Var, "Topic" ) == 0 )
        {
                /* Initial topic */
-               if( strlcpy( Conf_Channel[Conf_Channel_Count - 1].topic, Arg, sizeof( Conf_Channel[Conf_Channel_Count - 1].topic )) >= sizeof( Conf_Channel[Conf_Channel_Count - 1].topic )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Topic\" too long!", NGIRCd_ConfFile, Line );
+               if( strlcpy( Conf_Channel[Conf_Channel_Count - 1].topic, Arg, sizeof( Conf_Channel[Conf_Channel_Count - 1].topic )) >= sizeof( Conf_Channel[Conf_Channel_Count - 1].topic ))
+                       Config_Error_TooLong( Line, Var );
                return;
        }
 
@@ -865,13 +932,13 @@ Handle_CHANNEL( INT Line, CHAR *Var, CHAR *Arg )
 } /* Handle_CHANNEL */
 
 
-LOCAL VOID
-Validate_Config( BOOLEAN Configtest )
+LOCAL void
+Validate_Config( bool Configtest )
 {
        /* Validate configuration settings. */
 
 #ifdef DEBUG
-       INT i, servers, servers_once;
+       int i, servers, servers_once;
 #endif
 
        if( ! Conf_ServerName[0] )
@@ -915,9 +982,9 @@ Validate_Config( BOOLEAN Configtest )
                Config_Error( LOG_WARNING, "No administrative information configured but required by RFC!" );
        }
 #ifdef FD_SETSIZE      
-       if(( Conf_MaxConnections > (LONG)FD_SETSIZE ) || ( Conf_MaxConnections < 1 ))
+       if(( Conf_MaxConnections > (long)FD_SETSIZE ) || ( Conf_MaxConnections < 1 ))
        {
-               Conf_MaxConnections = (LONG)FD_SETSIZE;
+               Conf_MaxConnections = (long)FD_SETSIZE;
                Config_Error( LOG_ERR, "Setting MaxConnections to %ld, select() can't handle more file descriptors!", Conf_MaxConnections );
        }
 #else
@@ -939,18 +1006,30 @@ Validate_Config( BOOLEAN Configtest )
 } /* Validate_Config */
 
 
+LOCAL void
+Config_Error_TooLong ( const int Line, const char *Item )
+{
+       Config_Error( LOG_WARNING, "%s, line %d: Value of \"%s\" too long!", NGIRCd_ConfFile, Line, Item );
+}
+
+LOCAL void
+Config_Error_NaN( const int Line, const char *Item )
+{
+       Config_Error( LOG_WARNING, "%s, line %d: Value of \"%s\" is not a number!", NGIRCd_ConfFile, Line, Item );
+}
+
 #ifdef PROTOTYPES
-LOCAL VOID Config_Error( CONST INT Level, CONST CHAR *Format, ... )
+LOCAL void Config_Error( const int Level, const char *Format, ... )
 #else
-LOCAL VOID Config_Error( Level, Format, va_alist )
-CONST INT Level;
-CONST CHAR *Format;
+LOCAL void Config_Error( Level, Format, va_alist )
+const int Level;
+const char *Format;
 va_dcl
 #endif
 {
        /* Error! Write to console and/or logfile. */
 
-       CHAR msg[MAX_LOG_MSG_LEN];
+       char msg[MAX_LOG_MSG_LEN];
        va_list ap;
 
        assert( Format != NULL );
@@ -971,24 +1050,20 @@ va_dcl
 } /* Config_Error */
 
 
-LOCAL VOID
+LOCAL void
 Init_Server_Struct( CONF_SERVER *Server )
 {
        /* Initialize server configuration structur to default values */
 
        assert( Server != NULL );
 
-       strcpy( Server->host, "" );
-       strcpy( Server->ip, "" );
-       strcpy( Server->name, "" );
-       strcpy( Server->pwd_in, "" );
-       strcpy( Server->pwd_out, "" );
-       Server->port = 0;
+       memset( Server, 0, sizeof (CONF_SERVER) );
+
        Server->group = NONE;
        Server->lasttry = time( NULL ) - Conf_ConnectRetry + STARTUP_DELAY;
-       Server->res_stat = NULL;
+
        if( NGIRCd_Passive ) Server->flags = CONF_SFLAG_DISABLED;
-       else Server->flags = 0;
+
        Server->conn_id = NONE;
 } /* Init_Server_Struct */