fix(install): stop initUpdateConfigOption choking on '|' chars in comments
initUpdateConfigOption (init.sh) and commandUpdateConfigOption (the CLI
wrapper heredoc) both rewrite CFG_<NAME>= lines with a sed s-command
using `|` as the delimiter. The escaping covered only `/` and `&` in
$escaped_value, and $comment_part wasn't escaped at all — so any line
whose comment contains a literal `|` blew up the substitution:
sed: -e expression #1, char 167: unknown option to `s'
The trigger in the install log is the CFG_INSTALL_MODE comment:
# Installation Mode - ... [release:Release tarball (recommended)|git:Git clone (dev)|local:Local folder (dev)]
Two sed errors in install-20260526-223006.log, both same line — once
from initUpdateConfigOption during the initial-values pass, once from
the CFG_INSTALL_MODE re-set later. The substitution silently failed
(line not rewritten) and the install continued.
Switch the delimiter to SOH (\x01). Text-based config values + comments
never contain that byte, so the delimiter never needs to be escaped.
Only `&` (whole-match insertion in the replacement) and `\` (escape
char) remain hazardous in the replacement field, and BOTH are now
neutralised in $escaped_value AND in $comment_part.
Verified against the actual offending line: the old form reproduces
`sed: unknown option to 's'` at char 165; the new form rewrites cleanly
with every `|` in the comment preserved.
Same fix applied to both functions — initUpdateConfigOption lives at
install-time, commandUpdateConfigOption is baked into the CLI wrapper
at /usr/local/lib/libreportal/libreportal; new installs pick up both
from this commit.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Signed-off-by: librelad <librelad@digitalangels.vip>
This commit is contained in:
parent
c4ec01204b
commit
fd6f22e512
33
init.sh
33
init.sh
@ -338,14 +338,23 @@ initUpdateConfigOption() {
|
|||||||
for config_file in "$category_dir"/*; do
|
for config_file in "$category_dir"/*; do
|
||||||
if [ -f "$config_file" ] && [[ ! "$config_file" =~ \.category$ ]]; then
|
if [ -f "$config_file" ] && [[ ! "$config_file" =~ \.category$ ]]; then
|
||||||
if grep -q "^$config_option=" "$config_file"; then
|
if grep -q "^$config_option=" "$config_file"; then
|
||||||
local escaped_value=$(printf '%s\n' "$config_value" | sed -e 's/[\/&]/\\&/g')
|
# Use SOH (\x01) as the s-command delimiter — it can't appear
|
||||||
|
# in text-based config values or comments, so no field needs
|
||||||
|
# to escape the delimiter. The replacement field DOES need
|
||||||
|
# `&` (whole-match insertion) and `\` (escape char) neutralised
|
||||||
|
# in BOTH the value AND the comment — comments like
|
||||||
|
# `# Installation Mode - ...[release|git|local]` previously
|
||||||
|
# broke the `|`-delimited form with "unknown option to `s'".
|
||||||
|
local DELIM=$'\x01'
|
||||||
|
local escaped_value=$(printf '%s' "$config_value" | sed -e 's/[\\&]/\\&/g')
|
||||||
local original_line=$(grep "^$config_option=" "$config_file")
|
local original_line=$(grep "^$config_option=" "$config_file")
|
||||||
local comment_part=$(echo "$original_line" | sed -n "s|^$config_option=[^#]*\(#.*\)|\1|p")
|
local comment_part=$(echo "$original_line" | sed -n "s|^$config_option=[^#]*\(#.*\)|\1|p")
|
||||||
|
local escaped_comment=$(printf '%s' "$comment_part" | sed -e 's/[\\&]/\\&/g')
|
||||||
|
|
||||||
if [[ -n "$comment_part" ]]; then
|
if [[ -n "$comment_part" ]]; then
|
||||||
sed -i "s|^$config_option=.*|$config_option=$escaped_value $comment_part|" "$config_file"
|
sed -i "s${DELIM}^$config_option=.*${DELIM}$config_option=$escaped_value $escaped_comment${DELIM}" "$config_file"
|
||||||
else
|
else
|
||||||
sed -i "s|^$config_option=.*|$config_option=$escaped_value|" "$config_file"
|
sed -i "s${DELIM}^$config_option=.*${DELIM}$config_option=$escaped_value${DELIM}" "$config_file"
|
||||||
fi
|
fi
|
||||||
source "$config_file"
|
source "$config_file"
|
||||||
return 0
|
return 0
|
||||||
@ -1249,18 +1258,24 @@ commandUpdateConfigOption() {
|
|||||||
for config_file in "$category_dir"/*; do
|
for config_file in "$category_dir"/*; do
|
||||||
if [ -f "$config_file" ] && [[ ! "$config_file" =~ \.category$ ]]; then
|
if [ -f "$config_file" ] && [[ ! "$config_file" =~ \.category$ ]]; then
|
||||||
if grep -q "^$config_option=" "$config_file"; then
|
if grep -q "^$config_option=" "$config_file"; then
|
||||||
# Escape special characters in the config value to prevent sed issues
|
# Use SOH (\x01) as the s-command delimiter — it can't appear
|
||||||
local escaped_value=$(printf '%s\n' "$config_value" | sed -e 's/[\/&]/\\&/g')
|
# in text-based config values or comments, so no field needs
|
||||||
|
# to escape the delimiter. The replacement field DOES need
|
||||||
|
# `&` (whole-match insertion) and `\` (escape char) neutralised
|
||||||
|
# in BOTH the value AND the comment — comments like
|
||||||
|
# `# Installation Mode - ...[release|git|local]` previously
|
||||||
|
# broke the `|`-delimited form with "unknown option to `s'".
|
||||||
|
local DELIM=$'\x01'
|
||||||
|
local escaped_value=$(printf '%s' "$config_value" | sed -e 's/[\\&]/\\&/g')
|
||||||
|
|
||||||
# Extract the comment part first (everything after the first #)
|
# Extract the comment part first (everything after the first #)
|
||||||
local original_line=$(grep "^$config_option=" "$config_file")
|
local original_line=$(grep "^$config_option=" "$config_file")
|
||||||
local comment_part=$(echo "$original_line" | sed -n "s|^$config_option=[^#]*\(#.*\)|\1|p")
|
local comment_part=$(echo "$original_line" | sed -n "s|^$config_option=[^#]*\(#.*\)|\1|p")
|
||||||
|
local escaped_comment=$(printf '%s' "$comment_part" | sed -e 's/[\\&]/\\&/g')
|
||||||
# Replace the value, preserving comment if it existed
|
|
||||||
if [[ -n "$comment_part" ]]; then
|
if [[ -n "$comment_part" ]]; then
|
||||||
sed -i "s|^$config_option=.*|$config_option=$escaped_value $comment_part|" "$config_file"
|
sed -i "s${DELIM}^$config_option=.*${DELIM}$config_option=$escaped_value $escaped_comment${DELIM}" "$config_file"
|
||||||
else
|
else
|
||||||
sed -i "s|^$config_option=.*|$config_option=$escaped_value|" "$config_file"
|
sed -i "s${DELIM}^$config_option=.*${DELIM}$config_option=$escaped_value${DELIM}" "$config_file"
|
||||||
fi
|
fi
|
||||||
source "$config_file"
|
source "$config_file"
|
||||||
return 0
|
return 0
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user