rdo/readpassphrase.h
sw1tchbl4d3 fd4ee6a712 Use the correct file descriptor for printing
Before we used printf("\n"); to simulate the enter key the user pressed,
which prints to normal stdout, which could have been redirected.
Now we directly write to the found TTY.

We also close the TTY file descriptor on every code path now.
2022-05-06 08:19:18 +02:00

63 lines
1.3 KiB
C

#include <stdio.h>
#include <unistd.h>
#include <termios.h>
#include <fcntl.h>
char* readpassphrase(const char* prompt, char* buf, size_t bufsz) {
char stdin_path[256];
char tty_link_path[256];
int n;
int ttyfd = -1;
struct termios term;
for (int i = 0; i < 3; i++) {
if (tcgetattr(i, &term) == 0) {
ttyfd = i;
break;
}
}
if (ttyfd < 0)
return NULL;
snprintf(tty_link_path, sizeof(tty_link_path), "/proc/self/fd/%d", ttyfd);
n = readlink(tty_link_path, stdin_path, sizeof(stdin_path));
if (n < 0)
return NULL;
stdin_path[n] = '\0';
int fd = open(stdin_path, O_RDWR);
if (fd < 0)
return NULL;
term.c_lflag &= ~ECHO;
tcsetattr(ttyfd, 0, &term);
term.c_lflag |= ECHO;
if (write(fd, prompt, strlen(prompt)) < 0) {
tcsetattr(ttyfd, 0, &term);
close(fd);
return NULL;
}
n = read(fd, buf, bufsz);
if (n < 0) {
tcsetattr(ttyfd, 0, &term);
n = write(fd, "\n", 1);
close(fd);
return NULL;
}
buf[n-1] = '\0';
// NOTE: As we disabled echo, the enter sent by the user isn't displayed, so we resend it.
n = write(fd, "\n", 1);
close(fd);
tcsetattr(ttyfd, 0, &term);
return buf;
}