1. 程式人生 > >二十九、Linux 程序與訊號——minishell(2)

二十九、Linux 程序與訊號——minishell(2)

程式設計內容:

  1.完成  echo env export 命令

  2.完成前後臺程序

  3.完成重定向

完整程式碼如下:

29.1 主函式、通用標頭檔案和Makefile

29.1.1 主函式

  mshell_main.c

1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "mshell_handler.h"
4 
5 int main(int argc, char *argv[])
6 {
7     mshell_Handler();
8 }

29.1.2 通用檔案

  mshell_common.h

 1 #ifndef __MSHELL_COMMON_H__
 2 #define __MSHELL_COMMON_H__
 3 
 4 #include <stdio.h>
 5 #include <stdlib.h>
 6 
 7 typedef enum {
 8     MSHELL_ERROR_NONE        = 0,
 9     MSHELL_ERROR_PARAM            ,
10     MSHELL_ERROR_MALLOC            ,
11     MSHELL_ERROR_CALLOC            ,
12 MSHELL_ERROR_PROG_CREATE, 13 MSHELL_ERROR_PROG_DESTROY, 14 MSHELL_ERROR_JOB_CREATE, 15 MSHELL_ERROR_JOB_DESTROY, 16 MSHELL_ERROR_JOB_PROGADD, 17 MSHELL_ERROR_CMD_NONECMD, 18 MSHELL_ERROR_REDIRECION_PARAM, 19 MSHELL_ERROR_REDIRECTION_CREATE, 20 MSHELL_ERROR_REDIRECTION_PARSE
21 }mshell_error_t; 22 23 extern int mshell_args_Total(char **args); 24 extern void mshell_args_Free(char **args); 25 #endif

  mshell_common.c

 1 #include "mshell_common.h"
 2 
 3 
 4 /** 統計命令列引數的個數 */
 5 int mshell_args_Total(char **args)
 6 {
 7     int i = 0;
 8     char *start = args[0];
 9 
10     while(NULL != start) {
11         i++;
12         start = args[i];
13     }
14 
15     return i;
16 }
17 
18 void mshell_args_Free(char **args)
19 {
20     if(NULL == args){
21         return ;
22     }
23 
24     int i;
25     int len = sizeof(args);
26     for(i = 0; i < len; i++) {
27         free(args[i]);
28     }
29 #if 0
30     while(NULL != args[i]){
31         free(args[i]);
32         i++;
33     }
34 #endif
35     free(args);
36 }

29.1.3 Makefile

 1 #PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
 2 PROJECT_ROOT = $(shell pwd)
 3 SRC_DIR = $(PROJECT_ROOT)/src
 4 INCLUDE_DIR = $(PROJECT_ROOT)/include
 5 OBJ_DIR = $(PROJECT_ROOT)/obj
 6 BIN_DIR = $(PROJECT_ROOT)/bin
 7 
 8 
 9 # 找出 src 目錄下的所有 .c 檔案
