diff --git a/type/__dma/files/update_dma_conf.awk b/type/__dma/files/update_dma_conf.awk new file mode 100644 index 0000000..67661fd --- /dev/null +++ b/type/__dma/files/update_dma_conf.awk @@ -0,0 +1,170 @@ +#!/usr/bin/awk -f +# +# 2020 Dennis Camera (dennis.camera at ssrq-sds-fds.ch) +# +# This file is part of cdist. +# +# cdist 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 3 of the License, or +# (at your option) any later version. +# +# cdist 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 cdist. If not, see . + +function comment_line(line) { + # returns the position in line at which the comment'\''s text starts + # (0 if the line is not a comment) + match(line, /^[ \t]*\#+[ \t]*/) + return RSTART ? (RLENGTH + 1) : 0 +} +function empty_line(line) { return line ~ /^[ \t]*$/ } +function is_word(s) { return s ~ /^[A-Z_]+$/ } # "looks like a plausible word" + +function first(line, sep_re) { + # returns the part of the line until sep is found + # (or the whole line if sep is not found) + if (!sep_re) sep_re = "[" SUBSEP "]" + match(line, sep_re) + return RSTART ? substr(line, 1, RSTART - 1) : line +} + +function rest(line, sep_re) { + # returns the part of the line after the first occurrence of sep is found. + # (or nothing if sep is not found) + if (!sep_re) sep_re = "[" SUBSEP "]" + if (match(line, sep_re)) + return substr(line, RSTART + RLENGTH) +} + +function conf_pop(word, value) { + # returns the next value for the config `word` and delete it from the list. + # if value is set, this function will only return value if it is the first + # option in the list, otherwise it returns 0. + + if (!(word in conf)) return 0 + if (!value) { + if (index(conf[word], SUBSEP)) # more than one element? + value = substr(conf[word], 1, index(conf[word], SUBSEP) - 1) + else + value = conf[word] + } + + if (index(conf[word], SUBSEP)) { + if (index(conf[word], value SUBSEP) != 1) return 0 + conf[word] = substr(conf[word], length(value) + 2) + } else { + if (conf[word] != value) return 0 + delete conf[word] + } + return value +} + +function print_conf(word, value) { + # print a config line with the given parameters + printf "%s", word + if (value) printf " %s", value + printf "\n" +} + +function print_confs(word, value) { + # print config lines for all values stored in conf[word]. + if (!(word in conf)) return + if (conf[word]) { + while (value = conf_pop(word)) + print_conf(word, value) + } else { + print_conf(word) + delete conf[word] + } +} + +BEGIN { + FS = "\n" + EQS = "[ \t]" # copied from dma/conf.c + + # read the "should" state into the `conf` array. + while (getline < "/dev/stdin") { + word = first($0, EQS) + if ((word in conf)) + conf[word] = conf[word] SUBSEP rest($0, EQS) + else + conf[word] = rest($0, EQS) + } +} + +# first pass, gather information about where which information is stored in the +# current config file. This information will be used in the second pass. +NR == FNR { + if (comment_line($0)) { + # comment line + word = first(substr($0, comment_line($0)), " ") + if (is_word(word)) last_occ["#" word] = FNR + } else { + word = first($0, EQS) + if (is_word(word)) last_occ[word] = FNR + } +} + +# before second pass prepare hashes containing location information to be used +# in the second pass. +NR > FNR && FNR == 1 { + # First we drop the locations of commented-out options if a non-commented + # option is available. If a non-commented option is available, we will + # append new config options there to have them all at one place. + for (k in last_occ) + if (k ~ /^\#/ && (substr(k, 2) in last_occ)) + delete last_occ[k] + + # Reverse the option => line mapping. The line_map allows for easier lookups + # in the second pass. + for (k in last_occ) line_map[last_occ[k]] = k +} + +# second pass, generate and output new config +NR > FNR { + if (comment_line($0) || empty_line($0)) { + # comment or empty line + print + + if ((FNR in line_map)) { + if (line_map[FNR] ~ /^\#/) { + # This line contains a commented config option. If the conf hash + # contains options to be set, we output them here because this + # option is not used in the current config. + k = substr(line_map[FNR], 2) + if ((k in conf)) print_confs(k) + } + + if (("INSECURE" in conf) && line_map[FNR] ~ /^\#?SECURE$/) { + # INSECURE goes where SECURE comment is. + print_confs("INSECURE") + } + } + } else { + word = first($0, EQS) + value = rest($0, EQS) + sub(/[ \t]*\#.*$/, "", value) # ignore comments in value + + if ((word in conf) && value == first(conf[word])) { + # keep config options we want + conf_pop(word) + print + } + + if ((FNR in line_map) && line_map[FNR] == word) { + # rest of config options should be here + print_confs(word) + } + } +} + +END { + # print rest of config options ( + for (word in conf) print_confs(word) +} diff --git a/type/__dma/gencode-remote b/type/__dma/gencode-remote index a6aca0d..8177de9 100755 --- a/type/__dma/gencode-remote +++ b/type/__dma/gencode-remote @@ -1,5 +1,7 @@ #!/bin/sh -e +drop_awk_comments() { sed '/^[[:blank:]]*#.*$/d;/^$/d' "$@"; } + CONF_PATH=/etc/dma # set in Makefile # Determine mailname @@ -100,7 +102,7 @@ config_updated=false if ! echo "$conf_should" | cmp -s "${__object}/explorer/conf" - then # config needs to be updated - echo "dma_conf='${CONF_PATH:?}/dma.conf'" + dma_conf="${CONF_PATH:?}/dma.conf" # The following AWK script will output the new config file to be stored on # disk. To do so it reads the current dma.conf file and the config options @@ -119,164 +121,13 @@ then # options are grouped by word (the first word in the line) and appended # at the end of the file. - cat <<'EOF' -awk -F '\n' ' -function comment_line(line) { - # returns the position in line at which the comment'\''s text starts - # (0 if the line is not a comment) - match(line, /^[ \t]*\#+[ \t]*/) - return RSTART ? (RLENGTH + 1) : 0 -} -function empty_line(line) { return line ~ /^[ \t]*$/ } -function is_word(s) { return s ~ /^[A-Z_]+$/ } # "looks like a plausible word" - -function first(line, sep_re) { - # returns the part of the line until sep is found - # (or the whole line if sep is not found) - if (!sep_re) sep_re = "[" SUBSEP "]" - match(line, sep_re) - return RSTART ? substr(line, 1, RSTART - 1) : line -} - -function rest(line, sep_re) { - # returns the part of the line after the first occurrence of sep is found. - # (or nothing if sep is not found) - if (!sep_re) sep_re = "[" SUBSEP "]" - if (match(line, sep_re)) - return substr(line, RSTART + RLENGTH) -} - -function conf_pop(word, value) { - # returns the next value for the config `word` and delete it from the list. - # if value is set, this function will only return value if it is the first - # option in the list, otherwise it returns 0. - - if (!(word in conf)) return 0 - if (!value) { - if (index(conf[word], SUBSEP)) # more than one element? - value = substr(conf[word], 1, index(conf[word], SUBSEP) - 1) - else - value = conf[word] - } - - if (index(conf[word], SUBSEP)) { - if (index(conf[word], value SUBSEP) != 1) return 0 - conf[word] = substr(conf[word], length(value) + 2) - } else { - if (conf[word] != value) return 0 - delete conf[word] - } - return value -} - -function print_conf(word, value) { - # print a config line with the given parameters - printf "%s", word - if (value) printf " %s", value - printf "\n" -} - -function print_confs(word, value) { - # print config lines for all values stored in conf[word]. - if (!(word in conf)) return - if (conf[word]) { - while (value = conf_pop(word)) - print_conf(word, value) - } else { - print_conf(word) - delete conf[word] - } -} - -BEGIN { - EQS = "[ \t]" # copied from dma/conf.c - - # read the "should" state into the `conf` array. - while (getline < "/dev/stdin") { - word = first($0, EQS) - if ((word in conf)) - conf[word] = conf[word] SUBSEP rest($0, EQS) - else - conf[word] = rest($0, EQS) - } -} - -# first pass, gather information about where which information is stored in the -# current config file. This information will be used in the second pass. -NR == FNR { - if (comment_line($0)) { - # comment line - word = first(substr($0, comment_line($0)), " ") - if (is_word(word)) last_occ["#" word] = FNR - } else { - word = first($0, EQS) - if (is_word(word)) last_occ[word] = FNR - } -} - -# before second pass prepare hashes containing location information to be used -# in the second pass. -NR > FNR && FNR == 1 { - # First we drop the locations of commented-out options if a non-commented - # option is available. If a non-commented option is available, we will - # append new config options there to have them all at one place. - for (k in last_occ) - if (k ~ /^\#/ && (substr(k, 2) in last_occ)) - delete last_occ[k] - - # Reverse the option => line mapping. The line_map allows for easier lookups - # in the second pass. - for (k in last_occ) line_map[last_occ[k]] = k -} - -# second pass, generate and output new config -NR > FNR { - if (comment_line($0) || empty_line($0)) { - # comment or empty line - print - - if ((FNR in line_map)) { - if (line_map[FNR] ~ /^\#/) { - # This line contains a commented config option. If the conf hash - # contains options to be set, we output them here because this - # option is not used in the current config. - k = substr(line_map[FNR], 2) - if ((k in conf)) print_confs(k) - } - - if (("INSECURE" in conf) && line_map[FNR] ~ /^\#?SECURE$/) { - # INSECURE goes where SECURE comment is. - print_confs("INSECURE") - } - } - } else { - word = first($0, EQS) - value = rest($0, EQS) - sub(/[ \t]*\#.*$/, "", value) # ignore comments in value - - if ((word in conf) && value == first(conf[word])) { - # keep config options we want - conf_pop(word) - print - } - - if ((FNR in line_map) && line_map[FNR] == word) { - # rest of config options should be here - print_confs(word) - } - } -} - -END { - # print rest of config options ( - for (word in conf) print_confs(word) -} -' "${dma_conf}" "${dma_conf}" <<'EOF' >"${dma_conf}.tmp" \ - && mv "${dma_conf}.tmp" "${dma_conf}" + cat <'${dma_conf}.tmp' \ +&& cat '${dma_conf}.tmp' >'${dma_conf}' +${conf_should} EOF - # Pass in "conf_should" via stdin - echo "${conf_should}" - echo 'EOF' +rm '${dma_conf}.tmp' +CODE config_updated=true echo 'config updated' >>"${__messages_out}"