编程内容:
1.完成 echo env export 命令
2.完成前后台进程
3.完成重定向
完整代码如下:
29.1 主函数、通用头文件和Makefile
29.1.1 主函数
mshell_main.c
#include <stdio.h>
#include <stdlib.h>
#include "mshell_handler.h" int main(int argc, char *argv[])
{
mshell_Handler();
}
29.1.2 通用文件
mshell_common.h
#ifndef __MSHELL_COMMON_H__
#define __MSHELL_COMMON_H__ #include <stdio.h>
#include <stdlib.h> typedef enum {
MSHELL_ERROR_NONE = ,
MSHELL_ERROR_PARAM ,
MSHELL_ERROR_MALLOC ,
MSHELL_ERROR_CALLOC ,
MSHELL_ERROR_PROG_CREATE,
MSHELL_ERROR_PROG_DESTROY,
MSHELL_ERROR_JOB_CREATE,
MSHELL_ERROR_JOB_DESTROY,
MSHELL_ERROR_JOB_PROGADD,
MSHELL_ERROR_CMD_NONECMD,
MSHELL_ERROR_REDIRECION_PARAM,
MSHELL_ERROR_REDIRECTION_CREATE,
MSHELL_ERROR_REDIRECTION_PARSE
}mshell_error_t; extern int mshell_args_Total(char **args);
extern void mshell_args_Free(char **args);
#endif
mshell_common.c
#include "mshell_common.h" /** 统计命令行参数的个数 */
int mshell_args_Total(char **args)
{
int i = ;
char *start = args[]; while(NULL != start) {
i++;
start = args[i];
} return i;
} void mshell_args_Free(char **args)
{
if(NULL == args){
return ;
} int i;
int len = sizeof(args);
for(i = ; i < len; i++) {
free(args[i]);
}
#if 0
while(NULL != args[i]){
free(args[i]);
i++;
}
#endif
free(args);
}
29.1.3 Makefile
#PROJECT_ROOT = $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
PROJECT_ROOT = $(shell pwd)
SRC_DIR = $(PROJECT_ROOT)/src
INCLUDE_DIR = $(PROJECT_ROOT)/include
OBJ_DIR = $(PROJECT_ROOT)/obj
BIN_DIR = $(PROJECT_ROOT)/bin # 找出 src 目录下的所有 .c 文件
C_SRCS = $(wildcard $(SRC_DIR)/*.c)
# 将所有的 src 下的 .c 文件替换为 .o 文件
C_OBJS = $(patsubst %c, %o, $(C_SRCS))
TARGET = mshell
SHARE_LIB = libmshell.a C_SRC_MAIN = mshell_main.c CC = gcc
CCFLAGS += fPIC
LDFLAGS += -shared -fPIC
ASFLAGS +=
ARFLAGS = -crs
LIBS_FLAGS = -L$(BIN_DIR) RM = rm -rf CFLAGS += -Wall -g -I$(INCLUDE_DIR)
INCDIR += -I$(INCLUDE_DIR) .PHONY: all clean test all: $(TARGET)
cp $(SHARE_LIB) $(BIN_DIR)
cp $(SRC_DIR)/*.o $(OBJ_DIR)/
$(RM) $(SHARE_LIB) $(SRC_DIR)/*.o $(TARGET): $(SHARE_LIB)
$(CC) $(C_SRC_MAIN) -o $(TARGET) $(CFLAGS) $(INCDIR) $(LIBS_FLAGS) -lmshell $(SHARE_LIB): $(C_OBJS)
$(AR) $(ARFLAGS) $(SHARE_LIB) $(C_OBJS)
cp $(SHARE_LIB) $(BIN_DIR) $(C_OBJS) : %.o:%.c
$(CC) -c $(CFLAGS) $(INCDIR) -o $@ $< clean:
$(RM) mshell
$(RM) $(SHARE_LIB)
$(RM) $(OBJ_DIR)/$(OBJS)/*.o
$(RM) $(SRC_DIR)/*.o
29.2 handler
mshell_handler.c
#include "mshell_handler.h" static mshell_error_t mshell_cmd_Parsed(mshell_job_t *job, char *line, mshell_process_Flag_t *process_flag)
{
/** Create args secondary pointer stored in program */
char **args_tmp = (char **)malloc(MSHELL_ARGS_SIZE * sizeof(char *));
if(NULL == args_tmp) {
return MSHELL_ERROR_MALLOC;
} /** Split the command line */
char *cmd = strtok(line, " "); /** The first parameter is the command itself */
args_tmp[] = (char *)calloc(strlen(cmd + ), sizeof(char));
if(NULL == args_tmp[]) {
return MSHELL_ERROR_MALLOC;
}
strcpy(args_tmp[], cmd); /** Start with the second parameter */
int i = ;
char *cmd_param;
mshell_redirection_t *redirections[MSHELL_REDIRECTION_NUMBER];
int redirection_num = ; while(NULL != (cmd_param = strtok(NULL, " "))) { /** 对命令行进行解析,判断是否为后台进程 */
int process_ret;
*process_flag = mshell_process_BackParse(cmd_param, &process_ret);
if( == process_ret) {
continue;
} /** 分析重定向 */
mshell_error_t redirection_ret;
redirections[redirection_num] =
mshell_redirection_Parse(redirections, redirection_num, cmd_param, &redirection_ret);
if(NULL != redirections[redirection_num] && MSHELL_ERROR_NONE == redirection_ret){
redirection_num++;
continue;
}
else if (NULL == redirections[redirection_num] && MSHELL_ERROR_REDIRECION_PARAM == redirection_ret) {
printf("need param\n");
continue;
}
else if(NULL == redirections[redirection_num] && MSHELL_ERROR_REDIRECTION_CREATE == redirection_ret)
{
perror("error create redirection");
return MSHELL_ERROR_REDIRECTION_CREATE;
} /** 分析命令 */
args_tmp[i] = (char *)calloc(strlen(cmd_param + ), sizeof(char));
if(NULL == args_tmp[i]) {
return MSHELL_ERROR_MALLOC;
}
strcpy(args_tmp[i], cmd_param);
i++;
}
args_tmp[i] = NULL; /** Store all command line parameters in program and free args_tmp*/
mshell_prog_t *prog = mshell_prog_Create(args_tmp);
if(NULL == prog) {
return MSHELL_ERROR_PROG_CREATE;
}
mshell_args_Free(args_tmp); /** Add redirection to job and free redirections*/
for(i = ; i < redirection_num; i++){
mshell_prog_RedirectionAdd(prog, redirections[i]);
}
mshell_redirections_Free(redirections, redirection_num); /** Add program to the job*/
if(MSHELL_ERROR_NONE != mshell_job_AddProg(job, prog)) {
return MSHELL_ERROR_JOB_PROGADD;
} #if 0
/** free args_tmp */
mshell_args_Free(args_tmp);
#endif
return ;
} static void mshell_cmd_ExcuProcess(mshell_job_t job, int order, mshell_process_Flag_t process_flag)
{
pid_t pid;
if((pid = fork()) < ) {
perror("fork error");
}
else if(pid == ) {
/** child process */
if(order == ) {
/** order = 0, 则为 minishell 当中启动的第一个子进程,设置其为组长进程 */
job.pgid = mshell_process_GroupGet(getpid(), getpid());
}
else {
/** order > 0, 则为启动的第二个进程,将其设置进程组的成员进程 */
job.pgid = mshell_process_GroupGet(getpid(), job.pgid);
}
mshell_process_GroupSet(process_flag, getpid());
/** 对便准输入、标准输出和追加进行重定向 */
mshell_prog_RedirectionExcu(job.progs[order]); /** 调用 exec 函数执行系统中的其他命令 */
if(MSHELL_ERROR_CMD_NONECMD == mshell_Cmd_ExcuOther(job.progs[order].args))
exit();
}
else {
/** parent process */
if(order == ) {
job.pgid = mshell_process_GroupGet(pid, pid);
}
else {
job.pgid = mshell_process_GroupGet(pid, job.pgid);
}
mshell_process_GroupSet(process_flag, job.pgid); mshell_process_Wait(process_flag, job.pgid); #if 0
/** 等待指定的子进程结束, 阻塞版本,支持作业控制 */
if(waitpid(pid, NULL, WUNTRACED) < ) {
perror("waitpid error");
}
#endif
} } static mshell_error_t mshell_cmd_Excu(mshell_job_t *job, mshell_process_Flag_t process_flag)
{
int ret = MSHELL_ERROR_NONE;
int i;
for(i = ; i < job->progs_num; i++)
{
ret = mshell_Cmd_ExcuFun(job->progs[i].args);
if(MSHELL_ERROR_NONE == ret || MSHELL_ERROR_PARAM == ret) {
return MSHELL_ERROR_NONE;
} /** 执行其他命令 */
mshell_cmd_ExcuProcess(*job, i, process_flag);
#if 0
pid_t pid;
if((pid = fork()) < ) {
perror("fork error");
}
else if(pid == ) {
/** child process */
/** 调用 exec 函数执行系统中的其他命令 */
if(MSHELL_ERROR_CMD_NONECMD == mshell_Cmd_ExcuOther(job->progs[i].args))
exit();
}
else {
/** parent process */
/** 等待指定的子进程结束, 阻塞版本,支持作业控制 */
if(waitpid(pid, NULL, WUNTRACED) < ) {
perror("waitpid error");
}
}
#endif
} return ;
} mshell_error_t mshell_Handler()
{
/**创建一个进程组,将 minishell 进程设置为进程组的组长 */
setpgid(getpid(), getpid()); char buffer[MSHELL_COMMAND_LEN];
memset(buffer, , MSHELL_COMMAND_LEN); ssize_t size = strlen(MSHELL_PROMPT) * sizeof(char);
write(STDOUT_FILENO, MSHELL_PROMPT, size); mshell_process_Flag_t process_flag; ///< 设置前台和后台进程的标志
ssize_t len;
while() { len = read(STDIN_FILENO, buffer, MSHELL_COMMAND_LEN); ///< 从命令行读取内容到 buffer
buffer[len - 1] = 0;
if(strlen(buffer) > ){
mshell_job_t *job = mshell_job_Create(buffer);
if(NULL == job) {
return MSHELL_ERROR_JOB_CREATE;
} mshell_cmd_Parsed(job, buffer, &process_flag);
mshell_cmd_Excu(job, process_flag);
//mshell_job_Destroy(job);
} write(STDOUT_FILENO, MSHELL_PROMPT, size);
memset(buffer, , MSHELL_COMMAND_LEN);
}
}
mshell_handler.h
#ifndef __MSHELL_HANDLER_H__
#define __MSHELL_HANDLER_H__ #include "mshell_common.h"
#include "mshell_process.h"
#include "mshell_cmd_fun.h"
#include "mshell_program.h"
#include "mshell_job.h"
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <unistd.h>
#include <string.h>
#include <memory.h>
#include <sys/wait.h> #define MSHELL_PROMPT "mshell =>"
#define MSHELL_COMMAND_LEN 256
#define MSHELL_ARGS_SIZE 100 mshell_error_t mshell_Handler(); #endif
29.3 作业
mshell_job.h
#ifndef __MSHELL_JOB_H__
#define __MSHELL_JOB_H__ #include "mshell_common.h"
#include "mshell_program.h"
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h> /** job struct, A job contains several programs to execute */
typedef struct {
char *cmd; ///< String commands to be executed
pid_t pgid; ///< 进程组的 ID
int progs_num; ///< Number of programs to execute
mshell_prog_t *progs; ///< Point to several programs to be executed
}mshell_job_t; extern mshell_job_t* mshell_job_Create(char *cmd);
extern void mshell_job_Destroy(mshell_job_t *job);
extern mshell_error_t mshell_job_AddProg(mshell_job_t *job, mshell_prog_t *prog);
#endif
mshell_job.c
#include "mshell_common.h"
#include "mshell_program.h"
#include "mshell_job.h" mshell_job_t* mshell_job_Create(char *cmd)
{
mshell_job_t *job = (mshell_job_t *)malloc(sizeof(mshell_job_t));
if(NULL == job)
{
return NULL;
} job->cmd = (char *)malloc(sizeof(char) * strlen(cmd));
if(NULL == job->cmd)
{
return NULL;
} strcpy(job->cmd, cmd);
job->progs_num = ;
job->progs = NULL; return job;
}
void mshell_job_Destroy(mshell_job_t *job)
{
if(NULL == job)
{
return ;
}
free(job->progs);
free(job->cmd);
free(job);
} mshell_error_t mshell_job_AddProg(mshell_job_t *job, mshell_prog_t *prog)
{
mshell_prog_t *prog_tmp = (mshell_prog_t *)malloc(sizeof(mshell_prog_t) * (job->progs_num + ));//1 为NULL的初始化
if(NULL == prog_tmp) {
return MSHELL_ERROR_MALLOC;
} memcpy(prog_tmp, job->progs, job->progs_num * sizeof(mshell_prog_t));
prog_tmp[job->progs_num++] = *prog;
free(job->progs);
job->progs = prog_tmp; return MSHELL_ERROR_NONE;
}
29.4 程序
mshell_program.h
#ifndef __MSHELL_PROGRAM_H__
#define __MSHELL_PROGRAM_H__ #include "mshell_common.h"
#include "mshell_redirection.h"
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h> /** program struct */
typedef struct {
/**
* Command-line parameters obtained from the terminal
* Char*argv[] parameter corresponding to the main function
*/
char **args;
pid_t pid; ///< 进程 ID
int redirection_num; ///< 重定向的数量
mshell_redirection_t *redirecitons; ///< 重定向结构体数组
}mshell_prog_t; extern mshell_prog_t* mshell_prog_Create(char **args);
extern void mshell_prog_Destroy(mshell_prog_t *prog);
extern void mshell_prog_RedirectionAdd(mshell_prog_t *prog, mshell_redirection_t *redirection);
extern void mshell_prog_RedirectionExcu(mshell_prog_t prog);
#endif
mshell_program.c
#include "mshell_program.h" /**
* Init program's pointer array
*/
static mshell_prog_t * mshell_prog_ArgsInit(mshell_prog_t *prog, char **args, int counter)
{
int i; for(i = ; i < counter; i++) {
int len = strlen(args[i]);
prog->args[i] = (char *)malloc(len);
if(NULL == prog->args[i]){
return NULL;
} strcpy(prog->args[i], args[i]);
}
return prog;
} mshell_prog_t * mshell_prog_Create(char **args)
{
mshell_prog_t *prog = (mshell_prog_t *)malloc(sizeof(mshell_prog_t));
if(NULL == prog){
return NULL;
} /** Init program's redirection */
prog->redirection_num = ;
prog->redirecitons = NULL; /** Init program's pointer array */
int args_num = mshell_args_Total(args);
prog->args = (char **)calloc(args_num + , sizeof(char *));
prog = mshell_prog_ArgsInit(prog, args, args_num);
return prog;
} void mshell_prog_Destroy(mshell_prog_t *prog)
{
if(NULL == prog) {
return ;
} mshell_args_Free(prog->args);
free(prog->redirecitons);
free(prog);
} void mshell_prog_RedirectionAdd(mshell_prog_t *prog, mshell_redirection_t *redirection)
{
mshell_redirection_t *redirections = (mshell_redirection_t *)calloc(prog->redirection_num + , sizeof(mshell_redirection_t));
if(NULL == redirections){
return;
} if(NULL != prog->redirecitons) {
memcpy(redirections, prog->redirecitons, prog->redirection_num * sizeof(redirections));
free(redirections);
} prog->redirecitons = redirections;
memcpy(&prog->redirecitons[prog->redirection_num], redirection, sizeof(mshell_redirection_t));
prog->redirection_num += ;
} void mshell_prog_RedirectionExcu(mshell_prog_t prog)
{
int i;
for(i = ; i < prog.redirection_num; i++) {
mshell_redirection_Excu(prog.redirecitons[i]);
}
}
29.5 命令
mshell_cmd_fun.h
#ifndef __MSHELL_CMD_FUN_H__
#define __MSHELL_CMD_FUN_H__ #include "mshell_common.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h> #define MSHELL_CMD_CD "cd"
#define MSHELL_CMD_PWD "pwd"
#define MSHELL_CMD_EXIT "exit"
#define MSHELL_CMD_ENV "env"
#define MSHELL_CMD_ECHO "echo"
#define MSHELL_CMD_EXPORT "export" typedef void (* mshell_cmd_Fun)(char *args);
typedef struct {
char *cmd;
mshell_cmd_Fun callback;
}mshell_funs_t; mshell_error_t mshell_Cmd_ExcuFun(char **args);
mshell_error_t mshell_Cmd_ExcuOther(char **args);
#endif
mshell_cmd_fun.c
#include "mshell_cmd_fun.h" extern char** environ; static void mshell_cmd_Cd(char *args)
{
if(chdir(args) < ) {
perror("cd error");
}
} static void mshell_cmd_Pwd(char *args)
{
char buffer[];
memset(buffer, , sizeof(buffer));
if(getcwd(buffer, sizeof(buffer)) == NULL){
perror("pwd error");
} printf("%s\n", buffer);
} static void mshell_cmd_Exit(char *args)
{
exit();
} static void mshell_mcd_Env(char *args)
{
int i = ;
char *env = NULL; while(NULL != (env = environ[i])) {
printf("%s\n", env);
i++;
}
} static void mshell_mcd_Echo(char *args)
{
char *arg_tmp = args;
if(NULL == arg_tmp) {
fprintf(stderr, "echo: invalid argument\n");
return;
} if('$' == arg_tmp[]) {
char *env_tmp = getenv(arg_tmp + );
printf("%s\n", env_tmp);
}
else {
printf("%s\n", arg_tmp);
}
} static void mshell_mcd_Export(char *args)
{
if(NULL == args) {
fprintf(stderr, "export: invalid argument\n");
return;
} putenv(args);
} static mshell_funs_t mshell_table_fun[] = {
/** cmd func */
{MSHELL_CMD_CD , mshell_cmd_Cd},
{MSHELL_CMD_PWD , mshell_cmd_Pwd},
{MSHELL_CMD_EXIT, mshell_cmd_Exit},
{MSHELL_CMD_ENV , mshell_mcd_Env},
{MSHELL_CMD_ECHO, mshell_mcd_Echo},
{MSHELL_CMD_EXPORT, mshell_mcd_Export},
}; mshell_error_t mshell_Cmd_ExcuFun(char **args)
{
if(NULL == args) {
return MSHELL_ERROR_PARAM;
}
int len = sizeof(mshell_table_fun) / sizeof(mshell_funs_t);
int i;
for(i = ; i < len; i++) {
if(!strcmp(args[], mshell_table_fun[i].cmd)){
mshell_table_fun[i].callback(args[]);
return MSHELL_ERROR_NONE;
}
} return MSHELL_ERROR_CMD_NONECMD;
} mshell_error_t mshell_Cmd_ExcuOther(char **args)
{
/** excu 函数成功执行不返回,出错会返回 -1 */
if(execvp(args[], args) < ) {
perror("execvp error");
/** 这里退出后,让后面的程序继续执行 */
return MSHELL_ERROR_CMD_NONECMD;
} return MSHELL_ERROR_NONE;
}
29.6 重定向
mshell_redirection.h
#ifndef __MSHELL_REDIRECTION_H__
#define __MSHELL_REDIRECTION_H__ #include "mshell_common.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h> #define MSHELL_REDIRECTION_NUMBER 5 #define MSHELL_REDIRECTION_READ "<"
#define MSHELL_REDIRECTION_WRITE ">"
#define MSHELL_REDIRECTION_APPEND ">>" typedef enum {
mshell_Redirection_Read,
mshell_Redirection_Write,
mshell_Redirection_Append
}mshell_redirection_type_t; typedef struct {
mshell_redirection_type_t type;
int fd;
}mshell_redirection_t; typedef mshell_redirection_t* (* mshell_redirection_fun)(char *file);
typedef struct {
char *type;
mshell_redirection_fun callback;
}mshell_table_redirection_t; typedef void (* mshell_redirection_ExcuFun)(int fd);
typedef struct {
mshell_redirection_type_t type;
mshell_redirection_ExcuFun callback;
}mshell_Table_redirectionExcu_t; extern mshell_redirection_t *mshell_redirection_Create(int fd, mshell_redirection_type_t type);
extern void mshell_redirection_Destroy(mshell_redirection_t *redirection);
extern mshell_redirection_t *mshell_redirection_Parse(
mshell_redirection_t **redirection,
int num,
char *args,
mshell_error_t *error);
extern void mshell_redirections_Free(mshell_redirection_t **redirections, int num);
extern void mshell_redirection_Excu(mshell_redirection_t redirection);
#endif
mshell_redirection.c
#include "mshell_redirection.h" mshell_redirection_t *mshell_redirection_Create(int fd, mshell_redirection_type_t type)
{
mshell_redirection_t *redirection = (mshell_redirection_t *)calloc(, sizeof(mshell_redirection_t));
if(NULL == redirection){
return NULL;
} redirection->fd = fd;
redirection->type = type;
return redirection;
} void mshell_redirection_Destroy(mshell_redirection_t *redirection)
{
if(NULL == redirection) {
return;
}
free(redirection);
} static mshell_redirection_t *mshell_redirection_Read(char *file)
{
int fd = open(file, O_RDONLY);
mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Read);
return redirection;
} static mshell_redirection_t *mshell_redirection_Write(char *file)
{
int fd = open(file, O_WRONLY | O_CREAT | O_TRUNC, S_IRWXU | S_IRWXG | S_IRWXO);
mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Write);
return redirection;
} static mshell_redirection_t *mshell_redirection_Append(char *file)
{
int fd = open(file, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU | S_IRWXG | S_IRWXO);
mshell_redirection_t *redirection = mshell_redirection_Create(fd, mshell_Redirection_Append);
return redirection;
} static mshell_table_redirection_t mshell_redirection_table[] = {
/** args func */
{MSHELL_REDIRECTION_READ, mshell_redirection_Read},
{MSHELL_REDIRECTION_WRITE, mshell_redirection_Write},
{MSHELL_REDIRECTION_APPEND, mshell_redirection_Append},
}; mshell_redirection_t *mshell_redirection_Parse(
mshell_redirection_t **redirection,
int num,
char *args,
mshell_error_t *error)
{
int len = sizeof(mshell_redirection_table) / sizeof(mshell_table_redirection_t);
int i; for(i = ; i < len; i++) {
if(!strcmp(args, mshell_redirection_table[i].type)) {
char *file = strtok(NULL, " ");
if(NULL == file) {
*error = MSHELL_ERROR_REDIRECION_PARAM;
return NULL;
}
else
{
redirection[num] = mshell_redirection_table[i].callback(file);
if(NULL == redirection[num]){
*error = MSHELL_ERROR_REDIRECTION_CREATE;
return NULL;
}
else {
*error = MSHELL_ERROR_NONE;
return redirection[num];
}
}
}
} return NULL;
} void mshell_redirections_Free(mshell_redirection_t **redirections, int num)
{
if(NULL == redirections){
return;
}
int i;
for(i = ; i < num; i++) {
mshell_redirection_Destroy(redirections[i]);
} } static void mshell_redirection_ExcuRead(int fd)
{
if(dup2(fd, STDIN_FILENO) != STDIN_FILENO) {
perror("dup2");
}
} static void mshell_redirection_ExcuWrite(int fd)
{
if(dup2(fd, STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
}
} static void mshell_redirection_ExcuAppend(int fd)
{
if(dup2(fd, STDOUT_FILENO) != STDOUT_FILENO) {
perror("dup2");
}
} static mshell_Table_redirectionExcu_t mshell_redirection_ExcuTable[] = {
/** type func */
{mshell_Redirection_Read, mshell_redirection_ExcuRead},
{mshell_Redirection_Write, mshell_redirection_ExcuWrite},
{mshell_Redirection_Append, mshell_redirection_ExcuAppend},
}; /** 对标准输入、标准输出和追加进行重定向 */
void mshell_redirection_Excu(mshell_redirection_t redirection)
{
int i;
int len = sizeof(mshell_redirection_ExcuTable) / sizeof(mshell_Table_redirectionExcu_t);
for(i = ; i < len; i++) {
if(redirection.type == mshell_redirection_ExcuTable[i].type) {
mshell_redirection_ExcuTable[i].callback(redirection.fd);
}
}
}
29.7 进程
mshell_process.h
#ifndef __MSHELL_PROCESS_H__
#define __MSHELL_PROCESS_H__ #include "mshell_common.h"
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h> typedef enum {
MSHELL_PROCESS_FORE = ,
MSHELL_PROCESS_BACK =
}mshell_process_Flag_t; /** 解析 & 符号,设置进程组标志为前台或后台进程标指 */
extern mshell_process_Flag_t mshell_process_BackParse(char *args, int *error);
extern pid_t mshell_process_GroupGet(pid_t pid, pid_t group_pid);
extern void mshell_process_GroupSet(mshell_process_Flag_t process_flag, pid_t pid);
extern void mshell_process_Wait(mshell_process_Flag_t process_flag, pid_t pgid); #endif /* INCLUDE_MSHELL_PROCESS_H_ */
mshell_process.c
/*
* mshell_process.c
*
* Created on: 2018年12月26日
* Author: homework
* brief:
* 启动的 minishell 本身就是一个进程,在一个进程组当中,
* 在 minishell 中启动的若干个进程中,其中就有一个父进程,也可能还有其他子进程
* 在此基础上,再做一个进程组
* 把 minishell 启动起来后,做为一个进程组,minishell 为组长进程
* 在 minishell 上启动多个进程,将这些进程作为一个进程组
* 1. 把 minishell 单独设置为一个进程组
* 2. 把在 minishell 中启动的进程设置为一个进程组
* 2.1 把在 minishell 中启动的第一个进程作为进程组的组长
* 2.2 后面创建的进程放置进此进程组当中
*/ #include "mshell_process.h" /** 解析 & 符号,设置进程组标志为前台或后台进程标指 */
mshell_process_Flag_t mshell_process_BackParse(char *args, int *error)
{
mshell_process_Flag_t process_flag = MSHELL_PROCESS_FORE;
if(!strcmp(args, "&")){
process_flag = MSHELL_PROCESS_BACK;
*error = ;
return process_flag;
} *error = -;
return process_flag;
} /** 创建进程组并获取进程组 ID */
pid_t mshell_process_GroupGet(pid_t pid, pid_t group_pid)
{
if(setpgid(pid, group_pid) < ) {
perror("setpgid error");
} return group_pid;
} /** 设置前台进程组 */
void mshell_process_GroupSet(mshell_process_Flag_t process_flag, pid_t pid)
{
if(process_flag == MSHELL_PROCESS_FORE) {
tcsetpgrp(, getpgid(pid));
}
} void mshell_process_Wait(mshell_process_Flag_t process_flag, pid_t pgid)
{
if(process_flag == MSHELL_PROCESS_FORE) {
waitpid(-pgid, NULL, WUNTRACED);
} if(process_flag == MSHELL_PROCESS_BACK) {
waitpid(-pgid, NULL, WNOHANG);
}
}