Subject: Re: bug#31924: 27.0.50; tramp handler /sudo::FILE fails when /bin/sh points to zsh

From: Tino Calancha <[email-masked]>
Date: Mon, 25 Jun 2018 10:36:39 +0900

Michael Albinus <[email-masked]> writes:

> Tino Calancha <[email-masked]> writes:
>
>> Hi Michael,
>
> Hi Tino,
>
>> I got a patch that works in my box.  It does 2 things:
>>
>> 1) Ensure that zsh is invoked as zsh, that is, not as sh.  Otherwise
>>    our dotfiles are ignored, and we keep getting the bracketed paste
>>    codes.
>>    
>> 2) I also need to disable the zsh option promptcr, otherwise after I
>> introduce my root password, Emacs gets stuck in `tramp-wait-for-output';
>> this is becuse some '\r' are added in front the prompt, so the
>> regexp in ``tramp-wait-for-regexp' cannot match.
>
> Point 2) is OK. But your solution for point 1) doesn't work in general.
Please consider to apply the restricted patch at the end of this
message.  It's clean and it doesn't add method specific stuff.

I have successfully connected into a remote machine using this patch,
with my local machine having:
/bin/sh -> /bin/zsh

>> @@ -4110,7 +4112,11 @@ tramp-open-connection-setup-interactive-shell
>>  process to set up.  VEC specifies the connection."
>>    (let ((tramp-end-of-output tramp-initial-end-of-output)
>>  	(case-fold-search t))
>> -    (tramp-open-shell vec (tramp-get-method-parameter vec 'tramp-remote-shell))
>> +    (tramp-open-shell
>> +     vec
>> +     (if (not (equal "sudo" (tramp-file-name-method vec)))
>> +         (tramp-get-method-parameter vec 'tramp-remote-shell)
>> +       (file-truename (tramp-get-method-parameter vec 'tramp-remote-shell))))
>
> In tramp-sh.el, there shall be no code which relies on a given
> method. Everything which is method specific, must be configured in
> `tramp-methods'.
Do you want to support /sudo when the local machine has
/bin/sh -> /bin/zsh?
* If yes: then we obviously need to introduce changes in the code; it's
  a pity not supporting out of the box, i.e., with emacs -Q,
  a great shell as zsh is.

* If no: then I suggest explicitely say in the manual that such
configuration won't work.  Currently the manual suggest a workaround
that cannot work, because our .zshrc is ignored.  Reading the manual
that is not obvious for the reader.

> Furthermore, this code does not work at all. (file-truename "/bin/sh")
> is always eval'ed on the local host, but you want to get information
> about the remote host.
Have you tried it? It works for me :-) and pretty well, actually.
As you know better than me, the remote host _is_ just the local host
when you are invoking /sudo method.

> The better solution is to overwrite the `tramp-remote-shell' connection
> property. Do something like this:
>
>      (add-to-list 'tramp-connection-properties
>                   (list (regexp-quote "/ssh:[email-masked]:")
>                         "remote-shell" "/bin/zsh"))
>
> See the Tramp manual, (info "(tramp) Predefined connection information")
I am afraid this doesn't fix the issue.
* It won't work with emacs -Q
--8<-----------------------------cut here---------------start------------->8---
commit 789f6d789b93f87be4732a03c607a6a5b59dbaf0
Author: Tino Calancha <[email-masked]>
Date:   Mon Jun 25 09:58:05 2018 +0900

    Tramp: Remote connection when local /bin/sh points to zsh
    
    The dotfiles, e.g. ~/.zshrc., aren't read if zsh is invoked as sh.
    We also need to unset the option promptcr, otherwise
    `tramp-wait-for-output' might get stuck.
    
    * lisp/net/tramp-sh.el (tramp-maybe-open-connection):
    Use (file-truename tramp-encoding-shell) as the PROGRAM
    in the `start-process' call (Bug#31924).
    
    (tramp-sh-extra-args): Don't add CR to the zsh prompt.

diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 63b39a0378..ce196ff80e 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -550,7 +550,9 @@ tramp-remote-process-environment
   :type '(repeat string))
 
 ;;;###tramp-autoload
-(defcustom tramp-sh-extra-args '(("/bash\\'" . "-norc -noprofile"))
+(defcustom tramp-sh-extra-args
+  '(("/bash\\'" . "-norc -noprofile")
+    ("/zsh\\'" . "--no-promptcr"))
   "Alist specifying extra arguments to pass to the remote shell.
 Entries are (REGEXP . ARGS) where REGEXP is a regular expression
 matching the shell file name and ARGS is a string specifying the
@@ -4792,6 +4794,7 @@ tramp-maybe-open-connection
 		     ;; W32 systems.
 		     (process-coding-system-alist nil)
 		     (coding-system-for-read nil)
+		     (encoding-shell (file-truename tramp-encoding-shell))
 		     ;; This must be done in order to avoid our file
 		     ;; name handler.
 		     (p (let ((default-directory
@@ -4801,9 +4804,9 @@ tramp-maybe-open-connection
 			   (tramp-get-connection-name vec)
 			   (tramp-get-connection-buffer vec)
 			   (if tramp-encoding-command-interactive
-			       (list tramp-encoding-shell
+			       (list encoding-shell
 				     tramp-encoding-command-interactive)
-			     (list tramp-encoding-shell))))))
+			     (list encoding-shell))))))
 
 		;; Set sentinel and query flag.  Initialize variables.
 		(set-process-sentinel p 'tramp-process-sentinel)
@@ -4818,7 +4821,7 @@ tramp-maybe-open-connection
 		;; Check whether process is alive.
 		(tramp-barf-if-no-shell-prompt
 		 p 10
-		 "Couldn't find local shell prompt for %s" tramp-encoding-shell)
+		 "Couldn't find local shell prompt for %s" encoding-shell)
 
 		;; Now do all the connections as specified.
 		(while target-alist

--8<-----------------------------cut here---------------end--------------->8---