10 C_SRCS = $(wildcard $(SRC_DIR)/*.c)
11 # 將所有的 src 下的 .c 檔案替換為 .o 檔案
12 C_OBJS = $(patsubst %c, %o, $(C_SRCS))
13 TARGET = mshell
14 SHARE_LIB = libmshell.a
15 
16 C_SRC_MAIN = mshell_main.c
17 
18 CC = gcc
19 CCFLAGS += fPIC
20 LDFLAGS += -shared -fPIC
21 ASFLAGS +=
22 ARFLAGS = -crs
23 LIBS_FLAGS = -L$(BIN_DIR)
24 
25 RM = rm -rf
26  
27 CFLAGS += -Wall -g -I$(INCLUDE_DIR)
28 INCDIR += -I$(INCLUDE_DIR)
29 
30 
31 
32 .PHONY: all clean test
33 
34 all: $(TARGET)
35     cp $(SHARE_LIB) $(BIN_DIR)
36     cp $(SRC_DIR)/*.o $(OBJ_DIR)/
37     $(RM) $(SHARE_LIB) $(SRC_DIR)/*.o
38 
39 $(TARGET): $(SHARE_LIB)
40     $(CC) $(C_SRC_MAIN) -o $(TARGET) $(CFLAGS) $(INCDIR) $(LIBS_FLAGS) -lmshell
41 
42 $(SHARE_LIB): $(C_OBJS)
43     $(AR) $(ARFLAGS) $(SHARE_LIB) $(C_OBJS)
44     cp $(SHARE_LIB) $(BIN_DIR)
45 
46 $(C_OBJS) : %.o:%.c
47     $(CC) -c $(CFLAGS) $(INCDIR) -o [email protected] $<
48 
49 clean:
50     $(RM) mshell 
51     $(RM) $(SHARE_LIB) 
52     $(RM) $(OBJ_DIR)/$(OBJS)/*.o 
53     $(RM) $(SRC_DIR)/*.o

29.2 handler

  mshell_handler.c

  1 #include "mshell_handler.h"
  2 
  3 static mshell_error_t mshell_cmd_Parsed(mshell_job_t *job, char *line, mshell_process_Flag_t *process_flag)
  4 {
  5     /** Create args secondary pointer stored in program */
  6     char **args_tmp = (char **)malloc(MSHELL_ARGS_SIZE * sizeof(char *));
  7     if(NULL == args_tmp) {
  8         return MSHELL_ERROR_MALLOC;
  9     }
 10 
 11     /** Split the command line */
 12     char *cmd = strtok(line, " ");
 13 
 14     /** The first parameter is the command itself */
 15     args_tmp[0] = (char *)calloc(strlen(cmd + 1), sizeof(char));
 16     if(NULL == args_tmp[0]) {
 17         return MSHELL_ERROR_MALLOC;
 18     }
 19     strcpy(args_tmp[0], cmd);
 20 
 21     /** Start with the second parameter */
 22     int i = 1;
 23     char *cmd_param;
 24     mshell_redirection_t *redirections[MSHELL_REDIRECTION_NUMBER];
 25     int redirection_num = 0;
 26 
 27     while(NULL != (cmd_param = strtok(NULL, " "))) {
 28 
 29         /** 對命令列進行解析,判斷是否為後臺程序 */
 30         int process_ret;
 31         *process_flag = mshell_process_BackParse(cmd_param, &process_ret);
 32         if(0 == process_ret) {
 33             continue;
 34         }
 35 
 36         /** 分析重定向 */
 37         mshell_error_t redirection_ret;
 38         redirections[redirection_num] =
 39                 mshell_redirection_Parse(redirections, redirection_num, cmd_param, &redirection_ret);
 40         if(NULL != redirections[redirection_num] && MSHELL_ERROR_NONE == redirection_ret){
 41             redirection_num++;
 42             continue;
 43         }
 44         else if (NULL == redirections[redirection_num] && MSHELL_ERROR_REDIRECION_PARAM == redirection_ret) {
 45             printf("need param\n");
 46             continue;
 47         }
 48         else if(NULL == redirections[redirection_num] && MSHELL_ERROR_REDIRECTION_CREATE == redirection_ret)
 49         {
 50             perror("error create redirection");
 51             return MSHELL_ERROR_REDIRECTION_CREATE;
 52         }
 53 
 54         /** 分析命令 */
 55         args_tmp[i] = (char *)calloc(strlen(cmd_param + 1), sizeof(char));
 56         if(NULL == args_tmp[i]) {
 57             return MSHELL_ERROR_MALLOC;
 58         }
 59         strcpy(args_tmp[i], cmd_param);
 60         i++;
 61     }
 62     args_tmp[i] = NULL;
 63 
 64     /** Store all command line parameters in program and free args_tmp*/
 65     mshell_prog_t *prog = mshell_prog_Create(args_tmp);
 66     if(NULL == prog) {
 67         return MSHELL_ERROR_PROG_CREATE;
 68     }
 69     mshell_args_Free(args_tmp);
 70 
 71     /** Add redirection to job and free redirections*/
 72     for(i = 0; i < redirection_num; i++){
 73         mshell_prog_RedirectionAdd(prog, redirections[i]);
 74     }
 75     mshell_redirections_Free(redirections, redirection_num);
 76 
 77     /** Add program to the job*/
 78     if(MSHELL_ERROR_NONE != mshell_job_AddProg(job, prog)) {
 79         return MSHELL_ERROR_JOB_PROGADD;
 80     }
 81 
 82 #if 0
 83     /** free args_tmp */
 84     mshell_args_Free(args_tmp);
 85 #endif
 86     return 0;
 87 }
 88 
 89 static void mshell_cmd_ExcuProcess(mshell_job_t job, int order, mshell_process_Flag_t process_flag)
 90 {
 91     pid_t pid;
 92     if((pid = fork()) < 0) {
 93         perror("fork error");
 94     }
 95     else if(pid == 0) {
 96         /** child process */
 97         if(order == 0) {
 98             /** order = 0, 則為 minishell 當中啟動的第一個子程序,設定其為組長程序 */
 99             job.pgid = mshell_process_GroupGet(getpid(), getpid());
100         }
101         else {
102             /** order > 0, 則為啟動的第二個程序,將其設定程序組的成員程序 */
103             job.pgid = mshell_process_GroupGet(getpid(), job.pgid);
104         }
105         mshell_process_GroupSet(process_flag, getpid());
106         /** 對便準輸入、標準輸出和追加進行重定向 */
107         mshell_prog_RedirectionExcu(job.progs[order]);
108 
109         /** 呼叫 exec 函式執行系統中的其他命令 */
110         if(MSHELL_ERROR_CMD_NONECMD == mshell_Cmd_ExcuOther(job.progs[order].args))
111             exit(1);
112     }
113     else {
114         /** parent process */
115         if(order == 0) {
116             job.pgid = mshell_process_GroupGet(pid, pid);
117         }
118         else {
119             job.pgid = mshell_process_GroupGet(pid, job.pgid);
120         }
121         mshell_process_GroupSet(process_flag, job.pgid);
122 
123         mshell_process_Wait(process_flag, job.pgid);
124 
125 #if 0
126         /** 等待指定的子程序結束, 阻塞版本,支援作業控制 */
127         if(waitpid(pid, NULL, WUNTRACED) < 0) {
128             perror("waitpid error");
129         }
130 #endif
131     }
132 
133 }
134 
135 static mshell_error_t mshell_cmd_Excu(mshell_job_t *job, mshell_process_Flag_t process_flag)
136 {
137     int ret = MSHELL_ERROR_NONE;
138     int i;
139     for(i = 0; i < job->progs_num; i++)
140     {
141         ret = mshell_Cmd_ExcuFun(job->progs[i].args);
142         if(MSHELL_ERROR_NONE == ret || MSHELL_ERROR_PARAM == ret) {
143             return MSHELL_ERROR_NONE;
144         }
145 
146         /** 執行其他命令 */
147         mshell_cmd_ExcuProcess(*job, i, process_flag);
148 #if 0
149         pid_t pid;
150         if((pid = fork()) < 0) {
151             perror("fork error");
152         }
153         else if(pid == 0) {
154             /** child process */
155             /** 呼叫 exec 函式執行系統中的其他命令 */
156             if(MSHELL_ERROR_CMD_NONECMD == mshell_Cmd_ExcuOther(job->progs[i].args))
157                 exit(1);
158         }
159         else {
160             /** parent process */
161             /** 等待指定的子程序結束, 阻塞版本,支援作業控制 */
162             if(waitpid(pid, NULL, WUNTRACED) < 0) {
163                 perror("waitpid error");
164             }
165         }
166 #endif
167     }
168 
169     return 0;
170 }
171 
172 mshell_error_t mshell_Handler()
173 {
174     /**建立一個程序組,將 minishell 程序設定為程序組的組長 */
175     setpgid(getpid(), getpid());
176 
177     char buffer[MSHELL_COMMAND_LEN];
178     memset(buffer, 0, MSHELL_COMMAND_LEN);
179 
180     ssize_t size = strlen(MSHELL_PROMPT) * sizeof(char);
181     write(STDOUT_FILENO, MSHELL_PROMPT, size);
182 
183     mshell_process_Flag_t process_flag;    ///< 設定前臺和後臺程序的標誌
184     ssize_t len;
185     while(1) {
186 
187         len = read(STDIN_FILENO, buffer, MSHELL_COMMAND_LEN); ///< 從命令列讀取內容到 buffer
188         buffer[len - 1] = 0;
189         if(strlen(buffer) > 0){
190             mshell_job_t *job = mshell_job_Create(buffer);
191             if(NULL == job) {
192                 return MSHELL_ERROR_JOB_CREATE;
193             }
194 
195             mshell_cmd_Parsed(job, buffer, &process_flag);
196             mshell_cmd_Excu(job, process_flag);
197             //mshell_job_Destroy(job);
198         }
199 
200         write(STDOUT_FILENO, MSHELL_PROMPT, size);
201         memset(buffer, 0, MSHELL_COMMAND_LEN);
202     }
203 }
View Code

  mshell_handler.h

 1 #ifndef __MSHELL_HANDLER_H__
 2 #define __MSHELL_HANDLER_H__
 3 
 4 
 5 #include "mshell_common.h"
 6 #include "mshell_process.h"
 7 #include "mshell_cmd_fun.h"
 8 #include "mshell_program.h"
 9 #include "mshell_job.h"
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <malloc.h>
13 #include <unistd.h>
14 #include <string.h>
15 #include <memory.h>
16 #include <sys/wait.h>
17 
18 #define MSHELL_PROMPT    "mshell =>"
19 #define MSHELL_COMMAND_LEN     256
20 #define MSHELL_ARGS_SIZE    100
21 
22 mshell_error_t mshell_Handler();
23 
24 #endif
View Code

