MUX-AE handler
	-- 2000/12/10 ska

I. Overview

The MUX-AE handler allows TSRs and alike programs to install extensions
to COMMAND, hence this function is called "Installable Commands".

There are two subfunctions (quote from RBIL):

--------l-2FAE00-----------------------------
INT 2F U - DOS 3.3+ internal - INSTALLABLE COMMAND - INSTALLATION CHECK
        AX = AE00h
        DX = magic value FFFFh
        CH = FFh
        CL = length of command line tail (4DOS v4.0)
        DS:BX -> command line buffer (see #02977)
        DS:SI -> command name buffer (see #02978)
        DI = 0000h (4DOS v4.0)
Return: AL = FFh if this command is a TSR extension to COMMAND.COM
        AL = 00h if the command should be executed as usual
Notes:  This call provides a mechanism for TSRs to install permanent
          extensions to the command repertoire of COMMAND.COM.  It appears
          that COMMAND.COM makes this call before executing the current
          command line, and does not execute it itself if the return is FFh.
        APPEND hooks this call, to allow subsequent APPEND commands to
          execute without re-running APPEND
SeeAlso: AX=AE01h

Format of COMMAND.COM command line buffer:
Offset  Size    Description     (Table 02977)
 00h    BYTE    max length of command line, as in INT 21/AH=0Ah
 01h    BYTE    count of bytes to follow, excluding terminating 0Dh
      N BYTEs   command line text, terminated by 0Dh

Format of command name buffer:
Offset  Size    Description     (Table 02978)
 00h    BYTE    length of command name
 01h  N BYTEs   uppercased command name (blank-padded to 11 chars by 4DOS v4)
--------l-2FAE01-----------------------------
INT 2F U - DOS 3.3+ internal - INSTALLABLE COMMAND - EXECUTE
        AX = AE01h
        DX = magic value FFFFh
        CH = 00h
        CL = length of command name (4DOS v4.0)
        DS:BX -> command line buffer (see #02977)
        DS:SI -> command name buffer (see #02978)
Return: DS:SI buffer updated
          if length byte is nonzero, the following bytes contain the uppercase
          internal command to execute and the command line buffer contains the
          command's parameters (the first DS:[SI] bytes are ignored)
Notes:  this call requests execution of the command which a previous call to
          AX=AE00h indicated was resident
        APPEND hooks this call

===

FreeCOM implements the functionality as FEATURE_INSTALLABLE_COMMANDS
and performs the actions as described as follows.

II. Order of Execution

This pseudocode of how FreeCOM interpretes a parsed command line
shall demonstrate the internals and differences from other implementations.

1. Expand environment variables

2. Extract any redirections and decompose pipes
	in result the command line buffer DS:BX does not contain any
	">", "<" or ">>" metacommands nor does a pipe appears
	in the buffer -- this may be a violation of compatibly as the
	example in Undocumented DOS by Schulmann contains code handle
	redirections, thus, it opens the possibility that an Installed
	Command would be allowed to kill pending commands of a pipe.

3. Extract the first command name (first non-blank word fully constructed
out of characters permisable in filenames, but excluding colon, dot,
and backslash).

4. If found a word, pass through MUX-AE-00 and, on success, through
MUX-AE-01.
	If MUX-AE-00 succeeds and MUX-AE-01 returns BYTE DS:[SI] == 0,
	the interpretation of the command stops here.

	-> The number of characters ignored from the beginning of
	   STRING DS:[BX+2] is locally cached throughout the whole MUX
	   calling and is the same as the value originally passed
	   to MUX-AE-00 within BYTE DS:[SI].
	   If BYTE DS:[SI] != 0, it must form a valid Pascal string and
	   contain the command to execute

5. Search the internal commands list for the word left in STRING DS:[SI+1].
	The length of the command is re-generated by counting the number
	of characters permisable within filenames.
	On success, the internal command is executed with the argument
	left within the STRING DS:[BX+2] buffer, but skipping as many
	characters from the beginning as the length of the original
	command name was. Then the interpretation of commands stops.

	-> RBIL does not mention any minimum length requirements for the
	   STRING DS:[SI] buffer. FreeCOM passes a full
  	   BUFFER_SIZE_MUX_AE (currently 255 bytes) buffer to MUX-AE.

6. The remaining portion from STRING DS:[BX+2] is appended to DS:[SI+1]
and executed as external command.

III. Incompatiblies

- FreeCOM does not double buffer neither the command line nor the command.
	Thus if the Installed Command alters any of them, FreeCOM will use
	the modified ones furtherly.
	If this is an incompatibly or not, depends on the point of view strongly.

- If MUX-AE-00 succeeds, but the Installed Command does not return an
	internal command, an external command is executed, e.g.:

		C> INSTALL\COMMAND arguments

	When INSTALL is the name of an Installed Command, MUX-AE-00 will
	succeed. At this point DS:[SI+1] contains the string "INSTALL".
	MUX-AE-01 now alters the buffer DS:[SI+1] into "GO".
	As this is no internal command, FreeCOM tries to execute:

		C> GO\COMMAND arguments

	-> thus, the external command COMMAND.COM/EXE/BAT within the
	subdirectory GO.

- If an Installed Command may replace the command by another Installed
	Command depends on the order in which they had been installed.
	FreeCOM calls the MUX-AE chain exactly once per command.

- FreeCOM always uses BYTE DS:[BX+1] to determine the length of
	STRING DS:[BX+2]. If an Installed Command wants to change the
	arguments, this byte must be updated.

- FreeCOM supports the 4dos v4 extensions mentioned by RBIL.

- As FreeCOM has no meaning of "transient" portion, the segment
	registers simply point to the strings. DS == ES always.

IV. Side definitions

- The buffer DS:BX will always be larger than 12 bytes:
	  11 bytes (as 4dos v4 blank padded)
	+  1 byte (length byte)
	+  1 byte ('\0' byte at 13th position)

- The string at DS:[BX+2] is terminated by '\xd' and '\0' on entry to
	MUX-AE-00.
	There will always be a '\0' character at DS:[BX+2+[DS:BX]],
	thus the byte following the last byte, which is part of the string.

- If at any time BYTE DS:[BX+1] becomes greater than or equal to BYTE DS:[BX],
	FreeCOM aborts due to possible memory hazard.

- In step 6 (execute as external command) the first word of the command
	had been uppercased before it is globbed.

V. Installable Command samples

The TOOLS subdirectory contains several samples of Installable Commands.
They shall verify a working MUX-AE interface and are not meant as
something useful, hence, they are simple and display a lot of debugging
information.

LOAD_ICD.C implements the loader.
ICMD_*.NAS implement various samples. They are NASM sources and must be
compiled using this command:
C> NASM -f bin ICMD_#.NAS
In result a ICMD_# (without any extension) is created.

The format of such sample is:
1. The MUX-entry point is the very first byte of the file.
2. A validation area is located at the end of the file:
	begin of file --> entry point
	code
	BYTE Pascal string of the name of Installable Command
	WORD offset within file to DWORD of where to write the original
		value of INT-2F to in order to be able to chain the interrupt
	WORD offset within file to write the name to (see above)
	BYTE value 0 (zero)
	.... comment <<is displayed while loading>>
	.... Installable Command Image ID (see LOAD_ICD.C)	

During the load and installation of the Installable Command by LOAD_ICD
the filename without path nor extension is placed as Pascal string
at the position mentioned within the validation record. The last byte
of the name is the last byte of the residently installed image of the
Installed Command, too.

The name is displayed within debug messages and is the name of the
newly installed internal command. Because LOAD_ICD updates the name
during the load of the Installable Command, the same Installable
Command can be installed with different names by copying the file
to a different file.

VI. Examples

1) The simplest form is an Installable Command that performs any action
	itself.
-> MUX-AE-00 returns AL == 0xFF
-> MUX-AE-01 performs the action and returns DS:[SI] == 0

2) Map an Installable Command into another internal command.
-> MUX-AE-00 returns AL == 0xFF
-> MUX-AE-01 modifies Pascal string of command name at DS:[SI]

3) Map an Installable Command into an external command
-> MUX-AE-00 returns AL == 0xFF
-> MUX-AE-01 modifies Pascal string of command name at DS:[SI]
Note: DS:[BX+2] must be checked that it contains no path delimiter
character, that are colon ':', backslash '\\', nor dot '.'. Otherwise
the remaining command line tail will be appended to the command name
and will complete the name passed back within DS:[SI]. Internal as well
as Installable Commands are separated by such characters!
E.g.: Installable Command "GO" and maps to "WALK"
C> GO\THERE
--> GO rewrites the command "GO" into "WALK" and then appends the
remaining command line tail and, in result, performs:
C> WALK\THERE

To overcome this problem GO must rewrite the command line tail, too,
by inserting a blank at position DS:[BX+DS:[SI]]. (DS:[SI] is the
length of the original command name, 2 in this example.)
-->
C> WALK \THERE

4) Disable an internal command.
-> MUX-AE-00 returns AL == 0xFF
-> MUX-AE-01 returns DS:[SI] == 0
The Installable Command must be named equal to the internal command,
e.g.: Installable Command "DEL" will disable the internal command
DEL and any external one, too.

