Integrate basic UCI config file validation support Needs more testing and validation is not enforced yet
Code contributed by Fraunhofer Fokus SVN-Revision: 6391master
parent
c6a4f047e3
commit
9405a2a6be
@ -0,0 +1,255 @@ |
|||||||
|
# AWK file for parsing uci specification files |
||||||
|
# |
||||||
|
# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de> |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or modify |
||||||
|
# it under the terms of the GNU General Public License as published by |
||||||
|
# the Free Software Foundation; either version 2 of the License, or |
||||||
|
# (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||||
|
# General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||||
|
# |
||||||
|
# |
||||||
|
# general: unfortunately, the development was done using gawk providing |
||||||
|
# a different match() functions than e.g. mawk on debian systems |
||||||
|
# - therefore, the script was changed to run on most awk's |
||||||
|
# - even things like [:space:] are not used |
||||||
|
# |
||||||
|
# - script parses the config section definition contained in one |
||||||
|
# specification file |
||||||
|
# global variables: |
||||||
|
# * section - contains the current config section name |
||||||
|
# * var - contains the name of the current config option |
||||||
|
# * type - contains the type of the current config option |
||||||
|
# * required - contains the requirements of the current config option |
||||||
|
# * optional - contains the optional scope of the current config option |
||||||
|
# * vars[] - array, contains the name of all config options valid within |
||||||
|
# a certain config section, format: csv |
||||||
|
# |
||||||
|
# XXX todo: more than one config option with the same in different section |
||||||
|
# will clash for the following tables |
||||||
|
# * types[] - contains the type of a config option |
||||||
|
# * reqs[] - contains the requirements of a config option |
||||||
|
# * opts[] - contains the optional scope of a config option |
||||||
|
# |
||||||
|
BEGIN { |
||||||
|
section_count=1 |
||||||
|
section = "" |
||||||
|
simple_types = "int|ip|netmask|string|wep|hostname|mac|port|ports|wpapsk" |
||||||
|
} |
||||||
|
|
||||||
|
# function print_specification |
||||||
|
# - prints all information about the created tables containing the |
||||||
|
# specification |
||||||
|
function print_specification() { |
||||||
|
for (section in vars) { |
||||||
|
printf("%s\n",section); |
||||||
|
split(vars[section],arr,",") |
||||||
|
for (idx in arr) { |
||||||
|
printf("\t%s[%s]",arr[idx],types[section "_" arr[idx]]); |
||||||
|
if (length(reqs[section "_" arr[idx]])) { |
||||||
|
if (reqs[section "_" arr[idx]]==1) { |
||||||
|
printf(",req"); |
||||||
|
}else{ |
||||||
|
printf(", req(%s)", reqs[section "_" arr[idx]]); |
||||||
|
} |
||||||
|
} |
||||||
|
if (length(opts[section "_" arr[idx]])) { |
||||||
|
printf(", opt(%s)", opts[section "_" arr[idx]]); |
||||||
|
} |
||||||
|
printf("\n"); |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
function reset_option() { |
||||||
|
# just set global variables parsed on one line back to defaults |
||||||
|
var = "" |
||||||
|
type = "" |
||||||
|
required = "" |
||||||
|
optional = "" |
||||||
|
found = 0 |
||||||
|
} |
||||||
|
|
||||||
|
function store_option() { |
||||||
|
# save all information about a config option parsed from the spec file |
||||||
|
# to the relevant tables for future use |
||||||
|
|
||||||
|
# first check minimum requirements for storing information |
||||||
|
if (!length(section)) { |
||||||
|
print STDERR "line " NR ": section definition missing" |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
if (!length(var)) { |
||||||
|
print STDERR "line " NR ": invalid config option name" |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
if (!length(type)) { |
||||||
|
print STDERR "line " NR ": invalid config option type" |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
|
||||||
|
# add config options to the names of options available for this |
||||||
|
# section |
||||||
|
if (exists[section]!=1) { |
||||||
|
section_names[section_count] = section |
||||||
|
section_count++ |
||||||
|
exists[section] = 1 |
||||||
|
vars[section] = var |
||||||
|
} else { |
||||||
|
vars[section] = vars[section] "," var |
||||||
|
} |
||||||
|
|
||||||
|
# save the type, the requirements and the optional scope of the |
||||||
|
# config option |
||||||
|
types[section "_" var] = type |
||||||
|
reqs[section "_" var] = required |
||||||
|
opts[section "_" var] = optional |
||||||
|
} |
||||||
|
|
||||||
|
/^declare -x|^export/ { |
||||||
|
sub(/^declare -x /,"") |
||||||
|
sub(/^export /,"") |
||||||
|
split($0,arr,"=") |
||||||
|
val=substr(arr[2],2,length(arr[2])-2) |
||||||
|
ENVIRON[arr[1]] = val |
||||||
|
next |
||||||
|
} |
||||||
|
|
||||||
|
# main parsing function |
||||||
|
# this is done in one function block to allow multiple semicolon separated |
||||||
|
# definitions on one line |
||||||
|
{ |
||||||
|
# replace leading/trailing white space |
||||||
|
gsub("^[ \t\n]+",""); |
||||||
|
gsub("[ \t\n]+$",""); |
||||||
|
|
||||||
|
# comments are removed |
||||||
|
# XXX todo: check for quoted comments?? |
||||||
|
if (match($0,/[^#]*/)) { |
||||||
|
rest=substr($0,RSTART,RLENGTH) |
||||||
|
} else { |
||||||
|
rest=$0 |
||||||
|
} |
||||||
|
|
||||||
|
# match the config section "<section> {" |
||||||
|
if (match(rest,/^[^ \t\n{]+[ \t\n]*\{/)) { |
||||||
|
match(rest,/^[^ \t\n{]+/) |
||||||
|
section = substr(rest,RSTART,RLENGTH) |
||||||
|
rest=substr($0,RSTART+RLENGTH); |
||||||
|
match(rest,/[ \t\n]*\{/) |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
# check for array indication |
||||||
|
if (match(section,/\[[ \t\n]*\]/)) { |
||||||
|
section=substr(section,1,RSTART-1) |
||||||
|
multiple[section] = 1 |
||||||
|
} else { |
||||||
|
multiple[section] = 0 |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
reset_option() |
||||||
|
|
||||||
|
# parse the remaing line as long as there is something to parse |
||||||
|
while (rest ~ "[^ \t\n}]+") { |
||||||
|
found = 0 |
||||||
|
|
||||||
|
# get option name and option type |
||||||
|
# first, check for "simple" datatype definitions |
||||||
|
if (match(rest,"[^: \t\n]+[ \t\n]*:[ \t\n]*(" \ |
||||||
|
simple_types ")")){ |
||||||
|
match(rest,"[^: \t\n]+") |
||||||
|
var=substr(rest,RSTART,RLENGTH) |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,"[ \t\n]*:[ \t\n]*") |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,"(" simple_types ")") |
||||||
|
type=substr(rest,RSTART,RLENGTH) |
||||||
|
rest = substr(rest,RSTART+RLENGTH) |
||||||
|
found = 1 |
||||||
|
# next, check for enum definitions |
||||||
|
} else if (match(rest,/[^: \t\n]+[ \t\n]*:[ \t\n]*enum\([^\)]+\)/ )) { |
||||||
|
match(rest,"[^: \t\n]+") |
||||||
|
var=substr(rest,RSTART,RLENGTH) |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,/[ \t\n]*:[ \t\n]*enum\(/) |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,/[^\)]+/) |
||||||
|
type="enum," substr(rest,RSTART,RLENGTH) |
||||||
|
rest = substr(rest,RSTART+RLENGTH+1) |
||||||
|
found=1 |
||||||
|
} |
||||||
|
|
||||||
|
# after the name and the type, |
||||||
|
# get the option requirements/scope |
||||||
|
if (match(rest,/[^,]*,[ \t\n]*required\[[^]]+\]/)) { |
||||||
|
match(rest,"[^,]*") |
||||||
|
save=substr(rest,RSTART,RLENGTH) |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,/,[ \t\n]*required\[/); |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,/[^]]+\]/) |
||||||
|
required=substr(rest,RSTART,RLENGTH-1) |
||||||
|
save=save substr(rest,RSTART+RLENGTH) |
||||||
|
rest=save |
||||||
|
found=1 |
||||||
|
} else if (match(rest,/[^,]*,[ \t\n]*required/)) { |
||||||
|
match(rest,"[^,]*") |
||||||
|
save=substr(rest,RSTART,RLENGTH) |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,",[ \t\n]*required"); |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
required=1 |
||||||
|
save=save substr(rest,RSTART+RLENGTH) |
||||||
|
rest=save |
||||||
|
found=1 |
||||||
|
} |
||||||
|
if (match(rest,/[^,]*,[ \t\n]*optional\[[^]]+\]/)) { |
||||||
|
match(rest,"[^,]*") |
||||||
|
save=substr(rest,RSTART,RLENGTH) |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,/,[ \t\n]*optional\[/); |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
match(rest,/[^]]+\]/) |
||||||
|
optional=substr(rest,RSTART,RLENGTH-1) |
||||||
|
save=save substr(rest,RSTART+RLENGTH) |
||||||
|
rest=save |
||||||
|
found=1 |
||||||
|
} |
||||||
|
|
||||||
|
# if the remaining line contains a semicolon, complete the |
||||||
|
# specification of the config options |
||||||
|
if (match(rest, "^[ \t\n]*;(.*)")) { |
||||||
|
match(rest,"^[ \t\n]*;") |
||||||
|
rest=substr(rest,RSTART+RLENGTH) |
||||||
|
if (found==1) { |
||||||
|
store_option() |
||||||
|
} |
||||||
|
reset_option() |
||||||
|
|
||||||
|
# if nothing matched on this line, clear the rest |
||||||
|
} else if (!found) { |
||||||
|
rest = "" |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
# after the line is pared, store the configuration option in the |
||||||
|
# table if any has been defined |
||||||
|
if (length(var)) { |
||||||
|
store_option() |
||||||
|
reset_option() |
||||||
|
} |
||||||
|
# close the section if the line contained a closing section bracket, |
||||||
|
# XXX todo: check if this has to be done more intelligent |
||||||
|
if ($0 ~ /\}/) { |
||||||
|
section="" |
||||||
|
} |
||||||
|
} |
@ -0,0 +1,7 @@ |
|||||||
|
interface[] { |
||||||
|
proto: string, required; |
||||||
|
ipaddr: ip, required[proto=static]; |
||||||
|
netmask: ip, required[proto=static]; |
||||||
|
gateway: ip; |
||||||
|
dns: ip; |
||||||
|
} |
@ -0,0 +1,74 @@ |
|||||||
|
# Shell script defining validating configuration macros |
||||||
|
# |
||||||
|
# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de> |
||||||
|
# Copyright (C) 2007 by Felix Fietkau <nbd@openwrt.org> |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or modify |
||||||
|
# it under the terms of the GNU General Public License as published by |
||||||
|
# the Free Software Foundation; either version 2 of the License, or |
||||||
|
# (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||||
|
# General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||||
|
|
||||||
|
|
||||||
|
validate_spec() { |
||||||
|
export | grep 'CONFIG_' | cat - "$@" | awk \ |
||||||
|
-f $UCI_ROOT/lib/config/validate_config.awk \ |
||||||
|
-f $UCI_ROOT/lib/config/parse_spec.awk \ |
||||||
|
-f $UCI_ROOT/lib/config/validate_spec.awk |
||||||
|
} |
||||||
|
|
||||||
|
validate_config_cb () { |
||||||
|
local TYPE |
||||||
|
local res= |
||||||
|
|
||||||
|
[ -n "${CONFIG_SECTION}" ] || return 0 |
||||||
|
|
||||||
|
config_get TYPE ${CONFIG_SECTION} TYPE |
||||||
|
[ -n "$TYPE" ] || return 0 |
||||||
|
|
||||||
|
if type validate_${PACKAGE}_${TYPE} >/dev/null 2>&1; then |
||||||
|
validate_${PACKAGE}_${TYPE} |
||||||
|
res="$?" |
||||||
|
else |
||||||
|
if [ -f $UCI_ROOT/lib/config/specs/${PACKAGE}.spec ]; then |
||||||
|
# no special defined, use default one |
||||||
|
validate_spec $UCI_ROOT/lib/config/specs/${PACKAGE}.spec |
||||||
|
res="$?" |
||||||
|
fi |
||||||
|
fi |
||||||
|
|
||||||
|
VALIDATE_RES="${VALIDATE_RES:-$res}" |
||||||
|
} |
||||||
|
|
||||||
|
uci_validate() {( |
||||||
|
PACKAGE="$1" |
||||||
|
FILE="$2" |
||||||
|
VALIDATE_RES= |
||||||
|
|
||||||
|
[ -z "${PACKAGE}" ] && { |
||||||
|
echo "Error: no package defined" |
||||||
|
return 1 |
||||||
|
} |
||||||
|
|
||||||
|
reset_cb |
||||||
|
config_cb() { |
||||||
|
validate_config_cb "$@" |
||||||
|
} |
||||||
|
unset NO_EXPORT |
||||||
|
if [ -n "$FILE" ]; then |
||||||
|
. "$FILE" |
||||||
|
config |
||||||
|
else |
||||||
|
config_load "$1" |
||||||
|
fi |
||||||
|
|
||||||
|
return ${VALIDATE_RES:-0} |
||||||
|
)} |
@ -0,0 +1,105 @@ |
|||||||
|
# AWK file for validating uci specification files |
||||||
|
# |
||||||
|
# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de> |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or modify |
||||||
|
# it under the terms of the GNU General Public License as published by |
||||||
|
# the Free Software Foundation; either version 2 of the License, or |
||||||
|
# (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||||
|
# General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||||
|
# |
||||||
|
function is_int(value) { |
||||||
|
valid = 1 |
||||||
|
if (value !~ /^[0-9]*$/) { valid = 0 } |
||||||
|
return valid |
||||||
|
} |
||||||
|
|
||||||
|
function is_netmask(value) { |
||||||
|
return is_ip(value) |
||||||
|
} |
||||||
|
|
||||||
|
function is_ip(value) { |
||||||
|
valid = 1 |
||||||
|
if ((value != "") && (value !~ /^[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$/)) valid = 0 |
||||||
|
else { |
||||||
|
split(value, ipaddr, "\\.") |
||||||
|
for (i = 1; i <= 4; i++) { |
||||||
|
if ((ipaddr[i] < 0) || (ipaddr[i] > 255)) valid = 0 |
||||||
|
} |
||||||
|
} |
||||||
|
return valid |
||||||
|
} |
||||||
|
|
||||||
|
function is_wep(value) { |
||||||
|
valid = 1 |
||||||
|
if (value !~ /^[0-9A-Fa-f]*$/) { |
||||||
|
valid = 0 |
||||||
|
} else if ((length(value) != 0) && (length(value) != 10) && (length(value) != 26)) { |
||||||
|
valid = 0 |
||||||
|
} else if (value ~ /0$/) { |
||||||
|
valid = 0 |
||||||
|
} |
||||||
|
return valid |
||||||
|
} |
||||||
|
|
||||||
|
function is_hostname(value) { |
||||||
|
valid = 1 |
||||||
|
if (value !~ /^[0-9a-zA-z\.\-]*$/) { |
||||||
|
valid = 0 |
||||||
|
} |
||||||
|
return valid; |
||||||
|
} |
||||||
|
|
||||||
|
function is_string(value) { |
||||||
|
return 1; |
||||||
|
} |
||||||
|
|
||||||
|
function is_mac(value) { |
||||||
|
valid = 1 |
||||||
|
if ((value != "") && (value !~ /^[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]:[0-9a-fA-F][0-9a-fA-F]$/)) { |
||||||
|
valid = 0 |
||||||
|
} |
||||||
|
return valid |
||||||
|
} |
||||||
|
|
||||||
|
function is_port(value) { |
||||||
|
valid = 1 |
||||||
|
if (value !~ /^[0-9]*$/) { |
||||||
|
valid = 0 |
||||||
|
} |
||||||
|
return valid |
||||||
|
} |
||||||
|
|
||||||
|
function is_ports(value) { |
||||||
|
valid = 1 |
||||||
|
n = split(value ",", ports, ",") |
||||||
|
for (i = 1; i <= n; i++) { |
||||||
|
if ((ports[i] !~ /^[0-9]*$/) && (ports[i] !~ /^[0-9][0-9]*-[0-9][0-9]*$/)) { |
||||||
|
valid = 0 |
||||||
|
} |
||||||
|
} |
||||||
|
return valid |
||||||
|
} |
||||||
|
|
||||||
|
function is_wpapsk(value) { |
||||||
|
valid = 1 |
||||||
|
if (length(value) > 64) { |
||||||
|
valid = 0 |
||||||
|
} |
||||||
|
if ((length(value) != 0) && (length(value) < 8)) { |
||||||
|
valid = 0 |
||||||
|
} |
||||||
|
if ((length(value) == 64) && (value ~ /[^0-9a-fA-F]/)) { |
||||||
|
valid = 0 |
||||||
|
} |
||||||
|
return valid |
||||||
|
} |
||||||
|
|
@ -0,0 +1,171 @@ |
|||||||
|
# AWK file for validating uci specification files |
||||||
|
# |
||||||
|
# Copyright (C) 2006 by Fokus Fraunhofer <carsten.tittel@fokus.fraunhofer.de> |
||||||
|
# Copyright (C) 2007 by Felix Fietkau <nbd@openwrt.org> |
||||||
|
# |
||||||
|
# This program is free software; you can redistribute it and/or modify |
||||||
|
# it under the terms of the GNU General Public License as published by |
||||||
|
# the Free Software Foundation; either version 2 of the License, or |
||||||
|
# (at your option) any later version. |
||||||
|
# |
||||||
|
# This program is distributed in the hope that it will be useful, |
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
||||||
|
# General Public License for more details. |
||||||
|
# |
||||||
|
# You should have received a copy of the GNU General Public License |
||||||
|
# along with this program; if not, write to the Free Software |
||||||
|
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
||||||
|
# |
||||||
|
# |
||||||
|
# general: unfortunately, the development was done using gawk providing |
||||||
|
# a different match() functions than e.g. mawk on debian systems |
||||||
|
# - therefore, the script was changed to run on most awk's |
||||||
|
# - even things like [:space:] are not used |
||||||
|
# |
||||||
|
# - script parses the config section definition contained in one |
||||||
|
# specification file |
||||||
|
# global variables: |
||||||
|
# * section - contains the current config section name |
||||||
|
# * var - contains the name of the current config option |
||||||
|
# * type - contains the type of the current config option |
||||||
|
# * required - contains the requirements of the current config option |
||||||
|
# * optional - contains the optional scope of the current config option |
||||||
|
# * vars[] - array, contains the name of all config options valid within |
||||||
|
# a certain config section, format: csv |
||||||
|
# |
||||||
|
# XXX todo: more than one config option with the same in different section |
||||||
|
# will clash for the following tables |
||||||
|
# * types[] - contains the type of a config option |
||||||
|
# * reqs[] - contains the requirements of a config option |
||||||
|
# * opts[] - contains the optional scope of a config option |
||||||
|
# |
||||||
|
|
||||||
|
# - check requirement validates, if the config option is required in |
||||||
|
# the config section type and if so, if it is defined |
||||||
|
# - the functions exits with error in case of non-conforming |
||||||
|
# behaviour |
||||||
|
# XXX todo: use return instead of exit |
||||||
|
# |
||||||
|
function check_requirements(vsec,var) { |
||||||
|
# check, if config option is required in all cases |
||||||
|
if (reqs[vsec "_" var] == 1) { |
||||||
|
# option is always required, is it defined? |
||||||
|
if (!length(ENVIRON["CONFIG_" vsec "_" var])) { |
||||||
|
print STDERR "Error: missing config option " var " in " vsec |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
|
||||||
|
# check, if config option is required only when other options |
||||||
|
# have certain values |
||||||
|
} else if (length(reqs[vsec "_" var])) { |
||||||
|
# - check all requirements, e.g. proto=static,proto=pptp |
||||||
|
# - note, that the required flag is tiggered if at least one |
||||||
|
# of the conditions is met |
||||||
|
split(reqs[vsec "_" var],arr,","); |
||||||
|
for (idx in arr) { |
||||||
|
# parse the condition space tolerant |
||||||
|
if (!match(arr[idx],"^[ \t\n]*[^ \t\n=]+"\ |
||||||
|
"[ \t\n]*=.+")) { |
||||||
|
print STDERR "Error: invalid requirement "\ |
||||||
|
"in spec file for " var " : " arr[idx] |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
# get the name of the variable |
||||||
|
match(arr[idx],"[^ \t\n=]+"); |
||||||
|
name=substr(arr[idx],RSTART,RLENGTH) |
||||||
|
mrest=substr(arr[idx],RSTART+RLENGTH) |
||||||
|
# get the spaces |
||||||
|
match(mrest,"[ \t\n]*=[ \t\n]*") |
||||||
|
val=substr(mrest,RSTART+RLENGTH) |
||||||
|
# check the condition |
||||||
|
if (ENVIRON["CONFIG_" vsec "_" name] == val) { |
||||||
|
# condition is met, check requirement |
||||||
|
if (!length(ENVIRON["CONFIG_" vsec "_" var])) { |
||||||
|
print STDERR "Error: missing config " \ |
||||||
|
"option " var " in " vsec |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
# is_valid just returns true(1)/false(0) if the |
||||||
|
# given value is conform with the type definition |
||||||
|
# NOTE: this function needs the type validating function from |
||||||
|
# validate_config.awk |
||||||
|
# |
||||||
|
function is_valid(type,value) { |
||||||
|
|
||||||
|
# the enum type contains a definition of all allowed values as csv |
||||||
|
# e.g. enum,alpha,beta,gamma |
||||||
|
if (type ~ "enum" ) { |
||||||
|
split(type,tarr,",") |
||||||
|
for (num in tarr) { |
||||||
|
if (num > 0) { |
||||||
|
gsub("^[ \t\n]*","",tarr[num]); |
||||||
|
gsub("[ \t\n]*$","",tarr[num]); |
||||||
|
if (tarr[num] == value) { |
||||||
|
return 1 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
return 0; |
||||||
|
} |
||||||
|
|
||||||
|
# all other types are checked as defined in the former validate.awk |
||||||
|
if (type ~ "int") return is_int(value) |
||||||
|
if (type ~ "ip" ) return is_ip(value) |
||||||
|
if (type ~ "netmask" ) return is_netmask(value) |
||||||
|
if (type ~ "string" ) return is_string(value) |
||||||
|
if (type ~ "wep" ) return is_wep(value) |
||||||
|
if (type ~ "hostname" ) return is_hostname(value) |
||||||
|
if (type ~ "mac" ) return is_mac(value) |
||||||
|
if (type ~ "port" ) return is_port(value) |
||||||
|
if (type ~ "ports" ) return is_ports(value) |
||||||
|
if (type ~ "wpapsk" ) return is_wpapsk(value) |
||||||
|
} |
||||||
|
|
||||||
|
# validate_config compares the specification as parsed from the spec file |
||||||
|
# with the environment variables |
||||||
|
# CONFIG_SECTION contains the relevant config section name, e.g. wan |
||||||
|
# CONFIG_<section>_TYPE contains the type of the config, e.g. interface |
||||||
|
# CONFIG_<section>_<var> contains the value of the config option <var> |
||||||
|
# |
||||||
|
function validate_config() { |
||||||
|
# get the config section name |
||||||
|
vname=ENVIRON["CONFIG_SECTION"] |
||||||
|
if (!length(vname)) { |
||||||
|
print STDERR "Error: no current configuration" |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
# get the config section type |
||||||
|
vsec=ENVIRON["CONFIG_" vname "_TYPE"] |
||||||
|
if (!length(vsec)) { |
||||||
|
print STDERR "Error: section " vsec " not found" |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
|
||||||
|
# loop through all config options specified for this section type |
||||||
|
split(vars[vsec],options,",") |
||||||
|
for (oidx in options) { |
||||||
|
# first, look for all required attributes |
||||||
|
var=options[oidx] |
||||||
|
check_requirements(vname,var) |
||||||
|
|
||||||
|
# next look at each option and validate it |
||||||
|
val=ENVIRON["CONFIG_" vname "_" var] |
||||||
|
if (length(val)) { |
||||||
|
if (!is_valid(types[vsec "_" var],val)) { |
||||||
|
print "Error: type validation error for '" var "' in section '" vname "'" |
||||||
|
exit 1 |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
END { |
||||||
|
validate_config() |
||||||
|
} |
Loading…
Reference in new issue