- 論壇徽章:
- 0
|
呵,在我的blog上寫著玩的,因為在做之前搜了一下chinaunix(習慣性動作),沒搜到,所以就貼上來了,別見笑啊,有不對的請指正,謝謝!
最近由于一個程序安全的需要,在運行程序時需要用戶輸入用戶名密碼。哎,一直沒做過在程序運行時的權限認證,以前都是通過對機器系統(tǒng)級的用戶權限控制達到權限管理的需求(事實這也是我覺得最實用,簡單的一種)。OK,不做是不可能的,有時候被迫接受別人的思想,自己的思想無法體現也是非常痛苦的啊,題外話,呵呵。切入正題。
誰規(guī)定的輸入密碼時不能顯示出來?背著點人不就行了嘛,還要給技術找麻煩,要知道做技術多辛苦啊,又累!算了,順應大眾習慣吧。本來Linux下有系統(tǒng)提供的getpass()函數,可由于寫的時候太早了(我猜的呵呵,當時可能就這需求),只支持8位字符,同時有安全隱患(溢出。琽bsolate了,可憐的孩子啊。那總該有個替換的吧?例如像getpass_new()這種的函數,K~找了半天,沒找到!郁悶。沒辦法,想辦法吧。查了點資料,最多的是用ncurses庫里的getch(),可我的是Terminal啊,盜版SecureCRT,用不成。還有兩種就差不多了,都是通過termios來控制低層。一種是通過最最最強大的函數:ioctl(),用數據struct termio設置TCGETA、TCSETA。最討厭用ioctl了!本來這函數挺簡單,可我覺得就是做OS開發(fā)的人在偷懶!你要控制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 <termios.h>
-
- 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 的文件操作模式。
哎,做技術真是苦,一個小功能浪費了半天的時間,不過還是有點成就感的,探索的過程也很美:P
[ 本帖最后由 liangtf 于 2006-6-2 17:56 編輯 ] |
|