CLAY'S UTILITIES FOR DOS BATCH PROCESSES - LAST UPDATED 30 OCTOBER 1997
=======================================================================

Upon extracting the contents of this package you agree to the following:

******************************************************************************
The utilities included herewith are Copyright (C)1996-97 by Clay Ruth, who
reserves all rights of ownership.  You are granted a license to use this
software, free of charge, only for the purposes described below.  You are
also permitted to distribute this package, IN ITS ENTIRETY, INCLUDING THIS
NOTICE, WITHOUT CHARGE TO THE RECIPIENT other than reimbursement for any
media on which it is distributed and associated shipping costs.

YOU MAY NOT distribute this package or any component thereof for profit,
nor may you disassemble, reverse-engineer, or extract code from this software.

All software in this package has been thoroughly tested and is believed to
perform as described.  It is certified to have been free of viruses, trojans
and other malicious code when originally distributed by the author.  You, the
user, are solely responsible for its usage, including, but not limited to,
scanning for viruses and trojans it may have acquired in the distribution
channels, determining its suitability for the intended use, backing up all
critical files before modifying them with it, and accepting any and all
consequences of its use.  NEITHER THE AUTHOR NOR THE DISTRIBUTOR IS RESPON-
SIBLE FOR ANY DAMAGES, DIRECT OR INDIRECT, CONSEQUENTIAL OR OTHERWISE,
RESULTING FROM YOUR DECISION TO USE THIS SOFTWARE.  YOU ACCEPT AND ASSUME
ALL RISKS OF USE.

All trademarks referenced herein are the properties of their respective
owners. Their mention herein shall not be construed to infer any association
with, endorsement by, or critique by this package or its author.
******************************************************************************

To contact the author: cruth@netnitco.net

Links to the current release of this package, and any available interim
releases of its components, can be found at:

    http://ww2.netnitco.net/users/cruth/

Many of these utilities are useful at the command line, while others make
sense only in the batch programming environment. Before shrugging off a
utility as redundant, consider how it differs from the similar DOS command
in ways that matter to your batch program. For example, MAKEDIR, REMOVEDIR
and DELFILE seem unnecessary in light of DOS' MKDIR, RMDIR and ERASE
commands; however, the utilities provided here are friendlier to the batch
programmer because they return errorlevel codes and because all their
messages can be redirected to NUL or to a log file. This becomes significant
when your batch programs are executed on a network, where spurious error
messages would result in unwanted calls for support.


The latest updates include the following:

10/30/97 - Change of E-mail and Web page addresses

07/14/97 - Documentation updated for release 1.2.
           FIXTIME.COM added (was previously documented but had been
           inadvertently omitted from distribution).

07/12/97 -      TSR 1.1 - Made compatible with systems that lack upper
                          memory blocks; version 1.0 would hang if loaded
                          without UMBs available.

05/20/97 - SPLITFIL 3.0 - Added capability to split a file at a specified
                          size, which may be defined in decimal or hexa-
                          decimal, bytes or kbytes.  Existing seekstring-
                          based functionality is unchanged.

05/07/97 -  RUNBAT$ 2.0 - Modified to execute COMMAND.COM as a child process
                          instead of overlaying the utility. This prevents
                          illegal instruction errors when used with Win95.
                          The trade-off is 11K of conventional memory. The
                          original RUNBAT$.EXE is still provided for use in
                          DOS 6.22 and earlier environments only; the new
                          RUNBAT$.COM can be used in DOS or in Windows 95.
                          Because .COM files have execution priority over
                          .EXE files, a call to RUNBAT$ without an extension
                          will execute the new .COM (non-overlaid) version,
                          whereas a call to RUNBAT$.EXE will run the old EXE.
                          RUNBAT$.COM has a limit of approximately 4K of
                          tolerable predefined environment variables, beyond
                          which it will terminate without warning; the .EXE
                          has no such limit.

04/15/97 -  XCHANGE 3.0 - Added capability to change the paths to zipped
                          files (requires PKZIPFIX follow-up to clean up
                          the ZIP file's internal directory pointers).
                          To do this successfully, the first zipped file
                          must have the path you seek to change. See details
                          below.

03/10/97 - FILEDATA 1.1 - Added capability to reference a file containing a
                          list of items of interest, either as a screening
                          list for a wildcard filespec or as a list of
                          filespecs.

02/08/97 - FILEDATA 1.0 - Variant of FILEINFO 1.3, this utility exports its
                          data in a Comma Separated Values (CSV) format,
                          suitable for import into a database or spreadsheet
                          where it can be sorted and redundant or obsolete
                          files can be readily identified. An empty database
                          in Microsoft(TM) Access(TM) format is provided for
                          convenience, including a "Comparison" query that
                          puts the essential information together.

12/02/96 -    OCOPY 2.3 - Modified to allow copying to a network directory
                          in which the user has only Write privileges (and,
                          if the file doesn't already exist, Create). Earlier
                          versions required that the user be able to read the
                          target file. Now you can grant WC rights, denying
                          R and F, so your processes can copy user files to
                          a network repository in which they cannot scan the
                          directory nor read the files contained therein.

09/26/96 - Documentation updated for release 1.1

09/26/96 -   TPAUSE 2.0 - Modified to provide a user-specified timeout that
                          can range from 1 second to 23 hours, 59 minutes
                          and 59 seconds. The original code used a fixed
                          1-minute timeout, which remains the default when
                          a timeout setting isn't specified. TPAUSE 2.0
                          replaces the former TPAUSE, TP5, TP10, TP15 and
                          TP10S commands, which provided various fixed
                          timeouts.

09/21/96 -      TSR 1.0 - New, resizeable dummy TSR to consume conventional
                          or upper memory for the purpose of testing another
                          DOS program's performance under conditions of
                          limited memory availability. Replaces fixed-size
                          dummy TSRs TSR1K, TSR5K, TSR10K and TSR50K, which
                          are no longer included.

09/13/96 -    ISRUN 1.0 - New utility to determine whether a particular DOS
                          program or device driver is running (i.e., loaded
                          in DOS memory) and to report the addresses of its
                          code (PSP) and environment data segments.

08/20/96 -  INIREAD 3.1 - Fixed bug that prematurely truncated settings that
                          ended with a space followed by a single character.
                          Fixed minor bug that caused incorrect display of a
                          file content fragment instead of the file name when
                          reporting that a specified section or setting was
                          not found.

06/04/96 - FILEINFO 1.3 - It can now find files in the root directory as
                          well as in subdirectories.

06/03/96 - FILEINFO 1.2 - Added compatibility with 32-bit modules as well as
                          the 16-bit variety, plus better tolerance of format
                          variations. Fixed bug that occasionally caused an
                          item to be declared "n/a" (not available) when it
                          crossed a search region boundary. Information now
                          includes indication of whether the module is 16-bit
                          or 32-bit.

04/20/96 - Documentation updated for freeware distribution, release 1.0

04/14/96 -   INIMOD 2.2 - Improved matchup logic recognizes the equivalency
                          of commented and non-commented forms of the same
                          setting as well as case variations, so it won't
                          inadvertently add a redundant setting when the "/a"
                          switch is used; also, automatically deletes any
                          redundant settings it finds when the equivalent
                          setting is edited.

04/12/96 - FILEINFO 1.1 - New utility to find and report internal identifi-
                          cation of Windows program modules; version 1.1
                          incorporates speed enhancements.

04/09/96 -  INIREAD 3.0 ) These utilities, all of which edit one or more
04/08/96 - ENVMASTR 3.0 ) programs' environment spaces, incorporate improved
04/08/96 -    TZSET 3.0 ) environment location and editing functions that
                          can find their target environments in upper memory
                          blocks as well as in conventional memory. This
                          makes them compatible with Windows 95, which can
                          load COMMAND.COM and its environment into UMBs.

