1 {-# OPTIONS -optc-DNON_POSIX_SOURCE #-}
3 -- ---------------------------------------------------------------------------
4 -- $Id: PrelPosix.hsc,v 1.1 2001/05/18 16:54:05 simonmar Exp $
6 -- POSIX support layer for the standard libraries
22 import PrelMarshalAlloc
23 import PrelMarshalUtils
28 -- ---------------------------------------------------------------------------
34 type CDev = #type dev_t
35 type CIno = #type ino_t
36 type CMode = #type mode_t
37 type COff = #type off_t
38 type CPid = #type pid_t
39 #ifndef mingw32_TARGET_OS
40 type CGid = #type gid_t
41 type CNlink = #type nlink_t
42 type CSsize = #type ssize_t
43 type CUid = #type uid_t
45 type CSpeed = #type speed_t
46 type CTcflag = #type tcflag_t
49 -- ---------------------------------------------------------------------------
50 -- stat()-related stuff
54 fdFileSize :: Int -> IO Integer
56 allocaBytes (#const sizeof(struct stat)) $ \ p_stat -> do
57 throwErrnoIfMinus1Retry "fileSize" $
58 c_fstat (fromIntegral fd) p_stat
59 c_mode <- (#peek struct stat, st_mode) p_stat :: IO CMode
60 if not (s_isreg c_mode)
63 c_size <- (#peek struct stat, st_size) p_stat :: IO COff
64 return (fromIntegral c_size)
66 data FDType = Directory | Stream | RegularFile
69 fdType :: Int -> IO FDType
71 allocaBytes (#const sizeof(struct stat)) $ \ p_stat -> do
72 throwErrnoIfMinus1Retry "fileSize" $
73 c_fstat (fromIntegral fd) p_stat
74 c_mode <- (#peek struct stat, st_mode) p_stat :: IO CMode
76 _ | s_isdir c_mode -> return Directory
77 | s_isfifo c_mode || s_issock c_mode -> return Stream
78 | s_isreg c_mode -> return RegularFile
79 | otherwise -> ioException ioe_unknownfiletype
81 ioe_unknownfiletype = IOError Nothing UnsupportedOperation "fdType"
82 "unknown file type" Nothing
84 foreign import "s_isreg_wrap" s_isreg :: CMode -> Bool
85 #def inline int s_isreg_wrap(m) { return S_ISREG(m); }
87 foreign import "s_isdir_wrap" s_isdir :: CMode -> Bool
88 #def inline int s_isdir_wrap(m) { return S_ISDIR(m); }
90 foreign import "s_isfifo_wrap" s_isfifo :: CMode -> Bool
91 #def inline int s_isfifo_wrap(m) { return S_ISFIFO(m); }
93 foreign import "s_issock_wrap" s_issock :: CMode -> Bool
94 #def inline int s_issock_wrap(m) { return S_ISSOCK(m); }
96 -- ---------------------------------------------------------------------------
97 -- Terminal-related stuff
99 fdIsTTY :: Int -> IO Bool
100 fdIsTTY fd = c_isatty (fromIntegral fd) >>= return.toBool
104 setEcho :: Int -> Bool -> IO ()
106 allocaBytes (#const sizeof(struct termios)) $ \p_tios -> do
107 throwErrnoIfMinus1Retry "setEcho"
108 (c_tcgetattr (fromIntegral fd) p_tios)
109 c_lflag <- (#peek struct termios, c_lflag) p_tios :: IO CTcflag
110 let new_c_lflag | on = c_lflag .|. (#const ECHO)
111 | otherwise = c_lflag .&. complement (#const ECHO)
112 (#poke struct termios, c_lflag) p_tios (new_c_lflag :: CTcflag)
113 tcSetAttr fd (#const TCSANOW) p_tios
115 getEcho :: Int -> IO Bool
117 allocaBytes (#const sizeof(struct termios)) $ \p_tios -> do
118 throwErrnoIfMinus1Retry "setEcho"
119 (c_tcgetattr (fromIntegral fd) p_tios)
120 c_lflag <- (#peek struct termios, c_lflag) p_tios :: IO CTcflag
121 return ((c_lflag .&. (#const ECHO)) /= 0)
123 setCooked :: Int -> Bool -> IO ()
124 setCooked fd cooked =
125 allocaBytes (#const sizeof(struct termios)) $ \p_tios -> do
126 throwErrnoIfMinus1Retry "setCooked"
127 (c_tcgetattr (fromIntegral fd) p_tios)
129 -- turn on/off ICANON
130 c_lflag <- (#peek struct termios, c_lflag) p_tios :: IO CTcflag
131 let new_c_lflag | cooked = c_lflag .|. (#const ICANON)
132 | otherwise = c_lflag .&. complement (#const ICANON)
133 (#poke struct termios, c_lflag) p_tios (new_c_lflag :: CTcflag)
135 -- set VMIN & VTIME to 1/0 respectively
137 do let c_cc = (#ptr struct termios, c_cc) p_tios
138 vmin = c_cc `plusPtr` (#const VMIN) :: Ptr Word8
139 vtime = c_cc `plusPtr` (#const VTIME) :: Ptr Word8
143 tcSetAttr fd (#const TCSANOW) p_tios
145 -- tcsetattr() when invoked by a background process causes the process
146 -- to be sent SIGTTOU regardless of whether the process has TOSTOP set
147 -- in its terminal flags (try it...). This function provides a
148 -- wrapper which temporarily blocks SIGTTOU around the call, making it
151 tcSetAttr :: FD -> CInt -> Ptr Termios -> IO ()
152 tcSetAttr fd options p_tios = do
153 allocaBytes (#const sizeof(sigset_t)) $ \ p_sigset -> do
154 allocaBytes (#const sizeof(sigset_t)) $ \ p_old_sigset -> do
155 c_sigemptyset p_sigset
156 c_sigaddset p_sigset (#const SIGTTOU)
157 c_sigprocmask (#const SIG_BLOCK) p_sigset p_old_sigset
158 throwErrnoIfMinus1Retry_ "tcSetAttr" $
159 c_tcsetattr (fromIntegral fd) options p_tios
160 c_sigprocmask (#const SIG_SETMASK) p_old_sigset nullPtr
162 -- ---------------------------------------------------------------------------
163 -- Turning on non-blocking for a file descriptor
165 setNonBlockingFD fd = do
166 flags <- throwErrnoIfMinus1Retry "setNonBlockingFD"
167 (fcntl_read (fromIntegral fd) (#const F_GETFL))
168 throwErrnoIfMinus1Retry "setNonBlockingFD"
169 (fcntl_write (fromIntegral fd)
170 (#const F_SETFL) (flags .|. #const O_NONBLOCK))
172 -- -----------------------------------------------------------------------------
175 foreign import "stat" unsafe
176 c_stat :: CString -> Ptr CStat -> IO CInt
178 foreign import "fstat" unsafe
179 c_fstat :: CInt -> Ptr CStat -> IO CInt
182 foreign import "lstat" unsafe
183 c_lstat :: CString -> Ptr CStat -> IO CInt
186 foreign import "open" unsafe
187 c_open :: CString -> CInt -> CMode -> IO CInt
190 o_RDONLY = (#const O_RDONLY) :: CInt
191 o_WRONLY = (#const O_WRONLY) :: CInt
192 o_RDWR = (#const O_RDWR) :: CInt
193 o_APPEND = (#const O_APPEND) :: CInt
194 o_CREAT = (#const O_CREAT) :: CInt
195 o_EXCL = (#const O_EXCL) :: CInt
196 o_NOCTTY = (#const O_NOCTTY) :: CInt
197 o_TRUNC = (#const O_TRUNC) :: CInt
198 o_NONBLOCK = (#const O_NONBLOCK) :: CInt
200 foreign import "close" unsafe
201 c_close :: CInt -> IO CInt
203 foreign import "fcntl" unsafe
204 fcntl_read :: CInt -> CInt -> IO CInt
206 foreign import "fcntl" unsafe
207 fcntl_write :: CInt -> CInt -> CInt -> IO CInt
209 foreign import "fork" unsafe
212 foreign import "isatty" unsafe
213 c_isatty :: CInt -> IO CInt
215 foreign import "lseek" unsafe
216 c_lseek :: CInt -> COff -> CInt -> IO COff
218 foreign import "read" unsafe
219 c_read :: CInt -> Ptr CChar -> CSize -> IO CSsize
221 foreign import "sigemptyset" unsafe
222 c_sigemptyset :: Ptr CSigset -> IO ()
224 foreign import "sigaddset" unsafe
225 c_sigaddset :: Ptr CSigset -> CInt -> IO ()
227 foreign import "sigprocmask" unsafe
228 c_sigprocmask :: CInt -> Ptr CSigset -> Ptr CSigset -> IO ()
230 foreign import "tcgetattr" unsafe
231 c_tcgetattr :: CInt -> Ptr Termios -> IO CInt
233 foreign import "tcsetattr" unsafe
234 c_tcsetattr :: CInt -> CInt -> Ptr Termios -> IO CInt
236 foreign import "waitpid" unsafe
237 c_waitpid :: CPid -> Ptr CInt -> CInt -> IO CPid
239 foreign import "write" unsafe
240 c_write :: CInt -> Ptr CChar -> CSize -> IO CSsize