1(* Intefraces module for Augeas 2 Author: Free Ekanayaka <free@64studio.com> 3 4 Reference: man dhclient.conf 5 The only difference with the reference syntax is that this lens assumes 6 that statements end with a new line, while the reference syntax allows 7 new statements to be started right after the trailing ";" of the 8 previous statement. This should not be a problem in real-life 9 configuration files as statements get usually split across several 10 lines, rather than merged in a single one. 11 12*) 13 14module Dhclient = 15 16 autoload xfm 17 18(************************************************************************ 19 * USEFUL PRIMITIVES 20 *************************************************************************) 21 22let eol = Util.eol 23let comment = Util.comment 24let comment_or_eol = Util.comment_or_eol 25let empty = Util.empty 26 27(* Define separators *) 28let sep_spc = del /[ \t\n]+/ " " 29let sep_scl = del /[ \t]*;/ ";" 30let sep_obr = del /[ \t\n]*\{\n]*/ " {\n" 31let sep_cbr = del /[ \t\n]*\}/ " }" 32let sep_com = del /[ \t\n]*,[ \t\n]*/ "," 33let sep_slh = del "\/" "/" 34let sep_col = del ":" ":" 35let sep_eq = del /[ \t]*=[ \t]*/ "=" 36 37(* Define basic types *) 38let word = /[A-Za-z0-9_.-]+(\[[0-9]+\])?/ 39 40(* Define fields *) 41 42(* TODO: there could be a " " in the middle of a value ... *) 43let sto_to_spc = store /[^\\#,;{}" \t\n]+|"[^\\#"\n]+"/ 44let sto_to_spc_noeval = store /[^=\\#,;{}" \t\n]|[^=\\#,;{}" \t\n][^\\#,;{}" \t\n]*|"[^\\#"\n]+"/ 45let sto_to_scl = store /[^ \t\n][^;\n]+[^ \t]|[^ \t;\n]+/ 46let rfc_code = [ key "code" . sep_spc . store word ] 47 . sep_eq 48 . [ label "value" . sto_to_scl ] 49let eval = [ label "#eval" . Sep.equal . sep_spc . sto_to_scl ] 50let sto_number = store /[0-9][0-9]*/ 51 52(************************************************************************ 53 * SIMPLE STATEMENTS 54 *************************************************************************) 55 56let stmt_simple_re = "timeout" 57 | "retry" 58 | "select-timeout" 59 | "reboot" 60 | "backoff-cutoff" 61 | "initial-interval" 62 | "do-forward-updates" 63 | "reject" 64 65let stmt_simple = [ key stmt_simple_re 66 . sep_spc 67 . sto_to_spc 68 . sep_scl 69 . comment_or_eol ] 70 71 72(************************************************************************ 73 * ARRAY STATEMENTS 74 *************************************************************************) 75 76(* TODO: the array could also be empty, like in the request statement *) 77let stmt_array_re = "media" 78 | "request" 79 | "require" 80 81let stmt_array = [ key stmt_array_re 82 . sep_spc 83 . counter "stmt_array" 84 . [ seq "stmt_array" . sto_to_spc ] 85 . [ sep_com . seq "stmt_array" . sto_to_spc ]* 86 . sep_scl . comment_or_eol ] 87 88(************************************************************************ 89 * HASH STATEMENTS 90 *************************************************************************) 91 92 93let stmt_hash_re = "send" 94 | "option" 95 96let stmt_args = ( [ key word . sep_spc . sto_to_spc_noeval ] 97 | [ key word . sep_spc . (rfc_code|eval) ] ) 98 . sep_scl 99 . comment_or_eol 100 101let stmt_hash = [ key stmt_hash_re 102 . sep_spc 103 . stmt_args ] 104 105let stmt_opt_mod_re = "append" 106 | "prepend" 107 | "default" 108 | "supersede" 109 110let stmt_opt_mod = [ key stmt_opt_mod_re 111 . sep_spc 112 . stmt_args ] 113 114(************************************************************************ 115 * BLOCK STATEMENTS 116 *************************************************************************) 117 118let stmt_block_re = "interface" 119 | "lease" 120 | "alias" 121 122let stmt_block_opt_re = "interface" 123 | "script" 124 | "bootp" 125 | "fixed-address" 126 | "filename" 127 | "server-name" 128 | "medium" 129 | "vendor option space" 130 131(* TODO: some options could take no argument like bootp *) 132let stmt_block_opt = [ key stmt_block_opt_re 133 . sep_spc 134 . sto_to_spc 135 . sep_scl 136 . comment_or_eol ] 137 138let stmt_block_date_re 139 = "renew" 140 | "rebind" 141 | "expire" 142 143let stmt_block_date = [ key stmt_block_date_re 144 . [ sep_spc . label "weekday" . sto_number ] 145 . [ sep_spc . label "year" . sto_number ] 146 . [ sep_slh . label "month" . sto_number ] 147 . [ sep_slh . label "day" . sto_number ] 148 . [ sep_spc . label "hour" . sto_number ] 149 . [ sep_col . label "minute" . sto_number ] 150 . [ sep_col . label "second" . sto_number ] 151 . sep_scl 152 . comment_or_eol ] 153 154let stmt_block_arg = sep_spc . sto_to_spc 155 156let stmt_block_entry = sep_spc 157 . ( stmt_array 158 | stmt_hash 159 | stmt_opt_mod 160 | stmt_block_opt 161 | stmt_block_date ) 162 163let stmt_block = [ key stmt_block_re 164 . stmt_block_arg? 165 . sep_obr 166 . stmt_block_entry+ 167 . sep_cbr 168 . comment_or_eol ] 169 170(************************************************************************ 171 * LENS & FILTER 172 *************************************************************************) 173 174let statement = (stmt_simple|stmt_opt_mod|stmt_array|stmt_hash|stmt_block) 175 176let lns = ( empty 177 | comment 178 | statement )* 179 180let filter = incl "/etc/dhcp3/dhclient.conf" 181 . incl "/etc/dhcp/dhclient.conf" 182 . incl "/etc/dhclient.conf" 183 184let xfm = transform lns filter 185