2

Is there a way that I can make a heredoc in a script interactive as if I am at the prompt?

This is over ssh from linux to an ssh server runing on android connecting through mosh.

I'm making a set of a few small scripts to allow me to reasonably sms over ssh on my android from my laptop using bash under the app termux.

While testing the send command at the prompt all works well:

termux-sms-send -n "$(tail -n1 number | tr -d ' ')" << ''

However, when inside a script this no longer works. This is the result:

./main.sh: line 34: warning: here-document at line 33 delimited by end-of-file (wanted `')
./main.sh: line 35: syntax error: unexpected end of file

I could of course do it another way but it's so neat and simple with the heredoc method and it's something I haven't really used before in bash and I am unsure how to get the read command to work nicely with multi line input in such a graceful way as this.

__

Edit Addition:

In case anyone is interested and for context this is the script:

searchTxt=""
contacts="$(termux-contact-list | jq -r '.[].name')"

clear 

while :; do
   echo -ne "\nEnter searchterm: $searchTxt"
   read -rsn1 ret; clear

   if [ ${#ret} -eq 0 ]; then
      if [ $(wc -l <<< "$choice") -gt 1 ]; then
         echo -en "type enough characters to narrow down selecton until only 1 remains\n\n"
      else
         echo "choice = $choice"
         number="$(termux-contact-list | jq -r ".[] | select(.name==\"$choice\") | .number")"
         echo "using number: $number"
         echo "$choice" > number
         echo "$number" >> number
         break
      fi
   fi

   searchTxt+=$ret
   choice=$(grep -i "$searchTxt" <<< "$contacts")
   echo "$choice"
done

while :; do
   clear 
   echo "Type message to send, enter a blank line to send message"
   echo -n "message: "

   termux-sms-send -n "$(tail -n1 number | tr -d ' ')" << ''
done
12
  • Did you mean to use an empty here string instead of a here document? termux-sms-send ... <<< '' Commented May 14, 2017 at 1:24
  • If I understand correctly (and you're feeding the script text to the remote interpreter's stdin via a heredoc over SSH), SSH is really a critical part of this question -- having it only mentioned in the prose but its use not shown in an example is underplaying it. And if I don't understand correctly, perhaps there's some clarification to be done. Commented May 14, 2017 at 1:24
  • Or do you simply want to have termux-sms-send inherit its standard input from the script, in which case you don't need to do anything? Commented May 14, 2017 at 1:25
  • 1
    BTW, you're mixing code and data when you use jq -r "...\"$choice\"..."; that's prone to injection issues, which could turn into security bugs if future versions of jq add file I/O extensions or the ability to execute external programs. Instead, use jq --arg choice "$choice" '...$choice...', where $choice is passed as a jq variable separate from the code. Commented May 14, 2017 at 1:29
  • I'm looking to have it prompt for text when it reaches that command. So that I can type a message, which may have multiple lines and then have that typed message sent to the termux-sms-send command. I was unaware ssh was an important part to mention, I'll add that now. Commented May 14, 2017 at 1:29

1 Answer 1

2

The proposed idiom is looking for a bare newline in the code (since the code is from where the heredoc is being read), as opposed to a bare newline in stdin.

That works at an interactive prompt, where your code is coming from stdin -- but the reason it doesn't work from a script should be obvious.

The following loop is explicit about looking in the input stream:

while IFS= read -r line; do
  [[ $line ]] || break
  printf '%s\n' "$line"
done | termux-sms-send -n "$(tail -n1 number | tr -d ' ')"
Sign up to request clarification or add additional context in comments.

2 Comments

This is a more sane solution. After reading your comments about portability and future proofing the longer but more robust method does seem best. Thank you very much for all the tips. I didn't expect to learn so much from this question, its much appreciated =)
Note that some time around Q1 2019, Google started cracking down on app security policy. As a result, the Termux project was forced to remove SMS functionality in order to keep the app in the Play Store. However, installing Termux from the F-Droid package manager apparently still has SMS functionality.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.