Skip to content

Commit d17b03d

Browse files
committed
Don't assume tcdrain and ctermid exist always
This follows the scheme suggested in #24 This fixes #55
1 parent 4f3b5d8 commit d17b03d

File tree

5 files changed

+64
-4
lines changed

5 files changed

+64
-4
lines changed

System/Posix/Terminal.hsc

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE CApiFFI #-}
12
#if __GLASGOW_HASKELL__ >= 709
23
{-# LANGUAGE Safe #-}
34
#elif __GLASGOW_HASKELL__ >= 703
@@ -83,6 +84,11 @@ import System.Posix.IO
8384

8485
import System.Posix.Internals (peekFilePath)
8586

87+
#if !HAVE_CTERMID
88+
import System.IO.Error ( ioeSetLocation )
89+
import GHC.IO.Exception ( unsupportedOperation )
90+
#endif
91+
8692
-- | @getTerminalName fd@ calls @ttyname@ to obtain a name associated
8793
-- with the terminal for @Fd@ @fd@. If @fd@ is associated
8894
-- with a terminal, @getTerminalName@ returns the name of the
@@ -100,13 +106,23 @@ foreign import ccall unsafe "ttyname"
100106
-- controlling terminal exists,
101107
-- @getControllingTerminalName@ returns the name of the
102108
-- controlling terminal.
109+
--
110+
-- Throws 'IOError' (\"unsupported operation\") if platform does not
111+
-- provide @ctermid(3)@ (use @#if HAVE_CTERMID@ CPP guard to
112+
-- detect availability).
103113
getControllingTerminalName :: IO FilePath
114+
#if HAVE_CTERMID
104115
getControllingTerminalName = do
105116
s <- throwErrnoIfNull "getControllingTerminalName" (c_ctermid nullPtr)
106117
peekFilePath s
107118

108-
foreign import ccall unsafe "ctermid"
119+
foreign import capi unsafe "termios.h ctermid"
109120
c_ctermid :: CString -> IO CString
121+
#else
122+
{-# WARNING getControllingTerminalName
123+
"operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_CTERMID@)" #-}
124+
getControllingTerminalName = ioError (ioeSetLocation unsupportedOperation "getControllingTerminalName")
125+
#endif
110126

111127
-- | @getSlaveTerminalName@ calls @ptsname@ to obtain the name of the
112128
-- slave terminal associated with a pseudoterminal pair. The file

System/Posix/Terminal/ByteString.hsc

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
{-# LANGUAGE CApiFFI #-}
12
#if __GLASGOW_HASKELL__ >= 709
23
{-# LANGUAGE Safe #-}
34
#elif __GLASGOW_HASKELL__ >= 703
@@ -91,6 +92,10 @@ import Foreign.C hiding (
9192

9293
import System.Posix.ByteString.FilePath
9394

95+
#if !HAVE_CTERMID
96+
import System.IO.Error ( ioeSetLocation )
97+
import GHC.IO.Exception ( unsupportedOperation )
98+
#endif
9499

95100
-- | @getTerminalName fd@ calls @ttyname@ to obtain a name associated
96101
-- with the terminal for @Fd@ @fd@. If @fd@ is associated
@@ -109,13 +114,23 @@ foreign import ccall unsafe "ttyname"
109114
-- controlling terminal exists,
110115
-- @getControllingTerminalName@ returns the name of the
111116
-- controlling terminal.
117+
--
118+
-- Throws 'IOError' (\"unsupported operation\") if platform does not
119+
-- provide @ctermid(3)@ (use @#if HAVE_CTERMID@ CPP guard to
120+
-- detect availability).
112121
getControllingTerminalName :: IO RawFilePath
122+
#if HAVE_CTERMID
113123
getControllingTerminalName = do
114124
s <- throwErrnoIfNull "getControllingTerminalName" (c_ctermid nullPtr)
115125
peekFilePath s
116126

117-
foreign import ccall unsafe "ctermid"
127+
foreign import capi unsafe "termios.h ctermid"
118128
c_ctermid :: CString -> IO CString
129+
#else
130+
{-# WARNING getControllingTerminalName
131+
"operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_CTERMID@)" #-}
132+
getControllingTerminalName = ioError (ioeSetLocation unsupportedOperation "getControllingTerminalName")
133+
#endif
119134

120135
-- | @getSlaveTerminalName@ calls @ptsname@ to obtain the name of the
121136
-- slave terminal associated with a pseudoterminal pair. The file

System/Posix/Terminal/Common.hsc

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ import Foreign.Storable ( Storable(..) )
7878
import System.IO.Unsafe ( unsafePerformIO )
7979
import System.Posix.Types
8080

81+
#if !HAVE_TCDRAIN
82+
import System.IO.Error ( ioeSetLocation )
83+
import GHC.IO.Exception ( unsupportedOperation )
84+
#endif
85+
8186
-- -----------------------------------------------------------------------------
8287
-- Terminal attributes
8388

@@ -408,12 +413,21 @@ foreign import capi unsafe "termios.h tcsendbreak"
408413

409414
-- | @drainOutput fd@ calls @tcdrain@ to block until all output
410415
-- written to @Fd@ @fd@ has been transmitted.
416+
--
417+
-- Throws 'IOError' (\"unsupported operation\") if platform does not
418+
-- provide @tcdrain(3)@ (use @#if HAVE_TCDRAIN@ CPP guard to
419+
-- detect availability).
411420
drainOutput :: Fd -> IO ()
421+
#if HAVE_TCDRAIN
412422
drainOutput (Fd fd) = throwErrnoIfMinus1_ "drainOutput" (c_tcdrain fd)
413423

414424
foreign import capi unsafe "termios.h tcdrain"
415425
c_tcdrain :: CInt -> IO CInt
416-
426+
#else
427+
{-# WARNING drainOutput
428+
"operation will throw 'IOError' \"unsupported operation\" (CPP guard: @#if HAVE_TCDRAIN@)" #-}
429+
drainOutput _ = ioError (ioeSetLocation unsupportedOperation "drainOutput")
430+
#endif
417431

418432
data QueueSelector
419433
= InputQueue -- TCIFLUSH

changelog.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,9 @@
44

55
* Don't assume non-POSIX `WCOREDUMP(x)` macro exists
66

7-
* Don't assume existence of termios constants beyond `B38400`
7+
* Don't assume existence of `termios(3)` constants beyond `B38400`
8+
9+
* Don't assume existence of `ctermid(3)`/`tcdrain(3)`
810

911
* Turn build error into compile warnings for exotic `struct stat`
1012
configurations (GHC #8859).

configure.ac

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,19 @@ AC_CHECK_DECLS([fdatasync],[AC_CHECK_FUNCS([fdatasync])])
8080

8181
AC_CHECK_FUNCS([posix_fadvise posix_fallocate])
8282

83+
# Some termios(3) functions known to be missing sometimes (see also #55)
84+
AC_CHECK_DECLS([tcdrain],[AC_DEFINE([HAVE_TCDRAIN],[1],[Define to 1 if you have the `tcdrain' function.])],[],[AC_INCLUDES_DEFAULT
85+
#ifdef HAVE_TERMIOS_H
86+
#include <termios.h>
87+
#endif
88+
])
89+
90+
AC_CHECK_DECLS([ctermid],[AC_DEFINE([HAVE_CTERMID],[1],[Define to 1 if you have the `ctermid' function.])],[],[AC_INCLUDES_DEFAULT
91+
#ifdef HAVE_TERMIOS_H
92+
#include <termios.h>
93+
#endif
94+
])
95+
8396
# Avoid adding rt if absent or unneeded
8497
# shm_open needs -lrt on linux
8598
AC_SEARCH_LIBS(shm_open, rt, [AC_CHECK_FUNCS([shm_open shm_unlink])])

0 commit comments

Comments
 (0)