Fix php.aug now that inifile.aug supports spaces in values

(* PHP module for Augeas                      *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(*                                            *)

module PHP =

    autoload xfm

    (* PHP is a standard INI file *)
    let setting = IniFile.entry "always_populate_raw_post_data"
                | IniFile.entry "asp_tags"
                | IniFile.entry "browscap"
                | IniFile.entry "child_terminate"
                | IniFile.entry "define_syslog_variables"
                | IniFile.entry "doc_root"
                | IniFile.entry "enable_dl"
                | IniFile.entry "engine"
                | IniFile.entry "expose_php"
                | IniFile.entry "extension_dir"
                | IniFile.entry "file_uploads"
		| IniFile.entry "gpc_order"
                | IniFile.entry "html_errors"
                | IniFile.entry "implicit_flush"
                | IniFile.entry "include_path"
                | IniFile.entry "last_modified"
                | IniFile.entry "memory_limit"
                | IniFile.entry "open_basedir"
                | IniFile.entry "post_max_size"
                | IniFile.entry "precision"
                | IniFile.entry "serialize_precision"
                | IniFile.entry "short_open_tag"
                | IniFile.entry "SMTP"
                | IniFile.entry "smtp_port"
                | IniFile.entry "track_errors"
                | IniFile.entry "unserialize_callback_func"
                | IniFile.entry "variables_order"
                | IniFile.entry "xbithack"
                | IniFile.entry "y2k_compliance"
                | IniFile.entry /apc\.(cache_by_default|enabled|filters|gc_ttl|mmap_file_mask|num_files_hint|optimization|shm_segments|shm_size|slam_defense|ttl|user_entries_hint|user_ttl)/
                | IniFile.entry /apd\.(dumpdir|statement_tracing)/
                | IniFile.entry /arg_separator\.(input|output)/
                | IniFile.entry /assert\.(active|bail|callback|quiet_eval|warning)/
                | IniFile.entry /bcmath\.(scale)/
                | IniFile.entry /blenc\.(key_file)/
                | IniFile.entry /com\.(allow_dcom|autoregister_casesensitive|autoregister_typelib|autoregister_verbose|code_page|typelib_file)/
                | IniFile.entry /crack\.(default_dictionary)/
                | IniFile.entry /daffodildb\.(default_host|default_password|default_socket|default_user|port)/
                | IniFile.entry /date\.(default_latitude|default_longitude|sunrise_zenith|sunset_zenith)/
                | IniFile.entry /dba\.(default_handler)/
                | IniFile.entry /dbx\.(colnames_case)/
                | IniFile.entry /exif\.(decode_jis_intel|decode_jis_motorola|decode_unicode_intel|decode_unicode_motorola|encode_jis|encode_unicode)/
                | IniFile.entry /fbsql\.(allow_persistent|autocommit|batchsize|default_database|default_database_password|default_host|default_password|default_user|generate_warnings|max_connections|max_links|max_persistent|max_results)/
                | IniFile.entry /highlight\.(bg|comment|default|html|keyword|string)/
                | IniFile.entry /hyperwave\.(allow_persistent|default_port)/
                | IniFile.entry /ibase\.(allow_persistent|dateformat|default_charset|default_db|default_password|default_user|max_links|max_persistent|timeformat|timestampformat)/
                | IniFile.entry /iconv\.(input_encoding|internal_encoding|output_encoding)/
                | IniFile.entry /ifx\.(allow_persistent|blobinfile|byteasvarchar|charasvarchar|default_host|default_password|default_user|max_links|max_persistent|nullformat|textasvarchar)/
                | IniFile.entry /ingres\.(allow_persistent|default_database|default_password|default_user|max_links|max_persistent)/
                | IniFile.entry /ircg\.(control_user|keep_alive_interval|max_format_message_sets|shared_mem_size|work_dir)/
                | IniFile.entry /ldap\.(max_links)/
                | IniFile.entry /mail\.(force_extra_parameters)/
                | IniFile.entry /mailparse\.(def_charset)/
                | IniFile.entry /maxdb\.(default_db|default_host|default_pw|default_user|long_readlen)/
                | IniFile.entry /mbstring\.(detect_order|encoding_translation|func_overload|http_input|http_output|internal_encoding|language|script_encoding|substitute_character)/
                | IniFile.entry /mcrypt\.(algorithms_dir|modes_dir)/
                | IniFile.entry /mime_magic\.(debug|magicfile)/
                | IniFile.entry /mssql\.(allow_persistent|batchsize|compatability_mode|connect_timeout|datetimeconvert|max_links|max_persistent|max_procs|min_error_severity|min_message_severity|secure_connection|textlimit|textsize|timeout)/
                | IniFile.entry /msql\.(allow_persistent|max_links|max_persistent)/
                | IniFile.entry /mysql\.(allow_persistent|connect_timeout|default_host|default_password|default_port|default_socket|default_user|max_links|max_persistent|trace_mode)/
                | IniFile.entry /mysqli\.(default_host|default_port|default_pw|default_socket|default_user|max_links|reconnect)/
                | IniFile.entry /namazu\.(debugmode|lang|loggingmode|sortmethod|sortorder)/
                | IniFile.entry /nsapi\.(read_timeout)/
                | IniFile.entry /odbc\.(allow_persistent|check_persistent|defaultbinmode|defaultlrl|default_db|default_pw|default_user|max_links|max_persistent)/
                | IniFile.entry /opendirectory\.(max_refs|separator)/
                | IniFile.entry /pdo\.(global_value)/
                | IniFile.entry /pfpro\.(defaulthost|defaultport|defaulttimeout|proxyaddress|proxylogon|proxypassword|proxyport)/
                | IniFile.entry /pgsql\.(allow_persistent|auto_reset_persistent|ignore_notice|log_notice|max_links|max_persistent)/
                | IniFile.entry /printer\.(default_printer)/
                | IniFile.entry /session\.(auto_start|bug_compat_42|bug_compat_warn|cache_expire|cache_limiter|cookie_(domain|httponly|lifetime|path|secure)|entropy_file|entropy_length|gc_divisor|gc_maxlifetime|gc_probability|hash_bits_per_character|hash_function|name|referer_check|save_handler|save_path|serialize_handler|use_cookies|use_only_cookies|use_trans_sid)/
                | IniFile.entry /session_pgsql\.(create_table|db|disable|failover_mode|gc_interval|keep_expired|sem_file_name|serializable|short_circuit|use_app_vars|vacuum_interval)/
                | IniFile.entry /simple_cvs\.(authMethod|compressionLevel|cvsRoot|host|moduleName|userName|workingDir)/
                | IniFile.entry /soap\.(wsdl_cache_dir|wsdl_cache_enabled|wsdl_cache_ttl)/
                | IniFile.entry /sql\.(safe_mode)/
                | IniFile.entry /sqlite\.(assoc_case)/
		| IniFile.entry /sybase\.(allow_persistent|max_(persistent|links)|interface_file|min_(error|message)_severity|compatability_mode)/
                | IniFile.entry /sybct\.(allow_persistent|deadlock_retry_count|hostname|login_timeout|max_links|max_persistent|min_client_severity|min_server_severity)/
                | IniFile.entry /tidy\.(clean_output|default_config)/
                | IniFile.entry /url_rewriter\.(tags)/
                | IniFile.entry /valkyrie\.(auto_validate|config_path)/
                | IniFile.entry /xmms\.(path|session)/
                | IniFile.entry /yaz\.(keepalive|log_file|max_links)/
                | IniFile.entry /zend\.(ze1_compatibility_mode)/
                | IniFile.entry /zlib\.(output_compression|output_compression_level|output_handler)/
                | IniFile.entry /allow_(call_time_pass_reference|url_fopen|url_include)/
                | IniFile.entry /auto_(append_file|detect_line_endings|globals_jit|prepend_file)/
                | IniFile.entry /default_(charset|mimetype|socket_timeout)/
		| IniFile.entry /display(_startup)?_errors/
                | IniFile.entry /disable_(classes|functions)/
                | IniFile.entry /docref_(ext|root)/
                | IniFile.entry /error_(append_string|log|prepend_string|reporting)/
                | IniFile.entry /ignore_(repeated_errors|repeated_source|user_abort)/
                | IniFile.entry /log_errors(_max_len)?/
                | IniFile.entry /magic_quotes_(gpc|runtime|sybase)/
                | IniFile.entry /max_(execution_time|input_time)/
                | IniFile.entry /output_(buffering|handler)/
                | IniFile.entry /realpath_(cache_size|cache_ttl)/
                | IniFile.entry /register_(argc_argv|globals|long_arrays)/
                | IniFile.entry /report_(memleaks|zend_debug)/
                | IniFile.entry /safe_mode(_(allowed_env_vars|exec_dir|gid|include_dir|protected_env_vars))?/
                | IniFile.entry /sendmail_(from|path)/
                | IniFile.entry /upload_(max_filesize|tmp_dir)/
                | IniFile.entry /user_(agent|dir)/
                | IniFile.entry /xmlrpc_error(s|_number)/

	let record = IniFile.record "section" setting
	let lns    = IniFile.lns record

	let filter = (incl "/etc/php*/*/php.ini")
	           . Util.stdexcl

	let xfm = transform lns filter

(* PHP module for Augeas                      *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(*                                            *)

module PHP =

    autoload xfm

    (* Define a special entry when spaces are allowed in values *)
    (* This is the case for error_reporting for example         *)
    let comment_nospace  = IniFile.comment_generic /(#|;)/
    let value_allowspace = del /[ \t]*/ " " . store /[^;# \t\n][^;#\n]*[^;# \t\n]|[^;# \t\n]/
    let entry_allowspace (kw:regexp) = [ key kw . IniFile.value_sepwithcolon . value_allowspace? . (comment_nospace|IniFile.eol) ]

    (* PHP is a standard INI file *)
    let setting = IniFile.entry "always_populate_raw_post_data"
                | IniFile.entry "asp_tags"
                | IniFile.entry "browscap"
                | IniFile.entry "child_terminate"
                | IniFile.entry "define_syslog_variables"
                | IniFile.entry "doc_root"
                | IniFile.entry "enable_dl"
                | IniFile.entry "engine"
                | IniFile.entry "expose_php"
                | IniFile.entry "extension_dir"
                | IniFile.entry "file_uploads"
		| IniFile.entry "gpc_order"
                | IniFile.entry "html_errors"
                | IniFile.entry "implicit_flush"
                | IniFile.entry "include_path"
                | IniFile.entry "last_modified"
                | IniFile.entry "memory_limit"
                | IniFile.entry "open_basedir"
                | IniFile.entry "post_max_size"
                | IniFile.entry "precision"
                | IniFile.entry "serialize_precision"
                | IniFile.entry "short_open_tag"
                | IniFile.entry "SMTP"
                | IniFile.entry "smtp_port"
                | IniFile.entry "track_errors"
                | IniFile.entry "unserialize_callback_func"
                | IniFile.entry "variables_order"
                | IniFile.entry "xbithack"
                | IniFile.entry "y2k_compliance"
                | IniFile.entry /apc\.(cache_by_default|enabled|filters|gc_ttl|mmap_file_mask|num_files_hint|optimization|shm_segments|shm_size|slam_defense|ttl|user_entries_hint|user_ttl)/
                | IniFile.entry /apd\.(dumpdir|statement_tracing)/
                | IniFile.entry /arg_separator\.(input|output)/
                | IniFile.entry /assert\.(active|bail|callback|quiet_eval|warning)/
                | IniFile.entry /bcmath\.(scale)/
                | IniFile.entry /blenc\.(key_file)/
                | IniFile.entry /com\.(allow_dcom|autoregister_casesensitive|autoregister_typelib|autoregister_verbose|code_page|typelib_file)/
                | IniFile.entry /crack\.(default_dictionary)/
                | IniFile.entry /daffodildb\.(default_host|default_password|default_socket|default_user|port)/
                | IniFile.entry /date\.(default_latitude|default_longitude|sunrise_zenith|sunset_zenith)/
                | IniFile.entry /dba\.(default_handler)/
                | IniFile.entry /dbx\.(colnames_case)/
                | IniFile.entry /exif\.(decode_jis_intel|decode_jis_motorola|decode_unicode_intel|decode_unicode_motorola|encode_jis|encode_unicode)/
                | IniFile.entry /fbsql\.(allow_persistent|autocommit|batchsize|default_database|default_database_password|default_host|default_password|default_user|generate_warnings|max_connections|max_links|max_persistent|max_results)/
                | IniFile.entry /highlight\.(bg|comment|default|html|keyword|string)/
                | IniFile.entry /hyperwave\.(allow_persistent|default_port)/
                | IniFile.entry /ibase\.(allow_persistent|dateformat|default_charset|default_db|default_password|default_user|max_links|max_persistent|timeformat|timestampformat)/
                | IniFile.entry /iconv\.(input_encoding|internal_encoding|output_encoding)/
                | IniFile.entry /ifx\.(allow_persistent|blobinfile|byteasvarchar|charasvarchar|default_host|default_password|default_user|max_links|max_persistent|nullformat|textasvarchar)/
                | IniFile.entry /ingres\.(allow_persistent|default_database|default_password|default_user|max_links|max_persistent)/
                | IniFile.entry /ircg\.(control_user|keep_alive_interval|max_format_message_sets|shared_mem_size|work_dir)/
                | IniFile.entry /ldap\.(max_links)/
                | IniFile.entry /mail\.(force_extra_parameters)/
                | IniFile.entry /mailparse\.(def_charset)/
                | IniFile.entry /maxdb\.(default_db|default_host|default_pw|default_user|long_readlen)/
                | IniFile.entry /mbstring\.(detect_order|encoding_translation|func_overload|http_input|http_output|internal_encoding|language|script_encoding|substitute_character)/
                | IniFile.entry /mcrypt\.(algorithms_dir|modes_dir)/
                | IniFile.entry /mime_magic\.(debug|magicfile)/
                | IniFile.entry /mssql\.(allow_persistent|batchsize|compatability_mode|connect_timeout|datetimeconvert|max_links|max_persistent|max_procs|min_error_severity|min_message_severity|secure_connection|textlimit|textsize|timeout)/
                | IniFile.entry /msql\.(allow_persistent|max_links|max_persistent)/
                | IniFile.entry /mysql\.(allow_persistent|connect_timeout|default_host|default_password|default_port|default_socket|default_user|max_links|max_persistent|trace_mode)/
                | IniFile.entry /mysqli\.(default_host|default_port|default_pw|default_socket|default_user|max_links|reconnect)/
                | IniFile.entry /namazu\.(debugmode|lang|loggingmode|sortmethod|sortorder)/
                | IniFile.entry /nsapi\.(read_timeout)/
                | IniFile.entry /odbc\.(allow_persistent|check_persistent|defaultbinmode|defaultlrl|default_db|default_pw|default_user|max_links|max_persistent)/
                | IniFile.entry /opendirectory\.(max_refs|separator)/
                | IniFile.entry /pdo\.(global_value)/
                | IniFile.entry /pfpro\.(defaulthost|defaultport|defaulttimeout|proxyaddress|proxylogon|proxypassword|proxyport)/
                | IniFile.entry /pgsql\.(allow_persistent|auto_reset_persistent|ignore_notice|log_notice|max_links|max_persistent)/
                | IniFile.entry /printer\.(default_printer)/
                | IniFile.entry /session\.(auto_start|bug_compat_42|bug_compat_warn|cache_expire|cache_limiter|cookie_(domain|httponly|lifetime|path|secure)|entropy_file|entropy_length|gc_divisor|gc_maxlifetime|gc_probability|hash_bits_per_character|hash_function|name|referer_check|save_handler|save_path|serialize_handler|use_cookies|use_only_cookies|use_trans_sid)/
                | IniFile.entry /session_pgsql\.(create_table|db|disable|failover_mode|gc_interval|keep_expired|sem_file_name|serializable|short_circuit|use_app_vars|vacuum_interval)/
                | IniFile.entry /simple_cvs\.(authMethod|compressionLevel|cvsRoot|host|moduleName|userName|workingDir)/
                | IniFile.entry /soap\.(wsdl_cache_dir|wsdl_cache_enabled|wsdl_cache_ttl)/
                | IniFile.entry /sql\.(safe_mode)/
                | IniFile.entry /sqlite\.(assoc_case)/
		| IniFile.entry /sybase\.(allow_persistent|max_(persistent|links)|interface_file|min_(error|message)_severity|compatability_mode)/
                | IniFile.entry /sybct\.(allow_persistent|deadlock_retry_count|hostname|login_timeout|max_links|max_persistent|min_client_severity|min_server_severity)/
                | IniFile.entry /tidy\.(clean_output|default_config)/
                | IniFile.entry /url_rewriter\.(tags)/
                | IniFile.entry /valkyrie\.(auto_validate|config_path)/
                | IniFile.entry /xmms\.(path|session)/
                | IniFile.entry /yaz\.(keepalive|log_file|max_links)/
                | IniFile.entry /zend\.(ze1_compatibility_mode)/
                | IniFile.entry /zlib\.(output_compression|output_compression_level|output_handler)/
                | IniFile.entry /allow_(call_time_pass_reference|url_fopen|url_include)/
                | IniFile.entry /auto_(append_file|detect_line_endings|globals_jit|prepend_file)/
                | IniFile.entry /default_(charset|mimetype|socket_timeout)/
		| IniFile.entry /display(_startup)?_errors/
                | IniFile.entry /disable_(classes|functions)/
                | IniFile.entry /docref_(ext|root)/
                | IniFile.entry /error_(append_string|log|prepend_string)/
                | IniFile.entry /ignore_(repeated_errors|repeated_source|user_abort)/
                | IniFile.entry /log_errors(_max_len)?/
                | IniFile.entry /magic_quotes_(gpc|runtime|sybase)/
                | IniFile.entry /max_(execution_time|input_time)/
                | IniFile.entry /output_(buffering|handler)/
                | IniFile.entry /realpath_(cache_size|cache_ttl)/
                | IniFile.entry /register_(argc_argv|globals|long_arrays)/
                | IniFile.entry /report_(memleaks|zend_debug)/
                | IniFile.entry /safe_mode(_(allowed_env_vars|exec_dir|gid|include_dir|protected_env_vars))?/
                | IniFile.entry /sendmail_(from|path)/
                | IniFile.entry /upload_(max_filesize|tmp_dir)/
                | IniFile.entry /user_(agent|dir)/
                | IniFile.entry /xmlrpc_error(s|_number)/
		| entry_allowspace "error_reporting"

	let record = IniFile.record "section" setting
	let lns    = IniFile.lns record

	let filter = (incl "/etc/php*/*/php.ini")
	           . Util.stdexcl

	let xfm = transform lns filter


Add variables for default delimiters and regexps in build.aug


Shellvars.aug: Add bquot and dollar-assigned tests

(* Test for shell lens *)
module Test_shellvars =

  let eth_static = "# Intel Corporation PRO/100 VE Network Connection
DEVICE=eth0
BOOTPROTO=static
BROADCAST=172.31.0.255
HWADDR=ab:cd:ef:12:34:56
export IPADDR=172.31.0.31 # this is our IP
#DHCP_HOSTNAME=host.example.com
NETMASK=255.255.255.0
NETWORK=172.31.0.0
unset ONBOOT    #   We do not want this var
"
  let empty_val = "EMPTY=\nDEVICE=eth0\n"

  let key_brack = "SOME_KEY[1]=\nDEVICE=eth0\n"

  test Shellvars.lns get eth_static =
    { "#comment" = "Intel Corporation PRO/100 VE Network Connection" }
    { "DEVICE" = "eth0" }
    { "BOOTPROTO" = "static" }
    { "BROADCAST" = "172.31.0.255" }
    { "HWADDR" = "ab:cd:ef:12:34:56" }
    { "IPADDR" = "172.31.0.31"
        { "export" }
        { "#comment" = "this is our IP" } }
    { "#comment" = "DHCP_HOSTNAME=host.example.com" }
    { "NETMASK" = "255.255.255.0" }
    { "NETWORK" = "172.31.0.0" }
    { "@unset"   = "ONBOOT"
        { "#comment" = "We do not want this var" } }

  test Shellvars.lns put eth_static after
      set "BOOTPROTO" "dhcp" ;
      rm "IPADDR" ;
      rm "BROADCAST" ;
      rm "NETMASK" ;
      rm "NETWORK"
  = "# Intel Corporation PRO/100 VE Network Connection
DEVICE=eth0
BOOTPROTO=dhcp
HWADDR=ab:cd:ef:12:34:56
#DHCP_HOSTNAME=host.example.com
unset ONBOOT    #   We do not want this var
"
  test Shellvars.lns get empty_val =
    { "EMPTY" = "" } { "DEVICE" = "eth0" }

  test Shellvars.lns get key_brack =
    { "SOME_KEY[1]" = "" } { "DEVICE" = "eth0" }

  test Shellvars.lns get "smartd_opts=\"-q never\"\n" =
    { "smartd_opts" = "\"-q never\"" }

  test Shellvars.lns get "var=val  \n" = { "var" = "val" }

  test Shellvars.lns get ". /etc/java/java.conf\n" =
    { ".source" = "/etc/java/java.conf" }

  (* Quoted strings and other oddities *)
  test Shellvars.lns get "var=\"foo 'bar'\"\n" =
    { "var" = "\"foo 'bar'\"" }

  test Shellvars.lns get "var='Some \"funny\" value'\n" =
    { "var" = "'Some \"funny\" value'" }

  test Shellvars.lns get "var=\"\\\"\"\n" =
    { "var" = "\"\\\"\"" }

  test Shellvars.lns get "var=\\\"\n" =
    { "var" = "\\\"" }

  test Shellvars.lns get "var=ab#c\n" =
    { "var" = "ab"
        { "#comment" = "c" } }

  test Shellvars.lns get "var='ab#c'\n" =
    { "var" = "'ab#c'" }

  test Shellvars.lns get "var=\"ab#c\"\n" =
    { "var" = "\"ab#c\"" }

  test Shellvars.lns get "ESSID='Joe'\"'\"'s net'\n" =
    { "ESSID" = "'Joe'\"'\"'s net'" }

  test Shellvars.lns get "var=`ab#c`\n" =
    { "var" = "`ab#c`" }

  test Shellvars.lns get "var=`grep nameserver /etc/resolv.conf | head -1`\n" =
    { "var" = "`grep nameserver /etc/resolv.conf | head -1`" }

  test Shellvars.lns put "var=ab #c\n"
    after rm "/var/#comment" = "var=ab\n"

  test Shellvars.lns put "var=ab\n"
    after set "/var/#comment" "this is a var" =
       "var=ab # this is a var\n"

  (* Handling of arrays *)
  test Shellvars.lns get "var=(val1 \"val\\\"2\\\"\" val3)\n" =
    { "var"
        { "1" = "val1" }
        { "2" = "\"val\\\"2\\\"\"" }
        { "3" = "val3" } }

  test Shellvars.lns get "var=()\n" = { "var" = "()" }

  test Shellvars.lns put "var=()\n" after
      set "var" "value"
  = "var=value\n"

  test Shellvars.lns put "var=(v1 v2)\n" after
      rm "var/*" ;
      set "var" "value"
  = "var=value\n"

  test Shellvars.lns put "var=(v1 v2)\n" after
    set "var/3" "v3"
  = "var=(v1 v2 v3)\n"

  test Shellvars.lns get "var=(v1 v2   \n    \t v3)\n" =
  { "var"
    { "1" = "v1" }
    { "2" = "v2" }
    { "3" = "v3" } }

  (* Allow spaces after/before opening/closing parens for array *)
  test Shellvars.lns get "config_eth1=( \"10.128.0.48/24\" )\n" =
  { "config_eth1"  { "1" = "\"10.128.0.48/24\"" } }

  (* Bug 109: allow a bare export *)
  test Shellvars.lns get "export FOO\n" =
  { "@export" = "FOO" }

  (* Bug 73: allow ulimit builtin *)
  test Shellvars.lns get "ulimit -c unlimited\n" =
  { "@builtin" = "ulimit" { "args" = "-c unlimited" } }

  (* Test semicolons *)
  test Shellvars.lns get "VAR1=\"this;is;a;test\"\nVAR2=this;\n" =
  { "VAR1" = "\"this;is;a;test\"" }
  { "VAR2" = "this" }

  (* Bug 230: parse conditions *)
  test Shellvars.lns get "if [ -f /etc/default/keyboard ]; then\n. /etc/default/keyboard\nfi\n" =
  { "@if" = "[ -f /etc/default/keyboard ]" { ".source" = "/etc/default/keyboard" } }

  (* Recursive condition *)
  test Shellvars.lns get "if [ -f /tmp/file1 ]; then
  if [ -f /tmp/file2 ]
  then
    . /tmp/file2
  elif [ -f /tmp/file3 ]; then
    . /tmp/file3; else; . /tmp/file4
  fi
else
  . /tmp/file3
fi\n" =
  { "@if" = "[ -f /tmp/file1 ]"
    { "@if" = "[ -f /tmp/file2 ]"
      { ".source" = "/tmp/file2" }
      { "@elif" = "[ -f /tmp/file3 ]"
        { ".source" = "/tmp/file3" } }
      { "@else"
        { ".source" = "/tmp/file4" }
      }
    }
    { "@else"
      { ".source" = "/tmp/file3" }
    }
  }

  (* Multiple elif *)
  test Shellvars.lns get "if [ -f /tmp/file1 ]; then
  . /tmp/file1
  elif [ -f /tmp/file2 ]; then
  . /tmp/file2
  elif [ -f /tmp/file3 ]; then
  . /tmp/file3
  fi\n" =
  { "@if" = "[ -f /tmp/file1 ]"
    { ".source" = "/tmp/file1" }
    { "@elif" = "[ -f /tmp/file2 ]"
      { ".source" = "/tmp/file2" }
    }
    { "@elif" = "[ -f /tmp/file3 ]"
      { ".source" = "/tmp/file3" }
    }
  }

  (* Comment or eol *)
  test Shellvars.lns get "VAR=value # eol-comment\n" =
  { "VAR" = "value"
    { "#comment" = "eol-comment" }
  }

  (* One-liners *)
  test Shellvars.lns get "if [ -f /tmp/file1 ]; then . /tmp/file1; else . /tmp/file2; fi\n" =
  { "@if" = "[ -f /tmp/file1 ]"
    { ".source" = "/tmp/file1" }
    { "@else"
      { ".source" = "/tmp/file2" }
    }
  }

  (* Loops *)
  test Shellvars.lns get "for f in /tmp/file*; do
  while [ 1 ]; do . $f; done
done\n" =
  { "@for" = "f in /tmp/file*"
    { "@while" = "[ 1 ]"
      { ".source" = "$f" }
    }
  }

  (* Case *)
  test Shellvars.lns get "case $f in
  /tmp/file1)
    . /tmp/file1
    ;;
  /tmp/file2)
    . /tmp/file2
    ;;
  *)
    unset f
    ;;
esac\n" =
  { "@case" = "$f"
    { "@case_entry" = "/tmp/file1"
      { ".source" = "/tmp/file1" } }
    { "@case_entry" = "/tmp/file2"
      { ".source" = "/tmp/file2" } }
    { "@case_entry" = "*"
      { "@unset" = "f" } } }

  (* Select *)
  test Shellvars.lns get "select i in a b c; do . /tmp/file$i
   done\n" =
  { "@select" = "i in a b c"
    { ".source" = "/tmp/file$i" }
  }

  (* Return *)
  test Shellvars.lns get "return\nreturn 2\n" =
  { "@return" }
  { "@return" = "2" }

  (* Functions *)
  test Shellvars.lns get "foo() {
  . /tmp/bar
  }\n" =
  { "@function" = "foo"
    { ".source" = "/tmp/bar" }
  }

  test Shellvars.lns get "function foo () {
  . /tmp/bar
  }\n" =
  { "@function" = "foo"
    { ".source" = "/tmp/bar" }
  }

  (* Dollar assignment *)
  test Shellvars.lns get "FOO=$(bar arg)\n" =
  { "FOO" = "$(bar arg)" }

  (* Empty lines before esac *)
  test Shellvars.lns get "case $f in
  a)
    B=C
    ;;

  esac\n" =
  { "@case" = "$f"
    { "@case_entry" = "a"
      { "B" = "C" } }
    }

  (* Empty lines before a case_entry *)
  test Shellvars.lns get "case $f in

  a)
    B=C
    ;;

  b)
    A=D
    ;;
  esac\n" =
  { "@case" = "$f"
    { "@case_entry" = "a"
      { "B" = "C" } }
    { "@case_entry" = "b"
      { "A" = "D" } } }

  (* Comments anywhere *)
  test Shellvars.lns get "case ${INTERFACE} in
