Subject: Re: bug#16582: Bug: tramp shell command doesn't read stdin

From: Sylvain Chouleur <[email-masked]>
Date: Sun, 2 Feb 2014 15:27:35 +0100

Hi,

Here is my proposal (patch in attachment)

exec env PS1=.. bash <(cat <<'EOF'
heredoc commands
EOF
)

bash is still reading stdin and long lines seems to work.
Try it and let me know if any problems

-- 
Sylvain

2014-01-29 Michael Albinus <[email-masked]>:

> Sylvain Chouleur <[email-masked]> writes:
>
> > Hi,
>
> Hi Sylvain,
>
> > I don't understand what was this problem of long command lines
> > (Bug#16045): I've tried to execute shell comands with huge command
> > lines and all were successfull.
> > To keep the approach of splitting the lines, I would suggest something
> > like that:
> > exec /bin/bash -c "
> > commands
> > on
> > multiple lines
> > "
> >
> > But this needs to backslash all shell specific characters, and I don't
> > know if there is really benefit compared to the original solution
> > (before <<EOF)
> >
> > What do you think?
>
> The use case which has triggered the Bug#16045 is rgrep. Run `M-x rgrep'
> on a remote directory. This issues a command like this (in one line!):
>
> find . -type d \( -path \*/SCCS -o -path \*/RCS -o -path \*/CVS -o -path
> \*/MCVS -o -path \*/.svn -o -path \*/.git -o -path \*/.hg -o -path
> \*/.bzr -o -path \*/_MTN -o -path \*/_darcs -o -path \*/\{arch\} \)
> -prune -o \! -type d \( -name .\#\* -o -name \*.o -o -name \*\~ -o -name
> \*.bin -o -name \*.lbin -o -name \*.so -o -name \*.a -o -name \*.ln -o
> -name \*.blg -o -name \*.bbl -o -name \*.elc -o -name \*.lof -o -name
> \*.glo -o -name \*.idx -o -name \*.lot -o -name \*.fmt -o -name \*.tfm
> -o -name \*.class -o -name \*.fas -o -name \*.lib -o -name \*.mem -o
> -name \*.x86f -o -name \*.sparcf -o -name \*.dfsl -o -name \*.pfsl -o
> -name \*.d64fsl -o -name \*.p64fsl -o -name \*.lx64fsl -o -name
> \*.lx32fsl -o -name \*.dx64fsl -o -name \*.dx32fsl -o -name \*.fx64fsl
> -o -name \*.fx32fsl -o -name \*.sx64fsl -o -name \*.sx32fsl -o -name
> \*.wx64fsl -o -name \*.wx32fsl -o -name \*.fasl -o -name \*.ufsl -o
> -name \*.fsl -o -name \*.dxl -o -name \*.lo -o -name \*.la -o -name
> \*.gmo -o -name \*.mo -o -name \*.toc -o -name \*.aux -o -name \*.cp -o
> -name \*.fn -o -name \*.ky -o -name \*.pg -o -name \*.tp -o -name \*.vr
> -o -name \*.cps -o -name \*.fns -o -name \*.kys -o -name \*.pgs -o -name
> \*.tps -o -name \*.vrs -o -name \*.pyc -o -name \*.pyo \) -prune -o
> -type f \( -name \* -o -name .\* \) -exec grep -i -nH -e emacs {} +
>
> It didn't work with the previous Tramp command invocation, I could
> reproduce it locally. The changed command invocation, using a
> here-document, allows to execute the command.
>
> I understand your problem, and I would like to keep the previous command
> invocation method, but I don't know how to do. Breaking the command into
> several lines, escaped with "\\\n", doesn't work, because finally the
> shell interpreter removes those line breaks, and it is confronted with
> the long line, again.
>
> If somebody has a better idea, I would be happy to implement.
>
> Best regards, Michael.
>
> PS: Sorry for the late reply. I've seen your message on the Tramp ML as
> well, but I'm too busy just now for answering in short time.
>
From 2b9e28e2e453a068eb8898fb83d1d71008fdf3ff Mon Sep 17 00:00:00 2001
From: Sylvain Chouleur <[email-masked]>
Date: Fri, 24 Jan 2014 17:46:06 +0100
Subject: [PATCH] Fix tramp-sh-handle-start-file-process stdin

* net/tramp-sh.el (tramp-sh-handle-start-file-process):
The heredoc solution tho handle long command lines prevent the user to
pass some input to the program using stdin.
Use a coproc to pass the heredoc command to the shell
and preserved stdin for user input.
---
 lisp/net/tramp-sh.el | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/lisp/net/tramp-sh.el b/lisp/net/tramp-sh.el
index 65d5f27e967c..3f4f2bf77d7b 100644
--- a/lisp/net/tramp-sh.el
+++ b/lisp/net/tramp-sh.el
@@ -2705,16 +2705,15 @@ the result will be a local, non-Tramp, filename."
 		   (cdr args)))
 	   (command
 	    (when (stringp program)
-	      (format "cd %s; exec %s env PS1=%s %s"
+	      (format "cd %s; exec env PS1=%s %s"
 		      (tramp-shell-quote-argument localname)
-		      (if heredoc "<<EOF" "")
 		      ;; Use a human-friendly prompt, for example for `shell'.
 		      (tramp-shell-quote-argument
 		       (format "%s %s"
 			       (file-remote-p default-directory)
 			       tramp-initial-end-of-output))
 		      (if heredoc
-			  (format "%s\n%s\nEOF" program (car args))
+			  (format "%s <(cat <<'EOF'\n%s\nEOF\n)" program (car args))
 			(mapconcat 'tramp-shell-quote-argument
 				   (cons program args) " ")))))
 	   (tramp-process-connection-type
@@ -4561,7 +4560,7 @@ function waits for output unless NOOUTPUT is set."
     ;; following syntax for here-documents.  This we cannot test; it
     ;; shall be set via `tramp-connection-properties'.
     (when (and (string-match "<<'EOF'" command)
-	       (not (tramp-get-connection-property vec "busybox" nil)))
+	       (tramp-get-connection-property vec "busybox" nil))
       ;; Unset $PS1 when using here documents, in order to avoid
       ;; multiple prompts.
       (setq command (concat "(PS1= ; " command "\n)")))
-- 
1.8.5.2