十七、文件和目录——minishell(1)

  

  主函数运行要去读取从标准输入或终端上输入的整个命令行,然后再去解析命令行参数,解析出来之后,要将其封装成一个 program,然后再将 program 放入 job 中,然后再去执行 job 中的命令行的内容。

17.1 job.o

  job.h 文件

 1 #ifndef __JOB_H__
 2 #define __JOB_H__
 3 
 4 typedef struct
 5 {
 6     char **args; //shell 当中输入的命令参数;对应主函数中的 char *argv[] 参数
 7 }Program;
 8 
 9 //作业结构体,表示若干个要执行的参数
10 typedef struct
11 {
12     char         *cmd;
13     int         progs_num;
14     Program     *progs;//Program 的结构体指针
15 }Job;
16 
17 extern Job * create_job(char *cmd);
18 extern void destroy_job(Job *job);
19 extern Program* create_program(char **arg);//创建一个程序
20 extern void destroy_program(Program *prog);
21 extern int add_program(Job *job, Program *prog);//将程序加入到 job 中
22 
23 #endif

  job.c 文件

  1 #include "job.h"
  2 #include <malloc.h>
  3 #include <assert.h>
  4 #include <stdlib.h>
  5 #include <string.h>
  6 #include <stdio.h>
  7 #include <memory.h>
  8 
  9 
 10 /* 根据 commond 命令创建 job */
 11 Job * create_job(char *cmd)
 12 {
 13     Job *job = (Job *)malloc(sizeof(Job));
 14     assert(job != NULL);
 15 
 16     job->cmd = (char *)malloc(sizeof(char) * strlen(cmd));
 17     assert(job->cmd != NULL);
 18 
 19     strcpy(job->cmd, cmd);
 20     job->progs_num = 0;
 21     job->progs = NULL;
 22 
 23     return job;
 24 }
 25 
 26 void destroy_job(Job *job)
 27 {
 28     assert(job != NULL);
 29     free(job->progs);
 30     free(job->cmd);
 31     free(job);
 32 }
 33 
 34 /* 统计命令行参数的个数 */
 35 static int arg_num(char **arg)
 36 {
 37     int i = 0;
 38     char *start = arg[0];
 39 
 40     while(start != NULL) {
 41         i++;
 42         start = arg[i];
 43     }
 44 
 45     return i;
 46 }
 47 
 48 
 49 /*
 50  *     函数功能:    构建一个 program
 51  *     函数参数:
 52  *         @arg:命令行传入的参数
 53  *     返回值:
 54  */
 55 Program* create_program(char **arg)//创建一个程序
 56 {
 57     //在堆当中创建 program 内存块
 58     Program *prog = (Program *)malloc(sizeof(Program));
 59     assert(prog != NULL);
 60 
 61     int counter = arg_num(arg);
 62 
 63     //多 new 一个空间存放 NULL ,所以 counter 要 +1
 64     prog->args = (char **)calloc(counter + 1, sizeof(char *));
 65 
 66     int i;
 67     for(i = 0; i < counter; i++) {
 68         int len = strlen(arg[i]);
 69         prog->args[i] = (char *)malloc(len);
 70         assert(prog->args[i] != NULL);
 71         strcpy(prog->args[i], arg[i]);
 72     }
 73     prog->args[i] = NULL;
 74     return prog;
 75 }
 76 
 77 void destroy_program(Program *prog)
 78 {
 79     assert(prog != NULL);
 80     int i = 0;
 81 
 82     /* 命令行释放 */
 83     while(prog->args[i] != NULL) {
 84         free(prog->args[i]);
 85         i++;
 86     }
 87     free(prog->args);//数组释放
 88     free(prog);
 89 }
 90 
 91 /*    1.通过动态分配创建一个结构体数组
 92  *    2.将 job 中原先的 progs 复制给 ps 结构体数组
 93  *    3.在向 ps 结构体数组中加上新的 prog
 94  *    4.把  job 中原先的 progs 释放掉
 95  *    5.将 job 中的 progs 指向 ps
 96  */
 97 int add_program(Job *job, Program *prog)//将程序加入到 job 中
 98 {
 99     Program *ps = (Program *)malloc(sizeof(Program) * (job->progs_num + 1));//1 为NULL的初始化
100 
101     memcpy(ps, job->progs, job->progs_num * sizeof(Program));
102     ps[job->progs_num++] = *prog;
103     free(job->progs);
104     job->progs = ps;
105 }

  编译成 .o 文件

  gcc -o obj/job.o -Iinclude -c src/job.c

17.2 命令行参数的解析

