/*
* SARG Squid Analysis Report Generator http://sarg.sourceforge.net
- * 1998, 2011
+ * 1998, 2015
*
* SARG donations:
* please look at http://sarg.sourceforge.net/donations.php
#include "include/conf.h"
#include "include/defs.h"
+#include "include/filelist.h"
#define SET_LIST(list) list,sizeof(list)/sizeof(list[0])
+//! The configuration file from which the graph option was loaded
+char GraphConfigFile[MAXLEN]="";
+
+//! How many include directives were followed.
+static int IncludeLevel=0;
+
extern numlist hours, weekdays;
+extern FileListObject AccessLog;
+extern int PerUserLimitsNumber;
+extern struct PerUserLimitStruct PerUserLimits[MAX_USER_LIMITS];
+extern enum PerUserFileCreationEnum PerUserFileCreation;
+extern char ImageDir[MAXLEN];
+extern FileListObject UserAgentLog;
+extern bool UserAgentFromCmdLine;
+extern char StripUserSuffix[MAX_USER_LEN];
+extern int StripSuffixLen;
struct param_list
{
unsigned long int value;
};
+struct select_list
+{
+ //! The name of the value of the parameter.
+ const char *name;
+ //! The value to assign when the name is selected.
+ int value;
+};
+
static struct param_list report_type_values[]=
{
{"users_sites",REPORT_TYPE_USERS_SITES,0},
{"auth_failures",REPORT_TYPE_AUTH_FAILURES,0},
{"site_user_time_date",REPORT_TYPE_SITE_USER_TIME_DATE,0},
{"downloads",REPORT_TYPE_DOWNLOADS,0},
+ {"user_agent",REPORT_TYPE_USERAGENT,0},
};
static struct param_list data_field_values[]=
{"NUM",TOPUSERFIELDS_NUM,0},
{"DATE_TIME",TOPUSERFIELDS_DATE_TIME,0},
{"USERID",TOPUSERFIELDS_USERID,0},
+ {"USERIP",TOPUSERFIELDS_USERIP,0},
{"CONNECT",TOPUSERFIELDS_CONNECT,0},
{"BYTES",TOPUSERFIELDS_BYTES,0},
{"%BYTES",TOPUSERFIELDS_SETYB,0},
{"BYTES",TOPSITE_SORT_BYTES},
{"CONNECT",TOPSITE_SORT_CONNECT},
{"TIME",TOPSITE_SORT_TIME},
+ {"USER",TOPSITE_SORT_USER},
};
struct sort_list user_sort[]=
{"TIME",USER_SORT_TIME},
};
+static struct select_list per_user_limit_create_file[]=
+{
+ {"always",PUFC_Always}, //always create an empty file
+ {"as_required",PUFC_AsRequired}, //create the file if necessary (no empty file is created)
+};
+
static int is_param(const char *param,const char *buf)
{
int plen;
while (*buf && (unsigned char)*buf<=' ') buf++;
if (strlen(buf)>=value_size) {
- debuga(_("The string value of parameter \"%s\" is too long\n"),param);
+ debuga(__FILE__,__LINE__,_("The string value of parameter \"%s\" is too long\n"),param);
exit(EXIT_FAILURE);
}
strcpy(value,buf);
return(1);
}
+/*!
+ * Get a pointer to the beginning of the string value defined by the
+ * parameter. The returned value is NULL if the buffer doesn't contain
+ * the parameter.
+ *
+ * \param param The parameter to look for.
+ * \param buf The buffer containing the line read from the configuration
+ * file.
+ *
+ * \return A pointer to the beginning of the parameter value or NULL if
+ * the line is not for the requested parameter.
+ */
+static char *getparam_stringptr(const char *param,char *buf)
+{
+ int plen;
+
+ plen=strlen(param);
+ if (strncmp(buf,param,plen) != 0) return(NULL);
+ buf+=plen;
+ if ((unsigned char)*buf>' ') return(NULL);
+ while (*buf && (unsigned char)*buf<=' ') buf++;
+
+ return(buf);
+}
+
static int getparam_quoted(const char *param,char *buf,char *value,int value_size)
{
int plen;
while (*buf && (unsigned char)*buf<=' ') buf++;
if (*buf != '\"') {
- debuga(_("Missing double quote after parameter \"%s\"\n"),param);
+ debuga(__FILE__,__LINE__,_("Missing double quote after parameter \"%s\"\n"),param);
exit(EXIT_FAILURE);
}
buf++;
value[i]='\0';
if (*buf != '\"') {
- debuga(_("Missing double quote after parameter \"%s\" or value is more than %d bytes long\n"),param,value_size);
+ debuga(__FILE__,__LINE__,_("Missing double quote after parameter \"%s\" or value is more than %d bytes long\n"),param,value_size);
exit(EXIT_FAILURE);
}
fixnone(value);
for (i=0 ; i<word1_size && *buf && (unsigned char)*buf>' ' ; i++)
word1[i]=*buf++;
if (i>=word1_size) {
- debuga(_("The first word of parameter \"%s\" is more than %d bytes long\n"),param,word1_size-1);
+ debuga(__FILE__,__LINE__,_("The first word of parameter \"%s\" is more than %d bytes long\n"),param,word1_size-1);
exit(EXIT_FAILURE);
}
if (*buf!=' ') {
- debuga(_("Missing second word for parameter \"%s\"\n"),param);
+ debuga(__FILE__,__LINE__,_("Missing second word for parameter \"%s\"\n"),param);
exit(EXIT_FAILURE);
}
word1[i]=0;
for (i=0 ; i<word2_size && *buf && (unsigned char)*buf>' ' ; i++)
word2[i]=*buf++;
if (i>=word2_size) {
- debuga(_("The second word of parameter \"%s\" is more than %d bytes long\n"),param,word2_size-1);
+ debuga(__FILE__,__LINE__,_("The second word of parameter \"%s\" is more than %d bytes long\n"),param,word2_size-1);
exit(EXIT_FAILURE);
}
word2[i]=0;
next=0;
if (sscanf(buf,"%d%n",value,&next) != 1 || (unsigned char)buf[next] > ' ') {
- debuga(_("The integer value of parameter \"%s\" is invalid\n"),param);
+ debuga(__FILE__,__LINE__,_("The integer value of parameter \"%s\" is invalid\n"),param);
exit(EXIT_FAILURE);
}
return(1);
}
for (i=0 ; i<noptions && strcasecmp(buf,options[i].name) ; i++);
if (i>=noptions) {
- debuga(_("Unknown value \"%s\" for parameter \"%s\"\n"),buf,param);
+ debuga(__FILE__,__LINE__,_("Unknown value \"%s\" for parameter \"%s\"\n"),buf,param);
exit(EXIT_FAILURE);
}
if ((*value & options[i].exclude)!=0) {
- debuga(_("Value \"%s\" conflicts with other selected values for parameter \"%s\"\n"),buf,param);
+ debuga(__FILE__,__LINE__,_("Value \"%s\" conflicts with other selected values for parameter \"%s\"\n"),buf,param);
exit(EXIT_FAILURE);
}
*value|=options[i].value;
}
for (i=0 ; i<noptions && strcasecmp(buf,options[i].name) ; i++);
if (i>=noptions) {
- debuga(_("Unknown sort criterion \"%s\" for parameter \"%s\"\n"),buf,param);
+ debuga(__FILE__,__LINE__,_("Unknown sort criterion \"%s\" for parameter \"%s\"\n"),buf,param);
exit(EXIT_FAILURE);
}
*value=options[i].value;
if (strcasecmp(order,"reverse")==0 || strcasecmp(order,"D")==0) {
*value|=SORT_REVERSE;
} else if (strcasecmp(order,"normal")!=0 && strcasecmp(order,"A")!=0) {
- debuga(_("Unknown sort order \"%s\" for parameter \"%s\"\n"),order,param);
+ debuga(__FILE__,__LINE__,_("Unknown sort order \"%s\" for parameter \"%s\"\n"),order,param);
exit(EXIT_FAILURE);
}
}
return(1);
}
-static void parmtest(char *buf)
+static int getparam_select(const char *param,struct select_list *options,int noptions,char *buf,int *value)
+{
+ int plen;
+ char *str;
+ int i;
+
+ plen=strlen(param);
+ if (strncmp(buf,param,plen) != 0) return(0);
+ buf+=plen;
+ if ((unsigned char)*buf>' ') return(0);
+ while (*buf && (unsigned char)*buf<=' ') buf++;
+
+ str=buf;
+ while (*buf && (unsigned char)*buf>' ' && *buf!=';') buf++;
+ *buf='\0';
+ for (i=0 ; i<noptions && strcasecmp(str,options[i].name) ; i++);
+ if (i>=noptions) {
+ debuga(__FILE__,__LINE__,_("Unknown value \"%s\" for parameter \"%s\"\n"),str,param);
+ exit(EXIT_FAILURE);
+ }
+ *value=options[i].value;
+ return(1);
+}
+
+static int getparam_userlimit(const char *param,char *buf)
+{
+ int plen;
+ char *file_begin,*file_end;
+ int limit;
+ int digit;
+ char *str;
+ int i;
+ enum PerUserOutputEnum output;
+ const struct
+ {
+ const char *name;
+ enum PerUserOutputEnum value;
+ } output_types[]=
+ {
+ {"id",PUOE_UserId},
+ {"ip",PUOE_UserIp},
+ };
+
+ plen=strlen(param);
+ if (strncmp(buf,param,plen) != 0) return(0);
+ buf+=plen;
+ if ((unsigned char)*buf>' ') return(0);
+ while (*buf && (unsigned char)*buf<=' ') buf++;
+
+ /*
+ options are made of a file name, an integer limit and an optional
+ integer flag. The file name may contain spaces. We keep searching
+ until a valid number is found after a space.
+ */
+ file_begin=buf;
+ do {
+ while (*buf && (unsigned char)*buf>' ') buf++;
+ if (*buf!=' ') {
+ debuga(__FILE__,__LINE__,_("Missing limit in per_user_limit\n"));
+ exit(EXIT_FAILURE);
+ }
+ file_end=buf;
+ while (*buf && (unsigned char)*buf<=' ') buf++;
+ limit=0;
+ while (*buf && isdigit(*buf)) {
+ digit=*buf-'0';
+ if (limit>=(INT_MAX-digit)/10) break;
+ limit=limit*10+digit;
+ buf++;
+ }
+ } while (*buf && *buf!=' ');
+
+ output=PUOE_UserId;
+ if (*buf==' ') {
+ while (*buf && (unsigned char)*buf<=' ') buf++;
+ str=buf;
+ while (*buf && (unsigned char)*buf>' ') buf++;
+ *buf='\0';
+ for (i=sizeof(output_types)/sizeof(output_types[0])-1 ; i>=0 ; i--)
+ if (strcasecmp(output_types[i].name,str)==0) {
+ output=output_types[i].value;
+ break;
+ }
+ if (i<0) {
+ debuga(__FILE__,__LINE__,_("Invalid output type in per_user_limit\n"));
+ exit(EXIT_FAILURE);
+ }
+ }
+
+ if (PerUserLimitsNumber>=MAX_USER_LIMITS) {
+ debuga(__FILE__,__LINE__,_("Too many per_user_limit\n"));
+ exit(EXIT_FAILURE);
+ }
+ *file_end='\0';
+ safe_strcpy(PerUserLimits[PerUserLimitsNumber].File,file_begin,sizeof(PerUserLimits[PerUserLimitsNumber].File));
+ PerUserLimits[PerUserLimitsNumber].Limit=limit;
+ PerUserLimits[PerUserLimitsNumber].Output=output;
+ PerUserLimitsNumber++;
+
+ return(1);
+}
+
+static void ccharset(char *CharSet)
+{
+ if (strcmp(CharSet,"Latin2") == 0) strcpy(CharSet,"ISO-8859-2");
+ else if (strcmp(CharSet,"Latin3") == 0) strcpy(CharSet,"ISO-8859-3");
+ else if (strcmp(CharSet,"Latin4") == 0) strcpy(CharSet,"ISO-8859-4");
+ else if (strcmp(CharSet,"Cyrillic") == 0) strcpy(CharSet,"ISO-8859-5");
+ else if (strcmp(CharSet,"Arabic") == 0) strcpy(CharSet,"ISO-8859-6");
+ else if (strcmp(CharSet,"Greek") == 0) strcpy(CharSet,"ISO-8859-7");
+ else if (strcmp(CharSet,"Hebrew") == 0) strcpy(CharSet,"ISO-8859-8");
+ else if (strcmp(CharSet,"Latin5") == 0) strcpy(CharSet,"ISO-8859-9");
+ else if (strcmp(CharSet,"Latin6") == 0) strcpy(CharSet,"ISO-8859-10");
+ else if (strcmp(CharSet,"Japan") == 0) strcpy(CharSet,"EUC-JP");
+ else if (strcmp(CharSet,"Koi8-r") == 0) strcpy(CharSet,"KOI8-R");
+ /*
+ * Any other encoding name is left unchanged.
+ */
+ return;
+}
+
+static void parmtest(char *buf,const char *File)
{
char wbuf[2048];
struct getwordstruct gwarea;
+ int iVal;
while (*buf && (unsigned char)*buf<=' ') buf++;
if(*buf == '#' || *buf == '\0')
return;
- if(debugz)
+ if(debugz>=LogLevel_Process)
printf(_("SARG: TAG: %s\n"),buf);
if (getparam_string("background_color",buf,BgColor,sizeof(BgColor))>0) return;
if (getparam_quoted("title",buf,Title,sizeof(Title))>0) return;
- if (getparam_bool("resolve_ip",buf,&Ip2Name)>0) return;
+ if (strncasecmp(buf,"resolve_ip",10)==0) {
+ if (ip2name_config(buf+10)>0) return;
+ }
if (getparam_bool("user_ip",buf,&UserIp)>0) return;
if (is_param("date_format",buf)) {
getword_start(&gwarea,buf);
if (getword_multisep(wbuf,sizeof(wbuf),&gwarea,' ')<0) {
- debuga(_("Maybe you have a broken record or garbage in \"date_format\" parameter\n"));
+ debuga(__FILE__,__LINE__,_("Invalid record in \"date_format\" parameter\n"));
exit(EXIT_FAILURE);
}
- strncpy(DateFormat,gwarea.current,1);
- fixnone(DateFormat);
+ DateFormat=gwarea.current[0];
return;
}
if (is_param("hours",buf)) {
if( getnumlist( buf, &hours, 24, 24 ) ) {
- debuga(_("Error: Invalid syntax in hours tag!\n"));
+ debuga(__FILE__,__LINE__,_("Error: Invalid syntax in hours tag!\n"));
exit( 1 );
}
return;
if (is_param("weekdays",buf)) {
if( getnumlist( buf, &weekdays, 7, 7 ) ) {
- debuga(_("Error: Invalid syntax in weekdays tag!\n"));
+ debuga(__FILE__,__LINE__,_("Error: Invalid syntax in weekdays tag!\n"));
exit( 1 );
}
return;
if (is_param("access_log",buf)>0) {
if (AccessLogFromCmdLine==0) {
- if (NAccessLog>=MAXLOGS) {
- debuga(_("Too many log files in configuration file\n"));
+ char *FileName=getparam_stringptr("access_log",buf);
+ if (!AccessLog)
+ AccessLog=FileList_Create();
+ if (!FileList_AddFile(AccessLog,FileName)) {
+ debuga(__FILE__,__LINE__,_("Not enough memory to store the input log file names\n"));
exit(EXIT_FAILURE);
}
- getparam_string("access_log",buf,AccessLog[NAccessLog],MAX_LOG_FILELEN);
- NAccessLog++;
}
return;
}
if (is_param("redirector_log",buf)>0) {
if (RedirectorLogFromCmdLine==0) {
if (NRedirectorLogs>=MAX_REDIRECTOR_LOGS) {
- debuga(_("Too many redirector log files in configuration file\n"));
+ debuga(__FILE__,__LINE__,_("Too many redirector log files in configuration file\n"));
exit(EXIT_FAILURE);
}
getparam_string("redirector_log",buf,RedirectorLogs[NRedirectorLogs],MAX_REDIRECTOR_FILELEN);
return;
}
- if (getparam_string("useragent_log",buf,UserAgentLog,sizeof(UserAgentLog))>0) return;
+ if (is_param("useragent_log",buf)>0) {
+ if (!UserAgentFromCmdLine) {
+ if (!UserAgentLog)
+ UserAgentLog=FileList_Create();
+ char *FileName=getparam_stringptr("useragent_log",buf);
+ if (!FileList_AddFile(UserAgentLog,FileName)) {
+ debuga(__FILE__,__LINE__,_("Not enough memory to store a user agent file name\n"));
+ exit(EXIT_FAILURE);
+ }
+ }
+ return;
+ }
if (getparam_string("exclude_hosts",buf,ExcludeHosts,sizeof(ExcludeHosts))>0) return;
if (getparam_string("output_email",buf,OutputEmail,sizeof(OutputEmail))>0) return;
- if (getparam_2words("per_user_limit",buf,PerUserLimitFile,sizeof(PerUserLimitFile),wbuf,sizeof(wbuf))>0) {
- PerUserLimit=atoi(wbuf);
+ if (getparam_userlimit("per_user_limit",buf)>0) return;
+
+ if (getparam_select("per_user_limit_file_create",SET_LIST(per_user_limit_create_file),buf,&iVal)>0) {
+ PerUserFileCreation=(enum PerUserFileCreationEnum)iVal;
return;
}
if (getparam_bool("show_read_statistics",buf,&ShowReadStatistics)>0) return;
+ if (getparam_bool("show_read_percent",buf,&ShowReadPercent)>0) return;
+
if (getparam_list("topuser_fields",SET_LIST(topuserfields_values),buf,&TopUserFields)>0) return;
if (getparam_bool("bytes_in_sites_users_report",buf,&BytesInSitesUsersReport)>0) return;
if (getparam_bool("user_authentication",buf,&UserAuthentication)>0) return;
if (getparam_string("AuthUserTemplateFile",buf,wbuf,sizeof(wbuf))>0) {
- char dir[MAXLEN];
-
if (is_absolute(wbuf)) {
if (strlen(wbuf)>=sizeof(AuthUserTemplateFile)) {
- debuga(_("Template file name is too long in parameter \"AuthUserTemplateFile\"\n"));
+ debuga(__FILE__,__LINE__,_("Template file name is too long in parameter \"AuthUserTemplateFile\"\n"));
exit(EXIT_FAILURE);
}
- strcpy(AuthUserTemplateFile,wbuf);
+ safe_strcpy(AuthUserTemplateFile,wbuf,sizeof(AuthUserTemplateFile));
} else {
- strcpy(dir,ConfigFile);
+ char dir[MAXLEN];
+
+ safe_strcpy(dir,File,sizeof(dir));
if (snprintf(AuthUserTemplateFile,sizeof(AuthUserTemplateFile),"%s/%s",dirname(dir),wbuf)>=sizeof(AuthUserTemplateFile)) {
- debuga(_("Template file name is too long in parameter \"AuthUserTemplateFile\"\n"));
+ debuga(__FILE__,__LINE__,_("Template file name is too long in parameter \"AuthUserTemplateFile\"\n"));
exit(EXIT_FAILURE);
}
}
return;
}
- if (getparam_bool("graphs",buf,&Graphs)>0) return;
+ if (getparam_bool("graphs",buf,&Graphs)>0) {
+#ifndef HAVE_GD
+ if (Graphs)
+ debugaz(__FILE__,__LINE__,_("No graphs available as sarg was not compiled with libgd. Set \"graphs\" to \"no\" in %s to disable this warning\n"),
+ File);
+#endif
+ safe_strcpy(GraphConfigFile,File,sizeof(GraphConfigFile));
+ return;
+ }
if (getparam_string("graph_days_bytes_bar_color",buf,GraphDaysBytesBarColor,sizeof(GraphDaysBytesBarColor))>0) return;
if (getparam_string("redirector_log_format",buf,RedirectorLogFormat,sizeof(RedirectorLogFormat))>0) return;
if (getparam_string("squidguard_log_format",buf,RedirectorLogFormat,sizeof(RedirectorLogFormat))>0) {
- debuga(_("squidguard_log_format is deprecated and has been replaced by redirector_log_format. Please update your configuration file.\n"));
+ debuga(__FILE__,__LINE__,_("squidguard_log_format is deprecated and has been replaced by redirector_log_format. Please update your configuration file.\n"));
return;
}
/*
Due to an old bug in sarg before version 2.3, the option was having the opposite action than implied by the name.
*/
- debuga(_("redirector_ignore_date is deprecated and has been replaced by redirector_filter_out_date that does the action implied by its name as opposed to redirector_ignore_date. Please update your configuration file.\n"));
+ debuga(__FILE__,__LINE__,_("redirector_ignore_date is deprecated and has been replaced by redirector_filter_out_date that does the action implied by its name as opposed to redirector_ignore_date. Please update your configuration file.\n"));
RedirectorFilterOutDate=!RedirectorFilterOutDate;
return;
}
if (getparam_bool("squidguard_ignore_date",buf,&RedirectorFilterOutDate)>0) {
- debuga(_("squidguard_ignore_date is deprecated and has been replaced by redirector_filter_out_date that does the action implied by its name as opposed to squidguard_ignore_date. Please update your configuration file.\n"));
+ debuga(__FILE__,__LINE__,_("squidguard_ignore_date is deprecated and has been replaced by redirector_filter_out_date that does the action implied by its name as opposed to squidguard_ignore_date. Please update your configuration file.\n"));
RedirectorFilterOutDate=!RedirectorFilterOutDate;
return;
}
if (getparam_bool("dansguardian_filter_out_date",buf,&DansguardianFilterOutDate)>0) return;
if (getparam_bool("dansguardian_ignore_date",buf,&DansguardianFilterOutDate)>0) {
- debuga(_("dansguardian_ignore_date is deprecated and has been replaced by dansguardian_filter_out_date that does the action implied by its name as opposed to dansguardian_ignore_date. Please update your configuration file.\n"));
+ debuga(__FILE__,__LINE__,_("dansguardian_ignore_date is deprecated and has been replaced by dansguardian_filter_out_date that does the action implied by its name as opposed to dansguardian_ignore_date. Please update your configuration file.\n"));
DansguardianFilterOutDate=!DansguardianFilterOutDate;
return;
}
if (getparam_list("ntlm_user_format",SET_LIST(ntml_userformat_values),buf,&NtlmUserFormat)>0) return;
+ if (getparam_string("strip_user_suffix",buf,StripUserSuffix,sizeof(StripUserSuffix))>0) {
+ StripSuffixLen=strlen(StripUserSuffix);
+ return;
+ }
+
if (getparam_string("realtime_types",buf,RealtimeTypes,sizeof(RealtimeTypes))>0) return;
if (getparam_list("realtime_unauthenticated_records",SET_LIST(realtime_unauth_values),buf,&RealtimeUnauthRec)>0) return;
if (getparam_string("LDAPTargetAttr",buf,LDAPTargetAttr,sizeof(LDAPTargetAttr))>0) return;
+ if (getparam_string("LDAPNativeCharset",buf,LDAPNativeCharset,sizeof(LDAPNativeCharset))>0) return;
+
if (getparam_string("graph_font",buf,GraphFont,sizeof(GraphFont))>0) return;
if (getparam_string("sorttable",buf,SortTableJs,sizeof(SortTableJs))>0) return;
+ if (getparam_string("hostalias",buf,HostAliasFile,sizeof(HostAliasFile))>0) return;
+
+ if (getparam_string("useralias",buf,UserAliasFile,sizeof(UserAliasFile))>0) return;
+
+ if (getparam_bool("keep_temp_log",buf,&KeepTempLog)>0) return;
+
+ if (getparam_int("max_successive_log_errors",buf,&NumLogSuccessiveErrors)>0) return;
+
+ if (getparam_int("max_total_log_errors",buf,&NumLogTotalErrors)>0) return;
+
if(strstr(buf,"squid24") != 0) {
squid24=true;
return;
if(strstr(buf,"byte_cost") != 0) {
getword_start(&gwarea,buf);
if (getword_multisep(wbuf,sizeof(wbuf),&gwarea,' ')<0) {
- debuga(_("The \"byte_cost\" parameter of the configuration file is invalid\n"));
+ debuga(__FILE__,__LINE__,_("The \"byte_cost\" parameter of the configuration file is invalid\n"));
exit(EXIT_FAILURE);
}
cost=atol(gwarea.current);
if (getword_multisep(wbuf,sizeof(wbuf),&gwarea,' ')<0) {
- debuga(_("The \"byte_cost\" parameter of the configuration file is invalid\n"));
+ debuga(__FILE__,__LINE__,_("The \"byte_cost\" parameter of the configuration file is invalid\n"));
exit(EXIT_FAILURE);
}
nocost=my_atoll(gwarea.current);
return;
}
+ if (getparam_string("image_dir",buf,ImageDir,sizeof(ImageDir))>0) return;
+
printf(_("SARG: Unknown option %s\n"),buf);
}
-void getconf(void)
+void getconf(const char *File)
{
FILE *fp_in;
char buf[MAXLEN];
+ char IncludeFile[MAXLEN];
+
+ IncludeLevel++;
+ if (debug) {
+ if (IncludeLevel<=1)
+ debuga(__FILE__,__LINE__,_("Loading configuration file \"%s\"\n"),File);
+ else
+ debuga(__FILE__,__LINE__,_("Including configuration file \"%s\"\n"),File);
+ }
- if(debug)
- debuga(_("Loading configuration from %s\n"),ConfigFile);
+ // stop if include files are producing a loop
+ if (IncludeLevel>5) {
+ debuga(__FILE__,__LINE__,_("Too many nested configuration files included in \"%s\""),ConfigFile);
+ exit(EXIT_FAILURE);
+ }
- if ((fp_in = fopen(ConfigFile, "r")) == NULL) {
- debuga(_("(getconf) Cannot open file %s\n"),ConfigFile);
+ if ((fp_in = fopen(File, "r")) == NULL) {
+ debuga(__FILE__,__LINE__,_("Cannot open file \"%s\": %s\n"),File,strerror(errno));
exit(EXIT_FAILURE);
}
while (fgets(buf, sizeof(buf), fp_in) != NULL) {
fixendofline(buf);
- if(debugm)
- printf("SYSCONFDIR %s\n",buf);
+ if (getparam_string("include",buf,IncludeFile,sizeof(IncludeFile))>0) {
+ getconf(IncludeFile);
+ continue;
+ }
- parmtest(buf);
+ if (debugz>=LogLevel_Data)
+ printf("SYSCONFDIR %s\n",buf);
+ parmtest(buf,File);
}
- fclose(fp_in);
- return;
+ if (fclose(fp_in)==EOF) {
+ debuga(__FILE__,__LINE__,_("Read error in \"%s\": %s\n"),File,strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ IncludeLevel--;
}