unofficial mirror of bug-gnu-emacs@gnu.org 
 help / color / mirror / code / Atom feed
* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
@ 2022-10-30 16:42 Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2022-10-30 21:51 ` Jim Porter
  0 siblings, 1 reply; 11+ messages in thread
From: Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-10-30 16:42 UTC (permalink / raw)
  To: 58899

[-- Attachment #1: Type: text/plain, Size: 760 bytes --]


This patch adds a “doas” command alias to eshell for users who prefer
doas, similar to the existing “su” and “sudo” command aliases.

I'm unsare whether to use “TRAMP” or “Tramp” spelling. The existing
routines in the file use the former, but I've been informed the latter
is correct. A future patch should make all spellings (at least within
this module) consistent.

Additionaly, I've added a function for calculating the remote-path for
files accessed with doas. This function is currently limited to *only*
doas, because I didn't want to mess with the other su and sudo
functions, but there's no reason it can't be shared, and a future patch
should implement that sharing if this patch is considered desirable.

-bjc


[-- Attachment #2: v1-0001-Add-the-doas-alias-to-eshell.patch --]
[-- Type: text/x-patch, Size: 3345 bytes --]

From d31226fd4867c4af8a77e2a90771c9c927f02f88 Mon Sep 17 00:00:00 2001
From: Brian Cully <bjc@kublai.com>
Date: Wed, 26 Oct 2022 21:10:21 -0400
Subject: [PATCH v1] Add the "doas" alias to eshell.

  * lisp/eshell/em-tramp.el (eshell/doas): new function.
---
 lisp/eshell/em-tramp.el | 47 +++++++++++++++++++++++++++++++++++++----
 1 file changed, 43 insertions(+), 4 deletions(-)

diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index aebbc36e71..7969a88a2b 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -40,9 +40,10 @@
  (defgroup eshell-tramp nil
    "This module defines commands that use TRAMP in a way that is
   not transparent to the user.  So far, this includes only the
-  built-in su and sudo commands, which are not compatible with
-  the full, external su and sudo commands, and require the user
-  to understand how to use the TRAMP sudo method."
+  built-in su, sudo and doas commands, which are not compatible
+  with the full, external su, sudo, and doas commands, and
+  require the user to understand how to use the TRAMP sudo
+  method."
    :tag "TRAMP Eshell features"
    :group 'eshell-module))
 
@@ -52,7 +53,7 @@ eshell-tramp-initialize
     (add-hook 'pcomplete-try-first-hook
 	      'eshell-complete-host-reference nil t))
   (setq-local eshell-complex-commands
-              (append '("su" "sudo")
+              (append '("su" "sudo" "doas")
                       eshell-complex-commands)))
 
 (autoload 'eshell-parse-command "esh-cmd")
@@ -127,6 +128,44 @@ eshell/sudo
 
 (put 'eshell/sudo 'eshell-no-numeric-conversions t)
 
+(defun eshell--doas-directory (directory &optional user)
+  "Return DIRECTORY wrapped with a doas method for USER."
+  (let ((user (or user "root"))
+        (dir (file-local-name (expand-file-name directory)))
+        (prefix (file-remote-p directory))
+        (host (or (file-remote-p directory 'host)
+                 tramp-default-host))
+        (method (file-remote-p directory 'method))
+        (ruser (file-remote-p directory 'user)))
+    (if (and prefix (or (not (string-equal method "doas"))
+                     (not (string-equal ruser user))))
+        (format "%s|doas:%s@%s:%s"
+                (substring prefix 0 -1) user host dir)
+      (format "/doas:%s@%s:%s" user host dir))))
+
+(defun eshell/doas (&rest args)
+  "Call Tramp’s doas method with ARGS.
+
+Uses the system doas through Tramp's doas method."
+  (eshell-eval-using-options
+   "doas" args
+   '((?h "help" nil nil "show this usage screen")
+     (?u "user" t user "execute a command as another USER")
+     (?s "shell" nil shell "start a shell instead of executing COMMAND")
+     :show-usage
+     :parse-leading-options-only
+     :usage "[(-u | --user) USER] -s | COMMAND
+Execute a COMMAND as the superuser or another USER.")
+   (let ((dir (eshell--doas-directory default-directory user)))
+     (if shell
+         (throw 'eshell-replace-command
+                (eshell-parse-command "cd" (list dir)))
+       (throw 'eshell-external
+              (let ((default-directory dir))
+                (eshell-named-command (car args) (cdr args))))))))
+
+(put 'eshell/doas 'eshell-no-numeric-conversions t)
+
 (provide 'em-tramp)
 
 ;; Local Variables:
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-10-30 16:42 bug#58899: [PATCH v1] Add the "doas" alias to eshell Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-10-30 21:51 ` Jim Porter
  2022-10-30 22:06   ` Jim Porter
                     ` (2 more replies)
  0 siblings, 3 replies; 11+ messages in thread
From: Jim Porter @ 2022-10-30 21:51 UTC (permalink / raw)
  To: Brian Cully, 58899

On 10/30/2022 9:42 AM, Brian Cully via Bug reports for GNU Emacs, the 
Swiss army knife of text editors wrote:
> 
> This patch adds a “doas” command alias to eshell for users who prefer
> doas, similar to the existing “su” and “sudo” command aliases.

Thanks. I think this would be a good addition to Eshell.

> I'm unsare whether to use “TRAMP” or “Tramp” spelling. The existing
> routines in the file use the former, but I've been informed the latter
> is correct. A future patch should make all spellings (at least within
> this module) consistent.

I'd say go with "Tramp" like you did in your patch. Since you're 
modifying code near most of the existing usages of "TRAMP", now would 
probably be a good time to fix that everywhere in the file too.

> Additionaly, I've added a function for calculating the remote-path for
> files accessed with doas. This function is currently limited to *only*
> doas, because I didn't want to mess with the other su and sudo
> functions, but there's no reason it can't be shared, and a future patch
> should implement that sharing if this patch is considered desirable.

Since the 'eshell/doas' and 'eshell/sudo' functions are so similar, I 
definitely think it would make sense to share as much code as possible 
here. In particular, you could also add support for "--shell" to 
'eshell/sudo'.

There are some existing tests in test/lisp/eshell/em-tramp-tests.el, so 
I think it should be fairly safe to adjust 'eshell/sudo'; the regression 
tests should catch any problems. (Well ok, *some* problems.) It would 
probably be good to add some simple tests for 'eshell/doas' too.





^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-10-30 21:51 ` Jim Porter
@ 2022-10-30 22:06   ` Jim Porter
  2022-10-31 12:36     ` Eli Zaretskii
  2022-10-31  8:16   ` Michael Albinus
  2022-10-31 16:01   ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2 siblings, 1 reply; 11+ messages in thread
From: Jim Porter @ 2022-10-30 22:06 UTC (permalink / raw)
  To: Brian Cully, 58899

On 10/30/2022 2:51 PM, Jim Porter wrote:
> On 10/30/2022 9:42 AM, Brian Cully via Bug reports for GNU Emacs, the 
> Swiss army knife of text editors wrote:
>>
>> This patch adds a “doas” command alias to eshell for users who prefer
>> doas, similar to the existing “su” and “sudo” command aliases.
> 
> Thanks. I think this would be a good addition to Eshell.