17.2.1 主函数

  mshell.c

  1 #include "job.h"
  2 #include "cmd_func.h"
  3 #include <unistd.h>
  4 #include <string.h>
  5 #include <fcntl.h>
  6 #include <stdlib.h>
  7 #include <stdio.h>
  8 #include <stdlib.h>
  9 #include <memory.h>
 10 #include <assert.h>
 11 #include <malloc.h>
 12 
 13 /* shell 中的提示符 */
 14 char *prompt = "mshell > ";
 15 
 16 /* 指定命令行中传递的最大命令行的长度 */
 17 #define MAX_COMMAND_LEN 256
 18 
 19 
 20 /* 对命令行进行解析 */
 21 void parse_cmd(Job *job, char *line)
 22 {
 23     char **args = (char **)malloc(100 * sizeof(char *));//创建的 program 里面的args
 24     assert(args != NULL);
 25 
 26     /* 分割命令行 */
 27     char *cmd = strtok(line, " ");
 28     args[0] = (char *)malloc(strlen(cmd) * sizeof(char)); //第一个参数为命令本身
 29     strcpy(args[0], cmd);
 30 
 31     int i = 1;
 32     char *s;
 33     while((s = strtok(NULL, " ")) != NULL) {
 34         args[i] = (char *)malloc(strlen(s) * sizeof(char));
 35         strcpy(args[i], s);
 36         i++;
 37     }
 38 
 39     //根据  args 创建 program
 40     Program * prog = create_program(args);
 41     add_program(job, prog);
 42 
 43     int j;
 44     for(j = 0; j < i; j++) {
 45         free(args[j]);
 46     }
 47 
 48     free(args);
 49 }
 50 
 51 /* 执行命令 */
 52 void excute_cmd(Job *job)
 53 {
 54     int i;
 55     for(i = 0; i < job->progs_num; i++) {
 56         if(!strcmp(job->progs[i].args[0], "cd")) {
 57             cd_func(&job->progs[i]);
 58             return;
 59         }
 60 
 61         if(!strcmp(job->progs[i].args[0], "pwd")) {
 62             pwd_func(&job->progs[i]);
 63             return;
 64         }
 65 
 66         if(!strcmp(job->progs[i].args[0], "exit")) {
 67             exit_func(&job->progs[i]);
 68             return;
 69         }
 70     }
 71 }
 72 
 73 
 74 int main(int argc, char *argv[])
 75 {
 76     char buff[MAX_COMMAND_LEN];//存放从命令行中输入的整个命令行
 77     memset(buff, 0, MAX_COMMAND_LEN);
 78     ssize_t size = strlen(prompt) * sizeof(char);//提示符占用的总的大小
 79 
 80     write(STDOUT_FILENO, prompt, size);//输出 shell 的提示符
 81 
 82     ssize_t len;
 83     while(1) {
 84         /* 从标准输入读取命令行的内容 */
 85         len = read(STDIN_FILENO, buff, MAX_COMMAND_LEN);
 86         buff[len - 1] = 0; //结束符
 87 
 88         if(strlen(buff) > 0) {//命令行要大于0
 89             Job *job = create_job(buff);//创建 job
 90 
 91             parse_cmd(job, buff); //对命令行进行解析
 92 
 93             excute_cmd(job); // 执行命令
 94             destroy_job(job); // 销毁
 95 
 96         }
 97 
 98         write(STDOUT_FILENO, prompt, size);
 99         memset(buff, 0, MAX_COMMAND_LEN);
100     }
101 
102     return 0;
103 }

17.2.2 命令功能函数

  cmd_func.h

 1 #ifndef __CMD_FUNC_H__
 2 #define __CMD_FUNC_H__
 3 
 4 #include "job.h"
 5 
 6 #define BUFF_SIZE_256         256
 7 
 8 
 9 extern void cd_func(Program *prog);
10 extern void pwd_func(Program *prog);
11 extern void exit_func(Program *prog);
12 
13 #endif

  cmd_func.c

 1 #include "cmd_func.h"
 2 #include <stdio.h>
 3 #include <stdlib.h>
 4 #include <errno.h>
 5 #include "job.h"
 6 #include <fcntl.h>
 7 #include <string.h>
 8 #include <unistd.h>
 9 
10 /* 切换目录 */
11 void cd_func(Program *prog)
12 {
13     if(chdir(prog->args[1]) < 0) {
14         perror("cd error");
15     }
16 }
17 
18 /* 显示当前工作目录路径 */
19 void pwd_func(Program *prog)
20 {
21     char buff[256];
22     memset(buff, 0, sizeof(buff));
23 
24     /* 获取当前工作目录的绝对路径 */
25     if(getcwd(buff, sizeof(buff)) == NULL) {
26         perror("pwd error");
27     }
28 
29     printf("%s
", buff);
30 }
31 
32 /* 退出 */
33 void exit_func(Program *prog)
34 {
35     exit(0);
36 }

  编译成.o 文件

  gcc -o obj/cmd_func.o -Iinclude -c src/cmd_func.c

17.3 编译调试  

  gcc -o bin/mshell -Iinclude obj/*.o src/mshell.c

  

原文地址:https://www.cnblogs.com/kele-dad/p/9080289.html