29.3 作業

   mshell_job.h

 1 #ifndef __MSHELL_JOB_H__
 2 #define __MSHELL_JOB_H__
 3 
 4 #include "mshell_common.h"
 5 #include "mshell_program.h"
 6 #include <malloc.h>
 7 #include <stdio.h>
 8 #include <stdlib.h>
 9 #include <string.h>
10 #include <memory.h>
11 
12 /** job struct, A job contains several programs to execute */
13 typedef struct {
14     char             *cmd;        ///< String commands to be executed
15     pid_t            pgid;        ///< 程序組的 ID
16     int             progs_num;    ///< Number of programs to execute
17     mshell_prog_t    *progs;        ///< Point to several programs to be executed
18 }mshell_job_t;
19 
20 extern mshell_job_t* mshell_job_Create(char *cmd);
21 extern void mshell_job_Destroy(mshell_job_t *job);
22 extern mshell_error_t mshell_job_AddProg(mshell_job_t *job, mshell_prog_t *prog);
23 #endif
View Code

  mshell_job.c

 1 #include "mshell_common.h"
 2 #include "mshell_program.h"
 3 #include "mshell_job.h"
 4 
 5 
 6 mshell_job_t* mshell_job_Create(char *cmd)
 7 {
 8     mshell_job_t *job = (mshell_job_t *)malloc(sizeof(mshell_job_t));
 9     if(NULL == job)
10     {
11         return NULL;
12     }
13 
14     job->cmd = (char *)malloc(sizeof(char) * strlen(cmd));
15     if(NULL == job->cmd)
16     {
17         return NULL;
18     }
19 
20     strcpy(job->cmd, cmd);
21     job->progs_num = 0;
22     job->progs = NULL;
23 
24     return job;
25 }
26 void mshell_job_Destroy(mshell_job_t *job)
27 {
28     if(NULL == job)
29     {
30         return ;
31     }
32     free(job->progs);
33     free(job->cmd);
34     free(job);
35 }
36 
37 mshell_error_t mshell_job_AddProg(mshell_job_t *job, mshell_prog_t *prog)
38 {
39     mshell_prog_t *prog_tmp = (mshell_prog_t *)malloc(sizeof(mshell_prog_t) * (job->progs_num + 1));//1 為NULL的初始化
40     if(NULL == prog_tmp) {
41         return MSHELL_ERROR_MALLOC;
42     }
43 
44     memcpy(prog_tmp, job->progs, job->progs_num * sizeof(mshell_prog_t));
45     prog_tmp[job->progs_num++] = *prog;
46     free(job->progs);
47     job->progs = prog_tmp;
48 
49     return MSHELL_ERROR_NONE;
50 }
View Code

