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
%
%
APUE fig 1.10示例代码的完善--对提示符及输入回车的优化的更多相关文章
- redis 学习笔记(2)-client端示例代码
redis提供了几乎所有主流语言的client,java中主要使用二种:Jedis与Redisson 一.Jedis的使用 <dependency> <groupId>redi ...
- c# 使用hook来监控鼠标键盘事件的示例代码
如果这个程序在10几年前,QQ刚刚兴起的时候,有了这个代码,就可实现盗号了. 当然使用钩子我们更多的是实现"全局快捷键"的需求. 比如 程序最小化隐藏后要"某快捷键&qu ...
- Ajax原理,技术封装与完整示例代码
在做项目和学习的时候,经常用到Ajax的相关技术,但是这方面的技术总是运用的不是十分好,就寻找相关博客来学习加深Ajax技术相关. 一.Ajax简介 二.同步.异步传输区别 2.1 异步传输 2.2 ...
- ActiveMQ笔记(1):编译、安装、示例代码
一.编译 虽然ActiveMQ提供了发布版本,但是建议同学们自己下载源代码编译,以后万一有坑,还可以尝试自己改改源码. 1.1 https://github.com/apache/activemq/r ...
- php示例代码之类似于C#中的String.Format方法
php示例代码之类似于C#中的String.Format方法 原文来自于 http://stackoverflow.com/questions/1241177/c-string-format-equ ...
- C# 6新特性及示例代码
今天推荐的其实是一个Github开源项目,不过这个开源项目是专门介绍C# 6的最新特性,并给出了示例代码. 我们知道,微软即将发布Windows 10和Visual Studio 2015,在VS20 ...
- C# WebSocket 服务端示例代码 + HTML5客户端示例代码
WebSocket服务端 C#示例代码 using System; using System.Collections.Generic; using System.Linq; using System. ...
- Swift常用语法示例代码(二)
此篇文章整理自我以前学习Swift时的一些练习代码,其存在的意义多是可以通过看示例代码更快地回忆Swift的主要语法. 如果你想系统学习Swift或者是Swift的初学者请绕路,感谢Github上Th ...
- Swift常用语法示例代码(一)
此篇文章整理自我以前学习Swift时的一些练习代码,其存在的意义多是可以通过看示例代码更快地回忆Swift的主要语法. 如果你想系统学习Swift或者是Swift的初学者请绕路,感谢Github上Th ...
随机推荐
- Visaul Studio 常用快捷键的动画演示
从本篇文章开始,我将会陆续介绍提高 VS 开发效率的文章,欢迎大家补充~ 在进行代码开发的时候,我们往往会频繁的使用键盘.鼠标进行协作,但是切换使用两种工具会影响到我们的开发速度,如果所有的操作都可以 ...
- Python标准模块--ContextManager
1 模块简介 在数年前,Python 2.5 加入了一个非常特殊的关键字,就是with.with语句允许开发者创建上下文管理器.什么是上下文管理器?上下文管理器就是允许你可以自动地开始和结束一些事情. ...
- springMVC初探--环境搭建和第一个HelloWorld简单项目
注:此篇为学习springMVC时,做的笔记整理. MVC框架要做哪些事情? a,将url映射到java类,或者java类的方法上 b,封装用户提交的数据 c,处理请求->调用相关的业务处理—& ...
- HTML5笔记2——HTML5音/视频标签详解
音视频的发展史 早期:<embed>+<object>+文件 问题:不是所有浏览器都支持,而且embed不是标准. 现状:Realplay.window media.Quick ...
- form表单验证-Javascript
Form表单验证: js基础考试内容,form表单验证,正则表达式,blur事件,自动获取数组,以及css布局样式,动态清除等.完整代码如下: <!DOCTYPE html PUBLIC &qu ...
- Set up VLAN (802.1q) tagging on a network interface?
SOLUTION VERIFIED October 13 2015 KB39674 KB741413 environment Red Hat Enterprise Linux 4 Red Hat En ...
- SpringMvc中初始化参数绑定
初始化参数绑定与类型转换很类似,初始化绑定时,主要是参数类型 ---单日期 在处理器类中配置绑定方法 使用@InitBinder注解 在这里首先注册一个用户编辑器 参数一为目标类型 proper ...
- mono3.2和monodevelop4.0在ubuntu12.04上两天的苦战
首先第一步是设置ubuntu server 12.04版更新源,推荐中科大的比较快:deb http://debian.ustc.edu.cn/ubuntu/ precise main multive ...
- 【腾讯Bugly干货分享】微信iOS SQLite源码优化实践
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57b58022433221be01499480 作者:张三华 前言 随着微信iO ...
- ECMAScript 6 扫盲
ECMAScript 6 目前基本成为业界标准,它的普及速度比 ES5 要快很多,主要原因是现代浏览器对 ES6 的支持相当迅速,尤其是 Chrome 和 Firefox 浏览器,已经支持 ES6 中 ...