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>;