diff --git a/LICENSE b/LICENSE
new file mode 100644
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,26 @@
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+  * Redistributions of source code must retain the above copyright
+    notice, this list of conditions and the following disclaimer.
+
+  * Redistributions in binary form must reproduce the above copyright
+    notice, this list of conditions and the following disclaimer in the
+    documentation and/or other materials provided with the distribution.
+
+  * The names of its contributors may not be used to endorse or promote
+    products derived from this software without specific prior written
+    permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/README b/README
new file mode 100644
--- /dev/null
+++ b/README
@@ -0,0 +1,38 @@
+syslog(3) for Haskell_
+======================
+
+:Latest Release: hsyslog-1.2.tar.gz_
+:Darcs:          darcs_ get --partial http://cryp.to/hsyslog/
+
+Synopsis
+--------
+
+  This modules provides FFI bindings to ``syslog(3)``. The
+  bindings are somewhat incomplete, i.e. there is no way to set
+  log-masks. Patches are welcome. Process the file with
+  ``hsc2hs`` to obtain a usable Haskell module.
+
+Documentation
+-------------
+
+  `Reference Documentation`_
+     Haddock-generated reference of all exported functions.
+
+Copyleft
+--------
+
+  Copyright (c) 2008 Peter Simons <simons@cryp.to>. All rights
+  reserved. This software is released under `BSD-style license
+  <LICENSE>`_.
+
+-----------------------------------------------------------------
+
+`[Homepage] <http://cryp.to/>`_
+
+.. _Haskell: http://haskell.org/
+
+.. _darcs: http://abridgegame.org/darcs/
+
+.. _hsyslog-1.2.tar.gz: http://cryp.to/hsyslog/hsyslog-1.2.tar.gz
+
+.. _Reference Documentation: docs/index.html
diff --git a/Setup.lhs b/Setup.lhs
new file mode 100644
--- /dev/null
+++ b/Setup.lhs
@@ -0,0 +1,8 @@
+#!/usr/bin/env runhaskell
+
+> module Main (main) where
+>
+> import Distribution.Simple
+>
+> main :: IO ()
+> main = defaultMain
diff --git a/System/Posix/Syslog.hsc b/System/Posix/Syslog.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Syslog.hsc
@@ -0,0 +1,210 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+{- |
+   Module      :  System.Posix.Syslog
+   Copyright   :  (c) 2008 Peter Simons
+   License     :  BSD3
+
+   Maintainer  :  simons@cryp.to
+   Stability   :  provisional
+   Portability :  Posix
+
+   FFI bindings to Unix's @syslog(3)@. Process this file
+   with @hsc2hs@ to obtain a Haskell module.
+-}
+
+module System.Posix.Syslog where
+
+import System.IO
+import Control.Exception ( bracket_ )
+import Foreign.C
+
+#include <syslog.h>
+
+-- * Marshaled Data Types
+
+-- |Log messages are prioritized.
+
+data Priority
+  = Emergency   -- ^ system is unusable
+  | Alert       -- ^ action must be taken immediately
+  | Critical    -- ^ critical conditions
+  | Error       -- ^ error conditions
+  | Warning     -- ^ warning conditions
+  | Notice      -- ^ normal but significant condition
+  | Info        -- ^ informational
+  | Debug       -- ^ debug-level messages
+  deriving (Eq, Bounded, Show)
+
+instance Enum Priority where
+  toEnum #{const LOG_EMERG}   = Emergency
+  toEnum #{const LOG_ALERT}   = Alert
+  toEnum #{const LOG_CRIT}    = Critical
+  toEnum #{const LOG_ERR}     = Error
+  toEnum #{const LOG_WARNING} = Warning
+  toEnum #{const LOG_NOTICE}  = Notice
+  toEnum #{const LOG_INFO}    = Info
+  toEnum #{const LOG_DEBUG}   = Debug
+  toEnum i = error (showString "Syslog.Priority cannot be mapped from value " (show i))
+
+  fromEnum Emergency = #{const LOG_EMERG}
+  fromEnum Alert     = #{const LOG_ALERT}
+  fromEnum Critical  = #{const LOG_CRIT}
+  fromEnum Error     = #{const LOG_ERR}
+  fromEnum Warning   = #{const LOG_WARNING}
+  fromEnum Notice    = #{const LOG_NOTICE}
+  fromEnum Info      = #{const LOG_INFO}
+  fromEnum Debug     = #{const LOG_DEBUG}
+
+-- |Syslog distinguishes various system facilities. Most
+-- applications should log in 'USER'.
+
+data Facility
+  = KERN        -- ^ kernel messages
+  | USER        -- ^ user-level messages (default unless set otherwise)
+  | MAIL        -- ^ mail system
+  | DAEMON      -- ^ system daemons
+  | AUTH        -- ^ security\/authorization messages
+  | SYSLOG      -- ^ messages generated internally by syslogd
+  | LPR         -- ^ line printer subsystem
+  | NEWS        -- ^ network news subsystem
+  | UUCP        -- ^ UUCP subsystem
+  | CRON        -- ^ clock daemon
+  | AUTHPRIV    -- ^ security\/authorization messages (private)
+  | FTP         -- ^ ftp daemon
+  | LOCAL0      -- ^ reserved for local use
+  | LOCAL1      -- ^ reserved for local use
+  | LOCAL2      -- ^ reserved for local use
+  | LOCAL3      -- ^ reserved for local use
+  | LOCAL4      -- ^ reserved for local use
+  | LOCAL5      -- ^ reserved for local use
+  | LOCAL6      -- ^ reserved for local use
+  | LOCAL7      -- ^ reserved for local use
+  deriving (Eq, Bounded, Show)
+
+instance Enum Facility where
+  toEnum #{const LOG_KERN}      = KERN
+  toEnum #{const LOG_USER}      = USER
+  toEnum #{const LOG_MAIL}      = MAIL
+  toEnum #{const LOG_DAEMON}    = DAEMON
+  toEnum #{const LOG_AUTH}      = AUTH
+  toEnum #{const LOG_SYSLOG}    = SYSLOG
+  toEnum #{const LOG_LPR}       = LPR
+  toEnum #{const LOG_NEWS}      = NEWS
+  toEnum #{const LOG_UUCP}      = UUCP
+  toEnum #{const LOG_CRON}      = CRON
+  toEnum #{const LOG_AUTHPRIV}  = AUTHPRIV
+  toEnum #{const LOG_FTP}       = FTP
+  toEnum #{const LOG_LOCAL0}    = LOCAL0
+  toEnum #{const LOG_LOCAL1}    = LOCAL1
+  toEnum #{const LOG_LOCAL2}    = LOCAL2
+  toEnum #{const LOG_LOCAL3}    = LOCAL3
+  toEnum #{const LOG_LOCAL4}    = LOCAL4
+  toEnum #{const LOG_LOCAL5}    = LOCAL5
+  toEnum #{const LOG_LOCAL6}    = LOCAL6
+  toEnum #{const LOG_LOCAL7}    = LOCAL7
+  toEnum i = error ("Syslog.Facility cannot be mapped to value " ++ show i)
+
+  fromEnum KERN      = #{const LOG_KERN}
+  fromEnum USER      = #{const LOG_USER}
+  fromEnum MAIL      = #{const LOG_MAIL}
+  fromEnum DAEMON    = #{const LOG_DAEMON}
+  fromEnum AUTH      = #{const LOG_AUTH}
+  fromEnum SYSLOG    = #{const LOG_SYSLOG}
+  fromEnum LPR       = #{const LOG_LPR}
+  fromEnum NEWS      = #{const LOG_NEWS}
+  fromEnum UUCP      = #{const LOG_UUCP}
+  fromEnum CRON      = #{const LOG_CRON}
+  fromEnum AUTHPRIV  = #{const LOG_AUTHPRIV}
+  fromEnum FTP       = #{const LOG_FTP}
+  fromEnum LOCAL0    = #{const LOG_LOCAL0}
+  fromEnum LOCAL1    = #{const LOG_LOCAL1}
+  fromEnum LOCAL2    = #{const LOG_LOCAL2}
+  fromEnum LOCAL3    = #{const LOG_LOCAL3}
+  fromEnum LOCAL4    = #{const LOG_LOCAL4}
+  fromEnum LOCAL5    = #{const LOG_LOCAL5}
+  fromEnum LOCAL6    = #{const LOG_LOCAL6}
+  fromEnum LOCAL7    = #{const LOG_LOCAL7}
+
+-- |Options for the syslog service. Set with 'withSyslog'.
+
+data Option
+  = PID       -- ^ log the pid with each message
+  | CONS      -- ^ log on the console if errors in sending
+  | ODELAY    -- ^ delay open until first @syslog()@ (default)
+  | NDELAY    -- ^ don't delay open
+  | NOWAIT    -- ^ don't wait for console forks: DEPRECATED
+  | PERROR    -- ^ log to 'stderr' as well
+  deriving (Eq, Bounded, Show)
+
+instance Enum Option where
+  toEnum #{const LOG_PID}     = PID
+  toEnum #{const LOG_CONS}    = CONS
+  toEnum #{const LOG_ODELAY}  = ODELAY
+  toEnum #{const LOG_NDELAY}  = NDELAY
+  toEnum #{const LOG_NOWAIT}  = NOWAIT
+  toEnum #{const LOG_PERROR}  = PERROR
+  toEnum i = error ("Syslog.Option cannot be mapped to value " ++ show i)
+
+  fromEnum PID     = #{const LOG_PID}
+  fromEnum CONS    = #{const LOG_CONS}
+  fromEnum ODELAY  = #{const LOG_ODELAY}
+  fromEnum NDELAY  = #{const LOG_NDELAY}
+  fromEnum NOWAIT  = #{const LOG_NOWAIT}
+  fromEnum PERROR  = #{const LOG_PERROR}
+
+-- * Haskell API to syslog
+
+-- |Bracket an 'IO' computation between calls to '_openlog'
+-- and '_closelog'. Since these settings are for the
+-- /process/, multiple calls to this function will,
+-- unfortunately, overwrite each other.
+--
+-- Example:
+--
+-- > main = withSyslog "my-ident" [PID, PERROR] USER $ do
+-- >          putStrLn "huhu"
+-- >          syslog Debug "huhu"
+
+withSyslog :: String -> [Option] -> Facility -> IO a -> IO a
+withSyslog ident opts facil f = do
+  let opt = toEnum . sum . map fromEnum $ opts
+  let fac = toEnum . fromEnum           $ facil
+  withCString ident $ \p ->
+    bracket_ (_openlog p opt fac) (_closelog) f
+
+-- |Log a message with the given priority.
+
+syslog :: Priority -> String -> IO ()
+syslog l msg =
+  withCString (safeMsg msg)
+    (\p -> _syslog (toEnum (fromEnum l)) p)
+
+-- * Helpers
+
+-- | @useSyslog ident@ @=@ @withSyslog ident [PID, PERROR] USER@
+
+useSyslog :: String -> IO a -> IO a
+useSyslog ident = withSyslog ident [PID, PERROR] USER
+
+-- |Escape any occurances of \'@%@\' in a string, so that it
+-- is safe to pass it to '_syslog'. The 'syslog' wrapper
+-- does this automatically.
+
+safeMsg :: String -> String
+safeMsg []       = []
+safeMsg ('%':xs) = '%' : '%' : safeMsg xs
+safeMsg ( x :xs) = x : safeMsg xs
+
+-- * Low-level C functions
+
+foreign import ccall unsafe "closelog" _closelog ::
+  IO ()
+
+foreign import ccall unsafe "openlog" _openlog ::
+  CString -> CInt -> CInt -> IO ()
+
+foreign import ccall unsafe "setlogmask" _setlogmask ::
+  CInt -> IO CInt
+
+foreign import ccall unsafe "syslog" _syslog ::
+  CInt -> CString -> IO ()
diff --git a/hsyslog.cabal b/hsyslog.cabal
new file mode 100644
--- /dev/null
+++ b/hsyslog.cabal
@@ -0,0 +1,15 @@
+Name:           hsyslog
+Version:        1.2
+Author:         Peter Simons <simons@cryp.to>
+License:        BSD3
+License-file:   LICENSE
+Maintainer:     simons@cryp.to
+Homepage:       http://cryp.to/hsyslog/
+Description:    FFI interface to syslog(3) from POSIX.1-2001.
+Synopsis:       FFI interface to syslog(3) from POSIX.1-2001.
+Category:       Foreign
+Build-Depends:  base
+Build-Type:     Simple
+Extensions:     ForeignFunctionInterface
+Exposed-Modules:
+  System.Posix.Syslog
diff --git a/prologue.txt b/prologue.txt
new file mode 100644
--- /dev/null
+++ b/prologue.txt
@@ -0,0 +1,2 @@
+This package provides FFI bindings to the POSIX.1-2001 system
+logger, syslog(3).
