@DATABASE Shell.guide
@MASTER Shell.guide
@$VER: Shell.guide 45.2 (21.2.2002)
@(C) �2002 by Amiga, Inc., HAAGE&PARTNER and THOR-Software
@SMARTWRAP
@AUTHOR Thomas Richter
@INDEX Index

@NODE MAIN "Shell Guide"

@{b}@{u}@{fg shine}The V45 Shell Manual@{fg text}@{uu}@{ub}


@{"Introduction: What is this about?                                        " link Intro}

@{"New Features: Changes in the V45 Shell                                   " link News}

@{"New commands: Changes in the command set of the V45 Shell                " link Commands}

@{"Shell Syntax: The shell command line language                            " link Language}

@{"History     : What happened before                                       " link History}

@{"Index                                                                    " link Index }

@{BODY}

@ENDNODE
@NODE Intro "Introduction: What is this about?"
@TOC MAIN
The shell, or the CLI how it has been formerly called, is the command line
interpreter of the AmigaOs, and therefore one of the two basic user
interfaces the Amiga has to offer: The graphical Workbench, and the
text-based shell that is opened by the "Shell" icon on the workbench.


The shell reads command lines, one at a time, either from a special
window called "the console" and provided by console handlers like CON: or
ViNCEd, or from a script or "batch" file, of which the "Startup-Sequence" is
the most popular known.


None of this is of course new in the V45 shell, and this guide will not give
a complete introduction into how to use the shell. You'll find examples and
tutorials how to operate the shell in the "AmigaDos" Manual you got with
your computer. However, the shell has been reworked and enhanced a lot with
V45, and a couple of @{"new features" link News}�have been introduced.
Further, @{"new commands" link Commands}�have been added, and old commands
have been enhanced.


This manual also describes the @{"syntax" link Language} of the shell
language as used in batch files and in the console; strictly speaking, the
syntax did not change with V45, or got only enhanced very carefully to
guarantee backwards compatibility, but it has never been written down in
closed form. And, considering how the V40 shell sources used to look like,
has never been programmed in a closed form as well... all this changed in
V45.

@ENDNODE
@NODE NEWS "New V45 Shell features"
Quite some new features have been added in the V45 release of the Shell. The
following will describe these features one after another:


@{"Check variables for existance  : The $? and $?? operators" link VarEx}

@{"Recursive Alias Expansion                                " link RecAlias}

@{"Multiple Backticks                                       " link BackTicks}

@{"Launch commands, job control   : The & operator          " link RunBack}

@{"The revival of the h protection bit                      " link HBit}

@{"Alternative script interpreters: The #! and ;! tokens    " link HashBang}

@{"Datatypes support                                        " link DTypes}

@{"Extended redirection support   : <<, *>, *>> and *><     " link Redirect}

@{"Miscellaneous                  : $STACK: etc...          " link Misc}


A detailed description of @{"Shell Syntax for Experts" link Language} is
also available.

@ENDNODE
@NODE VarEx "Check Variables for Existance"
@TOC NEWS
The V45 shell adds two new operators for variable expansion, "$?" and "$??".
The first is used to check whether a local shell or global environment
variable has been defined, the second checks whether a variable exists as a
global environment definition.


Similar to the V40 Shell, local (shell) or global (environment) variables
are specified on the command line by prepending the variable name with a "$"
sign. Hence,

@{CODE}
echo $a
@{BODY}

prints the contents of the variable "a", should it be defined. Optionally,
the variable name can be enclosed in braces should it contain blanks or
other non-alpha-numeric characters. Hence, the above is equivalent to:

@{CODE}
echo ${a}
@{BODY}


Should "a" be undefined, the "$" sign stands for itself and is not regarded
as a special character: The first example would print "$a" and the second
would "${a}" for undefined a.

The V45 shell offers now a method to check whether a variable exists before
trying to use it. Even though the advanced freak should be able to implement
the very same checks by some trickery without using the new syntax, the V45
method is easier to read and straight-forward: The "$?" operator followed by
a variable name expands to "0" should the variable be undefined, or to "1"
should the variable exist already. The "$??" operator, however, will expand
to "1" only if the following variable name exists as a global environment
variable. It will remain zero for local or undefined variables.

Hence, to elaborate on the above example,

@{CODE}
echo $?a
@{BODY}

prints "0" for a undefined, and "1" otherwise. Similar to above, the braces
can be used to enclose variables of "unusal" names.


@{CODE}
echo $??a
@{BODY}

prints "1" only if "ENV:a" exists, hence a is a global variable.


See also: @{"Details: The variable expansion syntax" link VarSyntax}

@ENDNODE
@NODE RecAlias "Recursive Alias Expansion"
@TOC NEWS
The shell "alias" feature allows the definition of short command "macros"
that builds new commands on top of old. The line

@{CODE}
alias ls list
@{BODY}

defines a new command "ls" that is functional equivalent to "list". Aliases
may also re-arrange arguments, see
@{"Details: Alias syntax" link AliasSyntax}.


In V40 and below, the body of an alias must be a real existing command and
could not be an alias again. In V45, this condition was relaxed and the body
of an alias could be another alias which is recursively expanded:

@{CODE}
alias lq ls quick
@{BODY}

would introduce a new command "lq" that is equivalent to "ls quick", which
is again equivalent to "list quick". The above would not work in V40.


To avoid endless alias expansion should the alias definition contain
circular dependencies, an alias is expanded @{B}at most once@{UB} within one
command line invocation.


Alias expansion is suppressed if the command is enclosed in quotes.
Therefore, quoted commands always refer to executable binaries and never to
aliases.


See also: @{"Details: Alias syntax" link AliasSyntax}

@ENDNODE
@NODE BackTicks "Multiple Backticks"
@TOC NEWS
The Shell backtick operator encloses a command that is executed on
interpretation of a command line and whose output then substitutes the
backtick sequence. For example,

@{CODE}
type `list #?.txt`
@{CODE}

would display the contents of all files in the current directory whose name
ends on ".txt" using the "type" command.

On V40 and below, at most one pair of backticks was expanded on the command
line, the remaining backticks remained unexpanded and were considered as
literal characters. In V45, all backtick sequences are expanded at once.

@{CODE}
type `list #?.txt` `list #?.guide`
@{BODY}

would display all files ending on ".txt" or ".guide". This example would not
work for V40.


@{B}NOTE:@{UB} It might happen that some shell scripts depend on this
feature of the V40 shell by specifying an empty pair of backticks `` to
suppress expansion of a further pair. In V45 (or in V40 as well, as this
method is backwards compatible), add a * in front of a backtick sequence to
suppress its expansion. This is especially of importance should the backtick
be part of an alias:

@{CODE}
alias displaytext type *`list #?.txt*`
@{BODY}

would define an alias that displays the contents of all .txt files. Note
that we must here "escape" the backtick to avoid its expansion for the alias
definition already: The backtick should be part of the alias definition, and
not expanded before the alias is defined.


See also: @{"Details: Backtick syntax" link BackSyntax}

@ENDNODE
@NODE RunBack "The Shell Job Control and the & Operator"
@TOC NEWS
The "&" operator is completely new for the V45 shell; it is a convenient
replacement for the "run" command that launches commands while keeping the
shell available for further command input.

Should the shell find a single & sign on the command line that is not
enclosed in quotes and surrounded by blank spaces, the & gets removed and
the remaining command is "run" almost as if the "run" command has been
placed in front of it. For example,

@{CODE}
MultiView Shell.guide &
@{BODY}

would display this guide by MultiView, returning to the shell immediately.


There are two minor differences between "run" and &, however: The & operator
does not cut the command input stream off, hence the following command line
@{B}will@{UB} get input properly:

@{CODE}
ask "Do you really want to?" &
@{BODY}

If one would have used "run" instead, "ask" wouldn't be able to wait for any
user input.


The second difference between "run" and "&" is that "&" makes use of the
"job control" feature of the ViNCEd console handler. @{B}This feature is
not available for the ROM "CON:" handler.@{UB}


As soon as a program launched with "&" tries to print out a text, it is
stopped and ViNCEd prints a text similar to

@{CODE}
[CLI 8] : ask suspended. [ViNCEd output]
@{BODY}

on its console. The command has been "suspended". You may now move this
command "to foreground" by the "fg" script of the ViNCEd distribution:

@{CODE}
fg 8
@{BODY}

The "8" is here the CLI number found in the suspension message above.


@{B}NOTE:@{UB} The "&" operator prints a runback note onto the console that
is very similar to that of the "run" command. This message is
@{B}not@{UB} printed for execution of "&" within shell scripts, but except
that, the operator works the like.


See also: @{"The & syntax" link RunSyntax}

@ENDNODE
@NODE HBit "The Revival of the h Protection Bit"
@TOC NEWS
The V45 shell makes again use of the "h" protection bit for commands: Should
a command have its "p" (pure) and "h" (hold) bits set at once, it is made
resident on the first invocation of the command as if a "resident" command
has been used. This feature is, strictly speaking, not new as it was
available in the V39 shell as well. It had to be removed in V40 due to
lack of ROM space.

This feature is most useful in the startup-sequence to make commonly used
commands resident automatically. For example, setting the "h" bit for the
"assign" command would load "assign" into RAM as soon as it gets used,
without the need of a "resident assign". This is done by:

