而第一部分的难点则在于如何在输入密码时不回显输入的字符,这就需要更改终端的属性,涉及终端IO的编程,主要用到tcgetattr和setattr两个函数,通过取消终端的ECHO标记,即可禁用终端回显,在密码输入处理之后,要记得恢复终端原来的属性,避免影响到其它的进程。
终端IO处理大致过程如下:
struct
termios ts, ots;
/*禁用终端回显*/
ts.c_lflag
&= ~ECHO;
ts.c_lflag
|= ECHONL;
tcsetattr(STDIN_FILENO,
TCSAFLUSH, &ts);
/*在这里插入输入密码的代码 */
/*恢复终端原来的属性*/
tcsetattr(STDIN_FILENO,
TCSANOW, &ots);
实例:(为方便coding,输入与认证一同处理,使用gets存在缓冲区溢出的隐患,应使用getline或gets,使用时要注意去掉末尾的换行符)
#include
#include
#include
#include
#include
#include
#define
AUTH_SIZE 1024
int
main(int argc, char* argv[])
{
struct termios ts, ots;
char userbuf[AUTH_SIZE];
char passbuf[AUTH_SIZE];
tcgetattr(STDIN_FILENO, &ts);
ots = ts;
printf("Login:");
fflush(stdout);
gets(userbuf);
/*禁用终端回显*/
ts.c_lflag &= ~ECHO;
ts.c_lflag |= ECHONL;
tcsetattr(STDIN_FILENO, TCSAFLUSH,
&ts);
printf("Password:");
fflush(stdout);
gets(passbuf);
struct spwd *sp = getspnam(userbuf);
if(sp == NULL) {
printf("set sp
error\n");
}
/*验证用户名、密码的正确性*/
if(!strcmp(sp->sp_pwdp,
(char*)crypt(passbuf, sp->sp_pwdp))) {
printf("correct\n");
}
else {
printf("user or password
error\n");
}
/*恢复终端原来的属性*/
tcsetattr(STDIN_FILENO, TCSANOW,
&ots);
return 0;
}