zoukankan      html  css  js  c++  java
  • 第4章 文件和目录(5)_贯穿案例2:mini shell(1)

    6. 贯穿案例2:mini shell(1)

    【阶段性任务】实现cd、pwd和quit命令

     

    //job.h

    #ifndef __JOB_H__
    #define __JOB_H__
    
    //接收命令行参数
    typedef struct
    {
        char** args;  //对应于主函数中的char* argv[]参数(含进程名本身)
    }Program;
    
    //命令行中可以包含多个程序(命令),如
    //#date;ls -l,单个或多个命令通过cmd传入Job结构体中
    typedef struct
    {
        char* cmd; //单条命令或多条命令(用分号隔开)
        int progs_num;    //作业中包含程序的数量
        Program* progs;   //各个程序的命令行参数
    }Job;
    
    //创建作业
    extern Job* create_job(char* cmd);
    //销毁作业
    extern void destroy_job(Job* job);
    //创建进程(命令)
    extern Program* create_program(char** arg);
    //销毁进程(命令)
    extern void destroy_program(Program* prog);
    //将命令加入作业中
    extern int add_program(Job* job, Program* prog);
    
    #endif

    //job.c

    #include "job.h"
    #include <malloc.h>
    #include <assert.h>
    #include <string.h>
    
    //创建作业
    Job* create_job(char* cmd)
    {
        Job* job = (Job*)malloc(sizeof(Job));
        assert( job != NULL);
        
        job->cmd = (char*)malloc(sizeof(char) * strlen(cmd));
        assert(job->cmd != NULL);
        strcpy(job->cmd, cmd);
    
        job->progs_num = 0;
        job->progs = NULL;
    
        return job;
    }
    
    //销毁作业
    void destroy_job(Job* job)
    {
        assert(job != NULL);
        free(job->progs);
        free(job->cmd);
        free(job);
    }
    
    //arg格式:command  arg0 arg1 ==> 返回3
    static int arg_num(char** arg)
    {
        int ret = 0;
        char* start = arg[0];
       
        while(start != NULL){
            start = arg[++ret];
        }
    
        return ret;
    }
    
    //创建进程(命令)
    Program* create_program(char** arg)
    {
        Program* prog = (Program*)malloc(sizeof(Program));
        assert(prog != NULL);
        
        int counter = arg_num(arg);
        prog->args = (char**)calloc(counter + 1, sizeof(char*)); //以NULL结尾
    
        int i = 0;
        for(i=0; i< counter; i++){
           int len = strlen(arg[i]);
           prog->args[i] = (char*)malloc(len);
           assert(prog->args[i] != NULL);
    
           strcpy(prog->args[i], arg[i]);
        }
    
        prog->args[i] = NULL;  //指针数组,以NULL结尾
    
        return prog;
    }
    
    //销毁进程(命令)
    void destroy_program(Program* prog)
    {
        assert(prog != NULL);
    
        int i = 0;    
        while(prog->args[i] != NULL)
        {
            free(prog->args[i++]);        
        }
    
        free(prog->args);
        free(prog);
    }
    
    //将命令加入作业中
    int add_program(Job* job, Program* prog)
    {
        //重新申请一片空间以增加一条命令进来,放入job->progs中
        Program* ps = (Program*)malloc(sizeof(Program) * (job->progs_num + 1));
        memcpy(ps, job->progs, job->progs_num * sizeof(Program));
        
        ps[job->progs_num++] = *prog;//将新的进程(命令)加入进来
        
        free(job->progs); //释放旧的程序(命令)组
        job->progs = ps;
    
        return job->progs_num - 1; //返回新命令的索引号
    }

    //mshell.c

    #include "job.h"
    #include <unistd.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <malloc.h>
    #include <string.h>
    #include <assert.h>
    
    char* prompt = "mshell> "; //命令行的提示符
    #define MAX_COMMAND_LEN 256 //命令行最多的字符数
    
    //cd命令
    void cd_fun(Program* prog)
    {
        if(chdir(prog->args[1]) < 0){
            perror("cd error");
        }
    }
    
    //pwd命令
    void pwd_fun(Program* prog)
    {
        char buffer[256];
        memset(buffer, 0, sizeof(buffer));
    
        if(getcwd(buffer, sizeof(buffer)) == NULL){
            perror("pwd error");
        }
    
        printf("%s
    ", buffer);
    }
    
    //分析命令所带的参数(含进程名本身)
    void split_cmd(Job* job, char* arguments)
    {
        char** args = (char**)malloc(MAX_COMMAND_LEN * sizeof(char*));
        assert( args != NULL);
    
        char* cmd = strtok(arguments, " ");
    
        args[0] = (char*)malloc(strlen(cmd) * sizeof(char)); //命令本身
        strcpy(args[0], cmd);
    
        int i = 1;
        char* s = NULL;
        while((s = strtok(NULL, " ")) != NULL){  //将参数分隔出来
            args[i] = (char*)malloc(strlen(s) * sizeof(char));
            strcpy(args[i++], s);
        }
    
        //根据args创建一个Program
        Program* prog = create_program(args);
        add_program(job, prog);
    
        int j = 0;
        for(j=0; j < i; j++){
            free(args[j]);
        }
    
        free(args);
    }
    
    //多条命令的解析
    void parse_cmd(Job* job, char* line)
    {
        char buff [MAX_COMMAND_LEN];
    
        //以“;”号分隔多条命令
        char*  pos = line; 
        char*  start = line;
        int count = 0;
        while( start < (line + strlen(line)) ){
            memset(buff, 0, sizeof(buff));
            if((pos = strchr(pos, ';')) == NULL)
            {
                pos = line + strlen(line);      
            }
    
            count = pos-start;
            if(count > 0 ){
                 memcpy(buff, start, count);
                 split_cmd(job, buff);
            }
            start = ++pos;
        }
    }
    
    //执行命令
    void execute_cmd(Job* job)
    {
        int i = 0;
        for(i=0; i<job->progs_num; i++)
        {
            //cd命令
            if(!strcmp(job->progs[i].args[0], "cd")){
               cd_fun(&job->progs[i]);
            }
    
            //pwd命令
            if(!strcmp(job->progs[i].args[0], "pwd")){
               pwd_fun(&job->progs[i]);
            }
    
            //quit命令
            if(!strcmp(job->progs[i].args[0], "quit")){
               exit(0);
               return;
            }
        }
    }
    
    int main(int argc, char* argv[])
    {
        char buffer[MAX_COMMAND_LEN];
        memset(buffer, 0, MAX_COMMAND_LEN);
    
        ssize_t size = strlen(prompt) * sizeof(char);
        write(STDOUT_FILENO, prompt, size);
    
        ssize_t len = 0;
        while(1){
            len = read(STDIN_FILENO, buffer, MAX_COMMAND_LEN);
            buffer[len -1] = 0;  //以NULL结尾
    
            if(strlen(buffer) > 0){
                Job* job = create_job(buffer);
                
                //解析命令
                parse_cmd(job, buffer);
                //执行命令
                execute_cmd(job);
    
                destroy_job(job);
            }
    
            write(STDOUT_FILENO, prompt, size);
            memset(buffer, 0, MAX_COMMAND_LEN);
        }
    
        return 0;
    }
  • 相关阅读:
    异步、+回调机制、线程queue、线程Event、协程、单线程实现遇到IO切换
    GIL、进/线程池、同/异步、阻/非阻塞
    锁——死锁——单个锁锁死
    网络编程之多线程
    后台Response和异常和日志封装、跨域问题及解决、es6的箭头函数、xadmin后台管理
    pip换源、虚拟环境搭建、
    非对称加密和对称加密的区别
    JWT、多方式登录、django缓存
    自定制频率、自动生成接口文档、JWT、自定制auth认证类
    books系列表接口、表断关联、分页器、根据IP限制频率
  • 原文地址:https://www.cnblogs.com/5iedu/p/6352756.html
Copyright © 2011-2022 走看看