|
地板

楼主 |
发表于 2009-3-4 11:07:04
|
只看该作者
与终端对话(Talking to the terminal)
如果你需要阻止你程序中与用户交互的那部分不被重定向,但仍允许其作用在其他的输入或输出上,你需要把交互部分与 stdout 和 stderr 分开。你可以通过直接读写终端来做到这一点。因为 linux 天生就是一个多任务系统,经常有许多终端对其直连或通过网络连接 ,那我们如何才能发现有正确的终端可用呢?
幸运的是, linux 和 UNIX 通过提供一个特殊的设备 -- /dev/tty(这总是当前终端或登录会话),使这件事情变得容易。因为 linux 对所有的东西都认为是一个文件,所以你可以使用操作普通文件的方法来读写 /dev/tty。
测试程序:
01 #include <stdio.h>
02 #include <unistd.h>
03 #include <stdlib.h>
04
05 char *menu[] = {
06 "a - add new record",
07 "d - delete record",
08 "q - quit",
09 NULL,
10 };
11
12 int getchoice(char *greet, char *choices[], FILE *in, FILE *out);
13
14 int main()
15 {
16 int choice = 0;
17 FILE *input;
18 FILE *output;
19
20 if(!isatty(fileno(stdout))) {
21 fprintf(stderr, "you are not a terminal, OK.\\n");
22 }
23
24 input = fopen("/dev/tty", "r");
25 output = fopen("/dev/tty", "w");
26 if(!input || !output) {
27 fprintf(stderr, "Unable to open /dev/tty\\n");
28 exit(1);
29 }
30
31 do {
32 choice = getchoice("Please select an action", menu, input, output);
33 printf("You have chosen: %c\\n", choice);
34 } while(choice != 'q');
35 exit(0);
36 }
37
38 int getchoice(char *greet, char *choices[], FILE *in, FILE *out)
39 {
40 int chosen = 0;
41 int selected;
42 char **option;
43
44 do {
45 fprintf(out, "Choice: %s\\n", greet);
46 option = choices;
47
48 while(*option) {
49 fprintf(out, "%s\\n", *option);
50 option++;
51 }
52
53 do {
54 selected = fgetc(in);
55 } while(selected == '\\n');
56
57 option = choices;
58
59 while(*option) {
60 if(selected == *option[0]) {
61 chosen = 1;
62 break;
63 }
64 option++;
65 }
66 if(!chosen) {
67 fprintf(out, "Incorrect choice, select again\\n");
68 }
69
70 }while(!chosen);
71
72 return selected;
73 } 运行输出:[root@localhost C]# ./menu-2.exe > file
you are not a terminal, OK.
Choice: Please select an action
a - add new record
d - delete record
q - quit
almq #输入内容
Choice: Please select an action
a - add new record
d - delete record
q - quit
Incorrect choice, select again
Choice: Please select an action
a - add new record
d - delete record
q - quit
Incorrect choice, select again
Choice: Please select an action
a - add new record
d - delete record
q - quit
[root@localhost C]# cat file
You have chosen: a
You have chosen: q 在“运行输出”中可以看到,错误的选项输入返回的提示会直接显示出来;而正确的选项输入则被重定向到了文件 file 中。
这是因为,如果是错误的选项输入,那么经由 fprintf(out, "Incorrect choice, select again\\n"); 这个语句可以知道,输出被强制从当前的tty中输出;而正确的输入选项,则会经由 ./menu-2.exe > file 重定向到文件 file 中。
注意,在
20 if(!isatty(fileno(stdout))) {
21 fprintf(stderr, "you are not a terminal, OK.\\n");
22 } 中,这用来判断当前的标准输出是否连接一个终端上。可以做这么一个实验:
如果是在 linux 的桌面环境下开启的一个终端窗口,那么就会打印出:
you are not a terminal, OK
字样,表明当前的标准输出窗口不是一个终端。
如果在 windows 中用如 putty 这样的一个连接工具进行 ssh 连接到 linux 中,则这个提示不会出现,因为那样的连接方式所对的客户机就认为是一个终端。 |
|