xref: /plan9/sys/doc/rc.ms (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1.	\" /*% refer -k -e -n -l3,2 -s < % | tbl | troff -ms | lp -dfn
2.Tm shell programming language	g
3.de TP	\" An indented paragraph describing some command, tagged with the command name
4.IP "\\f(CW\\$1\\fR" 5
5.if \\w'\\f(CW\\$1\\fR'-4n .br
6..
7.de CI
8.nr Sf \\n(.f
9\%\&\\$3\f(CW\\$1\fI\&\\$2\f\\n(Sf
10..
11.TL
12Rc \(em The Plan 9 Shell
13.AU
14Tom Duff
15td@plan9.att.com
16.AB
17.I Rc
18is a command interpreter for Plan 9 that
19provides similar facilities to UNIX's
20Bourne shell,
21with some small additions and less idiosyncratic syntax.
22This paper uses numerous examples to describe
23.I rc 's
24features, and contrasts
25.I rc
26with the Bourne shell, a model that many readers will be familiar with.
27.AE
28.NH
29Introduction
30.PP
31.I Rc
32is similar in spirit but different in detail from UNIX's
33Bourne shell.  This paper describes
34.I rc 's
35principal features with many small examples and a few larger ones.
36It assumes familiarity with the Bourne shell.
37.NH
38Simple commands
39.PP
40For the simplest uses
41.I rc
42has syntax familiar to Bourne-shell users.
43All of the following behave as expected:
44.P1
45date
46cat /lib/news/build
47who >user.names
48who >>user.names
49wc <file
50echo [a-f]*.c
51who | wc
52who; date
53vc *.c &
54mk && v.out /*/bin/fb/*
55rm -r junk || echo rm failed!
56.P2
57.NH
58Quotation
59.PP
60An argument that contains a space or one of
61.I rc 's
62other syntax characters must be enclosed in apostrophes
63.CW ' ): (
64.P1
65rm 'odd file name'
66.P2
67An apostrophe in a quoted argument must be doubled:
68.P1
69echo 'How''s your father?'
70.P2
71.NH
72Patterns
73.PP
74An unquoted argument that contains any of the characters
75.CW *
76.CW ?
77.CW [
78is a pattern to be matched against file names.
79A
80.CW *
81character matches any sequence of characters,
82.CW ?
83matches any single character, and
84.CW [\fIclass\fP]
85matches any character in the
86.CW class ,
87unless the first character of
88.I class
89is
90.CW ~ ,
91in which case the class is complemented.
92The
93.I class
94may also contain pairs of characters separated by
95.CW - ,
96standing for all characters lexically between the two.
97The character
98.CW /
99must appear explicitly in a pattern, as must the path name components
100.CW .
101and
102.CW .. .
103A pattern is replaced by a list of arguments, one for each path name matched,
104except that a pattern matching no names is not replaced by the empty list;
105rather it stands for itself.
106.NH
107Variables
108.PP
109UNIX's Bourne shell offers string-valued variables.
110.I Rc
111provides variables whose values are lists of arguments \(em
112that is, arrays of strings.  This is the principal difference
113between
114.I rc
115and traditional UNIX command interpreters.
116Variables may be given values by typing, for example:
117.P1
118path=(. /bin)
119user=td
120font=/lib/font/bit/pelm/ascii.9.font
121.P2
122The parentheses indicate that the value assigned to
123.CW path
124is a list of two strings. The variables
125.CW user
126and
127.CW font
128are assigned lists containing a single string.
129.PP
130The value of a variable can be substituted into a command by
131preceding its name with a
132.CW $ ,
133like this:
134.P1
135echo $path
136.P2
137If
138.CW path
139had been set as above, this would be equivalent to
140.P1
141echo . /bin
142.P2
143Variables may be subscripted by numbers or lists of numbers,
144like this:
145.P1
146echo $path(2)
147echo $path(2 1 2)
148.P2
149These are equivalent to
150.P1
151echo /bin
152echo /bin . /bin
153.P2
154There can be no space separating the variable's name from the
155left parenthesis; otherwise, the subscript would be considered
156a separate parenthesized list.
157.PP
158The number of strings in a variable can be determined by the
159.CW $#
160operator.  For example,
161.P1
162echo $#path
163.P2
164would print 2 for this example.
165.PP
166The following two assignments are subtly different:
167.P1
168empty=()
169null=''
170.P2
171The first sets
172.CW empty
173to a list containing no strings.
174The second sets
175.CW null
176to a list containing a single string,
177but the string contains no characters.
178.PP
179Although these may seem like more or less
180the same thing (in Bourne's shell, they are
181indistinguishable), they behave differently
182in almost all circumstances.
183Among other things
184.P1
185echo $#empty
186.P2
187prints 0, whereas
188.P1
189echo $#null
190.P2
191prints 1.
192.PP
193All variables that have never been set have the value
194.CW () .
195.PP
196Occasionally, it is convenient to treat a variable's value
197as a single string.  The elements of a string are concatenated
198into a single string, with spaces between the elements, by
199the
200.CW $"
201operator.
202Thus, if we set
203.P1
204list=(How now brown cow)
205string=$"list
206.P2
207then both
208.P1
209echo $list
210.P2
211and
212.P1
213echo $string
214.P2
215cause the same output, viz:
216.P1
217How now brown cow
218.P2
219but
220.P1
221echo $#list $#string
222.P2
223will output
224.P1
2254 1
226.P2
227because
228.CW $list
229has four members, but
230.CW $string
231has a single member, with three spaces separating its words.
232.NH
233Arguments
234.PP
235When
236.I rc
237is reading its input from a file, the file has access
238to the arguments supplied on
239.I rc 's
240command line.  The variable
241.CW $*
242initially has the list of arguments assigned to it.
243The names
244.CW $1 ,
245.CW $2 ,
246etc. are synonyms for
247.CW $*(1) ,
248.CW $*(2) ,
249etc.
250In addition,
251.CW $0
252is the name of the file from which
253.I rc 's
254input is being read.
255.NH
256Concatenation
257.PP
258.I Rc
259has a string concatenation operator, the caret
260.CW ^ ,
261to build arguments out of pieces.
262.P1
263echo hully^gully
264.P2
265is exactly equivalent to
266.P1
267echo hullygully
268.P2
269Suppose variable
270.CW i
271contains the name of a command.
272Then
273.P1
274vc $i^.c
275vl -o $1 $i^.v
276.P2
277might compile the command's source code, leaving the
278result in the appropriate file.
279.PP
280Concatenation distributes over lists. The following
281.P1
282echo (a b c)^(1 2 3)
283src=(main subr io)
284cc $src^.c
285.P2
286are equivalent to
287.P1
288echo a1 b2 c3
289cc main.c subr.c io.c
290.P2
291In detail, the rule is: if both operands of
292.CW ^
293are lists of the same non-zero number of strings, they are concatenated
294pairwise.  Otherwise, if one of the operands is a single string,
295it is concatenated with each member of the other operand in turn.
296Any other combination of operands is an error.
297.NH
298Free carets
299.PP
300User demand has dictated that
301.I rc
302insert carets in certain places, to make the syntax
303look more like the Bourne shell.  For example, this:
304.P1
305cc -$flags $stems.c
306.P2
307is equivalent to
308.P1
309cc -^$flags $stems^.c
310.P2
311In general,
312.I rc
313will insert
314.CW ^
315between two arguments that are not separated by white space.
316Specifically, whenever one of
317.CW "$'`
318follows a quoted or unquoted word, or an unquoted word follows
319a quoted word with no intervening blanks or tabs, an implicit
320.CW ^
321is inserted between the two.  If an unquoted word immediately following a
322.CW $
323contains a character other than an alphanumeric, underscore or
324.CW * ,
325a
326.CW ^
327is inserted before the first such character.
328.NH
329Command substitution
330.PP
331It is often useful to build an argument list from the output of a command.
332.I Rc
333allows a command, enclosed in braces and preceded by a left quote,
334.CW "`{...}" ,
335anywhere that an argument is required.  The command is executed and its
336standard output captured.
337The characters stored in the variable
338.CW ifs
339are used to split the output into arguments.
340For example,
341.P1
342cat `{ls -tr|sed 10q}
343.P2
344will concatenate the ten oldest files in the current directory in temporal order, given the
345default
346.CW ifs
347setting of space, tab, and newline.
348.NH
349Pipeline branching
350.PP
351The normal pipeline notation is general enough for almost all cases.
352Very occasionally it is useful to have pipelines that are not linear.
353Pipeline topologies more general than trees can require arbitrarily large pipe buffers,
354or worse, can cause deadlock.
355.I Rc
356has syntax for some kinds of non-linear but treelike pipelines.
357For example,
358.P1
359	cmp <{old} <{new}
360.P2
361will regression-test a new version of a command.
362.CW <
363or
364.CW >
365followed by a command in braces causes the command to be run with
366its standard output or input attached to a pipe.  The parent command
367.CW cmp "" (
368in the example)
369is started with the other end of the pipe attached to some file descriptor
370or other, and with an argument that will connect to the pipe when opened
371(e.g.,
372.CW /dev/fd/6 ).
373Some commands are unprepared to deal with input files that turn out not to be seekable.
374For example
375.CW diff
376needs to read its input twice.
377.NH
378Exit status
379.PP
380When a command exits it returns status to the program that executed it.
381On Plan 9 status is a character string describing an error condition.
382On normal termination it is empty.
383.PP
384.I Rc
385captures command exit status in the variable
386.CW $status .
387For a simple command the value of
388.CW $status
389is just as described above.  For a pipeline
390.CW $status
391is set to the concatenation of the statuses of the pipeline components with
392.CW |
393characters for separators.
394.PP
395.I Rc
396has a several kinds of control flow,
397many of them conditioned by the status returned from previously
398executed commands.  Any
399.CW $status
400containing only
401.CW 0 's
402and
403.CW | 's
404has boolean value
405.I true .
406Any other status is
407.I false .
408.NH
409Command grouping
410.PP
411A sequence of commands enclosed in
412.CW {}
413may be used anywhere a command is required.
414For example:
415.P1
416{sleep 3600;echo 'Time''s up!'}&
417.P2
418will wait an hour in the background, then print a message.
419Without the braces,
420.P1
421sleep 3600;echo 'Time''s up!'&
422.P2
423would lock up the terminal for an hour,
424then print the message in the background.
425.NH
426Control flow \(em \f(CWfor\fP
427.PP
428A command may be executed once for each member of a list
429by typing, for example:
430.P1
431for(i in printf scanf putchar) look $i /usr/td/lib/dw.dat
432.P2
433This looks for each of the words
434.CW printf ,
435.CW scanf
436and
437.CW putchar
438in the given file.
439The general form is
440.P1
441for(\fIname\fP in \fIlist\fP) \fIcommand\fP
442.P2
443or
444.P1
445for(\fIname\fP) \fIcommand\fP
446.P2
447In the first case
448.I command
449is executed once for each member of
450.I list
451with that member assigned to variable
452.I name .
453If the clause
454.CW in "" ``
455.I list ''
456is missing,
457.CW in "" ``
458.CW $* ''
459is assumed.
460.NH
461Conditional execution \(em \f(CWif\fP
462.PP
463.I Rc
464also provides a general if-statement.  For example:
465.P1
466for(i in *.c) if(cpp $i >/tmp/$i) vc /tmp/$i
467.P2
468runs the C compiler on each C source program that
469cpp processes without error.
470An `if not' statement provides a two-tailed conditional.
471For example:
472.P1
473for(i){
474    if(test -f /tmp/$i) echo $i already in /tmp
475    if not cp $i /tmp
476}
477.P2
478This loops over each file in
479.CW $* ,
480copying to
481.CW /tmp
482those that do not already appear there, and
483printing a message for those that do.
484.NH
485Control flow \(em \f(CWwhile\fP
486.PP
487.I Rc 's
488while statement looks like this:
489.P1
490while(newer subr.v subr.c) sleep 5
491.P2
492This waits until
493.CW subr.v
494is newer than
495.CW subr.c ,
496presumably because the C compiler finished with it.
497.PP
498If the controlling command is empty, the loop will not terminate.
499Thus,
500.P1
501while() echo y
502.P2
503emulates the
504.I yes
505command.
506.NH
507Control flow \(em \f(CWswitch\fP
508.PP
509.I Rc
510provides a switch statement to do pattern-matching on
511arbitrary strings.  Its general form is
512.P1
513switch(\fIword\fP){
514case \fIpattern ...\fP
515    \fIcommands\fP
516case \fIpattern ...\fP
517    \fIcommands\fP
518\&...
519}
520.P2
521.I Rc
522attempts to match the word against the patterns in each case statement in turn.
523Patterns are the same as for filename matching, except that
524.CW /
525and
526.CW .
527and
528.CW ..
529need not be matched explicitly.
530.PP
531If any pattern matches, the
532commands following that case up to
533the next case (or the end of the switch)
534are executed, and execution of the switch
535is complete.  For example,
536.P1
537switch($#*){
538case 1
539    cat >>$1
540case 2
541    cat >>$2 <$1
542case *
543    echo 'Usage: append [from] to'
544}
545.P2
546is an append command.  Called with one file argument,
547it appends its standard input to the named file.  With two, the
548first is appended to the second.  Any other number
549elicits an error message.
550.PP
551The built-in
552.CW ~
553command also matches patterns, and is often more concise than a switch.
554Its arguments are a string and a list of patterns.  It sets
555.CW $status
556to true if and only if any of the patterns matches the string.
557The following example processes option arguments for the
558.I man (1)
559command:
560.P1
561opt=()
562while(~ $1 -* [1-9] 10){
563    switch($1){
564    case [1-9] 10
565        sec=$1 secn=$1
566    case -f
567        c=f s=f
568    case -[qwnt]
569        cmd=$1
570    case -T*
571        T=$1
572    case -*
573        opt=($opt $1)
574    }
575    shift
576}
577.P2
578.NH
579Functions
580.PP
581Functions may be defined by typing
582.P1
583fn \fIname\fP { \fIcommands\fP }
584.P2
585Subsequently, whenever a command named
586.I name
587is encountered, the remainder of the command's
588argument list will assigned to
589.CW $*
590and
591.I rc
592will execute the
593.I commands .
594The value of
595.CW $*
596will be restored on completion.
597For example:
598.P1
599fn g {
600    grep $1 *.[hcyl]
601}
602.P2
603defines
604.CI g " pattern
605to look for occurrences of
606.I pattern
607in all program source files in the current directory.
608.PP
609Function definitions are deleted by writing
610.P1
611fn \fIname\fP
612.P2
613with no function body.
614.NH
615Command execution
616.PP
617.I Rc
618does one of several things to execute a simple command.
619If the command name is the name of a function defined using
620.CW fn ,
621the function is executed.
622Otherwise, if it is the name of a built-in command, the
623built-in is executed directly by
624.I rc .
625Otherwise, directories mentioned in the variable
626.CW $path
627are searched until an executable file is found.
628Extensive use of the
629.CW $path
630variable is discouraged in Plan 9.  Instead, use the default
631.CW (.
632.CW /bin)
633and bind what you need into
634.CW /bin .
635.NH
636Built-in commands
637.PP
638Several commands are executed internally by
639.I rc
640because they are difficult to implement otherwise.
641.TP ". [-i] \fIfile ...\f(CW
642Execute commands from
643.I file .
644.CW $*
645is set for the duration to the reminder of the argument list following
646.I file .
647.CW $path
648is used to search for
649.I file .
650Option
651.CW -i
652indicates interactive input \(em a prompt
653(found in
654.CW $prompt )
655is printed before each command is read.
656.TP "builtin \fIcommand ...\f(CW
657Execute
658.I command
659as usual except that any function named
660.I command
661is ignored.
662For example,
663.P1
664fn cd{
665    builtin cd $* && pwd
666}
667.P2
668defines a replacement for the
669.CW cd
670built-in (see below) that announces the full name of the new directory.
671.TP "cd [\fIdir\f(CW]
672Change the current directory to
673.I dir .
674The default argument is
675.CW $home .
676.CW $cdpath
677is a list of places in which to search for
678.I dir .
679.TP "eval [\fIarg ...\f(CW]
680The arguments are concatenated (separated by spaces) into a string, read as input to
681.I rc ,
682and executed.  For example,
683.P1
684x='$y'
685y=Doody
686eval echo Howdy, $x
687.P2
688would echo
689.P1
690Howdy, Doody
691.P2
692since the arguments of
693.CW eval
694would be
695.P1
696echo Howdy, $y
697.P2
698after substituting for
699.CW $x .
700.TP "exec [\fIcommand ...\f(CW]
701.I Rc
702replaces itself with the given
703.I command .
704This is like a
705.I goto
706\(em
707.I rc
708does not wait for the command to exit, and does not return to read any more commands.
709.TP "exit [\fIstatus\f(CW]
710.I Rc
711exits immediately with the given status.  If none is given, the current value of
712.CW $status
713is used.
714.TP "flag \fIf\f(CW [+-]
715This command manipulates and tests the command line flags (described below).
716.P1
717flag \fIf\f(CW +
718.P2
719sets flag
720.I f .
721.P1
722flag \fIf\f(CW -
723.P2
724clears flag
725.I f .
726.P1
727flag \fIf\f(CW
728.P2
729tests flag
730.I f ,
731setting
732.CW $status
733appropriately.
734Thus
735.P1
736if(flag x) flag v +
737.P2
738sets the
739.CW -v
740flag if the
741.CW -x
742flag is already set.
743.TP "rfork [nNeEsfF]
744This uses the Plan 9
745.I rfork
746system entry to put
747.I rc
748into a new process group with the following attributes:
749.TS
750box;
751l l l
752lfCW l l.
753Flag	Name	Function
754_
755n	RFNAMEG	Make a copy of the parent's name space
756N	RFCNAMEG	Start with a new, empty name space
757e	RFENVG	Make a copy of the parent's environment
758E	RFCENVG	Start with a new, empty environment
759s	RFNOTEG	Make a new note group
760f	RFFDG	Make a copy of the parent's file descriptor space
761F	RFCFDG	Make a new, empty file descriptor space
762.TE
763Section
764.I fork (2)
765of the Programmer's Manual describes these attributes in more detail.
766.TP "shift [\fIn\f(CW]
767Delete the first
768.I n
769(default 1) elements of
770.CW $* .
771.TP "wait [\fIpid\fP]
772Wait for the process with the given
773.I pid
774to exit.  If no
775.I pid
776is given, all outstanding processes are waited for.
777.TP "whatis \fIname ...\f(CW
778Print the value of each
779.I name
780in a form suitable for input to
781.I rc .
782The output is an assignment to a variable, the definition of a function,
783a call to
784.CW builtin
785for a built-in command, or the path name of a binary program.
786For example,
787.P1
788whatis path g cd who
789.P2
790might print
791.P1
792path=(. /bin)
793fn g {gre -e $1 *.[hycl]}
794builtin cd
795/bin/who
796.P2
797.TP "~ \fIsubject pattern ...
798The
799.I subject
800is matched against each
801.I pattern
802in turn.  On a match,
803.CW $status
804is set to true.
805Otherwise, it is set to
806.CW "'no match'" .
807Patterns are the same as for filename matching.
808The
809.I patterns
810are not subjected to filename replacement before the
811.CW ~
812command is executed, so they need not be enclosed in
813quotation marks, unless of course, a literal match for
814.CW *
815.CW [
816or
817.CW ?
818is required.
819For example
820.P1
821~ $1 ?
822.P2
823matches any single character, whereas
824.P1
825~ $1 '?'
826.P2
827only matches a literal question mark.
828.NH
829Advanced I/O Redirection
830.PP
831.I Rc
832allows redirection of file descriptors other than 0 and 1
833(standard input and output) by specifying the file descriptor
834in square brackets
835.CW "[ ]
836after the
837.CW <
838or
839.CW > .
840For example,
841.P1
842vc junk.c >[2]junk.diag
843.P2
844saves the compiler's diagnostics from standard error in
845.CW junk.diag .
846.PP
847File descriptors may be replaced by a copy, in the sense of
848.I dup (2),
849of an already-open file by typing, for example
850.P1
851vc junk.c >[2=1]
852.P2
853This replaces file descriptor 2 with a copy of file descriptor 1.
854It is more useful in conjunction with other redirections, like this
855.P1
856vc junk.c >junk.out >[2=1]
857.P2
858Redirections are evaluated from left to right, so this redirects
859file descriptor 1 to
860.CW junk.out ,
861then points file descriptor 2 at the same file.
862By contrast,
863.P1
864vc junk.c >[2=1] >junk.out
865.P2
866redirects file descriptor 2 to a copy of file descriptor 1
867(presumably the terminal), and then directs file descriptor 1
868to a file.  In the first case, standard and diagnostic output
869will be intermixed in
870.CW junk.out .
871In the second, diagnostic output will appear on the terminal,
872and standard output will be sent to the file.
873.PP
874File descriptors may be closed by using the duplication notation
875with an empty right-hand side.
876For example,
877.P1
878vc junk.c >[2=]
879.P2
880will discard diagnostics from the compilation.
881.PP
882Arbitrary file descriptors may be sent through
883a pipe by typing, for example,
884.P1
885vc junk.c |[2] grep -v '^$'
886.P2
887This deletes blank lines
888from the C compiler's error output.  Note that the output
889of
890.CW grep
891still appears on file descriptor 1.
892.PP
893Occasionally you may wish to connect the input side of
894a pipe to some file descriptor other than zero.
895The notation
896.P1
897cmd1 |[5=19] cmd2
898.P2
899creates a pipeline with
900.CW cmd1 's
901file descriptor 5 connected through a pipe to
902.CW cmd2 's
903file descriptor 19.
904.NH
905Here documents
906.PP
907.I Rc
908procedures may include data, called ``here documents'',
909to be provided as input to commands, as in this version of the
910.I tel
911command
912.P1
913for(i) grep $i <<!
914\&...
915tor 2T-402 2912
916kevin 2C-514 2842
917bill 2C-562 7214
918\&...
919!
920.P2
921A here document is introduced by the redirection symbol
922.CW << ,
923followed by an arbitrary EOF marker
924.CW ! "" (
925in the example).  Lines following the command,
926up to a line containing only the EOF marker are saved
927in a temporary file that is connected to the command's
928standard input when it is run.
929.PP
930.I Rc
931does variable substitution in here documents.  The following command:
932.P1
933ed $3 <<EOF
934g/$1/s//$2/g
935w
936EOF
937.P2
938changes all occurrences of
939.CW $1
940to
941.CW $2
942in file
943.CW $3 .
944To include a literal
945.CW $
946in a here document, type
947.CW $$ .
948If the name of a variable is followed immediately by
949.CW ^ ,
950the caret is deleted.
951.PP
952Variable substitution can be entirely suppressed by enclosing
953the EOF marker following
954.CW <<
955in quotation marks, as in
956.CW <<'EOF' .
957.PP
958Here documents may be provided on file descriptors other than 0 by typing, for example,
959.P1
960cmd <<[4]End
961\&...
962End
963.P2
964.PP
965If a here document appears within a compound block, the contents of the document
966must be after the whole block:
967.P1
968for(i in $*){
969	mail $i <<EOF
970}
971words to live by
972EOF
973.P2
974.NH
975Catching Notes
976.PP
977.I Rc
978scripts normally terminate when an interrupt is received from the terminal.
979A function with the name of a UNIX signal, in lower case, is defined in the usual way,
980but called when
981.I rc
982receives the corresponding note.
983The
984.I notify (2)
985section of the Programmer's Manual discusses notes in some detail.
986Notes of interest are:
987.TP sighup
988The note was `hangup'.
989Plan 9 sends this when the terminal has disconnected from
990.I rc .
991.TP sigint
992The note was `interrupt', usually sent when
993the interrupt character (ASCII DEL) is typed on the terminal.
994.TP sigterm
995The note was `kill', normally sent by
996.I kill (1).
997.TP sigexit
998An artificial note sent when
999.I rc
1000is about to exit.
1001.PP
1002As an example,
1003.P1
1004fn sigint{
1005    rm /tmp/junk
1006    exit
1007}
1008.P2
1009sets a trap for the keyboard interrupt that
1010removes a temporary file before exiting.
1011.PP
1012Notes will be ignored if the note routine is set to
1013.CW {} .
1014Signals revert to their default behavior when their handlers'
1015definitions are deleted.
1016.NH
1017Environment
1018.PP
1019The environment is a list of name-value pairs made available to
1020executing binaries.
1021On Plan 9, the environment is stored in a file system named
1022.CW #e ,
1023normally mounted on
1024.CW /env .
1025The value of each variable is stored in a separate file, with components
1026terminated by zero bytes.
1027(The file system is
1028maintained entirely in core, so no disk or network access is involved.)
1029The contents of
1030.CW /env
1031are shared on a per-process group basis \(mi when a new process group is
1032created it effectively attaches
1033.CW /env
1034to a new file system initialized with a copy of the old one.
1035A consequence of this organization is that commands can change environment
1036entries and see the changes reflected in
1037.I rc .
1038.PP
1039Functions also appear in the environment, named by prefixing
1040.CW fn#
1041to their names, like
1042.CW /env/fn#roff .
1043.NH
1044Local Variables
1045.PP
1046It is often useful to set a variable for the duration
1047of a single command.  An assignment followed by a command
1048has this effect.  For example
1049.P1
1050a=global
1051a=local echo $a
1052echo $a
1053.P2
1054will print
1055.P1
1056local
1057global
1058.P2
1059This works even for compound commands, like
1060.P1
1061f=/fairly/long/file/name {
1062    { wc $f; spell $f; diff $f.old $f } |
1063      pr -h 'Facts about '$f | lp -dfn
1064}
1065.P2
1066.NH
1067Examples \(em \fIcd, pwd\fP
1068.PP
1069Here is a pair of functions that provide
1070enhanced versions of the standard
1071.CW cd
1072and
1073.CW pwd
1074commands.  (Thanks to Rob Pike for these.)
1075.P1
1076ps1='% '	# default prompt
1077tab='	'	# a tab character
1078fn cd{
1079  builtin cd $1 &&
1080  switch($#*){
1081  case 0
1082    dir=$home
1083    prompt=($ps1 $tab)
1084  case *
1085    switch($1)
1086    case /*
1087      dir=$1
1088      prompt=(`{basename `{pwd}}^$ps1 $tab)
1089    case */* ..*
1090      dir=()
1091      prompt=(`{basename `{pwd}}^$ps1 $tab)
1092    case *
1093      dir=()
1094      prompt=($1^$ps1 $tab)
1095    }
1096  }
1097}
1098fn pwd{
1099  if(~ $#dir 0)
1100    dir=`{/bin/pwd}
1101  echo $dir
1102}
1103.P2
1104Function
1105.CW pwd
1106is a version of the standard
1107.CW pwd
1108that caches its value in variable
1109.CW $dir ,
1110because the genuine
1111.CW pwd
1112can be quite slow to execute.
1113.PP
1114Function
1115.CW cd
1116calls the
1117.CW cd
1118built-in, and checks that it was successful.
1119If so, it sets
1120.CW $dir
1121and
1122.CW $prompt .
1123The prompt will include the last component of the
1124current directory (except in the home directory,
1125where it will be null), and
1126.CW $dir
1127will be reset either to the correct value or to
1128.CW () ,
1129so that the
1130.CW pwd
1131function will work correctly.
1132.NH
1133Examples \(em \fIman\fP
1134.PP
1135The
1136.I man
1137command prints pages of the Programmer's Manual.
1138It is called, for example, as
1139.P1
1140man 2 sinh
1141man rc
1142man -t cat
1143.P2
1144In the first case, the page for
1145.I sinh
1146in section 2 is printed.
1147In the second case, the manual page for
1148.I rc
1149is printed.  Since no manual section is specified,
1150all sections are searched for the page, and it is found
1151in section 1.
1152In the third case, the page for
1153.I cat
1154is typeset (the
1155.CW -t
1156option).
1157.P1
1158cd /sys/man || {
1159  echo $0: No manual! >[1=2]
1160  exit 1
1161}
1162NT=n  # default nroff
1163s='*' # section, default try all
1164for(i) switch($i){
1165case -t
1166  NT=t
1167case -n
1168  NT=n
1169case -*
1170  echo Usage: $0 '[-nt] [section] page ...' >[1=2]
1171  exit 1
1172case [1-9] 10
1173  s=$i
1174case *
1175  eval 'pages='$s/$i
1176  for(page in $pages){
1177    if(test -f $page)
1178      $NT^roff -man $page
1179    if not
1180      echo $0: $i not found >[1=2]
1181  }
1182}
1183.P2
1184Note the use of
1185.CW eval
1186to make a list of candidate manual pages.
1187Without
1188.CW eval ,
1189the
1190.CW *
1191stored in
1192.CW $s
1193would not trigger filename matching
1194\(em it's enclosed in quotation marks,
1195and even if it weren't, it would be expanded
1196when assigned to
1197.CW $s .
1198Eval causes its arguments
1199to be re-processed by
1200.I rc 's
1201parser and interpreter, effectively delaying
1202evaluation of the
1203.CW *
1204until the assignment to
1205.CW $pages .
1206.NH
1207Examples \(em \fIholmdel\fP
1208.PP
1209The following
1210.I rc
1211script plays the deceptively simple game
1212.I holmdel ,
1213in which the players alternately name Bell Labs locations,
1214the winner being the first to mention Holmdel.
1215.KF
1216.P1
1217t=/tmp/holmdel$pid
1218fn read{
1219	$1=`{awk '{print;exit}'}
1220}
1221ifs='
1222\&'	# just a newline
1223fn sigexit sigint sigquit sighup{
1224	rm -f $t
1225	exit
1226}
1227cat <<'!' >$t
1228Allentown
1229Atlanta
1230Cedar Crest
1231Chester
1232Columbus
1233Elmhurst
1234Fullerton
1235Holmdel
1236Indian Hill
1237Merrimack Valley
1238Morristown
1239Neptune
1240Piscataway
1241Reading
1242Short Hills
1243South Plainfield
1244Summit
1245Whippany
1246West Long Branch
1247!
1248while(){
1249   lab=`{fortune $t}
1250   echo $lab
1251   if(~ $lab Holmdel){
1252      echo You lose.
1253      exit
1254   }
1255   while(read lab; ! grep -i -s $lab $t) echo No such location.
1256   if(~ $lab [hH]olmdel){
1257      echo You win.
1258      exit
1259   }
1260}
1261.P2
1262.KE
1263.PP
1264This script is worth describing in detail
1265(rather, it would be if it weren't so silly.)
1266.PP
1267Variable
1268.CW $t
1269is an abbreviation for the name of a temporary file.
1270Including
1271.CW $pid ,
1272initialized by
1273.I rc
1274to its process-id,
1275in the names of temporary files insures that their
1276names won't collide, in case more than one instance
1277of the script is running at a time.
1278.PP
1279Function
1280.CW read 's
1281argument is the name of a variable into which a
1282line gathered from standard input is read.
1283.CW $ifs
1284is set to just a newline.  Thus
1285.CW read 's
1286input is not split apart at spaces, but the terminating
1287newline is deleted.
1288.PP
1289A handler is set to catch
1290.CW sigint ,
1291.CW sigquit ,
1292and
1293.CW sighup,
1294and the artificial
1295.CW sigexit
1296signal.  It just removes the temporary file and exits.
1297.PP
1298The temporary file is initialized from a here
1299document containing a list of Bell Labs locations, and
1300the main loop starts.
1301.PP
1302First, the program guesses a location (in
1303.CW $lab )
1304using the
1305.CW fortune
1306program to pick a random line from the location list.
1307It prints the location, and if it guessed Holmdel, prints
1308a message and exits.
1309.PP
1310Then it uses the
1311.CW read
1312function to get lines from standard input and validity-check
1313them until it gets a legal name.
1314Note that the condition part of a
1315.CW while
1316can be a compound command.  Only the exit status of the
1317last command in the sequence is checked.
1318.PP
1319Again, if the result
1320is Holmdel, it prints a message and exits.
1321Otherwise it goes back to the top of the loop.
1322.NH
1323Design Principles
1324.PP
1325.I Rc
1326draws heavily from Steve Bourne's
1327.CW /bin/sh .
1328Any successor of the Bourne shell is bound to
1329suffer in comparison.  I have tried to fix its
1330best-acknowledged shortcomings and to simplify things
1331wherever possible, usually by omitting inessential features.
1332Only when irresistibly tempted have I introduced novel ideas.
1333Obviously I have tinkered extensively with Bourne's syntax.
1334.PP
1335The most important principle in
1336.I rc 's
1337design is that it's not a macro processor.  Input is never
1338scanned more than once by the lexical and syntactic analysis
1339code (except, of course, by the
1340.CW eval
1341command, whose
1342.I "raison d'être
1343is to break the rule).
1344.PP
1345Bourne shell scripts can often be made
1346to run wild by passing them arguments containing spaces.
1347These will be split into multiple arguments using
1348.CW IFS ,
1349often at inopportune times.
1350In
1351.I rc ,
1352values of variables, including command line arguments, are not re-read
1353when substituted into a command.
1354Arguments have presumably been scanned in the parent process, and ought
1355not to be re-read.
1356.PP
1357Why does Bourne re-scan commands after variable substitution?
1358He needs to be able to store lists of arguments in variables whose values are
1359character strings.
1360If we eliminate re-scanning, we must change the type of variables, so that
1361they can explicitly carry lists of strings.
1362.PP
1363This introduces some
1364conceptual complications.  We need a notation for lists of words.
1365There are two different kinds of concatenation, for strings \(em
1366.CW $a^$b ,
1367and lists \(em
1368.CW "($a $b)" .
1369The difference between
1370.CW ()
1371and
1372.CW ''
1373is confusing to novices,
1374although the distinction is arguably sensible \(em
1375a null argument is not the same as no argument.
1376.PP
1377Bourne also rescans input when doing command substitution.
1378This is because the text enclosed in back-quotes is not
1379a string, but a command.  Properly, it ought to
1380be parsed when the enclosing command is, but this makes
1381it difficult to
1382handle nested command substitutions, like this:
1383.P1
1384size=`wc -l \e`ls -t|sed 1q\e``
1385.P2
1386The inner back-quotes must be escaped
1387to avoid terminating the outer command.
1388This can get much worse than the above example;
1389the number of
1390.CW \e 's
1391required is exponential in the nesting depth.
1392.I Rc
1393fixes this by making the backquote a unary operator
1394whose argument is a command, like this:
1395.P1
1396size=`{wc -l `{ls -t|sed 1q}}
1397.P2
1398No escapes are ever required, and the whole thing
1399is parsed in one pass.
1400.PP
1401For similar reasons
1402.I rc
1403defines signal handlers as though they were functions,
1404instead of associating a string with each signal, as Bourne does,
1405with the attendant possibility of getting a syntax error message
1406in response to typing the interrupt character.  Since
1407.I rc
1408parses input when typed, it reports errors when you make them.
1409.PP
1410For all this trouble, we gain substantial semantic simplifications.
1411There is no need for the distinction between
1412.CW $*
1413and
1414.CW $@ .
1415There is no need for four types of quotation, nor the
1416extremely complicated rules that govern them.  In
1417.I rc
1418you use quotation marks when you want a syntax character
1419to appear in an argument, or an argument that is the empty string,
1420and at no other time.
1421.CW IFS
1422is no longer used, except in the one case where it was indispensable:
1423converting command output into argument lists during command substitution.
1424.PP
1425This also avoids an important UNIX security hole.
1426In UNIX, the
1427.I system
1428and
1429.I popen
1430functions call
1431.CW /bin/sh
1432to execute a command.  It is impossible to use either
1433of these routines with any assurance that the specified command will
1434be executed, even if the caller of
1435.I system
1436or
1437.I popen
1438specifies a full path name for the command.  This can be devastating
1439if it occurs in a set-userid program.
1440The problem is that
1441.CW IFS
1442is used to split the command into words, so an attacker can just
1443set
1444.CW IFS=/
1445in his environment and leave a Trojan horse
1446named
1447.CW usr
1448or
1449.CW bin
1450in the current working directory before running the privileged program.
1451.I Rc
1452fixes this by never rescanning input for any reason.
1453.PP
1454Most of the other differences between
1455.I rc
1456and the Bourne shell are not so serious.  I eliminated Bourne's
1457peculiar forms of variable substitution, like
1458.P1
1459echo ${a=b} ${c-d} ${e?error}
1460.P2
1461because they are little used, redundant and easily
1462expressed in less abstruse terms.
1463I deleted the builtins
1464.CW export ,
1465.CW readonly ,
1466.CW break ,
1467.CW continue ,
1468.CW read ,
1469.CW return ,
1470.CW set ,
1471.CW times
1472and
1473.CW unset
1474because they seem redundant or
1475only marginally useful.
1476.PP
1477Where Bourne's syntax draws from Algol 68,
1478.I rc 's
1479is based on C or Awk.  This is harder to defend.
1480I believe that, for example
1481.P1
1482if(test -f junk) rm junk
1483.P2
1484is better syntax than
1485.P1
1486if test -f junk; then rm junk; fi
1487.P2
1488because it is less cluttered with keywords,
1489it avoids the semicolons that Bourne requires
1490in odd places,
1491and the syntax characters better set off the
1492active parts of the command.
1493.PP
1494The one bit of large-scale syntax that Bourne
1495unquestionably does better than
1496.I rc
1497is the
1498.CW if
1499statement with
1500.CW "else
1501clause.
1502.I Rc 's
1503.CW if
1504has no terminating
1505.CW fi -like
1506bracket.  As a result, the parser cannot
1507tell whether or not to expect an
1508.CW "else
1509clause without looking ahead in its input.
1510The problem is that after reading, for example
1511.P1
1512if(test -f junk) echo junk found
1513.P2
1514in interactive mode,
1515.I rc
1516cannot decide whether to execute it immediately and print
1517.CW $prompt(1) ,
1518or to print
1519.CW $prompt(2)
1520and wait for the
1521.CW "else
1522to be typed.
1523In the Bourne shell, this is not a problem, because the
1524.CW if
1525command must end with
1526.CW fi ,
1527regardless of whether it contains an
1528.CW else
1529or not.
1530.PP
1531.I Rc 's
1532admittedly feeble solution is to declare that the
1533.CW else
1534clause is a separate statement, with the semantic
1535proviso that it must immediately follow an
1536.CW if ,
1537and to call it
1538.CW "if not
1539rather than
1540.CW else ,
1541as a reminder that something odd is going on.
1542The only noticeable consequence of this is that
1543the braces are required in the construction
1544.P1
1545for(i){
1546    if(test -f $i) echo $i found
1547    if not echo $i not found
1548}
1549.P2
1550and that
1551.I rc
1552resolves the ``dangling else'' ambiguity in opposition
1553to most people's expectations.
1554.PP
1555It is remarkable that in the four most recent editions of the UNIX system
1556programmer's manual the Bourne shell grammar described in the manual page
1557does not admit the command
1558.CW who|wc .
1559This is surely an oversight, but it suggests something darker:
1560nobody really knows what the Bourne shell's grammar is.  Even examination
1561of the source code is little help.  The parser is implemented by recursive
1562descent, but the routines corresponding to the syntactic categories all
1563have a flag argument that subtly changes their operation depending on the
1564context.
1565.I Rc 's
1566parser is implemented using
1567.I yacc ,
1568so I can say precisely what the grammar is.
1569.NH
1570Acknowledgements
1571.PP
1572Rob Pike, Howard Trickey and other Plan 9 users have been insistent, incessant
1573sources of good ideas and criticism.  Some examples in this document are plagiarized
1574from [Bourne],
1575as are most of
1576.I rc 's
1577good features.
1578.NH
1579Reference
1580.LP
1581S. R. Bourne,
1582UNIX Time-Sharing System: The UNIX Shell,
1583Bell System Technical Journal, Volume 57 number 6, July-August 1978
1584