PART 2: 使 Shell 能读取命令
来源:互联网 发布:配电网数据采集与监控 编辑:程序博客网 时间:2024/04/30 10:56
这篇文章是《动手写 Shell》系列文章的第 <2> 篇。上篇文章中,我们已经完成了我们动手 Shell 的第一步:Shell 的提示符。在这篇文章中,我们开始使得我们的 Shell 能够开始读取命令,并且做简单的分词,将命令与参数分开。
读取命令
0x00 readline 库的使用
在实现读取命令的方法中我们所使用到的库是 readline
,其实我们使用 fgets()
方法也能达到目的,但是如果使用 fgets()
的话如果我们在使用 Shell 时输入错了命令不能通过退格键来撤销,因为 fgets()
是按字符进行读取的。
0x01 安装 readline 库
sudo apt-get install libreadline-dev
0x02 使用 readline 库
如果我们的程序中使用到了该库,需要在编译代码时需要链接到 libreadline
例:
gcc -o test test.o -I /usr/include -lreadline
处理命令
0x00 实现思路
对于一条命令
cmd para1 para2 […… paraN]
我们希望它能被识别成为:
命令: cmd
参数0: cmd
参数1: para1
参数2: para2
……
参数N: paraN
其实思路也是很简单:
我们需要一个command
指针来存储命令,一个数组来存储命令。
需要两个指针来顺着我们的整条指令来移动,来获取到每一个命令或者参数。
一开始时:
两个指针 *start
, *end
都指向指令的开头
如果 *start
, *end
指向空格,自动向后移动
定义一个计数器 count
,然后 *end
指针开始向后移动,直到碰到空格或者换行符或者结束符
如果 count
为0,说明当前处理的是命令,定一个临时指针 *p
,沿着 *end
向 *start
移动,将其赋给 *command
和 parameter[0]
,count
+ 2.
如果 *end
为换行符或终止符则停止,否则,将 *end
赋给 *start
,然后 *end
按上述方式继续向后移动,直到遇到空格,将 *start
赋给 parameters[count-1]
, count
+ 1.
重复以上工作,直到 *end
遇到终止符 \0
或者换行符 \n
0x01 实现代码
#include "lshell.h"#include <readline/readline.h>#include <readline/history.h>int read_command(char **command, char **parameters, char *prompt){ free(buffer); buffer = readline(prompt); if(feof(stdin)) { printf("\n"); exit(0); } if(buffer[0] == '\0') { return -1; } int count = 0; char *start, *end; int isFinished = 0; start = end = buffer; while(isFinished == 0) { while((*start == ' ' && *end == ' ') || (*start == '\t' && *end == '\t')) { start++; end++; } if(*end == '\0' || *end == '\n') { if(count == 0) { return -1; } break; } while(*end != '\0' && *end != '\n' && *end != ' ') { end++; } if(count == 0){ char *p = end; *command = start; while(p != start && *p != '/'){ p--; } if(*p == '/'){ p++; } parameters[0] = p; count += 2;#ifdef DEBUG printf("\ncommand:%s\n", *command);#endif // DEBUG } else if(count <= MAX_ARGS){ parameters[count-1] = start; count++; } else{ break; } if(*end = '\0' || *end == '\n'){ *end = '\0'; isFinished = 1; } else{ *end = '\0'; end++; start = end; } } parameters[count-1] = NULL;#ifdef DEBUG printf("input analysis:\n"); printf("command:[%s]\ncommand:[%s]\nparameters:\n",*command,parameters[0]); int i; for(i=0;i<count-1;i++) printf("[%s]\n",parameters[i]);#endif return count;}
完整代码详见:https://github.com/luoyhang003/linux_kernel_expriment/tree/master/exp2
本文的版权归作者 罗远航 所有,采用 Attribution-NonCommercial 3.0 License。任何人可以进行转载、分享,但不可在未经允许的情况下用于商业用途;转载请注明出处。感谢配合!
- PART 2: 使 Shell 能读取命令
- 使P2P能进行交互操作: Jxta命令shell
- 使 P2P 能进行交互操作: Jxta 命令 shell
- rtems网络移植-网络shell命令介绍和使能
- Shell命令读取IP地址
- shell命令一行一行读取文件数据
- Shell命令读取数据与输出数据
- VC++_读取SHELL命令结果
- Shell实现(三)读取命令的实现
- Shell编程基础 part 2/2
- 不用ReadFile读取文件(Part 2)
- Shell编程基础 part 1/2
- 【linux脚本】读取命令序列输出&&子shell&&父shell
- 能提高效率的svn命令-shell 进入全屏
- shell命令 2>&1
- shell基本命令2
- shell命令 2>&1
- 常用Shell命令2
- 使用tcmalloc提升mysql性能
- java 动态规划判断股票最大盈利问题
- 274. H-Index
- 指针数组和数组指针的区别
- hadoop学习序曲之java基础篇--java多线程
- PART 2: 使 Shell 能读取命令
- Shiro整合SSH开发4:Realm授权,perms过滤器测试和使用方法讲述
- Android Volley详细解析(一):Volley基本用法
- swift 网络请求&json解析
- 修改Ubuntu中locale转中文为英文
- OSG学习笔记5—使用开关节点
- Mac电脑快捷键
- Ubuntu 16.04安装和配置Sublime Text 3
- Memcache工作原理