[comp.sources.amiga] v02i021: shell - cshell-like command processor V2.11

page@swan.ulowell.edu (Bob Page) (10/25/88)

Submitted-by: dillon@cory.berkeley.edu (Matt Dillon)
Posting-number: Volume 2, Issue 21
Archive-name: unix/shell211.doc

# This is a shell archive.  Remove anything before this line
# then unpack it by saving it in a file and typing "sh file"
# (Files unpacked will be owned by you and have default permissions).
# This archive contains the following files:
#	shell.doc
#
if `test ! -s shell.doc`
then
echo "writing shell.doc"
cat > shell.doc << '\Rogue\Monster\'

SHELL V2.11  (C)Copyright 1986-88, Matthew Dillon, All Rights Reserved.
Freely distributable for non-profit only.

	    old users: Please read the version history at the bottom of
	    this document for changes and additions.


      (A)   Compiling
      (B)   Overview
      (C)   Quicky tech notes on implimentation.

      (D)   Command pre-processor
      (E)   Command-list
      (F)   special SET variables
      (G)   Version history

       See also EXAMPLES.TXT

			NEW FEATURES THIS VER

    (Taken from the history below):  an IPC implementation, ENV: variable
    support, many commands enhanced, some bugs fixed.

			    COMPILATION


    The SHELL will compile only under AZTEC C and requires my
    support library (SUP32.LIB) to link as well as a precompiled
    symbol table of all AMIGA .H files.  A Makefile is included.
    Note that the shell must be compiled using 32 bit integers (+L)
    option and linked with SUP32.LIB and C32.LIB.  Additionaly, my
    dres.library must be present in order to use the IPC facility.

    NOTE that converting the shell to use 16 bit integers does not
    make it significantly smaller or faster.  Do not waste your time.



			     OVERVIEW


    Matthew Dillon
    891 Regal Rd.
    Berkeley, California 94708
    USA

    ..!ucbvax!dillon
    dillon@ucbvax.Berkeley.EDU
    dillon@cory.Berkeley.EDU

    This is not a shareware program.  My basic philosophy is to write
    software for myself and distribute it if I think it will benefit
    others (that is, unless I start going broke).  Contribute if you want
    to.

    IT IS SUGGESTED THAT YOU USE CONMAN OR THE NEW 1.3 ENHANCED CONSOLE
    DEVICE.  CONMAN does to my shell what Steve did in his Manxfied (old
    term) 16 bit version of my shell, and more.  It isn't required, but
    CONMAN (shareware) complements the functionality of the shell quite
    well.


   PROBLEMS

   -Make sure you give the SHELL a big enough stack, especially if you
    intend on running shell scripts which source other scripts.  8192
    is suggested.  Remember, STACK must be run BEFORE you run the shell.
    Running it from the shell does not effect the shell's stack.

   -You should not redirect the RUN command. to redirect the command the
    RUN command is running, embed a standard CLI redirection in the command
    string:

    RUN ">file" command

   -Append '>>' does NOT work with BCPL programs.  It does work with all
    internal and non-bcpl (read C) programs.

   OVERVIEW of the major features:

   -History mechanism (complements conman quite nicely, in fact)
   -Redirection
   -Piping (sort of)
   -Command search path by name and by CLI path list
   -Aliases
   -Variables & variable handling (embedded variables), and enviroment variables
   -Automatic file name expansion via '?' and '*'
   -Conditionals
   -Shell Scripts
   -many built in commands to speed things up


			    COMMAND PREPROCESSOR


   preprocessing is done on the command line before it is passed on to
   an internal or external routine:

   ^c	    where c is a character is converted to that control character.
	    Thus, say '^l' for control-l.

   $name    where name is a variable name.  Variable names can consist of
	    0-9, a-z, A-Z, and underscore (_).  The contents of the
	    specified variable is used.  If the variable doesn't exist,
	    the specifier is used.  That is, if the variable 'i' contains
	    'charlie', then '$i' -> 'charlie'.  If the variable 'i' doesn't
	    exist, then '$i'->'$i' .

   ;	    delimits commands.	 echo charlie ; echo ben.

   ' '      (a space). Spaces delimit arguments.

   "string" a quoted string.  For instance, if you want to echo five spaces
	    and an 'a':

	    echo      a       -> a
	    echo "    a"      ->      a

   \c	    overide the meaning of special characters.	'\^a' is a
	    circumflex and an a rather than control-a.	To get a backslash,
	    you must say '\\'.

	    also used to overide alias searching for commands.

   >file    specify output redirection.  All output from the command is
	    placed in the specified file.

   >>file   specify append redirection (Does not work with BCPL programs).

   <file    specify input redirection.	The command takes input from the
	    file rather than the keyboard (note: not all commands require
	    input).  It makes no sense to say  'echo <charlie' since
	    the 'echo' command only outputs its arguments.

   |	    PIPE specifier.  The output from the command on the left becomes
	    the input to the command on the right.  The current SHELL
	    implimentation uses temporary files to store the data.

   !!	    execute the previously executed command.
   !nn	    (nn is a number).  Insert the history command numbered n (see
	    the HISTORY command)
   !partial search backwards through the history list for a command which
	    looks the same as 'partial', and execute it.

   #	    Enter comment.  The rest of the line is discarded (note: \#
	    will, of course, overide the comment character's special
	    meaning)

   ^search^replace
	    a '^' at the beginning of the line indicates history
	    replacement.  The first occurance of 'search' in the previous
	    command is changed to 'replace', and the command executed.



			     SHELL COMMANDS


   The first argument is the command-name... if it doesn't exist in the
   list below and isn't an alias, it is assumed to be an external (disk)
   command.

   AUTOMATIC SOURCING may be accomplished by naming shell scripts with a
   .sh suffix.	Thus, if you say 'stuff' and the file 'stuff.sh' exists in
   your current or C: directory, it will be SOURCED with any arguments you
   have placed in the $_passed variable.

			  EXCEPTION_PROCESSING

      if no _except variable exists, any command which fails causes the
      rest of the line to abort as if an ABORTLINE had been executed.  If
      the _except variable exists, it is of the form:

      "nnn;commands..."

      where nnn is some value representing the minimum return code required
      to cause an error.  Whenever a command returns a code which is
      larger or equal to nnn, the commands in _except are executed before
      anything.  WHEN _except EXISTS, THE COMMAND LINE DOES NOT ABORT
      AUTOMATICALLY.  Thus, if you want the current line being executed
      to be aborted, the last command in _except should be an "abortline".

      exception handling is disabled while in the exception handling routine
      (thus you can't get into any infinite loops this way).

      Thus if _except = ";", return codes are completely ignored.

      example:

      set _except "20;abortline"


   ABORTLINE

      or just 'abort'.  Causes the rest of the line to be aborted. Used in
      conjunction with exception handling.

      % echo a;abort;echo b
      a


   HELP

      simply displays all the available commands.  The commands are
      displayed in search-order.  That is, if you give a partial name
      the first command that matches that name in this list is the one
      executed.  Generally, you should specify enough of a command so that
      it is completely unique.

   QUIT
   EXIT
   RETURN [n]

      quit my SHELL (awww!).  End, El-Zappo, Kapow. Done, Finis.  If you
      use RETURN and are on the top source level, the shell exits with the
      optional return code.  (see RETURN below)


   SET
   SET name
   SET name string

      The first method lists all current variable settings.
      The second method lists the setting for that particular variable,
      or creates the variable if it doesn't exist (to "")
      The last method sets a variable to a string.

      see the section on special _ variables down below


   UNSET name name name....

      unset one or more variables.  Deletes them entirely.


   SETENV name string

      Create/Modify an enviroment variable.  The enviroment is maintained
      in ENV:, with a separate file for each enviroment variable.  This
      should be assigned to a directory somewhere.

   UNSETENV name name name....

      remove the specified variables from the enviroment list.	This
      call DeleteFile()'s the enviroment variable from ENV:

   PRINTENV

      Print the contents of the enviroment directory ENV:

   ALIAS
   ALIAS name
   ALIAS name string

      same as SET, but applies to the alias list.  You can alias a single
      name to a set of commands.  For instance:

      alias hi "echo a; echo b"

      then you can simply say 'hi'.  Aliases come in two forms the second
      form allows you to place the arguments after an alias in a variable
      for retrieval:

      alias xxx "%i echo this $i is a test"

      % xxx charlie
      this charlie is a test

      The rest of the command line is placed in the specified variable
      for the duration of the alias.  This is especially useful when used
      in conjunction with the 'FOREACH' command.


   UNALIAS name name name...

      delete aliases..


   ECHO string
   ECHO -n string

      echo the string to the screen.  If '-n' is specified, no newline is
      output.


   STRHEAD  varname breakchar string

      remove everything after and including the breakchar in 'string' and
      place in variable 'varname':

	 % strhead j . aaa.bbb
	 % echo $j
	 aaa
	 %


   STRTAIL  varname breakchar string

      remove everything before and including the breakchar in 'string' and
      place in variable 'varname':

	 % strtail j . aaa.bbb
	 % echo $j
	 bbb
	 %


   SOURCE file [arguments]

      execute commands from a file.  You can create SHELL programs in
      a file and then execute them with this command.  Source'd files
      have the added advantage that you can have loops in your command
      files (see GOTO and LABEL).  You can pass SOURCE files arguments
      by specifying arguments after the file name.  Arguments are passed
      via the _passed variable (as a single string).

      Automatic 'sourcing' is accomplished by placing a .sh extension on
      the file and executing it as you would a C program:

      --------- file hello.sh ---------
      foreach i ( $_passed ) "echo yo $i"
      ---------------------------------
      % hello a b c
      yo a
      yo b
      yo c

      NOTE: The hash '#' as the FIRST character on the line is a comment
	    within script files.

   MV from to
   MV from from from ... from todir

      Allows you to rename a file or move it around within a disk.  Allows
      you to move 1 or more files into a single directory.  (if todir == '/',
      the items are moved to the parent directory).

   CD
   CD ..
   CD path

      Change your current working directory.  You may specify '..' to go
      back one directory (this is a CD specific feature, and does not
      work with normal path specifications).  Note that CD / also goes
      back one directory.

      CD without any arguments displays the path of the directory you
      are currently in.


   PWD
      rebuild _cwd by backtracing from your current directory.	The $_cwd
      variable can get confused by Assign'd labels.

   RM [-r] file file file...

      DeleteFile().  Remove the specified files.  Remove always returns
      errorcode 0.  You can remove empty directories.  The '-r' option
      will remove non-empty directories by recursively removing all sub
      directories.

   CP file	(to current directory)
   CP [-r] dir	(to current directory)
   CP file file
   CP file1 file2...fileN dir
   CP [-r] dir1 dir2...dirN dir

      copy files or directories.  when copying directories, the "-r" option
      must be specified to copy subdirectories as well.  Otherwise, only
      top level files in the source directory are copied.


   MKDIR name name name...

      create the following directories.


   HISTORY [partial_string]

      Displays the enumerated history list.  The size of the list is
      controlled by the _history variable.  If you specify a partial-
      string, only those entries matching that string are displayed.


   MEM

      Display current memory statistics for CHIP and FAST memory.


   CAT [file file....]

      Type the specified files onto the screen.  If no file is specified,
      STDIN in used.  CAT is meant to output text files only.  You cannot
      use CAT to join binaries together.

   DIR [-s] [path path ... ]

      Get a directory listing of the current directory or specified
      directories.  The -s option causes DIR to display a short-form
      listing.

   DEVINFO [device: device:... ]

      Display Device statistics for the current device (CD base), or
      specified devices.


   FOREACH varname ( strings ) command

      'strings' is broken up into arguments.  Each argument is placed in
      the variable 'varname' in turn and 'command' executed.  To execute
      multiple commands, place them in quotes:

      % foreach i ( a b c d ) "echo -n $i;echo \" ha\""
      a ha
      b ha
      c ha
      d ha

      Foreach is especially useful when interpreting passed arguments in
      an alias or source file.

      NOTE: a GOTO inside a FOREACH will have an indeterminate effect.


   FOREVER command
   FOREVER "command;command;command..."

      The specified commands are executed over and over again forever.

      -Execution stops if you hit ^C
      -If the commands return with an error code.

      NOTE: a GOTO inside will have an indeterminate effect.


   RETURN [value]

      return from a source file.  The rest of the source file is
      discarded.  If given, the value becomes the return value for the
      SOURCE command.  If you are on the top level, this value is returned
      as the exit code for the shell.


   IF -f path
   IF argument conditional argument ;
   IF argument

      If a single argument is something to another argument.  Conditional
      clauses allowed:

      <, >, =, and combinations (wire or).  Thus <> is not-equal, >=
      larger or equal, etc...

      If the left argument is numeric, both arguments are treated as
      numeric.

      usually the argument is either a constant or a variable ($varname).

      The third form if IF is conditional on the existance of the argument.
      If the argument is a "" string, then FALSE , else TRUE.

      The first form is TRUE if the path can be openned with modes 1005.


   ELSE ;

      else clause.


   ENDIF ;

      the end of an if statement.


   LABEL name

      create a program label right here.  You can only have labels within
      a source file.


   GOTO label

      goto the specified label name.  You can only use this command from a
      source file.


   DEC var
   INC var

      decrement or increment the numerical equivalent of the variable and
      place the ascii-string result back into that variable.


   INPUT varname

      input from STDIN (or a redirection, or a pipe) to a variable.  The
      next input line is placed in the variable.


   VER

      display my name, the version number, and the version date.

   IPC appname[.project] command

      Send an IPC command to the .CMD IPC domain for the specified
      application.  An optional project name within that application
      may be supplied.	The text command is sent to the application.

      Only applications that support the DRES.LIBRARY IPC interface
      can communicate via this command.  DRES.LIBRARY must exist for
      this command to work.  Examples:

      forever "ipc dmouse mouse;ipc dmouse nomouse"     (DMouse V1.11 and beyond)

      Currently, the shell cannot receive IPC commands.

   SLEEP timeout

      Sleep for 'timeout' seconds.



			  SPECIAL VARIABLES


   _prompt
	 This variable is set to the command you wish executed that will
	 create your prompt.

   _history
	 This variable is set to a numerical value, and specifies how far
	 back your history should extend.

   _histnum
	 This variable contains the history # of the next command that
	 will be executed.

   _debug
	 Debug mode... use it if you dare.  must be set to some value

   _verbose
	 Verbose mode (for source files).  display commands as they are
	 executed.

   _maxerr
	 The worst (highest) return value to date.  To use this, you usually
	 set it to '0', then do some set of commands, then check it.

   _lasterr
	 Return code of last command executed.	This includes internal
	 commands as well as external comands, so to use this variables
	 you must check it IMMEDIATELY after the command in question.

   _cwd
	 Holds a string representing the current directory we are in from
	 root.	The SHELL can get confused as to its current directory if
	 some external program changes the directory.  Use PWD to rebuild
	 the _cwd variable in these cases.

   _passed
	 This variable contains the passed arguments when you SOURCE a file
	 or execute a .sh file.  For instance:

	 test a b c d

	 -------- file test.sh ----------
	 echo $_passed
	 foreach i ( $_passed ) "echo YO $i"
	 --------------------------------


   _path
	 This variable contains the search path when the shell is looking
	 for external commands.  The format is:  DIR,DIR,DIR  Each DIR must
	 have a trailing ':' or '/'.  The current directory is always
	 searched first.  The entire path will be searched first for the
	 <command>, then for <command>.sh (automatic shell script sourcing).

	 The default _path is set to  "c:,ram:,ram:c/,df1:c/,df0:c/"

	 NOTE:	The CLI path is also searched.

    _ignoreeof
	 If this variable exists, EOF is ignored on interactive
	 terminals.  This prevents accidental logouts.

    _copysilent
	 If this variable exists, the CP command will be silent.  The
	 default is now for CP to be verbose.

    _copydate
	If this variables exists, the CP command will attempt to
	transfer the datestamp src->dst file/dir.  For directories,
	only those that CP must create will get the old datestamp
	transfered to them.  Additionaly, the COMMENT, if any, will
	the transfered src->dst file/dir.



			    TECH NOTES



   PIPES have been implimented using temporary RAM: files.  Thus, you
   should be careful when specifying a 'ram:*' expansion as it might
   include the temp. files.  These files are deleted on completion of
   the pipe segment.

   The file names used are completely unique, even with multiple shells
   running simultaniously.

   My favorite new feature is the fact that you can now redirect to and
   from, and pipe internal commands.  'echo charlie >ram:x', for
   instance.  Another favorite:

      echo "echo mem | shell" | shell

   To accomplish these new features, I completely re-wrote the command
   parser in execom.c

   The BCPL 'RUN' command should not be redirected.. .strange things
   happen.  You can use redirection WITHIN the RUN's command line, of
   course, but it should be quoted so the shell doesn't think the
   redirection is for it.

   NO BCPL program should be output-append redirected (>>).



			     VERSION HISTORY

    V2.11:
	-IPC command added (requires dres.library to work).  All new
	 versions of my programs will support this IPC interface.

    V2.10:
	-Command dispatch has been fixed... RUN used to create problems
	 sometimes (would give you a CLI prompt when it should not have).

	-MV fixed ... had problems when moving things to the current
	 directory ("") and names starting with '/'.

	-SETENV, PRINTENV commands added.  $var variables search the
	 enviroment (ENV:).  Aliases are searched for in ENV: as well
	 now.

	 This allows you to have global variables and aliases for all
	 the shells running in the system without having to re-source an
	 initialization file.  Additionaly, to the limits of the command
	 line, the contents of any file in ENV: may be inserted by
	 referencing it as a variable.

	 ANY system variable may be placed in the enviroment instead of
	 the local variables if you wish.

	-DIR enhanced.	Defaults to long list format.

    V2.08:

	-WaitForChar() removed from main processing loop (the old Delay(0)
	 bug though in this case it is WaitForChar(x,1).

	-CP now accepts single parameters (ala MSDOS).. copy a file or
	 directory to the current directory (-r for recursive sub-dirs)
	    CP FILE
	    CP [-r] DIR

	-A new variable, _copydate, which, if it exits, causes CP to
	 transfer both the comment and datestamp of the source to the
	 destination.

	    set _copydate

    V2.07:  (Internal)

    V2.06B:
	-External programs that change the current directory are caught,
	 and no longer crash the machine.

	-CP command, the _copysilent variable, if it exists, causes
	 directory and recursive copies to do their work in silence.

    V2.06:
	-IF enhanced.  -f option added.  (if -f path).  If the named path
	 can be openned with modes 1005, then...

	-various routines fixed.

    V2.04:
	- CP command now internal... see instructions.
	- RM command now has '-r' option.
	- \command forces the command parser NOT to look at aliases.  Thus,
	   you can alias something like 'cd' and have the alias contain a 'cd'
	   which references the internal cd:

	   alias cd "stuff...;\\cd $x"

	- "-c" command line option to execute commands and return.

	   shell -c "echo a;echo b;echo c".

	- _path default now places RAM: and RAM:C first rather than last.
	- _histnum variable .. current history #
	- expanded filenames are sorted.
	- ^search^replace (modify previous command).

    V2.03 AND BELOW

	Before Written History (actually not quite, but there was this
	fire you see....)

\Rogue\Monster\
else
  echo "will not over write shell.doc"
fi
if [ `wc -c shell.doc | awk '{printf $1}'` -ne 21457 ]
then
echo `wc -c shell.doc | awk '{print "Got " $1 ", Expected " 21457}'`
fi
echo "Finished archive 1 of 1"
# if you want to concatenate archives, remove anything after this line
exit
-- 
Bob Page, U of Lowell CS Dept.  page@swan.ulowell.edu  ulowell!page
Have five nice days.