.\" es.1 -- es manual page ($Revision: 1.1.1.1 $) .\" macros stolen from rc.1 .\"------- .\" Man page portability notes .\" .\" These are some notes on conventions to maintain for greatest .\" portability of this man page to various other versions of .\" nroff. .\" .\" When you want a \ to appear in the output, use \e in the man page. .\" (NOTE this comes up in the rc grammar, where to print out '\n' the .\" man page must contain '\en'.) .\" .\" Evidently not all versions of nroff allow the omission of the .\" terminal " on a macro argument. Thus what could be written .\" .\" .Cr "exec >[2] err.out .\" .\" in true nroffs must be written .\" .\" .Cr "exec >[2] err.out" .\" .\" instead. .\" .\" Use symbolic font names (e.g. R, I, B) instead of the standard .\" font positions 1, 2, 3. Note that for Xf to work the standard .\" font names must be single characters. .\" .\" Not all man macros have the RS and RE requests (I altered the Ds .\" and De macros and the calls to Ds accordingly). .\" .\" Thanks to Michael Haardt (u31b3hs@cip-s01.informatik.rwth-aachen.de) .\" for pointing out these problems. .\" .\" Note that sentences should end at the end of a line. nroff and .\" troff will supply the correct intersentence spacing, but only if .\" the sentences end at the end of a line. Explicit spaces, if given, .\" are apparently honored and the normal intersentence spacing is .\" supressed. .\" .\" DaviD W. Sanderson .\"------- .\" Dd distance to space vertically before a "display" .\" These are what n/troff use for interparagraph distance .\"------- .if t .nr Dd .4v .if n .nr Dd 1v .\"------- .\" Ds begin a display, indented .5 inches from the surrounding text. .\" .\" Note that uses of Ds and De may NOT be nested. .\"------- .de Ds .\" .RS \\$1 .sp \\n(Ddu .in +0.5i .nf .. .\"------- .\" De end a display (no trailing vertical spacing) .\"------- .de De .fi .in .\" .RE .. .\"------- .\" I stole the Xf macro from the -man macros on my machine (originally .\" "}S", I renamed it so that it won't conflict). .\"------- .\" Set Cf to the name of the constant width font. .\" It will be "C" or "(CW", typically. .\" NOTEZ BIEN the lines defining Cf must have no trailing white space: .\"------- .if t .ds Cf C .if n .ds Cf R .\"------- .\" Rc - Alternate Roman and Courier .\"------- .de Rc .Xf R \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" .. .\"------- .\" Ic - Alternate Italic and Courier .\"------- .de Ic .Xf I \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" .. .\"------- .\" Bc - Alternate Bold and Courier .\"------- .de Bc .Xf B \\*(Cf \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" .. .\"------- .\" Cr - Alternate Courier and Roman .\"------- .de Cr .Xf \\*(Cf R \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" .. .\"------- .\" Ci - Alternate Courier and Italic .\"------- .de Ci .Xf \\*(Cf I \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" .. .\"------- .\" Cb - Alternate Courier and Bold .\"------- .de Cb .Xf \\*(Cf B \& "\\$1" "\\$2" "\\$3" "\\$4" "\\$5" "\\$6" .. .\"------- .\" Xf - Alternate fonts .\" .\" \$1 - first font .\" \$2 - second font .\" \$3 - desired word with embedded font changes, built up by recursion .\" \$4 - text for first font .\" \$5 - \$9 - remaining args .\" .\" Every time we are called: .\" .\" If there is something in \$4 .\" then Call ourself with the fonts switched, .\" with a new word made of the current word (\$3) and \$4 .\" rendered in the first font, .\" and with the remaining args following \$4. .\" else We are done recursing. \$3 holds the desired output .\" word. We emit \$3, change to Roman font, and restore .\" the point size to the default. .\" fi .\" .\" Use Xi to add a little bit of space after italic text. .\"------- .de Xf .ds Xi .\"------- .\" I used to test for the italic font both by its font position .\" and its name. Now just test by its name. .\" .\" .if "\\$1"2" .if !"\\$5"" .ds Xi \^ .\"------- .if "\\$1"I" .if !"\\$5"" .ds Xi \^ .\"------- .\" This is my original code to deal with the recursion. .\" Evidently some nroffs can't deal with it. .\"------- .\" .ie !"\\$4"" \{\ .\" . Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" .\" .\} .\" .el \{\\$3 .\" . ft R \" Restore the default font, since we don't know .\" . \" what the last font change was. .\" . ps 10 \" Restore the default point size, since it might .\" . \" have been changed by an argument to this macro. .\" .\} .\"------- .\" Here is more portable (though less pretty) code to deal with .\" the recursion. .\"------- .if !"\\$4"" .Xf \\$2 \\$1 "\\$3\\f\\$1\\$4\\*(Xi" "\\$5" "\\$6" "\\$7" "\\$8" "\\$9" .if "\\$4"" \\$3\fR\s10 .. .\"------- .\" IS, IE -- sublist begin and end .\"------- .de IS .ie \n(.g .RS .el \{\ .nr )R +7m .nr )P -.5v .sp .7v \} .. .de IE .ie \n(.g .RE .el \{\ .nr )R -7m .nr )P +.5v .sp .4v \} .. .TH ES 1 "5 March 1992" .SH NAME es \- extensible shell .SH SYNOPSIS .B es .RB [ \-silevxnpo ] .RB [ \-c .IR command | .IR file ] .RI [ arguments ] .SH DESCRIPTION .I Es is a command interpreter and programming language which combines the features of other Unix shells and the features of a functional programming language such as Scheme. The syntax is derived from .IR rc (1). .I Es is intended for use both as an interactive shell and a programming language for scripts. .PP .I Es is an extremely customizable language. The semantics can be altered radically by redefining functions that are called to implement internal operations. This manual page describes the default, initial configuration. See the section entitled .B "Hook Functions" for details on entry points which can be redefined to give the shell extended semantics. .SH LANGUAGE .I Es is an interpreter which reads commands and executes them. The simplest form of command in .I es is a sequence of words separated by white space (space and tab) characters. A word is either a string or a program fragment (see below). The first word is the command to be executed; the remaining words are passed as arguments to that command. If the first word is a string, it is a interpreted as the name of a program or shell function to run. If the name is the name of a shell function, that function is executed. Otherwise, the name is used as the name of an executable file. If the name begins with .Cr / , .Cr ./ , or .Cr ../ , then it is used as the absolute path name of a file; if not, .I es looks for an executable file in the directories named by .Cr $path . .PP Commands are terminated by newline or semicolon .Rc ( ; ). A command may also be terminated by an ampersand .Rc ( & ), which causes the command to be run in the background: the shell does not wait for the command to finish before continuing execution. Background processes have an implicit redirection of .Cr /dev/null as their standard input that may be overridden by an explicit redirection. .SS Quoting .IR Es gives several characters special meaning; special characters automatically terminate words. The following characters, along with space, tab, and newline, are special: .Ds .Cr "# $ & \' ( ) ; < = > \e ^ \` { | }" .De .PP The single quote .Rc ( ' ) prevents special treatment of any character other than itself. Any characters between single quotes, including newlines, backslashes, and control characters, are treated as an uninterpreted string. A quote character itself may be quoted by placing two quotes in a row. A single quote character is therefore represented by the sequence .Cr '''' . The empty string is represented by .Cr '' . Thus: .Ds .Cr "echo 'What''s the plan, Stan?'" .De .PP prints out .Ds .Cr "What's the plan, Stan?" .De .PP The backslash .Cr ( \e ) quotes the immediately following character, if it is one of the special characters, except for newline. In addition, .IR es recognizes backslash sequences similar to those used in C strings: .IS .TP .Cr \ea alert (bell) .TP .Cr \eb backspace .TP .Cr \ee escape .TP .Cr \ef form-feed .TP .Cr \en newline .TP .Cr \er carriage return .TP .Cr \et tab .TP .Ci \ex nn hexadecimal character .IR nn .TP .Ci \e nnn octal character .IR nnn .IE .SS Comments The number sign .Rc ( # ) begins a comment in .IR es . All characters up to but not including the next newline are ignored. .SS "Line continuation" A long logical line may be continued over several physical lines by terminating each line (except the last) with a backslash .Rc ( \e ). The backslash-newline sequence is treated as a space. Note that line continuation does not work in comments, where the backslash is treated as part of the comment, and inside quoted strings, where the backslash and newline are quoted. .SS Lists The primary data structure in .IR es is the list, which is a sequence of words. Parentheses are used to group lists. The empty list is represented by .Cr "()" . Lists have no hierarchical structure; a list inside another list is expanded so that the outer list contains all the elements of the inner list. Thus, the following are all equivalent: .Ds .Cr "one two three" .Cr "(one two three)" .Cr "((one) () ((two three)))" .De .PP Note that the null string, .Cr "''" , and the empty list, .Cr "()" , are two very different things. Assigning the null string to variable is a valid operation, but it does not remove its definition. .SS Concatenation Two lists may be joined by the concatenation operator .Rc ( ^ ). A single word is a list of length one, so .Ds .Cr "echo foo^bar" .De .PP produces the output .Ds .Cr foobar .De .PP For lists of more than one element, concatenation produces the cross (Cartesian) product of the elements in both lists: .Ds .Cr "echo (a\- b\- c\-)^(1 2)" .De .PP produces the output .Ds .Cr "a\-1 a\-2 b\-1 b\-2 c\-1 c\-2" .De .SS "Variables" A list may be assigned to a variable, using the notation: .Ds .Ic var " = " list .De .PP Any sequence of non-special characters, except a sequence including only digits, may be used as a variable name. .I Es exports all user-defined variables into the environment unless it is explicitly told not to. .PP The value of a variable is referenced with the notation: .Ds .Ci $ var .De .PP Any variable which has not been assigned a value returns the empty list when referenced. In addition, multiple references are allowed: .Ds .Cr "a = foo" .Cr "b = a" .Cr "echo $$b" .De .PP prints .Ds .Cr foo .De .PP A variable's definition may also be removed by assigning the empty list to a variable: .Ds .Ic var = .De .PP Multiple variables may be assigned with a single assignment statment. The left hand side of the assignment operation consists of a list of variables which are assigned, one by one, to the values in the list on the right hand side. If there are more variables than values in the list, the empty list is assigned to the remaining variables. If there are fewer variables than elements in the list, the last variable is bound to all the remaining list values. .PP For example, .Ds .Cr "(a b) = 1 2 3" .De .PP has the same effect as .Ds .Cr "a = 1" .Cr "b = 2 3" .Ds .PP and .Ds .Cr "(a b c) = 1 2" .De .PP is the same as .Ds .Cr "a = 1" .Cr "b = 2" .Cr "c =" .Ds .PP Note that when assigning values to more than one variable, the list of variables must be enclosed in parentheses. .PP For ``free careting'' (see below) to work correctly, .I es must make certain assumptions about what characters may appear in a variable name. .I Es assumes that a variable name consists only of alphanumeric characters, percent .Rc ( % ), star .Rc ( * ), dash .Rc ( - ), and underscore .Rc ( \|_\| ). To reference a variable with other characters in its name, quote the variable name. Thus: .Ds .Cr "echo $'we$Ird\Variab!le'" .De .PP A variable name produced by some complex operation, such as concatenation, should be enclosed in parentheses: .Ds .Ci $( var ) .De .PP Thus: .Ds .Cr "Good\-Morning = Bonjour" .Cr "Guten = Good" .Cr "Morgen = Morning" .Cr "echo $($Guten^\-^$Morgen)" .De .PP prints .Ds .Cr "Bonjour" .De .PP Each element of the list in parentheses is treated as an independent variable and expanded separately. Thus, given the above definitions, .Ds .Cr "echo $(Guten Morgen)" .De .PP prints .Ds .Cr "Good Morning" .De .PP To count the number of elements in a variable, use .Ds .Ci $# var .De .PP This returns a single-element list with the number of elements in .Ci $ var\fR. .SS Subscripting Variables may be indexed with the notation .Ds .Ci $ var ( n ) .De .PP where .I n is a list of integers or ranges. Subscript indexes are based at one. The list of subscripts need not be in order or even unique. Thus, if .Ds .Cr "a = one two three" .De .PP then .Ds .Cr "echo $a(3 3 3)" .De .PP prints .Ds .Cr "three three three" .De .PP Subscript indices which refer to nonexistent elements expand to the empty list. Thus, given the definition above .Ds .Cr "echo $a(3 1 4 1 5 9 2 6 5)" .De .PP prints .Ds .Cr "three one one two" .De .PP Subscript ranges are of the form .Ic lo ... hi and refer to all the elements between .I lo and .IR hi . If .I lo is omitted, then .Cr 1 is used as a default value; if .I hi is omitted, the length of the list is used. Thus .Ds .Cr "* = $*(2 ...)" .De .PP removes the first element of .Cr * , similar to the effect of .Cr shift in .IR rc (1) or .IR sh (1). .PP The notation .Ci "$" n\fR, where .I n is an integer, is a shorthand for .Ci $*( n )\fR. Thus, .IR es 's arguments may be referred to as .Cr "$1" , .Cr "$2" , and so on. .PP Note that the list of subscripts may be given by any .IR es expression, so .Ds .Cr "$var(\`{awk 'BEGIN{for(i=1;i<=10;i++)print i;exit }'})" .De .PP returns the first 10 elements of .Cr $var . .SS "Free Carets" .I Es inserts carets (concatenation operators) for free in certain situations, in order to save some typing on the user's behalf. For example, the following are all equivalent: .Ds .Cr "cc \-O \-g \-c malloc.c alloca.c" .Cr "cc \-^(O g c) (malloc alloca)^.c" .Cr "opts=O g c; files=malloc alloca; cc \-$opts $files.c" .De .PP .I Es inserts a free-caret between the .Rc `` \- '' and .Cr "$opts" , as well as between .Cr $files and .Cr ".c" . The rule for free carets is as follows: if a word or keyword is immediately followed by another word, keyword, dollar-sign or backquote without any intervening spaces, then .I es inserts a caret between them. .SS "Flattened Lists" To create a single-element list from a multi-element list, with the components space-separated, use .Ds .Ci $^ var .De .PP Flattening is useful when the normal list concatenation rules need to be bypassed. For example, to append a single period at the end of .Cr $path , use: .Ds .Cr "echo $^path." .De .SS "Wildcard Expansion" .I Es expands wildcards in filenames if possible. When the characters .Cr "*" , .Cr [ or .Cr ? occur in an argument or command, .I es looks at the argument as a pattern for matching against files. (Contrary to the behavior some other shells exhibit, .I es will only perform pattern matching if a metacharacter occurs unquoted and literally in the input. Thus, .Ds .Cr "foo = '*'" .Cr "echo $foo" .De .PP will always echo just a star. In order for non-literal metacharacters to be expanded, an .Cr eval statement must be used in order to rescan the input.) Pattern matching occurs according to the following rules: a .Cr "*" matches any number (including zero) of characters. A .Cr ? matches any single character, and a .Cr [ followed by a number of characters followed by a .Cr ] matches a single character in that class. The rules for character class matching are the same as those for .IR ed (1), with the exception that character class negation is achieved with the tilde .Rc ( ~ ), not the caret .Rc ( ^ ), since the caret already means something else in .IR es . The filename component separator, slash .Rc ( / ), must appear explicitly in patterns. .Cr "*" and .Cr ? do not match a dot character .Rc ( . ) at the beginning of a filename component. .PP A tilde .Rc ( ~ ) as the first character of an argument is used to refer to home directories. A tilde alone or followed by a slash .Rc ( / ) is replaced by the value of .Cr $home , which is usually the home directory of the current user. A tilde followed by a username is replaced with the home directory of that user, according to .IR getpwent (3). .SS "Pattern Matching" The tilde .Rc ( ~ ) operator is used in .I es for matching strings against wildcard patterns. The command .Ds .Cr "~ \fIsubject\fP \fIpattern\fP \fIpattern\fP ..." .De .PP returns a true value if and only if the subject matches any of the patterns. The matching follows the same rules as wildcard expansion, except that slashes .Rc ( / ) are not considered significant, leading dots .Rc ( . ) do not have to be matched explicitly, and home directory expansion does not occur. Thus .Ds .Cr "~ foo f*" .De .PP returns zero (true), while .Ds .Cr "~ (bar baz) f*" .De .PP returns one (false). The null list is matched by the null list, so .Ds .Cr "~ $foo ()" .De .PP checks to see whether .Cr $foo is empty or not. This may also be achieved by the test .Ds .Cr "~ $#foo 0" .De .PP Note that inside a .Cr ~ command .I es does not match patterns against file names, so it is not necessary to quote the characters .Cr "*" , .Cr [ and .Cr "?" . However, .I es does expand the subject against filenames if it contains metacharacters. Thus, the command .Ds .Cr "~ * ?" .De .PP returns true if any of the files in the current directory have a single-character name. Note that if the .Cr ~ command is given a list as its first argument, then a successful match against any of the elements of that list will cause .Cr ~ to return true. For example: .Ds .Cr "~ (foo goo zoo) z*" .De .PP is true. .SS "Pattern Extraction" The double-tilde .Rc ( ~~ ) operator is used in .I es for extracting the parts of strings that match patterns. The command .Ds .Cr "~~ \fIsubject\fP \fIpattern\fP \fIpattern\fP ..." .De .PP returns the parts of each matching subject which correspond to the wildcards. .PP Each subject is checked in order against each pattern; if it matches the pattern, the parts of the subject which matched each .Cr "*" , .Cr "?" , or .Cr "[]" character range are extracted, and processing moves on to the next subject. If the subject does not match, the next pattern is tried. .PP For example, the result of the extraction operation .Ds .Cr "~~ (foo.c foo.x bar.h) *.[ch]" .De .PP is the list .Cr "(foo c bar h)" . .SS "Command Substitution" A list may be formed from the output of a command by using backquote substitution: .Ds .Ci "\`{" " command " } .De .PP returns a list formed from the standard output of the command in braces. The characters stored in the variable .Cr $ifs (for ``input field separator'') are used to split the output into list elements. By default, .Cr $ifs has the value space-tab-newline. The braces may be omitted if the command is a single word. Thus .Cr \`ls may be used instead of .Cr "\`{ls}" . This last feature is useful when defining functions that expand to useful argument lists. A frequent use is: .Ds .Cr "fn src { echo *.[chy] }" .De .PP followed by .Ds .Cr "wc \`src" .De .PP (This will print out a word-count of all C and Yacc source files in the current directory.) .PP In order to override the value of .Cr $ifs for a single command substitution, use: .Ds .Ci "\`\`" " ifs-list " { " command " } .De .PP .Cr $ifs will be temporarily ignored and the command's output will be split as specified by the list following the double backquote. For example: .Ds .Cr "\`\` :\en {cat /etc/passwd}" .De .PP splits up .Cr /etc/passwd into fields. .SS "Return Values" The return value of a command is obtained with the construct .Ds .Ci "<={" " command " } .De .PP The return value of an external program is its exit status (which in other shells can be found in special variables such as .Cr $? or .Cr $status ), as either a small integer or the name of signal. Thus .Ds .Cr "echo <={test \-f /etc/motd} <={test \-w /vmunix} <=a.out" .De .PP might produce the output .Ds .Cr "0 1 sigsegv+core" .De .PP along with any output or error messages from the programs. .PP .I Es functions and primitives can produce ``rich return values,'' that is, arbitrary lists as return values. .PP When return values are interpreted as truth values, an extension of the normal shell conventions apply. If any element of a list is not equal to .Rc `` 0 '' (or the empty string), that list is considered false. .PP The return value of an assignment operation is the assigned value. .SS "Logical Operators" There are a number of operators in .I es which depend on the exit status of a command. .Ds .Ic command1 " && " command2 .De .PP executes the first command and then executes the second command if and only if the first command has a ``true'' return value. .Ds .Ic command1 " || " command2 .De .PP executes the first command and then executes the second command if and only if the first command has a ``false'' return value. .Ds .Ci ! " command" .De .PP inverts the truth value of the exit status of a command. .SS "Input and output" .PP The standard output of a command may be redirected to a file with .Ds .Cr "command > file" .De .PP and the standard input may be taken from a file with .Ds .Cr "command < file" .De .PP File descriptors other than 0 and 1 may be specified also. For example, to redirect standard error to a file, use: .Ds .Cr "command >[2] file" .De .PP In order to duplicate a file descriptor, use .Ci >[ n = m ]\fR. Thus to redirect both standard output and standard error to the same file, use .Ds .Cr "command > file >[2=1]" .De .PP To close a file descriptor that may be open, use .Ci >[ n =]\fR. For example, to close file descriptor 7: .Ds .Cr "command >[7=]" .De .PP In order to place the output of a command at the end of an already existing file, use: .Ds .Cr "command >> file" .De .PP If the file does not exist, then it is created. .PP To open a file for reading and writing, use the .Cr <> redirection operator; for reading and appending, use .Cr <>> . Both of these operators use file descriptor 0 (standard input) by default. Similarly, .Cr >< truncates a file and opens it for reading and writing, and .Cr >>< opens a file for reading and appending; these operators use file descriptor 1 by default. .PP ``Here documents'' are supported as in .IR sh (1) with the use of .Ds .Cr "command << 'eof-marker'" .De .PP If the end-of-file marker is quoted, then no variable substitution occurs inside the here document. Otherwise, every variable is substituted by its space-separated-list value (see .BR "Flat Lists" , below), and if a .Cr ^ character follows a variable name, it is deleted. This allows the unambiguous use of variables adjacent to text, as in .Ds .Cr $variable^follow .De .PP To include a literal .Cr $ in a here document created with an unquoted end-of-file marker, use .Cr $$ . .PP Additionally, .I es supports ``here strings'', which are like here documents, except that input is taken directly from a string on the command line. Its use is illustrated here: .Ds .Cr "cat <<< 'this is a here string' | wc" .De .PP (This feature enables .I es to export functions that use here documents.) .SS Pipes Two or more commands may be combined in a pipeline by placing the vertical bar .Rc ( \||\| ) between them. The standard output (file descriptor 1) of the command on the left is tied to the standard input (file descriptor 0) of the command on the right. The notation .Ci |[ n = m ] indicates that file descriptor .I n of the left process is connected to file descriptor .I m of the right process. .Ci |[ n ] is a shorthand for .Ci |[ n =0]\fR. As an example, to pipe the standard error of a command to .IR wc (1), use: .Ds .Cr "command |[2] wc" .De .PP The exit status of a pipeline is considered true if and only if every command in the pipeline exits true. .SS "Input/Output Substitution" Some commands, like .IR cmp (1) or .IR diff (1), take their input from named files on the command line, and do not use standard input. It is convenient sometimes to build nonlinear pipelines so that a command like .I cmp can read the output of two commands at once. .I Es does it like this: .Ds .Cr "cmp <{command1} <{command2}" .De .PP compares the output of the two commands. Note: on some systems, this form of redirection is implemented with pipes, and since one cannot .IR lseek (2) on a pipe, commands that use .I lseek will hang. For example, most versions of .I diff seek on their inputs. .PP Data can be sent down a pipe to several commands using .IR tee (1) and the output version of this notation: .Ds .Cr "echo hi there | tee >{sed 's/^/p1 /'} >{sed 's/^/p2 /'}" .De .SS "Program Fragments" .I Es allows the intermixing of code with strings. A program fragment, which is a group of commands enclosed in braces .Rc ( { " and " } ), may be used anywhere a word is expected, and is treated as an indivisible unit. For example, a program fragment may be passed as an argument, stored in a variable, or written to a file or pipe. If a program fragment appears as the first word in a command, it is executed, and any arguments are ignored. Thus the following all produce the same output: .Ds .Cr "{ echo hello, world }" .Cr "{ echo hello, world } foo bar" .Cr "es -c { echo hello, world }" .Cr "x = { echo hello, world }; $x" .Cr "echo { echo hello, world } | es" .Cr "echo { echo hello, world } > foo; es < foo" .De .PP Since program fragments in the first position in a command are executed, braces may be used as a grouping mechanism for commands. For example, to run several commands, with output from all of them redirected to the same file, one can do .Ds .Cr "{ date; ps agux; who } > snapshot" .De .PP In addition, program fragments can continue across multiple physical lines without explicit line continuations, so the above command could also be written: .Ds .Cr "{" .Cr " date" .Cr " ps agux" .Cr " who" .Cr "} > snapshot" .De .PP A .I lambda is a variant on a program fragment which takes arguments. A lambda has the form .Ds .Ci @ " parameters " { " commands " } .De .PP The .I parameters are one or more variable names, to which arguments of the lambda are assigned while the .I commands are run. The first argument is assigned to the first variable, the second to the second, and so on. If there are more arguments than parameters, the last named variable is assigned all the remaining arguments; if there are fewer, the parameters for which there are no arguments are bound to the empty list. If no parameters are listed, the variable named .Cr * is assigned all the arguments of the lambda. Note that .Cr @ is a keyword and not a special character in .IR es , so it must be separated by whitespace from other words. .PP As a small example, .Ds .Cr "@ { echo $* } hi" .De .PP is a complicated way of producing the output .Cr hi . The first word is a function which echoes its arguments, and the second word is the argument to the function, the word .Cr hi . .PP Lambdas, like other program fragments, can appear anywhere in a list. A more complicated example in the same spirit: .Ds .Cr "@ cmd arg { $cmd $arg } @ { echo $* } hi" .De .PP This command executes a lambda which runs its first argument, named .Cr cmd , using its second argument, named .Cr arg , as the argument for the first. The first argument of this function is another lambda, seen previously, and the second argument is the word .Cr hi . .PP These lambda expressions .Ds .Cr "@ a b c { echo $c $b $a } 1 2" .Cr "@ a b c { echo $c $b $a } 1 2 3 4 5" .De .PP produce this output: .Ds .Cr "2 1" .Cr "3 4 5 2 1" .De .SS Functions A function in .I es is introduced with the syntax .Ds .Ci fn " name parameters " { " commands " } " .De .PP If the function name appears as the first word of a command, the commands are run, with the named parameters bound to the arguments to the function. .PP The similarity between functions and lambdas is not coincidental. A function in .I es is a variable of the form .Ci fn\- name\fR. If name for which the appropriate .Cr fn- variable exists is found in the first position of a command, the value of the variable is substituted for the first word. The above syntax for creating functions is equivalent to the variable assignment .Ds .Ci fn\- name " = @" " parameters " "{ \fIcommands\fP }" .De .PP Functions may be deleted with the syntax .Ds .Ci fn " name" .De .PP which is equivalent to the assignment .Ds .Ci fn\- name = .De .PP If, as the most common case, a function variable is bound to a lambda, when the function is invoked, the variable .Cr $0 is bound (dynamically, see below) to the name of the function. .PP Lambdas are just another form of code fragment, and, as such, can be exported in the environment, passed as arguments, etc. The central difference between the two forms is that lambdas bind their arguments, while simple brace-enclosed groups just ignore theirs. .SS "Local Variables" Variable assignments may be made local to a set of commands with the .Cr local construct: .Ds .Cr "local (\fIvar\fP = \fIvalue\fP; \fIvar\fP = \fIvalue ...\fP) \fIcommand\fP" .De .PP The command may be a program fragment, so for example: .Ds .Cr "local (path = /bin /usr/bin; ifs = ) {" .Cr " " ... .Cr "}" .De .PP sets .Cr path to a minimal useful path and removes .Cr ifs for the duration of one long compound command. .PP Local-bound variables are exported into the environment, and will invoke appropriately named settor functions (see below). .SS "Lexically Scoped Variables" In addition to local variables, .I es supports a different form of temporary variable binding, using let-bound, or ``lexically scoped,'' variables. (Lexical scoping is the form of binding used by most compiled programming languages, such as C or Scheme.) A lexically scoped variable is introduced with a .Cr let statement: .Ds .Cr "let (\fIvar\fP = \fIvalue\fP; \fIvar\fP = \fIvalue ...\fP) \fIcommand\fP" .De .PP All references to any of the variables defined in a .Cr let statement by any code located lexically (that is, textually) within the .I command portion of the statement will refer to the let-bound variable rather than any environment or local-bound variable; the immediate text of the .Cr let statement is the complete extent of that binding. That is, lexically bound variables surrounding code fragments follow those code fragments around. .PP An example best shows the difference between .Cr let and .Cr local (also known as ``dynamic'') binding: (note that .Rc `` "; " '' is .IR es 's default prompt.) .Ds .Cr "; x = foo" .Cr "; let (x = bar) {" .Cr " echo $x" .Cr " fn lexical { echo $x }" .Cr "}" .Cr "bar" .Cr "; local (x = baz) {" .Cr " echo $x" .Cr " fn dynamic { echo $x }" .Cr "}" .Cr "baz" .Cr "; lexical" .Cr "bar" .Cr "; dynamic" .Cr "foo" .Cr "; " .De .PP Lexically bound variables are not exported into the environment, and never cause the invocation of settor functions. Function (lambda) parameters are lexically bound to their values. .SS "For loops" The command .Ds .Cr "for (\fIvar\fP = \fIlist\fP) \fIcommand\fP .De .PP Runs the .I command once for each element of the .IR list , with the named variable bound lexically to each element of the list, in order. .PP If multiple bindings are given in the .Cr for statement, the looping occurs in parallel and stops when all lists are exhausted. When one list is finished before the others, the corresponding variable is bound to the empty list for the remaining iterations. Thus the loop .Ds .Cr "for (i = a b c; j = x y) echo $#i $i $#j $j" .De .PP produces the output .Ds .Cr "1 a 1 x" .Cr "1 b 1 y" .Cr "1 c 0" .De .SS "Settor Functions" A settor function is a variable of the form .Ci set- var\fR, which is typically bound to a lambda. Whenever a value is assigned to the named variable, the lambda is invoked with its arguments bound to the new value. While the settor function is running, the variable .Cr $0 is bound to the name of the variable being assigned. The result of the settor function is used as the actual value in the assignment. .PP For example, the following settor function is used to keep the shell variables .Cr home and .Cr HOME synchronized. .Ds .Cr "set-HOME = @ {" .Cr " local (set-home = )" .Cr " home = $*" .Cr " result $*" .Cr "}" .De .PP This settor function is called when any assignment is made to the variable .Cr HOME . It assigns the new value to the variable .Cr home , but disables any settor function for .Cr home to prevent an infinite recursion. Then it returns its argument unchanged for use in the actual assignment to .Cr HOME . .PP Settor functions do not apply to lexically bound variables. .SS Primitives Primitives are internal .I es operations that cannot or should not (for reasons of performance) be written in the interpreter's language. The set of primitives makes up the run-time library for .IR es . .PP Primitives can be used with the syntax .Ds .Ci $& name .De .PP A primitive can be used anywhere a lambda is expected. The list of primitives is returned as the result of running the primitive .Cr $&primitives . .PP For details on specific primitives, see the section entitled .B PRIMITIVES below. .SS Exceptions Exceptions in .I es are used for many forms of non-structured control flow, notably error reporting, signals, and flow of control constructs such as .Cr break and .Cr return . .PP Exceptions are passed up the call chain to catching routines. A catcher may decide to intercept an exception, retry the code that caused the exception, or pass the exception along. There can only be one exception raised at any time. .PP Exceptions are represented by lists. The first word of an exception is, by convention, the type of exception being raised. The following exceptions are known: .TP .Cr "break \fIvalue\fP" Exit from a loop. The return value of the loop is the argument to the exception. .TP .Cr eof Raised by .Cr %parse when the end of input is reached. .TP .Cr "error \fIsource message\fP" A run-time error. Almost all shell errors are reported with the .Cr error exception. The default interactive loop and the outermost level of the interpreter catch this exception and print the message. .I Source is the name of the routine (typically a primitive) which raised the error. .TP .Cr retry When raised from a signal catcher, causes the body of the .Cr catch clause to be run again. .TP .Cr "return \fIvalue\fP" Causes the current function to exit, with .I value as the return value (exit status). .TP .Cr "signal \fIsigname\fP" Raised when the shell itself receives a signal, and the signal is listed in the variable .Cr signals . .I Signame is the name of the signal that was raised. .PP See the builtin commands .Cr catch and .Cr throw for details on how to manipulate exceptions. .SH "SPECIAL VARIABLES" Several variables are known to .I es and are treated specially. Redefining these variables can change interpreter semantics. Note that only dynamically bound (top-level or .Cr local -bound) variables are interpreted in this way; the names of lexically bound variables are unimportant. .TP .Cr * The argument list of .IR es . .Cr "$1, $2," etc. are the same as .Cr $*(1) , .Cr $*(2) , etc. .TP .Cr $0 Holds the value of .Cr argv[0] with which .I es was invoked. Additionally, .Cr $0 is set to the name of a function for the duration of the execution of that function, and .Cr $0 is also set to the name of the file being interpreted for the duration of a .Cr "." " command." .TP .Cr apid The process ID of the last process started in the background. .TP .Cr history The name of a file to which commands are appended as .I es reads them. This facilitates the use of a stand-alone history program (such as .IR history (1)) which parses the contents of the history file and presents them to .I es for reinterpretation. If .Cr history is not set, then .I es does not append commands to any file. .TP .Cr home The current user's home directory, used in tilde .Rc ( ~ ) expansion, as the default directory for the builtin .Cr cd command, and as the directory in which .I es looks to find its initialization file, .Cr .esrc , if .I es has been started up as a login shell. Like .Cr path and .Cr PATH , .Cr home and .Cr HOME are aliased to each other. .TP .Cr ifs The default input field separator, used for splitting up the output of backquote commands for digestion as a list. The initial value of .Cr ifs is space-tab-newline. .TP .Cr noexport A list of variables which .I es will not export. All variables except for the ones on this list and lexically bound variables are exported. .TP .Cr path This is a list of directories to search in for commands. The empty string stands for the current directory. Note also that an assignment to .Cr path causes an automatic assignment to .Cr PATH , and vice-versa. If neither .Cr path nor .Cr PATH are set at startup time, .Cr path assumes a default value suitable for your system. This is typically .Cr "/usr/ucb /usr/bin /bin ''" . .TP .Cr pid The process ID of the currently running .IR es . .TP .Cr prompt This variable holds the two prompts (in list form) that .I es prints. .Cr $prompt(1) is printed before each command is read, and .Cr $prompt(2) is printed when input is expected to continue on the next line. (See .Cr %parse for details.) .I es sets .Cr $prompt to .Cr "('; ' '')" by default. The reason for this is that it enables an .I es user to grab commands from previous lines using a mouse, and to present them to .I es for re-interpretation; the semicolon prompt is simply ignored by .IR es . The null .Cr $prompt(2) also has its justification: an .I es script, when typed interactively, will not leave .Cr $prompt(2) 's on the screen, and can therefore be grabbed by a mouse and placed directly into a file for use as a shell script, without further editing being necessary. .TP .Cr signals Contains a list of the signals which .I es traps. Any signal name which is added to this list causes that signal to raise an .I es exception. For example, to run some commands and make sure some cleanup routine is called even if the user interrupts or disconnects during the script, one can use the form: .Ds .Cr "local (signals = $signals sighup sigint) {" .Cr " catch @ e {" .Cr " cleanup" .Cr " throw $e" .Cr " } {" .Cr " " ... .Cr " }" .Cr "}" .De .TP \& A signal name prefixed by a hyphen .Rc ( - ) causes that signal to be ignored by .I es and all of its child processes, unless one of them resets its handler. A signal prefixed by a slash .Rc ( / ) is ignored in the current shell, but retains default behavior in child processes. In addition, the signal .Cr sigint may be preceeded by the prefix .Rc ( . ) to indicate that normal shell interrupt processing (i.e., the printing of an extra newline) occurs. By default .I es starts up with the values .Ds .Cr ".sigint /sigquit /sigterm" .De .TP \& in .Cr $signals ; other values will be on the list if the shell starts up with some signals ignored. .PP The values of .Cr path and .Cr home are derived from the environment values of .Cr PATH and .Cr HOME if those values are present. This is for compatibility with other Unix programs, such as .IR sh (1). .Cr $PATH is assumed to be a colon-separated list. .SH "SYNTACTIC SUGAR" .I Es internally rewrites much of the syntax presented thus far in terms of calls to shell functions. Most features of .I es that resemble traditional shell features are included in this category. This rewriting occurs at parse time, as commands are recognized by the interpreter. The shell functions that are the results of rewriting are some of the hook functions documented below. .PP The following tables list all of the major rewriting which .I es does, with the forms typically entered by the user on the left and their internal form on the right. There is no reason for the user to avoid using the right-hand side forms, except that they are usually less convenient. To see the internal form of a specific command, a user can run .I es with the .Cr \-n and .Cr \-x options; when invoked in this way, the shell prints the internal form of its commands rather than executing them. .ta 2.3i .SS "Control Flow" .Ds .ft \*(Cf ! \fIcmd\fP %not {\fIcmd\fP} \fIcmd\fP & %background {\fIcmd\fP} \fIcmd1\fP ; \fIcmd2\fP %seq {\fIcmd1\fP} {\fIcmd2\fP} \fIcmd1\fP && \fIcmd2\fP %and {\fIcmd1\fP} {\fIcmd2\fP} \fIcmd1\fP || \fIcmd2\fP %or {\fIcmd1\fP} {\fIcmd2\fP} fn \fIname\fP \fIargs\fP { \fIcmd\fP } fn-^\fIname\fP = @ \fIargs\fP {\fIcmd\fP} .ft R .De .SS "Input/Output Commands" .Ds .ft \*(Cf \fIcmd\fP < \fIfile\fP %open 0 \fIfile\fP {\fIcmd\fP} \fIcmd\fP > \fIfile\fP %create 1 \fIfile\fP {\fIcmd\fP} \fIcmd\fP >[\fIn\fP] \fIfile\fP %create \fIn\fP \fIfile\fP {\fIcmd\fP} \fIcmd\fP >> \fIfile\fP %append 1 \fIfile\fP {\fIcmd\fP} \fIcmd\fP <> \fIfile\fP %open-write 0 \fIfile\fP {\fIcmd\fP} \fIcmd\fP <>> \fIfile\fP %open-append 0 \fIfile\fP {\fIcmd\fP} \fIcmd\fP >< \fIfile\fP %open-create 1 \fIfile\fP {\fIcmd\fP} \fIcmd\fP >>< \fIfile\fP %open-append 1 \fIfile\fP {\fIcmd\fP} \fIcmd\fP >[\fIn\fP=] %close \fIn\fP {\fIcmd\fP} \fIcmd\fP >[\fIm\fP=\fIn\fP] %dup \fIm\fP \fIn\fP {\fIcmd\fP} \fIcmd\fP << tag \fIinput\fP tag %here 0 \fIinput\fP {\fIcmd\fP} \fIcmd\fP <<< \fIstring\fP %here 0 \fIstring\fP {\fIcmd\fP} \fIcmd1\fP | \fIcmd2\fP %pipe {\fIcmd1\fP} 1 0 {\fIcmd2\fP} \fIcmd1\fP |[\fIm\fP=\fIn\fP] \fIcmd2\fP %pipe {\fIcmd1\fP} \fIm\fP \fIn\fP {\fIcmd2\fP} \fIcmd1\fP >{ \fIcmd2\fP } %writeto \fIvar\fP {\fIcmd2\fP} {\fIcmd1\fP $\fIvar\fP} \fIcmd1\fP <{ \fIcmd2\fP } %readfrom \fIvar\fP {\fIcmd2\fP} {\fIcmd1\fP $\fIvar\fP} .ft R .De .SS "Expressions" .Ds .ft \*(Cf $#\fIvar\fP <={%count $\fIvar\fP} $^\fIvar\fP <={%flatten ' ' $\fIvar\fP} \`{\fIcmd args\fP} <={%backquote <={%flatten '' $ifs} {\fIcmd args\fP}} \`\`\fIifs\fP {\fIcmd args\fP} <={%backquote <={%flatten '' \fIifs\fP} {\fIcmd args\fP}} .ft R .De .SH BUILTINS Builtin commands are shell functions that exist at shell startup time. Most builtins are indistinguishable from external commands, except that they run in the context of the shell itself rather than as a child process. Many builtins are implemented with primitives (see above). .PP Some builtin functions have names that begin with a percent character .Rc ( % ). These are commands with some special meaning to the shell, or are meant for use only by users customizing the shell. (This distinction is somewhat fuzzy, and the decisions about which functions have .Cr % -names are somewhat arbitrary.) .PP All builtins can be redefined and extended by the user. .SS "Builtin Commands" .TP .Cr ". \fR[\fP-einvx\fR]\fP \fI file \fR[\fPargs ...\fR]\fP" Reads .I file as input to .I es and executes its contents. The options are a subset of the invocation options for the shell (see below). .TP .Cr "access \fR[\fP-n \fIname\fP\fR]\fP \fR[\fP-1e\fR]\fP \fR[\fP-rwx\fR]\fP \fR[\fP-fdcblsp\fR]\fP \fIpath ...\fP" Tests if the named paths are accessible according to the options presented. Normally, .Cr access returns zero (true) for files which are accessible and a printable error message (which evaluates as false, according to shell rules) for files which are not accessible. If the .Cr \-1 option is used, the name of the first file which the test succeeds for is returned; if the test succeeds for no file, the empty list is returned. However, if the .Cr \-e option was used, .Cr access raises an .Cr error exception. If the .Cr \-n option is used, the pathname arguments are treated as a list of directories, and the .I name option argument is used as a file in those directories .Rc "(i.e., " \-n is used for path searching). .sp 1v The default test is whether a file exists. These options change the test: .IS .TP .Cr \-r Is the file readable (by the current user)? .TP .Cr \-w Is the file writable? .TP .Cr \-x Is the file executable? .sp .7v .TP .Cr \-f Is the file a plain file? .TP .Cr \-d Is the file a directory? .TP .Cr \-c Is the file a character device? .TP .Cr \-b Is the file a block device? .TP .Cr \-l Is the file a symbolic link? .TP .Cr \-s Is the file a socket? .TP .Cr \-p Is the file a named pipe (FIFO)? .IE .TP .Cr "break \fIvalue\fP" Exits the current loop. .I Value is used as the return value for the loop command. .TP .Cr "catch \fIcatcher body\fP" Runs .IR body . If it raises an exception, .IR catcher is run and passed the exception as an argument. .TP .Cr "cd \fR[\fP\fIdirectory\fP\fR]\fP" Changes the current directory to .IR directory . With no argument, .Cr cd changes the current directory to .Cr "$home" . .TP .Cr "echo \fR[\fP-n\fR]\fP \fR[\fP--\fR]\fP \fIargs ...\fP" Prints its arguments to standard output, terminated by a newline. Arguments are separated by spaces. If the first argument is .Cr "\-n" no final newline is printed. If the first argument is .Cr "\-\|\-" , then all other arguments are echoed literally; this is used for echoing a literal .Cr "\-n" . .TP .Cr "eval \fIlist\fP" Concatenates the elements of .I list with spaces and feeds the resulting string to the interpreter for rescanning and execution. .TP .Cr "exec \fIcmd\fP" Replaces .I es with the given command. If the .Cr exec contains only redirections, then these redirections apply to the current shell and the shell does not exit. For example, .Ds .Cr "exec {>[2] err.out}" .De .TP \& places further output to standard error in the file .IR err.out . Unlike some other shells, .I es requires that redirections in an .Cr exec be enclosed in a program fragment. .TP .Cr "exit \fR[\fP\fIstatus\fP\fR]\fP" Causes the current shell to exit with the given exit .IR status . If no argument is given, zero (true) is used. (This is different from other shells, that often use the status of the last command executed.) .TP .Cr "false" Always returns a false (non-zero) return value. .TP .Cr "forever \fIcmd\fP" Runs the command repeatedly, until the shell exits or the command raises an exception. This is equivalent to a .Cr "while {true} {\fIcmd\fP}" loop except that .Cr forever does not catch any exceptions, including .Cr break . .TP .Cr "fork \fIcmd\fP" Runs a command in a subshell. This insulates the parent shell from the effects of state changing operations such as .Cr cd and variable assignments. For example: .Ds .Cr "fork {cd ..; make}" .De .TP \& runs .IR make (1) in the parent directory .Rc ( .. ), but leaves the shell in the current directory. .TP .Cr "if \fR[\fP\fItest then\fR]\fP ... \fR[\fPelse\fR]\fP" Evaluates the command .IR test . If the result is true, the command .I then is run and .Cr if completes. If the result of the test is false, the next .I "test-then" pair is checked, until one where the .I test is true is found. If none of the .IR test s are true, the .I else command is run. .TP .Cr "limit \fR[\fP-h\fR]\fP \fI\fR[\fPresource \fR[\fPvalue\fR]\fP\fR]\fP\fP" Similar to the .IR csh (1) .Cr limit builtin, this command operates upon the resource limits of a process. With no arguments, .Cr limit prints all the current limits; with one argument, .Cr limit prints the named limit; with two arguments, it sets the named limit to the given value. The .Cr \-h flag displays/alters the hard limits. The resources which can be shown or altered are .Cr cputime , .Cr filesize , .Cr datasize , .Cr stacksize , .Cr coredumpsize and .Cr memoryuse . For example: .Ds .Cr "limit coredumpsize 0" .De .TP \& disables core dumps. .TP \& The limit values must either be the word .Rc `` unlimited '' or a number with an optional suffix indicating units. For size limits, the suffixes .Cr k (kilobytes), .Cr m (megabytes), and .Cr g (gigabytes) are recognized. For time limits, .Cr s (seconds), .Cr m (minutes), and .Cr h (hours) are known; in addition, times of the form .Cr "\fIhh\fP:\fImm\fP:\fIss\fP" and .Cr "\fImm\fP:\fIss\fP" are accepted. See .IR getrlimit (2) for details on resource limit semantics. .TP .Cr "newpgrp" Puts .I es into a new process group. This builtin is useful for making .I es behave like a job-control shell in a hostile environment. One example is the NeXT Terminal program, which implicitly assumes that each shell it forks will put itself into a new process group. Note that the controlling tty for the process must be on standard error (file descriptor 2) when this operation is run. .TP .Cr "result \fIvalue ...\fP" Returns its arguments. This is .IR es 's identity function. .TP .Cr "return \fIvalue\fP" Causes the current function to exit, returning the named .IR value . .TP .Cr "throw \fIexception arg ...\fP" Raise the named exception, passing all of the arguments to .Cr throw to the enclosing exception handler. .TP .Cr "time \fIcmd arg ... \fP" Prints, on the shell's standard error, the real, user, and system time consumed by executing the command. .TP .Cr "true" Always returns a true (zero) return value. .TP .Cr "umask \fI\fR[\fPmask\fR]" Sets the current umask (see .IR umask (2)) to the octal .IR mask . If no argument is present, the current mask value is printed. .TP .Cr "unwind-protect \fIbody cleanup\fP" Runs .I body and, when it completes or raises an exception, runs .IR cleanup . .TP .Cr "var \fIvar ...\fP" Prints definitions of the named variables, suitable for being used as input to the shell. .TP .Cr "vars \fR[\fP-vfs\fR]\fP \fR[\fP-epi\fR]\fP" Prints all shell variables, functions, and settor functions (in a form suitable for use as shell input), which match the criteria specified by the options. .IS .TP .Cr \-v variables (that are not functions or settor functions) .TP .Cr \-f functions .TP .Cr \-s settor functions .sp .7v .TP .Cr \-e exported values .TP .Cr \-p private (not exported) values .TP .Cr \-i internal (predefined and builtin) values .sp .7v .TP .Cr \-a all of the above .IE .TP \& If none of .Cr \-v , .Cr \-f ", or" .Cr \-s are specified, .Cr \-v is used. If none of .Cr \-e , .Cr \-p ", or" .Cr \-i are specified, .Cr \-e is used. .TP .Cr "wait \fI\fR[\fPpid\fR]" Waits for the specified .IR pid , which must have been started by .IR es . If no .I pid is specified, waits for any child process to exit. .TP .Cr "whatis \fIprogam ...\fP" For each named .IR program , prints the pathname, primitive, lambda, or code fragment which would be run if the program appeared as the first word of a command. .TP .Cr "while \fItest body\fP" Evaluates the .I test and, if it is true, runs the .I body and repeats. .TP .Cr "%read" Reads from standard input and returns either the empty list (in the case of end-of-file) or a single element string with up to one line of data, including possible redirections. This function reads one character at a time in order to not read more data out of a pipe than it should. The terminating newline (if present) is not included in the returned string. .SS "Hook Functions" A subset of the .Cr % -named functions are known as ``hook functions.'' The hook functions are called to implement some internal shell operations, and are available as functions in order that their values can be changed. Typically, a call to a hook function is from code generated by the syntactic sugar rewritings. .TP .Cr "%and \fIcmd ...\fP" Runs the commands in order, stopping after the first one that has a false return value. Returns the result of the last command run. .TP .Cr "%append \fIfd file cmd\fP" Runs the command with file descriptor .I fd set up to append to the .IR file . .TP .Cr "%background \fIcmd\fP" Runs the command in the background. The shell variable .Cr apid contains the process ID of the background process, which is printed if the shell is interactive (according to .Cr %is-interactive ). .TP .Cr "%backquote \fIseparator cmd\fP" Runs the command in a child process and returns its standard output as a list, separated (with the same rules used in .Cr %split ) into elements according to .IR separator . .TP .Cr %batch-loop Parses commands from the current input source and passes the commands to the function .IR %dispatch , which is usually a dynamically bound identifier. This function catches the exception .Cr eof which causes it to return. This function is invoked by the shell on startup and from the dot .Rc ( . ) and .Cr eval commands, when the input source is not interactive. (See also .Cr %interactive-loop .) .TP .Cr "%close \fIfd cmd\fP" Runs the command with the given file descriptor closed. .TP .Cr "%count \fIlist\fP" Returns the number of arguments to the primitive. .TP .Cr "%create \fIfd file cmd\fP" Runs the command with file descriptor .I fd set up to write to the .IR file . .TP .Cr "%dup \fInewfd oldfd cmd\fP" Runs the command with the file descriptor .I oldfd copied (via .IR dup (2)) to file descriptor .IR newfd . .TP .Cr "%eval-noprint \fIcmd\fP" Run the command. (Passed as the argument to .Cr %batch-loop and .Cr %interactive-loop .) .TP .Cr "%eval-print \fIcmd\fP" Print and run the command. (Passed as the argument to .Cr %batch-loop and .Cr %interactive-loop when the .Cr \-x option is used.) .TP .Cr "%exec-failure \fIfile argv0 args ...\fP" This function, if it exists, is called in the context of a child process if an executable file was found but .IR execve (2) could not run it. If the function returns, an error message is printed and the shell exits, but the function can .Cr exec a program if it thinks it knows what to do. Note that the name of the program appears twice in the arguments to .Cr %exec-failure , once as a filename and once as the first element of the .Cr argv array; in some cases the two will be identical, but in others the former will be a full pathname and the latter will just be the basename. Some versions of .I es may provide a builtin version of this function to handle .Cr #! -style shell scripts if the kernel does not. .TP .Cr "%exit-on-false \fIcmd\fP" Runs the command, and exits if any command (except those executing as the tests of conditional statements) returns a non-zero status. (This function is used as an argument to .Cr %batch-loop and .Cr %interactive-loop when the shell is invoked with the .Cr \-e option.) .TP .Cr "%flatten \fIseparator list\fP" Concatenate the elements of .I list into one string, separated by the string .IR separator . .TP .Cr "%here \fIfd word ... cmd\fP" Runs the command with the .IR word s passed as input on file descriptor .IR fd . .TP .Cr "%home \fR[\fIuser\fR]" Returns the home directory of the named user, or .Cr $home if there are no arguments. .TP .Cr "%interactive-loop" Prompts, parses commands from the current input source and passes the commands to the function .IR %dispatch , which is usually a dynamically bound identifier. This function catches the exception .Cr eof which causes it to return. This function is invoked by the shell on startup and from the dot .Rc ( . ) commands, when the input source is interactive. (See also .Cr %batch-loop .) .TP .Cr "%noeval-noprint \fIcmd\fP" Do nothing. (Passed as the argument to .Cr %batch-loop and .Cr %interactive-loop when the .Cr \-n option is used.) .TP .Cr "%noeval-print \fIcmd\fP" Print but don't run the command. (Passed as the argument to .Cr %batch-loop and .Cr %interactive-loop when the .Cr \-x and .Cr \-n options are used.) .TP .Cr "%not \fIcmd\fP" Runs the command and returns false if its exit status was true, otherwise returns true. .TP .Cr "%one \fIlist\fP" If .I list is one element long, .Cr %one returns its value; otherwise it raises an exception. .Cr %one is used to ensure that redirection operations get passed exactly one filename. .TP .Cr "%open \fIfd file cmd\fP" Runs the command with .I file open for reading on file descriptor .IR fd . .TP .Cr "%open-append \fIfd file cmd\fP" Runs the command with .I file open for reading and appending on file descriptor .IR fd . .TP .Cr "%open-create \fIfd file cmd\fP" Runs the command with .I file open for reading and writing on file descriptor .IR fd . If the file already exists, it is truncated. .TP .Cr "%open-write \fIfd file cmd\fP" Runs the command with .I file open for reading and writing on file descriptor .IR fd . .TP .Cr "%openfile \fImode fd file cmd\fP" Runs the command with .I file opened according to .I mode on file descriptor .IR fd . The modes .Rc ( r , .Cr w , .Cr a , .Cr r+ , .Cr w+ , and .Cr a+ ) have the same meanings in .Cr %openfile as they do in .IR fopen (3). .Cr %openfile is invoked by the redirection hook functions: .Cr %append , .Cr %create , .Cr %open , .Cr %open-append , .Cr %open-create , and .Cr %open-write . .TP .Cr "%or \fIcmd ...\fP" Runs the commands in order, stopping after the first one that has a true return value. Returns the result of the last command run. .TP .Cr "%parse \fIprompt1 prompt2\fP" Reads input from the current input source, printing .I prompt1 before reading anything and .I prompt2 before reading continued lines. Returns a code fragment suitable for execution. Raises the exception .Cr eof on end of input. .TP .Cr "%pathsearch \fIprogram\fP" Looks for an executable file named .I program in the directories listed in .Cr $path . If such a file is found, it is returned; if one is not found, an .Cr error exception is raised. .TP .Cr "%pipe \fIcmd \fP\fR[\fP\fIoutfd infd cmd\fR] ..." Runs the commands, with the file descriptor .I outfd in the left-hand process connected by a pipe to the file descriptor .I infd in the right-hand process. If there are more than two commands, a multi-stage pipeline is created. .TP .Cr "%prompt" Called by .Cr %interactive-loop before every call to .Cr %parse . This function allows the user to provide any actions that he or she may wish to have executed before being prompted (e.g., updating the value of the .Cr prompt variable to contain all or part of the current working directory). .TP .Cr "%readfrom \fIvar input cmd\fP" Runs .I cmd with the variable .I var locally bound to the name of a file which contains the output of running the command .IR input . .TP .Cr "%seq \fIcmd ...\fP" Runs the commands, in order. .TP .Cr "%whatis \fIprogram ...\fP" For each named .IR program , returns the pathname, primitive, lambda, or code fragment which would be run if the program appeared as the first word of a command. .TP .Cr "%writeto \fIvar output cmd\fP" Runs .I cmd with the variable .I var locally bound to the name of a file which is used as the input for the command .IR output . .SS "Utility Functions" These functions are useful for people customizing the shell, may be used by other builtin commands, and probably don't make much sense to replace, though that is always possible. .TP .Cr "%apids" Returns the process IDs of all background processes that the shell has not yet waited for. .TP .Cr "%fsplit \fIseparator \fR[\fIargs ...\fR]" Splits its arguments into separate strings at every occurrence of any of the characters in the string .IR separator . Repeated instances of separator characters cause null strings to appear in the result. (This function is used by some builtin settor functions.) .TP .Cr "%is-interactive" Returns true if the current interpreter context is interactive; that is, if shell command input is currently coming from an interactive user. More precisely, this is true if the innermost enclosing read-eval-print loop is .Cr %interactive-loop rather than .Cr %batch-loop . .TP .Cr "%newfd" Returns a file descriptor that the shell thinks is not currently in use. .TP .Cr "%run \fIprogram argv0 args ...\fP" Run the named program, which is not searched for in .Cr $path , with the argument vector set to the remaining arguments. This builtin can be used to set .Cr argv[0] (by convention, the name of the program) to something other than file name. .TP .Cr "%split \fIseparator \fR[\fPargs ...\fR]" Splits its arguments into separate strings at every occurrence of any of the characters in the string .IR separator . Repeated instances of separator characters are coalesced. Backquote substitution splits with the same rules. .TP .Cr "%var \fIvar ...\fP" For each named variable, returns a string which, if interpreted by .I es would assign to the variable its current value. .SH PRIMITIVES Primitives exist in .I es so that, in the presence of spoofing and redefinitions, there is a way to refer to built-in behaviors. This ability is necessary for the shell to be able to unambiguously refer to itself, but is also useful for users who have otherwise made their environment unnecessary but don't want to kill the current shell. .PP Primitives are referenced with the .Ds .Cr "$&\fIname" .De .PP notation. In this section, the .Rc `` $& '' prefixes will be omitted when primitive names are mentioned. Note that, by convention, primitive names follow C identifier names where .I es variable and function names often contain .Rc `` % '' and .Rc `` - '' characters. .PP The following primitives directly implement the builtin functions with the same names: .ta 1.75i 3.5i .Ds .ft \*(Cf access forever throw catch fork umask echo if wait exec newpgrp exit result .ft R .De .PP In addition, the primitive .Cr dot implements the .Rc `` . '' builtin function. .PP The .Cr cd primitive is used in the implementation of the .Cr cd builtin, but does not understand no arguments to imply .Cr $home . The .Cr vars and .Cr internals primitives are used by the implementation of the .Cr vars builtin. .PP The following primitives implement the hook functions of the same names, with .Rc `` % '' prefixes: .ta 1.75i 3.5i .Ds .ft \*(Cf apids here read close home run count newfd seq dup openfile split flatten parse var fsplit pipe whatis .ft R .De .PP The following primitives implement the similar named hook functions, with .Rc `` % '' prefixes and internal hyphens: .ta 1.75i 3.5i .Ds .ft \*(Cf batchloop exitonfalse isinteractive .ft R .De .PP The .Cr background primitive is used to implement the .Cr %background hook function, but does not print the process ID of the background process or set .Cr $apid . The .Cr backquote primitive is used to implement the .Cr %backquote hook function, but returns the exit status of the child as the first value of its result instead of setting .Cr $bqstatus to it. .PP The following primitives implement the similarly named settor functions: .ta 1.75i 3.5i .Ds .ft \*(Cf sethistory setnoexport setsignals .ft R .De .PP Some primitives are included in .I es conditionally, based on compile-time configuration options. Those primitives, and the functions to which they are bound, are .ta 2i .Ds .ft \*(Cf execfailure %exec-failure limit limit readfrom %readfrom time time writeto %writeto .ft R .De .PP The primitive .Cr resetterminal is if .I es is compiled with support for the .I readline or .I editline libraries. It is used in the implementation of settor functions of the .Cr TERM and .Cr TERMCAP variables to notify the line editing packages that the terminal configuration has changed. .PP Several primitives are not directly associated with other function. They are: .TP .Cr "$&collect" Invokes the garbage collector. The garbage collector in .I es runs rather frequently; there should be no reason for a user to issue this command. .TP .Cr "$&noreturn \fIlambda args ...\fP" Call the .IR lambda , but in such a way that it does not catch the .Cr return exception. This primitive exists in order that some control-flow operations in .I es (e.g., .Cr while and .Cr "&&" ) can be implemented as lambdas rather than primitives. .TP .Cr "$&primitives" Returns a list of the names of es primitives. .TP .Cr "$&version" Returns the current version number and release date for .IR es . .SH OPTIONS .TP .Cr \-c Run the given .IR command , placing the rest of the arguments to .I es in .Cr $* . .TP .Cr \-s Read commands from standard input; i.e., put the first argument to .I es in .Cr $* rather than using it as the name of a file to source. .TP .Cr \-i Force .I es to be an interactive shell. Normally .I es is only interactive if it is run with commands coming from standard input and standard input is connected to a terminal. .TP .Cr \-l Run .Cr $home/.esrc on startup, i.e., be a login shell. .Cr \-l is implied if the name the shell was run under (that is, .Cr argv[0] ) starts with a dash .Rc ( - ). .TP .Cr \-e Exit if any command (except those executing as the tests of conditional statements) returns a non-zero status. .TP .Cr \-v Echo all input to standard error. .TP .Cr \-x Print commands to standard error before executing them. .TP .Cr \-n Turn off execution of commands. This can be used for checking the syntax of scripts. When combined with .Cr \-x , .I es prints the entered command based on the internal (parsed) representation. .TP .Cr \-p Don't initialize functions from the environment. This is used to help make scripts that don't break unexpectedly when the environment contains functions that would override commands used in the script. .TP .Cr \-o Don't open .Cr /dev/null on file descriptors 0, 1, and 2, if any of those descriptors are inherited closed. .TP .Cr \-d Don't trap .Cr SIGQUIT or .Cr SIGTERM . This is used for debugging. .SH FILES .Cr $home/.esrc , .Cr /dev/null .SH BUGS Lexical scope which is shared by two variables (or closures) in a parent shell is split in child shells. .PP The interpreter should be properly tail recursive; that is, tail calls should not consume stack space. .PP .Cr break and .Cr return should have lexical scope. .PP Woe betide the environment string set by some other program to contain either the character control-a or the sequence control-b followed by control-a or control-b. .PP .Cr \-x is not nearly as useful as it should be. .PP Line numbers in error messages refer to the last line parsed, rather than something more useful. .PP Too many creatures have fept in. .PP Please send bug reports to .Cr "haahr@adobe.com" and .Cr "byron@netapp.com" . .SH "SEE ALSO" .IR history (1), .IR rc (1), .IR sh (1), .IR execve (2), .IR getrlimit (2), .IR fopen (3), .IR getpwent (3) .PP Paul Haahr and Byron Rakitzis, .I "Es \(em A shell with higher-order functions," Proceedings of the Winter 1993 Usenix Conference, San Diego, CA. .PP Tom Duff, .I "Rc \(em A Shell for Plan 9 and UNIX Systems," Unix Research System, 10th Edition, Volume 2. (Saunders College Publishing)