su: Read password from /dev/tty instead of stdin
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
apio 2023-10-14 20:47:56 +02:00
parent c323a812a5
commit 56eb0c8130
Signed by: apio
GPG Key ID: B8A7D06E42258954

View File

@ -1,3 +1,4 @@
#include <fcntl.h>
#include <os/ArgumentParser.h>
#include <pwd.h>
#include <signal.h>
@ -7,10 +8,11 @@
#include <unistd.h>
static struct termios orig;
static int fd = -1;
void restore_terminal()
{
tcsetattr(STDIN_FILENO, TCSANOW, &orig);
tcsetattr(fd, TCSANOW, &orig);
}
void signal_handler(int signo)
@ -21,21 +23,25 @@ void signal_handler(int signo)
char* getpass()
{
if (!isatty(STDIN_FILENO))
FILE* f = fopen("/dev/tty", "r");
if (!f)
{
// FIXME: Just read from /dev/tty (the controlling terminal). Problem: that doesn't exist yet.
fprintf(stderr, "error: password must be read from a terminal!");
perror("Failed to open /dev/tty");
return nullptr;
}
tcsetpgrp(STDIN_FILENO, getpgid(0));
fd = fileno(f);
tcsetpgrp(fd, getpgid(0));
fputs("Password: ", stdout);
fflush(stdout);
if (tcgetattr(STDIN_FILENO, &orig) < 0)
if (tcgetattr(fd, &orig) < 0)
{
perror("tcgetattr");
fclose(f);
fd = -1;
return nullptr;
}
@ -51,18 +57,23 @@ char* getpass()
struct termios tc = orig;
tc.c_lflag &= ~ECHO;
if (tcsetattr(STDIN_FILENO, TCSANOW, &tc) < 0)
if (tcsetattr(fd, TCSANOW, &tc) < 0)
{
perror("tcsetattr");
fclose(f);
fd = -1;
return nullptr;
}
static char buf[BUFSIZ];
char* rc = fgets(buf, sizeof(buf), stdin);
char* rc = fgets(buf, sizeof(buf), f);
restore_terminal();
putchar('\n');
fclose(f);
fd = -1;
if (!rc)
{
perror("fgets");