The Section distprompter Edits dist Drafts gives an overview of this script. Here is the distprompter script (you might want to open it in a separate browser window). To install it, see the Section Programs in This Book's Archive.
The main part of distprompter is the while loop. It reads the template draft file (that dist built; the Section Making the Draft from the Template File explains how). The draft filename is in the first command-line parameter, $1. The while loop writes the edited header into the $header file. The loop is shown below. The line numbers like 31> aren't part of the file; they're just for reference.
30> # read COMMAND AT TOP OF LOOP GETS STDIN (FD 0), SO SAVE FD 0 NOW: 31> exec 4<&0 # SAVE ORIGINAL STDIN (USUALLY TTY) AS FD 4 32> while read label line 33> do 34> case "$label" in 35> [Rr]esent-?*:) 36> case "$line" in 37> ?*) # SHOW LINE ON SCREEN AND PUT INTO HEADER FILE: 38> echo "$label $line" 39> echo "$label $line" 1>&3 40> ;; 41> *) # FILL IT IN OURSELVES: 42> $echo "$label $nnl" 43> exec 5<&0 # SAVE DRAFT FILE FD; DO NOT CLOSE! 44> exec 0<&4 # RESTORE ORIGINAL STDIN 45> read ans 46> exec 0<&5 # RECONNECT DRAFT FILE TO STDIN 47> case "$ans" in 48> "") ;; # EMPTY; DO NOTHING 49> *) echo "$label $ans" 1>&3 ;; 50> esac 51> ;; 52> esac 53> ;; 54> ""|---*) # END OF HEADER 55> echo "-------" 1>&3 56> break # PROBABLY NOT NEEDED... 57> ;; 58> *) echo "$myname: illegal header component 59> '$label $line'" 1>&2 60> break 61> ;; 62> esac 63> done <$1 2>$err 3>$headerFor efficiency, the script uses UNIX file descriptors to keep several files open at once. The loop reads and writes those open files, one line at a time. The Bourne shell can manipulate file descriptors with its exec command and operators like 2>&1 and 0<&5. There isn't room here for a complete explanation; to get that, see an advanced Bourne shell programming book like UNIX Power Tools. The comments in the script and the explanation here will tell you what each file descriptor redirection does.
The Table below lists the file descriptor numbers used in operators like 4<&0.
Table: UNIX File Descriptor Numbers
Number Default Use 0 Standard input 1 Standard output 2 Standard error 3-9 Not assigned** If your MH was built with the [OVERHEAD] configuration option, some of the file descriptors 3-9 may already have been used. (Section The -help Switches shows how to list your configuration options with -help.) This distprompter script uses file descriptors 3-5. If you need to use those special [OVERHEAD] file descriptors inside distprompter (and that's not too likely), see the Table Environment Variables that MH Sets for an explanation of the MHFD and MHCONTEXTFD descriptors.
Outside the loop, the standard input of the commands is (by default) from your keyboard. But the loop is different because of the redirection at the done line (line 63 -- see below). Every command in the loop reads its standard input from the template draft file, not from your terminal. It "takes over" standard input during the loop. So, the read command at the top of the loop (line 32) reads the template draft file. But that means the read command inside the loop, on line 45, couldn't read from your terminal.
The answer is to connect any other files you want to read to their own file descriptors. Line 31 does that. Inside the loop, instead of reading its standard input, the read on line 45 reads file descriptor 4.
Before reconnecting to the saved file descriptor 4, there's one more thing the script needs to do. Line 43 saves the open draft file template as file descriptor 5. Because we don't close the file here (with exec 5<&-), the next read command at the top of the loop (line 32) will read the next line of the file. If we'd simply closed the template file and reopened it, the next read on line 32 would read the first line of the file instead of the correct line.
Next, line 44 changes file descriptor 0 to point to the original standard input before the loop -- it was saved as file descriptor 4 in line 31. Now, the read ans command on line 45 can read the original standard input and get your answer to the prompt. Line 46 rearranges descriptors for the rest of the loop -- it reconnects the draft template file from file descriptor 5 back to file descriptor 0. So, the next read at the top of the loop will read the template file.
Some shells can solve the problem on line 45 directly. They let you change what file descriptor the read command reads, instead of the default (file descriptor 0, the standard input). For instance, to read the value of the ans variable from file descriptor 4, line 45 could look like one of these:
read ans 0<&4 read -u4 ansBut some Bourne shells won't let you redirect the input of read on the same line.
That's why distprompter was written this way: the kind of redirection around line 45 works on all Bourne shells.
Now, about the loop: three file descriptors (fds) are redirected at line 63; these affect the input and output of every command inside the loop:
Any other command inside the loop that reads its standard input would read from this template file, too. That would be bad here, of course. See the explanation of lines 43-47, above.
The read in line 32 reads two shell variables. The first variable, label, always contains the first word on the line -- usually a field label like Resent-Fcc:. If the draft file has any other text (like the word outbox), that goes into the line variable.
The body of the loop is a big case structure. It tests the label and branches:
A simple read command won't read what you type at the prompt because the loop's standard input comes from the draft file. As you read at the start of this section, some shells' built-in read command will not let you redirect their standard input to another file descriptor. A workaround that should take care of all Bourne shells starts at line 43. It's explained in detail near the start of this section.
The case in lines 47-50 tests the response. The field is only printed to the new header if the user typed an answer.
This file is from the third edition of the book MH & xmh: Email for Users & Programmers, ISBN 1-56592-093-7, by Jerry Peek. It is freely available; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation. For more information, see COPYING.
Copyright © 1991, 1992, 1995 O'Reilly Media, Inc.
Copyright © 1996, 1997, 1999, 2000, 2002, 2004 Jerry Peek
Last modified: 2006-05-31 15:13:43 -0700