编写shell
刺猬@http://blog.csdn.net/littlehedgehog
接着来写shell,今天来加上我们的条件判断语句if。
为了处理if的逻辑判断,我们这里把代码区域做个划分。如下举例所示:
- who
- ls -al
- if diff file1 file2
- ---------------以上是中立区 netral
- then
- ---------------want_then区(经过if条件判断以后 可能是want_then 或者 want_else)
- echo different
- ---------------then_block区
- else
- ---------------want_else区
- echo same
- ---------------else_block区
- fi
- ---------------fi是if倒着写 表示if结束了 那么我们又进入中立区了
这里有几点需要注意的是:
1、经过if判断后,if后面的条件有可能成立有可能不成立,所以我们可能想要then(want_then),也可能想要else(want_else)。
2、假如是want_else ,那么执行then后面的命令,我们以为要执行else,所以这些命令不予执行,所处状态还是want_else
3、限于程序的简陋,很多功能未实现,比如if多条件判断,比如一行多命令执行等等。
现在那就看代码吧! 注意原书中没有考虑else,这里已经添上else判断。代码中我注释很多,算是对书上代码的一个补充了。
- #include <stdio.h>
- #include <string.h>
- //#define DEBUG
- extern execute(char **);
- enum states {NEUTRAL,WANT_THEN,THEN_BLOCK,WANT_ELSE,ELSE_BLOCK};
- enum result {SUCCESS,FAIL};
- static int if_state=NEUTRAL;
- static int if_result=SUCCESS;
- static int pro_state=0;
- void die(char *err)
- {
- fprintf(stderr,"fatal error :%s/n",err);
- exit(1);
- }
- int syn_err(char *err)
- {
- if_state=NEUTRAL; //出事前我们需要重新设置中立状态
- fprintf(stderr,"sysntax error : %s/n",err);
- return -1;
- }
- int is_ctlcmd(char *str)
- {
- if(strcmp(str,"if")==0||strcmp(str,"then")==0||strcmp(str,"else")==0||strcmp(str,"fi")==0)
- return 1;
- return 0;
- }
- /* 这个函数主要处理语法分析(目前仅支持if) */
- int do_ctlcmd(char **argv)
- {
- int ret=-1;
- char *cmd=argv[0];
- if(strcmp(cmd,"if")==0) //如果当前命令是if
- {
- if(if_state!=NEUTRAL) //暂时不支持命令嵌套
- {
- ret=-1;
- syn_err("if unexpected ");
- }
- else
- {
- #ifndef DEBUG
- pro_state=execute(argv+1); //执行if后面的语句 比如 if diff file1 file2
- #else
- pro_state=0;
- #endif
- if_state=pro_state?WANT_ELSE:WANT_THEN; //注意是0为成功 非0失败
- if_result=pro_state?FAIL:SUCCESS;
- ret=0;
- }
- }
- else if (strcmp(cmd,"then")==0) //如果当前命令是then 单独一行
- {
- if(if_state==WANT_THEN)
- {if_state=THEN_BLOCK;ret=0;}
- else if(if_state!=WANT_ELSE) //当前命令是then 那么state要么是WANT_THEN 要么是WANT_ELSE
- syn_err("then unexpected ");
- }
- else if (strcmp(cmd,"else")==0) //单独一行
- {
- if(if_state==WANT_ELSE)
- {if_state==ELSE_BLOCK;ret=0;}
- else if(if_state!=THEN_BLOCK) //既然进入else 那么要么是THEN_BLOCK 要么是WANT_ELSE
- syn_err("syntax error ");
- }
- else if (strcmp(cmd,"fi")==0)
- {
- if(if_state==NEUTRAL)
- syn_err("syntax error :");
- if_state==NEUTRAL;
- ret=0;
- }
- else
- die("process error! not your problem");
- return ret;
- }
- /* 检查当前 是否能执行语句
- * 返回值 1:能执行 0:不能执行
- */
- int check_execute()
- {
- int ret=1;
- switch(if_state)
- {
- case WANT_THEN:
- case WANT_ELSE:
- break;
- case THEN_BLOCK:
- if(if_result==FAIL) //进入了then 但是if中间的判断是 if(...) 为假 所以我们不能执行THEN_BLOCK
- ret=0;
- break;
- case ELSE_BLOCK:
- if (if_result==SUCCESS) //同样 不能执行ELSE_BLOCK
- ret=0;
- break;
- }
- return ret;
- }
- int process(char *argv[])
- {
- int ret=0;
- if(!argv[0])
- ret=0;
- else if (is_ctlcmd(argv[0])) //检查是不是命令 比如if
- ret=do_ctlcmd(argv);
- else if (check_execute()) //检查是否能运行
- #ifndef DEBUG
- ret=execute(argv);
- #else
- ret=0;
- #endif
- return ret;
- }
编译时,将《编写shell(一)》中的代码和此代码一起编译:
gcc -o target shell1.c shell2.c