diff options
author | John Goerzen <jgoerzen@complete.org> | 2006-08-30 13:25:50 +0000 |
---|---|---|
committer | John Goerzen <jgoerzen@complete.org> | 2006-08-30 13:25:50 +0000 |
commit | 23dffda7855bfac1e72f302184f3950de10f22cb (patch) | |
tree | e1c629c31382c48836e5d2b3b72ebaa962b88b4d | |
parent | 88beb9a9ba018a91023569b4da568e00949a46a7 (diff) |
Added support for getpwent/getgrent
-rw-r--r-- | System/Posix/User.hsc | 46 | ||||
-rw-r--r-- | configure.ac | 1 |
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]) |