3 Generic lens for shell-script config files like the ones found
7 This file is licenced under the LGPL v2+, like the rest of Augeas.
16 let empty = Util.empty
17 let empty_part_re = Util.empty_generic_re . /\n+/
18 let eol = del (/[ \t]+|[ \t]*[;\n]/ . empty_part_re*) "\n"
19 let semicol_eol = del (/[ \t]*[;\n]/ . empty_part_re*) "\n"
21 let key_re = /[A-Za-z0-9_]+(\[[0-9]+\])?/ - ("unset" | "export")
22 let matching_re = "${!" . key_re . /[\*@]\}/
23 let eq = Util.del_str "="
25 let eol_for_comment = del /([ \t]*\n)([ \t]*(#[ \t]*)?\n)*/ "\n"
26 let comment = Util.comment_generic_seteol /[ \t]*#[ \t]*/ " # " eol_for_comment
27 (* comment_eol in shell MUST begin with a space *)
28 let comment_eol = Util.comment_generic_seteol /[ \t]+#[ \t]*/ " # " eol_for_comment
29 let comment_or_eol = comment_eol | semicol_eol
31 let xchgs = Build.xchgs
32 let semicol = del /;?/ ""
34 let char = /[^`;() '"\t\n]|\\\\"/
36 let char = /[^"\\]|\\\\./ | Rx.cl
37 in "\"" . char* . "\"" (* " Emacs, relax *)
39 let bquot = /`[^`\n]*`/
40 (* dbquot don't take spaces or semi-colons *)
41 let dbquot = /``[^` \t\n;]+``/
42 let dollar_assign = /\$\([^\(\)#\n]*\)/
43 let dollar_arithm = /\$\(\([^\)#\n]*\)\)/
45 let anyquot = (dquot|squot)+ | bquot | dbquot | dollar_assign | dollar_arithm
47 let to_semicol_re = /[^#; \t\n][^#;\n]+[^#; \t\n]|[^#; \t\n]+/
48 let sto_to_semicol = store to_semicol_re
50 let sto_to_semicol_quot =
51 let no_semicol_re = /[^"'#;\n]/
52 in let no_semicol_spc_re = /[^"'#; \t\n]/
53 in let multi_chars = no_semicol_spc_re . (no_semicol_re|anyquot)+ . no_semicol_spc_re
54 in store (no_semicol_spc_re | multi_chars)
56 (* Array values of the form '(val1 val2 val3)'. We do not handle empty *)
57 (* arrays here because of typechecking headaches. Instead, they are *)
58 (* treated as a simple value *)
60 let array_value = store (char+ | anyquot) in
61 del /\([ \t]*/ "(" . counter "values" .
62 [ seq "values" . array_value ] .
63 [ del /[ \t\n]+/ " " . seq "values" . array_value ] *
66 (* Treat an empty list () as a value '()'; that's not quite correct *)
67 (* but fairly close. *)
69 let empty_array = /\([ \t]*\)/ in
70 store (char* | anyquot | empty_array)
72 let export = [ key "export" . Util.del_ws_spc ]
73 let kv = Util.indent . export? . key key_re
74 . eq . (simple_value | array)
76 let var_action (name:string) =
77 Util.indent . del name name . Util.del_ws_spc
78 . label ("@" . name) . counter "var_action"
79 . Build.opt_list [ seq "var_action" . store (key_re | matching_re) ] Util.del_ws_spc
81 let unset = var_action "unset"
82 let bare_export = var_action "export"
86 . del /\.|source/ "." . label ".source"
87 . Util.del_ws_spc . store /[^;=# \t\n]+/
89 let shell_builtin_cmds = "ulimit" | "shift" | "exit"
92 Util.indent . label "@builtin"
93 . store shell_builtin_cmds
95 . [ label "args" . sto_to_semicol ])?
97 let keyword (kw:string) = Util.indent . Util.del_str kw
98 let keyword_label (kw:string) (lbl:string) = keyword kw . label lbl
101 Util.indent . label "@return"
102 . Util.del_str "return"
103 . ( Util.del_ws_spc . store Rx.integer )?
106 (************************************************************************
107 * Group: CONDITIONALS AND LOOPS
108 *************************************************************************)
110 let generic_cond_start (start_kw:string) (lbl:string)
111 (then_kw:string) (contents:lens) =
112 keyword_label start_kw lbl . Sep.space
113 . sto_to_semicol_quot . semicol_eol
114 . keyword then_kw . eol
117 let generic_cond (start_kw:string) (lbl:string)
118 (then_kw:string) (contents:lens) (end_kw:string) =
119 [ generic_cond_start start_kw lbl then_kw contents
120 . keyword end_kw . comment_or_eol ]
122 let cond_if (entry:lens) =
123 let elif = [ generic_cond_start "elif" "@elif" "then" entry+ ] in
124 let else = [ keyword_label "else" "@else" . eol . entry+ ] in
125 generic_cond "if" "@if" "then" (entry+ . elif* . else?) "fi"
127 let loop_for (entry:lens) =
128 generic_cond "for" "@for" "do" entry+ "done"
130 let loop_while (entry:lens) =
131 generic_cond "while" "@while" "do" entry+ "done"
133 let loop_until (entry:lens) =
134 generic_cond "until" "@until" "do" entry+ "done"
136 let loop_select (entry:lens) =
137 generic_cond "select" "@select" "do" entry+ "done"
139 let case (entry:lens) (entry_noeol:lens) =
140 let case_entry = [ label "@case_entry"
141 . Util.indent . store /[^ \t\n\)]+/
142 . Util.del_str ")" . eol
143 . ( entry+ | entry_noeol )?
144 . Util.indent . Util.del_str ";;" . eol ] in
145 [ keyword_label "case" "@case" . Sep.space
146 . store (char+ | ("\"" . char+ . "\""))
147 . del /[ \t\n]+/ " " . Util.del_str "in" . eol
148 . (empty* . comment* . case_entry)*
150 . keyword "esac" . comment_or_eol ]
152 let function (entry:lens) =
153 [ Util.indent . label "@function"
154 . del /(function[ \t]+)?/ ""
155 . store Rx.word . del /[ \t]*\(\)/ "()"
156 . eol . Util.del_str "{" . eol
158 . Util.indent . Util.del_str "}" . eol ]
161 let entry_eol_item (item:lens) =
162 [ item . comment_or_eol ] in
163 entry_eol_item source
165 | entry_eol_item unset
166 | entry_eol_item bare_export
167 | entry_eol_item builtin
168 | entry_eol_item return
171 let entry_item (item:lens) = [ item ] in
175 | entry_item bare_export
180 let entry = comment | entry_eol | rec_entry in
186 | case entry entry_noeol
189 let lns_norec = empty* . (comment | entry_eol) *
191 let lns = empty* . (comment | entry_eol | rec_entry) *
193 let sc_incl (n:string) = (incl ("/etc/sysconfig/" . n))
194 let sc_excl (n:string) = (excl ("/etc/sysconfig/" . n))
196 let filter_sysconfig =
198 sc_excl "bootloader" .
201 sc_excl "ip*tables" .
202 sc_excl "ip*tables.save" .
205 sc_excl "sysstat.ioconf" .
206 sc_excl "system-config-firewall" .
207 sc_excl "system-config-securitylevel" .
208 sc_incl "network/config" .
209 sc_incl "network/dhcp" .
210 sc_incl "network/dhcp6r" .
211 sc_incl "network/dhcp6s" .
212 sc_incl "network/ifcfg-*" .
213 sc_incl "network/if-down.d/*" .
214 sc_incl "network/ifroute-*" .
215 sc_incl "network/if-up.d/*" .
216 sc_incl "network/providers/*" .
217 sc_excl "network-scripts" .
218 sc_incl "network-scripts/ifcfg-*" .
220 sc_incl "rhn/allowed-actions/*" .
221 sc_excl "rhn/allowed-actions/script" .
222 sc_incl "rhn/allowed-actions/script/*" .
223 sc_incl "rhn/rhnsd" .
224 sc_excl "SuSEfirewall2.d" .
225 sc_incl "SuSEfirewall2.d/cobbler" .
226 sc_incl "SuSEfirewall2.d/services/*" .
227 sc_excl "SuSEfirewall2.d/services/TEMPLATE" .
230 let filter_default = incl "/etc/default/*"
231 . excl "/etc/default/grub_installdevice*"
232 . excl "/etc/default/rmt"
233 . excl "/etc/default/whoopsie"
234 let filter_misc = incl "/etc/arno-iptables-firewall/debconf.cfg"
235 . incl "/etc/cron-apt/config"
236 . incl "/etc/environment"
237 . incl "/etc/firewalld/firewalld.conf"
238 . incl "/etc/blkid.conf"
239 . incl "/etc/adduser.conf"
240 . incl "/etc/cowpoke.conf"
241 . incl "/etc/cvs-cron.conf"
242 . incl "/etc/cvs-pserver.conf"
243 . incl "/etc/devscripts.conf"
244 . incl "/etc/lintianrc"
245 . incl "/etc/lsb-release"
246 . incl "/etc/os-release"
247 . incl "/etc/popularity-contest.conf"
248 . incl "/etc/rc.conf"
249 . incl "/etc/rc.conf.local"
250 . incl "/etc/selinux/config"
251 . incl "/etc/ucf.conf"
252 . incl "/etc/locale.conf"
253 . incl "/etc/vconsole.conf"
255 let filter = filter_sysconfig
260 let xfm = transform lns filter
262 (* Local Variables: *)