【Linux】实现简易的shell

# 简易实现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;
}

猜你喜欢

转载自blog.csdn.net/2301_79516932/article/details/133135145
今日推荐