二十九、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 $@ $< 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 }
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
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
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 }
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
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 }
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
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 }
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
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 }
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_ */
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) 55 { 56 if(process_flag == MSHELL_PROCESS_FORE) { 57 waitpid(-pgid, NULL, WUNTRACED); 58 } 59 60 if(process_flag == MSHELL_PROCESS_BACK) { 61 waitpid(-pgid, NULL, WNOHANG); 62 } 63 }