29.4 程式

  mshell_program.h

 1 #ifndef __MSHELL_PROGRAM_H__
 2 #define __MSHELL_PROGRAM_H__
 3 
 4 #include "mshell_common.h"
 5 #include "mshell_redirection.h"
 6 #include <malloc.h>
 7 #include <stdio.h>
 8 #include <stdlib.h>
 9 #include <string.h>
10 #include <memory.h>
11 
12 /** program struct */
13 typedef struct {
14     /**
15      * Command-line parameters obtained from the terminal
16      * Char*argv[] parameter corresponding to the main function
17      */
18     char                     **args;
19     pid_t                     pid;                ///< 程序 ID
20     int                     redirection_num;    ///< 重定向的數量
21     mshell_redirection_t     *redirecitons;        ///< 重定向結構體陣列
22 }mshell_prog_t;
23 
24 extern mshell_prog_t* mshell_prog_Create(char **args);
25 extern void mshell_prog_Destroy(mshell_prog_t *prog);
26 extern void mshell_prog_RedirectionAdd(mshell_prog_t *prog, mshell_redirection_t *redirection);
27 extern void mshell_prog_RedirectionExcu(mshell_prog_t prog);
28 #endif
View Code

  mshell_program.c

 1 #include "mshell_program.h"
 2 
 3 /**
 4  * Init program's pointer array
 5  */
 6 static mshell_prog_t * mshell_prog_ArgsInit(mshell_prog_t *prog, char **args, int counter)
 7 {
 8     int i;
 9 
10     for(i = 0; i < counter; i++) {
11         int len = strlen(args[i]);
12         prog->args[i] = (char *)malloc(len);
13         if(NULL == prog->args[i]){
14             return NULL;
15         }
16 
17         strcpy(prog->args[i], args[i]);
18     }
19     return prog;
20 }
21 
22 mshell_prog_t * mshell_prog_Create(char **args)
23 {
24     mshell_prog_t *prog = (mshell_prog_t *)malloc(sizeof(mshell_prog_t));
25     if(NULL == prog){
26         return NULL;
27     }
28 
29     /** Init program's redirection */
30     prog->redirection_num = 0;
31     prog->redirecitons = NULL;
32 
33     /** Init program's pointer array  */
34     int args_num = mshell_args_Total(args);
35     prog->args = (char **)calloc(args_num + 1, sizeof(char *));
36     prog = mshell_prog_ArgsInit(prog, args, args_num);
37     return prog;
38 }
39 
40 void mshell_prog_Destroy(mshell_prog_t *prog)
41 {
42     if(NULL == prog) {
43         return ;
44     }
45 
46     mshell_args_Free(prog->args);
47     free(prog->redirecitons);
48     free(prog);
49 }
50 
51 void mshell_prog_RedirectionAdd(mshell_prog_t *prog, mshell_redirection_t *redirection)
52 {
53     mshell_redirection_t *redirections = (mshell_redirection_t *)calloc(prog->redirection_num + 1, sizeof(mshell_redirection_t));
54     if(NULL == redirections){
55         return;
56     }
57 
58     if(NULL != prog->redirecitons) {
59         memcpy(redirections, prog->redirecitons, prog->redirection_num * sizeof(redirections));
60         free(redirections);
61     }
62 
63     prog->redirecitons = redirections;
64     memcpy(&prog->redirecitons[prog->redirection_num], redirection, sizeof(mshell_redirection_t));
65     prog->redirection_num += 1;
66 }
67 
68 void mshell_prog_RedirectionExcu(mshell_prog_t prog)
69 {
70     int i;
71     for(i = 0; i < prog.redirection_num; i++) {
72         mshell_redirection_Excu(prog.redirecitons[i]);
73     }
74 }
View Code

