aboutsummaryrefslogtreecommitdiffhomepage
path: root/System
diff options
context:
space:
mode:
authorGravatar dons <unknown>2004-09-30 03:13:23 +0000
committerGravatar dons <unknown>2004-09-30 03:13:23 +0000
commitb1e0d3e5781d429f781e71b29229d328a6e5f16c (patch)
tree3efb114c11d40656fa207f5c6a237375a59b0f63 /System
parentac941dea76fcbe604b75e58a161e36ce4ae175c4 (diff)
[project @ 2004-09-30 03:13:23 by dons]
Implement System.Posix.User.getUserEntryFor{ID,Name} on platforms without reentrant versions of getpw{uid,nam}. This includes all the BSDs. While I'm here, close getGroupEntryFor* "Result too large" bug on OpenBSD, mentioned last year: http://www.haskell.org/pipermail/glasgow-haskell-bugs/2003-September/003601.html grBufSize was too small, apparently. Thanks to Ian Lynagh for hint to do the locking.
Diffstat (limited to 'System')
-rw-r--r--System/Posix/User.hsc33
1 files changed, 32 insertions, 1 deletions
diff --git a/System/Posix/User.hsc b/System/Posix/User.hsc
index 965a0d0..ed5adfb 100644
--- a/System/Posix/User.hsc
+++ b/System/Posix/User.hsc
@@ -47,6 +47,10 @@ import Foreign
import Foreign.C
import System.Posix.Internals ( CGroup, CPasswd )
+#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R)
+import Control.Concurrent.MVar ( newMVar, withMVar )
+#endif
+
-- -----------------------------------------------------------------------------
-- user environemnt
@@ -168,7 +172,7 @@ grBufSize :: Int
grBufSize = fromIntegral $ unsafePerformIO $
c_sysconf (#const _SC_GETGR_R_SIZE_MAX)
#else
-grBufSize = 1024 -- just assume some value
+grBufSize = 2048 -- just assume some value (1024 is too small on OpenBSD)
#endif
#endif
@@ -192,6 +196,16 @@ data UserEntry =
userShell :: String
}
+--
+-- getpwuid and getpwnam leave results in a static object. Subsequent
+-- calls modify the same object, which isn't threadsafe. We attempt to
+-- mitigate this issue, on platforms that don't provide the safe _r versions
+--
+#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R)
+lock = unsafePerformIO $ newMVar ()
+{-# NOINLINE lock #-}
+#endif
+
getUserEntryForID :: UserID -> IO UserEntry
#ifdef HAVE_GETPWUID_R
getUserEntryForID uid = do
@@ -205,6 +219,14 @@ getUserEntryForID uid = do
foreign import ccall unsafe "getpwuid_r"
c_getpwuid_r :: CUid -> Ptr CPasswd ->
CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt
+#elif HAVE_GETPWUID
+getUserEntryForID uid = do
+ withMVar lock $ \_ -> do
+ ppw <- throwErrnoIfNull "getUserEntryForID" $ c_getpwuid uid
+ unpackUserEntry ppw
+
+foreign import ccall unsafe "getpwuid"
+ c_getpwuid :: CUid -> IO (Ptr CPasswd)
#else
getUserEntryForID = error "System.Posix.User.getUserEntryForID: not supported"
#endif
@@ -223,6 +245,15 @@ getUserEntryForName name = do
foreign import ccall unsafe "getpwnam_r"
c_getpwnam_r :: CString -> Ptr CPasswd ->
CString -> CSize -> Ptr (Ptr CPasswd) -> 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