From 26a4327b06fbdd186f8fac4181e94aefc1811fed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julian=20Eigm=C3=BCller?= Date: Fri, 28 Oct 2022 15:37:20 +0200 Subject: [PATCH] LibC: Implement getpass() This function is a deprecated POSIX function which prints a prompt and receives a password from the user, not echoing back to the terminal. --- Userland/Libraries/LibC/limits.h | 2 ++ Userland/Libraries/LibC/unistd.cpp | 54 ++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 3 deletions(-) diff --git a/Userland/Libraries/LibC/limits.h b/Userland/Libraries/LibC/limits.h index 936a9ab928..54d288a6e4 100644 --- a/Userland/Libraries/LibC/limits.h +++ b/Userland/Libraries/LibC/limits.h @@ -93,3 +93,5 @@ #define LINK_MAX 4096 #define TZNAME_MAX 64 + +#define PASS_MAX 128 diff --git a/Userland/Libraries/LibC/unistd.cpp b/Userland/Libraries/LibC/unistd.cpp index cd2f91bc89..d866e15165 100644 --- a/Userland/Libraries/LibC/unistd.cpp +++ b/Userland/Libraries/LibC/unistd.cpp @@ -972,11 +972,59 @@ int unveil(char const* path, char const* permissions) __RETURN_WITH_ERRNO(rc, rc, -1); } -// https://pubs.opengroup.org/onlinepubs/9699919799/functions/getpass.html +// https://pubs.opengroup.org/onlinepubs/7908799/xsh/getpass.html char* getpass(char const* prompt) { - dbgln("FIXME: getpass('{}')", prompt); - TODO(); + int tty = open("/dev/tty", O_RDWR | O_NOCTTY | O_CLOEXEC); + if (tty < 0) + return nullptr; + + static char password[PASS_MAX]; + ssize_t chars_read; + + { + auto close_tty = ScopeGuard([tty] { + close(tty); + }); + + struct termios backup { }; + if (tcgetattr(tty, &backup) < 0) + return nullptr; + + { + auto restore_termios = ScopeGuard([tty, backup] { + tcsetattr(tty, TCSAFLUSH, &backup); + }); + + struct termios noecho = backup; + noecho.c_lflag &= ~(ECHO); + noecho.c_lflag |= ICANON; + + if (tcsetattr(tty, TCSAFLUSH, &noecho) < 0) + return nullptr; + if (tcdrain(tty) < 0) + return nullptr; + + if (prompt) { + if (write(tty, prompt, strlen(prompt)) < 0) + return nullptr; + } + + chars_read = read(tty, password, sizeof(password)); + } + + write(tty, "\n", 1); + } + + if (chars_read < 0) + return nullptr; + + if (chars_read > 0 && (password[chars_read - 1] == '\n' || chars_read == sizeof(password))) + password[chars_read - 1] = '\0'; + else + password[chars_read] = '\0'; + + return password; } // https://pubs.opengroup.org/onlinepubs/9699919799/functions/sysconf.html