It's short, so I'll post it here.
Any comments?

Thanks,
-Yitz

module DevRandom where

import System.IO
import System.IO.Error
import Foreign.Marshal.Alloc
import Foreign.Storable
import Foreign.Ptr

data BlockingMode = Blocking | NonBlocking
 deriving (Eq, Show)

-- Read data from the system random device.
-- Return Nothing if there is currently not
-- enough entropy in the system random device.
devRandom :: Storable a => IO (Maybe a)
devRandom = readDev "/dev/random" NonBlocking

-- Read data from the system random device.
-- If necessary, wait until there is
-- enough entropy in the system random device.
devRandomWait :: Storable a => IO a
devRandomWait = readDev dev Blocking >>= maybe (devRandomError dev) return
 where
   dev = "/dev/random"

-- Read data from the system random device.
-- If there is currently not enough entropy
-- in the system random device, use a lower
-- quality source of randomness instead.
devURandom :: Storable a => IO a
devURandom = readDev dev NonBlocking >>= maybe (devRandomError dev) return
 where
   dev = "/dev/urandom"

readDev :: Storable a => FilePath -> BlockingMode -> IO (Maybe a)
readDev dev mode = do
   h <- openFile dev ReadMode
   hSetBuffering h NoBuffering
   alloca $ getMaybe h undefined
 where
   getMaybe :: Storable a => Handle -> a -> Ptr a -> IO (Maybe a)
   getMaybe h undef ptr = do
     let size = sizeOf undef
     n <- case mode of
            Blocking    -> hGetBuf            h ptr size
            NonBlocking -> hGetBufNonBlocking h ptr size
     if n < size
       then return Nothing
       else peek ptr >>= return . Just

devRandomError :: FilePath -> IO a
devRandomError p = ioError $ mkIOError illegalOperationErrorType
 "Unable to read from the system random device" Nothing (Just p)
_______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

Reply via email to