Oh also, I think it'd be good to add documentation about this to the 
Eshell manual (doc/misc/eshell.texi) and probably a mention in etc/NEWS too.





^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-10-30 21:51 ` Jim Porter
  2022-10-30 22:06   ` Jim Porter
@ 2022-10-31  8:16   ` Michael Albinus
  2022-10-31 16:01   ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2 siblings, 0 replies; 11+ messages in thread
From: Michael Albinus @ 2022-10-31  8:16 UTC (permalink / raw)
  To: Jim Porter; +Cc: 58899, Brian Cully

Jim Porter <jporterbugs@gmail.com> writes:

Hi,

>> I'm unsare whether to use “TRAMP” or “Tramp” spelling. The existing
>> routines in the file use the former, but I've been informed the latter
>> is correct. A future patch should make all spellings (at least within
>> this module) consistent.
>
> I'd say go with "Tramp" like you did in your patch. Since you're
> modifying code near most of the existing usages of "TRAMP", now would
> probably be a good time to fix that everywhere in the file too.

Yes. Sometimes it might even be worth to RTFM. From the Tramp manual
(info "(tramp) Frequently Asked Questions")

--8<---------------cut here---------------start------------->8---
   • What is the official name - “Tramp” or “TRAMP”?

     The official name is “Tramp”.  This is used in comments,
     docstrings, and everywhere speaking about TRAMP.

     However, for historical reasons this is formatted as “@sc{Tramp}”
     in the TRAMP manual.  *note (texinfo)Smallcaps::.  So it looks
     different there.
--8<---------------cut here---------------end--------------->8---

Best regards, Michael.





^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-10-30 22:06   ` Jim Porter
@ 2022-10-31 12:36     ` Eli Zaretskii
  0 siblings, 0 replies; 11+ messages in thread
From: Eli Zaretskii @ 2022-10-31 12:36 UTC (permalink / raw)
  To: Jim Porter; +Cc: 58899, bjc

> Date: Sun, 30 Oct 2022 15:06:12 -0700
> From: Jim Porter <jporterbugs@gmail.com>
> 
> On 10/30/2022 2:51 PM, Jim Porter wrote:
> > 
> > Thanks. I think this would be a good addition to Eshell.
> 
> Oh also, I think it'd be good to add documentation about this to the 
> Eshell manual (doc/misc/eshell.texi) and probably a mention in etc/NEWS too.

Yes, please (on both counts).





^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-10-30 21:51 ` Jim Porter
  2022-10-30 22:06   ` Jim Porter
  2022-10-31  8:16   ` Michael Albinus
