RC(1) RC(1) NAME rc, cd, wait, whatis - command language SYNOPSIS rc [ -dilxepv ] [ -c command ] [ file [ arg ... ] ] DESCRIPTION Rc is the Plan 9 shell. It executes command lines read from a terminal or a file or, with the -c flag, from rc's argu- ment list. Command Lines A command line is a sequence of commands, separated by ampersands or semicolons (& or ;) and terminated by a new- line. The commands are executed in sequence from left to right. Rc does not wait for a command followed by & to fin- ish executing before starting the following command. When- ever a command followed by & is executed, its process id is assigned to the rc variable $apid. Whenever a command not followed by & exits normally, the low 8 bits of the argument to its exit(2) call are assigned to the rc variable $status. If it terminates abnormally, $status has value 1000 plus the termination status provided to wait(2). A long command line may be continued on subsequent lines by typing a backslash (\) followed by a newline. This sequence is treated as though it were a blank. Backslash is not oth- erwise a special character. A number-sign (#) and any following characters up to (but not including) the next newline are ignored, except in quo- tation marks. Simple Commands A simple command is a sequence of arguments interspersed with I/O redirections. If the first argument is the name of an rc function or of one of rc's built-in commands, it is executed by rc. Otherwise if the name contains a slash (/), it must be the pathname of the program to be executed. Names containing no slash are searched for in a list of directory names stored in $path. The first executable file of the given name found in a directory in $path is the pro- gram to be executed. The first word of a simple command cannot be a keyword unless it is quoted or otherwise disguised. The keywords are for in while if not switch fn ~ ! @ Arguments and Variables RC(1) RC(1) A number of constructions may be used where 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. 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: # ; & | ^ $ = ` ' { } ( ) < > An unquoted word that contains any of the characters * ? or [, is a pattern for matching against file names. The char- acter * matches any sequence of characters, ? matches any single character and [class] matches any character in the class. If the first character of class is ~, the class is complemented. The class may also contain pairs of charac- ters separated by -, standing for all characters lexically between the two. The character / must appear explicitly in a pattern, as must the first character of the pathname com- ponents . and ... A pattern is replaced by a list of argu- ments, one for each pathname 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, x=/tmp echo $x^/*.c matches /tmp/*.c, rather than matching /*.c and then prepending /tmp. A quoted word is a sequence of characters surrounded by sin- gle quotes ('). A single quote is represented in a quoted word by a pair of quotes (''). Each of the following is an argument. (arguments) The value of a sequence of arguments enclosed in paren- theses 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: echo hi there everybody ((echo) (hi there) everybody) $argument $argument(subscript) The argument after the $ is the name of a variable whose value is substituted. Multiple levels of indi- rection are possible, but of questionable utility. Variable values are lists of strings. If argument is a number n, the value is the nth element of $*, unless $* doesn't have n elements, in which case the value is empty. If 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. RC(1) RC(1) Assignments to variables are described below. $#argument The value is the number of elements in the named vari- able. A variable never assigned a value has zero ele- ments. `{command} rc executes the command and reads its standard output, splitting it into a list of arguments, using characters in $ifs as separators. If $ifs is not otherwise set, its value is ' \t\n'. <{command} >{command} The command is executed asynchronously with its stan- dard 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 con- struction of non-linear pipelines. For example, the following runs two commands old and new and uses cmp to compare their outputs cmp <{old} <{new} This feature does not work on systems that do not sup- port /dev/fd or its equivalent, e.g. on Sunos and Sys- tem V. argument^argument The ^ 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. Free Carets In a most circumstances, rc will insert the ^ operator auto- matically between words that are not separated by white space. Whenever one of $ ' ` follows a quoted or unquoted word or an unquoted word follows a quoted word with no intervening blanks or tabs, a ^ is inserted between the two. If an unquoted word immediately follows a $ and contains a character other than an alphanumeric, underscore, or *, a ^ is inserted before the first such character. Thus cc -$flags $stem.c is equivalent to cc -^$flags $stem^.c I/O Redirections The sequence >file redirects the standard output file (file descriptor 1, normally the terminal) to the named file; >>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 <file, or from RC(1) RC(1) an inline `here document' by the sequence <<eof-marker. The contents of a here document are lines of text taken from the command input stream up to a line containing nothing but the eof-marker, which may be either a quoted or unquoted word. If eof-marker is unquoted, variable names of the form $word have their values substituted from rc's environment. If $word is followed by a caret (^), the caret is deleted. If eof-marker is quoted, no substitution occurs. Redirections may be applied to a file-descriptor other than standard input or output by qualifying the redirection oper- ator with a number in square brackets. For example, the diagnostic output (file descriptor 2) may be redirected by writing cc junk.c >[2]junk. A file descriptor may be redirected to an already open descriptor by writing >[fd0=fd1] or <[fd0=fd1]. Fd1 is a previously opened file descriptor, and fd0 becomes a new copy (in the sense of dup(2)) of it. A file descriptor may be closed by writing >[fd0=] or <[fd0=]. Redirections are executed from left to right. Therefore, cc junk.c >/dev/null >[2=1] and cc junk.c >[2=1] >/dev/null have different effects - the first puts standard output in /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 /dev/null. Compound Commands A pair of commands separated by a pipe operator (|) 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. |[fd] connects the output end of the pipe to file descriptor fd rather than 1. |[fd0=fd1] connects out- put to fd0 of the left command and input to fd1 of the right command. A pair of commands separated by && or || is a command. In either case, the left command is executed and its exit sta- tus examined. If the operator is && the right command is executed if the left command's status is zero. || causes the right command to be executed if the left command's sta- tus is non-zero. The exit status of a command may be inverted (non-zero is changed to zero, zero is changed to one) by preceding it with a !. The | operator has highest precedence, and is left- associative (i.e. binds tighter to the left than the right.) ! has intermediate precedence, and && and || have the lowest RC(1) RC(1) precedence. The unary @ operator, with precedence equal to !, causes its operand to be executed in a subshell. Each of the following is a command. if ( list ) command A list is a sequence of commands, separated by &, ; or newline. It is executed and if its exit status is zero, the command is executed. if not command The immediately preceding command must have been if ( list ) command. If its condition was non-zero, the command is executed. for ( name in arguments ) command for ( name ) command The command is executed once for each argument with that argument assigned to name. If the argument list is omitted, $* is used. while ( list ) command The list is executed repeatedly until its exit status is non-zero. Each time it returns zero status, the command is executed. The empty list always yields zero status. switch(argument){list} The list is searched for simple commands beginning with the word case. (The search is only at the `top level' of the list. That is, cases in nested constructs are not found.) Argument is matched against each word fol- lowing case using the pattern-matching algorithm described above, except that / and the first characters of . and .. need not be matched explicitly. When a match is found, commands in the list are executed up to the next following case command (at the top level) or the closing parenthesis. {list} Braces serve to alter the grouping of commands implied by operator priorities. The body is a sequence of com- mands separated by &, ; or newline. fn name{list} fn name The first form defines a function with the given name. Subsequently, whenever a command whose first argument is name is encountered, the current value of the remainder of the command's argument list will be assigned to $*, after saving its current value, and rc will execute the list. The second form removes name's function definition. fn signal{list} fn signal A function with the name of a signal, in lower case, is defined in the usual way, but called when rc receives RC(1) RC(1) that signal; see signal(2). By default rc exits on receiving any signal, except when run interactively, in which case interrupts and quits normally cause rc to stop whatever it's doing and start reading a new com- mand. The second form causes rc to handle a signal in the default manner. Rc recognizes an artificial sig- nal, sigexit, which occurs when rc is about to finish executing. name=argument command Any command may be preceded by a sequence of assign- ments 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. Built-in Commands These commands are executed internally by rc, usually because their execution changes or depends on rc's internal state. . file ... Execute commands from file. $* is set for the duration to the remainder of the argument list following file. File is searched for using $path. builtin command ... Execute command as usual except that any function named command is ignored. cd [dir] Change the current directory to dir. The default argu- ment is $home. dir is searched for in each of the directories mentioned in $cdpath. eval [arg ...] The arguments are concatenated separated by spaces into a single string, read as input to rc, and executed. exec [command ...] Rc replaces itself with the given (non-built-in) command. exit [status] Exit with the given exit status. If none is given, the current value of $status is used. shift [n] Delete the first n (default 1) elements of $*. umask [octal] Set rc's file-creation mask (see umask(2)) to the given octal value. If no value is given, the current mask value is printed. wait [pid] Wait for the process with the given pid to exit. If no pid is given, all outstanding processes are waited for. whatis name ... Print the value of each name in a form suitable for input to rc. The output is an assignment to any RC(1) RC(1) variable, the definition of any function, a call to builtin for any built-in command, or the completed path name of any executable file. ~ subject pattern ... The subject is matched against each pattern in sequence. If it matches any pattern, $status is set to zero. Otherwise, $status is set to one. Patterns are the same as for file name matching, except that / and the first character of . and .. need not be matched explicitly. The patterns are not subjected to file name matching before the ~ command is executed, so they need not be enclosed in quotation marks. Environment The environment is a list of strings made available to exe- cuting binaries. 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 fol- lowed by = and its value. If the value has more than one component, these are separated by ctrl-a ('\001') charac- ters. The string for a function is just the rc input that defines the function. When rc starts executing it reads variable and function def- initions from its environment. Special Variables The following variables are set or used by rc. $* Set to rc's argument list during initialization. When- ever a . command or a function is executed, the current value is saved and $* receives the new argument list. The saved value is restored on completion of the . or function. $apid Whenever a process is started asynchronously with &, $apid is set to its process id. $home The default directory for cd. Initially, if $home is not set and $HOME is, then $home is set to the value of $HOME. $ifs The input field separators used in backquote substitu- tions. If $ifs is not set in rc's environment, it is initialized to blank, tab and newline. $path The search path used to find commands and input files for the . command. If not set in the environment, it is initialized by path=(. /bin /usr/bin). $pid Set during initialization to rc's process id. $prompt When rc is run interactively, the first component of $prompt is printed before reading each command. The second component is printed whenever a newline is typed RC(1) RC(1) and more lines are required to complete the command. If not set in the environment, it is initialized by prompt=('% ' ' '). $status Set to the low 8 bits of the exit(2) argument of a nor- mally terminating binary (unless started with &), or to 1000 plus the termination status on abnormal termina- tion. ! and ~ also change $status. Its value is used to control execution in &&, ||, if and while commands. When rc exits at end-of-file of its input or on execut- ing an exit command with no argument, $status is its exit status. Invocation If 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 -c below). Subsequent arguments become the initial value of $*. Rc accepts the following command-line flags. -c string Commands are read from string. -d Debugging flag, causes rc only to catch SIGINT, so that SIGQUIT will cause it to dump core. -e Exit if $status is non-zero after executing a simple command. -i If -i is present, or rc is given no arguments and its standard input is a terminal, it runs interactively. Commands are prompted for using $prompt and SIGINT and SIGQUIT are caught and sloughed off. -l If -l is given or the first character of argument zero is -, rc reads commands from $home/.rcrc, if it exists, before reading its normal input. -p A no-op. -v Echo input on file descriptor 2 as it is read. -x Print each simple command before executing it. BUGS It's too slow and too big. There should be away to match patterns against whole lists rather than just single strings. Using ~ to check the value of $status changes $status. Functions that use here documents don't work. Environment entries for variables are kludgy for UNIX com- patibility. Woe betide the imported variable whose value contains a ctrl-a.