16

I'm trying to use whiptail as it's a lightweight alternative to dialog and seems to be installed by default in most systems (i.e., people don't have to go around and install it if it's "forgotten" or wasn't installed by default). I checked question #1562666 for a few examples here, but I'm looking for an alternative for redirecting output so that is sets an environment variable, instead of just writing to disk.

For example, when I try with dialog, this works (I see the dialog box, and an environment variable is set):

result=$(dialog --output-fd 1 --inputbox "Enter some text" 10 30)
echo Result=$result

However, this doesn't work when using whiptail in place of dialog, as the dialog box never shows up. I have to redirect it to a disk file and read it, for example:

result=$(tempfile) ; chmod go-rw $result
whiptail --inputbox "Enter some text" 10 30 2>$result
echo Result=$(cat $result)
rm $result

It works, and I can use the same tempfile from beginning to end (removing it when the script ends). But it feels awkward to be forced to use the disk just for this, instead of keeping it all in memory (redirecting to an environment variable).

So I'm asking: Am I forgetting something -- or do I really have to use the disk when using whiptail?

Thank you in advance for your feedback.

Community
  • 1
  • 1
jbatista
  • 2,747
  • 8
  • 30
  • 48
  • It seems like whenever whiptail has its stdin/stdout redirected, it doesn't show (whether with $(...) or ... | ). Your solution looks pretty good considered the behaviour of whiptail. BTW, on my debian machine, I have whiptail but no dialog by default, on opensuse, I have dialog and no existing whiptail in the official repositories. – Zeograd Dec 28 '09 at 16:30
  • @Zeograd at least on RHEL whiptail comes in "newt" package. – Kimvais Dec 28 '09 at 16:34
  • Right, thx Kimvais. "zypper search whiptail" failed on me even if the info was stating it was in. – Zeograd Dec 28 '09 at 19:33
  • @Zeograd : I suppose that given that each distribution "chooses" to install one or another, it should be a simple matter of testing the existence of one, defining an environment variable, and using it throughout the rest of the script. – jbatista Dec 29 '09 at 11:25

2 Answers2

40

This is probably because whiptail uses stdin and stdout to print the input box, so you cannot redirect stderr directly to stdout, but you need to swap them, e.g:

foobar=$(whiptail --inputbox "Enter some text" 10 30 3>&1 1>&2 2>&3)
Kimvais
  • 38,306
  • 16
  • 108
  • 142
  • I have a question. Why you put `3>&1 1>&2 2>&3` at the end of whiptail? Without it command is not working, but I don't know why. – A. Dziedziczak Jul 19 '17 at 20:35
  • It swaps stdout and stderr, restoring sanity to the world. `$(...)` captures stdout so you really want the GUI stuff to print to stderr and the result to go to stdout, but whiptail has them swapped for some reason. Those three redirections swap them back. – John Kugelman May 01 '19 at 01:11
  • 2
    ...I suppose one could add `3>&-` to the end, to leave 1 and 2 swapped and 3 nicely closed. Not that it particularly matters, though. – Charles Duffy May 01 '19 at 01:14
  • That's nice! This way we can define as a function: `function menu() { whiptail "$@" 3>&1 1>&2 2>&3 3>&- ; }` and then we can do a "cleaner" call such as `result=$(menu --inputbox "Enter some text" 10 30)` or similar. – jbatista Nov 17 '20 at 22:47
  • Could be helpful figuring out why it's hard to call from C. Spent a day or so trying that a couple years ago, gave up. – Alan Corey Dec 31 '21 at 19:06
2

It appears that whiptail(1) writes its control output to the termininal based on the setting of the TERM environment variable. Conseqently, you can't use the standard output stream of whiptail(1) to set a variable. Also, whiptail(1) writes the user-input of the input box to the standard error stream so, again, you can't use its standard output stream to set a variable.

Steve Emmerson
  • 7,702
  • 5
  • 33
  • 59