mirror of
https://git.disroot.org/FollieHiyuki/dotfiles.git
synced 2025-02-17 18:13:03 -05:00
105 lines
3.4 KiB
Bash
Executable File
105 lines
3.4 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
|
|
# doasedit
|
|
# Link: git.io/doasedit
|
|
|
|
# Dependencies: opendoas <https://github.com/Duncaen/OpenDoas> or doas <https://cvsweb.openbsd.org/src/usr.bin/doas/>
|
|
|
|
# Author: Stanislav <git.io/monesonn>
|
|
# Description: doas equivalent to sudoedit.
|
|
# Licence: ISC
|
|
# Contribution: If you have some ideas, how to improve this script, feel free to make pull request or write an issue.
|
|
|
|
# Tips: Use this script with enabled persistence in doas.conf file, like:
|
|
#
|
|
# `permit persist :wheel`
|
|
#
|
|
# Also make sure that your doas.conf is owned by root with read-only permissions, like:
|
|
#
|
|
# # chown -c root:root /path/to/doas.conf && chmod 0400 path/to/doas.conf
|
|
#
|
|
|
|
# Throw error message.
|
|
err() {
|
|
printf "%s%s\n" "doasedit: " "${1}" >&2
|
|
exit "${2}"
|
|
}
|
|
|
|
# Catch arguments.
|
|
if [ -n "${2}" ]; then
|
|
err "expected only one argument" 1
|
|
elif [ -z "${1}" ]; then
|
|
err "no file path provided" 2
|
|
elif [ "$(id -u)" -eq 0 ]; then
|
|
err "doasedit: cannot be run as root" 3
|
|
elif [ -d "${1}" ]; then
|
|
err "${1} is a directory" 4
|
|
fi
|
|
|
|
# Safe shell options.
|
|
set -eu
|
|
|
|
# Reset doas password promt. If you want, feel free to comment this.
|
|
case "$(uname -s | tr '[:upper:]' '[:lower:]')" in
|
|
linux) doas -L ;;
|
|
esac
|
|
|
|
# Absolute path to the source file (file for editing).
|
|
src="$(doas readlink -f "${1}")"
|
|
|
|
# Filename for the source file.
|
|
filename="${src##*/}"
|
|
|
|
# If filename have suffix then also use it for a temporary file.
|
|
# It's kinda useful for editors, that have plugins or something else for certain file extensions.
|
|
[ "$filename" = "${filename##*.}" ] && filename_ext="" || filename_ext=".${filename##*.}"
|
|
|
|
# Be sure /tmp as tmp directory by setting TMPDIR env.
|
|
export TMPDIR=/tmp
|
|
|
|
# Create a temporary directory.
|
|
tmp_d=$(mktemp -d)
|
|
|
|
# Create a temporary file for the source file in a temporary directory.
|
|
tmp_f="${tmp_d}/${filename}$(xxd -l4 -ps /dev/urandom)${filename_ext}"
|
|
|
|
# File writeability condition.
|
|
if [ -w "$src" ]; then
|
|
err "$filename: editing files in a writable directory is not permitted" 5
|
|
fi
|
|
|
|
# Other conditions: if file exist, readable, etc.
|
|
if [ -f "${src}" ] && [ ! -r "${src}" ]; then
|
|
doas cat "${src}" > "${tmp_f}" || err "the file is not readable" 6
|
|
elif [ -r "${src}" ]; then
|
|
cat "${src}" > "${tmp_f}" || err "cannot transfer to content of the file to temporary one" 7
|
|
elif [ ! -f "${src}" ]; then
|
|
# Grant .rw-r--r-- permission for newly created files by default owned by root.
|
|
:> "${tmp_f}" && doas chmod -R 0644 "${tmp_f}" || err "cannot create new file" 8
|
|
else
|
|
err "unexpected script behaviour" 9
|
|
fi
|
|
|
|
# Create copy of the temporary file.
|
|
tmp_cf="${tmp_d}/${filename}$(xxd -l4 -ps /dev/urandom).copy"
|
|
|
|
# Hooks for recursive removing of a temporary directory.
|
|
trap 'rm -rf ${tmp_d}' EXIT HUP QUIT TERM INT ABRT
|
|
|
|
# Move the contents of a temporary file to its copy for later comparison.
|
|
cat "${tmp_f}" > "${tmp_cf}"
|
|
|
|
# Editing the file by the user using the default editor, if not specified, the vi is used.
|
|
${EDITOR:-vi} "${tmp_f}"
|
|
|
|
# Compare the temporary file and the temporary copy.
|
|
if cmp -s "${tmp_f}" "${tmp_cf}"; then
|
|
printf "%s\n" "doasedit: $filename unchanged"
|
|
exit 0
|
|
else
|
|
# Replace the source file with temporary, repeats three times if it fails.
|
|
for doas_tries in $(seq 1 3); do doas cp -f "${tmp_f}" "${src}" && break; done
|
|
printf "%s\n" "doasedit: $filename changes are accepted"
|
|
exit 0
|
|
fi
|