做一个简单的shell
1.首先输入一个命令,并且用一个字符数组来保存这个命令
2.按照空格解析这个字符串(如果是用空格分割开的命令的话(ls -l),将空格前后字符串分开保存在字符串数组中)
3.创建一个子进程(fork()),然后替换子进程(execvp),让父进程等待子进程的退出然后释放掉子进程的资源(wait)。
#include<stdio.h>
#include<unistd.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
int argc = 0;//用来表示存放命令数组的下标
char *argv[32];//用来存放命令的字符串数组
//处理用户输入的字符串
//如果是几个命令的组合的话(ls -l)
//这样的话,就将ls和-l分割成两个字符串分别放入如argv中。
int param(char *buff)
{
argc = 0;
if(buff == NULL)
return -1;
char* ptr = buff;//记录的是从键盘上输入的字符串的首地址
char *tmp = ptr;//记录每个字符串的起始位置
while(*ptr != '\0')
{
int status = 0;//用来表示是否执行了下面的while循环
if(*ptr == ' ')//如果遇到的是空格的话
{
//将这个空格字符变成一个'\0',表示空格前面的字符串为一个独立的字符
//比如"ls -l" ----> "ls\0""-l"将他们分成两个字符串来存放。
*ptr = '\0';
argv[argc] = tmp;
tmp = ptr + 1;//然后让tmp继续指向空格后的第一个字符
argc++;
while(*++ptr == ' ')//如果又连续空格的话,直接跳过空格,直到下一个是字符为止
{
tmp++;
status = 1;
}
}
if(status == 0)//如果执行了上面的while循环的话,代表ptr现在指向的是一个字符,所以不用再次移动,如果没有执行while循环的话,代表还在字符串中,继续向后遍历。
ptr++;
}
if(tmp != '\0')//将最后一个的字符串放入到字符数组中,比如ls经过上面的判断并没有将ls放入到字符串数组中
{
argv[argc] = tmp;
argc++;
}
argv[argc] = NULL;//如果将命令解析完成之后的话,将数组的下一个位置置空,代表命令字符串的结束。
return 0;
}
//用来执行字符串数组中的命令
int exec_cmd()
{
int pid = 0;
pid = fork();
if(pid < 0)
{
exit(0);
}
//在子进程中进行程序替换。
else if(pid == 0)
{
execvp(argv[0], argv);
exit(0);
}
//父进程在这里等待子进程的退出
int statu;
wait(&statu);
//判断代码是否是运行完毕之后退出
if(WIFEXITED(statu))
{
//将子进程的退出码,转换为文本信息打印
printf("%s\n", strerror(WEXITSTATUS(statu)));
}
return 0;
}
int main()
{
//1.获取终端输入
//2.按照空格解析
//3.创建一个子进程
// 在子进程中进行程序替换,让子进程去运行命令
//4.等待子进程退出然后父进程释放子进程的资源
while(1)
{
printf("Myshell->");
char buff[1024] = {0};
fflush(stdout);//用来刷新缓冲区的
if(scanf("%[^\n]%*c", buff)!=1)
getchar();
param(buff);
exec_cmd();
}
return 0;
}