cdist/cdist/conf/type/__ini_value/explorer/state

166 lines
4.7 KiB
Bash
Executable File

#!/bin/sh -e
# __ini_value/explorer/state
# Check the state of the key-value pair in the ini file
#
# There are following states:
# - present
# - wrongvalue
# - wrongformat
# - commented
# - absent
# - nosuchfile
# Using ' \t' for matching spaces as char classes not implemented in mawk
# see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=65617#40
# Parameters
# (maybe multi-variable object id for this ..)
#state_should="$(cat "$__object/parameter/state")"
file="$(cat "$__object/parameter/file")"
# abort if no file exist
if ! [ -f "$file" ]; then
echo absent
exit
fi
# run awk
awk -f - "$file" <<'AWK'
function trim(var) {
sub(/^[ \t]*/, "", var)
sub(/[ \t]*$/, "", var)
return var
}
function check_spaces(var) {
return match(var, /^[ \t]*$/) == 1
}
function state(val) {
print val
exit
}
BEGIN {
_param = (ENVIRON["__object"] "/parameter/")
getline state_should < (_param "state")
getline section < (_param "section")
getline key < (_param "key")
getline delimiter < (_param "delimiter")
getline value < (_param "value")
getline indentation < (_param "indentation")
getline delimiter_space < (_param "delimiter-space")
do_normalization = (system("test -f " (_param "normalize")) == 0)
i=0; _comm_param = (_param "comment-sign");
while((getline tmp < _comm_param) > 0) {
comment_signs[i++] = tmp
}
if(system("test -f " (_param "quote")) == 0) {
# quote it now that it only wins checks against quoted values
value = ("\"" value "\"")
}
found=0
curr_section=""
if(section == "")
found_section=1
else
found_section=0
}
# catch sections
/^[ \t]*\[.*\][ \t]*$/ {
curr_section = trim($0)
if(found_section)
exit # game over, section ends
if(section == curr_section)
found_section=1
next
}
# only interesting if a delimiter was found
found_section {
line = $0
# index 1 cause of trimmed string
if((idel = index(line, delimiter)) && (ikey = index(line, key))) {
is_com=0
if(ikey > 1) {
# maybe comment character or only spaces
start_string = substr(line, 1, ikey - 1)
# something inside rather than a space -> comment
if((icom = match(start_string, /[^ \t]+/)) > 0) {
# icom = RSTART
# only one free-standing char or directly before the key
if(RLENGTH == 1 || icom == ikey - 1) {
start_sign = substr(line, RSTART, 1)
for(i in comment_signs) {
if(start_sign == comment_signs[i]) {
is_com = 1; break;
}
}
if(!is_com) next
else {
aftercom_length = ikey - icom - 1
if(!check_spaces(substr(line, icom + 1, aftercom_length))) next
start_spaces = (icom - 1) + aftercom_length
}
}
else next
}
# must only contain spaces
else start_spaces = ikey - 1
}
idelspace_start = ikey + length(key)
idelspace_length = idel - idelspace_start
# check for delimiter is only preceded with spaces
if(idelspace_length == 0 || check_spaces(substr(line, idelspace_start, idelspace_length))) {
found = 1
# short-circuit on state absent to just delete
if(state_should == "absent") state("present");
# extract the value
found_value = substr(line, idel + length(delimiter))
is_value = trim(found_value)
# check if value is incorrect
if(value != is_value) state("wrongvalue")
else {
# check if the format is important
if(do_normalization) {
if(match(found_value, /^[ \t]+/) == 1) {
found_value = substr(found_value, 1 + RLENGTH)
del_val_spacelen = RLENGTH
}
else
del_val_spacelen = 0
# the format must exactly match, else it is incorrect
if(start_spaces != indentation || found_value != is_value ||
idelspace_length != delimiter_space || del_val_spacelen != delimiter_space)
state("wrongformat")
}
if(is_com)
state("commented")
else
state("present")
}
# this will never be reached
}
}
}
# in the end, check if it is absent
END {
if(!found)
state("absent")
}
AWK