Museum

Home

Lab Overview

Retrotechnology Articles

Online Manuals

⇒ (1) — Plan9 3rd Edition (Vita Nuova)

Media Vault

Software Library

Restoration Projects

Artifacts Sought

Related Articles

mash-tk(1)

mash-make(1)

regex(2)

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 including) the next newline are ignored, except in quotation marks. 
 

Simple Commands

A simple command is a sequence of words interspersed with I/O redirections. 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, splitting 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, splitting 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 alphanumeric, 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 output to the file. The standard input file (file descriptor 0, also normally /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 standard 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 command 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 operator 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. Subsequently, whenever a command whose first word is ­name is encountered, 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 operand 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 associate to the left except ::. 
 

Built-in Commands

 
­Mash supports loadable modules of builtins. The ­Mashbuiltin module definition 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 Mashbuiltin.  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. Initially 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 escaping 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 completes.

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 loadable 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 function. 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 ALSO

mash-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. 

Plan 9  —  June 29, 2000

Typewritten Software • bear@typewritten.org • Edmonds, WA 98026