[augeas-devel] [PATCH] Add a lense for parsing /etc/syslog.conf and tests.

Mathieu Arnold mat at mat.cc
Wed Nov 3 16:04:54 UTC 2010


From: Mathieu Arnold <mat at FreeBSD.org>

---
 lenses/syslog.aug            |  248 +++++++++++++++++++++++++++++++++++
 lenses/tests/test_syslog.aug |  293 ++++++++++++++++++++++++++++++++++++++++++
 tests/Makefile.am            |    1 +
 3 files changed, 542 insertions(+), 0 deletions(-)
 create mode 100644 lenses/syslog.aug
 create mode 100644 lenses/tests/test_syslog.aug

diff --git a/lenses/syslog.aug b/lenses/syslog.aug
new file mode 100644
index 0000000..91d0d3a
--- /dev/null
+++ b/lenses/syslog.aug
@@ -0,0 +1,248 @@
+(*
+Module: Syslog
+  parses /etc/syslog.conf
+
+Author: Mathieu Arnold <mat at FreeBSD.org>
+
+About: Reference
+  This lens tries to keep as close as possible to `man 5 resolv.conf` where possible.
+  An online source being :
+  http://www.freebsd.org/cgi/man.cgi?query=syslog.conf&sektion=5
+
+About: Licence
+  This file is licensed under the BSD License.
+
+About: Lens Usage
+   To be documented
+
+About: Configuration files
+  This lens applies to /etc/syslog.conf. See <filter>.
+
+ *)
+module Syslog =
+  autoload xfm
+
+	(************************************************************************
+	 * Group:                 USEFUL PRIMITIVES
+	 *************************************************************************)
+
+	(* Group: Comments and empty lines *)
+
+	(* Variable: empty *)
+        let empty      = Util.empty
+	(* Variable: eol *)
+        let eol        = Util.eol
+	(* Variable: sep_tab *)
+        let sep_tab    = Sep.tab
+
+	(* View: comment
+	  Map comments into "#comment" nodes
+	  Can't use Util.comment as #+ and #! have a special meaning *)
+	let comment =
+	  [ label "#comment" . del /#[ \t]*/ "# "
+	      . store /([^ \t\n+!-].*[^ \t\n]|[^ \t\n+!-])/ . eol ]
+
+	(* Group: single characters macro *)
+
+        (* Variable: comma
+	 Deletes a comma and default to it
+	 *)
+	let comma      = Util.del_str ","
+	(* Variable: colon
+	 Deletes a colon and default to it
+	 *)
+	let colon      = Util.del_str ":"
+	(* Variable: semicolon
+	 Deletes a semicolon and default to it
+	 *)
+	let semicolon  = Util.del_str ";"
+	(* Variable: at
+	 Deletes a at and default to it
+	 *)
+	let at         = Util.del_str "@"
+	(* Variable: dot
+	 Deletes a dot and default to it
+	 *)
+	let dot        = Util.del_str "."
+	(* Variable: pipe
+	 Deletes a pipe and default to it
+	 *)
+	let pipe       = Util.del_str "|"
+	(* Variable: plus
+	 Deletes a plus and default to it
+	 *)
+	let plus       = Util.del_str "+"
+	(* Variable: bang
+	 Deletes a bang and default to it
+	 *)
+	let bang       = Util.del_str "!"
+
+	(* Variable: opt_hash
+	  deletes an optional # sign
+	  *)
+	let opt_hash   = del /#?/ ""
+	(* Variable: opt_plus
+	  deletes an optional + sign
+	  *)
+	let opt_plus   = del /\+?/ ""
+
+	(* Group: various macros *)
+
+	(* Variable: word
+	  our version can't start with [_.-] because it would mess up the grammar
+	  *)
+	let word      = /[A-Za-z0-9][A-Za-z0-9_.-]*/
+
+	(* Variable: comparison
+	  a comparison is an optional ! with optionaly some of [<=>]
+	  *)
+        let comparison = /(!|[<=>]+|![<=>]+)/
+
+	(* Variable: token
+	  alphanum or "*"
+	  *)
+        let token      = /([a-z0-9]+|\*)/
+
+	(* Variable: file_r
+	 a file begins with a / and get almost anything else after
+	 *)
+	let file_r     = /\/[^ \t\n]+/
+
+	(* Variable: loghost_r
+	 Matches a hostname, that is labels speparated by dots, labels can't
+	 start or end with a "-".  maybe a bit too complicated for what it's worth *)
+	let loghost_r = /[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?(\.[a-zA-Z0-9]([a-zA-Z0-9-]*[a-zA-Z0-9])?)*/
+
+	(* Group: Function *)
+
+	(* View: label_opt_list
+	 Uses Build.opt_list to generate a list of labels
+
+	 Parameters:
+	  l:string - the label name
+	  r:lens   - the lens going after the label
+	  s:lens   - the separator lens passed to Build.opt_list
+	 *)
+	let label_opt_list (l:string) (r:lens) (s:lens) = Build.opt_list [ label l . r ] s
+
+	(* View: label_opt_list_or
+	 Either label_opt_list matches something or it emits a single label
+	 with the "or" string.
+
+	 Parameters:
+	  l:string  - the label name
+	  r:lens    - the lens going after the label
+	  s:lens    - the separator lens passed to Build.opt_list
+	  or:string - the string used if the label_opt_list does not match anything
+	 *)
+	let label_opt_list_or (l:string) (r:lens) (s:lens) (or:string) =
+	  ( label_opt_list l r s | [ label l . store or ] )
+
+
+	(************************************************************************
+	 * Group:                 LENSE DEFINITION
+	 *************************************************************************)
+
+	(* Group: selector *)
+
+	(* View: facilities
+	 a list of facilities, separated by commas
+	 *)
+	let facilities = label_opt_list "facility" (store token) comma
+
+	(* View: selector
+	 a selector is a list of facilities, an optional comparison and a level
+	 *)
+	let selector = facilities . dot .
+                       [ label "comparison" . store comparison]? .
+                       [ label "level" . store token ]
+
+	(* View: selectors
+	 a list of selectors, separated by semicolons
+	 *)
+        let selectors = label_opt_list "selector" selector semicolon
+
+	(* Group: action *)
+
+	(* View: file
+	 a file may start with a "-" meaning it does not gets sync'ed everytime
+	 *)
+	let file = [ Build.xchgs "-" "no_sync" ]? . [ label "file" . store file_r ]
+
+	(* View: loghost
+	 a loghost is an @  sign followed by the hostname and a possible port
+	 *)
+	let loghost = at . [ label "hostname" . store loghost_r ] .
+	    (colon . [ label "port" . store /[0-9]+/ ] )?
+
+	(* View: users
+	 a list of users or a "*"
+	 *)
+	let users = label_opt_list_or "user" (store word) comma "*"
+
+	(* View: logprogram
+	 a log program begins with a pipe
+	 *)
+	let logprogram = pipe . [ label "program" . store /[^ \t\n][^\n]+[^ \t\n]/ ]
+
+	(* View: action
+	 an action is either a file, a host, users, or a program
+	 *)
+        let action = (file | loghost | users | logprogram)
+
+	(* Group: Entry *)
+
+	(* View: entry
+	 an entry contains selectors and an action
+	 *)
+        let entry = [ label "entry" .
+	    selectors . sep_tab .
+	    [ label "action" . action ] . eol ]
+
+	(* View: entries
+	 entries are either comments/empty lines or entries
+	 *)
+	let entries = (empty | comment | entry)*
+
+	(* Group: Program matching *)
+
+	(* View: programs
+	 a list of programs
+	 *)
+	let programs = label_opt_list_or "program" (store word) comma "*"
+
+	(* View: program
+	 a program begins with an optional hash, a bang, and an optional + or -
+	 *)
+	let program = [ label "program" . opt_hash . bang .
+	      ( opt_plus | [ Build.xchgs "-" "reverse" ] ) .
+	      programs . eol .  entries ]
+
+	(* Group: Hostname maching *)
+
+	(* View: hostnames
+	 a list of hostnames
+	 *)
+	let hostnames = label_opt_list_or "hostname" (store Rx.word) comma "*"
+
+	(* View: hostname
+	 a program begins with an optional hash, and a + or -
+	 *)
+	let hostname = [ label "hostname" . opt_hash .
+	      ( plus | [ Build.xchgs "-" "reverse" ] ) .
+	      hostnames . eol .  entries ]
+
+	(* Group: Top of the tree *)
+
+	(* View: lns
+	 generic entries then programs or hostnames matching blocs
+	 *)
+        let lns = entries . ( program | hostname )*
+
+	(* Variable: filter
+	 all you need is /etc/syslog.conf
+	 *)
+        let filter = incl "/etc/syslog.conf"
+
+        let xfm = transform lns filter
+
diff --git a/lenses/tests/test_syslog.aug b/lenses/tests/test_syslog.aug
new file mode 100644
index 0000000..3685535
--- /dev/null
+++ b/lenses/tests/test_syslog.aug
@@ -0,0 +1,293 @@
+module Test_syslog =
+
+	let conf="# $FreeBSD: src/etc/syslog.conf,v 1.30.2.1 2009/08/03 08:13:06 kensmith Exp $
+# 
+
+daemon.info                                     /var/log/cvsupd.log
+security.*					-/var/log/security
+*.notice;authpriv.none;kern.debug;lpr.info;mail.crit;news.err	/var/log/messages
+uucp,news.crit                                          /var/log/spooler
+*.emerg						*
+daemon.!info					/var/log/foo
+daemon.<=info					/var/log/foo
+daemon.!<=info					/var/log/foo
+*.*						@syslog.far.away
+*.*						@syslog.far.away:123
+*.*						foo,bar
+*.*						|\"/usr/bin/soft arg\"
+!startslip
+# get that out
+*.*						/var/log/slip.log
+!pppd,ppp
+
+*.*						/var/log/ppp.log
+!+startslip
+*.*						/var/log/slip.log
+!-startslip
+*.*						/var/log/slip.log
+#!pppd
+*.*						/var/log/ppp.log
++foo.example.com
+daemon.info                                     /var/log/cvsupd.log
++foo.example.com,bar.example.com
+daemon.info                                     /var/log/cvsupd.log
+#+bar.example.com
+daemon.info                                     /var/log/cvsupd.log
+-foo.example.com
+daemon.info                                     /var/log/cvsupd.log
++*
+daemon.info                                     /var/log/cvsupd.log
+!*
+daemon.info                                     /var/log/cvsupd.log
+"
+
+	test Syslog.lns get conf =
+          { "#comment" = "$FreeBSD: src/etc/syslog.conf,v 1.30.2.1 2009/08/03 08:13:06 kensmith Exp $" }
+	  { }
+	  { }
+	  { "entry"
+	    { "selector" { "facility" = "daemon" } { "level" = "info" } }
+	    { "action" { "file" = "/var/log/cvsupd.log" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "security" } { "level" = "*" } }
+	    { "action" { "no_sync" } { "file" = "/var/log/security" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "*" } { "level" = "notice" } }
+	    { "selector" { "facility" = "authpriv" } { "level" = "none" } }
+	    { "selector" { "facility" = "kern" } { "level" = "debug" } }
+	    { "selector" { "facility" = "lpr" } { "level" = "info" } }
+	    { "selector" { "facility" = "mail" } { "level" = "crit" } }
+	    { "selector" { "facility" = "news" } { "level" = "err" } }
+	    { "action" { "file" = "/var/log/messages" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "uucp" } { "facility" = "news" } { "level" = "crit" } }
+	    { "action" { "file" = "/var/log/spooler" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "*" } { "level" = "emerg" } }
+	    { "action" { "user" = "*" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "daemon" } { "comparison" = "!" } { "level" = "info" } }
+	    { "action" { "file" = "/var/log/foo" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "daemon" } { "comparison" = "<=" } { "level" = "info" } }
+	    { "action" { "file" = "/var/log/foo" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "daemon" } { "comparison" = "!<=" } { "level" = "info" } }
+	    { "action" { "file" = "/var/log/foo" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "*" } { "level" = "*" } }
+	    { "action" { "hostname" = "syslog.far.away" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "*" } { "level" = "*" } }
+	    { "action" { "hostname" = "syslog.far.away" } { "port" = "123" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "*" } { "level" = "*" } }
+	    { "action" { "user" = "foo" } { "user" = "bar" } }
+	  }
+	  { "entry"
+	    { "selector" { "facility" = "*" } { "level" = "*" } }
+	    { "action" { "program" = "\"/usr/bin/soft arg\"" } }
+	  }
+	  { "program"
+	    { "program" = "startslip" }
+	    { "#comment" = "get that out" }
+	    { "entry"
+	      { "selector" { "facility" = "*" } { "level" = "*" } }
+	      { "action" { "file" = "/var/log/slip.log" } }
+	    }
+	  }
+	  { "program"
+	    { "program" = "pppd" }
+	    { "program" = "ppp" }
+	    { }
+	    { "entry"
+	      { "selector" { "facility" = "*" } { "level" = "*" } }
+	      { "action" { "file" = "/var/log/ppp.log" } }
+	    }
+	  }
+	  { "program"
+	    { "program" = "startslip" }
+	    { "entry"
+	      { "selector" { "facility" = "*" } { "level" = "*" } }
+	      { "action" { "file" = "/var/log/slip.log" } }
+	    }
+	  }
+	  { "program"
+	    { "reverse" }
+	    { "program" = "startslip" }
+	    { "entry"
+	      { "selector" { "facility" = "*" } { "level" = "*" } }
+	      { "action" { "file" = "/var/log/slip.log" } }
+	    }
+	  }
+	  { "program"
+	    { "program" = "pppd" }
+	    { "entry"
+	      { "selector" { "facility" = "*" } { "level" = "*" } }
+	      { "action" { "file" = "/var/log/ppp.log" } }
+	    }
+	  }
+	  { "hostname"
+	    { "hostname" = "foo.example.com" }
+	    { "entry"
+	      { "selector" { "facility" = "daemon" } { "level" = "info" } }
+	      { "action" { "file" = "/var/log/cvsupd.log" } }
+	    }
+	  }
+	  { "hostname"
+	    { "hostname" = "foo.example.com" }
+	    { "hostname" = "bar.example.com" }
+	    { "entry"
+	      { "selector" { "facility" = "daemon" } { "level" = "info" } }
+	      { "action" { "file" = "/var/log/cvsupd.log" } }
+	    }
+	  }
+	  { "hostname"
+	    { "hostname" = "bar.example.com" }
+	    { "entry"
+	      { "selector" { "facility" = "daemon" } { "level" = "info" } }
+	      { "action" { "file" = "/var/log/cvsupd.log" } }
+	    }
+	  }
+	  { "hostname"
+	    { "reverse" }
+	    { "hostname" = "foo.example.com" }
+	    { "entry"
+	      { "selector" { "facility" = "daemon" } { "level" = "info" } }
+	      { "action" { "file" = "/var/log/cvsupd.log" } }
+	    }
+	  }
+	  { "hostname"
+	    { "hostname" = "*" }
+	    { "entry"
+	      { "selector" { "facility" = "daemon" } { "level" = "info" } }
+	      { "action" { "file" = "/var/log/cvsupd.log" } }
+	    }
+	  }
+	  { "program"
+	    { "program" = "*" }
+	    { "entry"
+	      { "selector" { "facility" = "daemon" } { "level" = "info" } }
+	      { "action" { "file" = "/var/log/cvsupd.log" } }
+	    }
+	  }
+
+	(* changing file *)
+	test Syslog.lns put "*.* /var\n" after
+	  set "/entry[1]/action/file" "/foo"
+	  = "*.* /foo\n"
+
+	(* removing entry *)
+	test Syslog.lns put "*.* /var\n" after
+	  rm "/entry[1]"
+	  = ""
+
+	(* changing facility and level *)
+	test Syslog.lns put "*.* /var\n" after
+	  set "/entry[1]/selector/facility" "daemon" ;
+	  set "/entry[1]/selector/level" "info"
+	  = "daemon.info /var\n"
+
+	(* insert a facility *)
+	test Syslog.lns put "daemon.* /var\n" after
+	  insa "facility" "/entry/selector/facility" ;
+	  set "/entry/selector/facility[2]" "mail"
+	  = "daemon,mail.* /var\n"
+
+	(* creating an entry *)
+	test Syslog.lns put "" after
+	  set "/entry/selector/facility" "daemon" ;
+	  set "/entry/selector/level" "info" ;
+	  set "/entry/action/file" "/var"
+	  = "daemon.info\t/var\n"
+
+	(* inserting an entry before *)
+	test Syslog.lns put "*.* /var\n" after
+	  insb "entry" "/entry" ;
+	  set "/entry[1]/selector/facility" "daemon" ;
+	  set "/entry[1]/selector/level" "info" ;
+	  set "/entry[1]/action/file" "/foo"
+	  = "daemon.info /foo\n*.*\t/var\n"
+
+	(* inserting an entry after *)
+	test Syslog.lns put "*.* /var\n" after
+	  insa "entry" "/entry" ;
+	  set "/entry[2]/selector/facility" "daemon" ;
+	  set "/entry[2]/selector/level" "info" ;
+	  set "/entry[2]/action/file" "/foo"
+	  = "*.* /var\ndaemon.info\t/foo\n"
+
+	(* insert sync on a file *)
+	test Syslog.lns put "*.* /var\n" after
+	  insb "no_sync" "/entry/action/file"
+	  = "*.* -/var\n"
+
+	(* changing file to remote host *)
+	test Syslog.lns put "*.* /var\n" after
+	  rm "/entry/action/file" ;
+	  set "/entry/action/hostname" "far.far.away"
+	  = "*.* @far.far.away\n"
+
+	(* changing file to * *)
+	test Syslog.lns put "*.* /var\n" after
+	  rm "/entry/action/file" ;
+	  set "/entry/action/user" "*"
+	  = "*.* *\n"
+
+	(* changing file to users *)
+	test Syslog.lns put "*.* /var\n" after
+	  rm "/entry/action/file" ;
+	  set "/entry/action/user[1]" "john" ;
+	  set "/entry/action/user[2]" "paul" ;
+	  set "/entry/action/user[3]" "george" ;
+	  set "/entry/action/user[4]" "ringo"
+	  = "*.* john,paul,george,ringo\n"
+
+	(* changing file to program *)
+	test Syslog.lns put "*.* /var\n" after
+	  rm "/entry/action/file" ;
+	  set "/entry/action/program" "/usr/bin/foo"
+	  = "*.* |/usr/bin/foo\n"
+
+	(* inserting a matching program *)
+	test Syslog.lns put "" after
+	  insa "program" "/" ;
+	  set "/program/program" "foo"
+	  = "!foo\n"
+
+	(* inserting an entry to a matching program *)
+	test Syslog.lns put "!foo\n" after
+	  set "/program/entry/selector/facility" "*" ;
+	  set "/program/entry/selector/level" "*" ;
+	  set "/program/entry/action/file" "/foo"
+	  = "!foo\n*.*\t/foo\n"
+
+	(* inserting a matching hostname *)
+	test Syslog.lns put "" after
+	  insa "hostname" "/" ;
+	  set "/hostname/hostname" "foo.foo.away"
+	  = "+foo.foo.away\n"
+
+	(* inserting an entry to a matching hostname *)
+	test Syslog.lns put "+foo.foo.away\n" after
+	  set "/hostname/entry/selector/facility" "*" ;
+	  set "/hostname/entry/selector/level" "*" ;
+	  set "/hostname/entry/action/file" "/foo"
+	  = "+foo.foo.away\n*.*\t/foo\n"
+
+	(* inserting a reverse matching hostname *)
+	test Syslog.lns put "" after
+	  insa "hostname" "/" ;
+	  set "/hostname/reverse" "" ;
+	  set "/hostname/hostname" "foo.foo.away"
+	  = "-foo.foo.away\n"
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 11e5319..ef3c604 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -80,6 +80,7 @@ lens_tests =			\
   lens-sshd.sh			\
   lens-sysconfig.sh		\
   lens-sysctl.sh		\
+  lens-syslog.sh		\
   lens-vsftpd.sh		\
   lens-webmin.sh		\
   lens-wine.sh			\
-- 
1.7.3.2




More information about the augeas-devel mailing list