Linux下Terminal的密码输入 |
| 作者:liangtf 来源:不详 (2006-06-13 17:49:28) |
|
作者:liangtf
呵,在我的blog上写着玩的,因为在做之前搜了一下chinaunix(习惯性动作),没搜到,所以就贴上来了,别见笑啊,有不对的请指正,谢谢!:mrgreen:
最近由于一个程序安全的需要,在运行程序时需要用户输入用户名密码。哎,一直没做过在程序运行时的权限认证,以前都是通过对机器系统级的用户权限控制达到权限管理的需求(事实这也是我觉得最实用,简单的一种)。OK,不做是不可能的,有时候被迫接受别人的思想,自己的思想无法体现也是非常痛苦的啊,题外话,呵呵。切入正题。
谁规定的输入密码时不能显示出来?背着点人不就行了嘛,还要给技术找麻烦,要知道做技术多辛苦啊,又累!算了,顺应大众习惯吧。本来Linux下有系统提供的getpass()函数,可由于写的时候太早了(我猜的呵呵,当时可能就这需求),只支持8位字符,同时有安全隐患(溢出!),obsolate了,可怜的孩子啊。那总该有个替换的吧?例如像getpass_new()这种的函数,K~找了半天,没找到啊!郁闷。没办法,想办法吧。查了点资料,最多的是用ncurses库里的getch(),可我的是Terminal啊,盗版SecureCRT,用不成。还有两种就差不多了,都是通过termios来控制低层。一种是通过最最最强大的函数:ioctl(),用数据struct termio设置TCGETA、TCSETA。最讨厌用ioctl了!本来这函数挺简单,可我觉得就是做OS开发的人在偷懒!你要控制IO的哪部分,怎么控制,都得自己去找参数,找数据结构,郁闷。嘿,终于轮到主角出场了,我觉得这个才是正道啊!猜对了,这就是termios.h里藏着的:
int tcgetattr (int __fd, struct termios *__termios_p); int tcsetattr (int __fd, int __optional_actions, __const struct termios *__termios_p);
哎,找了半天,终于找到让我一见钟情的她了~ 这个其实也是对文件(UNIX概念的文件)进行设置,应该也是调用ioctl吧?猜的,没看源码:)但起码感觉它是专门做这个的呀,看人家多专一!
查了一下,还好,tcsetattr的optional actions只有三个选择,一目了然了,当然是用Flush action(TCSAFLUSH)了。万事俱备啊!于是_fd用0(stdin),输出当然要用stderr了,action用TCSAFLUSH, termios_p只需要设置个c_lflag,和~ECHO做个&就OK了。呵,终于搞定了。源码奉上:
#include
void UserIf::Echoff(int f) { struct termios sg; tcgetattr(f, &sg); /* get settings */ sg.c_lflag &= ~ECHO; /* turn echo off */ tcsetattr(f,TCSAFLUSH,&sg); /* set settings */ }
void UserIf::Echon(int f) { struct termios sg; tcgetattr(f, &sg); /* get settings */ sg.c_lflag |= ECHO; /* turn echo on */ tcsetattr(f,TCSAFLUSH,&sg); /* set settings */ }
string UserIf::getPassword(string prompt, int n) { char c; // for read() int i; // number of input char *w; // warning on retry int f; // file descripto char *p = new char(n+2); string ret; f = 0; // Read from stdin // get password w = ""; //warning do { fputs(w, stderr); fputs(prompt.c_str(), stderr); fflush(stderr); i = 0; Echoff(f); do { /* read line, keeping n */ read(f, &c, 1); if (i < n) p[i++] = c; } while (c != '\n'); Echon(f); putc('\n', stderr); fflush(stderr); w = "(line too long)\n"; } while (p[i-1] != '\n'); p[i-1] = 0; //!!!notice ret = string(p); delete p; return ret; } /* end function getPassword */
写得有点乱,本来想用std的stream来做的,可除了最基本的功能都不太熟悉,还是改用了c 的文件操作模式。
(http://www.fanqiang.com)
|
|