remove obsolete uci validation awk code

SVN-Revision: 18110
master
Felix Fietkau 15 years ago
parent e69a6f1b82
commit e9aa394113
  1. 255
      package/base-files/files/lib/config/parse_spec.awk
  2. 7
      package/base-files/files/lib/config/specs/network.spec
  3. 42
      package/base-files/files/lib/config/template.awk
  4. 74
      package/base-files/files/lib/config/validate.sh
  5. 105
      package/base-files/files/lib/config/validate_config.awk
  6. 171
      package/base-files/files/lib/config/validate_spec.awk

@ -1,255 +0,0 @@
# 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=""
}
}

@ -1,7 +0,0 @@
interface[] {
proto: string, required;
ipaddr: ip, required[proto=static];
netmask: ip, required[proto=static];
gateway: ip;
dns: ip;
}

@ -1,42 +0,0 @@
# Copyright (C) 2006 OpenWrt.org
{
line=$0
gsub(/^[ \t]*/, "")
gsub(/[ \t]*$/, "")
}
$1 == "@define" {
v[$2] = $3
}
$1 == "@ifdef" {
if_open = 1
if (v[$2] != "") noprint = 0
else noprint = 1
}
$1 == "@ifndef" {
if_open = 1
if (v[$2] != "") noprint = 1
else noprint = 0
}
$1 == "@else" {
if (noprint == 1) noprint = 0
else noprint = 1
}
($1 !~ /^@[a-zA-Z0-9_]/) && (noprint != 1) {
n=split(line "@@", a, /@@/)
for (i=1; i<=n; i++) {
if ((i % 2) == 1) printf "%s" a[i]
else printf "%s" v[a[i]]
}
print ""
}
$1 == "@endif" {
if_open = 0
noprint = 0
}

@ -1,74 +0,0 @@
# 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}
)}

@ -1,105 +0,0 @@
# 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
}

@ -1,171 +0,0 @@
# 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…
Cancel
Save