summary refs log tree commit diff stats
diff options
context:
space:
mode:
authordef <dennis@felsin9.de>2015-02-03 17:47:27 +0100
committerdef <dennis@felsin9.de>2015-02-03 17:51:15 +0100
commitdcd23ae1f1b52f48f3d32a753ae4db065b3985f8 (patch)
tree48063ebe6d769fba073f1eb8502fb50fc5802e39
parent3b68d9e93c603117a301aa5048bfd61774434eb2 (diff)
downloadNim-dcd23ae1f1b52f48f3d32a753ae4db065b3985f8.tar.gz
Add readPasswordFromStdin to rdstdin
-rw-r--r--lib/impure/rdstdin.nim42
1 files changed, 38 insertions, 4 deletions
diff --git a/lib/impure/rdstdin.nim b/lib/impure/rdstdin.nim
index 07ef13fd9..258da2207 100644
--- a/lib/impure/rdstdin.nim
+++ b/lib/impure/rdstdin.nim
@@ -31,9 +31,27 @@ when defined(Windows):
     stdout.write(prompt)
     result = readLine(stdin, line)
 
+  proc getch(): cint {.header: "<conio.h>", importc: "_getch".}
+
+  proc readPasswordFromStdin*(prompt: string, password: var TaintedString) =
+    ## Reads a `password` from stdin without printing it. `password` must not
+    ## be ``nil``!
+    password.setLen(0)
+    var c: char
+    echo prompt
+    while true:
+       c = getch().char
+       case c
+       of '\r', chr(0xA):
+          break
+       of '\b':
+          password.setLen(result.len - 1)
+       else:
+          password.add(c)
+
 else:
-  import readline, history
-    
+  import readline, history, termios, unsigned
+
   proc readLineFromStdin*(prompt: string): TaintedString {.
                           tags: [ReadIOEffect, WriteIOEffect].} =
     var buffer = readline.readLine(prompt)
@@ -55,8 +73,24 @@ else:
     result = true
 
   # initialization:
-  # disable auto-complete: 
+  # disable auto-complete:
   proc doNothing(a, b: cint): cint {.cdecl, procvar.} = discard
-  
+
   discard readline.bind_key('\t'.ord, doNothing)
 
+  proc readPasswordFromStdin*(prompt: string, password: var TaintedString) =
+    password.setLen(0)
+    let fd = stdin.getFileHandle()
+    var cur, old: Termios
+    discard fd.tcgetattr(cur.addr)
+    old = cur
+    cur.lflag = cur.lflag and not Tcflag(ECHO)
+    discard fd.tcsetattr(TCSADRAIN, cur.addr)
+    stdout.write prompt
+    discard stdin.readLine(password)
+    discard fd.tcsetattr(TCSADRAIN, old.addr)
+
+proc readPasswordFromStdin*(prompt: string): TaintedString =
+  ## Reads a password from stdin without printing it.
+  result = TaintedString("")
+  readPasswordFromStdin(prompt, result)