home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Elysian Archive
/
AmigaElysianArchive.iso
/
newc_dev
/
arprel13.lha
/
AshMan
< prev
next >
Wrap
Text File
|
1989-04-04
|
46KB
|
1,651 lines
CONTENTS
1. Introducing Ash..................................... 1
Installing ASH...................................... 2
What commands work with Ash?........................ 2
1. What about Run? 3
2. Shell features...................................... 3
Resident programs................................... 3
Builtins............................................ 4
IO Redirection...................................... 4
Alias............................................... 5
1. Summary of Alias syntax 7
Script Language..................................... 7
Environment Variables............................... 8
1. Special Variables 10
Pipes and PipeLines................................. 11
1. Show me more pipelines 12
2. Show me how to use pipes with scripts 13
Command Substitution................................ 15
Prompt enhancements................................. 19
Using Variables and Substitutions in Prompt and
Alias............................................... 20
3. Modifying your startup sequence to use ASH.......... 22
Modifying 1.3 startup to take advantage of ARP...... 23
4. Appendix A: Finding a pipe device to work with
ASH................................................. 23
5. Appendix B: Bug reports and enhancement
requests............................................ 24
- i -
Introduction to ASH: The ARP Shell.
AmigaDOS Resource Project
Description of shell features, variables, batch language,
pipes and command substitution. Includes sample scripts and
command lines.
1.
Introducing Ash
The ARP Shell or 'Ash' is an alternative to the standard CLI
or 1.3 AmigaDOS shells. While not claiming to be the last
word in shell technology, we feel that it provides a
significant improvement over the customary shells in the
following areas:
- All improvements introduced by Commodore in the 1.3
Shell are supported by ASH in either an identical or
highly compatible fashion. This includes the Alias
function, auto-executing batch files and Prompt
enhancements. ASH runs both BCPL and non-BCPL
programs.
- Ash contains many builtin functions which save disk
access as well as disk and memory bytes. In
particular, the entire batch language is built into
Ash, which provides for much more efficient execution
of scripts.
- It is possible to replace many of the C: directory
commands with their builtin equivalents in ASH, and it
is interesting to compare the sizes involved. The
original 1.3 commands which ASH contains as builtins
total over 15,500 bytes! By contrast, ASH itself is
less than 8,000 bytes. To see a list of builtins, type
a single question mark at the shell prompt, then hit
return.
- Ash supports true concurrent pipes and command
substitution, as well as environment variable
expansion. These are advanced features not available
in the 1.3 shell.
- Ash uses the arp.library process functions to run your
programs, and so uses the ARP resident features. These
can save you greatly in memory use, since the stack
size and data size are encoded inside the program. ARP
resident programs are also much safer than the 1.3
Resident, because arp.library checks the program before
running it to make sure it has not been damaged, and is
residentable. This means that you do not have to crash
Page 1
Ash Users manual. V1.3.0 March 30, 1989
your computer to discover whether or not a program will
work as resident.
Installing ASH
If you have ASH as part of the ARP distribution, the ARP
install program will handle this for you. Otherwise, you
should copy ASH to the L: logical directory on your system
disk*.
If you are using the ARP supplied AShell program you
should delete the line in the Commodore supplied startup
sequence which reads something like:
Resident CLI L:Shell-Seg SYSTEM pure add; activate Shell
since AShell will locate and load ASH for you. If you
choose to use the Commodore supplied NewSHELL program and
still want to use ASH, you want to replace L:Shell-Seg in
the above line with L:ASH:
Resident CLI L:ASH SYSTEM pure add; activate arp shell
The only difference here is that the Commodore NewSHELL
command will not automatically load the shell into memory if
it is not present, and so requires extra work in the startup
script. (Note - you may also need to set the PURE protect
bit in L:ASH to do this).
What commands work with Ash?
As far as we know, all programs work fine with Ash,
including BCPL programs as distributed by Commodore. The
only command that you won't want to use with Ash is the
Commodore Resident command, you should use Arp's ARes
instead. Alternatively, if you prefer the Commodore shell,
do not replace Resident with ARes.
__________
* The ARP Install program won't change your startup script
for you. If you intend to use Ash, you should alter
your startup-sequence as described to avoid wasting
memory.
Page 2
Ash Users manual. V1.3.0 March 30, 1989
Each shell uses a different method of managing the
resident lists, and so will work only with its own Resident
loader. You won't crash if you mis-match these two, but you
won't be getting any use from the resident features of the
shell of your choice either.
1.
What about Run?
Run (either ARP's or Commodores) just
passes your command line to the currently loaded shell. If
you have loaded the Commodore shell, then using either the
ARP Run or Commodore Run will invoke the Commodore Shell.
If you have loaded Ash, then using either Run command will
invoke the Arp shell. This means that your background
processes invoked with Run (or by the AmigaDOS function call
Execute ()) will take advantage of resident programs and any
additional features of whatever shell is loaded.
2.
Shell features
We cover all features of the Arp Shell here, including those
which are shared by the 1.3 Commodore shell. This is done
for completeness, and also gives us the opportunity to
describe any differences in operation between the two.
Sometimes you might execute a command that Ash needs more
input to complete. If you do, then Ash will print a prompt
(a single '?' mark), and wait for you to type more (remember
to hit return). If you can't seem to feed the shell what it
wants, type an EOF character (Control-\), and you will
usually receive some kind of message that should allow you
to figure out what's going on for next time.
Resident programs
Resident programs save you memory and loading time, even
over the use of a ramdisk, by letting the system reuse the
same code for multiple invocations of the program. Due to
limitations of the current Commodore implementation of
Resident, you cannot mix the Arp ARes command with the
Commodore Resident command. You need to use ARes with Ash,
or Resident with Shell-seg (the 1.3 shell). You won't crash
if you mismatch these programs, but you won't be able to use
Resident programs either.
To make a program resident, simply type:
ARes programname
Then, the first time you attempt to access 'programname',
the system will load the program for you, and make it
Page 3
Ash Users manual. V1.3.0 March 30, 1989
resident. Each subsequent access will be much quicker,
since it will run directly from memory. This 'load on
demand' feature is nice, since you don't have to wait for
all those programs to be made resident in your startup
sequence. Also, if you do not use a program during a
session, it is not loaded at all, thus saving you memory.
Arp programs (and programs written using the Arp
conventions) will save you greatly in memory usage. Each
program requests only as much stack as it needs (whether
from disk or from resident), and can save many many bytes
per-invocation on this alone. Arp resident programs are
also smart, doing any data cloning required only if
resident, diskloaded copies don't need to be cloned, and so
they are not.
All programs which work on the Commodore list should
also work on Arp's, although they won't save you as much
memory as Arp's will, you can still take advantage of the
load-on-demand and checksum safety factors of the Arp
resident*.
Builtins
As mentioned above, the shell contains many commands already
builtin to ASH. To find out which ones, use the '?' command
(i.e., type ? and then hit return). A list of all builtin
commands will be displayed. See the appropriate section
below for a description of the commands and their
descriptions.
IO Redirection
You can redirect program input and output by using the '<',
'>' and
__________
* If you want fast error message reporting, you can make
the Fault program resident by doing 'Ares C:FAULT'.
This will force all error routines in ASH to use the
resident version of fault. This won't work with the
Commodore shell, incidentally.
Page 4
Ash Users manual. V1.3.0 March 30, 1989
1: Type <file ; reads from file
2: Type >file ; creates/overwrites to file.
3: Type >>file ; appends/creates file.
When the '>' operator is used, the file is created if it
does not exist. If it does exist, then all its former
contents are lost. When the '>>' operator is used, if the
file already exists the contents are *not* lost, new output
is appended to the end of the old. If the file does not
exist, then it is created. You can use '>>' to safely
output to files (for example, in shell scripts) without
worrying about destroying existing files*.
Note that even scripts can be redirected (either in or
out). See the section on scripts for more information.
Another type of IO Redirection is called piping. It is
important enough to deserve a special section of its own,
later on.
Alias
An Alias is a way of renaming commands in the shell without
actually changing the name of the command on the disk. This
is generally better than renaming the command, since if you
rename your command, other peoples scripts and programs that
reference the command might not find it. A common use of
alias's is to give commands shorter names that are easier to
type, here are a few:
Alias cp copy
Alias ls List
Alias rm Delete
Alias s Status Full
Now when you type 'cp', you will get the Copy command, but
__________
* This differs from the Commodore shell. Under the
Commodore shell, if the file does not exist the append
('>>') operator will not create the file for you, it
will abort with an error message.
Page 5
Ash Users manual. V1.3.0 March 30, 1989
with the name you defined. Other uses for Alias's are to
provide special names for commonly used functions. For
example, the ARP 1.3 Assign command provides a special
switch which will check to see if a name is already
specified as a logical device - its syntax is:
Assign NAME: Exists
which checks to see if NAME: has been assigned, and displays
its assignment if found. This is a common option, and you
can define an alias to shorten the typing and give it a
meaningful name like this:
Alias Exists Assign [] Exists
Notice the square brackets? This is a directive to the
shell which tells it to replace the brackets with any
command line input you supply when you invoke the alias.
For example:
Exists S:
will cause the shell to evaluate the command 'Assign S:
Exists'. Notice that the S: has replaced the square brackets
in the command? Some other useful alias's are listed below:
Alias Today list [] Dates Sort Since Today
Alias Recent list [] Dates Sort
Alias PathList list [] lformat "%S%S"
Alias Update Copy [] Flags cqo
Alias Pri ChangeTaskPri
Another use of Alias is to override the shell's builtin
commands with a disk based version of the same name. You
might want to do this because you prefer another command's
behavior, or it could be that a bug could crop up in one of
the builtin commands making it necessary that it be
replaced. To do this, simply define the command with the
full path name:
Page 6
Ash Users manual. V1.3.0 March 30, 1989
Alias Endskip C:Endskip
this will force the shell to use the version of the command
stored in the C: directory, rather than the shell's internal
version.
1.
Summary of Alias syntax
To sum up then, you can define
a new alias as follows:
Alias AliasName Body
where AliasName is the name you want to use to refer to your
alias, and Body is the command you wish to be executed.
Body can contain any legal command, and can optionally
contain square brackets ('[]') which tell the shell where to
place additional input from the command line.
To see the current alias's, type Alias by itself. To
remove an alias definition, type Alias AliasName. For
example:
Alias Exists
will remove the alias definition for Exists. If you want to
redefine an alias, it is not necessary to remove it first.
Script Language
Ash contains the complete AmigaDOS batch language
internally. This makes scripts with conditionals (IF ELSE)
and SKIP commands execute much more quickly. You can also
save a lot of disk space by deleting these commands from
your disk altogether. Note however, if you have
conditionals in your startup-sequence, you will have to
modify your startup-sequence to take advantage of ash's
builtins, so please don't Delete anything until you are sure
things are working correctly.
You can execute any script from the command line by
simply typing its name. Note that to do this, the 'S' and
the 'E' bits must be turned on (use the protect command for
this). The 'E' bit tells the shell the script is
executable, and the 'S' bit tells the shell that it is a
script, not a binary executable. To make a script
Page 7
Ash Users manual. V1.3.0 March 30, 1989
executable from the command line, you would use a command
line like this:
Protect Scriptname +se
To prevent a script from auto-executing, we recommend you
just clear the 'e' bit, since you can use the 's' bit in the
listings to remind you that it is a script file, and not a
program.
Scripts executed in this way appear indistinguishable
from programs, and you can use the i.o. redirection
operators (<, >, and >>) to divert the input or output to or
from files. Scripts can also be use as the source or the
sink for pipes. See the section on piping for more
information.
Other improvements to the script language include much
more informative error messages and regular handling of
parameter expansion including <$$>. Many irritating little
bugs (such as not recognizing tabs as whitespace) in the
current Commodore batch language have been fixed as well.
When using scripts with arguments (the .key directive
and the braket characters), we recommend that you always
change your braket characters to something other than the
default using the .BRA and .KET directives. These were
chosen badly by the original author of the script language
since they conflict with the IO redirection operators.
Perhaps the best choice are the curly braces, since these
are not used for anything else currently.
Environment Variables
The shell expands environment variables that you supply on
the command line. To expand a variable, you use the dollar
('$') character immediately before it. Here is an example:
Echo "$INCLUDE"
If there is an environment variable defined by the name
INCLUDE, the shell will replace it with value of that
variable, and the echo command will display it. Note that
the quotes are not necessary for the variable expansion, but
they are necessary for Echo, which doesn't like spaces in
its input (the variable could expand to a value with spaces
in them).
Page 8
Ash Users manual. V1.3.0 March 30, 1989
To set the value of an environment variable, just use
the '=' character:
FOO=Bar ; assign a value to FOO
Echo $FOO ; display the value
Bar ; echo's output.
You can also concatenate environment variables easily enough
like this:
FOO="$FOO"Fly
Echo $FOO
BarFly
Note that the quotes around the initial environment variable
are necessary for the shell to know when the variable ends.
If you use the variable at the end, these quotes are not
needed, since the dollar sign takes care of delimiting the
variable. It follows that if you want to concatenate
variables, you can do it as follows:
Echo "$FOO$FOO$FOO"
This will print three copies of the value of foo. Of
course, you can also use this in an assignment statement.
To remove an environment variable, give it a null
assignment:
FOO=
will remove FOO from the current environment*.
__________
* Environment variable expansion in the shell reads both
the old Manx/Rockiki/Arp environment variables and the
new Commodore ENV: definition, in that order. However,
setting environment variables from the shell writes only
the older environment implementation, it does not affect
ENV:. If you wish to do this from the shell, contact
ARP central for a patch to arp.library. You can always
Page 9
Ash Users manual. V1.3.0 March 30, 1989
1.
Special Variables
Each invocation of the shell has
three environment variables which are local to that shell,
and can be used by you to discover special state information
about the shell. These are $, ? and ?2. The $ variable
contains the current CLI number, ? contains the return code
of the last command and ?2 contains the operating systems
result2 error. Note that ? and ?2 are changed each time a
command executes, so if you want to use them, you should
assign their values to some other variable so that you can
preserve them. Here is an example of a script which exits
with an error message and reports the return code:
; This file fragment illustrates the use of ? and ?2
Command args ; execute some command
RC=$? ; get return code
R2=$?2 ; and save result 2
IF NOT VAL $RC EQ 0
Echo "Command exited with error $RC result2 $R2"
ENDIF
The variable '$' corresponds to the braketed expression <$$>
introduced by Commodore in 1.3. Generally, it is preferable
to use $$ without brakets to allow the shell to expand it
without writing a temporary file (as is required by the
Commodore convention). Ash supports both. This is useful in
making temporary files or assigns or whatever, since it is
unique to each CLI invocation, although concurrent shell
processes in ash do share the same number, so you should be
careful when piping to and from scripts and using this
variable. Here is an example that displays all three values
of these variables in an Echo command:
Echo "rc = $? Result2 = $?2 CLI# = $$"
____________________________________________________________
use the SetEnv program (ARP's or Commodores) to write to
env:.
Page 10
Ash Users manual. V1.3.0 March 30, 1989
Pipes and PipeLines
Pipes are a way of connecting programs together without
using temporary files. As a simple example, say you wanted
a line numbered listing of your current directory. One way
to do this is:
List >tmpfile
Type tmpfile opt n
Delete tmpfile
First we create a tempfile using the list command, then we
type it using the line number option of type, and then we
delete our tmpfile. Using pipes, this would all be
accomplished as follows*:
List | Type opt n
The '|' character is the pipe symbol. It causes Ash to
connect the output of the list command to the input of Type.
Aside from not using a temporary file, pipelines such as
this are much faster than the usual single command
execution, since Ash takes advantage of the multitasking
nature of the Amiga to run each one at the same time. This
means that List can be preparing more output for Type as
Type is processing the last input received from list.
More than one command can be used in a pipeline. Here
is an example which creates a line numbered hexdump from a
directory listing:
Dir | Type opt h | Type opt n
The basic idea behind pipes is to combine commands which do
one thing with other commands which do something else to get
the results you want. In the above example, List doesn't
create line numbers, while type does. By combining their
__________
* In order to use pipes with ASH you must have a pipe
device. See Appendix A for information on how to obtain
and mount a pipe device that will work with ash.
Page 11
Ash Users manual. V1.3.0 March 30, 1989
capabilities, you create a super list that also does line
numbers. (Note that you must separate the '|'s from the
commands by whitespace. While this differs from the
implementation of pipes on other operating systems, it is
necessary on the Amiga due to the use of '|' in wildcard
patterns).
Once you get accustomed to the idea of pipes and
connecting programs, you will wonder how you ever got along
without them. In the pipelines above, the Type program acts
as something called a 'filter'. A filter is any program
that takes something as input, does something to the input,
and outputs this altered input. In order to act as filters,
programs must be able to read from their standard input
(keyboard) and display to their standard output. Of the
standard set of commands that comes on the Workbench disk,
useful filters are Sort, Type and Search. Note that only
the ARP programs can be used in pipe lines, the Commodore
programs have bugs that prevent them from using the keyboard
as input*.
1.
Show me more pipelines
The Dir and List programs have a
lot of options (they probably have too many options, but
that's a story for another time). One thing you can't do
with List is display programs that match a certain set of
protect bits, for example, you might want to see all the
files in a directory which are scripts and executable. To
do this, you can use a pipeline such as the following:
List | Search STDIN " ?s????e? "
Note that when you use Search in a pipeline, you must supply
the STDIN keyword in caps as the filename. The search
string was made by examining the usual list output, and
masking out the protection bits we aren't interested in with
the '?', which matches any character:
-s--rwed (List output)
?s????e? (our search string)
__________
* Some people might like this. One person's bug is
another's feature.
Page 12
Ash Users manual. V1.3.0 March 30, 1989
Another useful example utilizes a pipeline to determine
how well commented 'C' language files are by combining
Search and Type:
Search *.c /'* | type opt n
The idea here is to Search through all the files ending in
'.c' in the current directory, looking for a comment start
sequence. (Notice that we have to use the single quote to
escape the star, which has a special meaning to Search as a
pattern. The single quote tells search to regard the star
as just a character, not a pattern.). Once Search has found
the commented lines, we pass them on to Type to count. The
highest numbered line will be the total number of comments
found in the files. We don't use the STDIN keyword here,
because Search is not reading from a pipe, it is acting as
the source (beginning) of a pipeline.
There are many utilities in the public domain and
elsewhere that can be used as filters, and since filters are
so easy to write, they are very convenient to create as you
need them.
2.
Show me how to use pipes with scripts
Combining scripts
in pipelines provides a convenient way to create new
commands from old, the applications are limitless. One
problem shared by many people is updating the software on
their disks when a new revision comes out. Often only a
subset of the distribution is used, or perhaps a different
organization of the software on the disk. In any case, it
rarely works to do a straight copy. Here is a solution in
the form of a script that uses pipes and the new Arp Read
command to copy only those files which already exist in the
destination directory from the source disk:
Page 13
Ash Users manual. V1.3.0 March 30, 1989
.Key Dest/a
;Update script: CD to directory with new files, then do
;List nohead quick | Update dest:dir/
Lab Loop ; loop back to here
Read Filename ; read the filename from pipe
if $? EQ 1 VAL ; Read returns 1 on eof
Echo "Copy complete!"
Quit 0
Endif
if Exists <Dest>$File ; If we have an old copy
Echo "Copying $File to <Dest>$File"
Copy $File to <Dest>$File ; copy to new
Endif
Skip Back Loop
Another way to do the same thing is to use the output of the
List command with its LFORMAT option to send the commands to
the shell. (You can send commands to the shell by piping
them into the builtin command Execute). Here is an example
which does the same thing using list and LFORMAT, if more
quietly:
cd destdir ; change to dest
list srcdir lformat="Copy %S%S to %S" | Execute
Read is an interesting and useful command. It can be used
to read from the keyboard as well as in a pipe, and it also
does a certain limited parsing on its input. For example:
Read First Last Middle
Will break the input up on quoted lines or (if no quotes) on
white space. The first variable gets the first portion of
the input, the second gets the second, and the last variable
gets whatever is left.
Here is an example using List and Read to do an
interactive version of type:
Page 14
Ash Users manual. V1.3.0 March 30, 1989
; Interactive type: Usage: List nohead | intertype
Lab Loop
Read Filename Size Protection DateTime
if $? EQ 1 VAL
Echo "No more files"
Quit 0
ENdif
ask "Type $Filename ?"
If WARN
Echo "==========================================="
Echo "File $Filename last modified on $DateTime"
Echo "============================================"
Type $Filename
Endif
skip back loop
Notice how we use the capability of Read to break up lists
output to display selected information about the file in a
custom header. Many more custom scripts are possible, and
are often easier to write the custom programs to do the same
thing. If you are not a programmer, but are familiar with
the commands available on the Amiga, you should also have
little difficulty in customizing your environment.
Command Substitution
Another advanced feature which Ash makes available to you is
Command Substitution. This feature allows you to replace a
command with its output, and it works like this:
Echo "Todays date is $(Date), have a nice day!"
When the shell sees the sequence '$(Command)', it runs
whatever* Command is (Date, in the example above), and then
__________
* This is implemented internally using pipes, so you will
need to have a pipe device mounted to use this command.
Please see Appendix A for information on pipes that will
Page 15
Ash Users manual. V1.3.0 March 30, 1989
replaces the entire string with the output of Command, the
parens and dollar sign do not appear in the output at all.
One possible outcome of the command line above is:
Todays date is Friday 16-Mar-89 10:57:12, have a nice day!
You can nest command substitutions, and the substitutions
can be any shell command, including a pipeline. Whatever
comes out of the end of the pipe is what the shell will use
in place of the command. Here is an example showing nested
command substitution:
Echo "The current time is $(Echo "$(Date)" len 8)"
The current time is 10:57:12
This example uses the ability of Echo to take a substring of
its input. First Date is expanded, and then the inner echo
is expanded, and eventually the output of this Echo replaces
the entire substitution request and the final Echo is
evaluated. This is an extremely useful ability, one which
often eliminates the need to write temporary files. Here is
an example of a loop counter using Eval and command
substitution in a script:
____________________________________________________________
work with ash.
Page 16
Ash Users manual. V1.3.0 March 30, 1989
.Key loop
; Demo loop
.Default loop 10
Counter=<loop> ; initialize counter
Lab start
Echo "Loop $Counter"
Counter=$(Eval $Counter - 1)
if val $Counter GT 0
skip back start
endif
Echo "All done"
The important line is the one containing Eval. Eval's
default behavior is to print its result, so we can use it in
a command substitution expression to update the value of the
variable Counter.
Another use of environment variables involves the Arp
programs Basename and TackOn. Basename takes a pathname and
extracts the filename portion of it:
Basename DF1:include/exec/types.h
types.h
You can also give Basename a suffix to delete. For example,
to change a file ending in .c to one ending in .o, try this:
Echo "$(Basename file/program.c .c).o"
program.o
TackOn takes a pathname and a filename, and tacks the
filename onto the end of the pathname*.
__________
* You could do this with normal variable concatenation
except that some pathnames contain a ':' character.
TackOn handles this condition more efficiently than a
shell comparison could.
Page 17
Ash Users manual. V1.3.0 March 30, 1989
Tackon DF1:include exec
DF1:include/exec
Tackon DF1:include/exec types.h
DF1:include/exec/types.h
You can use these two commands to make your scripts much
more robust. Here is another example of the update script
given earlier. This one handles filenames much better, and
also has a better user interface:
.Key Dest/a
; Update script: version 2.
; usage: pathlist | update dest
;
Lab Loop
Read Sourcename ; read source filename from pipe
if val $? EQ 1
Echo "Copy complete!"
Quit 0
ENDIF
tmp="$(Basename $Sourcename)"
Destname="$(Tackon <Dest> $tmp)"
if Exists $Destname
Echo "Copying $Sourcename to $Destname"
Copy $Sourcename to $Destname
Endif
Skip Back Loop
Notice that this uses the alias PathList shown earlier to
generate full pathnames for the pipe. This version of the
update script is much more robust than the earlier one,
since the user can type the destination directory in a
number of ways, and does not have to CD to the source
directory he wants to update from. Again, the interesting
lines are where the destination filename is generated. It
is quite simple, first we use Basename to extract the
filename from the piped input, and then we use TackOn to
append it to the destination directory name. You can take
advantage of the fact that command substitution nests to
eliminate the temporary variable by doing:
Page 18
Ash Users manual. V1.3.0 March 30, 1989
Destname="$(Tackon <Dest> $(Basename $Sourcename))"
Another useful thing you can do with command substitution is
to use it to generate a list of filenames for a command that
does not accept wildcards. There are many programs
available in the public domain and elsewhere that accept
multiple commands but do not let you use wildcards. To
generate a list of files for them to use, you can use the
statement:
Program "$(Dir)"
Of course, you can use any of the options to Dir, or the
list command to generate exactly the file list you want. To
check on your file list before passing it to the program you
can do:
Echo "$(Dir)"
first. Note that there is currently a limit of 1000
characters to the total length of the argument line in ash
(the total command line length is 1256 characters, including
the name of the command).
Prompt enhancements
Ash supports all the prompt enhancements introduced by
Commodore in their 1.3 shell. You can use "%S" in the
prompt definition to display the name of the current
directory, and you can use "%N" to display the current CLI
number. Ash supports all these, as well as %P which acts
the same as %S*. All of these can be in upper or lower
case.
__________
* This was done to be compatible with earlier releases of
the ARP software. Until Commodore released the 1.3
shell, one of the only ways to get the current directory
string in your prompt was with ARP's Prompt command, and
it used %P.
Page 19
Ash Users manual. V1.3.0 March 30, 1989
You can also have the prompt expand environment
variables and utilize command substitution in prompt lines
as explained below.
Using Variables and Substitutions in Prompt and Alias
The shell will handle environment expansion and command
substitution as well as pipes in prompt strings and aliases.
The methods for including these in each one are the same,
which is why they are discussed together here.
You can use command substitution in your shell prompt
to do things like display the current time by using the Date
command. Initially, you might try something like this:
Prompt "$(Date)"
which would appear to work. In fact, you might not notice
it didn't work until the morning, when the bright light of
the sun came pouring through the windows of your computer
room. What you really need to do is this:
Prompt "\$(Date)"
Notice the escape character before the $? This tells the
shell to delay evaluation of the prompt string until the
prompt is actually displayed*. Without the escape
character, the date command gets expanded immediately, and
so the time in your prompt gets set permanently to whatever
it was when you issued the prompt command. If you want to
only see the time portion of the string, you can do it like
this:
Prompt "\$(Echo len 8 \"\$(Date)\")\n> "
__________
* These examples use the \ character for an escape
character. If you have another preference, or if you
use the default ('*'), then just replace the backslashes
in this section with the escape character of your
choice.
Page 20
Ash Users manual. V1.3.0 March 30, 1989
This might look a little daunting, but most of the escape
sequences (with the exception of \n, which is there for
cosmetic purposes to print a newline as part of the prompt),
are there to force delayed evaluation on the shell. Quotes
are necessary around $(Date) because the 1.3 Echo requires
them. This means they must also be escaped, otherwise, the
prompt command will regard them as delimiters and give you a
"too many arguments" error.
The same thing is true as far as environment variable
expansion is concerned. It is interesting to be able to
display the return codes from the programs you run in the
shell prompt. This is easy to do using the escape trick
shown above:
Prompt "RC = \$? R2 = \$?2\n> "
Any environment variable can be displayed in this manner.
Alias's are similar. In fact, aliases are a little
clearer, because you can see what is actually stored there
by typing Alias without any arguments. Here is an example
that might clarify the above discussion:
Alias ThisTime Echo "$(Date)"
Alias CurrentTime Echo "\$(Date)"
If you now type 'Alias' <ret>, this is how the display
looks:
Alias <ret>
CurrentTime=Echo "$(Date)"
ThisTime=Echo "Saturday 18-Mar-89 11:49:31"
Notice that the ThisTime definition contains the expanded
string from when the alias was defined. The CurrentTime
definition, because we used an escaped dollar in its
definition, contains a command that will actually display
the current time when it is invoked*.
Page 21
Ash Users manual. V1.3.0 March 30, 1989
You can use pipes inside of Alias's if you need too,
but the same principles apply. You must escape all the pipe
characters you use in order to prevent the shell from trying
to pipe away immediately:
Alias Allc Dir [] opt a \| Search STDIN *.c
3.
Modifying your startup sequence to use ASH
Before trying to modify your startup-sequence in this way,
please make a copy of your disk and work from that. Then,
when you are sure it is working, you can make the changes on
the main disk. We are not trying to scare you, but it is
easy to make mistakes when doing things like this.
The main advantage to modifying your startup-sequence
to use Ash is to take advantage of the faster executing
conditionals language builtin to ash and/or some of the nice
features of ash such as variable expansion or command
substitution. If you don't use any conditionals in your
startup-script, or don't want to use any of the Ash features
in your startup-script, then you can skip this section, but
please see the section on the 1.3 startup.
What you will want to do is break out a portion of your
startup-script file into a special init file called shell-
boot. (You can call it whatever you want, but don't call it
shell-startup unless you want it to be executed whenever you
invoke a new shell). Place most of your commands in this
shell-boot file, and then let your startup-sequence file
have the single command:
AShell From S:Shell-Boot
That's all there is to it!
__________
* Of course, if you really want an alias to just display
the output of Date, this is much less efficient that
just using Date as in "Alias dt Date".
Page 22
Ash Users manual. V1.3.0 March 30, 1989
Modifying 1.3 startup to take advantage of ARP
In general, you can speed up your startup sequence file by
combining more commands on one line. Most of the Commodore
commands still do not accept multiple input arguments, while
most of ARP's always have. By doing all of your assigns and
mounts on one line you save a little bit of time.
If you are using ASH, then you should definitely remove
all the Resident stuff from StartupII (on a virgin 1.3
workbench disk), and replace it with ARes command lines.
Note that a lot of the things Commodore suggests you make
resident are built into ash, so you shouldn't just do a
global search and replace. Replacing Resident with ARes
will dramatically speed up your startup-sequence times,
since the Arp resident is 'load-on-demand'. The command
will only be loaded when you invoke it, not when you use
ARes (unless you use the Force keyword). This also saves you
memory, since if you don't use the command it is not made
resident.
4.
Appendix A: Finding a pipe device to work with ASH
The only pipe device known to work with ash at this time is
PIP:, which is part of conman, a console handler replacement
by William Hawes. If you have conman, you already have PIP,
otherwise, in order to use the full features of ASH you will
have to obtain a copy. Fortunately, this is easy to do, it
is widely available on bulletin boards and from users groups
as shareware.
Once you have installed conman as described in the
conman documentation, make sure you have an entry such as
the following in your mountlist file:
PIP: Handler = L:ConHandler
Stacksize = 600
Priority = 5
GlobVec = 0
#
Once you have done this, you can place a mount pip: command
in your startup-sequence, and start playing with pipes.
Note that the Commodore PIPE: device supplied with the
1.3 distribution does not work with ASH's internal pipes
(using the '|' character). PIPE: uses only named pipes, ASH
requires unnamed pipes internally. You can use both PIP:
and PIPE: together if you need both named and unnamed pipes
Page 23
Ash Users manual. V1.3.0 March 30, 1989
and we have also heard rumors of someone working on an
enhancement to PIPE: to allow it to support unnamed pipes as
well, but nothing definite is known about this new super
pipe.
5.
Appendix B: Bug reports and enhancement requests
If you find a bug in Ash or any of the Arp software, it is
important that you report it, so that we can fix it. Note
that ARP is distributed without a Warranty of any kind, but
we still want to fix our bugs. When you make a bug report,
it helps if you can state at the top of the page which Arp
program is the problem, this helps to route the report to
the person(s) currently working on that aspect of the ARP
project. It is also important to give enough information
for us to reproduce the problem. Right or wrong, if we can't
reproduce the problem we tend to assume it is operator error
and not worry about it.
Enhancement requests are similar, we are very
interested in requests for enhancements or ideas for new Arp
software. Things we would like to add to ash (for example)
are:
1. Complete subshell implementation. This is only
partially implemented currently, pipes and command
substitution run in subshells.
2. String operations on variables. Probably not csh
model. Note that you can do a limited amount of this
with Echo.
3. Enhancements to batch language, things like a for
command, possibly a case statement, others.
Page 24