{-# LINE 1 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} {-# LANGUAGE CApiFFI #-} {-# LINE 3 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} {-# LANGUAGE Safe #-} {-# LINE 7 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} ----------------------------------------------------------------------------- -- | -- Module : System.Posix.Terminal.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 Terminal support -- ----------------------------------------------------------------------------- module System.Posix.Terminal.ByteString ( -- * 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 import Foreign import System.Posix.Types import System.Posix.Terminal.Common {-# LINE 81 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} import System.Posix.IO.ByteString (defaultFileFlags, openFd, noctty, OpenMode(ReadWrite)) import Data.ByteString.Char8 as B ( pack, ) {-# LINE 84 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} import Foreign.C hiding ( throwErrnoPath, throwErrnoPathIf, throwErrnoPathIf_, throwErrnoPathIfNull, throwErrnoPathIfMinus1, throwErrnoPathIfMinus1_ ) import System.Posix.ByteString.FilePath {-# LINE 99 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} -- | @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 RawFilePath 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 RawFilePath {-# LINE 123 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} getControllingTerminalName = do s <- throwErrnoIfNull "getControllingTerminalName" (c_ctermid nullPtr) peekFilePath s foreign import capi unsafe "termios.h ctermid" c_ctermid :: CString -> IO CString {-# LINE 134 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} -- | @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 RawFilePath {-# LINE 141 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} getSlaveTerminalName (Fd fd) = do s <- throwErrnoIfNull "getSlaveTerminalName" (c_ptsname fd) peekFilePath s {-# LINE 150 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} foreign import capi unsafe "HsUnix.h ptsname" c_ptsname :: CInt -> IO CString {-# LINE 153 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} {-# LINE 157 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} -- ----------------------------------------------------------------------------- -- 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) {-# LINE 180 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} openPseudoTerminal = do (Fd master) <- openFd (B.pack "/dev/ptmx") ReadWrite Nothing 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} pushModule slave "ptem" pushModule slave "ldterm" {-# LINE 190 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} pushModule slave "ttcompat" {-# LINE 192 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} 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 {-# LINE 205 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} {-# LINE 213 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} foreign import capi unsafe "HsUnix.h grantpt" c_grantpt :: CInt -> IO CInt foreign import capi unsafe "HsUnix.h unlockpt" c_unlockpt :: CInt -> IO CInt {-# LINE 219 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} {-# LINE 226 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-} {-# LINE 227 "libraries/unix/System/Posix/Terminal/ByteString.hsc" #-}