Linux——创建my_bash(命令解释器)项目+代码

目录

1、bash介绍

 2、命令的分类

3、项目框架

4、my_bash项目代码

5、项目运行结果

6、mybin代码

7、关于修改颜色的printf命令

1、bash介绍

  • bash是一个命令处理器,通常运行于文本窗口中,并能执行用户直接输入的命令。bash还能从文件中读取命令,这样的文件称为脚本。和其他Unix shell 一样,它支持文件名替换(通配符匹配)、管道here文档、命令替换、变量,以及条件判断和循环遍历的结构控制语句。包括关键字、语法在内的基本特性全部是从sh借鉴过来的。其他特性,例如历史命令,是从cshksh借鉴而来。总的来说,bash虽然是一个满足POSIX规范的shell,但有很多扩展。
  • bash:命令解释器。

bash自身fork复制一份,子进程替换一份。

 2、命令的分类

①内置命令:cd exit等;

②普通命令: ls pwd cp ps等,通过which可以找到。

bash :复制自身,复制出来一个子进程, 替换ps/ls

3、项目框架

4、my_bash项目代码

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<sys/wait.h>
#include<sys/types.h>
#include<pwd.h>
#define PATH_BIN "/home/stu/1020/mybin"//自己的文件路径


#define ARG_MAX 10

void print_info()
{
    char *user_str="$";
    int user_id=getuid();
    if(user_id==0)
    {
        user_str="#";
    }
    struct passwd*ptr=getpwuid(user_id);
    if(ptr==NULL)
    {
        printf("my_bash1.0>>  ");
        fflush(stdout);
        return;
    }
    char hostname[128]={0};
    if(gethostname(hostname,128)==-1)
    {
        printf("my_bash1.0>> ");
        fflush(stdout);
        return;
    }

    char dir[256]={0};
    if(getcwd(dir,256)==NULL)
    {
        printf("my_bash1.0>> ");
        fflush(stdout);
        return;
    }

     printf("\033[1;32m%s@%s\033\[0m::\033[1;34m %s\033[0m%s ",ptr->pw_name,hostname,dir,user_str);
     fflush(stdout);
  
}

char *get_cmd(char *buff,char*myargv[])
{
    if(buff==NULL||myargv==NULL)
    {
        return NULL;
    }

    int i=0;
    char*s=strtok(buff," ");
    while(s!=NULL)
    {
        myargv[i++]=s;
        s=strtok(NULL," ");
    }
    return myargv[0];

}

void run_cmd(char*path,char*myargv[])
{    
    if(path==NULL||myargv==NULL )
     {  
        return;
     }
    pid_t pid=fork();
    if(pid==-1)
    {
        return;
    }
    
    if(pid==0)
    {
        //ti huan
       // execvp(path,myargv); 
        char pathname[128]={0};
        if(strncmp(path,"/",1)==0||strncmp(path,"/",2)==0)
        {
             strcpy(pathname,path);
        }
        execv(pathname,myargv);
        else
        {
             strcpy(pathname,PATH_BIN);
             strcat(pathnamme,path);
        }
        execv(pathname,myargv);
        perror("execvp error\n");
        exit(0);//子进程必须要退出
    }
    else
    {
        wait(NULL);
        
    }

}
int main()
{
    while(1)
    {  
       // printf("stu@localhost ~$");//默认
         print_info();
         fflush(stdout);

        char buff[128]={0};
        fgets(buff,128,stdin);
           
        buff[strlen(buff)-1]=0;       
        
        char*myargv[ARG_MAX]={0};   

        char*cmd=get_cmd(buff,myargv);
        if(cmd==NULL)
        {
            continue;
        }
        else if(strcmp(cmd,"cd")==0)
        {
            if(myargv[1]!=NULL)
            {  
                if(chdir(myargv[1])==-1)
                {
                    perror("cd err");      
                }
             }
         }
        else if(strcmp(cmd,"exit")==0)
        { 
          break;
        }
        else//普通命令
        {
            //fork+exec;
             run_cmd(cmd,myargv);
        }
 
    }
    exit(0);
    
}

5、项目运行结果

my_bash项目中有两个冒号::(与系统中bash区分开) ,这是个没有修改颜色之前的运行结果,可以看出my_bash与系统bash的区别。

 

6、mybin代码

主要写了clear.c、pwd.c、ls.c三个主要代码。

//clear.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
    printf("\033[2J\033[0H");

}
//pwd.c
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>

int main()
{
    char path[256]={0};
    if(getcwd(path,256)==NULL)
    {
        perror("getcwd error");
        exit(1);
    }
    printf("%s\n",path);
    exit(0);
}
//ls.c 
#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<dirent.h>
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main()
{
    char path[256]={0};
    if(getcwd(path,256)==NULL)
    {
        perror("getcwd error");
        exit(1);
    }
   // printf("%s\n",path);
    DIR *pdir=opendir(path);
    if(pdir==NULL)
    {
        perror("opendir error");
        exit(0);
    }

    struct dirent *s=NULL;
    while((s=readdir(pdir))!=NULL)
    {
        if(strncmp(s->d_name,". ",1)==0)
        {
            continue;
        }
       // printf("%s  ",s->d_name);
        struct stat filestat;
        stat(s->d_name,&filestat);
        if(S_ISDIR(filestat.st_mode))
        {
            printf("\033[1;34m%s\033[0m   ",s->d_name);
        }
        else
        {
            if(filestat.st_mode&(S_IXUSR|S_IXGRP|S_IXOTH))
             {
                printf("\033[1;32m%s\033[0m  ",s->d_name);
             }
             else
             {
                 printf("%s  ",s->d_name);
             }
        }
    }

    printf("\n");
    closedir(pdir);

    exit(0);
}

以下是运行mybin中与系统给出的结果,可以看出mybin与系统一致。 

 

7、关于修改颜色的printf命令

  • 关键部分的基本格式是:

printf("\033[字背景颜色;字体颜色m字符串\033[0m" );

  • 举例:

printf("\033[47;31mhello world\033[0m");

47是字背景颜色, 31是字体的颜色, hello world是字符串. 后面的\033[0m是控制码

printf("\033[1;32m%s\033[0m  ",s->d_name);

32是字体颜色(绿色),%s是字符串,\033[0m是控制码(关闭所有属性)

字背景颜色范围: 40--49 字颜色: 30--39

40: 黑 30: 黑

41: 红 31: 红

42: 绿 32: 绿

43: 黄 33: 黄

44: 蓝 34: 蓝

45: 紫 35: 紫

46: 深绿 36: 深绿

47: 白色 37: 白色

  • 其他的控制码:(标红的是经常使用的)

\033[0m 关闭所有属性

\033[1m 设置高亮度

\03[4m 下划线

\033[5m 闪烁

\033[7m 反显

\033[8m 消隐

\033[30m -- \033[37m 设置前景色

\033[40m -- \033[47m 设置背景色

\033[nA 光标上移n行

\03[nB 光标下移n行

\033[nC 光标右移n行

\033[nD 光标左移n行

\033[y;xH设置光标位置

\033[2J 清屏

\033[K 清除从光标到行尾的内容

\033[s 保存光标位置

\033[u 恢复光标位置

\033[?25l 隐藏光标

\33[?25h 显示光标

如有错误,敬请指正。

您的收藏与点赞都是对我最大的鼓励和支持!

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Sweep-

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值