3

I use Thunar file explorer and pass pathname and filename to a script audioplay. audioplay runs play command on my android via ssh which plays a song.

audioplay script :: cat audioplay

if [ $# -eq 1 ] ; then
echo "   Playing..." "$@"
sshpass -p $passwd  ssh root@192.168.43.10 -p $port  play "$@"
else
 echo "  No Input audio file."
fi

play script on my android :: cat play

    #!/data/bin/bash
    # Avoid linker errors due to libOpenSLES.so:
    echo "File ::" "$@"
    LD_LIBRARY_PATH= exec /data/bin/blob/play-audio "$@"

Problem is Path does not get passed correctly to play command over ssh. Path with multi spaces becomes single space and brackets create syntax error.

Example :

For file 18. Warriors.flac present in /sdcard/Music/Imagine Dragons - Smoke Mirrors -Deluxe Edition-2015

Path sent to audioplay is correct :: /sdcard/Music/Imagine Dragons - Smoke Mirrors -Deluxe Edition-2015/18. Warriors.flac

But the path received by play script is wrong :: /sdcard/Music/Imagine Dragons - Smoke Mirrors -Deluxe Edition-2015/18. Warriors.flac Multi spaces are turned into single space. Why ?

Then the main play-audio binary gets only path /sdcard/Music/Imagine upto first space only.

Example 2 ::

I tried with file having brackets :: 44. Go Tell Aunt Rhody -Resident Evil- (Short Version).flac Path received by audioplay script is correct :: /sdcard/Music/44. Go Tell Aunt Rhody -Resident Evil- (Short Version).flac But I get this error :: sh: syntax error: '(' unexpected

I tried with passing $@ $* "$@" and "$*". But none of them worked for me.

jonny789
  • 499

1 Answers1

2

Quote it again:

if [ "$#" -eq 1 ] ; then
    echo "   Playing..." "$1"
    sshpass -p "$passwd" ssh root@192.168.43.10 -p "$port" "play '$1'"
else
    echo "  No Input audio file."
fi

The thing is that the first layer of quotes, the "$@" are expanded when you run the sshpass command. So by the time you log in, launch the remote shell and execute play, you have an unquoted string, so your script chokes on whitespace. By enclosing it in a second layer of quotes, you ensure that it is passed quoted to the remote command.

This should work assuming that i) the remote machine is running sh or bash or a similar shell and ii) your file names don't contain single quotes. To make it truly robust, please see How to execute an arbitrary simple command over ssh without knowing the login shell of the remote user?.

For properly quoting an arbitrary string (or even a list of arbitrary strings so you can pass more than one argument to play) in the sh syntax, we can use that shquote() function mentioned there:

shquote() {
  LC_ALL=C awk -v q=\' -v b='\\' '
    BEGIN{
      for (i=1; i<ARGC; i++) {
        gsub(q, q b q q, ARGV[i])
        printf "%s ", q ARGV[i] q
      }
      print ""
      exit
    }' "$@"
}
if [ "$#" -ge 1 ] ; then
    echo "   Playing..." "$@"
    sshpass -p "$passwd" ssh root@192.168.43.10 -p "$port" "play $(shquote "$@")"
else
    echo "  No Input audio file."
fi

It would quote Sgt. Pepper's lonely hearts club band.flac as 'Sgt. Pepper'\''s lonely hearts club band.mp3' which is correct for sh (and evil';reboot;: '.flac as 'evil'\'';reboot;: '\''.flac' instead of rebooting the remote machine (do you have to run that play command as root?)).

terdon
  • 242,166
  • @StéphaneChazelas since it's an Android device, it's safe (I think) to assume the remote is running sh. But yes, it will indeed break on single quotes. – terdon Sep 26 '17 at 15:36
  • It worked. Thanks a lot. I spent hours on it searching and trying. – jonny789 Sep 26 '17 at 15:41
  • @jonny789 you're welcome. But do read Stéphane's answer in the linked post for more detail. – terdon Sep 26 '17 at 15:44
  • Yes. I login to android as root user. Running play as root works without any issue. – jonny789 Sep 26 '17 at 17:06