03/22/96 -    OCOPY 2.2 - Bug fix - When attempting to copy a zero-length
                          file, previous versions attempted to deallocate a
                          random memory buffer that had never been allocated,
                          due to an uninitialized pointer.

03/22/96 -   INIMOD 2.1 ) These utilities, all of which edit files, formerly
03/22/96 -  XCHANGE 2.1 ) used system calls to copy their temporary files
03/22/96 -     YANK 2.1 ) back onto the originals. They now incorporate the
03/22/96 -  LINEMOD 2.1 ) OCOPY code to rewrite the original files, thus
                          improving their speed, reducing their minimum
                          memory requirements and eliminating potential
                          problems that arise when doing system calls in a
                          Windows DOS box.

02/27/96 - INVORALL 2.1 - Added /T switch to add report of total bytes of
                          all listed files following the list itself.

02/09/96 -  FILEAGE 2.1 - Changed from "compatibility mode" to "sharing mode
                          with deny-none" file access to improve likelihood
                          of successfully reading the file's date/time stamp.

02/08/96 -  DELFILE 1.0 - New utility to delete a file with all output sent
                          to STDOUT; doesn't output to STDERR when a file
                          cannot be deleted. Returns errorlevel indicating
                          if the deletion was unsuccessful.

12/13/95 -    OCOPY 2.1 - Changed from "compatibility mode" to "sharing mode"
                          file access for better coordination with networks
                          and with Windows 95 file sharing. This utility has
                          an excellent chance of copying files when COPY and
                          XCOPY cannot.


Batch Programming Tips:

It is generally assumed that anyone who downloads this package is familiar
with DOS batch programming practices; however, since Microsoft's own
documentation on this subject has become scarce, I'll point out a few things
that might not be immediately obvious.

The first 9 command line parameters passed to your batch script can be
referenced as %1 through %9. The command that ran your batch script can be
referenced as %0, so you can call batch subroutines, self-extractors, etc.,
without knowing where they reside, by putting them in the same directory
with the main batch and appending simple suffixes to their names. For
example, if your main batch is DOIT.BAT, you could name a batch subroutine
DOIT_A.BAT and name a self-extractor DOIT_B.EXE. Your batch can call the
batch subroutine with all required path qualification with CALL %0_A and
it can run the self-extractor with %0_B. The underscore is for readability
only; you could omit it and use %0A and %0B.

Command line parameters beyond the 9th can be accessed by SHIFTing out the
ones you no longer need. Each SHIFT command moves all parameters to the
next lower number.

Environment variables, defined by SET commands or by programs such as
INIREAD, can be referenced by enclosing them between percent signs.
For example, you might use INIREAD to read a setting out of an .INI file.
You can then use SCANSTR to scan the retrieved setting for some particular
content of interest as follows:

   @echo off
   :: Batch program to interpret Windows display driver setting
   iniread c:\windows\system.ini "boot" "display.drv" dispdrv >nul
   if errorlevel 2 goto badini
   scanstr /i "%dispdrv%" "VGA.DRV" >nul
   if errorlevel 1 if not errorlevel 2 goto hasvga
   echo This system is using custom display driver %dispdrv%.
   goto end
   :badini
   echo SYSTEM.INI ERROR - Cannot find [boot] setting "display.drv"
   goto end
   :hasvga
   echo This system is configured with the generic VGA driver.
   :end
   set dispdrv=

INIREAD retrieves the display.drv setting from SYSTEM.INI's [boot]
section and stores it in environment variable DISPDRV. An errorlevel
of 2 or higher indicates that no such setting was found. SCANSTR checks
the content of the DISPDRV environment variable for "VGA.DRV". If such
content is found in the first character position, it's the generic VGA
driver; if it's at some higher character position, or is not present,
some other driver is in use, so its name is displayed.

Errorlevel tests return a true status if the error code returned by the
program is greater than, or equal to, the tested value. Errorlevels can
range from 0 through 255. The expression "if errorlevel 0" is useless
because it would always be true; test for zero with "if not errorlevel 1".

Note the use of the double colon to prefix a comment. This is preferable
over the use of "REM" because REM statements are parsed for environment
variables, which takes time. The double colon makes the remark look like
a label, which is quickly skipped over. By using a double colon instead
of a single colon, we ensure that no conflict will arise with a real
label.


Below is a summary, in no particular order, of each utility and its usage:



TSR.COM
-------
This is a dummy TSR that does nothing but consume DOS memory (conventional
or upper). Use it to test the minimum memory requirement for running any
program of interest.

Syntax: [LH] TSR [ [+ | -][X]size[K] [A] ] | [U] | [S]

Default interpretation of size is "decimal bytes".
"X" prefix specifies hexadecimal.  "K" suffix specifies kbytes (1K = 1024).

Use "+" or "-" prefix to change the last loaded existing dummy TSR's size by
a differential amount. If +/- is omitted, the last loaded dummy TSR, if any,
will attempt to change to the newly specified absolute size.

Option A adds another dummy TSR; U unloads the most recently added TSR.
Option S displays the status of all installed dummy TSRs.

The minimum dummy TSR size is 192 (xC0) bytes; the maximum is 65520 (xFFF0),
which is one paragraph (16 bytes) less than 64K. To quickly consume several
hundred K of memory, enter "TSR 63K A" repeatedly, then use MEM to see the
resulting largest executable program size. You can adjust the result in
large increments by adding or removing TSRs. For small increments, use
(for example) "TSR -64" and "LH TSR +32" to change the last loaded dummy
TSR's resident size (64-byte decrease and 32-byte increase, respectively).

Note that memory allocations change in increments of 16 bytes minimum. Any
TSR size specification that is not an integer multiple of 16 will be rounded
upward. This is an artifact of the 80x86 processor's design.

A TSR's size can increase only when the new instance you are running is in
another memory area. For example, to make the last TSR you loaded into
conventional memory grow 80 bytes larger, use "LH TSR +80". This technique
works if you have 3632 bytes or more free in upper memory blocks. When
upper memory isn't available, use "TSR U" followed by "TSR newsize A" to
unload the existing TSR and re-load it with the desired new size.

If you will be doing your DOS application testing under Windows, here's a
tip to make adjustments easier: Pre-load a 5K dummy TSR into upper memory
before starting Windows. You can add "LH TSR 5K A" to your AUTOEXEC.BAT
file to ensure that it will be there when you need it. Why do this? Because
when Windows starts, it will take whatever upper memory is left, leaving you
no room to use "LH TSR +nn" for later conventional memory size adjustments.
By preloading a 5K TSR, you're reserving the necessary space in upper memory.
After Windows starts and you open a DOS session, use "TSR 192" to shrink the
upper memory TSR to its minimum size. Now you can proceed to load additional
dummy TSRs in conventional memory, knowing that you have enough free upper
memory to make minor adjustments using the "LH" technique.



