A | |
alias | |
alias_entry, Sudoers | |
alias_entry_single, Sudoers | |
alias_field, Sudoers | |
alias_list, Sudoers | |
alias_name, Sudoers | |
argument, Keepalived | |
B | |
block, Keepalived | |
body, Xinetd | |
C | |
cmnd_alias, Sudoers | |
cmnd_spec, Sudoers | |
cmnd_spec_list, Sudoers | |
comment | |
D | |
dayofmonth, Cron | |
dayofweek, Cron | |
default_depth, Xorg | |
default_type, Sudoers | |
defaults, Sudoers | |
del_negate, Sudoers | |
device, Xorg | |
display, Xorg | |
display_entry, Xorg | |
display_modes, Xorg | |
driver, Xorg | |
E | |
empty | |
entry | |
entry_generic, Xorg | |
entry_int, Xorg | |
entry_rgb, Xorg | |
entry_str, Xorg | |
entry_xy, Xorg | |
H | |
host_alias, Sudoers | |
hour, Cron | |
I | |
identifier, Xorg | |
includes, Xinetd | |
indented_entry, IniFile | |
indented_title, IniFile | |
input_device, Xorg | |
L | |
line, Keepalived | |
lns | |
lns_noempty, IniFile | |
M | |
minute, Cron | |
month, Cron | |
N | |
negate_node, Sudoers | |
O | |
option, Xorg | |
P | |
paramater_list, Sudoers | |
parameter, Sudoers | |
parameter_flag, Sudoers | |
parameter_integer, Sudoers | |
parameter_lists, Sudoers | |
parameter_string, Sudoers | |
port, Services | |
protocol, Services | |
R | |
record | |
record_noempty, IniFile | |
runas_alias, Sudoers | |
runas_spec, Sudoers |
let alias = [ label "alias" . store word_re ]
Every kind of Alias entry, see user_alias, runas_alias, host_alias and cmnd_alias
let alias = user_alias | runas_alias | host_alias | cmnd_alias
Alias entry, a list of comma-separated alias_entry_single fields
let alias_entry ( kw:string ) (field:string) (sto:lens) = [ indent . key kw . sep_cont . alias_entry_single field sto . ( sep_col . alias_entry_single field sto )* . eol ]
Single alias_entry, named using alias_name and listing alias_list
let alias_entry_single ( field:string ) (sto:lens) = [ label "alias" . alias_name . sep_eq . alias_list field sto ]
Generic alias field to gather all Alias definitions
let alias_field ( kw:string ) (sto:lens) = [ label kw . sto ]
List of alias_fields, separated by commas
let alias_list ( kw:string ) (sto:lens) = alias_field kw sto . ( sep_com . alias_field kw sto )*
Name of an alias_entry_single
let alias_name = [ label "name" . store /[A-Z][A-Z0-9_]*/ ]
Arguments are key=value stanzas
let argument = let argument_re = Rx.word | /"[^\n"]*"/ in Build.key_value Rx.word Sep.equal (store argument_re)
A block is a standard Build.named_block of lines
let block = Build.named_block Rx.word line
We would really like to say “the body can contain any of a list of a list of attributes, each of them at most once”; but that would require that we build a lens that matches the permutation of all attributes; with around 40 individual attributes, that’s not computationally feasible, even if we didn’t have to worry about how to write that down.
let body ( attr:lens ) = Util.del_str "\n{\n" . (empty|comment|attr)* . del /[ \t]*}[ \t]*\n/ "}\n"
Cmnd_Alias, see alias_field
let cmnd_alias = alias_entry "Cmnd_Alias" "command" sto_to_com_cmnd
Command specification for spec, with optional runas_spec and any amount of tag_specs
let cmnd_spec = [ label "command" . runas_spec? . tag_spec* . sto_to_com_cmnd ]
A list of comma-separated cmnd_specs
let cmnd_spec_list = cmnd_spec . ( sep_com . cmnd_spec )*
Map comments into “#comment” nodes
let comment ( pat:regexp ) (default:string) = [ label "#comment" . sep pat default . sto_to_eol? . eol ]
Map comments in “#comment” nodes
let comment = let sto_to_eol = store /( [^ \t\n].*[^ \t\n]|[^ \t\n] )/ in [ label "#comment" . del /[ \t]*#[ \t]*/ "# " . sto_to_eol . eol ]
Map comments into “#comment” nodes
let comment = [ indent . label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n].*[^ \t\n]|[^ \t\n])/ . eol ]
let dayofmonth = [ label "dayofmonth" . store num ]
let dayofweek = [ label "dayofweek" . store alphanum ]
let default_depth = entry_int "DefaultDepth" /[dD]efault[dD]epth/
Type definition for defaults
let default_type = let value = store /[@:>][^ \t\n\\\\]+/ in [ label "type" . value ]
A Defaults entry
let defaults = [ indent . key "Defaults" . default_type? . sep_cont . parameter_list . eol ]
Delete an even number of ‘!’
let del_negate = del /( !! )*/ ""
let device = entry_str "Device" /[dD]evice/
let display = [ indent . del "SubSection" "SubSection" . sep_spc . sep_dquote . key "Display" . sep_dquote . eol . display_entry* . indent . del "EndSubSection" "EndSubSection" . eol ]
Known values for entries in the Display subsection
let display_entry = entry_int "Depth" /[dD]epth/ | entry_int "FbBpp" /[fF]b[bB]pp/ | entry_rgb "Weight" /[wW]eight/ | entry_xy "Virtual" /[vV]irtual/ | entry_xy "ViewPort" /[vV]iew[pP]ort/ | display_modes | entry_str "Visual" /[vV]isual/ | entry_rgb "Black" /[bB]lack/ | entry_rgb "White" /[wW]hite/ | entry_str "Options" /[oO]ptions/ | empty | comment
let display_modes = [ indent . del /[mM]odes/ "Modes" . label "Modes" . [ label "mode" . sep_spc . quoted_string_val ]+ . eol ]
let driver = entry_str "Driver" /[dD]river/
Empty line, an eol subnode
let empty = [ eol ]
Map empty lines
let empty = [ del /[ \t]*#?[ \t]*\n/ "\n" ]
Map empty lines, including empty comments
let empty = [ del /[ \t]*#?[ \t]*\n/ "\n" ]
A crontab entry
let entry = [ label "entry" . indent . ( time | schedule ) . sep_spc . user . sep_spc . store Rx.space_in . eol ]
Generic INI File entry
let entry ( kw:regexp ) (sep:lens) (comment:lens) = [ key kw . sep . sto_to_comment? . (comment|eol) ] | comment
An entry without a specific handler.
let entry_generic = [ indent . key generic_entry_re . sep_spc . store to_eol . eol ]
This matches an entry which takes a single integer for an argument
let entry_int ( canon:string ) (re:regexp) = [ indent . del re canon . label canon . sep_spc . store int . eol ]
This matches an entry which takes 3 integers as arguments representing red, green and blue components
let entry_rgb ( canon:string ) (re:regexp) = [ indent . del re canon . label canon . [ label "red" . sep_spc . store int ] . [ label "green" . sep_spc . store int ] . [ label "blue" . sep_spc . store int ] . eol ]
This matches an entry which takes a single quoted string
let entry_str ( canon:string ) (re:regexp) = [ indent . del re canon . label canon . sep_spc . quoted_string_val . eol ]
This matches an entry which takes 2 integers as arguments representing X and Y coordinates
let entry_xy ( canon:string ) (re:regexp) = [ indent . del re canon . label canon . [ label "x" . sep_spc . store int ] . [ label "y" . sep_spc . store int ] . eol ]
Host_Alias, see alias_field
let host_alias = alias_entry "Host_Alias" "host" sto_to_com
let hour = [ label "hour" . store num ]
let identifier = entry_str "Identifier" /[iI]dentifier/
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 ]
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.del_opt_ws "" . Util.del_str "[" . key kw . Util.del_str "]". eol
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 ]
Lines are made of a name, followed by a list of one of more arguments separated by a space.
let line = let arguments = Build.opt_list argument Sep.space in Build.key_value Rx.word Sep.space arguments
The cron lens
let lns = ( empty | comment | shellvar | entry )*
Any number of empty lines, comments, and records.
let lns = ( empty | comment | record ) *
Generic INI File lens
let lns ( record:lens ) (comment:lens) = lns_noempty record (comment|empty)
The lens is a series of blocks, with optional empty lines and comments before, between and after them.
let lns = let empty_or_comment = ( Util.empty | Util.comment )* in
let lns = ( empty | comment | record )*
The sudoers lens, any amount of
let lns = ( empty | comment | alias | defaults | spec )*
The xorg.conf lens
let lns = ( empty | comment | section )*
Generic INI File lens with no empty lines
let lns_noempty ( record:lens ) (comment:lens) = comment* . record*
let minute = [ label "minute" . store num ]
let month = [ label "month" . store alphanum ]
Negation of boolean values for defaults.
let negate_node = [ del "!" "!" . label "negate" ]
let option = [ indent . del /[oO]ption/ "Option" . label "Option" . sep_spc . quoted_string_val . [ label "value" . sep_spc . quoted_string_val ]* . eol ]
A single parameter for defaults
let parameter = parameter_flag | parameter_integer | parameter_string | parameter_lists
A flag parameter for defaults
let parameter_flag_kw = "always_set_home" | "authenticate" | "env_editor" | "env_reset" | "fqdn" | "ignore_dot" | "ignore_local_sudoers" | "insults" | "log_host" | "log_year" | "long_otp_prompt" | "mail_always" | "mail_badpass" | "mail_no_host" | "mail_no_perms" | "mail_no_user" | "noexec" | "path_info" | "passprompt_override" | "preserve_groups" | "requiretty" | "root_sudo" | "rootpw" | "runaspw" | "set_home" | "set_logname" | "setenv" | "shell_noargs" | "stay_setuid" | "targetpw" | "tty_tickets"
An integer parameter for defaults
let parameter_integer_nobool_kw = "passwd_tries"
A single list parameter for defaults
let parameter_lists_kw = "env_check" | "env_delete" | "env_keep"
A string parameter for defaults
let parameter_string_nobool_kw = "badpass_message" | "editor" | "mailsub" | "noexec_file" | "passprompt" | "runas_default" | "syslog_badpri" | "syslog_goodpri" | "timestampdir" | "timestampowner"
let port = [ label "port" . store num_re ]
let protocol = [ label "protocol" . store protocol_re ]
Keyword, followed by optional whitespace and value, followed by EOL.
let record = [ key keyword . (sep_spc . store word)? . eol ]
Generic INI File record
let record ( title:lens ) (entry:lens) = record_noempty title ( entry | empty )
A standard /etc/services record TODO: make sure a space is added before a comment on new nodes
let record = [ label "service-name" . store word_re . sep_spc . port . del "/" "/" . protocol . ( sep_spc . alias )* . (comment|eol) ]
INI File Record with no empty lines allowed.
let record_noempty ( title:lens ) (entry:lens) = [ title . entry* ]
Run_Alias, see alias_field
let runas_alias = alias_entry "Runas_Alias" "runas_user" sto_to_com
A runas specification for spec, using alias_list
let runas_spec = Util.del_str "(" . alias_list "runas_user" sto_to_com . Util.del_str ")" . sep_cont_opt