0

I am intending to use gdialog to take user input and feed it to switch case in shell. Below is my code:

#!/bin/sh


which gdialog 2> /dev/null && DIALOG=gdialog || DIALOG=dialog

end () {
    # rm -f $FILE1 $FILE2 $ERROR
    echo "User pressed cancel!"
exit
}

while true
do
    choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
    "Date" "Get today's date" \
    "Time" "Get today's time")|| end

    # echo $choice

    case "$choice" in
            "Date")

            MSG="Date is requested"
            echo $MSG
            $DIALOG --yesno "$MSG" 7 20 || end          
     ;;
            "Time")
            MSG="Time is requested!"
            $DIALOG --yesno "$MSG" 7 20 || end          
     ;;
    esac
done

The problem is the switch case executes and the control flow reaches the first case or second case but the line after the declaration of MSG variable does not execute. I am intending to ask the user if they want to continue by using a yes/no gdialog. What am I doing wrong here?

Rui F Ribeiro
  • 56,709
  • 26
  • 150
  • 232

2 Answers2

1

Command substitution gets replaced by the standard output of the command. dialog uses stdout to display it's UI, gdialog afaik doesn't use it at all. Both use stderr to return the result.

One way to make your script work as you expect is to swap stdout with stderr in your command substitution:

choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
"Date" "Get today's date" \
"Time" "Get today's time" 3>&2 2>&1 1>&3)|| end
adonis
  • 1,724
0

dialog will write its result to the standard error unless you do some workaround with redirection, or use the --stdout option (because, like any curses application, it writes its display to the standard output by default, and reports on the standard error). You wouldn't notice that with gdialog, since it writes its display to another window.

Because of this, gdialog would be writing nothing to the standard output, and $choice would be empty. The script will execute the case-statement, but not match any of the cases. As a rule, case statements should have a default, e.g., *) so that you can put a message there and see what is going on.

Not part of the question, but how to work around the problem seems to be expected. The script refers to gdialog, which likely is a script calling zenity (the original gdialog is long gone). Neither has the --stdout option, though that probably predates either program (see changelog entry from 2000). You can work around that in the shell by exchanging the file-descriptors for the standard output and error. That has been in dialog's sample scripts since late 2000 also, using a suggestion by Carey Evans (tn5250 developer):

    It's possible to capture the output from dialog, without using
    temporary files at all, as I did in tn5250's "xt5250" script:

        exec 3>&1
        XT5250_HOST="`$DIALOG --backtitle "xt5250" --title "Connect to Host" \
          --inputbox "Enter the name or IP address of the host to connect to:" \
          7 60 2>&1 1>&3`"
        ret=$?
        exec 3>&-

    Perhaps you could consider using something like this instead of
    temporary files.  The trickery with extra fd's gets a bit hard to
    read, though.

    > (they're examples though - how much work should I spend to make them secure?)

    People _will_ cut-and-paste them.

Agreeing with that, it helps to stop and explain scripts. The bash documentation helps here, with Moving file-descriptors. This script

(sh myscript.sh 3>&2 2>&1 1>&3) 2>/dev/null

can be read right-to-left as (a) moving the file descriptor 1 (stdout) to 3, 2 (stderr) to 1 and then 3 (originally stdout) to 2.

So you could improve your script by pasting in the same series of changes to the file descriptors:

3>&2 2>&1 1>&3

in the assignment to choice:

choice=$($DIALOG --title "Messenger" --menu "Command" 8 35 8 \
"Date" "Get today's date" \
"Time" "Get today's time" 3>&2 2>&1 1>&3 )|| end

Further reading:

Thomas Dickey
  • 76,765
  • But the $MSG variable is also not echoing the value either. The control exits the switch statement after executing the first line. – radiopassive May 31 '16 at 08:24