实现一个minishell
1.从标准输入获取用户的输入
2.将字符串进行解析,将获取的字符串划分为命令和参数的格式
3.创建子进程
4.进行进程替换
shell中处理命令是通过创建子进程后进程替换实现功能,但还有一部分功能使系统的内建功能,例如cd
重定向实现思路:
- 对传入的字符串进行解析,重定向符号的前是命令,重定向后是文件名称
- 在子进程程序替换之前,按照解析的重定向方向打开文件
- 使用dup2(int oldfd,int newfd);将oldfd描述符对应的描述信息向newfd中拷贝一份
代码实现:
实现一个minishell:
#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';
ptr++;
}
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;
}
在vim中写的代码,格式有点丑
pwd,ls -l等常用命令的测试
重定向测试
这个minishell还不能实现容错机制以及代码补全等功能哦