29.5 命令

  mshell_cmd_fun.h

 1 #ifndef __MSHELL_CMD_FUN_H__
 2 #define __MSHELL_CMD_FUN_H__
 3 
 4 #include "mshell_common.h"
 5 #include <stdio.h>
 6 #include <stdlib.h>
 7 #include <unistd.h>
 8 #include <string.h>
 9 
10 #define MSHELL_CMD_CD            "cd"
11 #define MSHELL_CMD_PWD            "pwd"
12 #define MSHELL_CMD_EXIT            "exit"
13 #define MSHELL_CMD_ENV            "env"
14 #define MSHELL_CMD_ECHO            "echo"
15 #define MSHELL_CMD_EXPORT        "export"
16 
17 typedef void (* mshell_cmd_Fun)(char *args);
18 typedef struct {
19     char *cmd;
20     mshell_cmd_Fun    callback;
21 }mshell_funs_t;
22 
23 mshell_error_t mshell_Cmd_ExcuFun(char **args);
24 mshell_error_t mshell_Cmd_ExcuOther(char **args);
25 #endif
View Code

  mshell_cmd_fun.c

  1 #include "mshell_cmd_fun.h"
  2 
  3 extern char** environ;
  4 
  5 static void mshell_cmd_Cd(char *args)
  6 {
  7     if(chdir(args) < 0) {
  8         perror("cd error");
  9     }
 10 }
 11 
 12 static void mshell_cmd_Pwd(char *args)
 13 {
 14     char buffer[256];
 15     memset(buffer, 0, sizeof(buffer));
 16     if(getcwd(buffer, sizeof(buffer)) == NULL){
 17         perror("pwd error");
 18     }
 19 
 20     printf("%s\n", buffer);
 21 }
 22 
 23 static void mshell_cmd_Exit(char *args)
 24 {
 25     exit(0);
 26 }
 27 
 28 static void mshell_mcd_Env(char *args)
 29 {
 30     int i = 0;
 31     char *env = NULL;
 32 
 33     while(NULL != (env = environ[i])) {
 34         printf("%s\n", env);
 35         i++;
 36     }
 37 }
 38 
 39 static void mshell_mcd_Echo(char *args)
 40 {
 41     char *arg_tmp = args;
 42     if(NULL == arg_tmp) {
 43         fprintf(stderr, "echo: invalid argument\n");
 44         return;
 45     }
 46 
 47     if('$' == arg_tmp[0]) {
 48         char *env_tmp = getenv(arg_tmp + 1);
 49         printf("%s\n", env_tmp);
 50     }
 51     else {
 52         printf("%s\n", arg_tmp);
 53     }
 54 }
 55 
 56 static void mshell_mcd_Export(char *args)
 57 {
 58     if(NULL == args) {
 59         fprintf(stderr, "export: invalid argument\n");
 60         return;
 61     }
 62 
 63     putenv(args);
 64 }
 65 
 66 static mshell_funs_t mshell_table_fun[] = {
 67     /** cmd                    func */
 68     {MSHELL_CMD_CD    ,        mshell_cmd_Cd},
 69     {MSHELL_CMD_PWD ,        mshell_cmd_Pwd},
 70     {MSHELL_CMD_EXIT,        mshell_cmd_Exit},
 71     {MSHELL_CMD_ENV ,        mshell_mcd_Env},
 72     {MSHELL_CMD_ECHO,        mshell_mcd_Echo},
 73     {MSHELL_CMD_EXPORT,        mshell_mcd_Export},
 74 };
 75 
 76 mshell_error_t mshell_Cmd_ExcuFun(char **args)
 77 {
 78     if(NULL == args) {
 79         return MSHELL_ERROR_PARAM;
 80     }
 81     int len = sizeof(mshell_table_fun) / sizeof(mshell_funs_t);
 82     int i;
 83     for(i = 0; i < len; i++) {
 84         if(!strcmp(args[0], mshell_table_fun[i].cmd)){
 85             mshell_table_fun[i].callback(args[1]);
 86             return MSHELL_ERROR_NONE;
 87         }
 88     }
 89 
 90     return MSHELL_ERROR_CMD_NONECMD;
 91 }
 92 
 93 mshell_error_t mshell_Cmd_ExcuOther(char **args)
 94 {
 95     /** excu 函式成功執行不返回,出錯會返回 -1 */
 96     if(execvp(args[0], args) < 0) {
 97         perror("execvp error");
 98         /** 這裡退出後,讓後面的程式繼續執行 */
 99         return MSHELL_ERROR_CMD_NONECMD;
100     }
101 
102     return MSHELL_ERROR_NONE;
103 }
View Code

