minishell.c代码:
#include<stdio.h> #include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include <sys/wait.h>
//各种头文件的引用,这里不做详细说明
int main(int argc,char* argv[])//命令行运行参数个数,和字符串指针
{
while(1)//一直循环,验证shell
{
char buf[1024]={0};//申请一个1024字节的数组空间来存放输入
printf("[user@host path]$ ");//打印
fflush(stdout);//强制刷新,让前面的打印输出到标准输出
fgets(buf,1023,stdin);
//fgets标准输入流函数,从stdin里输入,存放到buf数组中,不超过1023字节
buf[strlen(buf)-1]='\0';
//将buf的最后一个字节设为'\0',这样就可以保证不会将回车作为最后一个识别到的输入。因为我们都习惯输入完命令之后按一下回车。
char *ptr=buf;//定义一个指针,指向存放输入命令数组的首地址
char myargv[32][32];//定义一个二维数组来存放输入命令
int myargc=0;//定义一个整形变量来存放输入命令的个数
while(*ptr!='\0')//循环识别输入命令,当识别到的不是'\0',就一直向下寻找
{
if(!isspace(*ptr))//不是指向空格
{
int count=0;//定义count来计算一个命令的长度
while(*ptr!='\0' && !isspace(*ptr)){
myargv[myargc][count]=*ptr;//将识别到不是'\0'也不是空格的内容放到第几个命令的第几个参数
count++;//count加一来计算一个命令的长度
ptr++;//指针向下移动
}
myargc++;//,计算完了一个命令的长度,命令的个数加一
}
ptr++;//是空格一直向下移动
}
char* arg[32]={NULL};
int i=0;
for(i=0;i<32;i++)
{
arg[i]=myargv[i];
}
arg[myargc]=NULL;
//execvp参数类型是指针数组,而这里是二维数组,所以需要转换一下
pid_t pid=fork();//生成一个子进程,让子进程来调用execvp函数
if(pid<0)
{
continue;//这里不能return,需要continue继续执行
}
else if(pid==0)
{
execvp(arg[0],arg);
//调用execvp替换函数,第一个参数是第一个命令,因为基本上第一个命令就是要执行的命令,后面执行的命令都是命令参数。因为是execvp所以第一个参数可以不需要带路径。
exit(10);//exit函数退出
}
wait(NULL);//父进程等待子进程退出,避免形成僵尸进程
}
return 0;
}