aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar John Goerzen <jgoerzen@complete.org>2006-08-30 13:25:50 +0000
committerGravatar John Goerzen <jgoerzen@complete.org>2006-08-30 13:25:50 +0000
commit23dffda7855bfac1e72f302184f3950de10f22cb (patch)
treee1c629c31382c48836e5d2b3b72ebaa962b88b4d
parent88beb9a9ba018a91023569b4da568e00949a46a7 (diff)
Added support for getpwent/getgrent
-rw-r--r--System/Posix/User.hsc46
-rw-r--r--configure.ac1
2 files changed, 45 insertions, 2 deletions
diff --git a/System/Posix/User.hsc b/System/Posix/User.hsc
index fdbf98b..f98b30e 100644
--- a/System/Posix/User.hsc
+++ b/System/Posix/User.hsc
@@ -28,11 +28,13 @@ module System.Posix.User (
GroupEntry(..),
getGroupEntryForID,
getGroupEntryForName,
+ getAllGroupEntries,
-- *** The user database
UserEntry(..),
getUserEntryForID,
getUserEntryForName,
+ getAllUserEntries,
-- ** Modifying the user environment
setUserID,
@@ -47,7 +49,7 @@ import Foreign
import Foreign.C
import System.Posix.Internals ( CGroup, CPasswd )
-#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R)
+#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
import Control.Concurrent.MVar ( newMVar, withMVar )
#endif
@@ -197,6 +199,25 @@ foreign import ccall unsafe "getgrnam_r"
getGroupEntryForName = error "System.Posix.User.getGroupEntryForName: not supported"
#endif
+-- | @getAllGroupEntries@ returns all group entries on the system by
+-- repeatedly calling @getgrent@
+getAllGroupEntries :: IO [GroupEntry]
+#ifdef HAVE_GETGRENT
+getAllGroupEntries =
+ withMVar lock $ \_ -> worker []
+ where worker accum =
+ do ppw <- throwErrnoIfNullAndError "getAllGroupEntries" $ c_getgrent
+ if ppw == nullPtr
+ then return (reverse accum)
+ else do thisentry <- unpackGroupEntry ppw
+ worker (thisentry : accum)
+
+foreign import ccall unsafe "getgrent"
+ c_getgrent :: IO (Ptr CGroup)
+#else
+getAllGroupEntries = error "System.Posix.User.getAllGroupEntries: not supported"
+#endif
+
#if defined(HAVE_GETGRGID_R) || defined(HAVE_GETGRNAM_R)
grBufSize :: Int
#if defined(HAVE_SYSCONF) && defined(HAVE_SC_GETGR_R_SIZE_MAX)
@@ -235,7 +256,9 @@ data UserEntry =
-- 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)
+-- Also, getpwent/setpwent require a global lock since they maintain
+-- an internal file position pointer.
+#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
lock = unsafePerformIO $ newMVar ()
{-# NOINLINE lock #-}
#endif
@@ -302,6 +325,25 @@ foreign import ccall unsafe "getpwnam"
getUserEntryForName = error "System.Posix.User.getUserEntryForName: not supported"
#endif
+-- | @getAllUserEntries@ returns all user entries on the system by
+-- repeatedly calling @getpwent@
+getAllUserEntries :: IO [UserEntry]
+#ifdef HAVE_GETPWENT
+getAllUserEntries =
+ withMVar lock $ \_ -> worker []
+ where worker accum =
+ do ppw <- throwErrnoIfNullAndError "getAllUserEntries" $ c_getpwent
+ if ppw == nullPtr
+ then return (reverse accum)
+ else do thisentry <- unpackUserEntry ppw
+ worker (thisentry : accum)
+
+foreign import ccall unsafe "getpwent"
+ c_getpwent :: IO (Ptr CPasswd)
+#else
+getAllUserEntries = error "System.Posix.User.getAllUserEntries: not supported"
+#endif
+
#if defined(HAVE_GETPWUID_R) || defined(HAVE_GETPWNAM_R)
pwBufSize :: Int
#if defined(HAVE_SYSCONF) && defined(HAVE_SC_GETPW_R_SIZE_MAX)
diff --git a/configure.ac b/configure.ac
index b991b53..0f039fb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -17,6 +17,7 @@ AC_CHECK_HEADERS([sys/utsname.h sys/wait.h])
AC_CHECK_HEADERS([termios.h time.h unistd.h utime.h])
AC_CHECK_FUNCS([getgrgid_r getgrnam_r getpwnam_r getpwuid_r getpwnam getpwuid])
+AC_CHECK_FUNCS([getpwent getgrent])
AC_CHECK_FUNCS([lchown setenv sysconf unsetenv])
AC_MSG_CHECKING([for _SC_GETGR_R_SIZE_MAX])