From: Mathieu Arnold <[email protected]> --- 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 <[email protected]> + +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 _______________________________________________ augeas-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/augeas-devel