29.6 重定向

  mshell_redirection.h

 1 #ifndef __MSHELL_REDIRECTION_H__
 2 #define __MSHELL_REDIRECTION_H__
 3 
 4 #include "mshell_common.h"
 5 #include <stdio.h>
 6 #include <stdlib.h>
 7 #include <unistd.h>
 8 #include <fcntl.h>
 9 #include <string.h>
10 
11 #define MSHELL_REDIRECTION_NUMBER        5
12 
13 #define MSHELL_REDIRECTION_READ            "<"
14 #define MSHELL_REDIRECTION_WRITE        ">"
15 #define MSHELL_REDIRECTION_APPEND        ">>"
16 
17 typedef enum {
18     mshell_Redirection_Read,
19     mshell_Redirection_Write,
20     mshell_Redirection_Append
21 }mshell_redirection_type_t;
22 
23 typedef struct {
24     mshell_redirection_type_t    type;
25     int                            fd;
26 }mshell_redirection_t;
27 
28 typedef mshell_redirection_t* (* mshell_redirection_fun)(char *file);
29 typedef struct {
30     char                     *type;
31     mshell_redirection_fun     callback;
32 }mshell_table_redirection_t;
33 
34 typedef void (* mshell_redirection_ExcuFun)(int fd);
35 typedef struct {
36     mshell_redirection_type_t    type;
37     mshell_redirection_ExcuFun    callback;
38 }mshell_Table_redirectionExcu_t;
39 
40 extern mshell_redirection_t *mshell_redirection_Create(int fd, mshell_redirection_type_t type);
41 extern void mshell_redirection_Destroy(mshell_redirection_t *redirection);
42 extern mshell_redirection_t *mshell_redirection_Parse(
43         mshell_redirection_t **redirection,
44         int num,
45         char *args,
46         mshell_error_t *error);
47 extern void mshell_redirections_Free(mshell_redirection_t **redirections, int num);
48 extern void mshell_redirection_Excu(mshell_redirection_t redirection);
49 #endif
View Code

  mshell_redirection.c

  1 #include "mshell_redirection.h"
  2 
  3 
  4 mshell_redirection_t *mshell_redirection_Create(int fd, mshell_redirection_type_t type)
  5 {
  6     mshell_redirection_t *redirection = (mshell_redirection_t *)calloc(1, sizeof(mshell_redirection_t));
  7     if(NULL == redirection){
  8         return NULL;
  9     }
 10 
 11     redirection->fd = fd;
 12     redirection->type = type;
 13     return redirection;
 14 }
 15 
 16 void mshell_redirection_Destroy(mshell_redirection_t *redirection)
 17 {
 18     if(NULL == redirection) {
 19         return;
 20     }
 21     free(redirection);
 22 }
 23 
 24 static mshell_redirection_t *mshell_redirection_Read(char *file)
 25 {
 26     int fd = open(file, O_RDONLY);
 27     mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Read);
 28     return redirection;
 29 }
 30 
 31 static mshell_redirection_t *mshell_redirection_Write(char *file)
 32 {
 33     int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
 34     mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Write);
 35     return redirection;
 36 }
 37 
 38 static mshell_redirection_t *mshell_redirection_Append(char *file)
 39 {
 40     int fd = open(file, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU | S_IRWXG | S_IRWXO);
 41     mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Append);
 42     return redirection;
 43 }
 44 
 45 static mshell_table_redirection_t mshell_redirection_table[] = {
 46     /** args                    func */
 47     {MSHELL_REDIRECTION_READ,    mshell_redirection_Read},
 48     {MSHELL_REDIRECTION_WRITE,    mshell_redirection_Write},
 49     {MSHELL_REDIRECTION_APPEND,    mshell_redirection_Append},
 50 };
 51 
 52 mshell_redirection_t *mshell_redirection_Parse(
 53         mshell_redirection_t **redirection,
 54         int num,
 55         char *args,
 56         mshell_error_t *error)
 57 {
 58     int len = sizeof(mshell_redirection_table) / sizeof(mshell_table_redirection_t);
 59     int i;
 60 
 61     for(i = 0; i < len; i++) {
 62         if(!strcmp(args, mshell_redirection_table[i].type)) {
 63             char *file = strtok(NULL, " ");
 64             if(NULL == file) {
 65                 *error = MSHELL_ERROR_REDIRECION_PARAM;
 66                 return NULL;
 67             }
 68             else
 69             {
 70                 redirection[num] = mshell_redirection_table[i].callback(file);
 71                 if(NULL == redirection[num]){
 72                     *error = MSHELL_ERROR_REDIRECTION_CREATE;
 73                     return NULL;
 74                 }
 75                 else {
 76                     *error = MSHELL_ERROR_NONE;
 77                     return redirection[num];
 78                 }
 79             }
 80         }
 81     }
 82 
 83     return NULL;
 84 }
 85 
 86 void mshell_redirections_Free(mshell_redirection_t **redirections, int num)
 87 {
 88     if(NULL == redirections){
 89         return;
 90     }
 91     int i;
 92     for(i = 0; i < num; i++) {
 93         mshell_redirection_Destroy(redirections[i]);
 94     }
 95 
 96 }
 97 
 98 static void mshell_redirection_ExcuRead(int fd)
 99 {
100     if(dup2(fd, STDIN_FILENO) != STDIN_FILENO) {
101         perror("dup2");
102     }
103 }
104 
105 static void mshell_redirection_ExcuWrite(int fd)
106 {
107     if(dup2(fd, STDOUT_FILENO) != STDOUT_FILENO) {
108         perror("dup2");
109     }
110 }
111 
112 static void mshell_redirection_ExcuAppend(int fd)
113 {
114     if(dup2(fd, STDOUT_FILENO) != STDOUT_FILENO) {
115         perror("dup2");
116     }
117 }
118 
119 static mshell_Table_redirectionExcu_t mshell_redirection_ExcuTable[] = {
120     /** type                            func */
121     {mshell_Redirection_Read,            mshell_redirection_ExcuRead},
122     {mshell_Redirection_Write,            mshell_redirection_ExcuWrite},
123     {mshell_Redirection_Append,            mshell_redirection_ExcuAppend},
124 };
125 
126 /** 對標準輸入、標準輸出和追加進行重定向 */
127 void mshell_redirection_Excu(mshell_redirection_t redirection)
128 {
129     int i;
130     int len = sizeof(mshell_redirection_ExcuTable) / sizeof(mshell_Table_redirectionExcu_t);
131     for(i = 0; i < len; i++) {
132         if(redirection.type == mshell_redirection_ExcuTable[i].type) {
133             mshell_redirection_ExcuTable[i].callback(redirection.fd);
134         }
135     }
136 }
View Code

