diff --git a/System/Environment/Executable.hs b/System/Environment/Executable.hs
--- a/System/Environment/Executable.hs
+++ b/System/Environment/Executable.hs
@@ -21,6 +21,8 @@
  
  * Linux
 
+ * FreeBSD (tested on FreeBSD 6.4)
+
  * \*BSD (untested)
  
  * Solaris (untested, and probably works on Solaris 10 only) 
@@ -66,7 +68,7 @@
 
 #ifdef freebsd_HOST_OS
 #define SUPPORTED_OS
-import System.Environment.Executable.BSD
+import System.Environment.Executable.FreeBSD
 #endif
 
 #ifdef netbsd_HOST_OS
diff --git a/System/Environment/Executable/BSD.hs b/System/Environment/Executable/BSD.hs
--- a/System/Environment/Executable/BSD.hs
+++ b/System/Environment/Executable/BSD.hs
@@ -1,4 +1,5 @@
 
+-- It seems that on FreeBSD, /proc is not mounted by default
 
 {-
 symbolic links to the executable:
diff --git a/System/Environment/Executable/FreeBSD.hs b/System/Environment/Executable/FreeBSD.hs
new file mode 100644
--- /dev/null
+++ b/System/Environment/Executable/FreeBSD.hs
@@ -0,0 +1,148 @@
+
+-- | This code uses @sysctl@ and @KERN_PROC_PATHNAME@,
+-- if we are on FreeBSD 6.0 or newer, and falls back to procfs
+-- on older FreeBSD-s.
+
+{-# LANGUAGE CPP, ForeignFunctionInterface #-}
+module System.Environment.Executable.FreeBSD
+  ( getExecutablePath  
+  , getPID
+  )
+  where
+  
+import Data.Bits
+import Data.Word
+import Data.Int
+
+import Data.Char
+import Data.List
+
+import Control.Monad
+
+import Foreign
+import Foreign.C
+
+import System.Posix
+
+--------------------------------------------------------------------------------
+
+#define CTL_KERN             1 
+#define KERN_PROC           14    
+#define KERN_PROC_PATHNAME  12   
+-- KERN_PROC_PATHNAME exists from FreeBSD 6.0
+
+#define ENOMEM    12
+
+#define KERN_OSTYPE    1
+#define KERN_OSRELEASE 2
+#define KERN_OSREV     3
+-- KERN_OSREV gives back a totally random-looking
+-- number with a totally undocumented meaning, yeah, fuck that.
+
+#define KERN_VERSION   4
+
+--------------------------------------------------------------------------------
+
+-- the only data point is the string "6.4-RELEASE"
+-- yay for undocumented queries!
+-- not let's try to parse that
+parseOSRelease :: String -> Maybe (Int,Int)
+parseOSRelease text = 
+  if major /= "" && temp1 /= "" && minor /= "" && dot == '.'
+    then Just (read major, read minor)
+    else Nothing
+  where
+    (major,temp1) = span isDigit text
+    (dot:temp2)   = temp1
+    (minor,rest)  = span isDigit temp2
+
+getExecutablePath :: IO FilePath
+getExecutablePath = do
+{-
+  osrev <- getKernInt KERN_OSREV
+  ostype <- getKernString KERN_OSTYPE 256
+  kver  <- getKernString KERN_VERSION 256
+  print osrev
+  print ostype
+  print kver
+-}
+
+  osrel  <- getKernString KERN_OSRELEASE 256
+--  print osrel
+--  print $ parseOSRelease osrel
+  case parseOSRelease osrel of
+    Just (maj,_) -> if maj >= 6
+      then getExecutablePathSysCtl 256
+      else getExecutablePathProcFS
+    Nothing -> getExecutablePathProcFS
+
+--------------------------------------------------------------------------------
+
+-- int sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp, size_t newlen);
+foreign import ccall "sys/sysctl.h sysctl" 
+  sysctl :: Ptr CInt -> CUInt -> Ptr a -> Ptr CSize -> Ptr a -> CSize -> IO CInt
+
+-- brrrrrrr...
+foreign import ccall "errno.h &errno" errno :: Ptr CInt
+      
+getKernString :: CInt -> Int -> IO String
+getKernString what len = do
+  allocaArray 2 $ \mib -> do
+    pokeArray mib [ CTL_KERN, what ]  
+    alloca $ \buflen -> do
+      poke buflen (fromIntegral len :: CSize)
+      allocaBytes len $ \buf -> do
+        sysctl mib 2 buf buflen nullPtr 0
+        peekCString buf
+
+getKernInt :: CInt -> IO CInt
+getKernInt what = do
+  allocaArray 2 $ \mib -> do
+    pokeArray mib [ CTL_KERN, what ]  
+    alloca $ \posrev -> do
+      alloca $ \buflen -> do
+        poke buflen (fromIntegral (sizeOf (undefined :: CInt)) :: CSize)
+        sysctl mib 2 posrev buflen nullPtr 0
+        peek posrev
+      
+getExecutablePathSysCtl :: Int -> IO FilePath
+getExecutablePathSysCtl size = do
+  allocaArray 4 $ \mib -> do
+    pokeArray mib [ CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 ]   -- @-1@ is current process (could be a PID)
+    allocaBytes size $ \buf -> do
+      alloca $ \buflen -> do
+        poke buflen (fromIntegral size :: CSize)
+        err <- sysctl mib 4 buf buflen nullPtr 0
+        case err of
+          0 -> peekCString buf
+          -1 -> do
+            errn <- peek errno
+            case errn of
+              ENOMEM -> getExecutablePathSysCtl (size*2)
+              _ -> error "getExecutablePath: unknown system error"          
+
+{-
+int mib[4];
+mib[0] = CTL_KERN;
+mib[1] = KERN_PROC;
+mib[2] = KERN_PROC_PATHNAME;
+mib[3] = -1;
+char buf[1024];
+size_t cb = sizeof(buf);
+sysctl(mib, 4, buf, &cb, NULL, 0);
+-}
+
+--------------------------------------------------------------------------------
+
+-- procfs fallback for FreeBSD < 6.0
+
+getPID :: IO Int
+getPID = liftM fromIntegral $ getProcessID
+
+getExecutablePathProcFS :: IO FilePath
+getExecutablePathProcFS = do
+  pid <- getPID
+  fname <- readSymbolicLink $ "/proc/" ++ show pid ++ "/file"
+  return fname
+
+--------------------------------------------------------------------------------
diff --git a/executable-path.cabal b/executable-path.cabal
--- a/executable-path.cabal
+++ b/executable-path.cabal
@@ -1,5 +1,5 @@
 Name:                executable-path
-Version:             0.0
+Version:             0.0.1
 Synopsis:            Finding out the full path of the executable.
 
 Description:         The documentation of "System.Environment.getProgName" says that
@@ -26,9 +26,9 @@
 
 Library
   if flag(splitBase)
-    Build-Depends:       base >=3, filepath
+    Build-Depends:       base >= 3 && < 5 , filepath
   else
-    Build-Depends:       base < 3
+    Build-Depends:       base >= 2 && < 3
     
   Exposed-Modules:     System.Environment.Executable   
   Extensions:          ForeignFunctionInterface, CPP, EmptyDataDecls
@@ -46,7 +46,11 @@
     Build-Depends:       unix
     Other-Modules:       System.Environment.Executable.Linux
     
-  if os(freebsd) || os(openbsd) || os(netbsd)
+  if os(freebsd) 
+    Build-Depends:       unix
+    Other-Modules:       System.Environment.Executable.FreeBSD
+
+  if os(openbsd) || os(netbsd)
     Build-Depends:       unix
     Other-Modules:       System.Environment.Executable.BSD
 