@{CODE}
protect C:Assign ph add
@{BODY}


See also: @{"Details: Command Search Path" link ComPath}

@ENDNODE
@NODE HashBang "Alternative Script Interpreters"
@TOC NEWS
Should a file have its "s" (script) bit set, the shell treads this file as a
script file and executes this by the "Execute" command as a shell script.
In V40, ARexx files could be run with this trick as well, provided the first
two characters of the file are "/*", i.e. a Rexx comment. This replaces the
"Execute" command by the "Rx" command and runs the script thru ARexx rather
by the Shell.

V45 enhances this syntax and checks for the special two-character sequence
"#!" or ";!" at the start of a script file as well: If found, the shell
scans the remaining first line of the script file for a file name and
options; the file name is assumed to be the path of the script file
interpreter that is required to run the script. The shell then launches this
interpreter with the name of the script and further arguments found
following the command name on the "#!" or ";!" line as options.


Hence, the following script file would display itself in hexadecimal on the
console:

@{CODE}
;! type hex
Hello World!
@{BODY}


@{B}NOTE:@{UB} The script file name is inserted between the script file
interpreter "type" and the option "hex".


The following more useful example would run the script file thru the
interpreter "perl"

@{CODE}
#! C:Perl
@{BODY}

and the following would be equivalent to the old shell behaviour, making use
of the "Execute" command:

@{CODE}
;! Execute
@{BODY}

Note that ";" is the shell comment introducer.


See also: @{"Details: Command Search Path" link ComPath}

@ENDNODE
@NODE DTypes "DataTypes Support"
@TOC NEWS
The V45 shell is aware of the Amiga DataTypes system and can be setup to
display data types automatically. For that, the file to be displayed
@{B}must have its "e" (executable) bit cleared@{UB} and must be of a data
type that is known to the system. Further, the variable "$VIEWER" must be
set to the path of a command that is able to display data types.

In a typical application, this would be "MultiView", of course. The
following command is suitable to enable this feature permanently:

@{CODE}
SetENV SAVE VIEWER MultiView
@{BODY}

Then, this guide for example can be viewed with the one and only command

@{CODE}
Shell.guide
@{BODY}


@{B}NOTE:@{UB} Unfortunately, it is rather usual that editors and archivers
save files with the "e" bit set, failing to identify them as valid data
types for the shell. You have then to clear the "e" bit manually by

@{CODE}
Protect myfile e sub
@{BODY}

or, alternatively, by using the  "Icon/Information" menu of the Workbench,
of course.


See also: @{"Details: Command Search Path" link ComPath}

@ENDNODE
@NODE Redirect "Extended Redirection Support"
@TOC NEWS
The input and output of shell commands could be redirected by means of the
">" and "<" tokens since ever. For example, the output of the list command
can be redirected easely into a separate file rather than printing the file
list on the console:

@{CODE}
list >t:out
@{BODY}

would print the file list into the file "t:out".


V37 introduced the ">>" redirection to append the output to an already
existing file - or to create this file shouldn't it exist, and "<>" to
redirect input and output similarly. The latter works only on "interactive"
streams like the console or the "NIL:" pseudo-device (the "data grave").


V45 introduces four new redirection operators, "*>", "*>>", "*><" and "<<".

The first three are used to redirect diagnostic error messages of commands
into separate files, all provided the executed command makes use of
the diagnostic error stream.


@{B}NOTE:@{UB} At the time being, very few commands, if any, keep care of
the system provided "stderr" stream. Therefore, the three redirection
operators "*>", "*>>" and "*><" have little, if any effect. This is
unrelated to the shell, but rather due to commands ignoring the diagnostic
output stream which was introduced in V37 (Os 2.04). Program authors are
urged to have a serious look at the "pr_CES" component of the "struct
Process", found in the <dos/dosextens.h> file.


The "*>" operator redirects the diagnostic output into the file name
following, very much like ">" does for the "normal" output. "*>>" appends
the error messages to an already existing file, or creates this file. "*>>"
is the "stderr" counterpart of ">>". Last but not least, "*><" redirects the
diagnostic error output into the same file the ordinary output goes to.
Currently, this is the default anyhow unless one of the "*>" type operators
have been used. Unlike the former, "*><" does not take any arguments.


Experts may note that the syntax "*>" can be reminded by "redirecting the
current console stream" which is connected to the special file "*". Hence,
"*>" could be read as "redirect * into". In fact, "*>" and friends also
change the output console in case the target file is interactive.


@{B}NOTE:@{UB} There is no "*<>" operator; especially, "*><" is not
equivalent to it.


The fourth redirection operator "<<" is maybe hardest to understand: It
redirects the command input to the script file that is currently executed.
The "<<" operator expects an "end marker" specification as argument, and
then pushes all following lines up to this end marker into the command
input. To make this more clear, consider the following example script:

@{CODE}
ask "Enter a number:" numeric to num <<end
42
end
echo $num
@{BODY}

This "dummy script" will set the variable "num" to 42 and will display it
afterwards on the console. "<<end" redirects the following lines up to, but
not including the end-marker "end" as input into the "ask" command. All
these lines, but including the end marker, are bypased from further script
execution - the script continues below the end marker.


"<<" is most useful for making interactive commands working within script
files, or to overcome the limitation of the command line size of
some commands.


See also: @{"Detail: Redirection Syntax" link RedirSyntax}

@ENDNODE
@NODE Misc "Miscellaneous Features of the V45 Shell"
@TOC NEWS
The V45 shell offers some minor changes that do not fit into a separate
cathegory:


The V45 shell offers again the V39 compatibility switch "oldredirect".
Should this shell variable be set to "on", then redirection tokens are only
valid if they follow the command name immediately. Redirection tokens
following command arguments are then part of the command argument. Hence,
with "oldredirect" set to "on",

@{CODE}
echo "Hi" >t:out
@{BODY}

displays "Hi >t:out" instead of printing the string "Hi" into the file
t:out. This is a backwards compatibility switch to V33 and former versions
of the shell.

@{CODE}
echo >t:out "Hi"
@{BODY}

does the expected, though, in both cases.


The V45 shell offers a new variable named "keepdoublequotes" that controls
how variables, alias and backtick substitution cooperates with double
quotes. The default is either to leave quotes alone, or to remove the first
pair of double quotes should the variable be expanded within double quotes
itself. If "keepdoublequotes" is set to "on", the shell tries to keep the
meaning of quotation as close as possible. Especially, quotes that are part
of variable names are escaped by asterisks, and enclosed in double quotes
should the variable be not contained within a pair of quotes anyhow. This
feature is messy: see
@{"Details: The Variable Expansion Syntax" link VarSyntax}


The V45 shell no longer limits the size of command lines or variables.
Command lines can be as long as free memory permits as the shell is now able
to expand all of its internal buffers automatically as required. Hence, any
documented limit of "at most 512 characters a line" is obsolete now. Note
however that some commands by itself limit the size of its command line and
may fail on overlong command lines itself. This is out of control of the
shell. Especially, no limit exists for the size of the body of a backtick
sequence. Therefore, backtick sequences like

@{CODE}
echo `list SYS:#? all quick`
@{BODY}

may grow to @{B}very@{UB} long lines. While not a problem for the shell,
command lines as long as the above may successfully choke commands, and
hence should be avoided.


The shell supports now a feature to enlarge the stack size of commands
automatically. For this, the shell scans all hunks of the command to be
executed for the magic cookie "$STACK:". Should it be found, a decimal
number terminated by a line feed character is expected. This number is then
understood as the minimal suitable stack size in bytes for the command, and
the stack is enlarged as required. Therefore, program authors may simply
place the following line somewhere in their program sources

@{CODE}
char stacksize[]="$STACK:10240\\n";
@{BODY}

to guarantee a minimum stack size of 10K. The terminating line feed is a
mandatory part of this syntax and must be present to make this feature work
correctly.


See also: @{"Details: Miscellaneous Shell Features" link MiscSyn}

@ENDNODE
@NODE Commands "New and Enhanced Shell Commands"
@TOC MAIN
The V45 shell offers some new and some enhanced commands that are presented
in the following:


New commands:

  @{"PopCD              " link PopCD}

  @{"PushCD             " link PushCD}

  @{"SwapCD             " link SwapCD}



Enhanced commands:

  @{"SetEnv             " link SetEnv}

  @{"Ask                " link Ask}

  @{"Path               " link Path}

  @{"UnSetEnv           " link UnSetEnv}

@ENDNODE
@NODE Ask "Ask"
@TOC Commands

@{b}Ask@{ub}


Format:   ASK <prompt> [TO=<var>] [NUMERIC] [STRING]

Template: PROMPT/A,TO/K,NUMERIC/S,STRING/S

Purpose:  To obtain user inut when executing a script file

Path:     Internal


Specification:  ASK is used in scripts to write the <prompt> to the
current window, then wait for keyboard input. Depending on
the options, valid inputs are either Y (yes), Return = N (no),
a number, or any string. Without any further options, ASK signals
the return code 5 (WARN) for Y, and 0 for N. An IF WARN statement
can be used to check this kind of response. For numeric and
string input, the user input is printed onto the current window.
Alternatively, ASK may set a local variable to the user input.
If the PROMPT contains spaces, it should be enclosed in double
quotes.