ISRUN.COM
---------
This utility reports whether a specified program is loaded in DOS memory
and, when found, displays the addresses of its code (PSP) and environment
data segments.

Syntax: ISRUN progname   (maximum progname length = 8 characters)

ISRUN searches for the specified program in the Memory Control Block (MCB)
chain and returns a logical errorlevel code.  This is most useful for
determining whether your batch script is running under another process,
such as a network LOGIN program, the RUNBAT$ utility, etc.  It can also
report whether a particular TSR or device driver is loaded, and where.
When progname is wild (*), all modules running under DOS are listed.
The displayed segment address is that of the PSP, which is 1 greater than
the MCB segment address displayed by MEM /D.  Likewise, the displayed
environment data address is that of the data, not the environment's
MCB address.

The address shown for ISRUN itself is that at which the next program will
load, unless additional environment variable definitions require the allo-
cation of a larger environment block.  When "ISRUN *" shows that ISRUN's
environment block was previously used and released by some other resident
program, an increased environment will require a new memory block allo-
cation, shifting the program load point by a number of segments equal to
(new environment size in bytes / 16) + 1, rounded upward.  When ISRUN is
already using a new environment block (i.e., one that is not listed for
any other program), an increased environment will simply increase the size
of that block, moving the program load address in increments of 1 segment
for every 16 bytes of new environment.

Errorlevel 0 = specified program not found
Errorlevel 1 = specified program is in memory
Errorlevel 2 = syntax error
Errorlevel 3 = system error, cannot locate CVT

The CVT is the Configuration Variable Table, maintained within DOS, from
which a pointer to the first MCB is obtained. The CVT exists in DOS
versions 2 and higher, so an errorlevel 3 would indicate that the
operating system has become corrupted or is incompatible with MS-DOS
in the manner of locating the CVT.



FILEINFO.EXE
------------
This DOS-based utility locates and displays official Windows File Information
from any program module adhering to the "StringFileInfo" standard. The "File
Version" returned in the FILEINFO report is the best authority as to which
copy of a DLL file is actually the most up-to-date, regardless of what the
date/time stamps say. Software vendors often redate the files included in
their packages to reflect the date of package issue, causing obsolete DLLs
to appear newer than they really are. FILEINFO can help set things straight.

Syntax: FILEINFO filespec [/s]

Searches for standard Windows file information (StringFileInfo) and reports
the file name, date and time stamp, and size, followed by either a summary
of the found information or a statement that no other info is available.
Switch /s enables subdirectory searching.

Returns errorlevel 0 if info found, 1 if info not found, 2 if error.
When wildcards are used, highest level for the file group is returned.



FILEDATA.EXE
------------
This variant of FILEINFO produces its output in Comma Separated Values (CSV)
format, suitable for importing into a database or spreadsheet. To facilitate
the sorting and comparison of DLLs throughout your computer system, an empty
database structure in Microsoft(TM) Access(TM) format is provided, complete
with a "Comparison" query that sorts the essential information for you.
The first record contains field names.

Syntax: FILEDATA filespec [/s] >filename.txt   (or >filename.csv)

Switch /s enables subdirectory searching.

Returns errorlevel 0 if info found, 1 if info not found, 2 if error.
When wildcards are used, highest level for the file group is returned.

Here is an example of how data would be collected and imported into two
popular applications: Microsoft(TM) Access(TM) and Microsoft(TM) Excel(TM):

First, collect the data. If you're planning to import it into Access,
redirect its output to a file with extension .TXT; if importing into Excel,
use the .CSV extension. If you have multiple drives from which to collect
data, redirect each drive's data to a separate file. For example:

   filedata c:\*.dll /s >dlldatac.txt    (or >dlldatac.csv)
   filedata d:\*.dll /s >dlldatad.txt    (or >dlldatad.csv)
   filedata e:\*.dll /s >dlldatae.txt    (or >dlldatae.csv)

Next, open the application into which the data are to be imported.

If you are importing into Access:
    1. Open the provided FILEDATA.MDB database.
    2. Click File, Imp/Exp Setup. Select File Type: Windows(ANSI)
       Text Delimiter: "    Field Separator: ,          Date Order: MDY
       Date Delimiter: /    x Leading Zeros in Dates    x Four Digit Years
       Time Delimiter: :    Decimal Separator: .
    3. Click the "Save As" button and name it: CSV
    4. Click File, Import, Text (Delimited).
    5. Select a desired file (e.g., dlldatac.txt)
    6. x First Row Contains Field Names
    7. Click the "Options" button and select Specification Name: CSV
    8. Append to Table: FILEDATA
    9. Repeat steps 5 through 8 for each additional file to be imported.
   10. Close the Select File dialog box.
Now select the Query tab and open the "Comparison" query. Notice how all of
your DLL files are listed in alphabetical order, so you can readily identify
duplicate and obsolete files. Wherever multiple files have the same name,
check the File Version (FVER) column to see which one is really the latest
version. That's the one that should be in your Windows SYSTEM subdirectory,
and all duplicate copies (especially prior versions) should be archived and
then deleted so as to free up disk space and avoid conflicts. The primary
exception to this is if you have multiple versions of Windows, in which case
those DLLs intended for use with different Windows versions should be the
appropriate versions for the Windows version; e.g., don't move a Windows 95
DLL to a Windows 3.1 SYSTEM subdirectory or vice-versa.

If you are importing into Excel:
    1. Click File, Open.
    2. Select files of type: Text files, and select the first desired file
       (e.g., dlldatac.csv)
    3. Select Delimited, origin: Windows(ANSI).
    4. Select Start with Row: 1 if you want the headings to appear, else 2
    5. Click the "Next" button.
    6. Select only the Comma as the field delimiter, text qualifier: "
    7. DON'T treat consecutive delimiters as one.
    8. For the column formats, select: Text, Text, Date (MDY), General,
       General, General, and Text for all the rest.
    9. For any additional files select Insert, File, with the cursor on
       the row immediately below the last existing data line, column A.
       Import as described in steps 1 through 8, but start with Row 2.
Sort all data rows on Column A to get all names in alphabetical order.
Identify the duplicate and obsolete DLLs in accordance with the Access
example above.

Some applications will look only in their own directory for their custom
DLLs. Most applications will search Windows and its System subdirectory,
then the DOS search path, if a DLL isn't found in the application's own
directory. Once a particular DLL is in memory, another application cannot
open a different instance of that DLL; it must use the image already in
memory. If the first application already loaded an obsolete version, a
second application that needs the newer version will crash. Therefore,
the Windows System directory should contain the latest version of each
shared DLL and the obsolete versions should be deleted so that they can't
be loaded inadvertently.

Be sure to keep archived copies of all deleted DLLs so that you can put
them back if something doesn't work. In the vast majority of cases, having
the latest DLL (by file version, not date stamp) in the Windows SYSTEM
subdirectory, and no DLLs of the same name in the application directories,
will resolve conflicts. However, don't mix up different Windows versions.
Also, DLLs that are found only in a single application's directory, and
nowhere else, should be left where they are.



XCHANGE.EXE
-----------
Extended global find-and-replace for any kind of file, of any size.
This is suitable for use at the command prompt or in a batch file.
It can even be used to patch code within an executable file, provided that
the search and replace sequences contain the same quantity of bytes.
All byte values, 0 through 255 (x00 through xFF), are supported.

