I there a way to ask passw开发者_JS百科ord in lua but hide with asterisks?
I'm asking about a console application
For Unix: use os.execute("stty -echo raw")
to turn off echoing and enter raw mode (character-by-character input) and os.execute("stty echo cooked")
to turn it on and exit raw mode when you are done. In raw mode, you can get each character of the input using io.stdin:read(1)
and echo your asterisk as you go (use io.flush
to ensure the character appears straight away). You will need to handle deletes and the end of line yourself.
For Windows, the situation is a bit trickier. Look at What would be the Windows batch equivalent for HTML's input type=“password”? for some approaches, the best of which seems to be a VB script.
Postscript
Thanks for lhf for pointing out that you need raw mode besides -echo
on input and flush after each output asterisk to get the desired result: unless you have both, the asteriskes will not be echoed until the line is ended.
This code uses platform-specific features and works both on Linux and 32-bit Windows.
Compatible with Lua 5.1 and Lua 5.2
local console
local function enter_password(prompt_message, asterisk_char, max_length)
-- returns password string
-- "Enter" key finishes the password
-- "Backspace" key undoes last entered character
if not console then
if (os.getenv'os' or ''):lower():find'windows' then
------------------ Windows ------------------
local shift = 10
-- Create executable file which returns (getch()+shift) as exit code
local getch_filespec = 'getch.com'
-- mov AH,8
-- int 21h
-- add AL,shift
-- mov AH,4Ch
-- int 21h
local file = assert(io.open(getch_filespec, 'wb'))
file:write(string.char(0xB4,8,0xCD,0x21,4,shift,0xB4,0x4C,0xCD,0x21))
file:close()
console = {
wait_key = function()
local code_Lua51, _, code_Lua52 = os.execute(getch_filespec)
local code = (code_Lua52 or code_Lua51) - shift
assert(code >= 0, getch_filespec..' execution failed')
return string.char(code)
end,
on_start = function() end,
on_finish = function() end,
backspace_key = '\b'
}
-------------------------------------------
else
------------------ Linux ------------------
console = {
wait_key = function()
return io.read(1)
end,
on_start = function()
os.execute'stty -echo raw'
end,
on_finish = function()
os.execute'stty sane'
end,
backspace_key = '\127'
}
-------------------------------------------
end
end
io.write(prompt_message or '')
io.flush()
local pwd = ''
console.on_start()
repeat
local c = console.wait_key()
if c == console.backspace_key then
if #pwd > 0 then
io.write'\b \b'
pwd = pwd:sub(1, -2)
end
elseif c ~= '\r' and #pwd < (max_length or 32) then
io.write(asterisk_char or '*')
pwd = pwd..c
end
io.flush()
until c == '\r'
console.on_finish()
io.write'\n'
io.flush()
return pwd
end
-- Usage example
local pwd = enter_password'Enter password: '
print('You entered: '..pwd:gsub('%c','?'))
print(pwd:byte(1,-1))
Bug in code, for at least linux implementation. Need to add 'and c ~= nil`: elseif c ~= '\r' and #pwd < (max_length or 32) and c ~= nil then
精彩评论