@ 2022-10-31 16:01   ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2022-10-31 18:01     ` Eli Zaretskii
  2 siblings, 1 reply; 11+ messages in thread
From: Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-10-31 16:01 UTC (permalink / raw)
  To: Jim Porter, 58899

[-- Attachment #1: Type: text/plain, Size: 1293 bytes --]

Jim Porter <jporterbugs@gmail.com> writes:

> I'd say go with "Tramp" like you did in your patch. Since you're 
> modifying code near most of the existing usages of "TRAMP", now would 
> probably be a good time to fix that everywhere in the file too.

I've made this change in a separate patch so as not to muddy history too
much. If you'd prefer everything rolled up, I can do that, too.

> Since the 'eshell/doas' and 'eshell/sudo' functions are so similar, I 
> definitely think it would make sense to share as much code as possible 
> here. In particular, you could also add support for "--shell" to 
> 'eshell/sudo'.

Done.

> There are some existing tests in test/lisp/eshell/em-tramp-tests.el, so 
> I think it should be fairly safe to adjust 'eshell/sudo'; the regression 
> tests should catch any problems. (Well ok, *some* problems.) It would 
> probably be good to add some simple tests for 'eshell/doas' too.

I've added two more tests to cover the shell arguments to ‘eshell/sudo’,
plus equivalent tests for the doas functionality.

In addition, this patch adds a comment to NEWS and updates the Texinfo
docs. This is my first time messing with those files and I'm not very
familiar with Texinfo; if I've messed something up, let me know.

-bjc


[-- Attachment #2: v2-0001-Add-the-doas-alias-to-eshell.patch --]
[-- Type: text/x-patch, Size: 10857 bytes --]

From 16dbbd2f59b0ab31078b9ac499f18070eabc783a Mon Sep 17 00:00:00 2001
From: Brian Cully <bjc@kublai.com>
Date: Wed, 26 Oct 2022 21:10:21 -0400
Subject: [PATCH v2 1/2] Add the "doas" alias to eshell.

  * lisp/eshell/em-tramp.el (eshell/doas): new function.
  (eshell--method-wrap-directory): new function.
  (eshell/sudo): accept '-s'/'--shell' for interactive use.
  * test/lisp/eshell/em-tramp-tests.el
  (em-tramp-test/sudo-shell) (em-tramp-test/sudo-user-shell)
  (em-tramp-test/doas-basic) (em-tramp-test/doas-user)
  (em-tramp-test/doas-shell) (em-tramp-test/doas-user-shell): new
  tests.
  * etc/NEWS: mention new 'doas' eshell command.
  * doc/misc/eshell.texi: add 'doas' command documentation.
---
 doc/misc/eshell.texi               |  9 ++--
 etc/NEWS                           |  5 ++
 lisp/eshell/em-tramp.el            | 78 ++++++++++++++++++++----------
 test/lisp/eshell/em-tramp-tests.el | 66 +++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 29 deletions(-)

diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index ff368c9dc4..96873a3f9a 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -717,9 +717,12 @@ Built-ins
 @cmindex su
 @itemx sudo
 @cmindex sudo
-Uses TRAMP's @command{su} or @command{sudo} method @pxref{Inline methods, , , tramp}
-to run a command via @command{su} or @command{sudo}.  These commands
-are in the eshell-tramp module, which is disabled by default.
+@itemx doas
+@cmindex doas
+Uses TRAMP's @command{su}, @command{sudo}, or @command{doas} method
+@pxref{Inline methods, , , tramp} to run a command via @command{su},
+@command{sudo}, or @command{doas}.  These commands are in the
+eshell-tramp module, which is disabled by default.
 
 
 @item substitute
diff --git a/etc/NEWS b/etc/NEWS
index bf50c900ea..62093ada33 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -379,6 +379,11 @@ node in the Eshell manual for more details.
 *** Eshell pipelines now only pipe stdout by default.
 To pipe both stdout and stderr, use the '|&' operator instead of '|'.
 
+*** New eshell built-in command 'doas'.
+The privilege-escalation program 'doas' has been added to the existing
+'su' and 'sudo' commands from the 'eshell-tramp' module. The external
+command may still be accessed by using '*doas'.
+
 ---
 ** The 'delete-forward-char' command now deletes by grapheme clusters.
 This command is by default bound to the <Delete> function key
diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index aebbc36e71..fb5d5b86a2 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -40,9 +40,10 @@
  (defgroup eshell-tramp nil
    "This module defines commands that use TRAMP in a way that is
   not transparent to the user.  So far, this includes only the
-  built-in su and sudo commands, which are not compatible with
-  the full, external su and sudo commands, and require the user
-  to understand how to use the TRAMP sudo method."
+  built-in su, sudo and doas commands, which are not compatible
+  with the full, external su, sudo, and doas commands, and
+  require the user to understand how to use the TRAMP sudo
+  method."
    :tag "TRAMP Eshell features"
    :group 'eshell-module))
 
@@ -52,7 +53,7 @@ eshell-tramp-initialize
     (add-hook 'pcomplete-try-first-hook
 	      'eshell-complete-host-reference nil t))
   (setq-local eshell-complex-commands
-              (append '("su" "sudo")
+              (append '("su" "sudo" "doas")
                       eshell-complex-commands)))
 
 (autoload 'eshell-parse-command "esh-cmd")
@@ -91,6 +92,21 @@ eshell/su
 
 (put 'eshell/su 'eshell-no-numeric-conversions t)
 
+(defun eshell--method-wrap-directory (directory method &optional user)
+  "Return DIRECTORY as accessed by a Tramp METHOD for USER."
+  (let ((user (or user "root"))
+        (dir (file-local-name (expand-file-name directory)))
+        (prefix (file-remote-p directory))
+        (host (or (file-remote-p directory 'host)
+                 tramp-default-host))
+        (rmethod (file-remote-p directory 'method))
+        (ruser (file-remote-p directory 'user)))
+    (if (and prefix (or (not (string-equal rmethod method))
+                     (not (string-equal ruser user))))
+        (format "%s|%s:%s@%s:%s"
+                (substring prefix 0 -1) method user host dir)
+      (format "/%s:%s@%s:%s" method user host dir))))
+
 (defun eshell/sudo (&rest args)
   "Alias \"sudo\" to call Tramp.
 
@@ -99,34 +115,44 @@ eshell/sudo
    "sudo" args
    '((?h "help" nil nil "show this usage screen")
      (?u "user" t user "execute a command as another USER")
+     (?s "shell" nil shell "start a shell instead of executing COMMAND")
      :show-usage
      :parse-leading-options-only
-     :usage "[(-u | --user) USER] COMMAND
+     :usage "[(-u | --user) USER] (-s | --shell) | COMMANDq
 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)
-                           tramp-default-host))
-                 (dir (file-local-name (expand-file-name default-directory)))
-                 (prefix (file-remote-p default-directory))
-                 (default-directory
-                   (if (and prefix
-                            (or
-                             (not
-                              (string-equal
-                               "sudo"
-                               (file-remote-p default-directory 'method)))
-                             (not
-                              (string-equal
-                               user
-                               (file-remote-p default-directory 'user)))))
-                       (format "%s|sudo:%s@%s:%s"
-                               (substring prefix 0 -1) user host dir)
-                     (format "/sudo:%s@%s:%s" user host dir))))
-            (eshell-named-command (car args) (cdr args))))))
+   (let ((dir (eshell--method-wrap-directory default-directory "sudo" user)))
+     (if shell
+         (throw 'eshell-replace-command
+                (eshell-parse-command "cd" (list dir)))
+       (throw 'eshell-external
+              (let ((default-directory dir))
+                (eshell-named-command (car args) (cdr args))))))))
 
 (put 'eshell/sudo 'eshell-no-numeric-conversions t)
 
+(defun eshell/doas (&rest args)
+  "Call Tramp’s doas method with ARGS.
+
+Uses the system doas through Tramp's doas method."
+  (eshell-eval-using-options
+   "doas" args
+   '((?h "help" nil nil "show this usage screen")
+     (?u "user" t user "execute a command as another USER")
+     (?s "shell" nil shell "start a shell instead of executing COMMAND")
+     :show-usage
+     :parse-leading-options-only
+     :usage "[(-u | --user) USER] (-s | --shell) | COMMAND
+Execute a COMMAND as the superuser or another USER.")
+   (let ((dir (eshell--method-wrap-directory default-directory "doas" user)))
+     (if shell
+         (throw 'eshell-replace-command
+                (eshell-parse-command "cd" (list dir)))
+       (throw 'eshell-external
+              (let ((default-directory dir))
+                (eshell-named-command (car args) (cdr args))))))))
+
+(put 'eshell/doas 'eshell-no-numeric-conversions t)
+
 (provide 'em-tramp)
 
 ;; Local Variables:
diff --git a/test/lisp/eshell/em-tramp-tests.el b/test/lisp/eshell/em-tramp-tests.el
index 8969c1e229..9d28d6be82 100644
--- a/test/lisp/eshell/em-tramp-tests.el
+++ b/test/lisp/eshell/em-tramp-tests.el
@@ -85,4 +85,70 @@ em-tramp-test/sudo-user
              `(,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)
                ("echo" ("-u" "hi")))))))
 