Syntax: XCHANGE [/i] filespec "searchspec" ["replacespec"]
        XCHANGE [/i] filespec "searchspec" @imagefile
        XCHANGE [/i] filespec @scriptfile

Optional switch /i = Ignore case (can be in any parameter position).

Searchspec and replacespec are each made up of any combination of literals
and ^-prefixed ASCII codes. ASCII codes must be followed by commas if next
character is a digit (0-9 following a decimal; 0-9 or A-F following a hex).
Use double ^ or , for literal ^ or , in string, or ^94 & ^44 (^x5E & ^x2C).
If replacespec is omitted, search string is removed; nothing is inserted.

The @imagefile reference places an exact copy of the image file in place of
each occurrence of the search string (in lieu of replacespec).

The @scriptfile reference opens the script file, which contains the search
and replace specifications (or searchspec and @imagefile reference). This is
most useful when the command line would exceed the DOS limit of 127 charac-
ters if the search and replace specs were spelled out on the command line.

Known limitation: If the search string begins with multiple instances of one
character, and the file being searched contains the search string but has
more instances of the leading character than are included in the search
string, the search string might not be found. For example, if the file
contains "This   is   a   test" (three spaces between words) and the search
string is defined as "  test" (two leading spaces), the search string will
be missed. Work around this by searching for sequences that don't start with
multiple instances of the same character. In the example just given, " test"
(one leading space) will always be found. This limitation applies to all
binary-compatible utilities in this package.

New feature introduced in version 3.0: XCHANGE recognizes the ZIP file
format and can change the embedded path strings in such a manner that the
PKZIPFIX utility (provided by PKWare with PKZIP 2.04g) can clean up the
resulting ZIP file directory pointers. This applies only to ZIP files,
not executable self-extractors. To do this properly, the first zipped file
within the ZIP must have the path that you are seeking to change. Be sure
to keep a backup copy of any file whose paths you attempt to change until
you have fixed and tested the file, verifying that it extracts correctly.

XCHANGE returns errorlevel codes for use in a batch file. Type XCHANGE
with no parameters to get a syntax summary complete with list of
errorlevel codes.

Examples:

1) XCHANGE filename.ext "your place^13^10my place" "your^13^10place^13^10
                         my^13^10place"

This breaks up consecutive lines "your place" and "my place", putting each
word on its own line.


2) XCHANGE filename.ext "^13^10,0" "^13^10 "

This removes any zero at the start of a line, replacing it with a space.
The comma ends the ASCII code so that it won't be interpreted as 100.


3) XCHANGE filename.ext "Elementary,, my dear Watson!" "Gee,, I'm confused!"

Note the use of double commas to represent single commas. This could also
be expressed as follows:

   XCHANGE filename.ext "Elementary^44 my dear Watson!" "Gee^44 I'm confused!"

or as follows:

   XCHANGE filename.ext "Elementary^x2c my dear Watson!" "Gee^x2c I'm confused!"


4) XCHANGE filename.ext @script.fil

where script.fil contains:

   "Elementary,, my dear Watson!" @image.fil

and image.fil contains:

   Gee, I'm confused!

without any CR/LF at the end of the line.

Double comma (or equivalent ASCII code) is needed in the script, but not in
the image, because the image does not get parsed but is used as-is. Scripts
are generally used only for extremely long specifications, but an image could
also be something extracted from another file during a batch process.

ZIP File Example: You created a master directory in which to set up your
files. Let's assume this is C:\MASTER. Using that directory as the root
equivalent, you created the desired subdirectories under it and installed
the desired files. Using WinZip(TM) 32-bit to zip them with Win95's long
names, you discover that the MASTER directory is included on all the files
as well as the desired subdirectory paths. You want to get rid of the
"MASTER/" portion of the paths, leaving the remainder intact. Use the
command, XCHANGE MYZIP.ZIP "MASTER/" "" and then PKZIPFIX MYZIP.
You now have a ZIP file that extracts to the desired subdirectories
without the MASTER directory, and WinZip Self-Extractor can convert it to
a 32-bit self-extractor that does the same.



