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