Re-open read-only files as root automagically
I have my emacs running as server and two small wrapper scripts ec and et which connect to it with emacsclient (either creating a new frame or opening a terminal frame).
Because I want to do all my system administration (editing files in /etc/) with emacs and don’t want to start another emacs instance as root, I use TRAMP to switch to superuser mode automagically if the opened file is read-only.
Here’s the code (UPDATED: Uses defadvice instead of hooking into find-file-hook, which had the bad effect of find-file-hook running twice.):
(defun th-rename-tramp-buffer ()
(when (file-remote-p (buffer-file-name))
(rename-buffer
(format "%s:%s"
(file-remote-p (buffer-file-name) 'method)
(buffer-name)))))
(add-hook 'find-file-hook
'th-rename-tramp-buffer)
(defadvice find-file (around th-find-file activate)
"Open FILENAME using tramp's sudo method if it's read-only."
(if (and (not (file-writable-p (ad-get-arg 0)))
(y-or-n-p (concat "File "
(ad-get-arg 0)
" is read-only. Open it as root? ")))
(th-find-file-sudo (ad-get-arg 0))
ad-do-it))
(defun th-find-file-sudo (file)
"Opens FILE with root privileges."
(interactive "F")
(set-buffer (find-file (concat "/sudo::" file))))
Now whenever I type ec /some/file/i/have/no/permissions/to/write (or emacsclient [-c|-t] /some/root/file, emacs asks me to re-open it using TRAMP’s sudo method.
Hi,
I use something similar here, and I also use this little hack :
8<——————————–
(defun my-tramp-header-line-function ()
(when (string-match “^/su\\(do\\)?:” default-directory)
(setq header-line-format
(format-mode-line “—– THIS BUFFER IS VISITED WITH ROOT PRIVILEGES —–”
‘font-lock-warning-face))))
(add-hook ‘find-file-hooks ‘my-tramp-header-line-function)
8<——————————–
so that I’m warned whenever I’m editing something as root. It would be redundant with your hack to prefix buffer name with sudo, though.
paul r
August 20, 2008 at 9:43 pm
I also do something similar, except that along with my ‘em’ script (which runs emacsclient, emacsclient -nw, or emacs as needed), I also have a script called ’se’ (for sudo edit), which rewrites the filename as a tramp sudo path and then calls my ‘em’ script.
JFM
August 21, 2008 at 5:28 pm
How do you use it with zsh?
What tramp-shell-prompt-pattern variable value?
(I’m can’t do it working with zsh)
iNode
September 13, 2008 at 12:19 pm
Hi iNode,
with ZSH you have to disable the Z Line Editor. So I have this in my ~/.zshrc:
if [[ ${TERM} != "dumb" ]]; then
# Setup my default prompt
else
prompt off
# switch of the zsh line editor, cause emacs shell and TRAMP doesn’t work
# with it.
unsetopt zle
fi
Tassilo Horn
September 15, 2008 at 7:26 am
Hi
That is some very usefull code
However as I have several files I own that is read-only (files under version control with rcs), it would be nice not to be asked about opening my own files as root. I thought that should be easy to change even with my limited elisp knowledge. I have tried some thing like this:
(defun th-find-file-sudo-maybe ()
“Re-finds the current file as root if it’s read-only after
querying the user.”
(interactive)
(let ((file (buffer-file-name)))
(and
; (not (file-writable-p file))
(equal 0 (nth 3 (file-attributes file)))
(y-or-n-p “File is owned by root. Open it as root? “)
(progn
(kill-buffer (current-buffer))
(th-find-file-sudo file)))))
Well, it works, but it asks the question “File is owned by root. Open it as root? ” two times!? I have no clue why, as testing if the file is owned by root
(equal 0 (nth 3 (file-attributes file)))
returns t just as
(not (file-writable-p file))
Niels
September 27, 2008 at 2:06 pm
I guess your problem is due to find-file-hook being run twice. I post a better version which uses defadvice.
Bye,
Tassilo
Tassilo Horn
September 28, 2008 at 8:26 am
Put the buffer renaming within the advice, and added special case for when you are the owner of the file:
(defadvice find-file (around my-find-file activate)
“Open FILENAME using tramp’s sudo method if it’s read-only and
not owned by current user.”
(let* ((my-filename (ad-get-arg 0))
(file-owner-uid (nth 2 (file-attributes my-filename))))
(if (not (file-writable-p my-filename))
(if (and (not (= file-owner-uid (user-uid)))
(y-or-n-p (concat “File ” my-filename ” is read-only. Open it as root? “)))
(progn
(ad-set-arg 0 (concat “/sudo::” my-filename))
ad-do-it
(rename-buffer
(format “%s:%s”
(file-remote-p (buffer-file-name) ‘method)
(buffer-name))))
(if (and (= file-owner-uid (user-uid))
(y-or-n-p (concat “File ” my-filename ” is read-only. Make buffer writable? “)))
(progn
ad-do-it
(toggle-read-only -1))))
ad-do-it)))
Fernando
November 17, 2008 at 12:20 am