commit f206fda8ae14e9c76e3dca6aa67412d5ae9ee9f7 from: Alexander Barton date: Fri May 24 20:34:53 2013 UTC Implement new configuration option "IncludeDir" The option "IncludeDir" in the [Options] section can be used to specify a directory which can contain further configuration files and configuration file snippets matching the pattern "*.conf" that should be read in after the main configuration file ("ngircd.conf" by default) has been parsed. Closes bug #157. commit - 6beb0fad3ff09ae92a7aea0e4b8ad7b00fe2e26d commit + f206fda8ae14e9c76e3dca6aa67412d5ae9ee9f7 blob - 822fd5d4fb9dd5b99f2694b5be98ce88075c68c5 blob + 31333ec2c7265cb40253a2e63291c781a2d47c90 --- doc/sample-ngircd.conf.tmpl +++ doc/sample-ngircd.conf.tmpl @@ -166,6 +166,10 @@ # Users identified using IDENT are registered without the "~" character # prepended to their user name. ;Ident = yes + + # Directory containing configuration snippets (*.conf), that should + # be read in after parsing this configuration file. + ;IncludeDir = :ETCDIR:/conf.d # Enhance user privacy slightly (useful for IRC server on TOR or I2P) # by censoring some information like idle time, logon time, etc. blob - e5485dbf10edddc2c7c0532b79902bd696fedbc4 blob + 64acd9273456f7d12dc2dba4de5ba8eb5f041bc9 --- man/ngircd.conf.5.tmpl +++ man/ngircd.conf.5.tmpl @@ -1,7 +1,7 @@ .\" .\" ngircd.conf(5) manual page template .\" -.TH ngircd.conf 5 "Feb 2013" ngIRCd "ngIRCd Manual" +.TH ngircd.conf 5 "May 2013" ngIRCd "ngIRCd Manual" .SH NAME ngircd.conf \- configuration file of ngIRCd .SH SYNOPSIS @@ -265,6 +265,11 @@ Users identified using IDENT are registered without th prepended to their user name. Default: yes. .TP +.TP +\fBIncludeDir\fR (string) +Directory containing configuration snippets (*.conf), that should be read in +after parsing the current configuration file. +Default: none. \fBMorePrivacy\fR (boolean) This will cause ngIRCd to censor user idle time, logon time as well as the part/quit messages (that are sometimes used to inform everyone about which blob - eee1925555abbe8d05a7a3cc4ba85dfced474945 blob + d7e1a1542b327ccd2992ff91ad6d13edaa77fe67 --- src/ngircd/conf.c +++ src/ngircd/conf.c @@ -34,8 +34,8 @@ #include #include #include +#include - #include "array.h" #include "ngircd.h" #include "conn.h" @@ -55,6 +55,7 @@ static int New_Server_Idx; static char Conf_MotdFile[FNAME_LEN]; static char Conf_HelpFile[FNAME_LEN]; +static char Conf_IncludeDir[FNAME_LEN]; static void Set_Defaults PARAMS(( bool InitServers )); static bool Read_Config PARAMS(( bool TestOnly, bool IsStarting )); @@ -404,6 +405,7 @@ Conf_Test( void ) #ifdef IDENT printf(" Ident = %s\n", yesno_to_str(Conf_Ident)); #endif + printf(" IncludeDir = %s\n", Conf_IncludeDir); printf(" MorePrivacy = %s\n", yesno_to_str(Conf_MorePrivacy)); printf(" NoticeAuth = %s\n", yesno_to_str(Conf_NoticeAuth)); printf(" OperCanUseMode = %s\n", yesno_to_str(Conf_OperCanMode)); @@ -778,6 +780,7 @@ Set_Defaults(bool InitServers) #else Conf_Ident = false; #endif + strcpy(Conf_IncludeDir, ""); Conf_MorePrivacy = false; Conf_NoticeAuth = false; Conf_OperCanMode = false; @@ -876,8 +879,11 @@ static bool Read_Config(bool TestOnly, bool IsStarting) { const UINT16 defaultport = 6667; + char *ptr, file[FNAME_LEN]; + struct dirent *entry; int i, n; FILE *fd; + DIR *dh; /* Open configuration file */ fd = fopen( NGIRCd_ConfFile, "r" ); @@ -938,9 +944,37 @@ Read_Config(bool TestOnly, bool IsStarting) #endif Read_Config_File(NGIRCd_ConfFile, fd); + fclose(fd); - /* Close configuration file */ - fclose( fd ); + if (Conf_IncludeDir[0]) { + /* Include further configuration files, if any */ + dh = opendir(Conf_IncludeDir); + if (dh) { + while ((entry = readdir(dh)) != NULL) { + ptr = strrchr(entry->d_name, '.'); + if (!ptr || strcasecmp(ptr, ".conf") != 0) + continue; + snprintf(file, sizeof(file), "%s/%s", + Conf_IncludeDir, entry->d_name); + if (TestOnly) + Config_Error(LOG_INFO, + "Reading configuration from \"%s\" ...", + file); + fd = fopen(file, "r"); + if (fd) { + Read_Config_File(file, fd); + fclose(fd); + } else + Config_Error(LOG_ALERT, + "Can't read configuration \"%s\": %s", + file, strerror(errno)); + } + closedir(dh); + } else + Config_Error(LOG_ALERT, + "Can't open include directory \"%s\": %s", + Conf_IncludeDir, strerror(errno)); + } /* Check if there is still a server to add */ if( New_Server.name[0] ) { @@ -999,6 +1033,7 @@ static void Read_Config_File(const char *File, FILE *f size_t count; /* Read configuration file */ + section[0] = '\0'; while (true) { if (!fgets(str, LINE_LEN, fd)) break; @@ -1648,6 +1683,12 @@ Handle_OPTIONS(const char *File, int Line, char *Var, WarnIdent(Line); return; } + if (strcasecmp(Var, "IncludeDir") == 0) { + len = strlcpy(Conf_IncludeDir, Arg, sizeof(Conf_IncludeDir)); + if (len >= sizeof(Conf_IncludeDir)) + Config_Error_TooLong(File, Line, Var); + return; + } if (strcasecmp(Var, "MorePrivacy") == 0) { Conf_MorePrivacy = Check_ArgIsTrue(Arg); return;