Imported Upstream version 1.3.0
[platform/upstream/augeas.git] / lenses / shellvars.aug
1 (*
2 Module: Shellvars
3  Generic lens for shell-script config files like the ones found
4  in /etc/sysconfig
5
6 About: License
7    This file is licenced under the LGPL v2+, like the rest of Augeas.
8
9 About: Lens Usage
10    To be documented
11 *)
12
13 module Shellvars =
14   autoload xfm
15
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"
20
21   let key_re = /[A-Za-z0-9_]+(\[[0-9]+\])?/ - ("unset" | "export")
22   let matching_re = "${!" . key_re . /[\*@]\}/
23   let eq = Util.del_str "="
24
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
30
31   let xchgs   = Build.xchgs
32   let semicol = del /;?/ ""
33
34   let char  = /[^`;() '"\t\n]|\\\\"/
35   let dquot =
36        let char = /[^"\\]|\\\\./ | Rx.cl
37     in "\"" . char* . "\""                    (* " Emacs, relax *)
38   let squot = /'[^']*'/
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]*\)\)/
44
45   let anyquot = (dquot|squot)+ | bquot | dbquot | dollar_assign | dollar_arithm
46
47   let to_semicol_re = /[^#; \t\n][^#;\n]+[^#; \t\n]|[^#; \t\n]+/
48   let sto_to_semicol = store to_semicol_re
49
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)
55
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                                           *)
59   let array =
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 ] *
64       . del /[ \t]*\)/ ")"
65
66   (* Treat an empty list () as a value '()'; that's not quite correct *)
67   (* but fairly close.                                                *)
68   let simple_value =
69     let empty_array = /\([ \t]*\)/ in
70       store (char* | anyquot | empty_array)
71
72   let export = [ key "export" . Util.del_ws_spc ]
73   let kv = Util.indent . export? . key key_re
74            . eq . (simple_value | array)
75
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
80
81   let unset = var_action "unset"
82   let bare_export = var_action "export"
83
84   let source =
85     Util.indent
86     . del /\.|source/ "." . label ".source"
87     . Util.del_ws_spc . store /[^;=# \t\n]+/
88
89   let shell_builtin_cmds = "ulimit" | "shift" | "exit"
90
91   let builtin =
92     Util.indent . label "@builtin"
93     . store shell_builtin_cmds
94     . (Util.del_ws_spc
95     . [ label "args" . sto_to_semicol ])?
96
97   let keyword (kw:string) = Util.indent . Util.del_str kw
98   let keyword_label (kw:string) (lbl:string) = keyword kw . label lbl
99
100   let return =
101     Util.indent . label "@return"
102     . Util.del_str "return"
103     . ( Util.del_ws_spc . store Rx.integer )?
104
105
106 (************************************************************************
107  * Group:                 CONDITIONALS AND LOOPS
108  *************************************************************************)
109
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
115       . contents
116
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 ]
121
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"
126
127   let loop_for (entry:lens) =
128     generic_cond "for" "@for" "do" entry+ "done"
129
130   let loop_while (entry:lens) =
131     generic_cond "while" "@while" "do" entry+ "done"
132
133   let loop_until (entry:lens) =
134     generic_cond "until" "@until" "do" entry+ "done"
135
136   let loop_select (entry:lens) =
137     generic_cond "select" "@select" "do" entry+ "done"
138
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)*
149         . empty* . comment*
150         . keyword "esac" . comment_or_eol ]
151
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
157       . entry+
158       . Util.indent . Util.del_str "}" . eol ]
159
160   let entry_eol =
161     let entry_eol_item (item:lens) =
162       [ item . comment_or_eol ] in
163       entry_eol_item source
164         | entry_eol_item kv
165         | entry_eol_item unset
166         | entry_eol_item bare_export
167         | entry_eol_item builtin
168         | entry_eol_item return
169
170   let entry_noeol =
171     let entry_item (item:lens) = [ item ] in
172       entry_item source
173         | entry_item kv
174         | entry_item unset
175         | entry_item bare_export
176         | entry_item builtin
177         | entry_item return
178
179   let rec rec_entry =
180     let entry = comment | entry_eol | rec_entry in
181         cond_if entry
182       | loop_for entry
183       | loop_select entry
184       | loop_while entry
185       | loop_until entry
186       | case entry entry_noeol
187       | function entry
188
189   let lns_norec = empty* . (comment | entry_eol) *
190
191   let lns = empty* . (comment | entry_eol | rec_entry) *
192
193   let sc_incl (n:string) = (incl ("/etc/sysconfig/" . n))
194   let sc_excl (n:string) = (excl ("/etc/sysconfig/" . n))
195
196   let filter_sysconfig =
197       sc_incl "*" .
198       sc_excl "bootloader" .
199       sc_excl "hw-uuid" .
200       sc_excl "hwconf" .
201       sc_excl "ip*tables" .
202       sc_excl "ip*tables.save" .
203       sc_excl "kernel" .
204       sc_excl "*.pub" .
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-*" .
219       sc_excl "rhn" .
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" .
228       sc_excl "*.systemd"
229
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"
254
255   let filter = filter_sysconfig
256              . filter_default
257              . filter_misc
258              . Util.stdexcl
259
260   let xfm = transform lns filter
261
262 (* Local Variables: *)
263 (* mode: caml       *)
264 (* End:             *)