    {-# LANGUAGE CPP #-}

    module Network.DNS.Resolver.Internal (
          getDefaultDnsServers
        ) where

    import Network.DNS.Imports

    #if !defined(mingw32_HOST_OS)
    #define POSIX
    #else
    #define WIN
    #endif

    #if defined(WIN)
    import Foreign.C.String
    import Foreign.Marshal.Alloc (allocaBytes)
    #else
    import Data.Char (isSpace)
    #endif

    getDefaultDnsServers :: FilePath -> IO [String]

    #if defined(WIN)

    foreign import ccall "getWindowsDefDnsServers" getWindowsDefDnsServers :: CString -> Int -> IO Word32

    getDefaultDnsServers _ = do
      allocaBytes 256 $ \cString -> do
         res <- getWindowsDefDnsServers cString 256
         case res of
           0 -> split ',' <$> peekCString cString
           _ -> return [] -- TODO: Do proper error handling here.
      where
        split :: Char -> String -> [String]
        split c cs =
            let (h, t) = dropWhile (== c) <$> break (== c) cs
             in if null t
                then if null h then [] else [h]
                else if null h
                then split c t
                else h : split c t

    #else

    getDefaultDnsServers :: FilePath -> IO [FilePath]
    getDefaultDnsServers file :: FilePath
    file = FilePath -> [FilePath]
    toAddresses (FilePath -> [FilePath]) -> IO FilePath -> IO [FilePath]
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> FilePath -> IO FilePath
    readFile FilePath
    file
      where
        toAddresses :: String -> [String]
        toAddresses :: FilePath -> [FilePath]
    toAddresses cs :: FilePath
    cs = (FilePath -> FilePath) -> [FilePath] -> [FilePath]
    forall a b. (a -> b) -> [a] -> [b]
    map FilePath -> FilePath
    extract ((FilePath -> Bool) -> [FilePath] -> [FilePath]
    forall a. (a -> Bool) -> [a] -> [a]
    filter ("nameserver" FilePath -> FilePath -> Bool
    forall a. Eq a => [a] -> [a] -> Bool
    `isPrefixOf`) (FilePath -> [FilePath]
    lines FilePath
    cs))
        extract :: FilePath -> FilePath
    extract = FilePath -> FilePath
    forall a. [a] -> [a]
    reverse (FilePath -> FilePath)
    -> (FilePath -> FilePath) -> FilePath -> FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Bool) -> FilePath -> FilePath
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile Char -> Bool
    isSpace (FilePath -> FilePath)
    -> (FilePath -> FilePath) -> FilePath -> FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FilePath -> FilePath
    forall a. [a] -> [a]
    reverse (FilePath -> FilePath)
    -> (FilePath -> FilePath) -> FilePath -> FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Char -> Bool) -> FilePath -> FilePath
    forall a. (a -> Bool) -> [a] -> [a]
    dropWhile Char -> Bool
    isSpace (FilePath -> FilePath)
    -> (FilePath -> FilePath) -> FilePath -> FilePath
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> FilePath -> FilePath
    forall a. Int -> [a] -> [a]
    drop 11

    #endif