"What can I do so the characters can't be seen when a user types a
password?" is a frequent question. [Tk] applications have a complete
and simple answer: use [entry]'s -show option. For a usage example, see [A little login dialog].
A [pure-Tcl] solution is slightly subtler. In a Unix context, the
formula is
exec stty -echo / echo
[[elaborate, including [signal] hygiene ...--which [Expect]
handles by itself]]
"[stty] -echo ..." is an error-prone subject.
[Don Libes] and [marsd] describe, for example, a long-standing
problem that continues to plague Linux 2.4.12
[http://groups.google.com/groups?hl=en&lr=&frame=left&th=5433ad0c03fdc370].
The [Unix Terminal Extension] provides the ability to disable echoing, as well as the ability to read one character at a time from stdin. See [terminal:password:get] for an example.
If you don't mind using the Tcl Windows API extension (which only
works on Win NT platforms, not Win 98!), the following should do the
trick
package require twapi
set console_handle [twapi::GetStdHandle -10]
set oldmode [twapi::GetConsoleMode $console_handle]
set newmode [expr {$oldmode & ~4}] ;# Turn off the echo bit
twapi::SetConsoleMode $console_handle $newmode
gets stdin password ;#...or do whatever...
twapi::SetConsoleMode $console_handle $oldmode ;# Restore echo mode
Or a slightly simpler version using the higher level console API in TWAPI 0.7:
puts -nonewline "Enter password: "
flush stdout
set oldmode [twapi::modify_console_input_mode stdin -echoinput false -lineinput true]
gets stdin password
# Restore original input mode eval [list twapi::set_console_input_mode stdin] {*}$oldmode
The TWAPI extension is available from http://twapi.sf.net
----
[drh] FWIW, here is the code I am currently using to read echo-free passwords on unix:
# Read a single line of input from the terminal without echoing to the
# screen. If Control-C is pressed, exit immediately.
#
proc tty_gets_no_echo {{prompt {}}} {
if {$prompt!=""} {
puts -nonewline $prompt
}
flush stdout
global _tty_input _tty_wait tcl_platform
if {$tcl_platform(platform)!="unix"} {
# FIXME: This routine only works on unix. On other platforms, the
# password is still echoed to the screen as it is typed.
return [gets stdin]
}
set _tty_input {}
set _tty_wait 0
fileevent stdin readable _tty_read_one_character
exec /bin/stty raw -echo <@stdin
vwait ::_tty_wait
fileevent stdin readable {}
return $_tty_input
}
proc _tty_read_one_character {} {
set c [read stdin 1]
if {$c=="\n" || $c=="\003"} {
exec /bin/stty -raw echo <@stdin
puts ""
if {$c=="\003"} exit
incr ::_tty_wait
} else {
append ::_tty_input $c
}
}
----
See also the slightly related app [Password Gorilla]
<<categories>>Security