12.10. Coprocesses
A coprocess is a special two-way pipeline that allows shell scripts to write to the standard input of another command and to read from its standard output. This provides a way to create a new interface for an existing program. The append operator, |&, is placed at the end of the command to initiate the command as a coprocess. Normal redirection and background processing should not be used on coprocesses. The print and read commands require a –p switch to read from and write to a coprocess. The output must be sent to standard output and have a newline at the end of each message of output. The standard output must be flushed after each message is sent to standard output. You can run multiple coprocesses by using the exec command with the >&p or <&p operator. To open file descriptor 4 as a coprocess, you would enter exec 4>&p.
Example 12.65.
(The Script)
#!/bin/ksh
# Scriptname: mycalculator
# A simple calculator –– uses the bc command to perform the calculations
# Because the shell performs operations on integers only, this program allows
# you to use floating-point numbers by writing to and reading from the bcprogram.
1 cat << EOF
**************************************************
2 WELCOME TO THE CALCULATOR PROGRAM
*************************************************
3 EOF
4 bc |& # Open coprocess
5 while true
do
6 print "Select the letter for one of the operators below "
7 cat <<- EOF
a) +
s) –
m) *
d) /
e) ^
EOF
8 read op
9 case $op in
a) op="+";;
s) op="–";;
m) op="*";;
d) op="/";;
e) op="^";;
*) print "Bad operator"
continue;;
esac
10 print –p scale=3 # write to the coprocess
11 print "Please enter two numbers: " # write to standard out
12 read num1 num2 # read from standard in
13 print –p "$num1" "$op" "$num2" # write to the coprocess
14 read –p result # read from the coprocess
15 print $result
16 print –n "Continue (y/n)? "
17 read answer
18 case $answer in
[Nn]* )
19 break;;
esac
20 done
21 print Good–bye
(The Output)
$ mycalculator
**************************************************
1 WELCOME TO THE CALCULATOR PROGRAM
*************************************************
6 Select one of the operators below
7 a) +
s) –
m) *
d) /
e) ^
e
11 Please enter two numbers:
2.3 4
27.984
16 Continue (y/n)? y
6 Select one of the operators below
7 a) +
s) –
m) *
d) /
e) ^
d
11 Please enter two numbers:
2.1 4.6
0.456
16 Continue (y/n)? y
6 Select one of the operators below
7 a) +
s) –
m) *
d) /
e) ^
m
11 Please enter two numbers:
4 5
20
16 Continue (y/n)? n
21 Good–bye
EXPLANATION
The here document is used to display a title banner. This text is printed as a header to the menu below. EOF is a user-defined terminator, marking the end of the here document. The bc command (desk calculator) is opened as a coprocess. It is executed in the background. A while loop is started. Because the true command always returns a successful exit status of 0, the loop will continue indefinitely until a break or exit is reached. The user is prompted to select an item from a menu to be displayed. Another here document displays a list of math operations the user can choose for the bc program. The read command assigns user input to the variable op. The case command matches for one of the op values and assigns an operator to op. The print command with the –p option pipes output (scale=3) to the coprocess, the bc command. The bc command accepts the print output as input and sets the scale to 3. (The scale defines the number of significant digits to the right of the decimal point in a number that will be displayed by bc.) The user is prompted to enter two numbers. The read command assigns user input to the variables num1 and num2. The print –p command sends the arithmetic expression to the bc coprocess. The shell reads from the bc coprocess (read –p) and assigns the input to the variable result. The result of the calculation ($result) is printed. The user is asked about continuing. The user enters input. It is assigned to the variable answer. The case command evaluates the variable answer. If the user had entered No or no or nope, and so on, the break command would be executed, and the while loop would be terminated with control sent to line 21. The done keyword marks the end of the while loop. This line is printed when the loop terminates.
|