# comment before
eth0)
# comment in
OPTIONS=()
;;

# comment before 2
*)
# comment in 2
unset f
;;
# comment after
esac\n" =
  { "@case" = "${INTERFACE}"
    { "#comment" = "comment before" }
    { "@case_entry" = "eth0"
      { "#comment" = "comment in" }
      { "OPTIONS" = "()" } }
    { "#comment" = "comment before 2" }
    { "@case_entry" = "*"
      { "#comment" = "comment in 2" }
      { "@unset" = "f" } }
    { "#comment" = "comment after" } }

  (* Empty case *)
  test Shellvars.lns get "case $a in
  *)
  ;;
  esac\n" =
  { "@case" = "$a"
    { "@case_entry" = "*" } }

  (* Double quoted values can have newlines *)
  test Shellvars.lns get "FOO=\"123\n456\"\n" =
  { "FOO" = "\"123\n456\"" }

  (* Single quoted values can have newlines *)
  test Shellvars.lns get "FOO='123\n456'\n" =
  { "FOO" = "'123\n456'" }

  (* bquoted values can have semi-colons *)
  test Shellvars.lns get "FOO=`bar=date;$bar`\n" =
  { "FOO" = "`bar=date;$bar`" }

  (* dollar-assigned values can have semi-colons *)
  test Shellvars.lns get "FOO=$(bar=date;$bar)\n" =
  { "FOO" = "$(bar=date;$bar)" }

  (* dollar-assigned value in bquot *)
  test Shellvars.lns get "FOO=`echo $(date)`\n" =
  { "FOO" = "`echo $(date)`" }

  (* bquot value in dollar-assigned value *)
  test Shellvars.lns get "FOO=$(echo `date`)\n" =
  { "FOO" = "$(echo `date`)" }

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

