我实现的shell具有以下功能:
1. 支持ls,touch,wc 等外部命令
2. 支持输入输出重定向符
3. 支持管道命令
4 .支持后台作业
5. 支持cd,jobs,kill,exit等内部命令(自己还写了一个about 命令 ^ _ ^)
6. 支持对ctrl+c 和ctrl +z 信号的处理
接下来我们按照编写的步骤一一来分析:
(一)命令的解析
输入命令的解析在本程序中占到了很大的比重,虽然像这种解析普通命令的程序(正则表达式太难了。。)的解释器难度不大,但是健壮性和全面性还是需要周全考虑的。
这里采用了分段解析,先除去起始空格,制表符等,并以此和一些‘|’,‘<’为分割界限来解析命令至COMMAND结构体。直接看代码吧,注释很详细!
- /*
- * 解析命令
- * 成功返回解析到的命令个数,失败返回-1
- */
- int parse_command(void)
- {
- /* cat < test.txt | grep -n public > test2.txt & */
- if (check("\n"))
- return 0;
- /* 判断是否内部命令并执行它 */
- if (builtin())
- return 0;
- /* 1、解析第一条简单命令 */
- get_command(0);
- /* 2、判定是否有输入重定向符 */
- if (check("<"))
- getname(infile);
- /* 3、判定是否有管道 */
- int i;
- for (i=1; i<PIPELINE; ++i)
- {
- if (check("|"))
- get_command(i);
- else
- break;
- }
- /* 4、判定是否有输出重定向符 */
- if (check(">"))
- {
- if (check(">"))
- append = 1;
- getname(outfile);
- }
- /* 5、判定是否后台作业 */
- if (check("&"))
- backgnd = 1;
- /* 6、判定命令结束‘\n’*/
- if (check("\n"))
- {
- cmd_count = i;
- return cmd_count;
- }
- else
- {
- fprintf(stderr, "Command line syntax error\n");
- return -1;
- }
- }
- /*
- * 解析简单命令至cmd[i]
- * 提取cmdline中的命令参数到avline数组中,
- * 并且将COMMAND结构中的args[]中的每个指针指向这些字符串
- */
- void get_command(int i)
- {
- /* cat < test.txt | grep -n public > test2.txt & */
- int j = 0;
- int inword;
- while (*lineptr != '\0')
- {
- /* 去除空格 */
- while (*lineptr == ' ' || *lineptr == '\t')
- lineptr++;
- /* 将第i条命令第j个参数指向avptr */
- cmd[i].args[j] = avptr;