% $Id: ENVIRON.TEX 1.2 2001/02/27 04:41:00 ska Exp ska $
\section{\label{ssenviron}\subsys{environ}}

\subsection{Design}

In DOS each process natively consists of two blocks of memory: one
contains the code and the data loaded from the file into memory and
the other one holds the environment variables each programs passes
along to its child processes on execution.

Environment variables are represanted as a sequence of NUL-terminated
strings; an empty string indicates the end of the sequence.

Non-empty strings must contain at least one equal sign \tok{=};
all characters to the left of it form the name of the variable and
the other ones form the value of the variable.
Traditionally names of variables are all uppercased in DOS and neither
name nor value must be empty.

Immediately following the variables area a string area is located.
Strings are NUL-terminated as variables are, but they need not
contain an equal sign and they may be totally empty. Therefore,
the first two bytes (one word) of the string area contain the
string counter how many strings the are contains.

Traditionally the space both areas may occupy must not exceed 32KB.

\paragraphe{The usual C implementation} of how to handle the
environment follows standard ISO 4217:1987 (POSIX.1). That means it is
maintained the global variables \tok{char *environ[]}. In Unix
this definition may be suitable, in DOS there are two problems with
it:
\begin{enumerate}
\item In near data model, e.g. Small, the whole environment
	variables must be copied into the local address space, mostly
	duplicated into the heap.
\item For DOS several tools exist that patch the environment of the
	parent shell, keeping up with asynchroneous changes of the environment
	may be problematic.
\end{enumerate}
Furthermore, it is usual in DOS that changes of the environment, e.g.
via function \fct{putenv}, does not directly effect the environment.

This subsystem was designed to stick with the memory block provided by
the system and transfer the variables between the block and the program
on request. Of course, in the view of efficiency this will consume quite
more time, but it is assumed that accesses to the environment are
relatively seldom and these functions were written to minimize the
problems pop up with asynchroneous changes.

Therefore \subsys{environ} directly manipulates the environment passed
on by the system to the process and also passed to child processes, on
occasion. As a side-effect the subsystem can handle any memory block
and can manipulate it as if would be a \quote{normal} environment block.
All functions, except those offered for explicit compatibly with the
standard environment functions, accept the segment address of the
environment block and perform over it; if 0 (zero) is passed as environment
block, the default environment of the process is used.

\subsection{Implementation}

\paragraphe{The naming convention} implies that all symbols of this
subsystem are prefixed by either \tok{env\_} or \tok{ENV\_}. Symbols
directly dealing with the string area of an environment are prefixed
by \tok{env\_str}.

The memory block the environment is constructed in by the system
always starts at a segment boundary. Because the traditional limit
of environments is 32KB, it seems that to support 64KB (the native
easily accessable boundary on real-mode Intel CPUs) is sufficient.

When the subsystem addresses a variable, only the offset of it wihtin
the segment of the environment is used. It is assumed that the user
still knows what segment the offset was generated for. Because the offset
0 (zero) is perfectly valid, invalid or uninitialized offsets are
represanted by 0xFFFF (-1).

Also, the core functions {\em do} treat the variable names case-sensitively!
Though, some functions are provided to match a name with the correct
case-spelling present in the environment.

Most of the functions accept the generic \tok{0} as segment, which is
interpreted as {\em my standard segment}. This standard segment is
determined by either the {\em default} or the {\em global} segment.

\paragraphe{The {\em default} segment} is an user-specified segment,
which is set by the function \tok{env\_setDfltSeg()} and retrieved by
the macro \tok{env\_dfltSeg}. The structure of the default segment
does not differ from normal segments at all, it just provides a method
to let \SUPPL switch to a different segment by default, hence the name.

\paragraphe{The {\em global} segment} is the environment managed by
the system for the process. Its location is storred in the status block
of the process, the so-called PSP. This segment can be changed by
function \tok{env\_setGlbSeg} and read by function \tok{env\_glbSeg}.
Because the default segment is not set, the global segment is used
by most functions of \SUPPL by default.

\subsubsection{Functions Effecting Whole Environments}