(* Test for shell lens *)
module Test_shellvars =

  let eth_static = "# Intel Corporation PRO/100 VE Network Connection
DEVICE=eth0
BOOTPROTO=static
BROADCAST=172.31.0.255
HWADDR=ab:cd:ef:12:34:56
export IPADDR=172.31.0.31 # this is our IP
#DHCP_HOSTNAME=host.example.com
NETMASK=255.255.255.0
NETWORK=172.31.0.0
unset ONBOOT    #   We do not want this var
"
  let empty_val = "EMPTY=\nDEVICE=eth0\n"

  let key_brack = "SOME_KEY[1]=\nDEVICE=eth0\n"

  test Shellvars.lns get eth_static =
    { "#comment" = "Intel Corporation PRO/100 VE Network Connection" }
    { "DEVICE" = "eth0" }
    { "BOOTPROTO" = "static" }
    { "BROADCAST" = "172.31.0.255" }
    { "HWADDR" = "ab:cd:ef:12:34:56" }
    { "IPADDR" = "172.31.0.31"
        { "export" }
        { "#comment" = "this is our IP" } }
    { "#comment" = "DHCP_HOSTNAME=host.example.com" }
    { "NETMASK" = "255.255.255.0" }
    { "NETWORK" = "172.31.0.0" }
    { "@unset"   = "ONBOOT"
        { "#comment" = "We do not want this var" } }

  test Shellvars.lns put eth_static after
      set "BOOTPROTO" "dhcp" ;
      rm "IPADDR" ;
      rm "BROADCAST" ;
      rm "NETMASK" ;
      rm "NETWORK"
  = "# Intel Corporation PRO/100 VE Network Connection
DEVICE=eth0
BOOTPROTO=dhcp
HWADDR=ab:cd:ef:12:34:56
#DHCP_HOSTNAME=host.example.com
unset ONBOOT    #   We do not want this var
"
  test Shellvars.lns get empty_val =
    { "EMPTY" = "" } { "DEVICE" = "eth0" }

  test Shellvars.lns get key_brack =
    { "SOME_KEY[1]" = "" } { "DEVICE" = "eth0" }

  test Shellvars.lns get "smartd_opts=\"-q never\"\n" =
    { "smartd_opts" = "\"-q never\"" }

  test Shellvars.lns get "var=val  \n" = { "var" = "val" }

  test Shellvars.lns get ". /etc/java/java.conf\n" =
    { ".source" = "/etc/java/java.conf" }

  (* Quoted strings and other oddities *)
  test Shellvars.lns get "var=\"foo 'bar'\"\n" =
    { "var" = "\"foo 'bar'\"" }

  test Shellvars.lns get "var='Some \"funny\" value'\n" =
    { "var" = "'Some \"funny\" value'" }

  test Shellvars.lns get "var=\"\\\"\"\n" =
    { "var" = "\"\\\"\"" }

  test Shellvars.lns get "var=\\\"\n" =
    { "var" = "\\\"" }

  test Shellvars.lns get "var=ab#c\n" =
    { "var" = "ab"
        { "#comment" = "c" } }

  test Shellvars.lns get "var='ab#c'\n" =
    { "var" = "'ab#c'" }

  test Shellvars.lns get "var=\"ab#c\"\n" =
    { "var" = "\"ab#c\"" }

  test Shellvars.lns get "ESSID='Joe'\"'\"'s net'\n" =
    { "ESSID" = "'Joe'\"'\"'s net'" }

  test Shellvars.lns get "var=`ab#c`\n" =
    { "var" = "`ab#c`" }

  test Shellvars.lns get "var=`grep nameserver /etc/resolv.conf | head -1`\n" =
    { "var" = "`grep nameserver /etc/resolv.conf | head -1`" }

  test Shellvars.lns put "var=ab #c\n"
    after rm "/var/#comment" = "var=ab\n"

  test Shellvars.lns put "var=ab\n"
    after set "/var/#comment" "this is a var" =
       "var=ab # this is a var\n"

  (* Handling of arrays *)
  test Shellvars.lns get "var=(val1 \"val\\\"2\\\"\" val3)\n" =
    { "var"
        { "1" = "val1" }
        { "2" = "\"val\\\"2\\\"\"" }
        { "3" = "val3" } }

  test Shellvars.lns get "var=()\n" = { "var" = "()" }

  test Shellvars.lns put "var=()\n" after
      set "var" "value"
  = "var=value\n"

  test Shellvars.lns put "var=(v1 v2)\n" after
      rm "var/*" ;
      set "var" "value"
  = "var=value\n"

  test Shellvars.lns put "var=(v1 v2)\n" after
    set "var/3" "v3"
  = "var=(v1 v2 v3)\n"

  test Shellvars.lns get "var=(v1 v2   \n    \t v3)\n" =
  { "var"
    { "1" = "v1" }
    { "2" = "v2" }
    { "3" = "v3" } }

  (* Allow spaces after/before opening/closing parens for array *)
  test Shellvars.lns get "config_eth1=( \"10.128.0.48/24\" )\n" =
  { "config_eth1"  { "1" = "\"10.128.0.48/24\"" } }

  (* Bug 109: allow a bare export *)
  test Shellvars.lns get "export FOO\n" =
  { "@export" = "FOO" }

  (* Bug 73: allow ulimit builtin *)
  test Shellvars.lns get "ulimit -c unlimited\n" =
  { "@builtin" = "ulimit" { "args" = "-c unlimited" } }

  (* Test semicolons *)
  test Shellvars.lns get "VAR1=\"this;is;a;test\"\nVAR2=this;\n" =
  { "VAR1" = "\"this;is;a;test\"" }
  { "VAR2" = "this" }

  (* Bug 230: parse conditions *)
  test Shellvars.lns get "if [ -f /etc/default/keyboard ]; then\n. /etc/default/keyboard\nfi\n" =
  { "@if" = "[ -f /etc/default/keyboard ]" { ".source" = "/etc/default/keyboard" } }

  (* Recursive condition *)
  test Shellvars.lns get "if [ -f /tmp/file1 ]; then
  if [ -f /tmp/file2 ]
  then
    . /tmp/file2
  elif [ -f /tmp/file3 ]; then
    . /tmp/file3; else; . /tmp/file4
  fi
