| SH(2) | System Calls Manual | SH(2) |
Sh - module interface to the shell
include "sh.m";
sh := load Sh Sh->PATH;
Context, Listnode: import sh;
system: fn(drawctxt: ref Draw->Context, cmd: string): string;
run: fn(drawctxt: ref Draw->Context, argv: list of string): string;
parse: fn(s: string): (ref Cmd, string);
cmd2string: fn(c: ref Cmd): string;
list2stringlist: fn(nl: list of ref Listnode): list of string;
stringlist2list: fn(sl: list of string): list of ref Listnode;
Context: adt {
new: fn(drawcontext: ref Draw->Context): ref Context;
get: fn(c: self ref Context,
name: string): list of ref Listnode;
set: fn(c: self ref Context,
name: string,
value: list of ref Listnode);
setlocal: fn(c: self ref Context,
name: string,
value: list of ref Listnode);
envlist: fn(c: self ref Context):
list of (string, list of ref Listnode);
push, pop: fn(c: self ref Context);
copy: fn(c: self ref Context, copyenv: int): ref Context;
run: fn(c: self ref Context,
args: list of ref Listnode,
last: int): string;
addmodule: fn(c: self ref Context, name: string,
mod: Shellbuiltin);
addbuiltin: fn(c: self ref Context, name: string,
mod: Shellbuiltin);
removebuiltin: fn(c: self ref Context, name: string,
mod: Shellbuiltin);
addsbuiltin: fn(c: self ref Context, name: string,
mod: Shellbuiltin);
removesbuiltin: fn(c: self ref Context, name: string,
mod: Shellbuiltin);
fail: fn(c: self ref Context, ename, msg: string);
options: fn(c: self ref Context): int;
setoptions: fn(c: self ref Context, flags, on: int): int;
};
Listnode: adt {
cmd: ref Cmd;
word: string;
};
Cmd: adt {
# private data
};
Shellbuiltin: module {
initbuiltin: fn(ctxt: ref Context, sh: Sh): string;
whatis: fn(ctxt: ref Sh->Context, sh: Sh,
name: string, wtype: int): string;
runbuiltin: fn(ctxt: ref Context, sh: Sh,
cmd: list of ref Listnode,
last: int): string;
runsbuiltin: fn(ctxt: ref Context, sh: Sh,
cmd: list of ref Listnode): list of ref Listnode;
getself: fn(): Shellbuiltin;
};
Sh is a command-line interpreter and a scripting language; it also presents a module interface to allow Limbo modules to access its functionality at a lower level. The Sh module can be used in several different ways. At the simplest level, it can be run as a command-line program; for details of this, see sh (1). The simplest access at the Limbo level is through the system function, which given a draw Context (see draw-context (2)) and a string executes the sh command contained in s and returns its result. It catches any exceptions raised by the command. Almost as simple is run, which runs argv as a command, taking the first word as the command to be executed (it can be a braced block) and giving the rest as arguments, catching any exceptions raised.
Although program arguments are passed to external programs as lists of strings, at the Sh module level, an argument list is held as a list of ref Listnode. A Listnode holds either a simple string, or a braced block that has been parsed by the shell. Sometimes it can hold both; in this case the string and the block both represent the same thing. Parse converts from a string to a Cmd (a braced block). It returns a tuple (cmd, error) where cmd holds the parsed block, and error is non-empty if an error has occurred doing so. Cmd2string performs the opposite conversion; it returns a string that when parsed will yield the same command block it was passed. The utility functions List2stringlist and stringlist2list convert from and to a list of ref Listnode to or from a list of string respectively.
A Context holds all the state information needed by a currently running sh process; this adt holds current values of environment variables and a list of currently loaded modules and builtin commands. It is specific to the process within which it was created. If it is desired to run sh commands in a newly spawned process, a new Context must be created, or a copy of an existing Context made (making sure to synchronise access until the copy has been made).
Options are defined in the innermost scope of ctxt and will be lost when it is popped.
Shellbuiltin specifies the interface to a loadable sh builtin module. Any Limbo module mod adhering to this interface may be loaded into the shell.
The exceptions used within sh are exactly the same as those used within Limbo, except that all exceptions generated by the shell are prefixed by the string ``fail:'', and any exception caught with the prefix fail: has its first 5 characters removed before being made available to the sh script. This adheres to the convention defined by other shells within Inferno that a process that raises an exception with a fail: prefix is just returning a non-zero exit status, and should not be left in a Broken state. It also means that the number of bytes available for the exception string is reduced by 5 (to 59). Care must therefore be taken to avoid generating an exception with a name that is too long; sh takes the pragmatic approach of truncating any exception string that is too long.
/appl/cmd/sh/sh.y