Without the TO, NUMERIC and STRING arguments, ASK expects a boolean input
of the type "Y" or "YES" resp. "N" or "NO" or Return (no input) and sets
the condition codes accoringly: 5 (WARN) for "Y" and 0 otherwise.


If the TO option has been specified, ASK expects the name of a local
variable without $ sign and sets this variable to "1" for YES and to "0"
for NO.


If the NUMERIC keyword has been found, ASK expects the user to input a
decimal number. This number is either printed onto the current output,
or if the name of a local variable has been specified with the TO option,
this variable is set to the user input.


If the STRING keyword is found on the input, ASK expects the user to input
a string of any kind. Similar to the above, this string is either printed
to the current output, or placed into the variable given by the TO keyword.


Examples:


Assume a script contained the following commands:

@{CODE}
ASK Continue?
IF WARN
  ECHO Yes
ELSE
  ECHO No
ENDIF
@{BODY}

When the ASK command is reached, "Continue?" will appear on the screen. If
Y is pressed, "Yes" will be displayed on the screen. If N is pressed, "No"
will be displayed.


The following script will ask the user for a number, and will print this
number onto the output window:

@{CODE}
ASK NUMERIC "Enter a number:" TO num
ECHO $num
@{BODY}

ASK will continue to display its prompt until a valid number is found,
which will then be put into the variable num. Note that ASK expects the
variable name without a $ sign in front.


The next example will ask the user for a file name, and will then display
the contents of this file on the console:

@{CODE}
ASK STRING "Enter a file name to display:" TO file
TYPE $file
@{BODY}

See also: IF, SET

@ENDNODE
@NODE Path "Path"
@TOC Commands

@{b}Path@{ub}


Format:   PATH [{<dir>}] [ADD] [SHOW] [RESET] [QUIET]�[REMOVE] [HEAD]

Template: PATH/M,ADD/S,SHOW/S,RESET/S,REMOVE/S,HEAD/S,QUIET/S

Purpose:  To control the directory list that the shell searches to find
commands.

Path:     Internal


Specification:  PATH lets you see, add to, or change the search path that
AmigaDOS follows when looking for a command or program to execute.
When a directory is in the search path, you no longer need to specify
the complete path to any files or subdirectories within that
directory. You can just enter the filename, and AmigaDOS will look
through the directories in the search path until it finds the file.


Enter the PATH command alone, or with the SHOW option, and the directory names
in the current search path will be displayed. Normally, when PATH is
displaying the directory names, a requester appears if a volume that is part
of the search path cannot be found. For instance, if you added a floppy disk
to the search path, then removed that disk from the disk drive, a requester
would ask you to insert the disk.


If you specify the QUIET option, PATH will not display requesters for volumes
that are not currently mounted. If PATH encounters an unmounted volume, it
simply displays the apropriate error code, but continues with the listing.


The ADD option specifies directory names to be added to the current PATH.
You can add as many directories a time as you wish; the ADD keyword is
optional. Names of the directories must be separated by at least one space.
When you issue the PATH command, AmigaDOS searches for each of the ADDed
directories.


Directories within the PATH are searched in the order they appeared on
the command line, with new PATH components added to the tail of the PATH
list. That is, commands in a former PATH directory override those in a later
directory because they are found first when the Shell searches for commands.


If you specify the HEAD keyword, however, new directories are added the HEAD
of the PATH, to be searched first for commands.


To replace the existing search path with a completely new one, use PATH RESET
followed by the names of the directories. The exisitng search path, except for
the current directory and C:, is then erased and the new one is substituted.


The REMOVE option eliminates the named directory from the search path.


Examples:

@{CODE}
1> PATH EXTRAS2.0:Tools ADD
@{BODY}

adds the Tools directory on the Extras2.0 disk to the search path of the
Shell. If the Extras2.0 disk is not in a disk drive, a requester will ask
you to insert it in any drive.

If you remove Extras2.0 from the drive, and type

@{CODE}
1> PATH
@{BODY}

a list of directories in the search path will be displayed. A requester will
ask you to insert Extras2.0. However, if you had typed:

@{CODE}
1> PATH QUIET
@{BODY}

The list of directores in the search path will be displayed; however, when
the path comes to Extras2.0:Tools, only an error message

@{CODE}
device (or volume) is not mounted
@{BODY}

will appear in the list.


If you use two different versions of the "cmp" program, one residing in
SYS:Tools and another in SYS:Compiler/bin, and you add only the former
directory to the path in the User-Startup by

@{CODE}
PATH SYS:Tools ADD
@{BODY}

only "SYS:Tools/Cmp" will be used whenever you run the "cmp" program
from the shell. Even if you enlarge the path manually by

@{CODE}
1> PATH SYS:Compiler/bin ADD
@{BODY}

the "SYS:Tools/Cmp" program gets used because the new directory is added
to the tail of the directory list making up the PATH, and "SYS:Tools/Cmp"
is found before "SYS:Compiler/bin" is searched for another "cmp" program.


However, would you have specified

@{CODE}
1> PATH SYS:Compiler/bin ADD HEAD
@{BODY}

the directory "SYS:Compiler/bin" would have been added in front of
"SYS:Tools", and hence the Shell would have looked there first. Therefore,
"Cmp" would then refer to "SYS:Compiler/Cmp" rather than "SYS:Tools/Cmp"
because it is found first.


See also: ASSIGN, @{"Details: Command Search Path" link ComPath}

@ENDNODE
@NODE PopCD "PopCD"
@TOC Commands

@{b}PopCD@{ub}


Format:   POPCD

Template:

Purpose:  Restore the previously stacked directory

Path:     Internal


Specification: POPCD removes the top entry from the directory stack and
makes it the current working directory. In case the directory
stack is empty, SYS: will be made the current directory.


See also: @{"PUSHCD" link PushCD}, @{"SWAPCD" link SwapCD}

@ENDNODE
@NODE PushCD "PushCD"
@TOC Commands

@{b}PushCD@{ub}


Format:   PUSHCD [<dir>]

Template: DIR

Purpose:  Change and remember the current directory

Path:     Internal


Specification: PUSHCD places the current working directory onto the
directory stack and, optionally, changes the current directory to
the specified target.


PushCD works very much like the CD command except that it remembers the
current directory before it gets changes. This remembered directory can be
retrieved later on by means of either POPCD or SWAPCD.


The shell maintains a so-called "directory stack" onto which PUSHCD stacks
the directories; each "PUSHCD" enlarges this stack by one entry, adding it
to the top of the stack. A "POPCD" command removes the top entry from this
stack and makes it the current directory; it therefore retrieves the former
stored directory.


Examples:


Assume that the current directory is "SYS:" and you change into "Tools"
by means of PUSHCD:

@{CODE}
1.SYS:> pushcd Tools
@{BODY}

afterwards, the current directory will be "SYS:Tools", and the top entry
on the directory stack will be "SYS:";

@{CODE}
1.SYS:Tools>
@{BODY}

A subsequent POPCD will restore the former directory.

@{CODE}
1.SYS:Tools> popcd
@{BODY}

will result in the SYS: directory as current directory again.

@{CODE}
1.SYS:>
@{BODY}


See also: @{"PopCD" link PopCD}, @{"SwapCD" link SwapCD}

@ENDNODE
@NODE SetEnv "SetEnv"
@TOC Commands

@{b}SetEnv@{ub}


Format:   SETENV [SAVE] [<name>] [<string>]

Template: NAME,SAVE/S,STRING/F

Purpose:  To set a global variable

Path:     Internal


Specification: SETENV with <name> and <string> arguments creates a new
global environment variable. The first word after SETENV is taken
as the <name>. Everything else on the command line is taken as the
<string> argument. Quotation marks are not required.


SETENV with no arguments list the current global variables. Global
variables are stored in ENV: and are used by all processes in parallel.
However, if a local variable (defined by SET) and a global variable share
the same name, the local variable will be used.


Environent variables are called by scripts or other commands by including
a dollar sign ($) in front of the variable name.


To remove a global variable definition, use the UNSETENV command.


If the SAVE command line switch has been used, the variable will also be
saved out to disk making it permanent, i.e. reset-persistent. The SAVE
keyword must be placed immediately behind the SETENV command as it will
be otherwise interpreted as part of the variable definition.


If SAVE has been specified, the same variable will remain to be defined
even after a reboot and after a power-down cycle. Permanent environment
variables will be saved in ENVARC:


Examples:

@{CODE}
1> SETENV Editor Extras2.0/Tools/MEmacs
@{BODY}

creates the environment variable Editor which can be used with the More
utility. This specfies the ediro as being MEmacs, loocated in the Tools
drawer of the Extras2.0 disk. The variable Editor is available in any
shell.


To make the above choice permanent, use

@{CODE}
1> SETENV SAVE Editor Extras2.0/Tools/MEmacs
@{BODY}

The following line will select the editor "Ed" instead up to the next
reboot:

@{CODE}
1> SETENV Editor C:Ed
@{BODY}

Some implementations of the ENV: device will copy environment variables
from the permanent storage device ENVARC: to ENV: only when needed. If
such a device is used, SETENV without arguments will only list the
environment variables that have been used. A complete list can be obtained
by

