APUE fig 1.10示例代码的完善--对提示符及输入回车的优化

APUE 第3版第15页的shell2.c示例程序,运行效果如下:

 gcc ol.shell.c -o origin_shell

 ./origin_shell
% date
2015年12月13日 星期日 22时04分48秒 CST
% ^Cinterrupt
ls
Makefile getcputc.c mycat.c myls_info.c note.md origin_shell shell2.c uidgid.c
a.out hello.c myls.c myls_sort.c ol.shell.c shell1.c testerror.c
% %
couldn't execute: : No such file or directory
% ls
Makefile getcputc.c mycat.c myls_info.c note.md origin_shell shell2.c uidgid.c
a.out hello.c myls.c myls_sort.c ol.shell.c shell1.c testerror.c
%

从上述示例中可以看出,存在2个小问题:

1. 当通过ctrl+C输入中断信号时,中断捕获程序的输出语句的“%”并没有立即输出来,等到下一次回车时才输出,导致第10行有两个%%号。

2. 当出现%提示符时,直接回车,会提示如11行所示的错误。因为此时传递给execlp函数的buf内容是空的。其中问题1是出现在程序中的如下一句:

while (fgets(buf, MAXLINE, stdin) != NULL) {
}
// 即中断信号中断的是fgets函数,此时系统正在请求输入中,而中断处理程序的输出: printf("interrupt\n%% "); // 在换行之后,%并没有立即出来。如果将其修改如下, printf("interrupt\n%%\n");
// 则显示效果变成这样:
 % ^Cinterrupt
%
ls
Makefile mycat.c note.md shell2.c
a.out myls.c ol.shell.c testerror.c
getcputc.c myls_info.c origin_shell uidgid.c
hello.c myls_sort.c shell1.c

如上可见,上述增加一个'\n'后,虽然立即输出了%,但如第3行所见,光标移到%下一行了。

一个解决办法是使用fflush()函数。完整代码,新增为21-24行,以及46行:

 #include "../apue.h"
#include <sys/wait.h> static void sig_int(int); /* our signal-catching function */ int
main(void)
{
char buf[MAXLINE]; /* from apue.h */
pid_t pid;
int status; if (signal(SIGINT, sig_int) == SIG_ERR)
err_sys("signal error"); printf("%% "); /* print prompt (printf requires %% to print %) */
while (fgets(buf, MAXLINE, stdin) != NULL) {
if (buf[strlen(buf) - ] == '\n')
buf[strlen(buf) - ] = ; /* replace newline with null */ if (strlen(buf) == ) { // 此if语句用于处理直接回车
printf("%% ");
continue;
} if ((pid = fork()) < ) {
err_sys("fork error");
} else if (pid == ) { /* child */
execlp(buf, buf, (char *));
err_ret("couldn't execute: %s", buf);
exit();
} /* parent */
if ((pid = waitpid(pid, &status, )) < )
err_sys("waitpid error");
printf("%% ");
}
exit();
} void
sig_int(int signo)
{
printf(" interrupt!\n%%");
fflush(stdout); //强制输出所有stdout中的字符流
}

完善后效果如下:

 % date
2015年12月13日 星期日 22时31分53秒 CST
% ^C interrupt!
% date
2015年12月13日 星期日 22时32分15秒 CST
%
%
上一篇:一款jquery编写图文下拉二级导航菜单特效


下一篇:Ruby数组