从零开始编写一个minishell

编写一个简单的minishell


文章目录

  • 编写一个简单的minishell
  • 一、shell是什么?
  • 二、minishell的实现
    • 1.捕捉键盘输入
    • 2.创建进程
    • 3.在minishell中加上重定向功能
    • 4.整体代码


一、shell是什么?

  从零开始编写一个minishell:   1.shell:命令行解释器   2.捕捉键盘输入:scanf,fgets,gets   3.解析输入信息-命令名称,运行参数   4.创建子进程:fork    让子进程执行对应命令名称的程序(程序替换):execvp      子进程程序替换失败必须退出,成功运行完命令程序会自己退出:exit        等待子进程退出:wait

二、minishell的实现

1.捕捉键盘输入

从零开始编写一个minishell_第1张图片


简单示例
代码如下(示例):

  1 #include<stdio.h>
  2 #include<unistd.h>
  3 #include<stdlib.h>
  4 #include<string.h>
  5 int main(int argc, char* argv[])
  6 {
     
  7     while(1){
     
  8         printf("[user@host path]$ ");
  9         fflush(stdout);
 10         char buf[1024] = {
     0};
 11         fgets(buf, 1023, stdin);
 12         printf("cmd:[%s]\n", buf);
 13     }
 14     return 0;
 15 }

从零开始编写一个minishell_第2张图片
从零开始编写一个minishell_第3张图片
简单运行结果
从零开始编写一个minishell_第4张图片


完善之后:

 12         buf[strlen(buf) - 1] = '\0';
 13         int myargc = 0;
 14         char *ptr = buf, *myargv[32] = {
     NULL};
 15         while(*ptr != '\0'){
     
 16             if(*ptr != ' '){
     
 17                 myargv[myargc] = ptr;
 18                 myargc++;
 19                 while(*ptr != '\0' && *ptr != ' ') ptr++;
 20                 *ptr = '\0';
 21             }
 22             ptr++;
 23         }
 24         myargv[myargc] = NULL;
 25         int i = 0;
 26         for(i = 0;i < myargc;i++){
     
 27             printf("[%s]\n", myargv[i]);
 28         }

从零开始编写一个minishell_第5张图片

2.创建进程

 26         pid_t pid = fork();
 27         if(pid < 0){
     
 28             perror("fork error");
 29             continue;
 30         }else if(pid == 0){
     
 31             execvp(myargv[0], myargv);
 32             perror("execvp error");
 33             exit(-1);
 34         }
 35         wait(NULL);

从零开始编写一个minishell_第6张图片


但此时切换路径时切换不了的(cd无效), 所以此时只能调用函数改变当前的工作路径

 26         if(strcmp("cd", myargv[0]) == 0){
     
 27             chdir(myargv[1]);
 28             continue;
 29         }

从零开始编写一个minishell_第7张图片

3.在minishell中加上重定向功能

在我们自己实现的minishell中加入重定向功能 >> / >
  1.捕捉键盘输入;
   1.5解析重定向(判断有没有'>'符号)
   1.6将重定向符号之前信息按照以前的命令处理方式进行处理
   1.7取出重定向的文件名称
 2.解析输入(得到命令名称+参数);
 3.创建子进程;
   3.5在程序替换之前进行标准输出重定向到指定的文件,open, dup2
 4.在子进程中进行程序替换;
 5.父进程进行程序等待;
 重定向或者文件的信息并不会随着程序替换而消失
 20         int direct_flag = 0;//0-没有重定向,1-清空重定向,2-追加重定向
 21         char *ptr = buf;
 22         char *redirect_file = NULL;
 23         while(*ptr != '\0'){
     
 24             if(*ptr == '>'){
     
 25                 direct_flag = 1;
 26                 *ptr = '\0';
 27                 ptr++;
 28                 if(*ptr == '\0'){
     
 29                     direct_flag = 2;
 30                     *ptr = '\0';
 31                     ptr++;
 32                 }
 33                     while(*ptr != '\0' && *ptr == ' ') ptr++;
 34                     redirect_file = ptr;
 35                     while(*ptr != '\0' && *ptr != ' ') ptr++;
 36                     *ptr = '\0';
 37             }
 38             ptr++;
 39         }
 40         ptr = buf;

 62             if(direct_flag == 1){
     
 63                 int fd;
 64                 fd = open(redirect_file, O_CREAT|O_RDWR|O_TRUNC, 0664);
 65                 dup2(fd, 1);
 66             }else if(direct_flag == 2){
     
 67                 int fd;
 68                 fd = open(redirect_file, O_CREAT|O_RDWR|O_APPEND, 0664);
 69                 dup2(fd, 1);
 70             }

4.整体代码

  1 #include<stdio.h>
  2 #include<stdlib.h>
  3 #include<unistd.h>
  4 #include<string.h>
  5 #include<ctype.h>
  6 #include<fcntl.h>
  7 #include<sys/stat.h>
  8 #include<sys/wait.h>
  9 int main(int argc,char *argv[])
 10 {
     
 11     while(1){
     
 12         printf("[user@host path]$ ");
 13         fflush(stdout);//手动刷新缓冲区
 14         char buf[1024] = {
     0};
 15         fgets(buf, 1023, stdin);
 16         buf[strlen(buf) - 1] = '\0';
 17 
 18 
 19 
 20         int direct_flag = 0;//0-没有重定向,1-清空重定向,2-追加重定向
 21         char *ptr = buf;
 22         char *redirect_file = NULL;
 23         while(*ptr != '\0'){
     
 24             if(*ptr == '>'){
     
 25                 direct_flag = 1;
 26                 *ptr = '\0';
 27                 ptr++;
 28                 if(*ptr == '\0'){
     
 29                     direct_flag = 2;
 30                     *ptr = '\0';
 31                     ptr++;
 32                 }
 33                     while(*ptr != '\0' && *ptr == ' ') ptr++;
 34                     redirect_file = ptr;
 35                     while(*ptr != '\0' && *ptr != ' ') ptr++;
 36                     *ptr = '\0';
 37             }
 38             ptr++;
 39         }
 40         ptr = buf;
 41         char *myargv[32] = {
     NULL};
 42         int myargc = 0;
 43         while(*ptr != '\0'){
     
 44             if(*ptr != ' '){
     
 45                 myargv[myargc] = ptr;
 46                 myargc++;
 47                 while(*ptr != '\0' && *ptr != ' ') ptr++;
 48                 *ptr = '\0';
 49             }
 50             ptr++;
 51         }
 52         myargv[myargc] = NULL;
 53         if(strcmp("cd", myargv[0]) == 0){
     
 54             chdir(myargv[1]);
 55             continue;
 56         }
 57         pid_t pid = fork();
 58         if(pid < 0){
     
 59             perror("fork error");
 60             continue;
 61         }else if(pid == 0){
     
 62             if(direct_flag == 1){
     
 63                 int fd;
 64                 fd = open(redirect_file, O_CREAT|O_RDWR|O_TRUNC, 0664);
 65                 dup2(fd, 1);
 66             }else if(direct_flag == 2){
     
 67                 int fd;
 68                 fd = open(redirect_file, O_CREAT|O_RDWR|O_APPEND, 0664);
 69                 dup2(fd, 1);
 70             }
 71             execvp(myargv[0],myargv);
 72             perror("execvp error");
 73             exit(-1);
 74         }
 75         wait(NULL);
 76     }
 77     return 0;
 78 }


你可能感兴趣的:(Linux)