YANK.EXE
--------
This is similar to XCHANGE.EXE with one important exception. Whereas
XCHANGE removes/replaces only the sought text, YANK removes/replaces the
ENTIRE LINE that contains the sought text. It "yanks" out the whole line,
including the CR/LF at the end. Therefore, anything specified as a replace-
ment will be inserted at the start of the subsequent line. If the insertion
is to stand on a line of its own, include CR/LF (^13^10) at the end of it.
Also, because it is line-oriented, it can handle only ASCII files, not
binary files (valid ASCII codes for YANK are 1-255 (x01-xFF).



LINEMOD.EXE
-----------
Another variation on XCHANGE, LINEMOD changes only targeted lines, as
identified by a unique identifier string:

LINEMOD [/i] fs "idstrng" "[srchstrng][^chr,][...]" ["[replstrng][^chr,][...]"]
LINEMOD [/i] fs "idstrng" @scriptfile
LINEMOD [/i] fs "idstrng" "srchspec" @imagefile

For each line containing the ID string, the first occurrence of the search
string will be converted to the replacement string.  If all occurrences are
to be changed, loop back to repeat the command until errorlevel 1 occurs.
Being line-oriented, it is restricted to ASCII files, as is YANK, and it
uses the same ASCII character definitions as YANK.



SEEK.EXE
--------
This handy alternative to the DOS FIND command is extremely useful to batch
programmers who simply want to find out if something exists in a file.
SEEK works just like XCHANGE, but without the replacement string. It looks
for the search string and reports back whether or not it was found. To do
this with FIND, the batch programmer had to go through a sequence like this:

   set found=N
   find "searchstring" <sourcefile >temp1.fil
   copy temp1.fil temp2.fil
   if exist temp2.fil set found=Y
   del temp?.fil
   if %found%==Y do whatever...
   set found=

With SEEK, it's as easy as this:

   seek sourcefile "searchstring"
   if errorlevel 1 do whatever...

Another advantage of SEEK is that the search string can contain control
characters, graphics characters, CR/LF sequences, etc., that FIND cannot
look for. SEEK handles binary files as well as ASCII files; it can seek
search strings that include nulls. See the XCHANGE description for a
known search string limitation.



SCANSTR.COM
-----------
This program scans a string to determine whether it contains a second
specified string:

SCANSTR [/i] "string to be scanned" "[srchstrng][^[x]chr,][...]"

Switch /i = ignore case (can be in any parameter position); chr = ASCII.
The search string can be any combination of literals and ^-prefixed,
comma-delimited ASCII codes ^0 through ^255 or ^x00 through ^xFF.
Use double ^ or , for literal ^ or , character within the search string.
Quotes may be omitted if there are no spaces within the search string.
The string to be scanned is not subject to such parsing.

Primarily useful for screening the content of environment variables,
SCANSTR returns a message and errorlevel code indicating the relative
position of the search string within the target string.  If the search
string is not found within the target string, the return code is zero.
A return code of 1 indicates that the search string begins at the first
character of the target string; 2 indicates that it begins at the second
character, etc.



SPLITFIL.EXE
------------
Splits any file into two parts at the first occurrence of a search string,
other than at the very beginning of the file.

Syntax: SPLITFIL [/i] file1 file2 ["[srchstrng][^chr,][...]"] | [@scriptfile]

SPLITFIL searches file1 for the search string and truncates it just prior
to the first occurrence; the search string and all remaining bytes of file1
are written to file2, which is opened in "append" mode so that a new file 
can be readily assembled from pieces of other files. If appending is not
desired, be sure to delete any existing file2 before using SPLITFIL. The
files are unchanged if the search string is not found. Specific file names
(full qualification optional) must be provided; wild cards are not allowed.

Long search string descriptions can be placed in a script (8,192 char. max.).
Switch /i = ignore case; this can be in any parameter position.
Search string can be any combination of literals and ^-prefixed, comma-
delimited ASCII codes (^0 through ^255 or ^x00 through ^xFF).
Use double ^ or , for literal ^ or , character within a string.
Quotes may be omitted if there are no spaces within strings.
See the XCHANGE description for a known search string limitation.

Echos "Split" or "Not Split" to visually indicate outcome.
Returns errorlevel: 0 = split, 1 = not split, 2 = unable to write,
3 = syntax or memory error,  4 = file not found, 5 = error during read/write,
6 = insufficient disk space, 7 = read-only file, 8 = write-protected.



OCOPY.EXE
---------
Overwrites a specified target file with a copy of a specified source file.

OCOPY file1 file2

OCOPY is a true overwriting file copier.  Unlike COPY, which effectively
deletes any existing file of the target name and re-creates the file in a
new storage area, OCOPY ensures that the new file overwrites the existing
file, using the same storage allocation.  OCOPY copies any file, regardless
of S, H, or R attributes, but does not pass along those attributes.  If file2
exists, any "R" attribute must first be removed; it will be overwritten and
its size and date/time stamp will be adjusted to match file1.  If file2 does
not exist, it will be created.

File names must be explicit; i.e., file2 must be a complete file name, not
just a path, and neither file name can contain wildcards.  Beginning with
Version 1.2, OCOPY incorporates Novell Netware functions to make network
errors invisible to the user (previous versions required user interaction if
a "file busy" condition prevented overcopying).  Version 2.x maximizes speed
by allocating multiple memory buffers up to a total of all available DOS RAM
or the source file size, whichever is less.  Versions 2.1 and higher are
share-aware for smoother operation under Windows 95 and other networks.

Visually confirms success or failure of the operation, and returns errorlevels:
1=Read error or not found; 2=Write error, non-destructive (may be bad path);
3=Syntax or memory error; 4=Unable to truncate target file to source's size;
5=Write error (destructive), target file deleted.



FILEAGE.EXE
-----------
Determines the age of the specified file, in the specified units.

Syntax: FILEAGE filename [/s | /n | /h | /d | /w | /m | /y]

Returns an errorlevel code equal to the quantity of time units elapsed
since the file's modification date/time stamp.  Optional parameter can
specify units of seconds, minutes, hours, days, weeks, months, or years.
Default units are days.  The file's age is shown on the screen and returned
as an error code.  Returns 252 or more if unable to process request.  The
largest valid quantity returned by errorlevel is 250, but larger values
may be displayed (returns nonfatal errorlevel 251).  Fatal error codes are:

252 = File is busy, permission denied  253 = Invalid futuristic date/time stamp
254 = File not found or inaccessible   255 = Syntax error



SRCHDIR.COM
-----------
Subdirectory search for specified file(s).

Syntax: SRCHDIR filespec [ x | X | /x | /X | / ]

SRCHDIR produces a list of all files matching the file specification in the
base directory (i.e., current working directory, or other directory shown
in the filespec) and all of its subdirectories. This list differs from that
obtained by the DOS 5 command "DIR filespec /s /b" in two ways: it includes
each file's date/time stamp while omitting the usual DIR header and trailer,
and it lists hidden files as well as normal files, including any that are
in hidden subdirectories.  By including any one of the alternate parameters
shown, the subdirectory search can be omitted.

Returns errorlevel 1 if there are no files matching the filespec.



INVORALL.EXE
------------
File Inventory Utility with Multiple Seeks and Critical Error Trapping.

Syntax:  INVORALL d:path\seek1 [seek2 [seek3 [...]]] [ /X ] [ /T ]
Example: INVORALL c:\.exe .com

Switch /X excludes subdirectories; /T adds total bytes listed.

INVORALL is an enhanced SRCHDIR that returns all file names that include any
of the specified seek strings.  In addition to the information returned by
SRCHDIR, the file size (up to 2 GB) is appended to each line, and extremely
long paths are handled gracefully by omitting the lowest subdirectory levels
(substituting "\...\") and showing only what fits in the space.  The maximum
number of seek strings is limited only by the 127-character command line.

If seek1 contains wild cards (* or ?), it will serve as a first-level
filter; i.e., only files that satisfy the seek1 file specification (and
also contain any one or more of seek2 through seekN, if specified) will be
reported.  If seek1 does not contain wild cards, there is no first-level
filtering; i.e., seek1 then behaves just like any other seekstring.  The
other seekstrings (seek2 through seekN) must NOT contain any wildcards.

This utility employs critical error trapping, so it can be used on a
removable-media drive without triggering unwanted error messages.  File
inventory collection can be attempted on all possible drive letters,
regardless of whether they exist or have media in them.  Returns errorlevel:
1 = nothing found, 2 = memory allocation error, 3 = syntax or path error.

For example, to inventory all the .EXE, .COM, .SYS, and .DLL files on a
system, the following commands are used:

   INVORALL C:\.EXE .COM .SYS .DLL >INVNTORY.TXT
   INVORALL D:\.EXE .COM .SYS .DLL >>INVNTORY.TXT
   INVORALL E:\.EXE .COM .SYS .DLL >>INVNTORY.TXT

Continue in like fashion for all drives that could potentially be present.
It doesn't matter if the drive doesn't exist or has no media in it. Note
that there are NO wild cards in the above specifications; if C:\*.EXE had
been specified, nothing would be reported, because there is no .EXE file
that also has .COM, .SYS, or .DLL in its name.

If you are searching only for particular .EXE files, that's where the first
level filter comes in:

    INVORALL C:\*.EXE HJPRO. WPWIN. WINWORD. HGWIN. >INVNTORY.TXT
    etc.

This will collect data on the files of interest as quickly as possible,
without wasting time comparing non-.EXE files to the seek strings.

If the specific files sought have a combination of extensions, their full
names should be specified, without wild cards:

    INVORALL C:\HJPRO.EXE WPWIN.EXE XTGOLD.COM LIST.COM >INVNTORY.TXT
    etc.

This will generally be faster than using two separate INVORALL commands
on each drive (one with *.EXE and another with *.COM first level filters)
because the latter method would require a second full search of the drive's
subdirectory structure.

Use INVORALL to find out if a file exists on a drive you aren't sure is
there, without creating a messy error display.  For example, suppose you
want your batch script to find out if the PC has Windows installed on
Drive D: or E: instead of Drive C:.  If you use a command of the form
"if exist d:\windows\system.ini ..." and Drive D: is a CD ROM that doesn't
have a CD in it, the user will see a nasty "Not ready reading Drive D:"
error display and will have to decide whether to Abort, Retry, Ignore, or
Fail the error.  Not knowing why you are trying to read his CD ROM in the
first place, he is likely to be confused and angry.  Instead, use the form
"invorall d:\windows\system.ini /x >nul" and "if not errorlevel 1 ..." to
get the information you need without involving the user in any way.



MAKEDIR.COM and REMOVDIR.COM
----------------------------
These are non-complaining substitutes for the DOS "mkdir" or "md" command,
and "rmdir" or "rd" command, respectively, suitable for use in batch files.

Syntax: MAKEDIR dirspec
    or: REMOVDIR dirspec

MAKEDIR attempts to create the specified directory. If the directory already
exists, its report of "Cannot create directory dirspec" is directed to STDOUT
where it can be readily suppressed with ">nul". Returns errorlevel 1 if the
directory cannot be created.

Similarly, REMOVDIR attempts to remove the specified directory, and its
report of being unable to do so is redirectable. It returns errorlevel 1
if the directory cannot be removed.

Typically, one would have to do the following when writing a batch to install
files into a subdirectory:

   if not exist dirspec\nul md dirspec
   copy path\*.* dirspec >nul

Unfortunately, in some situations (e.g., network drives, or a DOS box in OS/2) 
DOS is fooled into thinking the directory already exists even when it doesn't.
The result is one large file named DIRSPEC instead of a directory with files.
With MAKEDIR, this is not a problem. The batch becomes:

   makedir dirspec >nul
   copy path\*.* dirspec >nul

This will create the directory properly in any operating environment.

The companion REMOVDIR command is provided for convenience, to avoid
constructs of the form "if not exist dirspec\*.* rd dirspec". This is
especially helpful when other conditions being tested in the batch are
already pushing the command line length to its 127 character limit.



DELFILE.COM
-----------
Just as REMOVDIR gets rid of directories in a batch-friendly way,
DELFILE gets rid of unwanted files.

Syntax: DELFILE filespec

Its report, announcing whether or not the file was deleted, is redirectable.
It returns errorlevel 1 if the file cannot be deleted.



BIN2ASC.EXE and ASC2BIN.EXE
---------------------------
This is a complementary pair of programs for converting binary files to
ASCII files and back again.

Syntax: BIN2ASC binfile.ext ascfile.ext
        ASC2BIN ascfile.ext binfile.ext

Some communication protocols, designed for use with ASCII files, cannot
transfer binary files due to their interpretation of special characters
within the data stream. BIN2ASC converts a binary file of size x to an
ASCII file of size 2x that contains the hexadecimal ASCII representation
of the binary values found in the original file. ASC2BIN converts such a
file back to its original binary form.



INTADD.COM
----------
Integer Addition program suitable for use with decimal or hexadecimal values.

Syntax: INTADD [x][-]value1 [x][-]value2

The output is a "SET RESULT=sum" command printed to stdout, which can be
redirected into a batch file and called to create the RESULT environment
variable. The sum is formatted as either a four-digit hexadecimal value
with leading zeros, or as a non-padded decimal value. The format of value1
determines the format of the sum. The formats of value1 and value2 need not
match. A leading "x" identifies the value as hexadecimal, but the output sum
will not include an x. The input parameters are not case-sensitive.
Permissible values are hexadecimal 0000 to FFFF or decimal -32768 to 32767.
Hexadecimal results of 8000 through FFFF are considered to be "negative".
The returned errorlevel code is 0 for positive result, 1 for negative, and
2 for syntax error.

Examples:

   INTADD xc800 x0400    produces   SET RESULT=CC00     with errorlevel 1

   INTADD xc800 -1       produces   SET RESULT=C7FF     with errorlevel 1

   INTADD xc800 x-c000   produces   SET RESULT=0800     with errorlevel 0

   INTADD x1000 4096     produces   SET RESULT=2000     with errorlevel 0

   INTADD 4096 x1000     produces   SET RESULT=8192     with errorlevel 0

   INTADD x7000 8192     produces   SET RESULT=9000     with errorlevel 1

   INTADD 8192 x7000     produces   SET RESULT=-28672   with errorlevel 1

Batch Example: Note that the "set v1" used here might be replaced with a
               batch-generated setting produced by reading a configuration
               file in a real situation.

   set v1=c800
   intadd x%v1% x03FF >temp.bat
   call temp.bat
   del temp.bat

   You now have a RESULT environment variable that contains CC00.
   Continuing:

   set test1=N
   set test2=N
   intadd x%result% x1000 >nul
   if errorlevel 1 set test1=Y
   intadd x%v1% x-c800 >nul
   if not errorlevel 1 set test2=Y
   if not %test1%%test2%==YY goto end
   echo Values are within the upper memory range; setting EMM exclusions:
   xchange /i c:\config.sys "emm386.exe" "emm386.exe x=%v1%-%result%" >nul
   inimod c:\windows\system.ini "386Enh" "EMMExclude" "%v1%-%result%" /a >nul
   :end



INPUT.COM
---------
Provides text input within a batch file, one line of up to 128 characters.

Syntax: INPUT "prompt" filespec

The prompt is displayed, and characters are fetched from STDIN until a
carriage return is received. The received characters are then appended to
the specified file, minus the carriage return. If a terminating carriage
return is required, the INPUT statement must be followed by the command,

   echo.>>filespec

INPUT has many possibilities. Because it doesn't pass the carriage return,
you can concatenate many responses or other text to the initial response.
Because it doesn't overwrite an existing file, concatenation is the default.
If you need a new file, be sure to delete any existing file by that name
before invoking INPUT.

Its input can be redirected from another file. This is a handy way of
creating strings of text that aren't return-terminated. For example, when
your batch says "echo string>file1", you actually get "string" + CRLF in the
file. To get just "string" without the CRLF, do this after the echo:

   input "" file2 <file1

INPUT is also very nice for getting input for other commands that don't
behave as you would like. For example, suppose another command displays a
nice prompt and requests input, but then messes up the screen with a report
of what it's doing with the input. If you redirect its output to nul or to
a file, you lose the nice prompt and the user can't see what he's typing.
Here's the solution:

   if exist file1 del file1
   input "nice prompt" file1
   echo.>>file1
   messycommand <file1 >nul

This lets the user see the nice prompt (which you can now tailor to your
liking), and it lets the messy command receive the intended input without
messing up the screen.

Another great use of INPUT is to set environment variables with input typed
by the user. Here's how:

   echo set envar=>temp.fil
   if exist temp.bat del temp.bat
   input "" temp.bat <temp.fil
   input "Please enter the desired setting:" temp.bat
   echo.>>temp.bat
   call temp.bat
   del temp.bat
   del temp.fil

You now have an environment variable named ENVAR that contains the string
typed by the user.



TPAUSE.COM
----------
Timed Pause displays a user-specified prompt and accepts a single-keystroke
response. If no key is pressed within the timeout interval, it terminates
with zero errorlevel.

Syntax: TPAUSE [/T:hh:mm:ss] "prompt"[,keylist]

Timeout may be from 1 second to 23 hours 59 minutes 59 seconds, or infinite.
Default timeout = 1 minute.  Keylist is case-insensitive.
If keylist is omitted, any keystroke will terminate the delay.
Returns errorlevel code = position of keystroke within list, 0 = timed out.
See (and execute) TPHELP.BAT for usage examples.

The colons are optional; when omitted there must be two digits per portion
with the exception of seconds. Short strings are assumed to represent short
intervals. For example, /t5 = 5 seconds, /t5:00 or /t0500 = 5 minutes,
/t050000 = 5 hours, /t5000 or /t500 = 50 minutes. Times of less than 100
seconds may be represented as seconds; e.g., /t90 = 90 seconds. To disable
timeout (infinite wait) use zero, /t0.



TZSET.EXE
---------
Automatic TZ Adjustment for Daylight Savings Time.

TZSET automatically sets the TZ environment variable to either CST6 or
CST6CDT, depending on whether or not the current system date is between the
first Sunday in April and the fourth Sunday in October. The central time zone
is only a default; if you use it in another time zone, simply preset TZ to
the base setting for your time zone (e.g., SET TZ=EST5) before invoking
TZSET. It will then produce either the same setting or one with the proper
"_DT" appended to it (e.g., SET TZ=EST5EDT). If the current TZ setting is
undefined, or if its 2nd through 4th characters are not "ST" followed by a
numeric character, the default CST zone is used. A confirmational message of
the form ":: Setting TZ=CST6CDT" is issued to STDOUT. The double colon is
for compatibility with the old TZSET.COM, which always generated SET TZ=
commands that had to be captured in a temporary batch; this prevents syntax
errors when its new output is inadvertently executed.

The environment that gets modified is that of the active COMMAND.COM command
processor (i.e., if you are shelled out to DOS from an application, or in a
DOS box in Windows, the subordinate COMMAND.COM environment in which you are
working gets modified rather than that of the master command environment
created at boot time; this is the same way the SET command works). This can
fail only if the command processor has a name other than COMMAND.COM or has
inadequate environment space to hold the new setting.

In the case of a differently-named command processor, TZSET will generate an
errorlevel of 1, and it will output a SET command that can be captured in a
temporary batch file as follows:

   tzset >temp.bat
   if errorlevel 1 call temp
   del temp.bat

If the error condition was generated by inadequate space in the command
processor environment, this will generate an "Out of environment space"
message when the "call temp" executes. TZSET itself does not produce such
a message, but returns errorlevel 1 to flag its inability to change the
environment.



FINDALL.EXE
-----------
An alternative to the DOS FIND command.  The syntax is different:

FINDALL [/i] filespec "[srchstrng][^[x]chr,][...]"
FINDALL [/i] filespec @scriptfile

Switch /i = ignore case (can be in any parameter position); chr = ASCII.
Search string can be any combination of literals and ^-prefixed, comma-
delimited ASCII codes (^1 through ^255 or ^x01 through ^xFF).
Use double ^ or , for literal ^ or , character within a string.
Quotes may be omitted if there are no spaces within strings.

NOTE: FIND's /V, /C, and /N switches are not supported.

This program provides "ignore case" (/I) capability to all versions of DOS
from 3.0 on up.  It will output lines of up to 8192 characters containing
the sought text.  By using wildcards in the filespec, multiple files may be
searched with a single command, and the output is not dirtied up with the
names of files being checked.



LMORE.COM
---------
An alternative to the DOS MORE command.  Use it in identical fashion.

Although the DOS MORE command has improved in recent versions, it is still
quite messy, especially when dealing with lines longer than 80 characters
(i.e., lines that wrap around to display as multiple-line records).  It has
a bad habit of printing its "-- More --" prompt in the middle of a line and
thoroughly messing up the display format of all remaining display lines of
the affected record.

LMORE is a line-based MORE that checks the length of each input record to
ensure that it will fit on the current screenful before displaying it.
If the entire record cannot fit on the screen, the "-- More --" prompt
appears in the position that the first line would occupy.  When a key is
pressed, it backspaces over its prompt, overwrites the prompt with spaces,
then backspaces over it again so that the display can continue in uninter-
rupted fashion.  If the keystroke is Esc or Ctrl-C, the process is aborted.



INIMOD.EXE
----------
This utility allows you to add, delete, or modify settings within specific
sections of Windows-style .INI files.

Syntax variations:

   1) INIMOD filespec "section" "variable" "value" [/a | /d]
   2) INIMOD filespec "section" "variable" /d
   3) INIMOD filespec "section" /d

Variation 1 looks for the specified variable name within the specified
section and changes its value to the one specified. If the section does
not exist, it gets appended to the end of the file, and if the variable
does not exist within the specified section, it gets appended to the end
of that section. Omitting the value will leave the variable in place with
nothing to the right of the equals sign. Options /a and /d are for variable
names that may exist in more than one instance within the section; e.g.,
the many "device=" lines in the [386Enh] section of SYSTEM.INI. Option /a
will add the requested setting, if not already present, without affecting
any existing settings that use the same keyword. Option /d will delete
only the line in which the setting is functionally equal to that specified.
Be very careful to always use the "/a" option when adding such a multiple-
instance setting, lest you lose all the other instances!

Variation 2 looks for the specified variable name within the specified
section and deletes that line. Be careful; if multiple instances of the
same keyword appear in that section, all will be deleted.

Variation 3 looks for the specified section header and deletes it along
with all variables following it until the next section header is reached.

If the value string is too long to fit on the command line, use a dummy
setting such as "!$!" and follow the INIMOD command with an XCHANGE command
using a script file to change the dummy setting to the desired setting.

All parameters are case-insensitive; however, a new or modified setting
will be written in the exact case used on the command line. All syntax
variations perform cleanup of redundant settings that are functionally
equal to the specified setting.

The present implementation handles just one setting at a time. If multiple
settings are to be made, use a batch to call INIMOD for each one. Output
to the screen identifies the changes made, or the fact that no change was
necessary. The INIMOD command, entered without parameters, will display a
syntax summary and a list of errorlevel codes.



INIREAD.EXE
----------- 
This .INI file interpreter for batch files allows you to capture any
desired setting, from any section, in the environment variable you name.

Syntax: INIREAD filename "section heading" "parameter" "envarname"

If the parameter is found in multiple lines of the same section (e.g.,
"device=" in the [386Enh] section of SYSTEM.INI), the first occurrence
will be returned in the specified variable, and the subsequent occurrences
will be returned in variables having similar names with numerical suffixes
2 through n, where n is the number of occurrences found.

Example: INIREAD c:\windows\system.ini "386enh" "device" "dev$dvr"
will return the first device= setting in environment variable DEV$DVR;
if there are 15 device= settings, the rest will be in DEV$DVR2 through
DEV$DVR15.

Multiple parameters can be handled in your batch via the INTADD.COM
and XCHANGE.EXE utilities in a loop structure. For example:

   @echo off
   INIREAD c:\windows\system.ini "386enh" "device" "dev$dvr" >nul
   if errorlevel 2 goto end
   echo Setting #1: %dev$dvr%
   set result=1
   :chknxt
   intadd %result% 1 >temp1.bat
   copy temp1.bat temp2.bat >nul
   xchange temp2.bat "SET RESULT=" "SET ENVAR=%%DEV$DVR" >nul
   xchange temp2.bat ^13 "%%^13" >nul
   call temp2.bat
   if %envar%.==. goto end
   call temp1.bat
   echo Setting #%result%: %envar%
   goto chknxt
   :end
   del temp?.bat
   set result=
   set envar=
   echo End of list.

Echos an indication of the outcome and returns an errorlevel code as follows:
0 = one setting found,  1 = multiple settings found,   2 = no setting found,
3 = section not found,  4 = out of environment space,  5 = file inaccessible,
6 = other error (syntax, path interpretation, or unable to locate environment)

Note: If the sought parameter is found in the specified section, but has
      nothing to the right of the "=" sign, the specified environment
      variable will be cleared and the errorlevel will be zero (or 1, if
      the empty setting was one of multiple settings), as the empty condition
      correctly reflects the content of the .INI file. However, when the
      errorlevel is 2 or greater, the environment table will retain any
      previously existing settings for variables corresponding to parameters
      that are not defined in the file or were not successfully processed
      prior to the error.



RUNBAT$.EXE
-----------
This is a batch file launcher for use within a user's Novell network
login script. It looks up the COMSPEC environment variable and calls
whatever is referenced therein (i.e., the fully qualified path to the
command line processor), passing it parameters requesting a 5K space
for environment variables (/E:5120) and command execution (/C) plus
whatever parameters (maximum quantity of 9) are included on the RUNBAT$
command line.

For example, if COMSPEC=C:\DOS\COMMAND.COM, then the following login
script entry:

   #RUNBAT$.EXE Y:\PUBLIC\BATCH\PROCESS.BAT PARM1 PARM2

is equivalent to this:

   #C:\DOS\COMMAND.COM /E:5120 /C Y:\PUBLIC\BATCH\PROCESS.BAT PARM1 PARM2

The use of RUNBAT$.EXE makes this work regardless of where COMMAND.COM
actually is, and eliminates the awkward COMMAND.COM parameter syntax
from the login script. RUNBAT$.EXE consumes virtually no memory, loading
COMMAND.COM into the memory space that RUNBAT$.EXE itself originally
occupied.

RUNBAT$.EXE is for use only with MS-DOS versions 3.0 through 6.22. It should
not be used with Windows 95 or later because COMMAND.COM is too large to
be compatible with the overlay process. See RUNBAT$.COM below.



RUNBAT$.COM
-----------
Used in the same manner described above for RUNBAT$.EXE, RUNBAT$.COM runs
COMMAND.COM as a child process instead of letting it overlay RUNBAT$.COM in
memory. This has an impact of approximately 15K on the conventional DOS
memory available to the launched batch process. However, this makes it
compatible with Windows 95 and later in addition to remaining compatible
with MS-DOS versions 3.0 through 6.22.



ENVMASTR.EXE
------------
When you use the SET command while shelled out from an application, it sees
only the local environment of the shell. ENVMASTR lets you work in the
master environment that was created when the system was booted, and/or
any subordinate environments. This is especially useful when using RUNBAT$
to execute a batch whose environment manipulation is expected to stick to
the command environment from which RUNBAT$ was executed. The batch can
either make all environment changes through ENVMASTR, or make them locally
and then use ENVMASTR to copy the modified environment into the master.
A display-only option lets you view the content of any environment space,
complete with a report of the environment size, bytes used and bytes free.
Beginning with Version 3.0, ENVMASTR can display and edit environment blocks
in upper memory as well as conventional memory, and any instance of COMMAND
found in upper memory is promoted to "master" status (this ensures that the
master environment is properly identified when Windows 95 or later
high-loads COMMAND.COM).

Syntax: ENVMASTR [/d] [/c] [/n:progname] [/s] [/x] [/l] [varname=setting]

If no option switches are given, it applies varname=setting to the master
command environment only (i.e., the command processor loaded by CONFIG.SYS).
The option switches, which may be indicated by either a slash or a dash,
modify its operation as follows:

/d displays the environment(s) without changing anything (ignores varname).
/c copies the entire current local environment to target(s) (ignores varname).
/n names a specific target program's environment to be modified (any level).
/s targets all subordinate environments that have room.
/x excludes the master environment (implies /s).
/l allows lower-case characters in the variable name (default is forced CAPS).

Note: If the desired value begins with a space, enclose it in quotation marks.
      For quotation marks within the setting, prefix each with a backslash.

The order of the option switches is not important, so long as all precede
the varname=setting (if any). The varname=setting is required except
when option /c or /d is used, in which case varname=setting is ignored.
The /c option should be used with caution, as you may be copying some
settings that you really don't want to have in the target environment,
especially when you use ENVMASTR from a DOS box under Windows. Windows
maintains some settings that should not be carried back to the master
environment from which Windows was launched. When this happens, the /l
option will allow you to get rid of the "windir" variable, which is in
lower case and cannot be removed by a SET command. When using /n to name
a specific target environment, the progname is typically the executable
file name without any extension.

For example, to change all COMMAND.COM environments regardless of how
many shell levels are present, without affecting any other programs,
use the following command, substituting your variable name and setting:

   ENVMASTR /N:COMMAND varname=value

If you were copying the local command environment to all COMMAND.COM
shell levels, the command would be:

   ENVMASTR /N:COMMAND /C

To copy the local environment to the master only, use ENVMASTR /C without
any /n specification.

To remove a variable name from the environment, use varname= (without a
setting), just as you do when using SET.

To view the usage of only the subordinate COMMAND.COM environment, without
seeing the master environment, use this command:

   ENVMASTR /N:COMMAND /X /D

Note that this will show nothing if the current command environment IS the
master environment. To see only the master environment, just do this:

   ENVMASTR /D

A list of target environments found, and the success or failure of the
requested setting in each, is sent to STDOUT for display or redirection.

It returns errorlevel 1 if a subordinate environment could not be changed,
and errorlevel 2 if the master environment could not be changed.
Errorlevel 3 indicates a syntax error (no setting attempted).

Errorlevel 1 or 2 occurs only in the event that the target environment
is too small to accommodate the requested change. There is no errorlevel
when a specified program environment is not present, nor when using /d.

ENVMASTR is very careful to ensure that the change can be accommodated
within the target environment. It also preserves command line argument
zero (i.e., the command line without parameters), which follows the
defined variables; this information is never copied from one environment
to another but is preserved in its original state. Argument zero will move
within its home environment, so that it always follows the variable list
in the correct relative position, and the change will be disallowed if
there is no room to append argument zero to the list.



NRTS.EXE
--------
This is a utility for testing a user's rights in a specified Novell
server volume subdirectory. It works with Novell Netware 3.11.

Syntax: NRTS d:path  (where "path" is a network directory mapped to drive d:)

If path begins with a backslash, it must be fully qualified RELATIVE TO THE
NETWORK SERVER VOLUME, which may differ from the path of the mapped DOS logical
drive if the drive is MAP ROOTed into a subdirectory of the server volume.

Returns errorlevel 0 for full Read/Write privileges, 1 for Read-Only, 2 for
neither Read nor Write, 3 for invalid path specification.  Text description
of rights is returned to STDOUT and may be redirected to NUL or to a file.

Caution: Netware will not properly reject the path as invalid when only the
last specified subdirectory level is non-existent.  Instead, it will report
that you have write privileges in the non-existent directory.  Be sure to spell
the subdirectory name correctly.  Do not rely upon this program to confirm that
a desired directory was properly mapped.  It is for rights testing ONLY!



All of the above utilities were generated with an assembler or a C compiler.
See README2.TXT for additional included utilities, which were hand-assembled.
