mirror of
https://github.com/RetroPie/RetroPie-Setup.git
synced 2025-04-02 10:51:41 -04:00
235 lines
7.5 KiB
Bash
Executable file
235 lines
7.5 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
# This file is part of The RetroPie Project
|
|
#
|
|
# The RetroPie Project is the legal property of its developers, whose names are
|
|
# too numerous to list here. Please refer to the COPYRIGHT.md file distributed with this source.
|
|
#
|
|
# See the LICENSE.md file at the top-level directory of this distribution and
|
|
# at https://raw.githubusercontent.com/RetroPie/RetroPie-Setup/master/LICENSE.md
|
|
#
|
|
|
|
## @file inifuncs.sh
|
|
## @brief RetroPie inifuncs library
|
|
## @copyright GPLv3
|
|
|
|
# @fn fatalError()
|
|
# @param message string or array of messages to display
|
|
# @brief echos message, and exits immediately.
|
|
function fatalError() {
|
|
echo -e "$1"
|
|
exit 1
|
|
}
|
|
|
|
# arg 1: delimiter, arg 2: quote, arg 3: file
|
|
|
|
## @fn iniConfig()
|
|
## @param delim ini file delimiter eg. ' = '
|
|
## @param quote ini file quoting character eg. '"'
|
|
## @param config ini file to edit
|
|
## @brief Configure an ini file for getting/setting values with `iniGet` and `iniSet`
|
|
function iniConfig() {
|
|
__ini_cfg_delim="$1"
|
|
__ini_cfg_quote="$2"
|
|
__ini_cfg_file="$3"
|
|
}
|
|
|
|
# arg 1: command, arg 2: key, arg 3: value, arg 4: file (optional - uses file from iniConfig if not used)
|
|
|
|
# @fn iniProcess()
|
|
# @param command `set`, `unset` or `del`
|
|
# @param key ini key to operate on
|
|
# @param value to set
|
|
# @param file optional file to use another file than the one configured with iniConfig
|
|
# @brief The main function for setting and deleting from ini files - usually
|
|
# not called directly but via iniSet iniUnset and iniDel
|
|
function iniProcess() {
|
|
local cmd="$1"
|
|
local key="$2"
|
|
local value="$3"
|
|
local file="$4"
|
|
[[ -z "$file" ]] && file="$__ini_cfg_file"
|
|
local delim="$__ini_cfg_delim"
|
|
local quote="$__ini_cfg_quote"
|
|
|
|
[[ -z "$file" ]] && fatalError "No file provided for ini/config change"
|
|
[[ -z "$key" ]] && fatalError "No key provided for ini/config change on $file"
|
|
|
|
# we strip the delimiter of spaces, so we can "fussy" match existing entries that have the wrong spacing
|
|
local delim_strip=${delim// /}
|
|
# if the stripped delimiter is empty - such as in the case of a space, just use the delimiter instead
|
|
[[ -z "$delim_strip" ]] && delim_strip="$delim"
|
|
local match_re="^[[:space:]#]*$key[[:space:]]*$delim_strip.*$"
|
|
|
|
local match
|
|
if [[ -f "$file" ]]; then
|
|
match=$(grep -i "$match_re" "$file" | tail -1)
|
|
else
|
|
touch "$file"
|
|
fi
|
|
|
|
if [[ "$cmd" == "del" ]]; then
|
|
[[ -n "$match" ]] && sed -i --follow-symlinks "\|$(sedQuote "$match")|d" "$file"
|
|
return 0
|
|
fi
|
|
|
|
[[ "$cmd" == "unset" ]] && key="# $key"
|
|
|
|
local replace="$key$delim$quote$value$quote"
|
|
if [[ -z "$match" ]]; then
|
|
# make sure there is a newline then add the key-value pair
|
|
sed -i --follow-symlinks '$a\' "$file"
|
|
echo "$replace" >> "$file"
|
|
else
|
|
# replace existing key-value pair
|
|
sed -i --follow-symlinks "s|$(sedQuote "$match")|$(sedQuote "$replace")|g" "$file"
|
|
fi
|
|
|
|
[[ "$file" =~ retroarch\.cfg$ ]] && retroarchIncludeToEnd "$file"
|
|
return 0
|
|
}
|
|
|
|
## @fn iniUnset()
|
|
## @param key ini key to operate on
|
|
## @param value to Unset (key will be commented out, but the value can be changed also)
|
|
## @param file optional file to use another file than the one configured with iniConfig
|
|
## @brief Unset (comment out) a key / value pair in an ini file.
|
|
## @details The key does not have to exist - if it doesn't exist a new line will
|
|
## be added - eg. `# key = "value"`
|
|
##
|
|
## This function is useful for creating example configuration entries for users
|
|
## to manually enable later or if a configuration is to be disabled but left
|
|
## as an example.
|
|
function iniUnset() {
|
|
iniProcess "unset" "$1" "$2" "$3"
|
|
}
|
|
|
|
## @fn iniSet()
|
|
## @param key ini key to operate on
|
|
## @param value to set
|
|
## @param file optional file to use another file than the one configured with iniConfig
|
|
## @brief Set a key / value pair in an ini file.
|
|
## @details If the key already exists the existing line will be changed. If not
|
|
## a new line will be created.
|
|
function iniSet() {
|
|
iniProcess "set" "$1" "$2" "$3"
|
|
}
|
|
|
|
## @fn iniDel()
|
|
## @param key ini key to operate on
|
|
## @param file optional file to use another file than the one configured with iniConfig
|
|
## @brief Delete a key / value pair in an ini file.
|
|
function iniDel() {
|
|
iniProcess "del" "$1" "" "$2"
|
|
}
|
|
|
|
## @fn iniGet()
|
|
## @param key ini key to get the value of
|
|
## @param file optional file to use another file than the one configured with iniConfig
|
|
## @brief Get the value of a key from an ini file.
|
|
## @details The value of the key will end up in the global ini_value variable.
|
|
function iniGet() {
|
|
local key="$1"
|
|
local file="$2"
|
|
[[ -z "$file" ]] && file="$__ini_cfg_file"
|
|
if [[ ! -f "$file" ]]; then
|
|
ini_value=""
|
|
return 1
|
|
fi
|
|
|
|
local delim="$__ini_cfg_delim"
|
|
local quote="$__ini_cfg_quote"
|
|
# we strip the delimiter of spaces, so we can "fussy" match existing entries that have the wrong spacing
|
|
local delim_strip=${delim// /}
|
|
# if the stripped delimiter is empty - such as in the case of a space, just use the delimiter instead
|
|
[[ -z "$delim_strip" ]] && delim_strip="$delim"
|
|
|
|
# create a regexp to match the value based on whether we are looking for quotes or not
|
|
local value_m
|
|
if [[ -n "$quote" ]]; then
|
|
value_m="$quote*\([^$quote|\r]*\)$quote*"
|
|
else
|
|
value_m="\([^\r]*\)"
|
|
fi
|
|
|
|
ini_value="$(sed -n "s#^[ |\t]*$key[ |\t]*$delim_strip[ |\t]*$value_m.*#\1#p" "$file" | tail -1)"
|
|
}
|
|
|
|
# @fn retroarchIncludeToEnd()
|
|
# @param file config file to process
|
|
# @brief Makes sure a `retroarch.cfg` file has the `#include` line at the end.
|
|
# @details Used in runcommand.sh and iniProcess to ensure the #include for the
|
|
# main retroarch.cfg is always at the end of a system `retroarch.cfg`. This
|
|
# is because when processing its config RetroArch will take the first value it
|
|
# finds, so any overrides need to be above the `#include` line where the global
|
|
# retroarch.cfg is included.
|
|
function retroarchIncludeToEnd() {
|
|
local config="$1"
|
|
|
|
[[ ! -f "$config" ]] && return
|
|
|
|
local re="^#include.*retroarch\.cfg"
|
|
|
|
# extract the include line (unless it is the last line in the file)
|
|
# (remove blank lines, the last line and search for an include line in remaining lines)
|
|
local include=$(sed '/^$/d;$d' "$config" | grep "$re")
|
|
|
|
# if matched remove it and re-add it at the end
|
|
if [[ -n "$include" ]]; then
|
|
sed -i --follow-symlinks "/$re/d" "$config"
|
|
# add newline if missing and the #include line
|
|
sed -i --follow-symlinks '$a\' "$config"
|
|
echo "$include" >>"$config"
|
|
fi
|
|
}
|
|
|
|
# arg 1: key, arg 2: default value (optional - is 1 if not used)
|
|
function addAutoConf() {
|
|
local key="$1"
|
|
local default="$2"
|
|
local file="$configdir/all/autoconf.cfg"
|
|
|
|
if [[ -z "$default" ]]; then
|
|
default="1"
|
|
fi
|
|
|
|
iniConfig " = " '"' "$file"
|
|
iniGet "$key"
|
|
ini_value="${ini_value// /}"
|
|
if [[ -z "$ini_value" ]]; then
|
|
iniSet "$key" "$default"
|
|
chown "$__user":"$__group" "$file"
|
|
fi
|
|
}
|
|
|
|
# arg 1: key, arg 2: value
|
|
function setAutoConf() {
|
|
local key="$1"
|
|
local value="$2"
|
|
local file="$configdir/all/autoconf.cfg"
|
|
|
|
iniConfig " = " '"' "$file"
|
|
iniSet "$key" "$value"
|
|
chown "$__user":"$__group" "$file"
|
|
}
|
|
|
|
# arg 1: key
|
|
function getAutoConf(){
|
|
local key="$1"
|
|
|
|
iniConfig " = " '"' "$configdir/all/autoconf.cfg"
|
|
iniGet "$key"
|
|
|
|
[[ "$ini_value" == "1" ]] && return 0
|
|
return 1
|
|
}
|
|
|
|
# escape special characters for sed
|
|
function sedQuote() {
|
|
local string="$1"
|
|
string="${string//\\/\\\\}"
|
|
string="${string//|/\\|}"
|
|
string="${string//[/\\[}"
|
|
string="${string//]/\\]}"
|
|
echo "$string"
|
|
}
|