文章目录
- minishell支持重定向
- minishell完整代码
minishell支持重定向
支持重定向的核心逻辑:
1.分析字符串是否含有重定向的符号,并且提取文件名。
#define INPUT_REDIR 0 //输入重定向
#define OUTPUT_REDIR 1 //输出重定向
#define APPEND_REDIR 2 //追加重定向
#define NONE_REDIR 4 //没有重定向
int redir_status = NONE_REDIR;//状态char* CheckRedir(char* start)
{ assert(start); char* end = start + strlen(start)-1; //end执行指令的最后一个内容 while(start < end) { if(*end == '>') { if(*(end -1) == '>') { //ls -a -l>>log.txt\0 追加redir_status = APPEND_REDIR; *(end-1) = '\0'; end++; break; } //ls -a -l>log.txt\0 输出redir_status = OUTPUT_REDIR; *(end) = '\0'; end++; break;}else if(*end == '<'){//ls -a -l<log.txt\0 输入redir_status = INPUT_REDIR;*end = '\0';end++;break;}else {end--;}}//循环结束,如果end还是大于start,说明存在重定向if(end > start){return end;}//走到这说明不存在重定向return NULL;
}
例子:
end开始向前找重定向符
然后end++
这样end指向的就是文件名,start执行的就是指令内容。
然后就开始在子进程进行重定向了。
//printf("parent process create subprocess success\n"); if(sep) { int fd = -1; switch(redir_status) { case INPUT_REDIR: fd = open(sep,O_RDONLY); dup2(fd,0); break; case OUTPUT_REDIR: fd = open(sep,O_WRONLY | O_CREAT | O_TRUNC,0666); dup2(fd,1); break; case APPEND_REDIR: fd = open(sep,O_WRONLY | O_CREAT | O_APPEND,0666); dup2(fd,1); break; default: assert(NULL); break; } }
minishell完整代码
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <assert.h>#define NUM 1024
#define SIZE 32
#define SEP " "#define INPUT_REDIR 0
#define OUTPUT_REDIR 1
#define APPEND_REDIR 2
#define NONE_REDIR 4
int redir_status = NONE_REDIR;char cmd_line[NUM];//array for saving command line
char* g_argv[SIZE];//the array are used to store paresed commands
char g_myval[64];char* CheckRedir(char* start)
{assert(start);char* end = start + strlen(start)-1;while(start < end) {if(*end == '>'){if(*(end -1) == '>'){//ls -a -l>>log.txt\0redir_status = APPEND_REDIR;*(end-1) = '\0';end++;break;}//ls -a -l>log.txt\0 redir_status = OUTPUT_REDIR;*(end) = '\0';end++;break;}else if(*end == '<'){//ls -a -l<log.txt\0redir_status = INPUT_REDIR;*end = '\0';end++;break;}else {end--;}}if(end > start){return end;}return NULL;
}
int main()
{//1.命令行解释器,一定是一个常驻内存的进程,不退出while(1) {//2.显示提示行printf("[xiaolin@localhost myshell]#");fflush(stdout);memset(cmd_line,'\0',sizeof cmd_line);//3.获取用户输入的字符串if(fgets(cmd_line,sizeof cmd_line,stdin) == NULL){//if cmd_line empty contiue get commandcontinue;}cmd_line[strlen(cmd_line)-1] = '\0';char* sep = CheckRedir(cmd_line);//4.对字符串进行解析int index = 0;g_argv[index++] = strtok(cmd_line,SEP);//Firest parse cmd_line while(1)//Second parse cmd_line don't pass cmdline;{g_argv[index] = strtok(NULL,SEP);if(g_argv[index] == NULL) break;index++;}if(strcmp(g_argv[0],"ls") == 0){g_argv[index++] = (char*)"--color=auto";g_argv[index] = NULL;} if(strcmp(g_argv[0],"ll") == 0){ g_argv[0] = (char*)"ls";g_argv[1] = (char*)"-l";g_argv[2] = (char*)"--color=auto";g_argv[3] = NULL;}// processing of built-in commandsif(strcmp(g_argv[0],"cd") == 0){//chdir() changes the current working directory of the calling process to the directory specified in path.if(g_argv[1] != NULL) chdir(g_argv[1]);continue;}if(strcmp(g_argv[0],"export") == 0 && g_argv[1] != NULL){//There is a very hidden issue here//Ptuenv passes an environment variable as a pointer to it //And g_ Argv [1] will be cleared on the next command_line read//In this way, the environment variable pointer points to a place with empty data, and this pointer is also a null pointer//int res = putenv(g_argv[1]);//if(res == 0) printf("export success\n");//else printf("export fail\n");//solve the problemstrcpy(g_myval,g_argv[1]);int res = putenv(g_myval);if(res == 0) printf("export success\n");else printf("expor fail\n");continue;}/*//test if the g_argv array id correct for(index = 0; g_argv[index]; index++){printf("g_argv[%d]:%s\n",index,g_argv[index]);}*///5.create subprocess execute commandpid_t id = fork();if(id == 0){//subprocess//printf("parent process create subprocess success\n");if(sep){int fd = -1;switch(redir_status){case INPUT_REDIR:fd = open(sep,O_RDONLY);dup2(fd,0);break;case OUTPUT_REDIR:fd = open(sep,O_WRONLY | O_CREAT | O_TRUNC,0666);dup2(fd,1);break;case APPEND_REDIR:fd = open(sep,O_WRONLY | O_CREAT | O_APPEND,0666);dup2(fd,1);break;default:assert(NULL); break;}}printf("subprocess starts running\n");execvp(g_argv[0],g_argv);printf("subprocess replace fail\n");}else if(id > 0){//parent processint status = 0;pid_t res = waitpid(-1,&status,0);//blocking waitingif(res == -1){printf("parent process wait subprocess fail\n");}else if(res > 0){printf("parent process wait subprocess success exit_code:%d\n",WEXITSTATUS(status));}else {printf("unkown error\n");}}else{//failprintf("parent procrss create subprocess fail\n");}}return 0;
}