Package: filtergen
Severity: wishlist
Tags: patch

The attached patch implements globbing for include directives in filtergen
rulesets, along with glob()s standard sorting functionality.  This allows
filtergen to be more safe (not read backup files and the like scattered
around a directory) and also to nicely order files within a directory so you
can know that 99log.fg is going to be at the end of all the rules.

- Matt
--- filtergen-0.12.4.orig/filter_syntax.5	2004-06-09 22:48:41.000000000 +1000
+++ filtergen-0.12.4.defined_include_order/filter_syntax.5	2009-10-02 08:21:35.000000000 +1000
@@ -175,6 +175,71 @@
 and "sport 12345" need to be either both in the group, or both
 out of it.
 
+.SH INCLUDING OTHER FILES
+
+You can, if necessary, include other files containing filtergen statements
+in your filter files, with the \fIinclude\fR directive.  This is legal
+anywhere in the file, and acts as if you literally read the included file
+into the position where the \fIinclude\fR is placed.  This allows you to,
+for example, specify a common set of addresses (say, your monitoring system)
+and reference them in multiple locations:
+
+.nf
+	input eth0 {
+		proto tcp dport ssh source {
+			include monitoring-hosts.acl
+		} accept;
+		
+		...
+		
+		# NRPE
+		proto tcp dport 5666 source {
+			include monitoring-hosts.acl
+		} accept;
+	}
+	
+	output eth0 {
+		proto tcp sport ssh dest {
+			include monitoring-hosts.acl
+		} accept;
+		
+		...
+		
+		# NRPE
+		proto tcp sport 5666 source {
+			include monitoring-hosts.acl
+		} accept;
+	}
+.fi
+
+Whilst you could improve this particular example without an \fIinclude\fR by
+grouping your ssh and NRPE ports together, you'd still have two places to
+edit when you changed your set of monitoring hosts.  Using include, you can
+have a single place to change when you change your monitoring hosts.
+
+You can also include a glob of files, rather than a single file, by using
+one of the shell globbing metacharacters '\fI*\fR', '\fI?\fR', or '\fI[\fR'. 
+This will cause filtergen to expand that glob and parse the files as if you
+had included them one-by-one, in your locale's sorted order.  This is very
+handy if you configure your systems with an automated system, because you
+can dump a series of files into a directory depending on what classes are
+defined, and filtergen will pick them all up.  The sorting is to ensure that
+your rules appear in the order you want them, rather than some
+higgledy-piggledy mess.  Note that any directories that match your glob will
+not be recursively included in this mode.
+
+Finally, you can just provide a directory name, and filtergen will include
+all the files and directories under there, recursively (excluding hidden
+files, starting with a '.').  \fBThis method of including files is strongly
+deprecated\fR.  There is no defined sort order, and if your editor leaves
+backup or temporary files around, or your configuration management system
+puts it's backups in the same directory as the original file (cfengine, I'm
+looking at \fIyou\fR), you can find yourself including files you really
+didn't intend -- hence why it is a bad idea.  Instead, use a glob (above)
+with an explicit extension (we like \fI*.fg\fR) to perform your directory
+inclusions with minimal chance of accidents.
+
+
 .SH EXAMPLE
 Here's a fairly complete example, for a single-interface machine:
 
--- filtergen-0.12.4.orig/scanner.l	2009-10-01 17:04:30.000000000 +1000
+++ filtergen-0.12.4.defined_include_order/scanner.l	2009-10-02 08:23:08.000000000 +1000
@@ -27,6 +27,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <dirent.h>
+#include <glob.h>
 #include "parser.h"
 
 /* include file stack */
@@ -194,7 +195,35 @@
 	char * fn;
 
 	if (stat(name, &st)) {
-		scan_err("warning: stat failed on %s: %s", name, strerror(errno));
+		if (errno == ENOENT && (index(name, '*') != NULL || index(name, '?') != NULL || index(name, '[') != NULL)) {
+			/* Globbing fiesta! */
+			glob_t glob_buf;
+			if (glob(name, 0, NULL, &glob_buf) != 0) {
+				scan_err("warning: failed to glob %s: %s", name, strerror(errno));
+			} else {
+				int n;
+				
+				/* We go through the list of files backwards, because
+				 * step_into_include_file() creates a stack of all the
+				 * files processed and then works on them in a LIFO
+				 * fashion -- which would make all of our rules files
+				 * go backwards.  Since I can't wrap my head around
+				 * why that is, exactly, I'm hacking it up with
+				 * this instead.  Fixination appreciated.
+				 */
+				for (n = glob_buf.gl_pathc - 1; n >= 0; n--) {
+					if (stat(glob_buf.gl_pathv[n], &st)) {
+						scan_err("warning: stat failed on globbed %s: %s", glob_buf.gl_pathv[n], strerror(errno));
+					} else if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
+						step_into_include_file(glob_buf.gl_pathv[n]);
+					}
+				}
+			}
+			
+			globfree(&glob_buf);
+		} else {
+			scan_err("warning: stat failed on %s: %s", name, strerror(errno));
+		}
 	} else {
 		if (S_ISDIR(st.st_mode)) {
 			if ((d = opendir(name)) == NULL) {
@@ -210,7 +239,8 @@
 				}
 				closedir(d);
 			}
-		} else
+		} else {
 			step_into_include_file(name);
+		}
 	}
 }

Reply via email to