network-bsd 2.8.0.0 → 2.8.1.0
raw patch · 3 files changed
+738/−8 lines, 3 filesdep +deepseqdep ~basedep ~network
Dependencies added: deepseq
Dependency ranges changed: base, network
Files
- CHANGELOG.md +7/−0
- Network/BSD.hsc +660/−0
- network-bsd.cabal +71/−8
+ CHANGELOG.md view
@@ -0,0 +1,7 @@+## 2.8.1.0++- First version to support `network-3.0.0.0`+- Fix dead-lock in `getProtocolEntries` and make the high-level composite `get*Entries` operations atomic+- Reexport `HostAddress` and `Family` (from `network`)+- Provide `ifNameToIndex` unconditionally+- Add `NFData` instances for `ServiceEntry`, `ProtocolEntry`, `HostEntry`, and `NetworkEntry`
+ Network/BSD.hsc view
@@ -0,0 +1,660 @@+{-# LANGUAGE CPP, NondecreasingIndentation, DeriveDataTypeable, BangPatterns #-}++-----------------------------------------------------------------------------+-- |+-- Module : Network.BSD+-- Copyright : (c) The University of Glasgow 2001+-- SPDX-License-Identifier: BSD-3-Clause+--+-- Maintainer : libraries@haskell.org+-- Stability : experimental+-- Portability : non-portable+--+-- The "Network.BSD" module defines Haskell bindings to network+-- programming functionality (mostly [network database operations](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html))+-- provided by BSD Unix derivatives.+--+-- __NOTE__: Some of the types are reexported from "Network.Socket" in order to make the @network-bsd@ API self-contained.+--+-- == Windows compatibility+--+-- The following functions are not exported by "Network.BSD" on the+-- Windows platform:+--+-- * 'getHostEntries', 'setHostEntry', 'getHostEntry', 'endHostEntry'+-- * 'getServiceEntries', 'getServiceEntry', 'setServiceEntry', 'endServiceEntry'+-- * 'getProtocolEntries', 'setProtocolEntry', 'getProtocolEntry', 'endProtocolEntry'+-- * 'getNetworkByName', 'getNetworkByAddr', 'getNetworkEntries',+-- 'setNetworkEntry', 'getNetworkEntry', 'endNetworkEntry'+--+-----------------------------------------------------------------------------++#include "HsNet.h"+##include "HsNetDef.h"++module Network.BSD+ (+ -- * Host names and network addresses+ N.HostName+ , N.HostAddress+ -- NB: We're explicit here to reduce the risk of inadvertently leaking through new constructors w/o reflecting this in @network-bsd@'s API version+ , N.Family(AF_UNSPEC, AF_UNIX, AF_INET, AF_INET6, AF_IMPLINK, AF_PUP, AF_CHAOS, AF_NS, AF_NBS, AF_ECMA, AF_DATAKIT, AF_CCITT, AF_SNA, AF_DECnet, AF_DLI, AF_LAT, AF_HYLINK, AF_APPLETALK, AF_ROUTE, AF_NETBIOS, AF_NIT, AF_802, AF_ISO, AF_OSI, AF_NETMAN, AF_X25, AF_AX25, AF_OSINET, AF_GOSSIP, AF_IPX, Pseudo_AF_XTP, AF_CTF, AF_WAN, AF_SDL, AF_NETWARE, AF_NDD, AF_INTF, AF_COIP, AF_CNT, Pseudo_AF_RTIP, Pseudo_AF_PIP, AF_SIP, AF_ISDN, Pseudo_AF_KEY, AF_NATM, AF_ARP, Pseudo_AF_HDRCMPLT, AF_ENCAP, AF_LINK, AF_RAW, AF_RIF, AF_NETROM, AF_BRIDGE, AF_ATMPVC, AF_ROSE, AF_NETBEUI, AF_SECURITY, AF_PACKET, AF_ASH, AF_ECONET, AF_ATMSVC, AF_IRDA, AF_PPPOX, AF_WANPIPE, AF_BLUETOOTH, AF_CAN)+ , getHostName++ , HostEntry(..)+ , getHostByName+ , getHostByAddr+ , hostAddress++#if defined(HAVE_GETHOSTENT) && !defined(mingw32_HOST_OS)+ , getHostEntries++ -- ** Low level functionality+ , setHostEntry+ , getHostEntry+ , endHostEntry+#endif++ -- * Service names+ , ServiceEntry(..)+ , N.ServiceName+ , N.PortNumber+ , getServiceByName+ , getServiceByPort+ , getServicePortNumber++#if !defined(mingw32_HOST_OS)+ , getServiceEntries++ -- ** Low level functionality+ , getServiceEntry+ , setServiceEntry+ , endServiceEntry+#endif++ -- * Protocol names+ , ProtocolName+ , N.ProtocolNumber+ , ProtocolEntry(..)+ , getProtocolByName+ , getProtocolByNumber+ , getProtocolNumber+ , N.defaultProtocol++#if !defined(mingw32_HOST_OS)+ , getProtocolEntries+ -- ** Low level functionality+ , setProtocolEntry+ , getProtocolEntry+ , endProtocolEntry+#endif++ -- * Network names+ , NetworkName+ , NetworkAddr+ , NetworkEntry(..)++#if !defined(mingw32_HOST_OS)+ , getNetworkByName+ , getNetworkByAddr+ , getNetworkEntries+ -- ** Low level functionality+ , setNetworkEntry+ , getNetworkEntry+ , endNetworkEntry+#endif++ -- * Interface names+ , N.ifNameToIndex++ ) where++import qualified Network.Socket as N++import Control.Concurrent (MVar, newMVar, withMVar)+import qualified Control.Exception as E+import Foreign.C.String (CString, peekCString, withCString)+#if defined(mingw32_HOST_OS)+import Foreign.C.Types ( CShort )+#endif+import Foreign.C.Types ( CInt(..), CULong(..), CSize(..) )+import Foreign.Ptr (Ptr, nullPtr)+import Foreign.Storable (Storable(..))+import Foreign.Marshal.Array (allocaArray0, peekArray0)+import Foreign.Marshal.Utils (with, fromBool)+import Data.Typeable+import System.IO.Error (ioeSetErrorString, mkIOError)+import System.IO.Unsafe (unsafePerformIO)++import GHC.IO.Exception++import Control.DeepSeq (NFData(rnf))+import Control.Monad (liftM)++import Network.Socket.Internal (throwSocketErrorIfMinus1_)++-- ---------------------------------------------------------------------------+-- Basic Types++type ProtocolName = String++-- ---------------------------------------------------------------------------+-- Service Database Access++-- Calling getServiceByName for a given service and protocol returns+-- the systems service entry. This should be used to find the port+-- numbers for standard protocols such as SMTP and FTP. The remaining+-- three functions should be used for browsing the service database+-- sequentially.++-- Calling setServiceEntry with True indicates that the service+-- database should be left open between calls to getServiceEntry. To+-- close the database a call to endServiceEntry is required. This+-- database file is usually stored in the file /etc/services.++-- | Representation of the POSIX @servent@ structure defined in [<netdb.h>](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html).+data ServiceEntry =+ ServiceEntry {+ serviceName :: N.ServiceName, -- ^ Official service name+ serviceAliases :: [N.ServiceName], -- ^ aliases+ servicePort :: N.PortNumber, -- ^ Port Number+ serviceProtocol :: ProtocolName -- ^ Protocol to use+ } deriving (Show, Typeable)++-- | @since 2.8.1.0+instance NFData ServiceEntry where+ -- TODO: PortNumber is a newtype over Word16; add NFData instance to `network`+ rnf (ServiceEntry n a !_pn pr) = rnf (n,a,pr)++instance Storable ServiceEntry where+ sizeOf _ = #const sizeof(struct servent)+ alignment _ = alignment (undefined :: CInt) -- ???++ peek p = do+ s_name <- (#peek struct servent, s_name) p >>= peekCString+ s_aliases <- (#peek struct servent, s_aliases) p+ >>= peekArray0 nullPtr+ >>= mapM peekCString+ s_port <- (#peek struct servent, s_port) p+ s_proto <- (#peek struct servent, s_proto) p >>= peekCString+ return (ServiceEntry {+ serviceName = s_name,+ serviceAliases = s_aliases,+#if defined(mingw32_HOST_OS)+ servicePort = (fromIntegral (s_port :: CShort)),+#else+ -- s_port is already in network byte order, but it+ -- might be the wrong size.+ servicePort = (fromIntegral (s_port :: CInt)),+#endif+ serviceProtocol = s_proto+ })++ poke = throwUnsupportedOperationPoke "ServiceEntry"+++-- | Get service by name.+getServiceByName :: N.ServiceName -- Service Name+ -> ProtocolName -- Protocol Name+ -> IO ServiceEntry -- Service Entry+getServiceByName name proto = withLock $ do+ withCString name $ \ cstr_name -> do+ withCString proto $ \ cstr_proto -> do+ throwNoSuchThingIfNull "Network.BSD.getServiceByName" "no such service entry"+ $ c_getservbyname cstr_name cstr_proto+ >>= peek++foreign import CALLCONV unsafe "getservbyname"+ c_getservbyname :: CString -> CString -> IO (Ptr ServiceEntry)++-- | Get the service given a 'N.PortNumber' and 'ProtocolName'.+getServiceByPort :: N.PortNumber -> ProtocolName -> IO ServiceEntry+getServiceByPort port proto = withLock $ do+ withCString proto $ \ cstr_proto -> do+ throwNoSuchThingIfNull "Network.BSD.getServiceByPort" "no such service entry"+ $ c_getservbyport (fromIntegral port) cstr_proto+ >>= peek++foreign import CALLCONV unsafe "getservbyport"+ c_getservbyport :: CInt -> CString -> IO (Ptr ServiceEntry)++-- | Get the 'N.PortNumber' corresponding to the 'N.ServiceName'.+getServicePortNumber :: N.ServiceName -> IO N.PortNumber+getServicePortNumber name = do+ (ServiceEntry _ _ port _) <- getServiceByName name "tcp"+ return port++#if !defined(mingw32_HOST_OS)++-- | @getservent(3)@.+getServiceEntry :: IO ServiceEntry+getServiceEntry = withLock getServiceEntry'++getServiceEntry' :: IO ServiceEntry+getServiceEntry' = do+ throwNoSuchThingIfNull "Network.BSD.getServiceEntry" "no such service entry"+ $ c_getservent+ >>= peek++foreign import ccall unsafe "getservent" c_getservent :: IO (Ptr ServiceEntry)++-- | @setservent(3)@.+setServiceEntry :: Bool -> IO ()+setServiceEntry = withLock . setServiceEntry'++setServiceEntry' :: Bool -> IO ()+setServiceEntry' flg = c_setservent (fromBool flg)++foreign import ccall unsafe "setservent" c_setservent :: CInt -> IO ()++-- | @endservent(3)@.+endServiceEntry :: IO ()+endServiceEntry = withLock $ c_endservent++foreign import ccall unsafe "endservent" c_endservent :: IO ()++-- | Retrieve list of all 'ServiceEntry' via @getservent(3)@.+getServiceEntries :: Bool -> IO [ServiceEntry]+getServiceEntries stayOpen = withLock $ do+ setServiceEntry' stayOpen+ getEntries getServiceEntry' c_endservent+#endif++-- ---------------------------------------------------------------------------+-- Protocol Entries++-- The following relate directly to the corresponding UNIX C+-- calls for returning the protocol entries. The protocol entry is+-- represented by the Haskell type ProtocolEntry.++-- As for setServiceEntry above, calling setProtocolEntry.+-- determines whether or not the protocol database file, usually+-- @/etc/protocols@, is to be kept open between calls of+-- getProtocolEntry. Similarly,++-- | Representation of the POSIX @protoent@ structure defined in [<netdb.h>](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html).+data ProtocolEntry =+ ProtocolEntry {+ protoName :: ProtocolName, -- ^ Official name+ protoAliases :: [ProtocolName], -- ^ aliases+ protoNumber :: N.ProtocolNumber -- ^ Protocol number+ } deriving (Read, Show, Typeable)++-- | @since 2.8.1.0+instance NFData ProtocolEntry where+ -- NB: deepseq-1.3 didn't have `NFData CInt` yet; but we don't need it+ rnf (ProtocolEntry na a !_nu) = rnf (na,a)++instance Storable ProtocolEntry where+ sizeOf _ = #const sizeof(struct protoent)+ alignment _ = alignment (undefined :: CInt) -- ???++ peek p = do+ p_name <- (#peek struct protoent, p_name) p >>= peekCString+ p_aliases <- (#peek struct protoent, p_aliases) p+ >>= peekArray0 nullPtr+ >>= mapM peekCString+#if defined(mingw32_HOST_OS)+ -- With WinSock, the protocol number is only a short;+ -- hoist it in as such, but represent it on the Haskell side+ -- as a CInt.+ p_proto_short <- (#peek struct protoent, p_proto) p+ let p_proto = fromIntegral (p_proto_short :: CShort)+#else+ p_proto <- (#peek struct protoent, p_proto) p+#endif+ return (ProtocolEntry {+ protoName = p_name,+ protoAliases = p_aliases,+ protoNumber = p_proto+ })++ poke = throwUnsupportedOperationPoke "ProtocolEntry"+++-- | @getprotobyname(3)@.+getProtocolByName :: ProtocolName -> IO ProtocolEntry+getProtocolByName name = withLock $ do+ withCString name $ \ name_cstr -> do+ throwNoSuchThingIfNull "Network.BSD.getProtocolByName" ("no such protocol name: " ++ name)+ $ c_getprotobyname name_cstr+ >>= peek++foreign import CALLCONV unsafe "getprotobyname"+ c_getprotobyname :: CString -> IO (Ptr ProtocolEntry)++-- | @getprotobynumber(3)@.+getProtocolByNumber :: N.ProtocolNumber -> IO ProtocolEntry+getProtocolByNumber num = withLock $ do+ throwNoSuchThingIfNull "Network.BSD.getProtocolByNumber" ("no such protocol number: " ++ show num)+ $ c_getprotobynumber (fromIntegral num)+ >>= peek++foreign import CALLCONV unsafe "getprotobynumber"+ c_getprotobynumber :: CInt -> IO (Ptr ProtocolEntry)++-- | @getprotobyname(3)@.+getProtocolNumber :: ProtocolName -> IO N.ProtocolNumber+getProtocolNumber proto = do+ (ProtocolEntry _ _ num) <- getProtocolByName proto+ return num++#if !defined(mingw32_HOST_OS)+-- | @getprotoent(3)@.+getProtocolEntry :: IO ProtocolEntry -- Next Protocol Entry from DB+getProtocolEntry = withLock getProtocolEntry'++getProtocolEntry' :: IO ProtocolEntry+getProtocolEntry' = do+ ent <- throwNoSuchThingIfNull "Network.BSD.getProtocolEntry" "no such protocol entry"+ $ c_getprotoent+ peek ent++foreign import ccall unsafe "getprotoent" c_getprotoent :: IO (Ptr ProtocolEntry)++-- | @setprotoent(3)@.+setProtocolEntry :: Bool -> IO () -- Keep DB Open ?+setProtocolEntry = withLock . setProtocolEntry'++setProtocolEntry' :: Bool -> IO () -- Keep DB Open ?+setProtocolEntry' flg = c_setprotoent (fromBool flg)++foreign import ccall unsafe "setprotoent" c_setprotoent :: CInt -> IO ()++-- | @endprotoent(3)@.+endProtocolEntry :: IO ()+endProtocolEntry = withLock $ c_endprotoent++foreign import ccall unsafe "endprotoent" c_endprotoent :: IO ()++-- | Retrieve list of all 'ProtocolEntry' via @getprotoent(3)@.+getProtocolEntries :: Bool -> IO [ProtocolEntry]+getProtocolEntries stayOpen = withLock $ do+ setProtocolEntry' stayOpen+ getEntries getProtocolEntry' c_endprotoent++#endif++-- ---------------------------------------------------------------------------+-- Host lookups++-- | Representation of the POSIX @hostent@ structure defined in [<netdb.h>](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html).+data HostEntry =+ HostEntry {+ hostName :: N.HostName, -- ^ Official name of the host+ hostAliases :: [N.HostName], -- ^ Alternative names of the host+ hostFamily :: N.Family, -- ^ Address type (currently @AF_INET@)+ hostAddresses :: [N.HostAddress] -- ^ Set of network addresses for the host+ } deriving (Read, Show, Typeable)++-- | @since 2.8.1.0+instance NFData HostEntry where+ -- TODO: NFData N.Family+ rnf (HostEntry n al !_f ad) = rnf (n,al,ad)++instance Storable HostEntry where+ sizeOf _ = #const sizeof(struct hostent)+ alignment _ = alignment (undefined :: CInt) -- ???++ peek p = do+ h_name <- (#peek struct hostent, h_name) p >>= peekCString+ h_aliases <- (#peek struct hostent, h_aliases) p+ >>= peekArray0 nullPtr+ >>= mapM peekCString+ h_addrtype <- (#peek struct hostent, h_addrtype) p+ -- h_length <- (#peek struct hostent, h_length) p+ h_addr_list <- (#peek struct hostent, h_addr_list) p+ >>= peekArray0 nullPtr+ >>= mapM peek+ return (HostEntry {+ hostName = h_name,+ hostAliases = h_aliases,+#if defined(mingw32_HOST_OS)+ hostFamily = N.unpackFamily (fromIntegral (h_addrtype :: CShort)),+#else+ hostFamily = N.unpackFamily h_addrtype,+#endif+ hostAddresses = h_addr_list+ })++ poke = throwUnsupportedOperationPoke "HostEntry"+++-- convenience function:+-- | Convenience function extracting one address in a 'HostEntry'.+-- Returns 'error' if 'HostEntry' contains no addresses.+hostAddress :: HostEntry -> N.HostAddress+hostAddress (HostEntry nm _ _ ls) =+ case ls of+ [] -> error $ "Network.BSD.hostAddress: empty network address list for " ++ nm+ (x:_) -> x++-- getHostByName must use the same lock as the *hostent functions+-- may cause problems if called concurrently.++-- | Resolve a 'N.HostName' to IPv4 address.+getHostByName :: N.HostName -> IO HostEntry+getHostByName name = withLock $ do+ withCString name $ \ name_cstr -> do+ ent <- throwNoSuchThingIfNull "Network.BSD.getHostByName" "no such host entry"+ $ c_gethostbyname name_cstr+ peek ent++foreign import CALLCONV safe "gethostbyname"+ c_gethostbyname :: CString -> IO (Ptr HostEntry)+++-- The locking of gethostbyaddr is similar to gethostbyname.+-- | Get a 'HostEntry' corresponding to the given address and family.+-- Note that only IPv4 is currently supported.+getHostByAddr :: N.Family -> N.HostAddress -> IO HostEntry+getHostByAddr family addr = do+ with addr $ \ ptr_addr -> withLock $ do+ throwNoSuchThingIfNull "Network.BSD.getHostByAddr" "no such host entry"+ $ c_gethostbyaddr ptr_addr (fromIntegral (sizeOf addr)) (N.packFamily family)+ >>= peek++foreign import CALLCONV safe "gethostbyaddr"+ c_gethostbyaddr :: Ptr N.HostAddress -> CInt -> CInt -> IO (Ptr HostEntry)++#if defined(HAVE_GETHOSTENT) && !defined(mingw32_HOST_OS)+-- | @gethostent(3)@.+getHostEntry :: IO HostEntry+getHostEntry = withLock getHostEntry++getHostEntry' :: IO HostEntry+getHostEntry' = do+ throwNoSuchThingIfNull "Network.BSD.getHostEntry" "unable to retrieve host entry"+ $ c_gethostent+ >>= peek++foreign import ccall unsafe "gethostent" c_gethostent :: IO (Ptr HostEntry)++-- | @sethostent(3)@.+setHostEntry :: Bool -> IO ()+setHostEntry = withLock . setHostEntry'++setHostEntry' :: Bool -> IO ()+setHostEntry' flg = c_sethostent (fromBool flg)++foreign import ccall unsafe "sethostent" c_sethostent :: CInt -> IO ()++-- | @endhostent(3)@.+endHostEntry :: IO ()+endHostEntry = withLock $ c_endhostent++foreign import ccall unsafe "endhostent" c_endhostent :: IO ()++-- | Retrieve list of all 'HostEntry' via @gethostent(3)@.+getHostEntries :: Bool -> IO [HostEntry]+getHostEntries stayOpen = withLock $ do+ setHostEntry' stayOpen+ getEntries getHostEntry' c_endhostent++#endif++-- ---------------------------------------------------------------------------+-- Accessing network information++-- Same set of access functions as for accessing host,protocol and+-- service system info, this time for the types of networks supported.++-- network addresses are represented in host byte order.+type NetworkAddr = CULong++type NetworkName = String++-- | Representation of the POSIX @netent@ structure defined in [<netdb.h>](http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/netdb.h.html).+data NetworkEntry =+ NetworkEntry {+ networkName :: NetworkName, -- ^ Official network name+ networkAliases :: [NetworkName], -- ^ aliases+ networkFamily :: N.Family, -- ^ Network address type+ networkAddress :: NetworkAddr -- ^ Network number+ } deriving (Read, Show, Typeable)++-- | @since 2.8.1.0+instance NFData NetworkEntry where+ -- NB: We avoid relying on the `NFData CULong` instance which isn't available in deepseq-1.3 yet+ rnf (NetworkEntry n al !_f !_ad) = rnf (n,al)++instance Storable NetworkEntry where+ sizeOf _ = #const sizeof(struct hostent)+ alignment _ = alignment (undefined :: CInt) -- ???++ peek p = do+ n_name <- (#peek struct netent, n_name) p >>= peekCString+ n_aliases <- (#peek struct netent, n_aliases) p+ >>= peekArray0 nullPtr+ >>= mapM peekCString+ n_addrtype <- (#peek struct netent, n_addrtype) p+ n_net <- (#peek struct netent, n_net) p+ return (NetworkEntry {+ networkName = n_name,+ networkAliases = n_aliases,+ networkFamily = N.unpackFamily (fromIntegral (n_addrtype :: CInt)),+ networkAddress = n_net+ })++ poke = throwUnsupportedOperationPoke "NetworkEntry"+++#if !defined(mingw32_HOST_OS)+-- | @getnetbyname(3)@.+getNetworkByName :: NetworkName -> IO NetworkEntry+getNetworkByName name = withLock $ do+ withCString name $ \ name_cstr -> do+ throwNoSuchThingIfNull "Network.BSD.getNetworkByName" "no such network entry"+ $ c_getnetbyname name_cstr+ >>= peek++foreign import ccall unsafe "getnetbyname"+ c_getnetbyname :: CString -> IO (Ptr NetworkEntry)++-- | @getnetbyaddr(3)@.+getNetworkByAddr :: NetworkAddr -> N.Family -> IO NetworkEntry+getNetworkByAddr addr family = withLock $ do+ throwNoSuchThingIfNull "Network.BSD.getNetworkByAddr" "no such network entry"+ $ c_getnetbyaddr addr (N.packFamily family)+ >>= peek++foreign import ccall unsafe "getnetbyaddr"+ c_getnetbyaddr :: NetworkAddr -> CInt -> IO (Ptr NetworkEntry)++-- | @getnetent(3)@.+getNetworkEntry :: IO NetworkEntry+getNetworkEntry = withLock getNetworkEntry'++getNetworkEntry' :: IO NetworkEntry+getNetworkEntry' = do+ throwNoSuchThingIfNull "Network.BSD.getNetworkEntry" "no more network entries"+ $ c_getnetent+ >>= peek++foreign import ccall unsafe "getnetent" c_getnetent :: IO (Ptr NetworkEntry)++-- | Open the network name database. The parameter specifies+-- whether a connection is maintained open between various+-- networkEntry calls+--+-- @setnetent(3)@.+setNetworkEntry :: Bool -> IO ()+setNetworkEntry = withLock . setNetworkEntry'++setNetworkEntry' :: Bool -> IO ()+setNetworkEntry' flg = c_setnetent (fromBool flg)++foreign import ccall unsafe "setnetent" c_setnetent :: CInt -> IO ()++-- | Close the connection to the network name database.+--+-- @endnetent(3)@.+endNetworkEntry :: IO ()+endNetworkEntry = withLock $ c_endnetent++foreign import ccall unsafe "endnetent" c_endnetent :: IO ()++-- | Get the list of network entries via @getnetent(3)@.+getNetworkEntries :: Bool -> IO [NetworkEntry]+getNetworkEntries stayOpen = withLock $ do+ setNetworkEntry' stayOpen+ getEntries getNetworkEntry' c_endnetent+#endif++-- Mutex for name service lockdown++{-# NOINLINE lock #-}+lock :: MVar ()+lock = unsafePerformIO $ N.withSocketsDo $ newMVar ()++withLock :: IO a -> IO a+withLock act = withMVar lock (\_ -> act)++-- ---------------------------------------------------------------------------+-- Miscellaneous Functions++-- | Calling 'getHostName' returns the standard host name for the current+-- processor, as set at boot time.+--+-- @gethostname(2)@.+getHostName :: IO N.HostName+getHostName = do+ let size = 256+ allocaArray0 size $ \ cstr -> do+ throwSocketErrorIfMinus1_ "Network.BSD.getHostName" $ c_gethostname cstr (fromIntegral size)+ peekCString cstr++foreign import CALLCONV unsafe "gethostname"+ c_gethostname :: CString -> CSize -> IO CInt++-- Helper function used by the exported functions that provides a+-- Haskellised view of the enumerator functions:++getEntries :: IO a -- read+ -> IO () -- at end+ -> IO [a]+getEntries getOne atEnd = loop+ where+ loop = do+ vv <- E.catch (liftM Just getOne)+ (\ e -> let _types = e :: IOException in return Nothing)+ case vv of+ Nothing -> return []+ Just v -> loop >>= \ vs -> atEnd >> return (v:vs)+++throwNoSuchThingIfNull :: String -> String -> IO (Ptr a) -> IO (Ptr a)+throwNoSuchThingIfNull loc desc act = do+ ptr <- act+ if (ptr == nullPtr)+ then ioError (ioeSetErrorString (mkIOError NoSuchThing loc Nothing Nothing) desc)+ else return ptr++throwUnsupportedOperationPoke :: String -> Ptr a -> a -> IO ()+throwUnsupportedOperationPoke typ _ _ =+ ioError $ ioeSetErrorString ioe "Operation not implemented"+ where+ ioe = mkIOError UnsupportedOperation+ ("Network.BSD: instance Storable " ++ typ ++ ": poke")+ Nothing+ Nothing
network-bsd.cabal view
@@ -1,24 +1,87 @@-cabal-version: 1.22+cabal-version: 1.12 name: network-bsd-version: 2.8.0.0+version: 2.8.1.0 license: BSD3 license-file: LICENSE-maintainer: Kazu Yamamoto-synopsis: Network.BSD+maintainer: Kazu Yamamoto, Herbert Valerio Riedel+synopsis: POSIX network database (<netdb.h>) API description:- This package reexports the "Network.BSD" module split from the <https://hackage.haskell.org/package/network-2.8.0.0 network-2.8.0.0> package.+ This package provides Haskell bindings to the+ the [POSIX network database (<netdb.h>) API](http://pubs.opengroup.org/onlinepubs/009696699/basedefs/netdb.h.html). .- See newer versions of <https://hackage.haskell.org/package/network-bsd network-bsd> for more information.+ === Relationship to the @network@ package+ .+ The @network@ package version 2.* series provides "Network.BSD" but+ it is removed starting with @network@ version 3.0.+ .+ This package provides the "Network.BSD" module split off from the+ <https://hackage.haskell.org/package/network network package>.+ .+ If in addition to the @network@'s modules also "Network.BSD" is+ necessary, add @network-bsd@ to your dependencies like so:+ .+ > library+ > build-depends: network >= 2.7 && < 3.1+ > , network-bsd >= 2.7 && < 2.9+ .+ I.e. you can control the version of the @network@ package+ independently.+ .+ __NOTE__: Starting with @network-bsd-2.8.1.0@ the APIs of @network@+ and @network-bsd@ evolve differently, and consequently the+ versioning doesn't match up anymore! Moreover, also starting with+ version @network-bsd-2.8.1.0@ this package requires @network >= 3@+ in order to avoid module name clashes with @network < 3@'s+ "Network.BSD" module.+ .+ However, @network-bsd-2.7.0.0@ and @network-bsd-2.8.0.0@ passes thru+ the "Network.BSD" module from @network-2.7.*@ and @network-2.8.*@+ respectively in a non-clashing way via Cabal's+ <https://www.haskell.org/cabal/users-guide/developing-packages.html#pkg-field-library-reexported-modules reexported-modules>+ feature while ensuring a well-defined+ <https://pvp.haskell.org/ API versioning> of the observable API of+ @network-bsd@. This is why the example above supporting a wide range+ of @network@ versions works by including version 2.7.0.0 in the+ required version range of @network-bsd@. category: Network build-type: Simple homepage: https://github.com/haskell/network-bsd bug-reports: https://github.com/haskell/network-bsd/issues+tested-with: GHC == 7.8.4+ , GHC == 7.10.3+ , GHC == 8.0.2+ , GHC == 8.2.2+ , GHC == 8.4.4+ , GHC == 8.6.3+extra-source-files: CHANGELOG.md library default-language: Haskell2010- reexported-modules: Network.BSD- build-depends: base >= 4.8 && < 5, network == 2.8.0.*+ other-extensions: CPP, NondecreasingIndentation+ exposed-modules: Network.BSD+ build-depends: base >= 4.7 && < 5+ , deepseq >= 1.3.0.0 && < 1.5+ -- NOTES on `network` depdendency+ --+ -- `network-bsd` heavily relies on `network`'s+ -- exported CPP headers! make sure that `network`+ -- doesn't inadvertently break/change its CPP+ -- headers before advertising support for new+ -- versions of `network`.+ --+ -- Moreover, `network-bsd` reexports entities from+ -- `network` so we need to be very conservative+ -- with the bounds to avoid leaking through API+ -- changes that aren't reflected in `network-bsd`'s+ -- API version.+ , network >= 3.0.0.0 && < 3.0.1+ build-tools: hsc2hs >= 0.67 && < 0.69+ ghc-options: -Wall++ if os(windows) && impl(ghc >= 7.10)+ -- See https://github.com/haskell/network/pull/362+ cpp-options: -D_WIN32_WINNT=0x0600 source-repository head type: git