+(ert-deftest em-tramp-test/sudo-shell ()
+  "Test Eshell `sudo' command with -s/--shell option."
+  (dolist (args '(("--shell")
+                  ("-s")))
+    (should (equal
+             (catch 'eshell-replace-command (apply #'eshell/sudo args))
+             `(eshell-trap-errors
+               (eshell-named-command
+                "cd"
+                (list ,(format "/sudo:root@%s:%s" tramp-default-host default-directory))))))))
+
+(ert-deftest em-tramp-test/sudo-user-shell ()
+  "Test Eshell `sudo' command with -s and -u options."
+  (should (equal
+           (catch 'eshell-replace-command (eshell/sudo "-u" "USER" "-s"))
+           `(eshell-trap-errors
+             (eshell-named-command
+              "cd"
+              (list ,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)))))))
+
+(ert-deftest em-tramp-test/doas-basic ()
+  "Test Eshell `doas' command with default user."
+  (cl-letf (((symbol-function 'eshell-named-command)
+             #'mock-eshell-named-command))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "echo" "hi"))
+             `(,(format "/doas:root@%s:%s" tramp-default-host default-directory)
+               ("echo" ("hi")))))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "echo" "-u" "hi"))
+             `(,(format "/doas:root@%s:%s" tramp-default-host default-directory)
+               ("echo" ("-u" "hi")))))))
+
+(ert-deftest em-tramp-test/doas-user ()
+  "Test Eshell `doas' command with specified user."
+  (cl-letf (((symbol-function 'eshell-named-command)
+             #'mock-eshell-named-command))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "-u" "USER" "echo" "hi"))
+             `(,(format "/doas:USER@%s:%s" tramp-default-host default-directory)
+               ("echo" ("hi")))))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "-u" "USER" "echo" "-u" "hi"))
+             `(,(format "/doas:USER@%s:%s" tramp-default-host default-directory)
+               ("echo" ("-u" "hi")))))))
+
+(ert-deftest em-tramp-test/doas-shell ()
+  "Test Eshell `doas' command with -s/--shell option."
+  (dolist (args '(("--shell")
+                  ("-s")))
+    (should (equal
+             (catch 'eshell-replace-command (apply #'eshell/doas args))
+             `(eshell-trap-errors
+               (eshell-named-command
+                "cd"
+                (list ,(format "/doas:root@%s:%s" tramp-default-host default-directory))))))))
+
+(ert-deftest em-tramp-test/doas-user-shell ()
+  "Test Eshell `doas' command with -s and -u options."
+  (should (equal
+           (catch 'eshell-replace-command (eshell/doas "-u" "USER" "-s"))
+           `(eshell-trap-errors
+             (eshell-named-command
+              "cd"
+              (list ,(format "/doas:USER@%s:%s" tramp-default-host default-directory)))))))
+
 ;;; em-tramp-tests.el ends here
-- 
2.38.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: v2-0002-lisp-eshell-em-tramp.el-Rename-TRAMP-to-Tramp.patch --]
[-- Type: text/x-patch, Size: 2500 bytes --]

From 531880fd892ab4a220fadcfba9b62779fb275ffc Mon Sep 17 00:00:00 2001
From: Brian Cully <bjc@kublai.com>
Date: Mon, 31 Oct 2022 11:55:45 -0400
Subject: [PATCH v2 2/2] lisp/eshell/em-tramp.el: Rename 'TRAMP' to 'Tramp'.

---
 lisp/eshell/em-tramp.el | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index fb5d5b86a2..336fe49932 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -1,4 +1,4 @@
-;;; em-tramp.el --- Eshell features that require TRAMP  -*- lexical-binding:t -*-
+;;; em-tramp.el --- Eshell features that require Tramp  -*- lexical-binding:t -*-
 
 ;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
 
@@ -21,7 +21,7 @@
 
 ;;; Commentary:
 
-;; Eshell features that require TRAMP.
+;; Eshell features that require Tramp.
 
 ;;; Code:
 
@@ -38,17 +38,17 @@
 ;;;###autoload
 (progn
  (defgroup eshell-tramp nil
-   "This module defines commands that use TRAMP in a way that is
+   "This module defines commands that use Tramp in a way that is
   not transparent to the user.  So far, this includes only the
   built-in su, sudo and doas commands, which are not compatible
   with the full, external su, sudo, and doas commands, and
-  require the user to understand how to use the TRAMP sudo
+  require the user to understand how to use the Tramp sudo
   method."
-   :tag "TRAMP Eshell features"
+   :tag "Tramp Eshell features"
    :group 'eshell-module))
 
 (defun eshell-tramp-initialize ()   ;Called from `eshell-mode' via intern-soft!
-  "Initialize the TRAMP-using commands code."
+  "Initialize the Tramp-using commands code."
   (when (eshell-using-module 'eshell-cmpl)
     (add-hook 'pcomplete-try-first-hook
 	      'eshell-complete-host-reference nil t))
@@ -59,9 +59,9 @@ eshell-tramp-initialize
 (autoload 'eshell-parse-command "esh-cmd")
 
 (defun eshell/su (&rest args)
-  "Alias \"su\" to call TRAMP.
+  "Alias \"su\" to call Tramp.
 
-Uses the system su through TRAMP's su method."
+Uses the system su through Tramp's su method."
   (eshell-eval-using-options
    "su" args
    '((?h "help" nil nil "show this usage screen")
@@ -110,7 +110,7 @@ eshell--method-wrap-directory
 (defun eshell/sudo (&rest args)
   "Alias \"sudo\" to call Tramp.
 
-Uses the system sudo through TRAMP's sudo method."
+Uses the system sudo through Tramp's sudo method."
   (eshell-eval-using-options
    "sudo" args
    '((?h "help" nil nil "show this usage screen")
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-10-31 16:01   ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-10-31 18:01     ` Eli Zaretskii
  2022-10-31 18:29       ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 11+ messages in thread
From: Eli Zaretskii @ 2022-10-31 18:01 UTC (permalink / raw)
  To: Brian Cully; +Cc: jporterbugs, 58899

> Date: Mon, 31 Oct 2022 12:01:47 -0400
> From:  Brian Cully via "Bug reports for GNU Emacs,
>  the Swiss army knife of text editors" <bug-gnu-emacs@gnu.org>
> 
> +*** New eshell built-in command 'doas'.
> +The privilege-escalation program 'doas' has been added to the existing
> +'su' and 'sudo' commands from the 'eshell-tramp' module. The external
> +command may still be accessed by using '*doas'.        ^^

Two spaces between sentences.

> +(defun eshell/doas (&rest args)
> +  "Call Tramp’s doas method with ARGS.
           ^^^^^^^
Please use only ASCII characters in the doc strings.

(I'm guessing you have some electric mode enabled, so please make sure
to have it disabled when you work on our documentation.)

Thanks.





^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-10-31 18:01     ` Eli Zaretskii
@ 2022-10-31 18:29       ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2022-11-03 17:09         ` Jim Porter
  0 siblings, 1 reply; 11+ messages in thread
From: Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-10-31 18:29 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: jporterbugs, 58899

[-- Attachment #1: Type: text/plain, Size: 522 bytes --]

Eli Zaretskii <eliz@gnu.org> writes:

> Two spaces between sentences.

Fixed.

>> +(defun eshell/doas (&rest args)
>> +  "Call Tramp’s doas method with ARGS.
>            ^^^^^^^
> Please use only ASCII characters in the doc strings.
>
> (I'm guessing you have some electric mode enabled, so please make sure
> to have it disabled when you work on our documentation.)

Fixed, and yes I do.

I also spotted an errant ‘q’ I managed to typo into the sudo usage
string, which is now removed.

-bjc


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v3-0001-Add-the-doas-alias-to-eshell.patch --]
[-- Type: text/x-patch, Size: 10603 bytes --]

From a4c060c7a540065e1fce321b7a4172c0a3da84c1 Mon Sep 17 00:00:00 2001
From: Brian Cully <bjc@kublai.com>
Date: Wed, 26 Oct 2022 21:10:21 -0400
Subject: [PATCH v3 1/2] Add the "doas" alias to eshell.

  * lisp/eshell/em-tramp.el (eshell/doas): new function.
  (eshell--method-wrap-directory): new function.
  (eshell/sudo): accept '-s'/'--shell' for interactive use.
  * test/lisp/eshell/em-tramp-tests.el
  (em-tramp-test/sudo-shell) (em-tramp-test/sudo-user-shell)
  (em-tramp-test/doas-basic) (em-tramp-test/doas-user)
  (em-tramp-test/doas-shell) (em-tramp-test/doas-user-shell): new
  tests.
  * etc/NEWS: mention new 'doas' eshell command.
  * doc/misc/eshell.texi: add 'doas' command documentation.
---
 doc/misc/eshell.texi               |  9 ++--
 etc/NEWS                           |  5 ++
 lisp/eshell/em-tramp.el            | 78 ++++++++++++++++++++----------
 test/lisp/eshell/em-tramp-tests.el | 66 +++++++++++++++++++++++++
 4 files changed, 129 insertions(+), 29 deletions(-)

diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index ff368c9dc4..96873a3f9a 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -717,9 +717,12 @@ Built-ins
 @cmindex su
 @itemx sudo
 @cmindex sudo
-Uses TRAMP's @command{su} or @command{sudo} method @pxref{Inline methods, , , tramp}
-to run a command via @command{su} or @command{sudo}.  These commands
-are in the eshell-tramp module, which is disabled by default.
+@itemx doas
+@cmindex doas
+Uses TRAMP's @command{su}, @command{sudo}, or @command{doas} method
+@pxref{Inline methods, , , tramp} to run a command via @command{su},
+@command{sudo}, or @command{doas}.  These commands are in the
+eshell-tramp module, which is disabled by default.
 
 
 @item substitute
diff --git a/etc/NEWS b/etc/NEWS
index bf50c900ea..175e190d31 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -379,6 +379,11 @@ node in the Eshell manual for more details.
 *** Eshell pipelines now only pipe stdout by default.
 To pipe both stdout and stderr, use the '|&' operator instead of '|'.
 
+*** New eshell built-in command 'doas'.
+The privilege-escalation program 'doas' has been added to the existing
+'su' and 'sudo' commands from the 'eshell-tramp' module.  The external
+command may still be accessed by using '*doas'.
+
 ---
 ** The 'delete-forward-char' command now deletes by grapheme clusters.
 This command is by default bound to the <Delete> function key
diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index aebbc36e71..3daac1db3b 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -40,9 +40,10 @@
  (defgroup eshell-tramp nil
    "This module defines commands that use TRAMP in a way that is
   not transparent to the user.  So far, this includes only the
-  built-in su and sudo commands, which are not compatible with
-  the full, external su and sudo commands, and require the user
-  to understand how to use the TRAMP sudo method."
+  built-in su, sudo and doas commands, which are not compatible
+  with the full, external su, sudo, and doas commands, and
+  require the user to understand how to use the TRAMP sudo
+  method."
    :tag "TRAMP Eshell features"
    :group 'eshell-module))
 
@@ -52,7 +53,7 @@ eshell-tramp-initialize
     (add-hook 'pcomplete-try-first-hook
 	      'eshell-complete-host-reference nil t))
   (setq-local eshell-complex-commands
-              (append '("su" "sudo")
+              (append '("su" "sudo" "doas")
                       eshell-complex-commands)))
 
 (autoload 'eshell-parse-command "esh-cmd")
@@ -91,6 +92,21 @@ eshell/su
 
 (put 'eshell/su 'eshell-no-numeric-conversions t)
 
+(defun eshell--method-wrap-directory (directory method &optional user)
+  "Return DIRECTORY as accessed by a Tramp METHOD for USER."
+  (let ((user (or user "root"))
+        (dir (file-local-name (expand-file-name directory)))
+        (prefix (file-remote-p directory))
+        (host (or (file-remote-p directory 'host)
+                 tramp-default-host))
+        (rmethod (file-remote-p directory 'method))
+        (ruser (file-remote-p directory 'user)))
+    (if (and prefix (or (not (string-equal rmethod method))
+                     (not (string-equal ruser user))))
+        (format "%s|%s:%s@%s:%s"
+                (substring prefix 0 -1) method user host dir)
+      (format "/%s:%s@%s:%s" method user host dir))))
+
 (defun eshell/sudo (&rest args)
   "Alias \"sudo\" to call Tramp.
 
@@ -99,34 +115,44 @@ eshell/sudo
    "sudo" args
    '((?h "help" nil nil "show this usage screen")
      (?u "user" t user "execute a command as another USER")
+     (?s "shell" nil shell "start a shell instead of executing COMMAND")
      :show-usage
      :parse-leading-options-only
-     :usage "[(-u | --user) USER] COMMAND
+     :usage "[(-u | --user) USER] (-s | --shell) | 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)
-                           tramp-default-host))
-                 (dir (file-local-name (expand-file-name default-directory)))
-                 (prefix (file-remote-p default-directory))
-                 (default-directory
-                   (if (and prefix
-                            (or
-                             (not
-                              (string-equal
-                               "sudo"
-                               (file-remote-p default-directory 'method)))
-                             (not
-                              (string-equal
-                               user
-                               (file-remote-p default-directory 'user)))))
-                       (format "%s|sudo:%s@%s:%s"
-                               (substring prefix 0 -1) user host dir)
-                     (format "/sudo:%s@%s:%s" user host dir))))
-            (eshell-named-command (car args) (cdr args))))))
+   (let ((dir (eshell--method-wrap-directory default-directory "sudo" user)))
+     (if shell
+         (throw 'eshell-replace-command
+                (eshell-parse-command "cd" (list dir)))
+       (throw 'eshell-external
+              (let ((default-directory dir))
+                (eshell-named-command (car args) (cdr args))))))))
 
 (put 'eshell/sudo 'eshell-no-numeric-conversions t)
 
+(defun eshell/doas (&rest args)
+  "Call Tramp's doas method with ARGS.
+
+Uses the system doas through Tramp's doas method."
+  (eshell-eval-using-options
+   "doas" args
+   '((?h "help" nil nil "show this usage screen")
+     (?u "user" t user "execute a command as another USER")
+     (?s "shell" nil shell "start a shell instead of executing COMMAND")
+     :show-usage
+     :parse-leading-options-only
+     :usage "[(-u | --user) USER] (-s | --shell) | COMMAND
+Execute a COMMAND as the superuser or another USER.")
+   (let ((dir (eshell--method-wrap-directory default-directory "doas" user)))
+     (if shell
+         (throw 'eshell-replace-command
+                (eshell-parse-command "cd" (list dir)))
+       (throw 'eshell-external
+              (let ((default-directory dir))
+                (eshell-named-command (car args) (cdr args))))))))
+
+(put 'eshell/doas 'eshell-no-numeric-conversions t)
+
 (provide 'em-tramp)
 
 ;; Local Variables:
diff --git a/test/lisp/eshell/em-tramp-tests.el b/test/lisp/eshell/em-tramp-tests.el
index 8969c1e229..9d28d6be82 100644
--- a/test/lisp/eshell/em-tramp-tests.el
+++ b/test/lisp/eshell/em-tramp-tests.el
@@ -85,4 +85,70 @@ em-tramp-test/sudo-user
              `(,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)
                ("echo" ("-u" "hi")))))))
 
+(ert-deftest em-tramp-test/sudo-shell ()
+  "Test Eshell `sudo' command with -s/--shell option."
+  (dolist (args '(("--shell")
+                  ("-s")))
+    (should (equal
+             (catch 'eshell-replace-command (apply #'eshell/sudo args))
+             `(eshell-trap-errors
+               (eshell-named-command
+                "cd"
+                (list ,(format "/sudo:root@%s:%s" tramp-default-host default-directory))))))))
+
+(ert-deftest em-tramp-test/sudo-user-shell ()
+  "Test Eshell `sudo' command with -s and -u options."
+  (should (equal
+           (catch 'eshell-replace-command (eshell/sudo "-u" "USER" "-s"))
+           `(eshell-trap-errors
+             (eshell-named-command
+              "cd"
+              (list ,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)))))))
+
+(ert-deftest em-tramp-test/doas-basic ()
+  "Test Eshell `doas' command with default user."
+  (cl-letf (((symbol-function 'eshell-named-command)
+             #'mock-eshell-named-command))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "echo" "hi"))
+             `(,(format "/doas:root@%s:%s" tramp-default-host default-directory)
+               ("echo" ("hi")))))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "echo" "-u" "hi"))
+             `(,(format "/doas:root@%s:%s" tramp-default-host default-directory)
+               ("echo" ("-u" "hi")))))))
+
+(ert-deftest em-tramp-test/doas-user ()
+  "Test Eshell `doas' command with specified user."
+  (cl-letf (((symbol-function 'eshell-named-command)
+             #'mock-eshell-named-command))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "-u" "USER" "echo" "hi"))
+             `(,(format "/doas:USER@%s:%s" tramp-default-host default-directory)
+               ("echo" ("hi")))))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "-u" "USER" "echo" "-u" "hi"))
+             `(,(format "/doas:USER@%s:%s" tramp-default-host default-directory)
+               ("echo" ("-u" "hi")))))))
+
+(ert-deftest em-tramp-test/doas-shell ()
+  "Test Eshell `doas' command with -s/--shell option."
+  (dolist (args '(("--shell")
+                  ("-s")))
+    (should (equal
+             (catch 'eshell-replace-command (apply #'eshell/doas args))
+             `(eshell-trap-errors
+               (eshell-named-command
+                "cd"
+                (list ,(format "/doas:root@%s:%s" tramp-default-host default-directory))))))))
+
+(ert-deftest em-tramp-test/doas-user-shell ()
+  "Test Eshell `doas' command with -s and -u options."
+  (should (equal
+           (catch 'eshell-replace-command (eshell/doas "-u" "USER" "-s"))
+           `(eshell-trap-errors
+             (eshell-named-command
+              "cd"
+              (list ,(format "/doas:USER@%s:%s" tramp-default-host default-directory)))))))
+
 ;;; em-tramp-tests.el ends here
-- 
2.38.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: v3-0002-lisp-eshell-em-tramp.el-Rename-TRAMP-to-Tramp.patch --]
[-- Type: text/x-patch, Size: 2500 bytes --]

From 4703a99e7b56d64686c3bd374657e2dbf7853e5d Mon Sep 17 00:00:00 2001
From: Brian Cully <bjc@kublai.com>
Date: Mon, 31 Oct 2022 11:55:45 -0400
Subject: [PATCH v3 2/2] lisp/eshell/em-tramp.el: Rename 'TRAMP' to 'Tramp'.

---
 lisp/eshell/em-tramp.el | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index 3daac1db3b..499deaa7fc 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -1,4 +1,4 @@
-;;; em-tramp.el --- Eshell features that require TRAMP  -*- lexical-binding:t -*-
+;;; em-tramp.el --- Eshell features that require Tramp  -*- lexical-binding:t -*-
 
 ;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
 
@@ -21,7 +21,7 @@
 
 ;;; Commentary:
 
-;; Eshell features that require TRAMP.
+;; Eshell features that require Tramp.
 
 ;;; Code:
 
@@ -38,17 +38,17 @@
 ;;;###autoload
 (progn
  (defgroup eshell-tramp nil
-   "This module defines commands that use TRAMP in a way that is
+   "This module defines commands that use Tramp in a way that is
   not transparent to the user.  So far, this includes only the
   built-in su, sudo and doas commands, which are not compatible
   with the full, external su, sudo, and doas commands, and
-  require the user to understand how to use the TRAMP sudo
+  require the user to understand how to use the Tramp sudo
   method."
-   :tag "TRAMP Eshell features"
+   :tag "Tramp Eshell features"
    :group 'eshell-module))
 
 (defun eshell-tramp-initialize ()   ;Called from `eshell-mode' via intern-soft!
-  "Initialize the TRAMP-using commands code."
+  "Initialize the Tramp-using commands code."
   (when (eshell-using-module 'eshell-cmpl)
     (add-hook 'pcomplete-try-first-hook
 	      'eshell-complete-host-reference nil t))
@@ -59,9 +59,9 @@ eshell-tramp-initialize
 (autoload 'eshell-parse-command "esh-cmd")
 
 (defun eshell/su (&rest args)
-  "Alias \"su\" to call TRAMP.
+  "Alias \"su\" to call Tramp.
 
-Uses the system su through TRAMP's su method."
+Uses the system su through Tramp's su method."
   (eshell-eval-using-options
    "su" args
    '((?h "help" nil nil "show this usage screen")
@@ -110,7 +110,7 @@ eshell--method-wrap-directory
 (defun eshell/sudo (&rest args)
   "Alias \"sudo\" to call Tramp.
 
-Uses the system sudo through TRAMP's sudo method."
+Uses the system sudo through Tramp's sudo method."
   (eshell-eval-using-options
    "sudo" args
    '((?h "help" nil nil "show this usage screen")
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-10-31 18:29       ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-11-03 17:09         ` Jim Porter
  2022-11-03 20:24           ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
  0 siblings, 1 reply; 11+ messages in thread
From: Jim Porter @ 2022-11-03 17:09 UTC (permalink / raw)
  To: Brian Cully, Eli Zaretskii; +Cc: 58899

On 10/31/2022 11:29 AM, Brian Cully via Bug reports for GNU Emacs, the 
Swiss army knife of text editors wrote:
> Fixed.

I took a look at these patches and they all look good to me[1], aside 
from one minor nitpick: could you wrap the new tests at 80 columns? It 
makes the code easier to read for people like me who have several 
80-column windows side-by-side. :)

[1] I haven't applied them locally to test, though.





^ permalink raw reply	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-11-03 17:09         ` Jim Porter
@ 2022-11-03 20:24           ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
  2022-11-05 19:10             ` Jim Porter
  0 siblings, 1 reply; 11+ messages in thread
From: Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors @ 2022-11-03 20:24 UTC (permalink / raw)
  To: Jim Porter, Eli Zaretskii; +Cc: 58899

[-- Attachment #1: Type: text/plain, Size: 386 bytes --]

Jim Porter <jporterbugs@gmail.com> writes:

> On 10/31/2022 11:29 AM, Brian Cully via Bug reports for GNU Emacs, the 
> I took a look at these patches and they all look good to me[1], aside 
> from one minor nitpick: could you wrap the new tests at 80 columns? It 
> makes the code easier to read for people like me who have several 
> 80-column windows side-by-side. :)

Fixed.

-bjc


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: v4-0001-Add-the-doas-alias-to-eshell.patch --]
[-- Type: text/x-patch, Size: 10846 bytes --]

From a522af9da41c423c094af39d9c469d520d50e4a0 Mon Sep 17 00:00:00 2001
From: Brian Cully <bjc@kublai.com>
Date: Wed, 26 Oct 2022 21:10:21 -0400
Subject: [PATCH v4 1/2] Add the "doas" alias to eshell.

  * lisp/eshell/em-tramp.el (eshell/doas): new function.
  (eshell--method-wrap-directory): new function.
  (eshell/sudo): accept '-s'/'--shell' for interactive use.
  * test/lisp/eshell/em-tramp-tests.el
  (em-tramp-test/sudo-shell) (em-tramp-test/sudo-user-shell)
  (em-tramp-test/doas-basic) (em-tramp-test/doas-user)
  (em-tramp-test/doas-shell) (em-tramp-test/doas-user-shell): new
  tests.
  * etc/NEWS: mention new 'doas' eshell command.
  * doc/misc/eshell.texi: add 'doas' command documentation.
---
 doc/misc/eshell.texi               |  9 ++--
 etc/NEWS                           |  5 ++
 lisp/eshell/em-tramp.el            | 78 ++++++++++++++++++++----------
 test/lisp/eshell/em-tramp-tests.el | 75 ++++++++++++++++++++++++++++
 4 files changed, 138 insertions(+), 29 deletions(-)

diff --git a/doc/misc/eshell.texi b/doc/misc/eshell.texi
index ff368c9dc4..96873a3f9a 100644
--- a/doc/misc/eshell.texi
+++ b/doc/misc/eshell.texi
@@ -717,9 +717,12 @@ Built-ins
 @cmindex su
 @itemx sudo
 @cmindex sudo
-Uses TRAMP's @command{su} or @command{sudo} method @pxref{Inline methods, , , tramp}
-to run a command via @command{su} or @command{sudo}.  These commands
-are in the eshell-tramp module, which is disabled by default.
+@itemx doas
+@cmindex doas
+Uses TRAMP's @command{su}, @command{sudo}, or @command{doas} method
+@pxref{Inline methods, , , tramp} to run a command via @command{su},
+@command{sudo}, or @command{doas}.  These commands are in the
+eshell-tramp module, which is disabled by default.
 
 
 @item substitute
diff --git a/etc/NEWS b/etc/NEWS
index bf50c900ea..175e190d31 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -379,6 +379,11 @@ node in the Eshell manual for more details.
 *** Eshell pipelines now only pipe stdout by default.
 To pipe both stdout and stderr, use the '|&' operator instead of '|'.
 
+*** New eshell built-in command 'doas'.
+The privilege-escalation program 'doas' has been added to the existing
+'su' and 'sudo' commands from the 'eshell-tramp' module.  The external
+command may still be accessed by using '*doas'.
+
 ---
 ** The 'delete-forward-char' command now deletes by grapheme clusters.
 This command is by default bound to the <Delete> function key
diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index aebbc36e71..3daac1db3b 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -40,9 +40,10 @@
  (defgroup eshell-tramp nil
    "This module defines commands that use TRAMP in a way that is
   not transparent to the user.  So far, this includes only the
-  built-in su and sudo commands, which are not compatible with
-  the full, external su and sudo commands, and require the user
-  to understand how to use the TRAMP sudo method."
+  built-in su, sudo and doas commands, which are not compatible
+  with the full, external su, sudo, and doas commands, and
+  require the user to understand how to use the TRAMP sudo
+  method."
    :tag "TRAMP Eshell features"
    :group 'eshell-module))
 
@@ -52,7 +53,7 @@ eshell-tramp-initialize
     (add-hook 'pcomplete-try-first-hook
 	      'eshell-complete-host-reference nil t))
   (setq-local eshell-complex-commands
-              (append '("su" "sudo")
+              (append '("su" "sudo" "doas")
                       eshell-complex-commands)))
 
 (autoload 'eshell-parse-command "esh-cmd")
@@ -91,6 +92,21 @@ eshell/su
 
 (put 'eshell/su 'eshell-no-numeric-conversions t)
 
+(defun eshell--method-wrap-directory (directory method &optional user)
+  "Return DIRECTORY as accessed by a Tramp METHOD for USER."
+  (let ((user (or user "root"))
+        (dir (file-local-name (expand-file-name directory)))
+        (prefix (file-remote-p directory))
+        (host (or (file-remote-p directory 'host)
+                 tramp-default-host))
+        (rmethod (file-remote-p directory 'method))
+        (ruser (file-remote-p directory 'user)))
+    (if (and prefix (or (not (string-equal rmethod method))
+                     (not (string-equal ruser user))))
+        (format "%s|%s:%s@%s:%s"
+                (substring prefix 0 -1) method user host dir)
+      (format "/%s:%s@%s:%s" method user host dir))))
+
 (defun eshell/sudo (&rest args)
   "Alias \"sudo\" to call Tramp.
 
@@ -99,34 +115,44 @@ eshell/sudo
    "sudo" args
    '((?h "help" nil nil "show this usage screen")
      (?u "user" t user "execute a command as another USER")
+     (?s "shell" nil shell "start a shell instead of executing COMMAND")
      :show-usage
      :parse-leading-options-only
-     :usage "[(-u | --user) USER] COMMAND
+     :usage "[(-u | --user) USER] (-s | --shell) | 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)
-                           tramp-default-host))
-                 (dir (file-local-name (expand-file-name default-directory)))
-                 (prefix (file-remote-p default-directory))
-                 (default-directory
-                   (if (and prefix
-                            (or
-                             (not
-                              (string-equal
-                               "sudo"
-                               (file-remote-p default-directory 'method)))
-                             (not
-                              (string-equal
-                               user
-                               (file-remote-p default-directory 'user)))))
-                       (format "%s|sudo:%s@%s:%s"
-                               (substring prefix 0 -1) user host dir)
-                     (format "/sudo:%s@%s:%s" user host dir))))
-            (eshell-named-command (car args) (cdr args))))))
+   (let ((dir (eshell--method-wrap-directory default-directory "sudo" user)))
+     (if shell
+         (throw 'eshell-replace-command
+                (eshell-parse-command "cd" (list dir)))
+       (throw 'eshell-external
+              (let ((default-directory dir))
+                (eshell-named-command (car args) (cdr args))))))))
 
 (put 'eshell/sudo 'eshell-no-numeric-conversions t)
 
+(defun eshell/doas (&rest args)
+  "Call Tramp's doas method with ARGS.
+
+Uses the system doas through Tramp's doas method."
+  (eshell-eval-using-options
+   "doas" args
+   '((?h "help" nil nil "show this usage screen")
+     (?u "user" t user "execute a command as another USER")
+     (?s "shell" nil shell "start a shell instead of executing COMMAND")
+     :show-usage
+     :parse-leading-options-only
+     :usage "[(-u | --user) USER] (-s | --shell) | COMMAND
+Execute a COMMAND as the superuser or another USER.")
+   (let ((dir (eshell--method-wrap-directory default-directory "doas" user)))
+     (if shell
+         (throw 'eshell-replace-command
+                (eshell-parse-command "cd" (list dir)))
+       (throw 'eshell-external
+              (let ((default-directory dir))
+                (eshell-named-command (car args) (cdr args))))))))
+
+(put 'eshell/doas 'eshell-no-numeric-conversions t)
+
 (provide 'em-tramp)
 
 ;; Local Variables:
diff --git a/test/lisp/eshell/em-tramp-tests.el b/test/lisp/eshell/em-tramp-tests.el
index 8969c1e229..6cc35ecdb1 100644
--- a/test/lisp/eshell/em-tramp-tests.el
+++ b/test/lisp/eshell/em-tramp-tests.el
@@ -85,4 +85,79 @@ em-tramp-test/sudo-user
              `(,(format "/sudo:USER@%s:%s" tramp-default-host default-directory)
                ("echo" ("-u" "hi")))))))
 
+(ert-deftest em-tramp-test/sudo-shell ()
+  "Test Eshell `sudo' command with -s/--shell option."
+  (dolist (args '(("--shell")
+                  ("-s")))
+    (should (equal
+             (catch 'eshell-replace-command (apply #'eshell/sudo args))
+             `(eshell-trap-errors
+               (eshell-named-command
+                "cd"
+                (list ,(format "/sudo:root@%s:%s"
+                               tramp-default-host default-directory))))))))
+
+(ert-deftest em-tramp-test/sudo-user-shell ()
+  "Test Eshell `sudo' command with -s and -u options."
+  (should (equal
+           (catch 'eshell-replace-command (eshell/sudo "-u" "USER" "-s"))
+           `(eshell-trap-errors
+             (eshell-named-command
+              "cd"
+              (list ,(format "/sudo:USER@%s:%s"
+                             tramp-default-host default-directory)))))))
+
+(ert-deftest em-tramp-test/doas-basic ()
+  "Test Eshell `doas' command with default user."
+  (cl-letf (((symbol-function 'eshell-named-command)
+             #'mock-eshell-named-command))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "echo" "hi"))
+             `(,(format "/doas:root@%s:%s"
+                        tramp-default-host default-directory)
+               ("echo" ("hi")))))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "echo" "-u" "hi"))
+             `(,(format "/doas:root@%s:%s"
+                        tramp-default-host default-directory)
+               ("echo" ("-u" "hi")))))))
+
+(ert-deftest em-tramp-test/doas-user ()
+  "Test Eshell `doas' command with specified user."
+  (cl-letf (((symbol-function 'eshell-named-command)
+             #'mock-eshell-named-command))
+    (should (equal
+             (catch 'eshell-external (eshell/doas "-u" "USER" "echo" "hi"))
+             `(,(format "/doas:USER@%s:%s"
+                        tramp-default-host default-directory)
+               ("echo" ("hi")))))
+    (should (equal
+             (catch 'eshell-external
+               (eshell/doas "-u" "USER" "echo" "-u" "hi"))
+             `(,(format "/doas:USER@%s:%s"
+                        tramp-default-host default-directory)
+               ("echo" ("-u" "hi")))))))
+
+(ert-deftest em-tramp-test/doas-shell ()
+  "Test Eshell `doas' command with -s/--shell option."
+  (dolist (args '(("--shell")
+                  ("-s")))
+    (should (equal
+             (catch 'eshell-replace-command (apply #'eshell/doas args))
+             `(eshell-trap-errors
+               (eshell-named-command
+                "cd"
+                (list ,(format "/doas:root@%s:%s"
+                               tramp-default-host default-directory))))))))
+
+(ert-deftest em-tramp-test/doas-user-shell ()
+  "Test Eshell `doas' command with -s and -u options."
+  (should (equal
+           (catch 'eshell-replace-command (eshell/doas "-u" "USER" "-s"))
+           `(eshell-trap-errors
+             (eshell-named-command
+              "cd"
+              (list ,(format "/doas:USER@%s:%s"
+                             tramp-default-host default-directory)))))))
+
 ;;; em-tramp-tests.el ends here
-- 
2.38.0


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: v4-0002-lisp-eshell-em-tramp.el-Rename-TRAMP-to-Tramp.patch --]
[-- Type: text/x-patch, Size: 2500 bytes --]

From 0f076d19d309fc53001518784a85635d71a2e94e Mon Sep 17 00:00:00 2001
From: Brian Cully <bjc@kublai.com>
Date: Mon, 31 Oct 2022 11:55:45 -0400
Subject: [PATCH v4 2/2] lisp/eshell/em-tramp.el: Rename 'TRAMP' to 'Tramp'.

---
 lisp/eshell/em-tramp.el | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/lisp/eshell/em-tramp.el b/lisp/eshell/em-tramp.el
index 3daac1db3b..499deaa7fc 100644
--- a/lisp/eshell/em-tramp.el
+++ b/lisp/eshell/em-tramp.el
@@ -1,4 +1,4 @@
-;;; em-tramp.el --- Eshell features that require TRAMP  -*- lexical-binding:t -*-
+;;; em-tramp.el --- Eshell features that require Tramp  -*- lexical-binding:t -*-
 
 ;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
 
@@ -21,7 +21,7 @@
 
 ;;; Commentary:
 
-;; Eshell features that require TRAMP.
+;; Eshell features that require Tramp.
 
 ;;; Code:
 
@@ -38,17 +38,17 @@
 ;;;###autoload
 (progn
  (defgroup eshell-tramp nil
-   "This module defines commands that use TRAMP in a way that is
+   "This module defines commands that use Tramp in a way that is
   not transparent to the user.  So far, this includes only the
   built-in su, sudo and doas commands, which are not compatible
   with the full, external su, sudo, and doas commands, and
-  require the user to understand how to use the TRAMP sudo
+  require the user to understand how to use the Tramp sudo
   method."
-   :tag "TRAMP Eshell features"
+   :tag "Tramp Eshell features"
    :group 'eshell-module))
 
 (defun eshell-tramp-initialize ()   ;Called from `eshell-mode' via intern-soft!
-  "Initialize the TRAMP-using commands code."
+  "Initialize the Tramp-using commands code."
   (when (eshell-using-module 'eshell-cmpl)
     (add-hook 'pcomplete-try-first-hook
 	      'eshell-complete-host-reference nil t))
@@ -59,9 +59,9 @@ eshell-tramp-initialize
 (autoload 'eshell-parse-command "esh-cmd")
 
 (defun eshell/su (&rest args)
-  "Alias \"su\" to call TRAMP.
+  "Alias \"su\" to call Tramp.
 
-Uses the system su through TRAMP's su method."
+Uses the system su through Tramp's su method."
   (eshell-eval-using-options
    "su" args
    '((?h "help" nil nil "show this usage screen")
@@ -110,7 +110,7 @@ eshell--method-wrap-directory
 (defun eshell/sudo (&rest args)
   "Alias \"sudo\" to call Tramp.
 
-Uses the system sudo through TRAMP's sudo method."
+Uses the system sudo through Tramp's sudo method."
   (eshell-eval-using-options
    "sudo" args
    '((?h "help" nil nil "show this usage screen")
-- 
2.38.0


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* bug#58899: [PATCH v1] Add the "doas" alias to eshell.
  2022-11-03 20:24           ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
@ 2022-11-05 19:10             ` Jim Porter
  0 siblings, 0 replies; 11+ messages in thread
From: Jim Porter @ 2022-11-05 19:10 UTC (permalink / raw)
  To: Brian Cully, Eli Zaretskii; +Cc: 58899-done

On 11/3/2022 1:24 PM, Brian Cully via Bug reports for GNU Emacs, the 
Swiss army knife of text editors wrote:
> Fixed.

Thanks. Everything looks good to me now, and since there have been no 
further comments from anyone else in the last few days, I've merged this 
as 4e108213341c99193d73133bb9d2cfbf31e6d8c9.






^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2022-11-05 19:10 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-30 16:42 bug#58899: [PATCH v1] Add the "doas" alias to eshell Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-30 21:51 ` Jim Porter
2022-10-30 22:06   ` Jim Porter
2022-10-31 12:36     ` Eli Zaretskii
2022-10-31  8:16   ` Michael Albinus
2022-10-31 16:01   ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-10-31 18:01     ` Eli Zaretskii
2022-10-31 18:29       ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-03 17:09         ` Jim Porter
2022-11-03 20:24           ` Brian Cully via Bug reports for GNU Emacs, the Swiss army knife of text editors
2022-11-05 19:10             ` Jim Porter

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).