did-you-know? rent-now

Amazon no longer offers textbook rentals. We do!

did-you-know? rent-now

Amazon no longer offers textbook rentals. We do!

We're the #1 textbook rental company. Let us show you why.

9780201310184

Hands-On KornShell93 Programming

by
  • ISBN13:

    9780201310184

  • ISBN10:

    020131018X

  • Edition: 1st
  • Format: Paperback
  • Copyright: 1998-10-13
  • Publisher: Addison-Wesley Professional
  • Purchase Benefits
  • Free Shipping Icon Free Shipping On Orders Over $35!
    Your order must be $35 or more to qualify for free economy shipping. Bulk sales, PO's, Marketplace items, eBooks and apparel do not qualify for this offer.
  • eCampus.com Logo Get Rewarded for Ordering Your Textbooks! Enroll Now
List Price: $49.99

Summary

Preface

              . . . That No One Will Ever Read

Research indicates that virtually no one actually reads prefaces in computer books. In fact, this preface could be about the Loch Ness Monster for all most readers care.

But why don't people read prefaces? Is it because prefaces sometimes get too personal? (". . . and I want to thank Sal, who made this book possible.") Is it because the sentiments of nerdy authors can be a bit repulsive? (". . . Sal, my SparcStation, was always there when I needed her.") Is it because they are predictably self-deprecatory in an ironic way? (". . . and I want to thank: list of 250 noted experts goes here for reviewing drafts of this manual. Naturally all mistakes are my own.") No, when it comes right down to it, people avoid prefaces because they're boring.

It is also de rigueur for the nerdish author to explain, folksinger style, why he or she decided to write this piece. I guess this book sort of came to me while I was camping out in the glorious Rocky Mountains. I was gazing at pristine waterfalls and awe-inspiring sunsets when I said to myself, "This land must be preserved: I shall write a KornShell book." Possessed by a demonic ecological fervor, I roared down that mountain in a snowmobile, fired up a 1200-watt workstation, and wrote it all down for you. I only ask that you use the power of the KornShell for good, rather than evil.

Through the years, I've been lucky enough to get lots of feedback from my readers. What do you think they ask for? More text? No. More syntax? Definitely not. When it comes right down to it, readers consistently ask for only one thing: more examples.

So, I listened to them and based this tutorial entirely on examples. I feel that short, focused examples are more valuable than long, detailed examples, and I've written the book accordingly. The purpose of the book is not to make me look clever; it is to make you look clever. Nevertheless, I've sprinkled a few lengthy examples into the mix for those of you who enjoy that sort of thing.

When I was a mere lad, my family doctor pointed to a massive encyclopedia of pharmaceuticals and told me that he could treat 90 percent of all patients with only six different medicines. Similarly, although the KornShell is a very rich language, my goal is to focus on the common script ailments and to leave the beriberi treatment to specialists.

Beginners may be wondering, "Is this book too hard for me?" No, probably not. Programmers experienced in various languages, though not in the KornShell, are probably wondering, "Is this book too wimpy for me?" No, probably not. To help guide both kinds of readers through the book, I've marked certain sections as being more appropriate for one group or the other. Many beginners need an explanation of loops, while experienced programmers need to know how KornShell loops differ from loops in other languages.

Since the KornShell runs on all sorts of operating systems, I've tried to keep operating system dependencies to a bare minimum. Nevertheless, I do assume that readers are either working directly on the UNIX operating system or indirectly on UNIX through a package like U/WIN.

My three primary reviewers were KornShell gurus David Korn, Steve Sommars, and Glenn Fowler, all of whom gave fantastic and diplomatic criticism.

I also received important criticism and help from Tom Barstow, Dave Beckedorff, Bart Hanlon, Warren Johnson, Ed Johnston, Mark Keil, Mike Kong, Alice Lynch, Dave Penfield, Will Roaf, Frank Rubinsky, John Weiss, Daryl Winters, Teri Witham, and other people whose names I have no doubt forgotten to list. Eric Eldred and Quentin Sullivan found so many bugs in early drafts that, and I mean this as a compliment, they should have a brand of insecticide named after them.

Judy Tarutz is my long-suffering editor. In person, Judy is a kind, gentle soul with an outrageous sense of humor. Give her a red pen, though, and she turns into Conan the Barbarian. Her savage red pen cut a bloody swath through early drafts of this book. If we should chance to meet up one day, dear reader, I'll tell you all the "weak" jokes she made me take out.

