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. |
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. |
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 | " |