[RndTbl] dialog(1) shell fd acrobatics question

Kevin McGregor kevin.a.mcgregor at gmail.com
Sat Jul 6 09:03:33 CDT 2024


Cool. Thanks for sharing that.

On Fri, Jul 5, 2024 at 21:33 Adam Thompson <athompso at athompso.net> wrote:

> I think I figured it out…
>
>
>
> Command substitution ( $(cmd) or `cmd`) redirects the inner command’s
> stdout and captures it – that’s the whole point of command substitution.
>
> So if I want dialog(1) to talk to the outer shell’s stdout * without*
> being captured by command substitution, I have to
>
>    1. tell dialog(1) to send its results to stderr – this is the default
>    2. redirect that diaglog(1) process’s stderr to FD 1 (stdout) using
>    the inner shell
>    3. redirect that dialog(1) process’s stdout to FD 3, which is the *original,
>    outer* shell’s stdout, not the captured-by-command-substitution
>    version of stdout.
>
> Ugh.
>
>
>
> -Adam
>
>
>
>
>
> *From:* Roundtable <roundtable-bounces at muug.ca> *On Behalf Of *Adam
> Thompson
> *Sent:* Thursday, July 4, 2024 9:01 PM
> *To:* MUUG Roundtable <roundtable at muug.ca>
> *Subject:* [RndTbl] dialog(1) shell fd acrobatics question
>
>
>
> I’m trying to debug a shell script that uses dialog(1), which has the
> unfortunate habit of overwriting the debug output I wanted to see.
>
> After quite some time banging my head against the wall, I grabbed the
> source to dialog to look at their examples.
>
>
>
> Their examples follow a pattern I have NOT been following; I’m now looking
> at this trying to understand WTF it does:
>
>
>
> 1             exec 3>&1
>
> 2             returntext=`$DIALOG --title "RANGE BOX" --rangebox "Please
> set the volume..." 0 60 0 123 5 2>&1 1>&3`
>
> 3             returncode=$?
>
> 4             exec 3>&-
>
>
>
> so… ok.
>
> Line 1 duplicates FD 1 (stdout) into FD 3.  That’s usually so we can mess
> with FD 1 later on and still have a handle to stdout.  Good so far.
>
> Line 2 runs /usr/bin/dialog in a subshell, the options to dialog(1) are
> irrelevant here.  I’m looking at the redirects.
>
>     “2>&1” duplicates FD 1 into FD 2, effectively throwing away the handle
> to the inherited /dev/stderr and forcing stderr output onto stdout.  That’s
> a good thing because dialog(1) reports its results onto stderr by default
> to avoid messing with curses(3) output.
>
>     “1>&3” however, throws away stdout (FD 1), replacing it with FD 3
> which is… already a copy of FD 1 ???
>
> Line 3 is obvious.
>
> Line 4 closes FD 3.  Not sure that we need to bother, but OK, cleaning up
> behind ourselves is usually a good thing.
>
>
>
> I get the need for swapping stdin/stderr, as dialog(1) – well, really
> curses(3) - uses stdout to paint the screen, so dialog(1) spits its results
> out on stderr to avoid conflicting.  If we’re in a subshell trying to
> capture that output, we need to grab it just as dialog(1) exits – and $()
> assignment only captures stdout.
>
>
>
> But what’s the point of having FD 3 in this setup, if all we do is assign
> it to stdin inside the subshell and then forget about it?
>
>
>
> Can anyone see what I’m missing here?
>
> -Adam
>
>
> _______________________________________________
> Roundtable mailing list
> Roundtable at muug.ca
> https://muug.ca/mailman/listinfo/roundtable
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://muug.ca/pipermail/roundtable/attachments/20240706/20fe882d/attachment-0001.htm>


More information about the Roundtable mailing list