home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / loccmds2.zip / lpdupes.cmd < prev    next >
OS/2 REXX Batch file  |  1998-09-08  |  12KB  |  255 lines

  1. /* LPDupes - REXX program to search all paths of the 'PATH' statement for possible
  2.           resolutions to the specified argument (program).
  3.  
  4.    RRC Mon  98-08-24 initial version -
  5.    RRC Tue  98-09-08 Fixed problems with paths which began with '\' and '..'
  6. */
  7.  
  8. call RxFuncAdd SysLoadFuncs, RexxUtil, SysLoadFuncs
  9. call SysLoadFuncs
  10.  
  11. '@echo off'
  12.  
  13. PARSE ARG FileName .
  14.  
  15. if FileName = "?" then
  16. do
  17.     say 'One optional argument.'
  18.     say ''
  19.     say 'LPDupes [FileName]'
  20.     say ''
  21.     say 'Locate "collisions" in your "libpath".  Detects DLLs with the same name in'
  22.     say 'Different directories.  A "*" character will be on the lines describing the'
  23.     say '"active" file - the DLL which would be loaded given the current directory.'
  24.     say 'The placement of "." in the libpath will cause the output to change depending'
  25.     say 'on the current directory.  This may be useful for testing.'
  26.     say ''
  27.     say 'The optional parameter is the first few letters of a filename to search for.'
  28.     say '".dll" is supplied, if you include ".dll" in the search spec it will not work.'
  29.     say ''
  30.     say 'The program outputs errors if there are no DLLs in a given directory.'
  31.     say 'It also outputs information about what it is doing so that you can tell'
  32.     say 'it is in fact doing anything.  You can get rid of many of these messages by'
  33.     say 'redirecting stderr to nul as in "lpdupes 2>nul".  Note that most of the'
  34.     say 'informational or noise messages would not be saved if you redirect output to'
  35.     say 'a file (only stdout will be redirected).  If you really want all of the'
  36.     say 'messages to go to a file you will need to use this form: "lpdupes >file 2>&1"'
  37.     say ''
  38.     say 'The way the root directory is output is a little unusual: "\" is not the last'
  39.     say 'character of the directory as it would be with a "dir" command.  All you get'
  40.     say 'is a drive letter and the colon.'
  41.     say ''
  42.     exit
  43. end
  44.  
  45. curdir = TRANSLATE(directory())         /* Get current directory in upper case*/
  46. IF RIGHT(curdir,1) = '\' THEN           /* If string ends in '\' (root dir)   */
  47.   curdir = LEFT(curdir, LENGTH(curdir)-1)   /* Strip it       */
  48.  
  49. say '. = ' curdir
  50. call lineout 'STDERR:'
  51.  
  52.      /* get boot drive letter from environment */
  53.      /* Other candidates for the env string to get the boot drive from:
  54.           ULSPATH, EPMPATH, DMIPATH, I18NDIR, MMBASE    */
  55. BootDrive=left(value('GLOSSARY',,'OS2ENVIRONMENT'),2)
  56. ProdConfig=BootDrive || '\CONFIG.SYS'
  57. rc = SysFileSearch('LIBPATH', ProdConfig, 'libp.')
  58. /* If file was found, set rc to 0 iff there was at least one occurrence of
  59.    the search string (note that rc = logical compare of libp.0 = 0) */
  60. if rc = 0 then rc = libp.0 = 0
  61. if rc <> 0 then do
  62.         say "Cannot find a libpath statement in "ProdConfig
  63.         pause
  64.         exit
  65. end
  66.  
  67. lix = libp.0                            /* Point to last occurrence           */
  68. DO FOREVER                              /* Until we find a real one           */
  69.  
  70.   PARSE UPPER VALUE libp.lix WITH LPCmd '=' CmdTail
  71.   IF LPCmd = 'LIBPATH' THEN DO          /* If this is a LIBPATH command       */
  72.     LEAVE                               /* This was the final LIBPATH -- done */
  73.   END
  74.  
  75.   lix = lix-1                           /* Check for an earlier statement     */
  76.   IF lix = 0 THEN DO                    /* If we just ran out of candidates   */
  77.     say "Cannot find a legitimate libpath statement in "ProdConfig
  78.     pause
  79.     exit
  80.   END
  81. END
  82.  
  83. /* CmdTail is everything past the '=' sign in CAPs, libp.lix is original line */
  84. WorkPath=CmdTail
  85. say 'Libpath = 'WorkPath
  86. say ''
  87. call lineout 'STDERR:'
  88.  
  89. myq = RXQUEUE('Get')                    /* Get our queue name */
  90. '@RXQUEUE 'myq' /CLEAR'       /* Clear the input/keybd queue */
  91.  
  92. /* We use 'dir | rxqueue' so that we can get the list pre-sorted */
  93. DirCmd = 'dir /A /B /L /On '
  94. IF FileName = '' THEN SearchFiles = '\*.dll'
  95.                  ELSE SearchFiles = '\'||FileName||'*.dll'
  96.  
  97. DirCmdTail = SearchFiles' | rxqueue'
  98.  
  99. /* Arrays which we will need */
  100. cDirs = 0
  101.  
  102. do FOREVER                              /* Until 'leave'                      */
  103.  
  104.   PARSE UPPER VAR WorkPath SearchPath';'WorkPath  /* Pull consecutive 'path's */
  105.  
  106.   if SearchPath = '' THEN DO            /* If we've run out                   */
  107.     LEAVE                               /* No more parsing to do              */
  108.   END
  109.  
  110.   SearchPath = STRIP(SearchPath)        /* Remove blanks (should not be!)     */
  111.   if RIGHT( SearchPath, 1 ) = '\'       /* If this path ends in bs            */
  112.   THEN SearchPath = LEFT(SearchPath, LENGTH(SearchPath)-1)  /* Strip it       */
  113.  
  114.     /* Remove directories which don't exist */
  115.   IF RIGHT(SearchPath,1) = ':' THEN DO  /* Root directories are special       */
  116.     SearchPath2 = SearchPath            /* Yes they exist                     */
  117.   END
  118.   ELSE IF (SearchPath = '') | (LEFT(SearchPath,1) = '\') THEN
  119.   DO                                    /* Root relative dirs exist by defn   */
  120.     SearchPath2 = LEFT(curdir,2)||SearchPath  /* Add Current drive and ':'    */
  121.   END
  122.   ELSE IF LEFT(SearchPath,2) = '..' THEN DO /* A Parent dir may exist         */
  123.     ParentDir = LASTPOS('\', curdir)    /* Find a backslash                   */
  124.     IF ParentDir = 0 THEN ITERATE       /* If no parent, Get next libpath dir */
  125.  
  126.       /* Form the full path */
  127.     SearchPath2 = LEFT(curdir,ParentDir-1)||SUBSTR(SearchPath,3)
  128.   END
  129.   ELSE IF LEFT(SearchPath,1) = '.' THEN DO  /* Relative dirs exist by defn    */
  130.     SearchPath2 = curdir||SUBSTR(SearchPath,2)  /* SysFileTree can't be used  */
  131.   END
  132.   ELSE DO
  133.     rc = SysFileTree(SearchPath, 'DirList', 'DO')
  134.     if DirList.0 <> 1 THEN DO           /* If dir does not exist or is odd */
  135.       SAY 'Directory in libpath ('SearchPath') not found!  SysFileTree='DirList.0
  136.       if DirList.0 > 0 THEN
  137.       DO ii=1 to DirList.0              /* If there was a value returned      */
  138.         SAY '-'DirList.ii               /* Share the erroroneous info         */
  139.       END
  140.       ITERATE                           /* Get next dir in libpath            */
  141.     END
  142.     SearchPath2 = TRANSLATE(DirList.1)  /* By fallthrough we have a valid dir */
  143.   END
  144.  
  145.  
  146.     /* Remove directories which are specified more than once */
  147.   DO ii=1 to cDirs                      /* For each directory already listed  */
  148.     FullPath = sDirName.ii           /* Make a copy of the directory name  */
  149.     IF LEFT(FullPath,1) = '.' THEN DO  /* Relative dirs need special care  */
  150.       FullPath = curdir||SUBSTR(FullPath,2)  /* SysFileTree can't be used  */
  151.     END
  152.     IF FullPath = SearchPath2 THEN DO   /* If this directory already in list */
  153.       SAY 'Duplicate directory: 'SearchPath' = 'sDirName.ii' -- 'SearchPath' dropped'
  154.       SearchPath = '*'                  /* Flag it so we don't search it      */
  155.       LEAVE                             /* Exit the hunt for duplicate dirs   */
  156.     END
  157.   END
  158.   IF SearchPath = '*' THEN ITERATE      /* If this is a duplicate directory   */
  159.  
  160.  
  161.     /* Remove directories with no matching DLLs */
  162.   rc = SysFileTree(SearchPath||SearchFiles, 'DirList', 'FO' )
  163.   if DirList.0 < 1 THEN DO
  164.     call lineout 'STDERR:', 'Directory contains no matching entries: 'SearchPath' removed from search'
  165.     ITERATE
  166.   END
  167.  
  168.  
  169.     /* Save directory info */
  170.   cDirs = cDirs+1                       /* We have another directory          */
  171.   sDirName.cDirs = SearchPath           /* The name of the directory          */
  172.   sDirIx.cDirs = 1                      /* Which line to parse next           */
  173.  
  174.     /* Execute a directory command on the libpath directory */
  175.   call lineout 'STDERR:', DirCmd SearchPath||DirCmdTail
  176.   ' 'DirCmd SearchPath||DirCmdTail
  177.  
  178.   cFiles = 0                            /* Assume no files                    */
  179.  
  180.     /* Read the lines into a 2 dimensional array */
  181.   DO WHILE QUEUED() > 0
  182.     cFiles = cFiles+1
  183.     PARSE PULL sFName.cDirs.cFiles      /* Put the filename in stem variable  */
  184.   END
  185.   sFName.cDirs.0 = cFiles               /* Set the count of files             */
  186.  
  187. END
  188.  
  189. sDirName.0 = cDirs                      /* Customary (just being compulsive)  */
  190.  
  191. call lineout 'STDERR:', 'Sort begun'
  192. /* 'pause' */
  193. do FOREVER                              /* Until 'exit'                       */
  194.   smallest = 0                          /* Assume no 'smallest' entry         */
  195.       
  196.     /* Find the first DLL name (lexically) among all the directories */
  197.   DO ii=1 to cDirs                      /* For each directory                 */
  198.     IF sDirIx.ii <= sFName.ii.0 THEN DO /* If still files we watch in this dir*/
  199.       ThisIx = sDirIx.ii                /* Get the index for this directory   */
  200.       StrNext = sFName.ii.ThisIx        /* Next DLL fname in this directory   */
  201.       IF smallest = 0 THEN DO
  202.         smallest = ii                   /* If no contenders yet, it is me   */
  203.         StrSmall = StrNext              /* Compare against this string        */
  204.         matchfound = 0
  205.       END
  206.       ELSE DO                           /* Need to compare against smallest   */
  207.         IF StrNext < StrSmall THEN DO   /* If this string is smaller          */
  208.           smallest = ii                 /* This is the new alphabetic first   */
  209.           StrSmall = StrNext            /* Keep the smallest string handy     */
  210.           matchfound = 0                /* And obviously it has no peers      */
  211.         END
  212.         ELSE IF StrNext = StrSmall THEN matchfound = 1
  213.       END                               /* Finding the first name lexically   */
  214.     END                                 /* If this directory still has names  */
  215.   END                                   /* Searching each directory           */
  216.  
  217.   IF smallest = 0 THEN LEAVE            /* If no smallest, all dirs exhausted */
  218.  
  219.   IF matchfound = 0 THEN DO             /* If no matches                      */
  220.     sDirIx.smallest = sDirIx.smallest+1 /* Just skip this filename            */
  221.   END
  222.   ELSE DO                               /* Collision: output all matches      */
  223.  
  224.       /* Output the known first entry */
  225.     rc = SysFileTree( sDirName.smallest||'\'||StrSmall, 'MatchList', 'F' )
  226.     FileInfo = LEFT(MatchList.1, 35)
  227.     OutDirName = sDirName.smallest
  228.     if LEFT(OutDirName,1) = '.' THEN DO /* Translate relative directory name  */
  229.       OutDirName = OutDirName' ('curdir||SUBSTR(OutDirName,2)')'
  230.     END
  231.     say '*'FileInfo LEFT(StrSmall,14) '*'OutDirName
  232.     sDirIx.smallest = sDirIx.smallest+1 /* Done with this entry               */
  233.  
  234.     DO ii=smallest+1 to cDirs           /* If this directory may have matched */
  235.       IF sDirIx.ii <= sFName.ii.0 THEN DO   /* If still files this directory  */
  236.         ThisIx = sDirIx.ii              /* Get the index for this directory   */
  237.         StrNext = sFName.ii.ThisIx      /* Next DLL fname in this directory   */
  238.         IF StrNext = StrSmall THEN DO
  239.           rc = SysFileTree( sDirName.ii||'\'||StrSmall, 'MatchList', 'F' )
  240.           FileInfo = LEFT(MatchList.1, 35)
  241.           OutDirName = sDirName.ii
  242.           if LEFT(OutDirName,1) = '.' THEN DO /* Translate relative directory name  */
  243.             OutDirName = OutDirName' ('curdir||SUBSTR(OutDirName,2)')'
  244.           END
  245.           say ' 'FileInfo LEFT(StrSmall,14) ' 'OutDirName
  246.           sDirIx.ii = sDirIx.ii+1       /* Done with this entry too           */
  247.         END                             /* Printing another match             */
  248.       END                               /* Directory with entries             */
  249.     END                                 /* For all the later directories      */
  250.   END                                   /* Print a dll collision              */
  251.  
  252. END                                     /* While there is a smallest          */
  253.  
  254. exit 0                                  /* And done                           */
  255.