Compare commits
10 Commits
6b85556a53
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
84e6fdd429 | ||
|
|
8fe11776cb | ||
|
|
0737d0c647 | ||
|
|
d72fa1a712 | ||
|
|
08e9e6c799 | ||
|
|
ac66e896dd | ||
|
|
0712be626b | ||
|
|
3f8b81562b | ||
|
|
96d1dc695d | ||
|
|
c039ab6ea0 |
17
profile.conf
17
profile.conf
@@ -70,26 +70,41 @@ MAKEFLAGS='-j12'
|
|||||||
PKGSOURCES='/share/src/archives'
|
PKGSOURCES='/share/src/archives'
|
||||||
|
|
||||||
[aliases]
|
[aliases]
|
||||||
|
# Aliases section is used to set user aliases, it is loaded only for
|
||||||
|
# interactive shells.
|
||||||
|
# Various ls aliases
|
||||||
ll='ls -laFh --color=auto'
|
ll='ls -laFh --color=auto'
|
||||||
la='ls -Ah --color=auto'
|
la='ls -Ah --color=auto'
|
||||||
l='ls -CF --color=auto'
|
l='ls -CF --color=auto'
|
||||||
ls='ls --color=auto'
|
ls='ls --color=auto'
|
||||||
|
|
||||||
|
# Add color to grep output
|
||||||
grep='grep --color=auto'
|
grep='grep --color=auto'
|
||||||
egrep='egrep --color=auto'
|
egrep='egrep --color=auto'
|
||||||
fgrep='fgrep --color=auto'
|
fgrep='fgrep --color=auto'
|
||||||
|
|
||||||
|
# Quick find alias
|
||||||
qfind="find . -name "
|
qfind="find . -name "
|
||||||
|
|
||||||
|
# Some alias for compiling
|
||||||
|
mk='make'
|
||||||
mkck='make check'
|
mkck='make check'
|
||||||
mkin='make install'
|
mkin='make install'
|
||||||
mkdin='make DESTDIR=$PWD/dest-install install'
|
mkdin='make DESTDIR=$PWD/dest-install install'
|
||||||
|
|
||||||
|
# ssh alias with X11 forwarding, without right restriction
|
||||||
ssh='ssh -Y'
|
ssh='ssh -Y'
|
||||||
|
|
||||||
|
# Resume mode for wget
|
||||||
wget='wget -c' # resume mode by default
|
wget='wget -c' # resume mode by default
|
||||||
myip='curl ip.appspot.com'
|
|
||||||
|
|
||||||
# Human readable by default
|
# Human readable by default
|
||||||
df='df -H'
|
df='df -H'
|
||||||
du='du -ch'
|
du='du -ch'
|
||||||
sdu='du -sk ./* | sort -n'
|
sdu='du -sk ./* | sort -n'
|
||||||
hdu='du -hs ./* | sort -H'
|
hdu='du -hs ./* | sort -H'
|
||||||
|
|
||||||
|
# Readable dmesg timestamps
|
||||||
|
dmesg='dmesg -T'
|
||||||
|
|
||||||
|
# End of profile.conf
|
||||||
|
|||||||
@@ -35,32 +35,85 @@
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# expandlist : treat wildcards in a file/directory list
|
# Expand wildcards in a file/directory list and quote the results
|
||||||
# Usage: expandlist <item1 [item2 ... itemN]>
|
# Usage: expandlist [options] <item1 [item2 ... itemN]>
|
||||||
expandlist()
|
expandlist()
|
||||||
{
|
{
|
||||||
if [[ "$1" == "-h" || "$1" == "--help" ]]; then
|
local separator=" "
|
||||||
printf "expandlist: Wraps a list of items in double quotes.\n\n"
|
local PARSED
|
||||||
printf "Usage: expandlist <item1 [item2 ... itemN]>\n\n"
|
|
||||||
|
PARSED=$(getopt -o hs:n --long help,separator:,newline -n 'expandlist' -- "$@")
|
||||||
|
if [[ $? -ne 0 ]]; then
|
||||||
|
disp E "Invalid options, use \"expandlist --help\" to display usage."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
eval set -- "$PARSED"
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help)
|
||||||
|
printf "expandlist: expand globs and wrap matched items in double quotes.\n\n"
|
||||||
|
printf "Usage: expandlist [options] <item1 [item2 ... itemN]>\n\n"
|
||||||
printf "Options:\n"
|
printf "Options:\n"
|
||||||
printf "\t-h, --help\t\tDisplay this help screen\n"
|
printf "\t-h, --help\t\tDisplay this help screen\n"
|
||||||
|
printf "\t-s, --separator SEP\tSet output separator (default: space)\n"
|
||||||
|
printf "\t-n, --newline\t\tUse a newline as separator\n"
|
||||||
return 0
|
return 0
|
||||||
|
;;
|
||||||
|
-s|--separator)
|
||||||
|
separator="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-n|--newline)
|
||||||
|
separator=$'\n'
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
disp E "Invalid options, use \"expandlist --help\" to display usage."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
local item="" result="" matched=0
|
||||||
|
shopt -s nullglob
|
||||||
|
|
||||||
|
for item in "$@"; do
|
||||||
|
local expanded=()
|
||||||
|
|
||||||
|
# True glob expansion when wildcards are present.
|
||||||
|
if [[ "$item" == *'*'* || "$item" == *'?'* || "$item" == *'['* ]]; then
|
||||||
|
expanded=( $item )
|
||||||
|
else
|
||||||
|
expanded=( "$item" )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
local result=""
|
if [[ ${#expanded[@]} -eq 0 ]]; then
|
||||||
for item in "$@"; do
|
continue
|
||||||
for content in "$item"; do
|
fi
|
||||||
|
|
||||||
|
for content in "${expanded[@]}"; do
|
||||||
|
if (( matched )); then
|
||||||
|
result+="$separator"
|
||||||
|
fi
|
||||||
result+="\"$content\""
|
result+="\"$content\""
|
||||||
|
matched=1
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
echo $result
|
|
||||||
|
shopt -u nullglob
|
||||||
|
printf '%s\n' "$result"
|
||||||
}
|
}
|
||||||
export -f expandlist
|
export -f expandlist
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Clean a directory or a tree from temporary or backup files
|
# Clean a directory tree from temporary or backup files
|
||||||
# Usage: clean [options] [directory1] [...[directoryX]]
|
# Usage: clean [options] [directory1] [...[directoryX]]
|
||||||
# Options:
|
# Options:
|
||||||
# -h, --help: display help screen
|
# -h, --help: display help screen
|
||||||
@@ -85,7 +138,7 @@ clean()
|
|||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-r|--recurs)
|
-r|--recurs)
|
||||||
local recursive=1
|
recursive=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-h|--help)
|
-h|--help)
|
||||||
@@ -100,11 +153,11 @@ clean()
|
|||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
-s|--shell)
|
-s|--shell)
|
||||||
local outshell=1
|
outshell=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-f|--force)
|
-f|--force)
|
||||||
local force=1
|
force=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
@@ -114,6 +167,7 @@ clean()
|
|||||||
*)
|
*)
|
||||||
disp E "Invalid parameter, use \"clean --help\" to display options list"
|
disp E "Invalid parameter, use \"clean --help\" to display options list"
|
||||||
return 1
|
return 1
|
||||||
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -121,21 +175,24 @@ clean()
|
|||||||
local dirlist=("$@")
|
local dirlist=("$@")
|
||||||
[[ ${#dirlist[@]} -eq 0 ]] && dirlist=(".")
|
[[ ${#dirlist[@]} -eq 0 ]] && dirlist=(".")
|
||||||
|
|
||||||
local findopt=() rmopt
|
local findopt=() rmopt=()
|
||||||
[[ ! $recursive ]] && findopt=(-maxdepth 1)
|
(( ! recursive )) && findopt=(-maxdepth 1)
|
||||||
[[ ! $force ]] && rmopt="-i"
|
(( ! force )) && rmopt=(-i)
|
||||||
unset recursive force
|
|
||||||
|
|
||||||
for dir in $dirlist; do
|
for dir in "${dirlist[@]}"; do
|
||||||
find "$dir" "${findopt[@]}" -type f \( -name "*~" -o -name "#*#" -o -name "*.bak" -o -name ".~*#" \) -print0 | while IFS= read -r -d '' f; do
|
find "$dir" "${findopt[@]}" -type f \( -name "*~" -o -name "#*#" -o -name "*.bak" -o -name ".~*#" \) -print0 |
|
||||||
if [[ ! $outshell ]]; then
|
while IFS= read -r -d '' f; do
|
||||||
rm $rmopt $f
|
if (( outshell )); then
|
||||||
|
if (( ${#rmopt[@]} )); then
|
||||||
|
printf 'rm %s -- "%s"\n' "${rmopt[*]}" "$f"
|
||||||
else
|
else
|
||||||
echo "rm $rmopt $f"
|
printf 'rm -- "%s"\n' "$f"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
rm "${rmopt[@]}" -- "$f"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
unset outshell dirlist dellist findopt rmopt
|
|
||||||
}
|
}
|
||||||
export -f clean
|
export -f clean
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
@@ -168,7 +225,7 @@ export -f mcd
|
|||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Rename all files in current directory to replace spaces with _
|
# Rename files and directories to replace spaces with another character
|
||||||
# Usage: rmspc [options]
|
# Usage: rmspc [options]
|
||||||
# Options:
|
# Options:
|
||||||
# -h, --help: display help screen
|
# -h, --help: display help screen
|
||||||
@@ -178,8 +235,11 @@ export -f mcd
|
|||||||
# -s, --shell: do nothing and display commands that would be executed
|
# -s, --shell: do nothing and display commands that would be executed
|
||||||
rmspc()
|
rmspc()
|
||||||
{
|
{
|
||||||
local lst=""
|
local recurs=0 verb=0 shell=0
|
||||||
|
local substchar="_" substchar_set=0
|
||||||
|
local mvopt=()
|
||||||
local PARSED
|
local PARSED
|
||||||
|
|
||||||
PARSED=$(getopt -o hr:c::vs --long help,recursive,subst-char::,verbose,shell -n 'rmspc' -- "$@")
|
PARSED=$(getopt -o hr:c::vs --long help,recursive,subst-char::,verbose,shell -n 'rmspc' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"rmspc --help\" to display usage."
|
disp E "Invalid options, use \"rmspc --help\" to display usage."
|
||||||
@@ -203,27 +263,20 @@ rmspc()
|
|||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
-r|--recursive)
|
-r|--recursive)
|
||||||
local recurs=1
|
recurs=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-c|--subst-char)
|
-c|--subst-char)
|
||||||
# Handle optional argument for short/long options
|
substchar_set=1
|
||||||
case "$2" in
|
|
||||||
"")
|
|
||||||
substchar=""
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
substchar="$2"
|
substchar="$2"
|
||||||
;;
|
|
||||||
esac
|
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-v|--verbose)
|
-v|--verbose)
|
||||||
local verb=1
|
verb=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-s|--shell)
|
-s|--shell)
|
||||||
local shell=1
|
shell=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
@@ -232,49 +285,58 @@ rmspc()
|
|||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
disp E "Invalid parameter, use \"rmspc --help\" to display options list"
|
disp E "Invalid parameter, use \"rmspc --help\" to display options list"
|
||||||
echo
|
|
||||||
return 1
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
[[ ! $substchar ]] && substchar="_"
|
[[ "$substchar" == "none" ]] && substchar=""
|
||||||
[[ $substchar == "none" ]] && local substchar=""
|
(( verb )) && mvopt=(-v)
|
||||||
[[ $verb ]] && local mvopt="-v"
|
|
||||||
|
|
||||||
shopt -s nullglob
|
shopt -s nullglob
|
||||||
for f in *; do
|
for f in *; do
|
||||||
[[ $recurs ]] && [[ -d "$f" ]] && (
|
if (( recurs )) && [[ -d "$f" ]]; then
|
||||||
[[ $verb ]] && disp I "Entering directory $(pwd)/$f ..."
|
(
|
||||||
local lastdir=$f
|
local lastdir=$f
|
||||||
pushd "$f" >/dev/null
|
(( verb )) && disp I "Entering directory $(pwd)/$f ..."
|
||||||
rmspc ${recurs:+-r} ${substchar:+-c "$substchar"} ${verb:+-v} ${shell:+-s}
|
pushd "$f" >/dev/null || return 1
|
||||||
popd >/dev/null
|
|
||||||
[[ $verb ]] && disp I "Leaving directory $(pwd)/$lastdir"
|
if (( substchar_set )); then
|
||||||
unset lastdir
|
rmspc ${recurs:+-r} -c "$substchar" ${verb:+-v} ${shell:+-s}
|
||||||
|
else
|
||||||
|
rmspc ${recurs:+-r} ${verb:+-v} ${shell:+-s}
|
||||||
|
fi
|
||||||
|
|
||||||
|
popd >/dev/null || return 1
|
||||||
|
(( verb )) && disp I "Leaving directory $(pwd)/$lastdir"
|
||||||
)
|
)
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ "$f" == *" "* ]]; then
|
if [[ "$f" == *" "* ]]; then
|
||||||
local newf="${f// /${substchar}}"
|
local newf="${f// /${substchar}}"
|
||||||
[[ "$f" == "$newf" ]] && continue # protection but should never happen
|
[[ "$f" == "$newf" ]] && continue
|
||||||
if [[ -n $shell ]]; then
|
if (( shell )); then
|
||||||
echo "mv ${mvopt:+$mvopt }\"$f\" \"$newf\""
|
if (( ${#mvopt[@]} )); then
|
||||||
|
printf 'mv %s -- "%s" "%s"\n' "${mvopt[*]}" "$f" "$newf"
|
||||||
else
|
else
|
||||||
mv ${mvopt:+$mvopt} "$f" "$newf" || {
|
printf 'mv -- "%s" "%s"\n' "$f" "$newf"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
mv "${mvopt[@]}" -- "$f" "$newf" || {
|
||||||
disp E "Failed renaming \"$f\" to \"$newf\"."
|
disp E "Failed renaming \"$f\" to \"$newf\"."
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
unset lst substchar verb shell newf command mvopt
|
shopt -u nullglob
|
||||||
}
|
}
|
||||||
export -f rmspc
|
export -f rmspc
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# display stats about a file structure
|
# Display statistics about a file tree
|
||||||
# Usage: file_stats [options] [path]
|
# Usage: file_stats [options] [path]
|
||||||
# Options:
|
# Options:
|
||||||
# -H, --human Human readable sizes\n"
|
# -H, --human Human readable sizes\n"
|
||||||
@@ -387,12 +449,12 @@ local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
|
|||||||
# Prepare find filters
|
# Prepare find filters
|
||||||
local find_cmd=(find "$path" -type f)
|
local find_cmd=(find "$path" -type f)
|
||||||
|
|
||||||
# Extension simple
|
# Single extension filter
|
||||||
if [[ -n "$ext_filter" ]]; then
|
if [[ -n "$ext_filter" ]]; then
|
||||||
find_cmd+=(-iname "*.$ext_filter")
|
find_cmd+=(-iname "*.$ext_filter")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Extension liste
|
# Extension list filter
|
||||||
if [[ -n "$ext_list" ]]; then
|
if [[ -n "$ext_list" ]]; then
|
||||||
IFS=',' read -ra exts <<< "$ext_list"
|
IFS=',' read -ra exts <<< "$ext_list"
|
||||||
find_cmd+=('(')
|
find_cmd+=('(')
|
||||||
@@ -403,7 +465,7 @@ local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
|
|||||||
find_cmd+=(')')
|
find_cmd+=(')')
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Taille min/max (à évaluer en octets)
|
# Minimum/maximum size filters (evaluated in bytes)
|
||||||
if [[ -n "$min_size" ]]; then
|
if [[ -n "$min_size" ]]; then
|
||||||
find_cmd+=(-size +"$(numfmt --from=iec "$min_size")"c)
|
find_cmd+=(-size +"$(numfmt --from=iec "$min_size")"c)
|
||||||
fi
|
fi
|
||||||
@@ -411,7 +473,7 @@ local human=0 details=0 only_avg=0 only_med=0 only_count=0 only_total=0
|
|||||||
find_cmd+=(-size -"$(( $(numfmt --from=iec "$max_size") + 1 ))"c)
|
find_cmd+=(-size -"$(( $(numfmt --from=iec "$max_size") + 1 ))"c)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Exécution
|
# Execution
|
||||||
"${find_cmd[@]}" -printf "%s\n" 2>/dev/null | sort -n | \
|
"${find_cmd[@]}" -printf "%s\n" 2>/dev/null | sort -n | \
|
||||||
awk -v human="$human" -v details="$details" -v only_avg="$only_avg" \
|
awk -v human="$human" -v details="$details" -v only_avg="$only_avg" \
|
||||||
-v only_med="$only_med" -v only_count="$only_count" \
|
-v only_med="$only_med" -v only_count="$only_count" \
|
||||||
@@ -512,10 +574,10 @@ export -f file_stats
|
|||||||
# -l : limit : number of files to return (default is 10)
|
# -l : limit : number of files to return (default is 10)
|
||||||
findbig()
|
findbig()
|
||||||
{
|
{
|
||||||
local details=0 limit=10 no_change=0 one_fs=0
|
local details=0 limit=10 one_fs=0
|
||||||
|
|
||||||
local PARSED
|
local PARSED
|
||||||
PARSED=$(getopt -o hd:l:x --long help,details,one-fs,limit: -n 'findbig' -- "$@")
|
PARSED=$(getopt -o hdl:x --long help,details,limit:,one-fs -n 'findbig' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"findbig --help\" to display usage."
|
disp E "Invalid options, use \"findbig --help\" to display usage."
|
||||||
return 1
|
return 1
|
||||||
@@ -538,14 +600,18 @@ findbig()
|
|||||||
details=1
|
details=1
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
-n|--no-change)
|
|
||||||
no_change=1
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-l|--limit)
|
-l|--limit)
|
||||||
limit="$2"
|
limit="$2"
|
||||||
|
[[ "$limit" =~ ^[0-9]+$ ]] || {
|
||||||
|
disp E "Invalid limit: must be a positive integer."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
|
-x|--one-fs)
|
||||||
|
one_fs=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
@@ -560,13 +626,16 @@ findbig()
|
|||||||
local dir="${1:-.}"
|
local dir="${1:-.}"
|
||||||
|
|
||||||
# Prepare find arguments in an array for cleaner handling
|
# Prepare find arguments in an array for cleaner handling
|
||||||
local find_args=("-L" "$dir" "-type" "f")
|
local find_args=(-L "$dir")
|
||||||
(( one_fs )) && find_args+=("-xdev")
|
(( one_fs )) && find_args+=(-xdev)
|
||||||
|
find_args+=(-type f)
|
||||||
|
|
||||||
# Logic: find files, print size and path, sort numeric reverse, take N
|
# Logic: find files, print size and path, sort numeric reverse, take N
|
||||||
if (( details )); then
|
if (( details )); then
|
||||||
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit" | while read -r size path; do
|
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit" |
|
||||||
ls -ld "$path"
|
while IFS= read -r line; do
|
||||||
|
local path="${line#* }"
|
||||||
|
ls -ld -- "$path"
|
||||||
done
|
done
|
||||||
else
|
else
|
||||||
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit"
|
find "${find_args[@]}" -printf "%s %p\n" 2>/dev/null | sort -rn | head -n "$limit"
|
||||||
@@ -586,7 +655,7 @@ export -f findbig
|
|||||||
# --delete : delete empty files and display their paths
|
# --delete : delete empty files and display their paths
|
||||||
findzero()
|
findzero()
|
||||||
{
|
{
|
||||||
local delete=0 details=0 one_fs=0 no_change=0
|
local delete=0 details=0 one_fs=0
|
||||||
|
|
||||||
local PARSED
|
local PARSED
|
||||||
# o: options, long: long equivalents
|
# o: options, long: long equivalents
|
||||||
@@ -660,7 +729,7 @@ export -f findzero
|
|||||||
# --delete : delete dead links and display their paths
|
# --delete : delete dead links and display their paths
|
||||||
finddead()
|
finddead()
|
||||||
{
|
{
|
||||||
local delete=0 details=0 one_fs=0 no_change=0
|
local delete=0 details=0 one_fs=0
|
||||||
|
|
||||||
local PARSED
|
local PARSED
|
||||||
PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'finddead' -- "$@")
|
PARSED=$(getopt -o hdx --long help,details,one-fs,delete -n 'finddead' -- "$@")
|
||||||
|
|||||||
@@ -39,6 +39,8 @@
|
|||||||
# Usage: help
|
# Usage: help
|
||||||
help()
|
help()
|
||||||
{
|
{
|
||||||
|
printf "${BIWhite}Welcome to your profile! Here is a list of available commands:${DEFAULTCOL}\n\n"
|
||||||
|
printf "check_updates\tCheck for new versions of profile\n"
|
||||||
printf "clean\t\tErase backup files\n"
|
printf "clean\t\tErase backup files\n"
|
||||||
printf "disp\t\tDisplay formatted info/warning/error/debug messages\n"
|
printf "disp\t\tDisplay formatted info/warning/error/debug messages\n"
|
||||||
printf "dwl\t\tDownload a URL to a local file\n"
|
printf "dwl\t\tDownload a URL to a local file\n"
|
||||||
@@ -60,6 +62,8 @@ help()
|
|||||||
printf "ppg\t\tDisplay process matching the given parameter\n"
|
printf "ppg\t\tDisplay process matching the given parameter\n"
|
||||||
printf "ppn\t\tDisplay process matching the exact process name given in parameter\n"
|
printf "ppn\t\tDisplay process matching the exact process name given in parameter\n"
|
||||||
printf "ppu\t\tDisplay processes owned by the given user\n"
|
printf "ppu\t\tDisplay processes owned by the given user\n"
|
||||||
|
printf "profile_upgrade\tUpgrade profile to the latest version\n"
|
||||||
|
printf "pwdscore\tCalculate password strength score\n"
|
||||||
printf "rain\t\tLet the rain fall\n"
|
printf "rain\t\tLet the rain fall\n"
|
||||||
printf "rmhost\t\tRemove host (IP and/or DNS name) from current known_hosts\n"
|
printf "rmhost\t\tRemove host (IP and/or DNS name) from current known_hosts\n"
|
||||||
printf "rmspc\t\tRemove spaces from file and directory names\n"
|
printf "rmspc\t\tRemove spaces from file and directory names\n"
|
||||||
|
|||||||
@@ -39,11 +39,14 @@
|
|||||||
# Usage: ver
|
# Usage: ver
|
||||||
ver()
|
ver()
|
||||||
{
|
{
|
||||||
local PARSED=$(getopt -o h --long help -n 'ver' -- "$@")
|
local PARSED
|
||||||
|
|
||||||
|
PARSED=$(getopt -o h --long help -n 'ver' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"ver --help\" to display usage."
|
disp E "Invalid options, use \"ver --help\" to display usage."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
eval set -- "$PARSED"
|
eval set -- "$PARSED"
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
@@ -72,11 +75,13 @@ export -f ver
|
|||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Display weather of the given city (or default one)
|
# Display weather for the given city (or the default one)
|
||||||
# Usage: meteo [city1 city2 ...]
|
# Usage: meteo [city1 city2 ...]
|
||||||
meteo()
|
meteo()
|
||||||
{
|
{
|
||||||
local PARSED=$(getopt -o h --long help -n 'meteo' -- "$@")
|
local PARSED
|
||||||
|
|
||||||
|
PARSED=$(getopt -o h --long help -n 'meteo' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"meteo --help\" to display usage."
|
disp E "Invalid options, use \"meteo --help\" to display usage."
|
||||||
return 1
|
return 1
|
||||||
@@ -85,7 +90,9 @@ meteo()
|
|||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
printf "meteo: Fetch weather data.\nUsage: meteo [city1 city2 ...]\n"
|
printf "meteo: Fetch weather data.\n"
|
||||||
|
printf "Usage: meteo [city1 city2 ...]\n"
|
||||||
|
printf "If no city is provided, the default city from configuration will be used.\n"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
@@ -100,12 +107,13 @@ meteo()
|
|||||||
done
|
done
|
||||||
|
|
||||||
local cities=("$@")
|
local cities=("$@")
|
||||||
|
local city="" encoded=""
|
||||||
[[ $# -eq 0 ]] && cities=("$DEFAULT_CITY")
|
[[ $# -eq 0 ]] && cities=("$DEFAULT_CITY")
|
||||||
|
|
||||||
for city in "${cities[@]}"; do
|
for city in "${cities[@]}"; do
|
||||||
encoded=$(urlencode "$city")
|
encoded=$(urlencode "$city")
|
||||||
dwl "https://wttr.in/$encoded" || \
|
dwl "https://wttr.in/$encoded" || \
|
||||||
disp E "Failed fetching datas for $city."
|
disp E "Failed to fetch weather data for $city."
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
export -f meteo
|
export -f meteo
|
||||||
@@ -117,16 +125,20 @@ export -f meteo
|
|||||||
# Usage: showinfo
|
# Usage: showinfo
|
||||||
showinfo()
|
showinfo()
|
||||||
{
|
{
|
||||||
local PARSED=$(getopt -o h --long help -n 'showinfo' -- "$@")
|
local PARSED
|
||||||
|
|
||||||
|
PARSED=$(getopt -o h --long help -n 'showinfo' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"showinfo --help\" to display usage."
|
disp E "Invalid options, use \"showinfo --help\" to display usage."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
eval set -- "$PARSED"
|
eval set -- "$PARSED"
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
printf "showinfo: Display system information (hostname, kernel, uptime).\nUsage: showinfo\n"
|
printf "showinfo: Display system information (hostname, kernel, uptime and fetch output when available).\n"
|
||||||
|
printf "Usage: showinfo\n"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
@@ -140,20 +152,20 @@ showinfo()
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
|
local hostname_str
|
||||||
|
local figopt=()
|
||||||
|
hostname_str="$(hostname)"
|
||||||
|
|
||||||
printf "\n"
|
printf "\n"
|
||||||
if command -v figlet >/dev/null 2>&1; then
|
if command -v figlet >/dev/null 2>&1; then
|
||||||
if [[ -s /usr/share/figlet/ansi_shadow.flf ]]; then
|
[[ -s /usr/share/figlet/ansi_shadow.flf ]] && \
|
||||||
local figopt="-f ansi_shadow"
|
figopt=(-f ansi_shadow)
|
||||||
fi
|
figlet -k "${figopt[@]}" "$hostname_str"
|
||||||
if [[ -n $figopt ]]; then
|
|
||||||
figlet -k $figopt $(hostname)
|
|
||||||
else
|
else
|
||||||
figlet $(hostname)
|
printf "%s\n" "$hostname_str"
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
hostname -f
|
printf "\n"
|
||||||
fi
|
|
||||||
echo ""
|
|
||||||
if command -v neofetch >/dev/null 2>&1; then
|
if command -v neofetch >/dev/null 2>&1; then
|
||||||
neofetch
|
neofetch
|
||||||
elif command -v fastfetch >/dev/null 2>&1; then
|
elif command -v fastfetch >/dev/null 2>&1; then
|
||||||
@@ -163,11 +175,11 @@ showinfo()
|
|||||||
if [[ -s /etc/os-release ]]; then
|
if [[ -s /etc/os-release ]]; then
|
||||||
# shellcheck disable=SC1091
|
# shellcheck disable=SC1091
|
||||||
. /etc/os-release
|
. /etc/os-release
|
||||||
printf "$NAME $VERSION\n"
|
printf "%s %s\n" "$NAME" "$VERSION"
|
||||||
else
|
else
|
||||||
cat /proc/version
|
cat /proc/version
|
||||||
fi
|
fi
|
||||||
printf "Uptime: $(uptime -p)\n"
|
printf "Uptime: %s\n" "$(uptime -p)"
|
||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
424
profile.d/pwd.sh
424
profile.d/pwd.sh
@@ -53,21 +53,22 @@
|
|||||||
genpwd()
|
genpwd()
|
||||||
{
|
{
|
||||||
local length=16
|
local length=16
|
||||||
local occurs=2 # Bug, if set to 1, seems to be ignored
|
local occurs=2
|
||||||
local symb=1 maj=1 min=1 numb=1
|
local symb=1 maj=1 min=1 numb=1
|
||||||
local nbpwd=1
|
local nbpwd=1
|
||||||
local extcar
|
local extcar=""
|
||||||
|
|
||||||
local PARSED
|
local PARSED
|
||||||
PARSED=$(getopt -o hsnule:L:o: --long \
|
PARSED=$(getopt -o hsnule:L:o: --long \
|
||||||
help,nosymbols,nonumbers,noup,nolow,extracars:,length:,occurences: -n 'genpwd' -- "$@")
|
help,nosymbols,nonumbers,noup,nolow,extracars:,length:,occurences:,occurrences: \
|
||||||
|
-n 'genpwd' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then return 1; fi
|
if [[ $? -ne 0 ]]; then return 1; fi
|
||||||
eval set -- "$PARSED"
|
eval set -- "$PARSED"
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
printf "genpwd: Generate secure random password(s).\n\n"
|
printf "genpwd: Generate random password(s).\n\n"
|
||||||
printf "Usage: genpwd [options] [nb_passwd]\n\n"
|
printf "Usage: genpwd [options] [nb_passwd]\n\n"
|
||||||
printf "Options:\n"
|
printf "Options:\n"
|
||||||
printf "\t-h, --help\t\tDisplay this help screen\n"
|
printf "\t-h, --help\t\tDisplay this help screen\n"
|
||||||
@@ -75,9 +76,9 @@ local PARSED
|
|||||||
printf "\t-n, --nonumbers\t\tExclude numbers\n"
|
printf "\t-n, --nonumbers\t\tExclude numbers\n"
|
||||||
printf "\t-u, --noup\t\tExclude uppercase letters\n"
|
printf "\t-u, --noup\t\tExclude uppercase letters\n"
|
||||||
printf "\t-l, --nolow\t\tExclude lowercase letters\n"
|
printf "\t-l, --nolow\t\tExclude lowercase letters\n"
|
||||||
printf "\t-e, --extracars <c>\tAdd characters to list\n"
|
printf "\t-e, --extracars <c>\tAdd characters to the pool\n"
|
||||||
printf "\t-L, --length <n>\tSet password length (default: 16)\n"
|
printf "\t-L, --length <n>\tSet password length (default: 16)\n"
|
||||||
printf "\t-o, --occurences <n>\tMax occurences per character (default: 2)\n"
|
printf "\t-o, --occurences <n>\tMax occurrences per character (default: 2)\n"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
-s|--nosymbols)
|
-s|--nosymbols)
|
||||||
@@ -102,22 +103,209 @@ local PARSED
|
|||||||
;;
|
;;
|
||||||
-L|--length)
|
-L|--length)
|
||||||
length="$2"
|
length="$2"
|
||||||
if ! [[ $length =~ ^[0-9]+$ ]]; then
|
if ! [[ $length =~ ^[1-9][0-9]*$ ]]; then
|
||||||
disp E "The --length parameter requires a number."
|
disp E "The --length parameter requires a positive integer."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
-o|--occurences)
|
-o|--occurences|--occurrences)
|
||||||
occurs="$2"
|
occurs="$2"
|
||||||
if ! [[ $occurs =~ ^[1-9]+$ ]]; then
|
if ! [[ $occurs =~ ^[1-9][0-9]*$ ]]; then
|
||||||
disp E "The --occurs parameter requires a number from 1 to 9."
|
disp E "The --occurences parameter requires a positive integer."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
shift 2
|
shift 2
|
||||||
;;
|
;;
|
||||||
--)
|
--)
|
||||||
shift; break
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
disp E "Invalid options, use \"genpwd --help\" to display usage."
|
||||||
|
return 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ $# -gt 1 ]]; then
|
||||||
|
disp E "Too many positional arguments. Use only [nb_passwd]."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $# -eq 1 ]]; then
|
||||||
|
nbpwd="$1"
|
||||||
|
if ! [[ $nbpwd =~ ^[1-9][0-9]*$ ]]; then
|
||||||
|
disp E "The number of passwords to generate must be a positive integer."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
local carset=""
|
||||||
|
local unique_carset=""
|
||||||
|
local ch=""
|
||||||
|
local i=0
|
||||||
|
local n=0
|
||||||
|
local idx=0
|
||||||
|
local attempts=0
|
||||||
|
local count=0
|
||||||
|
local max_attempts=0
|
||||||
|
local set=""
|
||||||
|
local char=""
|
||||||
|
local -a required_sets=()
|
||||||
|
declare -A seen_chars=()
|
||||||
|
|
||||||
|
(( symb )) && {
|
||||||
|
required_sets+=('!.@#&%/^-_')
|
||||||
|
carset+='!.@#&%/^-_'
|
||||||
|
}
|
||||||
|
(( numb )) && {
|
||||||
|
required_sets+=('0123456789')
|
||||||
|
carset+='0123456789'
|
||||||
|
}
|
||||||
|
(( maj )) && {
|
||||||
|
required_sets+=('ABCDEFGHIJKLMNOPQRSTUVWXYZ')
|
||||||
|
carset+='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||||
|
}
|
||||||
|
(( min )) && {
|
||||||
|
required_sets+=('abcdefghijklmnopqrstuvwxyz')
|
||||||
|
carset+='abcdefghijklmnopqrstuvwxyz'
|
||||||
|
}
|
||||||
|
if [[ -n $extcar ]]; then
|
||||||
|
required_sets+=("$extcar")
|
||||||
|
carset+="$extcar"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -z $carset ]]; then
|
||||||
|
disp E "No characters are available. Re-enable at least one character class."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
for (( i=0; i<${#carset}; i++ )); do
|
||||||
|
ch=${carset:i:1}
|
||||||
|
if [[ -z ${seen_chars["$ch"]+x} ]]; then
|
||||||
|
seen_chars["$ch"]=1
|
||||||
|
unique_carset+="$ch"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
unset seen_chars
|
||||||
|
carset="$unique_carset"
|
||||||
|
|
||||||
|
if (( ${#required_sets[@]} > length )); then
|
||||||
|
disp E "The selected character classes require a longer password."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( length > ${#carset} * occurs )); then
|
||||||
|
disp E "The occurrence limit is too strict for the selected length."
|
||||||
|
disp E "Please allow more characters or increase --occurences."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
disp I "Generating $nbpwd password(s), please wait..."
|
||||||
|
for (( n=1; n<=nbpwd; n++ )); do
|
||||||
|
local -a password_chars=()
|
||||||
|
local -A char_count=()
|
||||||
|
max_attempts=$(( ${#carset} * (occurs + 1) + 32 ))
|
||||||
|
|
||||||
|
for set in "${required_sets[@]}"; do
|
||||||
|
attempts=0
|
||||||
|
while :; do
|
||||||
|
if (( attempts >= max_attempts )); then
|
||||||
|
disp E "Unable to satisfy the occurrence limit with the current settings."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
idx=$(( RANDOM % ${#set} ))
|
||||||
|
char=${set:idx:1}
|
||||||
|
count=${char_count["$char"]:-0}
|
||||||
|
|
||||||
|
if (( count < occurs )); then
|
||||||
|
char_count["$char"]=$(( count + 1 ))
|
||||||
|
password_chars+=("$char")
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
((attempts++))
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
while (( ${#password_chars[@]} < length )); do
|
||||||
|
attempts=0
|
||||||
|
while :; do
|
||||||
|
if (( attempts >= max_attempts )); then
|
||||||
|
disp E "Unable to satisfy the occurrence limit with the current settings."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
idx=$(( RANDOM % ${#carset} ))
|
||||||
|
char=${carset:idx:1}
|
||||||
|
count=${char_count["$char"]:-0}
|
||||||
|
|
||||||
|
if (( count < occurs )); then
|
||||||
|
char_count["$char"]=$(( count + 1 ))
|
||||||
|
password_chars+=("$char")
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
|
||||||
|
((attempts++))
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
for (( i=${#password_chars[@]} - 1; i>0; i-- )); do
|
||||||
|
idx=$(( RANDOM % (i + 1) ))
|
||||||
|
char=${password_chars[i]}
|
||||||
|
password_chars[i]=${password_chars[idx]}
|
||||||
|
password_chars[idx]=$char
|
||||||
|
done
|
||||||
|
|
||||||
|
printf '%s' "${password_chars[@]}"
|
||||||
|
printf '\n'
|
||||||
|
done
|
||||||
|
}
|
||||||
|
export -f genpwd
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
# ------------------------------------------------------------------------------
|
||||||
|
# pwdscore : score a password quality from 1 to 100
|
||||||
|
# Usage: pwdscore [options] <password>
|
||||||
|
pwdscore()
|
||||||
|
{
|
||||||
|
local verbose=0
|
||||||
|
local read_stdin=0
|
||||||
|
local password=""
|
||||||
|
|
||||||
|
while [[ $# -gt 0 ]]; do
|
||||||
|
case "$1" in
|
||||||
|
-h|--help)
|
||||||
|
printf "pwdscore: Score a password from 1 to 100.\n\n"
|
||||||
|
printf "Usage: pwdscore [options] <password>\n"
|
||||||
|
printf " pwdscore [options] --stdin\n"
|
||||||
|
printf " pwdscore [options] # prompt on terminal\n\n"
|
||||||
|
printf "Options:\n"
|
||||||
|
printf "\t-h, --help\t\tDisplay this help screen\n"
|
||||||
|
printf "\t-v, --verbose\t\tShow details about the computed score\n"
|
||||||
|
printf "\t-i, --stdin\t\tRead the password from standard input\n\n"
|
||||||
|
printf "Note:\n"
|
||||||
|
printf " Passwords containing '!' should be quoted, or passed via --stdin.\n"
|
||||||
|
return 0
|
||||||
|
;;
|
||||||
|
-v|--verbose)
|
||||||
|
verbose=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-i|--stdin)
|
||||||
|
read_stdin=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--)
|
||||||
|
shift
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
-*)
|
||||||
|
disp E "Invalid option '$1'. Use \"pwdscore --help\" to display usage."
|
||||||
|
return 1
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
break
|
break
|
||||||
@@ -125,78 +313,164 @@ local PARSED
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if [[ -n "$1" ]]; then
|
if (( read_stdin )); then
|
||||||
nbpwd="$1"
|
[[ $# -eq 0 ]] || {
|
||||||
if ! [[ $nbpwd =~ ^[0-9]+$ ]]; then
|
disp E "Do not pass a positional password when using --stdin."
|
||||||
disp E "The number of password to generate must be a number."
|
|
||||||
return 1
|
return 1
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Function selecting a random caracter from the list in parameter
|
|
||||||
pickcar() {
|
|
||||||
# When a character is picked we check if it's not appearing already twice
|
|
||||||
# elsewhere, we choose an other char, to compensate weak bash randomizer
|
|
||||||
while [[ -z $char ]]; do
|
|
||||||
local char="${1:RANDOM%${#1}:1} $RANDOM"
|
|
||||||
if [[ $(awk -F"$char" '{print NF-1}' <<<"$picked") -gt $occurs ]]; then
|
|
||||||
unset char
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
picked+="$char"
|
|
||||||
echo "$char"
|
|
||||||
}
|
}
|
||||||
|
IFS= read -r password || true
|
||||||
disp I "Generating $nbpwd passwords, please wait..."
|
elif [[ $# -eq 0 ]]; then
|
||||||
for (( n=1; n<=nbpwd; n++ )); do
|
if [[ -t 0 ]]; then
|
||||||
{
|
read -r -s -p 'Password: ' password < /dev/tty || true
|
||||||
local carset='' # store final caracter set to use
|
printf '\n' > /dev/tty
|
||||||
local picked='' # store already used caracter
|
else
|
||||||
local rlength=0 # store already assigned length of caracters
|
IFS= read -r password || true
|
||||||
|
|
||||||
# ?, *, $ and \ impossible to use to my knowledge as it would be interpreted
|
|
||||||
if [[ $symb == 1 ]]; then
|
|
||||||
pickcar '!.@#&%/^-_'
|
|
||||||
carset+='!.@#&%/^-_'
|
|
||||||
((rlength++))
|
|
||||||
fi
|
fi
|
||||||
if [[ $numb == 1 ]]; then
|
else
|
||||||
pickcar '0123456789'
|
[[ $# -eq 1 ]] || {
|
||||||
carset+='0123456789'
|
disp E "Please provide exactly one password to score."
|
||||||
((rlength++))
|
|
||||||
fi
|
|
||||||
if [[ $maj == 1 ]]; then
|
|
||||||
pickcar 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
||||||
carset+='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
|
||||||
((rlength++))
|
|
||||||
fi
|
|
||||||
if [[ $min == 1 ]]; then
|
|
||||||
pickcar 'abcdefghijklmnopqrstuvwxyz'
|
|
||||||
carset+='abcdefghijklmnopqrstuvwxyz'
|
|
||||||
((rlength++))
|
|
||||||
fi
|
|
||||||
if [[ -n $extcar ]]; then
|
|
||||||
pickcar "$extcar"
|
|
||||||
carset+=$extcar
|
|
||||||
((rlength++))
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Check if we have enough car to have something viable
|
|
||||||
if [[ ${#carset} -lt $length ]]; then
|
|
||||||
disp E 'Not enought caracters are authorised for the password length.'
|
|
||||||
disp E 'Please allow more caracter (preferably) or reduce password lentgh.'
|
|
||||||
return 1
|
return 1
|
||||||
|
}
|
||||||
|
password="$1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for i in $(seq 1 $(($length - $rlength))); do
|
local lower=${password,,}
|
||||||
pickcar "$carset"
|
local length=${#password}
|
||||||
|
local score=0
|
||||||
|
local rating="very weak"
|
||||||
|
local unique_count=0
|
||||||
|
local i=0 idx=0
|
||||||
|
local c1=0 c2=0 c3=0
|
||||||
|
local ch=""
|
||||||
|
local has_lower=0 has_upper=0 has_digit=0 has_symbol=0
|
||||||
|
local pool_size=0
|
||||||
|
local entropy_bits="0.0"
|
||||||
|
local entropy_score=0
|
||||||
|
local -A seen=()
|
||||||
|
|
||||||
|
if [[ -z $password ]]; then
|
||||||
|
printf '1\n'
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( length >= 20 )); then
|
||||||
|
score=40
|
||||||
|
elif (( length >= 16 )); then
|
||||||
|
score=34
|
||||||
|
elif (( length >= 12 )); then
|
||||||
|
score=28
|
||||||
|
elif (( length >= 8 )); then
|
||||||
|
score=18
|
||||||
|
else
|
||||||
|
score=$(( length * 2 ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $password =~ [a-z] ]]; then
|
||||||
|
has_lower=1
|
||||||
|
pool_size=$(( pool_size + 26 ))
|
||||||
|
score=$(( score + 12 ))
|
||||||
|
fi
|
||||||
|
if [[ $password =~ [A-Z] ]]; then
|
||||||
|
has_upper=1
|
||||||
|
pool_size=$(( pool_size + 26 ))
|
||||||
|
score=$(( score + 12 ))
|
||||||
|
fi
|
||||||
|
if [[ $password =~ [0-9] ]]; then
|
||||||
|
has_digit=1
|
||||||
|
pool_size=$(( pool_size + 10 ))
|
||||||
|
score=$(( score + 12 ))
|
||||||
|
fi
|
||||||
|
if [[ $password =~ [^[:alnum:]] ]]; then
|
||||||
|
has_symbol=1
|
||||||
|
pool_size=$(( pool_size + 33 ))
|
||||||
|
score=$(( score + 14 ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
for (( i=0; i<length; i++ )); do
|
||||||
|
ch=${password:i:1}
|
||||||
|
if [[ -z ${seen["$ch"]+x} ]]; then
|
||||||
|
seen["$ch"]=1
|
||||||
|
unique_count=$(( unique_count + 1 ))
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
} | sort -R | awk '{printf "%s", $1}'
|
score=$(( score + (unique_count * 10) / length ))
|
||||||
unset picked carset rlength
|
|
||||||
echo
|
if (( pool_size > 1 )); then
|
||||||
|
entropy_bits=$(awk -v len="$length" -v pool="$pool_size" \
|
||||||
|
'BEGIN { printf "%.1f", len * (log(pool) / log(2)) }')
|
||||||
|
|
||||||
|
entropy_score=$(awk -v bits="$entropy_bits" 'BEGIN {
|
||||||
|
if (bits < 28) print -35;
|
||||||
|
else if (bits < 36) print -25;
|
||||||
|
else if (bits < 60) print -10;
|
||||||
|
else if (bits < 80) print 0;
|
||||||
|
else if (bits < 100) print 5;
|
||||||
|
else print 10;
|
||||||
|
}')
|
||||||
|
score=$(( score + entropy_score ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ $lower =~ (password|admin|root|qwerty|azerty|welcome|letmein|secret|changeme) ]]; then
|
||||||
|
score=$(( score - 25 ))
|
||||||
|
fi
|
||||||
|
if [[ $lower =~ (1234|abcd|qwer|0000|1111|aaaa) ]]; then
|
||||||
|
score=$(( score - 15 ))
|
||||||
|
fi
|
||||||
|
if [[ $password =~ (.)\1\1 ]]; then
|
||||||
|
score=$(( score - 10 ))
|
||||||
|
fi
|
||||||
|
if (( length < 8 )); then
|
||||||
|
score=$(( score - 10 ))
|
||||||
|
fi
|
||||||
|
if (( unique_count * 2 < length )); then
|
||||||
|
score=$(( score - 10 ))
|
||||||
|
fi
|
||||||
|
|
||||||
|
for (( idx=0; idx<length-2; idx++ )); do
|
||||||
|
printf -v c1 '%d' "'${lower:idx:1}"
|
||||||
|
printf -v c2 '%d' "'${lower:idx+1:1}"
|
||||||
|
printf -v c3 '%d' "'${lower:idx+2:1}"
|
||||||
|
if (( (c2 == c1 + 1 && c3 == c2 + 1) || \
|
||||||
|
(c2 == c1 - 1 && c3 == c2 - 1) )); then
|
||||||
|
score=$(( score - 10 ))
|
||||||
|
break
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if (( score < 1 )); then
|
||||||
|
score=1
|
||||||
|
elif (( score > 100 )); then
|
||||||
|
score=100
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( score >= 90 )); then
|
||||||
|
rating='excellent'
|
||||||
|
elif (( score >= 75 )); then
|
||||||
|
rating='strong'
|
||||||
|
elif (( score >= 60 )); then
|
||||||
|
rating='good'
|
||||||
|
elif (( score >= 40 )); then
|
||||||
|
rating='fair'
|
||||||
|
elif (( score >= 20 )); then
|
||||||
|
rating='weak'
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( verbose )); then
|
||||||
|
printf 'Score: %d/100\n' "$score"
|
||||||
|
printf 'Rating: %s\n' "$rating"
|
||||||
|
printf 'Length: %d\n' "$length"
|
||||||
|
printf 'Lowercase: %s\n' "$([[ $has_lower -eq 1 ]] && echo yes || echo no)"
|
||||||
|
printf 'Uppercase: %s\n' "$([[ $has_upper -eq 1 ]] && echo yes || echo no)"
|
||||||
|
printf 'Digits: %s\n' "$([[ $has_digit -eq 1 ]] && echo yes || echo no)"
|
||||||
|
printf 'Symbols: %s\n' "$([[ $has_symbol -eq 1 ]] && echo yes || echo no)"
|
||||||
|
printf 'Unique chars: %d\n' "$unique_count"
|
||||||
|
printf 'Entropy: ~%s bits\n' "$entropy_bits"
|
||||||
|
printf 'Entropy modifier: %+d\n' "$entropy_score"
|
||||||
|
else
|
||||||
|
printf '%d\n' "$score"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
export -f genpwd
|
export -f pwdscore
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
142
profile.d/ssh.sh
142
profile.d/ssh.sh
@@ -35,74 +35,118 @@
|
|||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Remove host from know_host (name and IP) for the active user
|
# Remove host entries (name and IP) from ~/.ssh/known_hosts for the active user
|
||||||
# Usage: rmhost <hostname|ip> [hostname2|ip2 [...]]
|
# Usage: rmhost <hostname|ip> [hostname2|ip2 [...]]
|
||||||
rmhost()
|
rmhost()
|
||||||
{
|
{
|
||||||
local PARSED
|
local PARSED
|
||||||
PARSED=$(getopt -o h --long help -n 'rmhost' -- "$@")
|
local all_users=0
|
||||||
|
local -a known_hosts_files=()
|
||||||
|
|
||||||
|
PARSED=$(getopt -o ha --long help,all-users -n 'rmhost' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then return 1; fi
|
if [[ $? -ne 0 ]]; then return 1; fi
|
||||||
eval set -- "$PARSED"
|
eval set -- "$PARSED"
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
printf "rmhost: Remove host/IP from ~/.ssh/known_hosts.\n\n"
|
printf "rmhost: Remove host/IP from known_hosts files.\n\n"
|
||||||
printf "Usage: rmhost <hostname|ip> [hostname2|ip2 ...]\n\n"
|
printf "Usage: rmhost [--all-users] <hostname|ip> [hostname2|ip2 ...]\n\n"
|
||||||
printf "Options:\n"
|
printf "Options:\n"
|
||||||
|
printf " -a, --all-users Remove entries from all local users when run as root\n"
|
||||||
printf " -h, --help Display this help screen\n"
|
printf " -h, --help Display this help screen\n"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
-a|--all-users)
|
||||||
|
all_users=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
disp E "Invalid options, use \"rmhost --help\" to display usage."
|
disp E "Invalid options, use \"rmhost --help\" to display usage."
|
||||||
break
|
return 1
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
# Validation: Ensure at least one argument remains
|
[[ $# -eq 0 ]] && {
|
||||||
if [[ $# -eq 0 ]]; then
|
|
||||||
disp E "Missing argument. Use 'rmhost --help' for usage."
|
disp E "Missing argument. Use 'rmhost --help' for usage."
|
||||||
return 1
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
command -v ssh-keygen >/dev/null 2>&1 || {
|
||||||
|
disp E "ssh-keygen is not installed."
|
||||||
|
return 127
|
||||||
|
}
|
||||||
|
|
||||||
|
if (( all_users )); then
|
||||||
|
[[ ${EUID:-$(id -u)} -eq 0 ]] || {
|
||||||
|
disp E "Option --all-users is only available when run as root."
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
while IFS=: read -r _ _ _ _ _ home _; do
|
||||||
|
[[ -n $home && -f $home/.ssh/known_hosts ]] || continue
|
||||||
|
known_hosts_files+=("$home/.ssh/known_hosts")
|
||||||
|
done < /etc/passwd
|
||||||
|
|
||||||
|
[[ -f /etc/ssh/ssh_known_hosts ]] && \
|
||||||
|
known_hosts_files+=("/etc/ssh/ssh_known_hosts")
|
||||||
|
|
||||||
|
[[ ${#known_hosts_files[@]} -gt 0 ]] || {
|
||||||
|
disp W "No known_hosts files found for local users."
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
else
|
||||||
|
known_hosts_files=("${HOME}/.ssh/known_hosts")
|
||||||
fi
|
fi
|
||||||
|
|
||||||
for target in "$@"; do
|
for target in "$@"; do
|
||||||
local hst=$target
|
local hst="$target"
|
||||||
isipv4 "$hst" >/dev/null
|
local ip=""
|
||||||
local v4=$?
|
local v4=1
|
||||||
isipv6 "$hst" >/dev/null
|
local v6=1
|
||||||
local v6=$?
|
|
||||||
|
isipv4 "$hst" >/dev/null 2>&1; v4=$?
|
||||||
|
isipv6 "$hst" >/dev/null 2>&1; v6=$?
|
||||||
|
|
||||||
if [[ $v4 -eq 0 || $v6 -eq 0 ]]; then
|
if [[ $v4 -eq 0 || $v6 -eq 0 ]]; then
|
||||||
local ip=$hst
|
ip="$hst"
|
||||||
unset hst
|
hst=""
|
||||||
fi
|
|
||||||
unset v4 v6
|
|
||||||
|
|
||||||
if [[ ! $ip && $hst ]]; then
|
|
||||||
if ! ip=$(host "$hst" 2>/dev/null | awk '/has address/ {print $NF; exit}'); then
|
|
||||||
disp E "Impossible to extract IP from hostname." &&
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
[[ -z $ip ]] && {
|
|
||||||
disp E "Impossible to extract IP from hostname."
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ $hst ]]; then
|
if [[ -z ${ip:-} && -n ${hst:-} ]]; then
|
||||||
disp I "Removing host $hst from ssh known_host..."
|
if command -v host >/dev/null 2>&1; then
|
||||||
ssh-keygen -R $hst >/dev/null
|
ip=$(host "$hst" 2>/dev/null |
|
||||||
|
awk '/has address|has IPv6 address/ {print $NF; exit}')
|
||||||
|
elif command -v getent >/dev/null 2>&1; then
|
||||||
|
ip=$(getent ahosts "$hst" 2>/dev/null | awk 'NR == 1 {print $1; exit}')
|
||||||
|
else
|
||||||
|
disp W "No resolver tool found; removing hostname only for '$hst'."
|
||||||
fi
|
fi
|
||||||
if [[ $ip ]]; then
|
|
||||||
disp I "Removing IP $ip from ssh known_host..."
|
[[ -z ${ip:-} ]] && \
|
||||||
ssh-keygen -R $ip >/dev/null
|
disp W "Could not resolve IP for '$hst'; removing hostname only."
|
||||||
fi
|
fi
|
||||||
unset hst ip
|
|
||||||
|
local known_hosts_file=""
|
||||||
|
for known_hosts_file in "${known_hosts_files[@]}"; do
|
||||||
|
if [[ -n ${hst:-} ]]; then
|
||||||
|
disp I "Removing host $hst from $known_hosts_file..."
|
||||||
|
if ! ssh-keygen -R "$hst" -f "$known_hosts_file" >/dev/null 2>&1; then
|
||||||
|
disp W "No known_hosts entry found for '$hst' in '$known_hosts_file'."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -n ${ip:-} ]]; then
|
||||||
|
disp I "Removing IP $ip from $known_hosts_file..."
|
||||||
|
if ! ssh-keygen -R "$ip" -f "$known_hosts_file" >/dev/null 2>&1; then
|
||||||
|
disp W "No known_hosts entry found for '$ip' in '$known_hosts_file'."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
done
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
export -f rmhost
|
export -f rmhost
|
||||||
@@ -114,41 +158,33 @@ export -f rmhost
|
|||||||
# Usage: ssr <server [ssh options]>
|
# Usage: ssr <server [ssh options]>
|
||||||
ssr()
|
ssr()
|
||||||
{
|
{
|
||||||
local PARSED
|
case "${1:-}" in
|
||||||
PARSED=$(getopt -o h --long help -n 'ssr' -- "$@")
|
|
||||||
if [[ $? -ne 0 ]]; then return 1; fi
|
|
||||||
eval set -- "$PARSED"
|
|
||||||
|
|
||||||
while true; do
|
|
||||||
case "$1" in
|
|
||||||
-h|--help)
|
-h|--help)
|
||||||
printf "ssr: SSH into a server as root.\n\n"
|
printf "ssr: SSH into a server as root.\n\n"
|
||||||
printf "Usage: ssr <server> [ssh_options...]\n\n"
|
printf "Usage: ssr <server> [ssh_options...]\n\n"
|
||||||
printf "Options:\n"
|
printf "Notes:\n"
|
||||||
printf "\t-h, --help\t\tDisplay this help screen\n"
|
printf " The first argument is the target server.\n"
|
||||||
|
printf " All remaining arguments are passed directly to ssh.\n\n"
|
||||||
|
printf "Examples:\n"
|
||||||
|
printf " ssr srv01\n"
|
||||||
|
printf " ssr srv01 -p 2222\n"
|
||||||
|
printf " ssr srv01 -i ~/.ssh/id_ed25519 -J bastion\n"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
--)
|
|
||||||
shift
|
|
||||||
break
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
disp E "Invalid options, use \"ssr --help\" to display usage."
|
|
||||||
return 1
|
|
||||||
;;
|
|
||||||
esac
|
esac
|
||||||
done
|
|
||||||
|
|
||||||
command -v ssh >/dev/null 2>&1 || {
|
command -v ssh >/dev/null 2>&1 || {
|
||||||
disp E "ssh is not installed."
|
disp E "ssh is not installed."
|
||||||
return 127
|
return 127
|
||||||
}
|
}
|
||||||
[[ ! $1 ]] && {
|
|
||||||
|
[[ $# -eq 0 || -z ${1:-} ]] && {
|
||||||
disp E "Please specify the server you want to log in."
|
disp E "Please specify the server you want to log in."
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
local srv=$1 && shift
|
local srv=$1
|
||||||
|
shift
|
||||||
|
|
||||||
ssh -Y root@"$srv" "$@"
|
ssh -Y root@"$srv" "$@"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,24 +39,27 @@ export UPDT_URL="$BASE_URL/raw/branch/master"
|
|||||||
export ARCH_URL="$BASE_URL/archive/master.tar.gz"
|
export ARCH_URL="$BASE_URL/archive/master.tar.gz"
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Check for profile updates
|
# Check whether a newer profile version is available
|
||||||
# Usage: check_updates [-q]
|
# Usage: check_updates [-q]
|
||||||
# If -q is specified, the function will operate in quiet mode (internal use only)
|
# If -q is specified, the function will operate in quiet mode (internal use only)
|
||||||
check_updates()
|
check_updates()
|
||||||
{
|
{
|
||||||
local quiet=0
|
local quiet=0 result=5 PARSED
|
||||||
local PARSED=$(getopt -o hq --long help,quiet -n 'check_updates' -- "$@")
|
local vfile="" lastver=""
|
||||||
|
|
||||||
|
PARSED=$(getopt -o hq --long help,quiet -n 'check_updates' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
disp E "Invalid options, use \"check_updates --help\" to display usage."
|
disp E "Invalid options, use \"check_updates --help\" to display usage."
|
||||||
return 1
|
return 2
|
||||||
fi
|
fi
|
||||||
eval set -- "$PARSED"
|
eval set -- "$PARSED"
|
||||||
|
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
printf "check_updates: Check for new versions.\n\n"
|
printf "check_updates: Check whether a newer profile version is available.\n\n"
|
||||||
printf "Usage: check_updates\n"
|
printf "Usage: check_updates [-q|--quiet]\n"
|
||||||
|
printf "This command only checks availability; it does not modify the installation.\n"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
-q|--quiet)
|
-q|--quiet)
|
||||||
@@ -73,28 +76,35 @@ check_updates()
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
(( $quiet != 1 )) && disp I "Checking for updates..."
|
(( quiet != 1 )) && disp I "Checking for updates..."
|
||||||
local vfile="/tmp/version"
|
|
||||||
wget "$UPDT_URL/version" -O $vfile >/dev/null 2>&1 || {
|
vfile=$(mktemp /tmp/profile_version.XXXXXX) || {
|
||||||
disp E "Can't download version file, impossible to proceed!"
|
disp E "Failed to create a temporary file."
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
|
||||||
|
dwl "$UPDT_URL/version" "$vfile" >/dev/null 2>&1 || {
|
||||||
|
rm -f "$vfile"
|
||||||
|
disp E "Cannot download version file; unable to continue."
|
||||||
return 5
|
return 5
|
||||||
}
|
}
|
||||||
|
|
||||||
if [[ -s $vfile ]]; then
|
if [[ -s $vfile ]]; then
|
||||||
local lastver=$(cat $vfile)
|
lastver=$(<"$vfile")
|
||||||
if [[ $lastver != $PROFVERSION ]]; then
|
if [[ "$lastver" != "$PROFVERSION" ]]; then
|
||||||
disp I "You have version $PROFVERSION installed. Version $lastver is available."
|
disp I "Installed: $PROFVERSION. Available: $lastver."
|
||||||
(( $quiet != 1 )) && disp I "You should upgrade to last version when possible."
|
(( quiet != 1 )) && disp I "You should upgrade when possible."
|
||||||
result=1
|
result=1
|
||||||
else
|
else
|
||||||
(( $quiet != 1 )) && disp I "Your version is up-to-date."
|
(( quiet != 1 )) && disp I "Your version is up-to-date."
|
||||||
result=0
|
result=0
|
||||||
fi
|
fi
|
||||||
rm -f $vfile
|
rm -f "$vfile"
|
||||||
else
|
else
|
||||||
disp E "Impossible to read temporary file, impossible to proceed."
|
rm -f "$vfile"
|
||||||
|
disp E "Temporary file is unreadable; unable to continue."
|
||||||
fi
|
fi
|
||||||
unset lastver vfile
|
|
||||||
return $result
|
return $result
|
||||||
}
|
}
|
||||||
export -f check_updates
|
export -f check_updates
|
||||||
@@ -102,23 +112,63 @@ export -f check_updates
|
|||||||
|
|
||||||
|
|
||||||
# ------------------------------------------------------------------------------
|
# ------------------------------------------------------------------------------
|
||||||
# Apply update to profile
|
# Apply the available profile upgrade
|
||||||
# Usage: profile_upgrade
|
# Usage: profile_upgrade [options]
|
||||||
profile_upgrade()
|
profile_upgrade()
|
||||||
{
|
{
|
||||||
local PARSED=$(getopt -o h --long help -n 'profile_upgrade' -- "$@")
|
local PARSED
|
||||||
|
local check_rc=0 dry_run=0 force_git=0 switch_to_git=0
|
||||||
|
local archive_file="" tmpbase="" use_archive=0 branch=""
|
||||||
|
local tmpdir="" archive="" extracted_root=""
|
||||||
|
|
||||||
|
PARSED=$(getopt -o hf:t:nFb:g --long help,file:,tmpdir:,dry-run,force,branch:,switch-to-git -n 'profile_upgrade' -- "$@")
|
||||||
if [[ $? -ne 0 ]]; then
|
if [[ $? -ne 0 ]]; then
|
||||||
printf "Invalid options, use \"profile_upgrade --help\" to display usage."
|
disp E "Invalid options, use \"profile_upgrade --help\" to display usage."
|
||||||
return 1
|
return 2
|
||||||
fi
|
fi
|
||||||
eval set -- "$PARSED"
|
eval set -- "$PARSED"
|
||||||
while true; do
|
while true; do
|
||||||
case "$1" in
|
case "$1" in
|
||||||
-h|--help)
|
-h|--help)
|
||||||
printf "profile_upgrade: Upgrade the profile to the latest version.\n\n"
|
printf "profile_upgrade: Apply the available profile upgrade.\n\n"
|
||||||
printf "Usage: profile_upgrade\n"
|
printf "Usage: profile_upgrade [options]\n\n"
|
||||||
|
printf "Options:\n"
|
||||||
|
printf "\t-h, --help\t\tDisplay this help screen\n"
|
||||||
|
printf "\t-f, --file ARCHIVE\tUse a local archive file for the upgrade\n"
|
||||||
|
printf "\t-t, --tmpdir DIR\tCreate the temporary working directory under DIR\n"
|
||||||
|
printf "\t-b, --branch NAME\tUse NAME as the target Git branch\n"
|
||||||
|
printf "\t-g, --switch-to-git\tReplace current install with a fresh Git clone\n"
|
||||||
|
printf "\t-n, --dry-run\t\tDisplay what would be done without changing anything\n"
|
||||||
|
printf "\t-F, --force\t\tDiscard local changes before upgrading\n\n"
|
||||||
|
printf "If the profile is installed from Git, the upgrade uses 'git pull'.\n"
|
||||||
|
printf "Otherwise, it downloads or applies an archive and refreshes the files.\n"
|
||||||
return 0
|
return 0
|
||||||
;;
|
;;
|
||||||
|
-f|--file)
|
||||||
|
archive_file="$2"
|
||||||
|
use_archive=1
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-t|--tmpdir)
|
||||||
|
tmpbase="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-b|--branch)
|
||||||
|
branch="$2"
|
||||||
|
shift 2
|
||||||
|
;;
|
||||||
|
-g|--switch-to-git)
|
||||||
|
switch_to_git=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-n|--dry-run)
|
||||||
|
dry_run=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
-F|--force)
|
||||||
|
force_git=1
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--)
|
--)
|
||||||
shift
|
shift
|
||||||
break
|
break
|
||||||
@@ -130,59 +180,229 @@ profile_upgrade()
|
|||||||
esac
|
esac
|
||||||
done
|
done
|
||||||
|
|
||||||
if check_updates -q; then
|
if (( ! use_archive && ! switch_to_git )); then
|
||||||
disp "No update available."
|
check_updates -q
|
||||||
|
check_rc=$?
|
||||||
|
if (( check_rc == 0 )); then
|
||||||
|
disp I "No update available."
|
||||||
return 0
|
return 0
|
||||||
|
elif (( check_rc > 1 )); then
|
||||||
|
disp E "Unable to check whether an update is available."
|
||||||
|
return "$check_rc"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ -s $MYPATH/profile.sh ]]; then
|
if [[ ! -s $MYPATH/profile.sh ]]; then
|
||||||
disp E "Installation path detection failed, cannot upgrade automatically."
|
disp E "Install path detection failed; cannot upgrade automatically."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [[ -d $MYPATH/.git ]] && (( use_archive )) && (( ! force_git )); then
|
||||||
|
disp E "Refusing archive upgrade on a Git install without --force."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if (( switch_to_git )); then
|
||||||
|
command -v git >/dev/null 2>&1 || {
|
||||||
|
disp E "Git is required to switch this install to a Git clone."
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
if (( dry_run )); then
|
||||||
|
disp I "[dry-run] rm -rf \"$MYPATH\"/.git"
|
||||||
|
disp I "[dry-run] git clone "$BASE_URL" \"$MYPATH\""
|
||||||
|
[[ -n "$branch" ]] && disp I "[dry-run] git -C \"$MYPATH\" checkout "$branch""
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if [[ -d $MYPATH/.git ]]; then
|
if [[ -d $MYPATH/.git ]]; then
|
||||||
|
disp W "Git repository already present; no switch is needed."
|
||||||
|
else
|
||||||
|
local backup_dir="${MYPATH}.pre-git.$$.bak"
|
||||||
|
mv "$MYPATH" "$backup_dir" || {
|
||||||
|
disp E "Failed to move current install out of the way."
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
git clone "$BASE_URL" "$MYPATH" || {
|
||||||
|
disp E "Git clone failed; previous install kept in $backup_dir."
|
||||||
|
mv "$backup_dir" "$MYPATH" 2>/dev/null || true
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
[[ -n "$branch" ]] && (
|
||||||
|
cd "$MYPATH" && git checkout "$branch"
|
||||||
|
) || true
|
||||||
|
disp I "Switched installation to Git source."
|
||||||
|
disp I "Previous install kept in $backup_dir."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -d $MYPATH/.git ]] && (( ! use_archive )); then
|
||||||
disp I "Git installation detected, applying git pull."
|
disp I "Git installation detected, applying git pull."
|
||||||
pushd "$MYPATH" || {
|
command -v git >/dev/null 2>&1 || {
|
||||||
|
disp E "Git is required for this upgrade but is not available."
|
||||||
|
return 3
|
||||||
|
}
|
||||||
|
pushd "$MYPATH" >/dev/null || {
|
||||||
disp E "Failed to change directory to $MYPATH."
|
disp E "Failed to change directory to $MYPATH."
|
||||||
return 3
|
return 3
|
||||||
}
|
}
|
||||||
git pull || {
|
git rev-parse --is-inside-work-tree >/dev/null 2>&1 || {
|
||||||
disp E "Git pull failed, upgrade not applyed."
|
disp E "Install directory is not a valid Git working tree."
|
||||||
popd
|
popd >/dev/null || return 1
|
||||||
return 2
|
return 3
|
||||||
}
|
}
|
||||||
disp I "Successfully upgraded using git."
|
if ! git diff --quiet || ! git diff --cached --quiet || [[ -n $(git ls-files --others --exclude-standard) ]]; then
|
||||||
popd
|
if (( force_git )); then
|
||||||
|
disp W "Force mode: local Git changes and untracked files will be lost."
|
||||||
|
if (( dry_run )); then
|
||||||
|
disp I "[dry-run] git fetch --all --prune"
|
||||||
|
disp I "[dry-run] git reset --hard HEAD"
|
||||||
|
disp I "[dry-run] git clean -fd"
|
||||||
else
|
else
|
||||||
disp I "No Git detected. Downloading and applying upgrade from archive..."
|
git fetch --all --prune || {
|
||||||
local tmpdir="/tmp/profile_upg.$$"
|
disp E "Git fetch failed, upgrade not applied."
|
||||||
mkdir -p "$tmpdir" || {
|
popd >/dev/null || return 1
|
||||||
disp E "Failed to create temporary directory."
|
|
||||||
return 4
|
return 4
|
||||||
}
|
}
|
||||||
|
git reset --hard HEAD || {
|
||||||
|
disp E "Git reset failed, upgrade not applied."
|
||||||
|
popd >/dev/null || return 1
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
git clean -fd || {
|
||||||
|
disp E "Git clean failed, upgrade not applied."
|
||||||
|
popd >/dev/null || return 1
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
disp W "The Git working tree contains local changes."
|
||||||
|
disp W "Consider committing or stashing them before upgrading, or use --force."
|
||||||
|
disp W "Upgrade may fail if the changes conflict with the upgrade."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [[ -n "$branch" ]]; then
|
||||||
|
if (( dry_run )); then
|
||||||
|
disp I "[dry-run] git fetch origin $branch"
|
||||||
|
disp I "[dry-run] git checkout $branch"
|
||||||
|
else
|
||||||
|
git fetch origin "$branch" || {
|
||||||
|
disp E "Git fetch failed for branch $branch."
|
||||||
|
popd >/dev/null || return 1
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
git checkout "$branch" || {
|
||||||
|
disp E "Git checkout failed for branch $branch."
|
||||||
|
popd >/dev/null || return 1
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
local archive="$tmpdir/profile.tar.gz"
|
if (( dry_run )); then
|
||||||
wget -q "$ARCH_URL" -O "$archive" || {
|
if [[ -n "$branch" ]]; then
|
||||||
disp E "Failed to download archive."
|
disp I "[dry-run] git pull origin $branch"
|
||||||
rm -rf "$tmpdir"
|
else
|
||||||
|
disp I "[dry-run] git pull"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [[ -n "$branch" ]]; then
|
||||||
|
git pull origin "$branch" || {
|
||||||
|
disp E "Git pull failed, upgrade not applied."
|
||||||
|
popd >/dev/null || return 1
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
else
|
||||||
|
git pull || {
|
||||||
|
disp E "Git pull failed, upgrade not applied."
|
||||||
|
popd >/dev/null || return 1
|
||||||
|
return 2
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
disp I "Successfully upgraded using git."
|
||||||
|
fi
|
||||||
|
popd >/dev/null || return 1
|
||||||
|
else
|
||||||
|
if (( use_archive )); then
|
||||||
|
[[ -r "$archive_file" ]] || {
|
||||||
|
disp E "Local archive '$archive_file' is missing or unreadable."
|
||||||
|
return 4
|
||||||
|
}
|
||||||
|
disp I "Using local archive $archive_file."
|
||||||
|
else
|
||||||
|
disp W "No Git repo found. Git is the recommended source."
|
||||||
|
disp I "Applying upgrade from archive..."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -n "$tmpbase" ]]; then
|
||||||
|
if (( dry_run )); then
|
||||||
|
disp I "[dry-run] mkdir -p \"$tmpbase\""
|
||||||
|
disp I "[dry-run] mktemp -d \"$tmpbase/profile_upg.XXXXXX\""
|
||||||
|
tmpdir="$tmpbase/profile_upg.DRYRUN"
|
||||||
|
else
|
||||||
|
mkdir -p "$tmpbase" || {
|
||||||
|
disp E "Failed to create temporary directory base $tmpbase."
|
||||||
return 5
|
return 5
|
||||||
}
|
}
|
||||||
|
tmpdir=$(mktemp -d "$tmpbase/profile_upg.XXXXXX") || {
|
||||||
|
disp E "Failed to create temp working directory under $tmpbase."
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if (( dry_run )); then
|
||||||
|
disp I "[dry-run] mktemp -d /tmp/profile_upg.XXXXXX"
|
||||||
|
tmpdir="/tmp/profile_upg.DRYRUN"
|
||||||
|
else
|
||||||
|
tmpdir=$(mktemp -d /tmp/profile_upg.XXXXXX) || {
|
||||||
|
disp E "Failed to create temporary directory."
|
||||||
|
return 5
|
||||||
|
}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
tar -xzf "$archive" -C "$tmpdir" || {
|
if (( use_archive )); then
|
||||||
disp E "Archive extraction failed."
|
archive="$archive_file"
|
||||||
|
else
|
||||||
|
archive="$tmpdir/profile.tar.gz"
|
||||||
|
if (( dry_run )); then
|
||||||
|
disp I "[dry-run] dwl \"$ARCH_URL\" \"$archive\""
|
||||||
|
else
|
||||||
|
dwl "$ARCH_URL" "$archive" || {
|
||||||
|
disp E "Failed to download archive."
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 6
|
return 6
|
||||||
}
|
}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
disp I "Installing new version..."
|
if (( dry_run )); then
|
||||||
cp -r "$tmpdir"/profile/* "$MYPATH"/ || {
|
disp I "[dry-run] tar -xzf \"$archive\" -C \"$tmpdir\""
|
||||||
disp E "Failed to copy new files to $MYPATH."
|
disp I "[dry-run] cp -a <extracted_profile>/. \"$MYPATH\"/"
|
||||||
|
else
|
||||||
|
tar -xzf "$archive" -C "$tmpdir" || {
|
||||||
|
disp E "Archive extraction failed."
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
return 7
|
return 7
|
||||||
}
|
}
|
||||||
|
|
||||||
disp I "Upgrade complete. You should now logout and login again."
|
extracted_root=$(find "$tmpdir" -mindepth 1 -maxdepth 1 -type d ! -name '.*' | head -n 1)
|
||||||
|
if [[ -z "$extracted_root" ]]; then
|
||||||
|
disp E "Could not find extracted profile files."
|
||||||
rm -rf "$tmpdir"
|
rm -rf "$tmpdir"
|
||||||
|
return 8
|
||||||
|
fi
|
||||||
|
|
||||||
|
disp I "Installing new version..."
|
||||||
|
cp -a "$extracted_root"/. "$MYPATH"/ || {
|
||||||
|
disp E "Failed to copy new files into $MYPATH."
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
return 9
|
||||||
|
}
|
||||||
|
|
||||||
|
disp I "Upgrade complete. Please log out and log in again."
|
||||||
|
rm -rf "$tmpdir"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
export -f profile_upgrade
|
export -f profile_upgrade
|
||||||
|
|||||||
Reference in New Issue
Block a user