anyone know how to get console input from the user without echoing their keypresses to the screen?
edit: also, I can reopen(stdout, "...") - how do I get it back? reopen(stdout, "????")
You'd do it the same way you'd do it in C, which is discussed here:
http://stackoverflow.com/questions/6856635/hide-password-input-on-terminal
Unfortunately, it doesn't seem like we have wrapping for termios.h :( I would add that as an issue on github, since the posix wrappers are part of the core library.
proc getpass(prompt: cstring) : cstring {.header: "<unistd.h>", importc: "getpass".}
var result = getpass("Password: ")
echo "result: ", result
Only tested/working on nix though.. idk about windows
Windows here, got this:
In file included from c:\dev\projects\nim\autohive\nimcache\b.c:10:0:
grabbing a "getopt.h" from winpython's mingw's include folder lets it compile, but it does not work correctly.
oh, well. thanks.
EDIT: nvm, didn't compile. was "succeeding" due to old .c files left in .\nimcache\
If you're fine with Windows-only, what about using _getch? That reads a single character without echoing. Try this (haven't tested because I don't have a Nim compiler on this machine)
http://msdn.microsoft.com/en-us/library/078sfkak.aspx
proc getch() : char {.header: "<conio.h>", importc: "_getch".}
@skyfex :: I will try that out, thanks.
EDIT:: nope, no conio.h in the windows default install
I came up with this, which works on Windows (no echo on password prompt, echo back on for input prompt):
import windows
var inputHandle = GetStdHandle(STD_INPUT_HANDLE)
var conMode: DWORD
discard GetConsoleMode(inputHandle, conMode)
write(stdout, "Password: ")
discard SetConsoleMode(inputHandle, conMode - ENABLE_ECHO_INPUT)
var password = readLine(stdin)
discard SetConsoleMode(inputHandle, conMode)
write(stdout, "\nInput, please: ")
var input = readLine(stdin)
echo ("\n\nPassword: " & password & "\nInput: " & input)
EDIT @ Varriount: Better?
Also, to answer my 2nd question up there:
reopen (stdout, "...whatever", fmWrite)
can be reverted (in Windows) by:
reopen (stdout, "CONOUT$", fnWrite)
Hmm in the Linux world masking isn't usually done with asterixs, normally echoing is just turned off and the terminal displays blanks eg if you use su or log into a virtual terminal etc.
There is a library function to handle getting passwords, it won't mask the password with asterix's but will disable echoing of the password to terminal I pulled this out of a linux book I have. I believe its part of the posix standard You can also check if http://bit.ly/1ChEoUj works.
I know it's been 8 years; but for anyone still wondering, I've found a simple code example that prints asterisks for password-input using getch:
from terminal import getch
from strutils import strip
from strformat import fmt
proc getPass(prompt = "Secret: "): string =
stdout.write(prompt)
while result == "" or result[^1] notin ['\x0D', '\n']:
result.add getch()
stdout.write("*")
stdout.write("\n")
return result.strip()
# Example
let password = getPass("What is your password? ")
echo fmt"Your password = '{password}'"
Or you can just use the one in the standard library (no asterisks, just turns off printing):
from terminal import readPasswordFromStdin
from strformat import fmt
let password = readPasswordFromStdin("What is your password? ")
echo fmt"Your password = '{password}'"
EDIT: Discovered my getPass() adds backspace characters too; here's one workaround for that:
proc getPassword(prompt = "Secret: "): string =
stdout.write(prompt)
const backspace_character = char(127) # ASCII code
while result == "" or result[^1] notin ['\r', '\n']:
let entered_char = getch()
# Cant actually implement backspace behaviour (remove char already printed to stdout), but can at least not add/print for its character
if entered_char != backspace_character:
result.add(entered_char)
stdout.write("*")
stdout.write("\n")
return result.strip()