summaryrefslogtreecommitdiff
path: root/libraries/base/GHC/ConsoleHandler.hs
blob: 761926db4f982bfbbb9fced4e24f5fce55aa48ef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
{-# OPTIONS_GHC -cpp #-}
-----------------------------------------------------------------------------
-- |
-- Module      :  GHC.ConsoleHandler
-- Copyright   :  whatevah
-- License     :  see libraries/base/LICENSE
-- 
-- Maintainer  :  cvs-ghc@haskell.org
-- Stability   :  internal
-- Portability :  non-portable (GHC extensions)
--
-- Installing Win32 console handlers.
-- 
-----------------------------------------------------------------------------
module GHC.ConsoleHandler
#ifndef mingw32_TARGET_OS
	where
import Prelude -- necessary to get dependencies right
#else /* whole file */
	( Handler(..)
	, installHandler
	, ConsoleEvent(..)
	) where

{-
#include "Signals.h"
-}

import Prelude -- necessary to get dependencies right

import Foreign
import Foreign.C

data Handler
 = Default
 | Ignore
 | Catch (ConsoleEvent -> IO ())

data ConsoleEvent
 = ControlC
 | Break
 | Close
    -- these are sent to Services only.
 | Logoff
 | Shutdown

installHandler :: Handler -> IO Handler
installHandler handler = 
  alloca $ \ p_sp -> do
   rc <- 
    case handler of
     Default -> rts_installHandler STG_SIG_DFL p_sp
     Ignore  -> rts_installHandler STG_SIG_IGN p_sp
     Catch h -> do
        v <- newStablePtr (toHandler h)
	poke p_sp v
	rts_installHandler STG_SIG_HAN p_sp
   case rc of
     STG_SIG_DFL -> return Default
     STG_SIG_IGN -> return Ignore
     STG_SIG_HAN -> do
        osptr <- peek p_sp
        oldh  <- deRefStablePtr osptr
	 -- stable pointer is no longer in use, free it.
	freeStablePtr osptr
	return (Catch (\ ev -> oldh (fromConsoleEvent ev)))
  where
   toConsoleEvent ev = 
     case ev of
       0 {- CTRL_C_EVENT-}        -> Just ControlC
       1 {- CTRL_BREAK_EVENT-}    -> Just Break
       2 {- CTRL_CLOSE_EVENT-}    -> Just Close
       5 {- CTRL_LOGOFF_EVENT-}   -> Just Logoff
       6 {- CTRL_SHUTDOWN_EVENT-} -> Just Shutdown
       _ -> Nothing
   fromConsoleEvent ev = 
     case ev of
       ControlC -> 0 {- CTRL_C_EVENT-}
       Break    -> 1 {- CTRL_BREAK_EVENT-}
       Close    -> 2 {- CTRL_CLOSE_EVENT-}
       Logoff   -> 5 {- CTRL_LOGOFF_EVENT-}
       Shutdown -> 6 {- CTRL_SHUTDOWN_EVENT-}

   toHandler hdlr ev = do
      case toConsoleEvent ev of
        Just x  -> hdlr x
	Nothing -> return () -- silently ignore..

foreign import ccall unsafe "Signals.h stg_InstallConsoleEvent" 
  rts_installHandler :: CInt -> Ptr (StablePtr (CInt -> IO ())) -> IO CInt
#endif /* mingw32_TARGET_OS */