diff --git a/CHANGELOG.md b/CHANGELOG.md index 18e8bcd6..01bfbf56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ * Watchdog scheme for gracefulClose. [#620](https://github.com/haskell/network/pull/620) * Exporting recvBufNoWait. +* Support for getHostName + [#621](https://github.com/haskell/network/pull/621) ## Version 3.2.8.0 diff --git a/Network/Socket.hs b/Network/Socket.hs index ebbd4c41..e219a68d 100644 --- a/Network/Socket.hs +++ b/Network/Socket.hs @@ -112,7 +112,6 @@ module Network.Socket ( getAddrInfo, -- ** Types - HostName, ServiceName, AddrInfo (..), defaultHints, @@ -340,6 +339,10 @@ module Network.Socket ( getNameInfo, NameInfoFlag (..), + -- * Host name information + getHostName, + HostName, + -- * Low level -- ** socket operations @@ -409,7 +412,8 @@ module Network.Socket ( -- * Multicast Group MulticastGroup (..), -) where +) +where import Network.Socket.Buffer hiding ( recvBufFrom, @@ -423,6 +427,11 @@ import Network.Socket.Flag import Network.Socket.Handle import Network.Socket.If import Network.Socket.Info +#if !defined(mingw32_HOST_OS) +import Network.Socket.Posix.HostName(getHostName) +#else +import Network.Socket.Win32.HostName(getHostName) +#endif import Network.Socket.Internal import Network.Socket.Name hiding (getPeerName, getSocketName) import Network.Socket.Options diff --git a/Network/Socket/Posix/HostName.hsc b/Network/Socket/Posix/HostName.hsc new file mode 100644 index 00000000..26358a54 --- /dev/null +++ b/Network/Socket/Posix/HostName.hsc @@ -0,0 +1,25 @@ +module Network.Socket.Posix.HostName ( + getHostName, +) +where + +#include "HsNet.h" + +import Foreign.C.Error +import Foreign.C.String +import Foreign.C.Types +import Foreign.Marshal.Array +import Network.Socket.Info (HostName) + +foreign import ccall unsafe "gethostname" + gethostname :: CString -> CSize -> IO CInt + +-- | Get name of current host +-- +-- Since: 3.3.0.0 +getHostName :: IO HostName +getHostName = allocaArray0 size $ \cstr -> do + throwErrnoIfMinus1_ "getHostName" $ gethostname cstr (fromIntegral size) + peekCString cstr + where + size = 256 diff --git a/Network/Socket/Win32/HostName.hsc b/Network/Socket/Win32/HostName.hsc new file mode 100644 index 00000000..b6e86db8 --- /dev/null +++ b/Network/Socket/Win32/HostName.hsc @@ -0,0 +1,39 @@ +{-# LANGUAGE CPP #-} + +#include "HsNet.h" +##include "HsNetDef.h" + +module Network.Socket.Win32.HostName ( + getHostName, +) +where + +import Foreign.C.Types +import Foreign.Marshal.Utils +import Foreign.Ptr +import Foreign.Storable +import Network.Socket.Info (HostName) +import System.Win32.Types + +foreign import CALLCONV unsafe "windows.h GetComputerNameExW" + getComputerNameEx :: COMPUTER_NAME_FORMAT -> LPTSTR -> LPDWORD -> IO BOOL + +type COMPUTER_NAME_FORMAT = CInt + +computerNamePhysicalDnsHostname :: COMPUTER_NAME_FORMAT +computerNamePhysicalDnsHostname = 5 + +-- | Get name of current host +-- +-- Since: 3.3.0.0 +getHostName :: IO HostName +getHostName = with 0 $ \p_charcount -> do + -- On the first run, determine the character count and ignore any error we get + _ <- getComputerNameEx computerNamePhysicalDnsHostname nullPtr p_charcount + charcount <- peek p_charcount + + -- The second time around, use the correct character count to retrieve the data + withTString (replicate (fromIntegral charcount) ' ') $ \name -> do + failIfFalse_ "GetComputerNameExW" $ + getComputerNameEx computerNamePhysicalDnsHostname name p_charcount + peekTString name diff --git a/network.cabal b/network.cabal index 0f30eb15..8a91859c 100644 --- a/network.cabal +++ b/network.cabal @@ -140,6 +140,7 @@ library Network.Socket.ByteString.Lazy.Posix Network.Socket.Posix.Cmsg Network.Socket.Posix.CmsgHdr + Network.Socket.Posix.HostName Network.Socket.Posix.IOVec Network.Socket.Posix.MsgHdr @@ -160,6 +161,7 @@ library Network.Socket.ByteString.Lazy.Windows Network.Socket.Win32.Cmsg Network.Socket.Win32.CmsgHdr + Network.Socket.Win32.HostName Network.Socket.Win32.WSABuf Network.Socket.Win32.MsgHdr diff --git a/tests/Network/SocketSpec.hs b/tests/Network/SocketSpec.hs index e3142081..068b7353 100644 --- a/tests/Network/SocketSpec.hs +++ b/tests/Network/SocketSpec.hs @@ -409,6 +409,10 @@ spec = do it "holds for CmsgId" $ forAll cmsgidGen $ \x -> (read . show $ x) == (x :: CmsgId) + describe "hostname" $ do + it "is not empty" $ do + hostname <- getHostName + hostname `shouldSatisfy` (not . null) -- Type-specific generators with strong bias towards pattern synonyms