secured some implementation, check bash version
This commit is contained in:
85
profile.sh
85
profile.sh
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# Begin profile
|
# Begin profile
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Copyright (c) 2013-2022 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
|
# Copyright (c) 2013-2026 Geoffray Levasseur <fatalerrors@geoffray-levasseur.org>
|
||||||
# Protected by the BSD3 license. Please read bellow for details.
|
# Protected by the BSD3 license. Please read bellow for details.
|
||||||
#
|
#
|
||||||
# * Redistribution and use in source and binary forms,
|
# * Redistribution and use in source and binary forms,
|
||||||
@@ -35,12 +35,19 @@
|
|||||||
# * OF SUCH DAMAGE.
|
# * OF SUCH DAMAGE.
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
if [[ ! $SHELL =~ bash|zsh ]]; then
|
if [[ ! $SHELL =~ bash ]]; then
|
||||||
echo "That environment script is designed to be used with bash or zsh being the shell."
|
echo "That environment script is designed to be used with bash being the shell."
|
||||||
echo "Please consider using bash or zsh instead, or patch me ;)!"
|
echo "Please consider using bash to enjoy our features!"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# Required for associative arrays (4.0+) and namerefs (4.3+)
|
||||||
|
if ((BASH_VERSINFO[0] < 4)) || [[ ${BASH_VERSINFO[0]} -eq 4 && ${BASH_VERSINFO[1]} -lt 3 ]]; then
|
||||||
|
echo "[ Error ] This profile requires Bash 4.3 or higher."
|
||||||
|
echo "Current version: $BASH_VERSION"
|
||||||
|
return 1 2>/dev/null || exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# path* : private functions for PATH variable management
|
# path* : private functions for PATH variable management
|
||||||
pathremove()
|
pathremove()
|
||||||
@@ -79,37 +86,43 @@ parse_conf()
|
|||||||
{
|
{
|
||||||
local config_file="$1"
|
local config_file="$1"
|
||||||
local current_section=""
|
local current_section=""
|
||||||
|
local line key value
|
||||||
|
|
||||||
[[ ! -f "$config_file" ]] && return 1
|
[[ ! -f "$config_file" ]] && return 1
|
||||||
|
|
||||||
while IFS='=' read -r key value || [[ -n "$key" ]]; do
|
while IFS='=' read -r key value || [[ -n "$key" ]]; do
|
||||||
# Clean key and value (strip CR and whitespace)
|
# Internal trimming (removes leading/trailing whitespace & CR)
|
||||||
key=$(printf '%s' "$key" | tr -d '\r' | xargs 2>/dev/null)
|
key="${key%"${key##*[![:space:]]}"}"
|
||||||
value=$(printf '%s' "$value" | tr -d '\r' | xargs 2>/dev/null)
|
key="${key#"${key%%[![:space:]]*}"}"
|
||||||
|
key="${key%$'\r'}" # Strip potential Windows line endings
|
||||||
|
|
||||||
# Skip comments and empty lines
|
# Skip comments and empty lines
|
||||||
[[ -z "$key" || "$key" =~ ^[#\;] ]] && continue
|
[[ -z "$key" || "$key" =~ ^[#\;] ]] && continue
|
||||||
|
|
||||||
# Section Detection: [section_name]
|
# Section Detection: [section_name]
|
||||||
if [[ "$key" =~ ^\[(.*)\]$ ]]; then
|
if [[ "$key" =~ ^\[([a-zA-Z0-9_]+)\]$ ]]; then
|
||||||
current_section="${BASH_REMATCH[1]}"
|
current_section="${BASH_REMATCH[1]}"
|
||||||
# Dynamically declare the associative array for this section
|
|
||||||
declare -g -A "CONF_$current_section"
|
declare -g -A "CONF_$current_section"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# If we have a key/value pair and are inside a section
|
# Secure Assignment (if inside a section)
|
||||||
if [[ -n "$current_section" && -n "$value" ]]; then
|
if [[ -n "$current_section" ]]; then
|
||||||
# Strip quotes from value
|
# Clean the value
|
||||||
|
value="${value%"${value##*[![:space:]]}"}"
|
||||||
|
value="${value#"${value%%[![:space:]]*}"}"
|
||||||
|
value="${value%$'\r'}"
|
||||||
|
|
||||||
|
# Strip quotes (handling both " and ')
|
||||||
value="${value%\"}"; value="${value#\"}"
|
value="${value%\"}"; value="${value#\"}"
|
||||||
value="${value%\'}"; value="${value#\'}"
|
value="${value%\'}"; value="${value#\'}"
|
||||||
|
|
||||||
# Store in the dynamic array: CONF_sectionname[key]=value
|
# Use a nameref for safe, eval-free assignment
|
||||||
eval "CONF_${current_section}['$key']='$value'"
|
local -n current_array="CONF_$current_section"
|
||||||
|
current_array["$key"]="$value"
|
||||||
fi
|
fi
|
||||||
done < "$config_file"
|
done < "$config_file"
|
||||||
}
|
}# ------------------------------------------------------------------------------
|
||||||
# ------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -118,20 +131,20 @@ load_alias()
|
|||||||
{
|
{
|
||||||
local section_name="CONF_$1"
|
local section_name="CONF_$1"
|
||||||
|
|
||||||
# Check if the associative array for this section exists
|
# Check if the associative array exists using declare -p
|
||||||
if [[ "$(declare -p "$section_name" 2>/dev/null)" != "declare -A"* ]]; then
|
[[ "$(declare -p "$section_name" 2>/dev/null)" != "declare -A"* ]] && return 1
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Reference the array keys
|
# Create a nameref to the section array
|
||||||
eval "local keys=\"\${!$section_name[@]}\""
|
local -n current_aliases="$section_name"
|
||||||
|
|
||||||
for key in $keys; do
|
# Iterate safely over the keys of the associative array
|
||||||
# Fetch the value for this specific key
|
for key in "${!current_aliases[@]}"; do
|
||||||
eval "local cmd=\"\${$section_name[$key]}\""
|
local cmd="${current_aliases[$key]}"
|
||||||
|
|
||||||
# Portability check: only alias if the command exists
|
# Extract the base command (first word) safely without awk
|
||||||
local base_cmd=$(echo "$cmd" | awk '{print $1}')
|
local base_cmd="${cmd%% *}"
|
||||||
|
|
||||||
|
# Only alias if the base command is executable
|
||||||
if command -v "$base_cmd" >/dev/null 2>&1; then
|
if command -v "$base_cmd" >/dev/null 2>&1; then
|
||||||
alias "$key"="$cmd"
|
alias "$key"="$cmd"
|
||||||
fi
|
fi
|
||||||
@@ -146,16 +159,14 @@ load_conf()
|
|||||||
{
|
{
|
||||||
local section_name="CONF_$1"
|
local section_name="CONF_$1"
|
||||||
|
|
||||||
if [[ "$(declare -p "$section_name" 2>/dev/null)" != "declare -A"* ]]; then
|
[[ "$(declare -p "$section_name" 2>/dev/null)" != "declare -A"* ]] && return 1
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
eval "local keys=\"\${!$section_name[@]}\""
|
local -n current_vars="$section_name"
|
||||||
|
|
||||||
for key in $keys; do
|
for key in "${!current_vars[@]}"; do
|
||||||
eval "local val=\"\${$section_name[$key]}\""
|
# Export the key/value pair as a standard shell variable
|
||||||
# Export as a standard shell variable
|
# We use 'export' directly; Bash handles the assignment safely here
|
||||||
export "$key"="$val"
|
export "$key"="${current_vars[$key]}"
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -168,8 +179,10 @@ load_conf()
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# Store script's path (realpath -s resolve symlinks if profile.sh is a symlink)
|
# Store script's path (realpath -s resolve symlinks if profile.sh is a symlink)
|
||||||
|
# Because we're more likely to be sourced, we use BASH_SOURCE to get the path
|
||||||
|
# of the sourced file instead of $0
|
||||||
if [[ -z "$PROFILE_PATH" ]]; then
|
if [[ -z "$PROFILE_PATH" ]]; then
|
||||||
export MYPATH=$(dirname "$(realpath -s "$0")")
|
export MYPATH=$(dirname "$(realpath -s "${BASH_SOURCE[0]}")")
|
||||||
else
|
else
|
||||||
export MYPATH="$PROFILE_PATH"
|
export MYPATH="$PROFILE_PATH"
|
||||||
fi
|
fi
|
||||||
|
|||||||
Reference in New Issue
Block a user