Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I disable control-C?

Tags:

io

haskell

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.

like image 372
pigworker Avatar asked Jan 23 '12 09:01

pigworker


People also ask

How do I disable Ctrl 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.

What command can disable Ctrl C from stopping a script?

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.


2 Answers

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.)

like image 173
ehird Avatar answered Sep 28 '22 17:09

ehird


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.

like image 22
Ingo Avatar answered Sep 28 '22 17:09

Ingo