前言
通过替换函数 execp使用命令行参数
命令行参数可转换为一个个指令选项
./execvp pwd->"./execvp" "pwd"
既然如此,如果能去掉前面地./execvp,那么后面的执行以及选项是不是就和命令行解释器一样
按照这个思路,下面来实现模拟命令行解释器
输入命令行参数
由于是在键盘上输入命令行参数,所以采取函数fgets,来获取命令行参数
char *fgets(char *s, int size, FILE *stream)
这里还是存在一个问题,该函数是获取所有从键盘输入的字符串,就连最后的回车也会被获取,这样就会造成,数据打印出来之后,会多出一行
所以需要将最后一个字符置为\0
linecommad[strlen(linecommand)-1]=0;
命令行切割
命令行是字符串,需要将其切割成一个个命令选项
这里采取函数 strtok
char *strtok(char *str, const char *delim);
以 为切割符,先将第一个字符放入指针数组第一个位置myargv[0]中;随后的字符通过循环依次放入数组中
"ls -l -a"->"ls""-l""-a" myargv[0]=strtok(linecommand," "); while(myargv[i++]=strtok(NULL," "));
测试是否成功
测试结果很成功,由于测试不止是一次,所以可以设置为循环,并且还需要添加一些其他的功能
改进
ls命令加颜色
先判断如果第一个字符就是 ls命令,那么就将其赋予颜色
if(myargv[0]!=NULL&&strcmp(myargv[0],"ls")==0) { myargv[i++]=(char*)"--color=auto"; }
内建(内置命令)
先观察下列指令
为什么指令没有效果呢???
先来学习什么是当前路径,当一个程序正在运行时,查看进程相关信息
先介绍这两个特别的信息exe当前进程执行的是磁盘路径下的哪个程序;cwd当前进程的工作目录
pwd指令所显示的就是当前工作目录
模拟实现的命令行解释器在cd ..时路径之所以没有发生变化是因为,进程先通过fork()创建子进程,子进程执行的cd ..,子进程也有自己的工作目录,所更改的是子进程的目录,所以并不是路径没有改变,只是没有看到而已。
为了能够看到父进程的工作目录发生改变,当命令是cd时不创建子进程,直接让命令行解释器去执行命令,而这种不需要子进程来执行的命令也称为内建/内置命令
可以进行如下操作
while(myargv[i++]=strtok(NULL," ")); if(myargv[0]!=NULL&&strcmp(myargv[0],"cd")==0) { if(myargv[1]!=NULL) { chdir(myargv[1]); } }
这里的函数chdir可以改变工作目录
int chdir(const char *path);
运行结果符合预期
总结
命令行解释器的模拟实现主要是依赖于替换函数,其他的细节也需要注意,此版本的解释器还有所欠缺,待补充的功能还有很多。