Ticket #258: libbasic_fix_1_of_1_rev_1c6f89bd0de6_Win32__fix__Win32OperatingSystem_class____pathOfCommand__.patch

File libbasic_fix_1_of_1_rev_1c6f89bd0de6_Win32__fix__Win32OperatingSystem_class____pathOfCommand__.patch, 8.5 KB (added by jan vrany, 5 years ago)
  • PCFilename.st

    # HG changeset patch
    # User Jan Vrany <jan.vrany@fit.cvut.cz>
    # Date 1547812634 0
    #      Fri Jan 18 11:57:14 2019 +0000
    # Branch jv
    # Node ID 1c6f89bd0de6ffc9c3c8445f79247a6d324cdc23
    # Parent  27c3cc6f53712b600b8f0e45cc168f5a1a67de84
    Win32: fix `Win32OperatingSystem class >> pathOfCommand:`
    
    The original implementation was bogus - in some caes it uses
    hardcoded extension list with typos, in some other it used
    `#executableFileExtensions`, inconsistent handling of absolute
    and relative paths and so on.
    
    This commit sanitize the code, making it correct (I hope) and
    robust.
    
    diff -r 27c3cc6f5371 -r 1c6f89bd0de6 PCFilename.st
    a b  
    618618        ^ true.
    619619    ].
    620620
    621     (#('bat' 'cmd') includes:self suffix asLowercase) ifTrue:[
     621    (OperatingSystem executableFileExtensions includes:self suffix asLowercase) ifTrue:[
    622622        ^ (OperatingSystem isValidPath:osName)     
    623623            and:[(OperatingSystem isDirectory:osName) not].
    624624    ].
     
    634634        OperatingSystem getBinaryType:'c:\' 
    635635    "
    636636
    637 
    638637    "Created: / 16-10-1997 / 13:19:10 / cg"
    639638    "Modified: / 09-09-1998 / 20:17:52 / cg"
    640     "Modified: / 23-08-2011 / 21:24:57 / jv"
     639    "Modified: / 18-01-2019 / 11:08:51 / jv"
    641640!
    642641
    643642isExplicitRelative
     
    992991    ^ '$Header$'
    993992!
    994993
     994version_HG
     995
     996    ^ '$Changeset: <not expanded> $'
     997!
     998
    995999version_SVN
    9961000    ^ '$Id$'
    9971001! !
  • Win32OperatingSystem.st

    diff -r 27c3cc6f5371 -r 1c6f89bd0de6 Win32OperatingSystem.st
    a b  
    2020AbstractOperatingSystem subclass:#Win32OperatingSystem
    2121        instanceVariableNames:''
    2222        classVariableNames:'CurrentDirectory DomainName HostName Initialized LastOsTimeHi
    23                 LastOsTimeLow LastTimeInfo LastTimeInfoIsLocal'
     23                LastOsTimeLow LastTimeInfo LastTimeInfoIsLocal PathExtensions'
    2424        poolDictionaries:'Win32Constants'
    2525        category:'OS-Windows'
    2626!
     
    39233923    self primitiveFailed
    39243924!
    39253925
    3926 pathOfCommand:aCommand
     3926pathOfCommand:aString
    39273927    "find where aCommand's executable file is;
    39283928     return its full pathName if there is such a command, otherwise
    39293929     return nil."
    39303930
    3931     |cmdFile path rentry rpath hasSuffix|
    3932 
    3933     cmdFile := aCommand asFilename.
    3934     cmdFile isAbsolute ifTrue:[
    3935         cmdFile isExecutableProgram ifTrue:[
    3936             ^ aCommand
    3937         ].
    3938         cmdFile suffix isEmpty ifTrue:[
    3939             ((path := cmdFile withSuffix: 'com') exists
    3940                 or:[ (path := cmdFile withSuffix: 'exe') exists
    3941                 or:[ (path := cmdFile withSuffix: 'bar') exists ]]) ifTrue:[
    3942                     path isExecutable ifTrue:[
    3943                         ^ path pathName
    3944                     ].
     3931    |path ext search rentry|
     3932
     3933    (aString includes: Filename separator) ifTrue:[
     3934        "/ If `aString` contains path separator, it is either
     3935        "/ relative or absolute path. In that case:
     3936        "/ * first check whether there's file named `aString`.
     3937        "/ * second, if `aString` has no extension, try same name  with
     3938        "/   all executable file extensions.
     3939        "/ If anything is found, return the absolute path.
     3940        path := aString asFilename.
     3941        ext := path suffix.
     3942        ext isEmptyOrNil ifTrue:[
     3943            self executableFileExtensions do:[:e |
     3944                path := path withSuffix: e.
     3945                (path exists and:[ path isRegularFile ]) ifTrue:[
     3946                    ^ path asAbsoluteFilename pathName.
    39453947                ].
     3948            ].
     3949        ] ifFalse:[
     3950            (self executableFileExtensions includes: ext) ifTrue:[
     3951                (path exists and:[ path isRegularFile ]) ifTrue:[
     3952                    ^ path asAbsoluteFilename pathName.
     3953                ].
     3954            ].
    39463955        ].
    3947         ^ nil
    3948     ].
    3949 
    3950     (aCommand includes:Filename separator) ifTrue:[
    3951         path := Filename currentDirectory construct:aCommand.
    3952         path isExecutableProgram ifTrue:[
    3953             ^ path pathName.
    3954         ].
    3955         ^ nil
    3956     ].
    3957 
    3958     "search in all directories of PATH.
    3959      If there no extension, add the known extensions."
    3960     path := (self getEnvironment:'PATH') ? ''.
    3961     (rentry := self registryEntry key: 'HKEY_CURRENT_USER\Environment') notNil ifTrue:[
    3962         rpath := rentry valueNamed: 'PATH'.
    3963         rpath notNil ifTrue:[
    3964             path := path , self pathSeparator , rpath
    3965         ].
    3966     ].
    3967     path := '.;', path.
    3968     hasSuffix := cmdFile suffix notEmpty.
    3969 
    3970     (path asCollectionOfSubstringsSeparatedBy:self pathSeparator) do:[:eachDirectory |
    3971         |file|
    3972 
    3973         eachDirectory isEmpty ifTrue:[
    3974             file := cmdFile
    3975         ] ifFalse:[
    3976             file := eachDirectory asFilename construct:aCommand.
    3977         ].
    3978         hasSuffix ifTrue:[
    3979             file isExecutableProgram ifTrue:[
    3980                 ^ file pathName.
    3981             ].
    3982         ] ifFalse:[
    3983             self executableFileExtensions do:[:ext |
    3984                 |fExt|
    3985 
    3986                 fExt := file withSuffix:ext.
    3987                 fExt isExecutableProgram ifTrue:[
    3988                     ^ fExt pathName.
    3989                 ].
    3990             ].
    3991         ].
    3992     ].
     3956    ] ifFalse:[
     3957        "/ If it does not contain path separator, then it's
     3958        "/ 'simple' command name that is to be looked up in PATH.
     3959
     3960        "/ First, construct the PATH.
     3961
     3962        "/ Start with current working directory..."
     3963        search := Array with: Filename currentDirectory.
     3964
     3965        "/ ...then add all directories in PATH environment variable...
     3966        search := search , (((self getEnvironment:'PATH') ? '') splitBy: $;).
     3967
     3968        "/ ...and finally get PATH from registry."
     3969        (rentry := self registryEntry key: 'HKEY_CURRENT_USER\Environment') notNil ifTrue:[
     3970            search := search , (((rentry valueNamed: 'PATH') ? '') splitBy: $;).
     3971        ].
     3972
     3973        "/ Second, search each directory for given command:
     3974        search do:[:directoryName |
     3975            | directory |
     3976
     3977            directory := directoryName asFilename.
     3978            (directory isAbsolute and:[ directory isDirectory ]) ifTrue:[
     3979                "/ If such directory exists, construct the program name
     3980                "/ as if it were in that `directory` and see if it is.
     3981
     3982                "/ This is a trick: we call this method recursively passing
     3983                "/ an ABSOLUTE path so it would fall into code in first part of
     3984                "/ this method. Note the ^ nil there...
     3985                path := self pathOfCommand: (directory pathName , Filename separator , aString).
     3986                "/ ...so if this method returns something, we found it and
     3987                "/ just return it.
     3988                path notNil ifTrue:[ ^ path ].
     3989            ].
     3990        ].
     3991    ].
     3992
     3993    "/ If we reach this point, no such executable was found
     3994    "/ along the path, so give up and return nil.
    39933995    ^ nil
    39943996
    39953997    "
    39963998     OperatingSystem pathOfCommand:'bcc32'
    39973999     OperatingSystem pathOfCommand:'diff'
    3998      OperatingSystem pathOfCommand:'cvs'
     4000     OperatingSystem pathOfCommand:'cvs'   
    39994001     OperatingSystem pathOfCommand:'cvs.exe'
    40004002     OperatingSystem pathOfCommand:'stx.exe'
    40014003     OperatingSystem pathOfCommand:'stx'
     
    40044006
    40054007    "Modified: / 20-01-2012 / 13:32:55 / cg"
    40064008    "Modified: / 01-07-2015 / 06:04:56 / Jan Vrany <jan.vrany@fit.cvut.cz>"
    4007 
     4009    "Modified: / 18-01-2019 / 11:46:23 / jv"
    40084010!
    40094011
    40104012primExec:commandPath commandLine:commandLine environment:environmentOrNil
     
    83348336    "return a collection of extensions for executable program files.
    83358337     Only req'd for msdos like systems ..."
    83368338
    8337     ^ #('com' 'exe' 'bat' 'cmd')
     8339    | pathext |
     8340
     8341    PathExtensions isNil ifTrue:[
     8342        "/ First, initialize to some (safe) default in case
     8343        "/ PATHEXT is not available.
     8344        "/
     8345        "/ Note: maybe we should also add .ps1 these days.
     8346        PathExtensions := #('com' 'exe' 'bat' 'cmd').
     8347
     8348        "/ If PATHEXT environment is available, use all extensions
     8349        "/ in that one but make sure defaults aboce are there
     8350        "/ in case of malformed PATHEXT.
     8351
     8352        pathext := self getEnvironment:'PATHEXT'. 
     8353        pathext notNil ifTrue:[
     8354            pathext := pathext asLowercase.
     8355            (pathext splitBy: $;) do:[:dotext |
     8356                | ext |
     8357
     8358                ext := dotext copyFrom: 2.
     8359                (PathExtensions includes: ext) ifFalse:[
     8360                    PathExtensions := PathExtensions copyWith: ext.
     8361                ].
     8362            ].
     8363        ].
     8364    ].
     8365    ^ PathExtensions
     8366
     8367    "
     8368    OperatingSystem executableFileExtensions
     8369    "
    83388370
    83398371    "Created: / 02-05-1997 / 11:42:29 / cg"
    8340     "Modified: / 23-08-2011 / 21:14:45 / jv"
     8372    "Modified: / 18-01-2019 / 11:06:55 / jv"
    83418373!
    83428374
    83438375expandEnvironmentStrings:aString