1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
|
.TH RC 1
.SH NAME
rc, cd, eval, exec, exit, flag, rfork, shift, wait, whatis, ., ~ \- command language
.SH SYNOPSIS
.B rc
[
.B -srdiIlxepvV
]
[
.B -c command
]
[
.I file
[
.I arg ...
]]
.SH DESCRIPTION
.I Rc
is the Plan 9 shell.
It executes command lines read from a terminal or a file or, with the
.B -c
flag, from
.I rc's
argument list.
.SS Command Lines
A command line is a sequence of commands, separated by ampersands or semicolons
.RB ( &
or
.BR ; ),
terminated by a newline.
The commands are executed in sequence
from left to right.
.I Rc
does not wait for a command followed by
.B &
to finish executing before starting
the following command.
Whenever a command followed by
.B &
is executed, its process id is assigned to the
.I rc
variable
.BR $apid .
Whenever a command
.I not
followed by
.B &
exits or is terminated, the
.I rc
variable
.B $status
gets the process's wait message (see
.IR wait (3));
it will be the null string if the command was successful.
.PP
A long command line may be continued on subsequent lines by typing
a backslash
.RB ( \e )
followed by a newline.
This sequence is treated as though it were a blank.
Backslash is not otherwise a special character.
.PP
A number-sign
.RB ( # )
and any following characters up to (but not including) the next newline
are ignored, except in quotation marks.
.SS Simple Commands
A simple command is a sequence of arguments interspersed with I/O redirections.
If the first argument is the name of an
.I rc
function or of one of
.I rc's
built-in commands, it is executed by
.IR rc .
Otherwise if the name starts with a slash
.RB ( / ),
it must be the path name of the program to be executed.
Names containing no initial slash are searched for in
a list of directory names stored in
.BR $path .
The first executable file of the given name found
in a directory in
.B $path
is the program to be executed.
To be executable, the user must have execute permission (see
.IR stat (3))
and the file must be either an executable binary
for the current machine's CPU type, or a shell script.
Shell scripts begin with a line containing the full path name of a shell
(usually
.BR /bin/rc ),
prefixed by
.LR #! .
.PP
The first word of a simple command cannot be a keyword unless it is
quoted or otherwise disguised.
The keywords are
.EX
for in while if not switch fn ~ ! @
.EE
.SS Arguments and Variables
A number of constructions may be used where
.I rc's
syntax requires an argument to appear.
In many cases a construction's
value will be a list of arguments rather than a single string.
.PP
The simplest kind of argument is the unquoted word:
a sequence of one or more characters none of which is a blank, tab,
newline, or any of the following:
.EX
# ; & | ^ $ ` ' { } ( ) < >
.EE
An unquoted word that contains any of the characters
.B *
.B ?
.B [
is a pattern for matching against file names.
The character
.B *
matches any sequence of characters,
.B ?
matches any single character, and
.BI [ class ]
matches any character in the
.IR class .
If the first character of
.I class
is
.BR ~ ,
the class is complemented.
The
.I class
may also contain pairs of characters separated by
.BR - ,
standing for all characters lexically between the two.
The character
.B /
must appear explicitly in a pattern, as must the
first character of the path name components
.B .
and
.BR .. .
A pattern is replaced by a list of arguments, one for each path name matched,
except that a pattern matching no names is not replaced by the empty list,
but rather stands for itself.
Pattern matching is done after all other
operations.
Thus,
.EX
x=/tmp echo $x^/*.c
.EE
matches
.BR /tmp/*.c ,
rather than matching
.B "/*.c
and then prefixing
.BR /tmp .
.PP
A quoted word is a sequence of characters surrounded by single quotes
.RB ( ' ).
A single quote is represented in a quoted word by a pair of quotes
.RB ( '' ).
.PP
Each of the following is an argument.
.PD 0
.HP
.BI ( arguments )
.br
The value of a sequence of arguments enclosed in parentheses is
a list comprising the members of each element of the sequence.
Argument lists have no recursive structure, although their syntax may
suggest it.
The following are entirely equivalent:
.EX
echo hi there everybody
((echo) (hi there) everybody)
.EE
.HP
.BI $ argument
.HP
.BI $ argument ( subscript )
.br
The
.I argument
after the
.B $
is the name of a variable whose value is substituted.
Multiple levels
of indirection are possible, but of questionable utility.
Variable values
are lists of strings.
If
.I argument
is a number
.IR n ,
the value is the
.IR n th
element of
.BR $* ,
unless
.B $*
doesn't have
.I n
elements, in which case the value is empty.
If
.I argument
is followed by a parenthesized list of subscripts, the
value substituted is a list composed of the requested elements (origin 1).
The parenthesis must follow the variable name with no spaces.
Subscripts can also take the form
.IB m - n
or
.IB m -
to indicate a sequence of elements.
Assignments to variables are described below.
.HP
.BI $# argument
.br
The value is the number of elements in the named variable.
A variable
never assigned a value has zero elements.
.HP
$"\c
.I argument
.br
The value is a single string containing the components of the named variable
separated by spaces. A variable with zero elements yields the empty string.
.HP
.BI `{ command }
.br
.I rc
executes the
.I command
and reads its standard output, splitting it into a list of arguments,
using characters in
.B $ifs
as separators.
If
.B $ifs
is not otherwise set, its value is
.BR "'\ \et\en'" .
.HP
.BI <{ command }
.HP
.BI >{ command }
.br
The
.I command
is executed asynchronously with its standard output or standard input
connected to a pipe.
The value of the argument is the name of a file
referring to the other end of the pipe.
This allows the construction of
non-linear pipelines.
For example, the following runs two commands
.B old
and
.B new
and uses
.B cmp
to compare their outputs
.EX
cmp <{old} <{new}
.EE
.HP
.BI <>{ command }
.br
The
.I command
is executed asynchronously with its standard input and
output each connected to a pipe. The value of the argument
is a pair of file names referring to the two other ends
of the pipes, in the order corresponding to the symbols
.B <
and
.B >
(first the pipe connected to the command's standard output,
then the pipe connected to its standard input).
.HP
.IB argument ^ argument
.br
The
.B ^
operator concatenates its two operands.
If the two operands
have the same number of components, they are concatenated pairwise.
If not,
then one operand must have one component, and the other must be non-empty,
and concatenation is distributive.
.PD
.SS Free Carets
.I Rc
will insert the
.B ^
operator automatically between words that are not separated by white space.
Thus
.IP
.B cc -$flags $stem.c
.LP
is equivalent to
.IP
.B cc -^$flags $stem^.c
.SS I/O Redirections
The sequence
.BI > file
redirects the standard output file (file descriptor 1, normally the
terminal) to the named
.IR file ;
.BI >> file
appends standard output to the file.
The standard input file (file descriptor 0, also normally the terminal)
may be redirected from a file by the sequence
.BI < file \f1,
or from an inline `here document'
by the sequence
.BI << eof-marker\f1.
The contents of a here document are lines of text taken from the command
input stream up to a line containing nothing but the
.IR eof-marker ,
which may be either a quoted or unquoted word.
If
.I eof-marker
is unquoted, variable names of the form
.BI $ word
have their values substituted from
.I rc's
environment.
If
.BI $ word
is followed by a caret
.RB ( ^ ),
the caret is deleted.
If
.I eof-marker
is quoted, no substitution occurs.
.PP
Redirections may be applied to a file-descriptor other than standard input
or output by qualifying the redirection operator
with a number in square brackets.
For example, the diagnostic output (file descriptor 2)
may be redirected by writing
.BR "cc junk.c >[2]junk" .
.PP
A file descriptor may be redirected to an already open descriptor by writing
.BI >[ fd0 = fd1 ]
or
.BI <[ fd0 = fd1 ]\f1.
.I Fd1
is a previously opened file descriptor and
.I fd0
becomes a new copy (in the sense of
.IR dup (3))
of it.
A file descriptor may be closed by writing
.BI >[ fd0 =]
or
.BI <[ fd0 =]\f1.
.PP
Redirections are executed from left to right.
Therefore,
.B cc junk.c >/dev/null >[2=1]
and
.B cc junk.c >[2=1] >/dev/null
have different effects: the first puts standard output in
.BR /dev/null
and then puts diagnostic output in the same place, where the second
directs diagnostic output to the terminal and sends standard output to
.BR /dev/null .
.SS Compound Commands
A pair of commands separated by a pipe operator
.RB ( | )
is a command.
The standard output of the left command is sent through a pipe
to the standard input of the right command.
The pipe operator may be decorated
to use different file descriptors.
.BI |[ fd ]
connects the output end of the pipe to file descriptor
.I fd
rather than 1.
.BI |[ fd0 = fd1 ]
connects output to
.I fd1
of the left command and input to
.I fd0
of the right command.
.PP
A pair of commands separated by
.B &&
or
.B ||
is a command.
In either case, the left command is executed and its exit status examined.
If the operator is
.B &&
the right command is executed if the left command's status is null.
.B ||
causes the right command to be executed if the left command's status is non-null.
.PP
The exit status of a command may be inverted (non-null is changed to null, null
is changed to non-null) by preceding it with a
.BR ! .
.PP
The
.B |
operator has highest precedence, and is left-associative (i.e. binds tighter
to the left than the right).
.B !
has intermediate precedence, and
.B &&
and
.B ||
have the lowest precedence.
.PP
The unary
.B @
operator, with precedence equal to
.BR ! ,
causes its operand to be executed in a subshell.
.PP
Each of the following is a command.
.PD 0
.HP
.B if (
.I list
.B )
.I command
.br
A
.I list
is a sequence of commands, separated by
.BR & ,
.BR ; ,
or newline.
It is executed and
if its exit status is null, the
.I command
is executed.
.HP
.B if not
.I command
.br
The immediately preceding command must have been
.BI if( list )
.IR command .
If its condition was non-zero, the
.I command
is executed.
.HP
.BI for( name
.B in
.IB arguments )
.I command
.HP
.BI for( name )
.I command
.br
The
.I command
is executed once for each
.IR argument
with that argument assigned to
.IR name .
If the argument list is omitted,
.B $*
is used.
.HP
.BI while( list )
.I command
.br
The
.I list
is executed repeatedly until its exit status is non-null.
Each time it returns null status, the
.I command
is executed.
An empty
.I list
is taken to give null status.
.HP
.BI "switch(" argument "){" list }
.br
The
.IR list
is searched for simple commands beginning with the word
.BR case .
(The search is only at the `top level' of the
.IR list .
That is,
.B cases
in nested constructs are not found.)
.I Argument
is matched against each word following
.B case
using the pattern-matching algorithm described above, except that
.B /
and the first characters of
.B .
and
.B ..
need not be matched explicitly.
When a match is found, commands in the list are executed up to the next
following
.B case
command (at the top level) or the closing brace.
.HP
.BI { list }
.br
Braces serve to alter the grouping of commands implied by operator
priorities.
The
.I body
is a sequence of commands separated by
.BR & ,
.BR ; ,
or newline.
.HP
.BI "fn " name { list }
.HP
.BI "fn " name
.br
The first form defines a function with the given
.IR name .
Subsequently, whenever a command whose first argument is
.I name
is encountered, the current value of
the remainder of the command's argument list will be assigned to
.BR $* ,
after saving its current value, and
.I rc
will execute the
.IR list .
The second form removes
.IR name 's
function definition.
.HP
.BI "fn " note { list }
.br
.HP
.BI "fn " note
.br
A function with a special name will be called when
.I rc
receives a corresponding note; see
.IR notify (3).
The valid note names (and corresponding notes) are
.B sighup
.RB ( hangup ),
.B sigint
.RB ( interrupt ),
.BR sigalrm
.RB ( alarm ),
and
.B sigfpe
(floating point trap).
By default
.I rc
exits on receiving any signal, except when run interactively,
in which case interrupts and quits normally cause
.I rc
to stop whatever it's doing and start reading a new command.
The second form causes
.I rc
to handle a signal in the default manner.
.I Rc
recognizes an artificial note,
.BR sigexit ,
which occurs when
.I rc
is about to finish executing.
.HP
.IB name = "argument command"
.br
Any command may be preceded by a sequence of assignments
interspersed with redirections.
The assignments remain in effect until the end of the command, unless
the command is empty (i.e. the assignments stand alone), in which case
they are effective until rescinded by later assignments.
.PD
.SS Built-in Commands
These commands are executed internally by
.IR rc ,
usually because their execution changes or depends on
.IR rc 's
internal state.
.PD 0
.HP
.BI . " file ..."
.br
Execute commands from
.IR file .
.B $*
is set for the duration to the remainder of the argument list following
.IR file .
.I File
is searched for using
.BR $path .
.HP
.BI builtin " command ..."
.br
Execute
.I command
as usual except that any function named
.I command
is ignored in favor of the built-in meaning.
.HP
.BI "cd [" dir "]"
.br
Change the current directory to
.IR dir .
The default argument is
.BR $home .
.I dir
is searched for in each of the directories mentioned in
.BR $cdpath .
.HP
.BI "eval [" "arg ..." "]"
.br
The arguments are concatenated separated by spaces into a single string,
read as input to
.IR rc ,
and executed.
.HP
.BI "exec [" "command ..." "]"
.br
This instance of
.I rc
replaces itself with the given (non-built-in)
.IR command .
.HP
.BI "flag " f " [+-]"
.br
Either set
.RB ( + ),
clear
.RB ( - ),
or test (neither
.B +
nor
.BR - )
the flag
.IR f ,
where
.I f
is a single character, one of the command line flags (see Invocation, below).
.HP
.BI "exit [" status "]"
.br
Exit with the given exit status.
If none is given, the current value of
.B $status
is used.
.HP
.BR "rfork " [ nNeEsfFm ]
.br
Become a new process group using
.BI rfork( flags )
where
.I flags
is composed of the bitwise OR of the
.B rfork
flags specified by the option letters
(see
.IR fork (2)).
If no
.I flags
are given, they default to
.BR ens .
The
.I flags
and their meanings are:
.B n
is
.BR RFNAMEG ;
.B N
is
.BR RFCNAMEG ;
.B e
is
.BR RFENVG ;
.B E
is
.BR RFCENVG ;
.B s
is
.BR RFNOTEG ;
.B f
is
.BR RFFDG ;
.B F
is
.BR RFCFDG ;
and
.B m
is
.BR RFNOMNT .
.HP
.BI "shift [" n "]"
.br
Delete the first
.IR n
(default 1)
elements of
.BR $* .
.HP
.BI "wait [" pid "]"
.br
Wait for the process with the given
.I pid
to exit.
If no
.I pid
is given, all outstanding processes are waited for.
.HP
.BI whatis " name ..."
.br
Print the value of each
.I name
in a form suitable for input to
.IR rc .
The output is
an assignment to any variable,
the definition of any function,
a call to
.B builtin
for any built-in command, or
the completed pathname of any executable file.
.HP
.BI ~ " subject pattern ..."
.br
The
.I subject
is matched against each
.I pattern
in sequence.
If it matches any pattern,
.B $status
is set to zero.
Otherwise,
.B $status
is set to one.
Patterns are the same as for file name matching, except that
.B /
and the first character of
.B .
and
.B ..
need not be matched explicitly.
The
.I patterns
are not subjected to
file name matching before the
.B ~
command is executed, so they need not be enclosed in quotation marks.
.PD
.SS Environment
The
.I environment
is a list of strings made available to executing binaries by the
kernel.
.I Rc
creates an environment entry for each variable whose value is non-empty,
and for each function.
The string for a variable entry has the variable's name followed by
.B =
and its value.
If the value has more than one component, these
are separated by SOH (001)
characters.
The string for a function is just the
.I rc
input that defines the function.
The name of a function in the environment is the function name
preceded by
.LR fn# .
.PP
When
.I rc
starts executing it reads variable and function definitions from its
environment.
.SS Special Variables
The following variables are set or used by
.IR rc .
.PD 0
.TP \w'\fL$promptXX'u
.B $*
Set to
.IR rc 's
argument list during initialization.
Whenever a
.B .
command or a function is executed, the current value is saved and
.B $*
receives the new argument list.
The saved value is restored on completion of the
.B .
or function.
.TP
.B $apid
Whenever a process is started asynchronously with
.BR & ,
.B $apid
is set to its process id.
.TP
.B $home
The default directory for
.BR cd .
Defaults to
.B $HOME
or else
.LR / .
.TP
.B $ifs
The input field separators used in backquote substitutions.
If
.B $ifs
is not set in
.IR rc 's
environment, it is initialized to blank, tab and newline.
.TP
.B $path
The search path used to find commands and input files
for the
.B .
command.
If not set in the environment, it is initialized by
parsing the
.B $PATH
variable
(as in
.IR sh (1))
or by
.BR "path=(.\ /bin)" .
The variables
.B $path
and
.B $PATH
are maintained together: changes to one will be reflected in the other.
.\" Its use is discouraged; instead use
.\" .IR bind (1)
.\" to build a
.\" .B /bin
.\" containing what's needed.
.TP
.B $pid
Set during initialization to
.IR rc 's
process id.
.TP
.B $prompt
When
.I rc
is run interactively, the first component of
.B $prompt
is printed before reading each command.
The second component is printed whenever a newline is typed and more lines
are required to complete the command.
If not set in the environment, it is initialized by
.BR "prompt=('%\ '\ '\ ')" .
.TP
.B $status
Set to the wait message of the last-executed program.
(unless started with
.BR &).
.B !
and
.B ~
also change
.BR $status .
Its value is used to control execution in
.BR && ,
.BR || ,
.B if
and
.B while
commands.
When
.I rc
exits at end-of-file of its input or on executing an
.B exit
command with no argument,
.B $status
is its exit status.
.PD
.SS Invocation
If
.I rc
is started with no arguments it reads commands from standard input.
Otherwise its first non-flag argument is the name of a file from which
to read commands (but see
.B -c
below).
Subsequent arguments become the initial value of
.BR $* .
.I Rc
accepts the following command-line flags.
.PD 0
.TP \w'\fL-c\ \fIstring\fLXX'u
.BI -c " string"
Commands are read from
.IR string .
.TP
.B -s
Print out exit status after any command where the status is non-null.
.TP
.B -e
Exit if
.B $status
is non-null after executing a simple command.
.TP
.B -i
If
.B -i
is present, or
.I rc
is given no arguments and its standard input is a terminal,
it runs interactively.
Commands are prompted for using
.BR $prompt .
.TP
.B -I
Makes sure
.I rc
is not run interactively.
.TP
.B -l
If
.B -l
is given or the first character of argument zero is
.BR - ,
.I rc
reads commands from
.BR $home/lib/profile ,
if it exists, before reading its normal input.
.TP
.B -p
A no-op.
.TP
.B -d
A no-op.
.TP
.B -v
Echo input on file descriptor 2 as it is read.
.TP
.B -x
Print each simple command before executing it.
.TP
.B -r
Print debugging information (internal form of commands
as they are executed).
.PD
.SH SOURCE
.B \*9/src/cmd/rc
.SH "SEE ALSO"
Tom Duff,
``Rc \- The Plan 9 Shell''.
.SH BUGS
There should be a way to match patterns against whole lists rather than
just single strings.
.PP
Using
.B ~
to check the value of
.B $status
changes
.BR $status .
.PP
Functions that use here documents don't work.
.PP
The
.BI <{ command }
syntax depends on the underlying operating system
providing a file descriptor device tree at
.BR /dev/fd .
.PP
Some FreeBSD installations
does not provide file descriptors greater than 2
in
.BR /dev/fd .
To fix this, add
.IP
.EX
/fdescfs /dev/fd fdescfs rw 0 0
.EE
.LP
to
.BR /etc/fstab ,
and then
.B mount
.BR /dev/fd .
(Adding the line to
.B fstab
ensures causes FreeBSD to mount the file system
automatically at boot time.)
.PP
Some systems require
.B \*9/bin/rc
to be listed in
.B /etc/shells
before it can be used as a login shell.
|