Refactor plugin to not rely on caching for writing anymore

Also test if the buffer is backed by a file, and fail if not
This commit is contained in:
Olivier Perret 2019-01-24 10:22:11 +01:00
parent f9bbf4606b
commit 9a11b5c8c2
2 changed files with 42 additions and 33 deletions

View File

@ -10,8 +10,6 @@ Add `sudo-write.kak` to your autoload dir: `~/.config/kak/autoload/`, or source
Call the `sudo-write` command. If your password has not been cached by `sudo`, you will be prompted to input it. Upon success, the buffer is written to the file.
Note that the plugin will not work if you do not use any cache for `sudo`.
**Warning**: while the input is hidden, the password is still passed through stdin to `sudo`. Do not use this plugin if you are not comfortable with this idea.
## License

View File

@ -1,9 +1,9 @@
# save the current buffer to its file as root
# save the current buffer to its file as root using `sudo`
# (optionally pass the user password to sudo if not cached)
define-command -hidden sudo-write-impl %{
define-command -hidden sudo-write-cached-password %{
# easy case: the password was already cached, so we don't need any tricky handling
eval -save-regs f %{
# TOOD this could take the content of the buffer from stdin instead
reg f %sh{ mktemp --tmpdir XXXXX }
write %reg{f}
eval %sh{
@ -11,49 +11,60 @@ define-command -hidden sudo-write-impl %{
if [ $? -eq 0 ]; then
echo "edit!"
else
echo "echo -markup '{Error}Something went wrong'"
echo 'fail "Unknown failure"'
fi
rm -f "$kak_main_reg_f"
}
}
}
define-command -hidden -params 1 sudo-cache-password %{
eval -no-hooks -save-regs '"c' %{
eval -draft %{
edit -scratch *sudo-write-pass*
reg '"' %arg{1}
exec "<a-p>|sudo -S echo ok<ret>"
try %{
exec '%H<a-k>ok<ret>'
reg c nop
} catch %{
reg c fail
}
}
delete-buffer *sudo-write-pass*
eval %reg{c}
}
}
define-command -hidden sudo-prompt-password %{
define-command -hidden sudo-write-prompt-password %{
prompt -password 'Password:' %{
try %{
sudo-cache-password %val{text}
sudo-write-impl
} catch %{
echo -markup '{Error}Incorrect password'
eval -save-regs r %{
eval -draft -save-regs 'tf|"' %{
reg t %val{buffile}
reg f %sh{ mktemp --tmpdir XXXXX }
write %reg{f}
# write the password in a buffer in order to pass it through STDIN to sudo
# somewhat dangerous, but better than passing the password
# through the shell scope's environment or interpolating it inside the shell string
# 'exec |' is pretty much the only way to pass data over STDIN
edit -scratch '*sudo-password-tmp*'
reg '"' "%val{text}"
exec <a-P>
reg | %{
sudo -S -- dd if="$kak_main_reg_f" of="$kak_main_reg_t" > /dev/null 2>&1
if [ $? -eq 0 ]; then
printf 'edit!'
else
printf 'fail "Incorrect password?"'
fi
rm -f "$kak_main_reg_f"
}
exec '|<ret>'
exec -save-regs '' '%"ry'
delete-buffer! '*sudo-password-tmp*'
}
eval %reg{r}
}
}
}
define-command sudo-write -docstring "Write the content of the buffer using sudo" %{
%sh{
eval %sh{
# tricky posix-way of getting the first character of a variable
# no subprocess!
if [ "${kak_buffile%"${kak_buffile#?}"}" != "/" ]; then
# not entirely foolproof as a scratch buffer may start with '/', but good enough
printf 'fail "Not a file"'
exit
fi
# check if the password is cached
if sudo -n true > /dev/null 2>&1; then
echo sudo-write-impl
printf sudo-write-cached-password
else
echo sudo-prompt-password
printf sudo-write-prompt-password
fi
}
}