Linux操作系统之C语言实现shell命令解释器项目

一、实现原理

普通命令:ls 、pwd、cp、clear…(通过exec+fork)
内置命令:cd、exit(bash本身提供方法,调用自己的函数,不会产生子进程)

二、具体实现过程

1.mybash项目里面的实现

  #include<stdio.h>
  #include<pwd.h>
  #include<unistd.h>
  #include<stdlib.h>
  #include<string.h>
  #include<sys/wait.h>
  
  #define ARG_MAX 10
  #define PATH_BIN "/home/stu/c/test1205/mybin/" //自定义路径
  
  void run_cmd(char* name, char* myargv[])  //系统提供的cp 可执行程序  ls...
     {
  
     if(name==NULL||myargv==NULL)return;
      int len=strlen(name);
      if(name[len-1]=='\n')
          name[len-1]=='\0';
     pid_t pid=fork();
      if(pid==0)//子进程处理  命令 exec
      {
          //execvp(name,myargv); 使用系统提供的命令  PATH
         char pathname[128]={0};
         if(strncmp(name,"./",2)==0||strncmp(name,"/",1)==0)
         {
  
              strcpy(pathname,name);
          }
         else  //将PATH_BIN +  ls
         {
              strcpy(pathname,PATH_BIN);
              strcat(pathname,name);
          }
        execvp(pathname,myargv);               
        perror("exec err");

        exit(1);
        }
      wait(NULL);
  }
 
 

 char* get_cmd(char *buff,char* myargv[])
  {
 
      if(buff==NULL&&myargv==NULL) return NULL;
      char* s=strtok(buff,"");
      int i=0;
      while(s!=NULL)
      {
 
          myargv[i++]=s;
          s=strtok(NULL," ");
 
     }
      return myargv[0];
  }
 
  void printf_info()60 {
  
      char* user_str="$";
      int user_id=getuid();
      if(user_id==0)user_str="#";
      struct passwd* ptr=getpwuid(user_id);
      char hostname[128]={0};
      gethostname(hostname,128);
      char dir[256]={0};
      getcwd(dir,256);
      printf("\033[1;32m%s@%s\033[0m:\033[1;34m:%s\033[0m %s ",ptr->pw_name,hostname,dir,user_str);
  
      fflush(stdout);
  }
  
  int main()
  {
    while(1)
     {
 
         printf_info();
         //printf("stu@localhost : ~ $ ");
         fflush(stdout);
         char buff[128]={0};//输入:pwd  ls  cp  a.c   b.c  ps -f
         fgets(buff,127,stdin); //"pwd\n"
         buff[strlen(buff)-1]='\0';
  
         //分隔["cp"]["a.c"]["b.c"]
        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&&chdir(myargv[1])==-1)
             {
  
                 perror("cd err");
            }
        }
       else if(strcmp(cmd,"exit")==0)
        {
 
            //exit(0)  程序不会帮我们释放资源
            break;
        }
        else
        {
           run_cmd(cmd,myargv);
                     //fork + exec 实现进程替换  pwd ls
        }
 
       // sleep(1000);
       }
}
                                                                                                                                                  

2、mybin路径下实现ls、pwd、mkdir、clear、vim、cp 命令

1)clear的实现

  #include<stdio.h>
  #include<unistd.h>
  #include<stdlib.h>
  
   int main()
   {
       printf("\033[2J\033[0;0H");
       exit(0);
   }

2)pwd的实现
在这里插入图片描述

   #include<stdio.h>
   #include<stdlib.h>
   #include<unistd.h>
   int main()
   {
       char path[128]={0};
       if(getcwd(path,128)==NULL)
       {
           perror("getcwd err");
         exit(1);
       }
       printf("%s\n",path);
       exit(0);
  }

3)mkdir的实现
在这里插入图片描述
(图片来自Linux程序设计)

   #include<sys/types.h>
   #include<unistd.h>
   #include<stdlib.h>
   #include<string.h>
   #include<stdio.h>
   #include<sys/stat.h>
   
   int main(int argc,char* argv[])
   {
  
     char path[128]={0};
    if(getcwd(path,128)==NULL)
    {
        perror("path err");
        exit(1);
    }
     if(argc!=2)
     {
         printf("mkdir err\n");
         exit(1);
     }
      if(mkdir(argv[1],S_IXUSR|S_IXGRP|S_IXOTH)==-1)
      {
          perror("mkdir err\n");
          exit(1);
      }
  
      exit(0);
  }

4)vim的实现

   #include<unistd.h>
   #include<stdio.h>
   #include<fcntl.h>
   #include<stdlib.h>
   #include<string.h>
   
   int main(int argc,char* argv[])
   {
       if(argc!=2)
      {
         perror("argc err");
      }
      char* s=argv[1];
      int  fd=open(s,O_WRONLY|O_CREAT,0600);
      if(fd==-1)exit(1);
      char buff[128]={0};
      while(1)
      {
          fgets(buff,128,stdin);
          if(strncmp(buff,"exit",4)==0)
          {
              break;
          }
         dprintf(fd,"%s\n",buff);
      }
      close(fd);
      exit(0);
  }

5)cp的实现

   #include<stdio.h>
   #include<stdlib.h>
   #include<unistd.h>
   #include<fcntl.h>
   
   int main(int argc,char* argv[])
   {
       char* s_name=argv[1];
       char* new_name=argv[2];
       int fdr= open(s_name,O_RDONLY);
       char buff[128]={0};
       int fdw=open(new_name,O_WRONLY|O_CREAT,0600);
       int num=0;
       while((num=read(fdr,buff,128))>0)
      {
         write(fdw,buff,num);
      }
      close(fdr);
      close(fdw);
  }

==6)ls + pathname 的实现 ==
在这里插入图片描述
在这里插入图片描述

  #include <sys/stat.h>
  #include <stdio.h>
  #include<unistd.h>
  #include <stdlib.h>
  #include <dirent.h>
  #include <string.h>
   int main(int argc,char* argv[]){
       char path[128]={0};
       if(getcwd(path,128) == NULL)  exit(1);
      if(argc!=1&&strncmp(argv[1],"/",1)==0||argc!=1&&strncmp(argv[1],".",1)==0)
      {
          int len=strlen(argv[1]);
          memset(path,0,128);
          strncpy(path,argv[1],len-1);
      }
      else if(argc!=1&&strncmp(argv[1],".",1)!=0)
      {
          int len=strlen(argv[1]);
          strcat(path,"/");
          strncat(path,argv[1],len-1);
      }
       //打开目录流opendir
      DIR* pdir = opendir(path);
      if(pdir == NULL)  exit(1);
      struct dirent* s = NULL;
      while((s=readdir(pdir)) != NULL){ //读取目录流里面的文件信息(readdir)
          if(strncmp(s->d_name,".",1) == 0){
              continue;
          }
  
          struct stat filestat;
          stat(s->d_name,&filestat);//获取当前文件信息 保存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)) { //  000100     &    0000111  -> 0000100  -> 1   true
                  printf("\033[1;32m%s\033[0m    ",s->d_name);
             }
             else{
                  printf("%s    ",s->d_name);
             }
          }
      }
      printf("\n");
      closedir(pdir);
      exit(0);
  }


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

淡蓝色的经典

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

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

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

打赏作者

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

抵扣说明:

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

余额充值