diff --git a/COPYING b/COPYING
new file mode 100644
--- /dev/null
+++ b/COPYING
@@ -0,0 +1,31 @@
+Copyright Jeremy Shaw, David Fox 2007-2012
+All rights reserved.
+
+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.
+
+   * Neither the name of the copyright holder nor the names of other
+     contributors may 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/Setup.hs b/Setup.hs
new file mode 100644
--- /dev/null
+++ b/Setup.hs
@@ -0,0 +1,3 @@
+#!/usr/bin/env runhaskell
+import Distribution.Simple
+main = defaultMainWithHooks simpleUserHooks
diff --git a/System/Unix/Shadow.hsc b/System/Unix/Shadow.hsc
new file mode 100644
--- /dev/null
+++ b/System/Unix/Shadow.hsc
@@ -0,0 +1,108 @@
+{-# LANGUAGE ForeignFunctionInterface #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Unix.Shadow
+-- Copyright   :  (c) 2010 Jeremy Shaw, The University of Glasgow
+-- License     :  BSD3
+-- 
+-- Maintainer  :  jeremy@seereason.com
+-- Stability   :  provisional
+-- Portability :  non-portable (requires POSIX)
+--
+-- support for /etc/shadow
+--
+-- TODO: This module is modelled after System.Posix.User but lacks many 
+-- of the #ifdefs. Those are probably important.
+-----------------------------------------------------------------------------
+module System.Unix.Shadow 
+    ( SUserEntry(..)
+    , getSUserEntryForName
+    ) where
+
+import Control.Exception
+import Control.Monad
+import Foreign
+import Foreign.C
+import System.Posix.Types
+import System.IO.Error
+
+#include "shadow.h"
+
+type CSpwd = ()
+
+-- | Entry returned by 'getSUserEntryForName'
+--
+-- TODO: add other fields
+data SUserEntry =
+ SUserEntry {
+   sUserName      :: String,     -- ^ Textual name of this user (pw_name)
+   sUserPassword  :: String      -- ^ Password -- may be empty or fake if shadow is in use (pw_passwd)
+ } deriving (Show, Read, Eq)
+
+
+
+-- | @getSUserEntryForName name@ calls @getspnam@ to obtain
+--   the @SUserEntry@ information associated with the user login
+--   @name@.p
+getSUserEntryForName :: String -> IO SUserEntry
+-- #if HAVE_GETPWNAM_R
+getSUserEntryForName name = do
+  allocaBytes (#const sizeof(struct spwd)) $ \ppw ->
+    alloca $ \ pppw ->
+      withCString name $ \ pstr -> do
+	throwErrorIfNonZero_ "getsUserEntryForName" $
+	  doubleAllocWhile isERANGE pwBufSize $ \s b ->
+	    c_getspnam_r pstr ppw b (fromIntegral s) pppw
+	r <- peekElemOff pppw 0
+	when (r == nullPtr) $
+	  ioError $ flip ioeSetErrorString "no user name"
+		  $ mkIOError doesNotExistErrorType
+			      "getUserEntryForName"
+			      Nothing
+			      (Just name)
+	unpackSUserEntry ppw
+
+foreign import ccall unsafe "getspnam_r"
+  c_getspnam_r :: CString -> Ptr CSpwd
+               -> CString -> CSize -> Ptr (Ptr CSpwd) -> IO CInt
+{-
+#elif HAVE_GETPWNAM
+getUserEntryForName name = do
+  withCString name $ \ pstr -> do
+    withMVar lock $ \_ -> do
+      ppw <- throwErrnoIfNull "getUserEntryForName" $ c_getpwnam pstr
+      unpackUserEntry ppw
+
+foreign import ccall unsafe "getpwnam" 
+  c_getpwnam :: CString -> IO (Ptr CPasswd)
+#else
+getUserEntryForName = error "System.Posix.User.getUserEntryForName: not supported"
+#endif
+-}
+
+unpackSUserEntry :: Ptr CSpwd -> IO SUserEntry
+unpackSUserEntry ptr = do
+   name   <- (#peek struct spwd, sp_namp)   ptr >>= peekCString
+   passwd <- (#peek struct spwd, sp_pwdp)   ptr >>= peekCString
+   return (SUserEntry name passwd)
+
+isERANGE :: Integral a => a -> Bool
+isERANGE = (== eRANGE) . Errno . fromIntegral
+
+doubleAllocWhile :: (a -> Bool) -> Int -> (Int -> Ptr b -> IO a) -> IO a
+doubleAllocWhile p s m = do
+  r <- allocaBytes s (m s)
+  if p r then doubleAllocWhile p (2 * s) m else return r
+
+
+pwBufSize :: Int
+pwBufSize = 1024
+
+-- Used when calling re-entrant system calls that signal their 'errno' 
+-- directly through the return value.
+throwErrorIfNonZero_ :: String -> IO CInt -> IO ()
+throwErrorIfNonZero_ loc act = do
+    rc <- act
+    if (rc == 0) 
+     then return ()
+     else ioError (errnoToIOError loc (Errno (fromIntegral rc)) Nothing Nothing)
diff --git a/Unixutils-shadow.cabal b/Unixutils-shadow.cabal
new file mode 100644
--- /dev/null
+++ b/Unixutils-shadow.cabal
@@ -0,0 +1,20 @@
+Name:           Unixutils-shadow
+Version:        1.0.0
+License:        BSD3
+License-File:	COPYING
+Author:         Jeremy Shaw, David Fox
+Homepage:       http://src.seereason.com/haskell-unixutils-shadow
+Category:	System
+Synopsis:       A simple interface to shadow passwords (aka, shadow.h)
+Maintainer:     jeremy@n-heptane.com
+Description:
+ Provides the ability to read a user entry from the shadow password database
+Build-type:	Simple
+Cabal-Version: >= 1.2
+
+Library 
+    Build-Depends:  base >= 4 && <5,
+                    unix
+    ghc-options:	-O2
+    Exposed-modules:
+        System.Unix.Shadow