else
  . /tmp/file3
fi\n" =
  { "@if" = "[ -f /tmp/file1 ]"
    { "@if" = "[ -f /tmp/file2 ]"
      { ".source" = "/tmp/file2" }
      { "@elif" = "[ -f /tmp/file3 ]"
        { ".source" = "/tmp/file3" } }
      { "@else"
        { ".source" = "/tmp/file4" }
      }
    }
    { "@else"
      { ".source" = "/tmp/file3" }
    }
  }

  (* Multiple elif *)
  test Shellvars.lns get "if [ -f /tmp/file1 ]; then
  . /tmp/file1
  elif [ -f /tmp/file2 ]; then
  . /tmp/file2
  elif [ -f /tmp/file3 ]; then
  . /tmp/file3
  fi\n" =
  { "@if" = "[ -f /tmp/file1 ]"
    { ".source" = "/tmp/file1" }
    { "@elif" = "[ -f /tmp/file2 ]"
      { ".source" = "/tmp/file2" }
    }
    { "@elif" = "[ -f /tmp/file3 ]"
      { ".source" = "/tmp/file3" }
    }
  }

  (* Comment or eol *)
  test Shellvars.lns get "VAR=value # eol-comment\n" =
  { "VAR" = "value"
    { "#comment" = "eol-comment" }
  }

  (* One-liners *)
  test Shellvars.lns get "if [ -f /tmp/file1 ]; then . /tmp/file1; else . /tmp/file2; fi\n" =
  { "@if" = "[ -f /tmp/file1 ]"
    { ".source" = "/tmp/file1" }
    { "@else"
      { ".source" = "/tmp/file2" }
    }
  }

  (* Loops *)
  test Shellvars.lns get "for f in /tmp/file*; do
  while [ 1 ]; do . $f; done
done\n" =
  { "@for" = "f in /tmp/file*"
    { "@while" = "[ 1 ]"
      { ".source" = "$f" }
    }
  }

  (* Case *)
  test Shellvars.lns get "case $f in
  /tmp/file1)
    . /tmp/file1
    ;;
  /tmp/file2)
    . /tmp/file2
    ;;
  *)
    unset f
    ;;
esac\n" =
  { "@case" = "$f"
    { "@case_entry" = "/tmp/file1"
      { ".source" = "/tmp/file1" } }
    { "@case_entry" = "/tmp/file2"
      { ".source" = "/tmp/file2" } }
    { "@case_entry" = "*"
      { "@unset" = "f" } } }

  (* Select *)
  test Shellvars.lns get "select i in a b c; do . /tmp/file$i
   done\n" =
  { "@select" = "i in a b c"
    { ".source" = "/tmp/file$i" }
  }

  (* Return *)
  test Shellvars.lns get "return\nreturn 2\n" =
  { "@return" }
  { "@return" = "2" }

  (* Functions *)
  test Shellvars.lns get "foo() {
  . /tmp/bar
  }\n" =
  { "@function" = "foo"
    { ".source" = "/tmp/bar" }
  }

  test Shellvars.lns get "function foo () {
  . /tmp/bar
  }\n" =
  { "@function" = "foo"
    { ".source" = "/tmp/bar" }
  }

  (* Dollar assignment *)
  test Shellvars.lns get "FOO=$(bar arg)\n" =
  { "FOO" = "$(bar arg)" }

  (* Empty lines before esac *)
  test Shellvars.lns get "case $f in
  a)
    B=C
    ;;

  esac\n" =
  { "@case" = "$f"
    { "@case_entry" = "a"
      { "B" = "C" } }
    }

  (* Empty lines before a case_entry *)
  test Shellvars.lns get "case $f in

  a)
    B=C
    ;;

  b)
    A=D
    ;;
  esac\n" =
  { "@case" = "$f"
    { "@case_entry" = "a"
      { "B" = "C" } }
    { "@case_entry" = "b"
      { "A" = "D" } } }

  (* Comments anywhere *)
  test Shellvars.lns get "case ${INTERFACE} in
# comment before
eth0)
# comment in
OPTIONS=()
;;

# comment before 2
*)
# comment in 2
unset f
;;
# comment after
esac\n" =
  { "@case" = "${INTERFACE}"
    { "#comment" = "comment before" }
    { "@case_entry" = "eth0"
      { "#comment" = "comment in" }
      { "OPTIONS" = "()" } }
    { "#comment" = "comment before 2" }
    { "@case_entry" = "*"
      { "#comment" = "comment in 2" }
      { "@unset" = "f" } }
    { "#comment" = "comment after" } }

  (* Empty case *)
  test Shellvars.lns get "case $a in
  *)
  ;;
  esac\n" =
  { "@case" = "$a"
    { "@case_entry" = "*" } }

  (* Double quoted values can have newlines *)
  test Shellvars.lns get "FOO=\"123\n456\"\n" =
  { "FOO" = "\"123\n456\"" }

  (* Single quoted values can have newlines *)
  test Shellvars.lns get "FOO='123\n456'\n" =
  { "FOO" = "'123\n456'" }

  (* bquoted values can have semi-colons *)
  test Shellvars.lns get "FOO=`bar=date;$bar`\n" =
  { "FOO" = "`bar=date;$bar`" }

  (* dollar-assigned values can have semi-colons *)
  test Shellvars.lns get "FOO=$(bar=date;$bar)\n" =
  { "FOO" = "$(bar=date;$bar)" }

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


* lenses/util.aug: do not set caml mode for Emacs

(*
Module: Util
  Generic module providing useful primitives

Author: David Lutterkort

About: License
  This file is licensed under the LGPLv2+, like the rest of Augeas.
*)

module Util =

(*
Variable: del_str
  Delete a string and default to it

  Parameters:
     s:string - the string to delete and default to
*)
  let del_str (s:string) = del s s

(*
Variable: del_ws
  Delete mandatory whitespace
*)
  let del_ws = del /[ \t]+/

(*
Variable: del_ws_spc
  Delete mandatory whitespace, default to single space
*)
  let del_ws_spc = del_ws " "

(*
Variable: del_ws_tab
  Delete mandatory whitespace, default to single tab
*)
  let del_ws_tab = del_ws "\t"

(*
Variable: del_opt_ws
  Delete optional whitespace
*)
  let del_opt_ws = del /[ \t]*/

(*
Variable: eol
  Delete end of line, including optional trailing whitespace
*)
  let eol = del /[ \t]*\n/ "\n"

(*
Variable: indent
  Delete indentation, including leading whitespace
*)
  let indent = del /[ \t]*/ ""

(* Group: Comment
     This is a general definition of comment
     It allows indentation for comments, removes the leading and trailing spaces
     of comments and stores them in nodes, except for empty comments which are
     ignored together with empty lines

View: comment_generic
  Map comments and set default comment sign
*)

  let comment_generic (r:regexp) (d:string) =
    [ label "#comment" . del r d
        . store /([^ \t\n].*[^ \t\n]|[^ \t\n])/ . eol ]

(* View: comment
  Map comments into "#comment" nodes
*)
  let comment = comment_generic /[ \t]*#[ \t]*/ "# "

(* View: comment_eol
  Map eol comments into "#comment" nodes
  Add a space before # for end of line comments
*)
  let comment_eol = comment_generic /[ \t]*#[ \t]*/ " # "