I'd also like to thank the members of the Academy.

A consortium of great minds--those minds owned and operated by Ted Ricks, John Wait, Jack Danahy, and Steve Spice--led me to the KornShell and helped me define the material for this book.

Finally, I'd like to thank the person who really made this book possible: my wife and best friend, Marilyn.

Whoops, almost forgot. Naturally, all mistakes are my own.

Author's Note Regarding the ksh93 Edition

It has been a very long time since I wrote the ksh88 edition, entitled KornShell Programming Tutorial. I began to suspect as much when I noticed that of all the people acknowledged in this Preface, and I'm sure they were capital reviewer--intelligent, meticulous, helpful--the only familiar name was my wife's.

But how to resurrect a vanished book? All traces of the ksh88 edition had disappeared until 1997, when a fragment was found suspended in a piece of amber at a Chinese restaurant in Palo Alto. Working round the clock, scientists at Addison Wesley Longman were able to piece together most of the old book. When gaps were found, DNA sequences from Kernighan and Ritchie were substituted.

After reading KornShell Programming Tutorial, many readers asked me important questions such as, "How does a joke get to be in your book?" or "Couldn't you just write a preface next time and skip the rest of the stuff that came after it?" or "Did you hear the one about the traveling KornShell salesman and the system administrator's daughter?"

Actually, creating humor for this book is not as haphazard as it may seem. All jokes are put through a rigorous five-step Beta testing procedure. I need to ensure that a joke is just as funny on the tenth reading as it is on the first. Although not all Beta testers installed the jokes, I did get enough feedback to toss out a ridiculous amount of material, for example, the original start of Chapter 1 went like this:

I first saw David Korn writing shell scripts in a small club in the Village in 1946. The post-War euphoria was contagious and it wasn't long before the whole room was up and swaying to a pounding UNIX beat.

