当前位置: 首页 > news >正文

【lesson38】让minishell支持重定向

文章目录

  • 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;
}
http://www.lryc.cn/news/293596.html

相关文章:

  • 【安装指南】maven下载、安装与配置详细教程
  • matplotlib-中文乱码问题解决方案
  • Redis(十一)单线程VS多线程
  • 【微服务】Spring Boot集成ELK实用案例
  • 已解决: ImportError: cannot import name ‘relu‘ from ‘keras.layers‘ 问题
  • python-产品篇-火车票分析助手
  • 设计一个可以智能训练神经网络的流程
  • 自然语言处理(02/10):自然语言处理任务和应用程序
  • Jmeter学习系列之三:测试计划详细介绍
  • mermaid使用指南+notion使用实例-持续更新中
  • Pytroch 自写训练模板适合入门版 包含十五种经典的自己复现的一维模型 1D CNN
  • 【30秒看懂大数据】变量
  • Redis - 多集群数据源配置
  • 五大架构风格之四-虚拟机架构风格
  • 在 C# 中 checked 和 unchecked 关键字
  • 【算法分析与设计】跳跃游戏
  • openssl3.2 - helpdoc - P12证书操作
  • 【产业实践】使用YOLO V5 训练自有数据集,并且在C# Winform上通过onnx模块进行预测全流程打通
  • 【操作系统】HeapByteBuffer和DirectByteBuffer的区别
  • C++并发编程 -2.线程间共享数据
  • Kubernetes-资源清单
  • ABAP 笔记--内表结构不一致,无法更新数据库MODIFY和UPDATE
  • 机器学习-3降低损失(Reducing Loss)
  • 蓝桥杯备战(AcWing算法基础课)-高精度-减-高精度
  • AspNet web api 和mvc 过滤器差异
  • HarmonyOS应用/服务发布:打造多设备生态的关键一步
  • 【数据结构】双向带头循环链表实现及总结
  • 创建自己的Hexo博客
  • 音箱、功放播放HDMI音频解决方案之HDMI音频分离器HHA
  • 天猫数据分析:2023年坚果炒货市场年销额超71亿,混合坚果成多数消费者首选