+ for table in "$@"; do
+ case "$table" in ?*) ;; *) continue ;; esac
+ while read -r name omit pat; do
+ eval foundp=\${$prefix$name+t}
+ case "$foundp,$omit" in
+ ,t) continue ;;
+ ,nil)
+ echo >&2 "$quis: missing $whatprop \`$name' required"
+ exit 1
+ ;;
+ esac
+ eval value=\$$prefix$name
+ check "value for $whatprop \`$name'" "$pat" "$value"
+ done <<EOF
+$table
+EOF
+ done
+}
+
+dumpprops () {
+ prefix=$1
+ ## Write the properties stored in the variables beginning with PREFIX.
+
+ set | sed -n "/^$prefix/{s/=.*\$//;p}" | sort | while read name; do
+ eval value=\$$name
+ echo "${name#$prefix}=$value"
+ done
+}
+
+defprops () {
+ name=$1
+ ## Define a properties table NAME.
+
+ table=$(cat)
+ eval $name=\$table
+}
+
+defprops g_props <<EOF
+type nil $R_IDENT
+recovery t $R_WORDSEQ
+random t $R_WORD
+nub_hash t $R_WORD
+nubid_hash t $R_WORD
+nub_random_bytes t $R_NUMERIC
+acl_encrypt t $R_ACL
+acl_decrypt t $R_ACL
+acl_sign t $R_ACL
+acl_verify t $R_ACL
+acl_info t $R_ACL
+EOF
+
+readprops () {
+ file=$1
+ ## Read a profile from a file. This doesn't check the form of the
+ ## filename, so it's not suitable for unchecked input. Properties are set
+ ## using `setprops' with prefix `kprop_'.
+
+ ## Parse the settings from the file.
+ exec 3<"$file"
+ while read line; do
+ case "$line" in "" | \#*) continue ;; esac
+ setprops "property" kprop_ "$line"
+ done <&3
+ exec 3>&-
+ checkprops "property" kprop_ "$g_props"
+
+ ## Fetch the key-type handling library.
+ if [ ! -f $KEYSLIB/ktype.$kprop_type ]; then
+ echo >&2 "$quis: unknown key type \`$kprop_type'"
+ exit 1
+ fi
+ . $KEYSLIB/ktype.$kprop_type
+ checkprops "property" kprop_ "$k_props"
+}
+
+readmeta () {
+ kdir=$1
+ ## Read key metadata from KDIR.
+
+ { read profile; } <"$kdir"/meta
+}
+
+makenub () {
+ ## Generate a key nub in the default way, and write it to standard output.
+ ## The properties `random', `nub_random_bytes' and `nub_hash' are referred
+ ## to.
+
+ dd 2>/dev/null \
+ if=/dev/${kprop_random-random} bs=1 count=${kprop_nub_random_bytes-64} |
+ openssl dgst -${kprop_nub_hash-sha256} -binary |
+ openssl base64
+}
+
+nubid () {
+ ## Compute a hash of the key nub in stdin, and write it to stdout in hex.
+ ## The property `nubid_hash' is used.
+
+ ## Stupid dance because the output incompatibly grew a filename, in order
+ ## to demonstrate the same idiocy as GNU mumblesum.
+ set _ $({ echo "distorted-keys nubid"; cat -; } |
+ openssl dgst -${kprop_nubid_hash-sha256})
+ if [ $# -gt 2 ]; then shift; fi
+ echo $2
+}
+
+subst () {
+ what=$1 templ=$2 prefix=$3 pat=$4
+ ## Substitute option values into the template TEMPL. Each occurrence of
+ ## %{VAR} is replaced by the value of the variable PREFIXVAR. Finally, an
+ ## error is reported unless the final value matches the regular expression
+ ## PAT.
+
+ out=""
+ rest=$templ
+ while :; do
+
+ ## If there are no more markers to substitute, then finish.
+ case "$rest" in *"%{"*"}"*) ;; *) out=$out$rest; break ;; esac
+
+ ## Split the template into three parts.
+ left=${rest%%\%\{*} right=${rest#*\%\{}
+ var=${right%%\}*} rest=${right#*\}}
+ case "$var" in
+ *-*) default=${var#*-} var=${var%%-*} defaultp=t ;;
+ *) defaultp=nil ;;
+ esac
+
+ ## Find the variable value.
+ checkident "template variable name" "$var"
+ eval foundp=\${$prefix$var+t}
+ case $foundp,$defaultp in
+ t,*) eval value=\$$prefix$var ;;
+ ,t) value=$default ;;
+ *)
+ echo >&2 "$quis: option \`$var' unset, used in template \`$templ'"
+ exit 1
+ ;;
+ esac
+
+ ## Do the substitution.
+ out=$out$left$value
+ done
+
+ ## Check the final result.
+ check "$what" "$pat" "$out"
+
+ ## Done.
+ echo "$out"
+}
+
+read_profile () {
+ owner=$1 profile=$2
+ ## Read property settings from a profile. The PROFILE name has the form
+ ## [USER:]LABEL; USER defaults to OWNER. Properties are set using
+ ## `setprops' with prefix `kprop_'.
+
+ reqtmp
+ case "$profile" in
+ :*)
+ label=${profile#:} uservp=nil
+ ;;