pcre_status="disabled"
fi
+# Build with file globbing
+AC_ARG_WITH([glob],
+AS_HELP_STRING([--without-glob],[Ignore wildcards in file names]),
+[with_glob=no],[with_glob=yes])
+if ( test "x$with_glob" != "xno" ) ; then
+ AC_CHECK_HEADERS(glob.h)
+else
+ glob_status="disabled"
+fi
+
dnl Checks for typedefs, structures, and compiler characteristics.
AC_C_CONST
AC_STRUCT_TM
elif ( test "x$ldap_status" = "xnot found" ) ; then
AC_MSG_NOTICE([ldap header files not found so LDAP is not available to resolve user's names])
fi
+
+if ( test "x$glob_status" = "xdisabled" ) ; then
+ AC_MSG_NOTICE([Not building with file globbing as requested on the configuration command line])
+fi
#include "include/defs.h"
#include "include/stringbuffer.h"
#include "include/filelist.h"
+#ifdef HAVE_GLOB_H
+#include <glob.h>
+#endif
struct DirEntryStruct
{
int Level;
//! The current node at each level.
struct DirEntryIterator *DirNodes;
+#ifdef HAVE_GLOB_H
+ //! Next globbed file to return
+ int NextGlob;
+ //! Buffer with the globbed files.
+ glob_t Glob;
+#endif
};
*/
const char *FileListIter_Next(struct _FileListIterator *FIter)
{
- int Length;
- int Level;
- struct DirEntryIterator *DIter;
-
- if (!FIter) return(NULL);
- if (!FIter->DirNodes) return(NULL);
- if (FIter->Level<0 || FIter->Level>=FIter->TreeDepth) return(NULL);
+ const char *Path;
- // how much space to store the path
- Length=FIter->DirNodes[FIter->CurrentPathLevel].PathLength;
- for (Level=FIter->CurrentPathLevel ; Level<=FIter->Level ; Level++)
+#ifdef HAVE_GLOB_H
+ if (FIter->NextGlob>0)
{
- DIter=FIter->DirNodes+Level;
- DIter->PathLength=Length;;
- Length+=strlen(DIter->Dir->Name)+1;
- }
-
- // get the memory to store the path
- if (Length>FIter->CurrentPathSize)
- {
- char *temp=realloc(FIter->CurrentPath,Length);
- if (!temp) return(NULL);
- FIter->CurrentPath=temp;
- FIter->CurrentPathSize=Length;
+ if (FIter->NextGlob<FIter->Glob.gl_pathc)
+ {
+ Path=FIter->Glob.gl_pathv[FIter->NextGlob++];
+ return(Path);
+ }
+ globfree(&FIter->Glob);
+ FIter->NextGlob=0;
}
-
- for (Level=FIter->CurrentPathLevel ; Level<=FIter->Level ; Level++)
+ /*
+ * Try every pattern until the list is exhausted or a real error
+ * occurs or a file is matched.
+ */
+ while ((Path=FileListIter_NextWithMask(FIter))!=NULL)
{
- DIter=FIter->DirNodes+Level;
- if (Level>0) FIter->CurrentPath[DIter->PathLength-1]='/';
- strcpy(FIter->CurrentPath+DIter->PathLength,DIter->Dir->Name);
+ int ErrCode=glob(Path,GLOB_ERR | GLOB_NOSORT,NULL,&FIter->Glob);
+ if (ErrCode==0)//success
+ {
+ Path=FIter->Glob.gl_pathv[0];
+ FIter->NextGlob=1;
+ break;
+ }
+ if (ErrCode!=GLOB_NOMATCH)
+ {
+ switch (ErrCode)
+ {
+ case GLOB_NOSPACE:
+ debuga(__FILE__,__LINE__,_("Not enough memory to read the files matching \"%s\"\n"),Path);
+ break;
+ case GLOB_ABORTED:
+ debuga(__FILE__,__LINE__,_("Read error while listing the files matching \"%s\"\n"),Path);
+ break;
+ }
+ exit(EXIT_FAILURE);
+ }
}
- FIter->CurrentPathLevel=Level;
-
- FileListIter_GetNext(FIter);
- return(FIter->CurrentPath);
+#else
+ /*
+ * Fall back to a simple enumeration. In that case, the user cannot use
+ * wildcards as they won't be expended.
+ */
+ Path=FileListIter_NextWithMask(FIter);
+#endif
+ return(Path);
}
/*!
for (Level=FIter->CurrentPathLevel ; Level<=FIter->Level ; Level++)
{
DIter=FIter->DirNodes+Level;
- DIter->PathLength=Length;;
+ DIter->PathLength=Length;
Length+=strlen(DIter->Dir->Name)+1;
}
{
if (FIter)
{
+#ifdef HAVE_GLOB_H
+ if (FIter->NextGlob>0) globfree(&FIter->Glob);
+#endif
if (FIter->CurrentPath) free(FIter->CurrentPath);
if (FIter->DirNodes) free(FIter->DirNodes);
free(FIter);
# safety against incomplete reporting due to problems occuring with the
# logs.
#
+# If the file globbing was compiled in, the file name can contain shell
+# wildcards such as * and ?. Tilde expension and variable expension are
+# not supported. Special characters can be escaped with a backslash.
+#
# If some files are passed on the command line with "sarg -l file" or
# "sarg file", the files listed here are ignored.
#
#exclude_hosts none
# TAG: useragent_log file
-# useragent.log file patch to generate useragent report.
+# useragent.log file to generate useragent report.
+#
+# This option may be repeated multiple times to process several files.
+#
+# Wildcards are allowed (see access_log).
#
#useragent_log none