From 190d79625e270de17d33f8f8960889ad819c41d0 Mon Sep 17 00:00:00 2001 From: Florian Pritz Date: Sun, 27 Oct 2013 22:01:37 +0100 Subject: replace sudo.vim with SudoEdit.vim Signed-off-by: Florian Pritz --- .vim/bundle/SudoEdit/autoload/SudoEdit.vim | 468 +++++++++++++++++++++++++++++ .vim/bundle/SudoEdit/autoload/sudo.cmd | 84 ++++++ 2 files changed, 552 insertions(+) create mode 100644 .vim/bundle/SudoEdit/autoload/SudoEdit.vim create mode 100644 .vim/bundle/SudoEdit/autoload/sudo.cmd (limited to '.vim/bundle/SudoEdit/autoload') diff --git a/.vim/bundle/SudoEdit/autoload/SudoEdit.vim b/.vim/bundle/SudoEdit/autoload/SudoEdit.vim new file mode 100644 index 0000000..a136c6e --- /dev/null +++ b/.vim/bundle/SudoEdit/autoload/SudoEdit.vim @@ -0,0 +1,468 @@ +" SudoEdit.vim - Use sudo/su for writing/reading files with Vim +" --------------------------------------------------------------- +" Version: 0.19 +" Authors: Christian Brabandt +" Last Change: Wed, 14 Aug 2013 22:29:27 +0200 +" Script: http://www.vim.org/scripts/script.php?script_id=2709 +" License: VIM License +" GetLatestVimScripts: 2709 19 :AutoInstall: SudoEdit.vim + +" Functions: "{{{1 + +let s:dir=fnamemodify(expand(""), ':p:h') + +fu! Init() "{{{2 +" Which Tool for super-user access to use +" Will be tried in order, first tool that is found will be used +" (e.g. you could use ssh) +" You can specify one in your .vimrc using the +" global variable g:sudoAuth + +" each time check, whether the authentication +" method changed (e.g. the User set a variable) +" if !exists("s:AuthTool") + let s:sudoAuth=" sudo su " + if Is("mac") + let s:sudoAuth = "security ". s:sudoAuth + elseif Is("win") + let s:sudoAuth = "runas elevate ". s:sudoAuth + endif + if exists("g:sudoAuth") + let s:sudoAuth = g:sudoAuth .' '. s:sudoAuth + endif + + " Specify the parameter to use for the auth tool e.g. su uses "-c", but + " for su, it will be autodetected, sudo does not need one, for ssh use + " "root@localhost" + " + " You can also use this parameter if you do not want to become root + " but any other user + " + " You can specify this parameter in your .vimrc using the + " global variable g:sudoAuthArg + if !exists("g:sudoAuthArg") + let s:sudoAuthArg="" + else + let s:sudoAuthArg=g:sudoAuthArg + endif + + let s:AuthTool = CheckAuthTool(split(s:sudoAuth, '\s')) + if empty(s:AuthTool) + call echoWarn("No authentication tool found, aborting!") + throw "sudo:noTool" + endif + if s:AuthTool[0] == "su" && empty(s:sudoAuthArg) + let s:sudoAuthArg="-c" + elseif s:AuthTool[0] == "security" && empty(s:sudoAuthArg) + let s:sudoAuthArg="execute-with-privileges" + elseif s:AuthTool[0] == "runas" && empty(s:sudoAuthArg) + let s:sudoAuthArg = "/noprofile /user:\"Administrator\"" + endif + if Is("win") + if !exists("s:writable_file") + " Write into public directory so everybody can access it + " easily + let s:writable_file = (empty(expand("$PUBLIC")) ? + \ expand("$TEMP") : expand("$PUBLIC") ). + \ '\vim_temp.txt' + let s:writable_file = shellescape(fnamemodify(s:writable_file, ':p:8')) + endif + else + let s:writable_file = tempname() + endif + + call SudoAskPasswd() + call add(s:AuthTool, s:sudoAuthArg . " ") + if !exists("s:error_dir") + let s:error_dir = tempname() + call Mkdir(s:error_dir) + let s:error_file = s:error_dir. '/error' + if Is("win") + let s:error_file = s:error_dir. '\error' + let s:error_file = fnamemodify(s:error_file, ':p:8') + endif + endif +" endif + " Stack of messages + let s:msg = [] +endfu + +fu! Mkdir(dir) "{{{2 + " First remove the directory, it might still be there from last call + let dir = shellescape(a:dir) + call SudoEdit#Rmdir(dir) + call system("mkdir ". dir) + " Clean up on Exit + if !exists('#SudoEditExit#VimLeave') + augroup SudoEditExit + au! + " Clean up when quitting Vim + exe "au VimLeave * :call SudoEdit#Rmdir(".dir. ")" + augroup END + endif +endfu + +fu! LocalSettings(values, readflag) "{{{2 + if empty(a:values) + " Set shellrediraction temporarily + " This is used to get su working right! + let o_srr = &srr + " avoid W11 warning + let o_ar = &l:ar + let &srr = '>' + setl ar + let o_tti = &t_ti + let o_tte = &t_te + " Turn off screen switching + set t_ti= t_te= + " Set shell to something sane (zsh, doesn't allow to override files using + " > redirection, issue #24, hopefully POSIX sh works everywhere) + let o_shell = &shell + if !Is("win") + set shell=sh + endif + call Init() + return [o_srr, o_ar, o_tti, o_tte, o_shell] + else + " Make sure, persistent undo information is written + " but only for valid files and not empty ones + let file=substitute(expand("%"), '^sudo:', '', '') + try + if has("persistent_undo") + let undofile = undofile(file) + if !empty(file) && + \!CheckNetrwFile(@%) && !empty(undofile) && + \ &l:udf + if !a:readflag + " Force reading in the buffer to avoid stupid W13 warning + " don't do this in GUI mode, so one does not have to enter + " the password again (Leave the W13 warning) + if !has("gui_running") && exists("s:new_file") && s:new_file + "sil call SudoRead(file) + " Be careful, :e! within a BufWriteCmd can crash Vim! + exe "e!" file + endif + if empty(glob(undofile)) && + \ &undodir =~ '^\.\($\|,\)' + " Can't create undofile + call add(s:msg, "Can't create undofile in current " . + \ "directory, skipping writing undofiles!") + throw "sudo:undofileError" + endif + call Exec("wundo! ". fnameescape(undofile(file))) + if empty(glob(fnameescape(undofile(file)))) + " Writing undofile not possible + call add(s:msg, "Error occured, when writing undofile") + return + endif + if is("unix") && !empty(undofile) + let ufile = string(shellescape(undofile, 1)) + let perm = system("stat -c '%u:%g' " . + \ shellescape(file, 1))[:-2] + " Make sure, undo file is readable for current user + let cmd = printf("!%s sh -c 'test -f %s && ". + \ "chown %s -- %s && ", + \ join(s:AuthTool, ' '), ufile, perm, ufile) + let cmd .= printf("chmod a+r -- %s 2>%s'", ufile, shellescape(s:error_file)) + if has("gui_running") + call echoWarn("Enter password again for". + \ " setting permissions of the undofile") + endif + call Exec(cmd) + "call system(cmd) + endif + endif + endif + endif " has("persistent_undo") + catch + " no-op + finally + " Make sure W11 warning is triggered and consumed by 'ar' setting + checktime + " Reset old settings + " shellredirection + let &srr = a:values[0] + " Screen switchting codes, and shell + let [ &t_ti, &t_te, &shell ] = a:values[2:4] + " Reset autoread option + let &l:ar = a:values[1] + endtry + endif +endfu + +fu! CheckAuthTool(Authlist) "{{{2 + for tool in a:Authlist + if executable(tool) || + \ (tool == 'uac' && Is("win")) "enable experimental support for UAC on windows + return [tool] + endif + endfor + echoerr "No tool found for authentication. Is sudo/su installed and in your $PATH?" + echoerr "Try setting g:sudoAuth and g:sudoAuthArg" + return [] +endfu + +fu! echoWarn(mess) "{{{2 + echohl WarningMsg + echomsg a:mess + echohl Normal +endfu + +fu! SudoRead(file) "{{{2 + sil %d _ + if Is("win") + let file=shellescape(fnamemodify(a:file, ':p:8')) + let cmd= '!'. s:dir.'\sudo.cmd dummy read '. file. + \ ' '. s:writable_file. ' '. + \ join(s:AuthTool, ' ') + else + let cmd='cat ' . shellescape(a:file,1) . ' 2>'. shellescape(s:error_file) + if s:AuthTool[0] =~ '^su$' + let cmd='"' . cmd . '" --' + endif + let cmd=':0r! ' . join(s:AuthTool, ' ') . cmd + endif + call Exec(cmd) + if v:shell_error + echoerr "Error reading ". a:file . "! Password wrong?" + throw "sudo:readError" + endif + if Is("win") + if !filereadable(s:writable_file[1:-2]) + call add(s:msg, "Temporary file ". s:writable_file. + \ " does not exist. Probably access was denied!") + throw "sudo:readError" + else + exe ':0r ' s:writable_file[1:-2] + endif + endif + sil $d _ + if has("persistent_undo") + " Force reading undofile, if one exists + if filereadable(undofile(a:file)) + exe "sil rundo" escape(undofile(a:file), '%') + endif + endif + filetype detect + set nomod +endfu + +fu! SudoWrite(file) range "{{{2 + if s:AuthTool[0] == 'su' + " Workaround since su cannot be run with :w ! + exe a:firstline . ',' . a:lastline . 'w! ' . s:writable_file + let cmd=':!' . join(s:AuthTool, ' ') . '"mv ' . s:writable_file . ' ' . + \ shellescape(a:file,1) . '" --' + else + if Is("win") + exe a:firstline . ',' . a:lastline . 'w! ' . s:writable_file[1:-2] + let cmd= '!'. s:dir.'\sudo.cmd dummy write '. shellescape(fnamemodify(a:file, ':p:8')). + \ ' '. s:writable_file. ' '. join(s:AuthTool, ' ') + else + let cmd=printf('tee >/dev/null 2>%s %s',shellescape(s:error_file), shellescape(a:file,1)) + let cmd=a:firstline . ',' . a:lastline . 'w !' . + \ join(s:AuthTool, ' ') . cmd + endif + endif + if CheckNetrwFile(a:file) && exists(":NetUserPass") == 2 + let protocol = matchstr(a:file, '^[^:]:') + call echoWarn('Using Netrw for writing') + let uid = input(protocol . ' username: ') + let passwd = inputsecret('password: ') + call NetUserPass(uid, passwd) + " Write using Netrw + w + else + let s:new_file = 0 + if empty(glob(a:file)) + let s:new_file = 1 + endif + call Exec(cmd) + endif + if v:shell_error + throw "sudo:writeError" + endif + " Write successful + if &mod + setl nomod + endif +endfu + +fu! Stats(file) "{{{2 + ":w echoes a string like this by default: + ""SudoEdit.vim" 108L, 2595C geschrieben + return '"' . a:file . '" ' . line('$') . 'L, ' . getfsize(expand(a:file)) . 'C written' +endfu + +fu! Is(os) "{{{2 + if (a:os == "win") + return has("win32") || has("win16") || has("win64") + elseif (a:os == "mac") + return has("mac") || has("macunix") + elseif (a:os == "unix") + return has("unix") || has("macunix") + endif +endfu + +fu! Mes(msg) "{{{2 + if !(exists("g:sudoDebug") && g:sudoDebug) + redr! + if empty(s:msg) + return + endif + endif + for mess in a:msg + echo mess + endfor + let s:msg=[] +endfu + +fu! Exception(msg) "{{{2 + echohl Error + echomsg a:msg + if exists("g:sudoDebug") && g:sudoDebug + echo v:throwpoint + else + echohl Normal + call input("Hit enter to continue") + endif + echohl Normal +endfu + +fu! CheckNetrwFile(file) "{{{2 + return a:file =~ '^\%(dav\|fetch\|ftp\|http\|rcp\|rsync\|scp\|sftp\):' +endfu + +fu! SudoAskPasswd() "{{{2 + if s:AuthTool[0] != 'sudo' || + \ s:AuthTool[0] =~ 'SUDO_ASKPASS' || + \ ( exists("g:sudo_no_gui") && g:sudo_no_gui == 1) || + \ !has("unix") || + \ !exists("$DISPLAY") + return + endif + + let askpwd = ["/usr/lib/openssh/gnome-ssh-askpass", + \ "/usr/bin/ksshaskpass", + \ "/usr/lib/ssh/x11-ssh-askpass" ] + if exists("g:sudo_askpass") + let askpwd = insert(askpwd, g:sudo_askpass, 0) + endif + let sudo_arg = '-A' + let sudo_askpass = expand("$SUDO_ASKPASS") + if sudo_askpass != "$SUDO_ASKPASS" + let list = [ sudo_askpass ] + askpwd + else + let list = askpwd + endif + for item in list + if executable(item) + " give environment value to sudo, so -A knows + " which program to call + if (s:AuthTool[0] !~ 'SUDO_ASKPASS') + call insert(s:AuthTool, 'SUDO_ASKPASS='.shellescape(item,1), 0) + call add(s:AuthTool, '-A') + return + endif + endif + endfor +endfu + +fu! Exec(cmd) "{{{2 + let cmd = a:cmd + if exists("g:sudoDebug") && g:sudoDebug + let cmd = substitute(a:cmd, '2>'.shellescape(s:error_file), '', 'g') + let cmd = 'verb '. cmd + call echoWarn(cmd) + exe cmd + " probably hit-enter prompt is shown + else + if has("gui_running") + exe cmd + else + silent exe cmd + " avoid hit-enter prompt + redraw! + endif + endif + if filereadable(s:error_file) && getfsize(s:error_file) > 0 + let error=readfile(s:error_file) + call add(s:msg, join(error, "\n")) + call delete(s:error_file) + endif +endfu +fu! SudoEdit#Rmdir(dir) "{{{2 + if Is("win") + sil! call system("rd /s /q ". a:dir) + else + sil! call system("rm -rf -- ". a:dir) + endif +endfu + +fu! SudoEdit#SudoDo(readflag, force, file) range "{{{2 + try + let _settings=LocalSettings([], 1) + catch /sudo:noTool/ + call LocalSettings(_settings, a:readflag) + return + endtry + let s:use_sudo_protocol_handler = 0 + if empty(a:file) + let file = expand("%") + else + let file = expand(a:file) + if empty(file) + let file = a:file " expand() might fail (issue #17) + endif + if file =~ '^sudo:' + let s:use_sudo_protocol_handler = 1 + let file = substitute(file, '^sudo:', '', '') + endif + let file = fnamemodify(file, ':p') + endif + if empty(file) + call echoWarn("Cannot write file. Please enter filename for writing!") + call LocalSettings(_settings, 1) + return + endif + try + if a:readflag + if !&mod || !empty(a:force) + call SudoRead(file) + else + call add(s:msg, "Buffer modified, not reloading!") + return + endif + else + if !&mod && empty(a:force) && empty(a:file) + call add(s:msg, "Buffer not modified, not writing!") + return + endif + exe a:firstline . ',' . a:lastline . 'call SudoWrite(file)' + call add(s:msg, Stats(file)) + endif + catch /sudo:writeError/ + call Exception("There was an error writing the file!") + return + catch /sudo:readError/ + call Exception("There was an error reading the file ". file. " !") + return + finally + " Delete temporary file + call delete(s:writable_file) + call LocalSettings(_settings, a:readflag) + call Mes(s:msg) + endtry + if file !~ 'sudo:' && s:use_sudo_protocol_handler + let file = 'sudo:' . fnamemodify(file, ':p') + endif + if s:use_sudo_protocol_handler || + \ empty(expand("%")) || + \ file != expand("%") + exe ':sil f ' . file + filetype detect + endif +endfu + +" Modeline {{{1 +" vim: set fdm=marker fdl=0 ts=4 sts=4 sw=4 et: }}} diff --git a/.vim/bundle/SudoEdit/autoload/sudo.cmd b/.vim/bundle/SudoEdit/autoload/sudo.cmd new file mode 100644 index 0000000..8f919cb --- /dev/null +++ b/.vim/bundle/SudoEdit/autoload/sudo.cmd @@ -0,0 +1,84 @@ +@echo off +cls + +setlocal DisableDelayedExpansion +set "batchPath=%~0" +setlocal EnableDelayedExpansion + +:: File to write to +set dummy=%1 +set mode=%2 +set myfile=%3 +set newcontent=%4 +set sudo=%5 +shift +shift +shift +shift +shift + +if '%sudo%' == 'uac' goto checkPrivileges +if '%dummy%' == 'ELEV' goto gotPrivileges + +:: Use runas or something alike to elevate priviliges, but +:: first parse parameter for runas +:: Windows cmd.exe is very clumsy to use ;( +set params=%1 +:loop +shift +if [%1]==[] goto afterloop +set params=%params% %1 +goto loop + +:afterloop + +:: Use runas or so to elevate rights +echo. +echo *************************************** +echo Calling %sudo% for Privilege Escalation +echo *************************************** +if '%mode%' == 'write' ( + %sudo% %params% "cmd.exe /c type %newcontent% >%myfile%" + ) else ( + %sudo% %params% "cmd.exe /c type %myfile% >%newcontent%" + ) +goto end + +:: Use UAC to elevate rights, idea taken from: +:: http://stackoverflow.com/questions/7044985/how-can-i-auto-elevate-my-batch-file-so-that-it-requests-from-uac-admin-rights +:checkPrivileges +::NET FILE 1>NUL 2>NUL +set vbs="%temp%\GetPrivileges.vbs" + +:: Check if we already have system priviliges +>NUL 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" +if '%errorlevel%' EQU '0' (goto gotPrivileges) else (goto getPrivileges) + +:getPrivileges +echo. +echo ************************************** +echo Invoking UAC for Privilege Escalation +echo ************************************** + +echo Set UAC = CreateObject^("Shell.Application"^) > %vbs% +echo UAC.ShellExecute "!batchPath!", "ELEV !mode! "!myfile!" "!newcontent!"" , "", "runas", 1 >> %vbs% +:: Run VBS script +%vbs% +exit /B + +:gotPrivileges +::setlocal & pushd . +:: Doesn't work? +if exist %vbs% (del %vbs%) +pushd "%CD%" +cd /d "%~dp0" + +if '%mode%' == 'write' ( + cmd.exe /c type %newcontent% > %myfile% +) else ( + cmd.exe /c type %myfile% > %newcontent% +) + +if '%errorlevel%' NEQ 0 echo "An error occured" + +:end -- cgit v1.2.3-24-g4f1b