MASH(1)MASH(1)NAME
mash - programmable shell
SYNOPSIS
mash [ -denx ][ -ccommand ] [ file [ arg ... ]]
DESCRIPTION
Mash is an older alternative to the original Inferno shell (now
tiny(1)). Mash is a programmable shell that also allows the definition
of simple dependency rules, resembling those of Unix make. It executes
commands read from standard input or a file or, with the -c flag, from
mash's argument list. Its syntax and semantics are similar to that of
Plan 9's rc.
Invocation
If mash 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 $args. Mash accepts the following command-line
flags.
-c string
Commands are read from string.
-d Dump parsed commands before execution.
-e Fail if a top level command does.
-n Parse but do not execute.
-x Print each simple command before executing it.
If invoked without arguments mash first runs the commands found in
/lib/mashinit.
Command Lines
Each command is terminated with an ampersand or a semicolon (& or ;).
When reading from /dev/cons a newline not escaped with a backslash (\)
is treated as a semicolon. Mash does not wait for a command followed
by & to finish executing before starting the following command.
A number-sign (#) and any following characters up to (but not includ‐
ing) the next newline are ignored, except in quotation marks.
Simple Commands
A simple command is a sequence of words interspersed with I/O redirec‐
tions. If the first word is the name of a mash function or of one of
mash's built-in commands, it is executed by mash. Otherwise, if the
name starts with a slash (/), it must be the path name of a Dis file to
be loaded and executed. Names containing no initial slash are searched
for in the current directory and then in /dis. The .dis extension need
not be supplied.
The keywords are
case else fn for hd if in len rescue tl while
Words and Variables
A number of constructions may be used where mash's syntax requires a
word to appear. In many cases a construction's value will be a list of
strings rather than a single string.
The simplest kind of word 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 character * matches any
sequence of characters, ? matches any single character, and [ class ]
matches any character in the class. The class may also contain pairs of
characters separated by -, standing for all characters lexically
between the two. The character / must appear explicitly in a pattern. A
pattern is replaced by a list of words, 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,
x=/tmp; echo $x^/*.c;
matches /tmp/*.c, rather than matching /*.c and then prefixing /tmp.
A quoted word is a sequence of characters surrounded by single quotes
('). A single quote is escaped with a backslash.
Each of the following is a word.
$identifier
The identifier after the $ is the name of a variable whose value
is substituted. Variable values are lists of strings. It is an
error if the named variable has never been assigned a value.
$number
See the description of rules for the mash-make(1) builtin.
$"identifier
The value is a single string containing the components of the
named variable separated by spaces.
`{commands}
mash executes the commands and reads the standard output, split‐
ting it into a list of words, using the whitespace characters
(space, tab, newline and carriage return) as separators.
"{commands}
mash executes the commands and reads the standard output, split‐
ting it into a list of words, using the whitespace characters
(space, tab, newline and carriage return) as separators.
<{commands}
>{commands}
The commands are executed asynchronously with their standard
output or standard input connected to a pipe. The value of the
word 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 old and new and uses
cmp to compare their outputs
cmp <{old} <{new};
(expr) mash evaluates expr as an expression. The value is a (possibly
null) list of words. Expressions are described in detail below.
word^word
The ^ operator concatenates its two operands. If either operand
is a singleton, the concatenation is distributive. Otherwise the
lists are concatenated pairwise.
Free Carets
In most circumstances, mash will insert the ^ operator automatically
between words that are not separated by white space. Whenever one of $
'or ` (dollar, single quote or back quote) 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 alphanu‐
meric, or underscore, a ^ is inserted before the first such character.
Thus
limbo -$flags $stem.b
is equivalent to
limbo -^$flags $stem^.b
I/O Redirections
The sequence >file redirects the standard output file (file descriptor
1, normally /dev/cons) to the named file; >>file appends standard out‐
put to the file. The standard input file (file descriptor 0, also nor‐
mally /dev/cons) may be redirected from a file by the sequence <file.
The sequence <>file opens the file for read/write and associates both
file descriptor 0 and 1 with it.
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 stan‐
dard input of the right command.
Each of the following is a command.
if ( expr ) command1
if ( expr ) command1 else command2
The expr
is evaluated and if the result is not null, then command1 is
executed. In the second form command2 is executed if the result
is null.
for ( name in list )command
The command is executed once for each word in list with that
word assigned to name.
while ( expr ) command
The expr is evaluated repeatedly until its value is null. Each
time it evaluates to non-null, the command is executed.
case expr { pattern-list => command ... }
case expr-list { pattern => command ... }
In the first form of the command the expr is matched against a
series of lists of regular expressions (See regex(2)). The com‐
mand associated with the matching expression is executed. In
the second form the command associated with the first pattern to
match one of the words in expr-list is executed. An expr-list
will never match a pattern-list.
{commands}
@{commands}
Braces serve to alter the grouping of commands implied by opera‐
tor priorities. The body is a sequence of commands separated by
& or ;. The second form is executed with a new scope. Either
form can be followed by redirections.
fnname{list}
fnname
The first form defines a function with the given name. Subse‐
quently, whenever a command whose first word is name is encoun‐
tered, the current value of the remainder of the command's word
list will be assigned to the local variable args, in a new
scope, and mash will execute the list. The second form removes
name's function definition.
name=list
name:=list
The first form is an assignment to a variable. If the name is
currently defined as a local variable its value will be updated.
Otherwise a global variable with the given name will be defined
or updated. The second form is an explicit definition or update
of a local variable.
list:list
list:list{commands}
word:~word{commands}
These forms define dependencies and rules for the make loadable
builtin. The first form defines a simple dependency, the second
a dependency with an explicit rule. The third form defines an
implicit rule where the left-hand word is a file pattern, the
right-hand word is the prerequisite. The right-hand word and the
commands can contain references to the characters matched by the
* meta-character in the pattern ($1 evaluates to the characters
matched by the first *, $2 the second and so on; $0 is the
entire match).
Expressions
Expressions evaluate to possibly null lists of strings. A word is an
expression. An expression may take one of the following forms
( expr )
Parentheses are used for grouping.
hd expr
tl expr
len expr
! expr
hd is the first element of a list, tl the remainder. len is the
length of a list. Both evaluate to the null list if their oper‐
and is a null list. ! is the not operator and evaluates to
true for a null list or to a null list otherwise.
expr ^ expr
expr :: expr
expr == expr
expr != expr
expr ~ expr
^ is concatenation (as defined above), :: is list concatenation,
== and != are the equality operators evaluating to true or the
null list, depending on the equality or inequality of the two
operands. ~ is the match operator, true if a singleton string
matches one of a list of regular expressions, or one of a list
of strings matches a regular expression. (If neither operand is
a singleton it evaluates to the null list.) ^ has the highest
precedence, followed by :: followed by the other three. All as‐
sociate to the left except ::.
Built-in Commands
Mash supports loadable modules of builtins. The Mashbuiltin module def‐
inition and description is in mash.m. One such module, builtins, is
loaded before mash begins parsing. This module defines the following
commands
env
Print global and local variables. Global variables are displayed
using a name=value format, and local variables using a
name:=value format.
eval
Concatenate arguments and use as mash input.
exit
Cause mash to raise an exit exception.
load file
Load a builtin module. The file must be a module with type Mash‐
builtin. The argument file is assumed to contain a path to the
loadable module. If no such module is found then the string
/dis/lib/mash/ is prepended to file and the load is retried.
prompt
prompttext
prompttext contin
When called with no arguments causes the current value of the
mash prompt to be printed to standard output. The default value
is mash%. The second form sets a new prompt. The final form
sets a new prompt and additionally a continuation string. Ini‐
tially the continuation string is set to a single tab character.
Mash uses the continuation string in place of the prompt string
to indicate that the preceding line has been continued by escap‐
ing with a final backslash (\) character.
quoteargs...
Print arguments quoted as input for mash.
run -[denx] file [arg...]
Interpret a file as input to mash.
timecmd [arg...]
Time the execution of a command. The total execution time is
reported in seconds and on standard error when the command com‐
pletes.
whatisname
Print variable, function or builtin. The object given by name is
described on standard output in a format that reflects its type.
The make loadable builtin provides `make` functionality. The tk load‐
able builtin provides control over some of the visual elements of a
mash window.
Adding Builtins
New builtins can be added to mash by creating a Dis module that can be
loaded with a Mashbuiltin module interface (defined in mash.m). The
new module is loaded with the builtin load command which calls its
mashinit function to initialise it with an argument containing the load
command line. The function should use this call to register the set of
builtins that the module will provide using the Env.defbuiltin func‐
tion. Thereafter, each time one of the registered builtins is invoked
the module's mashcmd function is called passing as an argument a list
containing the invoked builtin name and its arguments. See the examples
in mash/builtins.b, mash/make.b, and mash/tk.b.
FILES
/lib/mashinit
/dis/lib/mash
SOURCE
/appl/cmd/mash
SEE ALSOmash-tk(1), mash-make(1), regex(2)
Tom Duff, ``Rc - The Plan 9 Shell'', in the Plan 9 Programmer's Manual
, Second Edition, Volume 2.
MASH(1)