diff --git a/System/Posix/ByteString/FilePath.hsc b/System/Posix/ByteString/FilePath.hsc
--- a/System/Posix/ByteString/FilePath.hsc
+++ b/System/Posix/ByteString/FilePath.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 
 -----------------------------------------------------------------------------
 -- |
@@ -29,7 +25,8 @@
      throwErrnoPathIf_,
      throwErrnoPathIfNull,
      throwErrnoPathIfMinus1,
-     throwErrnoPathIfMinus1_
+     throwErrnoPathIfMinus1_,
+     throwErrnoTwoPathsIfMinus1_
   ) where
 
 import Foreign hiding ( void )
@@ -45,6 +42,9 @@
 import Data.ByteString
 import Data.ByteString.Char8 as BC
 import Prelude hiding (FilePath)
+#if !MIN_VERSION_base(4, 11, 0)
+import Data.Monoid ((<>))
+#endif
 
 -- | A literal POSIX file path
 type RawFilePath = ByteString
@@ -125,3 +125,9 @@
 --
 throwErrnoPathIfMinus1_ :: (Eq a, Num a) => String -> RawFilePath -> IO a -> IO ()
 throwErrnoPathIfMinus1_  = throwErrnoPathIf_ (== -1)
+
+-- | as 'throwErrnoTwoPathsIfMinus1_', but exceptions include two paths when appropriate.
+--
+throwErrnoTwoPathsIfMinus1_ :: (Eq a, Num a) => String -> RawFilePath -> RawFilePath -> IO a -> IO ()
+throwErrnoTwoPathsIfMinus1_  loc path1 path2 =
+    throwErrnoIfMinus1_ (loc <> " '" <> BC.unpack path1 <> "' to '" <> BC.unpack path2 <> "'")
diff --git a/System/Posix/Directory.hsc b/System/Posix/Directory.hsc
--- a/System/Posix/Directory.hsc
+++ b/System/Posix/Directory.hsc
@@ -1,10 +1,6 @@
 {-# LANGUAGE CApiFFI #-}
 {-# LANGUAGE NondecreasingIndentation #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 
 -----------------------------------------------------------------------------
 -- |
@@ -35,6 +31,7 @@
    DirStream,
    openDirStream,
    readDirStream,
+   readDirStreamMaybe,
    rewindDirStream,
    closeDirStream,
    DirStreamOffset,
@@ -51,6 +48,7 @@
    changeWorkingDirectoryFd,
   ) where
 
+import Data.Maybe
 import System.IO.Error
 import System.Posix.Error
 import System.Posix.Types
@@ -88,8 +86,20 @@
 --   next directory entry (@struct dirent@) for the open directory
 --   stream @dp@, and returns the @d_name@ member of that
 --  structure.
+--
+--  Note that this function returns an empty filepath if the end of the
+--  directory stream is reached. For a safer alternative use
+--  'readDirStreamMaybe'.
 readDirStream :: DirStream -> IO FilePath
-readDirStream (DirStream dirp) =
+readDirStream = fmap (fromMaybe "") . readDirStreamMaybe
+
+-- | @readDirStreamMaybe dp@ calls @readdir@ to obtain the
+--   next directory entry (@struct dirent@) for the open directory
+--   stream @dp@. It returns the @d_name@ member of that
+--  structure wrapped in a @Just d_name@ if an entry was read and @Nothing@ if
+--  the end of the directory stream was reached.
+readDirStreamMaybe :: DirStream -> IO (Maybe FilePath)
+readDirStreamMaybe (DirStream dirp) =
   alloca $ \ptr_dEnt  -> loop ptr_dEnt
  where
   loop ptr_dEnt = do
@@ -98,16 +108,16 @@
     if (r == 0)
          then do dEnt <- peek ptr_dEnt
                  if (dEnt == nullPtr)
-                    then return []
+                    then return Nothing
                     else do
                      entry <- (d_name dEnt >>= peekFilePath)
                      c_freeDirEnt dEnt
-                     return entry
+                     return $ Just entry
          else do errno <- getErrno
                  if (errno == eINTR) then loop ptr_dEnt else do
                  let (Errno eo) = errno
                  if (eo == 0)
-                    then return []
+                    then return Nothing
                     else throwErrno "readDirStream"
 
 -- traversing directories
diff --git a/System/Posix/Directory/ByteString.hsc b/System/Posix/Directory/ByteString.hsc
--- a/System/Posix/Directory/ByteString.hsc
+++ b/System/Posix/Directory/ByteString.hsc
@@ -1,10 +1,6 @@
 {-# LANGUAGE CApiFFI #-}
 {-# LANGUAGE NondecreasingIndentation #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 
 -----------------------------------------------------------------------------
 -- |
@@ -35,6 +31,7 @@
    DirStream,
    openDirStream,
    readDirStream,
+   readDirStreamMaybe,
    rewindDirStream,
    closeDirStream,
    DirStreamOffset,
@@ -45,12 +42,13 @@
    seekDirStream,
 #endif
 
-   -- * The working dirctory
+   -- * The working directory
    getWorkingDirectory,
    changeWorkingDirectory,
    changeWorkingDirectoryFd,
   ) where
 
+import Data.Maybe
 import System.IO.Error
 import System.Posix.Types
 import Foreign
@@ -89,8 +87,20 @@
 --   next directory entry (@struct dirent@) for the open directory
 --   stream @dp@, and returns the @d_name@ member of that
 --  structure.
+--
+--  Note that this function returns an empty filepath if the end of the
+--  directory stream is reached. For a safer alternative use
+--  'readDirStreamMaybe'.
 readDirStream :: DirStream -> IO RawFilePath
-readDirStream (DirStream dirp) =
+readDirStream = fmap (fromMaybe BC.empty) . readDirStreamMaybe
+
+-- | @readDirStreamMaybe dp@ calls @readdir@ to obtain the
+--   next directory entry (@struct dirent@) for the open directory
+--   stream @dp@. It returns the @d_name@ member of that
+--  structure wrapped in a @Just d_name@ if an entry was read and @Nothing@ if
+--  the end of the directory stream was reached.
+readDirStreamMaybe :: DirStream -> IO (Maybe RawFilePath)
+readDirStreamMaybe (DirStream dirp) =
   alloca $ \ptr_dEnt  -> loop ptr_dEnt
  where
   loop ptr_dEnt = do
@@ -99,16 +109,16 @@
     if (r == 0)
          then do dEnt <- peek ptr_dEnt
                  if (dEnt == nullPtr)
-                    then return BC.empty
+                    then return Nothing
                     else do
                      entry <- (d_name dEnt >>= peekFilePath)
                      c_freeDirEnt dEnt
-                     return entry
+                     return $ Just entry
          else do errno <- getErrno
                  if (errno == eINTR) then loop ptr_dEnt else do
                  let (Errno eo) = errno
                  if (eo == 0)
-                    then return BC.empty
+                    then return Nothing
                     else throwErrno "readDirStream"
 
 -- traversing directories
diff --git a/System/Posix/Directory/Common.hsc b/System/Posix/Directory/Common.hsc
--- a/System/Posix/Directory/Common.hsc
+++ b/System/Posix/Directory/Common.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
-{-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
+{-# LANGUAGE Safe, CApiFFI #-}
 
 -----------------------------------------------------------------------------
 -- |
@@ -22,6 +18,7 @@
 
 module System.Posix.Directory.Common (
        DirStream(..), CDir, CDirent, DirStreamOffset(..),
+       unsafeOpenDirStreamFd,
        rewindDirStream,
        closeDirStream,
 #ifdef HAVE_SEEKDIR
@@ -33,14 +30,48 @@
        changeWorkingDirectoryFd,
   ) where
 
+import Control.Exception (mask_)
+import Control.Monad (void, when)
 import System.Posix.Types
-import Foreign
+import Foreign hiding (void)
 import Foreign.C
 
 newtype DirStream = DirStream (Ptr CDir)
 
 data {-# CTYPE "DIR" #-} CDir
 data {-# CTYPE "struct dirent" #-} CDirent
+
+-- | Call @fdopendir@ to obtain a directory stream for @fd@. @fd@ must not be
+-- otherwise used after this.
+--
+-- On success, it is owned by the returned 'DirStream', which should be closed
+-- via 'closeDirStream' when no longer needed.  On error, the file descriptor
+-- is automatically closed and then an exception is thrown.  There is no code
+-- path in which the file descriptor remains open and yet not owned by a
+-- returned 'DirStream'.
+--
+-- The input file descriptor must not have been used with @threadWaitRead@ or
+-- @threadWaitWrite@.
+unsafeOpenDirStreamFd :: Fd -> IO DirStream
+unsafeOpenDirStreamFd (Fd fd) = mask_ $ do
+    ptr <- c_fdopendir fd
+    when (ptr == nullPtr) $ do
+        errno <- getErrno
+        void $ c_close fd
+        ioError (errnoToIOError "openDirStreamFd" errno Nothing Nothing)
+    return $ DirStream ptr
+
+-- We need c_close here, because 'closeFd' throws exceptions on error,
+-- but we want to silently close the (presumably directory) descriptor.
+foreign import ccall unsafe "HsUnix.h close"
+   c_close :: CInt -> IO CInt
+
+-- NOTE: It is /critical/ to use "capi" and "dirent.h" here, because system
+-- headers on e.g. macOS alias this function, and linking directly to the
+-- "fdopendir" symbol in libc leads to a crash!
+--
+foreign import capi unsafe "dirent.h fdopendir"
+    c_fdopendir :: CInt -> IO (Ptr CDir)
 
 -- | @rewindDirStream dp@ calls @rewinddir@ to reposition
 --   the directory stream @dp@ at the beginning of the directory.
diff --git a/System/Posix/Directory/Fd.hsc b/System/Posix/Directory/Fd.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Directory/Fd.hsc
@@ -0,0 +1,7 @@
+#include "HsUnix.h"
+
+module System.Posix.Directory.Fd (
+    unsafeOpenDirStreamFd
+) where
+
+import System.Posix.Directory.Common
diff --git a/System/Posix/Directory/Internals.hsc b/System/Posix/Directory/Internals.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Directory/Internals.hsc
@@ -0,0 +1,17 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.Directory.Internals
+-- Copyright   :  (c) The University of Glasgow 2022
+-- License     :  BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer  :  libraries@haskell.org
+-- Stability   :  provisional
+-- Portability :  non-portable (requires POSIX)
+--
+-- POSIX directory support (internal module, no PVP guarantees)
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.Directory.Internals ( DirStream(..), CDir, CDirent, DirStreamOffset(..) ) where
+
+import System.Posix.Directory.Common
diff --git a/System/Posix/Directory/PosixPath.hsc b/System/Posix/Directory/PosixPath.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Directory/PosixPath.hsc
@@ -0,0 +1,166 @@
+{-# LANGUAGE CApiFFI #-}
+{-# LANGUAGE NondecreasingIndentation #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.Directory.PosixPath
+-- 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)
+--
+-- PosixPath based POSIX directory support
+--
+-----------------------------------------------------------------------------
+
+#include "HsUnix.h"
+
+-- hack copied from System.Posix.Files
+#if !defined(PATH_MAX)
+# define PATH_MAX 4096
+#endif
+
+module System.Posix.Directory.PosixPath (
+   -- * Creating and removing directories
+   createDirectory, removeDirectory,
+
+   -- * Reading directories
+   DirStream,
+   openDirStream,
+   readDirStream,
+   rewindDirStream,
+   closeDirStream,
+   DirStreamOffset,
+#ifdef HAVE_TELLDIR
+   tellDirStream,
+#endif
+#ifdef HAVE_SEEKDIR
+   seekDirStream,
+#endif
+
+   -- * The working directory
+   getWorkingDirectory,
+   changeWorkingDirectory,
+   changeWorkingDirectoryFd,
+  ) where
+
+import System.IO.Error
+import System.Posix.Types
+import Foreign
+import Foreign.C
+
+import System.OsPath.Types
+import GHC.IO.Encoding.UTF8 ( mkUTF8 )
+import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )
+import System.OsPath.Posix
+import System.Posix.Directory hiding (createDirectory, openDirStream, readDirStream, getWorkingDirectory, changeWorkingDirectory, removeDirectory)
+import qualified System.Posix.Directory.Common as Common
+import System.Posix.PosixPath.FilePath
+
+-- | @createDirectory dir mode@ calls @mkdir@ to
+--   create a new directory, @dir@, with permissions based on
+--  @mode@.
+createDirectory :: PosixPath -> FileMode -> IO ()
+createDirectory name mode =
+  withFilePath name $ \s ->
+    throwErrnoPathIfMinus1Retry_ "createDirectory" name (c_mkdir s mode)
+    -- POSIX doesn't allow mkdir() to return EINTR, but it does on
+    -- OS X (#5184), so we need the Retry variant here.
+
+foreign import ccall unsafe "mkdir"
+  c_mkdir :: CString -> CMode -> IO CInt
+
+-- | @openDirStream dir@ calls @opendir@ to obtain a
+--   directory stream for @dir@.
+openDirStream :: PosixPath -> IO DirStream
+openDirStream name =
+  withFilePath name $ \s -> do
+    dirp <- throwErrnoPathIfNullRetry "openDirStream" name $ c_opendir s
+    return (Common.DirStream dirp)
+
+foreign import capi unsafe "HsUnix.h opendir"
+   c_opendir :: CString  -> IO (Ptr Common.CDir)
+
+-- | @readDirStream dp@ calls @readdir@ to obtain the
+--   next directory entry (@struct dirent@) for the open directory
+--   stream @dp@, and returns the @d_name@ member of that
+--  structure.
+readDirStream :: DirStream -> IO PosixPath
+readDirStream (Common.DirStream dirp) = alloca $ \ptr_dEnt  -> loop ptr_dEnt
+ where
+  loop ptr_dEnt = do
+    resetErrno
+    r <- c_readdir dirp ptr_dEnt
+    if (r == 0)
+         then do dEnt <- peek ptr_dEnt
+                 if (dEnt == nullPtr)
+                    then return mempty
+                    else do
+                     entry <- (d_name dEnt >>= peekFilePath)
+                     c_freeDirEnt dEnt
+                     return entry
+         else do errno <- getErrno
+                 if (errno == eINTR) then loop ptr_dEnt else do
+                 let (Errno eo) = errno
+                 if (eo == 0)
+                    then return mempty
+                    else throwErrno "readDirStream"
+
+-- traversing directories
+foreign import ccall unsafe "__hscore_readdir"
+  c_readdir  :: Ptr Common.CDir -> Ptr (Ptr Common.CDirent) -> IO CInt
+
+foreign import ccall unsafe "__hscore_free_dirent"
+  c_freeDirEnt  :: Ptr Common.CDirent -> IO ()
+
+foreign import ccall unsafe "__hscore_d_name"
+  d_name :: Ptr Common.CDirent -> IO CString
+
+
+-- | @getWorkingDirectory@ calls @getcwd@ to obtain the name
+--   of the current working directory.
+getWorkingDirectory :: IO PosixPath
+getWorkingDirectory = go (#const PATH_MAX)
+  where
+    go bytes = do
+        r <- allocaBytes bytes $ \buf -> do
+            buf' <- c_getcwd buf (fromIntegral bytes)
+            if buf' /= nullPtr
+                then do s <- peekFilePath buf
+                        return (Just s)
+                else do errno <- getErrno
+                        if errno == eRANGE
+                            -- we use Nothing to indicate that we should
+                            -- try again with a bigger buffer
+                            then return Nothing
+                            else throwErrno "getWorkingDirectory"
+        maybe (go (2 * bytes)) return r
+
+foreign import ccall unsafe "getcwd"
+   c_getcwd   :: Ptr CChar -> CSize -> IO (Ptr CChar)
+
+-- | @changeWorkingDirectory dir@ calls @chdir@ to change
+--   the current working directory to @dir@.
+changeWorkingDirectory :: PosixPath -> IO ()
+changeWorkingDirectory path =
+  modifyIOError (`ioeSetFileName` (_toStr path)) $
+    withFilePath path $ \s ->
+       throwErrnoIfMinus1Retry_ "changeWorkingDirectory" (c_chdir s)
+
+foreign import ccall unsafe "chdir"
+   c_chdir :: CString -> IO CInt
+
+removeDirectory :: PosixPath -> IO ()
+removeDirectory path =
+  modifyIOError (`ioeSetFileName` _toStr path) $
+    withFilePath path $ \s ->
+       throwErrnoIfMinus1Retry_ "removeDirectory" (c_rmdir s)
+
+foreign import ccall unsafe "rmdir"
+   c_rmdir :: CString -> IO CInt
+
+_toStr :: PosixPath -> String
+_toStr fp = either (error . show) id $ decodeWith (mkUTF8 TransliterateCodingFailure) fp
+
diff --git a/System/Posix/DynamicLinker.hsc b/System/Posix/DynamicLinker.hsc
--- a/System/Posix/DynamicLinker.hsc
+++ b/System/Posix/DynamicLinker.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.DynamicLinker
@@ -56,17 +52,15 @@
 #include "HsUnix.h"
 
 import Control.Exception        ( bracket )
-import Control.Monad    ( liftM )
 import Foreign
 import System.Posix.Internals ( withFilePath )
 
 dlopen :: FilePath -> [RTLDFlags] -> IO DL
-dlopen path flags = do
-  withFilePath path $ \ p -> do
-    liftM DLHandle $ throwDLErrorIf "dlopen" (== nullPtr) $ c_dlopen p (packRTLDFlags flags)
+dlopen path flags = withFilePath path $ \p -> DLHandle <$>
+  throwDLErrorIf "dlopen" (== nullPtr) (c_dlopen p (packRTLDFlags flags))
 
-withDL :: String -> [RTLDFlags] -> (DL -> IO a) -> IO a
+withDL :: FilePath -> [RTLDFlags] -> (DL -> IO a) -> IO a
 withDL file flags f = bracket (dlopen file flags) (dlclose) f
 
-withDL_ :: String -> [RTLDFlags] -> (DL -> IO a) -> IO ()
+withDL_ :: FilePath -> [RTLDFlags] -> (DL -> IO a) -> IO ()
 withDL_ file flags f = withDL file flags f >> return ()
diff --git a/System/Posix/DynamicLinker/ByteString.hsc b/System/Posix/DynamicLinker/ByteString.hsc
--- a/System/Posix/DynamicLinker/ByteString.hsc
+++ b/System/Posix/DynamicLinker/ByteString.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 
 -----------------------------------------------------------------------------
 -- |
@@ -57,14 +53,12 @@
 #include "HsUnix.h"
 
 import Control.Exception        ( bracket )
-import Control.Monad    ( liftM )
 import Foreign
 import System.Posix.ByteString.FilePath
 
 dlopen :: RawFilePath -> [RTLDFlags] -> IO DL
-dlopen path flags = do
-  withFilePath path $ \ p -> do
-    liftM DLHandle $ throwDLErrorIf "dlopen" (== nullPtr) $ c_dlopen p (packRTLDFlags flags)
+dlopen path flags = withFilePath path $ \p -> DLHandle <$>
+  throwDLErrorIf "dlopen" (== nullPtr) (c_dlopen p (packRTLDFlags flags))
 
 withDL :: RawFilePath -> [RTLDFlags] -> (DL -> IO a) -> IO a
 withDL file flags f = bracket (dlopen file flags) (dlclose) f
diff --git a/System/Posix/DynamicLinker/Common.hsc b/System/Posix/DynamicLinker/Common.hsc
--- a/System/Posix/DynamicLinker/Common.hsc
+++ b/System/Posix/DynamicLinker/Common.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.DynamicLinker.Common
diff --git a/System/Posix/DynamicLinker/Module.hsc b/System/Posix/DynamicLinker/Module.hsc
--- a/System/Posix/DynamicLinker/Module.hsc
+++ b/System/Posix/DynamicLinker/Module.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.DynamicLinker.Module
diff --git a/System/Posix/DynamicLinker/Module/ByteString.hsc b/System/Posix/DynamicLinker/Module/ByteString.hsc
--- a/System/Posix/DynamicLinker/Module/ByteString.hsc
+++ b/System/Posix/DynamicLinker/Module/ByteString.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 
 -----------------------------------------------------------------------------
 -- |
diff --git a/System/Posix/DynamicLinker/Prim.hsc b/System/Posix/DynamicLinker/Prim.hsc
--- a/System/Posix/DynamicLinker/Prim.hsc
+++ b/System/Posix/DynamicLinker/Prim.hsc
@@ -1,7 +1,5 @@
 {-# LANGUAGE Trustworthy #-}
-#if __GLASGOW_HASKELL__ >= 709
-{-# OPTIONS_GHC -fno-warn-trustworthy-safe #-}
-#endif
+{-# OPTIONS_GHC -Wno-trustworthy-safe #-}
 
 -----------------------------------------------------------------------------
 -- |
@@ -43,11 +41,16 @@
 import Foreign.C.Types
 import Foreign.C.String ( CString )
 
+#if !defined(HAVE_DLFCN_H)
+import Control.Exception ( throw )
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
 
 -- |On some hosts (e.g. SuSe and Ubuntu Linux) @RTLD_NEXT@ (and
 -- @RTLD_DEFAULT@) are not visible without setting the macro
 -- @_GNU_SOURCE@. Since we don\'t want to define this macro, you can use
--- the function 'haveRtldNext' to check wether the flag `Next` is
+-- the function 'haveRtldNext' to check whether the flag `Next` is
 -- available. Ideally, this will be optimized by the compiler so that it
 -- should be as efficient as an @#ifdef@.
 --
@@ -90,11 +93,20 @@
 packRTLDFlags flags = foldl (\ s f -> (packRTLDFlag f) .|. s) 0 flags
 
 packRTLDFlag :: RTLDFlags -> CInt
+#if defined(HAVE_DLFCN_H)
+
 packRTLDFlag RTLD_LAZY = #const RTLD_LAZY
 packRTLDFlag RTLD_NOW = #const RTLD_NOW
 packRTLDFlag RTLD_GLOBAL = #const RTLD_GLOBAL
 packRTLDFlag RTLD_LOCAL = #const RTLD_LOCAL
 
+#else
+
+{-# WARNING packRTLDFlag
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_DLFCN_H@)" #-}
+packRTLDFlag _ = throw (ioeSetLocation unsupportedOperation "packRTLDFlag")
+
+#endif // HAVE_DLFCN_H
 
 -- |Flags for 'System.Posix.DynamicLinker.dlsym'. Notice that 'Next'
 -- might not be available on your particular platform! Use
diff --git a/System/Posix/Env.hsc b/System/Posix/Env.hsc
--- a/System/Posix/Env.hsc
+++ b/System/Posix/Env.hsc
@@ -1,9 +1,5 @@
 {-# LANGUAGE CApiFFI #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Env
@@ -42,12 +38,6 @@
 import Data.Maybe (fromMaybe)
 import System.Posix.Internals
 
-#if !MIN_VERSION_base(4,7,0)
--- needed for backported local 'newFilePath' binding in 'putEnv'
-import GHC.IO.Encoding (getFileSystemEncoding)
-import qualified GHC.Foreign as GHC (newCString)
-#endif
-
 -- |'getEnv' looks up a variable in the environment.
 
 getEnv ::
@@ -56,7 +46,7 @@
 getEnv name = do
   litstring <- withFilePath name c_getenv
   if litstring /= nullPtr
-     then liftM Just $ peekFilePath litstring
+     then Just <$> peekFilePath litstring
      else return Nothing
 
 -- |'getEnvDefault' is a wrapper around 'getEnv' where the
@@ -67,7 +57,7 @@
   String    {- ^ variable name                    -} ->
   String    {- ^ fallback value                   -} ->
   IO String {- ^ variable value or fallback value -}
-getEnvDefault name fallback = liftM (fromMaybe fallback) (getEnv name)
+getEnvDefault name fallback = fromMaybe fallback <$> getEnv name
 
 foreign import ccall unsafe "getenv"
    c_getenv :: CString -> IO CString
@@ -150,11 +140,6 @@
                      -- According to SUSv2, the string passed to putenv
                      -- becomes part of the environment. #7342
                      throwErrnoIfMinus1_ "putenv" (c_putenv s)
-#if !MIN_VERSION_base(4,7,0)
-    where
-      newFilePath :: FilePath -> IO CString
-      newFilePath fp = getFileSystemEncoding >>= \enc -> GHC.newCString enc fp
-#endif
 
 foreign import ccall unsafe "putenv"
    c_putenv :: CString -> IO CInt
diff --git a/System/Posix/Env/ByteString.hsc b/System/Posix/Env/ByteString.hsc
--- a/System/Posix/Env/ByteString.hsc
+++ b/System/Posix/Env/ByteString.hsc
@@ -52,7 +52,7 @@
 getEnv name = do
   litstring <- B.useAsCString name c_getenv
   if litstring /= nullPtr
-     then liftM Just $ B.packCString litstring
+     then Just <$> B.packCString litstring
      else return Nothing
 
 -- |'getEnvDefault' is a wrapper around 'getEnv' where the
@@ -63,7 +63,7 @@
   ByteString    {- ^ variable name                    -} ->
   ByteString    {- ^ fallback value                   -} ->
   IO ByteString {- ^ variable value or fallback value -}
-getEnvDefault name fallback = liftM (fromMaybe fallback) (getEnv name)
+getEnvDefault name fallback = fromMaybe fallback <$> getEnv name
 
 foreign import ccall unsafe "getenv"
    c_getenv :: CString -> IO CString
@@ -104,7 +104,7 @@
 -- |'setEnvironment' resets the entire environment to the given list of
 -- @(key,value)@ pairs.
 --
--- @since 2.7.3
+-- @since 2.8.0.0
 setEnvironment ::
   [(ByteString,ByteString)] {- ^ @[(key,value)]@ -} ->
   IO ()
@@ -199,7 +199,7 @@
   alloca $ \ p_argc ->
   alloca $ \ p_argv -> do
    getProgArgv p_argc p_argv
-   p    <- fromIntegral `liftM` peek p_argc
+   p    <- fromIntegral <$> peek p_argc
    argv <- peek p_argv
    peekArray (p - 1) (advancePtr argv 1) >>= mapM B.packCString
 
diff --git a/System/Posix/Env/PosixString.hsc b/System/Posix/Env/PosixString.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Env/PosixString.hsc
@@ -0,0 +1,206 @@
+{-# LANGUAGE CApiFFI #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.Env.PosixString
+-- 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 environment support
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.Env.PosixString (
+       -- * Environment Variables
+        getEnv
+        , getEnvDefault
+        , getEnvironmentPrim
+        , getEnvironment
+        , setEnvironment
+        , putEnv
+        , setEnv
+        , unsetEnv
+        , clearEnv
+
+       -- * Program arguments
+       , getArgs
+) where
+
+#include "HsUnix.h"
+
+import Control.Monad
+import Foreign
+import Foreign.C
+import Data.Maybe       ( fromMaybe )
+
+import GHC.IO.Encoding.UTF8 ( mkUTF8 )
+import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )
+import System.Posix.Env ( clearEnv )
+import System.OsPath.Posix
+import System.OsString.Internal.Types
+import qualified System.OsPath.Data.ByteString.Short as B
+import Data.ByteString.Short.Internal ( copyToPtr )
+
+-- |'getEnv' looks up a variable in the environment.
+
+getEnv ::
+  PosixString            {- ^ variable name  -} ->
+  IO (Maybe PosixString) {- ^ variable value -}
+getEnv (PS name) = do
+  litstring <- B.useAsCString name c_getenv
+  if litstring /= nullPtr
+     then (Just . PS) <$> B.packCString litstring
+     else return Nothing
+
+-- |'getEnvDefault' is a wrapper around 'getEnv' where the
+-- programmer can specify a fallback as the second argument, which will be
+-- used if the variable is not found in the environment.
+
+getEnvDefault ::
+  PosixString    {- ^ variable name                    -} ->
+  PosixString    {- ^ fallback value                   -} ->
+  IO PosixString {- ^ variable value or fallback value -}
+getEnvDefault name fallback = fromMaybe fallback <$> getEnv name
+
+foreign import ccall unsafe "getenv"
+   c_getenv :: CString -> IO CString
+
+getEnvironmentPrim :: IO [PosixString]
+getEnvironmentPrim = do
+  c_environ <- getCEnviron
+  arr <- peekArray0 nullPtr c_environ
+  mapM (fmap PS . B.packCString) arr
+
+getCEnviron :: IO (Ptr CString)
+#if HAVE__NSGETENVIRON
+-- You should not access @char **environ@ directly on Darwin in a bundle/shared library.
+-- See #2458 and http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man7/environ.7.html
+getCEnviron = nsGetEnviron >>= peek
+
+foreign import ccall unsafe "_NSGetEnviron"
+   nsGetEnviron :: IO (Ptr (Ptr CString))
+#else
+getCEnviron = peek c_environ_p
+
+foreign import ccall unsafe "&environ"
+   c_environ_p :: Ptr (Ptr CString)
+#endif
+
+-- |'getEnvironment' retrieves the entire environment as a
+-- list of @(key,value)@ pairs.
+
+getEnvironment :: IO [(PosixString,PosixString)] {- ^ @[(key,value)]@ -}
+getEnvironment = do
+  env <- getEnvironmentPrim
+  return $ map (dropEq . (B.break ((==) _equal)) . getPosixString) env
+ where
+   dropEq (x,y)
+      | B.head y == _equal = (PS x, PS (B.tail y))
+      | otherwise          = error $ "getEnvironment: insane variable " ++ _toStr x
+
+-- |'setEnvironment' resets the entire environment to the given list of
+-- @(key,value)@ pairs.
+setEnvironment ::
+  [(PosixString,PosixString)] {- ^ @[(key,value)]@ -} ->
+  IO ()
+setEnvironment env = do
+  clearEnv
+  forM_ env $ \(key,value) ->
+    setEnv key value True {-overwrite-}
+
+-- |The 'unsetEnv' function deletes all instances of the variable name
+-- from the environment.
+
+unsetEnv :: PosixString {- ^ variable name -} -> IO ()
+#if HAVE_UNSETENV
+# if !UNSETENV_RETURNS_VOID
+unsetEnv (PS name) = B.useAsCString name $ \ s ->
+  throwErrnoIfMinus1_ "unsetenv" (c_unsetenv s)
+
+-- POSIX.1-2001 compliant unsetenv(3)
+foreign import capi unsafe "HsUnix.h unsetenv"
+   c_unsetenv :: CString -> IO CInt
+# else
+unsetEnv name = B.useAsCString name c_unsetenv
+
+-- pre-POSIX unsetenv(3) returning @void@
+foreign import capi unsafe "HsUnix.h unsetenv"
+   c_unsetenv :: CString -> IO ()
+# endif
+#else
+unsetEnv name = putEnv (name <> PosixString (B.pack "="))
+#endif
+
+-- |'putEnv' function takes an argument of the form @name=value@
+-- and is equivalent to @setEnv(key,value,True{-overwrite-})@.
+putEnv :: PosixString {- ^ "key=value" -} -> IO ()
+putEnv (PS sbs) = do
+  buf <- mallocBytes (l+1)
+  copyToPtr sbs 0 buf (fromIntegral l)
+  pokeByteOff buf l (0::Word8)
+  throwErrnoIfMinus1_ "putenv" (c_putenv buf)
+ where l = B.length sbs
+
+
+foreign import ccall unsafe "putenv"
+   c_putenv :: CString -> IO CInt
+
+{- |The 'setEnv' function inserts or resets the environment variable name in
+     the current environment list.  If the variable @name@ does not exist in the
+     list, it is inserted with the given value.  If the variable does exist,
+     the argument @overwrite@ is tested; if @overwrite@ is @False@, the variable is
+     not reset, otherwise it is reset to the given value.
+-}
+
+setEnv ::
+  PosixString {- ^ variable name  -} ->
+  PosixString {- ^ variable value -} ->
+  Bool       {- ^ overwrite      -} ->
+  IO ()
+#ifdef HAVE_SETENV
+setEnv (PS key) (PS value) ovrwrt = do
+  B.useAsCString key $ \ keyP ->
+    B.useAsCString value $ \ valueP ->
+      throwErrnoIfMinus1_ "setenv" $
+        c_setenv keyP valueP (fromIntegral (fromEnum ovrwrt))
+
+foreign import ccall unsafe "setenv"
+   c_setenv :: CString -> CString -> CInt -> IO CInt
+#else
+setEnv key value True = putEnv (key++"="++value)
+setEnv key value False = do
+  res <- getEnv key
+  case res of
+    Just _  -> return ()
+    Nothing -> putEnv (key++"="++value)
+#endif
+
+-- | Computation 'getArgs' returns a list of the program's command
+-- line arguments (not including the program name), as 'PosixString's.
+--
+-- Unlike 'System.Environment.getArgs', this function does no Unicode
+-- decoding of the arguments; you get the exact bytes that were passed
+-- to the program by the OS.  To interpret the arguments as text, some
+-- Unicode decoding should be applied.
+--
+getArgs :: IO [PosixString]
+getArgs =
+  alloca $ \ p_argc ->
+  alloca $ \ p_argv -> do
+   getProgArgv p_argc p_argv
+   p    <- fromIntegral <$> peek p_argc
+   argv <- peek p_argv
+   peekArray (p - 1) (advancePtr argv 1) >>= mapM (fmap PS . B.packCString)
+
+foreign import ccall unsafe "getProgArgv"
+  getProgArgv :: Ptr CInt -> Ptr (Ptr CString) -> IO ()
+
+_equal :: Word8
+_equal = 0x3d
+
+_toStr :: B.ShortByteString -> String
+_toStr = either (error . show) id . decodeWith (mkUTF8 TransliterateCodingFailure) . PosixString
diff --git a/System/Posix/Error.hs b/System/Posix/Error.hs
--- a/System/Posix/Error.hs
+++ b/System/Posix/Error.hs
@@ -1,9 +1,4 @@
-{-# LANGUAGE CPP #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Error
diff --git a/System/Posix/Fcntl.hsc b/System/Posix/Fcntl.hsc
--- a/System/Posix/Fcntl.hsc
+++ b/System/Posix/Fcntl.hsc
@@ -1,9 +1,5 @@
 {-# LANGUAGE CApiFFI #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Fcntl
diff --git a/System/Posix/Files.hsc b/System/Posix/Files.hsc
--- a/System/Posix/Files.hsc
+++ b/System/Posix/Files.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 {-# LANGUAGE CApiFFI #-}
 
 -----------------------------------------------------------------------------
@@ -52,7 +48,7 @@
     fileAccess, fileExist,
 
     -- * File status
-    FileStatus,
+    FileStatus(..),
     -- ** Obtaining file status
     getFileStatus, getFdStatus, getSymbolicLinkStatus,
     -- ** Querying file status
@@ -63,6 +59,9 @@
     isBlockDevice, isCharacterDevice, isNamedPipe, isRegularFile,
     isDirectory, isSymbolicLink, isSocket,
 
+    fileBlockSize,
+    fileBlocks,
+
     -- * Creation
     createNamedPipe,
     createDevice,
@@ -103,8 +102,24 @@
 import System.Posix.Error
 import System.Posix.Internals
 
+#if !MIN_VERSION_base(4, 11, 0)
+import Data.Monoid ((<>))
+#endif
+
 import Data.Time.Clock.POSIX (POSIXTime)
 
+#if !defined(HAVE_MKNOD)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
+-- throwErrnoTwoPathsIfMinus1_
+--
+-- | For operations that require two paths (e.g., renaming a file)
+throwErrnoTwoPathsIfMinus1_ :: (Eq a, Num a) => String -> FilePath -> FilePath -> IO a -> IO ()
+throwErrnoTwoPathsIfMinus1_ loc path1 path2 =
+  throwErrnoIfMinus1_ (loc <> " '" <> path1 <> "' to '" <> path2 <> "'")
+
 -- -----------------------------------------------------------------------------
 -- chmod()
 
@@ -202,6 +217,13 @@
   withFilePath name $ \s ->
     throwErrnoPathIfMinus1_ "createNamedPipe" name (c_mkfifo s mode)
 
+#if !defined(HAVE_MKNOD)
+
+{-# WARNING createDevice "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_MKNOD@)" #-}
+createDevice :: FilePath -> FileMode -> DeviceID -> IO ()
+createDevice _ _ _ = ioError (ioeSetLocation unsupportedOperation "createDevice")
+
+#else
 -- | @createDevice path mode dev@ creates either a regular or a special file
 -- depending on the value of @mode@ (and @dev@).  @mode@ will normally be either
 -- 'blockSpecialMode' or 'characterSpecialMode'.  May fail with
@@ -218,6 +240,8 @@
 foreign import capi unsafe "HsUnix.h mknod"
   c_mknod :: CString -> CMode -> CDev -> IO CInt
 
+#endif // HAVE_MKNOD
+
 -- -----------------------------------------------------------------------------
 -- Hard links
 
@@ -229,7 +253,7 @@
 createLink name1 name2 =
   withFilePath name1 $ \s1 ->
   withFilePath name2 $ \s2 ->
-  throwErrnoPathIfMinus1_ "createLink" name1 (c_link s1 s2)
+  throwErrnoTwoPathsIfMinus1_ "createLink" name1 name2 (c_link s1 s2)
 
 -- | @removeLink path@ removes the link named @path@.
 --
@@ -242,18 +266,18 @@
 -- -----------------------------------------------------------------------------
 -- Symbolic Links
 
--- | @createSymbolicLink file1 file2@ creates a symbolic link named @file2@
--- which points to the file @file1@.
+-- | @createSymbolicLink name1 name2@ creates a symbolic link named @name2@
+-- which points to the file @name1@.
 --
 -- Symbolic links are interpreted at run-time as if the contents of the link
 -- had been substituted into the path being followed to find a file or directory.
 --
 -- Note: calls @symlink@.
 createSymbolicLink :: FilePath -> FilePath -> IO ()
-createSymbolicLink file1 file2 =
-  withFilePath file1 $ \s1 ->
-  withFilePath file2 $ \s2 ->
-  throwErrnoPathIfMinus1_ "createSymbolicLink" file2 (c_symlink s1 s2)
+createSymbolicLink name1 name2 =
+  withFilePath name1 $ \s1 ->
+  withFilePath name2 $ \s2 ->
+  throwErrnoTwoPathsIfMinus1_ "createSymbolicLink" name1 name2 (c_symlink s1 s2)
 
 foreign import ccall unsafe "symlink"
   c_symlink :: CString -> CString -> IO CInt
@@ -291,7 +315,7 @@
 rename name1 name2 =
   withFilePath name1 $ \s1 ->
   withFilePath name2 $ \s2 ->
-  throwErrnoPathIfMinus1_ "rename" name1 (c_rename s1 s2)
+  throwErrnoTwoPathsIfMinus1_  "rename" name1 name2 (c_rename s1 s2)
 
 foreign import ccall unsafe "rename"
    c_rename :: CString -> CString -> IO CInt
@@ -345,8 +369,11 @@
 
 -- | Like 'setFileTimes' but timestamps can have sub-second resolution.
 --
--- Note: calls @utimensat@ or @utimes@.
+-- Note: calls @utimensat@ or @utimes@.  Support for high resolution timestamps
+--   is filesystem dependent with the following limitations:
 --
+-- - HFS+ volumes on OS X truncate the sub-second part of the timestamp.
+--
 -- @since 2.7.0.0
 setFileTimesHiRes :: FilePath -> POSIXTime -> POSIXTime -> IO ()
 #ifdef HAVE_UTIMENSAT
@@ -366,8 +393,11 @@
 -- This operation is not supported on all platforms. On these platforms,
 -- this function will raise an exception.
 --
--- Note: calls @utimensat@ or @lutimes@.
+-- Note: calls @utimensat@ or @lutimes@. Support for high resolution timestamps
+--   is filesystem dependent with the following limitations:
 --
+-- - HFS+ volumes on OS X truncate the sub-second part of the timestamp.
+--
 -- @since 2.7.0.0
 setSymbolicLinkTimesHiRes :: FilePath -> POSIXTime -> POSIXTime -> IO ()
 #if HAVE_UTIMENSAT
@@ -383,6 +413,9 @@
       throwErrnoPathIfMinus1_ "setSymbolicLinkTimesHiRes" name $
         c_lutimes s times
 #else
+{-# WARNING setSymbolicLinkTimesHiRes
+ "System.Posix.Files.setSymbolicLinkTImesHiRes: not available on this platform"
+  #-}
 setSymbolicLinkTimesHiRes =
   error "setSymbolicLinkTimesHiRes: not available on this platform"
 #endif
@@ -409,6 +442,9 @@
   withFilePath name $ \s ->
     throwErrnoPathIfMinus1_ "touchSymbolicLink" name (c_lutimes s nullPtr)
 #else
+{-#
+  WARNING touchSymbolicLink "System.Posix.Files.touchSymbolicLink: not available on this platform"
+  #-}
 touchSymbolicLink =
   error "touchSymbolicLink: not available on this platform"
 #endif
diff --git a/System/Posix/Files/ByteString.hsc b/System/Posix/Files/ByteString.hsc
--- a/System/Posix/Files/ByteString.hsc
+++ b/System/Posix/Files/ByteString.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 {-# LANGUAGE CApiFFI #-}
 
 -----------------------------------------------------------------------------
@@ -63,6 +59,9 @@
     isBlockDevice, isCharacterDevice, isNamedPipe, isRegularFile,
     isDirectory, isSymbolicLink, isSocket,
 
+    fileBlockSize,
+    fileBlocks,
+
     -- * Creation
     createNamedPipe,
     createDevice,
@@ -110,6 +109,11 @@
 
 import Data.Time.Clock.POSIX (POSIXTime)
 
+#if !defined(HAVE_MKNOD)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
 -- -----------------------------------------------------------------------------
 -- chmod()
 
@@ -208,6 +212,14 @@
   withFilePath name $ \s ->
     throwErrnoPathIfMinus1_ "createNamedPipe" name (c_mkfifo s mode)
 
+#if !defined(HAVE_MKNOD)
+
+{-# WARNING createDevice "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_MKNOD@)" #-}
+createDevice :: RawFilePath -> FileMode -> DeviceID -> IO ()
+createDevice _ _ _ = ioError (ioeSetLocation unsupportedOperation "createDevice")
+
+#else
+
 -- | @createDevice path mode dev@ creates either a regular or a special file
 -- depending on the value of @mode@ (and @dev@).  @mode@ will normally be either
 -- 'blockSpecialMode' or 'characterSpecialMode'.  May fail with
@@ -224,6 +236,8 @@
 foreign import capi unsafe "HsUnix.h mknod"
   c_mknod :: CString -> CMode -> CDev -> IO CInt
 
+#endif // HAVE_MKNOD
+
 -- -----------------------------------------------------------------------------
 -- Hard links
 
@@ -235,7 +249,7 @@
 createLink name1 name2 =
   withFilePath name1 $ \s1 ->
   withFilePath name2 $ \s2 ->
-  throwErrnoPathIfMinus1_ "createLink" name1 (c_link s1 s2)
+  throwErrnoTwoPathsIfMinus1_ "createLink" name1 name2 (c_link s1 s2)
 
 -- | @removeLink path@ removes the link named @path@.
 --
@@ -256,10 +270,10 @@
 --
 -- Note: calls @symlink@.
 createSymbolicLink :: RawFilePath -> RawFilePath -> IO ()
-createSymbolicLink file1 file2 =
-  withFilePath file1 $ \s1 ->
-  withFilePath file2 $ \s2 ->
-  throwErrnoPathIfMinus1_ "createSymbolicLink" file2 (c_symlink s1 s2)
+createSymbolicLink name1 name2 =
+  withFilePath name1 $ \s1 ->
+  withFilePath name2 $ \s2 ->
+  throwErrnoTwoPathsIfMinus1_ "createSymbolicLink" name1 name2 (c_symlink s1 s2)
 
 foreign import ccall unsafe "symlink"
   c_symlink :: CString -> CString -> IO CInt
@@ -297,7 +311,7 @@
 rename name1 name2 =
   withFilePath name1 $ \s1 ->
   withFilePath name2 $ \s2 ->
-  throwErrnoPathIfMinus1_ "rename" name1 (c_rename s1 s2)
+  throwErrnoTwoPathsIfMinus1_ "rename" name1 name2 (c_rename s1 s2)
 
 foreign import ccall unsafe "rename"
    c_rename :: CString -> CString -> IO CInt
@@ -351,7 +365,11 @@
 
 -- | Like 'setFileTimes' but timestamps can have sub-second resolution.
 --
--- Note: calls @utimensat@ or @utimes@.
+-- Note: calls @utimensat@ or @utimes@. Support for high resolution timestamps
+--   is filesystem dependent with the following limitations:
+--
+-- - HFS+ volumes on OS X truncate the sub-second part of the timestamp.
+--
 setFileTimesHiRes :: RawFilePath -> POSIXTime -> POSIXTime -> IO ()
 #ifdef HAVE_UTIMENSAT
 setFileTimesHiRes name atime mtime =
@@ -370,7 +388,11 @@
 -- This operation is not supported on all platforms. On these platforms,
 -- this function will raise an exception.
 --
--- Note: calls @utimensat@ or @lutimes@.
+-- Note: calls @utimensat@ or @lutimes@. Support for high resolution timestamps
+--   is filesystem dependent with the following limitations:
+--
+-- - HFS+ volumes on OS X truncate the sub-second part of the timestamp.
+--
 setSymbolicLinkTimesHiRes :: RawFilePath -> POSIXTime -> POSIXTime -> IO ()
 #if HAVE_UTIMENSAT
 setSymbolicLinkTimesHiRes name atime mtime =
@@ -385,6 +407,7 @@
       throwErrnoPathIfMinus1_ "setSymbolicLinkTimesHiRes" name $
         c_lutimes s times
 #else
+{-# WARNING setSymbolicLinkTimesHiRes "setSymbolicLinkTimesHiRes: not available on this platform" #-}
 setSymbolicLinkTimesHiRes =
   error "setSymbolicLinkTimesHiRes: not available on this platform"
 #endif
@@ -409,6 +432,7 @@
   withFilePath name $ \s ->
     throwErrnoPathIfMinus1_ "touchSymbolicLink" name (c_lutimes s nullPtr)
 #else
+{-# WARNING touchSymbolicLink "touchSymbolicLink: not available on this platform" #-}
 touchSymbolicLink =
   error "touchSymbolicLink: not available on this platform"
 #endif
diff --git a/System/Posix/Files/Common.hsc b/System/Posix/Files/Common.hsc
--- a/System/Posix/Files/Common.hsc
+++ b/System/Posix/Files/Common.hsc
@@ -56,6 +56,9 @@
     isBlockDevice, isCharacterDevice, isNamedPipe, isRegularFile,
     isDirectory, isSymbolicLink, isSocket,
 
+    fileBlockSize,
+    fileBlocks,
+
     -- * Setting file sizes
     setFdSize,
 
@@ -231,7 +234,12 @@
 -- 'FileStatus' type.
 --
 -- Note: see @chmod@.
-newtype FileStatus = FileStatus (ForeignPtr CStat)
+--
+-- Limitations: Support for high resolution timestamps is filesystem dependent:
+--
+-- - HFS+ volumes on OS X only support whole-second times.
+--
+newtype FileStatus = FileStatus (ForeignPtr CStat) -- ^ The constructor is considered internal and may change.
 
 -- | ID of the device on which this file resides.
 deviceID         :: FileStatus -> DeviceID
@@ -250,17 +258,28 @@
 -- | Size of the file in bytes. If this file is a symbolic link the size is
 -- the length of the pathname it contains.
 fileSize         :: FileStatus -> FileOffset
+-- | Number of blocks allocated for this file, in units of
+-- 512-bytes. Returns @Nothing@ if @st_blocks@ is not supported on this
+-- platform.
+fileBlocks       :: FileStatus -> Maybe CBlkCnt
+-- | Gives the preferred block size for efficient filesystem I/O in
+-- bytes. Returns @Nothing@ if @st_blocksize@ is not supported on this
+-- platform.
+fileBlockSize    :: FileStatus -> Maybe CBlkSize
 -- | Time of last access.
 accessTime       :: FileStatus -> EpochTime
--- | Time of last access in sub-second resolution.
+-- | Time of last access in sub-second resolution. Depends on the timestamp resolution of the
+-- underlying filesystem.
 accessTimeHiRes  :: FileStatus -> POSIXTime
 -- | Time of last modification.
 modificationTime :: FileStatus -> EpochTime
--- | Time of last modification in sub-second resolution.
+-- | Time of last modification in sub-second resolution. Depends on the timestamp resolution of the
+-- underlying filesystem.
 modificationTimeHiRes :: FileStatus -> POSIXTime
 -- | Time of last status change (i.e. owner, group, link count, mode, etc.).
 statusChangeTime :: FileStatus -> EpochTime
 -- | Time of last status change (i.e. owner, group, link count, mode, etc.) in sub-second resolution.
+-- Depends on the timestamp resolution of the underlying filesystem.
 statusChangeTimeHiRes :: FileStatus -> POSIXTime
 
 deviceID (FileStatus stat) =
@@ -286,6 +305,19 @@
 statusChangeTime (FileStatus stat) =
   unsafePerformIO $ withForeignPtr stat $ (#peek struct stat, st_ctime)
 
+#ifdef HAVE_STRUCT_STAT_ST_BLOCKS
+fileBlocks (FileStatus stat) =
+  Just $ unsafePerformIO $ withForeignPtr stat $ (#peek struct stat, st_blocks)
+#else
+fileBlocks _ = Nothing
+#endif
+#ifdef HAVE_STRUCT_STAT_ST_BLKSIZE
+fileBlockSize (FileStatus stat) =
+  Just $ unsafePerformIO $ withForeignPtr stat $ (#peek struct stat, st_blksize)
+#else
+fileBlockSize _ = Nothing
+#endif
+
 accessTimeHiRes (FileStatus stat) =
   unsafePerformIO $ withForeignPtr stat $ \stat_ptr -> do
     sec  <- (#peek struct stat, st_atime) stat_ptr :: IO EpochTime
@@ -465,8 +497,12 @@
 -- This operation is not supported on all platforms. On these platforms,
 -- this function will raise an exception.
 --
--- Note: calls @futimens@ or @futimes@.
+-- Note: calls @futimens@ or @futimes@. Support for high resolution timestamps
+--   is filesystem dependent with the following limitations:
 --
+-- - HFS+ volumes on OS X truncate the sub-second part of the timestamp.
+--
+--
 -- @since 2.7.0.0
 setFdTimesHiRes :: Fd -> POSIXTime -> POSIXTime -> IO ()
 #if HAVE_FUTIMENS
@@ -478,6 +514,7 @@
   withArray [toCTimeVal atime, toCTimeVal mtime] $ \times ->
     throwErrnoIfMinus1_ "setFdTimesHiRes" (c_futimes fd times)
 #else
+{-# WARNING setFdTimesHiRes "setFdTimesHiRes: not available on this platform" #-}
 setFdTimesHiRes =
   error "setSymbolicLinkTimesHiRes: not available on this platform"
 #endif
@@ -494,6 +531,7 @@
 touchFd (Fd fd) =
   throwErrnoIfMinus1_ "touchFd" (c_futimes fd nullPtr)
 #else
+{-# WARNING touchFd "touchFd: not available on this platform" #-}
 touchFd =
   error "touchFd: not available on this platform"
 #endif
diff --git a/System/Posix/Files/PosixString.hsc b/System/Posix/Files/PosixString.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Files/PosixString.hsc
@@ -0,0 +1,453 @@
+{-# LANGUAGE CApiFFI #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.Files.PosixString
+-- 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)
+--
+-- Functions defined by the POSIX standards for manipulating and querying the
+-- file system. Names of underlying POSIX functions are indicated whenever
+-- possible. A more complete documentation of the POSIX functions together
+-- with a more detailed description of different error conditions are usually
+-- available in the system's manual pages or from
+-- <http://www.unix.org/version3/online.html> (free registration required).
+--
+-- When a function that calls an underlying POSIX function fails, the errno
+-- code is converted to an 'IOError' using 'Foreign.C.Error.errnoToIOError'.
+-- For a list of which errno codes may be generated, consult the POSIX
+-- documentation for the underlying function.
+--
+-----------------------------------------------------------------------------
+
+#include "HsUnix.h"
+
+module System.Posix.Files.PosixString (
+    -- * File modes
+    -- FileMode exported by System.Posix.Types
+    unionFileModes, intersectFileModes,
+    nullFileMode,
+    ownerReadMode, ownerWriteMode, ownerExecuteMode, ownerModes,
+    groupReadMode, groupWriteMode, groupExecuteMode, groupModes,
+    otherReadMode, otherWriteMode, otherExecuteMode, otherModes,
+    setUserIDMode, setGroupIDMode,
+    stdFileMode,   accessModes,
+    fileTypeModes,
+    blockSpecialMode, characterSpecialMode, namedPipeMode, regularFileMode,
+    directoryMode, symbolicLinkMode, socketMode,
+
+    -- ** Setting file modes
+    setFileMode, setFdMode, setFileCreationMask,
+
+    -- ** Checking file existence and permissions
+    fileAccess, fileExist,
+
+    -- * File status
+    FileStatus,
+    -- ** Obtaining file status
+    getFileStatus, getFdStatus, getSymbolicLinkStatus,
+    -- ** Querying file status
+    deviceID, fileID, fileMode, linkCount, fileOwner, fileGroup,
+    specialDeviceID, fileSize, accessTime, modificationTime,
+    statusChangeTime,
+    accessTimeHiRes, modificationTimeHiRes, statusChangeTimeHiRes,
+    isBlockDevice, isCharacterDevice, isNamedPipe, isRegularFile,
+    isDirectory, isSymbolicLink, isSocket,
+
+    -- * Creation
+    createNamedPipe,
+    createDevice,
+
+    -- * Hard links
+    createLink, removeLink,
+
+    -- * Symbolic links
+    createSymbolicLink, readSymbolicLink,
+
+    -- * Renaming files
+    rename,
+
+    -- * Changing file ownership
+    setOwnerAndGroup,  setFdOwnerAndGroup,
+#if HAVE_LCHOWN
+    setSymbolicLinkOwnerAndGroup,
+#endif
+
+    -- * Changing file timestamps
+    setFileTimes, setFileTimesHiRes,
+    setSymbolicLinkTimesHiRes,
+    touchFile, touchFd, touchSymbolicLink,
+
+    -- * Setting file sizes
+    setFileSize, setFdSize,
+
+    -- * Find system-specific limits for a file
+    PathVar(..), getPathVar, getFdPathVar,
+  ) where
+
+import System.Posix.Types
+import System.Posix.Internals hiding (withFilePath, peekFilePathLen)
+import qualified System.Posix.Files.Common as Common
+import Foreign
+import Foreign.C hiding (
+     throwErrnoPath,
+     throwErrnoPathIf,
+     throwErrnoPathIf_,
+     throwErrnoPathIfNull,
+     throwErrnoPathIfMinus1,
+     throwErrnoPathIfMinus1_ )
+
+import System.OsPath.Types
+import System.Posix.Files hiding (getFileStatus, getSymbolicLinkStatus, createNamedPipe, createDevice, createLink, removeLink, createSymbolicLink, readSymbolicLink, rename, setOwnerAndGroup, setSymbolicLinkOwnerAndGroup, setFileTimes, setSymbolicLinkTimesHiRes, touchFile, touchSymbolicLink, setFileSize, getPathVar, setFileMode, fileAccess, fileExist, setFdTimesHiRes, setFileTimesHiRes)
+import System.Posix.PosixPath.FilePath
+
+import Data.Time.Clock.POSIX (POSIXTime)
+
+-- -----------------------------------------------------------------------------
+-- chmod()
+
+-- | @setFileMode path mode@ changes permission of the file given by @path@
+-- to @mode@. This operation may fail with 'throwErrnoPathIfMinus1_' if @path@
+-- doesn't exist or if the effective user ID of the current process is not that
+-- of the file's owner.
+--
+-- Note: calls @chmod@.
+setFileMode :: PosixPath -> FileMode -> IO ()
+setFileMode name m =
+  withFilePath name $ \s -> do
+    throwErrnoPathIfMinus1_ "setFileMode" name (c_chmod s m)
+
+
+-- -----------------------------------------------------------------------------
+-- access()
+
+-- | @fileAccess name read write exec@ checks if the file (or other file system
+-- object) @name@ can be accessed for reading, writing and\/or executing. To
+-- check a permission set the corresponding argument to 'True'.
+--
+-- Note: calls @access@.
+fileAccess :: PosixPath -> Bool -> Bool -> Bool -> IO Bool
+fileAccess name readOK writeOK execOK = access name flags
+  where
+   flags   = read_f .|. write_f .|. exec_f
+   read_f  = if readOK  then (#const R_OK) else 0
+   write_f = if writeOK then (#const W_OK) else 0
+   exec_f  = if execOK  then (#const X_OK) else 0
+
+-- | Checks for the existence of the file.
+--
+-- Note: calls @access@.
+fileExist :: PosixPath -> IO Bool
+fileExist name =
+  withFilePath name $ \s -> do
+    r <- c_access s (#const F_OK)
+    if (r == 0)
+        then return True
+        else do err <- getErrno
+                if (err == eNOENT)
+                   then return False
+                   else throwErrnoPath "fileExist" name
+
+access :: PosixPath -> CMode -> IO Bool
+access name flags =
+  withFilePath name $ \s -> do
+    r <- c_access s (fromIntegral flags)
+    if (r == 0)
+        then return True
+        else do err <- getErrno
+                if (err == eACCES || err == eROFS || err == eTXTBSY ||
+                    err == ePERM)
+                   then return False
+                   else throwErrnoPath "fileAccess" name
+
+
+-- | @getFileStatus path@ calls gets the @FileStatus@ information (user ID,
+-- size, access times, etc.) for the file @path@.
+--
+-- Note: calls @stat@.
+getFileStatus :: PosixPath -> IO FileStatus
+getFileStatus path = do
+  fp <- mallocForeignPtrBytes (#const sizeof(struct stat))
+  withForeignPtr fp $ \p ->
+    withFilePath path $ \s ->
+      throwErrnoPathIfMinus1Retry_ "getFileStatus" path (c_stat s p)
+  return (Common.FileStatus fp)
+
+-- | Acts as 'getFileStatus' except when the 'PosixPath' refers to a symbolic
+-- link. In that case the @FileStatus@ information of the symbolic link itself
+-- is returned instead of that of the file it points to.
+--
+-- Note: calls @lstat@.
+getSymbolicLinkStatus :: PosixPath -> IO FileStatus
+getSymbolicLinkStatus path = do
+  fp <- mallocForeignPtrBytes (#const sizeof(struct stat))
+  withForeignPtr fp $ \p ->
+    withFilePath path $ \s ->
+      throwErrnoPathIfMinus1_ "getSymbolicLinkStatus" path (c_lstat s p)
+  return (Common.FileStatus fp)
+
+foreign import capi unsafe "HsUnix.h lstat"
+  c_lstat :: CString -> Ptr CStat -> IO CInt
+
+-- | @createNamedPipe fifo mode@
+-- creates a new named pipe, @fifo@, with permissions based on
+-- @mode@. May fail with 'throwErrnoPathIfMinus1_' if a file named @name@
+-- already exists or if the effective user ID of the current process doesn't
+-- have permission to create the pipe.
+--
+-- Note: calls @mkfifo@.
+createNamedPipe :: PosixPath -> FileMode -> IO ()
+createNamedPipe name mode = do
+  withFilePath name $ \s ->
+    throwErrnoPathIfMinus1_ "createNamedPipe" name (c_mkfifo s mode)
+
+-- | @createDevice path mode dev@ creates either a regular or a special file
+-- depending on the value of @mode@ (and @dev@).  @mode@ will normally be either
+-- 'blockSpecialMode' or 'characterSpecialMode'.  May fail with
+-- 'throwErrnoPathIfMinus1_' if a file named @name@ already exists or if the
+-- effective user ID of the current process doesn't have permission to create
+-- the file.
+--
+-- Note: calls @mknod@.
+createDevice :: PosixPath -> FileMode -> DeviceID -> IO ()
+createDevice path mode dev =
+  withFilePath path $ \s ->
+    throwErrnoPathIfMinus1_ "createDevice" path (c_mknod s mode dev)
+
+foreign import capi unsafe "HsUnix.h mknod"
+  c_mknod :: CString -> CMode -> CDev -> IO CInt
+
+-- -----------------------------------------------------------------------------
+-- Hard links
+
+-- | @createLink old new@ creates a new path, @new@, linked to an existing file,
+-- @old@.
+--
+-- Note: calls @link@.
+createLink :: PosixPath -> PosixPath -> IO ()
+createLink name1 name2 =
+  withFilePath name1 $ \s1 ->
+  withFilePath name2 $ \s2 ->
+  throwErrnoTwoPathsIfMinus1_ "createLink" name1 name2 (c_link s1 s2)
+
+-- | @removeLink path@ removes the link named @path@.
+--
+-- Note: calls @unlink@.
+removeLink :: PosixPath -> IO ()
+removeLink name =
+  withFilePath name $ \s ->
+  throwErrnoPathIfMinus1_ "removeLink" name (c_unlink s)
+
+-- -----------------------------------------------------------------------------
+-- Symbolic Links
+
+-- | @createSymbolicLink file1 file2@ creates a symbolic link named @file2@
+-- which points to the file @file1@.
+--
+-- Symbolic links are interpreted at run-time as if the contents of the link
+-- had been substituted into the path being followed to find a file or directory.
+--
+-- Note: calls @symlink@.
+createSymbolicLink :: PosixPath -> PosixPath -> IO ()
+createSymbolicLink name1 name2 =
+  withFilePath name1 $ \s1 ->
+  withFilePath name2 $ \s2 ->
+  throwErrnoTwoPathsIfMinus1_ "createSymbolicLink" name1 name2 (c_symlink s1 s2)
+
+foreign import ccall unsafe "symlink"
+  c_symlink :: CString -> CString -> IO CInt
+
+-- ToDo: should really use SYMLINK_MAX, but not everyone supports it yet,
+-- and it seems that the intention is that SYMLINK_MAX is no larger than
+-- PATH_MAX.
+#if !defined(PATH_MAX)
+-- PATH_MAX is not defined on systems with unlimited path length.
+-- Ugly.  Fix this.
+#define PATH_MAX 4096
+#endif
+
+-- | Reads the @PosixPath@ pointed to by the symbolic link and returns it.
+--
+-- Note: calls @readlink@.
+readSymbolicLink :: PosixPath -> IO PosixPath
+readSymbolicLink file =
+  allocaArray0 (#const PATH_MAX) $ \buf -> do
+    withFilePath file $ \s -> do
+      len <- throwErrnoPathIfMinus1 "readSymbolicLink" file $
+        c_readlink s buf (#const PATH_MAX)
+      peekFilePathLen (buf,fromIntegral len)
+
+foreign import ccall unsafe "readlink"
+  c_readlink :: CString -> CString -> CSize -> IO CInt
+
+-- -----------------------------------------------------------------------------
+-- Renaming files
+
+-- | @rename old new@ renames a file or directory from @old@ to @new@.
+--
+-- Note: calls @rename@.
+rename :: PosixPath -> PosixPath -> IO ()
+rename name1 name2 =
+  withFilePath name1 $ \s1 ->
+  withFilePath name2 $ \s2 ->
+  throwErrnoTwoPathsIfMinus1_ "rename" name1 name2 (c_rename s1 s2)
+
+foreign import ccall unsafe "rename"
+   c_rename :: CString -> CString -> IO CInt
+
+-- -----------------------------------------------------------------------------
+-- chown()
+
+-- | @setOwnerAndGroup path uid gid@ changes the owner and group of @path@ to
+-- @uid@ and @gid@, respectively.
+--
+-- If @uid@ or @gid@ is specified as -1, then that ID is not changed.
+--
+-- Note: calls @chown@.
+setOwnerAndGroup :: PosixPath -> UserID -> GroupID -> IO ()
+setOwnerAndGroup name uid gid = do
+  withFilePath name $ \s ->
+    throwErrnoPathIfMinus1_ "setOwnerAndGroup" name (c_chown s uid gid)
+
+foreign import ccall unsafe "chown"
+  c_chown :: CString -> CUid -> CGid -> IO CInt
+
+#if HAVE_LCHOWN
+-- | Acts as 'setOwnerAndGroup' but does not follow symlinks (and thus
+-- changes permissions on the link itself).
+--
+-- Note: calls @lchown@.
+setSymbolicLinkOwnerAndGroup :: PosixPath -> UserID -> GroupID -> IO ()
+setSymbolicLinkOwnerAndGroup name uid gid = do
+  withFilePath name $ \s ->
+    throwErrnoPathIfMinus1_ "setSymbolicLinkOwnerAndGroup" name
+        (c_lchown s uid gid)
+
+foreign import ccall unsafe "lchown"
+  c_lchown :: CString -> CUid -> CGid -> IO CInt
+#endif
+
+-- -----------------------------------------------------------------------------
+-- Setting file times
+
+-- | @setFileTimes path atime mtime@ sets the access and modification times
+-- associated with file @path@ to @atime@ and @mtime@, respectively.
+--
+-- Note: calls @utime@.
+setFileTimes :: PosixPath -> EpochTime -> EpochTime -> IO ()
+setFileTimes name atime mtime = do
+  withFilePath name $ \s ->
+   allocaBytes (#const sizeof(struct utimbuf)) $ \p -> do
+     (#poke struct utimbuf, actime)  p atime
+     (#poke struct utimbuf, modtime) p mtime
+     throwErrnoPathIfMinus1_ "setFileTimes" name (c_utime s p)
+
+-- | Like 'setFileTimes' but timestamps can have sub-second resolution.
+--
+-- Note: calls @utimensat@ or @utimes@. Support for high resolution timestamps
+--   is filesystem dependent with the following limitations:
+--
+-- - HFS+ volumes on OS X truncate the sub-second part of the timestamp.
+--
+setFileTimesHiRes :: PosixPath -> POSIXTime -> POSIXTime -> IO ()
+#ifdef HAVE_UTIMENSAT
+setFileTimesHiRes name atime mtime =
+  withFilePath name $ \s ->
+    withArray [Common.toCTimeSpec atime, Common.toCTimeSpec mtime] $ \times ->
+      throwErrnoPathIfMinus1_ "setFileTimesHiRes" name $
+        Common.c_utimensat (#const AT_FDCWD) s times 0
+#else
+setFileTimesHiRes name atime mtime =
+  withFilePath name $ \s ->
+    withArray [Common.toCTimeVal atime, Common.toCTimeVal mtime] $ \times ->
+      throwErrnoPathIfMinus1_ "setFileTimesHiRes" name (Common.c_utimes s times)
+#endif
+
+-- | Like 'setFileTimesHiRes' but does not follow symbolic links.
+-- This operation is not supported on all platforms. On these platforms,
+-- this function will raise an exception.
+--
+-- Note: calls @utimensat@ or @lutimes@. Support for high resolution timestamps
+--   is filesystem dependent with the following limitations:
+--
+-- - HFS+ volumes on OS X truncate the sub-second part of the timestamp.
+--
+setSymbolicLinkTimesHiRes :: PosixPath -> POSIXTime -> POSIXTime -> IO ()
+#if HAVE_UTIMENSAT
+setSymbolicLinkTimesHiRes name atime mtime =
+  withFilePath name $ \s ->
+    withArray [Common.toCTimeSpec atime, Common.toCTimeSpec mtime] $ \times ->
+      throwErrnoPathIfMinus1_ "setSymbolicLinkTimesHiRes" name $
+        Common.c_utimensat (#const AT_FDCWD) s times (#const AT_SYMLINK_NOFOLLOW)
+#elif HAVE_LUTIMES
+setSymbolicLinkTimesHiRes name atime mtime =
+  withFilePath name $ \s ->
+    withArray [Common.toCTimeVal atime, Common.toCTimeVal mtime] $ \times ->
+      throwErrnoPathIfMinus1_ "setSymbolicLinkTimesHiRes" name $
+        Common.c_lutimes s times
+#else
+setSymbolicLinkTimesHiRes =
+  error "setSymbolicLinkTimesHiRes: not available on this platform"
+#endif
+
+-- | @touchFile path@ sets the access and modification times associated with
+-- file @path@ to the current time.
+--
+-- Note: calls @utime@.
+touchFile :: PosixPath -> IO ()
+touchFile name = do
+  withFilePath name $ \s ->
+   throwErrnoPathIfMinus1_ "touchFile" name (c_utime s nullPtr)
+
+-- | Like 'touchFile' but does not follow symbolic links.
+-- This operation is not supported on all platforms. On these platforms,
+-- this function will raise an exception.
+--
+-- Note: calls @lutimes@.
+touchSymbolicLink :: PosixPath -> IO ()
+#if HAVE_LUTIMES
+touchSymbolicLink name =
+  withFilePath name $ \s ->
+    throwErrnoPathIfMinus1_ "touchSymbolicLink" name (Common.c_lutimes s nullPtr)
+#else
+touchSymbolicLink =
+  error "touchSymbolicLink: not available on this platform"
+#endif
+
+-- -----------------------------------------------------------------------------
+-- Setting file sizes
+
+-- | Truncates the file down to the specified length. If the file was larger
+-- than the given length before this operation was performed the extra is lost.
+--
+-- Note: calls @truncate@.
+setFileSize :: PosixPath -> FileOffset -> IO ()
+setFileSize file off =
+  withFilePath file $ \s ->
+    throwErrnoPathIfMinus1_ "setFileSize" file (c_truncate s off)
+
+foreign import capi unsafe "HsUnix.h truncate"
+  c_truncate :: CString -> COff -> IO CInt
+
+-- -----------------------------------------------------------------------------
+-- pathconf()/fpathconf() support
+
+-- | @getPathVar var path@ obtains the dynamic value of the requested
+-- configurable file limit or option associated with file or directory @path@.
+-- For defined file limits, @getPathVar@ returns the associated
+-- value.  For defined file options, the result of @getPathVar@
+-- is undefined, but not failure.
+--
+-- Note: calls @pathconf@.
+getPathVar :: PosixPath -> PathVar -> IO Limit
+getPathVar name v = do
+  withFilePath name $ \ nameP ->
+    throwErrnoPathIfMinus1 "getPathVar" name $
+      c_pathconf nameP (Common.pathVarConst v)
+
+foreign import ccall unsafe "pathconf"
+  c_pathconf :: CString -> CInt -> IO CLong
diff --git a/System/Posix/IO.hsc b/System/Posix/IO.hsc
--- a/System/Posix/IO.hsc
+++ b/System/Posix/IO.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.IO
@@ -31,7 +27,7 @@
     -- ** Opening and closing files
     OpenMode(..),
     OpenFileFlags(..), defaultFileFlags,
-    openFd, createFile,
+    openFd, openFdAt, createFile, createFileAt,
     closeFd,
 
     -- ** Reading\/writing data
@@ -67,6 +63,13 @@
 
   ) where
 
+import Foreign ( allocaBytes, castPtr )
+import Foreign.C ( peekCStringLen, withCStringLen )
+
+import GHC.IO.Exception ( IOErrorType(EOF) )
+
+import System.IO.Error ( ioeSetErrorString, mkIOError )
+
 import System.Posix.Types
 import System.Posix.Error
 import System.Posix.IO.Common
@@ -76,18 +79,65 @@
 -- for information on how to use the 'FileMode' type.
 openFd :: FilePath
        -> OpenMode
-       -> Maybe FileMode -- ^Just x => creates the file with the given modes, Nothing => the file must exist.
        -> OpenFileFlags
        -> IO Fd
-openFd name how maybe_mode flags = do
-   withFilePath name $ \str -> do
-     throwErrnoPathIfMinus1Retry "openFd" name $
-       open_ str how maybe_mode flags
+openFd = openFdAt Nothing
 
+-- | Open a file relative to an optional directory file descriptor.
+--
+-- Directory file descriptors can be used to avoid some race conditions when
+-- navigating changing directory trees, or to retain access to a portion of the
+-- directory tree that would otherwise become inaccessible after dropping
+-- privileges.
+openFdAt :: Maybe Fd -- ^ Optional directory file descriptor
+         -> FilePath -- ^ Pathname to open
+         -> OpenMode -- ^ Read-only, read-write or write-only
+         -> OpenFileFlags -- ^ Append, exclusive, truncate, etc.
+         -> IO Fd
+openFdAt fdMay name how flags =
+  withFilePath name $ \str ->
+    throwErrnoPathIfMinus1Retry "openFdAt" name $
+      openat_ fdMay str how flags
+
 -- |Create and open this file in WriteOnly mode.  A special case of
 -- 'openFd'.  See 'System.Posix.Files' for information on how to use
 -- the 'FileMode' type.
-
 createFile :: FilePath -> FileMode -> IO Fd
-createFile name mode
-  = openFd name WriteOnly (Just mode) defaultFileFlags{ trunc=True }
+createFile = createFileAt Nothing
+
+-- | Create and open a file for write-only, with default flags,
+-- relative an optional directory file-descriptor.
+--
+-- Directory file descriptors can be used to avoid some race conditions when
+-- navigating changing directory trees, or to retain access to a portion of the
+-- directory tree that would otherwise become inaccessible after dropping
+-- privileges.
+createFileAt :: Maybe Fd -- ^ Optional directory file descriptor
+             -> FilePath -- ^ Pathname to create
+             -> FileMode -- ^ File permission bits (before umask)
+             -> IO Fd
+createFileAt fdMay name mode
+  = openFdAt fdMay name WriteOnly defaultFileFlags{ trunc=True, creat=(Just mode) }
+
+{-# DEPRECATED fdRead "This function is scheduled to be dropped in favor of 'System.Posix.IO.ByteString.fdRead', because decoding e.g. UTF-8 streams partially is unsafe." #-} -- deprecated in 2.8.0.0
+-- | Read data from an 'Fd' and convert it to a 'String' using the locale encoding.
+-- Throws an exception if this is an invalid descriptor, or EOF has been
+-- reached.
+fdRead :: Fd
+       -> ByteCount -- ^How many bytes to read
+       -> IO (String, ByteCount) -- ^The bytes read, how many bytes were read.
+fdRead _fd 0 = return ("", 0)
+fdRead fd nbytes =
+  allocaBytes (fromIntegral nbytes) $ \ buf -> do
+  rc <- fdReadBuf fd buf nbytes
+  case rc of
+    0 -> ioError (ioeSetErrorString (mkIOError EOF "fdRead" Nothing Nothing) "EOF")
+    n -> do
+      s <- peekCStringLen (castPtr buf, fromIntegral n)
+      return (s, n)
+
+-- | Write a 'String' to an 'Fd' using the locale encoding.
+fdWrite :: Fd -> String -> IO ByteCount
+fdWrite fd str =
+  withCStringLen str $ \ (buf,len) ->
+    fdWriteBuf fd (castPtr buf) (fromIntegral len)
diff --git a/System/Posix/IO/ByteString.hsc b/System/Posix/IO/ByteString.hsc
--- a/System/Posix/IO/ByteString.hsc
+++ b/System/Posix/IO/ByteString.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
-{-# LANGUAGE Safe #-}
-#else
 {-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.IO.ByteString
@@ -31,7 +27,7 @@
     -- ** Opening and closing files
     OpenMode(..),
     OpenFileFlags(..), defaultFileFlags,
-    openFd, createFile,
+    openFd, openFdAt, createFile, createFileAt,
     closeFd,
 
     -- ** Reading\/writing data
@@ -67,6 +63,16 @@
 
   ) where
 
+import Data.ByteString ( ByteString, empty )
+import qualified Data.ByteString.Internal as BI
+import qualified Data.ByteString.Unsafe as BU
+
+import Foreign ( castPtr )
+
+import GHC.IO.Exception ( IOErrorType(EOF) )
+
+import System.IO.Error ( ioeSetErrorString, mkIOError )
+
 import System.Posix.Types
 import System.Posix.IO.Common
 
@@ -76,18 +82,62 @@
 -- for information on how to use the 'FileMode' type.
 openFd :: RawFilePath
        -> OpenMode
-       -> Maybe FileMode -- ^Just x => creates the file with the given modes, Nothing => the file must exist.
        -> OpenFileFlags
        -> IO Fd
-openFd name how maybe_mode flags = do
-   withFilePath name $ \str -> do
-     throwErrnoPathIfMinus1Retry "openFd" name $
-       open_ str how maybe_mode flags
+openFd = openFdAt Nothing
 
+-- | Open a file relative to an optional directory file descriptor.
+--
+-- Directory file descriptors can be used to avoid some race conditions when
+-- navigating changing directory trees, or to retain access to a portion of the
+-- directory tree that would otherwise become inaccessible after dropping
+-- privileges.
+openFdAt :: Maybe Fd -- ^ Optional directory file descriptor
+         -> RawFilePath -- ^ Pathname to open
+         -> OpenMode -- ^ Read-only, read-write or write-only
+         -> OpenFileFlags -- ^ Append, exclusive, truncate, etc.
+         -> IO Fd
+openFdAt fdMay name how flags =
+  withFilePath name $ \str ->
+    throwErrnoPathIfMinus1Retry "openFdAt" name $
+      openat_ fdMay str how flags
+
 -- |Create and open this file in WriteOnly mode.  A special case of
 -- 'openFd'.  See 'System.Posix.Files' for information on how to use
 -- the 'FileMode' type.
-
 createFile :: RawFilePath -> FileMode -> IO Fd
-createFile name mode
-  = openFd name WriteOnly (Just mode) defaultFileFlags{ trunc=True }
+createFile = createFileAt Nothing
+
+-- | Create and open a file for write-only, with default flags,
+-- relative an optional directory file-descriptor.
+--
+-- Directory file descriptors can be used to avoid some race conditions when
+-- navigating changing directory trees, or to retain access to a portion of the
+-- directory tree that would otherwise become inaccessible after dropping
+-- privileges.
+createFileAt :: Maybe Fd -- ^ Optional directory file descriptor
+             -> RawFilePath -- ^ Pathname to create
+             -> FileMode -- ^ File permission bits (before umask)
+             -> IO Fd
+createFileAt fdMay name mode
+  = openFdAt fdMay name WriteOnly defaultFileFlags{ trunc=True, creat=(Just mode) }
+
+-- | Read data from an 'Fd' and return it as a 'ByteString'.
+-- Throws an exception if this is an invalid descriptor, or EOF has been
+-- reached.
+fdRead :: Fd
+       -> ByteCount -- ^How many bytes to read
+       -> IO ByteString -- ^The bytes read
+fdRead _fd 0 = return empty
+fdRead fd nbytes =
+  BI.createUptoN (fromIntegral nbytes) $ \ buf -> do
+  rc <- fdReadBuf fd buf nbytes
+  case rc of
+    0 -> ioError (ioeSetErrorString (mkIOError EOF "fdRead" Nothing Nothing) "EOF")
+    n -> return (fromIntegral n)
+
+-- | Write a 'ByteString' to an 'Fd'.
+fdWrite :: Fd -> ByteString -> IO ByteCount
+fdWrite fd bs =
+  BU.unsafeUseAsCStringLen bs $ \ (buf,len) ->
+    fdWriteBuf fd (castPtr buf) (fromIntegral len)
diff --git a/System/Posix/IO/Common.hsc b/System/Posix/IO/Common.hsc
--- a/System/Posix/IO/Common.hsc
+++ b/System/Posix/IO/Common.hsc
@@ -1,11 +1,7 @@
 {-# LANGUAGE CApiFFI #-}
 {-# LANGUAGE NondecreasingIndentation #-}
 {-# LANGUAGE RecordWildCards #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 
 -----------------------------------------------------------------------------
 -- |
@@ -28,14 +24,13 @@
     -- ** Opening and closing files
     OpenMode(..),
     OpenFileFlags(..), defaultFileFlags,
-    open_,
+    openat_,
     closeFd,
 
     -- ** Reading\/writing data
     -- |Programmers using the 'fdRead' and 'fdWrite' API should be aware that
     -- EAGAIN exceptions may occur for non-blocking IO!
 
-    fdRead, fdWrite,
     fdReadBuf, fdWriteBuf,
 
     -- ** Seeking
@@ -79,8 +74,22 @@
 import GHC.IO.Exception
 import Data.Typeable (cast)
 
+#if !defined(HAVE_PIPE)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
 #include "HsUnix.h"
 
+#if !defined(HAVE_PIPE)
+
+createPipe :: IO (Fd, Fd)
+{-# WARNING createPipe
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PIPE@)" #-}
+createPipe = ioError (ioeSetLocation unsupportedOperation "createPipe")
+
+#else
+
 -- -----------------------------------------------------------------------------
 -- Pipes
 -- |The 'createPipe' function creates a pair of connected file
@@ -101,6 +110,22 @@
 foreign import ccall unsafe "pipe"
    c_pipe :: Ptr CInt -> IO CInt
 
+#endif // HAVE_PIPE
+
+#if !defined(HAVE_DUP)
+
+dup :: Fd -> IO Fd
+{-# WARNING dup
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_DUP@)" #-}
+dup _ = ioError (ioeSetLocation unsupportedOperation "dup")
+
+dupTo :: Fd -> Fd -> IO Fd
+{-# WARNING dupTo
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_DUP@)" #-}
+dupTo _ _ = ioError (ioeSetLocation unsupportedOperation "dupTo")
+
+#else
+
 -- -----------------------------------------------------------------------------
 -- Duplicating file descriptors
 
@@ -120,6 +145,8 @@
 foreign import ccall unsafe "dup2"
    c_dup2 :: CInt -> CInt -> IO CInt
 
+#endif // HAVE_DUP
+
 -- -----------------------------------------------------------------------------
 -- Opening and closing files
 
@@ -129,20 +156,41 @@
 stdError   = Fd (#const STDERR_FILENO)
 
 data OpenMode = ReadOnly | WriteOnly | ReadWrite
+              deriving (Read, Show, Eq, Ord)
 
 -- |Correspond to some of the int flags from C's fcntl.h.
 data OpenFileFlags =
  OpenFileFlags {
-    append    :: Bool, -- ^ O_APPEND
-    exclusive :: Bool, -- ^ O_EXCL
-    noctty    :: Bool, -- ^ O_NOCTTY
-    nonBlock  :: Bool, -- ^ O_NONBLOCK
-    trunc     :: Bool  -- ^ O_TRUNC
+    append    :: Bool,           -- ^ O_APPEND
+    exclusive :: Bool,           -- ^ O_EXCL, result is undefined if O_CREAT is False
+                                 --
+                                 -- __NOTE__: Result is undefined if 'creat' is 'Nothing'.
+    noctty    :: Bool,           -- ^ O_NOCTTY
+    nonBlock  :: Bool,           -- ^ O_NONBLOCK
+    trunc     :: Bool,           -- ^ O_TRUNC
+    nofollow  :: Bool,           -- ^ O_NOFOLLOW
+                                 --
+                                 -- @since 2.8.0.0
+    creat     :: Maybe FileMode, -- ^ O_CREAT
+                                 --
+                                 -- @since 2.8.0.0
+    cloexec   :: Bool,           -- ^ O_CLOEXEC
+                                 --
+                                 -- @since 2.8.0.0
+    directory :: Bool,           -- ^ O_DIRECTORY
+                                 --
+                                 -- @since 2.8.0.0
+    sync      :: Bool            -- ^ O_SYNC
+                                 --
+                                 -- @since 2.8.0.0
  }
+ deriving (Read, Show, Eq, Ord)
 
 
--- |Default values for the 'OpenFileFlags' type. False for each of
--- append, exclusive, noctty, nonBlock, and trunc.
+-- | Default values for the 'OpenFileFlags' type.
+--
+-- Each field of 'OpenFileFlags' is either 'False' or 'Nothing'
+-- respectively.
 defaultFileFlags :: OpenFileFlags
 defaultFileFlags =
  OpenFileFlags {
@@ -150,32 +198,43 @@
     exclusive = False,
     noctty    = False,
     nonBlock  = False,
-    trunc     = False
+    trunc     = False,
+    nofollow  = False,
+    creat     = Nothing,
+    cloexec   = False,
+    directory = False,
+    sync      = False
   }
 
 
--- |Open and optionally create this file.  See 'System.Posix.Files'
--- for information on how to use the 'FileMode' type.
-open_  :: CString
-       -> OpenMode
-       -> Maybe FileMode -- ^Just x => creates the file with the given modes, Nothing => the file must exist.
-       -> OpenFileFlags
-       -> IO Fd
-open_ str how maybe_mode (OpenFileFlags appendFlag exclusiveFlag nocttyFlag
-                                nonBlockFlag truncateFlag) = do
-    fd <- c_open str all_flags mode_w
-    return (Fd fd)
+-- |Open and optionally create a file relative to an optional
+-- directory file descriptor.
+openat_  :: Maybe Fd -- ^ Optional directory file descriptor
+         -> CString -- ^ Pathname to open
+         -> OpenMode -- ^ Read-only, read-write or write-only
+         -> OpenFileFlags -- ^ Append, exclusive, etc.
+         -> IO Fd
+openat_ fdMay str how (OpenFileFlags appendFlag exclusiveFlag nocttyFlag
+                                nonBlockFlag truncateFlag nofollowFlag
+                                creatFlag cloexecFlag directoryFlag
+                                syncFlag) =
+    Fd <$> c_openat c_fd str all_flags mode_w
   where
+    c_fd = maybe (#const AT_FDCWD) (\ (Fd fd) -> fd) fdMay
     all_flags  = creat .|. flags .|. open_mode
 
     flags =
-       (if appendFlag    then (#const O_APPEND)   else 0) .|.
-       (if exclusiveFlag then (#const O_EXCL)     else 0) .|.
-       (if nocttyFlag    then (#const O_NOCTTY)   else 0) .|.
-       (if nonBlockFlag  then (#const O_NONBLOCK) else 0) .|.
-       (if truncateFlag  then (#const O_TRUNC)    else 0)
+       (if appendFlag       then (#const O_APPEND)    else 0) .|.
+       (if exclusiveFlag    then (#const O_EXCL)      else 0) .|.
+       (if nocttyFlag       then (#const O_NOCTTY)    else 0) .|.
+       (if nonBlockFlag     then (#const O_NONBLOCK)  else 0) .|.
+       (if truncateFlag     then (#const O_TRUNC)     else 0) .|.
+       (if nofollowFlag     then (#const O_NOFOLLOW)  else 0) .|.
+       (if cloexecFlag      then (#const O_CLOEXEC)   else 0) .|.
+       (if directoryFlag    then (#const O_DIRECTORY) else 0) .|.
+       (if syncFlag         then (#const O_SYNC)      else 0)
 
-    (creat, mode_w) = case maybe_mode of
+    (creat, mode_w) = case creatFlag of
                         Nothing -> (0,0)
                         Just x  -> ((#const O_CREAT), x)
 
@@ -184,14 +243,20 @@
                    WriteOnly -> (#const O_WRONLY)
                    ReadWrite -> (#const O_RDWR)
 
-foreign import capi unsafe "HsUnix.h open"
-   c_open :: CString -> CInt -> CMode -> IO CInt
+foreign import capi unsafe "HsUnix.h openat"
+   c_openat :: CInt -> CString -> CInt -> CMode -> IO CInt
 
 -- |Close this file descriptor.  May throw an exception if this is an
 -- invalid descriptor.
 
 closeFd :: Fd -> IO ()
 closeFd (Fd fd) = throwErrnoIfMinus1_ "closeFd" (c_close fd)
+-- Here we don't to retry on EINTR because according to
+--  http://pubs.opengroup.org/onlinepubs/9699919799/functions/close.html
+-- "with errno set to [EINTR] [...] the state of fildes is unspecified"
+-- and on Linux, already the first close() removes the FD from the process's
+-- FD table so closing a second time is invalid
+-- (see http://man7.org/linux/man-pages/man2/close.2.html#NOTES).
 
 foreign import ccall unsafe "HsUnix.h close"
    c_close :: CInt -> IO CInt
@@ -200,7 +265,15 @@
 -- Converting file descriptors to/from Handles
 
 -- | Extracts the 'Fd' from a 'Handle'.  This function has the side effect
--- of closing the 'Handle' and flushing its write buffer, if necessary.
+-- of closing the 'Handle' (and flushing its write buffer, if necessary),
+-- without closing the underlying 'Fd'.
+--
+-- __Warning:__ This means you take over ownership of the underlying 'Fd'.
+-- 'hClose` on the 'Handle' will no longer have any effect.
+-- This will break common patterns to avoid file descriptor leaks,
+-- such as using 'hClose' in the cleanup action of @Control.Exception.bracket@,
+-- making it a silent no-op.
+-- Be sure to close the returned 'Fd' yourself to not leak it.
 handleToFd :: Handle -> IO Fd
 
 -- | Converts an 'Fd' into a 'Handle' that can be used with the
@@ -292,6 +365,25 @@
 
 type FileLock = (LockRequest, SeekMode, FileOffset, FileOffset)
 
+#if !defined(HAVE_F_GETLK)
+
+getLock :: Fd -> FileLock -> IO (Maybe (ProcessID, FileLock))
+{-# WARNING getLock
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_F_GETLK@)" #-}
+getLock _ _ = ioError (ioeSetLocation unsupportedOperation "getLock")
+
+setLock :: Fd -> FileLock -> IO ()
+{-# WARNING setLock
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_F_GETLK@)" #-}
+setLock _ _ = ioError (ioeSetLocation unsupportedOperation "setLock")
+
+waitToSetLock :: Fd -> FileLock -> IO ()
+{-# WARNING waitToSetLock
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_F_GETLK@)" #-}
+waitToSetLock _ _ = ioError (ioeSetLocation unsupportedOperation "waitToSetLock")
+
+#else
+
 -- | May throw an exception if this is an invalid descriptor.
 getLock :: Fd -> FileLock -> IO (Maybe (ProcessID, FileLock))
 getLock (Fd fd) lock =
@@ -351,24 +443,10 @@
     throwErrnoIfMinus1_ "waitToSetLock"
         (Base.c_fcntl_lock fd (#const F_SETLKW) p_flock)
 
--- -----------------------------------------------------------------------------
--- fd{Read,Write}
+#endif // HAVE_F_GETLK
 
--- | Read data from an 'Fd' and convert it to a 'String' using the locale encoding.
--- Throws an exception if this is an invalid descriptor, or EOF has been
--- reached.
-fdRead :: Fd
-       -> ByteCount -- ^How many bytes to read
-       -> IO (String, ByteCount) -- ^The bytes read, how many bytes were read.
-fdRead _fd 0 = return ("", 0)
-fdRead fd nbytes = do
-    allocaBytes (fromIntegral nbytes) $ \ buf -> do
-    rc <- fdReadBuf fd buf nbytes
-    case rc of
-      0 -> ioError (ioeSetErrorString (mkIOError EOF "fdRead" Nothing Nothing) "EOF")
-      n -> do
-       s <- peekCStringLen (castPtr buf, fromIntegral n)
-       return (s, n)
+-- -----------------------------------------------------------------------------
+-- fd{Read,Write}Buf
 
 -- | Read data from an 'Fd' into memory.  This is exactly equivalent
 -- to the POSIX @read@ function.
@@ -384,12 +462,6 @@
 
 foreign import ccall safe "read"
    c_safe_read :: CInt -> Ptr CChar -> CSize -> IO CSsize
-
--- | Write a 'String' to an 'Fd' using the locale encoding.
-fdWrite :: Fd -> String -> IO ByteCount
-fdWrite fd str =
-  withCStringLen str $ \ (buf,len) ->
-    fdWriteBuf fd (castPtr buf) (fromIntegral len)
 
 -- | Write data from memory to an 'Fd'.  This is exactly equivalent
 -- to the POSIX @write@ function.
diff --git a/System/Posix/IO/PosixString.hsc b/System/Posix/IO/PosixString.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/IO/PosixString.hsc
@@ -0,0 +1,116 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.IO.PosixString
+-- 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 IO support.  These types and functions correspond to the unix
+-- functions open(2), close(2), etc.  For more portable functions
+-- which are more like fopen(3) and friends from stdio.h, see
+-- "System.IO".
+--
+-----------------------------------------------------------------------------
+
+#include "HsUnix.h"
+
+module System.Posix.IO.PosixString (
+    -- * Input \/ Output
+
+    -- ** Standard file descriptors
+    stdInput, stdOutput, stdError,
+
+    -- ** Opening and closing files
+    OpenMode(..),
+    OpenFileFlags(..), defaultFileFlags,
+    openFd, openFdAt, createFile, createFileAt,
+    closeFd,
+
+    -- ** Reading\/writing data
+    -- |Programmers using the 'fdRead' and 'fdWrite' API should be aware that
+    -- EAGAIN exceptions may occur for non-blocking IO!
+
+    fdRead, fdWrite,
+    fdReadBuf, fdWriteBuf,
+
+    -- ** Seeking
+    fdSeek,
+
+    -- ** File options
+    FdOption(..),
+    queryFdOption,
+    setFdOption,
+
+    -- ** Locking
+    FileLock,
+    LockRequest(..),
+    getLock,  setLock,
+    waitToSetLock,
+
+    -- ** Pipes
+    createPipe,
+
+    -- ** Duplicating file descriptors
+    dup, dupTo,
+
+    -- ** Converting file descriptors to\/from Handles
+    handleToFd,
+    fdToHandle,
+
+  ) where
+
+import System.Posix.Types
+import System.Posix.IO.Common
+import System.Posix.IO.ByteString ( fdRead, fdWrite )
+import System.OsPath.Types
+
+import System.Posix.PosixPath.FilePath
+
+
+
+-- |Open and optionally create this file.  See 'System.Posix.Files'
+-- for information on how to use the 'FileMode' type.
+openFd :: PosixPath
+       -> OpenMode
+       -> OpenFileFlags
+       -> IO Fd
+openFd = openFdAt Nothing
+
+-- | Open a file relative to an optional directory file descriptor.
+--
+-- Directory file descriptors can be used to avoid some race conditions when
+-- navigating changing directory trees, or to retain access to a portion of the
+-- directory tree that would otherwise become inaccessible after dropping
+-- privileges.
+openFdAt :: Maybe Fd -- ^ Optional directory file descriptor
+         -> PosixPath -- ^ Pathname to open
+         -> OpenMode -- ^ Read-only, read-write or write-only
+         -> OpenFileFlags -- ^ Append, exclusive, truncate, etc.
+         -> IO Fd
+openFdAt fdMay name how flags =
+   withFilePath name $ \str ->
+     throwErrnoPathIfMinus1Retry "openFdAt" name $
+       openat_ fdMay str how flags
+
+-- |Create and open this file in WriteOnly mode.  A special case of
+-- 'openFd'.  See 'System.Posix.Files' for information on how to use
+-- the 'FileMode' type.
+createFile :: PosixPath -> FileMode -> IO Fd
+createFile = createFileAt Nothing
+
+-- | Create and open a file for write-only, with default flags,
+-- relative an optional directory file-descriptor.
+--
+-- Directory file descriptors can be used to avoid some race conditions when
+-- navigating changing directory trees, or to retain access to a portion of the
+-- directory tree that would otherwise become inaccessible after dropping
+-- privileges.
+createFileAt :: Maybe Fd -- ^ Optional directory file descriptor
+             -> PosixPath -- ^ Pathname to create
+             -> FileMode -- ^ File permission bits (before umask)
+             -> IO Fd
+createFileAt fdMay name mode
+  = openFdAt fdMay name WriteOnly defaultFileFlags{ trunc=True, creat=(Just mode) }
diff --git a/System/Posix/PosixPath/FilePath.hsc b/System/Posix/PosixPath/FilePath.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/PosixPath/FilePath.hsc
@@ -0,0 +1,140 @@
+{-# LANGUAGE CPP #-}
+
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.PosixPath.FilePath
+-- 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)
+--
+-- Internal stuff: support for ByteString FilePaths
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.PosixPath.FilePath (
+     withFilePath, peekFilePath, peekFilePathLen,
+     throwErrnoPathIfMinus1Retry,
+     throwErrnoPathIfMinus1Retry_,
+     throwErrnoPathIfNullRetry,
+     throwErrnoPathIfRetry,
+     throwErrnoPath,
+     throwErrnoPathIf,
+     throwErrnoPathIf_,
+     throwErrnoPathIfNull,
+     throwErrnoPathIfMinus1,
+     throwErrnoPathIfMinus1_,
+     throwErrnoTwoPathsIfMinus1_
+  ) where
+
+import Foreign hiding ( void )
+import Foreign.C hiding (
+     throwErrnoPath,
+     throwErrnoPathIf,
+     throwErrnoPathIf_,
+     throwErrnoPathIfNull,
+     throwErrnoPathIfMinus1,
+     throwErrnoPathIfMinus1_ )
+
+import System.OsPath.Types
+import Control.Monad
+import GHC.IO.Encoding.UTF8 ( mkUTF8 )
+import GHC.IO.Encoding.Failure ( CodingFailureMode(..) )
+import System.OsPath.Posix
+import System.OsPath.Data.ByteString.Short
+import Prelude hiding (FilePath)
+import System.OsString.Internal.Types (PosixString(..))
+#if !MIN_VERSION_base(4, 11, 0)
+import Data.Monoid ((<>))
+#endif
+
+
+withFilePath :: PosixPath -> (CString -> IO a) -> IO a
+withFilePath = useAsCString . getPosixString
+
+peekFilePath :: CString -> IO PosixPath
+peekFilePath = fmap PosixString . packCString
+
+peekFilePathLen :: CStringLen -> IO PosixPath
+peekFilePathLen = fmap PosixString . packCStringLen
+
+
+throwErrnoPathIfMinus1Retry :: (Eq a, Num a)
+                            => String -> PosixPath -> IO a -> IO a
+throwErrnoPathIfMinus1Retry loc path f = do
+  throwErrnoPathIfRetry (== -1) loc path f
+
+throwErrnoPathIfMinus1Retry_ :: (Eq a, Num a)
+                             => String -> PosixPath -> IO a -> IO ()
+throwErrnoPathIfMinus1Retry_ loc path f =
+  void $ throwErrnoPathIfRetry (== -1) loc path f
+
+throwErrnoPathIfNullRetry :: String -> PosixPath -> IO (Ptr a) -> IO (Ptr a)
+throwErrnoPathIfNullRetry loc path f =
+  throwErrnoPathIfRetry (== nullPtr) loc path f
+
+throwErrnoPathIfRetry :: (a -> Bool) -> String -> PosixPath -> IO a -> IO a
+throwErrnoPathIfRetry pr loc rpath f =
+  do
+    res <- f
+    if pr res
+      then do
+        err <- getErrno
+        if err == eINTR
+          then throwErrnoPathIfRetry pr loc rpath f
+          else throwErrnoPath loc rpath
+      else return res
+
+-- | as 'throwErrno', but exceptions include the given path when appropriate.
+--
+throwErrnoPath :: String -> PosixPath -> IO a
+throwErrnoPath loc path =
+  do
+    errno <- getErrno
+    ioError (errnoToIOError loc errno Nothing (Just (_toStr path)))
+
+-- | as 'throwErrnoIf', but exceptions include the given path when
+--   appropriate.
+--
+throwErrnoPathIf :: (a -> Bool) -> String -> PosixPath -> IO a -> IO a
+throwErrnoPathIf cond loc path f =
+  do
+    res <- f
+    if cond res then throwErrnoPath loc path else return res
+
+-- | as 'throwErrnoIf_', but exceptions include the given path when
+--   appropriate.
+--
+throwErrnoPathIf_ :: (a -> Bool) -> String -> PosixPath -> IO a -> IO ()
+throwErrnoPathIf_ cond loc path f  = void $ throwErrnoPathIf cond loc path f
+
+-- | as 'throwErrnoIfNull', but exceptions include the given path when
+--   appropriate.
+--
+throwErrnoPathIfNull :: String -> PosixPath -> IO (Ptr a) -> IO (Ptr a)
+throwErrnoPathIfNull  = throwErrnoPathIf (== nullPtr)
+
+-- | as 'throwErrnoIfMinus1', but exceptions include the given path when
+--   appropriate.
+--
+throwErrnoPathIfMinus1 :: (Eq a, Num a) => String -> PosixPath -> IO a -> IO a
+throwErrnoPathIfMinus1 = throwErrnoPathIf (== -1)
+
+-- | as 'throwErrnoIfMinus1_', but exceptions include the given path when
+--   appropriate.
+--
+throwErrnoPathIfMinus1_ :: (Eq a, Num a) => String -> PosixPath -> IO a -> IO ()
+throwErrnoPathIfMinus1_  = throwErrnoPathIf_ (== -1)
+
+-- | as 'throwErrnoTwoPathsIfMinus1_', but exceptions include two paths when appropriate.
+--
+throwErrnoTwoPathsIfMinus1_ :: (Eq a, Num a) => String -> PosixPath -> PosixPath -> IO a -> IO ()
+throwErrnoTwoPathsIfMinus1_  loc path1 path2 =
+    throwErrnoIfMinus1_ (loc <> " '" <> _toStr path1 <> "' to '" <> _toStr path2 <> "'")
+
+
+_toStr :: PosixPath -> String
+_toStr fp = either (error . show) id $ decodeWith (mkUTF8 TransliterateCodingFailure) fp
+
diff --git a/System/Posix/PosixString.hs b/System/Posix/PosixString.hs
new file mode 100644
--- /dev/null
+++ b/System/Posix/PosixString.hs
@@ -0,0 +1,70 @@
+{-# LANGUAGE CPP #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.PosixString
+-- 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)
+--
+-- <http://pubs.opengroup.org/onlinepubs/9699919799/ POSIX.1-2008>
+-- support with 'ByteString' file paths and environment strings.
+--
+-- This module exports exactly the same API as "System.Posix", except
+-- that all file paths and environment strings are represented by
+-- 'ByteString' instead of 'String'.  The "System.Posix" API
+-- implicitly translates all file paths and environment strings using
+-- the locale encoding, whereas this version of the API does no
+-- encoding or decoding and works directly in terms of raw bytes.
+--
+-- Note that if you do need to interpret file paths or environment
+-- strings as text, then some Unicode encoding or decoding should be
+-- applied first.
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.PosixString (
+  System.OsString.Posix.PosixString,
+  System.OsPath.Posix.PosixPath,
+  module System.Posix.Types,
+  module System.Posix.Signals,
+  module System.Posix.Directory.PosixPath,
+  module System.Posix.Files.PosixString,
+  module System.Posix.Unistd,
+  module System.Posix.IO.PosixString,
+  module System.Posix.Env.PosixString,
+  module System.Posix.Process.PosixString,
+  module System.Posix.Temp.PosixString,
+  -- module System.Posix.Terminal.ByteString,
+  module System.Posix.Time,
+  module System.Posix.User,
+  module System.Posix.Resource,
+  module System.Posix.Semaphore,
+  module System.Posix.SharedMem,
+--  module System.Posix.DynamicLinker.ByteString,
+-- XXX 'Module' type clashes with GHC
+--  module System.Posix.DynamicLinker.Module.ByteString
+ ) where
+
+import System.OsPath.Posix
+import System.OsString.Posix
+import System.Posix.Types
+import System.Posix.Signals
+import System.Posix.Directory.PosixPath
+import System.Posix.Files.PosixString
+import System.Posix.Unistd
+import System.Posix.Process.PosixString
+import System.Posix.IO.PosixString
+import System.Posix.Env.PosixString
+import System.Posix.Temp.PosixString
+-- import System.Posix.Terminal.ByteString
+import System.Posix.Time
+import System.Posix.User
+import System.Posix.Resource
+import System.Posix.Semaphore
+import System.Posix.SharedMem
+-- XXX: bad planning, we have two constructors called "Default"
+-- import System.Posix.DynamicLinker.ByteString hiding (Default)
+--import System.Posix.DynamicLinker.Module.ByteString
diff --git a/System/Posix/Process.hsc b/System/Posix/Process.hsc
--- a/System/Posix/Process.hsc
+++ b/System/Posix/Process.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Process
@@ -76,6 +72,11 @@
 import System.Posix.Process.Common
 import System.Posix.Internals ( withFilePath )
 
+#if !defined(HAVE_EXECV)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
 -- | @'executeFile' cmd args env@ calls one of the
 --   @execv*@ family, depending on whether or not the current
 --   PATH is to be searched for the command, and whether or not an
@@ -89,6 +90,14 @@
             -> [String]                     -- ^ Arguments
             -> Maybe [(String, String)]     -- ^ Environment
             -> IO a
+#if !defined(HAVE_EXECV)
+
+{-# WARNING executeFile
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_EXECV@)" #-}
+executeFile _ _ _ _ = ioError (ioeSetLocation unsupportedOperation "executeFile")
+
+#else
+
 executeFile path search args Nothing = do
   withFilePath path $ \s ->
     withMany withFilePath (path:args) $ \cstrs ->
@@ -123,3 +132,4 @@
 foreign import ccall unsafe "execve"
   c_execve :: CString -> Ptr CString -> Ptr CString -> IO CInt
 
+#endif // HAVE_EXECV
diff --git a/System/Posix/Process/ByteString.hsc b/System/Posix/Process/ByteString.hsc
--- a/System/Posix/Process/ByteString.hsc
+++ b/System/Posix/Process/ByteString.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 
 -----------------------------------------------------------------------------
 -- |
@@ -88,6 +84,11 @@
 
 import System.Posix.ByteString.FilePath
 
+#if !defined(HAVE_EXECV)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
 -- | @'executeFile' cmd args env@ calls one of the
 --   @execv*@ family, depending on whether or not the current
 --   PATH is to be searched for the command, and whether or not an
@@ -101,6 +102,14 @@
             -> [ByteString]                 -- ^ Arguments
             -> Maybe [(ByteString, ByteString)]     -- ^ Environment
             -> IO a
+#if !defined(HAVE_EXECV)
+
+{-# WARNING executeFile
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_EXECV@)" #-}
+executeFile _ _ _ _ = ioError (ioeSetLocation unsupportedOperation "executeFile")
+
+#else
+
 executeFile path search args Nothing = do
   withFilePath path $ \s ->
     withMany withFilePath (path:args) $ \cstrs ->
@@ -134,3 +143,5 @@
 
 foreign import ccall unsafe "execve"
   c_execve :: CString -> Ptr CString -> Ptr CString -> IO CInt
+
+#endif // HAVE_EXECV
diff --git a/System/Posix/Process/Common.hsc b/System/Posix/Process/Common.hsc
--- a/System/Posix/Process/Common.hsc
+++ b/System/Posix/Process/Common.hsc
@@ -44,6 +44,7 @@
     -- ** Process times
     ProcessTimes(..),
     getProcessTimes,
+    clocksPerSec,
 
     -- ** Scheduling priority
     nice,
@@ -81,8 +82,22 @@
 
 import Control.Exception.Base ( bracket, getMaskingState, MaskingState(..) ) -- used by forkProcess
 import GHC.TopHandler   ( runIO )
-import GHC.IO ( unsafeUnmask, uninterruptibleMask_ )
 
+#if defined(HAVE_GETPID)
+import GHC.IO ( unsafeUnmask, uninterruptibleMask_  )
+#else
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
+#if !defined(HAVE_GETPID)
+
+getProcessID :: IO ProcessID
+{-# WARNING getProcessID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getProcessID = ioError (ioeSetLocation unsupportedOperation "getProcessID")
+
+#else
 -- -----------------------------------------------------------------------------
 -- Process environment
 
@@ -94,7 +109,18 @@
 foreign import ccall unsafe "getpid"
    c_getpid :: IO CPid
 
--- | 'getProcessID' calls @getppid@ to obtain the 'ProcessID' for
+#endif // HAVE_GETPID
+
+#if !defined(HAVE_GETPID)
+
+getParentProcessID :: IO ProcessID
+{-# WARNING getParentProcessID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getParentProcessID = ioError (ioeSetLocation unsupportedOperation "getParentProcessID")
+
+#else
+
+-- | 'getParentProcessID' calls @getppid@ to obtain the 'ProcessID' for
 --   the parent of the current process.
 getParentProcessID :: IO ProcessID
 getParentProcessID = c_getppid
@@ -102,6 +128,17 @@
 foreign import ccall unsafe "getppid"
   c_getppid :: IO CPid
 
+#endif // HAVE_GETPID
+
+#if !defined(HAVE_GETPID)
+
+getProcessGroupID :: IO ProcessGroupID
+{-# WARNING getProcessGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getProcessGroupID = ioError (ioeSetLocation unsupportedOperation "getProcessGroupID")
+
+#else
+
 -- | 'getProcessGroupID' calls @getpgrp@ to obtain the
 --   'ProcessGroupID' for the current process.
 getProcessGroupID :: IO ProcessGroupID
@@ -110,6 +147,17 @@
 foreign import ccall unsafe "getpgrp"
   c_getpgrp :: IO CPid
 
+#endif // HAVE_GETPID
+
+#if !defined(HAVE_GETPID)
+
+getProcessGroupIDOf :: ProcessID -> IO ProcessGroupID
+{-# WARNING getProcessGroupIDOf
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getProcessGroupIDOf _ = ioError (ioeSetLocation unsupportedOperation "getProcessGroupIDOf")
+
+#else
+
 -- | @'getProcessGroupIDOf' pid@ calls @getpgid@ to obtain the
 --   'ProcessGroupID' for process @pid@.
 getProcessGroupIDOf :: ProcessID -> IO ProcessGroupID
@@ -119,6 +167,8 @@
 foreign import ccall unsafe "getpgid"
   c_getpgid :: CPid -> IO CPid
 
+#endif // HAVE_GETPID
+
 {-
    To be added in the future, after the deprecation period for the
    existing createProcessGroup has elapsed:
@@ -132,6 +182,15 @@
   return pgid
 -}
 
+#if !defined(HAVE_GETPID)
+
+createProcessGroupFor :: ProcessID -> IO ProcessGroupID
+{-# WARNING createProcessGroupFor
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+createProcessGroupFor _ = ioError (ioeSetLocation unsupportedOperation "createProcessGroupFor")
+
+#else
+
 -- | @'createProcessGroupFor' pid@ calls @setpgid@ to make
 --   process @pid@ a new process group leader.
 createProcessGroupFor :: ProcessID -> IO ProcessGroupID
@@ -139,12 +198,25 @@
   throwErrnoIfMinus1_ "createProcessGroupFor" (c_setpgid pid 0)
   return pid
 
+#endif // HAVE_GETPID
+
+#if !defined(HAVE_GETPID)
+
+joinProcessGroup :: ProcessGroupID -> IO ()
+{-# WARNING joinProcessGroup
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+joinProcessGroup _ = ioError (ioeSetLocation unsupportedOperation "joinProcessGroup")
+
+#else
+
 -- | @'joinProcessGroup' pgid@ calls @setpgid@ to set the
 --   'ProcessGroupID' of the current process to @pgid@.
 joinProcessGroup :: ProcessGroupID -> IO ()
 joinProcessGroup pgid =
   throwErrnoIfMinus1_ "joinProcessGroup" (c_setpgid 0 pgid)
 
+#endif // HAVE_GETPID
+
 {-
    To be added in the future, after the deprecation period for the
    existing setProcessGroupID has elapsed:
@@ -156,6 +228,15 @@
   throwErrnoIfMinus1_ "setProcessGroupID" (c_setpgid 0 pgid)
 -}
 
+#if !defined(HAVE_GETPID)
+
+setProcessGroupIDOf :: ProcessID -> ProcessGroupID -> IO ()
+{-# WARNING setProcessGroupIDOf
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+setProcessGroupIDOf _ _ = ioError (ioeSetLocation unsupportedOperation "setProcessGroupIDOf")
+
+#else
+
 -- | @'setProcessGroupIDOf' pid pgid@ calls @setpgid@ to set the
 --   'ProcessGroupIDOf' for process @pid@ to @pgid@.
 setProcessGroupIDOf :: ProcessID -> ProcessGroupID -> IO ()
@@ -165,6 +246,17 @@
 foreign import ccall unsafe "setpgid"
   c_setpgid :: CPid -> CPid -> IO CInt
 
+#endif // HAVE_GETPID
+
+#if !defined(HAVE_GETPID)
+
+createSession :: IO ProcessGroupID
+{-# WARNING createSession
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+createSession = ioError (ioeSetLocation unsupportedOperation "createSession")
+
+#else
+
 -- | 'createSession' calls @setsid@ to create a new session
 --   with the current process as session leader.
 createSession :: IO ProcessGroupID
@@ -173,6 +265,8 @@
 foreign import ccall unsafe "setsid"
   c_setsid :: IO CPid
 
+#endif // HAVE_GETPID
+
 -- -----------------------------------------------------------------------------
 -- Process times
 
@@ -186,6 +280,8 @@
                  , childSystemTime :: ClockTick
                  }
 
+#if defined(HAVE_TIMES)
+
 -- | 'getProcessTimes' calls @times@ to obtain time-accounting
 --   information for the current process and its children.
 getProcessTimes :: IO ProcessTimes
@@ -208,10 +304,46 @@
 foreign import capi unsafe "HsUnix.h times"
   c_times :: Ptr CTms -> IO CClock
 
+-- | Returns the value from the @CLOCK_PER_SEC@ macro, which is required by POSIX.
+clocksPerSec :: ClockTick
+#ifdef HAVE_CLOCKS_PER_SEC
+clocksPerSec = c_clocks_per_sec
+
+foreign import capi unsafe "HsUnix.h __hsunix_clocks_per_second"
+  c_clocks_per_sec :: CClock
+#else
+{-# WARNING clocksPerSec
+    "CLOCK_PER_SEC not defined, defaulting to the value 1000000 as indicated by POSIX (CPP guard: @#if HAVE_CLOCKS_PER_SEC@)" #-}
+clocksPerSec = 1000000
+#endif // HAVE_CLOCKS_PER_SEC
+
+#else
+
+getProcessTimes :: IO ProcessTimes
+{-# WARNING getProcessTimes
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TIMES@)" #-}
+getProcessTimes = ioError (ioeSetLocation unsupportedOperation "getProcessTimes")
+
+clocksPerSec :: ClockTick
+{-# WARNING clocksPerSec
+    "CLOCK_PER_SEC not defined, defaulting to the value 1000000 as indicated by POSIX (CPP guard: @#if HAVE_CLOCKS_PER_SEC@)" #-}
+clocksPerSec = 1000000
+
+#endif // HAVE_TIMES
+
 -- -----------------------------------------------------------------------------
 -- Process scheduling priority
 
+#if !defined(HAVE_GETPID)
+
 nice :: Int -> IO ()
+{-# WARNING nice
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+nice _ = ioError (ioeSetLocation unsupportedOperation "nice")
+
+#else
+
+nice :: Int -> IO ()
 nice prio = do
   resetErrno
   res <- c_nice (fromIntegral prio)
@@ -222,10 +354,28 @@
 foreign import ccall unsafe "nice"
   c_nice :: CInt -> IO CInt
 
+#endif // HAVE_GETPID
+
 getProcessPriority      :: ProcessID      -> IO Int
 getProcessGroupPriority :: ProcessGroupID -> IO Int
 getUserPriority         :: UserID         -> IO Int
 
+#if !defined(HAVE_GETPID)
+
+{-# WARNING getProcessPriority
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getProcessPriority _ = ioError (ioeSetLocation unsupportedOperation "getProcessPriority")
+
+{-# WARNING getProcessGroupPriority
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getProcessGroupPriority _ = ioError (ioeSetLocation unsupportedOperation "getProcessGroupPriority")
+
+{-# WARNING getUserPriority
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getUserPriority _ = ioError (ioeSetLocation unsupportedOperation "getUserPriority")
+
+#else
+
 getProcessPriority pid = do
   r <- throwErrnoIfMinus1 "getProcessPriority" $
          c_getpriority (#const PRIO_PROCESS) (fromIntegral pid)
@@ -244,10 +394,28 @@
 foreign import ccall unsafe "getpriority"
   c_getpriority :: CInt -> CInt -> IO CInt
 
+#endif // HAVE_GETPID
+
 setProcessPriority      :: ProcessID      -> Int -> IO ()
 setProcessGroupPriority :: ProcessGroupID -> Int -> IO ()
 setUserPriority         :: UserID         -> Int -> IO ()
 
+#if !defined(HAVE_GETPID)
+
+{-# WARNING setProcessPriority
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+setProcessPriority _ _ = ioError (ioeSetLocation unsupportedOperation "setProcessPriority")
+
+{-# WARNING setProcessGroupPriority
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+setProcessGroupPriority _ _ = ioError (ioeSetLocation unsupportedOperation "setProcessGroupPriority")
+
+{-# WARNING setUserPriority
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+setUserPriority _ _ = ioError (ioeSetLocation unsupportedOperation "setUserPriority")
+
+#else
+
 setProcessPriority pid val =
   throwErrnoIfMinus1_ "setProcessPriority" $
     c_setpriority (#const PRIO_PROCESS) (fromIntegral pid) (fromIntegral val)
@@ -263,6 +431,8 @@
 foreign import ccall unsafe "setpriority"
   c_setpriority :: CInt -> CInt -> CInt -> IO CInt
 
+#endif // HAVE_GETPID
+
 -- -----------------------------------------------------------------------------
 -- Forking, execution
 
@@ -279,9 +449,27 @@
 threads are not copied into the child process, it's easy to go wrong:
 e.g. by accessing some shared resource that was held by another thread
 in the parent.
+
+GHC note: 'forkProcess' is not currently very well supported when using multiple
+capabilities (@+RTS -N@), although it is supported with @-threaded@ as
+long as only one capability is being used.
 -}
 
+#if !defined(HAVE_GETPID)
+
 forkProcess :: IO () -> IO ProcessID
+{-# WARNING forkProcess
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+forkProcess _ = ioError (ioeSetLocation unsupportedOperation "forkProcess")
+
+forkProcessWithUnmask :: ((forall a . IO a -> IO a) -> IO ()) -> IO ProcessID
+{-# WARNING forkProcessWithUnmask
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+forkProcessWithUnmask _ = ioError (ioeSetLocation unsupportedOperation "forkProcessWithUnmask")
+
+#else
+
+forkProcess :: IO () -> IO ProcessID
 forkProcess action = do
   -- wrap action to re-establish caller's masking state, as
   -- 'forkProcessPrim' starts in 'MaskedInterruptible' state by
@@ -305,6 +493,17 @@
 forkProcessWithUnmask :: ((forall a . IO a -> IO a) -> IO ()) -> IO ProcessID
 forkProcessWithUnmask action = forkProcess (action unsafeUnmask)
 
+#endif // HAVE_GETPID
+
+#if !defined(HAVE_GETPID)
+
+getProcessStatus :: Bool -> Bool -> ProcessID -> IO (Maybe ProcessStatus)
+{-# WARNING getProcessStatus
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getProcessStatus _ _ _ = ioError (ioeSetLocation unsupportedOperation "getProcessStatus")
+
+#else
+
 -- -----------------------------------------------------------------------------
 -- Waiting for process termination
 
@@ -328,6 +527,20 @@
 foreign import ccall interruptible "waitpid"
   c_waitpid :: CPid -> Ptr CInt -> CInt -> IO CPid
 
+#endif // HAVE_GETPID
+
+#if !defined(HAVE_GETPID)
+
+getGroupProcessStatus :: Bool
+                      -> Bool
+                      -> ProcessGroupID
+                      -> IO (Maybe (ProcessID, ProcessStatus))
+{-# WARNING getGroupProcessStatus
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getGroupProcessStatus _ _ _ = ioError (ioeSetLocation unsupportedOperation "getGroupProcessStatus")
+
+#else
+
 -- | @'getGroupProcessStatus' blk stopped pgid@ calls @waitpid@,
 --   returning @'Just' (pid, tc)@, the 'ProcessID' and 'ProcessStatus'
 --   for any process in group @pgid@ if one is available, or 'Nothing'
@@ -351,6 +564,17 @@
       _  -> do ps <- readWaitStatus wstatp
                return (Just (pid, ps))
 
+#endif // HAVE_GETPID
+
+#if !defined(HAVE_GETPID)
+
+getAnyProcessStatus :: Bool -> Bool -> IO (Maybe (ProcessID, ProcessStatus))
+{-# WARNING getAnyProcessStatus
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+getAnyProcessStatus _ _ = ioError (ioeSetLocation unsupportedOperation "getAnyProcessStatus")
+
+#else
+
 -- | @'getAnyProcessStatus' blk stopped@ calls @waitpid@, returning
 --   @'Just' (pid, tc)@, the 'ProcessID' and 'ProcessStatus' for any
 --   child process if a child process has exited, or 'Nothing' if
@@ -364,6 +588,10 @@
 getAnyProcessStatus :: Bool -> Bool -> IO (Maybe (ProcessID, ProcessStatus))
 getAnyProcessStatus block stopped = getGroupProcessStatus block stopped 1
 
+#endif // HAVE_GETPID
+
+#if defined(HAVE_GETPID)
+
 waitOptions :: Bool -> Bool -> CInt
 --             block   stopped
 waitOptions False False = (#const WNOHANG)
@@ -378,14 +606,26 @@
   wstat <- peek wstatp
   decipherWaitStatus wstat
 
+#endif // HAVE_GETPID
+
 -- -----------------------------------------------------------------------------
 -- Exiting
 
 -- | @'exitImmediately' status@ calls @_exit@ to terminate the process
 --   with the indicated exit @status@.
---   The operation never returns.
-exitImmediately :: ExitCode -> IO ()
-exitImmediately exitcode = c_exit (exitcode2Int exitcode)
+--   The operation never returns. Since it does not use the Haskell exception
+--   system and it cannot be caught.
+--
+--   Note: Prior to @unix-2.8.0.0@ the type-signature of 'exitImmediately' was
+--   @ExitCode -> IO ()@.
+--
+-- @since 2.8.0.0
+exitImmediately :: ExitCode -> IO a
+exitImmediately status = do
+    _ <- c_exit (exitcode2Int status)
+    -- The above will exit the program, but need the following to satisfy
+    -- the type signature.
+    exitImmediately status
   where
     exitcode2Int ExitSuccess = 0
     exitcode2Int (ExitFailure n) = fromIntegral n
@@ -393,6 +633,20 @@
 foreign import ccall unsafe "exit"
   c_exit :: CInt -> IO ()
 
+#if !defined(HAVE_GETPID)
+
+createProcessGroup :: ProcessID -> IO ProcessGroupID
+{-# WARNING createProcessGroup
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+createProcessGroup _ = ioError (ioeSetLocation unsupportedOperation "createProcessGroup")
+
+setProcessGroupID :: ProcessID -> ProcessGroupID -> IO ()
+{-# WARNING setProcessGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+setProcessGroupID _ _ = ioError (ioeSetLocation unsupportedOperation "setProcessGroupID")
+
+#else
+
 -- -----------------------------------------------------------------------------
 -- Deprecated or subject to change
 
@@ -418,3 +672,5 @@
   throwErrnoIfMinus1_ "setProcessGroupID" (c_setpgid pid pgid)
 
 -- -----------------------------------------------------------------------------
+
+#endif // HAVE_GETPID
diff --git a/System/Posix/Process/Internals.hs b/System/Posix/Process/Internals.hs
deleted file mode 100644
--- a/System/Posix/Process/Internals.hs
+++ /dev/null
@@ -1,78 +0,0 @@
-{-# LANGUAGE CApiFFI #-}
-{-# LANGUAGE Trustworthy #-}
-
-module System.Posix.Process.Internals (
-       pPrPr_disableITimers, c_execvpe,
-       decipherWaitStatus, ProcessStatus(..) ) where
-
-import Foreign
-import Foreign.C
-import System.Exit
-import System.IO.Error
-import GHC.Conc (Signal)
-
--- | The exit status of a process
-data ProcessStatus
-   = Exited ExitCode        -- ^ the process exited by calling
-                            -- @exit()@ or returning from @main@
-   | Terminated Signal Bool -- ^ the process was terminated by a
-                            -- signal, the @Bool@ is @True@ if a core
-                            -- dump was produced
-                            --
-                            -- @since 2.7.0.0
-   | Stopped Signal         -- ^ the process was stopped by a signal
-   deriving (Eq, Ord, Show)
-
--- this function disables the itimer, which would otherwise cause confusing
--- signals to be sent to the new process.
-foreign import capi unsafe "Rts.h stopTimer"
-  pPrPr_disableITimers :: IO ()
-
-foreign import ccall unsafe "__hsunix_execvpe"
-  c_execvpe :: CString -> Ptr CString -> Ptr CString -> IO CInt
-
-decipherWaitStatus :: CInt -> IO ProcessStatus
-decipherWaitStatus wstat =
-  if c_WIFEXITED wstat /= 0
-      then do
-        let exitstatus = c_WEXITSTATUS wstat
-        if exitstatus == 0
-           then return (Exited ExitSuccess)
-           else return (Exited (ExitFailure (fromIntegral exitstatus)))
-      else do
-        if c_WIFSIGNALED wstat /= 0
-           then do
-                let termsig    = c_WTERMSIG wstat
-                let coredumped = c_WCOREDUMP wstat /= 0
-                return (Terminated termsig coredumped)
-           else do
-                if c_WIFSTOPPED wstat /= 0
-                   then do
-                        let stopsig = c_WSTOPSIG wstat
-                        return (Stopped stopsig)
-                   else do
-                        ioError (mkIOError illegalOperationErrorType
-                                   "waitStatus" Nothing Nothing)
-
-
-foreign import capi unsafe "HsUnix.h WIFEXITED"
-  c_WIFEXITED :: CInt -> CInt
-
-foreign import capi unsafe "HsUnix.h WEXITSTATUS"
-  c_WEXITSTATUS :: CInt -> CInt
-
-foreign import capi unsafe "HsUnix.h WIFSIGNALED"
-  c_WIFSIGNALED :: CInt -> CInt
-
-foreign import capi unsafe "HsUnix.h WTERMSIG"
-  c_WTERMSIG :: CInt -> CInt
-
-foreign import capi unsafe "HsUnix.h WIFSTOPPED"
-  c_WIFSTOPPED :: CInt -> CInt
-
-foreign import capi unsafe "HsUnix.h WSTOPSIG"
-  c_WSTOPSIG :: CInt -> CInt
-
-foreign import capi unsafe "HsUnix.h WCOREDUMP"
-  c_WCOREDUMP :: CInt -> CInt
-
diff --git a/System/Posix/Process/Internals.hsc b/System/Posix/Process/Internals.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Process/Internals.hsc
@@ -0,0 +1,94 @@
+{-# LANGUAGE CApiFFI #-}
+{-# LANGUAGE Trustworthy #-}
+
+#include "HsUnix.h"
+
+module System.Posix.Process.Internals (
+       pPrPr_disableITimers, c_execvpe,
+       decipherWaitStatus, ProcessStatus(..) ) where
+
+import Foreign
+import Foreign.C
+import System.Exit
+import System.IO.Error
+import GHC.Conc (Signal)
+
+#if !defined(HAVE_GETPID)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
+-- | The exit status of a process
+data ProcessStatus
+   = Exited ExitCode        -- ^ the process exited by calling
+                            -- @exit()@ or returning from @main@
+   | Terminated Signal Bool -- ^ the process was terminated by a
+                            -- signal, the @Bool@ is @True@ if a core
+                            -- dump was produced
+                            --
+                            -- @since 2.7.0.0
+   | Stopped Signal         -- ^ the process was stopped by a signal
+   deriving (Eq, Ord, Show)
+
+-- this function disables the itimer, which would otherwise cause confusing
+-- signals to be sent to the new process.
+foreign import capi unsafe "Rts.h stopTimer"
+  pPrPr_disableITimers :: IO ()
+
+foreign import ccall unsafe "__hsunix_execvpe"
+  c_execvpe :: CString -> Ptr CString -> Ptr CString -> IO CInt
+
+#if !defined(HAVE_GETPID)
+
+{-# WARNING decipherWaitStatus "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_GETPID@)" #-}
+decipherWaitStatus :: CInt -> IO ProcessStatus
+decipherWaitStatus _ = ioError (ioeSetLocation unsupportedOperation "decipherWaitStatus")
+
+#else
+
+decipherWaitStatus :: CInt -> IO ProcessStatus
+decipherWaitStatus wstat =
+  if c_WIFEXITED wstat /= 0
+      then do
+        let exitstatus = c_WEXITSTATUS wstat
+        if exitstatus == 0
+           then return (Exited ExitSuccess)
+           else return (Exited (ExitFailure (fromIntegral exitstatus)))
+      else do
+        if c_WIFSIGNALED wstat /= 0
+           then do
+                let termsig    = c_WTERMSIG wstat
+                let coredumped = c_WCOREDUMP wstat /= 0
+                return (Terminated termsig coredumped)
+           else do
+                if c_WIFSTOPPED wstat /= 0
+                   then do
+                        let stopsig = c_WSTOPSIG wstat
+                        return (Stopped stopsig)
+                   else do
+                        ioError (mkIOError illegalOperationErrorType
+                                   "waitStatus" Nothing Nothing)
+
+
+foreign import capi unsafe "HsUnix.h WIFEXITED"
+  c_WIFEXITED :: CInt -> CInt
+
+foreign import capi unsafe "HsUnix.h WEXITSTATUS"
+  c_WEXITSTATUS :: CInt -> CInt
+
+foreign import capi unsafe "HsUnix.h WIFSIGNALED"
+  c_WIFSIGNALED :: CInt -> CInt
+
+foreign import capi unsafe "HsUnix.h WTERMSIG"
+  c_WTERMSIG :: CInt -> CInt
+
+foreign import capi unsafe "HsUnix.h WIFSTOPPED"
+  c_WIFSTOPPED :: CInt -> CInt
+
+foreign import capi unsafe "HsUnix.h WSTOPSIG"
+  c_WSTOPSIG :: CInt -> CInt
+
+foreign import capi unsafe "HsUnix.h WCOREDUMP"
+  c_WCOREDUMP :: CInt -> CInt
+
+#endif // HAVE_GETPID
diff --git a/System/Posix/Process/PosixString.hsc b/System/Posix/Process/PosixString.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Process/PosixString.hsc
@@ -0,0 +1,134 @@
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.Process.PosixString
+-- 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 process support.  See also the System.Cmd and System.Process
+-- modules in the process package.
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.Process.PosixString (
+    -- * Processes
+
+    -- ** Forking and executing
+    forkProcess,
+    forkProcessWithUnmask,
+    executeFile,
+
+    -- ** Exiting
+    exitImmediately,
+
+    -- ** Process environment
+    getProcessID,
+    getParentProcessID,
+
+    -- ** Process groups
+    getProcessGroupID,
+    getProcessGroupIDOf,
+    createProcessGroupFor,
+    joinProcessGroup,
+    setProcessGroupIDOf,
+
+    -- ** Sessions
+    createSession,
+
+    -- ** Process times
+    ProcessTimes(..),
+    getProcessTimes,
+
+    -- ** Scheduling priority
+    nice,
+    getProcessPriority,
+    getProcessGroupPriority,
+    getUserPriority,
+    setProcessPriority,
+    setProcessGroupPriority,
+    setUserPriority,
+
+    -- ** Process status
+    ProcessStatus(..),
+    getProcessStatus,
+    getAnyProcessStatus,
+    getGroupProcessStatus,
+
+    -- ** Deprecated
+    createProcessGroup,
+    setProcessGroupID,
+
+ ) where
+
+#include "HsUnix.h"
+
+import Foreign
+import System.Posix.Process.Internals
+import System.Posix.Process (ProcessTimes(..), setProcessGroupID, createProcessGroup, getGroupProcessStatus, getAnyProcessStatus, getProcessStatus, setUserPriority, setProcessGroupPriority, setProcessPriority, getUserPriority, getProcessGroupPriority, getProcessPriority, nice, getProcessTimes, createSession, setProcessGroupIDOf, joinProcessGroup, createProcessGroupFor, getProcessGroupIDOf, getProcessGroupID, getParentProcessID, getProcessID, exitImmediately, forkProcessWithUnmask, forkProcess)
+
+import Foreign.C hiding (
+     throwErrnoPath,
+     throwErrnoPathIf,
+     throwErrnoPathIf_,
+     throwErrnoPathIfNull,
+     throwErrnoPathIfMinus1,
+     throwErrnoPathIfMinus1_ )
+
+import System.OsPath.Types
+import System.OsString.Internal.Types (PosixString(..))
+import qualified System.OsPath.Data.ByteString.Short as BC
+
+import System.Posix.PosixPath.FilePath
+
+-- | @'executeFile' cmd args env@ calls one of the
+--   @execv*@ family, depending on whether or not the current
+--   PATH is to be searched for the command, and whether or not an
+--   environment is provided to supersede the process's current
+--   environment.  The basename (leading directory names suppressed) of
+--   the command is passed to @execv*@ as @arg[0]@;
+--   the argument list passed to 'executeFile' therefore
+--   begins with @arg[1]@.
+executeFile :: PosixPath                        -- ^ Command
+            -> Bool                                 -- ^ Search PATH?
+            -> [PosixString]                         -- ^ Arguments
+            -> Maybe [(PosixString, PosixString)]     -- ^ Environment
+            -> IO a
+executeFile path search args Nothing = do
+  withFilePath path $ \s ->
+    withMany withFilePath (path:args) $ \cstrs ->
+      withArray0 nullPtr cstrs $ \arr -> do
+        pPrPr_disableITimers
+        if search
+           then throwErrnoPathIfMinus1_ "executeFile" path (c_execvp s arr)
+           else throwErrnoPathIfMinus1_ "executeFile" path (c_execv s arr)
+        return undefined -- never reached
+
+executeFile path search args (Just env) = do
+  withFilePath path $ \s ->
+    withMany withFilePath (path:args) $ \cstrs ->
+      withArray0 nullPtr cstrs $ \arg_arr ->
+    let env' = map (\ (PosixString name, PosixString val) -> PosixString $ name `BC.append` (_equal `BC.cons` val)) env in
+    withMany withFilePath env' $ \cenv ->
+      withArray0 nullPtr cenv $ \env_arr -> do
+        pPrPr_disableITimers
+        if search
+           then throwErrnoPathIfMinus1_ "executeFile" path
+                   (c_execvpe s arg_arr env_arr)
+           else throwErrnoPathIfMinus1_ "executeFile" path
+                   (c_execve s arg_arr env_arr)
+        return undefined -- never reached
+
+foreign import ccall unsafe "execvp"
+  c_execvp :: CString -> Ptr CString -> IO CInt
+
+foreign import ccall unsafe "execv"
+  c_execv :: CString -> Ptr CString -> IO CInt
+
+foreign import ccall unsafe "execve"
+  c_execve :: CString -> Ptr CString -> Ptr CString -> IO CInt
+
+_equal :: Word8
+_equal = 0x3d
diff --git a/System/Posix/Resource.hsc b/System/Posix/Resource.hsc
--- a/System/Posix/Resource.hsc
+++ b/System/Posix/Resource.hsc
@@ -1,9 +1,10 @@
 {-# LANGUAGE CApiFFI #-}
-#if __GLASGOW_HASKELL__ >= 709
-{-# LANGUAGE Safe #-}
-#else
+#if __GLASGOW_HASKELL__ >= 905
 {-# LANGUAGE Trustworthy #-}
+#else
+{-# LANGUAGE Safe #-}
 #endif
+
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Resource
@@ -31,6 +32,14 @@
 import Foreign
 import Foreign.C
 
+#if !defined(HAVE_STRUCT_RLIMIT)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+#if __GLASGOW_HASKELL__ >= 905
+import GHC.Exts ( considerAccessible )
+#endif
+
 -- -----------------------------------------------------------------------------
 -- Resource limits
 
@@ -44,18 +53,32 @@
 #ifdef RLIMIT_AS
   | ResourceTotalMemory
 #endif
-  deriving Eq
+  deriving (Eq, Show)
 
 data ResourceLimits
   = ResourceLimits { softLimit, hardLimit :: ResourceLimit }
-  deriving Eq
+  deriving (Eq, Show)
 
 data ResourceLimit
   = ResourceLimitInfinity
   | ResourceLimitUnknown
   | ResourceLimit Integer
-  deriving Eq
+  deriving (Eq, Show)
 
+#if !defined(HAVE_STRUCT_RLIMIT)
+
+getResourceLimit :: Resource -> IO ResourceLimits
+{-# WARNING getResourceLimit
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_STRUCT_RLIMIT@)" #-}
+getResourceLimit _ = ioError (ioeSetLocation unsupportedOperation "getResourceLimit")
+
+setResourceLimit :: Resource -> ResourceLimits -> IO ()
+{-# WARNING setResourceLimit
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_STRUCT_RLIMIT@)" #-}
+setResourceLimit _ _ = ioError (ioeSetLocation unsupportedOperation "setResourceLimit")
+
+#else
+
 data {-# CTYPE "struct rlimit" #-} RLimit
 
 foreign import capi unsafe "HsUnix.h getrlimit"
@@ -100,13 +123,21 @@
 unpackRLimit (#const RLIM_INFINITY)  = ResourceLimitInfinity
 unpackRLimit other
 #if defined(RLIM_SAVED_MAX)
-    | ((#const RLIM_SAVED_MAX) :: CRLim) /= (#const RLIM_INFINITY) &&
-      other == (#const RLIM_SAVED_MAX) = ResourceLimitUnknown
+    | ((#const RLIM_SAVED_MAX) :: CRLim) /= (#const RLIM_INFINITY)
+    , other == (#const RLIM_SAVED_MAX)
+    = ResourceLimitUnknown
 #endif
 #if defined(RLIM_SAVED_CUR)
-    | ((#const RLIM_SAVED_CUR) :: CRLim) /= (#const RLIM_INFINITY) &&
-      other == (#const RLIM_SAVED_CUR) = ResourceLimitUnknown
+    | ((#const RLIM_SAVED_CUR) :: CRLim) /= (#const RLIM_INFINITY)
+    , other == (#const RLIM_SAVED_CUR)
+#if __GLASGOW_HASKELL__ >= 905
+    , considerAccessible
 #endif
+    = ResourceLimitUnknown
+    -- (*) This pattern match is redundant if RLIM_SAVED_MAX and RLIM_SAVED_CUR
+    -- are both defined and are equal. This redundancy is only detected by GHC
+    -- starting from version 9.5, so we use 'considerAccessible'.
+#endif
     | otherwise = ResourceLimit (fromIntegral other)
 
 packRLimit :: ResourceLimit -> Bool -> CRLim
@@ -164,3 +195,5 @@
 showRLim ResourceLimitUnknown  = "unknown"
 showRLim (ResourceLimit other)  = show other
 -}
+
+#endif // HAVE_STRUCT_RLIMIT
diff --git a/System/Posix/Semaphore.hsc b/System/Posix/Semaphore.hsc
--- a/System/Posix/Semaphore.hsc
+++ b/System/Posix/Semaphore.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 {-# LANGUAGE CApiFFI #-}
 -----------------------------------------------------------------------------
 -- |
@@ -24,18 +20,24 @@
      semPost, semGetValue)
     where
 
+#include "HsUnix.h"
 #include <semaphore.h>
 #include <fcntl.h>
 
 import Foreign.C
 import Foreign.ForeignPtr hiding (newForeignPtr)
 import Foreign.Concurrent
-import Foreign.Marshal
 import Foreign.Ptr
-import Foreign.Storable
 import System.Posix.Types
 import Control.Concurrent
 import Data.Bits
+#if !defined(HAVE_SEM_GETVALUE)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#else
+import Foreign.Marshal
+import Foreign.Storable
+#endif
 
 data OpenSemFlags = OpenSemFlags { semCreate :: Bool,
                                    -- ^ If true, create the semaphore if it
@@ -106,15 +108,24 @@
 
 -- | Return the semaphore's current value.
 semGetValue :: Semaphore -> IO Int
+#ifdef HAVE_SEM_GETVALUE
 semGetValue (Semaphore fptr) = withForeignPtr fptr semGetValue'
     where semGetValue' sem = alloca (semGetValue_ sem)
 
+
 semGetValue_ :: Ptr () -> Ptr CInt -> IO Int
 semGetValue_ sem ptr = do throwErrnoIfMinus1Retry_ "semGetValue" $
                             sem_getvalue sem ptr
                           cint <- peek ptr
                           return $ fromEnum cint
 
+foreign import capi safe "semaphore.h sem_getvalue"
+        sem_getvalue :: Ptr () -> Ptr CInt -> IO Int
+#else
+{-# WARNING semGetValue "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SEM_GETVALUE@)" #-}
+semGetValue _ = ioError (ioeSetLocation unsupportedOperation "semGetValue")
+#endif
+
 foreign import capi safe "semaphore.h sem_open"
         sem_open :: CString -> CInt -> CMode -> CUInt -> IO (Ptr ())
 foreign import capi safe "semaphore.h sem_close"
@@ -128,5 +139,3 @@
         sem_trywait :: Ptr () -> IO CInt
 foreign import capi safe "semaphore.h sem_post"
         sem_post :: Ptr () -> IO CInt
-foreign import capi safe "semaphore.h sem_getvalue"
-        sem_getvalue :: Ptr () -> Ptr CInt -> IO Int
diff --git a/System/Posix/SharedMem.hsc b/System/Posix/SharedMem.hsc
--- a/System/Posix/SharedMem.hsc
+++ b/System/Posix/SharedMem.hsc
@@ -1,8 +1,4 @@
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.SharedMem
@@ -24,7 +20,9 @@
 #include "HsUnix.h"
 
 #include <sys/types.h>
+#if defined(HAVE_SHM_OPEN) || defined(HAVE_SHM_UNLINK)
 #include <sys/mman.h>
+#endif
 #include <fcntl.h>
 
 import System.Posix.Types
@@ -67,6 +65,7 @@
                        shm_open cname cflags mode
                  return $ Fd fd
 #else
+{-# WARNING shmOpen "System.Posix.SharedMem: shm_open: not available" #-}
 shmOpen = error "System.Posix.SharedMem:shm_open: not available"
 #endif
 
@@ -77,6 +76,7 @@
     where shmUnlink' cname =
               throwErrnoIfMinus1_ "shmUnlink" $ shm_unlink cname
 #else
+{-# WARNING shmUnlink "System.Posix.SharedMem:shm_unlink: not available" #-}
 shmUnlink = error "System.Posix.SharedMem:shm_unlink: not available"
 #endif
 
diff --git a/System/Posix/Signals.hsc b/System/Posix/Signals.hsc
--- a/System/Posix/Signals.hsc
+++ b/System/Posix/Signals.hsc
@@ -101,6 +101,10 @@
 import Foreign.Marshal
 import Foreign.Ptr
 import Foreign.Storable
+#if !defined(HAVE_SIGNAL_H)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
 import System.IO.Unsafe (unsafePerformIO)
 import System.Posix.Types
 import System.Posix.Internals
@@ -112,154 +116,241 @@
 
 import GHC.Conc hiding (Signal)
 
+#if !defined(HAVE_SIGNAL_H)
+import Control.Exception ( throw )
+#endif
+
 -- -----------------------------------------------------------------------------
 -- Specific signals
 
 nullSignal :: Signal
 nullSignal = 0
 
+-- | Process abort signal.
 sigABRT   :: CInt
 sigABRT   = CONST_SIGABRT
+
+-- | Alarm clock.
 sigALRM   :: CInt
 sigALRM   = CONST_SIGALRM
+
+-- | Access to an undefined portion of a memory object.
 sigBUS    :: CInt
 sigBUS    = CONST_SIGBUS
+
+-- | Child process terminated, stopped, or continued.
 sigCHLD   :: CInt
 sigCHLD   = CONST_SIGCHLD
+
+-- | Continue executing, if stopped.
 sigCONT   :: CInt
 sigCONT   = CONST_SIGCONT
+
+-- | Erroneous arithmetic operation.
 sigFPE    :: CInt
 sigFPE    = CONST_SIGFPE
+
+-- | Hangup.
 sigHUP    :: CInt
 sigHUP    = CONST_SIGHUP
+
+-- | Illegal instruction.
 sigILL    :: CInt
 sigILL    = CONST_SIGILL
+
+-- | Terminal interrupt signal.
 sigINT    :: CInt
 sigINT    = CONST_SIGINT
+
+-- | Kill (cannot be caught or ignored).
 sigKILL   :: CInt
 sigKILL   = CONST_SIGKILL
+
+-- | Write on a pipe with no one to read it.
 sigPIPE   :: CInt
 sigPIPE   = CONST_SIGPIPE
+
+-- | Terminal quit signal.
 sigQUIT   :: CInt
 sigQUIT   = CONST_SIGQUIT
+
+-- | Invalid memory reference.
 sigSEGV   :: CInt
 sigSEGV   = CONST_SIGSEGV
+
+-- | Stop executing (cannot be caught or ignored).
 sigSTOP   :: CInt
 sigSTOP   = CONST_SIGSTOP
+
+-- | Termination signal.
 sigTERM   :: CInt
 sigTERM   = CONST_SIGTERM
+
+-- | Terminal stop signal.
 sigTSTP   :: CInt
 sigTSTP   = CONST_SIGTSTP
+
+-- | Background process attempting read.
 sigTTIN   :: CInt
 sigTTIN   = CONST_SIGTTIN
+
+-- | Background process attempting write.
 sigTTOU   :: CInt
 sigTTOU   = CONST_SIGTTOU
+
+-- | User-defined signal 1.
 sigUSR1   :: CInt
 sigUSR1   = CONST_SIGUSR1
+
+-- | User-defined signal 2.
 sigUSR2   :: CInt
 sigUSR2   = CONST_SIGUSR2
+
 #if CONST_SIGPOLL != -1
+-- | Pollable event.
 sigPOLL   :: CInt
 sigPOLL   = CONST_SIGPOLL
 #endif
+
+-- | Profiling timer expired.
 sigPROF   :: CInt
 sigPROF   = CONST_SIGPROF
+
+-- | Bad system call.
 sigSYS    :: CInt
 sigSYS    = CONST_SIGSYS
+
+-- | Trace/breakpoint trap.
 sigTRAP   :: CInt
 sigTRAP   = CONST_SIGTRAP
+
+-- | High bandwidth data is available at a socket.
 sigURG    :: CInt
 sigURG    = CONST_SIGURG
+
+-- | Virtual timer expired.
 sigVTALRM :: CInt
 sigVTALRM = CONST_SIGVTALRM
+
+-- | CPU time limit exceeded.
 sigXCPU   :: CInt
 sigXCPU   = CONST_SIGXCPU
+
+-- | File size limit exceeded.
 sigXFSZ   :: CInt
 sigXFSZ   = CONST_SIGXFSZ
 
+-- | Alias for 'sigABRT'.
 internalAbort ::Signal
 internalAbort = sigABRT
 
+-- | Alias for 'sigALRM'.
 realTimeAlarm :: Signal
 realTimeAlarm = sigALRM
 
+-- | Alias for 'sigBUS'.
 busError :: Signal
 busError = sigBUS
 
+-- | Alias for 'sigCHLD'.
 processStatusChanged :: Signal
 processStatusChanged = sigCHLD
 
+-- | Alias for 'sigCONT'.
 continueProcess :: Signal
 continueProcess = sigCONT
 
+-- | Alias for 'sigFPE'.
 floatingPointException :: Signal
 floatingPointException = sigFPE
 
+-- | Alias for 'sigHUP'.
 lostConnection :: Signal
 lostConnection = sigHUP
 
+-- | Alias for 'sigILL'.
 illegalInstruction :: Signal
 illegalInstruction = sigILL
 
+-- | Alias for 'sigINT'.
 keyboardSignal :: Signal
 keyboardSignal = sigINT
 
+-- | Alias for 'sigKILL'.
 killProcess :: Signal
 killProcess = sigKILL
 
+-- | Alias for 'sigPIPE'.
 openEndedPipe :: Signal
 openEndedPipe = sigPIPE
 
+-- | Alias for 'sigQUIT'.
 keyboardTermination :: Signal
 keyboardTermination = sigQUIT
 
+-- | Alias for 'sigSEGV'.
 segmentationViolation :: Signal
 segmentationViolation = sigSEGV
 
+-- | Alias for 'sigSTOP'.
 softwareStop :: Signal
 softwareStop = sigSTOP
 
+-- | Alias for 'sigTERM'.
 softwareTermination :: Signal
 softwareTermination = sigTERM
 
+-- | Alias for 'sigTSTP'.
 keyboardStop :: Signal
 keyboardStop = sigTSTP
 
+-- | Alias for 'sigTTIN'.
 backgroundRead :: Signal
 backgroundRead = sigTTIN
 
+-- | Alias for 'sigTTOU'.
 backgroundWrite :: Signal
 backgroundWrite = sigTTOU
 
+-- | Alias for 'sigUSR1'.
 userDefinedSignal1 :: Signal
 userDefinedSignal1 = sigUSR1
 
+-- | Alias for 'sigUSR2'.
 userDefinedSignal2 :: Signal
 userDefinedSignal2 = sigUSR2
 
 #if CONST_SIGPOLL != -1
+-- | Alias for 'sigPOLL'.
 pollableEvent :: Signal
 pollableEvent = sigPOLL
 #endif
 
+-- | Alias for 'sigPROF'.
 profilingTimerExpired :: Signal
 profilingTimerExpired = sigPROF
 
+-- | Alias for 'sigSYS'.
 badSystemCall :: Signal
 badSystemCall = sigSYS
 
+-- | Alias for 'sigTRAP'.
 breakpointTrap :: Signal
 breakpointTrap = sigTRAP
 
+-- | Alias for 'sigURG'.
 urgentDataAvailable :: Signal
 urgentDataAvailable = sigURG
 
+-- | Alias for 'sigVTALRM'.
 virtualTimerExpired :: Signal
 virtualTimerExpired = sigVTALRM
 
+-- | Alias for 'sigXCPU'.
 cpuTimeLimitExceeded :: Signal
 cpuTimeLimitExceeded = sigXCPU
 
+-- | Alias for 'sigXFSZ'.
 fileSizeLimitExceeded :: Signal
 fileSizeLimitExceeded = sigXFSZ
 
@@ -269,25 +360,53 @@
 -- | @signalProcess int pid@ calls @kill@ to signal process @pid@
 --   with interrupt signal @int@.
 signalProcess :: Signal -> ProcessID -> IO ()
+#if !defined(HAVE_SIGNAL_H)
+
+{-# WARNING signalProcess
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+signalProcess _ _ = ioError (ioeSetLocation unsupportedOperation "signalProcess")
+
+#else
+
 signalProcess sig pid
  = throwErrnoIfMinus1_ "signalProcess" (c_kill pid sig)
 
 foreign import ccall unsafe "kill"
   c_kill :: CPid -> CInt -> IO CInt
 
+#endif // HAVE_SIGNAL_H
 
+
 -- | @signalProcessGroup int pgid@ calls @kill@ to signal
 --  all processes in group @pgid@ with interrupt signal @int@.
 signalProcessGroup :: Signal -> ProcessGroupID -> IO ()
+#if !defined(HAVE_SIGNAL_H)
+
+{-# WARNING signalProcessGroup
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+signalProcessGroup _ _ = ioError (ioeSetLocation unsupportedOperation "signalProcessGroup")
+
+#else
+
 signalProcessGroup sig pgid
   = throwErrnoIfMinus1_ "signalProcessGroup" (c_killpg pgid sig)
 
 foreign import ccall unsafe "killpg"
   c_killpg :: CPid -> CInt -> IO CInt
 
+#endif // HAVE_SIGNAL_H
+
 -- | @raiseSignal int@ calls @kill@ to signal the current process
 --   with interrupt signal @int@.
 raiseSignal :: Signal -> IO ()
+#if !defined(HAVE_SIGNAL_H)
+
+{-# WARNING raiseSignal
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+raiseSignal _ = ioError (ioeSetLocation unsupportedOperation "raiseSignal")
+
+#else
+
 raiseSignal sig = throwErrnoIfMinus1_ "raiseSignal" (c_raise sig)
 
 -- See also note in GHC's rts/RtsUtils.c
@@ -301,15 +420,28 @@
   c_raise :: CInt -> IO CInt
 #endif
 
+#endif // HAVE_SIGNAL_H
 
 type Signal = CInt
 
 -- | The actions to perform when a signal is received.
 data Handler = Default
+                 -- ^ Sets the disposition of the signal to @SIG_DFL@, which
+                 -- means we want the default action associated with the
+                 -- signal. For example, the default action for @SIGTERM@ (and
+                 -- various other signals) is to terminate the process.
              | Ignore
+                 -- ^ Set the disposition of the signal to @SIG_IGN@, which
+                 -- means we want to /ignore/ the signal.  Ignored signals will
+                 -- not be delivered to the process, and if also /blocked/ will
+                 -- not be added to the pending set for later delivery (if/when
+                 -- unblocked).  Some signals (e.g. @SIGSTOP@ and @SIGKILL@)
+                 -- cannot be caught or ignored.
              -- not yet: | Hold
              | Catch (IO ())
+                 -- ^ signal handler is not reset
              | CatchOnce (IO ())
+                 -- ^ signal handler is automatically reset (via @SA_RESETHAND@)
              | CatchInfo (SignalInfo -> IO ())     -- ^ @since 2.7.0.0
              | CatchInfoOnce (SignalInfo -> IO ()) -- ^ @since 2.7.0.0
   deriving (Typeable)
@@ -350,8 +482,16 @@
                -> IO Handler            -- ^ old handler
 
 #ifdef __PARALLEL_HASKELL__
+{-# WARNING installHandler "installHandler: not available for Parallel Haskell"
+ - #-}
 installHandler =
   error "installHandler: not available for Parallel Haskell"
+#elif !defined(HAVE_SIGNAL_H)
+
+{-# WARNING installHandler
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+installHandler _ _ _ = ioError (ioeSetLocation unsupportedOperation "installHandler")
+
 #else
 
 installHandler sig handler _maybe_mask = do
@@ -447,6 +587,15 @@
 
 #endif /* !__PARALLEL_HASKELL__ */
 
+#if !defined(HAVE_ALARM)
+
+scheduleAlarm :: Int -> IO Int
+{-# WARNING scheduleAlarm
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_ALARM@)" #-}
+scheduleAlarm _ = ioError (ioeSetLocation unsupportedOperation "scheduleAlarm")
+
+#else
+
 -- -----------------------------------------------------------------------------
 -- Alarms
 
@@ -460,9 +609,23 @@
 foreign import ccall unsafe "alarm"
   c_alarm :: CUInt -> IO CUInt
 
+#endif // HAVE_ALARM
+
 -- -----------------------------------------------------------------------------
 -- The NOCLDSTOP flag
 
+#if !defined(HAVE_SIGNAL_H)
+
+{-# WARNING setStoppedChildFlag "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+setStoppedChildFlag :: Bool -> IO Bool
+setStoppedChildFlag _ = ioError (ioeSetLocation unsupportedOperation "setStoppedChildFlag")
+
+{-# WARNING queryStoppedChildFlag "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+queryStoppedChildFlag :: IO Bool
+queryStoppedChildFlag = ioError (ioeSetLocation unsupportedOperation "queryStoppedChildFlag")
+
+#else
+
 foreign import ccall "&nocldstop" nocldstop :: Ptr Int
 
 -- | Tells the system whether or not to set the @SA_NOCLDSTOP@ flag when
@@ -479,12 +642,57 @@
     rc <- peek nocldstop
     return (rc == (0::Int))
 
+#endif
+
 -- -----------------------------------------------------------------------------
 -- Manipulating signal sets
 
+#if defined(HAVE_SIGNAL_H)
+
 newtype SignalSet = SignalSet (ForeignPtr CSigset)
 
+#else
+
+data SignalSet
+
+#endif // HAVE_SIGNAL_H
+
+#if !defined(HAVE_SIGNAL_H)
+
 emptySignalSet :: SignalSet
+{-# WARNING emptySignalSet
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+emptySignalSet = throw (ioeSetLocation unsupportedOperation "emptySignalSet")
+
+fullSignalSet :: SignalSet
+{-# WARNING fullSignalSet
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+fullSignalSet = throw (ioeSetLocation unsupportedOperation "fullSignalSet")
+
+reservedSignals :: SignalSet
+{-# WARNING reservedSignals
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+reservedSignals = throw (ioeSetLocation unsupportedOperation "reservedSignals")
+
+infixr `addSignal`, `deleteSignal`
+addSignal :: Signal -> SignalSet -> SignalSet
+{-# WARNING addSignal
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+addSignal _ _ = throw (ioeSetLocation unsupportedOperation "addSignal")
+
+deleteSignal :: Signal -> SignalSet -> SignalSet
+{-# WARNING deleteSignal
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+deleteSignal _ _ = throw (ioeSetLocation unsupportedOperation "deleteSignal")
+
+inSignalSet :: Signal -> SignalSet -> Bool
+{-# WARNING inSignalSet
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+inSignalSet _ _ = throw (ioeSetLocation unsupportedOperation "inSignalSet")
+
+#else
+
+emptySignalSet :: SignalSet
 emptySignalSet = unsafePerformIO $ do
   fp <- mallocForeignPtrBytes sizeof_sigset_t
   throwErrnoIfMinus1_ "emptySignalSet" (withForeignPtr fp $ c_sigemptyset)
@@ -528,6 +736,32 @@
     r <- throwErrnoIfMinus1 "inSignalSet" (c_sigismember p sig)
     return (r /= 0)
 
+#endif // HAVE_SIGNAL_H
+
+#if !defined(HAVE_SIGNAL_H)
+
+getSignalMask :: IO SignalSet
+{-# WARNING getSignalMask
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+getSignalMask = ioError (ioeSetLocation unsupportedOperation "getSignalMask")
+
+setSignalMask :: SignalSet -> IO ()
+{-# WARNING setSignalMask
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+setSignalMask _ = ioError (ioeSetLocation unsupportedOperation "setSignalMask")
+
+blockSignals :: SignalSet -> IO ()
+{-# WARNING blockSignals
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+blockSignals _ = ioError (ioeSetLocation unsupportedOperation "blockSignals")
+
+unblockSignals :: SignalSet -> IO ()
+{-# WARNING unblockSignals
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+unblockSignals _ = ioError (ioeSetLocation unsupportedOperation "unblockSignals")
+
+#else
+
 -- | @getSignalMask@ calls @sigprocmask@ to determine the
 --   set of interrupts which are currently being blocked.
 getSignalMask :: IO SignalSet
@@ -559,6 +793,22 @@
 unblockSignals :: SignalSet -> IO ()
 unblockSignals set = sigProcMask "unblockSignals" (CONST_SIG_UNBLOCK :: CInt) set
 
+#endif // HAVE_SIGNAL_H
+
+#if !defined(HAVE_SIGNAL_H)
+
+getPendingSignals :: IO SignalSet
+{-# WARNING getPendingSignals
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+getPendingSignals = ioError (ioeSetLocation unsupportedOperation "getPendingSignals")
+
+awaitSignal :: Maybe SignalSet -> IO ()
+{-# WARNING awaitSignal
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_SIGNAL_H@)" #-}
+awaitSignal _ = ioError (ioeSetLocation unsupportedOperation "awaitSignal")
+
+#else
+
 -- | @getPendingSignals@ calls @sigpending@ to obtain
 --   the set of interrupts which have been received but are currently blocked.
 getPendingSignals :: IO SignalSet
@@ -594,21 +844,13 @@
   -- XXX My manpage says it can also return EFAULT. And why is ignoring
   -- EINTR the right thing to do?
 
-foreign import ccall unsafe "sigsuspend"
-  c_sigsuspend :: Ptr CSigset -> IO CInt
+#endif // HAVE_SIGNAL_H
 
-#if defined(darwin_HOST_OS) && __GLASGOW_HASKELL__ < 706
--- see http://ghc.haskell.org/trac/ghc/ticket/7359#comment:3
--- To be removed when support for GHC 7.4.x is dropped
-foreign import ccall unsafe "__hscore_sigdelset"
-  c_sigdelset   :: Ptr CSigset -> CInt -> IO CInt
+#if defined(HAVE_SIGNAL_H)
 
-foreign import ccall unsafe "__hscore_sigfillset"
-  c_sigfillset  :: Ptr CSigset -> IO CInt
+foreign import ccall unsafe "sigsuspend"
+  c_sigsuspend :: Ptr CSigset -> IO CInt
 
-foreign import ccall unsafe "__hscore_sigismember"
-  c_sigismember :: Ptr CSigset -> CInt -> IO CInt
-#else
 foreign import capi unsafe "signal.h sigdelset"
   c_sigdelset   :: Ptr CSigset -> CInt -> IO CInt
 
@@ -617,7 +859,8 @@
 
 foreign import capi unsafe "signal.h sigismember"
   c_sigismember :: Ptr CSigset -> CInt -> IO CInt
-#endif
 
 foreign import ccall unsafe "sigpending"
   c_sigpending :: Ptr CSigset -> IO CInt
+
+#endif // HAVE_SIGNAL_H
diff --git a/System/Posix/Temp.hsc b/System/Posix/Temp.hsc
--- a/System/Posix/Temp.hsc
+++ b/System/Posix/Temp.hsc
@@ -1,9 +1,5 @@
 {-# LANGUAGE CApiFFI #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Temp
@@ -34,6 +30,19 @@
 import System.Posix.Types
 import System.Posix.Internals (withFilePath, peekFilePath)
 
+#if !defined(HAVE_MKSTEMP)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
+#if !defined(HAVE_MKSTEMP)
+
+{-# WARNING mkstemp "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_MKSTEMP@)" #-}
+mkstemp :: String -> IO (FilePath, Handle)
+mkstemp _ = ioError (ioeSetLocation unsupportedOperation "mkstemp")
+
+#else
+
 foreign import capi unsafe "HsUnix.h mkstemp"
   c_mkstemp :: CString -> IO CInt
 
@@ -53,6 +62,8 @@
     h <- fdToHandle (Fd fd)
     return (name, h)
 
+#endif // HAVE_MKSTEMP
+
 #if HAVE_MKSTEMPS
 foreign import capi unsafe "HsUnix.h mkstemps"
   c_mkstemps :: CString -> CInt -> IO CInt
@@ -78,6 +89,7 @@
     h <- fdToHandle (Fd fd)
     return (name, h)
 #else
+{-# WARNING mkstemps "System.Posix.Temp.mkstemps: not available on this platform" #-}
 mkstemps = error "System.Posix.Temp.mkstemps: not available on this platform"
 #endif
 
@@ -103,7 +115,7 @@
     return name
 #else
   name <- mktemp template
-  h <- createDirectory name (toEnum 0o700)
+  _ <- createDirectory name (toEnum 0o700)
   return name
 #endif
 
@@ -118,7 +130,6 @@
 mktemp :: String -> IO String
 mktemp template = do
   withFilePath template $ \ ptr -> do
-    ptr <- throwErrnoIfNull "mktemp" (c_mktemp ptr)
-    peekFilePath ptr
+    ptr' <- throwErrnoIfNull "mktemp" (c_mktemp ptr)
+    peekFilePath ptr'
 #endif
-
diff --git a/System/Posix/Temp/ByteString.hsc b/System/Posix/Temp/ByteString.hsc
--- a/System/Posix/Temp/ByteString.hsc
+++ b/System/Posix/Temp/ByteString.hsc
@@ -1,9 +1,5 @@
 {-# LANGUAGE CApiFFI #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Temp.ByteString
@@ -39,6 +35,19 @@
 import System.Posix.IO
 import System.Posix.Types
 
+#if !defined(HAVE_MKSTEMP)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
+#if !defined(HAVE_MKSTEMP)
+
+{-# WARNING mkstemp "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_MKSTEMP@)" #-}
+mkstemp :: ByteString -> IO (RawFilePath, Handle)
+mkstemp _ = ioError (ioeSetLocation unsupportedOperation "mkstemp")
+
+#else
+
 foreign import capi unsafe "HsUnix.h mkstemp"
   c_mkstemp :: CString -> IO CInt
 
@@ -58,6 +67,8 @@
     h <- fdToHandle (Fd fd)
     return (name, h)
 
+#endif // HAVE_MKSTEMP
+
 #if HAVE_MKSTEMPS
 foreign import capi unsafe "HsUnix.h mkstemps"
   c_mkstemps :: CString -> CInt -> IO CInt
@@ -79,6 +90,7 @@
     h <- fdToHandle (Fd fd)
     return (name, h)
 #else
+{-# WARNING mkstemps "System.Posix.Temp.mkstemps: not available on this platform"  #-}
 mkstemps = error "System.Posix.Temp.mkstemps: not available on this platform"
 #endif
 
@@ -103,7 +115,7 @@
     return name
 #else
   name <- mktemp template
-  h <- createDirectory (BC.unpack name) (toEnum 0o700)
+  _ <- createDirectory (BC.unpack name) (toEnum 0o700)
   return name
 #endif
 
@@ -118,7 +130,6 @@
 mktemp :: ByteString -> IO RawFilePath
 mktemp template = do
   withFilePath template $ \ ptr -> do
-    ptr <- throwErrnoIfNull "mktemp" (c_mktemp ptr)
-    peekFilePath ptr
+    ptr' <- throwErrnoIfNull "mktemp" (c_mktemp ptr)
+    peekFilePath ptr'
 #endif
-
diff --git a/System/Posix/Temp/PosixString.hsc b/System/Posix/Temp/PosixString.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Temp/PosixString.hsc
@@ -0,0 +1,123 @@
+{-# LANGUAGE CApiFFI #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.Temp.PosixString
+-- Copyright   :  (c) Volker Stolz <vs@foldr.org>
+--                    Deian Stefan <deian@cs.stanford.edu>
+-- License     :  BSD-style (see the file libraries/base/LICENSE)
+--
+-- Maintainer  :  libraries@haskell.org, vs@foldr.org, deian@cs.stanford.edu
+-- Stability   :  provisional
+-- Portability :  non-portable (requires POSIX)
+--
+-- POSIX temporary file and directory creation functions.
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.Temp.PosixString (
+        mkstemp, mkstemps, mkdtemp
+    ) where
+
+#include "HsUnix.h"
+
+import qualified System.OsPath.Data.ByteString.Short as BC
+import Data.Word
+
+import Foreign.C
+
+import System.OsPath.Types
+import System.IO
+import System.Posix.PosixPath.FilePath
+import System.OsString.Internal.Types (PosixString(..))
+#if !HAVE_MKDTEMP
+import System.Posix.Directory.PosixPath (createDirectory)
+#endif
+import System.Posix.IO.PosixString
+import System.Posix.Types
+
+foreign import capi unsafe "HsUnix.h mkstemp"
+  c_mkstemp :: CString -> IO CInt
+
+-- | Make a unique filename and open it for reading\/writing. The returned
+-- 'PosixPath' is the (possibly relative) path of the created file, which is
+-- padded with 6 random characters. The argument is the desired prefix of the
+-- filepath of the temporary file to be created.
+--
+-- If you aren't using GHC or Hugs then this function simply wraps mktemp and
+-- so shouldn't be considered safe.
+mkstemp :: PosixString -> IO (PosixPath, Handle)
+mkstemp (PosixString template') = do
+  let template = PosixString $ template' `BC.append` (BC.pack [_X,_X,_X,_X,_X,_X])
+  withFilePath template $ \ ptr -> do
+    fd <- throwErrnoIfMinus1 "mkstemp" (c_mkstemp ptr)
+    name <- peekFilePath ptr
+    h <- fdToHandle (Fd fd)
+    return (name, h)
+
+#if HAVE_MKSTEMPS
+foreign import capi unsafe "HsUnix.h mkstemps"
+  c_mkstemps :: CString -> CInt -> IO CInt
+#endif
+
+-- |'mkstemps' - make a unique filename with a given prefix and suffix
+-- and open it for reading\/writing (only safe on GHC & Hugs).
+-- The returned 'PosixPath' is the (possibly relative) path of
+-- the created file, which contains  6 random characters in between
+-- the prefix and suffix.
+mkstemps :: PosixString -> PosixString -> IO (PosixPath, Handle)
+#if HAVE_MKSTEMPS
+mkstemps (PosixString prefix) (PosixString suffix) = do
+  let template = PosixString $ prefix `BC.append` (BC.pack [_X,_X,_X,_X,_X,_X]) `BC.append` suffix
+      lenOfsuf = (fromIntegral $ BC.length suffix) :: CInt
+  withFilePath template $ \ ptr -> do
+    fd <- throwErrnoIfMinus1 "mkstemps" (c_mkstemps ptr lenOfsuf)
+    name <- peekFilePath ptr
+    h <- fdToHandle (Fd fd)
+    return (name, h)
+#else
+mkstemps = error "System.Posix.Temp.mkstemps: not available on this platform"
+#endif
+
+#if HAVE_MKDTEMP
+foreign import capi unsafe "HsUnix.h mkdtemp"
+  c_mkdtemp :: CString -> IO CString
+#endif
+
+-- | Make a unique directory. The returned 'PosixPath' is the path of the
+-- created directory, which is padded with 6 random characters. The argument is
+-- the desired prefix of the filepath of the temporary directory to be created.
+--
+-- If you aren't using GHC or Hugs then this function simply wraps mktemp and
+-- so shouldn't be considered safe.
+mkdtemp :: PosixString -> IO PosixPath
+mkdtemp (PosixString template') = do
+  let template = PosixString $ template' `BC.append` (BC.pack [_X,_X,_X,_X,_X,_X])
+#if HAVE_MKDTEMP
+  withFilePath template $ \ ptr -> do
+    _ <- throwErrnoIfNull "mkdtemp" (c_mkdtemp ptr)
+    name <- peekFilePath ptr
+    return name
+#else
+  name <- mktemp template
+  h <- createDirectory name (toEnum 0o700)
+  return name
+#endif
+
+#if !HAVE_MKDTEMP
+
+foreign import ccall unsafe "mktemp"
+  c_mktemp :: CString -> IO CString
+
+-- | Make a unique file name It is required that the template have six trailing
+-- \'X\'s. This function should be considered deprecated.
+{-# WARNING mktemp "This function is unsafe; use mkstemp instead" #-}
+mktemp :: PosixString -> IO PosixPath
+mktemp template = do
+  withFilePath template $ \ ptr -> do
+    ptr <- throwErrnoIfNull "mktemp" (c_mktemp ptr)
+    peekFilePath ptr
+#endif
+
+_X :: Word8
+_X = 0x58
+
diff --git a/System/Posix/Terminal.hsc b/System/Posix/Terminal.hsc
--- a/System/Posix/Terminal.hsc
+++ b/System/Posix/Terminal.hsc
@@ -1,9 +1,5 @@
 {-# LANGUAGE CApiFFI #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Terminal
@@ -84,7 +80,7 @@
 
 import System.Posix.Internals (peekFilePath)
 
-#if !HAVE_CTERMID
+#if !(HAVE_CTERMID && defined(HAVE_TERMIOS_H))
 import System.IO.Error ( ioeSetLocation )
 import GHC.IO.Exception ( unsupportedOperation )
 #endif
@@ -111,7 +107,7 @@
 -- provide @ctermid(3)@ (use @#if HAVE_CTERMID@ CPP guard to
 -- detect availability).
 getControllingTerminalName :: IO FilePath
-#if HAVE_CTERMID
+#if HAVE_CTERMID && defined(HAVE_TERMIOS_H)
 getControllingTerminalName = do
   s <- throwErrnoIfNull "getControllingTerminalName" (c_ctermid nullPtr)
   peekFilePath s
@@ -134,17 +130,12 @@
   s <- throwErrnoIfNull "getSlaveTerminalName" (c_ptsname fd)
   peekFilePath s
 
-# if __GLASGOW_HASKELL__ < 800
--- see comment in cbits/HsUnix.c
-foreign import ccall unsafe "__hsunix_ptsname"
-  c_ptsname :: CInt -> IO CString
-# else
 foreign import capi unsafe "HsUnix.h ptsname"
   c_ptsname :: CInt -> IO CString
-# endif
 #else
 getSlaveTerminalName _ =
     ioError (errnoToIOError "getSlaveTerminalName" eNOSYS Nothing Nothing)
+{-# WARNING getSlaveTerminalName "getSlaveTerminalName: not available on this platform" #-}
 #endif
 
 -- -----------------------------------------------------------------------------
@@ -170,12 +161,12 @@
             -> IO CInt
 #else
 openPseudoTerminal = do
-  (Fd master) <- openFd "/dev/ptmx" ReadWrite Nothing
+  (Fd master) <- openFd "/dev/ptmx" ReadWrite
                         defaultFileFlags{noctty=True}
   throwErrnoIfMinus1_ "openPseudoTerminal" (c_grantpt master)
   throwErrnoIfMinus1_ "openPseudoTerminal" (c_unlockpt master)
   slaveName <- getSlaveTerminalName (Fd master)
-  slave <- openFd slaveName ReadWrite Nothing defaultFileFlags{noctty=True}
+  slave <- openFd slaveName ReadWrite defaultFileFlags{noctty=True}
   pushModule slave "ptem"
   pushModule slave "ldterm"
 # ifndef __hpux
@@ -183,6 +174,10 @@
 # endif /* __hpux */
   return (Fd master, slave)
 
+# ifndef HAVE_PTSNAME
+{-# WARNING openPseudoTerminal "openPseudoTerminal: not available on this platform (neither OPENPTY nor PTSNAME available)" #-}
+# endif  /* HAVE_PTSNAME */
+
 -- Push a STREAMS module, for System V systems.
 pushModule :: Fd -> String -> IO ()
 pushModule (Fd fd) name =
@@ -194,26 +189,16 @@
   c_push_module :: CInt -> CString -> IO CInt
 
 #ifdef HAVE_PTSNAME
-# if __GLASGOW_HASKELL__ < 800
--- see comment in cbits/HsUnix.c
-foreign import ccall unsafe "__hsunix_grantpt"
-  c_grantpt :: CInt -> IO CInt
-
-foreign import ccall unsafe "__hsunix_unlockpt"
-  c_unlockpt :: CInt -> IO CInt
-# else
 foreign import capi unsafe "HsUnix.h grantpt"
   c_grantpt :: CInt -> IO CInt
 
 foreign import capi unsafe "HsUnix.h unlockpt"
   c_unlockpt :: CInt -> IO CInt
-# endif
 #else
 c_grantpt :: CInt -> IO CInt
-c_grantpt _ = return (fromIntegral 0)
+c_grantpt _ = pure 0
 
 c_unlockpt :: CInt -> IO CInt
-c_unlockpt _ = return (fromIntegral 0)
+c_unlockpt _ = pure 0
 #endif /* HAVE_PTSNAME */
 #endif /* !HAVE_OPENPTY */
-
diff --git a/System/Posix/Terminal/ByteString.hsc b/System/Posix/Terminal/ByteString.hsc
--- a/System/Posix/Terminal/ByteString.hsc
+++ b/System/Posix/Terminal/ByteString.hsc
@@ -1,9 +1,5 @@
 {-# LANGUAGE CApiFFI #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Terminal.ByteString
@@ -92,7 +88,7 @@
 
 import System.Posix.ByteString.FilePath
 
-#if !HAVE_CTERMID
+#if !(HAVE_CTERMID && defined(HAVE_TERMIOS_H))
 import System.IO.Error ( ioeSetLocation )
 import GHC.IO.Exception ( unsupportedOperation )
 #endif
@@ -119,7 +115,7 @@
 -- provide @ctermid(3)@ (use @#if HAVE_CTERMID@ CPP guard to
 -- detect availability).
 getControllingTerminalName :: IO RawFilePath
-#if HAVE_CTERMID
+#if HAVE_CTERMID && defined(HAVE_TERMIOS_H)
 getControllingTerminalName = do
   s <- throwErrnoIfNull "getControllingTerminalName" (c_ctermid nullPtr)
   peekFilePath s
@@ -142,15 +138,10 @@
   s <- throwErrnoIfNull "getSlaveTerminalName" (c_ptsname fd)
   peekFilePath s
 
-# if __GLASGOW_HASKELL__ < 800
--- see comment in cbits/HsUnix.c
-foreign import ccall unsafe "__hsunix_ptsname"
-  c_ptsname :: CInt -> IO CString
-# else
 foreign import capi unsafe "HsUnix.h ptsname"
   c_ptsname :: CInt -> IO CString
-# endif
 #else
+{-# WARNING getSlaveTerminalName "getSlaveTerminalName: not available on this platform" #-}
 getSlaveTerminalName _ =
     ioError (errnoToIOError "getSlaveTerminalName" eNOSYS Nothing Nothing)
 #endif
@@ -178,12 +169,12 @@
             -> IO CInt
 #else
 openPseudoTerminal = do
-  (Fd master) <- openFd (B.pack "/dev/ptmx") ReadWrite Nothing
+  (Fd master) <- openFd (B.pack "/dev/ptmx") ReadWrite
                         defaultFileFlags{noctty=True}
   throwErrnoIfMinus1_ "openPseudoTerminal" (c_grantpt master)
   throwErrnoIfMinus1_ "openPseudoTerminal" (c_unlockpt master)
   slaveName <- getSlaveTerminalName (Fd master)
-  slave <- openFd slaveName ReadWrite Nothing defaultFileFlags{noctty=True}
+  slave <- openFd slaveName ReadWrite defaultFileFlags{noctty=True}
   pushModule slave "ptem"
   pushModule slave "ldterm"
 # ifndef __hpux
@@ -202,20 +193,11 @@
   c_push_module :: CInt -> CString -> IO CInt
 
 #if HAVE_PTSNAME
-# if __GLASGOW_HASKELL__ < 800
--- see comment in cbits/HsUnix.c
-foreign import ccall unsafe "__hsunix_grantpt"
-  c_grantpt :: CInt -> IO CInt
-
-foreign import ccall unsafe "__hsunix_unlockpt"
-  c_unlockpt :: CInt -> IO CInt
-# else
 foreign import capi unsafe "HsUnix.h grantpt"
   c_grantpt :: CInt -> IO CInt
 
 foreign import capi unsafe "HsUnix.h unlockpt"
   c_unlockpt :: CInt -> IO CInt
-# endif
 #else
 c_grantpt :: CInt -> IO CInt
 c_grantpt _ = return (fromIntegral (0::Int))
diff --git a/System/Posix/Terminal/Common.hsc b/System/Posix/Terminal/Common.hsc
--- a/System/Posix/Terminal/Common.hsc
+++ b/System/Posix/Terminal/Common.hsc
@@ -1,4 +1,6 @@
 {-# LANGUAGE CApiFFI #-}
+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
+{-# LANGUAGE PatternSynonyms #-}
 {-# LANGUAGE Trustworthy #-}
 
 -----------------------------------------------------------------------------
@@ -48,7 +50,82 @@
   minInput,
   withMinInput,
 
-  BaudRate(..),
+  BaudRate
+    ( ..
+    , B0
+    , B50
+    , B75
+    , B110
+    , B134
+    , B150
+    , B200
+    , B300
+    , B600
+    , B1200
+    , B1800
+    , B2400
+    , B4800
+    , B9600
+    , B19200
+    , B38400
+#ifdef B7200
+    , B7200
+#endif
+#ifdef B14400
+    , B14400
+#endif
+#ifdef B28800
+    , B28800
+#endif
+#ifdef B57600
+    , B57600
+#endif
+#ifdef B76800
+    , B76800
+#endif
+#ifdef B115200
+    , B115200
+#endif
+#ifdef B230400
+    , B230400
+#endif
+#ifdef B460800
+    , B460800
+#endif
+#ifdef B500000
+    , B500000
+#endif
+#ifdef B576000
+    , B576000
+#endif
+#ifdef B921600
+    , B921600
+#endif
+#ifdef B1000000
+    , B1000000
+#endif
+#ifdef B1152000
+    , B1152000
+#endif
+#ifdef B1500000
+    , B1500000
+#endif
+#ifdef B2000000
+    , B2000000
+#endif
+#ifdef B2500000
+    , B2500000
+#endif
+#ifdef B3000000
+    , B3000000
+#endif
+#ifdef B3500000
+    , B3500000
+#endif
+#ifdef B4000000
+    , B4000000
+#endif
+    ),
   inputSpeed,
   withInputSpeed,
   outputSpeed,
@@ -84,11 +161,14 @@
 import System.Posix.Types
 import System.Posix.Internals ( CTermios )
 
-#if !HAVE_TCDRAIN
+#if (!defined(HAVE_TCDRAIN)) || (!defined(HAVE_TERMIOS_H))
+import Control.Exception ( throw )
 import System.IO.Error ( ioeSetLocation )
 import GHC.IO.Exception ( unsupportedOperation )
 #endif
 
+#if defined(HAVE_TERMIOS_H)
+
 -- -----------------------------------------------------------------------------
 -- Terminal attributes
 
@@ -100,48 +180,98 @@
 withTerminalAttributes :: TerminalAttributes -> (Ptr CTermios -> IO a) -> IO a
 withTerminalAttributes (TerminalAttributes termios) = withForeignPtr termios
 
+#else
 
+data TerminalAttributes
+
+#endif // HAVE_TERMIOS_H
+
+
 data TerminalMode
         -- input flags
-   = InterruptOnBreak           -- BRKINT
-   | MapCRtoLF                  -- ICRNL
-   | IgnoreBreak                -- IGNBRK
-   | IgnoreCR                   -- IGNCR
-   | IgnoreParityErrors         -- IGNPAR
-   | MapLFtoCR                  -- INLCR
-   | CheckParity                -- INPCK
-   | StripHighBit               -- ISTRIP
-   | StartStopInput             -- IXOFF
-   | StartStopOutput            -- IXON
-   | MarkParityErrors           -- PARMRK
+   = InterruptOnBreak           -- ^ @BRKINT@ - Signal interrupt on break
+   | MapCRtoLF                  -- ^ @ICRNL@ - Map CR to NL on input
+   | IgnoreBreak                -- ^ @IGNBRK@ - Ignore break condition
+   | IgnoreCR                   -- ^ @IGNCR@ - Ignore CR
+   | IgnoreParityErrors         -- ^ @IGNPAR@ - Ignore characters with parity errors
+   | MapLFtoCR                  -- ^ @INLCR@ - Map NL to CR on input
+   | CheckParity                -- ^ @INPCK@ - Enable input parity check
+   | StripHighBit               -- ^ @ISTRIP@ - Strip character
+   | RestartOnAny               -- ^ @IXANY@ - Enable any character to restart output
+   | StartStopInput             -- ^ @IXOFF@ - Enable start/stop input control
+   | StartStopOutput            -- ^ @IXON@ - Enable start/stop output control
+   | MarkParityErrors           -- ^ @PARMRK@ - Mark parity errors
 
         -- output flags
-   | ProcessOutput              -- OPOST
-        -- ToDo: ONLCR, OCRNL, ONOCR, ONLRET, OFILL,
-        --       NLDLY(NL0,NL1), CRDLY(CR0,CR1,CR2,CR2)
-        --       TABDLY(TAB0,TAB1,TAB2,TAB3)
-        --       BSDLY(BS0,BS1), VTDLY(VT0,VT1), FFDLY(FF0,FF1)
+   | ProcessOutput              -- ^ @OPOST@ - Post-process output
+   | MapLFtoCRLF                -- ^ @ONLCR@ - (XSI) Map NL to CR-NL on output
+                                --
+                                -- @since 2.8.0.0
+   | OutputMapCRtoLF            -- ^ @OCRNL@ - (XSI) Map CR to NL on output
+                                --
+                                -- @since 2.8.0.0
+   | NoCRAtColumnZero           -- ^ @ONOCR@ - (XSI) No CR output at column 0
+                                --
+                                -- @since 2.8.0.0
+   | ReturnMeansLF              -- ^ @ONLRET@ - (XSI) NL performs CR function
+                                --
+                                -- @since 2.8.0.0
+   | TabDelayMask0              -- ^ @TABDLY(TAB0)@ - (XSI) Select horizontal-tab delays: type 0
+                                --
+                                -- @since 2.8.0.0
+   | TabDelayMask3              -- ^ @TABDLY(TAB3)@ - (XSI) Select horizontal-tab delays: type 3
+                                --
+                                -- @since 2.8.0.0
 
         -- control flags
-   | LocalMode                  -- CLOCAL
-   | ReadEnable                 -- CREAD
-   | TwoStopBits                -- CSTOPB
-   | HangupOnClose              -- HUPCL
-   | EnableParity               -- PARENB
-   | OddParity                  -- PARODD
+   | LocalMode                  -- ^ @CLOCAL@ - Ignore modem status lines
+   | ReadEnable                 -- ^ @CREAD@ - Enable receiver
+   | TwoStopBits                -- ^ @CSTOPB@ - Send two stop bits, else one
+   | HangupOnClose              -- ^ @HUPCL@ - Hang up on last close
+   | EnableParity               -- ^ @PARENB@ - Parity enable
+   | OddParity                  -- ^ @PARODD@ - Odd parity, else even
 
         -- local modes
-   | EnableEcho                 -- ECHO
-   | EchoErase                  -- ECHOE
-   | EchoKill                   -- ECHOK
-   | EchoLF                     -- ECHONL
-   | ProcessInput               -- ICANON
-   | ExtendedFunctions          -- IEXTEN
-   | KeyboardInterrupts         -- ISIG
-   | NoFlushOnInterrupt         -- NOFLSH
-   | BackgroundWriteInterrupt   -- TOSTOP
+   | EnableEcho                 -- ^ @ECHO@ - Enable echo
+   | EchoErase                  -- ^ @ECHOE@ - Echo erase character as error-correcting backspace
+   | EchoKill                   -- ^ @ECHOK@ - Echo KILL
+   | EchoLF                     -- ^ @ECHONL@ - Echo NL
+   | ProcessInput               -- ^ @ICANON@ - Canonical input (erase and kill processing)
+   | ExtendedFunctions          -- ^ @IEXTEN@ - Enable extended input character processing
+   | KeyboardInterrupts         -- ^ @ISIG@ - Enable signals
+   | NoFlushOnInterrupt         -- ^ @NOFLSH@ - Disable flush after interrupt or quit
+   | BackgroundWriteInterrupt   -- ^ @TOSTOP@ - Send @SIGTTOU@ for background output
 
+#if !defined(HAVE_TERMIOS_H)
+
 withoutMode :: TerminalAttributes -> TerminalMode -> TerminalAttributes
+{-# WARNING withoutMode
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withoutMode _ _ = throw (ioeSetLocation unsupportedOperation "withoutMode")
+
+withMode :: TerminalAttributes -> TerminalMode -> TerminalAttributes
+{-# WARNING withMode
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withMode _ _ = throw (ioeSetLocation unsupportedOperation "withMode")
+
+terminalMode :: TerminalMode -> TerminalAttributes -> Bool
+{-# WARNING terminalMode
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+terminalMode _ _ = throw (ioeSetLocation unsupportedOperation "terminalMode")
+
+bitsPerByte :: TerminalAttributes -> Int
+{-# WARNING bitsPerByte
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+bitsPerByte _ = throw (ioeSetLocation unsupportedOperation "bitsPerByte")
+
+withBits :: TerminalAttributes -> Int -> TerminalAttributes
+{-# WARNING withBits
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withBits _ _ = throw (ioeSetLocation unsupportedOperation "withBits")
+
+#else
+
+withoutMode :: TerminalAttributes -> TerminalMode -> TerminalAttributes
 withoutMode termios InterruptOnBreak = clearInputFlag (#const BRKINT) termios
 withoutMode termios MapCRtoLF = clearInputFlag (#const ICRNL) termios
 withoutMode termios IgnoreBreak = clearInputFlag (#const IGNBRK) termios
@@ -150,10 +280,17 @@
 withoutMode termios MapLFtoCR = clearInputFlag (#const INLCR) termios
 withoutMode termios CheckParity = clearInputFlag (#const INPCK) termios
 withoutMode termios StripHighBit = clearInputFlag (#const ISTRIP) termios
+withoutMode termios RestartOnAny = clearInputFlag (#const IXANY) termios
 withoutMode termios StartStopInput = clearInputFlag (#const IXOFF) termios
 withoutMode termios StartStopOutput = clearInputFlag (#const IXON) termios
 withoutMode termios MarkParityErrors = clearInputFlag (#const PARMRK) termios
 withoutMode termios ProcessOutput = clearOutputFlag (#const OPOST) termios
+withoutMode termios MapLFtoCRLF = clearOutputFlag (#const ONLCR) termios
+withoutMode termios OutputMapCRtoLF = clearOutputFlag (#const OCRNL) termios
+withoutMode termios NoCRAtColumnZero = clearOutputFlag (#const ONOCR) termios
+withoutMode termios ReturnMeansLF = clearOutputFlag (#const ONLRET) termios
+withoutMode termios TabDelayMask0 = clearOutputFlag (#const TAB0) termios
+withoutMode termios TabDelayMask3 = clearOutputFlag (#const TAB3) termios
 withoutMode termios LocalMode = clearControlFlag (#const CLOCAL) termios
 withoutMode termios ReadEnable = clearControlFlag (#const CREAD) termios
 withoutMode termios TwoStopBits = clearControlFlag (#const CSTOPB) termios
@@ -179,10 +316,17 @@
 withMode termios MapLFtoCR = setInputFlag (#const INLCR) termios
 withMode termios CheckParity = setInputFlag (#const INPCK) termios
 withMode termios StripHighBit = setInputFlag (#const ISTRIP) termios
+withMode termios RestartOnAny = setInputFlag (#const IXANY) termios
 withMode termios StartStopInput = setInputFlag (#const IXOFF) termios
 withMode termios StartStopOutput = setInputFlag (#const IXON) termios
 withMode termios MarkParityErrors = setInputFlag (#const PARMRK) termios
 withMode termios ProcessOutput = setOutputFlag (#const OPOST) termios
+withMode termios MapLFtoCRLF = setOutputFlag (#const ONLCR) termios
+withMode termios OutputMapCRtoLF = setOutputFlag (#const OCRNL) termios
+withMode termios NoCRAtColumnZero = setOutputFlag (#const ONOCR) termios
+withMode termios ReturnMeansLF = setOutputFlag (#const ONLRET) termios
+withMode termios TabDelayMask0 = setOutputFlag (#const TAB0) termios
+withMode termios TabDelayMask3 = setOutputFlag (#const TAB3) termios
 withMode termios LocalMode = setControlFlag (#const CLOCAL) termios
 withMode termios ReadEnable = setControlFlag (#const CREAD) termios
 withMode termios TwoStopBits = setControlFlag (#const CSTOPB) termios
@@ -208,10 +352,17 @@
 terminalMode MapLFtoCR = testInputFlag (#const INLCR)
 terminalMode CheckParity = testInputFlag (#const INPCK)
 terminalMode StripHighBit = testInputFlag (#const ISTRIP)
+terminalMode RestartOnAny = testInputFlag (#const IXANY)
 terminalMode StartStopInput = testInputFlag (#const IXOFF)
 terminalMode StartStopOutput = testInputFlag (#const IXON)
 terminalMode MarkParityErrors = testInputFlag (#const PARMRK)
 terminalMode ProcessOutput = testOutputFlag (#const OPOST)
+terminalMode MapLFtoCRLF = testOutputFlag (#const ONLCR)
+terminalMode OutputMapCRtoLF = testOutputFlag (#const OCRNL)
+terminalMode NoCRAtColumnZero = testOutputFlag (#const ONOCR)
+terminalMode ReturnMeansLF = testOutputFlag (#const ONLRET)
+terminalMode TabDelayMask0 = testOutputFlag (#const TAB0)
+terminalMode TabDelayMask3 = testOutputFlag (#const TAB3)
 terminalMode LocalMode = testControlFlag (#const CLOCAL)
 terminalMode ReadEnable = testControlFlag (#const CREAD)
 terminalMode TwoStopBits = testControlFlag (#const CSTOPB)
@@ -256,6 +407,8 @@
     mask 8 = (#const CS8)
     mask _ = error "withBits bit value out of range [5..8]"
 
+#endif // HAVE_TERMIOS_H
+
 data ControlCharacter
   = EndOfFile           -- VEOF
   | EndOfLine           -- VEOL
@@ -267,7 +420,102 @@
   | Stop                -- VSTOP
   | Suspend             -- VSUSP
 
+#if !defined(HAVE_TERMIOS_H)
+
 controlChar :: TerminalAttributes -> ControlCharacter -> Maybe Char
+{-# WARNING controlChar
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+controlChar _ _ = throw (ioeSetLocation unsupportedOperation "controlChar")
+
+withCC :: TerminalAttributes
+       -> (ControlCharacter, Char)
+       -> TerminalAttributes
+{-# WARNING withCC
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withCC _ _ = throw (ioeSetLocation unsupportedOperation "withCC")
+
+withoutCC :: TerminalAttributes
+          -> ControlCharacter
+          -> TerminalAttributes
+{-# WARNING withoutCC
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withoutCC _ _ = throw (ioeSetLocation unsupportedOperation "withoutCC")
+
+inputTime :: TerminalAttributes -> Int
+{-# WARNING inputTime
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+inputTime _ = throw (ioeSetLocation unsupportedOperation "inputTime")
+
+withTime :: TerminalAttributes -> Int -> TerminalAttributes
+{-# WARNING withTime
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withTime _ _ = throw (ioeSetLocation unsupportedOperation "withTime")
+
+minInput :: TerminalAttributes -> Int
+{-# WARNING minInput
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+minInput _ = throw (ioeSetLocation unsupportedOperation "minInput")
+
+withMinInput :: TerminalAttributes -> Int -> TerminalAttributes
+{-# WARNING withMinInput
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withMinInput _ _ = throw (ioeSetLocation unsupportedOperation "withMinInput")
+
+-- | Placeholder implementation
+newtype BaudRate = BaudRate Int deriving (Eq, Ord, Show, Enum, Real, Num)
+
+-- | Hang up
+pattern B0 :: BaudRate
+pattern B0 = BaudRate 0
+-- | 50 baud
+pattern B50 :: BaudRate
+pattern B50 = BaudRate 50
+-- | 75 baud
+pattern B75 :: BaudRate
+pattern B75 = BaudRate 75
+-- | 110 baud
+pattern B110 :: BaudRate
+pattern B110 = BaudRate 110
+-- | 134.5 baud
+pattern B134 :: BaudRate
+pattern B134 = BaudRate 134
+-- | 150 baud
+pattern B150 :: BaudRate
+pattern B150 = BaudRate 150
+-- | 200 baud
+pattern B200 :: BaudRate
+pattern B200 = BaudRate 200
+-- | 300 baud
+pattern B300 :: BaudRate
+pattern B300 = BaudRate 300
+-- | 600 baud
+pattern B600 :: BaudRate
+pattern B600 = BaudRate 600
+-- | 1200 baud
+pattern B1200 :: BaudRate
+pattern B1200 = BaudRate 1200
+-- | 1800 baud
+pattern B1800 :: BaudRate
+pattern B1800 = BaudRate 1800
+-- | 2400 baud
+pattern B2400 :: BaudRate
+pattern B2400 = BaudRate 2400
+-- | 4800 baud
+pattern B4800 :: BaudRate
+pattern B4800 = BaudRate 4800
+-- | 9600 baud
+pattern B9600 :: BaudRate
+pattern B9600 = BaudRate 9600
+-- | 19200 baud
+pattern B19200 :: BaudRate
+pattern B19200 = BaudRate 19200
+-- | 38400 baud
+pattern B38400 :: BaudRate
+pattern B38400 = BaudRate 38400
+
+#else
+
+controlChar :: TerminalAttributes -> ControlCharacter -> Maybe Char
 controlChar termios cc = unsafePerformIO $ do
   withTerminalAttributes termios $ \p -> do
     let c_cc = (#ptr struct termios, c_cc) p
@@ -316,39 +564,209 @@
     let c_cc = (#ptr struct termios, c_cc) p
     pokeElemOff c_cc (#const VMIN) (fromIntegral count :: CCc)
 
-data BaudRate
-  = B0
-  | B50
-  | B75
-  | B110
-  | B134
-  | B150
-  | B200
-  | B300
-  | B600
-  | B1200
-  | B1800
-  | B2400
-  | B4800
-  | B9600
-  | B19200
-  | B38400
-  | B57600
-  | B115200
-  deriving (Eq, Show)
+-- | Serial line baudrate.  The set of supported speeds is system-dependent.
+-- Portable use of the provided pattern synonyms that are outside the list
+-- mandated by POSIX requires @#ifdef@ guards.
+--
+-- Applications may need to be prepared to encounter speeds not known at
+-- compile time, these can be handled generically via the 'BaudRate'
+-- constructor.  In other words, the provided pattern synonyms are not
+-- necessarily a @COMPLETE@ set.
+--
+-- All non-zero /pseudo-terminal/ baud rates are functionally equivalent, and
+-- the @pty@ driver may accept any speed within a suitable range.  Requested
+-- speeds may be rounded up or down to fit into the supported range.
+--
+newtype BaudRate = BaudRate CSpeed deriving (Eq, Ord, Show, Enum, Real, Num)
 
+-- | Hang up
+pattern B0 :: BaudRate
+pattern B0 = BaudRate (#const B0)
+-- | 50 baud
+pattern B50 :: BaudRate
+pattern B50 = BaudRate (#const B50)
+-- | 75 baud
+pattern B75 :: BaudRate
+pattern B75 = BaudRate (#const B75)
+-- | 110 baud
+pattern B110 :: BaudRate
+pattern B110 = BaudRate (#const B110)
+-- | 134.5 baud
+pattern B134 :: BaudRate
+pattern B134 = BaudRate (#const B134)
+-- | 150 baud
+pattern B150 :: BaudRate
+pattern B150 = BaudRate (#const B150)
+-- | 200 baud
+pattern B200 :: BaudRate
+pattern B200 = BaudRate (#const B200)
+-- | 300 baud
+pattern B300 :: BaudRate
+pattern B300 = BaudRate (#const B300)
+-- | 600 baud
+pattern B600 :: BaudRate
+pattern B600 = BaudRate (#const B600)
+-- | 1200 baud
+pattern B1200 :: BaudRate
+pattern B1200 = BaudRate (#const B1200)
+-- | 1800 baud
+pattern B1800 :: BaudRate
+pattern B1800 = BaudRate (#const B1800)
+-- | 2400 baud
+pattern B2400 :: BaudRate
+pattern B2400 = BaudRate (#const B2400)
+-- | 4800 baud
+pattern B4800 :: BaudRate
+pattern B4800 = BaudRate (#const B4800)
+-- | 9600 baud
+pattern B9600 :: BaudRate
+pattern B9600 = BaudRate (#const B9600)
+-- | 19200 baud
+pattern B19200 :: BaudRate
+pattern B19200 = BaudRate (#const B19200)
+-- | 38400 baud
+pattern B38400 :: BaudRate
+pattern B38400 = BaudRate (#const B38400)
+
+#ifdef B7200
+-- | 7200 baud, non-POSIX system-dependent extension
+pattern B7200 :: BaudRate
+pattern B7200 = BaudRate (#const B7200)
+#endif
+#ifdef B14400
+-- | 14400 baud, non-POSIX system-dependent extension
+pattern B14400 :: BaudRate
+pattern B14400 = BaudRate (#const B14400)
+#endif
+#ifdef B28800
+-- | 28800 baud, non-POSIX system-dependent extension
+pattern B28800 :: BaudRate
+pattern B28800 = BaudRate (#const B28800)
+#endif
+#ifdef B57600
+-- | 57600 baud, non-POSIX system-dependent extension
+pattern B57600 :: BaudRate
+pattern B57600 = BaudRate (#const B57600)
+#endif
+#ifdef B76800
+-- | 76800 baud, non-POSIX system-dependent extension
+pattern B76800 :: BaudRate
+pattern B76800 = BaudRate (#const B76800)
+#endif
+#ifdef B115200
+-- | 115200 baud, non-POSIX system-dependent extension
+pattern B115200 :: BaudRate
+pattern B115200 = BaudRate (#const B115200)
+#endif
+#ifdef B230400
+-- | 230400 baud, non-POSIX system-dependent extension
+pattern B230400 :: BaudRate
+pattern B230400 = BaudRate (#const B230400)
+#endif
+#ifdef B460800
+-- | 460800 baud, non-POSIX system-dependent extension
+pattern B460800 :: BaudRate
+pattern B460800 = BaudRate (#const B460800)
+#endif
+#ifdef B500000
+-- | 500000 baud, non-POSIX system-dependent extension
+pattern B500000 :: BaudRate
+pattern B500000 = BaudRate (#const B500000)
+#endif
+#ifdef B576000
+-- | 576000 baud, non-POSIX system-dependent extension
+pattern B576000 :: BaudRate
+pattern B576000 = BaudRate (#const B576000)
+#endif
+#ifdef B921600
+-- | 921600 baud, non-POSIX system-dependent extension
+pattern B921600 :: BaudRate
+pattern B921600 = BaudRate (#const B921600)
+#endif
+#ifdef B1000000
+-- | 1000000 baud, non-POSIX system-dependent extension
+pattern B1000000 :: BaudRate
+pattern B1000000 = BaudRate (#const B1000000)
+#endif
+#ifdef B1152000
+-- | 1152000 baud, non-POSIX system-dependent extension
+pattern B1152000 :: BaudRate
+pattern B1152000 = BaudRate (#const B1152000)
+#endif
+#ifdef B1500000
+-- | 1500000 baud, non-POSIX system-dependent extension
+pattern B1500000 :: BaudRate
+pattern B1500000 = BaudRate (#const B1500000)
+#endif
+#ifdef B2000000
+-- | 2000000 baud, non-POSIX system-dependent extension
+pattern B2000000 :: BaudRate
+pattern B2000000 = BaudRate (#const B2000000)
+#endif
+#ifdef B2500000
+-- | 2500000 baud, non-POSIX system-dependent extension
+pattern B2500000 :: BaudRate
+pattern B2500000 = BaudRate (#const B2500000)
+#endif
+#ifdef B3000000
+-- | 3000000 baud, non-POSIX system-dependent extension
+pattern B3000000 :: BaudRate
+pattern B3000000 = BaudRate (#const B3000000)
+#endif
+#ifdef B3500000
+-- | 3500000 baud, non-POSIX system-dependent extension
+pattern B3500000 :: BaudRate
+pattern B3500000 = BaudRate (#const B3500000)
+#endif
+#ifdef B4000000
+-- | 4000000 baud, non-POSIX system-dependent extension
+pattern B4000000 :: BaudRate
+pattern B4000000 = BaudRate (#const B4000000)
+#endif
+
+#endif // HAVE_TERMIOS_H
+
+#if !defined(HAVE_TERMIOS_H)
+
 inputSpeed :: TerminalAttributes -> BaudRate
+{-# WARNING inputSpeed
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+inputSpeed _ = throw (ioeSetLocation unsupportedOperation "inputSpeed")
+
+withInputSpeed :: TerminalAttributes -> BaudRate -> TerminalAttributes
+{-# WARNING withInputSpeed
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withInputSpeed _ _ = throw (ioeSetLocation unsupportedOperation "withInputSpeed")
+
+outputSpeed :: TerminalAttributes -> BaudRate
+{-# WARNING outputSpeed
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+outputSpeed _ = throw (ioeSetLocation unsupportedOperation "outputSpeed")
+
+withOutputSpeed :: TerminalAttributes -> BaudRate -> TerminalAttributes
+{-# WARNING withOutputSpeed
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+withOutputSpeed _ _ = throw (ioeSetLocation unsupportedOperation "withOutputSpeed")
+
+getTerminalAttributes :: Fd -> IO TerminalAttributes
+{-# WARNING getTerminalAttributes
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+getTerminalAttributes _ = ioError (ioeSetLocation unsupportedOperation "getTerminalAttributes")
+
+#else
+
+inputSpeed :: TerminalAttributes -> BaudRate
 inputSpeed termios = unsafePerformIO $ do
   withTerminalAttributes termios $ \p -> do
     w <- c_cfgetispeed p
-    return (word2Baud w)
+    return (BaudRate w)
 
 foreign import capi unsafe "termios.h cfgetispeed"
   c_cfgetispeed :: Ptr CTermios -> IO CSpeed
 
 withInputSpeed :: TerminalAttributes -> BaudRate -> TerminalAttributes
-withInputSpeed termios br = unsafePerformIO $ do
-  withNewTermios termios $ \p -> c_cfsetispeed p (baud2Word br)
+withInputSpeed termios (BaudRate br) = unsafePerformIO $ do
+  withNewTermios termios $ \p -> c_cfsetispeed p br
 
 foreign import capi unsafe "termios.h cfsetispeed"
   c_cfsetispeed :: Ptr CTermios -> CSpeed -> IO CInt
@@ -358,14 +776,14 @@
 outputSpeed termios = unsafePerformIO $ do
   withTerminalAttributes termios $ \p ->  do
     w <- c_cfgetospeed p
-    return (word2Baud w)
+    return (BaudRate w)
 
 foreign import capi unsafe "termios.h cfgetospeed"
   c_cfgetospeed :: Ptr CTermios -> IO CSpeed
 
 withOutputSpeed :: TerminalAttributes -> BaudRate -> TerminalAttributes
-withOutputSpeed termios br = unsafePerformIO $ do
-  withNewTermios termios $ \p -> c_cfsetospeed p (baud2Word br)
+withOutputSpeed termios (BaudRate br) = unsafePerformIO $ do
+  withNewTermios termios $ \p -> c_cfsetospeed p br
 
 foreign import capi unsafe "termios.h cfsetospeed"
   c_cfsetospeed :: Ptr CTermios -> CSpeed -> IO CInt
@@ -382,11 +800,35 @@
 foreign import capi unsafe "termios.h tcgetattr"
   c_tcgetattr :: CInt -> Ptr CTermios -> IO CInt
 
+#endif // HAVE_TERMIOS_H
+
 data TerminalState
   = Immediately
   | WhenDrained
   | WhenFlushed
 
+#if !defined(HAVE_TERMIOS_H)
+
+setTerminalAttributes :: Fd
+                      -> TerminalAttributes
+                      -> TerminalState
+                      -> IO ()
+{-# WARNING setTerminalAttributes
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+setTerminalAttributes _ _ _ = ioError (ioeSetLocation unsupportedOperation "setTerminalAttributes")
+
+sendBreak :: Fd -> Int -> IO ()
+{-# WARNING sendBreak
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+sendBreak _ _ = ioError (ioeSetLocation unsupportedOperation "sendBreak")
+
+drainOutput :: Fd -> IO ()
+{-# WARNING drainOutput
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+drainOutput _ = ioError (ioeSetLocation unsupportedOperation "drainOutput")
+
+#else
+
 -- | @setTerminalAttributes fd attr ts@ calls @tcsetattr@ to change
 --   the @TerminalAttributes@ associated with @Fd@ @fd@ to
 --   @attr@, when the terminal is in the state indicated by @ts@.
@@ -435,11 +877,22 @@
 drainOutput _ = ioError (ioeSetLocation unsupportedOperation "drainOutput")
 #endif
 
+#endif // HAVE_TERMIOS_H
+
 data QueueSelector
   = InputQueue          -- TCIFLUSH
   | OutputQueue         -- TCOFLUSH
   | BothQueues          -- TCIOFLUSH
 
+#if !defined(HAVE_TERMIOS_H)
+
+discardData :: Fd -> QueueSelector -> IO ()
+{-# WARNING discardData
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+discardData _ _ = ioError (ioeSetLocation unsupportedOperation "discardData")
+
+#else
+
 -- | @discardData fd queues@ calls @tcflush@ to discard
 --   pending input and\/or output for @Fd@ @fd@,
 --   as indicated by the @QueueSelector@ @queues@.
@@ -455,12 +908,33 @@
 foreign import capi unsafe "termios.h tcflush"
   c_tcflush :: CInt -> CInt -> IO CInt
 
+#endif // HAVE_TERMIOS_H
+
 data FlowAction
   = SuspendOutput       -- ^ TCOOFF
   | RestartOutput       -- ^ TCOON
   | TransmitStop        -- ^ TCIOFF
   | TransmitStart       -- ^ TCION
 
+#if !defined(HAVE_TERMIOS_H)
+
+controlFlow :: Fd -> FlowAction -> IO ()
+{-# WARNING controlFlow
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+controlFlow _ _ = ioError (ioeSetLocation unsupportedOperation "controlFlow")
+
+getTerminalProcessGroupID :: Fd -> IO ProcessGroupID
+{-# WARNING getTerminalProcessGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+getTerminalProcessGroupID _ = ioError (ioeSetLocation unsupportedOperation "getTerminalProcessGroupID")
+
+setTerminalProcessGroupID :: Fd -> ProcessGroupID -> IO ()
+{-# WARNING setTerminalProcessGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TERMIOS_H@)" #-}
+setTerminalProcessGroupID _ _ = ioError (ioeSetLocation unsupportedOperation "setTerminalProcessGroupID")
+
+#else
+
 -- | @controlFlow fd action@ calls @tcflow@ to control the
 --   flow of data on @Fd@ @fd@, as indicated by
 --   @action@.
@@ -498,6 +972,8 @@
 foreign import ccall unsafe "tcsetpgrp"
   c_tcsetpgrp :: CInt -> CPid -> IO CInt
 
+#endif // HAVE_TERMIOS_H
+
 -- -----------------------------------------------------------------------------
 -- file descriptor queries
 
@@ -517,6 +993,8 @@
 
 -- Convert Haskell ControlCharacter to Int
 
+#if defined(HAVE_TERMIOS_H)
+
 cc2Word :: ControlCharacter -> Int
 cc2Word EndOfFile = (#const VEOF)
 cc2Word EndOfLine = (#const VEOL)
@@ -528,65 +1006,6 @@
 cc2Word Start     = (#const VSTART)
 cc2Word Stop      = (#const VSTOP)
 
--- Convert Haskell BaudRate to unsigned integral type (Word)
-
-baud2Word :: BaudRate -> CSpeed
-baud2Word B0 = (#const B0)
-baud2Word B50 = (#const B50)
-baud2Word B75 = (#const B75)
-baud2Word B110 = (#const B110)
-baud2Word B134 = (#const B134)
-baud2Word B150 = (#const B150)
-baud2Word B200 = (#const B200)
-baud2Word B300 = (#const B300)
-baud2Word B600 = (#const B600)
-baud2Word B1200 = (#const B1200)
-baud2Word B1800 = (#const B1800)
-baud2Word B2400 = (#const B2400)
-baud2Word B4800 = (#const B4800)
-baud2Word B9600 = (#const B9600)
-baud2Word B19200 = (#const B19200)
-baud2Word B38400 = (#const B38400)
-#ifdef B57600
-baud2Word B57600 = (#const B57600)
-#else
-baud2Word B57600 = error "B57600 not available on this system"
-#endif
-#ifdef B115200
-baud2Word B115200 = (#const B115200)
-#else
-baud2Word B115200 = error "B115200 not available on this system"
-#endif
-
--- And convert a word back to a baud rate
--- We really need some cpp macros here.
-
-word2Baud :: CSpeed -> BaudRate
-word2Baud x =
-    if x == (#const B0) then B0
-    else if x == (#const B50) then B50
-    else if x == (#const B75) then B75
-    else if x == (#const B110) then B110
-    else if x == (#const B134) then B134
-    else if x == (#const B150) then B150
-    else if x == (#const B200) then B200
-    else if x == (#const B300) then B300
-    else if x == (#const B600) then B600
-    else if x == (#const B1200) then B1200
-    else if x == (#const B1800) then B1800
-    else if x == (#const B2400) then B2400
-    else if x == (#const B4800) then B4800
-    else if x == (#const B9600) then B9600
-    else if x == (#const B19200) then B19200
-    else if x == (#const B38400) then B38400
-#ifdef B57600
-    else if x == (#const B57600) then B57600
-#endif
-#ifdef B115200
-    else if x == (#const B115200) then B115200
-#endif
-    else error "unknown baud rate"
-
 -- Clear termios i_flag
 
 clearInputFlag :: CTcflag -> TerminalAttributes -> TerminalAttributes
@@ -725,3 +1144,5 @@
     _ <- action p1
     return ()
   return $ makeTerminalAttributes fp1
+
+#endif // HAVE_TERMIOS_H
diff --git a/System/Posix/Terminal/PosixString.hsc b/System/Posix/Terminal/PosixString.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/Terminal/PosixString.hsc
@@ -0,0 +1,211 @@
+{-# LANGUAGE CApiFFI #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.Terminal.PosixString
+-- 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 Terminal support
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.Terminal.PosixString (
+  -- * Terminal support
+
+  -- ** Terminal attributes
+  TerminalAttributes,
+  getTerminalAttributes,
+  TerminalState(..),
+  setTerminalAttributes,
+
+  TerminalMode(..),
+  withoutMode,
+  withMode,
+  terminalMode,
+  bitsPerByte,
+  withBits,
+
+  ControlCharacter(..),
+  controlChar,
+  withCC,
+  withoutCC,
+
+  inputTime,
+  withTime,
+  minInput,
+  withMinInput,
+
+  BaudRate(..),
+  inputSpeed,
+  withInputSpeed,
+  outputSpeed,
+  withOutputSpeed,
+
+  -- ** Terminal operations
+  sendBreak,
+  drainOutput,
+  QueueSelector(..),
+  discardData,
+  FlowAction(..),
+  controlFlow,
+
+  -- ** Process groups
+  getTerminalProcessGroupID,
+  setTerminalProcessGroupID,
+
+  -- ** Testing a file descriptor
+  queryTerminal,
+  getTerminalName,
+  getControllingTerminalName,
+
+  -- ** Pseudoterminal operations
+  openPseudoTerminal,
+  getSlaveTerminalName
+  ) where
+
+#include "HsUnix.h"
+
+import Foreign
+import System.Posix.Types
+import System.Posix.Terminal.Common
+#ifndef HAVE_OPENPTY
+import qualified System.OsPath.Data.ByteString.Short as SBS
+import System.Posix.IO.ByteString (defaultFileFlags, openFd, noctty, OpenMode(ReadWrite))
+import Data.ByteString.Char8 as B ( pack, )
+import qualified System.OsPath.Data.ByteString.Short as BC
+import System.OsString.Internal.Types (PosixString(..))
+#endif
+
+import Foreign.C hiding (
+     throwErrnoPath,
+     throwErrnoPathIf,
+     throwErrnoPathIf_,
+     throwErrnoPathIfNull,
+     throwErrnoPathIfMinus1,
+     throwErrnoPathIfMinus1_ )
+
+import System.OsPath.Types
+import System.Posix.PosixPath.FilePath
+
+#if !(HAVE_CTERMID && defined(HAVE_TERMIOS_H))
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
+-- | @getTerminalName fd@ calls @ttyname@ to obtain a name associated
+--   with the terminal for @Fd@ @fd@. If @fd@ is associated
+--   with a terminal, @getTerminalName@ returns the name of the
+--   terminal.
+getTerminalName :: Fd -> IO PosixPath
+getTerminalName (Fd fd) = do
+  s <- throwErrnoIfNull "getTerminalName" (c_ttyname fd)
+  peekFilePath s
+
+foreign import ccall unsafe "ttyname"
+  c_ttyname :: CInt -> IO CString
+
+-- | @getControllingTerminalName@ calls @ctermid@ to obtain
+--   a name associated with the controlling terminal for the process.  If a
+--   controlling terminal exists,
+--   @getControllingTerminalName@ returns the name of the
+--   controlling terminal.
+--
+-- Throws 'IOError' (\"unsupported operation\") if platform does not
+-- provide @ctermid(3)@ (use @#if HAVE_CTERMID@ CPP guard to
+-- detect availability).
+getControllingTerminalName :: IO PosixPath
+#if HAVE_CTERMID && defined(HAVE_TERMIOS_H)
+getControllingTerminalName = do
+  s <- throwErrnoIfNull "getControllingTerminalName" (c_ctermid nullPtr)
+  peekFilePath s
+
+foreign import capi unsafe "termios.h ctermid"
+  c_ctermid :: CString -> IO CString
+#else
+{-# WARNING getControllingTerminalName
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_CTERMID@)" #-}
+getControllingTerminalName = ioError (ioeSetLocation unsupportedOperation "getControllingTerminalName")
+#endif
+
+-- | @getSlaveTerminalName@ calls @ptsname@ to obtain the name of the
+-- slave terminal associated with a pseudoterminal pair.  The file
+-- descriptor to pass in must be that of the master.
+getSlaveTerminalName :: Fd -> IO PosixPath
+
+#ifdef HAVE_PTSNAME
+getSlaveTerminalName (Fd fd) = do
+  s <- throwErrnoIfNull "getSlaveTerminalName" (c_ptsname fd)
+  peekFilePath s
+
+foreign import capi unsafe "HsUnix.h ptsname"
+  c_ptsname :: CInt -> IO CString
+#else
+{-# WARNING getSlaveTerminalName "getSlaveTerminalName: not available on this platform" #-}
+getSlaveTerminalName _ =
+    ioError (errnoToIOError "getSlaveTerminalName" eNOSYS Nothing Nothing)
+#endif
+
+-- -----------------------------------------------------------------------------
+-- openPseudoTerminal needs to be here because it depends on
+-- getSlaveTerminalName.
+
+-- | @openPseudoTerminal@ creates a pseudoterminal (pty) pair, and
+-- returns the newly created pair as a (@master@, @slave@) tuple.
+openPseudoTerminal :: IO (Fd, Fd)
+
+#ifdef HAVE_OPENPTY
+openPseudoTerminal =
+  alloca $ \p_master ->
+    alloca $ \p_slave -> do
+      throwErrnoIfMinus1_ "openPty"
+          (c_openpty p_master p_slave nullPtr nullPtr nullPtr)
+      master <- peek p_master
+      slave <- peek p_slave
+      return (Fd master, Fd slave)
+
+foreign import ccall unsafe "openpty"
+  c_openpty :: Ptr CInt -> Ptr CInt -> CString -> Ptr CTermios -> Ptr a
+            -> IO CInt
+#else
+openPseudoTerminal = do
+  (Fd master) <- openFd (B.pack "/dev/ptmx") ReadWrite
+                        defaultFileFlags{noctty=True}
+  throwErrnoIfMinus1_ "openPseudoTerminal" (c_grantpt master)
+  throwErrnoIfMinus1_ "openPseudoTerminal" (c_unlockpt master)
+  slaveName <- getSlaveTerminalName (Fd master)
+  slave <- openFd (SBS.fromShort . getPosixString $ slaveName) ReadWrite defaultFileFlags{noctty=True}
+  pushModule slave "ptem"
+  pushModule slave "ldterm"
+# ifndef __hpux
+  pushModule slave "ttcompat"
+# endif /* __hpux */
+  return (Fd master, slave)
+
+-- Push a STREAMS module, for System V systems.
+pushModule :: Fd -> String -> IO ()
+pushModule (Fd fd) name =
+  withCString name $ \p_name ->
+    throwErrnoIfMinus1_ "openPseudoTerminal"
+                        (c_push_module fd p_name)
+
+foreign import ccall unsafe "__hsunix_push_module"
+  c_push_module :: CInt -> CString -> IO CInt
+
+#if HAVE_PTSNAME
+foreign import capi unsafe "HsUnix.h grantpt"
+  c_grantpt :: CInt -> IO CInt
+
+foreign import capi unsafe "HsUnix.h unlockpt"
+  c_unlockpt :: CInt -> IO CInt
+#else
+c_grantpt :: CInt -> IO CInt
+c_grantpt _ = return (fromIntegral (0::Int))
+
+c_unlockpt :: CInt -> IO CInt
+c_unlockpt _ = return (fromIntegral (0::Int))
+#endif /* HAVE_PTSNAME */
+#endif /* !HAVE_OPENPTY */
diff --git a/System/Posix/Time.hs b/System/Posix/Time.hs
--- a/System/Posix/Time.hs
+++ b/System/Posix/Time.hs
@@ -1,10 +1,5 @@
 {-# LANGUAGE CApiFFI #-}
-{-# LANGUAGE CPP #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Time
diff --git a/System/Posix/Unistd.hsc b/System/Posix/Unistd.hsc
--- a/System/Posix/Unistd.hsc
+++ b/System/Posix/Unistd.hsc
@@ -1,10 +1,6 @@
 {-# LANGUAGE CApiFFI #-}
 {-# LANGUAGE NondecreasingIndentation #-}
-#if __GLASGOW_HASKELL__ >= 709
 {-# LANGUAGE Safe #-}
-#else
-{-# LANGUAGE Trustworthy #-}
-#endif
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.Unistd
@@ -156,6 +152,7 @@
 -- /GHC Note/: the comment for 'usleep' also applies here.
 nanosleep :: Integer -> IO ()
 #ifndef HAVE_NANOSLEEP
+{-# WARNING nanosleep "nanosleep: not available on this platform" #-}
 nanosleep = error "nanosleep: not available on this platform"
 #else
 nanosleep 0 = return ()
diff --git a/System/Posix/User.hsc b/System/Posix/User.hsc
--- a/System/Posix/User.hsc
+++ b/System/Posix/User.hsc
@@ -1,4 +1,4 @@
-{-# LANGUAGE Trustworthy, CApiFFI #-}
+{-# LANGUAGE Trustworthy, CApiFFI, PatternSynonyms, ViewPatterns #-}
 -----------------------------------------------------------------------------
 -- |
 -- Module      :  System.Posix.User
@@ -25,13 +25,25 @@
     getEffectiveUserName,
 
     -- *** The group database
-    GroupEntry(..),
+    groupName,
+    groupPassword,
+    groupID,
+    groupMembers,
+    pattern GroupEntry,
     getGroupEntryForID,
     getGroupEntryForName,
     getAllGroupEntries,
 
     -- *** The user database
-    UserEntry(..),
+    userName,
+    userPassword,
+    userID,
+    userGroupID,
+    userGecos,
+    homeDirectory,
+    userShell,
+    pattern UserEntry,
+
     getUserEntryForID,
     getUserEntryForName,
     getAllUserEntries,
@@ -53,23 +65,203 @@
 import Foreign.Ptr
 import Foreign.Marshal
 import Foreign.Storable
+import System.Posix.User.Common ( UserEntry, GroupEntry
+#if defined(HAVE_PWD_H)
+      , unpackUserEntry, unpackGroupEntry, LKUPTYPE(..), CPasswd, CGroup
+#endif
+  )
+import qualified System.Posix.User.Common as User
 
-#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
-import Control.Concurrent.MVar  ( MVar, newMVar, withMVar )
+#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
+#if defined(freebsd_HOST_OS)
+import Control.Concurrent (runInBoundThread, rtsSupportsBoundThreads)
 #endif
-#ifdef HAVE_GETPWENT
+import Control.Concurrent.MVar ( MVar, newMVar, withMVar )
 import Control.Exception
 #endif
 import Control.Monad
 import System.IO.Error
+import qualified Data.ByteString.Char8 as C8
 
--- internal types
-data {-# CTYPE "struct passwd" #-} CPasswd
-data {-# CTYPE "struct group"  #-} CGroup
+#if !defined(HAVE_PWD_H)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
 
+
+#if !defined(HAVE_PWD_H)
+
+getRealUserID :: IO UserID
+{-# WARNING getRealUserID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getRealUserID = ioError (ioeSetLocation unsupportedOperation "getRealUserID")
+
+getRealGroupID :: IO GroupID
+{-# WARNING getRealGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getRealGroupID = ioError (ioeSetLocation unsupportedOperation "getRealGroupID")
+
+getEffectiveUserID :: IO UserID
+{-# WARNING getEffectiveUserID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getEffectiveUserID = ioError (ioeSetLocation unsupportedOperation "getEffectiveUserID")
+
+getEffectiveGroupID :: IO GroupID
+{-# WARNING getEffectiveGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getEffectiveGroupID = ioError (ioeSetLocation unsupportedOperation "getEffectiveGroupID")
+
+getGroups :: IO [GroupID]
+{-# WARNING getGroups
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getGroups = ioError (ioeSetLocation unsupportedOperation "getGroups")
+
+setGroups :: [GroupID] -> IO ()
+{-# WARNING setGroups
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setGroups _ = ioError (ioeSetLocation unsupportedOperation "setGroups")
+
+getLoginName :: IO String
+{-# WARNING getLoginName
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getLoginName = ioError (ioeSetLocation unsupportedOperation "getLoginName")
+
+setUserID :: UserID -> IO ()
+{-# WARNING setUserID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setUserID _ = ioError (ioeSetLocation unsupportedOperation "setUserID")
+
+setEffectiveUserID :: UserID -> IO ()
+{-# WARNING setEffectiveUserID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setEffectiveUserID _ = ioError (ioeSetLocation unsupportedOperation "setEffectiveUserID")
+
+setGroupID :: GroupID -> IO ()
+{-# WARNING setGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setGroupID _ = ioError (ioeSetLocation unsupportedOperation "setGroupID")
+
+setEffectiveGroupID :: GroupID -> IO ()
+{-# WARNING setEffectiveGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setEffectiveGroupID _ = ioError (ioeSetLocation unsupportedOperation "setEffectiveGroupID")
+
+getEffectiveUserName :: IO String
+{-# WARNING getEffectiveUserName
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getEffectiveUserName = ioError (ioeSetLocation unsupportedOperation "getEffectiveUserName")
+
+#else
 -- -----------------------------------------------------------------------------
--- user environemnt
+-- Thread safety of passwd/group database access APIs:
+--
+-- All supported unix platforms have @get(pw|gr)(nam|[ug]id)_r(3)@, which
+-- store the result in a caller provided buffer, which solves the most
+-- immediate thread-safety issues.
+--
+-- Things are more complicated for getpwent(3) and getgrent(3).
+--
+-- * On Linux systems, these read a global open file, opened via
+--   setpwent(3) and closed via endpwent(3).  Only one thread at
+--   a time can safely iterate through the file.
+--
+-- * On macOS (through Catalina 10.15), there is no getpwent_r(3) or
+--   getgrent_r(3), so a lock is also required for safe buffer sharing.
+--
+-- * On FreeBSD, in the default configuration with passwd lookups configured
+--   in nsswitch.conf to use "compat" rather than "files", the getpwnam_r(3)
+--   and getpwuid_r(3) functions reset the iterator index used by getpwent(3).
+--   A bug [report](https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=252094)
+--   has been filed to track this long-standing issue.  A similar issue affects
+--   getgrent(3), this time regardless of the nsswitch.conf setting.  This too
+--   should be fixed at some point in the future.  The state in question is
+--   thread-specific, so both issues only affect overlapping use of the @*ent@
+--   and @*(nam|[ug]id)_r(3)@ functions in the /same/ thread.
+--
+-- * Despite rather similar manpages for getpwent(3) and getpwnam(3), ... as
+--   on FreeBSD, the above issue is not seen on NetBSD or macOS.
+--
+--   This is not an issue with 1-to-1 thread models, where the code executing
+--   @get(pw|gr)ent@ has exclusive use of its thread, but it is a real issue
+--   for Haskell with its many-to-1 green threads, because multiple `forkIO`
+--   threads may take turns using the same underlying OS thread, breaking the
+--   thread-safety of the @*_r@ functions, which mutate the file-offset of the
+--   open file shared with any overlapping execution of @*ent(3)@ in the same
+--   thread.
+--
+-- Consequently, correct portable support for @get(pw|gr)ent(3)@ is rather
+-- non-trivial.  In the threaded runtime, we can run these functions in a
+-- /bound thread/ (via 'forkOS'), thereby avoiding the FreeBSD issues.  We
+-- still need a lock to serialise multiple threads calling these functions
+-- on at least macOS for lack of @_r@ equivalents.  While on FreeBSD we could
+-- use @getpwent_r(3)@ and @getgrent_r(3)@ in a bound thread without any
+-- locks, implementing this special case is likely not worthwhile.
+--
+-- In the non-threaded runtime, `forkOS` is not available, and so on FreeBSD
+-- systems we have to also lock the @*(nam|[ug]id)_r(3)@ functions to avoid
+-- concurrent use with @*ent(3)@.
+--
+-- FWIW, the below Perl one-liners will quickly show whether interleaved calls
+-- of getpwuid() or getgrgid() disturb iteration through all the entries. If
+-- each line of output is distinct, there is likely no issue.  If the same
+-- passwd or group entry repeats multiple times, the system is affected.
+--
+-- > for ($i=0;$i<3;++$i) {getpwuid(0); print join(":",getpwent()),"\n"}
+-- > for ($i=0;$i<3;++$i) {getgrgid(0); print join(":",getgrent()),"\n"}
+--
+-- XXX: It has been suggested, not without some merit, that attempts to
+-- enumerate /all/ users or /all/ groups are fundamentally flawed.  Modern
+-- unix systems have a variety nsswitch backends, some of which instantiate
+-- users on demand or may enumerate slowly or not at all.  We could shed a
+-- lot of complexity by deprecating the "get all" functions and simply
+-- always returning an empty list.
+--
 
+#if defined(HAVE_GETPWENT)
+pwlock :: MVar ()
+pwlock = unsafePerformIO $ newMVar ()
+{-# NOINLINE pwlock #-}
+
+lockpw :: LKUPTYPE -> IO a -> IO a
+#if defined(freebsd_HOST_OS)
+lockpw GETONE
+    | rtsSupportsBoundThreads = id
+    | otherwise = withMVar pwlock . const
+lockpw GETALL
+    | rtsSupportsBoundThreads = runInBoundThread . withMVar pwlock . const
+    | otherwise = withMVar pwlock . const
+#else
+lockpw GETONE = id
+lockpw GETALL = withMVar pwlock . const
+#endif
+#else
+lockpw _ = id
+#endif
+
+#if defined(HAVE_GETGRENT)
+grlock :: MVar ()
+grlock = unsafePerformIO $ newMVar ()
+{-# NOINLINE grlock #-}
+
+lockgr :: LKUPTYPE -> IO a -> IO a
+#if defined(freebsd_HOST_OS)
+lockgr GETONE
+    | rtsSupportsBoundThreads = id
+    | otherwise = withMVar grlock . const
+lockgr GETALL
+    | rtsSupportsBoundThreads = runInBoundThread . withMVar grlock . const
+    | otherwise = withMVar grlock . const
+#else
+lockgr GETONE = id
+lockgr GETALL = withMVar grlock . const
+#endif
+#else
+lockgr _ = id
+#endif
+
+-- -----------------------------------------------------------------------------
+-- user environment
+
 -- | @getRealUserID@ calls @getuid@ to obtain the real @UserID@
 --   associated with the current process.
 getRealUserID :: IO UserID
@@ -127,7 +319,6 @@
   c_setgroups :: CInt -> Ptr CGid -> IO CInt
 
 
-
 -- | @getLoginName@ calls @getlogin@ to obtain the login name
 --   associated with the current process.
 getLoginName :: IO String
@@ -186,32 +377,69 @@
     pw <- getUserEntryForID euid
     return (userName pw)
 
+#endif // HAVE_PWD_H
+
 -- -----------------------------------------------------------------------------
 -- The group database (grp.h)
 
-data GroupEntry =
- GroupEntry {
-  groupName    :: String,       -- ^ The name of this group (gr_name)
-  groupPassword :: String,      -- ^ The password for this group (gr_passwd)
-  groupID      :: GroupID,      -- ^ The unique numeric ID for this group (gr_gid)
-  groupMembers :: [String]      -- ^ A list of zero or more usernames that are members (gr_mem)
- } deriving (Show, Read, Eq)
+groupName :: GroupEntry -> String
+groupName (GroupEntry gn _ _ _) = gn
 
+groupPassword :: GroupEntry -> String
+groupPassword (GroupEntry _ gp _ _) = gp
+
+groupID :: GroupEntry -> GroupID
+groupID (GroupEntry _ _ id' _) = id'
+
+groupMembers :: GroupEntry -> [String]
+groupMembers (GroupEntry _ _ _ gm) = gm
+
+-- | Manually constructing 'GroupEntry' in String modules is discouraged. It will truncate
+-- Chars to 8bit. Use 'System.Posix.User.ByteString' instead.
+pattern GroupEntry :: String          -- ^ The name of this group (gr_name)
+                   -> String          -- ^ The password for this group (gr_passwd)
+                   -> GroupID         -- ^ The unique numeric ID for this group (gr_gid)
+                   -> [String]        -- ^ A list of zero or more usernames that are members (gr_mem)
+                   -> GroupEntry
+pattern GroupEntry gn gp gi gm <- User.GroupEntry (C8.unpack -> gn) (C8.unpack -> gp) gi (fmap C8.unpack -> gm) where
+  GroupEntry gn gp gi gm = User.GroupEntry (C8.pack gn) (C8.pack gp) gi (C8.pack <$> gm)
+{-# COMPLETE GroupEntry #-}
+
+#if !defined(HAVE_PWD_H)
+
+getGroupEntryForID :: GroupID -> IO GroupEntry
+{-# WARNING getGroupEntryForID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getGroupEntryForID _ = ioError (ioeSetLocation unsupportedOperation "getGroupEntryForID")
+
+getGroupEntryForName :: String -> IO GroupEntry
+{-# WARNING getGroupEntryForName
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getGroupEntryForName _ = ioError (ioeSetLocation unsupportedOperation "getGroupEntryForName")
+
+getAllGroupEntries :: IO [GroupEntry]
+{-# WARNING getAllGroupEntries
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getAllGroupEntries = ioError (ioeSetLocation unsupportedOperation "getAllGroupEntries")
+
+#else
+
 -- | @getGroupEntryForID gid@ calls @getgrgid_r@ to obtain
 --   the @GroupEntry@ information associated with @GroupID@
 --   @gid@. This operation may fail with 'isDoesNotExistError'
 --   if no such group exists.
 getGroupEntryForID :: GroupID -> IO GroupEntry
 #ifdef HAVE_GETGRGID_R
-getGroupEntryForID gid =
-  allocaBytes (#const sizeof(struct group)) $ \pgr ->
-   doubleAllocWhileERANGE "getGroupEntryForID" "group" grBufSize unpackGroupEntry $
-     c_getgrgid_r gid pgr
+getGroupEntryForID gid = lockgr GETONE $
+    allocaBytes (#const sizeof(struct group)) $ \pgr ->
+        doubleAllocWhileERANGE "getGroupEntryForID" "group"
+            grBufSize unpackGroupEntry $ c_getgrgid_r gid pgr
 
-foreign import capi unsafe "HsUnix.h getgrgid_r"
+foreign import capi safe "HsUnix.h getgrgid_r"
   c_getgrgid_r :: CGid -> Ptr CGroup -> CString
                  -> CSize -> Ptr (Ptr CGroup) -> IO CInt
 #else
+{-# WARNING getGroupEntryForID "System.Posix.User.getGroupEntryForID: not supported" #-}
 getGroupEntryForID = error "System.Posix.User.getGroupEntryForID: not supported"
 #endif
 
@@ -221,16 +449,17 @@
 --   if no such group exists.
 getGroupEntryForName :: String -> IO GroupEntry
 #ifdef HAVE_GETGRNAM_R
-getGroupEntryForName name =
-  allocaBytes (#const sizeof(struct group)) $ \pgr ->
-    withCAString name $ \ pstr ->
-      doubleAllocWhileERANGE "getGroupEntryForName" "group" grBufSize unpackGroupEntry $
-        c_getgrnam_r pstr pgr
+getGroupEntryForName name = lockgr GETONE $
+    allocaBytes (#const sizeof(struct group)) $ \pgr ->
+        withCAString name $ \ pstr ->
+            doubleAllocWhileERANGE "getGroupEntryForName" "group"
+                grBufSize unpackGroupEntry $ c_getgrnam_r pstr pgr
 
-foreign import capi unsafe "HsUnix.h getgrnam_r"
+foreign import capi safe "HsUnix.h getgrnam_r"
   c_getgrnam_r :: CString -> Ptr CGroup -> CString
                  -> CSize -> Ptr (Ptr CGroup) -> IO CInt
 #else
+{-# WARNING getGroupEntryForName "System.Posix.User.getGroupEntryForName: not supported" #-}
 getGroupEntryForName = error "System.Posix.User.getGroupEntryForName: not supported"
 #endif
 
@@ -244,24 +473,21 @@
 --
 getAllGroupEntries :: IO [GroupEntry]
 #ifdef HAVE_GETGRENT
-getAllGroupEntries =
-    withMVar lock $ \_ -> bracket_ c_setgrent c_endgrent $ worker []
-    where worker accum =
-              do resetErrno
-                 ppw <- throwErrnoIfNullAndError "getAllGroupEntries" $
-                        c_getgrent
-                 if ppw == nullPtr
-                     then return (reverse accum)
-                     else do thisentry <- unpackGroupEntry ppw
-                             worker (thisentry : accum)
+getAllGroupEntries = lockgr GETALL $ bracket_ c_setgrent c_endgrent $ worker []
+  where
+    worker accum = do
+        resetErrno
+        ppw <- throwErrnoIfNullAndError "getAllGroupEntries" $ c_getgrent
+        if ppw == nullPtr
+            then return (reverse accum)
+            else do thisentry <- unpackGroupEntry ppw
+                    worker (thisentry : accum)
 
-foreign import ccall unsafe "getgrent"
-  c_getgrent :: IO (Ptr CGroup)
-foreign import ccall unsafe "setgrent"
-  c_setgrent :: IO ()
-foreign import ccall unsafe "endgrent"
-  c_endgrent :: IO ()
+foreign import ccall safe "getgrent" c_getgrent :: IO (Ptr CGroup)
+foreign import ccall safe "setgrent" c_setgrent :: IO ()
+foreign import ccall safe "endgrent" c_endgrent :: IO ()
 #else
+{-# WARNING getAllGroupEntries "System.Posix.User.getAllGroupEntries: not supported" #-}
 getAllGroupEntries = error "System.Posix.User.getAllGroupEntries: not supported"
 #endif
 
@@ -274,65 +500,74 @@
 #endif
 #endif
 
-unpackGroupEntry :: Ptr CGroup -> IO GroupEntry
-unpackGroupEntry ptr = do
-   name    <- (#peek struct group, gr_name) ptr >>= peekCAString
-   passwd  <- (#peek struct group, gr_passwd) ptr >>= peekCAString
-   gid     <- (#peek struct group, gr_gid) ptr
-   mem     <- (#peek struct group, gr_mem) ptr
-   members <- peekArray0 nullPtr mem >>= mapM peekCAString
-   return (GroupEntry name passwd gid members)
+#endif // HAVE_PWD_H
 
 -- -----------------------------------------------------------------------------
 -- The user database (pwd.h)
 
-data UserEntry =
- UserEntry {
-   userName      :: String,     -- ^ Textual name of this user (pw_name)
-   userPassword  :: String,     -- ^ Password -- may be empty or fake if shadow is in use (pw_passwd)
-   userID        :: UserID,     -- ^ Numeric ID for this user (pw_uid)
-   userGroupID   :: GroupID,    -- ^ Primary group ID (pw_gid)
-   userGecos     :: String,     -- ^ Usually the real name for the user (pw_gecos)
-   homeDirectory :: String,     -- ^ Home directory (pw_dir)
-   userShell     :: String      -- ^ Default shell (pw_shell)
- } deriving (Show, Read, Eq)
+userName :: UserEntry -> String
+userName (UserEntry n _ _ _ _ _ _) = n
 
---
--- getpwuid and getpwnam leave results in a static object. Subsequent
--- calls modify the same object, which isn't threadsafe. We attempt to
--- mitigate this issue, on platforms that don't provide the safe _r versions
---
--- Also, getpwent/setpwent require a global lock since they maintain
--- an internal file position pointer.
-#if !defined(HAVE_GETPWNAM_R) || !defined(HAVE_GETPWUID_R) || defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
-lock :: MVar ()
-lock = unsafePerformIO $ newMVar ()
-{-# NOINLINE lock #-}
-#endif
+userPassword :: UserEntry -> String
+userPassword (UserEntry _ p _ _ _ _ _) = p
 
--- | @getUserEntryForID gid@ calls @getpwuid_r@ to obtain
+userID :: UserEntry -> UserID
+userID (UserEntry _ _ id' _ _ _ _) = id'
+
+userGroupID :: UserEntry -> GroupID
+userGroupID (UserEntry _ _ _ gid _ _ _) = gid
+
+userGecos :: UserEntry -> String
+userGecos (UserEntry _ _ _ _ ge _ _) = ge
+
+homeDirectory :: UserEntry -> String
+homeDirectory (UserEntry _ _ _ _ _ hd _) = hd
+
+userShell :: UserEntry -> String
+userShell (UserEntry _ _ _ _ _ _ us) = us
+
+-- | Manually constructing 'UserEntry' in String modules is discouraged. It will truncate
+-- Chars to 8bit. Use 'System.Posix.User.ByteString' instead.
+pattern UserEntry :: String         -- ^ Textual name of this user (pw_name)
+                  -> String         -- ^ Password -- may be empty or fake if shadow is in use (pw_passwd)
+                  -> UserID         -- ^ Numeric ID for this user (pw_uid)
+                  -> GroupID        -- ^ Primary group ID (pw_gid)
+                  -> String         -- ^ Usually the real name for the user (pw_gecos)
+                  -> String         -- ^ Home directory (pw_dir)
+                  -> String         -- ^ Default shell (pw_shell)
+                  -> UserEntry
+pattern UserEntry un up ui ugi ug hd us <- User.UserEntry (C8.unpack -> un)
+                                                       (C8.unpack -> up)
+                                                       ui
+                                                       ugi
+                                                       (C8.unpack -> ug)
+                                                       (C8.unpack -> hd)
+                                                       (C8.unpack -> us) where
+  UserEntry un up ui ugi ug hd us = User.UserEntry (C8.pack un)
+                                                (C8.pack up)
+                                                ui
+                                                ugi
+                                                (C8.pack ug)
+                                                (C8.pack hd)
+                                                (C8.pack us)
+{-# COMPLETE UserEntry #-}
+
+-- | @getUserEntryForID uid@ calls @getpwuid_r@ to obtain
 --   the @UserEntry@ information associated with @UserID@
 --   @uid@. This operation may fail with 'isDoesNotExistError'
 --   if no such user exists.
 getUserEntryForID :: UserID -> IO UserEntry
 #ifdef HAVE_GETPWUID_R
-getUserEntryForID uid =
-  allocaBytes (#const sizeof(struct passwd)) $ \ppw ->
-    doubleAllocWhileERANGE "getUserEntryForID" "user" pwBufSize unpackUserEntry $
-      c_getpwuid_r uid ppw
+getUserEntryForID uid = lockpw GETONE $
+    allocaBytes (#const sizeof(struct passwd)) $ \ppw ->
+        doubleAllocWhileERANGE "getUserEntryForID" "user"
+            pwBufSize unpackUserEntry $ c_getpwuid_r uid ppw
 
-foreign import capi unsafe "HsUnix.h getpwuid_r"
+foreign import capi safe "HsUnix.h getpwuid_r"
   c_getpwuid_r :: CUid -> Ptr CPasswd ->
                         CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt
-#elif HAVE_GETPWUID
-getUserEntryForID uid = do
-  withMVar lock $ \_ -> do
-    ppw <- throwErrnoIfNull "getUserEntryForID" $ c_getpwuid uid
-    unpackUserEntry ppw
-
-foreign import ccall unsafe "getpwuid"
-  c_getpwuid :: CUid -> IO (Ptr CPasswd)
 #else
+{-# WARNING getUserEntryForID "System.Posix.User.getUserEntryForID: not supported" #-}
 getUserEntryForID = error "System.Posix.User.getUserEntryForID: not supported"
 #endif
 
@@ -342,25 +577,17 @@
 --   if no such user exists.
 getUserEntryForName :: String -> IO UserEntry
 #if HAVE_GETPWNAM_R
-getUserEntryForName name =
-  allocaBytes (#const sizeof(struct passwd)) $ \ppw ->
-    withCAString name $ \ pstr ->
-      doubleAllocWhileERANGE "getUserEntryForName" "user" pwBufSize unpackUserEntry $
-        c_getpwnam_r pstr ppw
+getUserEntryForName name = lockpw GETONE $
+    allocaBytes (#const sizeof(struct passwd)) $ \ppw ->
+        withCAString name $ \ pstr ->
+            doubleAllocWhileERANGE "getUserEntryForName" "user"
+                pwBufSize unpackUserEntry $ c_getpwnam_r pstr ppw
 
-foreign import capi unsafe "HsUnix.h getpwnam_r"
+foreign import capi safe "HsUnix.h getpwnam_r"
   c_getpwnam_r :: CString -> Ptr CPasswd
                -> CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt
-#elif HAVE_GETPWNAM
-getUserEntryForName name = do
-  withCAString name $ \ pstr -> do
-    withMVar lock $ \_ -> do
-      ppw <- throwErrnoIfNull "getUserEntryForName" $ c_getpwnam pstr
-      unpackUserEntry ppw
-
-foreign import ccall unsafe "getpwnam"
-  c_getpwnam :: CString -> IO (Ptr CPasswd)
 #else
+{-# WARNING getUserEntryForName "System.Posix.User.getUserEntryForName: not supported" #-}
 getUserEntryForName = error "System.Posix.User.getUserEntryForName: not supported"
 #endif
 
@@ -368,24 +595,21 @@
 --   repeatedly calling @getpwent@
 getAllUserEntries :: IO [UserEntry]
 #ifdef HAVE_GETPWENT
-getAllUserEntries =
-    withMVar lock $ \_ -> bracket_ c_setpwent c_endpwent $ worker []
-    where worker accum =
-              do resetErrno
-                 ppw <- throwErrnoIfNullAndError "getAllUserEntries" $
-                        c_getpwent
-                 if ppw == nullPtr
-                     then return (reverse accum)
-                     else do thisentry <- unpackUserEntry ppw
-                             worker (thisentry : accum)
+getAllUserEntries = lockpw GETALL $ bracket_ c_setpwent c_endpwent $ worker []
+  where
+    worker accum = do
+        resetErrno
+        ppw <- throwErrnoIfNullAndError "getAllUserEntries" $ c_getpwent
+        if ppw == nullPtr
+            then return (reverse accum)
+            else do thisentry <- unpackUserEntry ppw
+                    worker (thisentry : accum)
 
-foreign import capi unsafe "HsUnix.h getpwent"
-  c_getpwent :: IO (Ptr CPasswd)
-foreign import capi unsafe "HsUnix.h setpwent"
-  c_setpwent :: IO ()
-foreign import capi unsafe "HsUnix.h endpwent"
-  c_endpwent :: IO ()
+foreign import ccall safe "getpwent" c_getpwent :: IO (Ptr CPasswd)
+foreign import ccall safe "setpwent" c_setpwent :: IO ()
+foreign import ccall safe "endpwent" c_endpwent :: IO ()
 #else
+{-# WARNING getAllUserEntries "System.Posix.User.getAllUserEntries: not supported" #-}
 getAllUserEntries = error "System.Posix.User.getAllUserEntries: not supported"
 #endif
 
@@ -398,7 +622,7 @@
 #endif
 #endif
 
-#ifdef HAVE_SYSCONF
+#if defined(HAVE_SYSCONF) && defined(HAVE_PWD_H)
 foreign import ccall unsafe "sysconf"
   c_sysconf :: CInt -> IO CLong
 
@@ -412,6 +636,8 @@
                          return $ if v == (-1) then def else v
 #endif
 
+#if defined(HAVE_PWD_H)
+
 -- The following function is used by the getgr*_r, c_getpw*_r
 -- families of functions. These functions return their result
 -- in a struct that contains strings and they need a buffer
@@ -448,20 +674,6 @@
     ioError $ flip ioeSetErrorString ("no such " ++ enttype)
             $ mkIOError doesNotExistErrorType loc Nothing Nothing
 
-unpackUserEntry :: Ptr CPasswd -> IO UserEntry
-unpackUserEntry ptr = do
-   name   <- (#peek struct passwd, pw_name)   ptr >>= peekCAString
-   passwd <- (#peek struct passwd, pw_passwd) ptr >>= peekCAString
-   uid    <- (#peek struct passwd, pw_uid)    ptr
-   gid    <- (#peek struct passwd, pw_gid)    ptr
-#ifdef HAVE_NO_PASSWD_PW_GECOS
-   gecos  <- return ""  -- pw_gecos does not exist on android
-#else
-   gecos  <- (#peek struct passwd, pw_gecos)  ptr >>= peekCAString
-#endif
-   dir    <- (#peek struct passwd, pw_dir)    ptr >>= peekCAString
-   shell  <- (#peek struct passwd, pw_shell)  ptr >>= peekCAString
-   return (UserEntry name passwd uid gid gecos dir shell)
 
 -- Used when a function returns NULL to indicate either an error or
 -- EOF, depending on whether the global errno is nonzero.
@@ -472,3 +684,5 @@
     if rc == nullPtr && errno /= eOK
        then throwErrno loc
        else return rc
+
+#endif // HAVE_PWD_H
diff --git a/System/Posix/User/ByteString.hsc b/System/Posix/User/ByteString.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/User/ByteString.hsc
@@ -0,0 +1,604 @@
+{-# LANGUAGE Trustworthy, CApiFFI, PatternSynonyms, ViewPatterns #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.User.ByteString
+-- 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 user\/group support
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.User.ByteString (
+    -- * User environment
+    -- ** Querying the user environment
+    getRealUserID,
+    getRealGroupID,
+    getEffectiveUserID,
+    getEffectiveGroupID,
+    getGroups,
+    getLoginName,
+    getEffectiveUserName,
+
+    -- *** The group database
+    GroupEntry(..),
+
+    getGroupEntryForID,
+    getGroupEntryForName,
+    getAllGroupEntries,
+
+    -- *** The user database
+    UserEntry(..),
+
+    getUserEntryForID,
+    getUserEntryForName,
+    getAllUserEntries,
+
+    -- ** Modifying the user environment
+    setUserID,
+    setGroupID,
+    setEffectiveUserID,
+    setEffectiveGroupID,
+    setGroups
+
+  ) where
+
+#include "HsUnix.h"
+
+import System.Posix.Types
+import System.IO.Unsafe (unsafePerformIO)
+import Foreign.C ( CSize(..), CInt(..), CString, CLong(..), getErrno, throwErrno, eOK, throwErrnoIfMinus1_, throwErrnoIfNull, resetErrno, Errno(..), eRANGE, errnoToIOError )
+import Foreign.Ptr
+import Foreign.Marshal
+import Foreign.Storable
+
+import System.Posix.User.Common
+#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT)
+#if defined(freebsd_HOST_OS)
+import Control.Concurrent (runInBoundThread, rtsSupportsBoundThreads)
+#endif
+import Control.Concurrent.MVar ( MVar, newMVar, withMVar )
+import Control.Exception
+#endif
+import Control.Monad
+import System.IO.Error
+import Data.ByteString ( ByteString, packCString, useAsCString )
+
+#if !defined(HAVE_PWD_H)
+import System.IO.Error ( ioeSetLocation )
+import GHC.IO.Exception ( unsupportedOperation )
+#endif
+
+
+#if !defined(HAVE_PWD_H)
+
+getRealUserID :: IO UserID
+{-# WARNING getRealUserID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getRealUserID = ioError (ioeSetLocation unsupportedOperation "getRealUserID")
+
+getRealGroupID :: IO GroupID
+{-# WARNING getRealGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getRealGroupID = ioError (ioeSetLocation unsupportedOperation "getRealGroupID")
+
+getEffectiveUserID :: IO UserID
+{-# WARNING getEffectiveUserID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getEffectiveUserID = ioError (ioeSetLocation unsupportedOperation "getEffectiveUserID")
+
+getEffectiveGroupID :: IO GroupID
+{-# WARNING getEffectiveGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getEffectiveGroupID = ioError (ioeSetLocation unsupportedOperation "getEffectiveGroupID")
+
+getGroups :: IO [GroupID]
+{-# WARNING getGroups
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getGroups = ioError (ioeSetLocation unsupportedOperation "getGroups")
+
+setGroups :: [GroupID] -> IO ()
+{-# WARNING setGroups
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setGroups _ = ioError (ioeSetLocation unsupportedOperation "setGroups")
+
+getLoginName :: IO ByteString
+{-# WARNING getLoginName
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getLoginName = ioError (ioeSetLocation unsupportedOperation "getLoginName")
+
+setUserID :: UserID -> IO ()
+{-# WARNING setUserID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setUserID _ = ioError (ioeSetLocation unsupportedOperation "setUserID")
+
+setEffectiveUserID :: UserID -> IO ()
+{-# WARNING setEffectiveUserID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setEffectiveUserID _ = ioError (ioeSetLocation unsupportedOperation "setEffectiveUserID")
+
+setGroupID :: GroupID -> IO ()
+{-# WARNING setGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setGroupID _ = ioError (ioeSetLocation unsupportedOperation "setGroupID")
+
+setEffectiveGroupID :: GroupID -> IO ()
+{-# WARNING setEffectiveGroupID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+setEffectiveGroupID _ = ioError (ioeSetLocation unsupportedOperation "setEffectiveGroupID")
+
+getEffectiveUserName :: IO ByteString
+{-# WARNING getEffectiveUserName
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getEffectiveUserName = ioError (ioeSetLocation unsupportedOperation "getEffectiveUserName")
+
+#else
+-- -----------------------------------------------------------------------------
+-- Thread safety of passwd/group database access APIs:
+--
+-- All supported unix platforms have @get(pw|gr)(nam|[ug]id)_r(3)@, which
+-- store the result in a caller provided buffer, which solves the most
+-- immediate thread-safety issues.
+--
+-- Things are more complicated for getpwent(3) and getgrent(3).
+--
+-- * On Linux systems, these read a global open file, opened via
+--   setpwent(3) and closed via endpwent(3).  Only one thread at
+--   a time can safely iterate through the file.
+--
+-- * On macOS (through Catalina 10.15), there is no getpwent_r(3) or
+--   getgrent_r(3), so a lock is also required for safe buffer sharing.
+--
+-- * On FreeBSD, in the default configuration with passwd lookups configured
+--   in nsswitch.conf to use "compat" rather than "files", the getpwnam_r(3)
+--   and getpwuid_r(3) functions reset the iterator index used by getpwent(3).
+--   A bug [report](https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=252094)
+--   has been filed to track this long-standing issue.  A similar issue affects
+--   getgrent(3), this time regardless of the nsswitch.conf setting.  This too
+--   should be fixed at some point in the future.  The state in question is
+--   thread-specific, so both issues only affect overlapping use of the @*ent@
+--   and @*(nam|[ug]id)_r(3)@ functions in the /same/ thread.
+--
+-- * Despite rather similar manpages for getpwent(3) and getpwnam(3), ... as
+--   on FreeBSD, the above issue is not seen on NetBSD or macOS.
+--
+--   This is not an issue with 1-to-1 thread models, where the code executing
+--   @get(pw|gr)ent@ has exclusive use of its thread, but it is a real issue
+--   for Haskell with its many-to-1 green threads, because multiple `forkIO`
+--   threads may take turns using the same underlying OS thread, breaking the
+--   thread-safety of the @*_r@ functions, which mutate the file-offset of the
+--   open file shared with any overlapping execution of @*ent(3)@ in the same
+--   thread.
+--
+-- Consequently, correct portable support for @get(pw|gr)ent(3)@ is rather
+-- non-trivial.  In the threaded runtime, we can run these functions in a
+-- /bound thread/ (via 'forkOS'), thereby avoiding the FreeBSD issues.  We
+-- still need a lock to serialise multiple threads calling these functions
+-- on at least macOS for lack of @_r@ equivalents.  While on FreeBSD we could
+-- use @getpwent_r(3)@ and @getgrent_r(3)@ in a bound thread without any
+-- locks, implementing this special case is likely not worthwhile.
+--
+-- In the non-threaded runtime, `forkOS` is not available, and so on FreeBSD
+-- systems we have to also lock the @*(nam|[ug]id)_r(3)@ functions to avoid
+-- concurrent use with @*ent(3)@.
+--
+-- FWIW, the below Perl one-liners will quickly show whether interleaved calls
+-- of getpwuid() or getgrgid() disturb iteration through all the entries. If
+-- each line of output is distinct, there is likely no issue.  If the same
+-- passwd or group entry repeats multiple times, the system is affected.
+--
+-- > for ($i=0;$i<3;++$i) {getpwuid(0); print join(":",getpwent()),"\n"}
+-- > for ($i=0;$i<3;++$i) {getgrgid(0); print join(":",getgrent()),"\n"}
+--
+-- XXX: It has been suggested, not without some merit, that attempts to
+-- enumerate /all/ users or /all/ groups are fundamentally flawed.  Modern
+-- unix systems have a variety nsswitch backends, some of which instantiate
+-- users on demand or may enumerate slowly or not at all.  We could shed a
+-- lot of complexity by deprecating the "get all" functions and simply
+-- always returning an empty list.
+--
+
+#if defined(HAVE_GETPWENT)
+pwlock :: MVar ()
+pwlock = unsafePerformIO $ newMVar ()
+{-# NOINLINE pwlock #-}
+
+lockpw :: LKUPTYPE -> IO a -> IO a
+#if defined(freebsd_HOST_OS)
+lockpw GETONE
+    | rtsSupportsBoundThreads = id
+    | otherwise = withMVar pwlock . const
+lockpw GETALL
+    | rtsSupportsBoundThreads = runInBoundThread . withMVar pwlock . const
+    | otherwise = withMVar pwlock . const
+#else
+lockpw GETONE = id
+lockpw GETALL = withMVar pwlock . const
+#endif
+#else
+lockpw _ = id
+#endif
+
+#if defined(HAVE_GETGRENT)
+grlock :: MVar ()
+grlock = unsafePerformIO $ newMVar ()
+{-# NOINLINE grlock #-}
+
+lockgr :: LKUPTYPE -> IO a -> IO a
+#if defined(freebsd_HOST_OS)
+lockgr GETONE
+    | rtsSupportsBoundThreads = id
+    | otherwise = withMVar grlock . const
+lockgr GETALL
+    | rtsSupportsBoundThreads = runInBoundThread . withMVar grlock . const
+    | otherwise = withMVar grlock . const
+#else
+lockgr GETONE = id
+lockgr GETALL = withMVar grlock . const
+#endif
+#else
+lockgr _ = id
+#endif
+
+-- -----------------------------------------------------------------------------
+-- user environment
+
+-- | @getRealUserID@ calls @getuid@ to obtain the real @UserID@
+--   associated with the current process.
+getRealUserID :: IO UserID
+getRealUserID = c_getuid
+
+foreign import ccall unsafe "getuid"
+  c_getuid :: IO CUid
+
+-- | @getRealGroupID@ calls @getgid@ to obtain the real @GroupID@
+--   associated with the current process.
+getRealGroupID :: IO GroupID
+getRealGroupID = c_getgid
+
+foreign import ccall unsafe "getgid"
+  c_getgid :: IO CGid
+
+-- | @getEffectiveUserID@ calls @geteuid@ to obtain the effective
+--   @UserID@ associated with the current process.
+getEffectiveUserID :: IO UserID
+getEffectiveUserID = c_geteuid
+
+foreign import ccall unsafe "geteuid"
+  c_geteuid :: IO CUid
+
+-- | @getEffectiveGroupID@ calls @getegid@ to obtain the effective
+--   @GroupID@ associated with the current process.
+getEffectiveGroupID :: IO GroupID
+getEffectiveGroupID = c_getegid
+
+foreign import ccall unsafe "getegid"
+  c_getegid :: IO CGid
+
+-- | @getGroups@ calls @getgroups@ to obtain the list of
+--   supplementary @GroupID@s associated with the current process.
+getGroups :: IO [GroupID]
+getGroups = do
+    ngroups <- c_getgroups 0 nullPtr
+    allocaArray (fromIntegral ngroups) $ \arr -> do
+       throwErrnoIfMinus1_ "getGroups" (c_getgroups ngroups arr)
+       groups <- peekArray (fromIntegral ngroups) arr
+       return groups
+
+foreign import ccall unsafe "getgroups"
+  c_getgroups :: CInt -> Ptr CGid -> IO CInt
+
+
+-- | @setGroups@ calls @setgroups@ to set the list of
+--   supplementary @GroupID@s associated with the current process.
+setGroups :: [GroupID] -> IO ()
+setGroups groups = do
+    withArrayLen groups $ \ ngroups arr ->
+       throwErrnoIfMinus1_ "setGroups" (c_setgroups (fromIntegral ngroups) arr)
+
+foreign import ccall unsafe "setgroups"
+  c_setgroups :: CInt -> Ptr CGid -> IO CInt
+
+
+-- | @getLoginName@ calls @getlogin@ to obtain the login name
+--   associated with the current process.
+getLoginName :: IO ByteString
+getLoginName =  do
+    -- ToDo: use getlogin_r
+    str <- throwErrnoIfNull "getLoginName" c_getlogin
+    packCString str
+
+foreign import ccall unsafe "getlogin"
+  c_getlogin :: IO CString
+
+-- | @setUserID uid@ calls @setuid@ to set the real, effective, and
+--   saved set-user-id associated with the current process to @uid@.
+setUserID :: UserID -> IO ()
+setUserID uid = throwErrnoIfMinus1_ "setUserID" (c_setuid uid)
+
+foreign import ccall unsafe "setuid"
+  c_setuid :: CUid -> IO CInt
+
+-- | @setEffectiveUserID uid@ calls @seteuid@ to set the effective
+--   user-id associated with the current process to @uid@. This
+--   does not update the real user-id or set-user-id.
+setEffectiveUserID :: UserID -> IO ()
+setEffectiveUserID uid = throwErrnoIfMinus1_ "setEffectiveUserID" (c_seteuid uid)
+
+foreign import ccall unsafe "seteuid"
+  c_seteuid :: CUid -> IO CInt
+
+-- | @setGroupID gid@ calls @setgid@ to set the real, effective, and
+--   saved set-group-id associated with the current process to @gid@.
+setGroupID :: GroupID -> IO ()
+setGroupID gid = throwErrnoIfMinus1_ "setGroupID" (c_setgid gid)
+
+foreign import ccall unsafe "setgid"
+  c_setgid :: CGid -> IO CInt
+
+-- | @setEffectiveGroupID uid@ calls @setegid@ to set the effective
+--   group-id associated with the current process to @gid@. This
+--   does not update the real group-id or set-group-id.
+setEffectiveGroupID :: GroupID -> IO ()
+setEffectiveGroupID gid =
+  throwErrnoIfMinus1_ "setEffectiveGroupID" (c_setegid gid)
+
+
+foreign import ccall unsafe "setegid"
+  c_setegid :: CGid -> IO CInt
+
+-- -----------------------------------------------------------------------------
+-- User names
+
+-- | @getEffectiveUserName@ gets the name
+--   associated with the effective @UserID@ of the process.
+getEffectiveUserName :: IO ByteString
+getEffectiveUserName = do
+    euid <- getEffectiveUserID
+    pw <- getUserEntryForID euid
+    return (userName pw)
+
+#endif // HAVE_PWD_H
+
+-- -----------------------------------------------------------------------------
+-- The group database (grp.h)
+
+
+#if !defined(HAVE_PWD_H)
+
+getGroupEntryForID :: GroupID -> IO GroupEntry
+{-# WARNING getGroupEntryForID
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getGroupEntryForID _ = ioError (ioeSetLocation unsupportedOperation "getGroupEntryForID")
+
+getGroupEntryForName :: ByteString -> IO GroupEntry
+{-# WARNING getGroupEntryForName
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getGroupEntryForName _ = ioError (ioeSetLocation unsupportedOperation "getGroupEntryForName")
+
+getAllGroupEntries :: IO [GroupEntry]
+{-# WARNING getAllGroupEntries
+    "operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_PWD_H@)" #-}
+getAllGroupEntries = ioError (ioeSetLocation unsupportedOperation "getAllGroupEntries")
+
+#else
+
+-- | @getGroupEntryForID gid@ calls @getgrgid_r@ to obtain
+--   the @GroupEntry@ information associated with @GroupID@
+--   @gid@. This operation may fail with 'isDoesNotExistError'
+--   if no such group exists.
+getGroupEntryForID :: GroupID -> IO GroupEntry
+#ifdef HAVE_GETGRGID_R
+getGroupEntryForID gid = lockgr GETONE $
+    allocaBytes (#const sizeof(struct group)) $ \pgr ->
+        doubleAllocWhileERANGE "getGroupEntryForID" "group"
+            grBufSize unpackGroupEntry $ c_getgrgid_r gid pgr
+
+foreign import capi safe "HsUnix.h getgrgid_r"
+  c_getgrgid_r :: CGid -> Ptr CGroup -> CString
+                 -> CSize -> Ptr (Ptr CGroup) -> IO CInt
+#else
+{-# WARNING getGroupEntryForID "System.Posix.User.getGroupEntryForID: not supported" #-}
+getGroupEntryForID = error "System.Posix.User.getGroupEntryForID: not supported"
+#endif
+
+-- | @getGroupEntryForName name@ calls @getgrnam_r@ to obtain
+--   the @GroupEntry@ information associated with the group called
+--   @name@. This operation may fail with 'isDoesNotExistError'
+--   if no such group exists.
+getGroupEntryForName :: ByteString -> IO GroupEntry
+#ifdef HAVE_GETGRNAM_R
+getGroupEntryForName name = lockgr GETONE $
+    allocaBytes (#const sizeof(struct group)) $ \pgr ->
+        useAsCString name $ \ pstr ->
+            doubleAllocWhileERANGE "getGroupEntryForName" "group"
+                grBufSize unpackGroupEntry $ c_getgrnam_r pstr pgr
+
+foreign import capi safe "HsUnix.h getgrnam_r"
+  c_getgrnam_r :: CString -> Ptr CGroup -> CString
+                 -> CSize -> Ptr (Ptr CGroup) -> IO CInt
+#else
+{-# WARNING getGroupEntryForName "System.Posix.User.getGroupEntryForName: not supported" #-}
+getGroupEntryForName = error "System.Posix.User.getGroupEntryForName: not supported"
+#endif
+
+-- | @getAllGroupEntries@ returns all group entries on the system by
+--   repeatedly calling @getgrent@
+
+--
+-- getAllGroupEntries may fail with isDoesNotExistError on Linux due to
+-- this bug in glibc:
+--   http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=466647
+--
+getAllGroupEntries :: IO [GroupEntry]
+#ifdef HAVE_GETGRENT
+getAllGroupEntries = lockgr GETALL $ bracket_ c_setgrent c_endgrent $ worker []
+  where
+    worker accum = do
+        resetErrno
+        ppw <- throwErrnoIfNullAndError "getAllGroupEntries" $ c_getgrent
+        if ppw == nullPtr
+            then return (reverse accum)
+            else do thisentry <- unpackGroupEntry ppw
+                    worker (thisentry : accum)
+
+foreign import ccall safe "getgrent" c_getgrent :: IO (Ptr CGroup)
+foreign import ccall safe "setgrent" c_setgrent :: IO ()
+foreign import ccall safe "endgrent" c_endgrent :: IO ()
+#else
+{-# WARNING getAllGroupEntries "System.Posix.User.getAllGroupEntries: not supported" #-}
+getAllGroupEntries = error "System.Posix.User.getAllGroupEntries: not supported"
+#endif
+
+#if defined(HAVE_GETGRGID_R) || defined(HAVE_GETGRNAM_R)
+grBufSize :: Int
+#if defined(HAVE_SYSCONF) && defined(HAVE_SC_GETGR_R_SIZE_MAX)
+grBufSize = sysconfWithDefault 1024 (#const _SC_GETGR_R_SIZE_MAX)
+#else
+grBufSize = 1024
+#endif
+#endif
+
+#endif // HAVE_PWD_H
+
+-- -----------------------------------------------------------------------------
+-- The user database (pwd.h)
+
+
+-- | @getUserEntryForID uid@ calls @getpwuid_r@ to obtain
+--   the @UserEntry@ information associated with @UserID@
+--   @uid@. This operation may fail with 'isDoesNotExistError'
+--   if no such user exists.
+getUserEntryForID :: UserID -> IO UserEntry
+#ifdef HAVE_GETPWUID_R
+getUserEntryForID uid = lockpw GETONE $
+    allocaBytes (#const sizeof(struct passwd)) $ \ppw ->
+        doubleAllocWhileERANGE "getUserEntryForID" "user"
+            pwBufSize unpackUserEntry $ c_getpwuid_r uid ppw
+
+foreign import capi safe "HsUnix.h getpwuid_r"
+  c_getpwuid_r :: CUid -> Ptr CPasswd ->
+                        CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt
+#else
+{-# WARNING getUserEntryForID "System.Posix.User.getUserEntryForID: not supported" #-}
+getUserEntryForID = error "System.Posix.User.getUserEntryForID: not supported"
+#endif
+
+-- | @getUserEntryForName name@ calls @getpwnam_r@ to obtain
+--   the @UserEntry@ information associated with the user login
+--   @name@. This operation may fail with 'isDoesNotExistError'
+--   if no such user exists.
+getUserEntryForName :: ByteString -> IO UserEntry
+#if HAVE_GETPWNAM_R
+getUserEntryForName name = lockpw GETONE $
+    allocaBytes (#const sizeof(struct passwd)) $ \ppw ->
+        useAsCString name $ \ pstr ->
+            doubleAllocWhileERANGE "getUserEntryForName" "user"
+                pwBufSize unpackUserEntry $ c_getpwnam_r pstr ppw
+
+foreign import capi safe "HsUnix.h getpwnam_r"
+  c_getpwnam_r :: CString -> Ptr CPasswd
+               -> CString -> CSize -> Ptr (Ptr CPasswd) -> IO CInt
+#else
+{-# WARNING getUserEntryForName "System.Posix.User.getUserEntryForName: not supported" #-}
+getUserEntryForName = error "System.Posix.User.getUserEntryForName: not supported"
+#endif
+
+-- | @getAllUserEntries@ returns all user entries on the system by
+--   repeatedly calling @getpwent@
+getAllUserEntries :: IO [UserEntry]
+#ifdef HAVE_GETPWENT
+getAllUserEntries = lockpw GETALL $ bracket_ c_setpwent c_endpwent $ worker []
+  where
+    worker accum = do
+        resetErrno
+        ppw <- throwErrnoIfNullAndError "getAllUserEntries" $ c_getpwent
+        if ppw == nullPtr
+            then return (reverse accum)
+            else do thisentry <- unpackUserEntry ppw
+                    worker (thisentry : accum)
+
+foreign import ccall safe "getpwent" c_getpwent :: IO (Ptr CPasswd)
+foreign import ccall safe "setpwent" c_setpwent :: IO ()
+foreign import ccall safe "endpwent" c_endpwent :: IO ()
+#else
+{-# WARNING getAllUserEntries "System.Posix.User.getAllUserEntries: not supported" #-}
+getAllUserEntries = error "System.Posix.User.getAllUserEntries: not supported"
+#endif
+
+#if defined(HAVE_GETPWUID_R) || defined(HAVE_GETPWNAM_R)
+pwBufSize :: Int
+#if  defined(HAVE_SYSCONF) && defined(HAVE_SC_GETPW_R_SIZE_MAX)
+pwBufSize = sysconfWithDefault 1024 (#const _SC_GETPW_R_SIZE_MAX)
+#else
+pwBufSize = 1024
+#endif
+#endif
+
+#if defined(HAVE_SYSCONF) && defined(HAVE_PWD_H)
+foreign import ccall unsafe "sysconf"
+  c_sysconf :: CInt -> IO CLong
+
+-- We need a default value since sysconf can fail and return -1
+-- even when the parameter name is defined in unistd.h.
+-- One example of this is _SC_GETPW_R_SIZE_MAX under
+-- Mac OS X 10.4.9 on i386.
+sysconfWithDefault :: Int -> CInt -> Int
+sysconfWithDefault def sc =
+    unsafePerformIO $ do v <- fmap fromIntegral $ c_sysconf sc
+                         return $ if v == (-1) then def else v
+#endif
+
+#if defined(HAVE_PWD_H)
+
+-- The following function is used by the getgr*_r, c_getpw*_r
+-- families of functions. These functions return their result
+-- in a struct that contains strings and they need a buffer
+-- that they can use to store those strings. We have to be
+-- careful to unpack the struct containing the result before
+-- the buffer is deallocated.
+doubleAllocWhileERANGE
+  :: String
+  -> String -- entry type: "user" or "group"
+  -> Int
+  -> (Ptr r -> IO a)
+  -> (Ptr b -> CSize -> Ptr (Ptr r) -> IO CInt)
+  -> IO a
+doubleAllocWhileERANGE loc enttype initlen unpack action =
+  alloca $ go initlen
+ where
+  go len res = do
+    r <- allocaBytes len $ \buf -> do
+           rc <- action buf (fromIntegral len) res
+           if rc /= 0
+             then return (Left rc)
+             else do p <- peek res
+                     when (p == nullPtr) $ notFoundErr
+                     fmap Right (unpack p)
+    case r of
+      Right x -> return x
+      Left rc | Errno rc == eRANGE ->
+        -- ERANGE means this is not an error
+        -- we just have to try again with a larger buffer
+        go (2 * len) res
+      Left rc ->
+        ioError (errnoToIOError loc (Errno rc) Nothing Nothing)
+  notFoundErr =
+    ioError $ flip ioeSetErrorString ("no such " ++ enttype)
+            $ mkIOError doesNotExistErrorType loc Nothing Nothing
+
+-- Used when a function returns NULL to indicate either an error or
+-- EOF, depending on whether the global errno is nonzero.
+throwErrnoIfNullAndError :: String -> IO (Ptr a) -> IO (Ptr a)
+throwErrnoIfNullAndError loc act = do
+    rc <- act
+    errno <- getErrno
+    if rc == nullPtr && errno /= eOK
+       then throwErrno loc
+       else return rc
+
+#endif // HAVE_PWD_H
diff --git a/System/Posix/User/Common.hsc b/System/Posix/User/Common.hsc
new file mode 100644
--- /dev/null
+++ b/System/Posix/User/Common.hsc
@@ -0,0 +1,79 @@
+{-# LANGUAGE Safe #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module      :  System.Posix.User.Common
+-- 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 user\/group support
+--
+-----------------------------------------------------------------------------
+
+module System.Posix.User.Common where
+
+import Data.ByteString ( ByteString )
+import System.Posix.Types
+
+#include "HsUnix.h"
+
+
+#if defined(HAVE_PWD_H)
+import Foreign.Ptr
+import Foreign.Marshal
+import Foreign.Storable
+import Data.ByteString ( packCString )
+
+-- internal types
+data {-# CTYPE "struct passwd" #-} CPasswd
+data {-# CTYPE "struct group"  #-} CGroup
+
+data LKUPTYPE = GETONE | GETALL
+
+unpackGroupEntry :: Ptr CGroup -> IO GroupEntry
+unpackGroupEntry ptr = do
+   name    <- (#peek struct group, gr_name) ptr >>= packCString
+   passwd  <- (#peek struct group, gr_passwd) ptr >>= packCString
+   gid     <- (#peek struct group, gr_gid) ptr
+   mem     <- (#peek struct group, gr_mem) ptr
+   members <- peekArray0 nullPtr mem >>= mapM packCString
+   return (GroupEntry name passwd gid members)
+
+unpackUserEntry :: Ptr CPasswd -> IO UserEntry
+unpackUserEntry ptr = do
+   name   <- (#peek struct passwd, pw_name)   ptr >>= packCString
+   passwd <- (#peek struct passwd, pw_passwd) ptr >>= packCString
+   uid    <- (#peek struct passwd, pw_uid)    ptr
+   gid    <- (#peek struct passwd, pw_gid)    ptr
+#ifdef HAVE_NO_PASSWD_PW_GECOS
+   gecos  <- return ""  -- pw_gecos does not exist on android
+#else
+   gecos  <- (#peek struct passwd, pw_gecos)  ptr >>= packCString
+#endif
+   dir    <- (#peek struct passwd, pw_dir)    ptr >>= packCString
+   shell  <- (#peek struct passwd, pw_shell)  ptr >>= packCString
+   return (UserEntry name passwd uid gid gecos dir shell)
+
+#endif // HAVE_PWD_H
+
+data UserEntry =
+ UserEntry {
+   userName      :: ByteString,     -- ^ Textual name of this user (pw_name)
+   userPassword  :: ByteString,     -- ^ Password -- may be empty or fake if shadow is in use (pw_passwd)
+   userID        :: UserID,         -- ^ Numeric ID for this user (pw_uid)
+   userGroupID   :: GroupID,        -- ^ Primary group ID (pw_gid)
+   userGecos     :: ByteString,     -- ^ Usually the real name for the user (pw_gecos)
+   homeDirectory :: ByteString,     -- ^ Home directory (pw_dir)
+   userShell     :: ByteString      -- ^ Default shell (pw_shell)
+ } deriving (Show, Read, Eq)
+
+data GroupEntry =
+ GroupEntry {
+  groupName     :: ByteString,   -- ^ The name of this group (gr_name)
+  groupPassword :: ByteString,   -- ^ The password for this group (gr_passwd)
+  groupID       :: GroupID,      -- ^ The unique numeric ID for this group (gr_gid)
+  groupMembers  :: [ByteString]  -- ^ A list of zero or more usernames that are members (gr_mem)
+ } deriving (Show, Read, Eq)
diff --git a/cbits/HsUnix.c b/cbits/HsUnix.c
--- a/cbits/HsUnix.c
+++ b/cbits/HsUnix.c
@@ -16,16 +16,6 @@
 void *__hsunix_rtldDefault (void) {return RTLD_DEFAULT;}
 #endif
 
-#if HAVE_PTSNAME && (__GLASGOW_HASKELL__ < 800)
-// On Linux (and others), <stdlib.h> needs to be included while
-// `_XOPEN_SOURCE` is already defined. However, GHCs before GHC 8.0
-// didn't do that yet for CApiFFI, so we need this workaround here.
-
-char *__hsunix_ptsname(int fd)   { return ptsname(fd);  }
-int   __hsunix_grantpt(int fd)   { return grantpt(fd);  }
-int   __hsunix_unlockpt(int fd)  { return unlockpt(fd); }
-#endif
-
 // push a SVR4 STREAMS module; do nothing if STREAMS not available
 int __hsunix_push_module(int fd, const char *module)
 {
@@ -36,6 +26,10 @@
 #endif
 }
 
+#ifdef HAVE_CLOCKS_PER_SEC
+clock_t __hsunix_clocks_per_second (void) {return CLOCKS_PER_SEC;}
+#endif
+
 /*
  * GNU glibc 2.23 and later deprecate `readdir_r` in favour of plain old
  * `readdir` which in some upcoming POSIX standard is going to required to be
@@ -43,7 +37,7 @@
  * Eventually we want to drop `readder_r` all together, but want to be
  * compatible with older unixen which may not have a re-entrant `readdir`.
  * Solution is to make systems with *known* re-entrant `readir` use that and use
- * `readdir_r` whereever we have it and don't *know* that `readdir` is
+ * `readdir_r` wherever we have it and don't *know* that `readdir` is
  * re-entrant.
  */
 
diff --git a/cbits/execvpe.c b/cbits/execvpe.c
--- a/cbits/execvpe.c
+++ b/cbits/execvpe.c
@@ -3,7 +3,7 @@
 
    Our low-level exec() variant.
 
-   Note: __hsunix_execvpe() is very similiar to the function
+   Note: __hsunix_execvpe() is very similar to the function
          execvpe(3) as provided by glibc 2.11 and later. However, if
          execvpe(3) is available, we use that instead.
 
@@ -22,7 +22,6 @@
 #include <string.h>
 #include <errno.h>
 
-#define HSUNIX_EXECVPE_H_NO_COMPAT
 #include "execvpe.h"
 
 #if !defined(execvpe) && !HAVE_DECL_EXECVPE
@@ -72,6 +71,9 @@
 {
 #if HAVE_EXECVPE
     return execvpe(name, argv, envp);
+#elif !defined(HAVE_EXECV)
+    errno = ENOSYS;
+    return (-1);
 #else
     register int lp, ln;
     register char *p;
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,22 +1,71 @@
 # Changelog for [`unix` package](http://hackage.haskell.org/package/unix)
 
-## 2.7.2.3  *Unreleased*
+## 2.8.0.0 *August 2022*
+  * Use ByteString for GroupEntry/UserEntry
 
-  * Resource: Fix warning in case of no RLIM_SAVED_{CUR,MAX}
+  * Fix `semTrywait` on darwin
 
-  * Future-proof glibc version check
+  * Fix vanishing environment variables in `System.Posix.Env.ByteString.putEnv`/`System.Posix.Env.ByteString.getEnv`
 
-  * Fix the error handling of posix_fallocate in non-FreeBSD
+  * Add missing `setEnvironment` and `clearEnv` to `System.Posix.Env.ByteString`
 
-  * Synchronize ByteString and String modules and fix grave bug in 'putEnv'
+  * Add support for filepath-1.4.100.0 with `PosixString` variants
 
-  * Fix 'semTrywait: invalid argument (Bad file descriptor)' wrt #218
+  * Expose `DirStream`, `CDir`, `CDirent` and `DirStreamOffset` (internal API)
 
-  * Improve error messages
+  * Add `fdRead`/`fdWrite` with ByteString payload and deprecate String based `fdRead`
 
-  * Improve tests
+  * Add `clocksPerSec`
 
-  * Don't show repo as modified after configure
+  * Support wasm32-wasi
+
+  * Implement BaudRate as an `Int` newtype and allow matching via extensible PatternSynonyms
+
+  * Added `readDirStreamMaybe`
+
+  * Warn when functions are used on unsupported platforms
+
+  * Fix the error handling of `posix_fallocate`
+
+  * Export `FileStatus` constructor
+
+  * Various documentation and error message improvements
+
+  * Add openDirStreamFd, openFileAt and createFileAt
+
+  * Add accessors for st_blocks and st_blksize
+
+  * Deal with FreeBSD getpwnam_r(3), ... thread safety.  On FreeBSD these
+    are not in fact safe for overlapped execution with a sequence of
+    getpwent(3) or getgrent(3) calls when multiple "green" threads share
+    the same underlying OS thread.  The *ent(3) calls now run in bound
+    threads or else locks are used to avoid overlapped execution.
+
+  * Make passwd/group FFI functions "safe", these are not low-latency APIs.
+
+  * Drop support for non-thread-safe getpwnam(3) and getpwuid(3).  All
+    supported platforms have getpwnam_r(3) and getpwuid_r(3).  This was
+    already the case for the getgr(nam|gid) calls.
+
+  * Added terminal output flags to `System.Posix.Terminal.Common.TerminalMode`
+
+        IXANY, ONLCR, OCRNL, ONOCR, ONLRET, OFDEL, OFILL, NLDLY(NL0,NL1),
+        CRDLY(CR0,CR1,CR2,CR2), TABDLY(TAB0,TAB1,TAB2,TAB3) BSDLY(BS0,BS1),
+        VTDLY(VT0,VT1), FFDLY(FF0,FF1)
+
+  * Add support for `O_NOFOLLOW`, `O_CLOEXEC`, `O_DIRECTORY` and `O_SYNC`
+    (#6, #57)
+
+  * Refactor API of `openFd` removing `Maybe FileMode` argument,
+    which now must be passed as part of `OpenFileFlags`
+    (e.g. `defaultFileFlags { creat = Just mode }`)  (#58)
+
+  * Remove deprecated `execvpe(3)` legacy-emulation CPP macro
+
+  * Generalise return type of `exitImmediately` from `ExitCode -> IO ()` to
+    `∀a. ExitCode -> IO a` (#130)
+
+  * Add `Read`, `Show`, `Eq`, and `Ord` typeclass instances to `OpenFileFlags` and `OpenMode`. (#75, #141)
 
 ## 2.7.2.2  *May 2017*
 
diff --git a/config.guess b/config.guess
--- a/config.guess
+++ b/config.guess
@@ -1,1699 +1,1465 @@
 #! /bin/sh
 # Attempt to guess a canonical system name.
-#   Copyright 1992-2021 Free Software Foundation, Inc.
-
-timestamp='2021-01-25'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <https://www.gnu.org/licenses/>.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that
-# program.  This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-#
-# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
-#
-# You can get the latest version of this script from:
-# https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
-#
-# Please send patches to <config-patches@gnu.org>.
-
-
-me=$(echo "$0" | sed -e 's,.*/,,')
-
-usage="\
-Usage: $0 [OPTION]
-
-Output the configuration name of the system \`$me' is run on.
-
-Options:
-  -h, --help         print this help, then exit
-  -t, --time-stamp   print date of last modification, then exit
-  -v, --version      print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.guess ($timestamp)
-
-Originally written by Per Bothner.
-Copyright 1992-2021 Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions.  There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
-  case $1 in
-    --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
-    --version | -v )
-       echo "$version" ; exit ;;
-    --help | --h* | -h )
-       echo "$usage"; exit ;;
-    -- )     # Stop option processing
-       shift; break ;;
-    - )	# Use stdin as input.
-       break ;;
-    -* )
-       echo "$me: invalid option $1$help" >&2
-       exit 1 ;;
-    * )
-       break ;;
-  esac
-done
-
-if test $# != 0; then
-  echo "$me: too many arguments$help" >&2
-  exit 1
-fi
-
-# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
-# compiler to aid in system detection is discouraged as it requires
-# temporary files to be created and, as you can see below, it is a
-# headache to deal with in a portable fashion.
-
-# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
-# use `HOST_CC' if defined, but it is deprecated.
-
-# Portable tmp directory creation inspired by the Autoconf team.
-
-tmp=
-# shellcheck disable=SC2172
-trap 'test -z "$tmp" || rm -fr "$tmp"' 0 1 2 13 15
-
-set_cc_for_build() {
-    # prevent multiple calls if $tmp is already set
-    test "$tmp" && return 0
-    : "${TMPDIR=/tmp}"
-    # shellcheck disable=SC2039
-    { tmp=$( (umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null) && test -n "$tmp" && test -d "$tmp" ; } ||
-	{ test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir "$tmp" 2>/dev/null) ; } ||
-	{ tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir "$tmp" 2>/dev/null) && echo "Warning: creating insecure temp directory" >&2 ; } ||
-	{ echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; }
-    dummy=$tmp/dummy
-    case ${CC_FOR_BUILD-},${HOST_CC-},${CC-} in
-	,,)    echo "int x;" > "$dummy.c"
-	       for driver in cc gcc c89 c99 ; do
-		   if ($driver -c -o "$dummy.o" "$dummy.c") >/dev/null 2>&1 ; then
-		       CC_FOR_BUILD="$driver"
-		       break
-		   fi
-	       done
-	       if test x"$CC_FOR_BUILD" = x ; then
-		   CC_FOR_BUILD=no_compiler_found
-	       fi
-	       ;;
-	,,*)   CC_FOR_BUILD=$CC ;;
-	,*,*)  CC_FOR_BUILD=$HOST_CC ;;
-    esac
-}
-
-# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
-# (ghazi@noc.rutgers.edu 1994-08-24)
-if test -f /.attbin/uname ; then
-	PATH=$PATH:/.attbin ; export PATH
-fi
-
-UNAME_MACHINE=$( (uname -m) 2>/dev/null) || UNAME_MACHINE=unknown
-UNAME_RELEASE=$( (uname -r) 2>/dev/null) || UNAME_RELEASE=unknown
-UNAME_SYSTEM=$( (uname -s) 2>/dev/null) || UNAME_SYSTEM=unknown
-UNAME_VERSION=$( (uname -v) 2>/dev/null) || UNAME_VERSION=unknown
-
-case "$UNAME_SYSTEM" in
-Linux|GNU|GNU/*)
-	LIBC=unknown
-
-	set_cc_for_build
-	cat <<-EOF > "$dummy.c"
-	#include <features.h>
-	#if defined(__UCLIBC__)
-	LIBC=uclibc
-	#elif defined(__dietlibc__)
-	LIBC=dietlibc
-	#elif defined(__GLIBC__)
-	LIBC=gnu
-	#else
-	#include <stdarg.h>
-	/* First heuristic to detect musl libc.  */
-	#ifdef __DEFINED_va_list
-	LIBC=musl
-	#endif
-	#endif
-	EOF
-	eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^LIBC' | sed 's, ,,g')"
-
-	# Second heuristic to detect musl libc.
-	if [ "$LIBC" = unknown ] &&
-	   command -v ldd >/dev/null &&
-	   ldd --version 2>&1 | grep -q ^musl; then
-		LIBC=musl
-	fi
-
-	# If the system lacks a compiler, then just pick glibc.
-	# We could probably try harder.
-	if [ "$LIBC" = unknown ]; then
-		LIBC=gnu
-	fi
-	;;
-esac
-
-# Note: order is significant - the case branches are not exclusive.
-
-case "$UNAME_MACHINE:$UNAME_SYSTEM:$UNAME_RELEASE:$UNAME_VERSION" in
-    *:NetBSD:*:*)
-	# NetBSD (nbsd) targets should (where applicable) match one or
-	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
-	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
-	# switched to ELF, *-*-netbsd* would select the old
-	# object file format.  This provides both forward
-	# compatibility and a consistent mechanism for selecting the
-	# object file format.
-	#
-	# Note: NetBSD doesn't particularly care about the vendor
-	# portion of the name.  We always set it to "unknown".
-	UNAME_MACHINE_ARCH=$( (uname -p 2>/dev/null || \
-	    /sbin/sysctl -n hw.machine_arch 2>/dev/null || \
-	    /usr/sbin/sysctl -n hw.machine_arch 2>/dev/null || \
-	    echo unknown))
-	case "$UNAME_MACHINE_ARCH" in
-	    aarch64eb) machine=aarch64_be-unknown ;;
-	    armeb) machine=armeb-unknown ;;
-	    arm*) machine=arm-unknown ;;
-	    sh3el) machine=shl-unknown ;;
-	    sh3eb) machine=sh-unknown ;;
-	    sh5el) machine=sh5le-unknown ;;
-	    earmv*)
-		arch=$(echo "$UNAME_MACHINE_ARCH" | sed -e 's,^e\(armv[0-9]\).*$,\1,')
-		endian=$(echo "$UNAME_MACHINE_ARCH" | sed -ne 's,^.*\(eb\)$,\1,p')
-		machine="${arch}${endian}"-unknown
-		;;
-	    *) machine="$UNAME_MACHINE_ARCH"-unknown ;;
-	esac
-	# The Operating System including object format, if it has switched
-	# to ELF recently (or will in the future) and ABI.
-	case "$UNAME_MACHINE_ARCH" in
-	    earm*)
-		os=netbsdelf
-		;;
-	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
-		set_cc_for_build
-		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
-			| grep -q __ELF__
-		then
-		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
-		    # Return netbsd for either.  FIX?
-		    os=netbsd
-		else
-		    os=netbsdelf
-		fi
-		;;
-	    *)
-		os=netbsd
-		;;
-	esac
-	# Determine ABI tags.
-	case "$UNAME_MACHINE_ARCH" in
-	    earm*)
-		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
-		abi=$(echo "$UNAME_MACHINE_ARCH" | sed -e "$expr")
-		;;
-	esac
-	# The OS release
-	# Debian GNU/NetBSD machines have a different userland, and
-	# thus, need a distinct triplet. However, they do not need
-	# kernel version information, so it can be replaced with a
-	# suitable tag, in the style of linux-gnu.
-	case "$UNAME_VERSION" in
-	    Debian*)
-		release='-gnu'
-		;;
-	    *)
-		release=$(echo "$UNAME_RELEASE" | sed -e 's/[-_].*//' | cut -d. -f1,2)
-		;;
-	esac
-	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
-	# contains redundant information, the shorter form:
-	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
-	echo "$machine-${os}${release}${abi-}"
-	exit ;;
-    *:Bitrig:*:*)
-	UNAME_MACHINE_ARCH=$(arch | sed 's/Bitrig.//')
-	echo "$UNAME_MACHINE_ARCH"-unknown-bitrig"$UNAME_RELEASE"
-	exit ;;
-    *:OpenBSD:*:*)
-	UNAME_MACHINE_ARCH=$(arch | sed 's/OpenBSD.//')
-	echo "$UNAME_MACHINE_ARCH"-unknown-openbsd"$UNAME_RELEASE"
-	exit ;;
-    *:LibertyBSD:*:*)
-	UNAME_MACHINE_ARCH=$(arch | sed 's/^.*BSD\.//')
-	echo "$UNAME_MACHINE_ARCH"-unknown-libertybsd"$UNAME_RELEASE"
-	exit ;;
-    *:MidnightBSD:*:*)
-	echo "$UNAME_MACHINE"-unknown-midnightbsd"$UNAME_RELEASE"
-	exit ;;
-    *:ekkoBSD:*:*)
-	echo "$UNAME_MACHINE"-unknown-ekkobsd"$UNAME_RELEASE"
-	exit ;;
-    *:SolidBSD:*:*)
-	echo "$UNAME_MACHINE"-unknown-solidbsd"$UNAME_RELEASE"
-	exit ;;
-    *:OS108:*:*)
-	echo "$UNAME_MACHINE"-unknown-os108_"$UNAME_RELEASE"
-	exit ;;
-    macppc:MirBSD:*:*)
-	echo powerpc-unknown-mirbsd"$UNAME_RELEASE"
-	exit ;;
-    *:MirBSD:*:*)
-	echo "$UNAME_MACHINE"-unknown-mirbsd"$UNAME_RELEASE"
-	exit ;;
-    *:Sortix:*:*)
-	echo "$UNAME_MACHINE"-unknown-sortix
-	exit ;;
-    *:Twizzler:*:*)
-	echo "$UNAME_MACHINE"-unknown-twizzler
-	exit ;;
-    *:Redox:*:*)
-	echo "$UNAME_MACHINE"-unknown-redox
-	exit ;;
-    mips:OSF1:*.*)
-	echo mips-dec-osf1
-	exit ;;
-    alpha:OSF1:*:*)
-	case $UNAME_RELEASE in
-	*4.0)
-		UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $3}')
-		;;
-	*5.*)
-		UNAME_RELEASE=$(/usr/sbin/sizer -v | awk '{print $4}')
-		;;
-	esac
-	# According to Compaq, /usr/sbin/psrinfo has been available on
-	# OSF/1 and Tru64 systems produced since 1995.  I hope that
-	# covers most systems running today.  This code pipes the CPU
-	# types through head -n 1, so we only detect the type of CPU 0.
-	ALPHA_CPU_TYPE=$(/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1)
-	case "$ALPHA_CPU_TYPE" in
-	    "EV4 (21064)")
-		UNAME_MACHINE=alpha ;;
-	    "EV4.5 (21064)")
-		UNAME_MACHINE=alpha ;;
-	    "LCA4 (21066/21068)")
-		UNAME_MACHINE=alpha ;;
-	    "EV5 (21164)")
-		UNAME_MACHINE=alphaev5 ;;
-	    "EV5.6 (21164A)")
-		UNAME_MACHINE=alphaev56 ;;
-	    "EV5.6 (21164PC)")
-		UNAME_MACHINE=alphapca56 ;;
-	    "EV5.7 (21164PC)")
-		UNAME_MACHINE=alphapca57 ;;
-	    "EV6 (21264)")
-		UNAME_MACHINE=alphaev6 ;;
-	    "EV6.7 (21264A)")
-		UNAME_MACHINE=alphaev67 ;;
-	    "EV6.8CB (21264C)")
-		UNAME_MACHINE=alphaev68 ;;
-	    "EV6.8AL (21264B)")
-		UNAME_MACHINE=alphaev68 ;;
-	    "EV6.8CX (21264D)")
-		UNAME_MACHINE=alphaev68 ;;
-	    "EV6.9A (21264/EV69A)")
-		UNAME_MACHINE=alphaev69 ;;
-	    "EV7 (21364)")
-		UNAME_MACHINE=alphaev7 ;;
-	    "EV7.9 (21364A)")
-		UNAME_MACHINE=alphaev79 ;;
-	esac
-	# A Pn.n version is a patched version.
-	# A Vn.n version is a released version.
-	# A Tn.n version is a released field test version.
-	# A Xn.n version is an unreleased experimental baselevel.
-	# 1.2 uses "1.2" for uname -r.
-	echo "$UNAME_MACHINE"-dec-osf"$(echo "$UNAME_RELEASE" | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)"
-	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
-	exitcode=$?
-	trap '' 0
-	exit $exitcode ;;
-    Amiga*:UNIX_System_V:4.0:*)
-	echo m68k-unknown-sysv4
-	exit ;;
-    *:[Aa]miga[Oo][Ss]:*:*)
-	echo "$UNAME_MACHINE"-unknown-amigaos
-	exit ;;
-    *:[Mm]orph[Oo][Ss]:*:*)
-	echo "$UNAME_MACHINE"-unknown-morphos
-	exit ;;
-    *:OS/390:*:*)
-	echo i370-ibm-openedition
-	exit ;;
-    *:z/VM:*:*)
-	echo s390-ibm-zvmoe
-	exit ;;
-    *:OS400:*:*)
-	echo powerpc-ibm-os400
-	exit ;;
-    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
-	echo arm-acorn-riscix"$UNAME_RELEASE"
-	exit ;;
-    arm*:riscos:*:*|arm*:RISCOS:*:*)
-	echo arm-unknown-riscos
-	exit ;;
-    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
-	echo hppa1.1-hitachi-hiuxmpp
-	exit ;;
-    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
-	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
-	if test "$( (/bin/universe) 2>/dev/null)" = att ; then
-		echo pyramid-pyramid-sysv3
-	else
-		echo pyramid-pyramid-bsd
-	fi
-	exit ;;
-    NILE*:*:*:dcosx)
-	echo pyramid-pyramid-svr4
-	exit ;;
-    DRS?6000:unix:4.0:6*)
-	echo sparc-icl-nx6
-	exit ;;
-    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
-	case $(/usr/bin/uname -p) in
-	    sparc) echo sparc-icl-nx7; exit ;;
-	esac ;;
-    s390x:SunOS:*:*)
-	echo "$UNAME_MACHINE"-ibm-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
-	exit ;;
-    sun4H:SunOS:5.*:*)
-	echo sparc-hal-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
-	exit ;;
-    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
-	echo sparc-sun-solaris2"$(echo "$UNAME_RELEASE" | sed -e 's/[^.]*//')"
-	exit ;;
-    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
-	echo i386-pc-auroraux"$UNAME_RELEASE"
-	exit ;;
-    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
-	set_cc_for_build
-	SUN_ARCH=i386
-	# If there is a compiler, see if it is configured for 64-bit objects.
-	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
-	# This test works for both compilers.
-	if test "$CC_FOR_BUILD" != no_compiler_found; then
-	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
-		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		grep IS_64BIT_ARCH >/dev/null
-	    then
-		SUN_ARCH=x86_64
-	    fi
-	fi
-	echo "$SUN_ARCH"-pc-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
-	exit ;;
-    sun4*:SunOS:6*:*)
-	# According to config.sub, this is the proper way to canonicalize
-	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
-	# it's likely to be more like Solaris than SunOS4.
-	echo sparc-sun-solaris3"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
-	exit ;;
-    sun4*:SunOS:*:*)
-	case "$(/usr/bin/arch -k)" in
-	    Series*|S4*)
-		UNAME_RELEASE=$(uname -v)
-		;;
-	esac
-	# Japanese Language versions have a version number like `4.1.3-JL'.
-	echo sparc-sun-sunos"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/')"
-	exit ;;
-    sun3*:SunOS:*:*)
-	echo m68k-sun-sunos"$UNAME_RELEASE"
-	exit ;;
-    sun*:*:4.2BSD:*)
-	UNAME_RELEASE=$( (sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null)
-	test "x$UNAME_RELEASE" = x && UNAME_RELEASE=3
-	case "$(/bin/arch)" in
-	    sun3)
-		echo m68k-sun-sunos"$UNAME_RELEASE"
-		;;
-	    sun4)
-		echo sparc-sun-sunos"$UNAME_RELEASE"
-		;;
-	esac
-	exit ;;
-    aushp:SunOS:*:*)
-	echo sparc-auspex-sunos"$UNAME_RELEASE"
-	exit ;;
-    # The situation for MiNT is a little confusing.  The machine name
-    # can be virtually everything (everything which is not
-    # "atarist" or "atariste" at least should have a processor
-    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
-    # to the lowercase version "mint" (or "freemint").  Finally
-    # the system name "TOS" denotes a system which is actually not
-    # MiNT.  But MiNT is downward compatible to TOS, so this should
-    # be no problem.
-    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
-	echo m68k-atari-mint"$UNAME_RELEASE"
-	exit ;;
-    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
-	echo m68k-atari-mint"$UNAME_RELEASE"
-	exit ;;
-    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
-	echo m68k-atari-mint"$UNAME_RELEASE"
-	exit ;;
-    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
-	echo m68k-milan-mint"$UNAME_RELEASE"
-	exit ;;
-    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
-	echo m68k-hades-mint"$UNAME_RELEASE"
-	exit ;;
-    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
-	echo m68k-unknown-mint"$UNAME_RELEASE"
-	exit ;;
-    m68k:machten:*:*)
-	echo m68k-apple-machten"$UNAME_RELEASE"
-	exit ;;
-    powerpc:machten:*:*)
-	echo powerpc-apple-machten"$UNAME_RELEASE"
-	exit ;;
-    RISC*:Mach:*:*)
-	echo mips-dec-mach_bsd4.3
-	exit ;;
-    RISC*:ULTRIX:*:*)
-	echo mips-dec-ultrix"$UNAME_RELEASE"
-	exit ;;
-    VAX*:ULTRIX*:*:*)
-	echo vax-dec-ultrix"$UNAME_RELEASE"
-	exit ;;
-    2020:CLIX:*:* | 2430:CLIX:*:*)
-	echo clipper-intergraph-clix"$UNAME_RELEASE"
-	exit ;;
-    mips:*:*:UMIPS | mips:*:*:RISCos)
-	set_cc_for_build
-	sed 's/^	//' << EOF > "$dummy.c"
-#ifdef __cplusplus
-#include <stdio.h>  /* for printf() prototype */
-	int main (int argc, char *argv[]) {
-#else
-	int main (argc, argv) int argc; char *argv[]; {
-#endif
-	#if defined (host_mips) && defined (MIPSEB)
-	#if defined (SYSTYPE_SYSV)
-	  printf ("mips-mips-riscos%ssysv\\n", argv[1]); exit (0);
-	#endif
-	#if defined (SYSTYPE_SVR4)
-	  printf ("mips-mips-riscos%ssvr4\\n", argv[1]); exit (0);
-	#endif
-	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
-	  printf ("mips-mips-riscos%sbsd\\n", argv[1]); exit (0);
-	#endif
-	#endif
-	  exit (-1);
-	}
-EOF
-	$CC_FOR_BUILD -o "$dummy" "$dummy.c" &&
-	  dummyarg=$(echo "$UNAME_RELEASE" | sed -n 's/\([0-9]*\).*/\1/p') &&
-	  SYSTEM_NAME=$("$dummy" "$dummyarg") &&
-	    { echo "$SYSTEM_NAME"; exit; }
-	echo mips-mips-riscos"$UNAME_RELEASE"
-	exit ;;
-    Motorola:PowerMAX_OS:*:*)
-	echo powerpc-motorola-powermax
-	exit ;;
-    Motorola:*:4.3:PL8-*)
-	echo powerpc-harris-powermax
-	exit ;;
-    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
-	echo powerpc-harris-powermax
-	exit ;;
-    Night_Hawk:Power_UNIX:*:*)
-	echo powerpc-harris-powerunix
-	exit ;;
-    m88k:CX/UX:7*:*)
-	echo m88k-harris-cxux7
-	exit ;;
-    m88k:*:4*:R4*)
-	echo m88k-motorola-sysv4
-	exit ;;
-    m88k:*:3*:R3*)
-	echo m88k-motorola-sysv3
-	exit ;;
-    AViiON:dgux:*:*)
-	# DG/UX returns AViiON for all architectures
-	UNAME_PROCESSOR=$(/usr/bin/uname -p)
-	if test "$UNAME_PROCESSOR" = mc88100 || test "$UNAME_PROCESSOR" = mc88110
-	then
-	    if test "$TARGET_BINARY_INTERFACE"x = m88kdguxelfx || \
-	       test "$TARGET_BINARY_INTERFACE"x = x
-	    then
-		echo m88k-dg-dgux"$UNAME_RELEASE"
-	    else
-		echo m88k-dg-dguxbcs"$UNAME_RELEASE"
-	    fi
-	else
-	    echo i586-dg-dgux"$UNAME_RELEASE"
-	fi
-	exit ;;
-    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
-	echo m88k-dolphin-sysv3
-	exit ;;
-    M88*:*:R3*:*)
-	# Delta 88k system running SVR3
-	echo m88k-motorola-sysv3
-	exit ;;
-    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
-	echo m88k-tektronix-sysv3
-	exit ;;
-    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
-	echo m68k-tektronix-bsd
-	exit ;;
-    *:IRIX*:*:*)
-	echo mips-sgi-irix"$(echo "$UNAME_RELEASE"|sed -e 's/-/_/g')"
-	exit ;;
-    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
-	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
-	exit ;;               # Note that: echo "'$(uname -s)'" gives 'AIX '
-    i*86:AIX:*:*)
-	echo i386-ibm-aix
-	exit ;;
-    ia64:AIX:*:*)
-	if test -x /usr/bin/oslevel ; then
-		IBM_REV=$(/usr/bin/oslevel)
-	else
-		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
-	fi
-	echo "$UNAME_MACHINE"-ibm-aix"$IBM_REV"
-	exit ;;
-    *:AIX:2:3)
-	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
-		set_cc_for_build
-		sed 's/^		//' << EOF > "$dummy.c"
-		#include <sys/systemcfg.h>
-
-		main()
-			{
-			if (!__power_pc())
-				exit(1);
-			puts("powerpc-ibm-aix3.2.5");
-			exit(0);
-			}
-EOF
-		if $CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy")
-		then
-			echo "$SYSTEM_NAME"
-		else
-			echo rs6000-ibm-aix3.2.5
-		fi
-	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
-		echo rs6000-ibm-aix3.2.4
-	else
-		echo rs6000-ibm-aix3.2
-	fi
-	exit ;;
-    *:AIX:*:[4567])
-	IBM_CPU_ID=$(/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }')
-	if /usr/sbin/lsattr -El "$IBM_CPU_ID" | grep ' POWER' >/dev/null 2>&1; then
-		IBM_ARCH=rs6000
-	else
-		IBM_ARCH=powerpc
-	fi
-	if test -x /usr/bin/lslpp ; then
-		IBM_REV=$(/usr/bin/lslpp -Lqc bos.rte.libc |
-			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/)
-	else
-		IBM_REV="$UNAME_VERSION.$UNAME_RELEASE"
-	fi
-	echo "$IBM_ARCH"-ibm-aix"$IBM_REV"
-	exit ;;
-    *:AIX:*:*)
-	echo rs6000-ibm-aix
-	exit ;;
-    ibmrt:4.4BSD:*|romp-ibm:4.4BSD:*)
-	echo romp-ibm-bsd4.4
-	exit ;;
-    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
-	echo romp-ibm-bsd"$UNAME_RELEASE"   # 4.3 with uname added to
-	exit ;;                             # report: romp-ibm BSD 4.3
-    *:BOSX:*:*)
-	echo rs6000-bull-bosx
-	exit ;;
-    DPX/2?00:B.O.S.:*:*)
-	echo m68k-bull-sysv3
-	exit ;;
-    9000/[34]??:4.3bsd:1.*:*)
-	echo m68k-hp-bsd
-	exit ;;
-    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
-	echo m68k-hp-bsd4.4
-	exit ;;
-    9000/[34678]??:HP-UX:*:*)
-	HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
-	case "$UNAME_MACHINE" in
-	    9000/31?)            HP_ARCH=m68000 ;;
-	    9000/[34]??)         HP_ARCH=m68k ;;
-	    9000/[678][0-9][0-9])
-		if test -x /usr/bin/getconf; then
-		    sc_cpu_version=$(/usr/bin/getconf SC_CPU_VERSION 2>/dev/null)
-		    sc_kernel_bits=$(/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null)
-		    case "$sc_cpu_version" in
-		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
-		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
-		      532)                      # CPU_PA_RISC2_0
-			case "$sc_kernel_bits" in
-			  32) HP_ARCH=hppa2.0n ;;
-			  64) HP_ARCH=hppa2.0w ;;
-			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
-			esac ;;
-		    esac
-		fi
-		if test "$HP_ARCH" = ""; then
-		    set_cc_for_build
-		    sed 's/^		//' << EOF > "$dummy.c"
-
-		#define _HPUX_SOURCE
-		#include <stdlib.h>
-		#include <unistd.h>
-
-		int main ()
-		{
-		#if defined(_SC_KERNEL_BITS)
-		    long bits = sysconf(_SC_KERNEL_BITS);
-		#endif
-		    long cpu  = sysconf (_SC_CPU_VERSION);
-
-		    switch (cpu)
-			{
-			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
-			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
-			case CPU_PA_RISC2_0:
-		#if defined(_SC_KERNEL_BITS)
-			    switch (bits)
-				{
-				case 64: puts ("hppa2.0w"); break;
-				case 32: puts ("hppa2.0n"); break;
-				default: puts ("hppa2.0"); break;
-				} break;
-		#else  /* !defined(_SC_KERNEL_BITS) */
-			    puts ("hppa2.0"); break;
-		#endif
-			default: puts ("hppa1.0"); break;
-			}
-		    exit (0);
-		}
-EOF
-		    (CCOPTS="" $CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null) && HP_ARCH=$("$dummy")
-		    test -z "$HP_ARCH" && HP_ARCH=hppa
-		fi ;;
-	esac
-	if test "$HP_ARCH" = hppa2.0w
-	then
-	    set_cc_for_build
-
-	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
-	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
-	    # generating 64-bit code.  GNU and HP use different nomenclature:
-	    #
-	    # $ CC_FOR_BUILD=cc ./config.guess
-	    # => hppa2.0w-hp-hpux11.23
-	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
-	    # => hppa64-hp-hpux11.23
-
-	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
-		grep -q __LP64__
-	    then
-		HP_ARCH=hppa2.0w
-	    else
-		HP_ARCH=hppa64
-	    fi
-	fi
-	echo "$HP_ARCH"-hp-hpux"$HPUX_REV"
-	exit ;;
-    ia64:HP-UX:*:*)
-	HPUX_REV=$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*.[0B]*//')
-	echo ia64-hp-hpux"$HPUX_REV"
-	exit ;;
-    3050*:HI-UX:*:*)
-	set_cc_for_build
-	sed 's/^	//' << EOF > "$dummy.c"
-	#include <unistd.h>
-	int
-	main ()
-	{
-	  long cpu = sysconf (_SC_CPU_VERSION);
-	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
-	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
-	     results, however.  */
-	  if (CPU_IS_PA_RISC (cpu))
-	    {
-	      switch (cpu)
-		{
-		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
-		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
-		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
-		  default: puts ("hppa-hitachi-hiuxwe2"); break;
-		}
-	    }
-	  else if (CPU_IS_HP_MC68K (cpu))
-	    puts ("m68k-hitachi-hiuxwe2");
-	  else puts ("unknown-hitachi-hiuxwe2");
-	  exit (0);
-	}
-EOF
-	$CC_FOR_BUILD -o "$dummy" "$dummy.c" && SYSTEM_NAME=$("$dummy") &&
-		{ echo "$SYSTEM_NAME"; exit; }
-	echo unknown-hitachi-hiuxwe2
-	exit ;;
-    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:*)
-	echo hppa1.1-hp-bsd
-	exit ;;
-    9000/8??:4.3bsd:*:*)
-	echo hppa1.0-hp-bsd
-	exit ;;
-    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
-	echo hppa1.0-hp-mpeix
-	exit ;;
-    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:*)
-	echo hppa1.1-hp-osf
-	exit ;;
-    hp8??:OSF1:*:*)
-	echo hppa1.0-hp-osf
-	exit ;;
-    i*86:OSF1:*:*)
-	if test -x /usr/sbin/sysversion ; then
-	    echo "$UNAME_MACHINE"-unknown-osf1mk
-	else
-	    echo "$UNAME_MACHINE"-unknown-osf1
-	fi
-	exit ;;
-    parisc*:Lites*:*:*)
-	echo hppa1.1-hp-lites
-	exit ;;
-    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
-	echo c1-convex-bsd
-	exit ;;
-    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
-	if getsysinfo -f scalar_acc
-	then echo c32-convex-bsd
-	else echo c2-convex-bsd
-	fi
-	exit ;;
-    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
-	echo c34-convex-bsd
-	exit ;;
-    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
-	echo c38-convex-bsd
-	exit ;;
-    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
-	echo c4-convex-bsd
-	exit ;;
-    CRAY*Y-MP:*:*:*)
-	echo ymp-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    CRAY*[A-Z]90:*:*:*)
-	echo "$UNAME_MACHINE"-cray-unicos"$UNAME_RELEASE" \
-	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
-	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
-	      -e 's/\.[^.]*$/.X/'
-	exit ;;
-    CRAY*TS:*:*:*)
-	echo t90-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    CRAY*T3E:*:*:*)
-	echo alphaev5-cray-unicosmk"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    CRAY*SV1:*:*:*)
-	echo sv1-cray-unicos"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    *:UNICOS/mp:*:*)
-	echo craynv-cray-unicosmp"$UNAME_RELEASE" | sed -e 's/\.[^.]*$/.X/'
-	exit ;;
-    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
-	FUJITSU_PROC=$(uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz)
-	FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
-	FUJITSU_REL=$(echo "$UNAME_RELEASE" | sed -e 's/ /_/')
-	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-	exit ;;
-    5000:UNIX_System_V:4.*:*)
-	FUJITSU_SYS=$(uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///')
-	FUJITSU_REL=$(echo "$UNAME_RELEASE" | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/')
-	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
-	exit ;;
-    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
-	echo "$UNAME_MACHINE"-pc-bsdi"$UNAME_RELEASE"
-	exit ;;
-    sparc*:BSD/OS:*:*)
-	echo sparc-unknown-bsdi"$UNAME_RELEASE"
-	exit ;;
-    *:BSD/OS:*:*)
-	echo "$UNAME_MACHINE"-unknown-bsdi"$UNAME_RELEASE"
-	exit ;;
-    arm:FreeBSD:*:*)
-	UNAME_PROCESSOR=$(uname -p)
-	set_cc_for_build
-	if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
-	    | grep -q __ARM_PCS_VFP
-	then
-	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabi
-	else
-	    echo "${UNAME_PROCESSOR}"-unknown-freebsd"$(echo ${UNAME_RELEASE}|sed -e 's/[-(].*//')"-gnueabihf
-	fi
-	exit ;;
-    *:FreeBSD:*:*)
-	UNAME_PROCESSOR=$(/usr/bin/uname -p)
-	case "$UNAME_PROCESSOR" in
-	    amd64)
-		UNAME_PROCESSOR=x86_64 ;;
-	    i386)
-		UNAME_PROCESSOR=i586 ;;
-	esac
-	echo "$UNAME_PROCESSOR"-unknown-freebsd"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
-	exit ;;
-    i*:CYGWIN*:*)
-	echo "$UNAME_MACHINE"-pc-cygwin
-	exit ;;
-    *:MINGW64*:*)
-	echo "$UNAME_MACHINE"-pc-mingw64
-	exit ;;
-    *:MINGW*:*)
-	echo "$UNAME_MACHINE"-pc-mingw32
-	exit ;;
-    *:MSYS*:*)
-	echo "$UNAME_MACHINE"-pc-msys
-	exit ;;
-    i*:PW*:*)
-	echo "$UNAME_MACHINE"-pc-pw32
-	exit ;;
-    *:Interix*:*)
-	case "$UNAME_MACHINE" in
-	    x86)
-		echo i586-pc-interix"$UNAME_RELEASE"
-		exit ;;
-	    authenticamd | genuineintel | EM64T)
-		echo x86_64-unknown-interix"$UNAME_RELEASE"
-		exit ;;
-	    IA64)
-		echo ia64-unknown-interix"$UNAME_RELEASE"
-		exit ;;
-	esac ;;
-    i*:UWIN*:*)
-	echo "$UNAME_MACHINE"-pc-uwin
-	exit ;;
-    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
-	echo x86_64-pc-cygwin
-	exit ;;
-    prep*:SunOS:5.*:*)
-	echo powerpcle-unknown-solaris2"$(echo "$UNAME_RELEASE"|sed -e 's/[^.]*//')"
-	exit ;;
-    *:GNU:*:*)
-	# the GNU system
-	echo "$(echo "$UNAME_MACHINE"|sed -e 's,[-/].*$,,')-unknown-$LIBC$(echo "$UNAME_RELEASE"|sed -e 's,/.*$,,')"
-	exit ;;
-    *:GNU/*:*:*)
-	# other systems with GNU libc and userland
-	echo "$UNAME_MACHINE-unknown-$(echo "$UNAME_SYSTEM" | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]")$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')-$LIBC"
-	exit ;;
-    *:Minix:*:*)
-	echo "$UNAME_MACHINE"-unknown-minix
-	exit ;;
-    aarch64:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    aarch64_be:Linux:*:*)
-	UNAME_MACHINE=aarch64_be
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    alpha:Linux:*:*)
-	case $(sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' /proc/cpuinfo 2>/dev/null) in
-	  EV5)   UNAME_MACHINE=alphaev5 ;;
-	  EV56)  UNAME_MACHINE=alphaev56 ;;
-	  PCA56) UNAME_MACHINE=alphapca56 ;;
-	  PCA57) UNAME_MACHINE=alphapca56 ;;
-	  EV6)   UNAME_MACHINE=alphaev6 ;;
-	  EV67)  UNAME_MACHINE=alphaev67 ;;
-	  EV68*) UNAME_MACHINE=alphaev68 ;;
-	esac
-	objdump --private-headers /bin/sh | grep -q ld.so.1
-	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    arc:Linux:*:* | arceb:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    arm*:Linux:*:*)
-	set_cc_for_build
-	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
-	    | grep -q __ARM_EABI__
-	then
-	    echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	else
-	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
-		| grep -q __ARM_PCS_VFP
-	    then
-		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabi
-	    else
-		echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"eabihf
-	    fi
-	fi
-	exit ;;
-    avr32*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    cris:Linux:*:*)
-	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
-	exit ;;
-    crisv32:Linux:*:*)
-	echo "$UNAME_MACHINE"-axis-linux-"$LIBC"
-	exit ;;
-    e2k:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    frv:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    hexagon:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    i*86:Linux:*:*)
-	echo "$UNAME_MACHINE"-pc-linux-"$LIBC"
-	exit ;;
-    ia64:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    k1om:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    m32r*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    m68*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    mips:Linux:*:* | mips64:Linux:*:*)
-	set_cc_for_build
-	IS_GLIBC=0
-	test x"${LIBC}" = xgnu && IS_GLIBC=1
-	sed 's/^	//' << EOF > "$dummy.c"
-	#undef CPU
-	#undef mips
-	#undef mipsel
-	#undef mips64
-	#undef mips64el
-	#if ${IS_GLIBC} && defined(_ABI64)
-	LIBCABI=gnuabi64
-	#else
-	#if ${IS_GLIBC} && defined(_ABIN32)
-	LIBCABI=gnuabin32
-	#else
-	LIBCABI=${LIBC}
-	#endif
-	#endif
-
-	#if ${IS_GLIBC} && defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
-	CPU=mipsisa64r6
-	#else
-	#if ${IS_GLIBC} && !defined(__mips64) && defined(__mips_isa_rev) && __mips_isa_rev>=6
-	CPU=mipsisa32r6
-	#else
-	#if defined(__mips64)
-	CPU=mips64
-	#else
-	CPU=mips
-	#endif
-	#endif
-	#endif
-
-	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
-	MIPS_ENDIAN=el
-	#else
-	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
-	MIPS_ENDIAN=
-	#else
-	MIPS_ENDIAN=
-	#endif
-	#endif
-EOF
-	eval "$($CC_FOR_BUILD -E "$dummy.c" 2>/dev/null | grep '^CPU\|^MIPS_ENDIAN\|^LIBCABI')"
-	test "x$CPU" != x && { echo "$CPU${MIPS_ENDIAN}-unknown-linux-$LIBCABI"; exit; }
-	;;
-    mips64el:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    openrisc*:Linux:*:*)
-	echo or1k-unknown-linux-"$LIBC"
-	exit ;;
-    or32:Linux:*:* | or1k*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    padre:Linux:*:*)
-	echo sparc-unknown-linux-"$LIBC"
-	exit ;;
-    parisc64:Linux:*:* | hppa64:Linux:*:*)
-	echo hppa64-unknown-linux-"$LIBC"
-	exit ;;
-    parisc:Linux:*:* | hppa:Linux:*:*)
-	# Look for CPU level
-	case $(grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2) in
-	  PA7*) echo hppa1.1-unknown-linux-"$LIBC" ;;
-	  PA8*) echo hppa2.0-unknown-linux-"$LIBC" ;;
-	  *)    echo hppa-unknown-linux-"$LIBC" ;;
-	esac
-	exit ;;
-    ppc64:Linux:*:*)
-	echo powerpc64-unknown-linux-"$LIBC"
-	exit ;;
-    ppc:Linux:*:*)
-	echo powerpc-unknown-linux-"$LIBC"
-	exit ;;
-    ppc64le:Linux:*:*)
-	echo powerpc64le-unknown-linux-"$LIBC"
-	exit ;;
-    ppcle:Linux:*:*)
-	echo powerpcle-unknown-linux-"$LIBC"
-	exit ;;
-    riscv32:Linux:*:* | riscv32be:Linux:*:* | riscv64:Linux:*:* | riscv64be:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    s390:Linux:*:* | s390x:Linux:*:*)
-	echo "$UNAME_MACHINE"-ibm-linux-"$LIBC"
-	exit ;;
-    sh64*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    sh*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    sparc:Linux:*:* | sparc64:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    tile*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    vax:Linux:*:*)
-	echo "$UNAME_MACHINE"-dec-linux-"$LIBC"
-	exit ;;
-    x86_64:Linux:*:*)
-	set_cc_for_build
-	LIBCABI=$LIBC
-	if test "$CC_FOR_BUILD" != no_compiler_found; then
-	    if (echo '#ifdef __ILP32__'; echo IS_X32; echo '#endif') | \
-		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		grep IS_X32 >/dev/null
-	    then
-		LIBCABI="$LIBC"x32
-	    fi
-	fi
-	echo "$UNAME_MACHINE"-pc-linux-"$LIBCABI"
-	exit ;;
-    xtensa*:Linux:*:*)
-	echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
-	exit ;;
-    i*86:DYNIX/ptx:4*:*)
-	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
-	# earlier versions are messed up and put the nodename in both
-	# sysname and nodename.
-	echo i386-sequent-sysv4
-	exit ;;
-    i*86:UNIX_SV:4.2MP:2.*)
-	# Unixware is an offshoot of SVR4, but it has its own version
-	# number series starting with 2...
-	# I am not positive that other SVR4 systems won't match this,
-	# I just have to hope.  -- rms.
-	# Use sysv4.2uw... so that sysv4* matches it.
-	echo "$UNAME_MACHINE"-pc-sysv4.2uw"$UNAME_VERSION"
-	exit ;;
-    i*86:OS/2:*:*)
-	# If we were able to find `uname', then EMX Unix compatibility
-	# is probably installed.
-	echo "$UNAME_MACHINE"-pc-os2-emx
-	exit ;;
-    i*86:XTS-300:*:STOP)
-	echo "$UNAME_MACHINE"-unknown-stop
-	exit ;;
-    i*86:atheos:*:*)
-	echo "$UNAME_MACHINE"-unknown-atheos
-	exit ;;
-    i*86:syllable:*:*)
-	echo "$UNAME_MACHINE"-pc-syllable
-	exit ;;
-    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
-	echo i386-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
-    i*86:*DOS:*:*)
-	echo "$UNAME_MACHINE"-pc-msdosdjgpp
-	exit ;;
-    i*86:*:4.*:*)
-	UNAME_REL=$(echo "$UNAME_RELEASE" | sed 's/\/MP$//')
-	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
-		echo "$UNAME_MACHINE"-univel-sysv"$UNAME_REL"
-	else
-		echo "$UNAME_MACHINE"-pc-sysv"$UNAME_REL"
-	fi
-	exit ;;
-    i*86:*:5:[678]*)
-	# UnixWare 7.x, OpenUNIX and OpenServer 6.
-	case $(/bin/uname -X | grep "^Machine") in
-	    *486*)	     UNAME_MACHINE=i486 ;;
-	    *Pentium)	     UNAME_MACHINE=i586 ;;
-	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
-	esac
-	echo "$UNAME_MACHINE-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}"
-	exit ;;
-    i*86:*:3.2:*)
-	if test -f /usr/options/cb.name; then
-		UNAME_REL=$(sed -n 's/.*Version //p' </usr/options/cb.name)
-		echo "$UNAME_MACHINE"-pc-isc"$UNAME_REL"
-	elif /bin/uname -X 2>/dev/null >/dev/null ; then
-		UNAME_REL=$( (/bin/uname -X|grep Release|sed -e 's/.*= //'))
-		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
-		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
-			&& UNAME_MACHINE=i586
-		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
-			&& UNAME_MACHINE=i686
-		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
-			&& UNAME_MACHINE=i686
-		echo "$UNAME_MACHINE"-pc-sco"$UNAME_REL"
-	else
-		echo "$UNAME_MACHINE"-pc-sysv32
-	fi
-	exit ;;
-    pc:*:*:*)
-	# Left here for compatibility:
-	# uname -m prints for DJGPP always 'pc', but it prints nothing about
-	# the processor, so we play safe by assuming i586.
-	# Note: whatever this is, it MUST be the same as what config.sub
-	# prints for the "djgpp" host, or else GDB configure will decide that
-	# this is a cross-build.
-	echo i586-pc-msdosdjgpp
-	exit ;;
-    Intel:Mach:3*:*)
-	echo i386-pc-mach3
-	exit ;;
-    paragon:*:*:*)
-	echo i860-intel-osf1
-	exit ;;
-    i860:*:4.*:*) # i860-SVR4
-	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
-	  echo i860-stardent-sysv"$UNAME_RELEASE" # Stardent Vistra i860-SVR4
-	else # Add other i860-SVR4 vendors below as they are discovered.
-	  echo i860-unknown-sysv"$UNAME_RELEASE"  # Unknown i860-SVR4
-	fi
-	exit ;;
-    mini*:CTIX:SYS*5:*)
-	# "miniframe"
-	echo m68010-convergent-sysv
-	exit ;;
-    mc68k:UNIX:SYSTEM5:3.51m)
-	echo m68k-convergent-sysv
-	exit ;;
-    M680?0:D-NIX:5.3:*)
-	echo m68k-diab-dnix
-	exit ;;
-    M68*:*:R3V[5678]*:*)
-	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
-    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
-	OS_REL=''
-	test -r /etc/.relid \
-	&& OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
-	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-	  && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
-	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-	  && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
-    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
-	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-	  && { echo i486-ncr-sysv4; exit; } ;;
-    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
-	OS_REL='.3'
-	test -r /etc/.relid \
-	    && OS_REL=.$(sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid)
-	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
-	    && { echo i486-ncr-sysv4.3"$OS_REL"; exit; }
-	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
-	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; }
-	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
-	    && { echo i586-ncr-sysv4.3"$OS_REL"; exit; } ;;
-    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
-	echo m68k-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
-    mc68030:UNIX_System_V:4.*:*)
-	echo m68k-atari-sysv4
-	exit ;;
-    TSUNAMI:LynxOS:2.*:*)
-	echo sparc-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
-    rs6000:LynxOS:2.*:*)
-	echo rs6000-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
-    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
-	echo powerpc-unknown-lynxos"$UNAME_RELEASE"
-	exit ;;
-    SM[BE]S:UNIX_SV:*:*)
-	echo mips-dde-sysv"$UNAME_RELEASE"
-	exit ;;
-    RM*:ReliantUNIX-*:*:*)
-	echo mips-sni-sysv4
-	exit ;;
-    RM*:SINIX-*:*:*)
-	echo mips-sni-sysv4
-	exit ;;
-    *:SINIX-*:*:*)
-	if uname -p 2>/dev/null >/dev/null ; then
-		UNAME_MACHINE=$( (uname -p) 2>/dev/null)
-		echo "$UNAME_MACHINE"-sni-sysv4
-	else
-		echo ns32k-sni-sysv
-	fi
-	exit ;;
-    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
-			# says <Richard.M.Bartel@ccMail.Census.GOV>
-	echo i586-unisys-sysv4
-	exit ;;
-    *:UNIX_System_V:4*:FTX*)
-	# From Gerald Hewes <hewes@openmarket.com>.
-	# How about differentiating between stratus architectures? -djm
-	echo hppa1.1-stratus-sysv4
-	exit ;;
-    *:*:*:FTX*)
-	# From seanf@swdc.stratus.com.
-	echo i860-stratus-sysv4
-	exit ;;
-    i*86:VOS:*:*)
-	# From Paul.Green@stratus.com.
-	echo "$UNAME_MACHINE"-stratus-vos
-	exit ;;
-    *:VOS:*:*)
-	# From Paul.Green@stratus.com.
-	echo hppa1.1-stratus-vos
-	exit ;;
-    mc68*:A/UX:*:*)
-	echo m68k-apple-aux"$UNAME_RELEASE"
-	exit ;;
-    news*:NEWS-OS:6*:*)
-	echo mips-sony-newsos6
-	exit ;;
-    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
-	if test -d /usr/nec; then
-		echo mips-nec-sysv"$UNAME_RELEASE"
-	else
-		echo mips-unknown-sysv"$UNAME_RELEASE"
-	fi
-	exit ;;
-    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
-	echo powerpc-be-beos
-	exit ;;
-    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
-	echo powerpc-apple-beos
-	exit ;;
-    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
-	echo i586-pc-beos
-	exit ;;
-    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
-	echo i586-pc-haiku
-	exit ;;
-    x86_64:Haiku:*:*)
-	echo x86_64-unknown-haiku
-	exit ;;
-    SX-4:SUPER-UX:*:*)
-	echo sx4-nec-superux"$UNAME_RELEASE"
-	exit ;;
-    SX-5:SUPER-UX:*:*)
-	echo sx5-nec-superux"$UNAME_RELEASE"
-	exit ;;
-    SX-6:SUPER-UX:*:*)
-	echo sx6-nec-superux"$UNAME_RELEASE"
-	exit ;;
-    SX-7:SUPER-UX:*:*)
-	echo sx7-nec-superux"$UNAME_RELEASE"
-	exit ;;
-    SX-8:SUPER-UX:*:*)
-	echo sx8-nec-superux"$UNAME_RELEASE"
-	exit ;;
-    SX-8R:SUPER-UX:*:*)
-	echo sx8r-nec-superux"$UNAME_RELEASE"
-	exit ;;
-    SX-ACE:SUPER-UX:*:*)
-	echo sxace-nec-superux"$UNAME_RELEASE"
-	exit ;;
-    Power*:Rhapsody:*:*)
-	echo powerpc-apple-rhapsody"$UNAME_RELEASE"
-	exit ;;
-    *:Rhapsody:*:*)
-	echo "$UNAME_MACHINE"-apple-rhapsody"$UNAME_RELEASE"
-	exit ;;
-    arm64:Darwin:*:*)
-	echo aarch64-apple-darwin"$UNAME_RELEASE"
-	exit ;;
-    *:Darwin:*:*)
-	UNAME_PROCESSOR=$(uname -p)
-	case $UNAME_PROCESSOR in
-	    unknown) UNAME_PROCESSOR=powerpc ;;
-	esac
-	if command -v xcode-select > /dev/null 2> /dev/null && \
-		! xcode-select --print-path > /dev/null 2> /dev/null ; then
-	    # Avoid executing cc if there is no toolchain installed as
-	    # cc will be a stub that puts up a graphical alert
-	    # prompting the user to install developer tools.
-	    CC_FOR_BUILD=no_compiler_found
-	else
-	    set_cc_for_build
-	fi
-	if test "$CC_FOR_BUILD" != no_compiler_found; then
-	    if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
-		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		   grep IS_64BIT_ARCH >/dev/null
-	    then
-		case $UNAME_PROCESSOR in
-		    i386) UNAME_PROCESSOR=x86_64 ;;
-		    powerpc) UNAME_PROCESSOR=powerpc64 ;;
-		esac
-	    fi
-	    # On 10.4-10.6 one might compile for PowerPC via gcc -arch ppc
-	    if (echo '#ifdef __POWERPC__'; echo IS_PPC; echo '#endif') | \
-		   (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
-		   grep IS_PPC >/dev/null
-	    then
-		UNAME_PROCESSOR=powerpc
-	    fi
-	elif test "$UNAME_PROCESSOR" = i386 ; then
-	    # uname -m returns i386 or x86_64
-	    UNAME_PROCESSOR=$UNAME_MACHINE
-	fi
-	echo "$UNAME_PROCESSOR"-apple-darwin"$UNAME_RELEASE"
-	exit ;;
-    *:procnto*:*:* | *:QNX:[0123456789]*:*)
-	UNAME_PROCESSOR=$(uname -p)
-	if test "$UNAME_PROCESSOR" = x86; then
-		UNAME_PROCESSOR=i386
-		UNAME_MACHINE=pc
-	fi
-	echo "$UNAME_PROCESSOR"-"$UNAME_MACHINE"-nto-qnx"$UNAME_RELEASE"
-	exit ;;
-    *:QNX:*:4*)
-	echo i386-pc-qnx
-	exit ;;
-    NEO-*:NONSTOP_KERNEL:*:*)
-	echo neo-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
-    NSE-*:NONSTOP_KERNEL:*:*)
-	echo nse-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
-    NSR-*:NONSTOP_KERNEL:*:*)
-	echo nsr-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
-    NSV-*:NONSTOP_KERNEL:*:*)
-	echo nsv-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
-    NSX-*:NONSTOP_KERNEL:*:*)
-	echo nsx-tandem-nsk"$UNAME_RELEASE"
-	exit ;;
-    *:NonStop-UX:*:*)
-	echo mips-compaq-nonstopux
-	exit ;;
-    BS2000:POSIX*:*:*)
-	echo bs2000-siemens-sysv
-	exit ;;
-    DS/*:UNIX_System_V:*:*)
-	echo "$UNAME_MACHINE"-"$UNAME_SYSTEM"-"$UNAME_RELEASE"
-	exit ;;
-    *:Plan9:*:*)
-	# "uname -m" is not consistent, so use $cputype instead. 386
-	# is converted to i386 for consistency with other x86
-	# operating systems.
-	# shellcheck disable=SC2154
-	if test "$cputype" = 386; then
-	    UNAME_MACHINE=i386
-	else
-	    UNAME_MACHINE="$cputype"
-	fi
-	echo "$UNAME_MACHINE"-unknown-plan9
-	exit ;;
-    *:TOPS-10:*:*)
-	echo pdp10-unknown-tops10
-	exit ;;
-    *:TENEX:*:*)
-	echo pdp10-unknown-tenex
-	exit ;;
-    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
-	echo pdp10-dec-tops20
-	exit ;;
-    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
-	echo pdp10-xkl-tops20
-	exit ;;
-    *:TOPS-20:*:*)
-	echo pdp10-unknown-tops20
-	exit ;;
-    *:ITS:*:*)
-	echo pdp10-unknown-its
-	exit ;;
-    SEI:*:*:SEIUX)
-	echo mips-sei-seiux"$UNAME_RELEASE"
-	exit ;;
-    *:DragonFly:*:*)
-	echo "$UNAME_MACHINE"-unknown-dragonfly"$(echo "$UNAME_RELEASE"|sed -e 's/[-(].*//')"
-	exit ;;
-    *:*VMS:*:*)
-	UNAME_MACHINE=$( (uname -p) 2>/dev/null)
-	case "$UNAME_MACHINE" in
-	    A*) echo alpha-dec-vms ; exit ;;
-	    I*) echo ia64-dec-vms ; exit ;;
-	    V*) echo vax-dec-vms ; exit ;;
-	esac ;;
-    *:XENIX:*:SysV)
-	echo i386-pc-xenix
-	exit ;;
-    i*86:skyos:*:*)
-	echo "$UNAME_MACHINE"-pc-skyos"$(echo "$UNAME_RELEASE" | sed -e 's/ .*$//')"
-	exit ;;
-    i*86:rdos:*:*)
-	echo "$UNAME_MACHINE"-pc-rdos
-	exit ;;
-    *:AROS:*:*)
-	echo "$UNAME_MACHINE"-unknown-aros
-	exit ;;
-    x86_64:VMkernel:*:*)
-	echo "$UNAME_MACHINE"-unknown-esx
-	exit ;;
-    amd64:Isilon\ OneFS:*:*)
-	echo x86_64-unknown-onefs
-	exit ;;
-    *:Unleashed:*:*)
-	echo "$UNAME_MACHINE"-unknown-unleashed"$UNAME_RELEASE"
-	exit ;;
-esac
-
-# No uname command or uname output not recognized.
-set_cc_for_build
-cat > "$dummy.c" <<EOF
-#ifdef _SEQUENT_
-#include <sys/types.h>
-#include <sys/utsname.h>
-#endif
-#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
-#if defined (vax) || defined (__vax) || defined (__vax__) || defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
-#include <signal.h>
-#if defined(_SIZE_T_) || defined(SIGLOST)
-#include <sys/utsname.h>
-#endif
-#endif
-#endif
-main ()
-{
-#if defined (sony)
-#if defined (MIPSEB)
-  /* BFD wants "bsd" instead of "newsos".  Perhaps BFD should be changed,
-     I don't know....  */
-  printf ("mips-sony-bsd\n"); exit (0);
-#else
-#include <sys/param.h>
-  printf ("m68k-sony-newsos%s\n",
-#ifdef NEWSOS4
-  "4"
-#else
-  ""
-#endif
-  ); exit (0);
-#endif
-#endif
-
-#if defined (NeXT)
-#if !defined (__ARCHITECTURE__)
-#define __ARCHITECTURE__ "m68k"
-#endif
-  int version;
-  version=$( (hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null);
-  if (version < 4)
-    printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version);
-  else
-    printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version);
-  exit (0);
-#endif
-
-#if defined (MULTIMAX) || defined (n16)
-#if defined (UMAXV)
-  printf ("ns32k-encore-sysv\n"); exit (0);
-#else
-#if defined (CMU)
-  printf ("ns32k-encore-mach\n"); exit (0);
-#else
-  printf ("ns32k-encore-bsd\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (__386BSD__)
-  printf ("i386-pc-bsd\n"); exit (0);
-#endif
-
-#if defined (sequent)
-#if defined (i386)
-  printf ("i386-sequent-dynix\n"); exit (0);
-#endif
-#if defined (ns32000)
-  printf ("ns32k-sequent-dynix\n"); exit (0);
-#endif
-#endif
-
-#if defined (_SEQUENT_)
-  struct utsname un;
-
-  uname(&un);
-  if (strncmp(un.version, "V2", 2) == 0) {
-    printf ("i386-sequent-ptx2\n"); exit (0);
-  }
-  if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */
-    printf ("i386-sequent-ptx1\n"); exit (0);
-  }
-  printf ("i386-sequent-ptx\n"); exit (0);
-#endif
-
-#if defined (vax)
-#if !defined (ultrix)
-#include <sys/param.h>
-#if defined (BSD)
-#if BSD == 43
-  printf ("vax-dec-bsd4.3\n"); exit (0);
-#else
-#if BSD == 199006
-  printf ("vax-dec-bsd4.3reno\n"); exit (0);
-#else
-  printf ("vax-dec-bsd\n"); exit (0);
-#endif
-#endif
-#else
-  printf ("vax-dec-bsd\n"); exit (0);
-#endif
-#else
-#if defined(_SIZE_T_) || defined(SIGLOST)
-  struct utsname un;
-  uname (&un);
-  printf ("vax-dec-ultrix%s\n", un.release); exit (0);
-#else
-  printf ("vax-dec-ultrix\n"); exit (0);
-#endif
-#endif
-#endif
-#if defined(ultrix) || defined(_ultrix) || defined(__ultrix) || defined(__ultrix__)
-#if defined(mips) || defined(__mips) || defined(__mips__) || defined(MIPS) || defined(__MIPS__)
-#if defined(_SIZE_T_) || defined(SIGLOST)
-  struct utsname *un;
-  uname (&un);
-  printf ("mips-dec-ultrix%s\n", un.release); exit (0);
-#else
-  printf ("mips-dec-ultrix\n"); exit (0);
-#endif
-#endif
-#endif
-
-#if defined (alliant) && defined (i860)
-  printf ("i860-alliant-bsd\n"); exit (0);
-#endif
-
-  exit (1);
-}
-EOF
-
-$CC_FOR_BUILD -o "$dummy" "$dummy.c" 2>/dev/null && SYSTEM_NAME=$($dummy) &&
-	{ echo "$SYSTEM_NAME"; exit; }
-
-# Apollos put the system type in the environment.
-test -d /usr/apollo && { echo "$ISP-apollo-$SYSTYPE"; exit; }
-
-echo "$0: unable to guess system type" >&2
-
-case "$UNAME_MACHINE:$UNAME_SYSTEM" in
-    mips:Linux | mips64:Linux)
-	# If we got here on MIPS GNU/Linux, output extra information.
-	cat >&2 <<EOF
-
-NOTE: MIPS GNU/Linux systems require a C compiler to fully recognize
-the system type. Please install a C compiler and try again.
-EOF
-	;;
-esac
-
-cat >&2 <<EOF
-
-This script (version $timestamp), has failed to recognize the
-operating system you are using. If your script is old, overwrite *all*
-copies of config.guess and config.sub with the latest versions from:
-
-  https://git.savannah.gnu.org/cgit/config.git/plain/config.guess
-and
-  https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
-EOF
-
-year=$(echo $timestamp | sed 's,-.*,,')
-# shellcheck disable=SC2003
-if test "$(expr "$(date +%Y)" - "$year")" -lt 3 ; then
-   cat >&2 <<EOF
-
-If $0 has already been updated, send the following data and any
-information you think might be pertinent to config-patches@gnu.org to
-provide the necessary information to handle your system.
-
-config.guess timestamp = $timestamp
-
-uname -m = $( (uname -m) 2>/dev/null || echo unknown)
-uname -r = $( (uname -r) 2>/dev/null || echo unknown)
-uname -s = $( (uname -s) 2>/dev/null || echo unknown)
-uname -v = $( (uname -v) 2>/dev/null || echo unknown)
-
-/usr/bin/uname -p = $( (/usr/bin/uname -p) 2>/dev/null)
-/bin/uname -X     = $( (/bin/uname -X) 2>/dev/null)
-
-hostinfo               = $( (hostinfo) 2>/dev/null)
-/bin/universe          = $( (/bin/universe) 2>/dev/null)
-/usr/bin/arch -k       = $( (/usr/bin/arch -k) 2>/dev/null)
-/bin/arch              = $( (/bin/arch) 2>/dev/null)
-/usr/bin/oslevel       = $( (/usr/bin/oslevel) 2>/dev/null)
-/usr/convex/getsysinfo = $( (/usr/convex/getsysinfo) 2>/dev/null)
-
-UNAME_MACHINE = "$UNAME_MACHINE"
-UNAME_RELEASE = "$UNAME_RELEASE"
-UNAME_SYSTEM  = "$UNAME_SYSTEM"
-UNAME_VERSION = "$UNAME_VERSION"
-EOF
-fi
-
-exit 1
-
-# Local variables:
-# eval: (add-hook 'before-save-hook 'time-stamp)
+#   Copyright 1992-2017 Free Software Foundation, Inc.
+
+timestamp='2017-03-05'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+#
+# Originally written by Per Bothner; maintained since 2000 by Ben Elliston.
+#
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+#
+# Please send patches to <config-patches@gnu.org>.
+
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION]
+
+Output the configuration name of the system \`$me' is run on.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.guess ($timestamp)
+
+Originally written by Per Bothner.
+Copyright 1992-2017 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help" >&2
+       exit 1 ;;
+    * )
+       break ;;
+  esac
+done
+
+if test $# != 0; then
+  echo "$me: too many arguments$help" >&2
+  exit 1
+fi
+
+trap 'exit 1' 1 2 15
+
+# CC_FOR_BUILD -- compiler used by this script. Note that the use of a
+# compiler to aid in system detection is discouraged as it requires
+# temporary files to be created and, as you can see below, it is a
+# headache to deal with in a portable fashion.
+
+# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still
+# use `HOST_CC' if defined, but it is deprecated.
+
+# Portable tmp directory creation inspired by the Autoconf team.
+
+set_cc_for_build='
+trap "exitcode=\$?; (rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null) && exit \$exitcode" 0 ;
+trap "rm -f \$tmpfiles 2>/dev/null; rmdir \$tmp 2>/dev/null; exit 1" 1 2 13 15 ;
+: ${TMPDIR=/tmp} ;
+ { tmp=`(umask 077 && mktemp -d "$TMPDIR/cgXXXXXX") 2>/dev/null` && test -n "$tmp" && test -d "$tmp" ; } ||
+ { test -n "$RANDOM" && tmp=$TMPDIR/cg$$-$RANDOM && (umask 077 && mkdir $tmp) ; } ||
+ { tmp=$TMPDIR/cg-$$ && (umask 077 && mkdir $tmp) && echo "Warning: creating insecure temp directory" >&2 ; } ||
+ { echo "$me: cannot create a temporary directory in $TMPDIR" >&2 ; exit 1 ; } ;
+dummy=$tmp/dummy ;
+tmpfiles="$dummy.c $dummy.o $dummy.rel $dummy" ;
+case $CC_FOR_BUILD,$HOST_CC,$CC in
+ ,,)    echo "int x;" > $dummy.c ;
+	for c in cc gcc c89 c99 ; do
+	  if ($c -c -o $dummy.o $dummy.c) >/dev/null 2>&1 ; then
+	     CC_FOR_BUILD="$c"; break ;
+	  fi ;
+	done ;
+	if test x"$CC_FOR_BUILD" = x ; then
+	  CC_FOR_BUILD=no_compiler_found ;
+	fi
+	;;
+ ,,*)   CC_FOR_BUILD=$CC ;;
+ ,*,*)  CC_FOR_BUILD=$HOST_CC ;;
+esac ; set_cc_for_build= ;'
+
+# This is needed to find uname on a Pyramid OSx when run in the BSD universe.
+# (ghazi@noc.rutgers.edu 1994-08-24)
+if (test -f /.attbin/uname) >/dev/null 2>&1 ; then
+	PATH=$PATH:/.attbin ; export PATH
+fi
+
+UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown
+UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown
+UNAME_SYSTEM=`(uname -s) 2>/dev/null`  || UNAME_SYSTEM=unknown
+UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown
+
+case "${UNAME_SYSTEM}" in
+Linux|GNU|GNU/*)
+	# If the system lacks a compiler, then just pick glibc.
+	# We could probably try harder.
+	LIBC=gnu
+
+	eval $set_cc_for_build
+	cat <<-EOF > $dummy.c
+	#include <features.h>
+	#if defined(__UCLIBC__)
+	LIBC=uclibc
+	#elif defined(__dietlibc__)
+	LIBC=dietlibc
+	#else
+	LIBC=gnu
+	#endif
+	EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^LIBC' | sed 's, ,,g'`
+	;;
+esac
+
+# Note: order is significant - the case branches are not exclusive.
+
+case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in
+    *:NetBSD:*:*)
+	# NetBSD (nbsd) targets should (where applicable) match one or
+	# more of the tuples: *-*-netbsdelf*, *-*-netbsdaout*,
+	# *-*-netbsdecoff* and *-*-netbsd*.  For targets that recently
+	# switched to ELF, *-*-netbsd* would select the old
+	# object file format.  This provides both forward
+	# compatibility and a consistent mechanism for selecting the
+	# object file format.
+	#
+	# Note: NetBSD doesn't particularly care about the vendor
+	# portion of the name.  We always set it to "unknown".
+	sysctl="sysctl -n hw.machine_arch"
+	UNAME_MACHINE_ARCH=`(uname -p 2>/dev/null || \
+	    /sbin/$sysctl 2>/dev/null || \
+	    /usr/sbin/$sysctl 2>/dev/null || \
+	    echo unknown)`
+	case "${UNAME_MACHINE_ARCH}" in
+	    armeb) machine=armeb-unknown ;;
+	    arm*) machine=arm-unknown ;;
+	    sh3el) machine=shl-unknown ;;
+	    sh3eb) machine=sh-unknown ;;
+	    sh5el) machine=sh5le-unknown ;;
+	    earmv*)
+		arch=`echo ${UNAME_MACHINE_ARCH} | sed -e 's,^e\(armv[0-9]\).*$,\1,'`
+		endian=`echo ${UNAME_MACHINE_ARCH} | sed -ne 's,^.*\(eb\)$,\1,p'`
+		machine=${arch}${endian}-unknown
+		;;
+	    *) machine=${UNAME_MACHINE_ARCH}-unknown ;;
+	esac
+	# The Operating System including object format, if it has switched
+	# to ELF recently (or will in the future) and ABI.
+	case "${UNAME_MACHINE_ARCH}" in
+	    earm*)
+		os=netbsdelf
+		;;
+	    arm*|i386|m68k|ns32k|sh3*|sparc|vax)
+		eval $set_cc_for_build
+		if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \
+			| grep -q __ELF__
+		then
+		    # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout).
+		    # Return netbsd for either.  FIX?
+		    os=netbsd
+		else
+		    os=netbsdelf
+		fi
+		;;
+	    *)
+		os=netbsd
+		;;
+	esac
+	# Determine ABI tags.
+	case "${UNAME_MACHINE_ARCH}" in
+	    earm*)
+		expr='s/^earmv[0-9]/-eabi/;s/eb$//'
+		abi=`echo ${UNAME_MACHINE_ARCH} | sed -e "$expr"`
+		;;
+	esac
+	# The OS release
+	# Debian GNU/NetBSD machines have a different userland, and
+	# thus, need a distinct triplet. However, they do not need
+	# kernel version information, so it can be replaced with a
+	# suitable tag, in the style of linux-gnu.
+	case "${UNAME_VERSION}" in
+	    Debian*)
+		release='-gnu'
+		;;
+	    *)
+		release=`echo ${UNAME_RELEASE} | sed -e 's/[-_].*//' | cut -d. -f1,2`
+		;;
+	esac
+	# Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM:
+	# contains redundant information, the shorter form:
+	# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used.
+	echo "${machine}-${os}${release}${abi}"
+	exit ;;
+    *:Bitrig:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/Bitrig.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-bitrig${UNAME_RELEASE}
+	exit ;;
+    *:OpenBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/OpenBSD.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-openbsd${UNAME_RELEASE}
+	exit ;;
+    *:LibertyBSD:*:*)
+	UNAME_MACHINE_ARCH=`arch | sed 's/^.*BSD\.//'`
+	echo ${UNAME_MACHINE_ARCH}-unknown-libertybsd${UNAME_RELEASE}
+	exit ;;
+    *:ekkoBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-ekkobsd${UNAME_RELEASE}
+	exit ;;
+    *:SolidBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-solidbsd${UNAME_RELEASE}
+	exit ;;
+    macppc:MirBSD:*:*)
+	echo powerpc-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:MirBSD:*:*)
+	echo ${UNAME_MACHINE}-unknown-mirbsd${UNAME_RELEASE}
+	exit ;;
+    *:Sortix:*:*)
+	echo ${UNAME_MACHINE}-unknown-sortix
+	exit ;;
+    alpha:OSF1:*:*)
+	case $UNAME_RELEASE in
+	*4.0)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'`
+		;;
+	*5.*)
+		UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $4}'`
+		;;
+	esac
+	# According to Compaq, /usr/sbin/psrinfo has been available on
+	# OSF/1 and Tru64 systems produced since 1995.  I hope that
+	# covers most systems running today.  This code pipes the CPU
+	# types through head -n 1, so we only detect the type of CPU 0.
+	ALPHA_CPU_TYPE=`/usr/sbin/psrinfo -v | sed -n -e 's/^  The alpha \(.*\) processor.*$/\1/p' | head -n 1`
+	case "$ALPHA_CPU_TYPE" in
+	    "EV4 (21064)")
+		UNAME_MACHINE=alpha ;;
+	    "EV4.5 (21064)")
+		UNAME_MACHINE=alpha ;;
+	    "LCA4 (21066/21068)")
+		UNAME_MACHINE=alpha ;;
+	    "EV5 (21164)")
+		UNAME_MACHINE=alphaev5 ;;
+	    "EV5.6 (21164A)")
+		UNAME_MACHINE=alphaev56 ;;
+	    "EV5.6 (21164PC)")
+		UNAME_MACHINE=alphapca56 ;;
+	    "EV5.7 (21164PC)")
+		UNAME_MACHINE=alphapca57 ;;
+	    "EV6 (21264)")
+		UNAME_MACHINE=alphaev6 ;;
+	    "EV6.7 (21264A)")
+		UNAME_MACHINE=alphaev67 ;;
+	    "EV6.8CB (21264C)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.8AL (21264B)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.8CX (21264D)")
+		UNAME_MACHINE=alphaev68 ;;
+	    "EV6.9A (21264/EV69A)")
+		UNAME_MACHINE=alphaev69 ;;
+	    "EV7 (21364)")
+		UNAME_MACHINE=alphaev7 ;;
+	    "EV7.9 (21364A)")
+		UNAME_MACHINE=alphaev79 ;;
+	esac
+	# A Pn.n version is a patched version.
+	# A Vn.n version is a released version.
+	# A Tn.n version is a released field test version.
+	# A Xn.n version is an unreleased experimental baselevel.
+	# 1.2 uses "1.2" for uname -r.
+	echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[PVTX]//' | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	# Reset EXIT trap before exiting to avoid spurious non-zero exit code.
+	exitcode=$?
+	trap '' 0
+	exit $exitcode ;;
+    Alpha\ *:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# Should we change UNAME_MACHINE based on the output of uname instead
+	# of the specific Alpha model?
+	echo alpha-pc-interix
+	exit ;;
+    21064:Windows_NT:50:3)
+	echo alpha-dec-winnt3.5
+	exit ;;
+    Amiga*:UNIX_System_V:4.0:*)
+	echo m68k-unknown-sysv4
+	exit ;;
+    *:[Aa]miga[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-amigaos
+	exit ;;
+    *:[Mm]orph[Oo][Ss]:*:*)
+	echo ${UNAME_MACHINE}-unknown-morphos
+	exit ;;
+    *:OS/390:*:*)
+	echo i370-ibm-openedition
+	exit ;;
+    *:z/VM:*:*)
+	echo s390-ibm-zvmoe
+	exit ;;
+    *:OS400:*:*)
+	echo powerpc-ibm-os400
+	exit ;;
+    arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*)
+	echo arm-acorn-riscix${UNAME_RELEASE}
+	exit ;;
+    arm*:riscos:*:*|arm*:RISCOS:*:*)
+	echo arm-unknown-riscos
+	exit ;;
+    SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*)
+	echo hppa1.1-hitachi-hiuxmpp
+	exit ;;
+    Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*)
+	# akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE.
+	if test "`(/bin/universe) 2>/dev/null`" = att ; then
+		echo pyramid-pyramid-sysv3
+	else
+		echo pyramid-pyramid-bsd
+	fi
+	exit ;;
+    NILE*:*:*:dcosx)
+	echo pyramid-pyramid-svr4
+	exit ;;
+    DRS?6000:unix:4.0:6*)
+	echo sparc-icl-nx6
+	exit ;;
+    DRS?6000:UNIX_SV:4.2*:7* | DRS?6000:isis:4.2*:7*)
+	case `/usr/bin/uname -p` in
+	    sparc) echo sparc-icl-nx7; exit ;;
+	esac ;;
+    s390x:SunOS:*:*)
+	echo ${UNAME_MACHINE}-ibm-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4H:SunOS:5.*:*)
+	echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*)
+	echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    i86pc:AuroraUX:5.*:* | i86xen:AuroraUX:5.*:*)
+	echo i386-pc-auroraux${UNAME_RELEASE}
+	exit ;;
+    i86pc:SunOS:5.*:* | i86xen:SunOS:5.*:*)
+	eval $set_cc_for_build
+	SUN_ARCH=i386
+	# If there is a compiler, see if it is configured for 64-bit objects.
+	# Note that the Sun cc does not turn __LP64__ into 1 like gcc does.
+	# This test works for both compilers.
+	if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+	    if (echo '#ifdef __amd64'; echo IS_64BIT_ARCH; echo '#endif') | \
+		(CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		grep IS_64BIT_ARCH >/dev/null
+	    then
+		SUN_ARCH=x86_64
+	    fi
+	fi
+	echo ${SUN_ARCH}-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:6*:*)
+	# According to config.sub, this is the proper way to canonicalize
+	# SunOS6.  Hard to guess exactly what SunOS6 will be like, but
+	# it's likely to be more like Solaris than SunOS4.
+	echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    sun4*:SunOS:*:*)
+	case "`/usr/bin/arch -k`" in
+	    Series*|S4*)
+		UNAME_RELEASE=`uname -v`
+		;;
+	esac
+	# Japanese Language versions have a version number like `4.1.3-JL'.
+	echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'`
+	exit ;;
+    sun3*:SunOS:*:*)
+	echo m68k-sun-sunos${UNAME_RELEASE}
+	exit ;;
+    sun*:*:4.2BSD:*)
+	UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null`
+	test "x${UNAME_RELEASE}" = x && UNAME_RELEASE=3
+	case "`/bin/arch`" in
+	    sun3)
+		echo m68k-sun-sunos${UNAME_RELEASE}
+		;;
+	    sun4)
+		echo sparc-sun-sunos${UNAME_RELEASE}
+		;;
+	esac
+	exit ;;
+    aushp:SunOS:*:*)
+	echo sparc-auspex-sunos${UNAME_RELEASE}
+	exit ;;
+    # The situation for MiNT is a little confusing.  The machine name
+    # can be virtually everything (everything which is not
+    # "atarist" or "atariste" at least should have a processor
+    # > m68000).  The system name ranges from "MiNT" over "FreeMiNT"
+    # to the lowercase version "mint" (or "freemint").  Finally
+    # the system name "TOS" denotes a system which is actually not
+    # MiNT.  But MiNT is downward compatible to TOS, so this should
+    # be no problem.
+    atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*)
+	echo m68k-atari-mint${UNAME_RELEASE}
+	exit ;;
+    milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*)
+	echo m68k-milan-mint${UNAME_RELEASE}
+	exit ;;
+    hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*)
+	echo m68k-hades-mint${UNAME_RELEASE}
+	exit ;;
+    *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*)
+	echo m68k-unknown-mint${UNAME_RELEASE}
+	exit ;;
+    m68k:machten:*:*)
+	echo m68k-apple-machten${UNAME_RELEASE}
+	exit ;;
+    powerpc:machten:*:*)
+	echo powerpc-apple-machten${UNAME_RELEASE}
+	exit ;;
+    RISC*:Mach:*:*)
+	echo mips-dec-mach_bsd4.3
+	exit ;;
+    RISC*:ULTRIX:*:*)
+	echo mips-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    VAX*:ULTRIX*:*:*)
+	echo vax-dec-ultrix${UNAME_RELEASE}
+	exit ;;
+    2020:CLIX:*:* | 2430:CLIX:*:*)
+	echo clipper-intergraph-clix${UNAME_RELEASE}
+	exit ;;
+    mips:*:*:UMIPS | mips:*:*:RISCos)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+#ifdef __cplusplus
+#include <stdio.h>  /* for printf() prototype */
+	int main (int argc, char *argv[]) {
+#else
+	int main (argc, argv) int argc; char *argv[]; {
+#endif
+	#if defined (host_mips) && defined (MIPSEB)
+	#if defined (SYSTYPE_SYSV)
+	  printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_SVR4)
+	  printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0);
+	#endif
+	#if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD)
+	  printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0);
+	#endif
+	#endif
+	  exit (-1);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c &&
+	  dummyarg=`echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` &&
+	  SYSTEM_NAME=`$dummy $dummyarg` &&
+	    { echo "$SYSTEM_NAME"; exit; }
+	echo mips-mips-riscos${UNAME_RELEASE}
+	exit ;;
+    Motorola:PowerMAX_OS:*:*)
+	echo powerpc-motorola-powermax
+	exit ;;
+    Motorola:*:4.3:PL8-*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:*:*:PowerMAX_OS | Synergy:PowerMAX_OS:*:*)
+	echo powerpc-harris-powermax
+	exit ;;
+    Night_Hawk:Power_UNIX:*:*)
+	echo powerpc-harris-powerunix
+	exit ;;
+    m88k:CX/UX:7*:*)
+	echo m88k-harris-cxux7
+	exit ;;
+    m88k:*:4*:R4*)
+	echo m88k-motorola-sysv4
+	exit ;;
+    m88k:*:3*:R3*)
+	echo m88k-motorola-sysv3
+	exit ;;
+    AViiON:dgux:*:*)
+	# DG/UX returns AViiON for all architectures
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ]
+	then
+	    if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \
+	       [ ${TARGET_BINARY_INTERFACE}x = x ]
+	    then
+		echo m88k-dg-dgux${UNAME_RELEASE}
+	    else
+		echo m88k-dg-dguxbcs${UNAME_RELEASE}
+	    fi
+	else
+	    echo i586-dg-dgux${UNAME_RELEASE}
+	fi
+	exit ;;
+    M88*:DolphinOS:*:*)	# DolphinOS (SVR3)
+	echo m88k-dolphin-sysv3
+	exit ;;
+    M88*:*:R3*:*)
+	# Delta 88k system running SVR3
+	echo m88k-motorola-sysv3
+	exit ;;
+    XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3)
+	echo m88k-tektronix-sysv3
+	exit ;;
+    Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD)
+	echo m68k-tektronix-bsd
+	exit ;;
+    *:IRIX*:*:*)
+	echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'`
+	exit ;;
+    ????????:AIX?:[12].1:2)   # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX.
+	echo romp-ibm-aix     # uname -m gives an 8 hex-code CPU id
+	exit ;;               # Note that: echo "'`uname -s`'" gives 'AIX '
+    i*86:AIX:*:*)
+	echo i386-ibm-aix
+	exit ;;
+    ia64:AIX:*:*)
+	if [ -x /usr/bin/oslevel ] ; then
+		IBM_REV=`/usr/bin/oslevel`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${UNAME_MACHINE}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:2:3)
+	if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then
+		eval $set_cc_for_build
+		sed 's/^		//' << EOF >$dummy.c
+		#include <sys/systemcfg.h>
+
+		main()
+			{
+			if (!__power_pc())
+				exit(1);
+			puts("powerpc-ibm-aix3.2.5");
+			exit(0);
+			}
+EOF
+		if $CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy`
+		then
+			echo "$SYSTEM_NAME"
+		else
+			echo rs6000-ibm-aix3.2.5
+		fi
+	elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then
+		echo rs6000-ibm-aix3.2.4
+	else
+		echo rs6000-ibm-aix3.2
+	fi
+	exit ;;
+    *:AIX:*:[4567])
+	IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'`
+	if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then
+		IBM_ARCH=rs6000
+	else
+		IBM_ARCH=powerpc
+	fi
+	if [ -x /usr/bin/lslpp ] ; then
+		IBM_REV=`/usr/bin/lslpp -Lqc bos.rte.libc |
+			   awk -F: '{ print $3 }' | sed s/[0-9]*$/0/`
+	else
+		IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE}
+	fi
+	echo ${IBM_ARCH}-ibm-aix${IBM_REV}
+	exit ;;
+    *:AIX:*:*)
+	echo rs6000-ibm-aix
+	exit ;;
+    ibmrt:4.4BSD:*|romp-ibm:BSD:*)
+	echo romp-ibm-bsd4.4
+	exit ;;
+    ibmrt:*BSD:*|romp-ibm:BSD:*)            # covers RT/PC BSD and
+	echo romp-ibm-bsd${UNAME_RELEASE}   # 4.3 with uname added to
+	exit ;;                             # report: romp-ibm BSD 4.3
+    *:BOSX:*:*)
+	echo rs6000-bull-bosx
+	exit ;;
+    DPX/2?00:B.O.S.:*:*)
+	echo m68k-bull-sysv3
+	exit ;;
+    9000/[34]??:4.3bsd:1.*:*)
+	echo m68k-hp-bsd
+	exit ;;
+    hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*)
+	echo m68k-hp-bsd4.4
+	exit ;;
+    9000/[34678]??:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	case "${UNAME_MACHINE}" in
+	    9000/31? )            HP_ARCH=m68000 ;;
+	    9000/[34]?? )         HP_ARCH=m68k ;;
+	    9000/[678][0-9][0-9])
+		if [ -x /usr/bin/getconf ]; then
+		    sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null`
+		    sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null`
+		    case "${sc_cpu_version}" in
+		      523) HP_ARCH=hppa1.0 ;; # CPU_PA_RISC1_0
+		      528) HP_ARCH=hppa1.1 ;; # CPU_PA_RISC1_1
+		      532)                      # CPU_PA_RISC2_0
+			case "${sc_kernel_bits}" in
+			  32) HP_ARCH=hppa2.0n ;;
+			  64) HP_ARCH=hppa2.0w ;;
+			  '') HP_ARCH=hppa2.0 ;;   # HP-UX 10.20
+			esac ;;
+		    esac
+		fi
+		if [ "${HP_ARCH}" = "" ]; then
+		    eval $set_cc_for_build
+		    sed 's/^		//' << EOF >$dummy.c
+
+		#define _HPUX_SOURCE
+		#include <stdlib.h>
+		#include <unistd.h>
+
+		int main ()
+		{
+		#if defined(_SC_KERNEL_BITS)
+		    long bits = sysconf(_SC_KERNEL_BITS);
+		#endif
+		    long cpu  = sysconf (_SC_CPU_VERSION);
+
+		    switch (cpu)
+			{
+			case CPU_PA_RISC1_0: puts ("hppa1.0"); break;
+			case CPU_PA_RISC1_1: puts ("hppa1.1"); break;
+			case CPU_PA_RISC2_0:
+		#if defined(_SC_KERNEL_BITS)
+			    switch (bits)
+				{
+				case 64: puts ("hppa2.0w"); break;
+				case 32: puts ("hppa2.0n"); break;
+				default: puts ("hppa2.0"); break;
+				} break;
+		#else  /* !defined(_SC_KERNEL_BITS) */
+			    puts ("hppa2.0"); break;
+		#endif
+			default: puts ("hppa1.0"); break;
+			}
+		    exit (0);
+		}
+EOF
+		    (CCOPTS="" $CC_FOR_BUILD -o $dummy $dummy.c 2>/dev/null) && HP_ARCH=`$dummy`
+		    test -z "$HP_ARCH" && HP_ARCH=hppa
+		fi ;;
+	esac
+	if [ ${HP_ARCH} = hppa2.0w ]
+	then
+	    eval $set_cc_for_build
+
+	    # hppa2.0w-hp-hpux* has a 64-bit kernel and a compiler generating
+	    # 32-bit code.  hppa64-hp-hpux* has the same kernel and a compiler
+	    # generating 64-bit code.  GNU and HP use different nomenclature:
+	    #
+	    # $ CC_FOR_BUILD=cc ./config.guess
+	    # => hppa2.0w-hp-hpux11.23
+	    # $ CC_FOR_BUILD="cc +DA2.0w" ./config.guess
+	    # => hppa64-hp-hpux11.23
+
+	    if echo __LP64__ | (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) |
+		grep -q __LP64__
+	    then
+		HP_ARCH=hppa2.0w
+	    else
+		HP_ARCH=hppa64
+	    fi
+	fi
+	echo ${HP_ARCH}-hp-hpux${HPUX_REV}
+	exit ;;
+    ia64:HP-UX:*:*)
+	HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'`
+	echo ia64-hp-hpux${HPUX_REV}
+	exit ;;
+    3050*:HI-UX:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#include <unistd.h>
+	int
+	main ()
+	{
+	  long cpu = sysconf (_SC_CPU_VERSION);
+	  /* The order matters, because CPU_IS_HP_MC68K erroneously returns
+	     true for CPU_PA_RISC1_0.  CPU_IS_PA_RISC returns correct
+	     results, however.  */
+	  if (CPU_IS_PA_RISC (cpu))
+	    {
+	      switch (cpu)
+		{
+		  case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break;
+		  case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break;
+		  default: puts ("hppa-hitachi-hiuxwe2"); break;
+		}
+	    }
+	  else if (CPU_IS_HP_MC68K (cpu))
+	    puts ("m68k-hitachi-hiuxwe2");
+	  else puts ("unknown-hitachi-hiuxwe2");
+	  exit (0);
+	}
+EOF
+	$CC_FOR_BUILD -o $dummy $dummy.c && SYSTEM_NAME=`$dummy` &&
+		{ echo "$SYSTEM_NAME"; exit; }
+	echo unknown-hitachi-hiuxwe2
+	exit ;;
+    9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* )
+	echo hppa1.1-hp-bsd
+	exit ;;
+    9000/8??:4.3bsd:*:*)
+	echo hppa1.0-hp-bsd
+	exit ;;
+    *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*)
+	echo hppa1.0-hp-mpeix
+	exit ;;
+    hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* )
+	echo hppa1.1-hp-osf
+	exit ;;
+    hp8??:OSF1:*:*)
+	echo hppa1.0-hp-osf
+	exit ;;
+    i*86:OSF1:*:*)
+	if [ -x /usr/sbin/sysversion ] ; then
+	    echo ${UNAME_MACHINE}-unknown-osf1mk
+	else
+	    echo ${UNAME_MACHINE}-unknown-osf1
+	fi
+	exit ;;
+    parisc*:Lites*:*:*)
+	echo hppa1.1-hp-lites
+	exit ;;
+    C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*)
+	echo c1-convex-bsd
+	exit ;;
+    C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*)
+	if getsysinfo -f scalar_acc
+	then echo c32-convex-bsd
+	else echo c2-convex-bsd
+	fi
+	exit ;;
+    C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*)
+	echo c34-convex-bsd
+	exit ;;
+    C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*)
+	echo c38-convex-bsd
+	exit ;;
+    C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*)
+	echo c4-convex-bsd
+	exit ;;
+    CRAY*Y-MP:*:*:*)
+	echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*[A-Z]90:*:*:*)
+	echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \
+	| sed -e 's/CRAY.*\([A-Z]90\)/\1/' \
+	      -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \
+	      -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*TS:*:*:*)
+	echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*T3E:*:*:*)
+	echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    CRAY*SV1:*:*:*)
+	echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    *:UNICOS/mp:*:*)
+	echo craynv-cray-unicosmp${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/'
+	exit ;;
+    F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*)
+	FUJITSU_PROC=`uname -m | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz`
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'`
+	echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    5000:UNIX_System_V:4.*:*)
+	FUJITSU_SYS=`uname -p | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/\///'`
+	FUJITSU_REL=`echo ${UNAME_RELEASE} | tr ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz | sed -e 's/ /_/'`
+	echo "sparc-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}"
+	exit ;;
+    i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*)
+	echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE}
+	exit ;;
+    sparc*:BSD/OS:*:*)
+	echo sparc-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:BSD/OS:*:*)
+	echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE}
+	exit ;;
+    *:FreeBSD:*:*)
+	UNAME_PROCESSOR=`/usr/bin/uname -p`
+	case ${UNAME_PROCESSOR} in
+	    amd64)
+		UNAME_PROCESSOR=x86_64 ;;
+	    i386)
+		UNAME_PROCESSOR=i586 ;;
+	esac
+	echo ${UNAME_PROCESSOR}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    i*:CYGWIN*:*)
+	echo ${UNAME_MACHINE}-pc-cygwin
+	exit ;;
+    *:MINGW64*:*)
+	echo ${UNAME_MACHINE}-pc-mingw64
+	exit ;;
+    *:MINGW*:*)
+	echo ${UNAME_MACHINE}-pc-mingw32
+	exit ;;
+    *:MSYS*:*)
+	echo ${UNAME_MACHINE}-pc-msys
+	exit ;;
+    i*:windows32*:*)
+	# uname -m includes "-pc" on this system.
+	echo ${UNAME_MACHINE}-mingw32
+	exit ;;
+    i*:PW*:*)
+	echo ${UNAME_MACHINE}-pc-pw32
+	exit ;;
+    *:Interix*:*)
+	case ${UNAME_MACHINE} in
+	    x86)
+		echo i586-pc-interix${UNAME_RELEASE}
+		exit ;;
+	    authenticamd | genuineintel | EM64T)
+		echo x86_64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	    IA64)
+		echo ia64-unknown-interix${UNAME_RELEASE}
+		exit ;;
+	esac ;;
+    [345]86:Windows_95:* | [345]86:Windows_98:* | [345]86:Windows_NT:*)
+	echo i${UNAME_MACHINE}-pc-mks
+	exit ;;
+    8664:Windows_NT:*)
+	echo x86_64-pc-mks
+	exit ;;
+    i*:Windows_NT*:* | Pentium*:Windows_NT*:*)
+	# How do we know it's Interix rather than the generic POSIX subsystem?
+	# It also conflicts with pre-2.0 versions of AT&T UWIN. Should we
+	# UNAME_MACHINE based on the output of uname instead of i386?
+	echo i586-pc-interix
+	exit ;;
+    i*:UWIN*:*)
+	echo ${UNAME_MACHINE}-pc-uwin
+	exit ;;
+    amd64:CYGWIN*:*:* | x86_64:CYGWIN*:*:*)
+	echo x86_64-unknown-cygwin
+	exit ;;
+    p*:CYGWIN*:*)
+	echo powerpcle-unknown-cygwin
+	exit ;;
+    prep*:SunOS:5.*:*)
+	echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'`
+	exit ;;
+    *:GNU:*:*)
+	# the GNU system
+	echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-${LIBC}`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'`
+	exit ;;
+    *:GNU/*:*:*)
+	# other systems with GNU libc and userland
+	echo ${UNAME_MACHINE}-unknown-`echo ${UNAME_SYSTEM} | sed 's,^[^/]*/,,' | tr "[:upper:]" "[:lower:]"``echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`-${LIBC}
+	exit ;;
+    i*86:Minix:*:*)
+	echo ${UNAME_MACHINE}-pc-minix
+	exit ;;
+    aarch64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    aarch64_be:Linux:*:*)
+	UNAME_MACHINE=aarch64_be
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    alpha:Linux:*:*)
+	case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in
+	  EV5)   UNAME_MACHINE=alphaev5 ;;
+	  EV56)  UNAME_MACHINE=alphaev56 ;;
+	  PCA56) UNAME_MACHINE=alphapca56 ;;
+	  PCA57) UNAME_MACHINE=alphapca56 ;;
+	  EV6)   UNAME_MACHINE=alphaev6 ;;
+	  EV67)  UNAME_MACHINE=alphaev67 ;;
+	  EV68*) UNAME_MACHINE=alphaev68 ;;
+	esac
+	objdump --private-headers /bin/sh | grep -q ld.so.1
+	if test "$?" = 0 ; then LIBC=gnulibc1 ; fi
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arc:Linux:*:* | arceb:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    arm*:Linux:*:*)
+	eval $set_cc_for_build
+	if echo __ARM_EABI__ | $CC_FOR_BUILD -E - 2>/dev/null \
+	    | grep -q __ARM_EABI__
+	then
+	    echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	else
+	    if echo __ARM_PCS_VFP | $CC_FOR_BUILD -E - 2>/dev/null \
+		| grep -q __ARM_PCS_VFP
+	    then
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabi
+	    else
+		echo ${UNAME_MACHINE}-unknown-linux-${LIBC}eabihf
+	    fi
+	fi
+	exit ;;
+    avr32*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    cris:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    crisv32:Linux:*:*)
+	echo ${UNAME_MACHINE}-axis-linux-${LIBC}
+	exit ;;
+    e2k:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    frv:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    hexagon:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+	exit ;;
+    ia64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    k1om:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m32r*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    m68*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    mips:Linux:*:* | mips64:Linux:*:*)
+	eval $set_cc_for_build
+	sed 's/^	//' << EOF >$dummy.c
+	#undef CPU
+	#undef ${UNAME_MACHINE}
+	#undef ${UNAME_MACHINE}el
+	#if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL)
+	CPU=${UNAME_MACHINE}el
+	#else
+	#if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB)
+	CPU=${UNAME_MACHINE}
+	#else
+	CPU=
+	#endif
+	#endif
+EOF
+	eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep '^CPU'`
+	test x"${CPU}" != x && { echo "${CPU}-unknown-linux-${LIBC}"; exit; }
+	;;
+    mips64el:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    openrisc*:Linux:*:*)
+	echo or1k-unknown-linux-${LIBC}
+	exit ;;
+    or32:Linux:*:* | or1k*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    padre:Linux:*:*)
+	echo sparc-unknown-linux-${LIBC}
+	exit ;;
+    parisc64:Linux:*:* | hppa64:Linux:*:*)
+	echo hppa64-unknown-linux-${LIBC}
+	exit ;;
+    parisc:Linux:*:* | hppa:Linux:*:*)
+	# Look for CPU level
+	case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in
+	  PA7*) echo hppa1.1-unknown-linux-${LIBC} ;;
+	  PA8*) echo hppa2.0-unknown-linux-${LIBC} ;;
+	  *)    echo hppa-unknown-linux-${LIBC} ;;
+	esac
+	exit ;;
+    ppc64:Linux:*:*)
+	echo powerpc64-unknown-linux-${LIBC}
+	exit ;;
+    ppc:Linux:*:*)
+	echo powerpc-unknown-linux-${LIBC}
+	exit ;;
+    ppc64le:Linux:*:*)
+	echo powerpc64le-unknown-linux-${LIBC}
+	exit ;;
+    ppcle:Linux:*:*)
+	echo powerpcle-unknown-linux-${LIBC}
+	exit ;;
+    riscv32:Linux:*:* | riscv64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    s390:Linux:*:* | s390x:Linux:*:*)
+	echo ${UNAME_MACHINE}-ibm-linux-${LIBC}
+	exit ;;
+    sh64*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sh*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    sparc:Linux:*:* | sparc64:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    tile*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    vax:Linux:*:*)
+	echo ${UNAME_MACHINE}-dec-linux-${LIBC}
+	exit ;;
+    x86_64:Linux:*:*)
+	echo ${UNAME_MACHINE}-pc-linux-${LIBC}
+	exit ;;
+    xtensa*:Linux:*:*)
+	echo ${UNAME_MACHINE}-unknown-linux-${LIBC}
+	exit ;;
+    i*86:DYNIX/ptx:4*:*)
+	# ptx 4.0 does uname -s correctly, with DYNIX/ptx in there.
+	# earlier versions are messed up and put the nodename in both
+	# sysname and nodename.
+	echo i386-sequent-sysv4
+	exit ;;
+    i*86:UNIX_SV:4.2MP:2.*)
+	# Unixware is an offshoot of SVR4, but it has its own version
+	# number series starting with 2...
+	# I am not positive that other SVR4 systems won't match this,
+	# I just have to hope.  -- rms.
+	# Use sysv4.2uw... so that sysv4* matches it.
+	echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION}
+	exit ;;
+    i*86:OS/2:*:*)
+	# If we were able to find `uname', then EMX Unix compatibility
+	# is probably installed.
+	echo ${UNAME_MACHINE}-pc-os2-emx
+	exit ;;
+    i*86:XTS-300:*:STOP)
+	echo ${UNAME_MACHINE}-unknown-stop
+	exit ;;
+    i*86:atheos:*:*)
+	echo ${UNAME_MACHINE}-unknown-atheos
+	exit ;;
+    i*86:syllable:*:*)
+	echo ${UNAME_MACHINE}-pc-syllable
+	exit ;;
+    i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.[02]*:*)
+	echo i386-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    i*86:*DOS:*:*)
+	echo ${UNAME_MACHINE}-pc-msdosdjgpp
+	exit ;;
+    i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*)
+	UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'`
+	if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then
+		echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL}
+	else
+		echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL}
+	fi
+	exit ;;
+    i*86:*:5:[678]*)
+	# UnixWare 7.x, OpenUNIX and OpenServer 6.
+	case `/bin/uname -X | grep "^Machine"` in
+	    *486*)	     UNAME_MACHINE=i486 ;;
+	    *Pentium)	     UNAME_MACHINE=i586 ;;
+	    *Pent*|*Celeron) UNAME_MACHINE=i686 ;;
+	esac
+	echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION}
+	exit ;;
+    i*86:*:3.2:*)
+	if test -f /usr/options/cb.name; then
+		UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name`
+		echo ${UNAME_MACHINE}-pc-isc$UNAME_REL
+	elif /bin/uname -X 2>/dev/null >/dev/null ; then
+		UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')`
+		(/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486
+		(/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \
+			&& UNAME_MACHINE=i586
+		(/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		(/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \
+			&& UNAME_MACHINE=i686
+		echo ${UNAME_MACHINE}-pc-sco$UNAME_REL
+	else
+		echo ${UNAME_MACHINE}-pc-sysv32
+	fi
+	exit ;;
+    pc:*:*:*)
+	# Left here for compatibility:
+	# uname -m prints for DJGPP always 'pc', but it prints nothing about
+	# the processor, so we play safe by assuming i586.
+	# Note: whatever this is, it MUST be the same as what config.sub
+	# prints for the "djgpp" host, or else GDB configure will decide that
+	# this is a cross-build.
+	echo i586-pc-msdosdjgpp
+	exit ;;
+    Intel:Mach:3*:*)
+	echo i386-pc-mach3
+	exit ;;
+    paragon:*:*:*)
+	echo i860-intel-osf1
+	exit ;;
+    i860:*:4.*:*) # i860-SVR4
+	if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then
+	  echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4
+	else # Add other i860-SVR4 vendors below as they are discovered.
+	  echo i860-unknown-sysv${UNAME_RELEASE}  # Unknown i860-SVR4
+	fi
+	exit ;;
+    mini*:CTIX:SYS*5:*)
+	# "miniframe"
+	echo m68010-convergent-sysv
+	exit ;;
+    mc68k:UNIX:SYSTEM5:3.51m)
+	echo m68k-convergent-sysv
+	exit ;;
+    M680?0:D-NIX:5.3:*)
+	echo m68k-diab-dnix
+	exit ;;
+    M68*:*:R3V[5678]*:*)
+	test -r /sysV68 && { echo 'm68k-motorola-sysv'; exit; } ;;
+    3[345]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0 | SDS2:*:4.0:3.0 | SHG2:*:4.0:3.0 | S7501*:*:4.0:3.0)
+	OS_REL=''
+	test -r /etc/.relid \
+	&& OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	  && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*)
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	  && { echo i486-ncr-sysv4; exit; } ;;
+    NCR*:*:4.2:* | MPRAS*:*:4.2:*)
+	OS_REL='.3'
+	test -r /etc/.relid \
+	    && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid`
+	/bin/uname -p 2>/dev/null | grep 86 >/dev/null \
+	    && { echo i486-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; }
+	/bin/uname -p 2>/dev/null | /bin/grep pteron >/dev/null \
+	    && { echo i586-ncr-sysv4.3${OS_REL}; exit; } ;;
+    m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*)
+	echo m68k-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    mc68030:UNIX_System_V:4.*:*)
+	echo m68k-atari-sysv4
+	exit ;;
+    TSUNAMI:LynxOS:2.*:*)
+	echo sparc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    rs6000:LynxOS:2.*:*)
+	echo rs6000-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.[02]*:*)
+	echo powerpc-unknown-lynxos${UNAME_RELEASE}
+	exit ;;
+    SM[BE]S:UNIX_SV:*:*)
+	echo mips-dde-sysv${UNAME_RELEASE}
+	exit ;;
+    RM*:ReliantUNIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    RM*:SINIX-*:*:*)
+	echo mips-sni-sysv4
+	exit ;;
+    *:SINIX-*:*:*)
+	if uname -p 2>/dev/null >/dev/null ; then
+		UNAME_MACHINE=`(uname -p) 2>/dev/null`
+		echo ${UNAME_MACHINE}-sni-sysv4
+	else
+		echo ns32k-sni-sysv
+	fi
+	exit ;;
+    PENTIUM:*:4.0*:*)	# Unisys `ClearPath HMP IX 4000' SVR4/MP effort
+			# says <Richard.M.Bartel@ccMail.Census.GOV>
+	echo i586-unisys-sysv4
+	exit ;;
+    *:UNIX_System_V:4*:FTX*)
+	# From Gerald Hewes <hewes@openmarket.com>.
+	# How about differentiating between stratus architectures? -djm
+	echo hppa1.1-stratus-sysv4
+	exit ;;
+    *:*:*:FTX*)
+	# From seanf@swdc.stratus.com.
+	echo i860-stratus-sysv4
+	exit ;;
+    i*86:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo ${UNAME_MACHINE}-stratus-vos
+	exit ;;
+    *:VOS:*:*)
+	# From Paul.Green@stratus.com.
+	echo hppa1.1-stratus-vos
+	exit ;;
+    mc68*:A/UX:*:*)
+	echo m68k-apple-aux${UNAME_RELEASE}
+	exit ;;
+    news*:NEWS-OS:6*:*)
+	echo mips-sony-newsos6
+	exit ;;
+    R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*)
+	if [ -d /usr/nec ]; then
+		echo mips-nec-sysv${UNAME_RELEASE}
+	else
+		echo mips-unknown-sysv${UNAME_RELEASE}
+	fi
+	exit ;;
+    BeBox:BeOS:*:*)	# BeOS running on hardware made by Be, PPC only.
+	echo powerpc-be-beos
+	exit ;;
+    BeMac:BeOS:*:*)	# BeOS running on Mac or Mac clone, PPC only.
+	echo powerpc-apple-beos
+	exit ;;
+    BePC:BeOS:*:*)	# BeOS running on Intel PC compatible.
+	echo i586-pc-beos
+	exit ;;
+    BePC:Haiku:*:*)	# Haiku running on Intel PC compatible.
+	echo i586-pc-haiku
+	exit ;;
+    x86_64:Haiku:*:*)
+	echo x86_64-unknown-haiku
+	exit ;;
+    SX-4:SUPER-UX:*:*)
+	echo sx4-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-5:SUPER-UX:*:*)
+	echo sx5-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-6:SUPER-UX:*:*)
+	echo sx6-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-7:SUPER-UX:*:*)
+	echo sx7-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8:SUPER-UX:*:*)
+	echo sx8-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-8R:SUPER-UX:*:*)
+	echo sx8r-nec-superux${UNAME_RELEASE}
+	exit ;;
+    SX-ACE:SUPER-UX:*:*)
+	echo sxace-nec-superux${UNAME_RELEASE}
+	exit ;;
+    Power*:Rhapsody:*:*)
+	echo powerpc-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Rhapsody:*:*)
+	echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE}
+	exit ;;
+    *:Darwin:*:*)
+	UNAME_PROCESSOR=`uname -p` || UNAME_PROCESSOR=unknown
+	eval $set_cc_for_build
+	if test "$UNAME_PROCESSOR" = unknown ; then
+	    UNAME_PROCESSOR=powerpc
+	fi
+	if test `echo "$UNAME_RELEASE" | sed -e 's/\..*//'` -le 10 ; then
+	    if [ "$CC_FOR_BUILD" != no_compiler_found ]; then
+		if (echo '#ifdef __LP64__'; echo IS_64BIT_ARCH; echo '#endif') | \
+		    (CCOPTS="" $CC_FOR_BUILD -E - 2>/dev/null) | \
+		    grep IS_64BIT_ARCH >/dev/null
+		then
+		    case $UNAME_PROCESSOR in
+			i386) UNAME_PROCESSOR=x86_64 ;;
+			powerpc) UNAME_PROCESSOR=powerpc64 ;;
+		    esac
+		fi
+	    fi
+	elif test "$UNAME_PROCESSOR" = i386 ; then
+	    # Avoid executing cc on OS X 10.9, as it ships with a stub
+	    # that puts up a graphical alert prompting to install
+	    # developer tools.  Any system running Mac OS X 10.7 or
+	    # later (Darwin 11 and later) is required to have a 64-bit
+	    # processor. This is not true of the ARM version of Darwin
+	    # that Apple uses in portable devices.
+	    UNAME_PROCESSOR=x86_64
+	fi
+	echo ${UNAME_PROCESSOR}-apple-darwin${UNAME_RELEASE}
+	exit ;;
+    *:procnto*:*:* | *:QNX:[0123456789]*:*)
+	UNAME_PROCESSOR=`uname -p`
+	if test "$UNAME_PROCESSOR" = x86; then
+		UNAME_PROCESSOR=i386
+		UNAME_MACHINE=pc
+	fi
+	echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE}
+	exit ;;
+    *:QNX:*:4*)
+	echo i386-pc-qnx
+	exit ;;
+    NEO-?:NONSTOP_KERNEL:*:*)
+	echo neo-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSE-*:NONSTOP_KERNEL:*:*)
+	echo nse-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSR-?:NONSTOP_KERNEL:*:*)
+	echo nsr-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    NSX-?:NONSTOP_KERNEL:*:*)
+	echo nsx-tandem-nsk${UNAME_RELEASE}
+	exit ;;
+    *:NonStop-UX:*:*)
+	echo mips-compaq-nonstopux
+	exit ;;
+    BS2000:POSIX*:*:*)
+	echo bs2000-siemens-sysv
+	exit ;;
+    DS/*:UNIX_System_V:*:*)
+	echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE}
+	exit ;;
+    *:Plan9:*:*)
+	# "uname -m" is not consistent, so use $cputype instead. 386
+	# is converted to i386 for consistency with other x86
+	# operating systems.
+	if test "$cputype" = 386; then
+	    UNAME_MACHINE=i386
+	else
+	    UNAME_MACHINE="$cputype"
+	fi
+	echo ${UNAME_MACHINE}-unknown-plan9
+	exit ;;
+    *:TOPS-10:*:*)
+	echo pdp10-unknown-tops10
+	exit ;;
+    *:TENEX:*:*)
+	echo pdp10-unknown-tenex
+	exit ;;
+    KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*)
+	echo pdp10-dec-tops20
+	exit ;;
+    XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*)
+	echo pdp10-xkl-tops20
+	exit ;;
+    *:TOPS-20:*:*)
+	echo pdp10-unknown-tops20
+	exit ;;
+    *:ITS:*:*)
+	echo pdp10-unknown-its
+	exit ;;
+    SEI:*:*:SEIUX)
+	echo mips-sei-seiux${UNAME_RELEASE}
+	exit ;;
+    *:DragonFly:*:*)
+	echo ${UNAME_MACHINE}-unknown-dragonfly`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`
+	exit ;;
+    *:*VMS:*:*)
+	UNAME_MACHINE=`(uname -p) 2>/dev/null`
+	case "${UNAME_MACHINE}" in
+	    A*) echo alpha-dec-vms ; exit ;;
+	    I*) echo ia64-dec-vms ; exit ;;
+	    V*) echo vax-dec-vms ; exit ;;
+	esac ;;
+    *:XENIX:*:SysV)
+	echo i386-pc-xenix
+	exit ;;
+    i*86:skyos:*:*)
+	echo ${UNAME_MACHINE}-pc-skyos`echo ${UNAME_RELEASE} | sed -e 's/ .*$//'`
+	exit ;;
+    i*86:rdos:*:*)
+	echo ${UNAME_MACHINE}-pc-rdos
+	exit ;;
+    i*86:AROS:*:*)
+	echo ${UNAME_MACHINE}-pc-aros
+	exit ;;
+    x86_64:VMkernel:*:*)
+	echo ${UNAME_MACHINE}-unknown-esx
+	exit ;;
+    amd64:Isilon\ OneFS:*:*)
+	echo x86_64-unknown-onefs
+	exit ;;
+esac
+
+cat >&2 <<EOF
+$0: unable to guess system type
+
+This script (version $timestamp), has failed to recognize the
+operating system you are using. If your script is old, overwrite
+config.guess and config.sub with the latest versions from:
+
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.guess
+and
+  http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+If $0 has already been updated, send the following data and any
+information you think might be pertinent to config-patches@gnu.org to
+provide the necessary information to handle your system.
+
+config.guess timestamp = $timestamp
+
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null`
+/bin/uname -X     = `(/bin/uname -X) 2>/dev/null`
+
+hostinfo               = `(hostinfo) 2>/dev/null`
+/bin/universe          = `(/bin/universe) 2>/dev/null`
+/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null`
+/bin/arch              = `(/bin/arch) 2>/dev/null`
+/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null`
+
+UNAME_MACHINE = ${UNAME_MACHINE}
+UNAME_RELEASE = ${UNAME_RELEASE}
+UNAME_SYSTEM  = ${UNAME_SYSTEM}
+UNAME_VERSION = ${UNAME_VERSION}
+EOF
+
+exit 1
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
 # time-stamp-start: "timestamp='"
 # time-stamp-format: "%:y-%02m-%02d"
 # time-stamp-end: "'"
diff --git a/config.sub b/config.sub
--- a/config.sub
+++ b/config.sub
@@ -1,1859 +1,1835 @@
 #! /bin/sh
 # Configuration validation subroutine script.
-#   Copyright 1992-2021 Free Software Foundation, Inc.
-
-timestamp='2021-01-08'
-
-# This file is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-# General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# along with this program; if not, see <https://www.gnu.org/licenses/>.
-#
-# As a special exception to the GNU General Public License, if you
-# distribute this file as part of a program that contains a
-# configuration script generated by Autoconf, you may include it under
-# the same distribution terms that you use for the rest of that
-# program.  This Exception is an additional permission under section 7
-# of the GNU General Public License, version 3 ("GPLv3").
-
-
-# Please send patches to <config-patches@gnu.org>.
-#
-# Configuration subroutine to validate and canonicalize a configuration type.
-# Supply the specified configuration type as an argument.
-# If it is invalid, we print an error message on stderr and exit with code 1.
-# Otherwise, we print the canonical config type on stdout and succeed.
-
-# You can get the latest version of this script from:
-# https://git.savannah.gnu.org/cgit/config.git/plain/config.sub
-
-# This file is supposed to be the same for all GNU packages
-# and recognize all the CPU types, system types and aliases
-# that are meaningful with *any* GNU software.
-# Each package is responsible for reporting which valid configurations
-# it does not support.  The user should be able to distinguish
-# a failure to support a valid configuration from a meaningless
-# configuration.
-
-# The goal of this file is to map all the various variations of a given
-# machine specification into a single specification in the form:
-#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
-# or in some cases, the newer four-part form:
-#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
-# It is wrong to echo any other type of specification.
-
-me=$(echo "$0" | sed -e 's,.*/,,')
-
-usage="\
-Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
-
-Canonicalize a configuration name.
-
-Options:
-  -h, --help         print this help, then exit
-  -t, --time-stamp   print date of last modification, then exit
-  -v, --version      print version number, then exit
-
-Report bugs and patches to <config-patches@gnu.org>."
-
-version="\
-GNU config.sub ($timestamp)
-
-Copyright 1992-2021 Free Software Foundation, Inc.
-
-This is free software; see the source for copying conditions.  There is NO
-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
-
-help="
-Try \`$me --help' for more information."
-
-# Parse command line
-while test $# -gt 0 ; do
-  case $1 in
-    --time-stamp | --time* | -t )
-       echo "$timestamp" ; exit ;;
-    --version | -v )
-       echo "$version" ; exit ;;
-    --help | --h* | -h )
-       echo "$usage"; exit ;;
-    -- )     # Stop option processing
-       shift; break ;;
-    - )	# Use stdin as input.
-       break ;;
-    -* )
-       echo "$me: invalid option $1$help" >&2
-       exit 1 ;;
-
-    *local*)
-       # First pass through any local machine types.
-       echo "$1"
-       exit ;;
-
-    * )
-       break ;;
-  esac
-done
-
-case $# in
- 0) echo "$me: missing argument$help" >&2
-    exit 1;;
- 1) ;;
- *) echo "$me: too many arguments$help" >&2
-    exit 1;;
-esac
-
-# Split fields of configuration type
-# shellcheck disable=SC2162
-IFS="-" read field1 field2 field3 field4 <<EOF
-$1
-EOF
-
-# Separate into logical components for further validation
-case $1 in
-	*-*-*-*-*)
-		echo Invalid configuration \`"$1"\': more than four components >&2
-		exit 1
-		;;
-	*-*-*-*)
-		basic_machine=$field1-$field2
-		basic_os=$field3-$field4
-		;;
-	*-*-*)
-		# Ambiguous whether COMPANY is present, or skipped and KERNEL-OS is two
-		# parts
-		maybe_os=$field2-$field3
-		case $maybe_os in
-			nto-qnx* | linux-* | uclinux-uclibc* \
-			| uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* \
-			| netbsd*-eabi* | kopensolaris*-gnu* | cloudabi*-eabi* \
-			| storm-chaos* | os2-emx* | rtmk-nova*)
-				basic_machine=$field1
-				basic_os=$maybe_os
-				;;
-			android-linux)
-				basic_machine=$field1-unknown
-				basic_os=linux-android
-				;;
-			*)
-				basic_machine=$field1-$field2
-				basic_os=$field3
-				;;
-		esac
-		;;
-	*-*)
-		# A lone config we happen to match not fitting any pattern
-		case $field1-$field2 in
-			decstation-3100)
-				basic_machine=mips-dec
-				basic_os=
-				;;
-			*-*)
-				# Second component is usually, but not always the OS
-				case $field2 in
-					# Prevent following clause from handling this valid os
-					sun*os*)
-						basic_machine=$field1
-						basic_os=$field2
-						;;
-					# Manufacturers
-					dec* | mips* | sequent* | encore* | pc533* | sgi* | sony* \
-					| att* | 7300* | 3300* | delta* | motorola* | sun[234]* \
-					| unicom* | ibm* | next | hp | isi* | apollo | altos* \
-					| convergent* | ncr* | news | 32* | 3600* | 3100* \
-					| hitachi* | c[123]* | convex* | sun | crds | omron* | dg \
-					| ultra | tti* | harris | dolphin | highlevel | gould \
-					| cbm | ns | masscomp | apple | axis | knuth | cray \
-					| microblaze* | sim | cisco \
-					| oki | wec | wrs | winbond)
-						basic_machine=$field1-$field2
-						basic_os=
-						;;
-					*)
-						basic_machine=$field1
-						basic_os=$field2
-						;;
-				esac
-			;;
-		esac
-		;;
-	*)
-		# Convert single-component short-hands not valid as part of
-		# multi-component configurations.
-		case $field1 in
-			386bsd)
-				basic_machine=i386-pc
-				basic_os=bsd
-				;;
-			a29khif)
-				basic_machine=a29k-amd
-				basic_os=udi
-				;;
-			adobe68k)
-				basic_machine=m68010-adobe
-				basic_os=scout
-				;;
-			alliant)
-				basic_machine=fx80-alliant
-				basic_os=
-				;;
-			altos | altos3068)
-				basic_machine=m68k-altos
-				basic_os=
-				;;
-			am29k)
-				basic_machine=a29k-none
-				basic_os=bsd
-				;;
-			amdahl)
-				basic_machine=580-amdahl
-				basic_os=sysv
-				;;
-			amiga)
-				basic_machine=m68k-unknown
-				basic_os=
-				;;
-			amigaos | amigados)
-				basic_machine=m68k-unknown
-				basic_os=amigaos
-				;;
-			amigaunix | amix)
-				basic_machine=m68k-unknown
-				basic_os=sysv4
-				;;
-			apollo68)
-				basic_machine=m68k-apollo
-				basic_os=sysv
-				;;
-			apollo68bsd)
-				basic_machine=m68k-apollo
-				basic_os=bsd
-				;;
-			aros)
-				basic_machine=i386-pc
-				basic_os=aros
-				;;
-			aux)
-				basic_machine=m68k-apple
-				basic_os=aux
-				;;
-			balance)
-				basic_machine=ns32k-sequent
-				basic_os=dynix
-				;;
-			blackfin)
-				basic_machine=bfin-unknown
-				basic_os=linux
-				;;
-			cegcc)
-				basic_machine=arm-unknown
-				basic_os=cegcc
-				;;
-			convex-c1)
-				basic_machine=c1-convex
-				basic_os=bsd
-				;;
-			convex-c2)
-				basic_machine=c2-convex
-				basic_os=bsd
-				;;
-			convex-c32)
-				basic_machine=c32-convex
-				basic_os=bsd
-				;;
-			convex-c34)
-				basic_machine=c34-convex
-				basic_os=bsd
-				;;
-			convex-c38)
-				basic_machine=c38-convex
-				basic_os=bsd
-				;;
-			cray)
-				basic_machine=j90-cray
-				basic_os=unicos
-				;;
-			crds | unos)
-				basic_machine=m68k-crds
-				basic_os=
-				;;
-			da30)
-				basic_machine=m68k-da30
-				basic_os=
-				;;
-			decstation | pmax | pmin | dec3100 | decstatn)
-				basic_machine=mips-dec
-				basic_os=
-				;;
-			delta88)
-				basic_machine=m88k-motorola
-				basic_os=sysv3
-				;;
-			dicos)
-				basic_machine=i686-pc
-				basic_os=dicos
-				;;
-			djgpp)
-				basic_machine=i586-pc
-				basic_os=msdosdjgpp
-				;;
-			ebmon29k)
-				basic_machine=a29k-amd
-				basic_os=ebmon
-				;;
-			es1800 | OSE68k | ose68k | ose | OSE)
-				basic_machine=m68k-ericsson
-				basic_os=ose
-				;;
-			gmicro)
-				basic_machine=tron-gmicro
-				basic_os=sysv
-				;;
-			go32)
-				basic_machine=i386-pc
-				basic_os=go32
-				;;
-			h8300hms)
-				basic_machine=h8300-hitachi
-				basic_os=hms
-				;;
-			h8300xray)
-				basic_machine=h8300-hitachi
-				basic_os=xray
-				;;
-			h8500hms)
-				basic_machine=h8500-hitachi
-				basic_os=hms
-				;;
-			harris)
-				basic_machine=m88k-harris
-				basic_os=sysv3
-				;;
-			hp300 | hp300hpux)
-				basic_machine=m68k-hp
-				basic_os=hpux
-				;;
-			hp300bsd)
-				basic_machine=m68k-hp
-				basic_os=bsd
-				;;
-			hppaosf)
-				basic_machine=hppa1.1-hp
-				basic_os=osf
-				;;
-			hppro)
-				basic_machine=hppa1.1-hp
-				basic_os=proelf
-				;;
-			i386mach)
-				basic_machine=i386-mach
-				basic_os=mach
-				;;
-			isi68 | isi)
-				basic_machine=m68k-isi
-				basic_os=sysv
-				;;
-			m68knommu)
-				basic_machine=m68k-unknown
-				basic_os=linux
-				;;
-			magnum | m3230)
-				basic_machine=mips-mips
-				basic_os=sysv
-				;;
-			merlin)
-				basic_machine=ns32k-utek
-				basic_os=sysv
-				;;
-			mingw64)
-				basic_machine=x86_64-pc
-				basic_os=mingw64
-				;;
-			mingw32)
-				basic_machine=i686-pc
-				basic_os=mingw32
-				;;
-			mingw32ce)
-				basic_machine=arm-unknown
-				basic_os=mingw32ce
-				;;
-			monitor)
-				basic_machine=m68k-rom68k
-				basic_os=coff
-				;;
-			morphos)
-				basic_machine=powerpc-unknown
-				basic_os=morphos
-				;;
-			moxiebox)
-				basic_machine=moxie-unknown
-				basic_os=moxiebox
-				;;
-			msdos)
-				basic_machine=i386-pc
-				basic_os=msdos
-				;;
-			msys)
-				basic_machine=i686-pc
-				basic_os=msys
-				;;
-			mvs)
-				basic_machine=i370-ibm
-				basic_os=mvs
-				;;
-			nacl)
-				basic_machine=le32-unknown
-				basic_os=nacl
-				;;
-			ncr3000)
-				basic_machine=i486-ncr
-				basic_os=sysv4
-				;;
-			netbsd386)
-				basic_machine=i386-pc
-				basic_os=netbsd
-				;;
-			netwinder)
-				basic_machine=armv4l-rebel
-				basic_os=linux
-				;;
-			news | news700 | news800 | news900)
-				basic_machine=m68k-sony
-				basic_os=newsos
-				;;
-			news1000)
-				basic_machine=m68030-sony
-				basic_os=newsos
-				;;
-			necv70)
-				basic_machine=v70-nec
-				basic_os=sysv
-				;;
-			nh3000)
-				basic_machine=m68k-harris
-				basic_os=cxux
-				;;
-			nh[45]000)
-				basic_machine=m88k-harris
-				basic_os=cxux
-				;;
-			nindy960)
-				basic_machine=i960-intel
-				basic_os=nindy
-				;;
-			mon960)
-				basic_machine=i960-intel
-				basic_os=mon960
-				;;
-			nonstopux)
-				basic_machine=mips-compaq
-				basic_os=nonstopux
-				;;
-			os400)
-				basic_machine=powerpc-ibm
-				basic_os=os400
-				;;
-			OSE68000 | ose68000)
-				basic_machine=m68000-ericsson
-				basic_os=ose
-				;;
-			os68k)
-				basic_machine=m68k-none
-				basic_os=os68k
-				;;
-			paragon)
-				basic_machine=i860-intel
-				basic_os=osf
-				;;
-			parisc)
-				basic_machine=hppa-unknown
-				basic_os=linux
-				;;
-			psp)
-				basic_machine=mipsallegrexel-sony
-				basic_os=psp
-				;;
-			pw32)
-				basic_machine=i586-unknown
-				basic_os=pw32
-				;;
-			rdos | rdos64)
-				basic_machine=x86_64-pc
-				basic_os=rdos
-				;;
-			rdos32)
-				basic_machine=i386-pc
-				basic_os=rdos
-				;;
-			rom68k)
-				basic_machine=m68k-rom68k
-				basic_os=coff
-				;;
-			sa29200)
-				basic_machine=a29k-amd
-				basic_os=udi
-				;;
-			sei)
-				basic_machine=mips-sei
-				basic_os=seiux
-				;;
-			sequent)
-				basic_machine=i386-sequent
-				basic_os=
-				;;
-			sps7)
-				basic_machine=m68k-bull
-				basic_os=sysv2
-				;;
-			st2000)
-				basic_machine=m68k-tandem
-				basic_os=
-				;;
-			stratus)
-				basic_machine=i860-stratus
-				basic_os=sysv4
-				;;
-			sun2)
-				basic_machine=m68000-sun
-				basic_os=
-				;;
-			sun2os3)
-				basic_machine=m68000-sun
-				basic_os=sunos3
-				;;
-			sun2os4)
-				basic_machine=m68000-sun
-				basic_os=sunos4
-				;;
-			sun3)
-				basic_machine=m68k-sun
-				basic_os=
-				;;
-			sun3os3)
-				basic_machine=m68k-sun
-				basic_os=sunos3
-				;;
-			sun3os4)
-				basic_machine=m68k-sun
-				basic_os=sunos4
-				;;
-			sun4)
-				basic_machine=sparc-sun
-				basic_os=
-				;;
-			sun4os3)
-				basic_machine=sparc-sun
-				basic_os=sunos3
-				;;
-			sun4os4)
-				basic_machine=sparc-sun
-				basic_os=sunos4
-				;;
-			sun4sol2)
-				basic_machine=sparc-sun
-				basic_os=solaris2
-				;;
-			sun386 | sun386i | roadrunner)
-				basic_machine=i386-sun
-				basic_os=
-				;;
-			sv1)
-				basic_machine=sv1-cray
-				basic_os=unicos
-				;;
-			symmetry)
-				basic_machine=i386-sequent
-				basic_os=dynix
-				;;
-			t3e)
-				basic_machine=alphaev5-cray
-				basic_os=unicos
-				;;
-			t90)
-				basic_machine=t90-cray
-				basic_os=unicos
-				;;
-			toad1)
-				basic_machine=pdp10-xkl
-				basic_os=tops20
-				;;
-			tpf)
-				basic_machine=s390x-ibm
-				basic_os=tpf
-				;;
-			udi29k)
-				basic_machine=a29k-amd
-				basic_os=udi
-				;;
-			ultra3)
-				basic_machine=a29k-nyu
-				basic_os=sym1
-				;;
-			v810 | necv810)
-				basic_machine=v810-nec
-				basic_os=none
-				;;
-			vaxv)
-				basic_machine=vax-dec
-				basic_os=sysv
-				;;
-			vms)
-				basic_machine=vax-dec
-				basic_os=vms
-				;;
-			vsta)
-				basic_machine=i386-pc
-				basic_os=vsta
-				;;
-			vxworks960)
-				basic_machine=i960-wrs
-				basic_os=vxworks
-				;;
-			vxworks68)
-				basic_machine=m68k-wrs
-				basic_os=vxworks
-				;;
-			vxworks29k)
-				basic_machine=a29k-wrs
-				basic_os=vxworks
-				;;
-			xbox)
-				basic_machine=i686-pc
-				basic_os=mingw32
-				;;
-			ymp)
-				basic_machine=ymp-cray
-				basic_os=unicos
-				;;
-			*)
-				basic_machine=$1
-				basic_os=
-				;;
-		esac
-		;;
-esac
-
-# Decode 1-component or ad-hoc basic machines
-case $basic_machine in
-	# Here we handle the default manufacturer of certain CPU types.  It is in
-	# some cases the only manufacturer, in others, it is the most popular.
-	w89k)
-		cpu=hppa1.1
-		vendor=winbond
-		;;
-	op50n)
-		cpu=hppa1.1
-		vendor=oki
-		;;
-	op60c)
-		cpu=hppa1.1
-		vendor=oki
-		;;
-	ibm*)
-		cpu=i370
-		vendor=ibm
-		;;
-	orion105)
-		cpu=clipper
-		vendor=highlevel
-		;;
-	mac | mpw | mac-mpw)
-		cpu=m68k
-		vendor=apple
-		;;
-	pmac | pmac-mpw)
-		cpu=powerpc
-		vendor=apple
-		;;
-
-	# Recognize the various machine names and aliases which stand
-	# for a CPU type and a company and sometimes even an OS.
-	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
-		cpu=m68000
-		vendor=att
-		;;
-	3b*)
-		cpu=we32k
-		vendor=att
-		;;
-	bluegene*)
-		cpu=powerpc
-		vendor=ibm
-		basic_os=cnk
-		;;
-	decsystem10* | dec10*)
-		cpu=pdp10
-		vendor=dec
-		basic_os=tops10
-		;;
-	decsystem20* | dec20*)
-		cpu=pdp10
-		vendor=dec
-		basic_os=tops20
-		;;
-	delta | 3300 | motorola-3300 | motorola-delta \
-	      | 3300-motorola | delta-motorola)
-		cpu=m68k
-		vendor=motorola
-		;;
-	dpx2*)
-		cpu=m68k
-		vendor=bull
-		basic_os=sysv3
-		;;
-	encore | umax | mmax)
-		cpu=ns32k
-		vendor=encore
-		;;
-	elxsi)
-		cpu=elxsi
-		vendor=elxsi
-		basic_os=${basic_os:-bsd}
-		;;
-	fx2800)
-		cpu=i860
-		vendor=alliant
-		;;
-	genix)
-		cpu=ns32k
-		vendor=ns
-		;;
-	h3050r* | hiux*)
-		cpu=hppa1.1
-		vendor=hitachi
-		basic_os=hiuxwe2
-		;;
-	hp3k9[0-9][0-9] | hp9[0-9][0-9])
-		cpu=hppa1.0
-		vendor=hp
-		;;
-	hp9k2[0-9][0-9] | hp9k31[0-9])
-		cpu=m68000
-		vendor=hp
-		;;
-	hp9k3[2-9][0-9])
-		cpu=m68k
-		vendor=hp
-		;;
-	hp9k6[0-9][0-9] | hp6[0-9][0-9])
-		cpu=hppa1.0
-		vendor=hp
-		;;
-	hp9k7[0-79][0-9] | hp7[0-79][0-9])
-		cpu=hppa1.1
-		vendor=hp
-		;;
-	hp9k78[0-9] | hp78[0-9])
-		# FIXME: really hppa2.0-hp
-		cpu=hppa1.1
-		vendor=hp
-		;;
-	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
-		# FIXME: really hppa2.0-hp
-		cpu=hppa1.1
-		vendor=hp
-		;;
-	hp9k8[0-9][13679] | hp8[0-9][13679])
-		cpu=hppa1.1
-		vendor=hp
-		;;
-	hp9k8[0-9][0-9] | hp8[0-9][0-9])
-		cpu=hppa1.0
-		vendor=hp
-		;;
-	i*86v32)
-		cpu=$(echo "$1" | sed -e 's/86.*/86/')
-		vendor=pc
-		basic_os=sysv32
-		;;
-	i*86v4*)
-		cpu=$(echo "$1" | sed -e 's/86.*/86/')
-		vendor=pc
-		basic_os=sysv4
-		;;
-	i*86v)
-		cpu=$(echo "$1" | sed -e 's/86.*/86/')
-		vendor=pc
-		basic_os=sysv
-		;;
-	i*86sol2)
-		cpu=$(echo "$1" | sed -e 's/86.*/86/')
-		vendor=pc
-		basic_os=solaris2
-		;;
-	j90 | j90-cray)
-		cpu=j90
-		vendor=cray
-		basic_os=${basic_os:-unicos}
-		;;
-	iris | iris4d)
-		cpu=mips
-		vendor=sgi
-		case $basic_os in
-		    irix*)
-			;;
-		    *)
-			basic_os=irix4
-			;;
-		esac
-		;;
-	miniframe)
-		cpu=m68000
-		vendor=convergent
-		;;
-	*mint | mint[0-9]* | *MiNT | *MiNT[0-9]*)
-		cpu=m68k
-		vendor=atari
-		basic_os=mint
-		;;
-	news-3600 | risc-news)
-		cpu=mips
-		vendor=sony
-		basic_os=newsos
-		;;
-	next | m*-next)
-		cpu=m68k
-		vendor=next
-		case $basic_os in
-		    openstep*)
-		        ;;
-		    nextstep*)
-			;;
-		    ns2*)
-		      basic_os=nextstep2
-			;;
-		    *)
-		      basic_os=nextstep3
-			;;
-		esac
-		;;
-	np1)
-		cpu=np1
-		vendor=gould
-		;;
-	op50n-* | op60c-*)
-		cpu=hppa1.1
-		vendor=oki
-		basic_os=proelf
-		;;
-	pa-hitachi)
-		cpu=hppa1.1
-		vendor=hitachi
-		basic_os=hiuxwe2
-		;;
-	pbd)
-		cpu=sparc
-		vendor=tti
-		;;
-	pbb)
-		cpu=m68k
-		vendor=tti
-		;;
-	pc532)
-		cpu=ns32k
-		vendor=pc532
-		;;
-	pn)
-		cpu=pn
-		vendor=gould
-		;;
-	power)
-		cpu=power
-		vendor=ibm
-		;;
-	ps2)
-		cpu=i386
-		vendor=ibm
-		;;
-	rm[46]00)
-		cpu=mips
-		vendor=siemens
-		;;
-	rtpc | rtpc-*)
-		cpu=romp
-		vendor=ibm
-		;;
-	sde)
-		cpu=mipsisa32
-		vendor=sde
-		basic_os=${basic_os:-elf}
-		;;
-	simso-wrs)
-		cpu=sparclite
-		vendor=wrs
-		basic_os=vxworks
-		;;
-	tower | tower-32)
-		cpu=m68k
-		vendor=ncr
-		;;
-	vpp*|vx|vx-*)
-		cpu=f301
-		vendor=fujitsu
-		;;
-	w65)
-		cpu=w65
-		vendor=wdc
-		;;
-	w89k-*)
-		cpu=hppa1.1
-		vendor=winbond
-		basic_os=proelf
-		;;
-	none)
-		cpu=none
-		vendor=none
-		;;
-	leon|leon[3-9])
-		cpu=sparc
-		vendor=$basic_machine
-		;;
-	leon-*|leon[3-9]-*)
-		cpu=sparc
-		vendor=$(echo "$basic_machine" | sed 's/-.*//')
-		;;
-
-	*-*)
-		# shellcheck disable=SC2162
-		IFS="-" read cpu vendor <<EOF
-$basic_machine
-EOF
-		;;
-	# We use `pc' rather than `unknown'
-	# because (1) that's what they normally are, and
-	# (2) the word "unknown" tends to confuse beginning users.
-	i*86 | x86_64)
-		cpu=$basic_machine
-		vendor=pc
-		;;
-	# These rules are duplicated from below for sake of the special case above;
-	# i.e. things that normalized to x86 arches should also default to "pc"
-	pc98)
-		cpu=i386
-		vendor=pc
-		;;
-	x64 | amd64)
-		cpu=x86_64
-		vendor=pc
-		;;
-	# Recognize the basic CPU types without company name.
-	*)
-		cpu=$basic_machine
-		vendor=unknown
-		;;
-esac
-
-unset -v basic_machine
-
-# Decode basic machines in the full and proper CPU-Company form.
-case $cpu-$vendor in
-	# Here we handle the default manufacturer of certain CPU types in canonical form. It is in
-	# some cases the only manufacturer, in others, it is the most popular.
-	craynv-unknown)
-		vendor=cray
-		basic_os=${basic_os:-unicosmp}
-		;;
-	c90-unknown | c90-cray)
-		vendor=cray
-		basic_os=${Basic_os:-unicos}
-		;;
-	fx80-unknown)
-		vendor=alliant
-		;;
-	romp-unknown)
-		vendor=ibm
-		;;
-	mmix-unknown)
-		vendor=knuth
-		;;
-	microblaze-unknown | microblazeel-unknown)
-		vendor=xilinx
-		;;
-	rs6000-unknown)
-		vendor=ibm
-		;;
-	vax-unknown)
-		vendor=dec
-		;;
-	pdp11-unknown)
-		vendor=dec
-		;;
-	we32k-unknown)
-		vendor=att
-		;;
-	cydra-unknown)
-		vendor=cydrome
-		;;
-	i370-ibm*)
-		vendor=ibm
-		;;
-	orion-unknown)
-		vendor=highlevel
-		;;
-	xps-unknown | xps100-unknown)
-		cpu=xps100
-		vendor=honeywell
-		;;
-
-	# Here we normalize CPU types with a missing or matching vendor
-	dpx20-unknown | dpx20-bull)
-		cpu=rs6000
-		vendor=bull
-		basic_os=${basic_os:-bosx}
-		;;
-
-	# Here we normalize CPU types irrespective of the vendor
-	amd64-*)
-		cpu=x86_64
-		;;
-	blackfin-*)
-		cpu=bfin
-		basic_os=linux
-		;;
-	c54x-*)
-		cpu=tic54x
-		;;
-	c55x-*)
-		cpu=tic55x
-		;;
-	c6x-*)
-		cpu=tic6x
-		;;
-	e500v[12]-*)
-		cpu=powerpc
-		basic_os=${basic_os}"spe"
-		;;
-	mips3*-*)
-		cpu=mips64
-		;;
-	ms1-*)
-		cpu=mt
-		;;
-	m68knommu-*)
-		cpu=m68k
-		basic_os=linux
-		;;
-	m9s12z-* | m68hcs12z-* | hcs12z-* | s12z-*)
-		cpu=s12z
-		;;
-	openrisc-*)
-		cpu=or32
-		;;
-	parisc-*)
-		cpu=hppa
-		basic_os=linux
-		;;
-	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
-		cpu=i586
-		;;
-	pentiumpro-* | p6-* | 6x86-* | athlon-* | athalon_*-*)
-		cpu=i686
-		;;
-	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
-		cpu=i686
-		;;
-	pentium4-*)
-		cpu=i786
-		;;
-	pc98-*)
-		cpu=i386
-		;;
-	ppc-* | ppcbe-*)
-		cpu=powerpc
-		;;
-	ppcle-* | powerpclittle-*)
-		cpu=powerpcle
-		;;
-	ppc64-*)
-		cpu=powerpc64
-		;;
-	ppc64le-* | powerpc64little-*)
-		cpu=powerpc64le
-		;;
-	sb1-*)
-		cpu=mipsisa64sb1
-		;;
-	sb1el-*)
-		cpu=mipsisa64sb1el
-		;;
-	sh5e[lb]-*)
-		cpu=$(echo "$cpu" | sed 's/^\(sh.\)e\(.\)$/\1\2e/')
-		;;
-	spur-*)
-		cpu=spur
-		;;
-	strongarm-* | thumb-*)
-		cpu=arm
-		;;
-	tx39-*)
-		cpu=mipstx39
-		;;
-	tx39el-*)
-		cpu=mipstx39el
-		;;
-	x64-*)
-		cpu=x86_64
-		;;
-	xscale-* | xscalee[bl]-*)
-		cpu=$(echo "$cpu" | sed 's/^xscale/arm/')
-		;;
-	arm64-*)
-		cpu=aarch64
-		;;
-
-	# Recognize the canonical CPU Types that limit and/or modify the
-	# company names they are paired with.
-	cr16-*)
-		basic_os=${basic_os:-elf}
-		;;
-	crisv32-* | etraxfs*-*)
-		cpu=crisv32
-		vendor=axis
-		;;
-	cris-* | etrax*-*)
-		cpu=cris
-		vendor=axis
-		;;
-	crx-*)
-		basic_os=${basic_os:-elf}
-		;;
-	neo-tandem)
-		cpu=neo
-		vendor=tandem
-		;;
-	nse-tandem)
-		cpu=nse
-		vendor=tandem
-		;;
-	nsr-tandem)
-		cpu=nsr
-		vendor=tandem
-		;;
-	nsv-tandem)
-		cpu=nsv
-		vendor=tandem
-		;;
-	nsx-tandem)
-		cpu=nsx
-		vendor=tandem
-		;;
-	mipsallegrexel-sony)
-		cpu=mipsallegrexel
-		vendor=sony
-		;;
-	tile*-*)
-		basic_os=${basic_os:-linux-gnu}
-		;;
-
-	*)
-		# Recognize the canonical CPU types that are allowed with any
-		# company name.
-		case $cpu in
-			1750a | 580 \
-			| a29k \
-			| aarch64 | aarch64_be \
-			| abacus \
-			| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] \
-			| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] \
-			| alphapca5[67] | alpha64pca5[67] \
-			| am33_2.0 \
-			| amdgcn \
-			| arc | arceb \
-			| arm | arm[lb]e | arme[lb] | armv* \
-			| avr | avr32 \
-			| asmjs \
-			| ba \
-			| be32 | be64 \
-			| bfin | bpf | bs2000 \
-			| c[123]* | c30 | [cjt]90 | c4x \
-			| c8051 | clipper | craynv | csky | cydra \
-			| d10v | d30v | dlx | dsp16xx \
-			| e2k | elxsi | epiphany \
-			| f30[01] | f700 | fido | fr30 | frv | ft32 | fx80 \
-			| h8300 | h8500 \
-			| hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
-			| hexagon \
-			| i370 | i*86 | i860 | i960 | ia16 | ia64 \
-			| ip2k | iq2000 \
-			| k1om \
-			| le32 | le64 \
-			| lm32 \
-			| loongarch32 | loongarch64 | loongarchx32 \
-			| m32c | m32r | m32rle \
-			| m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k \
-			| m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x \
-			| m88110 | m88k | maxq | mb | mcore | mep | metag \
-			| microblaze | microblazeel \
-			| mips | mipsbe | mipseb | mipsel | mipsle \
-			| mips16 \
-			| mips64 | mips64eb | mips64el \
-			| mips64octeon | mips64octeonel \
-			| mips64orion | mips64orionel \
-			| mips64r5900 | mips64r5900el \
-			| mips64vr | mips64vrel \
-			| mips64vr4100 | mips64vr4100el \
-			| mips64vr4300 | mips64vr4300el \
-			| mips64vr5000 | mips64vr5000el \
-			| mips64vr5900 | mips64vr5900el \
-			| mipsisa32 | mipsisa32el \
-			| mipsisa32r2 | mipsisa32r2el \
-			| mipsisa32r6 | mipsisa32r6el \
-			| mipsisa64 | mipsisa64el \
-			| mipsisa64r2 | mipsisa64r2el \
-			| mipsisa64r6 | mipsisa64r6el \
-			| mipsisa64sb1 | mipsisa64sb1el \
-			| mipsisa64sr71k | mipsisa64sr71kel \
-			| mipsr5900 | mipsr5900el \
-			| mipstx39 | mipstx39el \
-			| mmix \
-			| mn10200 | mn10300 \
-			| moxie \
-			| mt \
-			| msp430 \
-			| nds32 | nds32le | nds32be \
-			| nfp \
-			| nios | nios2 | nios2eb | nios2el \
-			| none | np1 | ns16k | ns32k | nvptx \
-			| open8 \
-			| or1k* \
-			| or32 \
-			| orion \
-			| picochip \
-			| pdp10 | pdp11 | pj | pjl | pn | power \
-			| powerpc | powerpc64 | powerpc64le | powerpcle | powerpcspe \
-			| pru \
-			| pyramid \
-			| riscv | riscv32 | riscv32be | riscv64 | riscv64be \
-			| rl78 | romp | rs6000 | rx \
-			| s390 | s390x \
-			| score \
-			| sh | shl \
-			| sh[1234] | sh[24]a | sh[24]ae[lb] | sh[23]e | she[lb] | sh[lb]e \
-			| sh[1234]e[lb] |  sh[12345][lb]e | sh[23]ele | sh64 | sh64le \
-			| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet \
-			| sparclite \
-			| sparcv8 | sparcv9 | sparcv9b | sparcv9v | sv1 | sx* \
-			| spu \
-			| tahoe \
-			| thumbv7* \
-			| tic30 | tic4x | tic54x | tic55x | tic6x | tic80 \
-			| tron \
-			| ubicom32 \
-			| v70 | v850 | v850e | v850e1 | v850es | v850e2 | v850e2v3 \
-			| vax \
-			| visium \
-			| w65 \
-			| wasm32 | wasm64 \
-			| we32k \
-			| x86 | x86_64 | xc16x | xgate | xps100 \
-			| xstormy16 | xtensa* \
-			| ymp \
-			| z8k | z80)
-				;;
-
-			*)
-				echo Invalid configuration \`"$1"\': machine \`"$cpu-$vendor"\' not recognized 1>&2
-				exit 1
-				;;
-		esac
-		;;
-esac
-
-# Here we canonicalize certain aliases for manufacturers.
-case $vendor in
-	digital*)
-		vendor=dec
-		;;
-	commodore*)
-		vendor=cbm
-		;;
-	*)
-		;;
-esac
-
-# Decode manufacturer-specific aliases for certain operating systems.
-
-if test x$basic_os != x
-then
-
-# First recognize some ad-hoc caes, or perhaps split kernel-os, or else just
-# set os.
-case $basic_os in
-	gnu/linux*)
-		kernel=linux
-		os=$(echo $basic_os | sed -e 's|gnu/linux|gnu|')
-		;;
-	os2-emx)
-		kernel=os2
-		os=$(echo $basic_os | sed -e 's|os2-emx|emx|')
-		;;
-	nto-qnx*)
-		kernel=nto
-		os=$(echo $basic_os | sed -e 's|nto-qnx|qnx|')
-		;;
-	*-*)
-		# shellcheck disable=SC2162
-		IFS="-" read kernel os <<EOF
-$basic_os
-EOF
-		;;
-	# Default OS when just kernel was specified
-	nto*)
-		kernel=nto
-		os=$(echo $basic_os | sed -e 's|nto|qnx|')
-		;;
-	linux*)
-		kernel=linux
-		os=$(echo $basic_os | sed -e 's|linux|gnu|')
-		;;
-	*)
-		kernel=
-		os=$basic_os
-		;;
-esac
-
-# Now, normalize the OS (knowing we just have one component, it's not a kernel,
-# etc.)
-case $os in
-	# First match some system type aliases that might get confused
-	# with valid system types.
-	# solaris* is a basic system type, with this one exception.
-	auroraux)
-		os=auroraux
-		;;
-	bluegene*)
-		os=cnk
-		;;
-	solaris1 | solaris1.*)
-		os=$(echo $os | sed -e 's|solaris1|sunos4|')
-		;;
-	solaris)
-		os=solaris2
-		;;
-	unixware*)
-		os=sysv4.2uw
-		;;
-	# es1800 is here to avoid being matched by es* (a different OS)
-	es1800*)
-		os=ose
-		;;
-	# Some version numbers need modification
-	chorusos*)
-		os=chorusos
-		;;
-	isc)
-		os=isc2.2
-		;;
-	sco6)
-		os=sco5v6
-		;;
-	sco5)
-		os=sco3.2v5
-		;;
-	sco4)
-		os=sco3.2v4
-		;;
-	sco3.2.[4-9]*)
-		os=$(echo $os | sed -e 's/sco3.2./sco3.2v/')
-		;;
-	sco*v* | scout)
-		# Don't match below
-		;;
-	sco*)
-		os=sco3.2v2
-		;;
-	psos*)
-		os=psos
-		;;
-	qnx*)
-		os=qnx
-		;;
-	hiux*)
-		os=hiuxwe2
-		;;
-	lynx*178)
-		os=lynxos178
-		;;
-	lynx*5)
-		os=lynxos5
-		;;
-	lynxos*)
-		# don't get caught up in next wildcard
-		;;
-	lynx*)
-		os=lynxos
-		;;
-	mac[0-9]*)
-		os=$(echo "$os" | sed -e 's|mac|macos|')
-		;;
-	opened*)
-		os=openedition
-		;;
-	os400*)
-		os=os400
-		;;
-	sunos5*)
-		os=$(echo "$os" | sed -e 's|sunos5|solaris2|')
-		;;
-	sunos6*)
-		os=$(echo "$os" | sed -e 's|sunos6|solaris3|')
-		;;
-	wince*)
-		os=wince
-		;;
-	utek*)
-		os=bsd
-		;;
-	dynix*)
-		os=bsd
-		;;
-	acis*)
-		os=aos
-		;;
-	atheos*)
-		os=atheos
-		;;
-	syllable*)
-		os=syllable
-		;;
-	386bsd)
-		os=bsd
-		;;
-	ctix* | uts*)
-		os=sysv
-		;;
-	nova*)
-		os=rtmk-nova
-		;;
-	ns2)
-		os=nextstep2
-		;;
-	# Preserve the version number of sinix5.
-	sinix5.*)
-		os=$(echo $os | sed -e 's|sinix|sysv|')
-		;;
-	sinix*)
-		os=sysv4
-		;;
-	tpf*)
-		os=tpf
-		;;
-	triton*)
-		os=sysv3
-		;;
-	oss*)
-		os=sysv3
-		;;
-	svr4*)
-		os=sysv4
-		;;
-	svr3)
-		os=sysv3
-		;;
-	sysvr4)
-		os=sysv4
-		;;
-	ose*)
-		os=ose
-		;;
-	*mint | mint[0-9]* | *MiNT | MiNT[0-9]*)
-		os=mint
-		;;
-	dicos*)
-		os=dicos
-		;;
-	pikeos*)
-		# Until real need of OS specific support for
-		# particular features comes up, bare metal
-		# configurations are quite functional.
-		case $cpu in
-		    arm*)
-			os=eabi
-			;;
-		    *)
-			os=elf
-			;;
-		esac
-		;;
-	*)
-		# No normalization, but not necessarily accepted, that comes below.
-		;;
-esac
-
-else
-
-# Here we handle the default operating systems that come with various machines.
-# The value should be what the vendor currently ships out the door with their
-# machine or put another way, the most popular os provided with the machine.
-
-# Note that if you're going to try to match "-MANUFACTURER" here (say,
-# "-sun"), then you have to tell the case statement up towards the top
-# that MANUFACTURER isn't an operating system.  Otherwise, code above
-# will signal an error saying that MANUFACTURER isn't an operating
-# system, and we'll never get to this point.
-
-kernel=
-case $cpu-$vendor in
-	score-*)
-		os=elf
-		;;
-	spu-*)
-		os=elf
-		;;
-	*-acorn)
-		os=riscix1.2
-		;;
-	arm*-rebel)
-		kernel=linux
-		os=gnu
-		;;
-	arm*-semi)
-		os=aout
-		;;
-	c4x-* | tic4x-*)
-		os=coff
-		;;
-	c8051-*)
-		os=elf
-		;;
-	clipper-intergraph)
-		os=clix
-		;;
-	hexagon-*)
-		os=elf
-		;;
-	tic54x-*)
-		os=coff
-		;;
-	tic55x-*)
-		os=coff
-		;;
-	tic6x-*)
-		os=coff
-		;;
-	# This must come before the *-dec entry.
-	pdp10-*)
-		os=tops20
-		;;
-	pdp11-*)
-		os=none
-		;;
-	*-dec | vax-*)
-		os=ultrix4.2
-		;;
-	m68*-apollo)
-		os=domain
-		;;
-	i386-sun)
-		os=sunos4.0.2
-		;;
-	m68000-sun)
-		os=sunos3
-		;;
-	m68*-cisco)
-		os=aout
-		;;
-	mep-*)
-		os=elf
-		;;
-	mips*-cisco)
-		os=elf
-		;;
-	mips*-*)
-		os=elf
-		;;
-	or32-*)
-		os=coff
-		;;
-	*-tti)	# must be before sparc entry or we get the wrong os.
-		os=sysv3
-		;;
-	sparc-* | *-sun)
-		os=sunos4.1.1
-		;;
-	pru-*)
-		os=elf
-		;;
-	*-be)
-		os=beos
-		;;
-	*-ibm)
-		os=aix
-		;;
-	*-knuth)
-		os=mmixware
-		;;
-	*-wec)
-		os=proelf
-		;;
-	*-winbond)
-		os=proelf
-		;;
-	*-oki)
-		os=proelf
-		;;
-	*-hp)
-		os=hpux
-		;;
-	*-hitachi)
-		os=hiux
-		;;
-	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
-		os=sysv
-		;;
-	*-cbm)
-		os=amigaos
-		;;
-	*-dg)
-		os=dgux
-		;;
-	*-dolphin)
-		os=sysv3
-		;;
-	m68k-ccur)
-		os=rtu
-		;;
-	m88k-omron*)
-		os=luna
-		;;
-	*-next)
-		os=nextstep
-		;;
-	*-sequent)
-		os=ptx
-		;;
-	*-crds)
-		os=unos
-		;;
-	*-ns)
-		os=genix
-		;;
-	i370-*)
-		os=mvs
-		;;
-	*-gould)
-		os=sysv
-		;;
-	*-highlevel)
-		os=bsd
-		;;
-	*-encore)
-		os=bsd
-		;;
-	*-sgi)
-		os=irix
-		;;
-	*-siemens)
-		os=sysv4
-		;;
-	*-masscomp)
-		os=rtu
-		;;
-	f30[01]-fujitsu | f700-fujitsu)
-		os=uxpv
-		;;
-	*-rom68k)
-		os=coff
-		;;
-	*-*bug)
-		os=coff
-		;;
-	*-apple)
-		os=macos
-		;;
-	*-atari*)
-		os=mint
-		;;
-	*-wrs)
-		os=vxworks
-		;;
-	*)
-		os=none
-		;;
-esac
-
-fi
-
-# Now, validate our (potentially fixed-up) OS.
-case $os in
-	# Sometimes we do "kernel-libc", so those need to count as OSes.
-	musl* | newlib* | uclibc*)
-		;;
-	# Likewise for "kernel-abi"
-	eabi* | gnueabi*)
-		;;
-	# VxWorks passes extra cpu info in the 4th filed.
-	simlinux | simwindows | spe)
-		;;
-	# Now accept the basic system types.
-	# The portable systems comes first.
-	# Each alternative MUST end in a * to match a version number.
-	gnu* | android* | bsd* | mach* | minix* | genix* | ultrix* | irix* \
-	     | *vms* | esix* | aix* | cnk* | sunos | sunos[34]* \
-	     | hpux* | unos* | osf* | luna* | dgux* | auroraux* | solaris* \
-	     | sym* |  plan9* | psp* | sim* | xray* | os68k* | v88r* \
-	     | hiux* | abug | nacl* | netware* | windows* \
-	     | os9* | macos* | osx* | ios* \
-	     | mpw* | magic* | mmixware* | mon960* | lnews* \
-	     | amigaos* | amigados* | msdos* | newsos* | unicos* | aof* \
-	     | aos* | aros* | cloudabi* | sortix* | twizzler* \
-	     | nindy* | vxsim* | vxworks* | ebmon* | hms* | mvs* \
-	     | clix* | riscos* | uniplus* | iris* | isc* | rtu* | xenix* \
-	     | mirbsd* | netbsd* | dicos* | openedition* | ose* \
-	     | bitrig* | openbsd* | solidbsd* | libertybsd* | os108* \
-	     | ekkobsd* | freebsd* | riscix* | lynxos* | os400* \
-	     | bosx* | nextstep* | cxux* | aout* | elf* | oabi* \
-	     | ptx* | coff* | ecoff* | winnt* | domain* | vsta* \
-	     | udi* | lites* | ieee* | go32* | aux* | hcos* \
-	     | chorusrdb* | cegcc* | glidix* \
-	     | cygwin* | msys* | pe* | moss* | proelf* | rtems* \
-	     | midipix* | mingw32* | mingw64* | mint* \
-	     | uxpv* | beos* | mpeix* | udk* | moxiebox* \
-	     | interix* | uwin* | mks* | rhapsody* | darwin* \
-	     | openstep* | oskit* | conix* | pw32* | nonstopux* \
-	     | storm-chaos* | tops10* | tenex* | tops20* | its* \
-	     | os2* | vos* | palmos* | uclinux* | nucleus* | morphos* \
-	     | scout* | superux* | sysv* | rtmk* | tpf* | windiss* \
-	     | powermax* | dnix* | nx6 | nx7 | sei* | dragonfly* \
-	     | skyos* | haiku* | rdos* | toppers* | drops* | es* \
-	     | onefs* | tirtos* | phoenix* | fuchsia* | redox* | bme* \
-	     | midnightbsd* | amdhsa* | unleashed* | emscripten* | wasi* \
-	     | nsk* | powerunix* | genode* | zvmoe* | qnx* | emx*)
-		;;
-	# This one is extra strict with allowed versions
-	sco3.2v2 | sco3.2v[4-9]* | sco5v6*)
-		# Don't forget version if it is 3.2v4 or newer.
-		;;
-	none)
-		;;
-	*)
-		echo Invalid configuration \`"$1"\': OS \`"$os"\' not recognized 1>&2
-		exit 1
-		;;
-esac
-
-# As a final step for OS-related things, validate the OS-kernel combination
-# (given a valid OS), if there is a kernel.
-case $kernel-$os in
-	linux-gnu* | linux-dietlibc* | linux-android* | linux-newlib* | linux-musl* | linux-uclibc* )
-		;;
-	uclinux-uclibc* )
-		;;
-	-dietlibc* | -newlib* | -musl* | -uclibc* )
-		# These are just libc implementations, not actual OSes, and thus
-		# require a kernel.
-		echo "Invalid configuration \`$1': libc \`$os' needs explicit kernel." 1>&2
-		exit 1
-		;;
-	kfreebsd*-gnu* | kopensolaris*-gnu*)
-		;;
-	vxworks-simlinux | vxworks-simwindows | vxworks-spe)
-		;;
-	nto-qnx*)
-		;;
-	os2-emx)
-		;;
-	*-eabi* | *-gnueabi*)
-		;;
-	-*)
-		# Blank kernel with real OS is always fine.
-		;;
-	*-*)
-		echo "Invalid configuration \`$1': Kernel \`$kernel' not known to work with OS \`$os'." 1>&2
-		exit 1
-		;;
-esac
-
-# Here we handle the case where we know the os, and the CPU type, but not the
-# manufacturer.  We pick the logical manufacturer.
-case $vendor in
-	unknown)
-		case $cpu-$os in
-			*-riscix*)
-				vendor=acorn
-				;;
-			*-sunos*)
-				vendor=sun
-				;;
-			*-cnk* | *-aix*)
-				vendor=ibm
-				;;
-			*-beos*)
-				vendor=be
-				;;
-			*-hpux*)
-				vendor=hp
-				;;
-			*-mpeix*)
-				vendor=hp
-				;;
-			*-hiux*)
-				vendor=hitachi
-				;;
-			*-unos*)
-				vendor=crds
-				;;
-			*-dgux*)
-				vendor=dg
-				;;
-			*-luna*)
-				vendor=omron
-				;;
-			*-genix*)
-				vendor=ns
-				;;
-			*-clix*)
-				vendor=intergraph
-				;;
-			*-mvs* | *-opened*)
-				vendor=ibm
-				;;
-			*-os400*)
-				vendor=ibm
-				;;
-			s390-* | s390x-*)
-				vendor=ibm
-				;;
-			*-ptx*)
-				vendor=sequent
-				;;
-			*-tpf*)
-				vendor=ibm
-				;;
-			*-vxsim* | *-vxworks* | *-windiss*)
-				vendor=wrs
-				;;
-			*-aux*)
-				vendor=apple
-				;;
-			*-hms*)
-				vendor=hitachi
-				;;
-			*-mpw* | *-macos*)
-				vendor=apple
-				;;
-			*-*mint | *-mint[0-9]* | *-*MiNT | *-MiNT[0-9]*)
-				vendor=atari
-				;;
-			*-vos*)
-				vendor=stratus
-				;;
-		esac
-		;;
-esac
-
-echo "$cpu-$vendor-${kernel:+$kernel-}$os"
-exit
-
-# Local variables:
-# eval: (add-hook 'before-save-hook 'time-stamp)
+#   Copyright 1992-2017 Free Software Foundation, Inc.
+
+timestamp='2017-04-02'
+
+# This file is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that
+# program.  This Exception is an additional permission under section 7
+# of the GNU General Public License, version 3 ("GPLv3").
+
+
+# Please send patches to <config-patches@gnu.org>.
+#
+# Configuration subroutine to validate and canonicalize a configuration type.
+# Supply the specified configuration type as an argument.
+# If it is invalid, we print an error message on stderr and exit with code 1.
+# Otherwise, we print the canonical config type on stdout and succeed.
+
+# You can get the latest version of this script from:
+# http://git.savannah.gnu.org/gitweb/?p=config.git;a=blob_plain;f=config.sub
+
+# This file is supposed to be the same for all GNU packages
+# and recognize all the CPU types, system types and aliases
+# that are meaningful with *any* GNU software.
+# Each package is responsible for reporting which valid configurations
+# it does not support.  The user should be able to distinguish
+# a failure to support a valid configuration from a meaningless
+# configuration.
+
+# The goal of this file is to map all the various variations of a given
+# machine specification into a single specification in the form:
+#	CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM
+# or in some cases, the newer four-part form:
+#	CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM
+# It is wrong to echo any other type of specification.
+
+me=`echo "$0" | sed -e 's,.*/,,'`
+
+usage="\
+Usage: $0 [OPTION] CPU-MFR-OPSYS or ALIAS
+
+Canonicalize a configuration name.
+
+Operation modes:
+  -h, --help         print this help, then exit
+  -t, --time-stamp   print date of last modification, then exit
+  -v, --version      print version number, then exit
+
+Report bugs and patches to <config-patches@gnu.org>."
+
+version="\
+GNU config.sub ($timestamp)
+
+Copyright 1992-2017 Free Software Foundation, Inc.
+
+This is free software; see the source for copying conditions.  There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE."
+
+help="
+Try \`$me --help' for more information."
+
+# Parse command line
+while test $# -gt 0 ; do
+  case $1 in
+    --time-stamp | --time* | -t )
+       echo "$timestamp" ; exit ;;
+    --version | -v )
+       echo "$version" ; exit ;;
+    --help | --h* | -h )
+       echo "$usage"; exit ;;
+    -- )     # Stop option processing
+       shift; break ;;
+    - )	# Use stdin as input.
+       break ;;
+    -* )
+       echo "$me: invalid option $1$help"
+       exit 1 ;;
+
+    *local*)
+       # First pass through any local machine types.
+       echo $1
+       exit ;;
+
+    * )
+       break ;;
+  esac
+done
+
+case $# in
+ 0) echo "$me: missing argument$help" >&2
+    exit 1;;
+ 1) ;;
+ *) echo "$me: too many arguments$help" >&2
+    exit 1;;
+esac
+
+# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any).
+# Here we must recognize all the valid KERNEL-OS combinations.
+maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
+case $maybe_os in
+  nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+  linux-musl* | linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+  knetbsd*-gnu* | netbsd*-gnu* | netbsd*-eabi* | \
+  kopensolaris*-gnu* | cloudabi*-eabi* | \
+  storm-chaos* | os2-emx* | rtmk-nova*)
+    os=-$maybe_os
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
+    ;;
+  android-linux)
+    os=-linux-android
+    basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`-unknown
+    ;;
+  *)
+    basic_machine=`echo $1 | sed 's/-[^-]*$//'`
+    if [ $basic_machine != $1 ]
+    then os=`echo $1 | sed 's/.*-/-/'`
+    else os=; fi
+    ;;
+esac
+
+### Let's recognize common machines as not being operating systems so
+### that things like config.sub decstation-3100 work.  We also
+### recognize some manufacturers as not being operating systems, so we
+### can provide default operating systems below.
+case $os in
+	-sun*os*)
+		# Prevent following clause from handling this invalid input.
+		;;
+	-dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \
+	-att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \
+	-unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \
+	-convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\
+	-c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \
+	-harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \
+	-apple | -axis | -knuth | -cray | -microblaze*)
+		os=
+		basic_machine=$1
+		;;
+	-bluegene*)
+		os=-cnk
+		;;
+	-sim | -cisco | -oki | -wec | -winbond)
+		os=
+		basic_machine=$1
+		;;
+	-scout)
+		;;
+	-wrs)
+		os=-vxworks
+		basic_machine=$1
+		;;
+	-chorusos*)
+		os=-chorusos
+		basic_machine=$1
+		;;
+	-chorusrdb)
+		os=-chorusrdb
+		basic_machine=$1
+		;;
+	-hiux*)
+		os=-hiuxwe2
+		;;
+	-sco6)
+		os=-sco5v6
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5)
+		os=-sco3.2v5
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco4)
+		os=-sco3.2v4
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2.[4-9]*)
+		os=`echo $os | sed -e 's/sco3.2./sco3.2v/'`
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco3.2v[4-9]*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco5v6*)
+		# Don't forget version if it is 3.2v4 or newer.
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-sco*)
+		os=-sco3.2v2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-udk*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-isc)
+		os=-isc2.2
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-clix*)
+		basic_machine=clipper-intergraph
+		;;
+	-isc*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'`
+		;;
+	-lynx*178)
+		os=-lynxos178
+		;;
+	-lynx*5)
+		os=-lynxos5
+		;;
+	-lynx*)
+		os=-lynxos
+		;;
+	-ptx*)
+		basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'`
+		;;
+	-windowsnt*)
+		os=`echo $os | sed -e 's/windowsnt/winnt/'`
+		;;
+	-psos*)
+		os=-psos
+		;;
+	-mint | -mint[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+esac
+
+# Decode aliases for certain CPU-COMPANY combinations.
+case $basic_machine in
+	# Recognize the basic CPU types without company name.
+	# Some are omitted here because they have special meanings below.
+	1750a | 580 \
+	| a29k \
+	| aarch64 | aarch64_be \
+	| alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \
+	| alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \
+	| am33_2.0 \
+	| arc | arceb \
+	| arm | arm[bl]e | arme[lb] | armv[2-8] | armv[3-8][lb] | armv7[arm] \
+	| avr | avr32 \
+	| ba \
+	| be32 | be64 \
+	| bfin \
+	| c4x | c8051 | clipper \
+	| d10v | d30v | dlx | dsp16xx \
+	| e2k | epiphany \
+	| fido | fr30 | frv | ft32 \
+	| h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \
+	| hexagon \
+	| i370 | i860 | i960 | ia16 | ia64 \
+	| ip2k | iq2000 \
+	| k1om \
+	| le32 | le64 \
+	| lm32 \
+	| m32c | m32r | m32rle | m68000 | m68k | m88k \
+	| maxq | mb | microblaze | microblazeel | mcore | mep | metag \
+	| mips | mipsbe | mipseb | mipsel | mipsle \
+	| mips16 \
+	| mips64 | mips64el \
+	| mips64octeon | mips64octeonel \
+	| mips64orion | mips64orionel \
+	| mips64r5900 | mips64r5900el \
+	| mips64vr | mips64vrel \
+	| mips64vr4100 | mips64vr4100el \
+	| mips64vr4300 | mips64vr4300el \
+	| mips64vr5000 | mips64vr5000el \
+	| mips64vr5900 | mips64vr5900el \
+	| mipsisa32 | mipsisa32el \
+	| mipsisa32r2 | mipsisa32r2el \
+	| mipsisa32r6 | mipsisa32r6el \
+	| mipsisa64 | mipsisa64el \
+	| mipsisa64r2 | mipsisa64r2el \
+	| mipsisa64r6 | mipsisa64r6el \
+	| mipsisa64sb1 | mipsisa64sb1el \
+	| mipsisa64sr71k | mipsisa64sr71kel \
+	| mipsr5900 | mipsr5900el \
+	| mipstx39 | mipstx39el \
+	| mn10200 | mn10300 \
+	| moxie \
+	| mt \
+	| msp430 \
+	| nds32 | nds32le | nds32be \
+	| nios | nios2 | nios2eb | nios2el \
+	| ns16k | ns32k \
+	| open8 | or1k | or1knd | or32 \
+	| pdp10 | pdp11 | pj | pjl \
+	| powerpc | powerpc64 | powerpc64le | powerpcle \
+	| pru \
+	| pyramid \
+	| riscv32 | riscv64 \
+	| rl78 | rx \
+	| score \
+	| sh | sh[1234] | sh[24]a | sh[24]aeb | sh[23]e | sh[234]eb | sheb | shbe | shle | sh[1234]le | sh3ele \
+	| sh64 | sh64le \
+	| sparc | sparc64 | sparc64b | sparc64v | sparc86x | sparclet | sparclite \
+	| sparcv8 | sparcv9 | sparcv9b | sparcv9v \
+	| spu \
+	| tahoe | tic4x | tic54x | tic55x | tic6x | tic80 | tron \
+	| ubicom32 \
+	| v850 | v850e | v850e1 | v850e2 | v850es | v850e2v3 \
+	| visium \
+	| wasm32 \
+	| we32k \
+	| x86 | xc16x | xstormy16 | xtensa \
+	| z8k | z80)
+		basic_machine=$basic_machine-unknown
+		;;
+	c54x)
+		basic_machine=tic54x-unknown
+		;;
+	c55x)
+		basic_machine=tic55x-unknown
+		;;
+	c6x)
+		basic_machine=tic6x-unknown
+		;;
+	leon|leon[3-9])
+		basic_machine=sparc-$basic_machine
+		;;
+	m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
+		;;
+	ms1)
+		basic_machine=mt-unknown
+		;;
+
+	strongarm | thumb | xscale)
+		basic_machine=arm-unknown
+		;;
+	xgate)
+		basic_machine=$basic_machine-unknown
+		os=-none
+		;;
+	xscaleeb)
+		basic_machine=armeb-unknown
+		;;
+
+	xscaleel)
+		basic_machine=armel-unknown
+		;;
+
+	# We use `pc' rather than `unknown'
+	# because (1) that's what they normally are, and
+	# (2) the word "unknown" tends to confuse beginning users.
+	i*86 | x86_64)
+	  basic_machine=$basic_machine-pc
+	  ;;
+	# Object if more than one company name word.
+	*-*-*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+	# Recognize the basic CPU types with company name.
+	580-* \
+	| a29k-* \
+	| aarch64-* | aarch64_be-* \
+	| alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \
+	| alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \
+	| alphapca5[67]-* | alpha64pca5[67]-* | arc-* | arceb-* \
+	| arm-*  | armbe-* | armle-* | armeb-* | armv*-* \
+	| avr-* | avr32-* \
+	| ba-* \
+	| be32-* | be64-* \
+	| bfin-* | bs2000-* \
+	| c[123]* | c30-* | [cjt]90-* | c4x-* \
+	| c8051-* | clipper-* | craynv-* | cydra-* \
+	| d10v-* | d30v-* | dlx-* \
+	| e2k-* | elxsi-* \
+	| f30[01]-* | f700-* | fido-* | fr30-* | frv-* | fx80-* \
+	| h8300-* | h8500-* \
+	| hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \
+	| hexagon-* \
+	| i*86-* | i860-* | i960-* | ia16-* | ia64-* \
+	| ip2k-* | iq2000-* \
+	| k1om-* \
+	| le32-* | le64-* \
+	| lm32-* \
+	| m32c-* | m32r-* | m32rle-* \
+	| m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \
+	| m88110-* | m88k-* | maxq-* | mcore-* | metag-* \
+	| microblaze-* | microblazeel-* \
+	| mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \
+	| mips16-* \
+	| mips64-* | mips64el-* \
+	| mips64octeon-* | mips64octeonel-* \
+	| mips64orion-* | mips64orionel-* \
+	| mips64r5900-* | mips64r5900el-* \
+	| mips64vr-* | mips64vrel-* \
+	| mips64vr4100-* | mips64vr4100el-* \
+	| mips64vr4300-* | mips64vr4300el-* \
+	| mips64vr5000-* | mips64vr5000el-* \
+	| mips64vr5900-* | mips64vr5900el-* \
+	| mipsisa32-* | mipsisa32el-* \
+	| mipsisa32r2-* | mipsisa32r2el-* \
+	| mipsisa32r6-* | mipsisa32r6el-* \
+	| mipsisa64-* | mipsisa64el-* \
+	| mipsisa64r2-* | mipsisa64r2el-* \
+	| mipsisa64r6-* | mipsisa64r6el-* \
+	| mipsisa64sb1-* | mipsisa64sb1el-* \
+	| mipsisa64sr71k-* | mipsisa64sr71kel-* \
+	| mipsr5900-* | mipsr5900el-* \
+	| mipstx39-* | mipstx39el-* \
+	| mmix-* \
+	| mt-* \
+	| msp430-* \
+	| nds32-* | nds32le-* | nds32be-* \
+	| nios-* | nios2-* | nios2eb-* | nios2el-* \
+	| none-* | np1-* | ns16k-* | ns32k-* \
+	| open8-* \
+	| or1k*-* \
+	| orion-* \
+	| pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \
+	| powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* \
+	| pru-* \
+	| pyramid-* \
+	| riscv32-* | riscv64-* \
+	| rl78-* | romp-* | rs6000-* | rx-* \
+	| sh-* | sh[1234]-* | sh[24]a-* | sh[24]aeb-* | sh[23]e-* | sh[34]eb-* | sheb-* | shbe-* \
+	| shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \
+	| sparc-* | sparc64-* | sparc64b-* | sparc64v-* | sparc86x-* | sparclet-* \
+	| sparclite-* \
+	| sparcv8-* | sparcv9-* | sparcv9b-* | sparcv9v-* | sv1-* | sx*-* \
+	| tahoe-* \
+	| tic30-* | tic4x-* | tic54x-* | tic55x-* | tic6x-* | tic80-* \
+	| tile*-* \
+	| tron-* \
+	| ubicom32-* \
+	| v850-* | v850e-* | v850e1-* | v850es-* | v850e2-* | v850e2v3-* \
+	| vax-* \
+	| visium-* \
+	| wasm32-* \
+	| we32k-* \
+	| x86-* | x86_64-* | xc16x-* | xps100-* \
+	| xstormy16-* | xtensa*-* \
+	| ymp-* \
+	| z8k-* | z80-*)
+		;;
+	# Recognize the basic CPU types without company name, with glob match.
+	xtensa*)
+		basic_machine=$basic_machine-unknown
+		;;
+	# Recognize the various machine names and aliases which stand
+	# for a CPU type and a company and sometimes even an OS.
+	386bsd)
+		basic_machine=i386-unknown
+		os=-bsd
+		;;
+	3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc)
+		basic_machine=m68000-att
+		;;
+	3b*)
+		basic_machine=we32k-att
+		;;
+	a29khif)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	abacus)
+		basic_machine=abacus-unknown
+		;;
+	adobe68k)
+		basic_machine=m68010-adobe
+		os=-scout
+		;;
+	alliant | fx80)
+		basic_machine=fx80-alliant
+		;;
+	altos | altos3068)
+		basic_machine=m68k-altos
+		;;
+	am29k)
+		basic_machine=a29k-none
+		os=-bsd
+		;;
+	amd64)
+		basic_machine=x86_64-pc
+		;;
+	amd64-*)
+		basic_machine=x86_64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	amdahl)
+		basic_machine=580-amdahl
+		os=-sysv
+		;;
+	amiga | amiga-*)
+		basic_machine=m68k-unknown
+		;;
+	amigaos | amigados)
+		basic_machine=m68k-unknown
+		os=-amigaos
+		;;
+	amigaunix | amix)
+		basic_machine=m68k-unknown
+		os=-sysv4
+		;;
+	apollo68)
+		basic_machine=m68k-apollo
+		os=-sysv
+		;;
+	apollo68bsd)
+		basic_machine=m68k-apollo
+		os=-bsd
+		;;
+	aros)
+		basic_machine=i386-pc
+		os=-aros
+		;;
+	asmjs)
+		basic_machine=asmjs-unknown
+		;;
+	aux)
+		basic_machine=m68k-apple
+		os=-aux
+		;;
+	balance)
+		basic_machine=ns32k-sequent
+		os=-dynix
+		;;
+	blackfin)
+		basic_machine=bfin-unknown
+		os=-linux
+		;;
+	blackfin-*)
+		basic_machine=bfin-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	bluegene*)
+		basic_machine=powerpc-ibm
+		os=-cnk
+		;;
+	c54x-*)
+		basic_machine=tic54x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c55x-*)
+		basic_machine=tic55x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c6x-*)
+		basic_machine=tic6x-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	c90)
+		basic_machine=c90-cray
+		os=-unicos
+		;;
+	cegcc)
+		basic_machine=arm-unknown
+		os=-cegcc
+		;;
+	convex-c1)
+		basic_machine=c1-convex
+		os=-bsd
+		;;
+	convex-c2)
+		basic_machine=c2-convex
+		os=-bsd
+		;;
+	convex-c32)
+		basic_machine=c32-convex
+		os=-bsd
+		;;
+	convex-c34)
+		basic_machine=c34-convex
+		os=-bsd
+		;;
+	convex-c38)
+		basic_machine=c38-convex
+		os=-bsd
+		;;
+	cray | j90)
+		basic_machine=j90-cray
+		os=-unicos
+		;;
+	craynv)
+		basic_machine=craynv-cray
+		os=-unicosmp
+		;;
+	cr16 | cr16-*)
+		basic_machine=cr16-unknown
+		os=-elf
+		;;
+	crds | unos)
+		basic_machine=m68k-crds
+		;;
+	crisv32 | crisv32-* | etraxfs*)
+		basic_machine=crisv32-axis
+		;;
+	cris | cris-* | etrax*)
+		basic_machine=cris-axis
+		;;
+	crx)
+		basic_machine=crx-unknown
+		os=-elf
+		;;
+	da30 | da30-*)
+		basic_machine=m68k-da30
+		;;
+	decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn)
+		basic_machine=mips-dec
+		;;
+	decsystem10* | dec10*)
+		basic_machine=pdp10-dec
+		os=-tops10
+		;;
+	decsystem20* | dec20*)
+		basic_machine=pdp10-dec
+		os=-tops20
+		;;
+	delta | 3300 | motorola-3300 | motorola-delta \
+	      | 3300-motorola | delta-motorola)
+		basic_machine=m68k-motorola
+		;;
+	delta88)
+		basic_machine=m88k-motorola
+		os=-sysv3
+		;;
+	dicos)
+		basic_machine=i686-pc
+		os=-dicos
+		;;
+	djgpp)
+		basic_machine=i586-pc
+		os=-msdosdjgpp
+		;;
+	dpx20 | dpx20-*)
+		basic_machine=rs6000-bull
+		os=-bosx
+		;;
+	dpx2* | dpx2*-bull)
+		basic_machine=m68k-bull
+		os=-sysv3
+		;;
+	e500v[12])
+		basic_machine=powerpc-unknown
+		os=$os"spe"
+		;;
+	e500v[12]-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=$os"spe"
+		;;
+	ebmon29k)
+		basic_machine=a29k-amd
+		os=-ebmon
+		;;
+	elxsi)
+		basic_machine=elxsi-elxsi
+		os=-bsd
+		;;
+	encore | umax | mmax)
+		basic_machine=ns32k-encore
+		;;
+	es1800 | OSE68k | ose68k | ose | OSE)
+		basic_machine=m68k-ericsson
+		os=-ose
+		;;
+	fx2800)
+		basic_machine=i860-alliant
+		;;
+	genix)
+		basic_machine=ns32k-ns
+		;;
+	gmicro)
+		basic_machine=tron-gmicro
+		os=-sysv
+		;;
+	go32)
+		basic_machine=i386-pc
+		os=-go32
+		;;
+	h3050r* | hiux*)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	h8300hms)
+		basic_machine=h8300-hitachi
+		os=-hms
+		;;
+	h8300xray)
+		basic_machine=h8300-hitachi
+		os=-xray
+		;;
+	h8500hms)
+		basic_machine=h8500-hitachi
+		os=-hms
+		;;
+	harris)
+		basic_machine=m88k-harris
+		os=-sysv3
+		;;
+	hp300-*)
+		basic_machine=m68k-hp
+		;;
+	hp300bsd)
+		basic_machine=m68k-hp
+		os=-bsd
+		;;
+	hp300hpux)
+		basic_machine=m68k-hp
+		os=-hpux
+		;;
+	hp3k9[0-9][0-9] | hp9[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k2[0-9][0-9] | hp9k31[0-9])
+		basic_machine=m68000-hp
+		;;
+	hp9k3[2-9][0-9])
+		basic_machine=m68k-hp
+		;;
+	hp9k6[0-9][0-9] | hp6[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hp9k7[0-79][0-9] | hp7[0-79][0-9])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k78[0-9] | hp78[0-9])
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893)
+		# FIXME: really hppa2.0-hp
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][13679] | hp8[0-9][13679])
+		basic_machine=hppa1.1-hp
+		;;
+	hp9k8[0-9][0-9] | hp8[0-9][0-9])
+		basic_machine=hppa1.0-hp
+		;;
+	hppa-next)
+		os=-nextstep3
+		;;
+	hppaosf)
+		basic_machine=hppa1.1-hp
+		os=-osf
+		;;
+	hppro)
+		basic_machine=hppa1.1-hp
+		os=-proelf
+		;;
+	i370-ibm* | ibm*)
+		basic_machine=i370-ibm
+		;;
+	i*86v32)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv32
+		;;
+	i*86v4*)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv4
+		;;
+	i*86v)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-sysv
+		;;
+	i*86sol2)
+		basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'`
+		os=-solaris2
+		;;
+	i386mach)
+		basic_machine=i386-mach
+		os=-mach
+		;;
+	i386-vsta | vsta)
+		basic_machine=i386-unknown
+		os=-vsta
+		;;
+	iris | iris4d)
+		basic_machine=mips-sgi
+		case $os in
+		    -irix*)
+			;;
+		    *)
+			os=-irix4
+			;;
+		esac
+		;;
+	isi68 | isi)
+		basic_machine=m68k-isi
+		os=-sysv
+		;;
+	leon-*|leon[3-9]-*)
+		basic_machine=sparc-`echo $basic_machine | sed 's/-.*//'`
+		;;
+	m68knommu)
+		basic_machine=m68k-unknown
+		os=-linux
+		;;
+	m68knommu-*)
+		basic_machine=m68k-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	m88k-omron*)
+		basic_machine=m88k-omron
+		;;
+	magnum | m3230)
+		basic_machine=mips-mips
+		os=-sysv
+		;;
+	merlin)
+		basic_machine=ns32k-utek
+		os=-sysv
+		;;
+	microblaze*)
+		basic_machine=microblaze-xilinx
+		;;
+	mingw64)
+		basic_machine=x86_64-pc
+		os=-mingw64
+		;;
+	mingw32)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	mingw32ce)
+		basic_machine=arm-unknown
+		os=-mingw32ce
+		;;
+	miniframe)
+		basic_machine=m68000-convergent
+		;;
+	*mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*)
+		basic_machine=m68k-atari
+		os=-mint
+		;;
+	mips3*-*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`
+		;;
+	mips3*)
+		basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown
+		;;
+	monitor)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	morphos)
+		basic_machine=powerpc-unknown
+		os=-morphos
+		;;
+	moxiebox)
+		basic_machine=moxie-unknown
+		os=-moxiebox
+		;;
+	msdos)
+		basic_machine=i386-pc
+		os=-msdos
+		;;
+	ms1-*)
+		basic_machine=`echo $basic_machine | sed -e 's/ms1-/mt-/'`
+		;;
+	msys)
+		basic_machine=i686-pc
+		os=-msys
+		;;
+	mvs)
+		basic_machine=i370-ibm
+		os=-mvs
+		;;
+	nacl)
+		basic_machine=le32-unknown
+		os=-nacl
+		;;
+	ncr3000)
+		basic_machine=i486-ncr
+		os=-sysv4
+		;;
+	netbsd386)
+		basic_machine=i386-unknown
+		os=-netbsd
+		;;
+	netwinder)
+		basic_machine=armv4l-rebel
+		os=-linux
+		;;
+	news | news700 | news800 | news900)
+		basic_machine=m68k-sony
+		os=-newsos
+		;;
+	news1000)
+		basic_machine=m68030-sony
+		os=-newsos
+		;;
+	news-3600 | risc-news)
+		basic_machine=mips-sony
+		os=-newsos
+		;;
+	necv70)
+		basic_machine=v70-nec
+		os=-sysv
+		;;
+	next | m*-next )
+		basic_machine=m68k-next
+		case $os in
+		    -nextstep* )
+			;;
+		    -ns2*)
+		      os=-nextstep2
+			;;
+		    *)
+		      os=-nextstep3
+			;;
+		esac
+		;;
+	nh3000)
+		basic_machine=m68k-harris
+		os=-cxux
+		;;
+	nh[45]000)
+		basic_machine=m88k-harris
+		os=-cxux
+		;;
+	nindy960)
+		basic_machine=i960-intel
+		os=-nindy
+		;;
+	mon960)
+		basic_machine=i960-intel
+		os=-mon960
+		;;
+	nonstopux)
+		basic_machine=mips-compaq
+		os=-nonstopux
+		;;
+	np1)
+		basic_machine=np1-gould
+		;;
+	neo-tandem)
+		basic_machine=neo-tandem
+		;;
+	nse-tandem)
+		basic_machine=nse-tandem
+		;;
+	nsr-tandem)
+		basic_machine=nsr-tandem
+		;;
+	nsx-tandem)
+		basic_machine=nsx-tandem
+		;;
+	op50n-* | op60c-*)
+		basic_machine=hppa1.1-oki
+		os=-proelf
+		;;
+	openrisc | openrisc-*)
+		basic_machine=or32-unknown
+		;;
+	os400)
+		basic_machine=powerpc-ibm
+		os=-os400
+		;;
+	OSE68000 | ose68000)
+		basic_machine=m68000-ericsson
+		os=-ose
+		;;
+	os68k)
+		basic_machine=m68k-none
+		os=-os68k
+		;;
+	pa-hitachi)
+		basic_machine=hppa1.1-hitachi
+		os=-hiuxwe2
+		;;
+	paragon)
+		basic_machine=i860-intel
+		os=-osf
+		;;
+	parisc)
+		basic_machine=hppa-unknown
+		os=-linux
+		;;
+	parisc-*)
+		basic_machine=hppa-`echo $basic_machine | sed 's/^[^-]*-//'`
+		os=-linux
+		;;
+	pbd)
+		basic_machine=sparc-tti
+		;;
+	pbb)
+		basic_machine=m68k-tti
+		;;
+	pc532 | pc532-*)
+		basic_machine=ns32k-pc532
+		;;
+	pc98)
+		basic_machine=i386-pc
+		;;
+	pc98-*)
+		basic_machine=i386-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium | p5 | k5 | k6 | nexgen | viac3)
+		basic_machine=i586-pc
+		;;
+	pentiumpro | p6 | 6x86 | athlon | athlon_*)
+		basic_machine=i686-pc
+		;;
+	pentiumii | pentium2 | pentiumiii | pentium3)
+		basic_machine=i686-pc
+		;;
+	pentium4)
+		basic_machine=i786-pc
+		;;
+	pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*)
+		basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumpro-* | p6-* | 6x86-* | athlon-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentiumii-* | pentium2-* | pentiumiii-* | pentium3-*)
+		basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pentium4-*)
+		basic_machine=i786-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	pn)
+		basic_machine=pn-gould
+		;;
+	power)	basic_machine=power-ibm
+		;;
+	ppc | ppcbe)	basic_machine=powerpc-unknown
+		;;
+	ppc-* | ppcbe-*)
+		basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppcle | powerpclittle)
+		basic_machine=powerpcle-unknown
+		;;
+	ppcle-* | powerpclittle-*)
+		basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64)	basic_machine=powerpc64-unknown
+		;;
+	ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ppc64le | powerpc64little)
+		basic_machine=powerpc64le-unknown
+		;;
+	ppc64le-* | powerpc64little-*)
+		basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	ps2)
+		basic_machine=i386-ibm
+		;;
+	pw32)
+		basic_machine=i586-unknown
+		os=-pw32
+		;;
+	rdos | rdos64)
+		basic_machine=x86_64-pc
+		os=-rdos
+		;;
+	rdos32)
+		basic_machine=i386-pc
+		os=-rdos
+		;;
+	rom68k)
+		basic_machine=m68k-rom68k
+		os=-coff
+		;;
+	rm[46]00)
+		basic_machine=mips-siemens
+		;;
+	rtpc | rtpc-*)
+		basic_machine=romp-ibm
+		;;
+	s390 | s390-*)
+		basic_machine=s390-ibm
+		;;
+	s390x | s390x-*)
+		basic_machine=s390x-ibm
+		;;
+	sa29200)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	sb1)
+		basic_machine=mipsisa64sb1-unknown
+		;;
+	sb1el)
+		basic_machine=mipsisa64sb1el-unknown
+		;;
+	sde)
+		basic_machine=mipsisa32-sde
+		os=-elf
+		;;
+	sei)
+		basic_machine=mips-sei
+		os=-seiux
+		;;
+	sequent)
+		basic_machine=i386-sequent
+		;;
+	sh)
+		basic_machine=sh-hitachi
+		os=-hms
+		;;
+	sh5el)
+		basic_machine=sh5le-unknown
+		;;
+	sh64)
+		basic_machine=sh64-unknown
+		;;
+	sparclite-wrs | simso-wrs)
+		basic_machine=sparclite-wrs
+		os=-vxworks
+		;;
+	sps7)
+		basic_machine=m68k-bull
+		os=-sysv2
+		;;
+	spur)
+		basic_machine=spur-unknown
+		;;
+	st2000)
+		basic_machine=m68k-tandem
+		;;
+	stratus)
+		basic_machine=i860-stratus
+		os=-sysv4
+		;;
+	strongarm-* | thumb-*)
+		basic_machine=arm-`echo $basic_machine | sed 's/^[^-]*-//'`
+		;;
+	sun2)
+		basic_machine=m68000-sun
+		;;
+	sun2os3)
+		basic_machine=m68000-sun
+		os=-sunos3
+		;;
+	sun2os4)
+		basic_machine=m68000-sun
+		os=-sunos4
+		;;
+	sun3os3)
+		basic_machine=m68k-sun
+		os=-sunos3
+		;;
+	sun3os4)
+		basic_machine=m68k-sun
+		os=-sunos4
+		;;
+	sun4os3)
+		basic_machine=sparc-sun
+		os=-sunos3
+		;;
+	sun4os4)
+		basic_machine=sparc-sun
+		os=-sunos4
+		;;
+	sun4sol2)
+		basic_machine=sparc-sun
+		os=-solaris2
+		;;
+	sun3 | sun3-*)
+		basic_machine=m68k-sun
+		;;
+	sun4)
+		basic_machine=sparc-sun
+		;;
+	sun386 | sun386i | roadrunner)
+		basic_machine=i386-sun
+		;;
+	sv1)
+		basic_machine=sv1-cray
+		os=-unicos
+		;;
+	symmetry)
+		basic_machine=i386-sequent
+		os=-dynix
+		;;
+	t3e)
+		basic_machine=alphaev5-cray
+		os=-unicos
+		;;
+	t90)
+		basic_machine=t90-cray
+		os=-unicos
+		;;
+	tile*)
+		basic_machine=$basic_machine-unknown
+		os=-linux-gnu
+		;;
+	tx39)
+		basic_machine=mipstx39-unknown
+		;;
+	tx39el)
+		basic_machine=mipstx39el-unknown
+		;;
+	toad1)
+		basic_machine=pdp10-xkl
+		os=-tops20
+		;;
+	tower | tower-32)
+		basic_machine=m68k-ncr
+		;;
+	tpf)
+		basic_machine=s390x-ibm
+		os=-tpf
+		;;
+	udi29k)
+		basic_machine=a29k-amd
+		os=-udi
+		;;
+	ultra3)
+		basic_machine=a29k-nyu
+		os=-sym1
+		;;
+	v810 | necv810)
+		basic_machine=v810-nec
+		os=-none
+		;;
+	vaxv)
+		basic_machine=vax-dec
+		os=-sysv
+		;;
+	vms)
+		basic_machine=vax-dec
+		os=-vms
+		;;
+	vpp*|vx|vx-*)
+		basic_machine=f301-fujitsu
+		;;
+	vxworks960)
+		basic_machine=i960-wrs
+		os=-vxworks
+		;;
+	vxworks68)
+		basic_machine=m68k-wrs
+		os=-vxworks
+		;;
+	vxworks29k)
+		basic_machine=a29k-wrs
+		os=-vxworks
+		;;
+	wasm32)
+		basic_machine=wasm32-unknown
+		;;
+	w65*)
+		basic_machine=w65-wdc
+		os=-none
+		;;
+	w89k-*)
+		basic_machine=hppa1.1-winbond
+		os=-proelf
+		;;
+	xbox)
+		basic_machine=i686-pc
+		os=-mingw32
+		;;
+	xps | xps100)
+		basic_machine=xps100-honeywell
+		;;
+	xscale-* | xscalee[bl]-*)
+		basic_machine=`echo $basic_machine | sed 's/^xscale/arm/'`
+		;;
+	ymp)
+		basic_machine=ymp-cray
+		os=-unicos
+		;;
+	z8k-*-coff)
+		basic_machine=z8k-unknown
+		os=-sim
+		;;
+	z80-*-coff)
+		basic_machine=z80-unknown
+		os=-sim
+		;;
+	none)
+		basic_machine=none-none
+		os=-none
+		;;
+
+# Here we handle the default manufacturer of certain CPU types.  It is in
+# some cases the only manufacturer, in others, it is the most popular.
+	w89k)
+		basic_machine=hppa1.1-winbond
+		;;
+	op50n)
+		basic_machine=hppa1.1-oki
+		;;
+	op60c)
+		basic_machine=hppa1.1-oki
+		;;
+	romp)
+		basic_machine=romp-ibm
+		;;
+	mmix)
+		basic_machine=mmix-knuth
+		;;
+	rs6000)
+		basic_machine=rs6000-ibm
+		;;
+	vax)
+		basic_machine=vax-dec
+		;;
+	pdp10)
+		# there are many clones, so DEC is not a safe bet
+		basic_machine=pdp10-unknown
+		;;
+	pdp11)
+		basic_machine=pdp11-dec
+		;;
+	we32k)
+		basic_machine=we32k-att
+		;;
+	sh[1234] | sh[24]a | sh[24]aeb | sh[34]eb | sh[1234]le | sh[23]ele)
+		basic_machine=sh-unknown
+		;;
+	sparc | sparcv8 | sparcv9 | sparcv9b | sparcv9v)
+		basic_machine=sparc-sun
+		;;
+	cydra)
+		basic_machine=cydra-cydrome
+		;;
+	orion)
+		basic_machine=orion-highlevel
+		;;
+	orion105)
+		basic_machine=clipper-highlevel
+		;;
+	mac | mpw | mac-mpw)
+		basic_machine=m68k-apple
+		;;
+	pmac | pmac-mpw)
+		basic_machine=powerpc-apple
+		;;
+	*-unknown)
+		# Make sure to match an already-canonicalized machine name.
+		;;
+	*)
+		echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2
+		exit 1
+		;;
+esac
+
+# Here we canonicalize certain aliases for manufacturers.
+case $basic_machine in
+	*-digital*)
+		basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'`
+		;;
+	*-commodore*)
+		basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'`
+		;;
+	*)
+		;;
+esac
+
+# Decode manufacturer-specific aliases for certain operating systems.
+
+if [ x"$os" != x"" ]
+then
+case $os in
+	# First match some system type aliases
+	# that might get confused with valid system types.
+	# -solaris* is a basic system type, with this one exception.
+	-auroraux)
+		os=-auroraux
+		;;
+	-solaris1 | -solaris1.*)
+		os=`echo $os | sed -e 's|solaris1|sunos4|'`
+		;;
+	-solaris)
+		os=-solaris2
+		;;
+	-svr4*)
+		os=-sysv4
+		;;
+	-unixware*)
+		os=-sysv4.2uw
+		;;
+	-gnu/linux*)
+		os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'`
+		;;
+	# First accept the basic system types.
+	# The portable systems comes first.
+	# Each alternative MUST END IN A *, to match a version number.
+	# -sysv* is not here because it comes later, after sysvr4.
+	-gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \
+	      | -*vms* | -sco* | -esix* | -isc* | -aix* | -cnk* | -sunos | -sunos[34]*\
+	      | -hpux* | -unos* | -osf* | -luna* | -dgux* | -auroraux* | -solaris* \
+	      | -sym* | -kopensolaris* | -plan9* \
+	      | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \
+	      | -aos* | -aros* | -cloudabi* | -sortix* \
+	      | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \
+	      | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \
+	      | -hiux* | -386bsd* | -knetbsd* | -mirbsd* | -netbsd* \
+	      | -bitrig* | -openbsd* | -solidbsd* | -libertybsd* \
+	      | -ekkobsd* | -kfreebsd* | -freebsd* | -riscix* | -lynxos* \
+	      | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \
+	      | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \
+	      | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
+	      | -chorusos* | -chorusrdb* | -cegcc* | -glidix* \
+	      | -cygwin* | -msys* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
+	      | -midipix* | -mingw32* | -mingw64* | -linux-gnu* | -linux-android* \
+	      | -linux-newlib* | -linux-musl* | -linux-uclibc* \
+	      | -uxpv* | -beos* | -mpeix* | -udk* | -moxiebox* \
+	      | -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
+	      | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
+	      | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \
+	      | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \
+	      | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* \
+	      | -powermax* | -dnix* | -nx6 | -nx7 | -sei* | -dragonfly* \
+	      | -skyos* | -haiku* | -rdos* | -toppers* | -drops* | -es* \
+	      | -onefs* | -tirtos* | -phoenix* | -fuchsia* | -redox*)
+	# Remember, each alternative MUST END IN *, to match a version number.
+		;;
+	-qnx*)
+		case $basic_machine in
+		    x86-* | i*86-*)
+			;;
+		    *)
+			os=-nto$os
+			;;
+		esac
+		;;
+	-nto-qnx*)
+		;;
+	-nto*)
+		os=`echo $os | sed -e 's|nto|nto-qnx|'`
+		;;
+	-sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \
+	      | -windows* | -osx | -abug | -netware* | -os9* | -beos* | -haiku* \
+	      | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*)
+		;;
+	-mac*)
+		os=`echo $os | sed -e 's|mac|macos|'`
+		;;
+	-linux-dietlibc)
+		os=-linux-dietlibc
+		;;
+	-linux*)
+		os=`echo $os | sed -e 's|linux|linux-gnu|'`
+		;;
+	-sunos5*)
+		os=`echo $os | sed -e 's|sunos5|solaris2|'`
+		;;
+	-sunos6*)
+		os=`echo $os | sed -e 's|sunos6|solaris3|'`
+		;;
+	-opened*)
+		os=-openedition
+		;;
+	-os400*)
+		os=-os400
+		;;
+	-wince*)
+		os=-wince
+		;;
+	-osfrose*)
+		os=-osfrose
+		;;
+	-osf*)
+		os=-osf
+		;;
+	-utek*)
+		os=-bsd
+		;;
+	-dynix*)
+		os=-bsd
+		;;
+	-acis*)
+		os=-aos
+		;;
+	-atheos*)
+		os=-atheos
+		;;
+	-syllable*)
+		os=-syllable
+		;;
+	-386bsd)
+		os=-bsd
+		;;
+	-ctix* | -uts*)
+		os=-sysv
+		;;
+	-nova*)
+		os=-rtmk-nova
+		;;
+	-ns2 )
+		os=-nextstep2
+		;;
+	-nsk*)
+		os=-nsk
+		;;
+	# Preserve the version number of sinix5.
+	-sinix5.*)
+		os=`echo $os | sed -e 's|sinix|sysv|'`
+		;;
+	-sinix*)
+		os=-sysv4
+		;;
+	-tpf*)
+		os=-tpf
+		;;
+	-triton*)
+		os=-sysv3
+		;;
+	-oss*)
+		os=-sysv3
+		;;
+	-svr4)
+		os=-sysv4
+		;;
+	-svr3)
+		os=-sysv3
+		;;
+	-sysvr4)
+		os=-sysv4
+		;;
+	# This must come after -sysvr4.
+	-sysv*)
+		;;
+	-ose*)
+		os=-ose
+		;;
+	-es1800*)
+		os=-ose
+		;;
+	-xenix)
+		os=-xenix
+		;;
+	-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+		os=-mint
+		;;
+	-aros*)
+		os=-aros
+		;;
+	-zvmoe)
+		os=-zvmoe
+		;;
+	-dicos*)
+		os=-dicos
+		;;
+	-nacl*)
+		;;
+	-ios)
+		;;
+	-none)
+		;;
+	*)
+		# Get rid of the `-' at the beginning of $os.
+		os=`echo $os | sed 's/[^-]*-//'`
+		echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2
+		exit 1
+		;;
+esac
+else
+
+# Here we handle the default operating systems that come with various machines.
+# The value should be what the vendor currently ships out the door with their
+# machine or put another way, the most popular os provided with the machine.
+
+# Note that if you're going to try to match "-MANUFACTURER" here (say,
+# "-sun"), then you have to tell the case statement up towards the top
+# that MANUFACTURER isn't an operating system.  Otherwise, code above
+# will signal an error saying that MANUFACTURER isn't an operating
+# system, and we'll never get to this point.
+
+case $basic_machine in
+	score-*)
+		os=-elf
+		;;
+	spu-*)
+		os=-elf
+		;;
+	*-acorn)
+		os=-riscix1.2
+		;;
+	arm*-rebel)
+		os=-linux
+		;;
+	arm*-semi)
+		os=-aout
+		;;
+	c4x-* | tic4x-*)
+		os=-coff
+		;;
+	c8051-*)
+		os=-elf
+		;;
+	hexagon-*)
+		os=-elf
+		;;
+	tic54x-*)
+		os=-coff
+		;;
+	tic55x-*)
+		os=-coff
+		;;
+	tic6x-*)
+		os=-coff
+		;;
+	# This must come before the *-dec entry.
+	pdp10-*)
+		os=-tops20
+		;;
+	pdp11-*)
+		os=-none
+		;;
+	*-dec | vax-*)
+		os=-ultrix4.2
+		;;
+	m68*-apollo)
+		os=-domain
+		;;
+	i386-sun)
+		os=-sunos4.0.2
+		;;
+	m68000-sun)
+		os=-sunos3
+		;;
+	m68*-cisco)
+		os=-aout
+		;;
+	mep-*)
+		os=-elf
+		;;
+	mips*-cisco)
+		os=-elf
+		;;
+	mips*-*)
+		os=-elf
+		;;
+	or32-*)
+		os=-coff
+		;;
+	*-tti)	# must be before sparc entry or we get the wrong os.
+		os=-sysv3
+		;;
+	sparc-* | *-sun)
+		os=-sunos4.1.1
+		;;
+	pru-*)
+		os=-elf
+		;;
+	*-be)
+		os=-beos
+		;;
+	*-haiku)
+		os=-haiku
+		;;
+	*-ibm)
+		os=-aix
+		;;
+	*-knuth)
+		os=-mmixware
+		;;
+	*-wec)
+		os=-proelf
+		;;
+	*-winbond)
+		os=-proelf
+		;;
+	*-oki)
+		os=-proelf
+		;;
+	*-hp)
+		os=-hpux
+		;;
+	*-hitachi)
+		os=-hiux
+		;;
+	i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent)
+		os=-sysv
+		;;
+	*-cbm)
+		os=-amigaos
+		;;
+	*-dg)
+		os=-dgux
+		;;
+	*-dolphin)
+		os=-sysv3
+		;;
+	m68k-ccur)
+		os=-rtu
+		;;
+	m88k-omron*)
+		os=-luna
+		;;
+	*-next )
+		os=-nextstep
+		;;
+	*-sequent)
+		os=-ptx
+		;;
+	*-crds)
+		os=-unos
+		;;
+	*-ns)
+		os=-genix
+		;;
+	i370-*)
+		os=-mvs
+		;;
+	*-next)
+		os=-nextstep3
+		;;
+	*-gould)
+		os=-sysv
+		;;
+	*-highlevel)
+		os=-bsd
+		;;
+	*-encore)
+		os=-bsd
+		;;
+	*-sgi)
+		os=-irix
+		;;
+	*-siemens)
+		os=-sysv4
+		;;
+	*-masscomp)
+		os=-rtu
+		;;
+	f30[01]-fujitsu | f700-fujitsu)
+		os=-uxpv
+		;;
+	*-rom68k)
+		os=-coff
+		;;
+	*-*bug)
+		os=-coff
+		;;
+	*-apple)
+		os=-macos
+		;;
+	*-atari*)
+		os=-mint
+		;;
+	*)
+		os=-none
+		;;
+esac
+fi
+
+# Here we handle the case where we know the os, and the CPU type, but not the
+# manufacturer.  We pick the logical manufacturer.
+vendor=unknown
+case $basic_machine in
+	*-unknown)
+		case $os in
+			-riscix*)
+				vendor=acorn
+				;;
+			-sunos*)
+				vendor=sun
+				;;
+			-cnk*|-aix*)
+				vendor=ibm
+				;;
+			-beos*)
+				vendor=be
+				;;
+			-hpux*)
+				vendor=hp
+				;;
+			-mpeix*)
+				vendor=hp
+				;;
+			-hiux*)
+				vendor=hitachi
+				;;
+			-unos*)
+				vendor=crds
+				;;
+			-dgux*)
+				vendor=dg
+				;;
+			-luna*)
+				vendor=omron
+				;;
+			-genix*)
+				vendor=ns
+				;;
+			-mvs* | -opened*)
+				vendor=ibm
+				;;
+			-os400*)
+				vendor=ibm
+				;;
+			-ptx*)
+				vendor=sequent
+				;;
+			-tpf*)
+				vendor=ibm
+				;;
+			-vxsim* | -vxworks* | -windiss*)
+				vendor=wrs
+				;;
+			-aux*)
+				vendor=apple
+				;;
+			-hms*)
+				vendor=hitachi
+				;;
+			-mpw* | -macos*)
+				vendor=apple
+				;;
+			-*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*)
+				vendor=atari
+				;;
+			-vos*)
+				vendor=stratus
+				;;
+		esac
+		basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"`
+		;;
+esac
+
+echo $basic_machine$os
+exit
+
+# Local variables:
+# eval: (add-hook 'write-file-hooks 'time-stamp)
 # time-stamp-start: "timestamp='"
 # time-stamp-format: "%:y-%02m-%02d"
 # time-stamp-end: "'"
diff --git a/configure b/configure
--- a/configure
+++ b/configure
@@ -637,7 +637,6 @@
 build_vendor
 build_cpu
 build
-BUILD_PACKAGE_BOOL
 EGREP
 GREP
 CPP
@@ -1770,6 +1769,60 @@
 
 } # ac_fn_c_check_func
 
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+  as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+  { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  eval "$3=no"
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+	 return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+	    return 0;
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+  eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+	       { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
 # ac_fn_c_check_decl LINENO SYMBOL VAR INCLUDES
 # ---------------------------------------------
 # Tests whether SYMBOL is declared in INCLUDES, setting cache variable VAR
@@ -3664,17 +3717,6 @@
 ac_config_headers="$ac_config_headers include/HsUnixConfig.h"
 
 
-# Is this a Unix system?
-ac_fn_c_check_header_mongrel "$LINENO" "dlfcn.h" "ac_cv_header_dlfcn_h" "$ac_includes_default"
-if test "x$ac_cv_header_dlfcn_h" = xyes; then :
-  BUILD_PACKAGE_BOOL=True
-else
-  BUILD_PACKAGE_BOOL=False
-fi
-
-
-
-
 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for an ANSI C-conforming const" >&5
 $as_echo_n "checking for an ANSI C-conforming const... " >&6; }
 if ${ac_cv_c_const+:} false; then :
@@ -4105,6 +4147,133 @@
 done
 
 
+for ac_func in alarm
+do :
+  ac_fn_c_check_func "$LINENO" "alarm" "ac_cv_func_alarm"
+if test "x$ac_cv_func_alarm" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_ALARM 1
+_ACEOF
+
+fi
+done
+
+for ac_func in dup
+do :
+  ac_fn_c_check_func "$LINENO" "dup" "ac_cv_func_dup"
+if test "x$ac_cv_func_dup" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_DUP 1
+_ACEOF
+
+fi
+done
+
+for ac_func in execv
+do :
+  ac_fn_c_check_func "$LINENO" "execv" "ac_cv_func_execv"
+if test "x$ac_cv_func_execv" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_EXECV 1
+_ACEOF
+
+fi
+done
+
+for ac_func in getpid
+do :
+  ac_fn_c_check_func "$LINENO" "getpid" "ac_cv_func_getpid"
+if test "x$ac_cv_func_getpid" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_GETPID 1
+_ACEOF
+
+fi
+done
+
+for ac_func in mknod
+do :
+  ac_fn_c_check_func "$LINENO" "mknod" "ac_cv_func_mknod"
+if test "x$ac_cv_func_mknod" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MKNOD 1
+_ACEOF
+
+fi
+done
+
+for ac_func in mkstemp
+do :
+  ac_fn_c_check_func "$LINENO" "mkstemp" "ac_cv_func_mkstemp"
+if test "x$ac_cv_func_mkstemp" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_MKSTEMP 1
+_ACEOF
+
+fi
+done
+
+for ac_func in pipe
+do :
+  ac_fn_c_check_func "$LINENO" "pipe" "ac_cv_func_pipe"
+if test "x$ac_cv_func_pipe" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_PIPE 1
+_ACEOF
+
+fi
+done
+
+for ac_func in times
+do :
+  ac_fn_c_check_func "$LINENO" "times" "ac_cv_func_times"
+if test "x$ac_cv_func_times" = xyes; then :
+  cat >>confdefs.h <<_ACEOF
+#define HAVE_TIMES 1
+_ACEOF
+
+fi
+done
+
+
+ac_fn_c_check_type "$LINENO" "struct rlimit" "ac_cv_type_struct_rlimit" "#include <sys/resource.h>
+"
+if test "x$ac_cv_type_struct_rlimit" = xyes; then :
+
+$as_echo "#define HAVE_STRUCT_RLIMIT 1" >>confdefs.h
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for F_GETLK from fcntl.h" >&5
+$as_echo_n "checking for F_GETLK from fcntl.h... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h.  */
+
+ #include <fcntl.h>
+ #ifdef F_GETLK
+        yes
+ #endif
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+  $EGREP "yes" >/dev/null 2>&1; then :
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+
+$as_echo "#define HAVE_F_GETLK 1" >>confdefs.h
+
+
+else
+
+  { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+
+fi
+rm -f conftest*
+
+
 ac_aux_dir=
 for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do
   if test -f "$ac_dir/install-sh"; then
@@ -4297,6 +4466,28 @@
 done
 
 
+ac_fn_c_check_decl "$LINENO" "CLOCKS_PER_SEC" "ac_cv_have_decl_CLOCKS_PER_SEC" "$ac_includes_default
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+"
+if test "x$ac_cv_have_decl_CLOCKS_PER_SEC" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_CLOCKS_PER_SEC $ac_have_decl
+_ACEOF
+if test $ac_have_decl = 1; then :
+
+$as_echo "#define HAVE_CLOCKS_PER_SEC 1" >>confdefs.h
+
+fi
+
+
 ac_fn_c_check_member "$LINENO" "struct stat" "st_atim" "ac_cv_member_struct_stat_st_atim" "$ac_includes_default"
 if test "x$ac_cv_member_struct_stat_st_atim" = xyes; then :
 
@@ -4448,6 +4639,27 @@
 fi
 
 
+ac_fn_c_check_member "$LINENO" "struct stat" "st_blocks" "ac_cv_member_struct_stat_st_blocks" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_blocks" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLOCKS 1
+_ACEOF
+
+
+fi
+
+ac_fn_c_check_member "$LINENO" "struct stat" "st_blksize" "ac_cv_member_struct_stat_st_blksize" "$ac_includes_default"
+if test "x$ac_cv_member_struct_stat_st_blksize" = xyes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_STRUCT_STAT_ST_BLKSIZE 1
+_ACEOF
+
+
+fi
+
+
 ac_fn_c_check_member "$LINENO" "struct passwd" "pw_gecos" "ac_cv_member_struct_passwd_pw_gecos" "#include <pwd.h>
 "
 if test "x$ac_cv_member_struct_passwd_pw_gecos" = xyes; then :
@@ -4486,7 +4698,7 @@
 
 
 # Additional temp functions
-# We explicilty check for android, as the check AC_CHECK_FUNCS performs returns "yes" for mkstemps
+# We explicitly check for android, as the check AC_CHECK_FUNCS performs returns "yes" for mkstemps
 # when targetting android. See similar conditionals for seekdir and telldir.
 case $target_os in #(
   *-android*) :
@@ -4708,7 +4920,6 @@
   fp_check_const_result='-1'
 fi
 
-
 eval "$as_fp_Cache=\$fp_check_const_result"
 fi
 eval ac_res=\$$as_fp_Cache
@@ -5136,6 +5347,26 @@
 else
   { $as_echo "$as_me:${as_lineno-$LINENO}: Not found" >&5
 $as_echo "$as_me: Not found" >&6;}
+fi
+
+
+ac_fn_c_check_decl "$LINENO" "sem_getvalue" "ac_cv_have_decl_sem_getvalue" "$ac_includes_default
+#include <semaphore.h>
+
+"
+if test "x$ac_cv_have_decl_sem_getvalue" = xyes; then :
+  ac_have_decl=1
+else
+  ac_have_decl=0
+fi
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_DECL_SEM_GETVALUE $ac_have_decl
+_ACEOF
+if test $ac_have_decl = 1; then :
+
+$as_echo "#define HAVE_SEM_GETVALUE 1" >>confdefs.h
+
 fi
 
 
diff --git a/configure.ac b/configure.ac
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,5 @@
-AC_PREREQ([2.60])
-AC_INIT([Haskell unix package], [2.0], [libraries@haskell.org], [unix])
+AC_PREREQ([2.69])
+AC_INIT([Haskell unix package],[2.0],[libraries@haskell.org],[unix])
 
 # Safety check: Ensure that we are in the correct source directory.
 AC_CONFIG_SRCDIR([include/HsUnix.h])
@@ -11,10 +11,6 @@
 
 AC_CONFIG_HEADERS([include/HsUnixConfig.h])
 
-# Is this a Unix system?
-AC_CHECK_HEADER([dlfcn.h], [BUILD_PACKAGE_BOOL=True], [BUILD_PACKAGE_BOOL=False])
-AC_SUBST([BUILD_PACKAGE_BOOL])
-
 AC_C_CONST
 
 dnl ** Enable large file support.  NB. do this before testing the type of
@@ -38,6 +34,31 @@
 AC_CHECK_FUNCS([setitimer])
 AC_CHECK_FUNCS([readdir_r])
 
+AC_CHECK_FUNCS([alarm])
+AC_CHECK_FUNCS([dup])
+AC_CHECK_FUNCS([execv])
+AC_CHECK_FUNCS([getpid])
+AC_CHECK_FUNCS([mknod])
+AC_CHECK_FUNCS([mkstemp])
+AC_CHECK_FUNCS([pipe])
+AC_CHECK_FUNCS([times])
+
+AC_CHECK_TYPE([struct rlimit],[AC_DEFINE([HAVE_STRUCT_RLIMIT],[1],[HAVE_STRUCT_RLIMIT])],[],[#include <sys/resource.h>])
+
+AC_MSG_CHECKING(for F_GETLK from fcntl.h)
+AC_EGREP_CPP(yes,
+[
+ #include <fcntl.h>
+ #ifdef F_GETLK
+        yes
+ #endif
+], [
+  AC_MSG_RESULT(yes)
+  AC_DEFINE([HAVE_F_GETLK], [1], [Define to 1 if F_GETLK is available.])
+], [
+  AC_MSG_RESULT(no)
+  ])
+
 dnl not available on android so check for it
 AC_CANONICAL_TARGET
 AS_CASE([$target_os],[*-android*],[],[AC_CHECK_FUNCS([telldir seekdir])])
@@ -50,6 +71,12 @@
 AC_CHECK_DECLS([execvpe])
 AC_CHECK_FUNCS([execvpe])
 
+AC_CHECK_DECLS([CLOCKS_PER_SEC], [AC_DEFINE([HAVE_CLOCKS_PER_SEC],[1],[Define to 1 if you have the CLOCKS_PER_SEC macro.])], [], [AC_INCLUDES_DEFAULT
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+])
+
 AC_CHECK_MEMBERS([struct stat.st_atim])
 AC_CHECK_MEMBERS([struct stat.st_mtim])
 AC_CHECK_MEMBERS([struct stat.st_ctim])
@@ -66,6 +93,9 @@
 AC_CHECK_MEMBERS([struct stat.st_umtime])
 AC_CHECK_MEMBERS([struct stat.st_uctime])
 
+AC_CHECK_MEMBERS([struct stat.st_blocks])
+AC_CHECK_MEMBERS([struct stat.st_blksize])
+
 AC_CHECK_MEMBER([struct passwd.pw_gecos], [], [AC_DEFINE([HAVE_NO_PASSWD_PW_GECOS],[],[Ignore the pw_gecos member of passwd where it does not exist])], [[#include <pwd.h>]])
 
 # Functions for changing file timestamps
@@ -74,7 +104,7 @@
 
 # Additional temp functions
 dnl androids bionic doesn't have mkstemps
-# We explicilty check for android, as the check AC_CHECK_FUNCS performs returns "yes" for mkstemps
+# We explicitly check for android, as the check AC_CHECK_FUNCS performs returns "yes" for mkstemps
 # when targetting android. See similar conditionals for seekdir and telldir.
 AS_CASE([$target_os],[*-android*],[AC_CHECK_FUNCS([mkdtemp])],[AC_CHECK_FUNCS([mkstemps mkdtemp])])
 
@@ -181,7 +211,7 @@
   AC_DEFINE([HAVE_RTLDNEXT], [1], [Define to 1 if we can see RTLD_NEXT in dlfcn.h.])
 ], [
   AC_MSG_RESULT(no)
-  ])    
+  ])
 
 AC_MSG_CHECKING(for RTLD_DEFAULT from dlfcn.h)
 AC_EGREP_CPP(yes,
@@ -195,7 +225,7 @@
   AC_DEFINE([HAVE_RTLDDEFAULT], [1], [Define to 1 if RTLD_DEFAULT is available.])
 ], [
   AC_MSG_RESULT(no)
-  ])    
+  ])
 
 AC_CHECK_FUNCS(openpty,,
    AC_CHECK_LIB(util,openpty,
@@ -233,6 +263,10 @@
 AC_SEARCH_LIBS(sem_close, pthread,
     [EXTRA_LIBS="$EXTRA_LIBS $ac_lib"],
     [AC_MSG_NOTICE([Not found])])
+
+AC_CHECK_DECLS([sem_getvalue],[AC_DEFINE([HAVE_SEM_GETVALUE],[1],[Define to 1 if you have the `sem_getvalue' function.])],[],[AC_INCLUDES_DEFAULT
+#include <semaphore.h>
+])
 
 AC_SUBST([EXTRA_LIBS])
 AC_CONFIG_FILES([unix.buildinfo])
diff --git a/include/HsUnix.h b/include/HsUnix.h
--- a/include/HsUnix.h
+++ b/include/HsUnix.h
@@ -83,7 +83,9 @@
 #include <utmp.h>
 #endif
 
+#if defined(HAVE_DLFCN_H)
 #include <dlfcn.h>
+#endif
 
 #ifdef HAVE_SIGNAL_H
 #include <signal.h>
@@ -116,5 +118,9 @@
 
 // push a SVR4 STREAMS module; do nothing if STREAMS not available
 int __hsunix_push_module(int fd, const char *module);
+
+#ifdef HAVE_CLOCKS_PER_SEC
+clock_t __hsunix_clocks_per_second (void);
+#endif
 
 #endif
diff --git a/include/HsUnixConfig.h.in b/include/HsUnixConfig.h.in
--- a/include/HsUnixConfig.h.in
+++ b/include/HsUnixConfig.h.in
@@ -99,15 +99,25 @@
 /* The value of SIG_UNBLOCK. */
 #undef CONST_SIG_UNBLOCK
 
+/* Define to 1 if you have the `alarm' function. */
+#undef HAVE_ALARM
+
 /* Define to 1 if you have the <bsd/libutil.h> header file. */
 #undef HAVE_BSD_LIBUTIL_H
 
 /* Define to 1 if you have the `clearenv' function. */
 #undef HAVE_CLEARENV
 
+/* Define to 1 if you have the CLOCKS_PER_SEC macro. */
+#undef HAVE_CLOCKS_PER_SEC
+
 /* Define to 1 if you have the `ctermid' function. */
 #undef HAVE_CTERMID
 
+/* Define to 1 if you have the declaration of `CLOCKS_PER_SEC', and to 0 if
+   you don't. */
+#undef HAVE_DECL_CLOCKS_PER_SEC
+
 /* Define to 1 if you have the declaration of `ctermid', and to 0 if you
    don't. */
 #undef HAVE_DECL_CTERMID
@@ -120,6 +130,10 @@
    don't. */
 #undef HAVE_DECL_FDATASYNC
 
+/* Define to 1 if you have the declaration of `sem_getvalue', and to 0 if you
+   don't. */
+#undef HAVE_DECL_SEM_GETVALUE
+
 /* Define to 1 if you have the declaration of `tcdrain', and to 0 if you
    don't. */
 #undef HAVE_DECL_TCDRAIN
@@ -133,6 +147,12 @@
 /* Define to 1 if you have the <dirent.h> header file. */
 #undef HAVE_DIRENT_H
 
+/* Define to 1 if you have the `dup' function. */
+#undef HAVE_DUP
+
+/* Define to 1 if you have the `execv' function. */
+#undef HAVE_EXECV
+
 /* Define to 1 if you have the `execvpe' function. */
 #undef HAVE_EXECVPE
 
@@ -151,6 +171,9 @@
 /* Define to 1 if you have the `futimes' function. */
 #undef HAVE_FUTIMES
 
+/* Define to 1 if F_GETLK is available. */
+#undef HAVE_F_GETLK
+
 /* Define to 1 if you have the `getgrent' function. */
 #undef HAVE_GETGRENT
 
@@ -160,6 +183,9 @@
 /* Define to 1 if you have the `getgrnam_r' function. */
 #undef HAVE_GETGRNAM_R
 
+/* Define to 1 if you have the `getpid' function. */
+#undef HAVE_GETPID
+
 /* Define to 1 if you have the `getpwent' function. */
 #undef HAVE_GETPWENT
 
@@ -199,6 +225,12 @@
 /* Define to 1 if you have the `mkdtemp' function. */
 #undef HAVE_MKDTEMP
 
+/* Define to 1 if you have the `mknod' function. */
+#undef HAVE_MKNOD
+
+/* Define to 1 if you have the `mkstemp' function. */
+#undef HAVE_MKSTEMP
+
 /* Define to 1 if you have the `mkstemps' function. */
 #undef HAVE_MKSTEMPS
 
@@ -211,6 +243,9 @@
 /* Define to 1 if you have the `openpty' function. */
 #undef HAVE_OPENPTY
 
+/* Define to 1 if you have the `pipe' function. */
+#undef HAVE_PIPE
+
 /* Define to 1 if you have the `posix_fadvise' function. */
 #undef HAVE_POSIX_FADVISE
 
@@ -244,6 +279,9 @@
 /* Define to 1 if you have the `seekdir' function. */
 #undef HAVE_SEEKDIR
 
+/* Define to 1 if you have the `sem_getvalue' function. */
+#undef HAVE_SEM_GETVALUE
+
 /* Define to 1 if you have the `setenv' function. */
 #undef HAVE_SETENV
 
@@ -271,6 +309,9 @@
 /* Define to 1 if you have the <string.h> header file. */
 #undef HAVE_STRING_H
 
+/* HAVE_STRUCT_RLIMIT */
+#undef HAVE_STRUCT_RLIMIT
+
 /* Define to 1 if `st_atim' is a member of `struct stat'. */
 #undef HAVE_STRUCT_STAT_ST_ATIM
 
@@ -283,6 +324,12 @@
 /* Define to 1 if `st_atime_n' is a member of `struct stat'. */
 #undef HAVE_STRUCT_STAT_ST_ATIME_N
 
+/* Define to 1 if `st_blksize' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLKSIZE
+
+/* Define to 1 if `st_blocks' is a member of `struct stat'. */
+#undef HAVE_STRUCT_STAT_ST_BLOCKS
+
 /* Define to 1 if `st_ctim' is a member of `struct stat'. */
 #undef HAVE_STRUCT_STAT_ST_CTIM
 
@@ -348,6 +395,9 @@
 
 /* Define to 1 if you have the <termios.h> header file. */
 #undef HAVE_TERMIOS_H
+
+/* Define to 1 if you have the `times' function. */
+#undef HAVE_TIMES
 
 /* Define to 1 if you have the <time.h> header file. */
 #undef HAVE_TIME_H
diff --git a/include/execvpe.h b/include/execvpe.h
--- a/include/execvpe.h
+++ b/include/execvpe.h
@@ -10,16 +10,4 @@
 extern int
 __hsunix_execvpe(const char *name, char *const argv[], char *const envp[]);
 
-// this hack is needed for `process`; to be removed in unix-2.8
-#ifndef HSUNIX_EXECVPE_H_NO_COMPAT
-#include "HsUnixConfig.h"
-#if HAVE_EXECVPE
-# include <unistd.h>
-extern int
-execvpe(const char *name, char *const argv[], char *const envp[]);
-#else
-# define execvpe(name,argv,envp) __hsunix_execvpe(name,argv,envp)
-#endif
-#endif
-
 #endif
diff --git a/tests/FileStatus.hs b/tests/FileStatus.hs
--- a/tests/FileStatus.hs
+++ b/tests/FileStatus.hs
@@ -95,7 +95,7 @@
   fs  <- getFileStatus f
   ls  <- getSymbolicLinkStatus f
 
-  fd  <- openFd f ReadOnly Nothing defaultFileFlags
+  fd  <- openFd f ReadOnly defaultFileFlags
   fs' <- getFdStatus fd
 
   when (statusElements fs /= statusElements fs') $
diff --git a/tests/FileStatusByteString.hs b/tests/FileStatusByteString.hs
--- a/tests/FileStatusByteString.hs
+++ b/tests/FileStatusByteString.hs
@@ -93,7 +93,7 @@
   fs  <- getFileStatus f
   ls  <- getSymbolicLinkStatus f
 
-  fd  <- openFd f ReadOnly Nothing defaultFileFlags
+  fd  <- openFd f ReadOnly defaultFileFlags
   fs' <- getFdStatus fd
 
   when (statusElements fs /= statusElements fs') $
diff --git a/unix.buildinfo.in b/unix.buildinfo.in
--- a/unix.buildinfo.in
+++ b/unix.buildinfo.in
@@ -1,3 +1,2 @@
-buildable: @BUILD_PACKAGE_BOOL@
 extra-libraries: @EXTRA_LIBS@
 install-includes: HsUnixConfig.h
diff --git a/unix.cabal b/unix.cabal
--- a/unix.cabal
+++ b/unix.cabal
@@ -1,16 +1,23 @@
+cabal-version:  1.12
 name:           unix
-version:        2.7.3
+version:        2.8.0.0
 -- NOTE: Don't forget to update ./changelog.md
+
 license:        BSD3
 license-file:   LICENSE
-maintainer:     libraries@haskell.org
+maintainer:     Julian Ospald <hasufell@posteo.de>, Viktor Dukhovni <ietf-dane@dukhovni.org>, Andrew Lelechenko <andrew.lelechenko@gmail.com>
 homepage:       https://github.com/haskell/unix
 bug-reports:    https://github.com/haskell/unix/issues
 synopsis:       POSIX functionality
 category:       System
 build-type:     Configure
-cabal-version:  >= 1.10
-tested-with:    GHC>=7.4.1
+tested-with:    GHC==9.2.4,
+                GHC==9.0.2,
+                GHC==8.10.7,
+                GHC==8.8.4,
+                GHC==8.6.5,
+                GHC==8.4.4,
+                GHC==8.2.2
 description:
     This package gives you access to the set of operating system
     services standardised by
@@ -64,26 +71,34 @@
     build-depends:
         base        >= 4.10    && < 4.18,
         bytestring  >= 0.9.2   && < 0.12,
+        filepath    >= 1.4.100.0 && < 1.5,
         time        >= 1.2     && < 1.13
 
     exposed-modules:
         System.Posix
         System.Posix.ByteString
+        System.Posix.PosixString
 
         System.Posix.Error
         System.Posix.Resource
         System.Posix.Time
         System.Posix.Unistd
-        System.Posix.User
         System.Posix.Signals
         System.Posix.Signals.Exts
         System.Posix.Semaphore
         System.Posix.SharedMem
 
+        System.Posix.User
+        System.Posix.User.ByteString
+
         System.Posix.ByteString.FilePath
+        System.Posix.PosixPath.FilePath
 
         System.Posix.Directory
+        System.Posix.Directory.Internals
+        System.Posix.Directory.Fd
         System.Posix.Directory.ByteString
+        System.Posix.Directory.PosixPath
 
         System.Posix.DynamicLinker.Module
         System.Posix.DynamicLinker.Module.ByteString
@@ -93,24 +108,30 @@
 
         System.Posix.Files
         System.Posix.Files.ByteString
+        System.Posix.Files.PosixString
 
         System.Posix.IO
         System.Posix.IO.ByteString
+        System.Posix.IO.PosixString
 
         System.Posix.Env
         System.Posix.Env.ByteString
+        System.Posix.Env.PosixString
 
         System.Posix.Fcntl
 
         System.Posix.Process
         System.Posix.Process.Internals
         System.Posix.Process.ByteString
+        System.Posix.Process.PosixString
 
         System.Posix.Temp
         System.Posix.Temp.ByteString
+        System.Posix.Temp.PosixString
 
         System.Posix.Terminal
         System.Posix.Terminal.ByteString
+        System.Posix.Terminal.PosixString
 
     other-modules:
         System.Posix.Directory.Common
@@ -119,6 +140,7 @@
         System.Posix.IO.Common
         System.Posix.Process.Common
         System.Posix.Terminal.Common
+        System.Posix.User.Common
 
     ghc-options: -Wall
 
