diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+Copyright (c) 2009 Dan Knapp
+
+Permission is hereby granted, free of charge, to any person
+obtaining a copy of this software and associated documentation
+files (the "Software"), to deal in the Software without
+restriction, including without limitation the rights to use,
+copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the
+Software is furnished to do so, subject to the following
+conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
diff --git a/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,5 @@
+#!/usr/bin/env runhaskell
+
+import Distribution.Simple
+
+main = defaultMain
diff --git a/System/Daemonize.hs b/System/Daemonize.hs
new file mode 100644
--- /dev/null
+++ b/System/Daemonize.hs
@@ -0,0 +1,86 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+module System.Daemonize (
+                         DaemonOptions(..),
+                         defaultDaemonOptions,
+                         daemonize
+                        )
+  where
+
+import qualified Control.Exception as Exception
+import Foreign
+import Foreign.C
+import System.IO
+import qualified System.Posix as POSIX
+
+
+data DaemonOptions = DaemonOptions {
+    daemonShouldChangeDirectory :: Bool,
+    daemonShouldRedirectStandardStreams :: Bool,
+    daemonShouldCloseAllStreams :: Bool,
+    daemonFileDescriptorsToLeaveOpen :: [POSIX.Fd],
+    daemonShouldIgnoreSignals :: Bool,
+    daemonUserToChangeTo :: Maybe String,
+    daemonGroupToChangeTo :: Maybe String
+  }
+
+
+defaultDaemonOptions :: DaemonOptions
+defaultDaemonOptions = DaemonOptions {
+                         daemonShouldChangeDirectory = True,
+                         daemonShouldRedirectStandardStreams = False,
+                         daemonShouldCloseAllStreams = True,
+                         daemonFileDescriptorsToLeaveOpen = [],
+                         daemonShouldIgnoreSignals = True,
+                         daemonUserToChangeTo = Nothing,
+                         daemonGroupToChangeTo = Nothing
+                       }
+
+
+foreign import ccall "daemon" c_daemon :: CInt -> CInt -> IO CInt
+
+
+daemonize :: DaemonOptions -> IO ()
+daemonize options = do
+  case daemonGroupToChangeTo options of
+    Nothing -> return ()
+    Just groupName -> do
+      groupEntry <- POSIX.getGroupEntryForName groupName
+      POSIX.setGroupID $ POSIX.groupID groupEntry
+  case daemonUserToChangeTo options of
+    Nothing -> return ()
+    Just userName -> do
+      userEntry <- POSIX.getUserEntryForName userName
+      POSIX.setUserID $ POSIX.userID userEntry
+  let c_shouldChangeDirectory
+        = if daemonShouldChangeDirectory options
+            then 0
+            else 1
+      c_shouldRedirectStandardStreams
+        = if daemonShouldRedirectStandardStreams options
+            then 0
+            else 1
+  throwErrnoIfMinus1 "daemonize"
+                     $ c_daemon c_shouldChangeDirectory
+                                c_shouldRedirectStandardStreams
+  if daemonShouldIgnoreSignals options
+    then do
+      POSIX.installHandler POSIX.sigTTOU POSIX.Ignore Nothing
+      POSIX.installHandler POSIX.sigTTIN POSIX.Ignore Nothing
+      POSIX.installHandler POSIX.sigTSTP POSIX.Ignore Nothing
+      return ()
+    else return ()
+  if daemonShouldCloseAllStreams options
+    then do
+      mapM hClose [stdin, stdout, stderr]
+      let closeLoop i | i == 65536 = return ()
+                      | otherwise = do
+                          if not $ elem (POSIX.Fd i)
+                                        $ daemonFileDescriptorsToLeaveOpen options
+                            then Exception.catch (POSIX.closeFd $ POSIX.Fd i)
+                                   (\e -> do
+                                      return (e :: Exception.SomeException)
+                                      return ())
+                            else return ()
+                          closeLoop $ i + 1
+      closeLoop 0
+    else return ()
diff --git a/direct-daemonize.cabal b/direct-daemonize.cabal
new file mode 100644
--- /dev/null
+++ b/direct-daemonize.cabal
@@ -0,0 +1,22 @@
+name: direct-daemonize
+version: 1.0
+cabal-version: >= 1.2
+build-type: Simple
+license: BSD3
+license-file: LICENSE
+copyright: Copyright (c) 2009 Dan Knapp
+author: Dan Knapp
+maintainer: dankna@gmail.com
+homepage: http://dankna.com/software/
+bug-reports: http://dankna.com/issues/create/
+category: System
+synopsis: Library to switch to daemon mode using built-in OS facilities.
+description:
+  This package is a wrapper around the daemon() function on BSD-like Unices,
+  including Mac OS X and glibc-based Linux distributions.  It does not function on
+  other systems.
+
+Library
+  exposed-modules: System.Daemonize
+  build-depends: base >= 4.1 && < 5,
+                 unix >= 2.4.0.1
