The following Haskell program prompts the user for a password in the terminal and continues if he has entered the correct one:
main = do
putStrLn \"Password:
There is a getPassword in System.Console.Haskeline
. Probably it's an overkill for your case but someone may find it useful.
An example:
> runInputT defaultSettings $ do {p <- getPassword (Just '*') "pass:"; outputStrLn $ fromJust p}
pass:***
asd
withEcho can be written with a little less noise:
withEcho :: Bool -> IO a -> IO a
withEcho echo action =
bracket (hGetEcho stdin)
(hSetEcho stdin)
(const $ hSetEcho stdin echo >> action)
As I commented above, I suggest you use haskeline, which is a full prompt library. I've used it happily for LambdaCalculator with no complaints.
I have found this useful when reading passwords:
import Control.Exception
import System.IO
withoutEcho :: IO a -> IO a
withoutEcho action =
finally (hSetEcho stdin False >> action) (hSetEcho stdin True)
Do this:
module Main
where
import System.IO
import Control.Exception
main :: IO ()
main = getPassword >>= putStrLn . ("Entered: " ++)
getPassword :: IO String
getPassword = do
putStr "Password: "
hFlush stdout
pass <- withEcho False getLine
putChar '\n'
return pass
withEcho :: Bool -> IO a -> IO a
withEcho echo action = do
old <- hGetEcho stdin
bracket_ (hSetEcho stdin echo) (hSetEcho stdin old) action
It is possible to disable echoing in the terminal with the System.Posix.Terminal module. However, this requires POSIX support, so may not work on Windows (I didn't check).
import System.Posix.Terminal
import System.Posix.IO (stdInput)
getPassword :: IO String
getPassword = do
tc <- getTerminalAttributes stdInput
setTerminalAttributes stdInput (withoutMode tc EnableEcho) Immediately
password <- getLine
setTerminalAttributes stdInput tc Immediately
return password
main = do
putStrLn "Password:"
password <- getPassword
putStrLn "Name:"
name <- getLine
putStrLn $ "Your password is " ++ password ++ " and your name is " ++ name
Note that the stdin is line-buffered, so if you use putStr "Password:"
instead of putStrLn
, you need to flush the buffer first, otherwise the prompt will be inhibited also.