From 3ba30eb8377c8b895ce75ef25057cf4304d7cd2a Mon Sep 17 00:00:00 2001
From: Michael Albinus <michael.albinus@gmx.de>
Date: Fri, 27 Nov 2009 16:29:03 +0000
Subject: [PATCH] * eshell/em-unix.el (eshell/su, eshell/sudo): New defuns,
 providing a Tramp related implementation of "su" and "sudo".
 (eshell-unix-initialize): Add "su" and "sudo".

---
 lisp/ChangeLog         |  6 ++++
 lisp/eshell/em-unix.el | 62 +++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 67 insertions(+), 1 deletion(-)

diff --git a/lisp/ChangeLog b/lisp/ChangeLog
index 7227f11add3..6e719cfe520 100644
--- a/lisp/ChangeLog
+++ b/lisp/ChangeLog
@@ -1,3 +1,9 @@
+2009-11-27  Michael Albinus  <michael.albinus@gmx.de>
+
+	* eshell/em-unix.el (eshell/su, eshell/sudo): New defuns,
+	providing a Tramp related implementation of "su" and "sudo".
+	(eshell-unix-initialize): Add "su" and "sudo".
+
 2009-11-27  Daiki Ueno  <ueno@unixuser.org>
 
 	* net/socks.el (socks-send-command): Convert binary request to
diff --git a/lisp/eshell/em-unix.el b/lisp/eshell/em-unix.el
index d6ba970b6bb..ceba51ea830 100644
--- a/lisp/eshell/em-unix.el
+++ b/lisp/eshell/em-unix.el
@@ -145,7 +145,7 @@ Otherwise, Emacs will attempt to use rsh to invoke du on the remote machine."
   (make-local-variable 'eshell-complex-commands)
   (setq eshell-complex-commands
 	(append '("grep" "egrep" "fgrep" "agrep" "glimpse" "locate"
-		  "cat" "time" "cp" "mv" "make" "du" "diff")
+		  "cat" "time" "cp" "mv" "make" "du" "diff" "su" "sudo")
 		eshell-complex-commands)))
 
 (defalias 'eshell/date     'current-time-string)
@@ -1041,6 +1041,66 @@ Show wall-clock time elapsed during execution of COMMAND.")
 
 (put 'eshell/occur 'eshell-no-numeric-conversions t)
 
+;; Pacify the byte-compiler.
+(defvar tramp-default-proxies-alist)
+
+(defun eshell/su (&rest args)
+  "Alias \"su\" to call Tramp."
+  (let ((-login (member "-" args)) ;; not handled by `eshell-eval-using-options'
+	login)
+    (eshell-eval-using-options
+     "sudo" args
+     '((?h "help" nil nil "show this usage screen")
+       (?l "login" nil login "provide a login environment")
+       (?  nil nil login "provide a login environment")
+       :usage "[- | -l | --login] [USER]
+Become another USER during a login session.")
+     (throw 'eshell-replace-command
+	    (let ((user "root")
+		  (host (or (file-remote-p default-directory 'host)
+			    "localhost"))
+		  (dir (or (file-remote-p default-directory 'localname)
+			   default-directory)))
+	      (if (or login -login) (setq dir "~/"))
+	      (if (stringp (car args)) (setq user (car args)))
+	      (if (and (file-remote-p default-directory)
+		       (not (string-equal
+			     user (file-remote-p default-directory 'user))))
+		  (add-to-list
+		   'tramp-default-proxies-alist
+		   (list host user (file-remote-p default-directory))))
+	      (eshell-parse-command
+	       "eshell/cd" (list (format "/su:%s@%s:%s" user host dir))))))))
+
+(put 'eshell/su 'eshell-no-numeric-conversions t)
+
+(defun eshell/sudo (&rest args)
+  "Alias \"sudo\" to call Tramp."
+  (let (user)
+    (eshell-eval-using-options
+     "sudo" args
+     '((?h "help" nil nil "show this usage screen")
+       (?u "user" t user "execute a command as another USER")
+       :show-usage
+       :usage "[(-u | --user) USER] COMMAND
+Execute a COMMAND as the superuser or another USER.")
+     (throw 'eshell-external
+	    (let* ((user (or user "root"))
+		   (host (or (file-remote-p default-directory 'host)
+			     "localhost"))
+		   (dir (or (file-remote-p default-directory 'localname)
+			    default-directory))
+		   (default-directory (format "/sudo:%s@%s:%s" user host dir)))
+	      (if (and (file-remote-p default-directory)
+		       (not (string-equal
+			     user (file-remote-p default-directory 'user))))
+		  (add-to-list
+		   'tramp-default-proxies-alist
+		   (list host user (file-remote-p default-directory))))
+	      (eshell-named-command (car args) (cdr args)))))))
+
+(put 'eshell/sudo 'eshell-no-numeric-conversions t)
+
 (provide 'em-unix)
 
 ;; Local Variables:
-- 
2.39.5