summary refs log tree commit diff stats
path: root/lib/pure/ospaths.nim
diff options
context:
space:
mode:
Diffstat (limited to 'lib/pure/ospaths.nim')
-rw-r--r--lib/pure/ospaths.nim32
1 files changed, 29 insertions, 3 deletions
diff --git a/lib/pure/ospaths.nim b/lib/pure/ospaths.nim
index 9fc816f2f..56671ee62 100644
--- a/lib/pure/ospaths.nim
+++ b/lib/pure/ospaths.nim
@@ -10,7 +10,7 @@
 # Included by the ``os`` module but a module in its own right for NimScript
 # support.
 
-when isMainModule:
+when not declared(os):
   {.pragma: rtl.}
   import strutils
 
@@ -556,12 +556,20 @@ when declared(getEnv) or defined(nimscript):
           yield substr(s, first, last-1)
           inc(last)
 
-  proc findExe*(exe: string): string {.
+  when not defined(windows) and declared(os):
+    proc checkSymlink(path: string): bool =
+      var rawInfo: Stat
+      if lstat(path, rawInfo) < 0'i32: result = false
+      else: result = S_ISLNK(rawInfo.st_mode)
+
+  proc findExe*(exe: string, followSymlinks: bool = true): string {.
     tags: [ReadDirEffect, ReadEnvEffect, ReadIOEffect].} =
     ## Searches for `exe` in the current working directory and then
     ## in directories listed in the ``PATH`` environment variable.
     ## Returns "" if the `exe` cannot be found. On DOS-like platforms, `exe`
     ## is added the `ExeExt <#ExeExt>`_ file extension if it has none.
+    ## If the system supports symlinks it also resolves them until it
+    ## meets the actual file. This behavior can be disabled if desired.
     result = addFileExt(exe, ExeExt)
     if existsFile(result): return
     var path = string(getEnv("PATH"))
@@ -572,7 +580,25 @@ when declared(getEnv) or defined(nimscript):
                result
       else:
         var x = expandTilde(candidate) / result
-      if existsFile(x): return x
+      if existsFile(x):
+        when not defined(windows) and declared(os):
+          while followSymlinks: # doubles as if here
+            if x.checkSymlink:
+              var r = newString(256)
+              var len = readlink(x, r, 256)
+              if len < 0:
+                raiseOSError(osLastError())
+              if len > 256:
+                r = newString(len+1)
+                len = readlink(x, r, len)
+              setLen(r, len)
+              if isAbsolute(r):
+                x = r
+              else:
+                x = parentDir(x) / r
+            else:
+              break
+        return x
     result = ""
 
 when defined(nimscript) or (defined(nimdoc) and not declared(os)):