@{CODE}
1> list ENVARC:
@{BODY}

See also: GetEnv, @{"UnSetEnv" link UnSetEnv}, @{"Details: The variable expansion syntax" link VarSyntax}

@ENDNODE
@NODE SwapCD "SwapCD"
@TOC Commands

@{b}SwapCD@{ub}


Format:   SWAPCD [level] [<dir>]

Template: LEVEL/N,DIR/K

Purpose:  Swap the top of the directory stack

Path:     Internal


Specification: SWAPCD exchanges the top or the given level of the
directory stack with either the current directory, or the
given directory should the directory be given.


The shell maintains a so-called directory stack of directories; items
can be placed on this stack by means of "PUSHCD", and retrieved by
"POPCD". SWAPCD is used to quickly switch between two directories, namely
the top entry on this directory stack and the current working directory,
or the specified directory.


SWAPCD with a given level exchanges not the top level, but the n-th level
of the directory stack with the current directory. Hence, "SwapCD 2"
exchanges the entry below the top of the directory stack with the current
directory.


Examples:


Consider the current directory is SYS: and you change into SYS:Tools with
the PUSHCD command:

@{CODE}
1.SYS:> pushcd Tools
@{BODY}

This will place SYS: onto the directory stack and will make SYS:Tools the
current directory.


Then, you can easely toggle between SYS: and SYS:Tools simply by SWAPCD:

@{CODE}
1.SYS:Tools> swapcd
@{BODY}

will re-install SYS: as current directory and will place SYS: on top of the
directory stack instead; a second SWAPCD will restore the above situation
again:

@{CODE}
1.SYS:> swapcd
@{BODY}

will therefore result in "SYS:Tools" as current directory again.

@{CODE}
1.SYS:Tools>
@{BODY}

Consider that you now push another directory onto the directory stack:

@{CODE}
1.SYS:Tools> pushcd C:
@{BODY}

resulting in the current directory C:

@{CODE}
1.SYS:C>
@{BODY}

Now the top entry of the directory stack is "SYS:Tools", below we find
"SYS:", the current directory is "SYS:C". Then

@{CODE}
1.SYS:C> swapcd 2
@{BODY}

exchanges the current directory "SYS:C" with level 2 of the directory stack,
which is "SYS:". Therefore, the result is

@{CODE}
1.SYS:>
@{BODY}

See also: @{"PushCD" link PushCD}, @{"PopCD" link PopCD}

@ENDNODE
@NODE UnSetEnv "UnSetEnv"
@TOC Commands

@{b}UnSetENV@{ub}


Format:   UNSETENV [<name>] [SAVE]

Template: NAME,SAVE/S

Purpose:  To remove a global variable

Path:     Internal


Specification: UNSETENV removes thenamed global variable from the
current varaible list. If the SAVE keyword is specified, a
possible permanent copy of the variable is also removed from
the system. With no arguments, UNSETENV lists the current
variables.


See also: @{"SetEnv" link SetEnv}

@ENDNODE
@NODE Language "The Shell Command Line Syntax"
@TOC Main

The following is a detailed description of the shell command line syntax.
The intended audience is the advanced user that is already familiar with the
shell and requires a detailed manual for looking up the shell
specifications.

@{CODE}
@{"Introduction: Command lines              " link Lines}
@{"Argument Parsing and Quoting             " link Quotes}
@{"Variable Substitution                    " link VarSyntax}
@{"Alias Substitution                       " link AliasSyntax}
@{"Expansion of Back-Ticks                  " link BackSyntax}
@{"Redirection of Input/Output/Error Streams" link RedirSyntax}
@{"The Detach-Operator &                    " link RunSyntax}
@{"The Line Continuation Operator +         " link ContSyntax}
@{"The Comment Introducer ;                 " link CommentSyntax}
@{"Loading of Commands                      " link ComPath}
@{"Miscellaneous Features                   " link MiscSyn}
@{BODY}

@ENDNODE
@NODE Lines "Command Lines"
@TOC Language

The purpose of the Amiga-OS shell is to parse its input stream for commands,
then locate these commands either on disk or in memory, and execute these
commands. An input stream is typically the stream of a console handler, as
for example the CON: window or a ViNCEd window. Other input streams are
command files, or "batch files" as they are called sometimes. The most
popular batch file is of course the "Startup-Sequence" in the S: assign.


The input stream is therefore read line by line, that is, up to a
terminating line feed character (or the end of file, where the shell
generates this line feed implicitly). Should the input be read from a
console window, this line feed is of course generated by the console handler
as soon as the user presses the return key.


The input line is then scanned for the command itself and for the input/output
and error redirection of the command defining the streams the command will
print to, will read its input from and may write its diagnostic output to.
Furthermore, the shell also handles expansion of back-tick sequences, aliases
and variables. A special feature of the shell is the "&" character and the
"+" sign at the end of a line, further the comment introducer ";".

@ENDNODE
@NODE Quotes "Argument Parsing and Quoting"
@TOC Language

Even though the shell parses the command line, it does not prepare argument
lists for the command to be executed; the command line is scanned for
shell specific control features like input/output redirection or back-ticks,
and the remaining input is forwarded as is to the command. It is the matter
of the command itself to parse this input string a second time. This has the
unfortune side effect that the shell has to second-guess about the expected
syntax of the appropriate command; for the time being, the shell assumes
the following syntax, which - surprise, surprise - coincides with the syntax
of the ROM function ReadArgs() resp. ReadItem() used by most commands anyhow:


This pair of commands knows only two special characters - or maybe four,
depending on how you count: Blanks = the space character and the TAB which
are considered equivalent, the double quote " and the asterisk * as the BCPL
style escape character. A command argument is to be understood as a sequence
of non-blank characters up to the line feed, unless the blanks and the
remaining argument are enclosed in double quotes. Interestingly, this goes
only for quotes following a blank space. Quotes within an argument, meaning
not following a blank, are not counted as argument separators. Hence,

@{CODE}
list abc
list ab"cd"ef
list abcd"
@{BODY}

present all three the attempt to run "list" with one single argument in
which the quote stands for itself.
Within quoted arguments, and only there(!) the escape character * gets
its special meaning. Outside of quotes, the star stands for itself.


Four *-escaped sequences exist: ** is the star itself, *" the double
quote, *N a line feed character and *E an "escape" character, of ASCII
code 27 = hex 0x1B. Therefore,

@{CODE}
echo "**"
echo **
@{BODY}

prints one star, and two stars respectively. Unlike other claims, the
sequence "*E[" is not directly related to the "csi" character of code
155 = 0x9b; as far as argument parsing is concerned, this is regarded as
"escape [". It is merely the console driver which interprets the latter as
a substitute for "csi", neither ReadItem() nor ReadArgs() do.


Even though these are all syntax rules as far as the ROM argument parsing
routines are concerned, the shell itself parses its input line as well, and
performs various operations on this line before it is provided as input to
the command to be executed.


The first step is back-tick substitution; then the first argument according
to the above rules is parsed off, ignoring leading blanks. Alias substitution
follows next. As soon as the alias expansion fails to expand further, it
checks whether the command name is a shell variable to be substituted, and
then tries to locate the command to be executed. This may be either an
explicit command found in the current directory, the command search path
or the resident list, or an implicit command for script files, non-executable
files or directories. The last step parses the command arguments for shell
variables to be substituted, and for input/output redirection.

@ENDNODE
@NODE VarSyntax "Variable Substitution"
@TOC Language

Local or global variables are set by means of the "set" or "setenv"
commands. Both are built into the ROM, or the Shell-Segment, as "resident
commands". Should the shell find a variable specification on the command
line, this specification is replaced by the contents of the variable before
the line is feed into the command as input, or used as the command to be
loaded directly.


A variable specification is either a $ sign, followed by alpha-numeric
characters, or a "${" sequence followed by arbitrary characters up to the line
end and a pairing "}" brace to end the variable name. The braces itself do not
count as part of the variable name itself and are therefore discarded. Should
the variable be undefined, no substitution takes place and the $ followed by
the supposed to be variable name stands for itself. An alpha-numeric character
is here any digit, any lower or upper case character or any national character
within the code range of 161..255, i.e. hex 0xa1..0xff. Hence,

@{CODE}
echo $a
echo ${a}
@{BODY}

print the same text if there should be a variable named "a", otherwise both
print the argument literally. Even though the above side effect can be used to
test whether a variable has been set or not, the shell offers a more
orthogonal way to check the existence of a variable, namely by $? followed by
the variable to be tested for existence. This expression returns the string 0
if the variable is not defined, or 1 otherwise. Hence,

@{CODE}
echo $?a
echo $?{a}
@{BODY}

generate the same output, 0 for a undefined and 1 for a defined. Note that
the ? is part of the $, and not part of the variable name.


The second related sequence is $?? which returns 1 only if the variable is
defined as a global variable, i.e. exists as a file within the ENV: device.


The usage of { } allows rather weird variable names, even names containing
spaces, escape characters, question marks, quotes, ">" or "<". Due to a side
effect of the internal working, ":" does NOT work as part of any variable
name; unfortunately this cannot be fixed since variables are stored by a
device handler that reacts in a special way on ":". Similar restrictions arise
for the slash / that implies a special meaning for global variables.
(Make a guess how!)


