ACC SHELL

Path : /usr/share/libaugeas0/augeas/lenses/dist/
File Upload :
Current File : //usr/share/libaugeas0/augeas/lenses/dist/xinetd.aug

(*
 * Module: Xinetd
 *   Parses xinetd configuration files
 *
 *  The structure of the lens and allowed attributes are ripped directly
 *  from xinetd's parser in xinetd/parse.c in xinetd's source checkout  
 *  The downside of being so precise here is that if attributes are added
 *  they need to be added here, too. Writing a catchall entry, and getting
 *  to typecheck correctly would be a huge pain.                         
 *
 *  A really enterprising soul could tighten this down even further by    
 *  restricting the acceptable values for each attribute.                  
 * 
 * Author: David Lutterkort
 *)

module Xinetd =
  autoload xfm

  let comment = [ del /[ \t]*(#.*|[ \t]*)\n/ "#\n" ]

  let name = key /[^ \t\n\/+-=]+/
  let bol_spc = del /[ \t]*/ "\t"
  let spc = del /[ \t]+/ " "
  let eol = del /[ \t]*\n/ "\n"

  let op_delim (op:string) = del (/[ \t]*/ . op . /[ \t]*/) (" " . op . " ")
  let eq       = op_delim "="

  let op = ([ label "add" . op_delim "+=" ]
           |[ label "del" . op_delim "-=" ]
           | eq)

  let value = store /[^ \t\n]+/

  let attr_one (n:regexp) =
    [ bol_spc . key n . eq . value . eol ]

  let attr_lst (n:regexp) (op_eq: lens) =
    [ bol_spc . key n . op_eq .
        [label "value" . value] . [label "value" . spc . value]* .
      eol ]

  let attr_lst_eq (n:regexp) = attr_lst n eq

  let attr_lst_op (n:regexp) = attr_lst n op

  (* Variable: service_attr
   *   Note: 
   *      It is much faster to combine, for example, all the attr_one 
   *      attributes into one regexp and pass that to a lens instead of 
   *      using lens union (attr_one "a" | attr_one "b"|..) because the latter 
   *      causes the type checker to work _very_ hard.                         
   *)

  let service_attr =
    attr_one ("socket_type" | "protocol" | "wait" | "user" | "group"
             |"server" | "instances"  | "rpc_version" | "rpc_number"
             | "id" | "port" | "nice" | "banner" | "bind" | "interface"
             | "per_source" | "groups" | "banner_success" | "banner_fail"
             | "disable" | "max_load" | "rlimit_as" | "rlimit_cpu"
             | "rlimit_data" | "rlimit_rss" | "rlimit_stack" | "v6only"
             | "deny_time" | "umask" | "mdns" | "libwrap")
   (* redirect and cps aren't really lists, they take exactly two values *)
   |attr_lst_eq ("server_args" | "log_type" |  "access_times" | "type"
                | "flags" | "redirect" | "cps")
   |attr_lst_op ( "log_on_success" | "log_on_failure"| "only_from"
                | "no_access" | "env" | "passenv")

  let default_attr =
    attr_one ( "instances" | "banner" | "bind" | "interface" | "per_source"
             | "groups" | "banner_success" | "banner_fail" | "max_load"
             | "v6only" | "umask" | "mdns")
   |attr_lst_eq "cps"       (* really only two values, not a whole list *)
   |attr_lst_op ( "log_type" | "log_on_success" | "log_on_failure" | "disabled"
                | "no_access" | "only_from" | "passenv" | "enabled" )

  (* View: body
   *   Note: 
   *       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. The resulting regular expressions 
   *       would simply be prohibitively large. 
   *)
  let body (attr:lens) = Util.del_str "\n{\n"
                       . (comment|attr)*
                       . del /[ \t]*}[ \t]*\n/ "}\n"

  (* View: includes
   *  Note:
   *   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 ]

  let service = 
     let key_re = /[^ \t\n\/]+/ - /include|includedir|defaults/ in
     [ del /service[ \t]+/ "service " . key key_re . body service_attr ]

  let defaults = [ key "defaults" . del /[ \t]*/ "" . body default_attr ]

  let lns = ( comment | includes | defaults | service )*

  let filter = incl "/etc/xinetd.d/*"
             . incl "/etc/xinetd.conf"
             . Util.stdexcl

  let xfm = transform lns filter

(* Local Variables: *)
(* mode: caml       *)
(* End:             *)

ACC SHELL 2018