29.7 程序

  mshell_process.h

 1 #ifndef __MSHELL_PROCESS_H__
 2 #define __MSHELL_PROCESS_H__
 3 
 4 #include "mshell_common.h"
 5 #include <unistd.h>
 6 #include <sys/wait.h>
 7 #include <stdio.h>
 8 #include <stdlib.h>
 9 #include <string.h>
10 
11 typedef enum {
12     MSHELL_PROCESS_FORE = 0,
13     MSHELL_PROCESS_BACK = 1
14 }mshell_process_Flag_t;
15 
16 /** 解析 & 符號,設定程序組標誌為前臺或後臺程序標指 */
17 extern mshell_process_Flag_t mshell_process_BackParse(char *args, int *error);
18 extern pid_t mshell_process_GroupGet(pid_t pid, pid_t group_pid);
19 extern void mshell_process_GroupSet(mshell_process_Flag_t process_flag, pid_t pid);
20 extern void mshell_process_Wait(mshell_process_Flag_t process_flag, pid_t pgid);
21 
22 #endif /* INCLUDE_MSHELL_PROCESS_H_ */
View Code

  mshell_process.c

 1 /*
 2  * mshell_process.c
 3  *
 4  *  Created on: 2018年12月26日
 5  *      Author: homework
 6  *  brief:
 7  *      啟動的 minishell 本身就是一個程序,在一個程序組當中,
 8  *      在 minishell 中啟動的若干個程序中,其中就有一個父程序,也可能還有其他子程序
 9  *      在此基礎上,再做一個程序組
10  *      把 minishell 啟動起來後,做為一個程序組,minishell 為組長程序
11  *      在 minishell 上啟動多個程序,將這些程序作為一個程序組
12  *  1. 把 minishell 單獨設定為一個程序組
13  *  2. 把在 minishell 中啟動的程序設定為一個程序組
14  *      2.1 把在 minishell 中啟動的第一個程序作為程序組的組長
15  *      2.2 後面建立的程序放置進此程序組當中
16  */
17 
18 
19 #include "mshell_process.h"
20 
21 
22 /** 解析 & 符號,設定程序組標誌為前臺或後臺程序標指 */
23 mshell_process_Flag_t mshell_process_BackParse(char *args, int *error)
24 {
25     mshell_process_Flag_t process_flag = MSHELL_PROCESS_FORE;
26     if(!strcmp(args, "&")){
27         process_flag = MSHELL_PROCESS_BACK;
28         *error = 0;
29         return process_flag;
30     }
31 
32     *error = -1;
33     return process_flag;
34 }
35 
36 /** 建立程序組並獲取程序組 ID */
37 pid_t mshell_process_GroupGet(pid_t pid, pid_t group_pid)
38 {
39     if(setpgid(pid, group_pid) < 0) {
40         perror("setpgid error");
41     }
42 
43     return group_pid;
44 }
45 
46 /** 設定前臺程序組 */
47 void mshell_process_GroupSet(mshell_process_Flag_t process_flag, pid_t pid)
48 {
49     if(process_flag == MSHELL_PROCESS_FORE) {
50         tcsetpgrp(0, getpgid(pid));
51     }
52 }
53 
54 void mshell_process_Wait(mshell_process_Flag_t process_flag, pid_t pgid)