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;
    }
  • 相关阅读:
    算法----(1)冒泡排序
    淘宝爬虫
    爬虫_豆瓣电影top250 (正则表达式)
    爬虫_猫眼电影top100(正则表达式)
    Android 简单调用摄像头
    Android 简单天气预报
    思维模型
    This view is not constrained, it only has designtime positions, so it will jump to (0,0) unless you
    Android studio preview界面无法预览,报错render problem
    Android studio 3.1.2报错,no target device found
  • 原文地址:https://www.cnblogs.com/5iedu/p/6352756.html
Copyright © 2011-2022 走看看