#!/bin/bash # Pacdiff for EndeavourOS. UserWants() { case "$user_wants" in cli | both) [ "$1" = "cli" ] && return 0 ;; esac which yad &>/dev/null || return 1 case "$user_wants" in gui | both) [ "$1" = "gui" ] && return 0 ;; esac return 1 } SafetyWarning() { if [ "$EOS_PACDIFF_WARNING" = "yes" ] ; then local txt="" txt+="NOTE: $progname is a powerful tool, so use it carefully!\n\n" txt+="For example, please do not modify files like:\n" txt+=" /etc/passwd\n" txt+=" /etc/group\n" txt+=" /etc/shadow\n" txt+="and related files unless you know exactly what you are doing.\n\n" txt+="You can remove this warning popup by changing the value of\n" txt+="variable EOS_PACDIFF_WARNING in file /etc/eos-script-lib-yad.conf.\n" txt+="(Note that you may need to merge the changes from\nfile /etc/eos-script-lib-yad.conf.pacnew first!)\n" if UserWants cli ; then txt2="$(echo "$txt" | sed -e 's|<[/bit]*>||g' -e 's|\\n|\n|g')" printf "%s\n\n" "$txt2" >&2 fi if UserWants gui ; then eos_yad --form --image=$ICO_WARNING --title="Warning" --text="$txt" --button="yad-ok!!I understand":1 fi fi } HasPacdiffs() { test -n "$(echo q | DIFFPROG=diff /usr/bin/pacdiff)" ; } DoesSudo() { groups | grep -Pw 'root|wheel' >/dev/null ; } PacdiffCmd() { local differ="$1" if HasPacdiffs ; then case "$differ" in # some differs may need options vim) differ+=" -d" ;; esac local -r doas="/usr/bin/sudo" local -r compress="/usr/bin/gzip" # compress with "gzip" or "zstd --rm" local cmdfile cmdfile=$(mktemp "$HOME/.tmp.$progname.tmpXXX") || DIE "creating a temporary file under $HOME failed" # don't mount $HOME with noexec! cat < $cmdfile #!/bin/bash echo "==> starting pacdiff with '$differ' diff support..." >&2 EOF if [ $backup_all = yes ] ; then local -r pacnews=($(DIFFPROG=diff /usr/bin/pacdiff -o)) local -r time=$(date +%Y%m%d-%H%M%S) cat <> $cmdfile echo " -> creating backups under folder $backupdir" >&2 $doas /usr/bin/mkdir -p $backupdir $doas /usr/bin/chmod go-rwx $backupdir EOF local bf bu for bf in "${pacnews[@]}" ; do bf=${bf%.*} # e.g. /etc/akm.conf bu=${bf##*/}.$time # e.g. akm.conf.20250215-170300 echo "$doas /usr/bin/cp $bf $backupdir/$bu" >> $cmdfile echo "$doas $compress $backupdir/$bu" >> $cmdfile done fi echo "DIFFPROG=\"/usr/bin/$differ\" /usr/bin/pacdiff -s 2>/dev/null" >> $cmdfile chmod u+x,go-rwx $cmdfile if [ $start_new_terminal = yes ] ; then RunInTerminal "$cmdfile" else bash -c "$cmdfile" fi rm -f $cmdfile return $diffs_yes else local msg="$progname: nothing to do." if UserWants cli ; then echo "$indent$msg" >&2 fi if UserWants gui ; then eos_yad_nothing_todo "$msg" 5 fi [ $start_new_terminal = yes ] && return $diffs_no_nt || return $diffs_no fi } Usage() { cat <&2 Usage: $progname [options] Options: -h, --help This help. -b, --backup Save the old files (in view, merge, and overwrite modes) with .bak. Default. --no-backup The opposite of option --backup. --nt Starts a new terminal for the output (used by the Welcome app). --quiet Do not display messages. --msg-types=WHAT Selects how informational messages will be displayed. Supported values for WHAT: "cli" Only using terminal CLI. "gui" Only using popup windows. "both" "cli" + "gui". "" Do not display messages (same as --quiet). Default: "both". EOF case "$1" in OK) exit 0 ;; FAIL) exit 1 ;; esac } DIE() { local msg="$1" local linenr="${BASH_LINENO[0]}" case "$linenr" in [1-9]*) linenr=" (line $linenr)" ;; *) linenr="" ;; esac echo -e "\n==> $progname$linenr: error: $msg\n" >&2 Usage FAIL } Main() { local progname=${0##*/} # exit codes local diffs_yes=0 local diffs_error=1 local diffs_no=2 local diffs_no_nt=3 local start_new_terminal=no local indent="" local user_wants=both local -r backup_default=yes local backup_all=$backup_default local -r backupdir="/etc/.EOS_BACKUPDIR" local -r extra_conf=/etc/$progname.conf local arg DoesSudo || DIE "sorry, user needs to have proper rights for 'sudo'" # pre-handling of certain options for arg in "$@" ; do case "$arg" in --quiet) user_wants="" ;; --msg-types=*) user_wants="${1#*=}" ;; # cli gui both "" esac done source /usr/share/endeavouros/scripts/eos-script-lib-yad || return $diffs_error export -f eos_yad export -f eos_yad_nothing_todo AssignIconVariables_in_eos_bash_shared case "$user_wants" in gui|both) CanRunYad || user_wants=cli ;; esac # read config file if it exists; command line options will override config file values if [ -e $extra_conf ] ; then case "$user_wants" in cli | both) echo "==> reading $extra_conf" >&2 ;; esac source $extra_conf else echo "==> info: file $extra_conf is not available." >&2 fi # handle rest of the options while [ "$1" ] ; do case "$1" in -h | --help) Usage OK ;; -b | --backup) backup_all=yes ;; --no-backup) backup_all=no ;; --indent=*) indent="${1#*=}" ;; --nt) start_new_terminal=yes ;; --quiet) ;; # user_wants="" ;; --msg-types=*) ;; # user_wants="${1#*=}" ;; # cli gui both "" -*) DIE "option '$1' not supported." ;; esac shift done SafetyWarning # see /etc/eos-script-lib-yad.conf about EOS_WELCOME_PACDIFFERS for differ in "${EOS_WELCOME_PACDIFFERS[@]}" ; do if [ -x /usr/bin/${differ%% *} ] ; then PacdiffCmd "$differ" return $? fi done } Main "$@"