base-files: remove obsolete stuff from common.awk
[openwrt.git] / package / base-files / files / lib / config / validate_spec.awk
1 # AWK file for validating uci specification files
2 #
3 # Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de>
4 # Copyright (C) 2007 by Felix Fietkau <nbd@openwrt.org>
5 #
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the Free Software
18 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 #
20 #
21 # general: unfortunately, the development was done using gawk providing
22 #  a different match() functions than e.g. mawk on debian systems
23 #  - therefore, the script was changed to run on most awk's 
24 #  - even things like [:space:] are not used
25 #
26 # - script  parses the config section definition contained in one 
27 #   specification file
28 # global variables:
29 # * section  - contains the current config section name
30 # * var      - contains the name of the current config option
31 # * type     - contains the type of the current config option
32 # * required - contains the requirements of the current config option
33 # * optional - contains the optional scope of the current config option
34 # * vars[]  - array, contains the name of all config options valid within
35 #             a certain config section, format: csv
36 #
37 # XXX todo: more than one config option with the same in different section
38 # will clash for the following tables
39 # * types[] - contains the type of a config option
40 # * reqs[]  - contains the requirements of a config option
41 # * opts[]  - contains the optional scope of a config option
42 #
43
44 # - check requirement validates, if the config option is required in
45 #   the config section type and if so, if it is defined
46 # - the functions exits with error in case of non-conforming 
47 #   behaviour
48 # XXX todo: use return instead of exit
49 #
50 function check_requirements(vsec,var) {
51         # check, if config option is required in all cases
52         if (reqs[vsec "_" var] == 1) {
53                 # option is always required, is it defined?
54                 if (!length(ENVIRON["CONFIG_" vsec "_" var])) {
55                         print STDERR "Error: missing config option " var " in " vsec
56                         exit 1
57                 }
58
59         # check, if config option is required only when other options
60         # have certain values
61         } else if (length(reqs[vsec "_" var])) {
62                 # - check all requirements, e.g. proto=static,proto=pptp
63                 # - note, that the required flag is tiggered if at least one
64                 #   of the conditions is met
65                 split(reqs[vsec "_" var],arr,",");
66                 for (idx in arr) {
67                         # parse the condition space tolerant
68                         if (!match(arr[idx],"^[ \t\n]*[^ \t\n=]+"\
69                                 "[ \t\n]*=.+")) {
70                                 print STDERR "Error: invalid requirement "\
71                                         "in spec file for " var " : " arr[idx]
72                                 exit 1
73                         }
74                         # get the name of the variable
75                         match(arr[idx],"[^ \t\n=]+");
76                         name=substr(arr[idx],RSTART,RLENGTH)
77                         mrest=substr(arr[idx],RSTART+RLENGTH)
78                         # get the spaces
79                         match(mrest,"[ \t\n]*=[ \t\n]*")
80                         val=substr(mrest,RSTART+RLENGTH)
81                         # check the condition
82                         if (ENVIRON["CONFIG_" vsec "_" name] == val) {
83                                 # condition is met, check requirement
84                                 if (!length(ENVIRON["CONFIG_" vsec "_" var])) {
85                                         print STDERR "Error: missing config " \
86                                                 "option " var " in " vsec 
87                                         exit 1
88                                 }
89                         }
90                 }
91         }
92 }
93
94 # is_valid just returns true(1)/false(0) if the
95 # given value is conform with the type definition 
96 # NOTE: this function needs the type validating function from
97 # validate_config.awk
98 #
99 function is_valid(type,value) {
100
101         # the enum type contains a definition of all allowed values as csv
102         # e.g. enum,alpha,beta,gamma
103         if (type ~ "enum" ) {
104                 split(type,tarr,",")
105                 for (num in tarr) {
106                         if (num > 0) {
107                                 gsub("^[ \t\n]*","",tarr[num]);
108                                 gsub("[ \t\n]*$","",tarr[num]);
109                                 if (tarr[num] == value) {
110                                         return 1
111                                 }       
112                         }
113                 }
114                 return 0;
115         }
116
117         # all other types are checked as defined in the former validate.awk
118         if (type ~ "int") return is_int(value)
119         if (type ~ "ip" ) return is_ip(value)
120         if (type ~ "netmask" ) return is_netmask(value)
121         if (type ~ "string" ) return is_string(value)
122         if (type ~ "wep" ) return is_wep(value)
123         if (type ~ "hostname" ) return is_hostname(value)
124         if (type ~ "mac" ) return is_mac(value)
125         if (type ~ "port" ) return is_port(value)
126         if (type ~ "ports" ) return is_ports(value)
127         if (type ~ "wpapsk" ) return is_wpapsk(value)
128 }
129
130 # validate_config compares the specification as parsed from the spec file
131 # with the environment variables
132 # CONFIG_SECTION contains the relevant config section name, e.g. wan
133 # CONFIG_<section>_TYPE contains the type of the config, e.g. interface
134 # CONFIG_<section>_<var> contains the value of the config option <var>
135 #
136 function validate_config() {
137         # get the config section name
138         vname=ENVIRON["CONFIG_SECTION"]
139         if (!length(vname)) {
140                 print STDERR "Error: no current configuration"
141                 exit 1
142         }
143         # get the config section type
144         vsec=ENVIRON["CONFIG_" vname "_TYPE"]
145         if (!length(vsec)) {
146                 print STDERR "Error: section " vsec " not found"
147                 exit 1
148         }
149
150         # loop through all config options specified for this section type
151         split(vars[vsec],options,",")
152         for (oidx in options) {
153                 # first, look for all required attributes
154                 var=options[oidx]
155                 check_requirements(vname,var)
156
157                 # next look at each option and validate it
158                 val=ENVIRON["CONFIG_" vname "_" var]
159                 if (length(val)) {
160                         if (!is_valid(types[vsec "_" var],val)) {
161                                 print "Error: type validation error for '" var "' in section '" vname "'"
162                                 exit 1
163                         }
164                 }
165         }
166 }
167
168
169 END {
170         validate_config()
171 }