The $ itself can be escaped by an asterisk, hence *$ stands for a single $.
Unfortunately, THIS meaning of escaping is independent of the * concerning the
argument parsing mentioned above, and is therefore valid within and outside
of quotes, but only in front of a $ sign (and other shell-only tokens like the
back-tick ` and the bracket [, see below). For the same reason, the parsing of
variable names, though not variable expansion, works the same way within and
outside of quotes, except that stars * that are not in front of $ have a
different meaning. Therefore, confusingly,

@{CODE}
echo ${*}
echo "${**}"
@{BODY}

address the same variable, namely *, whereas both

@{CODE}
echo *$
echo "*$"
@{BODY}

print the same string $, regardless of the quotes.


The escaping can be escaped with another star as well. Hence,

@{CODE}
echo **$a
@{BODY}

will print a star, followed by the contents of a. This kind of escaping the
$ sign is independent of the quotation as well and works only in front of $
and related shell-only tokens. Therefore,

@{CODE}
echo "**$a"
@{BODY}

does right the same. More precisely, $ stands for itself with an odd number of
stars in front, and is regarded as variable expansion command with an even
number of stars. Since variable substitution happens before argument analysis,

@{CODE}
echo "***$a"
@{BODY}

will be parsed as "star, star, escaped dollar, a" on expanding variables, and
the resulting string is analyzed as argument of "echo" as "**$a" with the $
meaning of a literal "$". Now, the star escapes the second star within the
quoted argument: echo prints therefore *$a onto the console. Since * is not an
escape character for itself within arguments,

@{CODE}
echo ***$a
@{BODY}

will print one star more instead, but the interpretation of $ does not change.
Clearly, all this is messy, and can be understood only in the historical
context of the Amiga shell where $ was added after argument parsing syntax has
been set in stone. The very same rules for escaping apply to ` and [ as well,
for exactly the same reason.


The main idea of the above rules is that $ should not influence argument
parsing "too much", should work outside and inside of quotes, but should be
escapable by the same BCPL syntax. Looking back, a backslash-driven
and more consistent escaping mechanism would have been more appropriate, of
course.


A second rule formulates how variable expansion interacts with quoting:
Should the $ sequence be within double quotes, and should the variable
contents be quoted as well, the outermost pair of quotes of the variable
contents gets removed. Otherwise, the result could have been a quote within
a quote, undesirably terminating the argument. The following example
demonstrates this:

@{CODE}
set a "*"hi*""    ;defines a as "hi", note the escaping of quotes
                  ;due to a first parsing step before executing the
                  ;set command.

echo "a is $a"    ;results in "a is hi"
@{BODY}

Leaving the quotes around $a would have resulted in

@{CODE}
echo "a is "hi""
@{BODY}

This would be interpreted as two arguments rather than one, the first one
being "a is " and the second one being hi"".


If this is undesirable, set the local variable "keepdoublequotes" to "on"
by the following command

@{CODE}
set keepdoublequotes on
@{BODY}

Thereafter, the above command

@{CODE}
echo "a is $a"    ;results in "a is *"hi*"" and prints a is "hi"
@{BODY}

will get the quotes escaped properly such that the "echo" command really
prints the text including the quotes of the variable contents.


The very same idea of "double quoting" is applied to variable expansion
outside of quotes, except that the shell now either leaves the possibly
quoted variable contents alone, or adds quoting and escaping to guarantee
that the command reads the quotes as part of its argument. Therefore, the
command

@{CODE}
echo $a     ;results in "hi" with keepdoublequotes off
            ;results in "*"hi*"" with keepdoublequotes on
@{BODY}

prints either hi or "hi", depending on whether "keepdoublequotes" is "off" or
"on". In most cases, you might find "off" more attractive as it is backwards
compatible, even though it drops one level of quoting. However, if
"keepdoublequotes" is set to "on", the shell tries to preserve as much of the
original meaning of the variable, possibly adding escape characters.

@ENDNODE
@NODE AliasSyntax "Alias Substitution"
@TOC Language

Before the shell is trying to locate a command, it tries to expand this as
an alias. Aliases are command renames with additional argument relocation,
to be defined by the shell-resident "alias" command. On invocation, the
alias is then replaced by the contents of the alias, "shifting remaining
arguments to the right" after inserting a blank. Hence,

@{CODE}
alias foo echo a
foo b
@{BODY}

will result in the command "echo a b" and the output "a b". With the aid of
the additional alias token [] one can relocate the remaining arguments to
other places, e.g. in front of additional arguments of the alias contents.
No blank is inserted in this case:

@{CODE}
alias foo echo [] a
foo b
@{BODY}

will move the "b" in place of the [] and therefore print "b a", the opposite
of the above. No blank spaces are inserted in front of the [], this should be
done manually if required.

@{CODE}
alias foo echo []a
foo b
@{BODY}

will therefore really print "ba". Unfortunately, the brackets do not try to
analyze the argument syntax for traditional reasons and work therefore only
the first time within the alias contents, i.e.

@{CODE}
alias foo echo [] a []
@{BODY}

will not work as expected. The second [] is regarded as literal bracket.
Future releases might introduce further refinements of [] that allow finer
control of the arguments.


Similar to the $ sign, the [] can be escaped by a *, applying the very same
@{"messy rules" link VarSyntax} concerning the counting of stars. However,
one should now be even aware that aliases must enter the shell database
somehow: This is of course done by the "alias" command which, by itself,
parses its arguments @{B}again@{UB}. Hence, should it be necessary to
enclose the "alias body" of the alias command in double quotes, then all
stars @{B}MUST BE DOUBLED@{UB}.

@{CODE}
alias bracket "echo **[]"
bracket
@{BODY}

will just print [] on the console. The ** is escaped into a * by the argument
parsing of the alias command, and *[] escapes into [] upon expansion of the
alias.


Once again, the @{"same quotation rules" link VarSyntax} as for variable
expansion apply: By setting "keepdoublequotes" to "on", you may define
whether the shell shall prevent quotes or shall drop one level of quoting.


Alias expansion happens recursively until no alias are found to expanded any
more: If the expansion of an alias happens to be an alias again, then this
alias is expanded, and so on. Since this would imply the possibility of an
infinite loop of an alias that expands into itself, or into an alias that
expands into an alias it was expanded from, no alias will be used more than
once within a single command line. Hence, the following alias definition is
legal:

@{CODE}
alias hi ho
alias ho echo "ho"
@{BODY}

and defines the "hi" command to output "ho", whereas the following alias
definition is asking for trouble:

@{CODE}
alias gnu gnu is not unix
@{BODY}

This will first expand "gnu" into "gnu is not unix", and will stop then since
the "gnu" alias has been "used up" already. Since the gnu command cannot be
resolved further - unless of course you provide this command as a binary - an
error message will result.


Expansion of aliases can be prevented completely by enclosing the command in
quotes. "hi", therefore, will not try to use the above hi-alias, but will try
to find a file named "hi". Otherwise, alias definition take precedence over
ordinary files, i.e. the alias expansion will be applied first when
applicable, and only if this fails the shell tries to locate an appropriate
command.

@ENDNODE
@NODE BackSyntax "Expansion of Back-Ticks"
@TOC Language

As the very first step of command line interpretation, the shell
will expand all back-tick sequences on this line. The commands enclosed in
back-ticks will be executed, and the resulting output, after a mild
preprocessing step described below, is inserted instead of the back-tick
sequence. The reader should be aware that the resulting command line might be
very long; even though the shell itself has no problem to process long lines,
some commands may.


The back-tick itself is represented by *`, and hence
@{"escaped in the very same way" link VarSyntax} as the $ sign for variable
expansion and the [ bracket of the alias argument placement operator; this
goes also for the messy multiple-star sequences, hence **` is a literal star
followed by a back-tick sequence, and ***` a literal star followed by a
literal back-tick, and so on - see the
@{"syntax description of $" link VarSyntax} for all the side effects one
should expect.


The command output of the "backtick'd" command is processed before it replaces
the back-tick sequence, though. The shell removes a final terminating line
feed, should it be present, and replaces all other line feeds by blank spaces.
Finally, the shell handles double quotes in the very same way as for $ and []:
If "keepdoublequotes" is "off", quotes resulting from back-tick sequences
within quotes are removed, and no additional quotes are paired around back-tick
expansions resulting in quoted strings. If "keepdoublequotes" is "on",
however, the shell tries to preserve the meaning of the string as close as
possible and adds escaping stars to preserve quotes within the command output.


The body of the backtick'd sequence is considered to be a separate command
line and is therefore parsed separately. Especially, quotes outside a
back-tick sequence can never match any quote within, and do not influence
the meaning of the back-tick sequence as far as escape characters are
concerned. Hence, in the following two command lines

@{CODE}
echo `echo *.`
echo "`echo *.`"
@{BODY}

the star stands for itself, even for the second line. It is not considered to
be "within" the surrounding double quotes and is therefore not treated as an
escape character. However, the reader should be aware of the * as an escape
sequence for the back-tick itself, as mentioned in the first paragraph! The
two commands

@{CODE}
echo `echo *`
echo "`echo *`"
@{BODY}

will NOT print a single star since the star in front of the second back-tick
escapes this back-tick and hence disables the expansion of the back-tick
sequence at all. One correct way to print a single star by this admittedly
complex method would be

@{CODE}
echo `echo **`
@{BODY}

whereas

@{CODE}
echo `echo ***`
@{BODY}

prints `echo **` with one star less, namely the star that prevented the last
back-tick to be part of a back-tick sequence. This is again the "count the
stars" rule @{"we have been observing for $ and []" link VarSyntax}.


Needless to say, back-tick expansion works also within the prompt, and for the
command itself. The latter is a new feature for the V45 shell.

@{CODE}
`echo type` s:Startup-Sequence
@{BODY}

is a rather complex and weird way to display the startup sequence on the
console window, and

@{CODE}
prompt "*`date*` %N.%S> "
@{BODY}

prints the date in front of the typical CLI number/directory prompt
indicator. The command to be executed within the prompt should be better
fast and small, of course! The reason for the asterisks in front of the
back-ticks is left as a little exercise for the alert reader.

@ENDNODE
@NODE RedirSyntax "Redirection of Input/Output/Error Streams"
@TOC Language

Each command to be executed inherits three I/O streams from the shell. An
input stream user input is read from, an output channel the command prints
output to, and a diagnostic channel error codes should appear on.
Unfortunately, the consistent use of the latter has never been very popular
and is not even supported to full extend by various Os functions; the
PrintFault() dos.library call, for instance, does NOT print to the
diagnostic output. Nevertheless, all three streams can be redirected by
appropriate shell constructions:


An unquoted > followed by a file name defines the output stream, a < plus
file name the input stream and a *> the diagnostic output channel. Should
these sequences be required as part of any argument for the command, they
should be enclosed in double quotes. Should the shell find more than one
similar redirection on the command line, all additional redirections are
regarded as literal strings. Hence,

@{CODE}
echo >t:out >NIL:
@{BODY}

prints the string ">NIL:" into the file "t:out". Further, the shell applies
special rules to the commands "alias", "run" and "pipe" leaving the parsing
of the redirection tokens to the command itself. This has the effect that,
for example, the following alias

@{CODE}
alias foo echo foo >t:out
@{BODY}

defines the "foo" command to print the string "foo" into the "t:out" file,
rather than printing the (empty) result of the alias command into that file.
Similar considerations apply to "run" and "alias" as well, of course.


Furthermore, should the variable "oldredirect" set to "on", then the shell
will only try to interpret redirection tokens following immediately the
command name; otherwise, the position of the redirection tokens do not
matter.

@{CODE}
echo "foo" >t:out
@{BODY}

will either print "foo" to the file "t:out", or will print "foo >t:out" if
"oldredirect" is set to "on". This is a backwards compatibility feature for
pre V37 shell scripts.


Needless to say, the file name argument of >, < and *> must be quoted if it
contains spaces, and can be as well a variable specification by means of $,
or a back-tick sequence. Therefore,

@{CODE}
set t t:out
echo foo >$t
@{BODY}

and

@{CODE}
echo foo >`echo t:out`
@{BODY}

write both "foo" into the file "t:out". Besides these three commands, the
shell also understands the following additional  redirection tokens:


>> appends the output to a file, or creates it should it be not yet existing.


<> redirects both input and output into the same file. However, since this
implies that the input stream must be "cloned", the "file" must be either
NIL: or any kind of interactive device, e.g. CON: or RAW:. An ordinary file
cannot be written to and read from at the same time.


*>> works much the same way as >> does, but just for the diagnostic output:
It either creates the file, or appends to an existing stream.


*>< redirects the diagnostic output into the same file as > does.
Unfortunately, this has to be the default anyhow for compatibility reasons
beyond logic, and is explained below in more detail. *<> is NOT equivalent
to *>< and currently a reserved token.


Last but not least, the shell also understands a very special input
redirection using the << token. This token takes a string as argument and
scans the shell input - typically a batch file containing the << redirection -
up to the specified string and pastes the result into the stdin of the
command. The following example may enlighten the reader a bit:

@{CODE}
ask "Enter a number:" numeric to num
echo $num
@{BODY}

asks the user for a number - to be entered on the input stream of course -
and then prints this number. The following silly script will define this
number to be 42:

@{CODE}
ask "Enter a number:" numeric to num <<end
42
end
echo $num
@{BODY}

The lines between "<<end" and the "end" token form the input of the "ask"
command. This may seem rather un-useful here, but may become important if
a command expects rather lengthy user input on the command line and the
command shall be run as part of a shell script. Due to the way how << works,
though, this construction fails for commands launched by the "run" command;
instead, usage of the "&" token described below is recommended because it
knows how to deal with this kind of input redirection.


Finally, some words concerning the diagnostic output redirection:
Unfortunately, this is not widely used, if it is used at all. Instead,
commands either print error messages into their ordinary output, or into a
file opened as "*", i.e. the console. The first case is of course out of
control of the shell, but the second case is kept care of: Should the
diagnostic output be some kind of interactive stream, say a console handler,
then *> sets the terminal console task of the command as well, and hence
redirects the "*" output into the  console specified by *>.

Unfortunately, it is quite typical to detach commands by means of "<>NIL:"
from the console. Without further care, this would NOT redirect stderr
anymore and would therefore break existing shell scripts. Hence, some
messy compatibility rules for *> redirection have been established:

@{code}
Without *>
        The diagnostic error stream goes into the output
        stream, the command console goes into the current
        console. A "run" command would clear the current console
        anyhow, and would hence dispatch the file from the terminal.

With *>
        Diagnostic output will go into the specified file,
        the command console is the current console unless
        the specified file is interactive or NIL:. In the
        first case, the program console is set to the
        controlling console of the stream, in the second
        no terminal console is provided.

With *><
        Diagnostic output will go into the output stream,
        the command console will be set to the console
        controlling the output stream should this be inter-
        active, or will be cleared in case the output goes
        to NIL:
@{BODY}

Similar rules apply if the command is run in background by means of the "&"
token, except that there is no default command console unless one is provided
by means of *> or *><. This makes it a bit easier to detach commands from
the shell by using "&" and "<>NIL:".

@ENDNODE
@NODE RunSyntax "The Detach-Operator &"
@TOC Language

Should the shell find a & sign on the command line that is surrounded by
blank spaces and neither quoted, then this sign is removed from the command
line and the command gets detached from the shell very similar to what "run"
would do.


By default, these commands get a new separate console, and a new console owner
should the console driver support this concept (ViNCEd does, the ROM CON:
handler does not) and hence make use of the "job control feature" of the
console.


These commands will keep the console window locked open unless you explicitly
redirect the command input and output to NIL: - this is simply because
commands launched in this way are handled very similar to commands launched
by "run".


There is, however, one important difference between "run" and "&": Unlike
"run", the "&" sign does not detach the command to be run from the standard
input. Hence, "ask &" will still ask for input on the console, "run ask" will
not. Furthermore, "run" doesn't mix with << input redirection, "&" does. All
this is because the "&" sign is handled by the shell directly and is much
better integrated into the internal wiring than "run" could.


@ENDNODE
@NODE ContSyntax "The Line Continuation Operator +"
@TOC Language

Should a command line end on a single + sign, the shell waits for additional
input and concatenates this input with the previous command input, including
the line feed, but excluding the + sign itself.


However, this second line is not parsed as a shell command line, but is
rather placed on the command arguments of the command of the previous line.
Since the ROM ReadArgs() and ReadItem() functions only parse up to the first
line feed character, this additional line is typically lost and is only of
interest for special commands like "run" that read their arguments in a
non-standard way.

@ENDNODE
@NODE CommentSyntax "The Comment Introducer ;"
@TOC Language

If found unquoted on the command line, the ";" introduces a comment.
All characters following the semicolon, and the semicolon itself are removed
from the command arguments.

@ENDNODE
@NODE ComPath "Loading of Commands"
@TOC Language

Besides @{"aliases" link AliasSyntax}, the shell knows also the following
types of commands:


The PIPE command, which is used as soon as one of the pipe tokens is found on
the command line, resident (or so-called "built-in", though this
nomenclature is sort of incorrect) commands, implicit commands, commands on
the command search path, and commands within the current directory.


Should the shell find that the user defined either the _pchar or the _mchar
local variables, then the command line is scanned for the contents of these
variables. For historical reasons, both variables should contain strings of
at most two characters in size.


If these characters are found, then the shell assumes an implicit "PIPE"
command that is prepended to the full command line before further parsing.


Resident commands are found on the dos.library "resident command" list and
are program segments similar to those generated by the LoadSeg() command.
Unlike the latter, they do not get a "fresh" copy of their segments each
time but are assumed not to touch their code and data space; hence, not all
commands should be made resident as they are not "pure". Pure commands are
usually in ROM space, or can be placed onto the list of residents by the
"resident" command, which, by itself, is resident. The "resident" command
checks the "p" bit of the command file whether a certain command can be
made resident or not. Since the "p" bit can be set by hand, this is not
much of a safety feature, though. The original "arp" ("Amiga Replacement
Project") commands where the resident feature goes back to had an additional
check concerning the purity of commands.


If a command is neither resident nor an alias, the shell tries to find it on
the command path list, which is controlled by the "path" command. If an
executable binary load file is found, this is assumed to be the command;
should the "h" = "hold" bit of this executable be set as well along with
the "p" bit, the command is made resident as it is loaded.


If the file in question is not executable, but the "s" bit is set, then the
first two characters of the file are investigated. If they are "/*", hence a
Rexx-comment introducer, a rexx script is assumed and an implicit "RX" command
is prepended to the argument line. If they are "#!" or ";!", the first line
of the script is assumed to be the file name of a script interpreter. This
name must be enclosed in double quotes should it contain blanks. The script
name itself gets then inserted @{B}between@{UB} the command interpreter file
name, and its options on this line.


Therefore, the following command interpreter specification on the first line
of the file "foo"

@{CODE}
#! type HEX
@{BODY}

will run the following text of foo thru the interpreter "type" with the option
"HEX", as if

@{CODE}
type foo HEX
@{BODY}

has been input on the command line. Note that the HEX option is placed behind
the "script" file name, and not in front of it.


If neither a "/*", a "#!" nor a ";!" is found, the script is assumed to be a
shell script and run thru the "Execute" command. Curiously, "Execute" expands
only the arguments and generates a temporary script file, but the actual
command interpretation of this file is left to the shell again by making use
of a not-so-well documented side effect of the shell segment.


If the found file is neither a script, nor executable, the shell checks for
the variable "VIEWER". Should it be found, then the shell further checks
whether the file is any known data type by using the datatypes library. If so,
then the contents of this variable is understood as a command that should be
run to display this file. For this, the contents of the VIEWER variable is
placed in front of the command line before further interpretation. Typically,
VIEWER should be set to the MultiView command, of course:

@{CODE}
SetEnv SAVE VIEWER MultiView
@{BODY}

Finally, if the "file" is in fact a directory, the implicit command "CD" is
assumed and inserted in front of the command line.


The shell can be restricted to search on the current directory only by
enclosing the command within double quotes; this will remove the resident
command list and the command path from the search targets the shell will scan
for commands.

@ENDNODE
@NODE MiscSyn "Miscellaneous Features"
@TOC Language

The shell scans all segments except resident INTERNAL commands for the
"magic cookie"

@{CODE}
$STACK:
@{BODY}

Should it be found, then a decimal string terminated by a line feed (!) is
expected. This string is then regarded as a request to enlarge the stack to
at least the specified amount of bytes.


Therefore, the following string near the startup code of your program will
guarantee at least 10240 bytes of stack:

@{CODE}
char stack[]="$STACK:10240\\n";
@{BODY}

Note that the "\\n" is necessary and that "STACK" is in capitals.

@ENDNODE
@NODE History "History: What Happened Before?"
@TOC Main
@{CODE}
Shell V45.0:

Oh wow, this was a tough job. The Shell really looked like
some kind of BCPL left-over. It took several days just to
cleanup the code and turn it into something more readable.
BCPL was lurking thru the code all over. No more, folks,
no more...

The V40 shell was unable to perform the "implicit CD" command
properly if the directory name was quoted. It inserted an
unnecessary blank space behind the directory name.

The shell didn't support multiple backticks on the command line;
the backtick parser was simply broken: Fixed handling of 
asterisk-backtick sequences. The backtick wasn't escaped properly.

The shell did not treat TABs as blank spaces. Fixed.

Removed the SetClock kludge. Whoever is still using a 1.3
SetClock nowadays cannot be helped anymore and deserves
to be crashed. (-;

Added a few missing Forbid/Permit locks around access of
the list of resident commands.

Removed an ugly hack to set the RC and Result2 variables;
this really uses now the proper system functions and doesn't
attempt to hack directly into the variable buffers.

Reworked the parser a lot; it partially tried to fiddle in
the internal buffers of file handles using structures that
have never been documented. The code now loads full lines
at once (no matter how big they are) and then parses within
its buffers. This removes all dependencies of implementation
details of the file handles.

Arguments to redirection did not expand backticks. Fixed.

Added a lot of proper error checking if it is low on memory.

The internal (and deceased "GlobalVector") is no longer
passed thru to all functions. Instead, I'm now using some
SAS magic to allocate my data segment myself on each
invocaton.

Decided not to disable echo-ing for non-interactive shells.
Otherwise, we could not debug scripts or the startup-sequence.
Sorry, Heinz, but I reconsidered and it's really better this
way.

Shell V45 re-introduces the handling of the "h" bit. Should it
find a command with "pure" and "h" bits set, it makes the 
command resident automatically. Note that this is (again) the
V39 behaivour. Note that "h" is for "hold", not for "hidden".

The shell does no longer limit command lines to 512 characters.
Command lines can now be unlimited in size, provided the
command itself is smaller than the AmigaOs file name size
limit (107 characters). The Shell will now auto-expand all of 
its internal buffers if required to do so. Furthermore, it
uses now memory pools for this kind of administration.

The shell offers now extended "script" support. In case a script
file - i.e. a file whose "s" and "e" bits are set - starts with
either the magic characters "#!" or ";!", the string behind this
magic cookie is understood as the path to a command parser that
shall execute this script.

Added support for "file browsing". 

If the shell encounters now a file as first argument that has
its "e" bit cleared (!) and is parsed and recognized as a data-
type by the data types system, the shell runs a "viewer"
program whose path should be placed in the $VIEWER shell
variable.

Added support for "stderr" redirection. Therefore, the V45 
shell introduces three new redirection symbols:

*>  filename    : redirects stderr to a file
*>> filename    : appends output to stderr to a file
*><             : redirects stderr to the same file that stdout
                  goes into.

The shell will also assign the console to the stderr stream
should stderr be an interactive stream.

Added support for "script stdin". A "<<" will pull the next
symbol from the shell script and will push all following
lines up to a line starting with this symbol as input into 
the command. Hence, "<<" is exactly the Un*xoid input redirection.

Added a new command line token, the "&" character, 
the "implicit run". If found, the shell opens named consoles
with of a name generated thru utility/GetUniqueID(), and assigns
these to the stdin/stdout/stderr of the command, shouldn't 
redirection be used anyhow. Then the command is detached from
the shell segment.

Added automatic stack size setup for shell commands. This is a 
new feature that would hopefully limit the number of stack
underflows as it allows application developers to increase the 
stack automatically without the need for stack swap code. The 
shell scans now the first 1K of each segment of a loaded binary 
for the magic cookie "$STACK:". The string behind this cookie 
is expected to be a decimal number, terminated with a line feed 
(and an ASCII NUL, i.e. '\0', as for all C strings).
This number is then interpreted as the stack size in bytes. The shell
will automatically increase the stack size *for this command only*.
If the pre-defined stack size is larger than the program-implicit,
nothing will happen.

AGENDA:

Rewrite the parser for shell-variables. This looks currently messy
and not very well thought-about. Especially the handling of
asterisks is broken here.

Rewrite the parser for backticks. This happend already to some
degree, but it is not yet perfect.



Shell 45.1:

The shell did not handle script files correctly that did not end
on a line feed. Fixed.
The shell bootstrap code was partially broken and could not run
the "Initial CLI" correctly. The BCPL startup mechanism was
rewritten completely (to the better).
Incorporated all traditionally resident commands into the Shell-Seg
making this a self-contained shell with a resident segment that
is rom-able and can bootstrap the system.
Rewrote the shell command line parser to some degree. This implies
various changes on how the command line gets interpreted. Good
news is that backticks can now also be used to specify the command
itself, alias [] works within backticks, and backticks cooperate
nicely with aliases in general. Furthermore, the new parser
allows multiple, recursive, but non-looping alias expansion,
and aliases containing backticks that are expanded correctly.

Fixed *>< redirection hits. Fixed generation of result codes, the
shell forgot to forward command result codes properly. Fixed
stderr redirection: stderr defaults to stdout, it now defaults
to the shell output stream; hence, an explicit *>< is required
for the old behaivour.

Fixed escaping for implicit commands CD,EXECUTE, and others:
They no longer escape " and * if found in an unquoted string.
Note that this is the proper behaivour, even though this is
more a "feature" of ReadItem() than anything else.

Fixed the "CD" command: It did not allocate the anchor path
from memory resulting in a possibly mis-aligned "FileInfoBlock"
and damaged memory. Yikes!

Fixed the "resident" command: First of all, it also placed
"AnchorPath"s on the stack, which is no good. Second, it did
the printf for the resident command list within a loop while
Forbid(), making the forbid for the list lock pretty much
useless.

Reworked set,setenv,alias,unset,unsetenv,unalias: All of
these six commands are handled by the same segment, but the
division into various subcommands happened in a rather
unorthogonal way by second-guessing from the command name.
It is now organized in several segments calling the same
main routine with parameters. "set" became reorganized
a lot as well: "setenv" without parameters is no longer
redirected to "list", making this independent of whether
external commands are available. "set" reformats now ESC
and CSI sequences on the screen consistently by using the
BCPL escape character "*". Other non-printables are (as it 
always has been the case) replaced by the smear-character
0x7f (DEL).

Reworked get, getenv for the same reason: One segment, two
commands.

Reworked "run", but not quite as much as I would like to.
This still rolls its own faked input file handle. Even
worse, it gets the command line from the undocumented
internal buffer of its stdin stream. There's currently no
better way of doing it.

Added a new option "HEAD" to "path". This will add new paths to
the start of the command search path and will hence search
them first.

Reworked "newshell". It no longer tries to place critical
DOS structures on the stack, and will therefore long-word align
them correctly all the time. The window open path of NewShell
has been changed to CON://130/AmigaShell/CLOSE/SHELL to signal
shell usage for console handlers, e.g. ViNCEd.

AGENDA: 

The shell argument parsing is still somewhat wierd. Backticks
are not recognized as "quotes" and don't group commands
on parsing - this happens only on expanding them. This is
mainly the matter of ReadItem() which should be replaced
by a custom routine. Further, single quotes are not handled
at all. I wonder whether I should touch this or leave it as
"compatibility feature".



Shell 45.2:

Fixed several missing error reports, for example for out-of-memory
situations and unability to open redirection files.

Changes the style of stderr redirection: Stderr defaults now to
stdout, unless redirected otherwise. This is a compatibility
cludge for <>NIL: type redirection.

Redirection with <> checks now explicitly whether the target file
is interactive or NIL: It will fail in all other cases.

Redirection into "*" with the run-back operator "&" will now go
into the console owner established for the command output rather
than the current console.

Added PushCD, PopCD and SwapCD commands as build-ins.

Re-established the "oldredirect" variable. If set to "on", the
shell will check for redirection operators only immediately 
behind the command name and nowhere else. This is a pre-V36
compatibility feature that was dropped in V40 due to limited
ROM space.

Added SAVE keyword to UNSETENV to make the changes permanent.

Fixed wrong templates for unalias, unset and unsetenv.

Reworked ASK a lot; this command allows now numeric and string
input, and places the result either on stdout or into a user
specified local variable.


Shell 45.3:

The "&" symbol was broken in several ways: First of all, it
unlocked home and current directory twice instead of once,
causing possible memory trashes. Further, it did not set
CLI->cli_Module correctly which is required for some run-back
and stay-resident programs. Thrid, it did not check the very
same CLI variable to release the program again, hence might
have even unloaded segments that are not meant to be unloaded.
Fourth, it did not work well with "Execute" due to the rather
clumpsy way the original BCPL shell introduced the execute
logic. The "&" handling was more or less rewritten for the
45.3. The new logic introduced another kludge in the shell
startup logic (oh no!) but makes it possible to run programs
in background *without* destroying stdin, hence unlike run.
Therefore "run" is more or less obsolete now.

The shell command line parser was turned upside down. Nothing
of the old parser is left. The net effect is that the general
logic of argument parsing has been improved much. The shell
now knows on variable expansion and backtick expansion whether
it inserts arguments into quotes, and if so, escapes properly.

Fixed handling of aliases in some ways, especially fixed a
bug of the 45.2 where the shell forgot to insert a space.

Removed handling of ( and ) in pipes. They aren't used
by any pipe command I know of and are therefore just here to
make the syntax even more cludgy.

Fixed handling of interpreter setup by means of #! or #;.
The line behind the magic symbols is now parsed thru ReadItem
and hence requires proper quoting, so beware!

Fixed handling of implicit commands on arguments starting
with quotes. The old shell could not run these commands
properly due to unadequate re-escaping of the command argument.
This is now all handled (hopefully correctly) by one common
routine that is also used for variable and backtick sub-
stitution.


Version 45.4:

The 45.3 release caused problems with existing scripts because
quoted variables within quotes where escaped by * such that
double quotes resulted. While this is correct in principle,
it broke already existing scripts. For this reason, a special
rule is now applied: Variables within quotes get their first
pair of surrounding quotes removed. You can avoid this by
setting the variable "keepdoublequotes" to "on":

set keepdoublequotes on

Pre 45.3 releases generated a wrong error for script files
that are read-protected. Fixed.



Version 45.5:

Fixed the parser state machine such that variables of wierd
names like ">t" are possible. The parser used to be quite
inconsistent how to handle them.

SwapCD has an optional LEVEL argument that defines which
level of the directory stack to swap with.

The stack extension logic scans now the first 4K for the
stack cookie.

Setenv SAVE clears now the "e" bit on the saved variables.

The asterisk in front of $, [�and ` is now handled
correctly again. * escapes the following character, **
escapes the star from escaping, *** is a double star with
escaped following control character.

Added the possibility to check for the existance of a
variable by the $?varname method. $?a will expand to
1 if a is defined, 0 otherwise. $??a will expand to
1 only if a is found as a global variable.

Fixed handling of quotes in variables and backticks
outside of quotes. Behaivour of the shell depends here now
again on the "keepdoublequotes" variable. If "on", the
quotes are escaped and the full string is put into quotes,
otherwise the string is left alone. If already in quotes,
"keepdoublequotes" = "on" escapes quotes within the
variable body, otherwise the outermost quote gets removed.

Fixed the escaping of the rear backtick of a backtick
sequence.

StdErr redirection to NIL: by *>NIL: will now clear the
console task for the command to be run.

Command interpreters specified by the #! or ;! token may
now get additional arguments specified on this line. The
script file name is inserted between the command and these 
arguments.

Fixed the multiple redirection issue. Fixed handling
of alias and redirection. As a side condition, the output
of the "set" and "setenv" commands can now be redirected just
fine.


Version 45.6:

Various minor code cleanup concerning the command buffers;
they are now all static to the functions they belong to.

Fixed recognition of $VIEWER which had to be a local variable
to be functional. 

Removed beta warning message on startup.

The shell scans now all hunks of a loaded binary for the
stack size. Furthermore, several enhanced safety checks have
been added for this feature.

Added a german documentation, proof-read and spell-checked
the english documentation.


Version 45.7:

The run-back operator & did not move the shell segment in
the seg-array and hence might have crashed some BCPL commands.

The stack size search routine got improved quite a lot and is
now much faster than before - by a factor of four to five.

The "setenv" command clears now the "e" bit of the variables
it saves.
@{BODY}

@ENDNODE
@NODE INDEX "Index"
@{CODE}

        A...

        @{"Alias�Substitution" link ALIASSYNTAX}
        @{"Recursive�Alias�Expansion" link RECALIAS}
        @{"Alternative�Script�Interpreters" link HASHBANG}
        @{"Argument�Parsing�and�Quoting" link QUOTES}
        @{"Ask" link ASK}

        B...

        @{"Expansion�of�Back-Ticks" link BACKSYNTAX}
        @{"Multiple�Backticks" link BACKTICKS}

        C...

        @{"Check�Variables�for�Existance" link VAREX}
        @{"New�and�Enhanced�Shell�Commands" link COMMANDS}
        @{"Command�Lines" link LINES}
        @{"The�Comment�Introducer�;" link COMMENTSYNTAX}
        @{"The�Line�Continuation�Operator�+" link CONTSYNTAX}

        D...

        @{"DataTypes�Support" link DTYPES}
        @{"The�Detach-Operator�&" link RUNSYNTAX}
        @{"The�Shell�Job�Control�and�the�&�Operator" link RUNBACK}

        E...

        @{"Expansion�of�Back-Ticks" link BACKSYNTAX}
        @{"Extended�Redirection�Support" link REDIRECT}

        F...

        @{"New�V45�Shell�features" link NEWS}

        H...

        @{"H Bit: The�Revival�of�the�h�Protection�Bit" link HBIT}
        @{"History:�What�Happened�Before?" link HISTORY}

        I...

        @{"Alternative�Script�Interpreters" link HASHBANG}
        @{"Introduction:�What�is�this�about?" link INTRO}

        J...

        @{"The�Shell�Job�Control�and�the�&�Operator" link RUNBACK}

        L...

        @{"The�Shell�Language" link LANGUAGE}
        @{"The�Line�Continuation�Operator�+" link CONTSYNTAX}
        @{"Loading�of�Commands" link COMPATH}

        M...

        @{"Miscellaneous�Features" link MISCSYN}
        @{"Miscellaneous�Features�of�the�V45�Shell" link MISC}
        @{"Multiple�Backticks" link BACKTICKS}

        N...

        @{"New�and�Enhanced�Shell�Commands" link COMMANDS}
        @{"New�V45�Shell�features" link NEWS}

        P...

        @{"Path" link PATH}
        @{"PopCD" link POPCD}
        @{"PushCD" link PUSHCD}

        R...

        @{"Recursive�Alias�Expansion" link RECALIAS}
        @{"Redirection�of�Input/Output/Error�Streams" link REDIRSYNTAX}
        @{"Extended�Redirection�Support" link REDIRECT}
        @{"The�Run-Operator�&" link RUNSYNTAX}
        @{"The�Shell�Job�Control�and�the�&�Operator" link RUNBACK}

        Q...

        @{"Argument�Parsing�and�Quoting" link QUOTES}

        S...

        @{"Alternative�Script�Interpreters" link HASHBANG}
        @{"SetEnv" link SETENV}
        @{"SwapCD" link SWAPCD}
        @{"The�Shell�Command�Line�Syntax" link LANGUAGE}

        U...

        @{"UnSetEnv" link UNSETENV}

        V...

        @{"Check�Variables�for�Existance" link VAREX}
        @{"Variable�Substitution" link VARSYNTAX}
        @{"$VIEWER: DataTypes�Support" link DTYPES}


@{BODY}
@ENDNODE