shell命令解释器

shell 命令解释器:
bash ./bash
测试: ls /cp /pwd
ls.c/cp.c/pwd.c
bash 是不会通过exit退出的。
cd/exit等等,属于内置命令 ./只能在父进程直接实现。/只能对当前进程进行操作。[exit是把当前进程进行退出)(所以不能通过fork() + exec 实现,子进程不能通过exit结束父进程)是通过函数,方法实现的,没有在系统中。
而ls/cp等只是对文件进行查看和拷贝,所以无论是父进程还是子进程都能完成。
strtok() 可以记住和上一个分割的位置(全局,静态实现)
模拟:
stu@stu-virtual-machine:~/linux/day6/bash$

  • get_cmd() 将输入的 字符串分割,并返回ptr指向的第一个字符
    //通过 man getpwuid 来查找具体获取用户名等方法。
  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<sys/wait.h>
  6 #include<pwd.h>
  7 #define ARG_MAX 10
  8 char* get_cmd(char buff[],char*myargv[])//解析命令
  9 {
 10     if(buff == NULL||myargv == NULL)
 11      {
 12              return NULL;
 13       }
 14 
 15     int i = 0;
 16     char*s = strtok(buff," ");  //strtok会自动记录分割的位置,定义静态变量 全局变量
 17      while(s != NULL)
 18      {
 19         myargv[i++] = s;
 20         s = strtok(NULL," ");  //把空格替换成\0,
 21      }
 22      return myargv[0];
 23  }
  • 创建一个新进程执行字符
 24 void run_cmd(char*path,char* myargv[])//运行命令
 25 {
 26 
 27         if(path == NULL || myargv == NULL)
 28         {
 29                  return;
 30 
 31          }
 32         pid_t pid = fork();
 33         if(pid == -1)
 34         {
 35              return ;
 36          }
 37         if(pid == 0)
 38         {
 39            execvp(path,myargv);
 40            perror("cmd err");
 41           exit(0);
 42         }
 43         int val = 0;
 44         wait(&val);
 45 
 46 
 47 }
  • 输出
 48 void print_info()
 49 {
 50  //判断用户是普通用户还是管理员
 51  //通过uid来判断
 52  char *user_str = "$";
 53  int user_id = getuid();
 54  if(user_id == 0)
 55  {
 56           user_str ="#";
 57  }
 58  struct passwd* ptr = getpwuid(user_id);
 59  if(ptr == NULL)
 60  {
 61           printf("mybash1.0>>");
 62           fflush(stdout);
 63           return;
 64   }
 65  char hostname[128] = {0};
 66  if(gethostname(hostname,128)==-1)
 67  {
 68        printf("mtbash1.0>>");
 69        fflush(stdout);
 70        return;
 71  }
 72  char dir[256] = {0};
 73  if( getcwd(dir,256) == NULL)//得到当前位置
 74  {
 75           printf("mybash1.0>>");
 76           fflush(stdout);
 77           return ;
 78   }
 79  printf("\033[1;32m%s@%s\033[0m \033[1;34m%s\033[0m%s",ptr->pw_name,hostname,dir,user_str);
 80  fflush(stdout);
 81 }
  • strcmp函数:
    strcmp比较两个字符串的大小,一个字符一个字符比较,按ASCLL码比较.

标准规定:
第一个字符串大于第二个字符串,则返回大于0的数字
第一个字符串等于第二个字符串,则返回0
第一个字符串小于第二个字符串,则返回小于0的数字.

 82 int main()
 83 {
 84     while(1)
 85     {
 86      print_info();
 87      char buff[128]={0};   //一次只输入一个命令
 88      fgets(buff,128,stdin);//输入的时候每个命令之间用空格或者逗号间隔
 89      buff[strlen(buff)-1] = 0;//去掉fgets回车获得的\n
 90 
 91      char* myargv[ARG_MAX] = {0};//对myargv中的ls/ps/cp/等进行解析
 92      char*cmd = get_cmd(buff,myargv);
 93      if(cmd == NULL)
 94      {
 95               continue;
 96       }
 97      else if(strcmp(cmd,"exit")==0)
 98      {
 99               break;
100       }
101      else if(strcmp(cmd,"cd")==0)
102      {
103              break;
104      }
105      else
106      {//fork+excv
107 
108         run_cmd(cmd,myargv);
109       }
110 
111     }
112      exit(0);
113 
114  }

其中的很多功能,其实都可以手工实现。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值