POSIX.1定义了11个在输入是做特殊处理的字符。实现定义了另外一些特殊字符。下表摘要列出了这些特殊字符。
POSIX.1允许禁用这些字符。若将c_cc数组中的某项设置为_POSIX_VDISABLE的值,则禁用相应的特殊字符。可以使用
tcsetattr函数进行操作。
使用函数tcgetattr和tcsetattr可以获得或设置termios结构。
#include<termios.h>
int tcgetattr(int filedes, struct termios *termptr);
int tcsetattr(int filedes, int opt, const struct termios *termptr);
//这两个函数若成功则返回0,出错则返回-1.
因为这两个函数只对终端设备进行操作,所以若filedes并不引用一个终端设备则出错返回-1,errno设置为ENOTTY。
opt参数使我们可以指定在什么时候新的终端属性才起作用。使用以下的常量:
TCSANOW 更改立即发生。
TCSADRAIN 发送了所有输出后更改才发生。若更改输出参数则应使用此选项。
TCSAFLUSH 发送了所有输出后更改才发生。更进一步,在更改发生时未读的所有输入数据都被删除。
实践:程序中禁用了终端信号。
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
int main(void){
struct termios term;
long vdisable;
if(isatty(STDIN_FILENO) == 0){
printf("STDIN is not a terminal device.\n");
return -1;
}
if((vdisable = fpathconf(STDIN_FILENO, _PC_VDISABLE)) < 0){
perror("fpathconf");
return -1;
}
if(tcgetattr(STDIN_FILENO, &term) < 0){
perror("tcgetattr");
return -1;
}
term.c_cc[VINTR] = vdisable;
if(tcsetattr(STDIN_FILENO, TCSAFLUSH, &term) < 0){
perror("tcsetattr");
return -1;
}
return 0;
}
执行结果:
yan@vm:~/apue$ ping 192.168.18.249
PING 192.168.18.249 (192.168.18.249) 56(84) bytes of data.
64 bytes from 192.168.18.249: icmp_req=1 ttl=64 time=4.65 ms
64 bytes from 192.168.18.249: icmp_req=2 ttl=64 time=0.464 ms
64 bytes from 192.168.18.249: icmp_req=3 ttl=64 time=0.803 ms
^C
--- 192.168.18.249 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2002ms
rtt min/avg/max/mdev = 0.464/1.973/4.653/1.900 ms
yan@vm:~/apue$ ./a.out
yan@vm:~/apue$ ping 192.168.18.249
PING 192.168.18.249 (192.168.18.249) 56(84) bytes of data.
64 bytes from 192.168.18.249: icmp_req=1 ttl=64 time=0.456 ms
64 bytes from 192.168.18.249: icmp_req=2 ttl=64 time=0.555 ms
^C^C^C64 bytes from 192.168.18.249: icmp_req=3 ttl=64 time=0.482 ms
^C^C^C64 bytes from 192.168.18.249: icmp_req=4 ttl=64 time=0.774 ms
^C^C^C^C64 bytes from 192.168.18.249: icmp_req=5 ttl=64 time=0.479 ms
可以看到在执行程序前可以使用ctrl+c取消程序,但是执行程序后,ctrl+c已经被禁用了。关闭终端后再次打开,恢复原来的设置,
ctrl+c再次能使用。因为重新打开终端后,termios中的值变成默认值。
tcsetattr设置的选项可以使用stty -a命令查看:
yan@yanwenjie-vm:~/apue$ stty -a
speed 9600 baud; rows 24; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
yan@yan-vm:~/apue$ ./a.out
yan@yan-vm:~/apue$ stty -a
speed 9600 baud; rows 24; columns 80; line = 0;
intr = <undef>; quit = ^\; erase = ^H; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
上述中,intr = ^C; 变成了intr = <undef>;