|
|
1.1 root 1: .so ../ADM/mac
2: .XX rc 283 "Rc \(em A Shell for Plan 9 and UNIX"
3: .fp 5 T CW \" T for Typewriter
4: .Tm shell programming language g
5: .de TP \" An indented paragraph describing some command, tagged with the command name
6: .IP "\\fT\\$1\\fR" 5
7: .if \\w'\\fT\\$1\\fR'-4n .br
8: ..
9: .de CI
10: .nr Sf \\n(.f
11: \%\&\\$3\f(CW\\$1\fI\&\\$2\f\\n(Sf
12: ..
13: .TL
14: Rc \(em A Shell for Plan 9 and UNIX
15: .AU
16: Tom Duff
17: .AI
18: .MH
19: .AB
20: .I Rc
21: is a command interpreter for Plan 9.
22: It also runs on a variety of UNIX systems,
23: including SunOS and the Tenth Edition.
24: It provides similar facilities to Bourne's
25: .I /bin/sh ,
26: with some small additions and mostly less idiosyncratic syntax.
27: This paper introduces
28: .I rc
29: with numerous examples, and discusses its design and
30: why it varies from Bourne's.
31: .AE
32: .2C
33: .NH
34: Introduction
35: .PP
36: Plan 9 needs a command-programming language. As porting the
37: Bourne shell to a non-UNIX environment seemed a daunting task,
38: I chose to write a new command interpreter, called
39: .I rc
40: because it runs commands.
41: Although tinkering with perfection is a dangerous business,
42: I could hardly resist trying to `improve' on Bourne's design.
43: Thus,
44: .I rc
45: is similar in spirit, but different in detail from Bourne's
46: shell.
47: .NH
48: Simple commands
49: .PP
50: For the simplest uses,
51: .I rc
52: has syntax familiar to Bourne shell users.
53: A simple command is a blank-separated sequence of arguments.
54: .P1
55: date
56: .P2
57: prints the current date and time, and
58: .P1
59: con alice
60: .P2
61: connects the user's terminal to the machine
62: .CW alice .
63: .NH
64: Quotation
65: .PP
66: An argument that contains a space or one of
67: .I rc 's
68: other syntax characters should be enclosed in apostrophes
69: .CW ' ). (
70: For example:
71: .P1
72: rm 'odd file name'
73: .P2
74: To include an apostrophe in a quoted name, it must be doubled:
75: .P1
76: echo 'How''s your father?'
77: .P2
78: .NH
79: Comments and continuation
80: .PP
81: A number-sign
82: .CW # ) (
83: and all characters following it up to, but not including, the next newline
84: are ignored, except in quotation marks.
85: .PP
86: A long command line may be continued on subsequent lines by typing a
87: backslash
88: .CW \e ) (
89: followed immediately by a newline, anywhere that white space is required.
90: Commands also continue onto the next line when the last symbol on
91: a line could not reasonably be the end of the command.
92: .NH
93: I/O Redirection
94: .PP
95: Many commands write output on the standard output file, normally the terminal.
96: A command's standard output may be made to overwrite a file by writing
97: .P1
98: who >user.names
99: .P2
100: This command produces a list of the currently logged in users in a file named
101: .CW user.names .
102: Standard output may be appended to the end of a file by
103: .P1
104: who >>user.names
105: .P2
106: In either case, mentioning a non-existent file causes it to be created.
107: .PP
108: Likewise, a command's standard input, also normally the terminal, may be connected to
109: a file by
110: .P1
111: wc <file
112: .P2
113: This command will report the number of characters, lines and words in
114: .CW file .
115: ........
116: .NH
117: Pipelines
118: .PP
119: The standard output of one command may be connected to the standard input of another
120: command like this:
121: .P1
122: who | wc
123: .P2
124: This prints the number of users currently logged in, and is equivalent to
125: .P1
126: who >tmp
127: wc <tmp
128: .P2
129: except that no temporary file is produced. Instead a pipe \(em an
130: interprocess channel that looks to one process like an output file and to
131: another like an input file \(em is created joining the two commands, which
132: run simultaneously. The pipe contains a data buffer so that the two
133: commands need not produce and consume data in perfect lock-step.
134: .NH
135: Filename patterns
136: .PP
137: .I Rc
138: has several ways to generate argument lists automatically.
139: These include filename pattern matching, variable substitution, string concatenation,
140: command substitution and pipeline branching.
141: .PP
142: Any literal word containing one of the meta-characters
143: .CW * ,
144: .CW ?
145: or
146: .CW [
147: is a pattern used to match filenames.
148: A
149: .CW *
150: matches any sequence of characters
151: a
152: .CW ?
153: matches any single character,
154: and a list of characters between
155: .CW [
156: and
157: .CW ]
158: matches a single character from the listed set.
159: The list may include ranges like
160: .CW a-z ,
161: specifying all ASCII characters between the two.
162: The entire set is complemented if the first character
163: after
164: .CW [
165: is
166: .CW ~
167: (a tilde.)
168: No meta-character can match
169: the first character of the filenames
170: .CW .
171: and
172: .CW ..
173: or the character
174: .CW / .
175: .PP
176: A pattern is replaced by a list of all the names that it matches.
177: If it matches no name, it remains unreplaced.
178: .PP
179: Meta-characters are active only when they appear literally
180: and unquoted. For example, if a variable (see below) has a
181: .CW *
182: in it, and the value is substituted into a line, it is
183: not used for filename matching.
184: .NH
185: Variables
186: .PP
187: .I Rc
188: provides variables whose values are lists of arguments.
189: Variables may be given values by typing, for example:
190: .P1
191: path=(. /bin /usr/bin)
192: user=td
193: tty=/dev/tty8
194: .P2
195: The parentheses indicate that the value assigned to
196: .CW path
197: is a list of three strings. The variables
198: .CW user
199: and
200: .CW tty
201: are assigned lists containing a single string.
202: .PP
203: The value of a variable can be substituted into a command by
204: preceding its name with a
205: .CW $ ,
206: like this:
207: .P1
208: echo $path
209: .P2
210: If
211: .CW path
212: had been set as above, this would be equivalent to
213: .P1
214: echo . /bin /usr/bin
215: .P2
216: Variables may be subscripted by numbers or lists of numbers,
217: like this:
218: .P1
219: echo $path(2)
220: echo $path(3 2 1)
221: .P2
222: These are equivalent to
223: .P1
224: echo /bin
225: echo /usr/bin /bin .
226: .P2
227: There can be no space separating the variable's name from the
228: left parenthesis. Otherwise, the subscript would be considered
229: a separate parenthesized list.
230: .PP
231: The number of strings in a variable can be determined by the
232: .CW $#
233: operator. For example,
234: .P1
235: echo $#path
236: .P2
237: would print the number of entries in
238: .CW $path .
239: .PP
240: The following two assignments are subtly different:
241: .P1
242: empty=()
243: null=''
244: .P2
245: The first sets
246: .CW empty
247: to a list containing no strings.
248: The second sets
249: .CW null
250: to a list containing a single string,
251: but the string contains no characters.
252: .PP
253: Although these may seem like more or less
254: the same thing (in Bourne's shell, they are
255: indistinguishable), they behave differently
256: in almost all circumstances.
257: Among other things
258: .P1
259: echo $#empty
260: .P2
261: prints 0, whereas
262: .P1
263: echo $#null
264: .P2
265: prints 1.
266: .PP
267: All variables that have never been set have the value
268: .CW () .
269: ......
270: .NH
271: Arguments
272: .PP
273: When
274: .I rc
275: is reading its input from a file, the file has access
276: to the arguments supplied on
277: .I rc 's
278: command line. The variable
279: .CW $*
280: initially has the list of arguments assigned to it.
281: The names
282: .CW $1 ,
283: .CW $2 ,
284: etc. are synonyms for
285: .CW $*(1) ,
286: .CW $*(2) ,
287: etc.
288: In addition,
289: .CW $0
290: is the name of the file from which
291: .I rc 's
292: input is being read.
293: .PP
294: The built-in
295: .CW shift
296: command deletes the first member of
297: .CW $* .
298: If
299: .CW shift
300: is given an argument, it deletes the given
301: number of members from
302: .CW $*.
303: Thus,
304: .P1
305: *=(Never, ever type rm -fr /)
306: shift 2
307: echo Please $*
308: .P2
309: would print
310: .P1
311: Please type rm -fr /
312: .P2
313: .NH
314: Concatenation
315: .PP
316: .I Rc
317: has a string concatenation operator, the caret
318: .CW ^ ,
319: to build a arguments out of pieces.
320: .P1
321: echo hully^gully
322: .P2
323: is exactly equivalent to
324: .P1
325: echo hullygully
326: .P2
327: Suppose variable
328: .CW i
329: contains the name of a command.
330: Then
331: .P1
332: cc -o $i $i^.c
333: .P2
334: might compile the command's source code, leaving the
335: result in the appropriate file.
336: .PP
337: Concatenation distributes over lists. The following
338: .P1
339: echo (a b c)^(1 2 3)
340: src=(main subr io)
341: cc $src^.c
342: .P2
343: are equivalent to
344: .P1
345: echo a1 b2 c3
346: cc main.c subr.c io.c
347: .P2
348: In detail, the rule is: if both operands of
349: .CW ^
350: are lists of the same non-zero number of strings, they are concatenated
351: pairwise. Otherwise, if one of the operands is a single string,
352: it is concatenated with each member of the other operand in turn.
353: Any other combination of operands is an error.
354: .NH
355: Free carets
356: .PP
357: User demand has dictated that
358: .I rc
359: insert carets in certain places, to make the syntax
360: look more like the Bourne shell. For example, this:
361: .P1
362: cc -$flags $stems.c
363: .P2
364: is equivalent to
365: .P1
366: cc -^$flags $stems^.c
367: .P2
368: In general,
369: .I rc
370: will insert
371: .CW ^
372: between two arguments that are not separated by white space.
373: Specifically, whenever one of
374: .CW "$'`
375: follows a quoted or unquoted word, or an unquoted word follows
376: a quoted word with no intervening blanks or tabs, a
377: .CW ^
378: is inserted between the two. If an unquoted word immediately following a
379: .CW $
380: contains a character other than an alphanumeric, underscore or
381: .CW * ,
382: a
383: .CW ^
384: is inserted before the first such character.
385: .NH
386: Command substitution
387: .PP
388: It is often useful to build an argument list from the output of a command.
389: .I Rc
390: allows a command, enclosed in braces and preceded by a left quote,
391: .CW "`{...}" ,
392: anywhere that an argument is required. The command is executed and its
393: standard output captured.
394: The characters stored in the variable
395: .CW ifs
396: are used to split the output into arguments.
397: For example,
398: .P1
399: cat `{ls -tr|sed 10q}
400: .P2
401: will catenate the ten oldest files in the current directory in temporal order.
402: .NH
403: Pipeline branching
404: .PP
405: The pipeline notation described above is general enough for almost all cases.
406: Very occasionally it is useful to have pipelines that are not linear.
407: Pipeline topologies more general than trees can require arbitrarily large pipe buffers,
408: or worse, can cause deadlock.
409: .I Rc
410: has syntax for some kinds of non-linear but treelike pipelines.
411: For example,
412: .P1
413: cmp <{old} <{new}
414: .P2
415: will regression test a new version of a command.
416: A
417: .CW <
418: (or
419: .CW > )
420: followed by a command in braces causes the command to be run with
421: its standard output (or input) attached to a pipe. The parent command
422: .CW cmp "" (
423: in the example)
424: is started with the other end of the pipe attached to some file descriptor
425: or other, and with an argument that will connect to the pipe when opened
426: (e.g.
427: .CW /dev/fd/6 .)
428: On systems without
429: .CW /dev/fd ,
430: or something similar (SunOS for example) this feature does not work.
431: .....
432: .NH
433: Exit status
434: .PP
435: When a command exits, it returns status to the program that executed it.
436: On UNIX, status is a small positive number, with zero indicating normal termination
437: and non-zero values encoding error conditions (in a non-standard way). If a
438: UNIX command terminates abnormally rather than by executing
439: .CW exit (2),
440: .I rc
441: takes the status to be 1000 plus the termination status provided to
442: .CW wait (2).
443: On Plan 9 status is a character string describing an error condition.
444: On normal termination it is empty.
445: .PP
446: .I Rc
447: captures commands' exit statuses in the variable
448: .CW $status .
449: For a simple command, the value of
450: .CW $status
451: is just as described above. For a pipeline,
452: .CW $status
453: is set to the concatenation of the statuses of the pipeline components,
454: with
455: .CW |
456: characters for separators.
457: .PP
458: .I Rc
459: has a number of command forms that various kinds of control flow,
460: many of them conditioned by the status returned from previously
461: executed commands. In all cases, any
462: .CW $status
463: containing only
464: .CW 0 's
465: and
466: .CW | 's
467: has boolean value
468: .I true .
469: Any other status is
470: .I false .
471: .NH
472: Flow of control
473: .PP
474: .I Rc
475: will accept multiple commands on a line, separated by
476: .CW &
477: or
478: .CW ; .
479: A command followed by
480: .CW &
481: is executed asynchronously \(em
482: .I rc
483: does not wait for it to exit, and it
484: disconnects its standard input from the terminal,
485: redirecting it to
486: .CW /dev/null
487: so that the command and
488: .I rc
489: do not compete for input lines.
490: The process id of an asynchronous command is stored in the variable
491: .CW $apid ,
492: and if
493: .I rc
494: is running interactively (that is, its input is coming from a terminal),
495: the process id is printed when the command starts.
496: .PP
497: Commands separated by
498: .CW ;
499: are executed in sequence, but
500: .I rc
501: waits for the first command to terminate before starting the second.
502: Thus
503: .P1
504: fortune;fortune&
505: .P2
506: prints out two fortunes (and a process id), not waiting for the
507: second to appear before prompting for more commands.
508: .NH
509: Command grouping
510: .PP
511: A sequence of commands enclosed in
512: .CW {}
513: may be used anywhere a command is required.
514: For example:
515: .P1
516: {sleep 3600;echo 'Time''s up!'}&
517: .P2
518: will wait an hour in the background, then print a message.
519: Without the braces:
520: .P1
521: sleep 3600;echo 'Time''s up!'&
522: .P2
523: this would lock up the terminal for an hour,
524: then print the message in the background!
525: .NH
526: Conditional execution \(em \f(CW&&\fP and \f(CW||\fP
527: .PP
528: A pair of commands may be separated by
529: .CW &&
530: or
531: .CW || .
532: In either case, the first command is executed and its
533: status examined.
534: If the operator is
535: .CW &&
536: and the status is
537: .I true ,
538: the second command is executed.
539: If the operator is
540: .CW ||
541: the status must be
542: .I false
543: to execute the second command.
544: Thus
545: .P1
546: cyntax *.c && cc -g -o cmd *.c
547: .P2
548: compiles
549: .CW cmd
550: only if
551: .CW cyntax
552: passes on it, and
553: .P1
554: {sleep 86400;rm -r /junk} ||
555: echo Failure!|mail td &
556: .P2
557: waits 24 hours, then tries to remove all files in
558: .CW /junk .
559: On failure it sends me mail. It does all of this in
560: the background, so I can use my terminal for something
561: else in the interim.
562: .NH
563: Subshells
564: .PP
565: The
566: .CW @
567: operator executes the following command in a new process.
568: This is useful primarily to insulate the parent process
569: from the effects of built-in commands, like this
570: .P1
571: @ {cd /elsewhere;tar cf - .} |
572: tar -xf -
573: .P2
574: This dubious but venerated idiom copies
575: the contents of
576: .CW /elsewhere
577: to the current directory by building a
578: .CW tar
579: file on standard output and immediately
580: cracking it at the other end of a pipe.
581: The first
582: .CW tar
583: runs in
584: .CW /elsewhere ,
585: but, because of the
586: .CW @ ,
587: the second operates in the original directory.
588: .NH
589: Control flow \(em \f(CWfor\fP
590: .PP
591: A command may be executed once for each member of a list
592: by typing, for example:
593: .P1
594: for(i in printf scanf putchar)
595: look $i /usr/td/lib/dw.dat
596: .P2
597: This looks for each of the words
598: .CW printf ,
599: .CW scanf
600: and
601: .CW putchar
602: in the given file.
603: The general form is
604: .P1
605: for(\fIname\fP in \fIlist\fP)
606: \fIcommand\fP
607: .P2
608: or
609: .P1
610: for(\fIname\fP)
611: \fIcommand\fP
612: .P2
613: In the first case,
614: .I command
615: is executed once for each member of
616: .I list ,
617: with that member assigned to variable
618: .I name .
619: If
620: .CI in " list
621: is not given,
622: .I $*
623: is used.
624: .NH
625: Conditional execution \(em \f(CWif\fP
626: .PP
627: .I Rc
628: also provides a general if-statement. For example:
629: .P1
630: if(cyntax *.c)
631: cc -g -o cmd *.c
632: .P2
633: is equivalent to the similar example above.
634: An `if not' statement provides a two-tailed conditional.
635: For example:
636: .P1
637: for(i){
638: if(test -f /tmp/$i)
639: echo $i already in /tmp
640: if not
641: cp $i /tmp
642: }
643: .P2
644: This loops over each file in
645: .CW $* ,
646: copying to
647: .CW /tmp
648: those that do not already appear there, and
649: printing a message for those that do.
650: .NH
651: Control flow \(em \f(CWwhile\fP
652: .PP
653: .I Rc 's
654: while statement looks like this:
655: .P1
656: while(newer subr.c subr.o) sleep 5
657: .P2
658: This waits until
659: .CW subr.o
660: is newer than
661: .CW subr.c
662: (presumably because the C compiler finished with it.)
663: .NH
664: Control flow \(em \f(CWswitch\fP
665: .PP
666: .I Rc
667: provides a switch statement to do pattern-matching on
668: arbitrary strings. Its general form is
669: .P1
670: switch(\fIword\fP){
671: case \fIpattern ...\fP
672: \fIcommands\fP
673: case \fIpattern ...\fP
674: \fIcommands\fP
675: ...
676: }
677: .P2
678: .I Rc
679: attempts to match the word against the patterns in each case statement in turn.
680: Patterns are the same as for filename matching, except that
681: .CW /
682: and the first characters of
683: .CW .
684: and
685: .CW ..
686: need not be matched explicitly.
687: .PP
688: If any pattern matches, the
689: commands following that case up to
690: the next case (or the end of the switch)
691: are executed, and execution of the switch
692: is complete. For example,
693: .P1
694: switch($#*){
695: case 1
696: cat >>$1
697: case 2
698: cat >>$2 <$1
699: case *
700: echo 'Usage: append [from] to'
701: }
702: .P2
703: is an append command. Called with one file argument,
704: it tacks standard input to its end. With two, the
705: first is appended to the second. Any other number
706: elicits a usage message.
707: .PP
708: The built-in
709: .CW ~
710: command also matches patterns, and is often more concise than a switch.
711: Its arguments are a string and a list of patterns. It sets
712: .CW $status
713: to zero if and only if any of the patterns matches the string.
714: The following example processes option arguments for the
715: .I man (1)
716: command:
717: .P1
718: opt=()
719: while(~ $1 -* [1-9] 10){
720: switch($1){
721: case [1-9] 10
722: sec=$1 secn=$1
723: case -f
724: c=f s=f
725: case -[qwnt]
726: cmd=$1
727: case -T*
728: T=$1
729: case -*
730: opt=($opt $1)
731: }
732: shift
733: }
734: .P2
735: .NH
736: Functions
737: .PP
738: Functions may be defined by typing
739: .P1
740: fn \fIname\fP { \fIcommands\fP }
741: .P2
742: Subsequently, whenever a command named
743: .I name
744: is encountered, the remainder of the command's
745: argument list will assigned to
746: .CW $*
747: and
748: .I rc
749: will execute the
750: .I commands .
751: The value of
752: .CW $*
753: will be restored on completion.
754: For example:
755: .P1
756: fn g {
757: gre -e $1 *.[hcyl]
758: }
759: .P2
760: defines
761: .CI g " pattern
762: to look for occurrences of
763: .I pattern
764: in all program source files in the current directory.
765: .PP
766: Function definitions are deleted by writing
767: .P1
768: fn \fIname\fP
769: .P2
770: with no function body.
771: .....
772: .NH
773: Command execution
774: .PP
775: Up to now we've said very little about what
776: .I rc
777: does to execute a simple command.
778: If the command name is the name of a function defined using
779: .CW fn ,
780: the function is executed.
781: Otherwise, if it is the name of a built-in command, the
782: built-in is executed directly by
783: .I rc .
784: Otherwise, if the name contains a
785: .CW / ,
786: it is taken to be the name of a binary program
787: and is executed using
788: .I exec (2).
789: If the name contains no
790: .CW / ,
791: then directories mentioned in the variable
792: .CW $path
793: are searched until an executable file is found.
794: .NH
795: Built-in commands
796: .PP
797: Several commands are executed internally by
798: .I rc ,
799: usually because their execution changes or depends on
800: .I rc 's
801: internal state.
802: .TP ". [-i] \fIfile ...\fT
803: Execute commands from
804: .I file .
805: .CW $*
806: is set for the duration to the reminder of the argument list following
807: .I file .
808: .CW $path
809: is used to search for
810: .I file .
811: Option
812: .CW -i
813: indicates interactive input \(mi a prompt
814: (found in
815: .CW $prompt )
816: is printed before each command is read.
817: .TP "builtin \fIcommand ...\fT
818: Execute
819: .I command
820: as usual except that any function named
821: .I command
822: is ignored.
823: For example,
824: .P1
825: fn cd{
826: builtin cd $* && pwd
827: }
828: .P2
829: defines a replacement for the
830: .CW cd
831: built-in (see below) that announces the full name of the new directory.
832: .TP "cd [\fIdir\fT]
833: Change the current directory to
834: .I dir .
835: The default argument is
836: .CW $home .
837: .CW $cdpath
838: is a list of places in which to search for
839: .I dir .
840: .TP "eval [\fIarg ...\fT]
841: The arguments are concatenated separated by spaces into a string, read as input to
842: .I rc ,
843: and executed. For example,
844: .P1
845: x='$y'
846: y=Doody
847: eval echo Howdy, $x
848: .P2
849: would echo
850: .P1
851: Howdy, Doody
852: .P2
853: since arguments of
854: .CW eval
855: would be
856: .P1
857: Howdy, $y
858: .P2
859: .TP "exec \fIcommand ...\fT
860: .I Rc
861: replaces itself with the given non-built-in
862: .I command .
863: .TP "exit [\fIstatus\fP]
864: Exit with the given status. If none is given, the current value of
865: .CW $status
866: is used.
867: .TP finit
868: Initialize functions imported from the environment.
869: Intended for use only by
870: .I rc 's
871: initialization procedure.
872: Currently this is non-functional on Plan 9, as no
873: means of environmental function-storage yet exists.
874: .TP "flag \fIletter\fP"
875: Sets
876: .CW $status
877: to zero if and only if
878: .I rc
879: was invoked with option
880: .CI - letter
881: set. Intended for use by
882: .I rc 's
883: initialization procedure.
884: .TP "mount \fInew old\fT
885: (Plan 9 only.)
886: Mount the name
887: .I new
888: on
889: .I old .
890: .TP "shift [\fIn\fT]
891: Delete the first
892: .I n
893: (default 1) elements of
894: .CW $* .
895: .TP "umask [\fIoctal\fP]
896: (UNIX only.) Set
897: .I rc 's
898: file creation mask to the given octal value.
899: If no value is given, the current mask value is printed.
900: .TP "unmount [\fInew\fT] \fIold
901: (Plan 9 only.)
902: Unmount the name
903: .I old .
904: If
905: .I new
906: is given, unmount
907: .I old
908: from
909: .I new .
910: .TP "wait [\fIpid\fP]
911: Wait for the process with the given
912: .I pid
913: to exit. If no
914: .I pid
915: is given, all outstanding processes are waited for.
916: .TP "whatis \fIname ...\fT
917: Print the value of each
918: .I name
919: in a form suitable for input to
920: .I rc .
921: The output is an assignment to any variable, the definition of any function,
922: a call to
923: .CW builtin
924: for any built-in command, or the full path name of any binary program.
925: For example,
926: .P1
927: whatis path g cd who
928: .P2
929: might print
930: .P1
931: path=(. /bin /usr/bin)
932: fn g {gre -e $1 *.[hycl]}
933: builtin cd
934: /bin/who
935: .P2
936: .TP "~ \fIsubject pattern ...
937: The
938: .I subject
939: is matched against each
940: .I pattern
941: in turn. On a match,
942: .CW $status
943: is set to zero.
944: Otherwise, it is set to one.
945: Patterns are the same as for filename matching,
946: except that
947: .CW /
948: and the first character of
949: .CW .
950: and
951: .CW ..
952: need not be matched explicitly.
953: The
954: .I patterns
955: are not subjected to filename replacement before the
956: .CW ~
957: command is executed, so they need not be enclosed in
958: quotation marks, unless of course, a literal match for
959: .CW *
960: .CW [
961: or
962: .CW ?
963: is required.
964: For example
965: .P1
966: ~ $1 ?
967: .P2
968: matches any single character, whereas
969: .P1
970: ~ $1 '?'
971: .P2
972: only matches a literal question mark.
973: .NH
974: Special variables
975: .PP
976: Several variables are set internally by
977: .I rc
978: or used to guide its execution.
979: .TP $*
980: Set to
981: .I rc 's
982: argument list during initialization.
983: A
984: .CW .
985: command or function execution saves
986: .CW $*
987: on a stack and sets it to the new argument list. The saved
988: value is restored on completion.
989: .TP $apid
990: Whenever a process is started asynchronously with
991: .CW & ,
992: .CW $apid
993: receives its process id.
994: .TP $cflag
995: Set to the string provided on
996: .I rc 's
997: command line with the
998: .CW -c
999: option, if any. This is provided for the
1000: use of
1001: .I rc's initialization procedure.
1002: .TP $home
1003: The default directory for
1004: .CW cd .
1005: On UNIX, if
1006: .CW $home
1007: is not initially set, and
1008: .CW $HOME
1009: is, then
1010: .CW $home
1011: is set to
1012: .CW $HOME .
1013: .TP $ifs
1014: The input field separators used in command substitution.
1015: If not set in
1016: .I rc 's
1017: environment, it is initialized to blank, tab and newline.
1018: .TP $path
1019: The search path used to find commands and input files for the
1020: .CW .
1021: command.
1022: If not set in the environment, it is initialized to
1023: .CW "(. /bin /usr/bin)
1024: on UNIX,
1025: .CW "(. /bin)
1026: on Plan 9.
1027: .TP $pid
1028: Set during initialization to
1029: .I rc 's
1030: process id.
1031: .TP $prompt
1032: When
1033: .I rc
1034: is run interactively, the first member of
1035: .CW $prompt
1036: is printed before reading each command.
1037: The second member is printed if
1038: .I rc
1039: expects a command to be continued on another line.
1040: If not set in the environment,
1041: .I rc
1042: initializes it to
1043: .CW "('% ' ' ')" .
1044: .TP $status
1045: On UNIX, this is set to the low 8 bits of the
1046: .I exit (2)
1047: argument of a normally terminating binary (unless started with
1048: .CW & ),
1049: or to 1000 plus the termination status on abnormal termination.
1050: On Plan 9,
1051: .CW $status
1052: is set to the process's termination message.
1053: On either system, the statuses of all processes in a pipeline
1054: are captured and concatenated, separated by
1055: .CW |
1056: characters.
1057: .CW !
1058: and
1059: .CW ~
1060: also set
1061: .CW $status .
1062: Its value is used to control execution in
1063: .CW && ,
1064: .CW || ,
1065: .CW if
1066: and
1067: .CW while
1068: commands.
1069: When
1070: .I rc
1071: exits at end-of-file of its input or on executing an
1072: .CW exit
1073: command with no argument,
1074: .CW $status
1075: is its exit status.
1076: (This is only strictly true on Plan 9. On UNIX, the exit status
1077: must be numeric. Therefore, if the value of
1078: .CW $status
1079: contains
1080: .CW |
1081: characters, they are deleted before converting it to a number, and if
1082: .CW $status
1083: contains other non-numeric characters,
1084: .I rc
1085: exits with status 1.)
1086: .NH
1087: Advanced I/O Redirection
1088: .PP
1089: .I Rc
1090: allows redirection of file descriptors other than 0 and 1
1091: (standard input and output) by specifying the file descriptor
1092: in square brackets
1093: .CW "[ ]
1094: after the
1095: .CW <
1096: or
1097: .CW > .
1098: For example,
1099: .P1
1100: cc junk.c >[2]junk.diag
1101: .P2
1102: saves the compiler's diagnostics in
1103: .CW junk.diag .
1104: .PP
1105: File descriptors may be replaced by a copy, in the sense of
1106: .I dup (2),
1107: of an already-open file by typing, for example
1108: .P1
1109: cc junk.c >[2=1]
1110: .P2
1111: This replaces file descriptor 2 with a copy of file descriptor 1.
1112: It is more useful in conjunction with other redirections, like this
1113: .P1
1114: cc junk.c >junk.out >[2=1]
1115: .P2
1116: Redirections are evaluated from left to right, so this redirects
1117: file descriptor 1 to
1118: .CW junk.out ,
1119: then points file descriptor 2 at the same file.
1120: By contrast,
1121: .P1
1122: cc junk.c >[2=1] >junk.out
1123: .P2
1124: Redirects file descriptor 2 to a copy of file descriptor 1
1125: (presumably the terminal), and then directs file descriptor 1
1126: at a file. In the first case, standard and diagnostic output
1127: will be intermixed in
1128: .CW junk.out .
1129: In the second, diagnostic output will appear on the terminal,
1130: and standard output will be sent to the file.
1131: .PP
1132: File descriptors may be closed by using the duplication notation
1133: with an empty right-hand side.
1134: For example,
1135: .P1
1136: cc junk.c >[2=]
1137: .P2
1138: will discard diagnostics from the compilation.
1139: Often closing a file descriptor will not have the
1140: expected effect, because many UNIX programs do not
1141: behave politely when started with file descriptors
1142: 0, 1 or 2 closed. Consider, for example,
1143: .P1
1144: who | tee a b c >[1=]
1145: .P2
1146: One might expect this to produce copies of the output of
1147: .CW who
1148: on files
1149: .CW a ,
1150: .CW b
1151: and
1152: .CW c ,
1153: discarding the copy that
1154: .CW tee
1155: normally writes on its standard output.
1156: However,
1157: .CW tee
1158: does not check for its standard output being closed.
1159: When it opens
1160: .CW a ,
1161: the file descriptor returned is 1, and unsurprisingly,
1162: .CW tee
1163: writes two interleaved copies of its input onto
1164: .CW a .
1165: It is better explicitly to direct the output at
1166: .CW /dev/null .
1167: .PP
1168: Arbitrary file descriptors may be sent through
1169: a pipe by typing, for example
1170: .P1
1171: cc junk.c |[2] grep -v '^$'
1172: .P2
1173: This deletes those ever-so-annoying blank lines
1174: from the C compiler's output. Note that the output
1175: of
1176: .CW grep
1177: still appears on file descriptor 1.
1178: .PP
1179: Very occasionally you may wish to connect the input side of
1180: a pipe to some file descriptor other than zero.
1181: The notation
1182: .P1
1183: cmd1 |[5=19] cmd2
1184: .P2
1185: creates a pipeline with
1186: .CW cmd1 's
1187: file descriptor 5 connected through a pipe to
1188: .CW cmd2 's
1189: file descriptor 19.
1190: .NH
1191: Here documents
1192: .PP
1193: .I Rc
1194: procedures may include data, called ``here documents'',
1195: to be provided as input to commands, as in this version of the
1196: .I tel
1197: command
1198: .P1
1199: for(i) grep $i <<!
1200: ...
1201: nls 2T-402 2912
1202: norman 2C-514 2842
1203: pjw 2T-502 7214
1204: ...
1205: !
1206: .P2
1207: A here document is introduced by the redirection symbol
1208: .CW << ,
1209: followed by an arbitrary eof marker
1210: .CW ! "" (
1211: in the example). Lines following the command,
1212: up to a line containing only the eof marker are saved
1213: in a temporary file that it connected to the command's
1214: standard input when it is run.
1215: .PP
1216: .I Rc
1217: does variable substitution in here documents. The following
1218: .I subst
1219: command:
1220: .P1
1221: ed $3 <<EOF
1222: g/$1/s//$2/g
1223: w
1224: EOF
1225: .P2
1226: changes all occurrences of
1227: .CW $1
1228: to
1229: .CW $2
1230: in file
1231: .CW $3 .
1232: To include a literal
1233: .CW $
1234: in a here document, type
1235: .CW $$ .
1236: If the name of a variable is followed immediately by
1237: .CW ^ ,
1238: the caret is deleted.
1239: .PP
1240: Variable substitution can be entirely suppressed by enclosing
1241: the eof marker following
1242: .CW <<
1243: in quotation marks.
1244: .PP
1245: Here documents may be provided on file descriptors other than 0 by typing, for example
1246: .P1
1247: cmd <<[4]End
1248: ...
1249: End
1250: .P2
1251: .NH
1252: Signals
1253: .PP
1254: .I Rc
1255: scripts normally terminate when an interrupt is received from the terminal.
1256: A function with the name of a signal, in lower case, is defined in the usual way,
1257: but called when
1258: .I rc
1259: receives the signal. Signals of interest are:
1260: .TP sighup
1261: Hangup. The controlling teletype has disconnected from
1262: .I rc .
1263: .TP sigint
1264: The interrupt character (usually ASCII del) was typed on the controlling terminal.
1265: .TP sigquit
1266: The quit character (usually ASCII fs, ctrl-\e) was typed on the controlling terminal.
1267: .TP sigterm
1268: This signal is normally sent by
1269: .I kill (1).
1270: .TP sigexit
1271: An artificial signal sent when
1272: .I rc
1273: is about to exit.
1274: .LP
1275: As an example,
1276: .P1
1277: fn sigint{
1278: rm /tmp/junk
1279: exit
1280: }
1281: .P2
1282: sets a trap for the keyboard interrupt that
1283: removes a temporary file before exiting.
1284: .PP
1285: Signals will be ignored if the signal routine is set to
1286: .CW {} .
1287: Signals revert to their default behavior when their handlers'
1288: definitions are deleted.
1289: .NH
1290: Environment
1291: .PP
1292: The environment is a list of name-value pairs made available to
1293: executing binaries. On UNIX the environment is passed
1294: to commands as a second argument list containing
1295: an entry for each variable whose value is non-empty, and
1296: an entry for each function. UNIX does not directly support
1297: environment entries containing multiple strings, so if a variable
1298: has more than one component, these are separated by ctrl-a
1299: .CW \e001 ) (
1300: characters.
1301: .PP
1302: On Plan 9, the environment is stored in a file system named
1303: .CW #e ,
1304: normally mounted on
1305: .CW /env .
1306: The value of each variable is stored in a separate file, with components
1307: terminated by ASCII nuls.
1308: (This is not quite as horrendous as it sounds, the file system is
1309: maintained entirely in core, so no disk or network access is involved.)
1310: The contents of
1311: .CW /env
1312: are shared on a per-process group basis \(mi when a new process group is
1313: created it effectively attaches
1314: .CW /env
1315: to a new file system initialized with a copy of the old one.
1316: A consequence of this organization is that commands can change environment
1317: entries and see the changes reflected in
1318: .I rc .
1319: This is not possible on UNIX, as the environment is passed to children by
1320: .I exec (2),
1321: but is not passed back by
1322: .I fork (2)
1323: and
1324: .I wait (2).
1325: .PP
1326: There is not currently a way on Plan 9 to place functions in the environment,
1327: although this could easily done by mounting another instance of
1328: .CW #e
1329: on another directory. The problem is that currently there can be only one instance of
1330: .CW #e
1331: per process group.
1332: .NH
1333: Local Variables
1334: .PP
1335: It is often useful to set a variable for the duration
1336: of a single command. An assignment followed by a command
1337: has this effect. For example
1338: .P1
1339: a=global
1340: a=local echo $a
1341: echo $a
1342: .P2
1343: will print
1344: .P1
1345: local
1346: global
1347: .P2
1348: This works even for compound commands, like
1349: .P1
1350: f=/fairly/long/file/name {
1351: { wc $f
1352: spell $f
1353: diff $f.old $f
1354: } | pr -h 'Facts about '$f |
1355: lp -ddp
1356: }
1357: .P2
1358: .NH
1359: Invocation
1360: .PP
1361: When
1362: .I rc
1363: starts, it digests its option arguments, initializes variables
1364: and functions from the environment, sets
1365: .CW $* ,
1366: .CW $pid
1367: and, if the
1368: .CW -c
1369: option is given,
1370: .CW $cflag ,
1371: and starts reading commands.
1372: .PP
1373: Most of
1374: .I rc 's
1375: initialization is done in a command file that is run at startup.
1376: On UNIX the file is called
1377: .CW /usr/lib/rcmain .
1378: On Plan 9 it is
1379: .CW /sys/lib/rcmain .
1380: .LP
1381: Legal options are:
1382: .TP "-c \fIstring
1383: Commands are read from
1384: .I string .
1385: .TP -e
1386: Exit if
1387: .CW $status
1388: is non-zero after executing any simple command.
1389: .TP -i
1390: Interactive mode.
1391: Also set if
1392: .I rc
1393: is given no arguments and its standard input is a terminal,
1394: as determined by
1395: .I isatty (3)
1396: on UNIX, or by presumption on Plan 9.
1397: Commands are prompted for using
1398: .CW $prompt .
1399: .CW SIGINT
1400: and
1401: .CW SIGQUIT
1402: are caught and sloughed off.
1403: .TP -I
1404: Non-interactive mode.
1405: Suppresses interactive mode even if
1406: .I rc
1407: is given no arguments and its standard input is a terminal.
1408: .TP -l
1409: Login mode.
1410: Also set if the first character of argument zero is
1411: .CW -
1412: (this is an obscure UNIX convention).
1413: .I Rc
1414: reads commands from
1415: .CW $home/.rcrc ,
1416: if it exists, before reading its normal input.
1417: .TP -p
1418: Protected mode.
1419: .CW $path
1420: is set to
1421: .CW "(/bin /usr/bin)
1422: on UNIX, or
1423: .CW "/bin
1424: on Plan 9, regardless of the setting in the environment.
1425: Furthermore, functions are not initialized from the environment.
1426: This provides a ``protected environment'' in which it is
1427: difficult for malicious users to subvert an
1428: .I rc
1429: script by placing Trojan-horse versions of commands in
1430: the environment or an unprotected directory. On Plan 9 this is
1431: not much use, since the meaning of all names, including those in
1432: .CW /bin ,
1433: is determined by the user.
1434: .TP -v
1435: Echo input on file descriptor 2 (diagnostic output) as it is read.
1436: Useful for clarifying syntax problems in
1437: .I rc
1438: scripts.
1439: .TP -x
1440: Print each simple command on diagnostic output before executing it.
1441: Useful for debugging
1442: .I rc
1443: scripts.
1444: .PP
1445: The following flags are useful primarily for debugging
1446: .I rc .
1447: .TP -d
1448: Causes
1449: .I rc
1450: only to catch
1451: .CW SIGINT ,
1452: so that
1453: .CW SIGQUIT
1454: will cause it to dump core.
1455: .TP -r
1456: .I Rc 's
1457: interpreter will print a running commentary on its state.
1458: This is useful only for debugging
1459: .I rc .
1460: .TP -V
1461: Echo input on diagnostic output as it is read, including
1462: .CW rcmain ,
1463: which is normally suppressed when using
1464: .CW -v .
1465: .NH
1466: Examples \(em \fIcd, pwd\fP
1467: .PP
1468: Here is a pair of functions that provide
1469: enhanced versions of the standard
1470: .CW cd
1471: and
1472: .CW pwd
1473: commands. (Thanks to Rob Pike for these.)
1474: .P1
1475: ps1='% ' # default prompt
1476: tab=' ' # a tab character
1477: fn pbd{
1478: /bin/pwd|sed 's;.*/;;'
1479: }
1480: fn cd{
1481: builtin cd $1 &&
1482: switch($#*){
1483: case 0
1484: dir=$home
1485: prompt=($ps1 $tab)
1486: case *
1487: switch($1)
1488: case /*
1489: dir=$1
1490: prompt=(`{pbd}^$ps1 $tab)
1491: case */* ..*
1492: dir=()
1493: prompt=(`{pbd}^$ps1 $tab)
1494: case *
1495: dir=()
1496: prompt=($1^$ps1 $tab)
1497: }
1498: }
1499: }
1500: fn pwd{
1501: if(~ $#dir 0)
1502: dir=`{/bin/pwd}
1503: echo $dir
1504: }
1505: .P2
1506: Function
1507: .CW pwd
1508: is a version of the standard
1509: .CW pwd
1510: that caches its value in variable
1511: .CW $dir ,
1512: because the genuine
1513: .CW pwd
1514: can be quite slow to execute.
1515: .PP
1516: Function
1517: .CW pbd
1518: is a helper that prints the last component of a directory name.
1519: Function
1520: .CW cd
1521: calls the
1522: .CW cd
1523: built-in, and checks that it was successful.
1524: If so, it sets
1525: .CW $dir
1526: and
1527: .CW $prompt .
1528: The prompt will include the last component of the
1529: current directory (except in the home directory,
1530: where it will be null), and
1531: .CW $dir
1532: will be reset either to the correct value or to
1533: .CW () ,
1534: so that the
1535: .CW pwd
1536: function will work correctly.
1537: .NH
1538: Examples \(em \fIman\fP
1539: .PP
1540: The
1541: .I man
1542: command prints pages from of the UNIX Programmer's Manual.
1543: It is called, for example, as
1544: .P1
1545: man 3 isatty
1546: man rc
1547: man -t cat
1548: .P2
1549: In the first case, the page for
1550: .I isatty
1551: in section 3 is printed.
1552: In the second case, the manual page for
1553: .I rc
1554: is printed. Since no manual section is specified,
1555: all sections are searched for the page, and it is found
1556: in section 1.
1557: In the third case, the page for
1558: .I cat
1559: is typeset (the
1560: .CW -t
1561: option).
1562: .P1
1563: cd /n/bowell/usr/man || {
1564: echo $0: Manual not on line! >[1=2]
1565: exit 1
1566: }
1567: NT=n # default nroff
1568: s='*' # section, default try all
1569: for(i) switch($i){
1570: case -t
1571: NT=t
1572: case -n
1573: NT=n
1574: case -*
1575: echo Usage: $0\e
1576: '[-nt] [section] page ...' >[1=2]
1577: exit 1
1578: case [1-9] 10
1579: s=$i
1580: case *
1581: eval 'pages=man'$s/$i'.*'
1582: for(page in $pages){
1583: if(test -f $page)
1584: $NT^roff -man $page
1585: if not
1586: echo $0: $i not found >[1=2]
1587: }
1588: }
1589: .P2
1590: Note the use of
1591: .CW eval
1592: to make a list of candidate manual pages.
1593: Without
1594: .CW eval ,
1595: the
1596: .CW *
1597: stored in
1598: .CW $s
1599: would not trigger filename matching
1600: \(em it's enclosed in quotation marks,
1601: and even if it weren't, it would be expanded
1602: when assigned to
1603: .CW $s .
1604: Eval causes its arguments
1605: to be re-processed by
1606: .I rc 's
1607: parser and interpreter, effectively delaying
1608: evaluation of the
1609: .CW *
1610: until the assignment to
1611: .CW $pages .
1612: .NH
1613: Examples \(em \fIholmdel\fP
1614: .PP
1615: The following
1616: .I rc
1617: script plays the deceptively simple game
1618: .I holmdel ,
1619: in which the players alternately name Bell Labs locations,
1620: the winner being the first to mention Holmdel.
1621: .KF
1622: .P1
1623: t=/tmp/holmdel$pid
1624: fn read{
1625: $1=`{awk '{print;exit}'}
1626: }
1627: ifs='
1628: \&' # just a newline
1629: fn sigexit sigint sigquit sighup{
1630: rm -f $t
1631: exit
1632: }
1633: cat <<'!' >$t
1634: Allentown
1635: Atlanta
1636: Cedar Crest
1637: Chester
1638: Columbus
1639: Elmhurst
1640: Fullerton
1641: Holmdel
1642: Indian Hill
1643: Merrimack Valley
1644: Morristown
1645: Piscataway
1646: Reading
1647: Short Hills
1648: South Plainfield
1649: Summit
1650: Whippany
1651: West Long Branch
1652: !
1653: while(true){
1654: lab=`{/usr/games/fortune $t}
1655: echo $lab
1656: if(~ $lab Holmdel){
1657: echo You lose.
1658: exit
1659: }
1660: while(read lab
1661: ! grep -i -s $lab $t)
1662: echo No such location.
1663: if(~ $lab [hH]olmdel){
1664: echo You win.
1665: exit
1666: }
1667: }
1668: .P2
1669: .KE
1670: .LP
1671: This script is worth describing in detail
1672: (rather, it would be if it weren't so silly.)
1673: .PP
1674: Variable
1675: .CW $t
1676: is an abbreviation for the name of a temporary file.
1677: Including
1678: .CW $pid
1679: in the names of temporary files insures that their
1680: names won't collide, in case more than one instance
1681: of the script is running at a time.
1682: .PP
1683: Function
1684: .CW read 's
1685: argument is the name of a variable into which a
1686: line gathered from standard input is read.
1687: .CW $ifs
1688: is set to just a newline. Thus
1689: .CW read 's
1690: input is not split apart at spaces, but the terminating
1691: newline is deleted.
1692: .PP
1693: A handler is set to catch
1694: .CW sigint ,
1695: .CW sigquit ,
1696: and
1697: .CW sighup,
1698: and the artificial
1699: .CW sigexit
1700: signal. It just removes the temporary file and exits.
1701: .PP
1702: The temporary file is initialized from a here
1703: document containing a list of Bell Labs locations, and
1704: the main loop starts.
1705: .PP
1706: First, the program guesses a location (in
1707: .CW $lab )
1708: using the
1709: .CW fortune
1710: program to pick a random line from the location list.
1711: It prints the location, and if it guessed Holmdel, prints
1712: a message and exits.
1713: .PP
1714: Then it uses the
1715: .CW read
1716: function to get lines from standard input and validity-check
1717: them until it gets a legal name.
1718: Note that the condition part of a
1719: .CW while
1720: can be a compound command. Only the exit status of the
1721: last command in the sequence is checked.
1722: .PP
1723: Again, if the result
1724: is Holmdel, it prints a message and exits.
1725: Otherwise it goes back to the top of the loop.
1726: .NH
1727: Discussion
1728: .PP
1729: Steve Bourne's
1730: .CW /bin/sh
1731: is extremely well-designed; any successor is bound to
1732: suffer in comparison. I have tried to fix its
1733: best-acknowledged shortcomings and to simplify things
1734: wherever possible, usually by omitting unessential features.
1735: Only when irresistibly tempted have I introduced novel ideas.
1736: Obviously I have tinkered extensively with Bourne's syntax,
1737: that being where his work was most open to criticism.
1738: .PP
1739: The most important principle in
1740: .I rc 's
1741: design is that it's not a macro processor. Input is never
1742: scanned more than once by the lexical and syntactic analysis
1743: code (except, of course, by the
1744: .CW eval
1745: command, whose
1746: .I "raison d'etre
1747: is to break the rule).
1748: .PP
1749: Bourne shell scripts can often be made
1750: to run wild by passing them arguments containing spaces.
1751: These will be split into multiple arguments using
1752: .CW IFS ,
1753: often as inopportune times.
1754: In
1755: .I rc ,
1756: values of variables, including command line arguments, are not re-read
1757: when substituted into a command.
1758: Arguments have presumably been scanned in the parent process, and ought
1759: not to be re-read.
1760: .PP
1761: Why does Bourne re-scan commands after variable substitution?
1762: He needs to be able to store lists of arguments in variables whose values are
1763: character strings.
1764: If we eliminate re-scanning, we must change the type of variables, so that
1765: they can explicitly carry lists of strings.
1766: .PP
1767: This introduces some
1768: conceptual complications. We need a notation for lists of words.
1769: There are two different kinds of concatenation, for strings \(em
1770: .CW $a^$b ,
1771: and lists \(em
1772: .CW "($a $b)" .
1773: The difference between
1774: .CW ()
1775: and
1776: .CW ''
1777: is confusing to novices,
1778: although the distinction is arguably sensible \(em
1779: a null argument is not the same as no argument.
1780: .PP
1781: Bourne also rescans input when doing command substitution.
1782: This is because the text enclosed in back-quotes is not
1783: properly a string, but a command. Properly, it ought to
1784: be parsed when the enclosing command is, but this makes
1785: it difficult to
1786: handle nested command substitutions, like this:
1787: .P1
1788: size=`wc -l \e`ls -t|sed 1q\e``
1789: .P2
1790: The inner back-quotes must be escaped
1791: to avoid terminating the outer command.
1792: This can get much worse than the above example;
1793: the number of
1794: .CW \e 's
1795: required is exponential in the nesting depth.
1796: .I Rc
1797: fixes this by making the backquote a unary operator
1798: whose argument is a command, like this:
1799: .P1
1800: size=`{wc -l `{ls -t|sed 1q}}
1801: .P2
1802: No escapes are ever required, and the whole thing
1803: is parsed in one pass.
1804: .PP
1805: A similar rationale explains why
1806: .I rc
1807: defines signal handlers as though they were functions,
1808: instead of associating a string with each signal, as Bourne does,
1809: with the attendant possibility of getting a syntax error message
1810: in response to typing the interrupt character. Since
1811: .I rc
1812: parses input when typed, it reports errors when you make them.
1813: .PP
1814: For all this trouble, we gain substantial semantic simplifications.
1815: There is no need for the distinction between
1816: .CW $*
1817: and
1818: .CW $@ .
1819: There is no need for four types of quotation, nor the
1820: extremely complicated rules that govern them. In
1821: .I rc
1822: you use quotation marks exactly when you want a syntax character
1823: to appear in an argument.
1824: .CW IFS
1825: is no longer used, except in the one case where it was indispensable:
1826: converting command output into argument lists during command substitution.
1827: .PP
1828: This also avoids an important security hole|reference(reeds loophole).
1829: .I System (3)
1830: and
1831: .I popen (3)
1832: call
1833: .CW /bin/sh
1834: to execute a command. It is impossible to use either
1835: of these routines with any assurance that the specified command will
1836: be executed, even if the caller of
1837: .I system
1838: or
1839: .I popen
1840: specifies a full path name for the command. This can be devastating
1841: if it occurs in a set-userid program.
1842: The problem is that
1843: .CW IFS
1844: is used to split the command into words, so an attacker can just
1845: set
1846: .CW IFS=/
1847: in his environment and leave a Trojan horse
1848: named
1849: .CW usr
1850: or
1851: .CW bin
1852: in the current working directory before running the privileged program.
1853: .I Rc
1854: fixes this by not ever rescanning input for any reason.
1855: .PP
1856: Most of the other differences between
1857: .I rc
1858: and the Bourne shell are not so serious. I eliminated Bourne's
1859: peculiar forms of variable substitution, like
1860: .P1
1861: echo ${a=b} ${c-d} ${e?error}
1862: .P2
1863: because they are little used, redundant and easily
1864: expressed in less abstruse terms.
1865: I deleted the builtins
1866: .CW export ,
1867: .CW readonly ,
1868: .CW break ,
1869: .CW continue ,
1870: .CW read ,
1871: .CW return ,
1872: .CW set ,
1873: .CW times
1874: and
1875: .CW unset
1876: because they seem redundant or
1877: only marginally useful.
1878: .PP
1879: Where Bourne's syntax draws from Algol 68,
1880: .I rc 's
1881: is based on C or Awk. This is harder to defend.
1882: I believe that, for example
1883: .P1
1884: if(test -f junk) rm junk
1885: .P2
1886: is better syntax than
1887: .P1
1888: if test -f junk; then rm junk; fi
1889: .P2
1890: because it is less cluttered with keywords,
1891: it avoids the semicolons that Bourne requires
1892: in odd places,
1893: and the syntax characters better set off the
1894: active parts of the command.
1895: .PP
1896: The one bit of large-scale syntax that Bourne
1897: unquestionably does better than
1898: .I rc
1899: is the
1900: .CW if
1901: statement with
1902: .CW "else
1903: clause.
1904: .I Rc 's
1905: .CW if
1906: has no terminating
1907: .CW fi -like
1908: bracket. As a result, the parser cannot
1909: tell whether or not to expect an
1910: .CW "else
1911: clause without looking ahead in its input.
1912: The problem is that after reading, for example
1913: .P1
1914: if(test -f junk) echo junk found
1915: .P2
1916: in interactive mode,
1917: .I rc
1918: cannot decide whether to execute it immediately and print
1919: .CW $prompt(1) ,
1920: or to print
1921: .CW $prompt(2)
1922: and wait for the
1923: .CW "else
1924: to be typed.
1925: In the Bourne shell, this is not a problem, because the
1926: .CW if
1927: command must end with
1928: .CW fi ,
1929: regardless of whether it contains an
1930: .CW else
1931: or not.
1932: .PP
1933: .I Rc 's
1934: admittedly feeble solution is to declare that the
1935: .CW else
1936: clause is a separate statement, with the semantic
1937: proviso that it must immediately follow an
1938: .CW if ,
1939: and to call it
1940: .CW "if not
1941: rather than
1942: .CW else ,
1943: as a reminder that something odd is going on.
1944: The only noticeable consequences of this is that
1945: the braces are required in the construction
1946: .P1
1947: for(i){
1948: if(test -f $i) echo $i found
1949: if not echo $i not found
1950: }
1951: .P2
1952: and that
1953: .I rc
1954: resolves the ``dangling else'' ambiguity in opposition
1955: to most people's expectations.
1956: .PP
1957: It is remarkable that in the four most recent editions of the UNIX
1958: programmer's manual the Bourne shell grammar described in the manual page
1959: does not admit the command
1960: .CW who|wc .
1961: This is surely an oversight, but it suggests something darker:
1962: nobody really knows what the Bourne shell's grammar is. Even examination
1963: of the source code is little help. The parser is implemented by recursive
1964: descent, but the routines corresponding to the syntactic categories all
1965: have a flag argument that subtly changes their operation depending on the
1966: context.
1967: .I Rc 's
1968: parser is implemented using
1969: .I yacc ,
1970: so I can say precisely what the grammar is \(em it's reproduced in the appendix.
1971: .PP
1972: Its lexical structure is harder to describe.
1973: I would simplify it considerably
1974: except for two things.
1975: There is a lexical kludge to distinguish between parentheses that immediately
1976: follow a word with no intervening spaces and those that don't that I would
1977: eliminate if there were a reasonable pair of characters to use
1978: for subscript brackets. I could also eliminate the insertion of
1979: free carets if users were not adamant about it.
1980: .NH
1981: Acknowledgements
1982: .PP
1983: Rob Pike, Howard Trickey and other Plan 9 users have been insistent, incessant
1984: sources of good ideas and criticism. Some examples in this document are plagiarized
1985: from |reference(bstj shell), as are most of
1986: .I rc 's
1987: good features.
1988: .NH
1989: References
1990: .LP
1991: |reference_placement
1992: .SH
1993: Appendix \(em an
1994: .I rc
1995: grammar
1996: .PP
1997: Below is reproduced
1998: .I rc 's
1999: .I yacc
2000: grammar, extracted directly from the source code, edited only
2001: to remove semantic actions. The grammar describes a single
2002: command. An
2003: .I rc
2004: script is a sequence of zero or more of these.
2005: .PP
2006: In the grammar, the token
2007: .CW WORD
2008: represents either a quoted string or
2009: a non-empty string of characters other
2010: than blank, tab, newline or any of the following:
2011: .P1
2012: # ; & | ^ $ = ` ' { } ( ) < >
2013: .P2
2014: with the proviso that a word that immediately follows a
2015: .CW $
2016: or
2017: .CW $#
2018: ends at the first character that is not alphanumeric or
2019: .CW _
2020: or
2021: .CW * .
2022: .PP
2023: The token
2024: .CW SUB
2025: represents a left parenthesis that follows a
2026: .CW WORD
2027: with no intervening spaces and therefore should be interpreted
2028: as the start of a subscript.
2029: .CW REDIR
2030: represents any of the redirection symbols,
2031: .P1
2032: > >[\fIn\fT]
2033: < <[\fIn\fT]
2034: >> >>[\fIn\fT]
2035: << <<[\fIn\fT]
2036: .P2
2037: .CW PIPE
2038: is any of the pipe symbols
2039: .P1
2040: | |[\fIn\fT] |[\fIn\fT=\fIm\fT]
2041: .P2
2042: .CW DUP
2043: is any of the file-descriptor duplication or closing symbols
2044: .P1
2045: >[\fIn\fT=\fIm\fT] <[\fIn\fT=\fIm\fT] >>[\fIn\fT=\fIm\fT]
2046: >[\fIn\fT=] <[\fIn\fT=] >>[\fIn\fT=]
2047: .P2
2048: .CW ANDAND
2049: stands for
2050: .CW && ,
2051: .CW OROR
2052: stands for
2053: .CW || ,
2054: and
2055: .CW COUNT
2056: stands for
2057: .CW $# .
2058: The other token names stand for or key words, which are lexically
2059: indistinguishable from
2060: .CW WORD s:
2061: .P1
2062: BANG !
2063: FN fn
2064: FOR for
2065: IF if
2066: IN in
2067: NOT not
2068: SUBSHELL @
2069: SWITCH switch
2070: TWIDDLE ~
2071: WHILE while
2072: .P2
2073: .PP
2074: Comments start with
2075: .CW #
2076: and continue to the end of the line, and are deleted by lexical
2077: analysis, which also converts a backslash
2078: .CW \e ) (
2079: followed by a newline into a space, and
2080: inserts free carets whenever a
2081: .CW WORD
2082: is followed by another
2083: .CW WORD
2084: or a
2085: .CW `
2086: or
2087: .CW $ ,
2088: with no intervening spaces.
2089: .PP
2090: Here then is
2091: .I rc 's
2092: grammar. Semantic actions that call function
2093: .CW skipnl
2094: have been included at places where a command
2095: may be continued on a new line.
2096: .br
2097: \X'PARM CT 80'
2098: .KS
2099: .P1
2100: %term FOR IN WHILE IF NOT
2101: %term TWIDDLE BANG SUBSHELL
2102: %term SWITCH FN WORD REDIR DUP
2103: %term PIPE SUB
2104: %left IF WHILE FOR SWITCH ')' NOT
2105: %left ANDAND OROR
2106: %left BANG SUBSHELL
2107: %left PIPE
2108: %left '^'
2109: %right '$' COUNT
2110: %left SUB
2111: %%
2112: rc:
2113: | line '\en'
2114: line: cmd
2115: | cmdsa line
2116: body: cmd
2117: | cmdsan body
2118: cmdsa: cmd ';'
2119: | cmd '&'
2120: cmdsan: cmdsa
2121: | cmd '\en'
2122: brace: '{' body '}'
2123: paren: '(' body ')'
2124: assign: first '=' word
2125: epilog:
2126: | redir epilog
2127: redir: REDIR word
2128: | DUP
2129: cmd:
2130: | brace epilog
2131: | IF paren {skipnl();} cmd
2132: | IF NOT {skipnl();} cmd
2133: | FOR '(' word IN words ')'
2134: {skipnl();} cmd
2135: | FOR '(' word ')'
2136: {skipnl();} cmd
2137: | WHILE paren {skipnl();} cmd
2138: | SWITCH word {skipnl();} brace
2139: | simple
2140: | TWIDDLE word words
2141: | cmd ANDAND cmd
2142: | cmd OROR cmd
2143: | cmd PIPE cmd
2144: | redir cmd %prec BANG
2145: | assign cmd %prec BANG
2146: | BANG cmd
2147: | SUBSHELL cmd
2148: | FN words brace
2149: | FN words
2150: .P2
2151: .KE
2152: .KS
2153: .P1
2154: simple: first
2155: | simple word
2156: | simple redir
2157: first: comword
2158: | first '^' word
2159: word: keyword
2160: | comword
2161: | word '^' word
2162: comword: '$' word
2163: | '$' word SUB words ')'
2164: | COUNT word
2165: | WORD
2166: | '`' brace
2167: | '(' words ')'
2168: | REDIR brace
2169: keyword: FOR|IN|WHILE|IF|NOT
2170: | TWIDDLE|BANG|SUBSHELL|SWITCH
2171: | FN
2172: words:
2173: | words word
2174: .P2
2175: .KE
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.