#!/bin/sh set -eu if [ "$#" -ne 2 ]; then echo "Usage: $0 ENV_FILE VALUES_FILE" >&2 exit 1 fi env_file=$1 values_file=$2 if [ ! -f "$env_file" ]; then echo "Environment file does not exist: $env_file" >&2 exit 1 fi if [ ! -f "$values_file" ]; then echo "Values file does not exist: $values_file" >&2 exit 1 fi if [ "$(stat -c '%a' "$env_file")" != 600 ]; then echo "Environment file must have mode 0600: $env_file" >&2 exit 1 fi case "$(stat -c '%a' "$values_file")" in 400|600) ;; *) echo "Values file must have mode 0400 or 0600: $values_file" >&2 exit 1 ;; esac env_dir=$(CDPATH='' cd -- "$(dirname -- "$env_file")" && pwd) env_name=$(basename -- "$env_file") temporary_env=$(mktemp "$env_dir/$env_name.tmp.XXXXXX") trap 'rm -f "$temporary_env"' EXIT HUP INT TERM chmod 600 "$temporary_env" if ! awk ' BEGIN { FS = "=" reading_values = 1 } FNR == 1 && NR != 1 { reading_values = 0 } reading_values { key = $1 if (key !~ /^[A-Z][A-Z0-9_]*$/ || key in replacement) { exit 40 } value = substr($0, index($0, "=") + 1) gsub(/\$/, "$$", value) replacement[key] = value replacement_count++ next } { separator = index($0, "=") if (separator > 1) { key = substr($0, 1, separator - 1) if (key in replacement) { seen[key]++ print key "=" replacement[key] next } } print } END { if (replacement_count == 0) { exit 41 } for (key in replacement) { if (seen[key] != 1) { exit 42 } } } ' "$values_file" "$env_file" >"$temporary_env"; then echo "Refusing to update the environment: values must use unique KEY=VALUE lines and every key must already occur exactly once." >&2 exit 1 fi mv "$temporary_env" "$env_file" trap - EXIT HUP INT TERM echo "Environment values updated without printing their contents: $env_file"