linux版的.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <termios.h>
int main(int argc, char **argv)
{
char passwd[16];
char *in = passwd;
struct termios tty_orig;
char c;
tcgetattr( STDIN_FILENO, &tty_orig );
struct termios tty_work = tty_orig;
puts("Please input password:");
tty_work.c_lflag &= ~( ECHO | ICANON );
tty_work.c_cc[ VMIN ] = 1;
tty_work.c_cc[ VTIME ] = 0;
tcsetattr( STDIN_FILENO, TCSAFLUSH, &tty_work );
while (1) {
if (read(STDIN_FILENO, &c, sizeof c) > 0) {
if ('/n' == c) {
break;
}
*in++ = c;
write(STDOUT_FILENO, "*", 1);
}
}
tcsetattr( STDIN_FILENO, TCSAFLUSH, &tty_orig );
*in = '/0';
fputc('/n', stdout);
printf("Got password: %s/n", passwd);
return 0;
}
下面的那个版本有个小bug,在aix64位上,星号不是一个一个显示的,所以要加上上面的设置.
//于是完整的在linux和windows下通用的版本出来了......
#include <stdio.h>
#ifndef _WIN32 //Linux platform
#include <termio.h>
#ifndef STDIN_FILENO
#define STDIN_FILENO 0
#endif
int getch(void)
{
struct termios tm, tm_old;
int fd = STDIN_FILENO, c;
if(tcgetattr(fd, &tm) < 0)
return -1;
tm_old = tm;
cfmakeraw(&tm);
//这里要加入的设置
tm
.c_cc[ VMIN ] = 1;
tm
.c_cc[ VTIME ] = 0;
if(tcsetattr(fd, TCSANOW, &tm) < 0)
return -1;
c = fgetc(stdin);
if(tcsetattr(fd, TCSANOW, &tm_old) < 0)
return -1;
return c;
}
#else //WIN32 platform
#include <conio.h>
#endif
#define MAX_LEN 8
#define BACKSPACE 8
#define ENTER 13
#define ALARM 7
char *getPasswd(const char *prompt)
{
int i=0, ch;
static char p[MAX_LEN+1]="";
printf("%s", prompt);
while((ch = getch())!= -1 && ch != ENTER)
{
if(i == MAX_LEN && ch != BACKSPACE)
{
putchar(ALARM);
continue;
}
if(ch == BACKSPACE)
{
if(i==0)
{
putchar(ALARM);
continue;
}
i--;
putchar(BACKSPACE);
putchar(' ');
putchar(BACKSPACE);
}
else
{
p[i] = ch;
putchar('*');
i++;
}
}
if(ch == -1)
{
while(i != -1)
{
p[i--] = '/0';
}
return NULL;
}
p[i]='/0';
printf("/n");
return p;
}
int main()
{
char *pw = getPasswd("passwd:");
puts(pw);
puts("clearing the static buffer with 0 ...");
while(*pw)
{
*pw++=0;
}
pw=NULL;
return 0;
}
下面是对于关键设置的解释.就是终端属性的设置.
ONLRET 不输出回车
TERMIOS
Section: Linux Programmer's Manual (3)
Updated: 2001-12-17
Index Return to Main Contents
termios, tcgetattr, tcsetattr, tcsendbreak, tcdrain, tcflush, tcflow, cfmakeraw, cfgetospeed, cfgetispeed, cfsetispeed, cfsetospeed - 获取和设置终端属性,行控制,获取和设置波特率
#include <termios.h >
#include <unistd.h >
int tcgetattr(int fd , struct termios * termios_p );
int tcsetattr(int fd , int optional_actions , struct termios * termios_p );
int tcsendbreak(int fd , int duration );
int tcdrain(int fd );
int tcflush(int fd , int queue_selector );
int tcflow(int fd , int action );
int cfmakeraw(struct termios * termios_p );
speed_t cfgetispeed(struct termios * termios_p );
speed_t cfgetospeed(struct termios * termios_p );
int cfsetispeed(struct termios * termios_p , speed_t speed );
int cfsetospeed(struct termios * termios_p , speed_t speed );
termios 函数族提供了一个常规的终端接口,用于控制非同步通信端口。
这里描述的大部分属性有一个 termios_p 类型的参数,它是指向一个 termios 结构的指针。这个结构包含了至少下列成员:
tcflag_t
c_iflag
; /* 输入模式 */
tcflag_t
c_oflag
; /* 输出模式 */
tcflag_t
c_cflag
; /* 控制模式 */
tcflag_t
c_lflag
; /* 本地模式 */
cc_t
c_cc
[
NCCS
]; /* 控制字符 */
c_iflag 标志常量:
POSIX.1 中定义的 c_oflag 标志常量:
其余 c_oflag 标志常量定义在 POSIX 1003.1-2001 中,除非另外说明。
c_cflag 标志常量:
(POSIX 规定波特率存储在 termios 结构中,并未精确指定它的位置,而是提供了函数 cfgetispeed() 和 cfsetispeed() 来存取它。一些系统使用 c_cflag 中 CBAUD 选择的位,其他系统使用单独的变量,例如 sg_ispeed 和 sg_ospeed 。)
c_lflag 标志常量:
c_cc 数组定义了特殊的控制字符。符号下标 (初始值) 和意义为:
这 些符号下标值是互不相同的,除了 VTIME,VMIN 的值可能分别与 VEOL,VEOF 相同。 (在 non-canonical 模式下,特殊字符的含义更改为延时含义。MIN 表示应当被读入的最小字符数。TIME 是以十分之一秒为单位的计时器。如果同时设置了它们,read 将等待直到至少读入一个字符,一旦读入 MIN 个字符或者从上次读入字符开始经过了 TIME 时间就立即返回。如果只设置了 MIN,read 在读入 MIN 个字符之前不会返回。如果只设置了 TIME,read 将在至少读入一个字符,或者计时器超时的时候立即返回。如果都没有设置,read 将立即返回,只给出当前准备好的字符。) (?)
tcgetattr() 得到与 fd 指向的对象相关的参数,将它们保存于 termios_p 引用的 termios 结构中。函数可以从后台进程中调用;但是,终端属性可能被后来的前台进程所改变。
tcsetattr() 设置与终端相关的参数 (除非需要底层支持却无法满足),使用 termios_p 引用的 termios 结构。 optional_actions 指定了什么时候改变会起作用:
tcsendbreak() 传送连续的 0 值比特流,持续一段时间,如果终端使用异步串行数据传输的话。如果 duration 是 0,它至少传输 0.25 秒,不会超过 0.5 秒。如果 duration 非零,它发送的时间长度由实现定义。
如果终端并非使用异步串行数据传输, tcsendbreak() 什么都不做。
tcdrain() 等待直到所有写入 fd 引用的对象的输出都被传输。
tcflush() 丢弃要写入 引用的对象,但是尚未传输的数据,或者收到但是尚未读取的数据,取决于 queue_selector 的值:
tcflow() 挂起 fd 引用的对象上的数据传输或接收,取决于 action 的值:
打开一个终端设备时的默认设置是输入和输出都没有挂起。
波特率函数被用来获取和设置 termios 结构中,输入和输出波特率的值。新值不会马上生效,直到成功调用了 tcsetattr() 函数。
设置速度为 B0 使得 modem "挂机"。与 B38400 相应的实际比特率可以用 setserial (8) 调整。
输入和输出波特率被保存于 termios 结构中。
cfmakeraw 设置终端属性如下:
termios_p->c_iflag &= ~(IGNBRK|BRKINT|PARMRK|ISTRIP
|INLCR|IGNCR|ICRNL|IXON);
termios_p->c_oflag &= ~OPOST;
termios_p->c_lflag &= ~(ECHO|ECHONL|ICANON|
ISIG
|IEXTEN);
termios_p->c_cflag &= ~(CSIZE|PARENB);
termios_p->c_cflag |= CS8;
cfgetospeed() 返回 termios_p 指向的 termios 结构中存储的输出波特率
cfsetospeed() 设置 termios_p 指向的 termios 结构中存储的输出波特率为 speed 。取值必须是以下常量之一:
B0
B50
B75
B110
B134
B150
B200
B300
B600
B1200
B1800
B2400
B4800
B9600
B19200
B38400
B57600
B115200
B230400
零值 B0 用来中断连接。如果指定了 B0,不应当再假定存在连接。通常,这样将断开连接。 CBAUDEX 是一个掩码,指示高于 POSIX.1 定义的速度的那一些 (57600 及以上)。因此, B57600 & CBAUDEX 为非零。
cfgetispeed() 返回 termios 结构中存储的输入波特率。
cfsetispeed() 设置 termios 结构中存储的输入波特率为 speed 。如果输入波特率被设为 0,实际输入波特率将等于输出波特率。
cfgetispeed() 返回 termios 结构中存储的输入波特率。
cfgetospeed() 返回 termios 结构中存储的输出波特率。
其他函数返回:
注意 tcsetattr() 返回成功,如果任何所要求的修改可以实现的话。因此,当进行多重修改时,应当在这个函数之后再次调用 tcgetattr() 来检测是否所有修改都成功实现。
Unix V7 以及很多后来的系统有一个波特率的列表,在十四个值 B0, ..., B9600 之后可以看到两个常数 EXTA, EXTB ("External A" and "External B")。很多系统将这个列表扩展为更高的波特率。
tcsendbreak 中非零的 duration 有不同的效果。SunOS 指定中断 duration * N 秒,其中 N 至少为 0.25,不高于 0.5 。Linux, AIX, DU, Tru64 发送 duration 微秒的 break 。FreeBSD, NetBSD, HP-UX 以及 MacOS 忽略 duration 的值。在 Solaris 和 Unixware 中, tcsendbreak 搭配非零的 duration 效果类似于 tcdrain 。
stty (1), setserial (8)
This document was created by man2html , using the manual pages.
Time: 06:25:07 GMT, July 01, 2004