\begin{tabTS}
\fct{env_resizeCtrl} & Variable that controls various aspects of
	these functions:
	\begin{description}
	\item[ENV_SHRINKBELOW:] Allows to resize an environment
		below its last used byte (will destroy the contents of the environment,
		is necessary to delete environment with \fct{env_setsize})
	\item[ENV_ALLOWMOVE:] Re-allocates the environment segment if grow fails
	\item[ENV_USEUMB:] when the environment is (re-) allocated,
		the UMB areas are searched first
	\item[ENV_FIRSTFIT:] When an enviornment is (re-) allocated,
		the first fitting memory block is used (lowest address)
	\item[ENV_LASTFIT:] When an enviornment is (re-) allocated,
		the last fitting memory block is used (highest address)
	\end{description}
	If neither \tok{ENV_FIRSTFIT} nor \tok{ENV_LASTFIT} are specified,
	the best fitting block is used. \\
\fct{env_setGlbSeg} & 	Sets the default environment segment. \\
\fct{env_glbSeg} &	Returns the default environment segment. \\
\fct{env_master} &	Returns the environment segment of the master shell. \\
\fct{env_shell}	&	Returns the environment segment of the most currently
	launched shell. \\
\fct{env_check} &	Checks an environment for integrity errors. \\
\fct{env_delete} &	Deletes (frees / deallocates) an environment. \\
\fct{env_create} &	Creates and initializes a new and empty environment. \\
\fct{env_replace} &	Replaces or duplicates an environment. \\
\fct{env_resize} &	Shrinks or grows an environment by an
	\tok{(signed int)} delta value. \\
\fct{env_newsize} &	Sets the size of an environment to an absolute value. \\
\end{tabTS}


\subsubsection{Core Functions}

\begin{tabTS}
\fct{env_endOfVars} &	Returns the offset the last byte used by
	the variable area of the environment. \\
\fct{env_firstFree} &	Returns the offset of the first unused byte of
	the environment segment. \\
\fct{env_freeCount} &	Returns the number of unused bytes of the
	environment segment. \\
\fct{env_varlen} &	Returns the number of bytes used by the
	specified variable. \\
\fct{env_noSpace} &	Checks if the environment segment has enough unused
	space left to hold another variable. \\
\fct{env_findVar} &	Locates a variable in an environment segment
	(case-sensitive). \\
\fct{env_insVarOffset} &	Inserts a new environment variable before
	another one at the specified offset. \\
\fct{env_ovrVarOffset} &	Overwrites one environment variable
	at the specified offset with a new one. \\
\fct{env_appVar} &	Appends a new variable to an environment segment. \\
\fct{env_subVarOffset} &	Removes the variable starting at the specified
	offset. \\
\end{tabTS}

\subsubsection{Environment Variables Functions}

\begin{tabTS}
\fct{chgenv} &		Changes a variable within the default environment. \\
\fct{env_change} &	Changes a variables within an environment. \\
\fct{cpyenv} &		Copies the value of a variable of the default
	environment into the specified buffer. \\
\fct{env_get} &		Copies the value of a variable of an
	environment into the specified buffer. \\
\fct{dupvar} &		Duplicates the value of a variable of the default
	environment into the heap. \\
\fct{env_dupvar} &	Duplicates the value of a variable of an
	environment into the heap. \\
\fct{env_forAll} &	Spawns a function for all variables of an environment. \\
\fct{env_findAnyVar} &	Finds the first case-sensitive variable and the first
	case-insensitively matching variable name. \\
\fct{env_fetch} &	Duplicates the value a variable of an environment
	into the heap. The previously fetched value is automatically deallocated.
	The name of the variable is matched in DOS-ish style. \\
\fct{env_matchVar} &	Finds the best matching variable by adjusting
	the case-spelling of the specified variable to the variable found
	in the environment. \\
\fct{putenv} &		Inserts or updates an environment string. \\
\end{tabTS}



\subsubsection{Environment String Functions}

\begin{tabTS}
\fct{env_nullStrings} & 	Clears the string counter to zero. \\
\fct{env_strcounter} & 	Modifies the string counter with a \tok{(signed
	int)} delta value. \\
\fct{env_strings} & 	Returns the number of strings of an environment. \\
\fct{env_string} & 	Returns the offset of a string of an environment. \\
\fct{env_strcpy} & 	Copies a string of the environment to a buffer. \\
\fct{env_strdup} & 	Duplicates a string of the environment into the heap. \\
\fct{env_strinsert} & 	Insert a new string before another one. \\
\fct{env_strput} & 	Replaces or deletes or appends a string. \\
\hline
\end{tabTS}


