chrisbra / sudoedit.vim Goto Github PK
View Code? Open in Web Editor NEWEdit Files using sudo or su or any other tool
Home Page: http://www.vim.org/scripts/script.php?script_id=2709
Edit Files using sudo or su or any other tool
Home Page: http://www.vim.org/scripts/script.php?script_id=2709
This problem surfaces when using eg. let g:sudoAuthArg="-u <user>"
.
Steps to reproduce:
VIM - Vi IMproved 7.3 (2010 Aug 15, compiled Feb 10 2013 02:28:47)
.vimrc
:
set undofile
set undodir=~/.vim/undo
sudo -u vim /tmp/test
vim /tmp/test
:let g:sudoAuth="sudo"
:let g:sudoAuthArg="-u nobody"
:SudoWrite
Now you have lost your undo. You can verify it by writing more and closing and opening the file, you won't get the undo.
Not sure what causes this. Will be happy to help debugging and testing.
SudoWrite
does not work with symlinks:
% echo foo > foo
% sudo chown root foo
% ln -s foo symlink
% vim -c 'norm o2' -c 'SudoWrite' -c q symlink
% cat foo
foo
The expected result would be to have "2" after "foo".
TEST CASE:
1. vim /etc/hosts
2. :SudoWrite /tmp/f1
3. :w /tmp/f2
"/tmp/f1" 15L, 298C written
Error occured, when writing undofile
It should write /tmp/f2
instead.
The error related to "undofile" might not be required (I was not seeing it initially).
Ref: 306d3f9
I just got the error "There was an error writing the file!", which is not very helpful.
It would be nice to have the error (from stderr) there additionally.
set runtimepath+=$PWD/sudoedit.vim
autocmd BufReadPre * echom "AU"
function! Test()
set foldlevel=99
normal 100gg
split
normal 200gg
" SudoWrite
endfunction
Run it using vim -Nu minimal.vim autoload/SudoEdit.vim
, then :call Test()
, and :SudoWrite
.
Notice how the buffer in the second window is at line 1, not 100.
I've noticed this for a long time already, and finally debugged it - vim-repeat is a (popular) plugin setting up BufReadPre
.
Might be a bug in Vim actually - happens with both Vim (8.1.1073) and Neovim for me.
After :SudoWrite
the cursor jumps to the beginning of the file.
This behavior changed recently (I've just noticed it), and might be caused by some other changes I've made to my configuration.
I am will debug this further / provide more information, if you cannot confirm it.
SudoEdit fails with error
'Error writing to file'
This is because in zsh, >$file fails if $file already exists.
So, the fix is to either use vim functions to write/append to
file or set shell in the beginning of script to bash or so,
latter is what I have done.
Test case:
1. echo 1 > 1
2. vi 1
3. `r2`
The buffer name is changed to "2", but the buffer's contents is back at "1". :e
will update it to "2".
:SudoWrite <tab>
should complete files from the current directory, but does not.
You need to use SudoWrite ./<tab>
.
TEST CASE:
1. cd /tmp
2. echo foo > foo
3. ln -sfn foo bar
4. start vim with "foo"
5. :SudoWrite bar
This is the output with g:sudoDebug=1
:
verb 1,1w !SUDO_ASKPASS='/usr/lib/openssh/gnome-ssh-askpass' sudo -A tee >/dev/null 'bar'
tee: bar: Permission denied
shell returned 1
1
verb wundo! /home/user/.local/share/vim/undo/\%tmp\%foo
Skipping undo file write, nothing to undo
Error detected while processing function SudoEdit#SudoDo..<SNR>155_Exception:
line 1:
The files:
lrwxrwxrwx 1 user user 3 Dec 17 17:41 /tmp/bar -> foo
-rw-rw-r-- 1 user user 4 Dec 17 17:41 /tmp/foo
:e sudo:/etc/rc.conf
shell returned 1
Error detected while processing function SudoEdit#SudoDo..122_SudoRead:
line 9:
Error reading ! Password wrong?
After issue #21 is fixed, another one pops up:
There is a Found a swap file by the name ".1.swp".
warning via:
line 31: exe "f" fnameescape(a:file)
This causes SudoWrite to abort:
Exception thrown: Vim(file):E325: ATTENTION
function SudoEdit#SudoDo..2_SudoWrite
line 31: End of function
TEST CASE:
echo 1 > 1
vim -u NONE -N -c 'set rtp+=~/.vim/bundle/sudoedit | ru! plugin/SudoEdit.vim | set undofile | exe "norm! r2" | SudoWrite' 1
I have a fix for this already, and will provide a pull request.
When I open a file, modify it, exec :SudoWrite and got an "NO (-60031)" error. I don't know how to get more detail error message but just let g:sudoDebug=1
verb 1,20w !security execute-with-privileges tee >/dev/null '/private/etc/hosts'
There was an error writing the file!
verb wundo! /Users/leemars/.vim/tmp/undo/\%private\%etc\%hosts
Writing undo file: /Users/leemars/.vim/tmp/undo/%private%etc%hosts
When creating a new file using :SudoWrite $filename
it is considered to be modified afterwards.
ifoo<Esc>
:SudoWrite /tmp/foo
While /tmp/foo
is written correctly, Vim considers it to be modified (see :set modified?
).
I have tested it using revision 69e6ccd.
I just had a problem where expand()
in SudoEdit#SudoDo
would fail (return an empty string).
SudoWrite 1
would fail with "Cannot write file. Please enter filename for writing!".
The directory (/srv/example.com/shared) contains a symlink:
drwxr-xr-x 1 user root 310 Dec 12 22:37 /srv
lrwxrwxrwx 1 root root 28 Jul 26 16:38 /srv/example.com -> /home/www-data/example.com
drwxrwxr-x 1 user www-data 120 Nov 25 22:11 /srv/example.com/shared
Here is screencast for demo. I also run vim without configuration (-u NORC), the result is remain the same.
My environment
$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description: Ubuntu 16.04.6 LTS
Release: 16.04
Codename: xenial
$ vim --version
VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Jan 02 2017 06:40:50)
Included patches: 1-134
Modified by pi-rho
Compiled by buildd@lcy01-12
Huge version without GUI. Features included (+) or not (-):
+acl +file_in_path +mouse_sgr +tag_old_static
+arabic +find_in_path -mouse_sysmouse -tag_any_white
+autocmd +float +mouse_urxvt -tcl
-balloon_eval +folding +mouse_xterm +termguicolors
-browse -footer +multi_byte +terminfo
++builtin_terms +fork() +multi_lang +termresponse
+byte_offset +gettext -mzscheme +textobjects
+channel -hangul_input +netbeans_intg +timers
+cindent +iconv +num64 +title
-clientserver +insert_expand +packages -toolbar
-clipboard +job +path_extra +user_commands
+cmdline_compl +jumplist +perl +vertsplit
+cmdline_hist +keymap +persistent_undo +virtualedit
+cmdline_info +lambda +postscript +visual
+comments +langmap +printer +visualextra
+conceal +libcall +profile +viminfo
+cryptv +linebreak +python/dyn +vreplace
+cscope +lispindent +python3/dyn +wildignore
+cursorbind +listcmds +quickfix +wildmenu
+cursorshape +localmap +reltime +windows
+dialog_con +lua/dyn +rightleft +writebackup
+diff +menu +ruby/dyn -X11
+digraphs +mksession +scrollbind -xfontset
-dnd +modify_fname +signs -xim
-ebcdic +mouse +smartindent -xpm
+emacs_tags -mouseshape +startuptime -xsmp
+eval +mouse_dec +statusline -xterm_clipboard
+ex_extra +mouse_gpm -sun_workshop -xterm_save
+extra_search -mouse_jsbterm +syntax
+farsi +mouse_netterm +tag_binary
system vimrc file: "$VIM/vimrc"
user vimrc file: "$HOME/.vimrc"
2nd user vimrc file: "~/.vim/vimrc"
user exrc file: "$HOME/.exrc"
defaults file: "$VIMRUNTIME/defaults.vim"
fall-back for $VIM: "/usr/share/vim"
Compilation: gcc -c -I. -Iproto -DHAVE_CONFIG_H -Wdate-time -Wall -Wextra -g -O2 -fPIE -Wformat -Werror=format-security -fstack-protector-all -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1
Linking: gcc -L. -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fstack-protector -rdynamic -Wl,-export-dynamic -Wl,-E -Wl,-Bsymbolic-functions -fPIE -pie -Wl,-z,relro -Wl,-z,now -Wl,-z,nodlopen -Wl,-z,nodump -Wl,-z,noexecstack -Wl,-z,noexecheap -Wl,--as-needed -o vim -lm -ltinfo -lnsl -lselinux -lacl -lattr -lgpm -ldl -Wl,-E -fstack-protector-strong -L/usr/local/lib -L/usr/lib/x86_64-linux-gnu/perl/5.22/CORE -lperl -ldl -lm -lpthread -lcrypt
My configuration for Vim
https://github.com/Gasol/vimrc
After having used SudoWrite
on a file, it would be nice to automatically use it for :w
etc afterwards.
This could be optional, of course.
What do you think?
gives multiple errors, starting with creating the empty error file.
see vim/vim#8600
workaround could be to use :p:8
only on the existing directory and appending the new filename later (which is not 8.3 format and wasn't in the past, because VIM appended the given text).
When trying to write the current buffer into a new filename, SudoEdit refuses to write it, if the buffer is unmodified: "Buffer not modified, not writing!"
I suggest that SudoEdit writes the buffer with the new name in this case.
(a workaround is to use the bang with "SudoWrite" to force writing)
I am getting the following error when trying to :SudoWrite
without a filename:
Cannot write file. Please enter filename for writing!
Error detected while processing function SudoEdit#SudoDo..SudoEdit#LocalSettings:
line 13:
E499: Empty file name for '%' or '#', only works with ":p:h": ^Isil e! %
I will submit a fix shortly.
I have started vim baz
, added some contents and then saved it using SudoWrite
directly.
This results in the following error:
Error detected while processing function SudoEdit#SudoDo..SudoEdit#SudoWrite:
line 20:
E325: ATTENTION
Press ENTER or type command to continue
W13: Warning: File "baz" has been created after editing started
[O]K, (L)oad File:
Vim 7.3.315.
I've noticed that :SudoWrite
messes with the undostack: after :SudoWrite
u
will jump back to the top of the file, instead of undoing the last edit.
It seems like the writing is added as a separate undo step, and it could be fixed by using :undojoin
probably.
When BufWriteCmd
is used/installed, it should trigger BufWritePost
after writing the file then.
Related code reference:
SudoEdit.vim/autoload/SudoEdit.vim
Line 354 in 80c04e0
This is required for statusline plugins to pick up the new modified state for example, and should be just done in general AFAIK.
I'm using Lion 10.7.2 and MacVim snapshot 63.
When I tried this command in MacVim :SudoEdit /private/etc/hosts, it frozen, and I can't do anything on it except quit.
I added this to my vimrc, the result is that I no longer get that annoying warning when editing a file where I don't have the correct permissions, and also that my normal write binding automatically calls SudoWrite (mine is nnoremap <leader>fw :set buftype=""<CR>:write!<CR>
- we may want to make this work for just regular :w
). My suggestion is to include this in SudoEdit.
augroup SudoWriteReadOnly
autocmd FileChangedRO * set noreadonly | execute "autocmd BufWriteCmd <buffer> SudoWrite"
augroup END
autocmd BufReadPre * echom 'AU'
function! Test()
call append(0, range(100))
exe 'w' tempname()
normal! 50gg
split
normal! 100gg
" edit
endfunction
When calling edit
at the end of the test setup (or manually) will scroll the buffer in the other window to the top.
This does not happen without the BufReadPre autocommand.
When editing autoload/SudoEdit.vim
, and setting foldlevel=99
it gets reset to 0 after :SudoWrite
.
I know filenames containing spaces are a terrible idea, but alas sometimes software from non-UNIX backgrounds ships with them by default. Whilst attempting to :SudoWrite a file whose filename contains spaces, I receive the following error:
verb try | undojoin | catch /^Vim\%((\a\+)\)\=:E790/ | endtry | 1,12w !SUDO_ASKPASS='/usr/bin/ksshaskpass' sudo -A tee >/dev/null '/opt/ti/Code Composer Studio 7.4.0.desktop'
Error detected while processing function SudoEdit#SudoDo[46]..<SNR>163_LocalSettings:
line 114:
E172: Only one file name allowed: edit Code Composer Studio 7.4.0.desktop
Which looks like the extension is misinterpreting a filename with spaces as multiple seperate filenames, unless I'm doing something else wrong? Thanks!
EDIT: Remove spurious errors in debug log.
Trying to write something to a directory where the user does not have write permission (say /etc) you get something like this:
E828: Cannot open undo file for writing: /etc/.foo.un~
It still writes the file, but you lose all content from the buffer and have to reopen if you want to edit more.
function SudoEdit#SudoDo[23]..<SNR>150_SudoWrite[52]..<SNR>150_Exec
line 14: 1,1088w !SUDO_ASKPASS='/usr/lib/ssh/x11-ssh-askpass' sudo -A tee >/dev/null 2>'/tmp/nvimxdnM8q/8/error' '/usr/share/awesome/lib/awful/prompt.lua'
>
sh: /tmp/nvimxdnM8q/8/error: Permission denied
shell returned 1
function SudoEdit#SudoDo[23]..<SNR>150_SudoWrite[52]..<SNR>150_Exec
This seems to come from s:error_file
being used for both privileged and unprivileged writes, and not being deleted always.
:SudoWrite foo
"foo" is missing from the undodir - no history has been written.
You need to trigger a regular write (using :w
for example) for the undofile being generated.
A simple :SudoWrite
throws There was an error writing the file! sudo: no tty present and no askpass program specified
in Neovim.
Doesn't occur in vanilla Vim.
:!sudo -v
and :!sh -ic 'sudo -v'
return the same sudo error.
See also:
https://github.com/neovim/neovim/wiki/FAQ#-and-system-do-weird-things-with-interactive-processes
neovim/neovim#1496
I have noticed several times already, that :SudoEdit
says:
Buffer not modified, not writing!
In that case, the buffer is considered to be not modified by Vim, but in fact it is.
I guess that it has something to do with the &undofile handling, because AFAIK undo is involved.
It happens in cases where I edit a file, save it with SudoEdit, then undo the change and then try to save it again:
TEST CASE:
Hi, since the very last commit I've been getting this error when trying to execute SudoWrite:
Error detected while processing function SudoEdit#SudoDo..107_SudoWrite:
line 35:
E117: Unknown function: 107_SetBufName
Thank you very much for this awesome plugin! One of my favorites :)
First of all, thanks for sharing this great plugin! It is far better than using the following,
cabbr w!! w !sudo tee > /dev/null %
, as it is not OS dependent, far easier to remember and very well documented.
I've just found it on a vi.stackexchange question and played a little with it (on linux). One point that I noticed is that it asks for the password a second time.
This seems to be caused by the wundo
call on <sid>LocalSettings()
.
But I don't understand why it is necessary; using the cabbr
above asks for the password only once, and it still writes to the undofile (I've tested restarting Vim and it still remembered the changes). If it is for some very specific corner case, do you think it is reasonable to change s:skip_wundo
to a global variable?
When trying to ":SudoWrite" a file opened via the netrw plugin (e.g. "scp://host//etc/fstab"), it fails as follows:
Error detected while processing function SudoEdit#SudoDo:
line 17:
There was an error writing the file!
It would be great if SudoWrite could manage this by e.g. logging in via "ssh" and copy/write the file using sudo
from there.
Hello, Chris!
I'm using SudoEdit.vim in gVim and it always returns 'no tty present and no askpass program specified' when executing ':SudoRead'. Finally I found that when I comment the following in my vimrc, :SudoRead works correctly.
set noshelltemp
So why couldn't I set 'noshelltemp' in my vimrc?
Hope for your reply!
OS: Arch Linux
Shell: zsh 5.0.5
gVim 7.4.220
Sudo 1.8.10
No graphical askpass program installed.
Latest version of SudoEdit.vim installed.
When trying to SudoWrite a file like /etc/fstab, I am getting the following error:
"/etc/fstab" 26L, 1473C written
Error detected while processing function SudoEdit#SudoDo..SudoEdit#LocalSettings:
line 16:
E828: Cannot open undo file for writing: /home/user/.local/share/vim/undo//etc/fstabetc/etc/fstabfstab
It looks like the undofile() function returns some odd path (in SudoEdit#LocalSettings), but works properly when called manually:
:echo undofile(@%)
/home/user/.local/share/vim/undo/%etc%fstab
Using Vim 7.3.315.
This is related to the fix for issue 3.
I have just used :SudoWrite
on a fresh profile (mkdir /tmp/h ; HOME=/tmp/h ; vim
), and got the following error:
Error detected while processing function SudoEdit#SudoDo:
line 5:
E605: Exception not caught: emptyfile
Reading the docs for :rundo
it seems something similar could be added to plugin/SudoEdit.vim:
au BufReadPost * call ReadUndo()
au BufWritePost * call WriteUndo()
func ReadUndo()
if filereadable(expand('%:h'). '/UNDO/' . expand('%:t'))
rundo %:h/UNDO/%:t
endif
endfunc
func WriteUndo()
let dirname = expand('%:h') . '/UNDO'
if !isdirectory(dirname)
call mkdir(dirname)
endif
wundo %:h/UNDO/%:t
endfunc
But changing the paths for the user's undodir
variable
After using SudoWrite
, I see the following error on exit:
Executing VimLeave Auto commands for "*"
autocommand :call SudoEdit#Rmdir(''/tmp/vwpmAmh/6'')
Error detected while processing VimLeave Auto commands for "*":
E121: Undefined variable: tmp
E116: Invalid arguments for function SudoEdit#Rmdir
This is caused because Mkdir(s:error_dir)
is called with s:error_dir
being escaped already, and the VimLeave autocommand adds additional quotes around it.
I think that Mkdir should take care of shell-escaping the argument.
On windows there are some problems one of them is that: fnmodify(path, ':p:8') return the part of the path that already exists.
i.e.
if C:\Users\Public\vim_temp_15128.txt
does not exist but C:\Users\Public
does then: fnmodify('C:\Users\Public\vim_temp_15128.txt', ':p:8')
returns C:\Users\Public
.
I suppose you are using the 8.3 format to avoid space in the path and to avoid the quote problem in the runas syntax:
runas /noprofile /user:MT-BRU-2-0102\ladmin "C:\Windows\system32\cmd.exe /k copy /Y C:\Users\Public\vim_temp_9676.txt C:\Users\vds\Desktop\hosts"
Maybe the alternative syntax is a fit that doesn't requiers the 8.3 syntax.
runas /noprofile /user:MT-BRU-2-0102\ladmin "C:\Windows\system32\cmd.exe /k copy /Y \"C:\Users\Public\vim_temp_9676.txt\" \"C:\Users\vds\Desktop\hosts\""
I'll create a Pull Request to proposes my changes.
Remark:
To convert to the 8.3 syntax you need to know what are the files in the directory.
Suppose you have in the folder the files:
abcdefgh1.txt
abcdefgh2.txt
abcdefgh3.txt
Convert abcdefg3.txt
in 8.3 will depend of the presence of abcdefg1.txt
.
Actually I believe the 8.3 name is created when the file is created in the folder or moved into the folder.
http://sprunge.us/IIDa is the output of :verbose autocmd BufWriteCmd
http://sprunge.us/jccZ is the output of :verbose autocmd FileWriteCmd
For instance for
vim sudo:/etc/rc.conf
while writing I get
File permissions of "rc.conf" are read-only.
It may still be possible to write it.
Do you wish to try?
(Y)es, [N]o:
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.