home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C!T ROM 2
/
ctrom_ii_b.zip
/
ctrom_ii_b
/
OS2
/
SYSTEEM
/
ROBOSV
/
ROBOSAVE.CMD
< prev
next >
Wrap
OS/2 REXX Batch file
|
1993-11-09
|
65KB
|
1,358 lines
/*****************************************************************************/
/* ROBOSAVE by Dick Kurtz and Jeff Knauth */
/* */
/* (c) Copyright International Business Machines Corporation 1994. */
/* All rights Reserved. */
/* */
/* Saves files and Extended Attributes for Desktop for OS/2 2.x. */
/* */
/* Issue "ROBOSAVE ?" for some brief help. For a detailed description see */
/* the ROBOSAVE User's Guide. */
/*****************************************************************************/
'@Echo off'
ver='3.04 1993/11/09' /* Version and creation date */
parse source . . robosavex /* v3.02 */
Say 'ROBOSAVE v'ver' by Dick Kurtz and Jeff Knauth.'
Say '(c) Copyright International Business Machines Corporation 1994.'
Say 'All rights Reserved.'
Say
Arg roboparm '/'op.1 . '/'op.2 . /* Get user parms */
curdir=Directory() /* Save current directory */
headnum=0 /* Number of header lines to write to ROBOREST.CMD */
pause='@PAUSE' /* Allow user to see msgs until log file is setup */
lognum=0 /* No log records built yet */
If roboparm='?' | roboparm='-?' | op.1='?' | op.2='?' then
Do
Call Tell
tell=1 /* v3.03b */
err=0
Signal Done1
End
err=1 /* Assume something will go wrong (makes the code simpler) */
tell=0 /* Indicate help was not invoked v3.03b */
/*****************************************************************************/
/* Register all REXXUTIL functions */
/*****************************************************************************/
rc=RxFuncAdd('SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs')
If rc>1 then
Do
Call Dosay 'Unable to register REXXUTIL functions.'
Signal Done1
End
Call SysLoadFuncs
If ReadPro()<>0 then /* Process profile data */
Signal Done1 /* Bail out if problems */
If FindBoot()<>0 then /* Find the boot drive */
Signal Done1
Call GetVolInfo /* Log volid and label of target */
If LocateDesktop()<>0 then /* Locate the Desktop anchor directory */
Signal Done1
If GenTargetDir()<>0 then /* Create target directories as necessary */
Signal Done1 /* Bail out if any problem */
pause='' /* Log is setup, no need to pause on exit now */
Call GenDebugInfo /* Record additional info for problem debug v3.02 */
Call MakeEraseDTP /* Set up the commands to erase the current Desktop */
/* v2.14 */
If GetMarker()<>0 then /* Get last use fn from marker file in target dir */
Signal Done /* Bail out if any problem */
/*****************************************************************************/
/* See if user wants to cleanup at start of run. Risky but allowed. */
/*****************************************************************************/
If cleanup='B' then /* Cleanup target at start of run? */
If ProcessRcmd()<>0 then /* Handle existing ROBOREST.CMx files */
Signal Done
/*****************************************************************************/
/* Finally we start by saving EAs. Initialize the various output record */
/* counters. */
/* ifnotrest =number of IF NOT records to write */
/* eautrest =number of EAUTIL records to write */
/* copyrest =number of COPY records to write */
/* echorest =number of ECHO records to write */
/* Variable robodir will have any files found in any of the desktop directo- */
/* ries that need to be copied in FileSave. */
/*****************************************************************************/
Parse value '0 0 0 0' with ifnotrest eautrest copyrest echorest .
If SaveEA()<>0 then
Signal Done
Call Dosay 'Desktop EAs saved: 'hit
/*****************************************************************************/
/* Now we save files. Those found in the Desktop directory structure, any */
/* contained in the profile and any specified on the CMD line call. */
/*****************************************************************************/
If FileSave()<>0 then
Signal Done
Call Dosay 'Files saved: 'hit
/*****************************************************************************/
/* See if we need to cleanup now or did we already do it at start of run. */
/*****************************************************************************/
If cleanup='E' then
If ProcessRcmd()<>0 then /* Handle existing ROBOREST.CM files */
Signal Done
/*****************************************************************************/
/* Now we create the new ROBOREST.CMD file. */
/*****************************************************************************/
If Genhdr()<>0 then /* Header records go first */
Signal Done
If ProcessIfnot()<>0 then /* Build IF NOT records */
Signal Done
If ProcessCrest()<>0 then /* and COPY records */
Signal Done
If ProcessErest()<>0 then /* and ECHO records */
Signal Done
If ProcessEaut()<>0 then /* and EAUTIL records */
Signal Done
err=0 /* How about that, it all worked! */
/*****************************************************************************/
/* Only exit from program. If fall through for normal exit or signal to */
/* Done then write log. data to ROBOSAVE.LOG in the specified directory. */
/* If signal to Done1 then log file is not setup yet so can't write it. */
/* Make sure we're back at the starting directory and exit. */
/*****************************************************************************/
Done:
Say 'Writing log file 'robolog
Do j=1 to lognum
rc=lineout(robolog,log.j)
If rc<>0 then
Do
Say 'Error writing 'robolog', RC 'rc
err=1
pause='@PAUSE'
Leave j
End
End
If \err then /* v3.02 */
x=lineout(robolog,"ROBOSAVE completed normally") /* v3.02 */
x=lineout(robolog) /* Close the file */
If ismarker then /* Marker file exist? */
Call SysFileDelete marker /* Yes, delete it */
x=lineout(marker,lastname) /* Write a new one */
x=lineout(marker) /* Close it */
Done1:
x=Directory(curdir) /* Put us back where we started */
pause /* Will pause if fail before log setup or log not written */
If err then Do /* v3.02 */
Call Beep 512,300 /* v3.02 */
Call Beep 256,500 /* v3.02 */
Call Beep 200,400 /* v3.02 */
Say /* v3.02 */
Say '*** ROBOSAVE has encountered an error. ***' /* v3.02 */
End /* v3.02 */
Else
If \tell then Say 'ROBOSAVE completed normally.' /* v3.03b */
Exit 0
/*****************************************************************************/
/* Locate the boot drive via the location of COMSPEC environment var. Not a */
/* foolproof method but should work well enough until REXXUTIL provides a */
/* means of doing this correctly. */
/*****************************************************************************/
FindBoot: Procedure expose boot lognum log. headnum head.
rc=0
env='OS2ENVIRONMENT' /* Environment name */
boot=Filespec("DRIVE",value('COMSPEC',,env)) /* Find Boot drive */
If boot='' | length(boot)<>2 | right(boot,1)<>':' then
Do
Call Dosay 'Unable to locate your boot drive. This should be pointed to'
Call Dosay 'by the SET COMSPEC= entry in CONFIG.SYS. ROBOSAVE can not'
Call Dosay 'continue. Please check your CONFIG.SYS for the above entry.'
rc=1 /* Force tremination */
End
Else
Do
l='Boot drive is 'boot
Call Dosay l
headnum=headnum+1 /* Create header line for ROBOREST.CMD */
head.headnum='Rem' l
End
Return rc
/*****************************************************************************/
/* Get target volid and label (if any) and place in log (ASIS) */
/*****************************************************************************/
GetVolInfo: Procedure expose svdir lognum log. headnum head.
'@VOL 'left(svdir,2)' | RXQUEUE'
Do queued()
Parse Pull data
If data<>'' then
Do
Call Dosay strip(data)
headnum=headnum+1 /* Gen another header line */
head.headnum='Rem' strip(data)
End
End
Return
/****************************************************************************/
/* Locate the active desktop. */
/* */
/* Extract all NODE entries from PM_Workplace:Handlesn (n=0 or 1) which is */
/* pointed to by PM_Workplace:ActiveHandles (SP or above) or */
/* PM_Workplace:Handles (GA). */
/* */
/* Get the 2 byte hex handle of <WP_DESKTOP> from PM_Workplace:Location of */
/* OS2.INI. Scan the nodes for a match (offset 7, length 2). When found */
/* save the name associated with the handle (offset 33 to end of node) and */
/* get the parent handle (offset 9, length 2). Restart scan from 1st node */
/* looking for the parent (offset 7, length 2). When found extract the drive*/
/* (offset 33 length 2) and append \name found previously. This gives us */
/* the current desktop directory anchor. */
/****************************************************************************/
LocateDesktop: Procedure Expose log. lognum dtp
Call Dosay 'Locating Desktop directory'
If Getnodes()<>0 Then
Do
rc=1
Signal LocateDesktopDone
End
gpinode=(Substr(SysIni('USER','PM_Workplace:Location','<WP_DESKTOP>'),1,2))
Parse value '' with gp dtp
Do gpi=1 to nodes.0
If substr(nodes.gpi,7,2)=gpinode then
Do
gp=substr(nodes.gpi,33,length(nodes.gpi)-33)
gpparent=substr(nodes.gpi,9,2)
Do until gpparent='0000'x
Do gpl=1 to nodes.0
If substr(nodes.gpl,7,2)=gpparent Then
Do
gp=substr(nodes.gpl,33,length(nodes.gpl)-33)||'\'||gp
gpparent=substr(nodes.gpl,9,2)
Leave gpl
End
End
End
dtp=gp /* Got it */
Leave gpi
End
End
If dtp='' then
Do
Call Dosay 'Unable to locate your Desktop directory. This is a critical',
'failure.'
Call Dosay 'ROBOSAVE cannot continue.'
rc=1
Signal LocateDesktopDone
End
Call Dosay 'Desktop directory is 'dtp
rc=0
LocateDesktopDone:
Return rc
/*****************************************************************************/
/* Get all the nodes. Fix to handle errors if DRIV/NODE pair not found. */
/*****************************************************************************/
Getnodes: Procedure Expose nodes. log. lognum
handlesapp=SysIni('SYSTEM','PM_Workplace:ActiveHandles','HandlesAppName')
If handlesapp='ERROR:' then
handlesapp='PM_Workplace:Handles' /* SP not installed, use GA default */
/*****************************************************************************/
/* Find all valid BLOCKn entries and append them into a single BLOCK1. v2.14 */
/*****************************************************************************/
Parse value '' with block block1
Do i = 1 to 999
block = SysIni('SYSTEM', handlesapp, 'BLOCK'||i)
If block = 'ERROR:' Then Do
If i = 1 Then Do
Call Dosay "Error ==> SysIni('SYSTEM', "handlesapp", 'BLOCK'||i)"
Call Dosay " ==> Unable to locate the NODE table"
rc=1
Signal GetnodesDone
End
Leave
End
block1 = block1||block
End
Call Dosay 'Blocks found =' i-1 ' Combined NODE table length =' length(block1)
/* v3.00b */
Parse value '0 0 0' with nodes. i l .
Do until l>=length(block1)
Select
When substr(block1,l+5,4)='DRIV' then
Do
xl=pos('00'x||'NODE'||'01'x,block1,l+5)-l
If xl<=0 then /* No NODE entry after DRIV? */
Leave /* Yes, we're done */
l=l+xl
Iterate
End
When substr(block1,l+1,4)='DRIV' Then
Do
xl=pos('00'x||'NODE'||'01'x,block1,l+1)-l
If xl<=0 then /* No NODE entry after DRIV? */
Leave /* Yes, we're done */
l=l+xl
Iterate
End
Otherwise
Do
data=substr(block1,l+1,32)
xl=c2d(substr(block1,l+31,1))
data=data||substr(block1,l+33,xl+1)
l=l+length(data)
End
End
i=i+1
nodes.i=data
End
nodes.0=i
rc=0
GetnodesDone:
Return rc
/*****************************************************************************/
/* See if target directory exists. If not then create it from the 1st level */
/* directory to the final target as needed. If svdir is only 3 bytes then it */
/* is the root of a drive/partition so does not need to be created. */
/*****************************************************************************/
GenTargetDir: Procedure expose svdir lognum log. curdir robolog
savedrive_currdir = Directory(left(svdir,2)) /* v3.02 */
rc=0
If length(svdir)>3 & (translate(Directory(svdir))<>translate(svdir)) then
Do /* outer do */ /* Does not exist */
If lastpos('\',svdir)=3 then /* Single level after drive? */
Do /* Yes */
rc = SysMkDir(svdir) /* Create directory v3.03b */
If rc<>0 then /* Problem? */
Do
Call Dosay 'SysMkDir error, RC 'rc svdir
Signal GenTargetDirDone /* Yes, bail out */
End
Call Dosay 'Target directory 'svdir' created.'
End
Else /* Nope, nested directories */
Do /* else do */
savedrive=Filespec('DRIVE',svdir) /* Drive for save target */
savepath =Filespec('PATH',svdir) /* Path for save target */
Do j=2 to length(savepath) /* Skip lead backslash */
If substr(savepath,j,1)='\' then /* Find next backslash */
Do /* Got one */
testdir=savedrive||substr(savepath,1,j-1) /* Dir to create */
If translate(Directory(testdir))<>translate(testdir) then
Do /* It's not there */
rc = SysMkDir(testdir) /* Create directory v3.03b */
If rc<>0 then /* Problem? */
Do
Call Dosay 'SysMkDir error, RC 'rc testdir
Signal GenTargetDirDone /* Yes, bail out */
End
Call Dosay 'Target directory 'testdir' created.'
End
End
End /* j */
End /* of else do */
End /* of outer do */
rc=lineout(robolog,copies('=',80)) /* Test log accessibility */
If rc<>0 then
Do
say 'Error writing to log:' robolog
Signal GenTargetDirDone
End
GenTargetDirDone:
rc1=rc
y=Directory(savedrive_currdir) /* v3.02 */
x=Directory(curdir) /* Back to orig dir */
Return rc1
/*****************************************************************************/
/* Place additional debug information in the log file. */
/* OS/2 version */
/* Selected OS/2 environment values */
/* Selected module information v3.02 */
/*****************************************************************************/
GenDebugInfo: Procedure expose boot lognum log. rscopyx robosavex
Call Dosay 'OS/2 version' SysOS2Ver() /* Display OS/2 version */
check=boot'\OS2KRNL', /* Get data for the modules in this list */
boot'\OS2\CMD.EXE',
boot'\OS2\DLL\PMWP.DLL',
boot'\OS2\DLL\REXXUTIL.DLL',
rscopyx, /* ROBOSVUT.EXE */
robosavex /* ROBOSAVE.CMD */
Do j=1 to words(check)
file=word(check,j) /* File to locate */
rc=SysFileTree( file , sfile ,'F' ) /* Get its file info */
If rc<>0 then
Call Dosay 'SysFileTree error, RC 'rc' ==> 'file
Else
Do
If sfile.0=0 then /* Was it found? */
Call Dosay '***' file 'not found.'
Else
Call Dosay ' ' sfile.1
End
End
Call Dosay 'USER_INI='value('USER_INI',,'OS2ENVIRONMENT')
Call Dosay 'SYSTEM_INI='value('SYSTEM_INI',,'OS2ENVIRONMENT')
Call Dosay 'OS2_SHELL='value('OS2_SHELL',,'OS2ENVIRONMENT')
Call Dosay 'RUNWORKPLACE='value('RUNWORKPLACE',,'OS2ENVIRONMENT')
Call Dosay
Return
/*****************************************************************************/
/* Set up the commands for ROBOREST.CMD to erase the current Desktop. v2.14 */
/*****************************************************************************/
MakeEraseDTP: Procedure Expose headnum head. svdir dtp boot /* v3.02 */
/* v3.02 */
headnum=headnum+1
parse value SysOS2Ver() with major '.' minor . /* v3.02 */
OS2_version = major*10 || '.' || left(minor,2,'0') /* v3.02 */
/* v3.02 */
head.headnum=svdir'ROBOSVUT ERASE_DESKTOP "'dtp'"' boot OS2_version
headnum=headnum+1
head.headnum='IF ERRORLEVEL 200 GOTO END'
headnum=headnum+1
head.headnum='IF ERRORLEVEL 199 GOTO CONTINUE'
headnum=headnum+1
head.headnum='IF ERRORLEVEL 0 GOTO END'
headnum=headnum+1
head.headnum=':CONTINUE'
headnum=headnum+1
head.headnum='@Echo Creating Desktop directory structure'
Return 0
/*****************************************************************************/
/* Get last filename used from marker file. Marker file was setup in the */
/* ReadPro sub-routine and points to the save directory. 0 if not found. */
/*****************************************************************************/
GetMarker: Procedure expose marker ismarker lastname lognum log.
rc=SysFileTree( marker , sfile ,'F' ) /* Get its file info */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'marker
Signal GetMarkerDone
End
If sfile.0>0 then /* Was it found? */
Do
ismarker=1
x=linein(marker,1,0) /* Open to record 1 */
lastname=linein(marker) /* Read a record */
x=lineout(marker) /* Close the file */
If lastname=''|datatype(lastname,'W')=0 then
lastname=0 /* In case empty or invalid file */
End
Else
Do
lastname=0
ismarker=0
End
GetMarkerDone:
Return rc
/*****************************************************************************/
/* Check for existing ROBOREST.CMD. If there move any existing CMn files */
/* down one slot. If all filled then delete the oldest and all files it */
/* points to. Rename others downward and rename CMD to CM1. */
/* */
/* Always start with the maximum supported number of 8 (totals 9 including */
/* CMD). This allows us to cleanup older sets if the user reduces the */
/* savenum var. */
/*****************************************************************************/
ProcessRcmd: Procedure expose roborest savenum svdir lognum log.,
boot /* v3.01 */
eaut_cmd=boot||'\OS2\EAUTIL' /* v3.01 */
rc=SysFileTree( roborest , sfile ,'F' ) /* Get its file info */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'roborest
Signal ProcessRcmdDone
End
If sfile.0>0 then /* Was it found? */
Do /* outer do */
todo='D 1 2 3 4 5 6 7 8' /* Extension suffixes to process */
Do j=words(todo) to 1 by -1 /* Works from oldest to newest */
tmp=svdir||'ROBOREST.CM'word(todo,j)
rc=SysFileTree( tmp , sfile , 'F')
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'tmp
Signal ProcessRcmdDone
End
If sfile.0>0 then /* Does it exist? */
If j>=savenum then /* Exceeds or equals max allowed? */
Do /* j>=savenum */
Call Dosay 'Deleting files pointed to by 'tmp
x=linein(tmp,1,0) /* Open to record 1 */
Do forever /* Till we run out of data */
input=linein(tmp) /* Read a record */
If input=='' then /* NULL (EOF)? */
Leave /* Yes, done */
Parse value input with cmd '"'part1'"' '"'part2'"'
Select
When cmd='COPY' then /* COPY entry? */
Call SysFileDelete part1
When cmd=eaut_cmd then /* EAUTIL entry? */ /* v3.01 */
Call SysFileDelete part2
Otherwise /* Neither, ignore it */
Iterate
End
End /* forever */
x=lineout(tmp) /* Close the file */
Call Dosay 'Deleting 'tmp
Call SysFileDelete tmp
Iterate j
End /* of j>= savenum */
Else /* Not max allowed, rename downward to make room */
Do
tmp1='ROBOREST.CM'||word(todo,j+1)
Call Dosay 'Renaming 'tmp' to 'tmp1
'@REN 'tmp tmp1
End
End /* j */
End /* of outer do */
ProcessRcmdDone:
Return rc
/*****************************************************************************/
/* Now process the head. entries which are REM statements to identify which */
/* run this ROBOREST.CMD file is associated with. Has date/time and */
/* VOLUME/LABEL of target drive. */
/*****************************************************************************/
GenHdr: Procedure expose roborest headnum head. lognum log.
rc=0
Call Dosay 'Creating 'roborest
x=lineout(roborest,,1) /* Open output file */
Do r=1 to headnum
rc=lineout(roborest,head.r)
If rc<>0 then
Do
Call Dosay 'Error writing 'roborest', RC 'rc
Leave r
End
End
Return rc
/*****************************************************************************/
/* Now process the ifnot.n entries which are IF NOT EXIST statements that if */
/* true will do a MD of the missing directory. 'ifnotrest' has the number of */
/* desktop directories processed for which there will be IF NOT records. */
/*****************************************************************************/
ProcessIfnot: Procedure expose roborest ifnotrest ifnot. lognum log.
rc=0
Do r=1 to ifnotrest /* Create any missing Directories first */
rc=lineout(roborest,ifnot.r)
If rc<>0 then
Do
Call Dosay 'Error writing 'roborest', RC 'rc
Leave r
End
End
Return rc
/*****************************************************************************/
/* Now process the copyfile.n entries which are the COPY calls. 'copyrest' */
/* has the number of files to copy. */
/* */
/* For COPY records, need to see if there is an attrib.copyrest record to go */
/* with it. If yes, write the ATTRIB record, the COPY record, then another */
/* ATTRIB record to reverse the results of the previous ATTRIB command. */
/*****************************************************************************/
ProcessCrest: Procedure expose copyrest attrib. roborest copyfile.,
log. lognum boot
os2ini=boot||'\OS2\OS2.INI' /* v3.00c */
os2sysini=boot||'\OS2\OS2SYS.INI' /* v3.00c */
rc=0
Do r=1 to copyrest /* Do the COPY statements next */
Parse value copyfile.r with . '"'.'"' '"'ctrg'"' .
If attrib.r<>'' then
Do /* if */
Parse value attrib.r with cmd '"'part1'"' atts
rc=lineout(roborest,'@ECHO Attrib === "'part1'"' atts)
rc=lineout(roborest,attrib.r) /* Turn off System/Hidden/Read Only */
If rc<>0 then
Do
Call Dosay 'Error writing 'roborest', RC 'rc
Leave r
End
rc=lineout(roborest,'@ECHO Restore === "'ctrg'"')
rc=lineout(roborest,copyfile.r) /* Add COPY record */
If rc<>0 then
Do
Call Dosay 'Error writing 'roborest', RC 'rc
Leave r
End
/* Don't set any attributes for OS2.INI and OS2SYS.INI v3.00c */
If translate(part1)<>os2ini & translate(part1)<>os2sysini then
Do
atts=translate(atts,'+','-') /* Reverse - to + */
rc=lineout(roborest,'@ECHO Attrib === "'part1'"' atts)
rc=lineout(roborest,cmd '"'part1'"' atts) /* 2nd ATTRIB command */
End
If rc<>0 then
Do
Call Dosay 'Error writing 'roborest', RC 'rc
Leave r
End
End /* of if */
Else
Do
rc=lineout(roborest,'@ECHO Restore === "'ctrg'"')
rc=lineout(roborest,copyfile.r)
If rc<>0 then
Do
Call Dosay 'Error writing 'roborest', RC 'rc
Leave r
End
End
End /* r */
Return rc
/*****************************************************************************/
/* Now process the echo.n entries which are the ECHO calls to create files */
/* with a size of 0. echorest has the number to create. */
/*****************************************************************************/
ProcessErest: Procedure expose echorest roborest echo. log. lognum
rc=0
Do r=1 to echorest
Parse value echo.r with . '>' . '>' part1
rc=lineout(roborest,'@ECHO Create === 'part1)
rc=lineout(roborest,echo.r)
If rc<>0 then
Do
Call Dosay 'Error writing 'roborest', RC 'rc
Leave r
End
End
Return rc
/*****************************************************************************/
/* Last we process the eautdir.n entries which are the EAUTIL calls. */
/* 'eautrest' has the number of EAUTIL cmds issued. */
/*****************************************************************************/
ProcessEaut: Procedure expose eautrest eautdir. roborest log. lognum
rc=0
Do r=1 to eautrest /* and finally the EAUTIL statements */
Parse value eautdir.r with . '"'part1'"' .
rc=lineout(roborest,'@ECHO Join EA === "'part1'"')
rc=lineout(roborest,eautdir.r)
If rc<>0 then
Do
Call Dosay 'Error writing 'roborest', RC 'rc
Leave r
End
End
If rc=0 then /* v2.14 */
Do /* v2.14 */
rc=lineout(roborest,":END") /* v2.14 */
If rc<>0 then Call Dosay 'Error writing 'roborest', RC 'rc /* v2.14 */
End /* v2.14 */
rc1=rc
x=lineout(roborest) /* Close the file */
Return rc1
/*****************************************************************************/
/* Save Extended Attributes (EA) for the Desktop, including the root and all */
/* sub-directories using */
/* EAUTIL source target /P /S */
/* */
/* Also need to handle the Templates folder which contains real files that */
/* take up disk space. Make this generic so anything new in the future will */
/* be handled. Do this by scanning for files in each of the directories. Any */
/* found add to 'robodir' which is the list of files found in the Desktop */
/* directory structure that need to be processed in the FileSave routine. */
/* */
/* Also build the IF NOT records to recreate desktop directories that may be */
/* missing during the restore process. */
/*****************************************************************************/
SaveEA: Procedure expose svdir hit dtp ifnotrest ifnot. eautrest eautdir.,
robodir lastname lognum log. echorest echo. boot /* v2.14 */
hit=0 /* Total num of dirs/files processed (includes anchor) */
rc=SysFileTree( dtp||'\*.*' , dtpdir ,'SDO' ) /* All sub-dirs under Desktop */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc'==>'dtp
Signal SaveEADone
End
If dtpdir.0=0 then /* Was it found? */
Do
Call Dosay 'No subdirectories found under 'dtp
Call Dosay 'This is an impossible situation, please investigate.'
rc=1
Signal SaveEADone
End
numdirs=dtpdir.0 /* Move to working directory counter */
dtpdir.0=dtp /* Make 1st one the Desktop anchor */
Call Dosay 'Starting Desktop EA save to 'svdir
robodir='' /* Files in Desktop structure to save via COPY */
Do j=0 while j<=numdirs /* Start with Desktop anchor directory */
source=dtpdir.j /* Source file to work with */
/***************************************************************************/
/* Now check for files in this Desktop directory. Add to robodir var if */
/* found for file save later. */
/***************************************************************************/
src=source||'\*.*'
rc=SysFileTree( src , sfile ,'FT' ) /* See if any files in directory */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'source
Signal SaveEADone
End
Do fp=1 to sfile.0 /* Process each file found in directory */
Parse value sfile.fp with sdate ssize satt src /* File attributes */
src=strip(src,'B') /* Get rid of any trash */
/*************************************************************************/
/* Check filesize. If 0 create an echo. record to recreate on restore by */
/* redirect STDERR to file so it will be a null file (size 0). Also add */
/* to 'echosrc' var so EAs for the file will be saved. Otherwise just */
/* add to robodir for later copy. */
/*************************************************************************/
If ssize=0 then /* 0 size file? */
Do
Call Dosay 'ECHO ==> 'src' <.>' /* v3.02 */
echorest=echorest+1 /* Bump echo counter */
echo.echorest='ECHO >NUL 2>"'src'"' /* Build ECHO record */
echosrc.echorest=src /* Add to EA save list for 0 size files */
End
Else
robodir=robodir translate(src,'00'x,' ') /* No, add to COPY list */
End /* fp */
/***************************************************************************/
/* Start with last used name+1 to pick an unused name in the target dir. */
/***************************************************************************/
Do forever /* Till we find an unused filename.ext */
lastname=lastname+1
filename=right(lastname,8,'0')||.'EAS'
ttarg=svdir||filename /* Fully qualified target */
rc=SysFileTree( ttarg , tfile , 'F' )
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'ttarg
Signal SaveEADone
End
If tfile.0=0 then /* File exists? */
Leave /* No, done */
End /* forever */
target=ttarg
Call Dosay 'EAUTIL ==> 'source' <'target'>' /* v3.02 */
If DoEautil(1)<>0 then
Signal SaveEADone
End /* while */
/*****************************************************************************/
/* Now process any echo. entries generated (file size=0 files). */
/*****************************************************************************/
Do j=1 to echorest
source=echosrc.j
Do forever /* Till we find an unused filename.ext */
lastname=lastname+1
filename=right(lastname,8,'0')||.'EAS'
ttarg=svdir||filename /* Fully qualified target */
rc=SysFileTree( ttarg , tfile , 'F' )
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'ttarg
Signal SaveEADone
End
If tfile.0=0 then /* File exists? */
Leave /* No, done */
End /* forever */
target=ttarg
Call Dosay 'EAUTIL ==> 'source' <'target'>' /* v3.02 */
If DoEautil(0)<>0 then /* Run EAUTIL, no MD statement */
Signal SaveEADone
End /* j */
SaveEADone:
Return rc
/*****************************************************************************/
/* Run EAUTIL /P /S to create a copy of the EAs for the directory being */
/* processed. /P will preserve the EAs attached to the directory. /S will */
/* copy (split) them off to the target. */
/* */
/* Check the target file to make sure it was created. Only then do we add a */
/* eautdir. record. If target does not exist place entry in log file and */
/* continue, not an error. Note that we always create an IF NOT record for */
/* directories. */
/* */
/* Var 'ifnotrest' contains number of IF NOT commands needed for same. */
/* Var 'eautrest' contains the number of EAUTIL commands needed for ROBOREST.*/
/*****************************************************************************/
DoEautil:
Arg make_directory . /* 0=no MD, 1=MD */
eaut_cmd=boot||'\OS2\EAUTIL' /* v2.14 */
rc=0
'@EAUTIL "'source'"' '"'target'" /P /S'
If rc>0 then
Do
If rc=1 then
Call Dosay 'Not found ==> 'source
Else
Call Dosay 'EAUTIL processing error, RC 'rc
End
Else /* EAUTIL returned RC=0 */
Do
rc=SysFileTree( target, efile , 'F' ) /* See if target file created */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'target
Signal DoEautilDone
End
hit=hit+1 /* All is well, bump saved count */
If make_directory then /* Directory of file? */
Do
ifnotrest=ifnotrest+1
ifnot.ifnotrest='IF NOT EXIST "'source'" MD "'source'"'
End
If efile.0=0 then /* File exists? */
Call Dosay 'No EA ==> 'source /* No, place entry in log */
Else
Do /* Yes, need EAUTIL command */
eautrest=eautrest+1 /* Bump restore counter */
eautdir.eautrest=eaut_cmd '"'source'"' '"'target'" /P /J /O'/* v2.14 */
End
End
DoEautilDone:
Return rc
/*****************************************************************************/
/* Save files to target directory. Translate all '00'x to blanks to support */
/* HPFS directory names. */
/* */
/* Note that the source file can have any of the normal substitution chars */
/* so more than one file may be returned from SysFileTree therefore all have */
/* to be processed. */
/*****************************************************************************/
FileSave: Procedure expose svdir robo hit boot copyrest copyfile.,
robodir lastname attrib. lognum log. rscopyx /* v3.02 */
hit=0
Call Dosay 'Starting file save to 'svdir
os2ini=boot||'\OS2\OS2.INI' /* Require special handling */
os2sysini=boot||'\OS2\OS2SYS.INI' /* Ditto */
/*****************************************************************************/
/* 1st we save any files found in the Desktop directory structure during the */
/* EA save process. Convert any '00'x to blanks. Any error or file not found */
/* will terminate. */
/*****************************************************************************/
Do j=1 to words(robodir)
source=translate(word(robodir,j),' ','00'x) /* Pick file. Remove '00'x */
rc=SysFileTree( source , sfile ,'FT' ) /* Get its file info */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'source
Signal FileSaveDone
End
If sfile.0=0 then /* Was it found? */
Do
Call Dosay 'Not found ==> 'source
rc=1
Signal FileSaveDone
End
If DoSave()<>0 then
Signal FileSaveDone
End /* j for robodir */
/*****************************************************************************/
/* Now we save all files from robo=lines in the profile plus any passed as */
/* parms on the command line. Use COPY for all except OS2.INI and OS2SYS.INI */
/* then use ROBOSVUT since they are locked (in use) files (also use ROBOSVUT */
/* if copy fails). */
/* */
/* Files not found will be logged but processing continues. */
/* Translate all '00'x to blanks at start. */
/* */
/* One special case to handle. [d:\path\filename.ext]. The brackets mean to */
/* search the specified directory and all subdirectories for all cases of */
/* the specified filename.ext. As in the normal case, all wildcards are */
/* allowed. */
/*****************************************************************************/
Do j=1 to words(robo)
source=translate(word(robo,j),' ','00'x) /* Pick a file. Remove '00'x */
If substr(source,1,1)='[' then /* All subdirs format? */
Do /* Yes */
source=substr(source,2,length(source)-2) /* Remove brackets */
Call Dosay 'Scanning ==> 'source
rc=SysFileTree( source , sfile ,'FST' ) /* Get info from all subdirs */
End
Else
rc=SysFileTree( source , sfile ,'FT' ) /* Get its file info */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'source
Signal FileSaveDone
End
If sfile.0=0 then /* Was it found? */
Do
Call Dosay 'Not found ==> 'source
Iterate j
End
If DoSave()<>0 then
Signal FileSaveDone
End /* j for robo */
/*****************************************************************************/
/* Place a copy of ROBOSVUT.EXE in the target directory. This will be used */
/* by ROBOREST.CMD to delete the Desktop directory tree. v2.14 */
/*****************************************************************************/
src = rscopyx /* v3.02 */
target = svdir'ROBOSVUT.EXE'
Call Dosay 'COPY ==> 'src' <'target'>'
'@COPY "'src'"' '"'target'"' '/F /V > NUL' /* Put on target dir */
If rc<>0 then
Do
Call Dosay 'COPY error, RC 'rc src target
Call Dosay 'Manually place a copy of 'src' in 'svdir
rc=0 /* Force good rc to continue */
End
FileSaveDone:
Return rc
/*****************************************************************************/
/* Normally use COPY to copy source to target. If this fails then try */
/* ROBOSVUT. */
/* */
/* ROBOSVUT will be used for OS2.INI and OS2SYS.INI at all times since they */
/* are locked (in use) files. */
/* */
/* Use similar naming convention as EAs, nnnnnnnn.FIL to maintain the FAT */
/* 8.3 form. */
/* */
/* Check source file attributes. If S (System), H (hidden) or R (read only) */
/* then build an attrib.copyrest record with appropriate -S -H -R parms. */
/* */
/* OS2.INI and OS2SYS.INI need to be cleaned up to remove autostart of all */
/* restart objects to prevent ROBOSAVE from autostart on first boot after */
/* ROBOREST has been run. The S, H, and R attributes are forced off. v3.03 */
/*****************************************************************************/
DoSave:
attr_cmd=boot||'\OS2\ATTRIB' /* v2.14 */
rc=0
Do fp=1 to sfile.0 /* Process each file found that matched filespec */
Parse value sfile.fp with sdate ssize satt src /* File attributes */
src=strip(src,'B') /* Get rid of any trash */
If translate(src)=os2ini | translate(src)=os2sysini then
howcopy='ROBOSVUT'
Else
howcopy='COPY'
Do forever /* Till we find a unused filename.ext on the target dir */
lastname=lastname+1 /* Bump last used filename by 1 */
filename=right(lastname,8,'0') /* Build the actual filename */
target=svdir||filename'.FIL' /* Complete filespec */
rc=SysFileTree( target , tfile , 'FT' ) /* Target info */
If rc<>0 then
Do
Call Dosay 'SysFileTree Error ==> RC 'rc target
Signal DoSaveDone
End
If tfile.0=0 then /* Existing backup? */
Leave /* No, done */
End /* forever */
If verify(satt,'-AR') > 0 then howcopy ='ROBOSVUT' /* v3.03 */
Call Dosay left(howcopy,8)' ==> 'src' <'target'>' /* v3.02 */
If verify(satt,'-A') > 0 then /* v3.03 */
Call DoSay ' Current file attributes: ' satt /* v3.03 */
If howcopy='ROBOSVUT' then
Do /* v2.14 */
/* Save source in target */
'@'rscopyx '"'src'"' '"'target'" /A /V' /* v3.03b */
If rc=100 Then rc=0 /* v2.14 */
End /* v2.14 */
Else
Do
'@COPY' '"'src'"' '"'target'" /F /V' '> NUL' /* Save source in target */
If rc<>0 then
Do
Call Dosay 'Failed ==> RC 'rc', will try ROBOSVUT'
howcopy='ROBOSVUT'
Call Dosay left(howcopy,8)' ==> 'src' <'target'>' /* v3.02 */
/* Save source in target */
'@'rscopyx '"'src'"' '"'target'" /A /V' /* v3.03b */
If rc=100 Then rc=0 /* v2.14 */
End
End
If rc=0 then
Do /* rc=0 */
hit=hit+1 /* Bump saved count */
copyrest=copyrest+1 /* Bump restore counter */
copyfile.copyrest='COPY "'target'"' '"'src'" /F /V > NUL'
atts='' /* Check for source being System, Hidden or Read Only */
If pos('S',satt)>0 then
atts=atts '-S'
If pos('H',satt)>0 then
atts=atts '-H'
If pos('R',satt)>0 then
atts=atts '-R'
If atts<>'' then
attrib.copyrest=attr_cmd '"'src'"' atts /* v2.14 */
Else
attrib.copyrest=''
If translate(src)=os2ini then
Do
attrib.copyrest=attr_cmd '"'src'" -R -S -H' /* v3.03 */
Call SysIni target, 'PM_WorkPlace:Restart', 'DELETE:';
If result<>'ERROR:' then
Call Dosay 'Cleanup ==> PM_WorkPlace:Restart <.>' /* v3.02 */
End
If translate(src)=os2sysini then
Do
attrib.copyrest=attr_cmd '"'src'" -R -S -H' /* v3.03 */
Call SysIni target, 'FolderWorkareaRunningObjects', 'DELETE:';
If result<>'ERROR:' then
Call Dosay 'Cleanup ==> FolderWorkareaRunningObjects <.>'
End /* v3.02 */
End /* rc=0 */
Else
Do
Call Dosay howcopy 'error, RC 'rc
Signal DoSaveDone
End
End /* fp */
DoSaveDone:
Return rc
/*****************************************************************************/
/* Display data to screen and build entry for the log file. Note that log */
/* entry can be larger than screen data. Any data enclosed in < > is for the */
/* log file only. v3.02 */
/*****************************************************************************/
Dosay: Procedure expose lognum log. svdir
Parse arg saydata '<'tgt'>' 1 verb . '==>' src '<' .
Say saydata
lognum=lognum+1
If tgt<>'' then Select
When verb='COPY' | verb='ROBOSVUT' | verb='EAUTIL' then
Do
leftside=length(svdir'nnnnnnnn.EAS')
log.lognum=left(tgt,leftside) 'via' left(verb,8) 'from' src
End
When verb='ECHO' then
Do
leftside=length(svdir'nnnnnnnn.EAS via EAUTIL from')
log.lognum=right('ECHO will create null file for',leftside) src
End
When verb='Cleanup' then
log.lognum=' 'src'deleted' /* v3.03 */
Otherwise
log.lognum=saydata tgt
End /* select */
Else log.lognum=saydata
Return
/*****************************************************************************/
/* Make sure ROBOSVUT.EXE is available in PATH before doing anything else. */
/* Process user profile (ROBOSAVE.PRO) which can be anywhere in PATH or in */
/* current directory. Can also be specified via /p=d:\path as a parameter on */
/* the invocation with or without a different filename.ext. */
/* */
/* Cannot have ANY blank lines. * in col 1 is a comment record. */
/* */
/* 'save=' identifies the drive\path where you want backup files placed */
/* <REQUIRED> */
/* 'savenum=' number of incremental backups of files and EAs to keep */
/* <REQUIRED> */
/* 'log=' T to place log in target directory. P to place in directory */
/* profile was found in. If not specified defaults to P. */
/* 'cleanup=' control when cleanup of existing saved files occurs. */
/* cleanup=B to do at beginning of run. */
/* cleanup=E to do at end of run (default). */
/* 'robo=' fully qualified files to backup, as many robo= lines as needed */
/* full wildcard support of * and ?. Enclose in double quotes if */
/* file contains blanks. */
/* */
/* /P=d:\path can be specified on invocation to point to the location of */
/* ROBOSAVE.PRO or the fully qualified path (including filename.ext) if the */
/* filename or ext has been changed (/p=d:\path\filename.ext). If not then */
/* search the current directory and path for ROBOSAVE.PRO. */
/* */
/* Setup ROBOSAVE.LOG based on the log= entry. Default to directory profile */
/* found in if not specified. */
/*****************************************************************************/
ReadPro: Procedure expose ver svdir savenum robo op. robolog lognum log.,
roborest marker cleanup roboparm head. headnum rscopyx /* v3.02 */
Parse value 'ROBOSAVE.PRO' with profile svdir savenum robo robolog cleanup .
rscopyx = SysSearchPath('PATH','ROBOSVUT.EXE') /* v3.02 */
If rscopyx = '' then /* Make sure ROBOSVUT available */ /* v3.02 */
Do
Say 'ROBOSVUT.EXE not found in current directory or via PATH.'
Say 'This is a required file.'
rc=1
Signal ReadProDone
End
prf=''
rc=0
Do j=1 to 2
Select
When op.j='' then
Iterate j
When left(op.j,2)='P=' then /* Was profile specified? */
Do /* P= */
If right(op.j,1)='\' then /* Trailing /? */
profile=substr(op.j,3)||'ROBOSAVE.PRO' /* Yes, tack on profile */
Else /* No, may be a d:\path\filename.ext, check for it */
Do
profile=strip(substr(op.j,3),'B')
rc=SysFileTree( profile , sfile ,'F' ) /* See if file exists */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'profile
rc=1
Signal ReadProDone
End
If sfile.0=0 then /* Was it found? */
profile=substr(op.j,3)||'\ROBOSAVE.PRO' /* No, add \profile */
End
rc=SysFileTree( profile , sfile ,'F' ) /* See if it exists */
If rc<>0 then
Do
Call Dosay 'SysFileTree error, RC 'rc' ==> 'profile
rc=1
Signal ReadProDone
End
If sfile.0>0 then /* Was it found? */
prf=profile
Else
Do
Call Dosay 'Cannot locate' profile
rc=1
Signal ReadProDone
End
End /* P= */
Otherwise
Do
Call Dosay 'Invalid parameter entered on command line 'op.j
rc=1
Signal ReadProDone
End
End /* Select */
End /* j */
If prf='' then /* No */
prf=SysSearchPath('PATH',profile) /* See if profile exists in path */
If prf='' then
Do
Say 'Profile 'profile' not found in current directory, or via PATH, or in'
Say 'location specified via /P= parameter. This is a required file.'
rc=1
Signal ReadProDone
End
Else
profile=prf
timestamp = 'Saved on ' date('O') time() ' by ROBOSAVE version' ver
headnum=headnum+1
head.headnum='@ECHO OFF'
headnum=headnum+1
head.headnum='Rem' timestamp
Call Dosay timestamp
Call Dosay 'Reading' profile
x=linein(profile,1,0) /* Open to 1st record of file */
If roboparm<>'' then /* Treat roboparm as line 0 */
input="robo="roboparm
Else
input="*"
Do r=0 by 1 /* Process all profile lines */
If r>0 then input=linein(profile) /* Read next line */
If input='' then /* Null then we're done */
Leave
If left(input,1)='*' then /* Comment? */
Iterate r
Parse value input with verb'='data /* Got one, parse it out */
If verb='' then /* Right format? */
Do
Call Dosay profile' line 'r' invalid format.'
Call Dosay input
rc=2
Signal ReadProDone
End
If data='' then
Do
Call Dosay profile' line 'r' missing data after keyword.'
Call Dosay input
rc=2
Signal ReadProDone
End
verb=translate(verb) /* Yes, upper case it */
Select
When verb='SAVE' then
svdir=translate(strip(data,'B')) /* Force upper case */
When verb='SAVENUM' then
Do
savenum=strip(data,'B')
If datatype(savenum,'W')=0 | savenum<1 | savenum>9 then
Do
Call Dosay '"savenum" variable ('savenum') invalid, must be 1 to 9.'
rc=2
Signal ReadProDone
End
End
When verb='ROBO' then
Do /* Need to process for quoted names that contain blanks */
data=strip(data,'B')' ' /* Add a space as the final word delimiter */
hold='' /* Holds current file being assembled */
qt=0 /* Indicates a " has been found */
If r=0 then /* Set up error message text */
lineloc="command line parameter"
Else
lineloc=profile "line" r
Do j=1 to length(data)
If substr(data,j,1)=' ' then /* End or word or blank in name? */
Do /* data */
If qt then /* Processing a quoted file? */
hold=hold||' ' /* Yes, add to file being processed then */
Else /* No, end of a filename */
Do /* Check for bracketed case */
If left(hold,1)='[' & right(hold,1)<>']' then
Do
Call Dosay 'Missing ] or " in' lineloc
rc=2
Signal ReadProDone
End
robo=robo translate(hold,'00'x,' ') /* Blanks to '00'x */
hold=''
End
Iterate j
End /* data */
If substr(data,j,1)='"' then /* Double quote mark? */
If qt then /* Yes, previous pending? */
Do /* Yes, end of a quoted file then */
If left(hold,1)='[' & right(hold,1)<>']' then
Do
Call Dosay 'Missing ] or " in' lineloc
rc=2
Signal ReadProDone
End
robo=robo translate(hold,'00'x,' ') /* Blanks to '00'x */
hold=''
qt=0
Iterate j
End /* qt */
Else /* No, start of a quoted file then */
qt=1
Else /* Just add to file being built */
hold=hold||substr(data,j,1)
End /* j */
If qt then /* Premature end? */
Do
Call Dosay 'Unbalanced " in' lineloc
rc=2
Signal ReadProDone
End
End /* robo= */
When verb='LOG' then /* Location of log file specified? */
robolog=translate(strip(data,'B'))
When verb='CLEANUP' then
Do
cleanup=translate(strip(data,'B'))
If cleanup<>'E' & cleanup<>'B' then
Do
Call Dosay '"cleanup" variable ('cleanup') invalid, must be B or E.'
rc=2
Signal ReadProDone
End
End
Otherwise
Do
Call Dosay profile' line 'r' has invalid keyword.'
Call Dosay input
rc=2
Signal ReadProDone
End
End /* Select for verbs */
End /* r */
x=lineout(profile) /* Close the file */
If svdir='' | savenum='' | robo='' then /* Check required parms */
Do
Call Dosay 'Invalid 'profile', missing "save=, savenum= or robo=" entry.'
rc=2
Signal ReadProDone
End
If substr(svdir,2,1)<>':' then /* Drive specified as part of save path? */
Do
Call Dosay '"save" variable ('svdir') invalid, drive not specified.'
rc=2
Signal ReadProDone
End
If datatype(substr(svdir,1,1),'M')<>1 then
Do
Call Dosay '"save" variable ('svdir') invalid, drive not A to Z.'
rc=2
Signal ReadProDone
End
If right(svdir,1)<>'\' then /* Trailing backslash last char? */
svdir=svdir||'\' /* No, add it */
Select
When robolog='T' then /* Wants log in save directory? */
robolog=svdir||'ROBOSAVE.LOG'
When robolog=''|robolog='P' then /* No, default to profile directory */
robolog=Filespec('DRIVE',profile)||Filespec('PATH',profile)||'ROBOSAVE.LOG'
Otherwise
Do
Call Dosay '"log" variable ('robolog') invalid. P or T only.'
rc=2
Signal ReadProDone
End
End
If cleanup='' then /* Default to cleanup at end if not specified */
cleanup='E'
roborest=svdir||'ROBOREST.CMD' /* Restore CMD file */
marker=svdir||'ROBOSAVE.MRK' /* Contains last filename used */
ReadProDone:
Return rc
/*****************************************************************************/
/* Display help */
/*****************************************************************************/
Tell:
Say 'This version of ROBOSAVE is valid only for OS/2 2.0 GA and later.'
Say
Say 'ROBOSAVE <parm> <op1>'
Say ' "parm" can be fully qualified name(s) of one or more files to save.'
Say ' These names are appended to data from robo= lines in the profile.'
Say ' "op1" can be'
say ' "/p=d:\path", where "d:\path" specifies the path to a specific'
Say ' ROBOSAVE.PRO file, or "op1" can be'
Say ' "/p=d:\path\filename.ext" if your profile is not ROBOSAVE.PRO.'
Say
Say 'Examples:'
Say ' 1 ROBOSAVE -> saves files and Desktop EAs'
Say ' 2 ROBOSAVE d:\os2\my.dat -> saves this file plus robo= files'
Say ' 3 ROBOSAVE d:\a.a d:\b.b -> saves these two files plus robo= files'
Say ' 4 ROBOSAVE /P=e:\ -> same as 1 but uses E:\ROBOSAVE.PRO'
Say ' 5 ROBOSAVE /P=e:\my1.pro -> same as 1 but uses E:\MY1.PRO'
Say
'@PAUSE'
Say 'All activity is recorded in ROBOSAVE.LOG. The default is to write to',
'the same'
Say 'directory where the profile was found. You can override this with the',
'"log="'
Say 'entry in your profile. ROBOREST.CMD will contain all the commands',
'necessary'
Say 'to restore your desktop. For details of ROBOSAVE operation, you',
'can issue'
Say '"VIEW ROBOSAVE"' "or read the ROBOSAVE User's Guide."
Return