a list of facilities, separated by commas
let facilities = label_opt_list "facility" (store token) comma
let field (kw:string) (sto:lens) = indent . Build.key_value_line_comment kw sep_spc sto comment_eol
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 ]
A full configuration file
let file = "# # Aliases in this file will NOT be expanded in the header from # Mail, but WILL be visible over networks or from /bin/mail. # Basic system aliases -- these MUST be present. mailer-daemon: postmaster postmaster: root # General redirections for pseudo accounts. bin: root , adm, bob daemon: root adm: root file: /var/foo pipe1: |/bin/ls pipe2 : |\"/usr/bin/ls args,\" "
a file begins with a / and get almost anything else after
let file_r = /\/[^ \t\n]+/
let filesystem = [ label "filesystem" . store filesystem_kw ]
Regexps for filesystem
let filesystem_kw = "-" | "swap"
A simple flag subnode, consisting of a single key
let flag (kw:regexp) = [ key kw ]
A single word
let flag (kw:regexp) = [ indent . key kw . comment_or_eol ]
A simple flag line, consisting of a single key
let flag_line (kw:regexp) = [ key kw . eol ]
let fs_option = [ key /createopts|tuneopts/ . Util.del_str "=\"" . store /[^"\n]*/ . Util.del_str "\"" ]
An array of fs_options
let fs_options =
A fs_types section
let fs_types = IniFile.record fs_types_title (fs_types_record | comment)
Possible entries under a fs_types_record group
let fs_types_entry =list_sto "features" ([del /\^/ "^" . label "disable"]? . key Rx.word) | list_sto "options" (key Rx.word . Util.del_str "=" . store Rx.word) | entry_sto "lazy_itable_init" ("true"|"false") | entry_sto "flex_bg_size" Rx.integer
Fs group records under the fs_types section
let fs_types_record = [ label "filesystem" . Util.indent . store Rx.word . del /[ \t]*=[ \t]*\{[ \t]*\n/ " = {\n" . ((Util.indent . (fs_types_entry|common_entry)) | empty | comment)* . del /[ \t]*\}[ \t]*\n/ " }\n" ]
Title for the fs_types section
let fs_types_title = IniFile.title "fs_types"
let fspath = Rx.fspath
A filesystem path
let fspath = /[^ \t\n]+/
let generic_entry_re = /[^# \t\n\/]+/ - entries_re
A generic key/value option
let generic_opt (type:string) (kw:regexp) = [ key type . Util.del_str ":" . store kw ]
A generic key/list option
let generic_opt_list (type:string) (kw:regexp) = [ key type . Util.del_str ":" . counter "locallist" . Build.opt_list [seq "locallist" . store kw] Sep.comma ]
A global configuration entry
let global_conf = global_defs | static_routes
A global_defs block
let global_defs = block "global_defs" global_defs_field
Possible fields in the global_defs block
let global_defs_field = block "notification_email" email | field "notification_email_from" sto_email_addr | field "smtp_server" sto_word | field "smtp_connect_timeout" sto_num | field "lvs_id" sto_word | field "router_id" sto_word
Format is (GROUP)
let group = [ label "group" . Util.del_str "(" . store Rx.word . Util.del_str ")" ]
let group_record = generic_record "group" (Util.del_str "@" . store name)
Host_Alias, see alias_field
let host_alias = alias_entry "Host_Alias" "host" sto_to_com
a program begins with an optional hash, and a + or -
let hostname = [ label "hostname" . opt_hash . ( plus | [ Build.xchgs "-" "reverse" ] ) . hostnames . eol . entries ]
a list of hostnames
let hostnames = label_opt_list_or "hostname" (store Rx.word) comma "*"
let hour = [ label "hour" . store num ]
let identifier = entry_str "Identifier" /[iI]dentifier/
A file inclusion /!\ The manpage is not clear on the syntax
let include = [ indent . key "#include" . Sep.space . store Rx.fspath . eol ]
An include entry.
let include = [ key "include" . [ label "file" . eq . store word . eol ] ]
include_dir=/path/to/dir/
let include_dir = [ key "include_dir" . [ label "dir" . eq . store word . eol ] ]
let includedir = [ key /#include(dir)?/ . Sep.space . store Rx.fspath . eol ]
It would be nice if we could use the directories given in include and includedir directives to parse additional files instead of hardcoding all the places where xinetd config files can be found; but that is currently not possible, and implementing that has a good amount of hairy corner cases to consider.
let includes = [ key /include|includedir/ . Util.del_ws_spc . store /[^ \t\n]+/ . eol ]
An Util.indent
let indent = Util.indent
An indentation
let indent = Util.indent
let indent = Util.indent
let indent = Util.indent
let indent = del /[ \t]*/ ""
Delete indentation, including leading whitespace
let indent = del /[ \t]*/ ""
let indent = Util.indent
Generic INI File entry that might be indented with an arbitrary amount of whitespace
let indented_entry (kw:regexp) (sep:lens) (comment:lens) = [ Util.del_opt_ws "" . key kw . sep . sto_to_comment? . (comment|eol) ] | comment
Title for record.
let indented_title (kw:regexp) = Util.indent . title kw
Title for record.
let indented_title_label (name:string) (kw:regexp) = Util.indent . title_label name kw
let input_device = [ indent . del /[iI]nput[dD]evice/ "InputDevice" . label "InputDevice" . sep_spc . quoted_string_val . [ label "option" . sep_spc . quoted_string_val ]* . eol ]
let input1 = "<?xml version=\"1.0\" encoding=\"UTF-8\"?> <html> <head> <title>Wiki</title> </head> <body> <h1>Augeas</h1> <p class=\"main\">Augeas is now able to parse XML files!</p> <ul> <li>Translate from XML to a tree syntax</li> <li>Translate from the tree back to XML</li> <!-- this is some comment --> <li>this</li> </ul> </body> </html> "
let int = /[0-9]+/
One or more digits
let integer = /[0-9]+/
An ipv4 or ipv6
let ip = ipv4 | ipv6
ip6-dotint option, which supports negation
let ip6_dotint = let negate = [ del "no-" "no-" . label "negate" ] in [ negate? . key "ip6-dotint" ]
An IP address or range with an optional mask
let ipaddr = label "ipaddr" . store /[0-9.-]+/ . prefixlen?
CIDR or ip+netmask
let ipaddr = /[0-9a-fA-F:.]+(\/[0-9]+|[ \t]+[0-9.]+)/
An IP address or range with an optional mask
let ipaddr = [label "ipaddr" . store Rx.ip . netmask?]
A device for IP addresses
let ipdev = [ key "dev" . sep_spc . sto_word ]
A network IP, trailing .0 may be omitted
let ipv4 = let dot = "." in let digits = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/ in digits . dot . digits . dot . digits . (dot . "0")?
let ipv4 = let dot = "." in let digits = /(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)/ in digits . dot . digits . dot . digits . dot . digits
let ipv6 = /(([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})/ | /(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})/ | /(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})/ | /(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})/ | /(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})/ | /(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})/ | ( /([0-9A-Fa-f]{1,4}:){6}/ . /((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}/ . /(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))/ ) | ( /([0-9A-Fa-f]{1,4}:){0,5}:/ . /((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}/ . /(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))/ ) | ( /::([0-9A-Fa-f]{1,4}:){0,5}/ . /((((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))\.){3}/ . /(((25[0-5])|(1[0-9]{2})|(2[0-4][0-9])|([0-9]{1,2})))/ ) | ( /[0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}/ . /[0-9A-Fa-f]{1,4}/ ) | /(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})/ | /(([0-9A-Fa-f]{1,4}:){1,7}:)/
regular entries
let item = [ key item_re . eq . store word . eol ]
regular entries re
let item_re = "server_port" | "command_prefix" | "server_address" | "allowed_hosts" | "debug" | "nrpe_user" | "nrpe_group" | "dont_blame_nrpe" | "command_timeout" | "connection_timeout" | "allow_weak_random_seed" | "pid_file" | "log_facility"
let kernel = [ command /kernel\$?/ "\t" . (spc . ([switch "type" . eq . store /[a-z]+/] |[switch "no-mem-option"]))* . spc . kernel_args ]
Parse the file name and args on a kernel or module line.
let kernel_args = let arg = /[A-Za-z0-9_.$-]+/ - /type|no-mem-option/ in store /(\([a-z0-9,]+\))?\/[^ \t\n]*/ . (spc . multiboot_arg)? . (spc . [ key arg . (eq. store /([^ \t\n])*/)?])* . eol
let key_re = /\$?[A-Za-z0-9_.-]+/
Same as key_value_line, but does not end with an end of line
let key_value (kw: regexp) (sep:lens) (sto:lens) = [ key kw . sep . sto ]
A subnode with a keyword, a separator and a storing lens, and an end of line
let key_value_line (kw:regexp) (sep:lens) (sto:lens) = [ key kw . sep . sto . eol ]
Same as key_value_line, but allows to have a comment in the end of a line and an end of line
let key_value_line_comment (kw:regexp) (sep:lens) (sto:lens) (comment:lens) = [ key kw . sep . sto . (eol|comment) ]
Store a key/value pair where key and value are separated by whitespace and the value goes to the end of the line.
let key_ws_value (kw:regexp) = key_value_line kw Util.del_ws_spc (store Rx.space_in)
A simple flag function
let knode (r:regexp) = [ key r ]
let kv = [ indent . key key_re . del sep " " . store value_re . eol ]
let kw_arg (kw:regexp) (indent:string) (dflt_sep:string) = [ command kw indent . value_sep dflt_sep . value_to_eol . eol ]
let kw_boot_arg (kw:string) = kw_arg kw "\t" " "
let kw_menu_arg (kw:string) = kw_arg kw "" " "
let kw_pres (kw:string) = [ opt_ws . key kw . del_to_eol . eol ]