Subject: bug#35639: 27.0.50; tramp fails to use ssh on LibreCMC (no base64 encoder available, and not mentioned in tramp manual)

From: Michael Albinus <[email-masked]>
Date: Sun, 12 May 2019 10:43:12 +0200

Jeronimo Pellegrini <[email-masked]> writes:

Hi Jeronimo,

>> Or I can try to make the shell code that is sent to the remote
>> end do the verification itself (I'd test using dash, which I
>> hope will work on most systems of interest). Something like
>>
>> { hexdump < /dev/null && HD=hexdump; } || \
>> { busybox hexdump < /dev/null && HD="busybox hexdump"; } &&  \
>> $HD ...
>
> I actually implemented the shell scripting solution.
> Only tramp-hexdump-awk-encode is in the email body, but the
> full patch is attached.
>
> This seems to work, and requires no extra coding in tramp
> (only the constant strings are changed).

Thanks for this. However, it is not the approach Tramp goes for remote
command detection. The major downsides are, that the whole script must
be transferred to the remote side again and again, and that the
detection code runs again and again. Both decreases the performance.

> I can also do the templating in elisp, if you think it would be
> better.

Yes, please. First, you shall define the functions

tramp-get-remote-busybox
tramp-get-remote-awk
tramp-get-remote-hexdump
tramp-get-remote-od

All of them use connection caching, in order to run the detection only
once, and use the cached result afterwards. tramp-get-remote-busybox is
just a helper function for the other three functions, it could look like

(with-tramp-connection-property vec "busybox"
  (tramp-message vec 5 "Finding a suitable `busybox' command")
  (tramp-find-executable vec "busybox" (tramp-get-remote-path vec)))

See, how other tramp-get-remote-* functions in tramp-sh.el look like.
tramp-get-remote-{awk,hexdump,od} are implemented as

(with-tramp-connection-property vec "awk"
  (tramp-message vec 5 "Finding a suitable `awk' command")
  (or (tramp-find-executable vec "awk" (tramp-get-remote-path vec))
      (let* ((busybox (tramp-get-connection-property vec "busybox" nil))
	     (command (concat busybox " awk {} </dev/null")))
	(and busybox
	     (tramp-send-command-and-check vec command)
	     command))))

In tramp-remote-coding-commands, TEST must be extended not to be only a
string (which is run as command on the remote side), but also a Lisp
form to be evaluated. We would need tramp-hexdump-awk-coding-test and
tramp-od-awk-coding-test, with code like this:

(and (tramp-get-connection-property vec "hexdump" nil)
     (tramp-get-connection-property vec "awk" nil))

and the same for tramp-od-awk-coding-test.

Finally, the encoding/decoding commands in
tramp-{hexcdump,od}-awk-{encode,decode} would need place-holders for
%a (for awk), %h (for hexdump), and %o (for od), like:

"%h -v -e '16/1 \" %%02x\" \"\\n\"'| %a '\\
 ...
 }'"

In tramp-find-inline-encoding, these place-holders must be expanded by
the result of tramp-get-connection-property for the respective command.

All of this sounds a little bit complicate, but it ensures, that every
test on the remote side is run only once, and the result is taken from
the cache afterwards.

Best regards, Michael.