# 简易实现shell
显示用户名
printf("[Hayaizo@mudan currpath]$ ");
切割字符串
int split(char* commandstr,char* argv[])
{
assert(commandstr);
assert(argv);
argv[0]=strtok(commandstr,SEP);
if(argv[0]==NULL) return -1;//异常了
int i=1;
while(argv[i++]=strtok(NULL,SEP));
return 0;//正常退出,切割完毕
}
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/wait.h>
#include<stdlib.h>
#define MAX 1024
#define ARGC 64
#define SEP " "
int split(char* commandstr,char* argv[])
{
assert(commandstr);
assert(argv);
argv[0]=strtok(commandstr,SEP);
if(argv[0]==NULL) return -1;//异常了
int i=1;
while(argv[i++]=strtok(NULL,SEP));
return 0;//正常退出,切割完毕
}
void debugPrint(char *argv[])
{
for(int i = 0; argv[i]; i++)
{
printf("%d: %s\n", i, argv[i]);
}
}
int main(void)
{
while(1)
{
char commandstr[MAX]={
0};
char* argv[ARGC]={
NULL};
printf("[Hayaizo@mudan currpath]$ ");
//fflush(stdout);//刷新缓冲区
char* s=fgets(commandstr,sizeof(commandstr),stdin);//读取字符串
assert(s);
(void)s;
commandstr[strlen(commandstr)-1]='\0';
printf("%s",commandstr);
int n=split(commandstr,argv);
//debugPrint(argv);
//sleep(10);
}
return 0;
}
进行进程替换
//创建子进程
pid_t id=fork();
if(id==0)
{
//当前为子进程
execvp(argv[0],argv);
exit(1);
}
//走到这里为父进程
int status=0;
pid_t ret=waitpid(id,&status,NULL);
完善cd指令
**chdir
**用于打开文件的系统接口。
if(strcmp(argv[0],"cd")==0)
{
if(argv[1]!=NULL)
{
chdir(argv[1]);
}
continue;
}
export添加环境变量
**putenv
**是一个用于添加环境变量的系统接口。
if(strcmp(argv[0],"export")==0)
{
if(argv[1]!=NULL)
{
strcpy(myenv[env_index],argv[1]);
putenv(myenv[env_index++]);
}
continue;
}
echo查询环境变量
if (strcmp(argv[0],"echo")==0)
{
const char* target_env=NULL;
if(argv[1][0]=='$')
{
if(argv[1][1]=='?')
{
printf("%d\n",last_exit);
continue;
}
else target_env=getenv(argv[1]+1);
if(target_env!=NULL) printf("%s=%s\n",argv[1]+1,target_env);
continue;
}
}
添加字体颜色
在命令后面添加这个代码
--color=auto
即可自动显示颜色
if(strcmp(argv[0],"ls")==0)
{
//添加颜色
int pos=0;
while(argv[pos++]);
argv[pos++]=(char*)"--color=auto";
argv[pos]=NULL;
}
总代码
#include<stdio.h>
#include<sys/types.h>
#include<unistd.h>
#include<string.h>
#include<assert.h>
#include<sys/wait.h>
#include<stdlib.h>
#define MAX 1024
#define ARGC 64
#define SEP " "
int split(char* commandstr,char* argv[])
{
assert(commandstr);
assert(argv);
argv[0]=strtok(commandstr,SEP);
if(argv[0]==NULL) return -1;//异常了
int i=1;
while(argv[i++]=strtok(NULL,SEP));
return 0;//正常退出,切割完毕
}
void debugPrint(char *argv[])
{
for(int i = 0; argv[i]; i++)
{
printf("%d: %s\n", i, argv[i]);
}
}
int main(void)
{
int last_exit = 0;//退出码
char myenv[32][256];//环境变量
int env_index = 0;//记录到了第几个环境变量
while(1)
{
char commandstr[MAX]={
0};
char* argv[ARGC]={
NULL};
printf("[Hayaizo@mudan currpath]$ ");
//fflush(stdout);//刷新缓冲区
char* s=fgets(commandstr,sizeof(commandstr),stdin);//读取字符串
assert(s);
(void)s;
commandstr[strlen(commandstr)-1]='\0';
//printf("%s",commandstr);
int n=split(commandstr,argv);
//debugPrint(argv);
if(strcmp(argv[0],"cd")==0)
{
if(argv[1]!=NULL)
{
chdir(argv[1]);
}
continue;
}else if(strcmp(argv[0],"export")==0)
{
if(argv[1]!=NULL)
{
strcpy(myenv[env_index],argv[1]);
putenv(myenv[env_index++]);
}
continue;
}else if (strcmp(argv[0],"echo")==0)
{
const char* target_env=NULL;
if(argv[1][0]=='$')
{
if(argv[1][1]=='?')
{
printf("%d\n",last_exit);
continue;
}
else target_env=getenv(argv[1]+1);
if(target_env!=NULL) printf("%s=%s\n",argv[1]+1,target_env);
continue;
}
}
if(strcmp(argv[0],"ls")==0)
{
//添加颜色
int pos=0;
while(argv[pos++]);
argv[pos++]=(char*)"--color=auto";
argv[pos]=NULL;
}
//创建子进程
pid_t id=fork();
if(id==0)
{
//当前为子进程
execvp(argv[0],argv);
exit(1);
}
//走到这里为父进程
int status=0;
pid_t ret=waitpid(id,&status,NULL);
//记录退出码
if(ret>0)
{
last_exit=WEXITSTATUS(status);
}
}
return 0;
}