home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 11 Util / 11-Util.zip / robosv.zip / ROBOSAVE.CMD < prev    next >
OS/2 REXX Batch file  |  1993-11-09  |  65KB  |  1,358 lines

  1. /*****************************************************************************/
  2. /* ROBOSAVE                                    by Dick Kurtz and Jeff Knauth */
  3. /*                                                                           */
  4. /* (c) Copyright International Business Machines Corporation 1994.           */
  5. /* All rights Reserved.                                                      */
  6. /*                                                                           */
  7. /* Saves files and Extended Attributes for Desktop for OS/2 2.x.             */
  8. /*                                                                           */
  9. /* Issue "ROBOSAVE ?" for some brief help.  For a detailed description see   */
  10. /* the ROBOSAVE User's Guide.                                                */
  11. /*****************************************************************************/
  12. '@Echo off'
  13. ver='3.04 1993/11/09'                           /* Version and creation date */
  14. parse source . . robosavex                                          /* v3.02 */
  15. Say 'ROBOSAVE v'ver' by Dick Kurtz and Jeff Knauth.'
  16. Say '(c) Copyright International Business Machines Corporation 1994.'
  17. Say 'All rights Reserved.'
  18. Say
  19.  
  20. Arg roboparm '/'op.1 . '/'op.2 .                           /* Get user parms */
  21. curdir=Directory()                                 /* Save current directory */
  22.  
  23. headnum=0                 /* Number of header lines to write to ROBOREST.CMD */
  24. pause='@PAUSE'             /* Allow user to see msgs until log file is setup */
  25. lognum=0                                         /* No log records built yet */
  26. If roboparm='?' | roboparm='-?' | op.1='?' | op.2='?' then
  27.   Do
  28.     Call Tell
  29.     tell=1                                                         /* v3.03b */
  30.     err=0
  31.     Signal Done1
  32.   End
  33. err=1             /* Assume something will go wrong (makes the code simpler) */
  34. tell=0            /* Indicate help was not invoked                    v3.03b */
  35.  
  36. /*****************************************************************************/
  37. /* Register all REXXUTIL functions                                           */
  38. /*****************************************************************************/
  39. rc=RxFuncAdd('SysLoadFuncs', 'REXXUTIL', 'SysLoadFuncs')
  40. If rc>1 then
  41.   Do
  42.     Call Dosay 'Unable to register REXXUTIL functions.'
  43.     Signal Done1
  44.   End
  45. Call SysLoadFuncs
  46.  
  47. If ReadPro()<>0 then                                 /* Process profile data */
  48.   Signal Done1                                       /* Bail out if problems */
  49. If FindBoot()<>0 then                                 /* Find the boot drive */
  50.   Signal Done1
  51. Call GetVolInfo                             /* Log volid and label of target */
  52. If LocateDesktop()<>0 then            /* Locate the Desktop anchor directory */
  53.   Signal Done1
  54. If GenTargetDir()<>0 then          /* Create target directories as necessary */
  55.   Signal Done1                                    /* Bail out if any problem */
  56.  
  57. pause=''                       /* Log is setup, no need to pause on exit now */
  58. Call GenDebugInfo          /* Record additional info for problem debug v3.02 */
  59. Call MakeEraseDTP        /* Set up the commands to erase the current Desktop */
  60.                                                                     /* v2.14 */
  61.  
  62. If GetMarker()<>0 then     /* Get last use fn from marker file in target dir */
  63.   Signal Done                                     /* Bail out if any problem */
  64.  
  65. /*****************************************************************************/
  66. /* See if user wants to cleanup at start of run. Risky but allowed.          */
  67. /*****************************************************************************/
  68. If cleanup='B' then                       /* Cleanup target at start of run? */
  69.   If ProcessRcmd()<>0 then             /* Handle existing ROBOREST.CMx files */
  70.     Signal Done
  71.  
  72.  
  73. /*****************************************************************************/
  74. /* Finally we start by saving EAs. Initialize the various output record      */
  75. /* counters.                                                                 */
  76. /*           ifnotrest =number of IF NOT records to write                    */
  77. /*            eautrest =number of EAUTIL records to write                    */
  78. /*            copyrest =number of COPY records to write                      */
  79. /*            echorest =number of ECHO records to write                      */
  80. /* Variable robodir will have any files found in any of the desktop directo- */
  81. /* ries that need to be copied in FileSave.                                  */
  82. /*****************************************************************************/
  83. Parse value '0 0 0 0' with ifnotrest eautrest copyrest echorest .
  84. If SaveEA()<>0 then
  85.   Signal Done
  86. Call Dosay 'Desktop EAs saved: 'hit
  87.  
  88. /*****************************************************************************/
  89. /* Now we save files. Those found in the Desktop directory structure, any    */
  90. /* contained in the profile and any specified on the CMD line call.          */
  91. /*****************************************************************************/
  92. If FileSave()<>0 then
  93.   Signal Done
  94. Call Dosay 'Files saved: 'hit
  95.  
  96. /*****************************************************************************/
  97. /* See if we need to cleanup now or did we already do it at start of run.    */
  98. /*****************************************************************************/
  99. If cleanup='E' then
  100.   If ProcessRcmd()<>0 then              /* Handle existing ROBOREST.CM files */
  101.     Signal Done
  102.  
  103. /*****************************************************************************/
  104. /* Now we create the new ROBOREST.CMD file.                                  */
  105. /*****************************************************************************/
  106. If Genhdr()<>0 then                               /* Header records go first */
  107.   Signal Done
  108. If ProcessIfnot()<>0 then                            /* Build IF NOT records */
  109.   Signal Done
  110. If ProcessCrest()<>0 then                                /* and COPY records */
  111.   Signal Done
  112. If ProcessErest()<>0 then                                /* and ECHO records */
  113.   Signal Done
  114. If ProcessEaut()<>0 then                               /* and EAUTIL records */
  115.   Signal Done
  116. err=0                                      /* How about that, it all worked! */
  117.  
  118. /*****************************************************************************/
  119. /* Only exit from program. If fall through for normal exit or signal to      */
  120. /* Done then write log. data to ROBOSAVE.LOG in the specified directory.     */
  121. /* If signal to Done1 then log file is not setup yet so can't write it.      */
  122. /* Make sure we're back at the starting directory and exit.                  */
  123. /*****************************************************************************/
  124. Done:
  125. Say 'Writing log file 'robolog
  126. Do j=1 to lognum
  127.   rc=lineout(robolog,log.j)
  128.   If rc<>0 then
  129.     Do
  130.       Say 'Error writing 'robolog', RC 'rc
  131.       err=1
  132.       pause='@PAUSE'
  133.       Leave j
  134.     End
  135. End
  136. If \err then                                                        /* v3.02 */
  137.   x=lineout(robolog,"ROBOSAVE completed normally")                  /* v3.02 */
  138. x=lineout(robolog)                                         /* Close the file */
  139.  
  140. If ismarker then                                       /* Marker file exist? */
  141.   Call SysFileDelete marker                                /* Yes, delete it */
  142. x=lineout(marker,lastname)                                /* Write a new one */
  143. x=lineout(marker)                                                /* Close it */
  144.  
  145. Done1:
  146. x=Directory(curdir)                          /* Put us back where we started */
  147. pause              /* Will pause if fail before log setup or log not written */
  148. If err then Do                                                      /* v3.02 */
  149.   Call Beep 512,300                                                 /* v3.02 */
  150.   Call Beep 256,500                                                 /* v3.02 */
  151.   Call Beep 200,400                                                 /* v3.02 */
  152.   Say                                                               /* v3.02 */
  153.   Say '*** ROBOSAVE has encountered an error. ***'                  /* v3.02 */
  154. End                                                                 /* v3.02 */
  155. Else
  156.   If \tell then Say 'ROBOSAVE completed normally.'                 /* v3.03b */
  157. Exit 0
  158.  
  159. /*****************************************************************************/
  160. /* Locate the boot drive via the location of COMSPEC environment var. Not a  */
  161. /* foolproof method but should work well enough until REXXUTIL provides a    */
  162. /* means of doing this correctly.                                            */
  163. /*****************************************************************************/
  164. FindBoot: Procedure expose boot lognum log. headnum head.
  165. rc=0
  166. env='OS2ENVIRONMENT'                                     /* Environment name */
  167. boot=Filespec("DRIVE",value('COMSPEC',,env))              /* Find Boot drive */
  168. If boot='' | length(boot)<>2 | right(boot,1)<>':' then
  169.   Do
  170.     Call Dosay 'Unable to locate your boot drive. This should be pointed to'
  171.     Call Dosay 'by the SET COMSPEC= entry in CONFIG.SYS. ROBOSAVE can not'
  172.     Call Dosay 'continue. Please check your CONFIG.SYS for the above entry.'
  173.     rc=1                                                /* Force tremination */
  174.   End
  175. Else
  176.   Do
  177.     l='Boot drive is 'boot
  178.     Call Dosay l
  179.     headnum=headnum+1                 /* Create header line for ROBOREST.CMD */
  180.     head.headnum='Rem' l
  181.   End
  182. Return rc
  183.  
  184. /*****************************************************************************/
  185. /* Get target volid and label (if any) and place in log (ASIS)               */
  186. /*****************************************************************************/
  187. GetVolInfo: Procedure expose svdir lognum log. headnum head.
  188. '@VOL 'left(svdir,2)' | RXQUEUE'
  189. Do queued()
  190.   Parse Pull data
  191.   If data<>'' then
  192.     Do
  193.       Call Dosay strip(data)
  194.       headnum=headnum+1                           /* Gen another header line */
  195.       head.headnum='Rem' strip(data)
  196.     End
  197. End
  198. Return
  199.  
  200. /****************************************************************************/
  201. /* Locate the active desktop.                                               */
  202. /*                                                                          */
  203. /* Extract all NODE entries from PM_Workplace:Handlesn (n=0 or 1) which is  */
  204. /* pointed to by PM_Workplace:ActiveHandles (SP or above) or                */
  205. /* PM_Workplace:Handles (GA).                                               */
  206. /*                                                                          */
  207. /* Get the 2 byte hex handle of <WP_DESKTOP> from PM_Workplace:Location of  */
  208. /* OS2.INI. Scan the nodes for a match (offset 7, length 2). When found     */
  209. /* save the name associated with the handle (offset 33 to end of node) and  */
  210. /* get the parent handle (offset 9, length 2). Restart scan from 1st node   */
  211. /* looking for the parent (offset 7, length 2). When found extract the drive*/
  212. /* (offset 33 length 2) and append \name found previously. This gives us    */
  213. /* the current desktop directory anchor.                                    */
  214. /****************************************************************************/
  215. LocateDesktop: Procedure Expose log. lognum dtp
  216. Call Dosay 'Locating Desktop directory'
  217. If Getnodes()<>0 Then
  218.   Do
  219.     rc=1
  220.     Signal LocateDesktopDone
  221.   End
  222. gpinode=(Substr(SysIni('USER','PM_Workplace:Location','<WP_DESKTOP>'),1,2))
  223. Parse value '' with gp dtp
  224. Do gpi=1 to nodes.0
  225.   If substr(nodes.gpi,7,2)=gpinode then
  226.     Do
  227.       gp=substr(nodes.gpi,33,length(nodes.gpi)-33)
  228.       gpparent=substr(nodes.gpi,9,2)
  229.       Do until gpparent='0000'x
  230.         Do gpl=1 to nodes.0
  231.           If substr(nodes.gpl,7,2)=gpparent Then
  232.             Do
  233.               gp=substr(nodes.gpl,33,length(nodes.gpl)-33)||'\'||gp
  234.               gpparent=substr(nodes.gpl,9,2)
  235.               Leave gpl
  236.             End
  237.         End
  238.       End
  239.       dtp=gp                                                      /* Got it */
  240.       Leave gpi
  241.     End
  242. End
  243. If dtp='' then
  244.   Do
  245.     Call Dosay 'Unable to locate your Desktop directory. This is a critical',
  246.       'failure.'
  247.     Call Dosay 'ROBOSAVE cannot continue.'
  248.     rc=1
  249.     Signal LocateDesktopDone
  250.   End
  251. Call Dosay 'Desktop directory is 'dtp
  252. rc=0
  253. LocateDesktopDone:
  254. Return rc
  255.  
  256. /*****************************************************************************/
  257. /* Get all the nodes. Fix to handle errors if DRIV/NODE pair not found.      */
  258. /*****************************************************************************/
  259. Getnodes: Procedure Expose nodes. log. lognum
  260. handlesapp=SysIni('SYSTEM','PM_Workplace:ActiveHandles','HandlesAppName')
  261. If handlesapp='ERROR:' then
  262.   handlesapp='PM_Workplace:Handles'      /* SP not installed, use GA default */
  263.  
  264. /*****************************************************************************/
  265. /* Find all valid BLOCKn entries and append them into a single BLOCK1. v2.14 */
  266. /*****************************************************************************/
  267. Parse value '' with block block1
  268. Do i = 1 to 999
  269.   block = SysIni('SYSTEM', handlesapp, 'BLOCK'||i)
  270.   If block = 'ERROR:' Then Do
  271.     If i = 1 Then Do
  272.       Call Dosay "Error    ==> SysIni('SYSTEM', "handlesapp", 'BLOCK'||i)"
  273.       Call Dosay "         ==> Unable to locate the NODE table"
  274.       rc=1
  275.       Signal GetnodesDone
  276.     End
  277.     Leave
  278.   End
  279.   block1 = block1||block
  280. End
  281. Call Dosay 'Blocks found =' i-1 '  Combined NODE table length =' length(block1)
  282.                                                                    /* v3.00b */
  283. Parse value '0 0 0' with nodes. i l .
  284. Do until l>=length(block1)
  285.   Select
  286.   When substr(block1,l+5,4)='DRIV' then
  287.     Do
  288.       xl=pos('00'x||'NODE'||'01'x,block1,l+5)-l
  289.       If xl<=0 then                             /* No NODE entry after DRIV? */
  290.         Leave                                             /* Yes, we're done */
  291.       l=l+xl
  292.       Iterate
  293.     End
  294.   When substr(block1,l+1,4)='DRIV' Then
  295.     Do
  296.       xl=pos('00'x||'NODE'||'01'x,block1,l+1)-l
  297.       If xl<=0 then                             /* No NODE entry after DRIV? */
  298.         Leave                                             /* Yes, we're done */
  299.       l=l+xl
  300.       Iterate
  301.     End
  302.   Otherwise
  303.     Do
  304.       data=substr(block1,l+1,32)
  305.       xl=c2d(substr(block1,l+31,1))
  306.       data=data||substr(block1,l+33,xl+1)
  307.       l=l+length(data)
  308.     End
  309.   End
  310.   i=i+1
  311.   nodes.i=data
  312. End
  313. nodes.0=i
  314. rc=0
  315. GetnodesDone:
  316. Return rc
  317.  
  318. /*****************************************************************************/
  319. /* See if target directory exists. If not then create it from the 1st level  */
  320. /* directory to the final target as needed. If svdir is only 3 bytes then it */
  321. /* is the root of a drive/partition so does not need to be created.          */
  322. /*****************************************************************************/
  323. GenTargetDir: Procedure expose svdir lognum log. curdir robolog
  324. savedrive_currdir = Directory(left(svdir,2))                        /* v3.02 */
  325. rc=0
  326. If length(svdir)>3 & (translate(Directory(svdir))<>translate(svdir)) then
  327.   Do  /* outer do */                                       /* Does not exist */
  328.     If lastpos('\',svdir)=3 then                /* Single level after drive? */
  329.       Do                                                              /* Yes */
  330.         rc = SysMkDir(svdir)                      /* Create directory v3.03b */
  331.         If rc<>0 then                                            /* Problem? */
  332.           Do
  333.             Call Dosay 'SysMkDir error, RC 'rc svdir
  334.             Signal GenTargetDirDone                         /* Yes, bail out */
  335.           End
  336.         Call Dosay 'Target directory 'svdir' created.'
  337.       End
  338.     Else                                         /* Nope, nested directories */
  339.       Do /* else do */
  340.         savedrive=Filespec('DRIVE',svdir)           /* Drive for save target */
  341.         savepath =Filespec('PATH',svdir)             /* Path for save target */
  342.         Do j=2 to length(savepath)                    /* Skip lead backslash */
  343.           If substr(savepath,j,1)='\' then            /* Find next backslash */
  344.             Do                                                    /* Got one */
  345.               testdir=savedrive||substr(savepath,1,j-1)     /* Dir to create */
  346.               If translate(Directory(testdir))<>translate(testdir) then
  347.                 Do                                         /* It's not there */
  348.                   rc = SysMkDir(testdir)          /* Create directory v3.03b */
  349.                   If rc<>0 then                                  /* Problem? */
  350.                     Do
  351.                       Call Dosay 'SysMkDir error, RC 'rc testdir
  352.                       Signal GenTargetDirDone               /* Yes, bail out */
  353.                     End
  354.                   Call Dosay 'Target directory 'testdir' created.'
  355.                 End
  356.             End
  357.         End /* j */
  358.       End /* of else do */
  359.   End /* of outer do */
  360.  
  361. rc=lineout(robolog,copies('=',80))                /* Test log accessibility */
  362. If rc<>0 then
  363.   Do
  364.      say 'Error writing to log:' robolog
  365.      Signal GenTargetDirDone
  366.   End
  367.  
  368. GenTargetDirDone:
  369. rc1=rc
  370. y=Directory(savedrive_currdir)                                      /* v3.02 */
  371. x=Directory(curdir)                                      /* Back to orig dir */
  372. Return rc1
  373.  
  374. /*****************************************************************************/
  375. /* Place additional debug information in the log file.                       */
  376. /*   OS/2 version                                                            */
  377. /*   Selected OS/2 environment values                                        */
  378. /*   Selected module information                                       v3.02 */
  379. /*****************************************************************************/
  380. GenDebugInfo: Procedure expose boot lognum log. rscopyx robosavex
  381. Call Dosay 'OS/2 version' SysOS2Ver()                /* Display OS/2 version */
  382.  
  383. check=boot'\OS2KRNL',               /* Get data for the modules in this list */
  384.       boot'\OS2\CMD.EXE',
  385.       boot'\OS2\DLL\PMWP.DLL',
  386.       boot'\OS2\DLL\REXXUTIL.DLL',
  387.       rscopyx,                                               /* ROBOSVUT.EXE */
  388.       robosavex                                              /* ROBOSAVE.CMD */
  389.  
  390. Do j=1 to words(check)
  391.   file=word(check,j)                                       /* File to locate */
  392.   rc=SysFileTree( file , sfile ,'F' )                   /* Get its file info */
  393.   If rc<>0 then
  394.     Call Dosay 'SysFileTree error, RC 'rc' ==> 'file
  395.   Else
  396.     Do
  397.       If sfile.0=0 then                                     /* Was it found? */
  398.         Call Dosay '***' file 'not found.'
  399.       Else
  400.         Call Dosay '   ' sfile.1
  401.     End
  402. End
  403.  
  404. Call Dosay 'USER_INI='value('USER_INI',,'OS2ENVIRONMENT')
  405. Call Dosay 'SYSTEM_INI='value('SYSTEM_INI',,'OS2ENVIRONMENT')
  406. Call Dosay 'OS2_SHELL='value('OS2_SHELL',,'OS2ENVIRONMENT')
  407. Call Dosay 'RUNWORKPLACE='value('RUNWORKPLACE',,'OS2ENVIRONMENT')
  408. Call Dosay
  409. Return
  410.  
  411. /*****************************************************************************/
  412. /* Set up the commands for ROBOREST.CMD to erase the current Desktop.  v2.14 */
  413. /*****************************************************************************/
  414. MakeEraseDTP: Procedure Expose headnum head. svdir dtp boot         /* v3.02 */
  415.                                                                     /* v3.02 */
  416. headnum=headnum+1
  417. parse value SysOS2Ver() with major '.' minor .                      /* v3.02 */
  418. OS2_version = major*10 || '.' || left(minor,2,'0')                  /* v3.02 */
  419.                                                                     /* v3.02 */
  420. head.headnum=svdir'ROBOSVUT ERASE_DESKTOP "'dtp'"' boot  OS2_version
  421. headnum=headnum+1
  422. head.headnum='IF ERRORLEVEL 200 GOTO END'
  423. headnum=headnum+1
  424. head.headnum='IF ERRORLEVEL 199 GOTO CONTINUE'
  425. headnum=headnum+1
  426. head.headnum='IF ERRORLEVEL 0 GOTO END'
  427. headnum=headnum+1
  428. head.headnum=':CONTINUE'
  429. headnum=headnum+1
  430. head.headnum='@Echo Creating Desktop directory structure'
  431. Return 0
  432.  
  433. /*****************************************************************************/
  434. /* Get last filename used from marker file. Marker file was setup in the     */
  435. /* ReadPro sub-routine and points to the save directory. 0 if not found.     */
  436. /*****************************************************************************/
  437. GetMarker: Procedure expose marker ismarker lastname lognum log.
  438. rc=SysFileTree( marker , sfile ,'F' )                   /* Get its file info */
  439. If rc<>0 then
  440.   Do
  441.     Call Dosay 'SysFileTree error, RC 'rc' ==> 'marker
  442.     Signal GetMarkerDone
  443.   End
  444. If sfile.0>0 then                                           /* Was it found? */
  445.   Do
  446.     ismarker=1
  447.     x=linein(marker,1,0)                                 /* Open to record 1 */
  448.     lastname=linein(marker)                                 /* Read a record */
  449.     x=lineout(marker)                                      /* Close the file */
  450.     If lastname=''|datatype(lastname,'W')=0 then
  451.       lastname=0                            /* In case empty or invalid file */
  452.   End
  453. Else
  454.   Do
  455.     lastname=0
  456.     ismarker=0
  457.   End
  458. GetMarkerDone:
  459. Return rc
  460.  
  461. /*****************************************************************************/
  462. /* Check for existing ROBOREST.CMD. If there move any existing CMn files     */
  463. /* down one slot. If all filled then delete the oldest and all files it      */
  464. /* points to. Rename others downward and rename CMD to CM1.                  */
  465. /*                                                                           */
  466. /* Always start with the maximum supported number of 8 (totals 9 including   */
  467. /* CMD). This allows us to cleanup older sets if the user reduces the        */
  468. /* savenum var.                                                              */
  469. /*****************************************************************************/
  470. ProcessRcmd: Procedure expose roborest savenum svdir lognum log.,
  471.                        boot                                         /* v3.01 */
  472. eaut_cmd=boot||'\OS2\EAUTIL'                                        /* v3.01 */
  473. rc=SysFileTree( roborest , sfile ,'F' )                 /* Get its file info */
  474. If rc<>0 then
  475.   Do
  476.     Call Dosay 'SysFileTree error, RC 'rc' ==> 'roborest
  477.     Signal ProcessRcmdDone
  478.   End
  479. If sfile.0>0 then                                           /* Was it found? */
  480.   Do                                                             /* outer do */
  481.     todo='D 1 2 3 4 5 6 7 8'                /* Extension suffixes to process */
  482.     Do j=words(todo) to 1 by -1               /* Works from oldest to newest */
  483.       tmp=svdir||'ROBOREST.CM'word(todo,j)
  484.       rc=SysFileTree( tmp , sfile , 'F')
  485.       If rc<>0 then
  486.         Do
  487.           Call Dosay 'SysFileTree error, RC 'rc' ==> 'tmp
  488.           Signal ProcessRcmdDone
  489.         End
  490.       If sfile.0>0 then                                    /* Does it exist? */
  491.         If j>=savenum then                 /* Exceeds or equals max allowed? */
  492.           Do                                                   /* j>=savenum */
  493.             Call Dosay 'Deleting files pointed to by 'tmp
  494.             x=linein(tmp,1,0)                            /* Open to record 1 */
  495.             Do forever                            /* Till we run out of data */
  496.               input=linein(tmp)                             /* Read a record */
  497.               If input=='' then                               /* NULL (EOF)? */
  498.                 Leave                                           /* Yes, done */
  499.               Parse value input with cmd '"'part1'"' '"'part2'"'
  500.               Select
  501.               When cmd='COPY' then                            /* COPY entry? */
  502.                 Call SysFileDelete part1
  503.               When cmd=eaut_cmd then            /* EAUTIL entry? */ /* v3.01 */
  504.                 Call SysFileDelete part2
  505.               Otherwise                                /* Neither, ignore it */
  506.                 Iterate
  507.               End
  508.             End                                                   /* forever */
  509.             x=lineout(tmp)                                 /* Close the file */
  510.             Call Dosay 'Deleting 'tmp
  511.             Call SysFileDelete tmp
  512.             Iterate j
  513.           End                                              /* of j>= savenum */
  514.         Else                /* Not max allowed, rename downward to make room */
  515.           Do
  516.             tmp1='ROBOREST.CM'||word(todo,j+1)
  517.             Call Dosay 'Renaming 'tmp' to 'tmp1
  518.             '@REN 'tmp tmp1
  519.           End
  520.     End                                                                 /* j */
  521.   End                                                         /* of outer do */
  522. ProcessRcmdDone:
  523. Return rc
  524.  
  525. /*****************************************************************************/
  526. /* Now process the head. entries which are REM statements to identify which  */
  527. /* run this ROBOREST.CMD file is associated with. Has date/time and          */
  528. /* VOLUME/LABEL of target drive.                                             */
  529. /*****************************************************************************/
  530. GenHdr: Procedure expose roborest headnum head. lognum log.
  531. rc=0
  532. Call Dosay 'Creating 'roborest
  533. x=lineout(roborest,,1)                                   /* Open output file */
  534. Do r=1 to headnum
  535.   rc=lineout(roborest,head.r)
  536.   If rc<>0 then
  537.     Do
  538.       Call Dosay 'Error writing 'roborest', RC 'rc
  539.       Leave r
  540.     End
  541. End
  542. Return rc
  543.  
  544. /*****************************************************************************/
  545. /* Now process the ifnot.n entries which are IF NOT EXIST statements that if */
  546. /* true will do a MD of the missing directory. 'ifnotrest' has the number of */
  547. /* desktop directories processed for which there will be IF NOT records.     */
  548. /*****************************************************************************/
  549. ProcessIfnot: Procedure expose roborest ifnotrest ifnot. lognum log.
  550. rc=0
  551. Do r=1 to ifnotrest                  /* Create any missing Directories first */
  552.   rc=lineout(roborest,ifnot.r)
  553.   If rc<>0 then
  554.     Do
  555.       Call Dosay 'Error writing 'roborest', RC 'rc
  556.       Leave r
  557.     End
  558. End
  559. Return rc
  560.  
  561. /*****************************************************************************/
  562. /* Now process the copyfile.n entries which are the COPY calls. 'copyrest'   */
  563. /* has the number of files to copy.                                          */
  564. /*                                                                           */
  565. /* For COPY records, need to see if there is an attrib.copyrest record to go */
  566. /* with it. If yes, write the ATTRIB record, the COPY record, then another   */
  567. /* ATTRIB record to reverse the results of the previous ATTRIB command.      */
  568. /*****************************************************************************/
  569. ProcessCrest: Procedure expose copyrest attrib. roborest copyfile.,
  570.               log. lognum boot
  571.  
  572. os2ini=boot||'\OS2\OS2.INI'                                        /* v3.00c */
  573. os2sysini=boot||'\OS2\OS2SYS.INI'                                  /* v3.00c */
  574.  
  575. rc=0
  576. Do r=1 to copyrest                            /* Do the COPY statements next */
  577.   Parse value copyfile.r with . '"'.'"' '"'ctrg'"' .
  578.   If attrib.r<>'' then
  579.     Do                                                                 /* if */
  580.       Parse value attrib.r with cmd '"'part1'"' atts
  581.       rc=lineout(roborest,'@ECHO Attrib    === "'part1'"' atts)
  582.       rc=lineout(roborest,attrib.r)      /* Turn off System/Hidden/Read Only */
  583.       If rc<>0 then
  584.         Do
  585.           Call Dosay 'Error writing 'roborest', RC 'rc
  586.           Leave r
  587.         End
  588.       rc=lineout(roborest,'@ECHO Restore   === "'ctrg'"')
  589.       rc=lineout(roborest,copyfile.r)                     /* Add COPY record */
  590.       If rc<>0 then
  591.         Do
  592.           Call Dosay 'Error writing 'roborest', RC 'rc
  593.           Leave r
  594.         End
  595.  
  596. /* Don't set any attributes for OS2.INI and OS2SYS.INI                v3.00c */
  597.       If translate(part1)<>os2ini & translate(part1)<>os2sysini then
  598.         Do
  599.           atts=translate(atts,'+','-') /* Reverse - to + */
  600.           rc=lineout(roborest,'@ECHO Attrib    === "'part1'"' atts)
  601.           rc=lineout(roborest,cmd '"'part1'"' atts)    /* 2nd ATTRIB command */
  602.         End
  603.  
  604.       If rc<>0 then
  605.         Do
  606.           Call Dosay 'Error writing 'roborest', RC 'rc
  607.           Leave r
  608.         End
  609.     End                                                             /* of if */
  610.   Else
  611.     Do
  612.       rc=lineout(roborest,'@ECHO Restore   === "'ctrg'"')
  613.       rc=lineout(roborest,copyfile.r)
  614.       If rc<>0 then
  615.         Do
  616.           Call Dosay 'Error writing 'roborest', RC 'rc
  617.           Leave r
  618.         End
  619.     End
  620. End                                                                     /* r */
  621. Return rc
  622.  
  623. /*****************************************************************************/
  624. /* Now process the echo.n entries which are the ECHO calls to create files   */
  625. /* with a size of 0. echorest has the number to create.                      */
  626. /*****************************************************************************/
  627. ProcessErest: Procedure expose echorest roborest echo. log. lognum
  628. rc=0
  629. Do r=1 to echorest
  630.   Parse value echo.r with . '>' . '>' part1
  631.   rc=lineout(roborest,'@ECHO Create    === 'part1)
  632.   rc=lineout(roborest,echo.r)
  633.   If rc<>0 then
  634.     Do
  635.       Call Dosay 'Error writing 'roborest', RC 'rc
  636.       Leave r
  637.     End
  638. End
  639. Return rc
  640.  
  641. /*****************************************************************************/
  642. /* Last we process the eautdir.n entries which are the EAUTIL calls.         */
  643. /* 'eautrest' has the number of EAUTIL cmds issued.                          */
  644. /*****************************************************************************/
  645. ProcessEaut: Procedure expose eautrest eautdir. roborest log. lognum
  646. rc=0
  647. Do r=1 to eautrest                      /* and finally the EAUTIL statements */
  648.   Parse value eautdir.r with . '"'part1'"' .
  649.   rc=lineout(roborest,'@ECHO Join EA   === "'part1'"')
  650.   rc=lineout(roborest,eautdir.r)
  651.   If rc<>0 then
  652.     Do
  653.       Call Dosay 'Error writing 'roborest', RC 'rc
  654.       Leave r
  655.     End
  656. End
  657. If rc=0 then                                                        /* v2.14 */
  658.   Do                                                                /* v2.14 */
  659.     rc=lineout(roborest,":END")                                     /* v2.14 */
  660.     If rc<>0 then Call Dosay 'Error writing 'roborest', RC 'rc      /* v2.14 */
  661.   End                                                               /* v2.14 */
  662. rc1=rc
  663. x=lineout(roborest)                                        /* Close the file */
  664. Return rc1
  665.  
  666. /*****************************************************************************/
  667. /* Save Extended Attributes (EA) for the Desktop, including the root and all */
  668. /* sub-directories using                                                     */
  669. /*                        EAUTIL source target /P /S                         */
  670. /*                                                                           */
  671. /* Also need to handle the Templates folder which contains real files that   */
  672. /* take up disk space. Make this generic so anything new in the future will  */
  673. /* be handled. Do this by scanning for files in each of the directories. Any */
  674. /* found add to 'robodir' which is the list of files found in the Desktop    */
  675. /* directory structure that need to be processed in the FileSave routine.    */
  676. /*                                                                           */
  677. /* Also build the IF NOT records to recreate desktop directories that may be */
  678. /* missing during the restore process.                                       */
  679. /*****************************************************************************/
  680. SaveEA: Procedure expose svdir hit dtp ifnotrest ifnot. eautrest eautdir.,
  681.         robodir lastname lognum log. echorest echo. boot            /* v2.14 */
  682.  
  683. hit=0                 /* Total num of dirs/files processed (includes anchor) */
  684. rc=SysFileTree( dtp||'\*.*' , dtpdir ,'SDO' )  /* All sub-dirs under Desktop */
  685. If rc<>0 then
  686.   Do
  687.     Call Dosay 'SysFileTree error, RC 'rc'==>'dtp
  688.     Signal SaveEADone
  689.   End
  690. If dtpdir.0=0 then                                          /* Was it found? */
  691.   Do
  692.     Call Dosay 'No subdirectories found under 'dtp
  693.     Call Dosay 'This is an impossible situation, please investigate.'
  694.     rc=1
  695.     Signal SaveEADone
  696.   End
  697.  
  698. numdirs=dtpdir.0                        /* Move to working directory counter */
  699. dtpdir.0=dtp                              /* Make 1st one the Desktop anchor */
  700.  
  701. Call Dosay 'Starting Desktop EA save to 'svdir
  702. robodir=''                    /* Files in Desktop structure to save via COPY */
  703. Do j=0 while j<=numdirs               /* Start with Desktop anchor directory */
  704.   source=dtpdir.j                                /* Source file to work with */
  705.  
  706.   /***************************************************************************/
  707.   /* Now check for files in this Desktop directory. Add to robodir var if    */
  708.   /* found for file save later.                                              */
  709.   /***************************************************************************/
  710.   src=source||'\*.*'
  711.   rc=SysFileTree( src , sfile ,'FT' )       /* See if any files in directory */
  712.   If rc<>0 then
  713.     Do
  714.       Call Dosay 'SysFileTree error, RC 'rc' ==> 'source
  715.       Signal SaveEADone
  716.     End
  717.  
  718.   Do fp=1 to sfile.0                 /* Process each file found in directory */
  719.     Parse value sfile.fp with sdate ssize satt src        /* File attributes */
  720.     src=strip(src,'B')                               /* Get rid of any trash */
  721.     /*************************************************************************/
  722.     /* Check filesize. If 0 create an echo. record to recreate on restore by */
  723.     /* redirect STDERR to file so it will be a null file (size 0). Also add  */
  724.     /* to 'echosrc' var so EAs for the file will be saved. Otherwise just    */
  725.     /* add to robodir for later copy.                                        */
  726.     /*************************************************************************/
  727.     If ssize=0 then                                          /* 0 size file? */
  728.       Do
  729.         Call Dosay 'ECHO      ==> 'src' <.>'                        /* v3.02 */
  730.         echorest=echorest+1                             /* Bump echo counter */
  731.         echo.echorest='ECHO >NUL 2>"'src'"'             /* Build ECHO record */
  732.         echosrc.echorest=src         /* Add to EA save list for 0 size files */
  733.       End
  734.     Else
  735.       robodir=robodir translate(src,'00'x,' ')       /* No, add to COPY list */
  736.   End                                                                  /* fp */
  737.  
  738.   /***************************************************************************/
  739.   /* Start with last used name+1 to pick an unused name in the target dir.   */
  740.   /***************************************************************************/
  741.   Do forever                          /* Till we find an unused filename.ext */
  742.     lastname=lastname+1
  743.     filename=right(lastname,8,'0')||.'EAS'
  744.     ttarg=svdir||filename                          /* Fully qualified target */
  745.     rc=SysFileTree( ttarg , tfile , 'F' )
  746.     If rc<>0 then
  747.       Do
  748.         Call Dosay 'SysFileTree error, RC 'rc' ==> 'ttarg
  749.         Signal SaveEADone
  750.       End
  751.     If tfile.0=0 then                                        /* File exists? */
  752.       Leave                                                      /* No, done */
  753.   End                                                             /* forever */
  754.   target=ttarg
  755.   Call Dosay 'EAUTIL    ==> 'source' <'target'>'                    /* v3.02 */
  756.   If DoEautil(1)<>0 then
  757.     Signal SaveEADone
  758. End                                                                 /* while */
  759. /*****************************************************************************/
  760. /* Now process any echo. entries generated (file size=0 files).              */
  761. /*****************************************************************************/
  762. Do j=1 to echorest
  763.   source=echosrc.j
  764.   Do forever                          /* Till we find an unused filename.ext */
  765.     lastname=lastname+1
  766.     filename=right(lastname,8,'0')||.'EAS'
  767.     ttarg=svdir||filename                          /* Fully qualified target */
  768.     rc=SysFileTree( ttarg , tfile , 'F' )
  769.     If rc<>0 then
  770.       Do
  771.         Call Dosay 'SysFileTree error, RC 'rc' ==> 'ttarg
  772.         Signal SaveEADone
  773.       End
  774.     If tfile.0=0 then                                        /* File exists? */
  775.       Leave                                                      /* No, done */
  776.   End                                                             /* forever */
  777.   target=ttarg
  778.   Call Dosay 'EAUTIL    ==> 'source' <'target'>'                    /* v3.02 */
  779.   If DoEautil(0)<>0 then                      /* Run EAUTIL, no MD statement */
  780.     Signal SaveEADone
  781. End                                                                     /* j */
  782. SaveEADone:
  783. Return rc
  784.  
  785. /*****************************************************************************/
  786. /* Run EAUTIL /P /S to create a copy of the EAs for the directory being      */
  787. /* processed. /P will preserve the EAs attached to the directory. /S will    */
  788. /* copy (split) them off to the target.                                      */
  789. /*                                                                           */
  790. /* Check the target file to make sure it was created. Only then do we add a  */
  791. /* eautdir. record. If target does not exist place entry in log file and     */
  792. /* continue, not an error. Note that we always create an IF NOT record for   */
  793. /* directories.                                                              */
  794. /*                                                                           */
  795. /* Var 'ifnotrest' contains number of IF NOT commands needed for same.       */
  796. /* Var 'eautrest' contains the number of EAUTIL commands needed for ROBOREST.*/
  797. /*****************************************************************************/
  798. DoEautil:
  799. Arg make_directory .                                        /* 0=no MD, 1=MD */
  800. eaut_cmd=boot||'\OS2\EAUTIL'                                        /* v2.14 */
  801. rc=0
  802. '@EAUTIL "'source'"' '"'target'" /P /S'
  803. If rc>0 then
  804.   Do
  805.     If rc=1 then
  806.       Call Dosay 'Not found ==> 'source
  807.     Else
  808.       Call Dosay 'EAUTIL processing error, RC 'rc
  809.   End
  810. Else                                                 /* EAUTIL returned RC=0 */
  811.   Do
  812.     rc=SysFileTree( target, efile , 'F' )      /* See if target file created */
  813.     If rc<>0 then
  814.       Do
  815.         Call Dosay 'SysFileTree error, RC 'rc' ==> 'target
  816.         Signal DoEautilDone
  817.       End
  818.     hit=hit+1                               /* All is well, bump saved count */
  819.     If make_directory then                             /* Directory of file? */
  820.       Do
  821.         ifnotrest=ifnotrest+1
  822.         ifnot.ifnotrest='IF NOT EXIST "'source'" MD "'source'"'
  823.       End
  824.     If efile.0=0 then                                        /* File exists? */
  825.       Call Dosay 'No EA     ==> 'source            /* No, place entry in log */
  826.     Else
  827.       Do                                         /* Yes, need EAUTIL command */
  828.         eautrest=eautrest+1                          /* Bump restore counter */
  829.         eautdir.eautrest=eaut_cmd '"'source'"' '"'target'" /P /J /O'/* v2.14 */
  830.       End
  831.   End
  832. DoEautilDone:
  833. Return rc
  834.  
  835. /*****************************************************************************/
  836. /* Save files to target directory. Translate all '00'x to blanks to support  */
  837. /* HPFS directory names.                                                     */
  838. /*                                                                           */
  839. /* Note that the source file can have any of the normal substitution chars   */
  840. /* so more than one file may be returned from SysFileTree therefore all have */
  841. /* to be processed.                                                          */
  842. /*****************************************************************************/
  843. FileSave: Procedure expose svdir robo hit boot copyrest copyfile.,
  844.          robodir lastname attrib. lognum log. rscopyx               /* v3.02 */
  845.  
  846. hit=0
  847. Call Dosay 'Starting file save to 'svdir
  848.  
  849. os2ini=boot||'\OS2\OS2.INI'                      /* Require special handling */
  850. os2sysini=boot||'\OS2\OS2SYS.INI'                                   /* Ditto */
  851.  
  852. /*****************************************************************************/
  853. /* 1st we save any files found in the Desktop directory structure during the */
  854. /* EA save process. Convert any '00'x to blanks. Any error or file not found */
  855. /* will terminate.                                                           */
  856. /*****************************************************************************/
  857. Do j=1 to words(robodir)
  858.   source=translate(word(robodir,j),' ','00'x)    /* Pick file. Remove '00'x  */
  859.   rc=SysFileTree( source , sfile ,'FT' )                /* Get its file info */
  860.   If rc<>0 then
  861.     Do
  862.       Call Dosay 'SysFileTree error, RC 'rc' ==> 'source
  863.       Signal FileSaveDone
  864.     End
  865.   If sfile.0=0 then                                         /* Was it found? */
  866.     Do
  867.       Call Dosay 'Not found ==> 'source
  868.       rc=1
  869.       Signal FileSaveDone
  870.     End
  871.   If DoSave()<>0 then
  872.     Signal FileSaveDone
  873. End                                                         /* j for robodir */
  874.  
  875. /*****************************************************************************/
  876. /* Now we save all files from robo=lines in the profile  plus any passed as  */
  877. /* parms on the command line. Use COPY for all except OS2.INI and OS2SYS.INI */
  878. /* then use ROBOSVUT since they are locked (in use) files (also use ROBOSVUT */
  879. /* if copy fails).                                                           */
  880. /*                                                                           */
  881. /* Files not found will be logged but processing continues.                  */
  882. /* Translate all '00'x to blanks at start.                                   */
  883. /*                                                                           */
  884. /* One special case to handle. [d:\path\filename.ext]. The brackets mean to  */
  885. /* search the specified directory and all subdirectories for all cases of    */
  886. /* the specified filename.ext. As in the normal case, all wildcards are      */
  887. /* allowed.                                                                  */
  888. /*****************************************************************************/
  889. Do j=1 to words(robo)
  890.   source=translate(word(robo,j),' ','00'x)      /* Pick a file. Remove '00'x */
  891.   If substr(source,1,1)='[' then                      /* All subdirs format? */
  892.     Do                                                                /* Yes */
  893.       source=substr(source,2,length(source)-2)            /* Remove brackets */
  894.       Call Dosay 'Scanning  ==> 'source
  895.       rc=SysFileTree( source , sfile ,'FST' )   /* Get info from all subdirs */
  896.     End
  897.   Else
  898.     rc=SysFileTree( source , sfile ,'FT' )              /* Get its file info */
  899.   If rc<>0 then
  900.     Do
  901.       Call Dosay 'SysFileTree error, RC 'rc' ==> 'source
  902.       Signal FileSaveDone
  903.     End
  904.   If sfile.0=0 then                                         /* Was it found? */
  905.     Do
  906.       Call Dosay 'Not found ==> 'source
  907.       Iterate j
  908.     End
  909.   If DoSave()<>0 then
  910.     Signal FileSaveDone
  911. End                                                            /* j for robo */
  912.  
  913. /*****************************************************************************/
  914. /* Place a copy of ROBOSVUT.EXE in the target directory.  This will be used  */
  915. /* by ROBOREST.CMD to delete the Desktop directory tree.               v2.14 */
  916. /*****************************************************************************/
  917. src = rscopyx                                                       /* v3.02 */
  918. target = svdir'ROBOSVUT.EXE'
  919. Call Dosay 'COPY      ==> 'src' <'target'>'
  920. '@COPY "'src'"' '"'target'"' '/F /V > NUL'              /* Put on target dir */
  921. If rc<>0 then
  922.   Do
  923.     Call Dosay 'COPY error, RC 'rc src target
  924.     Call Dosay 'Manually place a copy of 'src' in 'svdir
  925.     rc=0                                        /* Force good rc to continue */
  926.   End
  927.  
  928. FileSaveDone:
  929. Return rc
  930.  
  931. /*****************************************************************************/
  932. /* Normally use COPY to copy source to target. If this fails then try        */
  933. /* ROBOSVUT.                                                                 */
  934. /*                                                                           */
  935. /* ROBOSVUT will be used for OS2.INI and OS2SYS.INI at all times since they  */
  936. /* are locked (in use) files.                                                */
  937. /*                                                                           */
  938. /* Use similar naming convention as EAs, nnnnnnnn.FIL to maintain the FAT    */
  939. /* 8.3 form.                                                                 */
  940. /*                                                                           */
  941. /* Check source file attributes. If S (System), H (hidden) or R (read only)  */
  942. /* then build an attrib.copyrest record with appropriate -S -H -R parms.     */
  943. /*                                                                           */
  944. /* OS2.INI and OS2SYS.INI need to be cleaned up to remove autostart of all   */
  945. /* restart objects to prevent ROBOSAVE from autostart on first boot after    */
  946. /* ROBOREST has been run.  The S, H, and R attributes are forced off.  v3.03 */
  947. /*****************************************************************************/
  948. DoSave:
  949. attr_cmd=boot||'\OS2\ATTRIB'                                        /* v2.14 */
  950. rc=0
  951. Do fp=1 to sfile.0          /* Process each file found that matched filespec */
  952.   Parse value sfile.fp with sdate ssize satt src          /* File attributes */
  953.   src=strip(src,'B')                                 /* Get rid of any trash */
  954.   If translate(src)=os2ini | translate(src)=os2sysini then
  955.     howcopy='ROBOSVUT'
  956.   Else
  957.     howcopy='COPY'
  958.   Do forever         /* Till we find a unused filename.ext on the target dir */
  959.     lastname=lastname+1                      /* Bump last used filename by 1 */
  960.     filename=right(lastname,8,'0')              /* Build the actual filename */
  961.     target=svdir||filename'.FIL'                        /* Complete filespec */
  962.     rc=SysFileTree( target , tfile , 'FT' )                   /* Target info */
  963.     If rc<>0 then
  964.       Do
  965.         Call Dosay 'SysFileTree Error  ==> RC 'rc target
  966.         Signal DoSaveDone
  967.       End
  968.     If tfile.0=0 then                                    /* Existing backup? */
  969.       Leave                                                      /* No, done */
  970.   End                                                             /* forever */
  971.   If verify(satt,'-AR') > 0 then howcopy ='ROBOSVUT'                /* v3.03 */
  972.   Call Dosay left(howcopy,8)'  ==> 'src' <'target'>'                /* v3.02 */
  973.   If verify(satt,'-A') > 0 then                                     /* v3.03 */
  974.     Call DoSay '     Current file attributes:  ' satt               /* v3.03 */
  975.   If howcopy='ROBOSVUT' then
  976.     Do                                                              /* v2.14 */
  977.                                                     /* Save source in target */
  978.       '@'rscopyx '"'src'"' '"'target'" /A /V'                      /* v3.03b */
  979.       If rc=100 Then rc=0                                           /* v2.14 */
  980.     End                                                             /* v2.14 */
  981.   Else
  982.     Do
  983.       '@COPY' '"'src'"' '"'target'" /F /V' '> NUL'  /* Save source in target */
  984.       If rc<>0 then
  985.         Do
  986.           Call Dosay 'Failed    ==> RC 'rc', will try ROBOSVUT'
  987.           howcopy='ROBOSVUT'
  988.           Call Dosay left(howcopy,8)'  ==> 'src' <'target'>'        /* v3.02 */
  989.                                                     /* Save source in target */
  990.           '@'rscopyx '"'src'"' '"'target'" /A /V'                  /* v3.03b */
  991.           If rc=100 Then rc=0                                       /* v2.14 */
  992.         End
  993.     End
  994.   If rc=0 then
  995.     Do                                                               /* rc=0 */
  996.       hit=hit+1                                          /* Bump saved count */
  997.       copyrest=copyrest+1                            /* Bump restore counter */
  998.       copyfile.copyrest='COPY "'target'"' '"'src'" /F /V > NUL'
  999.       atts=''          /* Check for source being System, Hidden or Read Only */
  1000.       If pos('S',satt)>0 then
  1001.         atts=atts '-S'
  1002.       If pos('H',satt)>0 then
  1003.         atts=atts '-H'
  1004.       If pos('R',satt)>0 then
  1005.         atts=atts '-R'
  1006.       If atts<>'' then
  1007.         attrib.copyrest=attr_cmd '"'src'"' atts                     /* v2.14 */
  1008.       Else
  1009.         attrib.copyrest=''
  1010.       If translate(src)=os2ini then
  1011.         Do
  1012.           attrib.copyrest=attr_cmd '"'src'" -R -S -H'               /* v3.03 */
  1013.           Call SysIni target, 'PM_WorkPlace:Restart', 'DELETE:';
  1014.           If result<>'ERROR:' then
  1015.             Call Dosay 'Cleanup   ==>   PM_WorkPlace:Restart <.>'   /* v3.02 */
  1016.         End
  1017.       If translate(src)=os2sysini then
  1018.         Do
  1019.           attrib.copyrest=attr_cmd '"'src'" -R -S -H'               /* v3.03 */
  1020.           Call SysIni target, 'FolderWorkareaRunningObjects', 'DELETE:';
  1021.           If result<>'ERROR:' then
  1022.             Call Dosay 'Cleanup   ==>   FolderWorkareaRunningObjects <.>'
  1023.         End                                                         /* v3.02 */
  1024.     End /* rc=0 */
  1025.   Else
  1026.     Do
  1027.       Call Dosay howcopy 'error, RC 'rc
  1028.       Signal DoSaveDone
  1029.     End
  1030. End /* fp */
  1031. DoSaveDone:
  1032. Return rc
  1033.  
  1034. /*****************************************************************************/
  1035. /* Display data to screen and build entry for the log file. Note that log    */
  1036. /* entry can be larger than screen data. Any data enclosed in < > is for the */
  1037. /* log file only.                                                      v3.02 */
  1038. /*****************************************************************************/
  1039. Dosay: Procedure expose lognum log. svdir
  1040. Parse arg saydata '<'tgt'>' 1 verb . '==>' src '<' .
  1041. Say saydata
  1042. lognum=lognum+1
  1043. If tgt<>'' then Select
  1044.   When verb='COPY' | verb='ROBOSVUT' | verb='EAUTIL' then
  1045.     Do
  1046.       leftside=length(svdir'nnnnnnnn.EAS')
  1047.       log.lognum=left(tgt,leftside) 'via' left(verb,8) 'from' src
  1048.     End
  1049.   When verb='ECHO' then
  1050.     Do
  1051.       leftside=length(svdir'nnnnnnnn.EAS via EAUTIL   from')
  1052.       log.lognum=right('ECHO will create null file for',leftside) src
  1053.     End
  1054.   When verb='Cleanup' then
  1055.     log.lognum='  'src'deleted'                                     /* v3.03 */
  1056.   Otherwise
  1057.     log.lognum=saydata tgt
  1058.   End /* select */
  1059. Else log.lognum=saydata
  1060. Return
  1061.  
  1062. /*****************************************************************************/
  1063. /* Make sure ROBOSVUT.EXE is available in PATH before doing anything else.   */
  1064. /* Process user profile (ROBOSAVE.PRO) which can be anywhere in PATH or in   */
  1065. /* current directory. Can also be specified via /p=d:\path as a parameter on */
  1066. /* the invocation with or without a different filename.ext.                  */
  1067. /*                                                                           */
  1068. /* Cannot have ANY blank lines. * in col 1 is a comment record.              */
  1069. /*                                                                           */
  1070. /* 'save='    identifies the drive\path where you want backup files placed   */
  1071. /*            <REQUIRED>                                                     */
  1072. /* 'savenum=' number of incremental backups of files and EAs to keep         */
  1073. /*            <REQUIRED>                                                     */
  1074. /* 'log='     T to place log in target directory. P to place in directory    */
  1075. /*            profile was found in. If not specified defaults to P.          */
  1076. /* 'cleanup=' control when cleanup of existing saved files occurs.           */
  1077. /*            cleanup=B to do at beginning of run.                           */
  1078. /*            cleanup=E to do at end of run (default).                       */
  1079. /* 'robo='    fully qualified files to backup, as many robo= lines as needed */
  1080. /*            full wildcard support of * and ?. Enclose in double quotes if  */
  1081. /*            file contains blanks.                                          */
  1082. /*                                                                           */
  1083. /* /P=d:\path can be specified on invocation to point to the location of     */
  1084. /* ROBOSAVE.PRO or the fully qualified path (including filename.ext) if the  */
  1085. /* filename or ext has been changed (/p=d:\path\filename.ext). If not then   */
  1086. /* search the current directory and path for ROBOSAVE.PRO.                   */
  1087. /*                                                                           */
  1088. /* Setup ROBOSAVE.LOG based on the log= entry. Default to directory profile  */
  1089. /* found in if not specified.                                                */
  1090. /*****************************************************************************/
  1091. ReadPro: Procedure expose ver svdir savenum robo op. robolog lognum log.,
  1092.          roborest marker cleanup roboparm head. headnum rscopyx     /* v3.02 */
  1093. Parse value 'ROBOSAVE.PRO' with profile svdir savenum robo robolog cleanup .
  1094. rscopyx = SysSearchPath('PATH','ROBOSVUT.EXE')                      /* v3.02 */
  1095. If rscopyx = '' then    /* Make sure ROBOSVUT available */          /* v3.02 */
  1096.   Do
  1097.     Say 'ROBOSVUT.EXE not found in current directory or via PATH.'
  1098.     Say 'This is a required file.'
  1099.     rc=1
  1100.     Signal ReadProDone
  1101.   End
  1102. prf=''
  1103. rc=0
  1104. Do j=1 to 2
  1105.   Select
  1106.   When op.j='' then
  1107.     Iterate j
  1108.   When left(op.j,2)='P=' then                      /* Was profile specified? */
  1109.     Do                                                                 /* P= */
  1110.       If right(op.j,1)='\' then                               /* Trailing /? */
  1111.         profile=substr(op.j,3)||'ROBOSAVE.PRO'       /* Yes, tack on profile */
  1112.       Else                /* No, may be a d:\path\filename.ext, check for it */
  1113.         Do
  1114.           profile=strip(substr(op.j,3),'B')
  1115.           rc=SysFileTree( profile , sfile ,'F' )       /* See if file exists */
  1116.           If rc<>0 then
  1117.             Do
  1118.               Call Dosay 'SysFileTree error, RC 'rc' ==> 'profile
  1119.               rc=1
  1120.               Signal ReadProDone
  1121.             End
  1122.           If sfile.0=0 then                                 /* Was it found? */
  1123.             profile=substr(op.j,3)||'\ROBOSAVE.PRO'      /* No, add \profile */
  1124.         End
  1125.       rc=SysFileTree( profile , sfile ,'F' )             /* See if it exists */
  1126.       If rc<>0 then
  1127.         Do
  1128.           Call Dosay 'SysFileTree error, RC 'rc' ==> 'profile
  1129.           rc=1
  1130.           Signal ReadProDone
  1131.         End
  1132.       If sfile.0>0 then                                     /* Was it found? */
  1133.         prf=profile
  1134.       Else
  1135.         Do
  1136.           Call Dosay 'Cannot locate' profile
  1137.           rc=1
  1138.           Signal ReadProDone
  1139.         End
  1140.     End                                                                /* P= */
  1141.   Otherwise
  1142.     Do
  1143.       Call Dosay 'Invalid parameter entered on command line 'op.j
  1144.       rc=1
  1145.       Signal ReadProDone
  1146.     End
  1147.   End                                                              /* Select */
  1148. End                                                                     /* j */
  1149. If prf='' then                                                         /* No */
  1150.   prf=SysSearchPath('PATH',profile)         /* See if profile exists in path */
  1151. If prf='' then
  1152.   Do
  1153.     Say 'Profile 'profile' not found in current directory, or via PATH, or in'
  1154.     Say 'location specified via /P= parameter.  This is a required file.'
  1155.     rc=1
  1156.     Signal ReadProDone
  1157.   End
  1158. Else
  1159.   profile=prf
  1160.  
  1161. timestamp = 'Saved on ' date('O') time() ' by  ROBOSAVE version' ver
  1162. headnum=headnum+1
  1163. head.headnum='@ECHO OFF'
  1164. headnum=headnum+1
  1165. head.headnum='Rem' timestamp
  1166. Call Dosay timestamp
  1167. Call Dosay 'Reading' profile
  1168. x=linein(profile,1,0)                          /* Open to 1st record of file */
  1169. If roboparm<>'' then                           /* Treat roboparm as line 0   */
  1170.    input="robo="roboparm
  1171. Else
  1172.    input="*"
  1173. Do r=0 by 1                                     /* Process all profile lines */
  1174.   If r>0 then input=linein(profile)                        /* Read next line */
  1175.   If input='' then                                   /* Null then we're done */
  1176.     Leave
  1177.   If left(input,1)='*' then                                      /* Comment? */
  1178.     Iterate r
  1179.   Parse value input with verb'='data                /* Got one, parse it out */
  1180.   If verb='' then                                           /* Right format? */
  1181.     Do
  1182.       Call Dosay profile' line 'r' invalid format.'
  1183.       Call Dosay input
  1184.       rc=2
  1185.       Signal ReadProDone
  1186.     End
  1187.   If data='' then
  1188.     Do
  1189.       Call Dosay profile' line 'r' missing data after keyword.'
  1190.       Call Dosay input
  1191.       rc=2
  1192.       Signal ReadProDone
  1193.     End
  1194.   verb=translate(verb)                                 /* Yes, upper case it */
  1195.   Select
  1196.   When verb='SAVE' then
  1197.     svdir=translate(strip(data,'B'))                     /* Force upper case */
  1198.   When verb='SAVENUM' then
  1199.     Do
  1200.       savenum=strip(data,'B')
  1201.       If datatype(savenum,'W')=0 | savenum<1 | savenum>9 then
  1202.         Do
  1203.           Call Dosay '"savenum" variable ('savenum') invalid, must be 1 to 9.'
  1204.           rc=2
  1205.           Signal ReadProDone
  1206.         End
  1207.     End
  1208.   When verb='ROBO' then
  1209.     Do               /* Need to process for quoted names that contain blanks */
  1210.       data=strip(data,'B')' '     /* Add a space as the final word delimiter */
  1211.       hold=''                          /* Holds current file being assembled */
  1212.       qt=0                                   /* Indicates a " has been found */
  1213.       If r=0 then                            /* Set up error message text    */
  1214.          lineloc="command line parameter"
  1215.       Else
  1216.          lineloc=profile "line" r
  1217.       Do j=1 to length(data)
  1218.         If substr(data,j,1)=' ' then        /* End or word or blank in name? */
  1219.           Do                                                         /* data */
  1220.             If qt then                          /* Processing a quoted file? */
  1221.               hold=hold||' '        /* Yes, add to file being processed then */
  1222.             Else                                    /* No, end of a filename */
  1223.               Do                                 /* Check for bracketed case */
  1224.                 If left(hold,1)='[' & right(hold,1)<>']' then
  1225.                   Do
  1226.                     Call Dosay 'Missing ] or " in' lineloc
  1227.                     rc=2
  1228.                     Signal ReadProDone
  1229.                   End
  1230.                 robo=robo translate(hold,'00'x,' ')       /* Blanks to '00'x */
  1231.                 hold=''
  1232.               End
  1233.             Iterate j
  1234.           End                                                        /* data */
  1235.         If substr(data,j,1)='"' then                   /* Double quote mark? */
  1236.           If qt then                               /* Yes, previous pending? */
  1237.             Do                             /* Yes, end of a quoted file then */
  1238.               If left(hold,1)='[' & right(hold,1)<>']' then
  1239.                 Do
  1240.                   Call Dosay 'Missing ] or " in' lineloc
  1241.                   rc=2
  1242.                   Signal ReadProDone
  1243.                 End
  1244.               robo=robo translate(hold,'00'x,' ')         /* Blanks to '00'x */
  1245.               hold=''
  1246.               qt=0
  1247.               Iterate j
  1248.             End                                                        /* qt */
  1249.           Else                            /* No, start of a quoted file then */
  1250.             qt=1
  1251.         Else                                 /* Just add to file being built */
  1252.           hold=hold||substr(data,j,1)
  1253.       End                                                               /* j */
  1254.       If qt then                                           /* Premature end? */
  1255.         Do
  1256.           Call Dosay 'Unbalanced " in' lineloc
  1257.           rc=2
  1258.           Signal ReadProDone
  1259.         End
  1260.     End                                                             /* robo= */
  1261.   When verb='LOG' then                    /* Location of log file specified? */
  1262.     robolog=translate(strip(data,'B'))
  1263.   When verb='CLEANUP' then
  1264.     Do
  1265.       cleanup=translate(strip(data,'B'))
  1266.       If cleanup<>'E' & cleanup<>'B' then
  1267.         Do
  1268.           Call Dosay '"cleanup" variable ('cleanup') invalid, must be B or E.'
  1269.           rc=2
  1270.           Signal ReadProDone
  1271.         End
  1272.     End
  1273.   Otherwise
  1274.     Do
  1275.       Call Dosay profile' line 'r' has invalid keyword.'
  1276.       Call Dosay input
  1277.       rc=2
  1278.       Signal ReadProDone
  1279.     End
  1280.   End                                                    /* Select for verbs */
  1281. End                                                                     /* r */
  1282.  
  1283. x=lineout(profile)                                         /* Close the file */
  1284. If svdir='' | savenum='' | robo='' then              /* Check required parms */
  1285.   Do
  1286.     Call Dosay 'Invalid 'profile', missing "save=, savenum= or robo=" entry.'
  1287.     rc=2
  1288.     Signal ReadProDone
  1289.   End
  1290. If substr(svdir,2,1)<>':' then      /* Drive specified as part of save path? */
  1291.   Do
  1292.     Call Dosay '"save" variable ('svdir') invalid, drive not specified.'
  1293.     rc=2
  1294.     Signal ReadProDone
  1295.   End
  1296. If datatype(substr(svdir,1,1),'M')<>1 then
  1297.   Do
  1298.     Call Dosay '"save" variable ('svdir') invalid, drive not A to Z.'
  1299.     rc=2
  1300.     Signal ReadProDone
  1301.   End
  1302. If right(svdir,1)<>'\' then                 /* Trailing backslash last char? */
  1303.   svdir=svdir||'\'                                             /* No, add it */
  1304.  
  1305. Select
  1306. When robolog='T' then                        /* Wants log in save directory? */
  1307.   robolog=svdir||'ROBOSAVE.LOG'
  1308. When robolog=''|robolog='P' then         /* No, default to profile directory */
  1309.   robolog=Filespec('DRIVE',profile)||Filespec('PATH',profile)||'ROBOSAVE.LOG'
  1310. Otherwise
  1311.   Do
  1312.     Call Dosay '"log" variable ('robolog') invalid. P or T only.'
  1313.     rc=2
  1314.     Signal ReadProDone
  1315.   End
  1316. End
  1317.  
  1318. If cleanup='' then             /* Default to cleanup at end if not specified */
  1319.   cleanup='E'
  1320.  
  1321. roborest=svdir||'ROBOREST.CMD'                           /* Restore CMD file */
  1322. marker=svdir||'ROBOSAVE.MRK'                  /* Contains last filename used */
  1323. ReadProDone:
  1324. Return rc
  1325.  
  1326. /*****************************************************************************/
  1327. /* Display help                                                              */
  1328. /*****************************************************************************/
  1329. Tell:
  1330. Say 'This version of ROBOSAVE is valid only for OS/2 2.0 GA and later.'
  1331. Say
  1332. Say 'ROBOSAVE <parm> <op1>'
  1333. Say '  "parm" can be fully qualified name(s) of one or more files to save.'
  1334. Say '       These names are appended to data from robo= lines in the profile.'
  1335. Say '  "op1" can be'
  1336. say '       "/p=d:\path", where "d:\path" specifies the path to a specific'
  1337. Say '             ROBOSAVE.PRO file, or "op1" can be'
  1338. Say '       "/p=d:\path\filename.ext" if your profile is not ROBOSAVE.PRO.'
  1339. Say
  1340. Say 'Examples:'
  1341. Say '  1 ROBOSAVE                    -> saves files and Desktop EAs'
  1342. Say '  2 ROBOSAVE d:\os2\my.dat      -> saves this file plus robo= files'
  1343. Say '  3 ROBOSAVE d:\a.a d:\b.b      -> saves these two files plus robo= files'
  1344. Say '  4 ROBOSAVE /P=e:\             -> same as 1 but uses E:\ROBOSAVE.PRO'
  1345. Say '  5 ROBOSAVE /P=e:\my1.pro      -> same as 1 but uses E:\MY1.PRO'
  1346. Say
  1347. '@PAUSE'
  1348. Say 'All activity is recorded in ROBOSAVE.LOG.  The default is to write to',
  1349.   'the same'
  1350. Say 'directory where the profile was found.  You can override this with the',
  1351.   '"log="'
  1352. Say 'entry in your profile.  ROBOREST.CMD will contain all the commands',
  1353.   'necessary'
  1354. Say 'to restore your desktop.  For details of ROBOSAVE operation, you',
  1355.   'can issue'
  1356. Say '"VIEW ROBOSAVE"' "or read the ROBOSAVE User's Guide."
  1357. Return
  1358.