The problem with your code is that fgets is taking the first 8 characters off the input and ignoring the rest. Obviously, if you are inviting a password you don't want to ignore any input! You might want to do something a little more fancy to ensure that you capture the full input.
My first two tries at answering this were wrong. Thanks to wildplasser for holding my feet to the fire.
So, the hack answer is: use a really big buffer. fgets is probably your easier solution there.
Alternatively, you could allocate memory dynamically as your input string exceeds your buffer.
But, just for fun, here is an implementation that breaks us out of the "line buffer" trap that I wasn't aware getchar was in.
For this, I leveraged a very beautiful comment here: getchar() and stdin
PS: Ok, Ok, I tested it this time. It works. On my Mac.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
int main(void)
{
int c, i;
char buffer[9];
struct termios tty_opts_default, tty_opts_raw;
if (!isatty(STDIN_FILENO)) {
printf("Error: stdin is not a TTY\n");
return 1;
}
/* save tty settings for later. */
tcgetattr(STDIN_FILENO, &tty_opts_default);
/* put tty settings into raw mode. */
cfmakeraw(&tty_opts_raw);
tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_raw);
/* NOW we can grab the input one character at a time. */
c = getchar();
while (i < 8 && c != EOF && c != '\n' && c != '\r') {
/* Since we are collecting a pwd, we might want to enforce other
password logic here, such as no control characters! */
putchar('*');
buffer[i++] = c;
c = getchar();
}
buffer[i] = '\0';
/* Restore default TTY settings */
tcsetattr(STDIN_FILENO, TCSANOW, &tty_opts_default);
/* Report results to user. */
printf("\nPassword received.\n");
printf("(It was '%s' -- don't tell anyone! Quick! Hide the terminal!)\n", buffer);
return 0;
}