X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=ngircd-alex.git;a=blobdiff_plain;f=src%2Fngircd%2Fconf.c;h=9d6071e1e5c165c90a535b42450329a754e0dab3;hp=c2478b8eb0c99d36689a1ad5e2573863d2485f5f;hb=0b91df05e0b85980292956973b339ecce31e28ed;hpb=6626395c88fc46eeb110942b17eb9245a1d0021b diff --git a/src/ngircd/conf.c b/src/ngircd/conf.c index c2478b8e..9d6071e1 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.50 2002/12/26 16:48:14 alex Exp $"; +static char UNUSED id[] = "$Id: conf.c,v 1.56 2003/04/20 23:09:43 alex Exp $"; #include "imp.h" #include @@ -46,9 +46,11 @@ static char UNUSED id[] = "$Id: conf.c,v 1.50 2002/12/26 16:48:14 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(( BOOLEAN TestOnly )); @@ -59,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( FALSE ); } /* Config_Init */ +GLOBAL VOID +Conf_Rehash( VOID ) +{ + Set_Defaults( FALSE ); + Read_Config( ); + Validate_Config( FALSE ); +} /* Config_Rehash */ + + GLOBAL INT Conf_Test( VOID ) { @@ -79,7 +92,7 @@ Conf_Test( VOID ) INT i; Use_Log = FALSE; - Set_Defaults( ); + Set_Defaults( TRUE ); Read_Config( ); Validate_Config( TRUE ); @@ -134,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; @@ -165,13 +178,158 @@ 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 ); + sprintf( Conf_ServerInfo, "%s %s", PACKAGE_NAME, PACKAGE_VERSION ); strcpy( Conf_ServerPwd, "" ); strcpy( Conf_ServerAdmin1, "" ); @@ -191,13 +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 = -1; Conf_MaxJoins = 10; + + /* Initialize server configuration structures */ + if( InitServers ) for( i = 0; i < MAX_SERVERS; Init_Server_Struct( &Conf_Server[i++] )); } /* Set_Defaults */ @@ -207,22 +367,63 @@ 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 ) { /* No configuration file found! */ Config_Error( LOG_ALERT, "Can't read configuration \"%s\": %s", NGIRCd_ConfFile, strerror( errno )); - Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); + Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME ); exit( 1 ); } 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, "Marked 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; @@ -235,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 ) { @@ -251,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 ) @@ -303,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 ) @@ -519,35 +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 */ - if( strlcpy( Conf_Server[Conf_Server_Count - 1].host, Arg, sizeof( Conf_Server[Conf_Server_Count - 1].host )) >= sizeof( Conf_Server[Conf_Server_Count - 1].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( 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") */ - if( strlcpy( Conf_Server[Conf_Server_Count - 1].name, Arg, sizeof( Conf_Server[Conf_Server_Count - 1].name )) >= sizeof( Conf_Server[Conf_Server_Count - 1].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( 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 */ - if( strlcpy( Conf_Server[Conf_Server_Count - 1].pwd_in, Arg, sizeof( Conf_Server[Conf_Server_Count - 1].pwd_in )) >= sizeof( Conf_Server[Conf_Server_Count - 1].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( 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 */ - if( strlcpy( Conf_Server[Conf_Server_Count - 1].pwd_out, Arg, sizeof( Conf_Server[Conf_Server_Count - 1].pwd_out )) >= sizeof( Conf_Server[Conf_Server_Count - 1].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( 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; } @@ -558,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; } @@ -600,14 +822,18 @@ LOCAL 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 ); if( ! Configtest ) { - Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); + Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME ); exit( 1 ); } } @@ -619,7 +845,7 @@ Validate_Config( BOOLEAN Configtest ) Config_Error( LOG_ALERT, "No administrator email address configured in \"%s\" ('AdminEMail')!", NGIRCd_ConfFile ); if( ! Configtest ) { - Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE ); + Config_Error( LOG_ALERT, "%s exiting due to fatal errors!", PACKAGE_NAME ); exit( 1 ); } } @@ -639,6 +865,19 @@ Validate_Config( BOOLEAN Configtest ) #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 */ @@ -674,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- */