unix-2.0: System/Posix/Unistd.hsc
{-# OPTIONS -fffi #-}
-----------------------------------------------------------------------------
-- |
-- Module : System.Posix.Unistd
-- Copyright : (c) The University of Glasgow 2002
-- License : BSD-style (see the file libraries/base/LICENSE)
--
-- Maintainer : libraries@haskell.org
-- Stability : provisional
-- Portability : non-portable (requires POSIX)
--
-- POSIX miscellaneous stuff, mostly from unistd.h
--
-----------------------------------------------------------------------------
module System.Posix.Unistd (
-- * System environment
SystemID(..),
getSystemID,
SysVar(..),
getSysVar,
-- * Sleeping
sleep, usleep,
{-
ToDo from unistd.h:
confstr,
lots of sysconf variables
-- use Network.BSD
gethostid, gethostname
-- should be in System.Posix.Files?
pathconf, fpathconf,
-- System.Posix.Signals
ualarm,
-- System.Posix.IO
read, write,
-- should be in System.Posix.User?
getEffectiveUserName,
-}
) where
#include "HsUnix.h"
import Foreign.C.Error
import Foreign.C.String ( peekCString )
import Foreign.C.Types ( CInt, CUInt, CLong )
import Foreign.Marshal.Alloc ( allocaBytes )
import Foreign.Ptr ( Ptr, plusPtr )
import System.Posix.Types
import System.Posix.Internals
-- -----------------------------------------------------------------------------
-- System environment (uname())
data SystemID =
SystemID { systemName :: String
, nodeName :: String
, release :: String
, version :: String
, machine :: String
}
getSystemID :: IO SystemID
getSystemID = do
allocaBytes (#const sizeof(struct utsname)) $ \p_sid -> do
throwErrnoIfMinus1_ "getSystemID" (c_uname p_sid)
sysN <- peekCString ((#ptr struct utsname, sysname) p_sid)
node <- peekCString ((#ptr struct utsname, nodename) p_sid)
rel <- peekCString ((#ptr struct utsname, release) p_sid)
ver <- peekCString ((#ptr struct utsname, version) p_sid)
mach <- peekCString ((#ptr struct utsname, machine) p_sid)
return (SystemID { systemName = sysN,
nodeName = node,
release = rel,
version = ver,
machine = mach
})
foreign import ccall unsafe "uname"
c_uname :: Ptr CUtsname -> IO CInt
-- -----------------------------------------------------------------------------
-- sleeping
-- | Sleep for the specified duration (in seconds). Returns the time remaining
-- (if the sleep was interrupted by a signal, for example).
--
-- GHC Note: the comment for 'usleep' also applies here.
--
sleep :: Int -> IO Int
sleep 0 = return 0
sleep secs = do r <- c_sleep (fromIntegral secs); return (fromIntegral r)
foreign import ccall safe "sleep"
c_sleep :: CUInt -> IO CUInt
-- | Sleep for the specified duration (in microseconds).
--
-- GHC Note: 'Control.Concurrent.threadDelay' is a better choice.
-- Without the @-threaded@ option, 'usleep' will block all other user
-- threads. Even with the @-threaded@ option, 'usleep' requires a
-- full OS thread to itself. 'Control.Concurrent.threadDelay' has
-- neither of these shortcomings.
--
usleep :: Int -> IO ()
usleep 0 = return ()
#ifdef USLEEP_RETURNS_VOID
usleep usecs = c_usleep (fromIntegral usecs)
#else
usleep usecs = throwErrnoIfMinus1Retry_ "usleep" (c_usleep (fromIntegral usecs))
#endif
#ifdef USLEEP_RETURNS_VOID
foreign import ccall safe "usleep"
c_usleep :: CUInt -> IO ()
#else
foreign import ccall safe "usleep"
c_usleep :: CUInt -> IO CInt
#endif
-- -----------------------------------------------------------------------------
-- System variables
data SysVar = ArgumentLimit
| ChildLimit
| ClockTick
| GroupLimit
| OpenFileLimit
| PosixVersion
| HasSavedIDs
| HasJobControl
-- ToDo: lots more
getSysVar :: SysVar -> IO Integer
getSysVar v =
case v of
ArgumentLimit -> sysconf (#const _SC_ARG_MAX)
ChildLimit -> sysconf (#const _SC_CHILD_MAX)
ClockTick -> sysconf (#const _SC_CLK_TCK)
GroupLimit -> sysconf (#const _SC_NGROUPS_MAX)
OpenFileLimit -> sysconf (#const _SC_OPEN_MAX)
PosixVersion -> sysconf (#const _SC_VERSION)
HasSavedIDs -> sysconf (#const _SC_SAVED_IDS)
HasJobControl -> sysconf (#const _SC_JOB_CONTROL)
sysconf :: CInt -> IO Integer
sysconf n = do
r <- throwErrnoIfMinus1 "getSysVar" (c_sysconf n)
return (fromIntegral r)
foreign import ccall unsafe "sysconf"
c_sysconf :: CInt -> IO CLong