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