1
0
mirror of https://github.com/slicer69/doas synced 2024-07-09 03:55:50 +00:00
doas/vidoas
Kimmo Suominen 7648f25667 Install doas.conf safely. Define DOAS_CONF only once.
- Use mv(1) to install doas.conf to avoid writing a configuration file
  while other processes might be reading it.
- Define the DOAS_CONF path once in Makefile and pass that to the
  substitutions instead of recreating the full path independently in
  multiple files.
- Add a separate rule for building the doas binary, instead of creating
  it in the "all" target.  This avoids some unnecessary re-linking.
2020-11-09 00:12:50 +02:00

125 lines
2.5 KiB
Bash
Executable File

#!/bin/sh
# Edit a temporary copy of the doas.conf file and check it for syntax
# errors before installing it as the actual doas.conf file.
set -eu
PATH=/bin:/usr/bin:/usr/local/bin
export PATH
PROG="${0##*/}"
umask 022
DOAS_CONF=@DOAS_CONF@
doas_lock_file="${DOAS_CONF}.lck"
die()
{
echo "${PROG}: ${@}" 1>&2
exit 1
}
warn()
{
echo "${PROG}: ${@}" 1>&2
}
get_intr()
{
stty -a \
| sed -En '
/^(.* )?intr = / {
s///
s/;.*$//
p
}
'
}
set_trap_rm()
{
local file file_list
file_list=
for file
do
file_list="${file_list} '${file}'"
done
if [ -n "${file_list}" ]
then
trap "rm -f ${file_list}" 0 1 2 15
fi
}
tmp_doas="$(mktemp "${DOAS_CONF}.XXXXXXXXXX")" \
|| die "You probably need to run ${PROG} as root"
set_trap_rm "${tmp_doas}"
# It is important that the ln(1) command fails if the target already
# exists. Some versions are known to behave like "ln -f" by default
# (removing any existing target). Adjust PATH to avoid such ln(1)
# implementations.
tmp_test_ln="$(mktemp "${DOAS_CONF}.XXXXXXXXXX")"
set_trap_rm "${tmp_doas}" "${tmp_test_ln}"
if ln "${tmp_doas}" "${tmp_test_ln}" 2>/dev/null
then
die 'ln(1) is not safe for lock files, bailing'
fi
# If a doas.conf file exists, copy it into the temporary file for
# editing. If none exist, the editor will open with an empty file.
if [ -f "${DOAS_CONF}" ]
then
if [ -r "${DOAS_CONF}" ]
then
cp "${DOAS_CONF}" "${tmp_doas}"
else
die "Cannot read ${DOAS_CONF}"
fi
fi
# Link the temporary file to the lock file.
if ln "${tmp_doas}" "${doas_lock_file}"
then
set_trap_rm "${tmp_doas}" "${tmp_test_ln}" "${doas_lock_file}"
else
die "${DOAS_CONF} is already locked"
fi
# Some versions of vi(1) exit with a code that reflects the number of
# editing errors made. This is why we ignore the exit code from the
# editor.
"${EDITOR:-vi}" "${tmp_doas}" || true
while ! doas -C "${tmp_doas}"
do
warn "Press enter to edit doas.conf again to fix it,"
warn "or interrupt ($(get_intr)) to cancel."
read status
"${EDITOR:-vi}" "${tmp_doas}" || true
done
# Use mv(1) to rename the temporary file to doas.conf as it is atomic.
# This avoids any problems from another process reading doas.conf while
# it is being written.
if [ -s "${tmp_doas}" ]
then
if cmp -s "${tmp_doas}" "${DOAS_CONF}"
then
warn "No changes made"
warn "${DOAS_CONF} unchanged"
else
mv "${tmp_doas}" "${DOAS_CONF}" \
&& warn "${DOAS_CONF} updated"
fi
else
warn "Not installing an empty doas.conf file"
warn "${DOAS_CONF} unchanged"
fi