完成一个minishell,其中可以实现简单的命令解释,以及重定向符号功能。
首先实现命令解释的思路:
- 获取用户输入内容
- 解析获取到的内容,得到命令及其参数
- 创建子进程
- 程序替换
shell中处理外部命令是通过创建子进程后程序替换完成功能,还有一部分命令是内建命令,也就是shell自身实现的功能,比如cd。
重定向实现思路:
- 解析字符串,重定向符号前是命令及参数,后面是文件名称
- 在子进程程序替换之前,按照解析出的重定向方式打开文件
- 使用dup2(int oldfd,int newfd);将oldfd描述符对应的描述信息向newfd中拷贝一份
后面就进行程序替换即可。
具体代码如下:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
#include <ctype.h>
int main()
{
while(1)
{
printf("[wg@minihost ~]$");
fflush(stdout);
char tmp[1024] = {0};
scanf("%[^\n]%*c",tmp);
printf("[%s]\n",tmp);
//需要将整体字符串解析成 命令名称+参数 的形式
char* ptr=tmp;
int redirect_flag=0;//用来标志不同的重定向符号
char* redirect_file=NULL;
while(*ptr!='\0')
{
if(*ptr=='>')
{
redirect_flag=0;
*ptr='\0';
ptr++;
if(*ptr=='>')
{
redirect_flag=2;
*ptr='\0';
pte++;
}
while(isspace(*ptr) && *ptr!='\0')
ptr++;
redirect_file=ptr;
while(!isspace(*ptr) && *ptr!='\0')
ptr++;
ptr='\0';
ptr++;
continue;
}
ptr++;
}
ptr=tmp;
char* argv[32]={NULL};
int argc=0;
while(*ptr!='\0')
{
if(!isspace(*ptr))
{
argv[argc]=ptr;
argc++;
while(!issapce(*ptr) && *ptr!='\0')
ptr++;
*ptr='\0';
ptr++;
continue;
}
ptr++;
}
argv[argc]=NULL;
if(!strcmp(argv[0],"cd"))
{
chdir(argv[1];
}
int pid=fork();
if(pid==0)
{
int fd=1;
if(redirect_flag==1)
{
fd=open(redirect_file,O_CREAT|O_WRONLY|O_TRUNC,0664);
}
else if(redirect_flag==2)
{
fd=open(redirect_file,O_CREAT|O_WRONLY|O_ADDEND,0664);
}
dup2(fd,1);
execvp(argv[0],argv);
exit(0);
}
wait(NULL);//等待子进程退出,避免僵尸进程
}
return 0;
}
运行结果:
命令解释:
重定向实现:
没有容错及自动补全等等的功能。。。