Is there a way to disable (temporarily) the interrupting effect of control-C in a regular running-in-a-shell Haskell executable?
Context: I have a little exercise which I set each year. It's a game where the students zipper around expressions triggering pattern matching rewrites as applicable, running in a shell window using hncurses. When the students have finished the last puzzle, they get an individual password which they need to send me. Being Windows veterans and Unix newbies, and of course (virtuously) lazy, they tend to select the password and type control-C. This has the unintended effect of interrupting the program and causing their password to vanish. The only way to recover it is to repeat the exercise. How cruel!
Whilst there are other ways I could work around the problem (e.g., printing a warning message or writing the password to a file), I'm curious to know if there's way to disable control-C.
To disable ctrl+c or ctrl+z for all users, append the trap command combinations in /etc/profile. If these signals should only be enabled for a specfic user, the trap command can be added to ~/. bash_profile.
How do I disable Control-C? You need to use the trap command which can enable or disable keyboard keys such as Crtl-C. SIGINT is Crtl-C and it is represented using number 2.
Yep, you just have to temporarily ignore SIGINT:
import Prelude hiding (catch)
import Control.Exception
import Control.Concurrent
import System.Posix.Signals
-- Ensures the original handler is restored even after an exception.
--
-- installHandler returns the previous signal handler, so if you're
-- tied to some existing main loop, you could instead just keep
-- its return value around for later restoration.
ignoreSignal :: Signal -> IO a -> IO a
ignoreSignal sig = bracket (install Ignore) install . const
where install handler = installHandler sig handler Nothing
pause :: IO ()
pause = threadDelay 2000000
main :: IO ()
main = do
ignoreSignal keyboardSignal $ do
putStrLn "Ctrl+C disabled."
pause
putStrLn "\nCtrl+C re-enabled."
pause
(You can also write keyboardSignal
as sigINT
if you want to name it more directly.)
You could also replace Ignore
with Catch m
, where m
is some action that prints guidance on the correct way to copy text. (Be careful, though; it'll run in a separate Haskell thread.)
Quick and easy, use the shell:
stty intr ^T
run your haskell program here
stty intr ^C
This has the added benefit that programs can still be interrupted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With