I have customized the getpass() as follows:
char* my_getpass(const char* str) {
struct termios oflags, nflags;
static char passwd[64];
/* disabling echo */
tcgetattr(fileno(stdin), &oflags);
nflags = oflags;
nflags.c_lflag &= ~ECHO;
nflags.c_lflag |= ECHONL;
tcsetattr(fileno(stdin), TCSANOW, &nflags);
printf(str);
fgets(passwd, sizeof(passwd), stdin);
passwd[strlen(passwd) - 1] = '\0';
/* restore terminal */
tcsetattr(fileno(stdin), TCSANOW, &oflags);
return passwd;
}
int main() {
char name[8], *pwd;
printf("Login as: ");
fgets(name, sizeof(name), stdin);
pwd = my_getpass("Password: ");
if (strcmp(pwd, "george"))
fprintf(stderr, "\nPassword incorrect\n");
else {
puts("\nCorrect Password");
FILE* fp = fopen("./passwd.txt", "w");
fprintf(fp, "user: (%s), password: (%s) \n", name, pwd);
fclose(fp);
}
}
but now the output file "password.txt" contains a carriage return in the result as
$ more passwd.txt
user: (dude
), password: (george)
which should have been as,
user: (dude), password: (george)
could anyone suggest me how to correct this bug?
fgets(passwd, sizeof(passwd), stdin);
passwd[strlen(passwd) - 1] = '\0';
This looks to me like you're trying to add a null-terminator to the string.
strlen() only works when the string already has a null terminator.
fgets() gives it a null terminator anyway.
It's not a bug, it's doing exactly what you tell it to... fgets() adds the return key to the string. So change it to this:
fgets(passwd, sizeof(passwd), stdin);
passwd[strlen(passwd) - 2] = '\0';
...to wipe out the very last character in the string, the newline.
Also: Make your buffer 4096, not 8, or someone is almost guaranteed to overflow and crash it.
1 Like
Thanks a lot for the impeccable and intuitive hint!! hats off to you "The Geek"
But a small correction is, I have to do it for the name variable inside main() instead of passwd variable in the my_getpass() function like
printf("Login as: ");
fgets(name, sizeof(name), stdin);
name[strlen(name) - 1] = '\0'; // newly added line for the bug
it then works fine and gives me the expected output.
I suspect you'll want to do both, actually, since there will be a \n on the end in both places.
This is a common enough need I usually make it a function:
void chomp(char *str)
{
int len=strlen(str);
if(len>0)
while((len>0) && isspace(str[len-1]))
str[--len]='\0';
}
then you just
fgets(buf, size, stdin);
chomp(buf);
1 Like