Is there a way to get user input from the terminal without displaying the input? The user should either see nothing or *****.
You might want to try this library, I don’t know if it has the password input feature but you could always add it! Using a readline-type line editor would let your users do basic line editing, it’s always frustrating when the left arrow inserts some control character etc. Line Editing on any platform: Anyline
This code is for POSIX systems, not for Windows
const std = @import("std");
fn disableEcho(fd: std.posix.fd_t) !void {
var termios: std.posix.termios = try std.posix.tcgetattr(fd);
termios.lflag.ECHO = false;
try std.posix.tcsetattr(fd, .NOW, termios);
}
fn enableEcho(fd: std.posix.fd_t) !void {
var termios: std.posix.termios = try std.posix.tcgetattr(fd);
termios.lflag.ECHO = true;
try std.posix.tcsetattr(fd, .NOW, termios);
}
pub fn interactivePassword(buf: []u8) ![]u8 {
const stdin = std.fs.File.stdin();
try disableEcho(stdin.handle);
defer enableEcho(stdin.handle) catch unreachable;
var stdin_reader = stdin.reader(buf);
return try stdin_reader.interface.takeDelimiterExclusive('\n');
}
pub fn main() !void {
var buf: [128]u8 = undefined;
std.debug.print("print password here:", .{});
const password = try interactivePassword(&buf);
std.debug.print("\n{s}\n", .{password});
}
Thanks. I ended up using the ICANON flag: termios.lflag.ICANON = false. It gives me more control.
In case someone needs it, here is my solution: GitHub - eltNEG/passprompt: A simple Zig library for secure password input from the terminal with customizable display options
This however will not work for windows, as it is solely focused on posix. After a little bit of scouting the zig 0.15.2 files, I
fn setEchoW(enable: bool) !void {
const windows = std.os.windows;
const kernel32 = windows.kernel32;
const stdout_handle = kernel32.GetStdHandle(windows.STD_INPUT_HANDLE) orelse return error.StdHandleFailed;
var mode: windows.DWORD = undefined;
_ = kernel32.GetConsoleMode(stdout_handle, &mode);
const ENABLE_ECHO_MODE: u32 = 0x0004;
const new_mode = if (enable) mode | ENABLE_ECHO_MODE else mode & ~ENABLE_ECHO_MODE;
_ = kernel32.SetConsoleMode(stdout_handle, new_mode);
}
fn setEchoL(enable: bool) !void {
const fd = std.fs.File.stdin().handle;
var termios: std.posix.termios = try std.posix.tcgetattr(fd);
termios.lflag.ECHO = enable;
try std.posix.tcsetattr(fd, .NOW, termios);
}
fn setEcho(enable: bool) !void {
switch (builtin.os.tag) {
.windows => setEchoW(enable) catch {},
else => setEchoL(enable) catch {},
}
}