X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fconf.c;h=4cc78fe20bb99a1d373cde763cddc685db015891;hp=5fdac5fff225a8165f1f600b87f22e03180c48f0;hb=02a22611be07e39b8267a27ae0f391aa1f81ede9;hpb=6725d7893ca62007ba828b9d8eb94e81f275a880 diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c index 5fdac5ff..4cc78fe2 100644 --- a/src/ngircd/conf.c +++ b/src/ngircd/conf.c @@ -14,7 +14,7 @@ #include "portab.h" -static char UNUSED id[] = "$Id: conf.c,v 1.42 2002/12/12 11:26:08 alex Exp $"; +static char UNUSED id[] = "$Id: conf.c,v 1.54 2003/03/27 01:21:38 alex Exp $"; #include "imp.h" #include @@ -27,6 +27,7 @@ static char UNUSED id[] = "$Id: conf.c,v 1.42 2002/12/12 11:26:08 alex Exp $"; #include #include #include +#include #ifdef HAVE_CTYPE_H # include @@ -45,11 +46,13 @@ static char UNUSED id[] = "$Id: conf.c,v 1.42 2002/12/12 11:26:08 alex Exp $"; LOCAL BOOLEAN Use_Log = TRUE; +LOCAL CONF_SERVER New_Server; +LOCAL INT New_Server_Idx; -LOCAL VOID Set_Defaults PARAMS(( VOID )); +LOCAL VOID Set_Defaults PARAMS(( BOOLEAN InitServers )); LOCAL VOID Read_Config PARAMS(( VOID )); -LOCAL VOID Validate_Config PARAMS(( VOID )); +LOCAL VOID Validate_Config PARAMS(( BOOLEAN TestOnly )); LOCAL VOID Handle_GLOBAL PARAMS(( INT Line, CHAR *Var, CHAR *Arg )); LOCAL VOID Handle_OPERATOR PARAMS(( INT Line, CHAR *Var, CHAR *Arg )); @@ -58,16 +61,27 @@ LOCAL VOID Handle_CHANNEL PARAMS(( INT Line, CHAR *Var, CHAR *Arg )); LOCAL VOID Config_Error PARAMS(( CONST INT Level, CONST CHAR *Format, ... )); +LOCAL VOID Init_Server_Struct PARAMS(( CONF_SERVER *Server )); + GLOBAL VOID Conf_Init( VOID ) { - Set_Defaults( ); + Set_Defaults( TRUE ); Read_Config( ); - Validate_Config( ); + Validate_Config( FALSE ); } /* Config_Init */ +GLOBAL VOID +Conf_Rehash( VOID ) +{ + Set_Defaults( FALSE ); + Read_Config( ); + Validate_Config( FALSE ); +} /* Config_Rehash */ + + GLOBAL INT Conf_Test( VOID ) { @@ -78,9 +92,10 @@ Conf_Test( VOID ) INT i; Use_Log = FALSE; - Set_Defaults( ); + Set_Defaults( TRUE ); Read_Config( ); + Validate_Config( TRUE ); /* If stdin is a valid tty wait for a key: */ if( isatty( fileno( stdout ))) @@ -117,6 +132,8 @@ Conf_Test( VOID ) printf( " OperCanUseMode = %s\n", Conf_OperCanMode == TRUE ? "yes" : "no" ); if( Conf_MaxConnections > 0 ) printf( " MaxConnections = %ld\n", Conf_MaxConnections ); else printf( " MaxConnections = -1\n" ); + if( Conf_MaxJoins > 0 ) printf( " MaxJoins = %d\n", Conf_MaxJoins ); + else printf( " MaxJoins = -1\n" ); puts( "" ); for( i = 0; i < Conf_Oper_Count; i++ ) @@ -130,7 +147,7 @@ Conf_Test( VOID ) puts( "" ); } - for( i = 0; i < Conf_Server_Count; i++ ) + for( i = 0; i < MAX_SERVERS; i++ ) { if( ! Conf_Server[i].name[0] ) continue; @@ -161,11 +178,156 @@ Conf_Test( VOID ) } /* Conf_Test */ +GLOBAL VOID +Conf_UnsetServer( CONN_ID Idx ) +{ + /* Set next time for next connection attempt, if this is a server + * link that is (still) configured here. If the server is set as + * "once", delete it from our configuration. + * Non-Server-Connections will be silently ignored. */ + + INT i; + + /* Check all our configured servers */ + for( i = 0; i < MAX_SERVERS; i++ ) + { + if( Conf_Server[i].conn_id != Idx ) continue; + + /* Gotcha! Mark server configuration as "unused": */ + Conf_Server[i].conn_id = NONE; + + if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) + { + /* Delete configuration here */ + Init_Server_Struct( &Conf_Server[i] ); + } + else + { + /* Set time for next connect attempt */ + if( Conf_Server[i].lasttry < time( NULL ) - Conf_ConnectRetry ) + { + /* Okay, the connection was established "long enough": */ + Conf_Server[i].lasttry = time( NULL ) - Conf_ConnectRetry + RECONNECT_DELAY; + } + } + } +} /* Conf_UnsetServer */ + + +GLOBAL VOID +Conf_SetServer( INT ConfServer, CONN_ID Idx ) +{ + /* Set connection for specified configured server */ + + assert( ConfServer > NONE ); + assert( Idx > NONE ); + + Conf_Server[ConfServer].conn_id = Idx; +} /* Conf_SetServer */ + + +GLOBAL INT +Conf_GetServer( CONN_ID Idx ) +{ + /* Get index of server in configuration structure */ + + INT i; + + assert( Idx > NONE ); + + for( i = 0; i < MAX_SERVERS; i++ ) + { + if( Conf_Server[i].conn_id == Idx ) return i; + } + return NONE; +} /* Conf_GetServer */ + + +GLOBAL BOOLEAN +Conf_EnableServer( CHAR *Name, INT Port ) +{ + /* Enable specified server and adjust port */ + + INT i; + + assert( Name != NULL ); + + for( i = 0; i < MAX_SERVERS; i++ ) + { + if( strcasecmp( Conf_Server[i].name, Name ) == 0 ) + { + /* Gotcha! Set port and enable server: */ + Conf_Server[i].port = Port; + Conf_Server[i].flags &= ~CONF_SFLAG_DISABLED; + return TRUE; + } + } + return FALSE; +} /* Conf_EnableServer */ + + +GLOBAL BOOLEAN +Conf_DisableServer( CHAR *Name ) +{ + /* Enable specified server and adjust port */ + + INT i; + + assert( Name != NULL ); + + for( i = 0; i < MAX_SERVERS; i++ ) + { + if( strcasecmp( Conf_Server[i].name, Name ) == 0 ) + { + /* 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; + } + } + return FALSE; +} /* Conf_DisableServer */ + + +GLOBAL BOOLEAN +Conf_AddServer( CHAR *Name, INT Port, CHAR *Host, CHAR *MyPwd, CHAR *PeerPwd ) +{ + /* Add new server to configuration */ + + INT i; + + assert( Name != NULL ); + assert( Host != NULL ); + assert( MyPwd != NULL ); + assert( PeerPwd != NULL ); + + /* Search unused item in server configuration structure */ + for( i = 0; i < MAX_SERVERS; i++ ) + { + /* Is this item used? */ + if( ! Conf_Server[i].name[0] ) break; + } + if( i >= MAX_SERVERS ) return FALSE; + + Init_Server_Struct( &Conf_Server[i] ); + strlcpy( Conf_Server[i].name, Name, sizeof( Conf_Server[i].name )); + strlcpy( Conf_Server[i].host, Host, sizeof( Conf_Server[i].host )); + strlcpy( Conf_Server[i].pwd_out, MyPwd, sizeof( Conf_Server[i].pwd_out )); + strlcpy( Conf_Server[i].pwd_in, PeerPwd, sizeof( Conf_Server[i].pwd_in )); + Conf_Server[i].port = Port; + Conf_Server[i].flags = CONF_SFLAG_ONCE; + + return TRUE; +} /* Conf_AddServer */ + + LOCAL VOID -Set_Defaults( VOID ) +Set_Defaults( BOOLEAN InitServers ) { /* Initialize configuration variables with default values. */ + INT i; + strcpy( Conf_ServerName, "" ); sprintf( Conf_ServerInfo, "%s %s", PACKAGE, VERSION ); strcpy( Conf_ServerPwd, "" ); @@ -174,7 +336,8 @@ Set_Defaults( VOID ) strcpy( Conf_ServerAdmin2, "" ); strcpy( Conf_ServerAdminMail, "" ); - strcpy( Conf_MotdFile, MOTD_FILE ); + strlcpy( Conf_MotdFile, SYSCONFDIR, sizeof( Conf_MotdFile )); + strlcat( Conf_MotdFile, MOTD_FILE, sizeof( Conf_MotdFile )); Conf_ListenPorts_Count = 0; @@ -186,12 +349,15 @@ Set_Defaults( VOID ) Conf_ConnectRetry = 60; Conf_Oper_Count = 0; - Conf_Server_Count = 0; Conf_Channel_Count = 0; Conf_OperCanMode = FALSE; - Conf_MaxConnections = 0; + Conf_MaxConnections = -1; + Conf_MaxJoins = 10; + + /* Initialize server configuration structures */ + if( InitServers ) for( i = 0; i < MAX_SERVERS; Init_Server_Struct( &Conf_Server[i++] )); } /* Set_Defaults */ @@ -201,9 +367,10 @@ Read_Config( VOID ) /* Read configuration file. */ CHAR section[LINE_LEN], str[LINE_LEN], *var, *arg, *ptr; - INT line; + INT line, i, n; FILE *fd; + /* Open configuration file */ fd = fopen( NGIRCd_ConfFile, "r" ); if( ! fd ) { @@ -215,8 +382,48 @@ Read_Config( VOID ) Config_Error( LOG_INFO, "Reading configuration from \"%s\" ...", NGIRCd_ConfFile ); + /* Clean up server configuration structure: mark all already + * configured servers as "once" so that they are deleted + * after the next disconnect and delete all unused servers. + * And delete all servers which are "duplicates" of servers + * that are already marked as "once" (such servers have been + * created by the last rehash but are now useless). */ + for( i = 0; i < MAX_SERVERS; i++ ) + { + if( Conf_Server[i].conn_id == NONE ) Init_Server_Struct( &Conf_Server[i] ); + else + { + /* This structure is in use ... */ + if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) + { + /* Check for duplicates */ + for( n = 0; n < MAX_SERVERS; n++ ) + { + if( n == i ) continue; + + if( Conf_Server[i].conn_id == Conf_Server[n].conn_id ) + { + Init_Server_Struct( &Conf_Server[n] ); + Log( LOG_DEBUG, "Deleted unused duplicate server %d (kept %d).", n, i ); + } + } + } + else + { + /* Mark server as "once" */ + Conf_Server[i].flags |= CONF_SFLAG_ONCE; + Log( LOG_DEBUG, "Market server %d as \"once\"", i ); + } + } + } + + /* Initialize variables */ line = 0; strcpy( section, "" ); + Init_Server_Struct( &New_Server ); + New_Server_Idx = NONE; + + /* Read configuration file */ while( TRUE ) { if( ! fgets( str, LINE_LEN, fd )) break; @@ -229,7 +436,7 @@ Read_Config( VOID ) /* Is this the beginning of a new section? */ if(( str[0] == '[' ) && ( str[strlen( str ) - 1] == ']' )) { - strcpy( section, str ); + strlcpy( section, str, sizeof( section )); if( strcasecmp( section, "[GLOBAL]" ) == 0 ) continue; if( strcasecmp( section, "[OPERATOR]" ) == 0 ) { @@ -245,21 +452,30 @@ Read_Config( VOID ) } if( strcasecmp( section, "[SERVER]" ) == 0 ) { - if( Conf_Server_Count + 1 > MAX_SERVERS ) Config_Error( LOG_ERR, "Too many servers configured." ); - else + /* Check if there is already a server to add */ + if( New_Server.name[0] ) + { + /* Copy data to "real" server structure */ + assert( New_Server_Idx > NONE ); + Conf_Server[New_Server_Idx] = New_Server; + } + + /* Re-init structure for new server */ + Init_Server_Struct( &New_Server ); + + /* Search unused item in server configuration structure */ + for( i = 0; i < MAX_SERVERS; i++ ) { - /* Initialize new server structure */ - strcpy( Conf_Server[Conf_Server_Count].host, "" ); - strcpy( Conf_Server[Conf_Server_Count].ip, "" ); - strcpy( Conf_Server[Conf_Server_Count].name, "" ); - strcpy( Conf_Server[Conf_Server_Count].pwd_in, "" ); - strcpy( Conf_Server[Conf_Server_Count].pwd_out, "" ); - Conf_Server[Conf_Server_Count].port = 0; - Conf_Server[Conf_Server_Count].group = -1; - Conf_Server[Conf_Server_Count].lasttry = time( NULL ) - Conf_ConnectRetry + STARTUP_DELAY; - Conf_Server[Conf_Server_Count].res_stat = NULL; - Conf_Server_Count++; + /* Is this item used? */ + if( ! Conf_Server[i].name[0] ) break; } + if( i >= MAX_SERVERS ) + { + /* Oops, no free item found! */ + Config_Error( LOG_ERR, "Too many servers configured." ); + New_Server_Idx = NONE; + } + else New_Server_Idx = i; continue; } if( strcasecmp( section, "[CHANNEL]" ) == 0 ) @@ -297,8 +513,17 @@ Read_Config( VOID ) else if( strcasecmp( section, "[CHANNEL]" ) == 0 ) Handle_CHANNEL( line, var, arg ); else Config_Error( LOG_ERR, "%s, line %d: Variable \"%s\" outside section!", NGIRCd_ConfFile, line, var ); } - + + /* Close configuration file */ fclose( fd ); + + /* Check if there is still a server to add */ + if( New_Server.name[0] ) + { + /* Copy data to "real" server structure */ + assert( New_Server_Idx > NONE ); + Conf_Server[New_Server_Idx] = New_Server; + } /* If there are no ports configured use the default: 6667 */ if( Conf_ListenPorts_Count < 1 ) @@ -324,49 +549,37 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg ) if( strcasecmp( Var, "Name" ) == 0 ) { /* Server name */ - strncpy( Conf_ServerName, Arg, CLIENT_ID_LEN - 1 ); - Conf_ServerName[CLIENT_ID_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_ID_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Info" ) == 0 ) { /* Info text of server */ - strncpy( Conf_ServerInfo, Arg, CLIENT_INFO_LEN - 1 ); - Conf_ServerInfo[CLIENT_INFO_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_INFO_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Info\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Password" ) == 0 ) { /* Global server password */ - strncpy( Conf_ServerPwd, Arg, CLIENT_PASS_LEN - 1 ); - Conf_ServerPwd[CLIENT_PASS_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Password\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "AdminInfo1" ) == 0 ) { /* Administrative info #1 */ - strncpy( Conf_ServerAdmin1, Arg, CLIENT_INFO_LEN - 1 ); - Conf_ServerAdmin1[CLIENT_INFO_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_INFO_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"AdminInfo1\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "AdminInfo2" ) == 0 ) { /* Administrative info #2 */ - strncpy( Conf_ServerAdmin2, Arg, CLIENT_INFO_LEN - 1 ); - Conf_ServerAdmin2[CLIENT_INFO_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_INFO_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"AdminInfo2\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "AdminEMail" ) == 0 ) { /* Administrative email contact */ - strncpy( Conf_ServerAdminMail, Arg, CLIENT_INFO_LEN - 1 ); - Conf_ServerAdminMail[CLIENT_INFO_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_INFO_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"AdminEMail\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Ports" ) == 0 ) @@ -391,9 +604,7 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg ) if( strcasecmp( Var, "MotdFile" ) == 0 ) { /* "Message of the day" (MOTD) file */ - strncpy( Conf_MotdFile, Arg, FNAME_LEN - 1 ); - Conf_MotdFile[FNAME_LEN - 1] = '\0'; - if( strlen( Arg ) > FNAME_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"MotdFile\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "ServerUID" ) == 0 ) @@ -478,7 +689,17 @@ Handle_GLOBAL( INT Line, CHAR *Var, CHAR *Arg ) Conf_MaxConnections = atol( Arg ); return; } - + if( strcasecmp( Var, "MaxJoins" ) == 0 ) + { + /* Maximum number of channels a user can join. Values <= 0 are equal to "no limit". */ +#ifdef HAVE_ISDIGIT + if( ! isdigit( *Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"MaxJoins\" is not a number!", NGIRCd_ConfFile, Line ); + else +#endif + Conf_MaxJoins = atoi( Arg ); + return; + } + Config_Error( LOG_ERR, "%s, line %d (section \"Global\"): Unknown variable \"%s\"!", NGIRCd_ConfFile, Line, Var ); } /* Handle_GLOBAL */ @@ -494,17 +715,13 @@ Handle_OPERATOR( INT Line, CHAR *Var, CHAR *Arg ) if( strcasecmp( Var, "Name" ) == 0 ) { /* Name of IRC operator */ - strncpy( Conf_Oper[Conf_Oper_Count - 1].name, Arg, CLIENT_PASS_LEN - 1 ); - Conf_Oper[Conf_Oper_Count - 1].name[CLIENT_PASS_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Password" ) == 0 ) { /* Password of IRC operator */ - strncpy( Conf_Oper[Conf_Oper_Count - 1].pwd, Arg, CLIENT_PASS_LEN - 1 ); - Conf_Oper[Conf_Oper_Count - 1].pwd[CLIENT_PASS_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Password\" too long!", NGIRCd_ConfFile, Line ); return; } @@ -521,43 +738,38 @@ Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg ) assert( Var != NULL ); assert( Arg != NULL ); + /* Ignore server block if no space is left in server configuration structure */ + if( New_Server_Idx <= NONE ) return; + if( strcasecmp( Var, "Host" ) == 0 ) { /* Hostname of the server */ - strncpy( Conf_Server[Conf_Server_Count - 1].host, Arg, HOST_LEN - 1 ); - Conf_Server[Conf_Server_Count - 1].host[HOST_LEN - 1] = '\0'; - if( strlen( Arg ) > HOST_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Host\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Name" ) == 0 ) { /* Name of the server ("Nick"/"ID") */ - strncpy( Conf_Server[Conf_Server_Count - 1].name, Arg, CLIENT_ID_LEN - 1 ); - Conf_Server[Conf_Server_Count - 1].name[CLIENT_ID_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_ID_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "MyPassword" ) == 0 ) { /* Password of this server which is sent to the peer */ - strncpy( Conf_Server[Conf_Server_Count - 1].pwd_in, Arg, CLIENT_PASS_LEN - 1 ); - Conf_Server[Conf_Server_Count - 1].pwd_in[CLIENT_PASS_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"MyPassword\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "PeerPassword" ) == 0 ) { /* Passwort of the peer which must be received */ - strncpy( Conf_Server[Conf_Server_Count - 1].pwd_out, Arg, CLIENT_PASS_LEN - 1 ); - Conf_Server[Conf_Server_Count - 1].pwd_out[CLIENT_PASS_LEN - 1] = '\0'; - if( strlen( Arg ) > CLIENT_PASS_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"PeerPassword\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Port" ) == 0 ) { /* Port to which this server should connect */ port = atol( Arg ); - if( port > 0 && port < 0xFFFF ) Conf_Server[Conf_Server_Count - 1].port = (INT)port; + if( port > 0 && port < 0xFFFF ) New_Server.port = (INT)port; else Config_Error( LOG_ERR, "%s, line %d (section \"Server\"): Illegal port number %ld!", NGIRCd_ConfFile, Line, port ); return; } @@ -568,7 +780,7 @@ Handle_SERVER( INT Line, CHAR *Var, CHAR *Arg ) if( ! isdigit( *Arg )) Config_Error( LOG_WARNING, "%s, line %d: Value of \"Group\" is not a number!", NGIRCd_ConfFile, Line ); else #endif - Conf_Server[Conf_Server_Count - 1].group = atoi( Arg ); + New_Server.group = atoi( Arg ); return; } @@ -586,25 +798,19 @@ Handle_CHANNEL( INT Line, CHAR *Var, CHAR *Arg ) if( strcasecmp( Var, "Name" ) == 0 ) { /* Name of the channel */ - strncpy( Conf_Channel[Conf_Channel_Count - 1].name, Arg, CHANNEL_NAME_LEN - 1 ); - Conf_Channel[Conf_Channel_Count - 1].name[CHANNEL_NAME_LEN - 1] = '\0'; - if( strlen( Arg ) > CHANNEL_NAME_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Name\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Modes" ) == 0 ) { /* Initial modes */ - strncpy( Conf_Channel[Conf_Channel_Count - 1].modes, Arg, CHANNEL_MODE_LEN - 1 ); - Conf_Channel[Conf_Channel_Count - 1].modes[CHANNEL_MODE_LEN - 1] = '\0'; - if( strlen( Arg ) > CHANNEL_MODE_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Modes\" too long!", NGIRCd_ConfFile, Line ); return; } if( strcasecmp( Var, "Topic" ) == 0 ) { /* Initial topic */ - strncpy( Conf_Channel[Conf_Channel_Count - 1].topic, Arg, CHANNEL_TOPIC_LEN - 1 ); - Conf_Channel[Conf_Channel_Count - 1].topic[CHANNEL_TOPIC_LEN - 1] = '\0'; - if( strlen( Arg ) > CHANNEL_TOPIC_LEN - 1 ) 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( LOG_WARNING, "%s, line %d: Value of \"Topic\" too long!", NGIRCd_ConfFile, Line ); return; } @@ -613,16 +819,23 @@ Handle_CHANNEL( INT Line, CHAR *Var, CHAR *Arg ) LOCAL VOID -Validate_Config( VOID ) +Validate_Config( BOOLEAN Configtest ) { /* Validate configuration settings. */ - + +#ifdef DEBUG + INT i, servers, servers_once; +#endif + if( ! Conf_ServerName[0] ) { /* No server name configured! */ Config_Error( LOG_ALERT, "No server name configured in \"%s\" ('ServerName')!", NGIRCd_ConfFile ); - Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); - exit( 1 ); + if( ! Configtest ) + { + Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); + exit( 1 ); + } } #ifdef STRICT_RFC @@ -630,16 +843,41 @@ Validate_Config( VOID ) { /* No administrative contact configured! */ Config_Error( LOG_ALERT, "No administrator email address configured in \"%s\" ('AdminEMail')!", NGIRCd_ConfFile ); - Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); - exit( 1 ); + if( ! Configtest ) + { + Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); + exit( 1 ); + } } #endif if( ! Conf_ServerAdmin1[0] && ! Conf_ServerAdmin2[0] && ! Conf_ServerAdminMail[0] ) { /* No administrative information configured! */ - Log( LOG_WARNING, "No administrative information configured but required by RFC!" ); + Config_Error( LOG_WARNING, "No administrative information configured but required by RFC!" ); + } +#ifdef FD_SETSIZE + if(( Conf_MaxConnections > (LONG)FD_SETSIZE ) || ( Conf_MaxConnections < 1 )) + { + Conf_MaxConnections = (LONG)FD_SETSIZE; + Config_Error( LOG_ERR, "Setting MaxConnections to %ld, select() can't handle more file descriptors!", Conf_MaxConnections ); } +#else + Config_Error( LOG_WARN, "Don't know how many file descriptors select() can handle on this system, don't set MaxConnections too high!" ); +#endif + +#ifdef DEBUG + servers = servers_once = 0; + for( i = 0; i < MAX_SERVERS; i++ ) + { + if( Conf_Server[i].name[0] ) + { + servers++; + if( Conf_Server[i].flags & CONF_SFLAG_ONCE ) servers_once++; + } + } + Log( LOG_DEBUG, "Configuration: Operators=%d, Servers=%d[%d], Channels=%d", Conf_Oper_Count, servers, servers_once, Conf_Channel_Count ); +#endif } /* Validate_Config */ @@ -675,4 +913,26 @@ va_dcl } /* Config_Error */ +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; + 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 */ + + /* -eof- */