In a second edition, the author is obliged to correct the occasional error or two that cropped up in the first edition. (A special note to all of you at the Strategic Air Command--you're absolutely right guys, it was supposed to be a comma, not a semicolon.) A pair of translators, Hideyuki Hayashi and Masataka Isoya, get the credit for finding the most mistakes in the ksh88 edition. These two were incredibly rigorous and could not have been more diplomatic. ("Barry-San, every word on page 233 appears to be a typo.") Yep, the truth is out there, but a lot of it failed to work its way into the ksh88 edition. To improve accuracy, Sarah Tuttle wrote a validation suite that tests most of the sample KornShell scripts appearing in this book.

When I wrote the KornShell Programming Tutorial book, KornShell88 was beginning to make KornShell86 obsolete. As I go to press with this book, Hands-On KornShell93 Programming, KornShell93 is starting to overtake KornShell88. The KornShell93 scripts are far richer than KornShell88, and I've focused this book completely on KornShell93. If you liked KornShell88, you're going to love KornShell93.

Several reviewers strongly suggested a chapter on CGI programming with KornShell. As an avid CGI programmer, I happily agreed.

The CD accompanying this book contains the U/WIN p

Author Biography

Barry Rosenberg is an independent technical writer and a software instructor for Technology Exchange Company. He is the author of more than 30 programming manuals, including Addison-Wesleyis Client/Server Computing for Technical Professionals: Concepts and Solutions and KornShell Programming Tutorial.

020131018XAB04062001

Table of Contents

List of Tables
xix(2)
List of Figures
xxi(2)
Preface... That No One Will Ever Read xxiii
Author's Note Regarding the ksh93 Edition xxiv
1 Before Writing Your First KornShell Scripts
1(4)
2 Getting Started
5(20)
What Shell Is Executing My Script?
6(2)
Operating System Commands in a Shell Script
8(1)
BEWARE: Are You Allowed to Execute This Script?
9(1)
Commenting Your Code
10(1)
BEWARE: Picking a Bad Name for Your Script
11(1)
The Usage Line
12(1)
Simple Output
13(1)
Variables
14(1)
BEWARE: Variable Names Are Case Sensitive
14(1)
Simple Input
15(1)
Obtaining the Value of a Variable
16(1)
BEWARE: The Dollar Sign in read Statements
16(1)
Newlines, Semicolons, White Space, and Columns
17(1)
BEWARE: Confusing + and -
17(1)
Assigning a Value to a Variable
18(1)
BEWARE: Common Mistakes When Assigning Variables
19(1)
Finding Your Mistakes
20(1)
Can I Quote You on That?
21(4)
3 Data Types
25(18)
If You're New to Programming
25(1)
If You're an Experienced Programmer
26(2)
Declaring Strings
28(1)
Declaring Integers
29(1)
Binary, Octal, Hex, and So On
30(1)
Declaring Floats
31(1)
Declaring Constants
32(1)
Declaring nameref Variables
33(1)
Declaring Arrays
34(1)
Declaring Arrays with set -A
35(1)
Printing Array Values
36(1)
BEWARE: Common Array Mistakes
37(1)
Declaring Associative Arrays
38(1)
Probing Arrays
39(1)
Declaring Structures Part I
40(1)
Declaring Structures Part II
41(1)
Arrays of Structures
42(1)
4 Math
43(14)
If You're New to Programming
43(1)
If You're an Experienced Programmer
43(1)
Double Parentheses
44(1)
Integer Addition, Subtraction, and Multiplication
45(1)
Integer Division
46(1)
Floating-Point Math
47(1)
Mixing Floating-Point and Integer Math
48(1)
Grouping Mathematical Operations
49(1)
BEWARE: Common Mistakes in Math Operations
50(1)
Mathematical Assignment Operators
51(1)
The Triggy Stuff
52(1)
BEWARE: Math Functions Inside Double Parentheses
52(1)
A Practical Math Example
53(1)
Math Operator Summary
54(3)
5 Pattern Matching
57(16)
If You're New to Programming
57(1)
If You're an Experienced Programmer
57(1)
For Everyone
58(1)
The ? Wildcard
59(1)
The [char1char2...charN] Wildcard
60(1)
Character Classes
61(1)
The * Wildcard
62(1)
BEWARE: Matching Filenames
62(1)
The ?(pattern1/pattern2... /patternN) Wildcard
63(1)
BEWARE: White Space Within Patterns
63(1)
The @(pattern1/pattern2... /patternN) Wildcard
64(1)
The *(pattern1/pattern2... /patternN) Wildcard
65(1)
The +(pattern1/pattern2... /patternN) Wildcard
66(1)
The !(subpattern1/subpattern2... /subpatternN) Wildcard
67(1)
Matching Subpatterns with \d
68(1)
Simple Commands Containing Patterns
69(1)
Wildcard Summary
70(3)
6 Conditions
73(30)
If You're New to Programming
73(1)
If You're an Experienced Programmer
73(2)
Tests on Numbers and Strings
75(2)
Comparing Numbers with if
77(1)
BEWARE: Common Mistakes Using if with Numbers
78(1)
Comparing Numbers with the ? : Operator
79(1)
BEWARE: Common Mistakes in ?
79(1)
Compound Statements
80(1)
else and elif
81(1)
Comparing Strings with if
82(1)
Comparing Alphabetical Order with [and]
83(1)
Comparing a String to a Pattern with if
84(1)
BEWARE: Common Mistakes Comparing Strings
85(1)
Boolean AND, Boolean OR
86(1)
The case Statement
87(1)
Unexpected Values in a case Statement
88(1)
Wildcards in a case Statement
89(1)
Multiple Patterns in a case Statement
90(1)
BEWARE: Common Mistakes in case
91(1)
Tests on Files, Directories, and the Like
92(1)
BEWARE: No Filename Expansion Inside [[ ]]
92(1)
What Kind of Object Is This?
93(2)
Boolean NOT
95(1)
How Is This Object Protected?
96(2)
Comparing the Time of Last Modification
98(1)
Mixing Tests
99(4)
7 Loops
103(24)
If You're New to Programming
103(1)
If You're an Experienced Programmer
104(1)
Simple while, until, and for Loops
105(2)
Using while to Average Five Floats
107(1)
BEWARE: while Loop Not Guaranteed to Iterate
107(1)
Using a C-Style for Loop to Average Five Floats
108(1)
Using break to Leave a Loop
109(1)
Using continue to Skip Part of One Loop Iteration
110(1)
Using: to Create an Always True Loop
111(1)
BEWARE: The Nature of Truth
112(1)
Lists in for Loops
113(1)
A List of Filenames in a for Loop
114(1)
Patterns in a for Loop
115(2)
Searching for Objects in Subdirectories
117(2)
BEWARE: Nonexistent Patterns
119(1)
A Loop Within a Loop
120(1)
The break Statement Within a Nested Loop
121(6)
8 Creating Menus
127(14)
A Simple select Example
128(1)
A select with a case
129(1)
Unexpected User Input
130(1)
Gracefully Exiting from Menus
131(1)
Repeating the Menu Selections
132(1)
Wildcards in Menu Entries
133(1)
Wildcards in case Statements
134(1)
A Practical select Example
135(1)
Menus Inside of Menus (Submenus)
136(5)
9 Command Line Arguments and Positional Parameters
141(22)
If You're New to Programming
141(1)
If You're an Experienced Programmer
142(1)
Command Line Arguments
143(1)
Counting the Number of Command Line Arguments
144(1)
Giving the User a Choice of How to Enter Arguments
145(1)
BEWARE: Can't Put Positional Parameters to Left of =
145(1)
Default Values of Positional Parameters
146(1)
Processing Positional Parameters with shift
147(1)
Processing Positional Parameters with $* and $@
148(1)
"$*" Versus "$@" Part 1
149(1)
"$*" Versus "$@" Part 2
150(1)
Using the set Statement to Assign Positional Parameters
151(1)
Processing Simple Switches with getopts
152(1)
What If the User Enters an Invalid Switch?
153(1)
On and Off Switches
154(1)
Processing Switch Arguments
155(1)
Processing Missing Switch Arguments
156(1)
A Command Line Containing More Than Just Switches
157(1)
BEWARE: The Colon of getopts
158(1)
Positional Parameters Syntax Overview
159(4)
10 Functions
163(34)
If You're New to Programming
163(1)
If You're an Experienced Programmer
164(1)
BEWARE: Two Kinds of Functions
164(1)
A Disorganized Script Without Functions
165(1)
The Same Script Organized into Functions
166(1)
Simple Function with One Argument
167(1)
BEWARE: When $1 Isn't the First Command Line Argument
168(1)
A Function with Multiple Arguments
169(1)
A Script That Calls Another Script
170(1)
Two Ways to Return Values
171(1)
Returning a Value from a Function with return
172(1)
BEWARE: $? Doesn't Stick Around Long
173(1)
Using $(...) to Return Values from a Function
174(1)
Local Variables Versus Global Variables
175(1)
BEWARE: Global and Local Variables with the Same Name
176(1)
Passing Arrays as Function Arguments: Call-by-Reference
177(1)
Sorting Arrays Using Call-by-Value
178(2)
Discipline Functions Overview
180(1)
Using a.set Discipline Function to Monitor a Variable
181(1)
BEWARE: Data Type Declarations and Discipline Functions
181(1)
Using a.set Discipline Function to Constrain a Value
182(1)
Recursive Functions
183(2)
Autoloaded Functions
185(1)
BEWARE: Tricky Loading Rules
186(1)
Extending the KornShell by Writing C Functions
187(4)
Practical Example: The Game of moo
191(6)
11 Start-Up Scripts and Environments
197(12)
Start-Up Scripts
197(1)
Environments
198(5)
Dot Scripts
203(1)
Aliases
204(2)
Example of a $HOME/.profile Start-Up Script
206(1)
Example of an Environment (ENV) Script
207(2)
12 Input and Output
209(46)
If You're New to Programming
209(1)
If You're an Experienced Programmer
210(1)
read, REPLY, and Prompts
211(1)
Reading Three Values
212(1)
Ignoring Extraneous Input
213(1)
Reading Values Having Different Data Types
214(1)
Rushing Users to Supply Input
215(1)
The IFS Variable
216(1)
Input Longer Than One Line
217(1)
BEWARE: Put Nothing After the Backslash
217(1)
Using a Loop to Process Input
218(1)
Reading Text out of a File with less than
219(1)
Putting less than Within a Statement
220(1)
BEWARE: Common Input Mistakes
221(1)
Up Close and Personal with the print Statement
222(1)
BEWARE: Bad Options in print Statement
222(1)
BEWARE: Wildcards Within Strings
223(1)
Getting Fancy Output with the printf Statement
224(1)
BEWARE: print and printf Handle Newlines Differently
225(2)
Redirecting Standard Output with greater than
227(1)
BEWARE: "But It Was Right There a Second Ago!"
228(1)
Appending with greater greater than
229(1)
Mixing [and]
230(1)
Pipes
231(1)
Streams
232(2)
Redirecting Standard Error
234(2)
BEWARE: Redirecting Standard Output and Standard Error to Same File
236(1)
Opening Files with exec
237(1)
Using exec to Do I/O on Multiple Files
238(2)
Closing Streams
240(1)
Using $(...) to Assign the Output of a Command to a Variable
241(2)
Here Documents
243(12)
13 Manipulating Strings
255(28)
If You're New to Programming
255(1)
If You're an Experienced Programmer
255(1)
Uppercase and Lowercase
256(1)
Left Justification
257(2)
Concatenating Strings
259(1)
Reading an Entire File into One String Variable
260(1)
Search and Replace Overview
261(1)
Search and Replace Practical Example
262(1)
Isolating a Portion of a String
263(1)
Removing the Leftmost Characters in a String with #
264(1)
Removing the Rightmost Characters in a String with %
265(1)
An Application of %
266(1)
# Versus ##
267(1)
% Versus %%
268(1)
Using # on Numbers
269(1)
Deleting a Substring from the Middle of a String
270(1)
Pruning Branches from Pathnames
271(1)
Matching Multiple Strings on the Same Line
272(1)
Finding the Length of a String
273(1)
Parsing Strings into Words
274(2)
Parsing Strings into Characters
276(1)
Specifying Default Values
277(2)
Parsing PATH
279(1)
Practical Application: Extracting Comments From C Source Code
280(2)
String Manipulation Summary
282(1)
14 KornShell Reserved Variables
283(26)
If You're New to Programming
283(1)
If You're an Experienced Programmer
283(3)
.sh.edchar, .sh.edcol, .sh.edmode, .sh.edtext
286(1)
.sh.name, .sh.subscript, and .sh.value
287(1)
.sh.version
287(1)
ENV
287(1)
FIGNORE
288(1)
$? -- Error Status
288(1)
HISTFILE, HISTSIZE, HISTEDIT, HISTCMD, and FCEDIT -- History File
288(1)
IFS -- Parsing Lines into Tokens
289(2)
LANG, LC_ALL, LC_COLLATE, LC_TYPE, and LC_NUMERIC
291(1)
LINENO -- Current Line Number
292(1)
MAIL, MAILPATH, and MAILCHECK -- Electronic Mail
293(1)
OPTARG and OPTIND -- Values Associated with getopts
293(1)
PATH, CDPATH, and FPATH -- Search Directories
294(2)
PS1, PS2, PS3, and PS4 -- Prompts
296(2)
BEWARE: Common Mistakes in Setting Prompts
298(1)
HOME, PWD, and OLDPWD -- Login, Current, and Previous Directories
299(1)
RANDOM -- Random Integer Generator
300(2)
REPLY, -, and _-- Miscellaneous Input Repository
302(1)
SECONDS--Elapsed Time
303(1)
SHELL
304(1)
TERM, COLUMN, LINES--Terminal Characteristics
305(1)
TMOUT--Time Out an Unused KornShell
305(1)
VISUAL and EDITOR--Command Line Text Editors
306(1)
$$, $!, and PPID--Process ID
307(2)
15 Foreground, Background, and Signaling
309(16)
Background and Foreground
309(3)
Signaling
312(1)
How to Send a Signal to a Script
313(1)
Writing Scripts That Respond to Signals
314(1)
Catching Signals
315(1)
A Trap That Calls Another Script
316(2)
Trapping Whenever a Script Exits
318(1)
Trapping Whenever Error Status Becomes Nonzero
319(1)
Writing Your Own Debugger
320(1)
Trapping KEYBD Signals
321(4)
16 Command Line Editing and the History File
325(10)
What Is Command Line Editing?
325(1)
What Is a History File?
325(1)
Listing Previous Commands
326(1)
Re-Executing Previous Commands
327(1)
BEWARE: Can't Use r on Multiple Commands
327(1)
Editing Previous Commands, Then Executing Them
328(1)
The Thing You're Going to Do Anyway
329(1)
Pathname Completion
330(1)
Command Completion
331(4)
17 Writing CGI Scripts
335(34)
If You're New to CGI Programming
335(3)
If You're an Experienced CGI Programmer
338(1)
Forms
339(1)
Text Boxes and Password Boxes
340(2)
Checkboxes
342(1)
Radio Buttons
343(1)
Getting Started Writing CGI Programs
344(2)
BEWARE: If Your CGI Script Doesn't Work
346(1)
A CGI Script Containing More Than Just print Statements
347(1)
File I/O from CGI Scripts
348(1)
BEWARE: File Permissions
349(1)
Analyzing Form Input: The Get and Post Methods
350(1)
The Get Method
351(3)
Get Method: Multiple Input Values
354(3)
The Post Method
357(3)
Handling Special Characters
360(3)
Environment Variables Passed by the Web Server
363(2)
Browserless Browsing
365(2)
BEWARE: Moral Concerns
367(1)
Browserless Browsing for GIFs
368(1)
BEWARE: When Browserless Browsing Fails
368(1)
Appendixes 369(48)
A Statement and Alias Quick Reference 369(38)
B Just Enough HTML 407(10)
Essential HTML Tags 408(2)
Headings 410(2)
Lists 412(1)
Character Tags 413(1)
Hyperlinks 414(2)
Images 416(1)
Bibliography 417(2)
Index 419

Supplemental Materials

What is included with this book?

The New copy of this book will include any supplemental materials advertised. Please check the title of the book to determine if it should include any access cards, study guides, lab manuals, CDs, etc.

The Used, Rental and eBook copies of this book are not guaranteed to include any supplemental materials. Typically, only the book itself is included. This is true even if the title states it includes any access cards, study guides, lab manuals, CDs, etc.

Excerpts

Preface . . . That No One Will Ever ReadResearch indicates that virtually no one actually reads prefaces in computer books. In fact, this preface could be about the Loch Ness Monster for all most readers care.But why don't people read prefaces? Is it because prefaces sometimes get too personal? (". . . and I want to thank Sal, who made this book possible.") Is it because the sentiments of nerdy authors can be a bit repulsive? (". . . Sal, my SparcStation, was always there when I needed her.") Is it because they are predictably self-deprecatory in an ironic way? (". . . and I want to thank: list of 250 noted experts goes here for reviewing drafts of this manual. Naturally all mistakes are my own.") No, when it comes right down to it, people avoid prefaces because they're boring.It is alsode rigueurfor the nerdish author to explain, folksinger style, why he or she decided to write this piece. I guess this book sort of came to me while I was camping out in the glorious Rocky Mountains. I was gazing at pristine waterfalls and awe-inspiring sunsets when I said to myself, "This land must be preserved: I shall write a KornShell book." Possessed by a demonic ecological fervor, I roared down that mountain in a snowmobile, fired up a 1200-watt workstation, and wrote it all down for you. I only ask that you use the power of the KornShell for good, rather than evil.Through the years, I've been lucky enough to get lots of feedback from my readers. What do you think they ask for? More text? No. More syntax? Definitely not. When it comes right down to it, readers consistently ask for only one thing: moreexamples.So, I listened to them and based this tutorial entirely on examples. I feel that short, focused examples are more valuable than long, detailed examples, and I've written the book accordingly. The purpose of the book is not to make me look clever; it is to make you look clever. Nevertheless, I've sprinkled a few lengthy examples into the mix for those of you who enjoy that sort of thing.When I was a mere lad, my family doctor pointed to a massive encyclopedia of pharmaceuticals and told me that he could treat 90 percent of all patients with only six different medicines. Similarly, although the KornShell is a very rich language, my goal is to focus on the common script ailments and to leave the beriberi treatment to specialists.Beginners may be wondering, "Is this book too hard for me?" No, probably not. Programmers experienced in various languages, though not in the KornShell, are probably wondering, "Is this book too wimpy for me?" No, probably not. To help guide both kinds of readers through the book, I've marked certain sections as being more appropriate for one group or the other. Many beginners need an explanation of loops, while experienced programmers need to know how KornShell loops differ from loops in other languages.Since the KornShell runs on all sorts of operating systems, I've tried to keep operating system dependencies to a bare minimum. Nevertheless, I do assume that readers are either working directly on the UNIX operating system or indirectly on UNIX through a package like U/WIN.My three primary reviewers were KornShell gurus David Korn, Steve Sommars, and Glenn Fowler, all of whom gave fantastic and diplomatic criticism.I also received important criticism and help from Tom Barstow, Dave Beckedorff, Bart Hanlon, Warren Johnson, Ed Johnston, Mark Keil, Mike Kong, Alice Lynch, Dave Penfield, Will Roaf, Frank Rubinsky, John Weiss, Daryl Winters, Teri Witham, and other people whose names I have no doubt forgotten to list. Eric Eldred and Quentin Sullivan found so many bugs in early drafts that, and I mean this as a compliment, they should have a brand of insecticide named after them.Judy Tarutz is my long-suffering editor

Rewards Program