(* View: comment_or_eol
    A <comment_eol> or <eol>, with an optional empty comment *)
 let comment_or_eol = comment_eol | (del /[ \t]*(#[ \t]*)?\n/ "\n")

(* View: comment_multiline
    A C-style multiline comment *)
  let comment_multiline =
     let mline_re = (/[^ \t\n].*[^ \t\n]|[^ \t\n]/ - /.*\*\/.*/) in
     let mline = [ seq "mline"
                 . store mline_re ] in
     [ label "#mcomment" . del /[ \t]*\/\*[ \t\n]*/ "/*\n"
       . counter "mline"
       . (mline . (eol . mline)*)
       . del /[ \t\n]*\*\/[ \t]*\n/ "\n*/\n" ]

(* View: comment_c_style
    A comment line, C-style *)
  let comment_c_style =
    comment_generic /[ \t]*\/\/[ \t]*/ "// "

(* View: empty_generic
  A generic definition of <empty>
  Map empty lines, including empty comments *)
  let empty_generic (r:regexp) =
    [ del r "" . del_str "\n" ]

(* View: empty
  Map empty lines, including empty comments *)
  let empty = empty_generic /[ \t]*#?[ \t]*/

(* View: empty_c_style
  Map empty lines, including C-style empty comment *)
  let empty_c_style =
    empty_generic /[ \t]*((\/\/)|(\/\*[ \t]*\*\/))?[ \t]*/

(* View: Split *)
(* Split (SEP . ELT)* into an array-like tree where each match for ELT *)
(* appears in a separate subtree. The labels for the subtrees are      *)
(* consecutive numbers, starting at 0                                  *)
  let split (elt:lens) (sep:lens) =
    let sym = gensym "split" in
    counter sym . ( [ seq sym . sep . elt ] ) *

(* Group: Exclusions

Variable: stdexcl
  Exclusion for files that are commonly not wanted/needed
*)
  let stdexcl = (excl "*~") .
    (excl "*.rpmnew") .
    (excl "*.rpmsave") .
    (excl "*.dpkg-old") .
    (excl "*.dpkg-new") .
    (excl "*.dpkg-bak") .
    (excl "*.dpkg-dist") .
    (excl "*.augsave") .
    (excl "*.augnew")

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


php.aug  - Fix php7 FPM support

php.aug  - Fix php7 FPM support

Update path to reflect the transition from:
/etc/php5/ to /etc/php/7.0/

(* PHP module for Augeas                      *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(*                                            *)

module PHP =
  autoload xfm

(************************************************************************
 * INI File settings
 *************************************************************************)

let comment  = IniFile.comment IniFile.comment_re IniFile.comment_default
let sep      = IniFile.sep IniFile.sep_re IniFile.sep_default
let empty    = IniFile.empty

(************************************************************************
 *                        ENTRY
 *
 * We have to remove the keyword "section" from possible entry keywords
 * otherwise it would lead to an ambiguity with the "section" label
 * since PHP allows entries outside of sections.
 *************************************************************************)
let entry    =
     let word = IniFile.entry_re
  in let entry_re = word . ( "[" . word . "]" )?
  in IniFile.indented_entry entry_re sep comment

(************************************************************************
 *                         TITLE
 *
 * We use IniFile.title_label because there can be entries
 * outside of sections whose labels would conflict with section names
 *************************************************************************)
let title       = IniFile.title ( IniFile.record_re - ".anon" )
let record      = IniFile.record title entry

let record_anon = [ label ".anon" . ( entry | empty )+ ]

(************************************************************************
 *                         LENS & FILTER
 * There can be entries before any section
 * IniFile.entry includes comment management, so we just pass entry to lns
 *************************************************************************)
let lns    = record_anon? . record*

let filter = (incl "/etc/php*/*/*.ini")
             . (incl "/etc/php/*/*/*.ini")
             . (incl "/etc/php.ini")
             . (incl "/etc/php.d/*.ini")
             (* PHPFPM Support *)
             . (incl "/etc/php*/fpm/pool.d/*.conf")
             . (incl "/etc/php/*/fpm/pool.d/*.conf")
             (* Zend Community edition *)
             . (incl "/usr/local/zend/etc/php.ini")
             . (incl "/usr/local/zend/etc/conf.d/*.ini")
             . Util.stdexcl

let xfm = transform lns filter

(* PHP module for Augeas                      *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(*                                            *)

module PHP =
  autoload xfm

(************************************************************************
 * INI File settings
 *************************************************************************)

let comment  = IniFile.comment IniFile.comment_re IniFile.comment_default
let sep      = IniFile.sep IniFile.sep_re IniFile.sep_default
let empty    = IniFile.empty

(************************************************************************
 *                        ENTRY
 *
 * We have to remove the keyword "section" from possible entry keywords
 * otherwise it would lead to an ambiguity with the "section" label
 * since PHP allows entries outside of sections.
 *************************************************************************)
let entry    =
     let word = IniFile.entry_re
  in let entry_re = word . ( "[" . word . "]" )?
  in IniFile.indented_entry entry_re sep comment

(************************************************************************
 *                         TITLE
 *
 * We use IniFile.title_label because there can be entries
 * outside of sections whose labels would conflict with section names
 *************************************************************************)
let title       = IniFile.title ( IniFile.record_re - ".anon" )
let record      = IniFile.record title entry

let record_anon = [ label ".anon" . ( entry | empty )+ ]

(************************************************************************
 *                         LENS & FILTER
 * There can be entries before any section
 * IniFile.entry includes comment management, so we just pass entry to lns
 *************************************************************************)
let lns    = record_anon? . record*

let filter = (incl "/etc/php*/*/*.ini")
             . (incl "/etc/php/*/*/*.ini")
             . (incl "/etc/php.ini")
             . (incl "/etc/php.d/*.ini")
             (* PHPFPM Support *)
             . (incl "/etc/php*/fpm/pool.d/*.conf")
             (* Zend Community edition *)
             . (incl "/usr/local/zend/etc/php.ini")
             . (incl "/usr/local/zend/etc/conf.d/*.ini")
             . Util.stdexcl

let xfm = transform lns filter


Clean wrong lines in modprobe.aug's header

(*
Module: Modprobe
  Parses /etc/modprobe.conf and /etc/modprobe.d/*

Original Author: David Lutterkort <lutter@redhat.com>

Author: Raphael Pinson <raphink@gmail.com>

About: Reference
  This lens tries to keep as close as possible to `man 5 modprobe.conf` where possible.

About: License
   This file is licenced under the LGPLv2+, like the rest of Augeas.

About: Lens Usage
   To be documented

About: Configuration files
   This lens applies to /etc/modprobe.conf and /etc/modprobe.d/*. See <filter>.
*)

module Modprobe =
autoload xfm

(************************************************************************
 * Group:                 USEFUL PRIMITIVES
 *************************************************************************)

(* View: comment *)
let comment = Util.comment

(* View: empty *)
let empty = Util.empty

(* View: sep_space *)
let sep_space = del /([ \t]|(\\\\\n))+/ " "

(* View: sto_no_spaces *)
let sto_no_spaces = store /[^# \t\n\\\\]+/

(* View: sto_to_eol *)
let sto_to_eol = store /[^# \t\n\\\\][^#\n\\\\]*[^# \t\n\\\\]|[^# \t\n\\\\]/

(* View: alias *)
let alias =
  let modulename = [ label "modulename" . sto_no_spaces ] in
  Build.key_value_line_comment "alias" sep_space
                       (sto_no_spaces . sep_space . modulename)
                       comment

(************************************************************************
 * Group:                 ENTRY TYPES
 *************************************************************************)

(* View: options *)
let options =
  let opt_value = /[^#" \t\n\\\\]+|"[^#"\n\\\\]*"/ in
  let option = [ key Rx.word . (Util.del_str "=" . store opt_value)? ] in
  [ key "options" . sep_space . sto_no_spaces
                  . (sep_space . option)* . Util.comment_or_eol ]

(* View: install_remove *)
let kv_line_command (kw:regexp) =
  let command = [ label "command" . sto_to_eol ] in
  [ key kw . sep_space . sto_no_spaces
                         . sep_space . command . Util.comment_or_eol ]

(* View: blacklist *)
let blacklist = Build.key_value_line_comment "blacklist" sep_space
                       sto_no_spaces
                       comment

(* View: config *)
let config = Build.key_value_line_comment "config" sep_space
                       (store /binary_indexes|yes|no/)
                       comment

(* View: entry *)
let entry = alias
          | options
          | kv_line_command /install|remove/
          | blacklist
          | config

(************************************************************************
 * Group:                 LENS AND FILTER
 *************************************************************************)

(* View: lns *)
let lns = (comment|empty|entry)*

(* View: filter *)
let filter = (incl "/etc/modprobe.conf") .
  (incl "/etc/modprobe.d/*").
  (incl "/etc/modprobe.conf.local").
  Util.stdexcl

let xfm = transform lns filter

(*
Module: Modprobe
  Parses /etc/modprobe.conf and /etc/modprobe.d/*
*)
(*
Module: Keepalived
  Parses /etc/modprobe.conf and /etc/modprobe.d/*

Original Author: David Lutterkort <lutter@redhat.com>

Author: Raphael Pinson <raphink@gmail.com>

About: Reference
  This lens tries to keep as close as possible to `man 5 modprobe.conf` where possible.

About: License
   This file is licenced under the LGPLv2+, like the rest of Augeas.

About: Lens Usage
   To be documented

About: Configuration files
   This lens applies to /etc/modprobe.conf and /etc/modprobe.d/*. See <filter>.
*)

module Modprobe =
autoload xfm

(************************************************************************
 * Group:                 USEFUL PRIMITIVES
 *************************************************************************)

(* View: comment *)
let comment = Util.comment

(* View: empty *)
let empty = Util.empty

(* View: sep_space *)
let sep_space = del /([ \t]|(\\\\\n))+/ " "

(* View: sto_no_spaces *)
let sto_no_spaces = store /[^# \t\n\\\\]+/

(* View: sto_to_eol *)
let sto_to_eol = store /[^# \t\n\\\\][^#\n\\\\]*[^# \t\n\\\\]|[^# \t\n\\\\]/

(* View: alias *)
let alias =
  let modulename = [ label "modulename" . sto_no_spaces ] in
  Build.key_value_line_comment "alias" sep_space
                       (sto_no_spaces . sep_space . modulename)
                       comment

(************************************************************************
 * Group:                 ENTRY TYPES
 *************************************************************************)

(* View: options *)
let options =
  let opt_value = /[^#" \t\n\\\\]+|"[^#"\n\\\\]*"/ in
  let option = [ key Rx.word . (Util.del_str "=" . store opt_value)? ] in
  [ key "options" . sep_space . sto_no_spaces
                  . (sep_space . option)* . Util.comment_or_eol ]

(* View: install_remove *)
let kv_line_command (kw:regexp) =
  let command = [ label "command" . sto_to_eol ] in
  [ key kw . sep_space . sto_no_spaces
                         . sep_space . command . Util.comment_or_eol ]

(* View: blacklist *)
let blacklist = Build.key_value_line_comment "blacklist" sep_space
                       sto_no_spaces
                       comment

(* View: config *)
let config = Build.key_value_line_comment "config" sep_space
                       (store /binary_indexes|yes|no/)
                       comment

(* View: entry *)
let entry = alias
          | options
          | kv_line_command /install|remove/
          | blacklist
          | config

(************************************************************************
 * Group:                 LENS AND FILTER
 *************************************************************************)

(* View: lns *)
let lns = (comment|empty|entry)*

(* View: filter *)
let filter = (incl "/etc/modprobe.conf") .
  (incl "/etc/modprobe.d/*").
  (incl "/etc/modprobe.conf.local").
  Util.stdexcl

let xfm = transform lns filter


Php: simplified and based on Inifile

Php: simplified and based on Inifile

"Slightly" simplify php.aug now that the comment issue is fixed in
inifile.aug

(* PHP module for Augeas                      *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(*                                            *)

module PHP =
  autoload xfm

(* PHP is a standard INI file *)

let entry  = IniFile.entry /[a-z][a-z0-9\._-]+/

let record = IniFile.record "section" entry
let lns    = IniFile.lns record

let filter = (incl "/etc/php*/*/php.ini")
             . Util.stdexcl

let xfm = transform lns filter

(* PHP module for Augeas                      *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(*                                            *)

module PHP =

    autoload xfm

    (* PHP is a standard INI file *)
    let setting = "always_populate_raw_post_data"
                | "asp_tags"
                | "browscap"
                | "child_terminate"
                | "define_syslog_variables"
                | "doc_root"
                | "enable_dl"
                | "engine"
                | "expose_php"
                | "extension_dir"
                | "file_uploads"
		| "gpc_order"
                | "html_errors"
                | "implicit_flush"
                | "include_path"
                | "last_modified"
                | "memory_limit"
                | "open_basedir"
                | "post_max_size"
                | "precision"
                | "serialize_precision"
                | "short_open_tag"
                | "SMTP"
                | "smtp_port"
                | "track_errors"
                | "unserialize_callback_func"
                | "variables_order"
                | "xbithack"
                | "y2k_compliance"
                | /apc\.(cache_by_default|enabled|filters|gc_ttl|mmap_file_mask|num_files_hint|optimization|shm_segments|shm_size|slam_defense|ttl|user_entries_hint|user_ttl)/
                | /apd\.(dumpdir|statement_tracing)/
                | /arg_separator\.(input|output)/
                | /assert\.(active|bail|callback|quiet_eval|warning)/
                | /bcmath\.(scale)/
                | /blenc\.(key_file)/
                | /com\.(allow_dcom|autoregister_casesensitive|autoregister_typelib|autoregister_verbose|code_page|typelib_file)/
                | /crack\.(default_dictionary)/
                | /daffodildb\.(default_host|default_password|default_socket|default_user|port)/
                | /date\.(default_latitude|default_longitude|sunrise_zenith|sunset_zenith)/
                | /dba\.(default_handler)/
                | /dbx\.(colnames_case)/
                | /exif\.(decode_jis_intel|decode_jis_motorola|decode_unicode_intel|decode_unicode_motorola|encode_jis|encode_unicode)/
                | /fbsql\.(allow_persistent|autocommit|batchsize|default_database|default_database_password|default_host|default_password|default_user|generate_warnings|max_connections|max_links|max_persistent|max_results)/
                | /highlight\.(bg|comment|default|html|keyword|string)/
                | /hyperwave\.(allow_persistent|default_port)/
                | /ibase\.(allow_persistent|dateformat|default_charset|default_db|default_password|default_user|max_links|max_persistent|timeformat|timestampformat)/
                | /iconv\.(input_encoding|internal_encoding|output_encoding)/
                | /ifx\.(allow_persistent|blobinfile|byteasvarchar|charasvarchar|default_host|default_password|default_user|max_links|max_persistent|nullformat|textasvarchar)/
                | /ingres\.(allow_persistent|default_database|default_password|default_user|max_links|max_persistent)/
                | /ircg\.(control_user|keep_alive_interval|max_format_message_sets|shared_mem_size|work_dir)/
                | /ldap\.(max_links)/
                | /mail\.(force_extra_parameters)/
                | /mailparse\.(def_charset)/
                | /maxdb\.(default_db|default_host|default_pw|default_user|long_readlen)/
                | /mbstring\.(detect_order|encoding_translation|func_overload|http_input|http_output|internal_encoding|language|script_encoding|substitute_character)/
                | /mcrypt\.(algorithms_dir|modes_dir)/
                | /mime_magic\.(debug|magicfile)/
                | /mssql\.(allow_persistent|batchsize|compatability_mode|connect_timeout|datetimeconvert|max_links|max_persistent|max_procs|min_error_severity|min_message_severity|secure_connection|textlimit|textsize|timeout)/
                | /msql\.(allow_persistent|max_links|max_persistent)/
                | /mysql\.(allow_persistent|connect_timeout|default_host|default_password|default_port|default_socket|default_user|max_links|max_persistent|trace_mode)/
                | /mysqli\.(default_host|default_port|default_pw|default_socket|default_user|max_links|reconnect)/
                | /namazu\.(debugmode|lang|loggingmode|sortmethod|sortorder)/
                | /nsapi\.(read_timeout)/
                | /odbc\.(allow_persistent|check_persistent|defaultbinmode|defaultlrl|default_db|default_pw|default_user|max_links|max_persistent)/
                | /opendirectory\.(max_refs|separator)/
                | /pdo\.(global_value)/
                | /pfpro\.(defaulthost|defaultport|defaulttimeout|proxyaddress|proxylogon|proxypassword|proxyport)/
                | /pgsql\.(allow_persistent|auto_reset_persistent|ignore_notice|log_notice|max_links|max_persistent)/
                | /printer\.(default_printer)/
                | /session\.(auto_start|bug_compat_42|bug_compat_warn|cache_expire|cache_limiter|cookie_(domain|httponly|lifetime|path|secure)|entropy_file|entropy_length|gc_divisor|gc_maxlifetime|gc_probability|hash_bits_per_character|hash_function|name|referer_check|save_handler|save_path|serialize_handler|use_cookies|use_only_cookies|use_trans_sid)/
                | /session_pgsql\.(create_table|db|disable|failover_mode|gc_interval|keep_expired|sem_file_name|serializable|short_circuit|use_app_vars|vacuum_interval)/
                | /simple_cvs\.(authMethod|compressionLevel|cvsRoot|host|moduleName|userName|workingDir)/
                | /soap\.(wsdl_cache_dir|wsdl_cache_enabled|wsdl_cache_ttl)/
                | /sql\.(safe_mode)/
                | /sqlite\.(assoc_case)/
		| /sybase\.(allow_persistent|max_(persistent|links)|interface_file|min_(error|message)_severity|compatability_mode)/
                | /sybct\.(allow_persistent|deadlock_retry_count|hostname|login_timeout|max_links|max_persistent|min_client_severity|min_server_severity)/
                | /tidy\.(clean_output|default_config)/
                | /url_rewriter\.(tags)/
                | /valkyrie\.(auto_validate|config_path)/
                | /xmms\.(path|session)/
                | /yaz\.(keepalive|log_file|max_links)/
                | /zend\.(ze1_compatibility_mode)/
                | /zlib\.(output_compression|output_compression_level|output_handler)/
                | /allow_(call_time_pass_reference|url_fopen|url_include)/
                | /auto_(append_file|detect_line_endings|globals_jit|prepend_file)/
                | /default_(charset|mimetype|socket_timeout)/
		| /display(_startup)?_errors/
                | /disable_(classes|functions)/
                | /docref_(ext|root)/
                | /error_(append_string|log|prepend_string|reporting)/
                | /ignore_(repeated_errors|repeated_source|user_abort)/
                | /log_errors(_max_len)?/
                | /magic_quotes_(gpc|runtime|sybase)/
                | /max_(execution_time|input_time)/
                | /output_(buffering|handler)/
                | /realpath_(cache_size|cache_ttl)/
                | /register_(argc_argv|globals|long_arrays)/
                | /report_(memleaks|zend_debug)/
                | /safe_mode(_(allowed_env_vars|exec_dir|gid|include_dir|protected_env_vars))?/
                | /sendmail_(from|path)/
                | /upload_(max_filesize|tmp_dir)/
                | /user_(agent|dir)/
                | /xmlrpc_error(s|_number)/

	let entry  = IniFile.entry setting

	let record = IniFile.record "section" entry
	let lns    = IniFile.lns record

	let filter = (incl "/etc/php*/*/php.ini")
	           . Util.stdexcl

	let xfm = transform lns filter


Update the lens to work with the logging format

(* Holland module for Augeas
 Author: Russell Harrison <rharrison@fedoraproject.org>

 holland.conf is almost a standard INI File.
*)

module Holland =
  autoload xfm

(************************************************************************
 * INI File settings
 *
 * holland.conf only supports "# as comment and "=" as separator
 * some values may be comma separated lists
 *************************************************************************)
let comment    = IniFile.comment "#" "#"
let sep        = IniFile.sep "=" "="
let comma      = del /[ \t]*,[ \t]*/ ", "

(************************************************************************
 *                        LISTS
 * Setup the comma seperated lists
 *************************************************************************)
let set_list  = Build.opt_list ([ label "set" . store Rx.word ]) comma
let path_list = Build.opt_list ([ label "path" . store Rx.neg1 ]) comma

(************************************************************************
 *                        ENTRY
 * holland.conf uses standard INI File entries and comma separated lists
 *************************************************************************)
let backupsets_entry =
  Build.key_value_line_comment "backupsets" sep ( Sep.opt_space
                                                . set_list
                                                ) comment
let plugindirs_entry =
  Build.key_value_line_comment "plugin_dirs" sep ( Sep.opt_space
                                                 . path_list
                                                 ) comment
let common_entry   = IniFile.indented_entry ( "backup_directory"
                                            | "umask"
                                            | "path"
                                            | "filename"
                                            | "level"
                                            | "format"
                                            ) sep comment

(************************************************************************
 *                        RECORD
 *************************************************************************)
let title   = IniFile.indented_title IniFile.record_re
let record  = IniFile.record title ( common_entry
                                   | backupsets_entry
                                   | plugindirs_entry
                                   )

(************************************************************************
 *                        LENS & FILTER
 *************************************************************************)
let lns    = IniFile.lns record comment
let filter = (incl "/etc/holland/holland.conf")
let xfm    = transform lns filter

(* Holland module for Augeas
 Author: Russell Harrison <rharrison@fedoraproject.org>

 holland.conf is almost a standard INI File.
*)

module Holland =
  autoload xfm

(************************************************************************
 * INI File settings
 *
 * holland.conf only supports "# as comment and "=" as separator
 * some values may be comma separated lists
 *************************************************************************)
let comment    = IniFile.comment "#" "#"
let sep        = IniFile.sep "=" "="
let comma      = del /[ \t]*,[ \t]*/ ", "

(************************************************************************
 *                        LISTS
 * Setup the comma seperated lists
 *************************************************************************)
let set_list  = Build.opt_list ([ label "set" . store Rx.word ]) comma
let path_list = Build.opt_list ([ label "path" . store Rx.neg1 ]) comma

(************************************************************************
 *                        ENTRY
 * holland.conf uses standard INI File entries and comma separated lists
 *************************************************************************)
let backupsets_entry =
  Build.key_value_line_comment "backupsets" sep ( Sep.opt_space
                                                . set_list
                                                ) comment
let plugindirs_entry =
  Build.key_value_line_comment "plugin_dirs" sep ( Sep.opt_space
                                                 . path_list
                                                 ) comment
let common_entry   = IniFile.indented_entry ( "backup_directory"
                                            | "umask"
                                            | "path"
                                            | "filename"
                                            | "level"
                                            ) sep comment

(************************************************************************
 *                        RECORD
 *************************************************************************)
let title   = IniFile.indented_title IniFile.record_re
let record  = IniFile.record title ( common_entry
                                   | backupsets_entry
                                   | plugindirs_entry
                                   )

(************************************************************************
 *                        LENS & FILTER
 *************************************************************************)
let lns    = IniFile.lns record comment
let filter = (incl "/etc/holland/holland.conf")
let xfm    = transform lns filter


Add email_addr to rx.aug

Add email_addr to rx.aug


Improve build.aug

Improve build.aug


Simplelines: parse OpenBSD's hostname.if(5) files

(*
Module: Simplelines
   Parses simple lines conffiles

Author: Raphael Pinson <raphink@gmail.com>

About: License
   This file is licenced under the LGPL v2+, like the rest of Augeas.

About: Lens Usage
   To be documented

About: Configuration files
   See <filter>.

About: Examples
   The <Test_Simplelines> file contains various examples and tests.
*)

module Simplelines =

autoload xfm

(* View: line
     A simple, uncommented, line *)
let line =
   let line_re = /[^# \t\n].*[^ \t\n]|[^# \t\n]/
   in [ seq "line" . Util.indent
      . store line_re . Util.eol ]

(* View: lns
     The simplelines lens *)
let lns = (Util.empty | Util.comment | line)*

(* Variable: filter *)
let filter = incl "/etc/at.allow"
           . incl "/etc/at.deny"
           . incl "/etc/cron.allow"
           . incl "/etc/cron.deny"
           . incl "/etc/cron.d/at.allow"
           . incl "/etc/cron.d/at.deny"
           . incl "/etc/cron.d/cron.allow"
           . incl "/etc/cron.d/cron.deny"
           . incl "/etc/default/grub_installdevice"
           . incl "/etc/pam.d/allow.pamlist"
           . incl "/etc/hostname.*"

let xfm = transform lns filter

(*
Module: Simplelines
   Parses simple lines conffiles

Author: Raphael Pinson <raphink@gmail.com>

About: License
   This file is licenced under the LGPL v2+, like the rest of Augeas.

About: Lens Usage
   To be documented

About: Configuration files
   See <filter>.

About: Examples
   The <Test_Simplelines> file contains various examples and tests.
*)

module Simplelines =

autoload xfm

(* View: line
     A simple, uncommented, line *)
let line =
   let line_re = /[^# \t\n].*[^ \t\n]|[^# \t\n]/
   in [ seq "line" . Util.indent
      . store line_re . Util.eol ]

(* View: lns
     The simplelines lens *)
let lns = (Util.empty | Util.comment | line)*

(* Variable: filter *)
let filter = incl "/etc/at.allow"
           . incl "/etc/at.deny"
           . incl "/etc/cron.allow"
           . incl "/etc/cron.deny"
           . incl "/etc/cron.d/at.allow"
           . incl "/etc/cron.d/at.deny"
           . incl "/etc/cron.d/cron.allow"
           . incl "/etc/cron.d/cron.deny"
           . incl "/etc/default/grub_installdevice"
           . incl "/etc/pam.d/allow.pamlist"

let xfm = transform lns filter


Fix typo in postfix_master.aug (Fix ticket 234)


Make aliases work

Make aliases work

# Parse mail aliases in /etc/aliases

map
  grammar aliases
  include '/etc/aliases' '/system/config/aliases'
end

grammar aliases
  token COMMENT /^[ \t]*(#.*?)?\n/ = '#\n'
  token COMMA /,[ \t]+(\n[ \t]+)?/ = ', '
  token NAME /([^ \t\n#:@]+|"[^"]*")/ = 'missing' # "
  token COLON /:[ \t]+/ = ': '
  token EOL /[ \t]*\n/ = '\n'

  file: (comment | alias)*

  comment: [ COMMENT ]

  alias: [ seq 'alias' .
           [ label 'name' . store NAME ] .
           COLON .
           counter 'values' .
           [ label 'values' .
             [ seq 'values' . store ... ] .
             ([COMMA . seq 'values' . store ...])*
           ]
         ] . EOL
end

# Parse mail aliases in /etc/aliases

#map
#  grammar aliases
#  include '/etc/aliases' '/system/config/aliases'
#end

grammar aliases
  token COMMENT /^[ \t]*(#.*?)?\n/ = '#\n'
  token COMMA /,[ \t]+(\n[ \t]+)?/ = ', '
  token NAME /([^ \t\n#:@]+|"[^"]*")/ = 'missing' # "
  token COLON /:[ \t]+/ = ':'
  token EOL /[ \t]*\n/ = '\n'

  file: (comment | alias)*

  comment: COMMENT

  alias: [ seq 'alias' .
           [ label 'name' . store NAME ] .
           COLON .
           counter 'values' .
           [ label 'values' .
             [ seq 'values' . store ... ] .
             ([COMMA . seq 'values' . store ...])*
           ]
         ] . EOL
end


Add some doc to pg_hba.aug

Add some doc to pg_hba.aug

(*
Module: Pg_Hba
  Parses PostgreSQL's pg_hba.conf

Author: Aurelien Bompard <aurelien@bompard.org>

About: Reference
  The file format is described in PostgreSQL's documentation:
  http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html

About: License
  This file is licensed under the GPL.

About: Configuration files
  This lens applies to pg_hba.conf. See <filter> for exact locations.
*)

module Pg_Hba =
    autoload xfm

    (* Group: Generic primitives *)

    let eol     = Util.eol
    let word    = Rx.neg1
    (* Variable: ipaddr
       CIDR or ip+netmask *)
    let ipaddr   = /[0-9a-fA-F:\.]+(\/[0-9]+|[ \t]+[0-9\.]+)/

    let comma_sep_list (l:string) =
        let lns = [ label l . store word ] in
            Build.opt_list lns Sep.comma

    (* Group: Columns definitions *)

    (* View: database
       TODO: support for quoted strings *)
    let database = comma_sep_list "database"
    (* View: user
       TODO: support for quoted strings *)
    let user = comma_sep_list "user"
    (* View: address *)
    let address = [ label "address" . store ipaddr ]
    (* View: option
       part of <method> *)
    let option = [ label "option" . store word ]
    (* View: method
       can contain an <option> *)
    let method = [ label "method" . store Rx.word . ( Sep.tab . option )? ]

    (* Group: Records definitions *)

    (* View: record_local
       when type is "local", there is no "address" field *)
    let record_local = [ label "type" . store "local" ] . Sep.tab .
                       database . Sep.tab . user . Sep.tab . method

    (* Variable: remtypes
       non-local connection types *)
    let remtypes = "host" | "hostssl" | "hostnossl"

    (* View: record_remote *)
    let record_remote = [ label "type" . store remtypes ] . Sep.tab .
                        database . Sep.tab .  user . Sep.tab .
                        address . Sep.tab . method

    (* View: record
        A sequence of <record_local> or <record_remote> entries *)
    let record = [ seq "entries" . (record_local | record_remote) . eol ]

    (* View: filter
        The pg_hba.conf conf file *)
    let filter = (incl "/var/lib/pgsql/data/pg_hba.conf" .
                  incl "/etc/postgresql/*/*/pg_hba.conf" )

    (* View: lns
        The pg_hba.conf lens *)
    let lns = ( record | Util.comment | Util.empty ) *

    let xfm = transform lns filter

(*
Module: Pg_Hba
  Parses PostgreSQL's pg_hba.conf

Author: Aurelien Bompard <aurelien@bompard.org>

About: Reference
  The file format is described in PostgreSQL's documentation:
  http://www.postgresql.org/docs/current/static/auth-pg-hba-conf.html

About: License
  This file is licensed under the GPL.

About: Configuration files
  This lens applies to pg_hba.conf. See <filter> for exact locations.
*)

module Pg_Hba =
    autoload xfm

    (* Group: Generic primitives *)

    let eol     = Util.eol
    let word    = Rx.neg1
    (* Variable: ipaddr
       CIDR or ip+netmask *)
    let ipaddr   = /[0-9a-fA-F:\.]+(\/[0-9]+|[ \t]+[0-9\.]+)/

    let comma_sep_list (l:string) =
        let lns = [ label l . store word ] in
            Build.opt_list lns Sep.comma

    (* Group: Columns definitions *)

    (* View: database
       TODO: support for quoted strings *)
    let database = comma_sep_list "database"
    (* View: user
       TODO: support for quoted strings *)
    let user = comma_sep_list "user"
    (* View: address *)
    let address = [ label "address" . store ipaddr ]
    (* View: option
       part of <method> *)
    let option = [ label "option" . store word ]
    (* View: method
       can contain an <option> *)
    let method = [ label "method" . store Rx.word . ( Sep.tab . option )? ]

    (* Group: Records definitions *)

    (* View: record_local
       when type is "local", there is no "address" field *)
    let record_local = [ label "type" . store "local" ] . Sep.tab .
                       database . Sep.tab . user . Sep.tab . method

    (* Variable: remtypes
       non-local connection types *)
    let remtypes = "host" | "hostssl" | "hostnossl"
    (* View: record_remote *)
    let record_remote = [ label "type" . store remtypes ] . Sep.tab .
                        database . Sep.tab .  user . Sep.tab .
                        address . Sep.tab . method

    let record = [ seq "entries" . (record_local | record_remote) . eol ]

    let filter = (incl "/var/lib/pgsql/data/pg_hba.conf" .
                  incl "/etc/postgresql/*/*/pg_hba.conf" )

    let lns = ( record | Util.comment | Util.empty ) *

    let xfm = transform lns filter


Add hourly schedule to logrotate lens. (#655)

Hourly is a valid logrotate schedule value.

(* Logrotate module for Augeas                *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(* Patches from:                              *)
(*   Sean Millichamp <sean@bruenor.org>       *)
(*                                            *)
(* Supported :                                *)
(*   - defaults                               *)
(*   - rules                                  *)
(*   - (pre|post)rotate entries               *)
(*                                            *)
(* Todo :                                     *)
(*                                            *)

module Logrotate =
   autoload xfm

   let sep_spc = Sep.space
   let sep_val = del /[ \t]*=[ \t]*|[ \t]+/ " "
   let eol = Util.eol
   let num = Rx.relinteger
   let word = /[^,#= \n\t{}]+/
   let filename = Quote.do_quote_opt (store /\/[^"',#= \n\t{}]+/)
   let size = num . /[kMG]?/

   let indent = del Rx.opt_space "\t"

   (* define omments and empty lines *)
   let comment = Util.comment
   let empty   = Util.empty

   (* Useful functions *)

   let list_item = [ sep_spc . key /[^\/+,# \n\t{}]+/ ]
   let select_to_eol (kw:string) (select:regexp) = [ label kw . store select ]
   let value_to_eol (kw:string) (value:regexp)  = Build.key_value kw sep_val (store value)
   let flag_to_eol (kw:string) = Build.flag kw
   let list_to_eol (kw:string) = [ key kw . list_item+ ]

   (* Defaults *)

   let create =
     let mode = sep_spc . [ label "mode" . store num ] in
     let owner = sep_spc . [ label "owner" . store word ] in
     let group = sep_spc . [ label "group" . store word ] in
     [ key "create" .
         ( mode | mode . owner | mode . owner . group )? ]

   let su =
     let owner = sep_spc . [ label "owner" . store word ] in
     let group = sep_spc . [ label "group" . store word ] in
     [ key "su" .
         ( owner | owner . group )? ]

   let tabooext = [ key "tabooext" . ( sep_spc . store /\+/ )? . list_item+ ]

   let attrs = select_to_eol "schedule" /(hourly|daily|weekly|monthly|yearly)/
                | value_to_eol "rotate" num
        | create
        | flag_to_eol "nocreate"
        | su
        | value_to_eol "include" word
        | select_to_eol "missingok" /(no)?missingok/
        | select_to_eol "compress" /(no)?compress/
        | select_to_eol "delaycompress" /(no)?delaycompress/
        | select_to_eol "ifempty" /(not)?ifempty/
        | select_to_eol "sharedscripts" /(no)?sharedscripts/
        | value_to_eol "size" size
        | tabooext
        | value_to_eol "olddir" word
        | flag_to_eol "noolddir"
        | value_to_eol "mail" word
        | flag_to_eol "mailfirst"
        | flag_to_eol "maillast"
        | flag_to_eol "nomail"
        | value_to_eol "errors" word
        | value_to_eol "extension" word
        | select_to_eol "dateext" /(no)?dateext/
        | value_to_eol "dateformat" word
        | flag_to_eol "dateyesterday"
        | value_to_eol "compresscmd" word
        | value_to_eol "uncompresscmd" word
        | value_to_eol "compressext" word
        | list_to_eol "compressoptions"
        | select_to_eol "copy" /(no)?copy/
        | select_to_eol "copytruncate" /(no)?copytruncate/
        | value_to_eol "maxage" num
        | value_to_eol "minsize" size
        | value_to_eol "maxsize" size
        | select_to_eol "shred" /(no)?shred/
        | value_to_eol "shredcycles" num
        | value_to_eol "start" num

   (* Define hooks *)

   let hook_lines =
     let line_re = /.*/ - /[ \t]*endscript[ \t]*/ in
       store ( line_re . ("\n" . line_re)* )? . Util.del_str "\n"

   let hooks =
     let hook_names = /(pre|post)rotate|(first|last)action/ in
     [ key hook_names . eol .
       hook_lines? .
       del /[ \t]*endscript/ "\tendscript" ]

   (* Define rule *)

   let body = Build.block_newlines
                 (indent . (attrs | hooks) . eol)
                 Util.comment

   let rule =
     let filename_entry = [ label "file" . filename ] in
     let filename_sep = del /[ \t\n]+/ " " in
     let filenames = Build.opt_list filename_entry filename_sep in
     [ label "rule" . Util.indent . filenames . body . eol ]

   let lns = ( comment | empty | (attrs . eol) | rule )*

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

   let xfm = transform lns filter

(* Logrotate module for Augeas                *)
(* Author: Raphael Pinson <raphink@gmail.com> *)
(* Patches from:                              *)
(*   Sean Millichamp <sean@bruenor.org>       *)
(*                                            *)
(* Supported :                                *)
(*   - defaults                               *)
(*   - rules                                  *)
(*   - (pre|post)rotate entries               *)
(*                                            *)
(* Todo :                                     *)
(*                                            *)

module Logrotate =
   autoload xfm

   let sep_spc = Sep.space
   let sep_val = del /[ \t]*=[ \t]*|[ \t]+/ " "
   let eol = Util.eol
   let num = Rx.relinteger
   let word = /[^,#= \n\t{}]+/
   let filename = Quote.do_quote_opt (store /\/[^"',#= \n\t{}]+/)
   let size = num . /[kMG]?/

   let indent = del Rx.opt_space "\t"

   (* define omments and empty lines *)
   let comment = Util.comment
   let empty   = Util.empty

   (* Useful functions *)

   let list_item = [ sep_spc . key /[^\/+,# \n\t{}]+/ ]
   let select_to_eol (kw:string) (select:regexp) = [ label kw . store select ]
   let value_to_eol (kw:string) (value:regexp)  = Build.key_value kw sep_val (store value)
   let flag_to_eol (kw:string) = Build.flag kw
   let list_to_eol (kw:string) = [ key kw . list_item+ ]

   (* Defaults *)

   let create =
     let mode = sep_spc . [ label "mode" . store num ] in
     let owner = sep_spc . [ label "owner" . store word ] in
     let group = sep_spc . [ label "group" . store word ] in
     [ key "create" .
         ( mode | mode . owner | mode . owner . group )? ]

   let su =
     let owner = sep_spc . [ label "owner" . store word ] in
     let group = sep_spc . [ label "group" . store word ] in
     [ key "su" .
         ( owner | owner . group )? ]

   let tabooext = [ key "tabooext" . ( sep_spc . store /\+/ )? . list_item+ ]

   let attrs = select_to_eol "schedule" /(daily|weekly|monthly|yearly)/
                | value_to_eol "rotate" num
        | create
        | flag_to_eol "nocreate"
        | su
        | value_to_eol "include" word
        | select_to_eol "missingok" /(no)?missingok/
        | select_to_eol "compress" /(no)?compress/
        | select_to_eol "delaycompress" /(no)?delaycompress/
        | select_to_eol "ifempty" /(not)?ifempty/
        | select_to_eol "sharedscripts" /(no)?sharedscripts/
        | value_to_eol "size" size
        | tabooext
        | value_to_eol "olddir" word
        | flag_to_eol "noolddir"
        | value_to_eol "mail" word
        | flag_to_eol "mailfirst"
        | flag_to_eol "maillast"
        | flag_to_eol "nomail"
        | value_to_eol "errors" word
        | value_to_eol "extension" word
        | select_to_eol "dateext" /(no)?dateext/
        | value_to_eol "dateformat" word
        | flag_to_eol "dateyesterday"
        | value_to_eol "compresscmd" word
        | value_to_eol "uncompresscmd" word
        | value_to_eol "compressext" word
        | list_to_eol "compressoptions"
        | select_to_eol "copy" /(no)?copy/
        | select_to_eol "copytruncate" /(no)?copytruncate/
        | value_to_eol "maxage" num
        | value_to_eol "minsize" size
        | value_to_eol "maxsize" size
        | select_to_eol "shred" /(no)?shred/
        | value_to_eol "shredcycles" num
        | value_to_eol "start" num

   (* Define hooks *)

   let hook_lines =
     let line_re = /.*/ - /[ \t]*endscript[ \t]*/ in
       store ( line_re . ("\n" . line_re)* )? . Util.del_str "\n"

   let hooks =
     let hook_names = /(pre|post)rotate|(first|last)action/ in
     [ key hook_names . eol .
       hook_lines? .
       del /[ \t]*endscript/ "\tendscript" ]

   (* Define rule *)

   let body = Build.block_newlines
                 (indent . (attrs | hooks) . eol)
                 Util.comment

   let rule =
     let filename_entry = [ label "file" . filename ] in
     let filename_sep = del /[ \t\n]+/ " " in
     let filenames = Build.opt_list filename_entry filename_sep in
     [ label "rule" . Util.indent . filenames . body . eol ]

   let lns = ( comment | empty | (attrs . eol) | rule )*

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

   let xfm = transform lns filter


Add flag_line to build.aug

Add flag_line to build.aug


Cleanup unused code in lens

Cleanup unused code in lens

(*
Module: Trapperkeeper
  Parses Trapperkeeper configuration files

Author: Raphael Pinson <raphael.pinson@camptocamp.com>

About: License
   This file is licenced under the LGPL v2+, like the rest of Augeas.

About: Lens Usage
   To be documented

About: Configuration files
   This lens applies to Trapperkeeper webservice configuration files. See <filter>.

About: Examples
   The <Test_Trapperkeeper> file contains various examples and tests.
*)
module Trapperkeeper =

autoload xfm

(************************************************************************
 * Group:                 USEFUL PRIMITIVES
 *************************************************************************)

(* View: empty *)
let empty = Util.empty

(* View: comment *)
let comment = Util.comment

(* View: sep *)
let sep = del /[ \t]*[:=]/ ":"

(* View: sep_with_spc *)
let sep_with_spc = sep . Sep.opt_space

(************************************************************************
 * Group:       BLOCKS (FROM 1.2, FOR 0.10 COMPATIBILITY)
 *************************************************************************)

(* Variable: block_ldelim_newlines_re *)
let block_ldelim_newlines_re = /[ \t\n]+\{([ \t\n]*\n)?/

(* Variable: block_rdelim_newlines_re *)
let block_rdelim_newlines_re = /[ \t]*\}/

(* Variable: block_ldelim_newlines_default *)
let block_ldelim_newlines_default = "\n{\n"

(* Variable: block_rdelim_newlines_default *)
let block_rdelim_newlines_default = "}"

(************************************************************************
 * View: block_newline
 *   A block enclosed in brackets, with newlines forced
 *   and indentation defaulting to a tab.
 *
 *   Parameters:
 *     entry:lens - the entry to be stored inside the block.
 *                  This entry should not include <Util.empty>,
 *                  <Util.comment> or <Util.comment_noindent>,
 *                  should be indented and finish with an eol.
 ************************************************************************)
let block_newlines (entry:lens) (comment:lens) =
   del block_ldelim_newlines_re block_ldelim_newlines_default
 . ((entry | comment) . (Util.empty | entry | comment)*)?
 . del block_rdelim_newlines_re block_rdelim_newlines_default

(************************************************************************
 * Group:                 ENTRY TYPES
 *************************************************************************)

let opt_dquot (lns:lens) = del /"?/ "" . lns . del /"?/ ""

(* View: simple *)
let simple = [ Util.indent . label "@simple" . opt_dquot (store /[A-Za-z0-9_.\/-]+/) . sep_with_spc
             . [ label "@value" . opt_dquot (store /[^,"\[ \t\n]+/) ]
             . Util.eol ]

(* View: array *)
let array =
     let lbrack = Util.del_str "["
  in let rbrack = Util.del_str "]"
  in let opt_space = del /[ \t]*/ ""
  in let comma = opt_space . Util.del_str "," . opt_space
  in let elem = [ seq "elem" . opt_dquot (store /[^,"\[ \t\n]+/) ]
  in let elems = counter "elem" . Build.opt_list elem comma
  in [ Util.indent . label "@array" . store Rx.word
     . sep_with_spc . lbrack . Sep.opt_space
     . (elems . Sep.opt_space)?
     . rbrack . Util.eol ]

(* View: hash *)
let hash (lns:lens) = [ Util.indent . label "@hash" . store Rx.word . sep
               . block_newlines lns Util.comment
               . Util.eol ]

(************************************************************************
 * Group:                   ENTRY
 *************************************************************************)

(* Just for typechecking *)
let entry_no_rec = hash (simple|array)

(* View: entry *)
let rec entry = hash (entry|simple|array)

(************************************************************************
 * Group:                LENS AND FILTER
 *************************************************************************)

(* View: lns *)
let lns = (empty|comment)* . (entry . (empty|comment)*)*

(* Variable: filter *)
let filter = incl "/etc/puppetserver/conf.d/*"
           . incl "/etc/puppetlabs/puppetserver/conf.d/*"
           . Util.stdexcl

let xfm = transform lns filter

(*
Module: Trapperkeeper
  Parses Trapperkeeper configuration files

Author: Raphael Pinson <raphael.pinson@camptocamp.com>

About: License
   This file is licenced under the LGPL v2+, like the rest of Augeas.

About: Lens Usage
   To be documented

About: Configuration files
   This lens applies to Trapperkeeper webservice configuration files. See <filter>.

About: Examples
   The <Test_Trapperkeeper> file contains various examples and tests.
*)
module Trapperkeeper =

autoload xfm

(************************************************************************
 * Group:                 USEFUL PRIMITIVES
 *************************************************************************)

(* View: empty *)
let empty = Util.empty

(* View: comment *)
let comment = Util.comment

(* View: sep *)
let sep = del /[ \t]*[:=]/ ":"

(* View: sep_with_spc *)
let sep_with_spc = sep . Sep.opt_space

(************************************************************************
 * Group:       BLOCKS (FROM 1.2, FOR 0.10 COMPATIBILITY)
 *************************************************************************)

(* Variable: block_ldelim_newlines_re *)
let block_ldelim_newlines_re = /[ \t\n]+\{([ \t\n]*\n)?/

(* Variable: block_rdelim_newlines_re *)
let block_rdelim_newlines_re = /[ \t]*\}/

(* Variable: block_ldelim_newlines_default *)
let block_ldelim_newlines_default = "\n{\n"

(* Variable: block_rdelim_newlines_default *)
let block_rdelim_newlines_default = "}"

(************************************************************************
 * View: block_newline
 *   A block enclosed in brackets, with newlines forced
 *   and indentation defaulting to a tab.
 *
 *   Parameters:
 *     entry:lens - the entry to be stored inside the block.
 *                  This entry should not include <Util.empty>,
 *                  <Util.comment> or <Util.comment_noindent>,
 *                  should be indented and finish with an eol.
 ************************************************************************)
let block_newlines (entry:lens) (comment:lens) =
      let indent = del /[ \t]*/ "\t"
   in del block_ldelim_newlines_re block_ldelim_newlines_default
 . ((entry | comment) . (Util.empty | entry | comment)*)?
 . del block_rdelim_newlines_re block_rdelim_newlines_default

(************************************************************************
 * Group:                 ENTRY TYPES
 *************************************************************************)

let opt_dquot (lns:lens) = del /"?/ "" . lns . del /"?/ ""

(* View: simple *)
let simple = [ Util.indent . label "@simple" . opt_dquot (store /[A-Za-z0-9_.\/-]+/) . sep_with_spc
             . [ label "@value" . opt_dquot (store /[^,"\[ \t\n]+/) ]
             . Util.eol ]

(* View: array *)
let array =
     let lbrack = Util.del_str "["
  in let rbrack = Util.del_str "]"
  in let opt_space = del /[ \t]*/ ""
  in let comma = opt_space . Util.del_str "," . opt_space
  in let elem = [ seq "elem" . opt_dquot (store /[^,"\[ \t\n]+/) ]
  in let elems = counter "elem" . Build.opt_list elem comma
  in [ Util.indent . label "@array" . store Rx.word
     . sep_with_spc . lbrack . Sep.opt_space
     . (elems . Sep.opt_space)?
     . rbrack . Util.eol ]

(* View: hash *)
let hash (lns:lens) = [ Util.indent . label "@hash" . store Rx.word . sep
               . block_newlines lns Util.comment
               . Util.eol ]

(************************************************************************
 * Group:                   ENTRY
 *************************************************************************)

(* Just for typechecking *)
let entry_no_rec = hash (simple|array)

(* View: entry *)
let rec entry = hash (entry|simple|array)

(************************************************************************
 * Group:                LENS AND FILTER
 *************************************************************************)

(* View: lns *)
let lns = (empty|comment)* . (entry . (empty|comment)*)*

(* Variable: filter *)
let filter = incl "/etc/puppetserver/conf.d/*"
           . incl "/etc/puppetlabs/puppetserver/conf.d/*"
           . Util.stdexcl

let xfm = transform lns filter