Prompting for a password in Haskell command line application

前端 未结 6 950
傲寒
傲寒 2021-02-01 04:10

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:         


        
相关标签:
6条回答
  • 2021-02-01 04:14

    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
    
    0 讨论(0)
  • 2021-02-01 04:15

    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)
    
    0 讨论(0)
  • 2021-02-01 04:16

    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.

    0 讨论(0)
  • 2021-02-01 04:19

    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)
    
    0 讨论(0)
  • 2021-02-01 04:25

    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
    
    0 讨论(0)
  • 2021-02-01 04:32

    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.

    0 讨论(0)
提交回复
热议问题