Unix/Linux Go Back    


Shell Programming and Scripting BSD, Linux, and UNIX shell scripting — Post awk, bash, csh, ksh, perl, php, python, sed, sh, shell scripts, and other shell scripting languages questions here.

Problem reading terminal response string from Zsh

Shell Programming and Scripting


Tags
tty, zsh

Reply    
 
Thread Tools Search this Thread Display Modes
    #1  
Old Unix and Linux 2 Weeks Ago   -   Original Discussion by rovf
rovf's Unix or Linux Image
rovf rovf is offline
Registered User
 
Join Date: Jun 2011
Last Activity: 15 January 2018, 2:25 AM EST
Posts: 196
Thanks: 29
Thanked 43 Times in 37 Posts
Problem reading terminal response string from Zsh

Note: This posting is related to my posting at bash - Reading answer to control string sent to xterm - Stack Overflow , but I could get there a solution only for bash. I can use that solution, but for curiosity, I wonder, whether I could do this in Zsh as well.

The problem is to send a (Posix-) terminal query string to the terminal where the (interactive) shell is running, and to read the response from the terminal. For example, when we send Escape followed by the letter Z, the terminal is supposed to respond with the terminal ID. This response also starts with an Escape, followed by an arbitrary number of characters. Since I don't know the number of characters returned in advance, I have to accumulate them one by one.

This is the solution I achieved with bash, ask_tty.sh:



Code:
#!/bin/bash

str='' # Buffer for response
tty=$(tty)

# Send query string to terminal. Example: Esc Z queries for terminal id
echo -e '\e'${1:-Z}  >$tty

# Read response from terminal
while :
do
  read -rs -t 1 -n 1 <$tty
  if [[ -z $REPLY ]]
  then
    break
  fi
  str="${str}$REPLY"
done

# Output response without leading Esc
echo "${str#?}"

If I run in my terminal either ask_tty.sh Z or ask_tty.sh (because I made Z the default value), I get as response on stdout

