devstack/inc/ini-config
Nobuhiro MIKI d266c87b1d iniset: fix handling of values containg ampersand
Attempting to set a value containing the ampersand
character (&) by iniset would corrupt the value.
So, add an escaping process.

Signed-off-by: Nobuhiro MIKI <nmiki@yahoo-corp.jp>
Closes-Bug: #1983816
Change-Id: Ie2633bacd2d761d110e6cb12f95382325c329415
2022-08-08 18:59:53 +09:00

457 lines
12 KiB
Bash

#!/bin/bash
#
# **inc/ini-config** - Configuration/INI functions
#
# Support for manipulating INI-style configuration files
#
# These functions have no external dependencies and no side-effects
# Save trace setting
INC_CONF_TRACE=$(set +o | grep xtrace)
set +o xtrace
# Config Functions
# ================
# Append a new option in an ini file without replacing the old value
# iniadd [-sudo] config-file section option value1 value2 value3 ...
function iniadd {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sudo=""
if [ $1 == "-sudo" ]; then
sudo="-sudo "
shift
fi
local file=$1
local section=$2
local option=$3
shift 3
local values
values="$(iniget_multiline $file $section $option) $@"
iniset_multiline $sudo $file $section $option $values
$xtrace
}
# Comment an option in an INI file
# inicomment [-sudo] config-file section option
function inicomment {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sudo=""
if [ $1 == "-sudo" ]; then
sudo="sudo "
shift
fi
local file=$1
local section=$2
local option=$3
$sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" "$file"
$xtrace
}
# Get an option from an INI file
# iniget config-file section option
function iniget {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local file=$1
local section=$2
local option=$3
local line
line=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
echo ${line#*=}
$xtrace
}
# Get a multiple line option from an INI file
# iniget_multiline config-file section option
function iniget_multiline {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local file=$1
local section=$2
local option=$3
local values
values=$(sed -ne "/^\[$section\]/,/^\[.*\]/ { s/^$option[ \t]*=[ \t]*//gp; }" "$file")
echo ${values}
$xtrace
}
# Determinate is the given option present in the INI file
# ini_has_option [-sudo] config-file section option
function ini_has_option {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sudo=""
if [ $1 == "-sudo" ]; then
sudo="sudo "
shift
fi
local file=$1
local section=$2
local option=$3
local line
line=$($sudo sed -ne "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ p; }" "$file")
$xtrace
[ -n "$line" ]
}
# Add another config line for a multi-line option.
# It's normally called after iniset of the same option and assumes
# that the section already exists.
#
# Note that iniset_multiline requires all the 'lines' to be supplied
# in the argument list. Doing that will cause incorrect configuration
# if spaces are used in the config values.
#
# iniadd_literal [-sudo] config-file section option value
function iniadd_literal {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sudo=""
if [ $1 == "-sudo" ]; then
sudo="sudo "
shift
fi
local file=$1
local section=$2
local option=$3
local value=$4
if [[ -z $section || -z $option ]]; then
$xtrace
return
fi
# Add it
$sudo sed -i -e "/^\[$section\]/ a\\
$option = $value
" "$file"
$xtrace
}
# Remove an option from an INI file
# inidelete [-sudo] config-file section option
function inidelete {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sudo=""
if [ $1 == "-sudo" ]; then
sudo="sudo "
shift
fi
local file=$1
local section=$2
local option=$3
if [[ -z $section || -z $option ]]; then
$xtrace
return
fi
# Remove old values
$sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
$xtrace
}
# Set an option in an INI file
# iniset [-sudo] config-file section option value
# - if the file does not exist, it is created
function iniset {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sudo=""
local sudo_option=""
if [ $1 == "-sudo" ]; then
sudo="sudo "
sudo_option="-sudo "
shift
fi
local file=$1
local section=$2
local option=$3
local value=$4
# Escape the ampersand character (&)
value=$(echo $value | sed -e 's/&/\\&/g')
if [[ -z $section || -z $option ]]; then
$xtrace
return
fi
if ! $sudo grep -q "^\[$section\]" "$file" 2>/dev/null; then
# Add section at the end
echo -e "\n[$section]" | $sudo tee --append "$file" > /dev/null
fi
if ! ini_has_option $sudo_option "$file" "$section" "$option"; then
# Add it
$sudo sed -i -e "/^\[$section\]/ a\\
$option = $value
" "$file"
else
local sep
sep=$(echo -ne "\x01")
# Replace it
$sudo sed -i -e '/^\['${section}'\]/,/^\[.*\]/ s'${sep}'^\('"${option}"'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file"
fi
$xtrace
}
# Set a multiple line option in an INI file
# iniset_multiline [-sudo] config-file section option value1 value2 value3 ...
function iniset_multiline {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sudo=""
if [ $1 == "-sudo" ]; then
sudo="sudo "
shift
fi
local file=$1
local section=$2
local option=$3
shift 3
local values
for v in $@; do
# The later sed command inserts each new value in the line next to
# the section identifier, which causes the values to be inserted in
# the reverse order. Do a reverse here to keep the original order.
values="$v ${values}"
done
if ! $sudo grep -q "^\[$section\]" "$file"; then
# Add section at the end
echo -e "\n[$section]" | $sudo tee --append "$file" > /dev/null
else
# Remove old values
$sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
fi
# Add new ones
for v in $values; do
$sudo sed -i -e "/^\[$section\]/ a\\
$option = $v
" "$file"
done
$xtrace
}
# Uncomment an option in an INI file
# iniuncomment config-file section option
function iniuncomment {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sudo=""
if [ $1 == "-sudo" ]; then
sudo="sudo "
shift
fi
local file=$1
local section=$2
local option=$3
$sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" "$file"
$xtrace
}
# Get list of sections from an INI file
# iniget_sections config-file
function iniget_sections {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local file=$1
echo $(sed -ne "s/^\[\(.*\)\]/\1/p" "$file")
$xtrace
}
# Set a localrc var
function localrc_set {
local file=$1
local group="local"
local conf="localrc"
local section=""
local option=$2
local value=$3
localconf_set "$file" "$group" "$conf" "$section" "$option" "$value"
}
# Check if local.conf has section.
function localconf_has_section {
local file=$1
local group=$2
local conf=$3
local section=$4
local sep
sep=$(echo -ne "\x01")
local line
line=$(sed -ne "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
/\[${section}\]/p
}" "$file")
[ -n "$line" ]
}
# Check if local.conf has option.
function localconf_has_option {
local file=$1
local group=$2
local conf=$3
local section=$4
local option=$5
local sep
sep=$(echo -ne "\x01")
local line
if [[ -z "$section" ]]; then
line=$(sed -ne "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
/${option}[ \t]*=.*$/p
}" "$file")
else
line=$(sed -ne "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
/\[${section}\]/,/\[\[.*\]\]\|\[.*\]/{
/${option}[ \t]*=.*$/p}
}" "$file")
fi
[ -n "$line" ]
}
# Update option in local.conf.
function localconf_update_option {
local sudo=$1
local file=$2
local group=$3
local conf=$4
local section=$5
local option=$6
local value=$7
local sep
sep=$(echo -ne "\x01")
if [[ -z "$section" ]]; then
$sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
s${sep}^\(${option}[ \t]*=[ \t]*\).*\$${sep}\1${value}${sep}
}" "$file"
else
$sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
/\[${section}\]/,/\[\[.*\]\]\|\[.*\]/s${sep}^\(${option}[ \t]*=[ \t]*\).*\$${sep}\1${value}${sep}
}" "$file"
fi
}
# Add option in local.conf.
function localconf_add_option {
local sudo=$1
local file=$2
local group=$3
local conf=$4
local section=$5
local option=$6
local value=$7
local sep
sep=$(echo -ne "\x01")
if [[ -z "$section" ]]; then
$sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep} a $option=$value" "$file"
else
$sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep},\\${sep}\[\[.*\]\]${sep}{
/\[${section}\]/ a $option=$value
}" "$file"
fi
}
# Add section and option in local.conf.
function localconf_add_section_and_option {
local sudo=$1
local file=$2
local group=$3
local conf=$4
local section=$5
local option=$6
local value=$7
local sep
sep=$(echo -ne "\x01")
$sudo sed -i -e "\\${sep}^\[\[${group}|${conf}\]\]${sep} {
a [$section]
a $option=$value
}" "$file"
}
# Set an option in a local.conf file.
# localconf_set [-sudo] config-file group conf-name section option value
# - if the file does not exist, it is created
function localconf_set {
local xtrace
xtrace=$(set +o | grep xtrace)
set +o xtrace
local sep
sep=$(echo -ne "\x01")
local sudo=""
if [ $1 == "-sudo" ]; then
sudo="sudo "
shift
fi
local file=$1
local group=$2
local conf=$3
local section=$4
local option=$5
local value=$6
if [[ -z $group || -z $conf || -z $option || -z $value ]]; then
$xtrace
return
fi
if ! grep -q "^\[\[${group}|${conf}\]\]" "$file" 2>/dev/null; then
# Add meta section at the end if it does not exist
echo -e "\n[[${group}|${conf}]]" | $sudo tee --append "$file" > /dev/null
# Add section at the end
if [[ -n "$section" ]]; then
echo -e "[$section]" | $sudo tee --append "$file" > /dev/null
fi
# Add option at the end
echo -e "$option=$value" | $sudo tee --append "$file" > /dev/null
elif [[ -z "$section" ]]; then
if ! localconf_has_option "$file" "$group" "$conf" "$section" "$option"; then
# Add option
localconf_add_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
else
# Replace it
localconf_update_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
fi
elif ! localconf_has_section "$file" "$group" "$conf" "$section"; then
# Add section and option in specified meta section
localconf_add_section_and_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
elif ! localconf_has_option "$file" "$group" "$conf" "$section" "$option"; then
# Add option
localconf_add_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
else
# Replace it
localconf_update_option "$sudo" "$file" "$group" "$conf" "$section" "$option" "$value"
fi
$xtrace
}
# Restore xtrace
$INC_CONF_TRACE
# Local variables:
# mode: shell-script
# End: