home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
cidsam.zip
/
SAMPINST.CMD
< prev
next >
Wrap
OS/2 REXX Batch file
|
1993-06-07
|
29KB
|
734 lines
/***************************************************************************/
/* product XXXXX Installation */
/* */
/*******************************************/
/* This command file is an example of a */
/* complete CID installation. */
/* It is based on production code, but */
/* is provided only as an example. */
/* Some external routines called by this */
/* sample are *not* provided. */
/*******************************************/
/* Install product AAAAA if version installed is < 1.00 */
/* Install product BBBBB if the version installed is < 2.00 */
/* Install product XXXXX if the version installed is < 1.00 */
/* */
/* Note: program getbootd must be in the same directory as this cmd file */
/* */
/***************************************************************************/
/* Change History */
/* */
/* Mark Doc When Who Why */
/***************************************************************************/
/* This command file accepts a set of input parameters that are fairly */
/* common among CID-enabled install programs. All of the IBM OS/2 cid- */
/* enabled programs use them, for example. */
/* */
/* /R:<path>respfile gives the name of the response file. This is a */
/* required parameter. */
/* */
/* /S:<path> names the directory where the source files (the */
/* files from which the install is done) reside. *
/* This is typically a network drive. If not */
/* specified, the path defaults to the directory */
/* from which this program was loaded. */
/* */
/* /G:<path> names another directory where other needed */
/* might be located (imbedded response files, */
/* for example). */
/* */
/* /L1:<path>file names a file where history and log information */
/* will be placed. */
/***************************************************************************/
arg inparms
/* If NVDM/2 invoked us, and this is not */
/* the first invocation, we must be done */
/******************************************/
/* The environment variable */
/* REMOTE_INSTALL_NEXT_STATE */
/* is specified by LAN CID Utility. See */
/* the LCU guide for information on this */
/* variable. */
/******************************************/
state = VALUE('REMOTE_INSTALL_NEXT_STATE',,'OS2ENVIRONMENT')
IF state <> "" THEN
IF state <> 0 THEN
DO
CALL ENDLOCAL
EXIT 0
END
/**************************** Start *************************************/
/******************************************/
/* Most of the things in the main routine */
/* of this command file have to be done. */
/* The way you do them may vary. */
/* Basically, the main line of this */
/* program */
/* Parses the command line */
/* Reads the response file */
/* Unpacks the programs needed to do */
/* the install. */
/* Checks to make sure there is enough */
/* space to do the install. */
/* Installs the product(s). */
/* Does something to handle files that */
/* could not be replaced because */
/* they were in use. */
/* */
/* The return codes used are those */
/* required by LAN CID Utility (LCU) and */
/* Netview DM/2. */
/******************************************/
CALL SETLOCAL
/* Set the default source path. */
srcpath = GetLoadDir() /* srcpath may be overridden later */
BootDrive = GetBootDrive() /* What drive were we booted from? */
WkDir = BootDrive"\OS2\INSTALL\ESAWKDIR" /* Create a working directory. */
ADDRESS CMD "@MkDir" WkDir ">NUL 2>&1"
/* create log and history file names */
hist = WkDir"\dcfinst.hst"
logf = WkDir"\dcfinst.log"
ADDRESS CMD "@ERASE" hist ">NUL 2>&1"
ADDRESS CMD "@ERASE" logf ">NUL 2>&1"
/******************************************/
/* Set up the environment for the error */
/* logging routine from hlrfio. (See */
/* cidlog.c) */
/******************************************/
CALL VALUE "LOG_FILE",logf,"OS2ENVIRONMENT"
CALL VALUE "LOG_MESSAGE_FILE","XXXXX.msg","OS2ENVIRONMENT"
histout = ">>"hist" 2>>&1"
irc = 0
/* Check command line and do initialization */
IF ParseParms(inparms) THEN
DO
/* Locate the message file so we can log stuff */
/* Parse the response file */
IF (ParseRespFile(respfile)) THEN
/* Make sure there's at least enough */
/* space for our files */
IF EnoughRoomForInstFiles(BootDrive, TargetDrive) THEN
DO
/* Read the installation directory */
IF (readlist(loadpath"\XXXXX.dat")) THEN
DO
/* See what groups, if any, we will be installing */
CALL GetInstallGroups
IF (instgrps.0 > 0) THEN
DO
/* Unpack the installation stuff */
CALL InstUnpack
/* See if there's enough space */
IF spacecalc() THEN /* do the installation. */
DO
CALL Install /* Install selected groups */
/* Put Locked file Device Driver in config.sys */
IF (LFDDused) THEN
DO
ADDRESS CMD "@"loadpath"\addlfdd" BootDrive"\OS2\INSTALL"
irc = C2D('fe00'x, 2) /* reboot is required */
ADDRESS CMD "@ECHO XXXXX CID Install was successful. LFDD used." histout
END
END
ELSE /* No space available */
irc = C2D('1208'x, 2)
END
END
ELSE /* failed reading the directory */
irc = C2D('1604'x, 2);
END
ELSE /* no space for install files, even */
irc = C2D('1208'x, 2)
ELSE /* Failed parsing the response file */
irc = C2D('1604'x, 2);
END
ELSE /* command line parsing failed */
irc = C2D('1604'x, 2); /* Set 'error' return code */
IF irc = 0 THEN
ADDRESS CMD "@ECHO DCFINST CID Install was successful." histout
IF logfile <> "" THEN
DO
ADDRESS CMD "@type" WkDir"\XXXXX.hst >"logfile
ADDRESS CMD "@echo ---------------- log file ---------------- >"logfile
ADDRESS CMD "@type" WkDir"\XXXXX.log >>"logfile
END
CALL ENDLOCAL
EXIT irc
/***************************************************************************/
/* DoWeInstallIt - Decides whether a componant needs installed */
/***************************************************************************/
DoWeInstallIt: PROCEDURE EXPOSE fl. BootDrive srcpath loadpath TargetDrive hist
arg product, ver, grp.1, grp.2 grp.3, grp.4, grp.5
/******************************************/
/* This routine uses a very simple little */
/* program called "chklvl" to check what */
/* level a componant is at. You will */
/* probably want to create your own such */
/* utility specific to the product you */
/* are interested in. The source for */
/* this chklvl is included in the samples */
/* package for reference. */
/******************************************/
hout = ">>"hist" 2>>&1"
ADDRESS CMD "@"loadpath"\chklvl" BootDrive"\ibmlvl.ini" product ver hout
IF rc = 0 THEN /* product is not installed, or back-level */
RETURN 1 /* so we will definitely install it */
ELSE
IF rc = 2 THEN /* product is at a higher level. We won't install */
RETURN 0
ELSE /* product is at current level. Install if corrupted */
DO
DO k = 1 to 5 /* We can have up to 5 groups */
IF grp.k = "" THEN LEAVE
i = gindex(grp.k) /* find out what drive the file is on */
IF fl.i.DRIVE = '@' THEN
dr = BootDrive
ELSE
dr = TargetDrive
IF i > 0 THEN DO
DO j = 1 to fl.i.0 /* See if the file exists */
IF (STREAM(dr||fl.i.j.FNAME, 'c', 'query exists') = "") THEN
DO
CALL logXXXXXMsg 6, product, ver
RETURN(1) /* corrupted or installed on another drive */
END
END
END
RETURN 0 /* Already correctly installed */
END
RETURN 1 /* should never get here */
/***************************************************************************/
/* GetInstallGroups - decide what needs to be installed */
/***************************************************************************/
GetInstallGroups: PROCEDURE EXPOSE instgrps. fl. BootDrive srcpath loadpath,
TargetDrive instprods. hist
i = 0
j = 0
IF DoWeInstallIt("AAAAA", "1.00", "[AAAAFILS]") THEN
DO
i = i + 1
instgrps.i = "[AAAAFILS]"
CALL logXXXXXMsg 7, "FFST 1.00"
j = j + 1
instprods.j = "AAAAA"
instprods.j.RELVER = "1.00"
instprods.j.IPATH = BootDrive"\OS2"
END
ELSE
CALL logXXXXXMsg 8, "AAAAA 1.00"
IF DoWeInstallIt("BBBBB", "2.00", "[BBBFILE1]") THEN
DO
i = i + 1
instgrps.i = "[BBBFILE1]"
CALL logXXXXXMsg 7, "BBBBB 2.00"
j = j + 1
instprods.j = "BBBBB"
instprods.j.RELVER = "2.00"
instprods.j.IPATH = BootDrive"\MUGLIB"
END
ELSE
CALL logXXXXXMsg 8, "BBBBB 2.00"
IF DoWeInstallIt("XXXXX", "1.00", "[XXXFILS1]", "[XXXFILS2]") THEN
DO
i = i + 1
instgrps.i = "[XXXFILS1]"
i = i + 1
instgrps.i = "[XXXFILS2]"
CALL logXXXXXMsg 7, "DCF 1.00"
j = j + 1
instprods.j = "XXXXX"
instprods.j.RELVER = "1.00"
instprods.j.IPATH = TargetDrive"\SQLLIB"
END
ELSE
CALL logXXXXXMsg 8, "XXXXX 1.00"
instgrps.0 = i
instprods.0 = j
RETURN
/***************************************************************************/
/* Install - moves the files from server to PC */
/***************************************************************************/
Install: PROCEDURE EXPOSE fl. BootDrive TargetDrive srcpath LFDDused,
instgrps. histout loadpath instprods.
/******************************************/
/* This sample assumes that the files to */
/* be installed are stored in PKZIPed */
/* groups. Change the unpacking code to */
/* accomodate other packing schemes. */
/******************************************/
LFDDused = 0
DO i = 1 to instgrps.0
filename = SUBSTR(instgrps.i, 2)
filename = STRIP(filename, 't', ']')
filename = srcpath"\"filename".ZIP"
j = gindex(instgrps.i)
IF j > 0 THEN
DO
IF fl.j.DRIVE = "@" THEN
tdrive = BootDrive"\"
ELSE
tdrive = TargetDrive"\"
lfddcmd = "MOVE"
IF left(tdrive,1) <> left(BootDrive,1) THEN
lfddcmd = "COPY"
IF fl.j.LOCKED THEN
DO
ADDRESS CMD "@PKUNZIP2 -o -d" filename BootDrive"\IBMLANLK" histout
DO k = 1 to fl.j.0
ADDRESS CMD "@ECHO" lfddcmd BootDrive"\IBMLANLK"fl.j.k.FNAME tdrive||fl.j.k.FNAME ">>"BootDrive"\OS2\INSTALL\IBMLANLK.LST"
END
LFDDused = 1
END
ELSE
ADDRESS CMD "@PKUNZIP2 -o -d" filename tdrive histout
END
END
DO i = 1 to instprods.0
ADDRESS CMD "@setlvl c:\ibmlvl.ini" instprods.i instprods.i.RELVER instprods.i.IPATH
END
RETURN
/***************************************************************************/
/* spacecalc -- see if there is enough space to install */
/* (also sees if any files are locked) */
/***************************************************************************/
spacecalc: PROCEDURE EXPOSE fl. BootDrive TargetDrive instgrps. loadpath
size.1 = 0
size.2 = 0
DO i = 1 TO instgrps.0
j = gindex(instgrps.i)
IF fl.j.DRIVE = '@' THEN
dr = 1
ELSE
dr = 2
DO k = 1 to fl.j.0
filename = fl.j.k.FNAME
cursize = CurrentSizeOf(filename, dr)
size.dr = size.dr + fl.j.k.SIZE - cursize
IF cursize > 0 THEN
IF NotWriteable(filename, dr) THEN
DO
IF (fl.j.LOCKED = 0) THEN
CALL logXXXXXMsg 9, instgrps.i, filename
fl.j.LOCKED = 1
size.dr = size.dr + cursize
END
END
END
IF LEFT(BootDrive, 1) = LEFT(TargetDrive, 1) THEN
DO
size.2 = size.2 + size.1
size.1 = 0
END
IF EnoughSpace(TargetDrive, size.2) THEN
IF EnoughSpace(BootDrive, size.1) THEN
RETURN 1
RETURN 0
/***************************************************************************/
/* CurrentSizeOf - return the size in bytes of a file */
/***************************************************************************/
CurrentSizeOf: PROCEDURE EXPOSE BootDrive TargetDrive
arg filename, dr
IF dr = '1' THEN
size = STREAM(BootDrive||filename, 'c', 'query size')
ELSE
size = STREAM(TargetDrive||filename, 'c', 'query size')
IF size = "" THEN
size = 0
RETURN size
/***************************************************************************/
/* EnoughRoomForInstFiles() - returns 1 if there is enough */
/***************************************************************************/
EnoughRoomForInstFiles: PROCEDURE EXPOSE hist loadpath
arg bootd, targetd
/******************************************/
/* Of course, your install programs will */
/* probably take a different amount of */
/* space. This one takes 340K on the */
/* boot drive and 20K whereever. */
/******************************************/
IF bootd = targetd THEN
RETURN(EnoughSpace(bootd, 360000))
ELSE
RETURN(EnoughSpace(bootd, 340000) & EnoughSpace(targetd, 20000))
/***************************************************************************/
/* EnoughSpace -- return 1 if there is enough space, 0 otherwise */
/***************************************************************************/
EnoughSpace: PROCEDURE EXPOSE loadpath
arg dr, bogey
IF bogey <= 0 THEN
RETURN 1
DO queued()
PARSE PULL something
END
ADDRESS CMD "@DIR" LEFT(dr, 1)||":\*. /N | RXQUEUE /lifo 2>&1"
PARSE PULL free .
DO queued()
PARSE PULL something
END
IF free < bogey THEN
DO
CALL logXXXXXMsg 3, dr, bogey, free
RETURN 0
END
RETURN 1
/***************************************************************************/
/* NotWriteable: returns 1 if file could not be opened for write */
/***************************************************************************/
NotWriteable: PROCEDURE EXPOSE BootDrive TargetDrive
arg filename, dr
IF dr = '1' THEN
p = BootDrive
ELSE
p = TargetDrive
fn = p||filename
ADDRESS CMD "@"BootDrive"\OS2\attrib -R" fn ">NUL 2>&1"
IF rc = 0 THEN
DO
q = STREAM(fn, 'c', 'open')
IF q <> "READY:" THEN
RETURN 1
CALL STREAM fn, 'c', 'close'
END
RETURN 0
/***************************************************************************/
/* readlist -- read in the list of files to be unzipped */
/***************************************************************************/
readlist: PROCEDURE EXPOSE fl.
arg listfile
IF STREAM(listfile, 'c', 'query exists') = "" THEN
DO
logXXXXXMsg 5, listfile
RETURN 0
END
fl.0 = 0
i = 0
DO WHILE LINES(listfile)
lin = LINEIN(listfile)
IF LEFT(lin, 1) = "[" THEN
DO
i = i + 1
fl.0 = i
fl.i.ZIPNAME = WORD(lin, 1)
fl.i.DRIVE = WORD(lin, 2)
fl.i.LOCKED = 0
fl.i.0 = 0
j = 0
END
ELSE
DO
j = j + 1
fl.i.0 = j
fl.i.j.REPLACE = 1
k = 1
IF WORD(lin, 1) = "NOREPLACE" THEN
DO
k = 2
fl.i.j.REPLACE = 0
END
fl.i.j.SIZE = WORD(lin, k)
fl.i.j.FNAME = WORD(lin, k+1)
fl.i.j.EXISTS = 0
END
END
CALL STREAM listfile, 'c', 'CLOSE'
RETURN 1
/****************************************************************/
/* gindex - returns the index in fl. corresponding to the group*/
/****************************************************************/
gindex: PROCEDURE EXPOSE fl.
arg grp
DO i = 1 to fl.0
IF fl.i.ZIPNAME = grp THEN
RETURN i
END
RETURN 0
/****************************************************************/
/* GetBootDrive - sets the BootDrive variable */
/****************************************************************/
GetBootDrive: PROCEDURE EXPOSE srcpath
/******************************************/
/* It is very easy to write an OS/2 */
/* routine to extract the boot drive. */
/* The source for "getbootd" is included */
/* in the sample code for reference. */
/******************************************/
ADDRESS CMD '@'srcpath'\getbootd'
driveno = rc
IF ((driveno < 1) | (driveno > 26)) THEN
driveno = 3
bootdrive = SUBSTR("ABCDEFGHIJKLMNOPQRSTUVWXYZ", driveno, 1) || ":"
RETURN BootDrive
/******************************************************************************/
/* GetLoadDir() |*/
/* */
/* Extract the name of the directory from which this module was */
/* loaded. */
/******************************************************************************/
GetLoadDir: PROCEDURE
PARSE SOURCE "OS/2" "COMMAND" progname
loaddir = FILESPEC('drive', progname) || FILESPEC('path', progname)
loaddir = strip(loaddir)
loaddir = STRIP(loaddir, 'trailing', '\')
return loaddir
/****************************************************************/
/* ParseParms() - read the command line and set things up */
/****************************************************************/
ParseParms: PROCEDURE EXPOSE TargetDrive srcpath histout respfile genpath,
logfile loadpath
PARSE ARG inparms
genpath = ""
respfile = ""
logfile = ""
TargetDrive = ""
ADDRESS CMD "@ECHO" inparms histout
DO i = 1 to WORDS(inparms)
parm = WORD(inparms, i)
IF (POS('=', parm) > 0) THEN
PARSE VAR parm clflag '=' clval;
ELSE
PARSE VAR parm clflag ':' clval;
clval = STRIP(clval, 'both');
clflag = TRANSLATE(clflag); /* force flag to upper case */
SELECT
WHEN (clflag = "/S") THEN
srcpath = clval;
WHEN (clflag = "/R") THEN respfile = clval;
WHEN (clflag = "/G") THEN genpath = clval;
WHEN (clflag = "/L1") THEN logfile = clval;
WHEN (clflag = "/T") THEN TargetDrive = clval;
OTHERWISE DO
CALL logXXXXXMsg 1, parms.i;
shlrc = 4;
END
END
END
IF (respfile = "") THEN
DO
CALL logXXXXXMsg 2
RETURN 0
END
IF STREAM(respfile, 'c', 'query exists') = "" THEN
DO
CALL logXXXXXMsg 10, respfile
RETURN 0
END
loadpath = GetLoadDir()
IF srcpath = "" THEN
srcpath = loadpath
IF TargetDrive <> "" THEN
TargetDrive = LEFT(TargetDrive, 1) || ":"
path = VALUE('PATH',,'OS2ENVIRONMENT')
dpath = VALUE('DPATH',,'OS2ENVIRONMENT')
rfpath = FILESPEC("drive", respfile) || FILESPEC("path", respfile)
rfpath = STRIP(rfpath, 'trailing', '\')
IF genpath <> "" THEN
DO
p = genpath
IF (LENGTH(p) = 2) & (SUBSTR(p, 2, 1) = ":") THEN
p = p"\"
path = p || ";" || path
dpath = p || ";" || dpath
END
IF rfpath <> "" THEN
DO
p = rfpath
IF (LENGTH(p) = 2) & (SUBSTR(p, 2, 1) = ":") THEN
p = p"\"
path = p || ";" || path
dpath = p || ";" || dpath
END
IF srcpath <> "" THEN
DO
p = srcpath
IF (LENGTH(p) = 2) & (SUBSTR(p, 2, 1) = ":") THEN
p = p"\"
path = p || ";" || path
dpath = p || ";" || dpath
END
IF loadpath <> srcpath THEN
DO
p = loadpath
IF (LENGTH(p) = 2) & (SUBSTR(p, 2, 1) = ":") THEN
p = p"\"
path = p || ";" || path
dpath = p || ";" || dpath
END
call VALUE 'PATH',path,'OS2ENVIRONMENT'
call VALUE 'DPATH',dpath,'OS2ENVIRONMENT'
RETURN 1
/****************************************************************/
/* InstUnpack: prepare for installation */
/****************************************************************/
InstUnpack: PROCEDURE EXPOSE TargetDrive srcpath BootDrive hist loadpath
p = ">>"hist" 2>>&1"
ADDRESS CMD "@MKDIR" TargetDrive"\SQLLIB" p
ADDRESS CMD "@PKUNZIP2 -o -d" srcpath"\XXXXX1.ZIP" BootDrive"\" p
ADDRESS CMD "@PKUNZIP2 -o -d" srcpath"\XXXXX2.ZIP" BootDrive"\" p
ADDRESS CMD "@COPY" srcpath"\PKUNZIP2.EXE" BootDrive"\OS2\INSTALL\PKUNZIP2.EXE" p
ADDRESS CMD "@COPY" srcpath"\XXXXINST.EXE" BootDrive"\OS2\INSTALL\XXXXINST.EXE" p
ADDRESS CMD "@COPY" srcpath"\XXXXLVL.ASC" BootDrive"\OS2\INSTALL\XXXXXLVL.ASC" p
RETURN
/****************************************************************/
/* ParseRespFile: read and validate resp file data */
/****************************************************************/
ParseRespFile: PROCEDURE EXPOSE BootDrive srcpath WkDir TargetDrive histout,
loadpath
arg respfile
cmdname = "SETENVIR.CMD"
cmdname = WkDir || "\" || cmdname
ADDRESS CMD "@ERASE" cmdname ">NUL 2>&1"
ADDRESS CMD "@ERASE DCFCFG.DAT >NUL 2>&1"
CALL VALUE 'LOG_MESSAGE_FILE','ESAINST.MSG','OS2ENVIRONMENT'
/******************************************/
/* XXXXXRF would act very much like */
/* SAMPLE1, reading the response file and */
/* putting the keywords and values into */
/* a command file (SETENVIR.CMD) which */
/* would put the pairs into the environ- */
/* ment. */
/******************************************/
ADDRESS CMD "@XXXXXRF /R:"respfile ">"cmdname
CALL VALUE 'LOG_MESSAGE_FILE','XXXXINST.MSG','OS2ENVIRONMENT'
IF rc <> 0 THEN
RETURN 0
p = STREAM(cmdname, 'c', 'query exists');
IF p <> "" THEN
CALL cmdname
IF TargetDrive = "" THEN
DO
TargetDrive = VALUE("XXXTARGT",,"OS2ENVIRONMENT")
If TargetDrive = "" THEN
TargetDrive = "C:"
ELSE
TargetDrive = LEFT(TargetDrive, 1) || ":"
END
RETURN 1
/******************************************************************************/
/* logXXXXXMsg() |*/
/* */
/* This procedure does all error logging. Message logging may be */
/* also be done in the body of the shell. */
/* */
/* We find the name of the log message file, and try to open it. */
/* If the message file isn't found, we put out a message to STDOUT. */
/* If the message file is found, we look at offset '1F'X to find the */
/* offset of Message 1. We read to that position, then read the */
/* 'msgno'th line to get the message text. Then we process the */
/* substitution variables and put out the resultant message either */
/* to the Log File or to STDOUT */
/* */
/* We try really hard to find the log file. If it's not on the */
/* source path and not on the current path, we try every path in */
/* PATH and DPATH. */
/******************************************************************************/
logXXXXXMsg: PROCEDURE EXPOSE srcpath loadpath header wkdir histout
arg msgno,parm.1,parm.2,parm.3,parm.4,parm.5,parm.6,parm.7,parm.8,parm.9 .
lmfile = VALUE('LOG_MESSAGE_FILE',,"OS2ENVIRONMENT")
fqlmfile = srcpath"\"lmfile
IF STREAM(fqlmfile, 'c', 'query exists') = "" THEN
fqlmfile = loadpath"\"lmfile
IF STREAM(fqlmfile, 'c', 'query exists') == "" THEN
DO
ADDRESS CMD '@echo Log Message File' fqlmfile 'not found.' histout
ADDRESS CMD '@echo Can not log message number' msgno'. Message parms were:' histout
DO i = 1 to 9
IF parm.i == "" THEN
LEAVE
ELSE
ADDRESS CMD '@echo 'parm.i histout
END
RETURN
END
OffsetX = CHARIN(fqlmfile, 32 + (msgno * 2), 2)
wkvar = SUBSTR(OffsetX, 2, 1) || SUBSTR(OffsetX, 1, 1)
StartingOffsetD = C2D(wkvar)
OffsetX = CHARIN(fqlmfile, 32 + ((msgno+1)*2), 2)
wkvar = SUBSTR(OffsetX, 2, 1) || SUBSTR(OffsetX, 1, 1)
EndingOffsetD = C2D(wkvar)
lin = CHARIN(fqlmfile, StartingOffsetD + 1, EndingOffsetD - StartingOffsetD - 1)
CALL STREAM fqlmfile, "C", "CLOSE" /* Close the file @d3a*/
DO i = 1 to 9
n = POS("%" || i, lin)
IF (n <> 0) THEN
DO
lin = DELSTR(lin, n, 2)
temp = STRIP(parm.i)
lin = INSERT(temp, lin, n-1)
END
END
header = "DCA"
n = LENGTH(msgno)
DO i = 4 to (7-n)
header = header || '0'
END
if substr(lin,1,1) = "I" then /* INFO message */
header = substr(lin,2)
else
header = header || msgno || LEFT(lin, 1) || " " || SUBSTR(lin,2)
LogFile = VALUE("LOG_FILE",,"OS2ENVIRONMENT")
IF (LogFile <> "") THEN
DO
CALL LINEOUT LogFile, header
CALL STREAM LogFile, "C", "CLOSE" /* close the log file */
END
ELSE
ADDRESS CMD '@echo' header histout
RETURN