[?63;1;2;4;6;9;15;22;29c

The actual reading of each character is done by read -rs -t 1 -n 1 <$tty.

I feel that for adapting this solution to Zsh, I have to change the bash read to an equivalent Zsh read, but I could not get it done: Either the command hangs, or it returns only the first character of the answer string. For instance, I tried read -rs -t -k and read -rs -t 1 -k 1.

How can I solve this in Zsh?

Update: I'm using Zsh 5.3 (given the evolution of Zsh, version might matter here), running on Cygwin.

Last edited by rovf; 2 Weeks Ago at 09:46 AM.. Reason: Providing additional information
Sponsored Links
    #2  
Old Unix and Linux 2 Weeks Ago   -   Original Discussion by rovf
Scrutinizer's Unix or Linux Image
Scrutinizer Scrutinizer is offline Forum Staff  
Moderator
 
Join Date: Nov 2008
Last Activity: 19 January 2018, 2:53 AM EST
Location: Amsterdam
Posts: 11,706
Thanks: 530
Thanked 3,398 Times in 2,994 Posts
Did you try:


Code:
read -rs -t 1 -q <$tty

Sponsored Links
    #3  
Old Unix and Linux 2 Weeks Ago   -   Original Discussion by rovf
rovf's Unix or Linux Image
rovf rovf is offline
Registered User
 
Join Date: Jun 2011
Last Activity: 15 January 2018, 2:25 AM EST
Posts: 196
Thanks: 29
Thanked 43 Times in 37 Posts
Quote:
Originally Posted by Scrutinizer View Post
Did you try:


Code:
read -rs -t 1 -q <$tty
According to the man page, this can not work. Quoting the man-page:

-q Read only one character from the terminal and set name to `y' if this character was `y' or `Y' and to `n' otherwise.

So, even if it would work, it would not return the answered character, but set my variable to y or n.

Interestingly, the actual effect is that I don't even get this result, but instead the script loops forever, always returning n. It doesn't seem to actually "consume" the character.
    #4  
Old Unix and Linux 2 Weeks Ago   -   Original Discussion by rovf
Chubler_XL's Unix or Linux Image
Chubler_XL Chubler_XL is offline Forum Staff  
Moderator
 
Join Date: Oct 2010
Last Activity: 18 January 2018, 9:44 PM EST
Posts: 3,434
Thanks: 149
Thanked 1,216 Times in 1,115 Posts
In bash you could simplify the logic as -t will timeout if a full line is not received



Code:
#!/bin/bash

str='' # Buffer for response
tty=$(tty)

# Send query string to terminal. Example: Esc Z queries for terminal id
echo -e '\e'${1:-Z}  >$tty

# Read response from terminal (200ms timeout empty delimiter)
read -rs -t 0.2 -d "" <$tty

# Output response without leading Esc
echo "Response: ${REPLY#?}"

Under zsh -t is just a timeout for the first character being available. Use return value of read to detect a timeout, as REPLY is not emptied on timeout:



Code:
#!/bin/zsh
str='' # Buffer for response
tty=$(tty)

# Send query string to terminal. Example: Esc Z queries for terminal id
echo -e '\e'${1:-Z}  >$tty

# Read response from terminal
while :
do
  read -rs -t 0.2 -k 1 <$tty || break
  str="${str}$REPLY"
done


# Output response without leading Esc
echo "Response: ${str#?}"


Last edited by Chubler_XL; 2 Weeks Ago at 09:30 PM..
Sponsored Links
    #5  
Old Unix and Linux 2 Weeks Ago   -   Original Discussion by rovf
apmcd47's Unix or Linux Image
apmcd47 apmcd47 is online now
Registered User
 
Join Date: Feb 2011
Last Activity: 19 January 2018, 4:19 AM EST
Posts: 293
Thanks: 13
Thanked 79 Times in 76 Posts
From a 1980's script, written by somebody else for Suns:


Code:
stty raw >/dev/tty
echo -n "$report" >/dev/tty
ch=`dd </dev/tty count=1 2>/dev/null`
stty cooked >/dev/tty

Where $report is your input string.

The above still works today in a ROXTERM and xfce4-terminal on Linux, and should work on other terminal emulators.

Also note the /dev/tty will use the current terminal without having to find it with tty

Andrew
The Following User Says Thank You to apmcd47 For This Useful Post:
rovf (2 Weeks Ago)
Sponsored Links
    #6  
Old Unix and Linux 2 Weeks Ago   -   Original Discussion by rovf
rovf's Unix or Linux Image
rovf rovf is offline
Registered User
 
Join Date: Jun 2011
Last Activity: 15 January 2018, 2:25 AM EST
Posts: 196
Thanks: 29
Thanked 43 Times in 37 Posts
Quote:
Originally Posted by apmcd47 View Post


Code:
stty raw >/dev/tty
echo -n "$report" >/dev/tty
ch=`dd </dev/tty count=1 2>/dev/null`
stty cooked >/dev/tty

Where $report is your input string.
This does work too, indeed, though I don't fully understand the script: Why do we need the count parameter here. I see that we do need it, because when I set it to a higher value or omit it, the script hangs (probably waiting for input). But how does this parameter make it work?

I understand that with count=1, you tell dd to return one block only, where the default block size is 512 bytes. I can understand, how this works, when reading from a file, but how does dd know that it has finished reading? There is, I think, no EOF when reading from /dev/tty, and if there were an EOF condition, the count parameter would not be needed at all.
Sponsored Links
    #7  
Old Unix and Linux 2 Weeks Ago   -   Original Discussion by rovf
Don Cragun's Unix or Linux Image
Don Cragun Don Cragun is online now Forum Staff  
Administrator
 
Join Date: Jul 2012
Last Activity: 19 January 2018, 4:40 AM EST
Location: San Jose, CA, USA
Posts: 10,916
Thanks: 609
Thanked 3,817 Times in 3,261 Posts
The assumption is that the terminal will send its entire response to your terminal query in a single burst of characters. That burst of characters will be read as one "block" by dd and with the directive count=1 it will quit after it has successfully read that single block. Without the count=1, dd will continue reading blocks from the terminal until it hits an EOF condition, which won't happen until you type CTL-D (i.e., hold down the control key while you hit the "d" key).
The Following User Says Thank You to Don Cragun For This Useful Post:
rovf (1 Week Ago)
Sponsored Links
Reply

Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Linux More UNIX and Linux Forum Topics You Might Find Helpful
Thread Thread Starter Forum Replies Last Post
[Solved] Need Help in reading Response file mallak Shell Programming and Scripting 6 03-02-2014 10:19 PM
slow response on solaris terminal skamal4u Solaris 3 09-06-2011 11:31 AM
ssh error: Error reading response length from authentication socket cpp6f UNIX for Advanced & Expert Users 1 10-27-2009 07:16 PM
Running a String as a command, zsh. drnkhmlck Shell Programming and Scripting 2 04-03-2008 03:21 PM
Reading response from server frustrated1 Shell Programming and Scripting 4 03-24-2004 02:22 PM



All times are GMT -4. The time now is 05:45 AM.