【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.mzph.cn/news/666538.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑上常见的绘图软件有哪些?

现在在电脑上绘图很流行&#xff0c;不仅可以随时更改&#xff0c;还可以提高绘图效率&#xff0c;绘图软件中有很多工具。市场上的计算机绘图软件种类繁多。包括艺术设计、工业绘图和3D绘图。那么每个绘图软件都有自己的特点。那么&#xff0c;哪个更适合计算机绘画软件呢&…

路由器、路由器的构成、交换结构

目录 1 路由器 1.1 路由器的结构 “转发”和“路由选择”的区别 1.1.1 输入端口对线路上收到的分组的处理 1.1.2 输出端口将交换结构传送来的分组发送到线路 2.2 交换结构 2.2.1 通过存储器 2.2.2 通过总线 2.2.3 通过纵横交换结构 (crossbar switch fabric) 1 路由器…

算法练习-环形链表(思路+流程图+代码)

难度参考 难度&#xff1a;中等 分类&#xff1a;链表 难度与分类由我所参与的培训课程提供&#xff0c;但需要注意的是&#xff0c;难度与分类仅供参考。且所在课程未提供测试平台&#xff0c;故实现代码主要为自行测试的那种&#xff0c;以下内容均为个人笔记&#xff0c;旨在…

用Jmeter进行接口测试

web接口测试工具&#xff1a; 手工测试的话可以用postman &#xff0c;自动化测试多是用到 Jmeter&#xff08;开源&#xff09;、soupUI&#xff08;开源&商业版&#xff09;。 下面将对前一篇Postman做接口测试中的接口用Jmeter来实现。 一、Jmeter 的使用步骤 打开Jme…

SpringCloud Gateway(4.1.0) 返回503:原因分析与解决方案

文章目录 一、环境版本二、原因分析三、解决方案 一、环境版本 Versionspring-cloud-dependencies2023.0.0spring-cloud-starter-gateway4.1.0Nacosv2.3.0 二、原因分析 在 Spring Cloud Gateway 的早期版本中&#xff0c;Ribbon 被用作默认的负载均衡器。随着Spring Cloud的…

修复wordpress安全漏洞

1. 问题描述&#xff1a; 用wordpress建了一个网站&#xff0c;但是学校反映说存在安全漏洞&#xff0c;通过接口https://xxx.xxx.edu.cn/?rest_route/wp/v2/users/可以访问到一些内容&#xff0c;希望可以关闭这个接口。 2. 解决办法 一共两步 &#xff08;1&#xff09;在fu…

系统架构20 - 统一建模语言UML(上)

统一建模语言 组成要素事物关系 在目前的软件开发方法中&#xff0c;面向对象的方法占据着主导地位。面向对象方法的主导地位也决定着软件开发过程模型化技术的发展&#xff0c;面向对象的建模技术方法也就成为主导的方法。 公认的面向对象建模语言出现于20世纪70年代中期。从1…

vulhub中Adminer ElasticSearch 和 ClickHouse 错误页面SSRF漏洞复现(CVE-2021-21311)

Adminer是一个PHP编写的开源数据库管理工具&#xff0c;支持MySQL、MariaDB、PostgreSQL、SQLite、MS SQL、Oracle、Elasticsearch、MongoDB等数据库。 在其4.0.0到4.7.9版本之间&#xff0c;连接 ElasticSearch 和 ClickHouse 数据库时存在一处服务端请求伪造漏洞&#xff08…

学习ArtTs -- 初见ArkTs

作者&#xff1a;Uncle_Tom 原文链接&#xff1a;学习ArtTs -- 初见ArkTs-云社区-华为云 1. 前言 需要静态分析去检查一个语言&#xff0c;必须对这个语言有深刻的认识&#xff0c;才能有效的对这个语言进行有效的检查。 我常说:“作为一个程序分析员需要比一般的程序员考虑…

反演LAI(二)基于查找表的反演

反演LAI(二)基于查找表的反演 相关波段选取 首先我们使用gf-1数据有四个波段,使用其他高光谱会有几十个波段,但并不是所有波段都需要选用,lai对于不同波段的响应不同。根据上一节的敏感性分析结果,可以发现,400-500,600-700的两个波段对于LAI敏感性更大,因此选取这两…

【人工智能时代】AI赋能编程 | 自动化工具助力高效办公

前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家&#xff1a;https://www.captainbed.cn/z ChatGPT体验地址 文章目录 前言泡泡AI工具卡片思维导图Markdown编辑器 其他工具文件免费处理工具结语 合集…

【C/C++ 11】贪吃蛇游戏

一、题目 贪吃蛇游戏机制是通过控制蛇上下左右移动并吃到食物得分。 蛇头碰到墙壁或者碰到蛇身就游戏结束。 食物随机生成&#xff0c;蛇吃到食物之后蛇身变长&#xff0c;蛇速加快。 二、算法 1. 初始化游戏地图并打印&#xff0c;地图的边缘是墙&#xff0c;地图的每个坐…

Python tkinter (14) —— 按键事件

本文主要介绍Python tkinter 几种按键事件及其示例。 目录 按键事件 响应所有按键事件 窗体绑定事件 响应特殊按键事件 指定按键事件 组合按键事件 总结 tkinter系列文章 python tkinter窗口简单实现 Python tkinter (1) —— Label标签 Python tkinter (2) —— But…

Kafka相关内容复习

为什么要用消息队列 解耦 允许你独立的扩展或修改两边的处理过程&#xff0c;只要确保它们遵守同样的接口约束。 可恢复性 系统的一部分组件失效时&#xff0c;不会影响到整个系统。消息队列降低了进程间的耦合度&#xff0c;所以即使一个处理消息的进程挂掉&#xff0c;加入队…

Transformer 自然语言处理(三)

原文&#xff1a;Natural Language Processing with Transformers 译者&#xff1a;飞龙 协议&#xff1a;CC BY-NC-SA 4.0 第八章&#xff1a;使 transformers 在生产中更高效 在之前的章节中&#xff0c;您已经看到了 transformers 如何被微调以在各种任务上产生出色的结果。…

AI 数字人从制作到变现

最近AI很火&#xff0c;无意中发现一个宝藏专栏《AI数字人从制作到变现》&#xff0c;原价599&#xff0c;现在推广阶段&#xff0c;只需要10元&#xff0c;专栏持续更新中&#xff0c;会有更多的知识后续分享。如有兴趣可以用微信扫描左侧海报二维码&#xff0c;下面我将介绍专…

『运维备忘录』之 Cron 命令详解

运维人员不仅要熟悉操作系统、服务器、网络等只是&#xff0c;甚至对于开发相关的也要有所了解。很多运维工作者可能一时半会记不住那么多命令、代码、方法、原理或者用法等等。这里我将结合自身工作&#xff0c;持续给大家更新运维工作所需要接触到的知识点&#xff0c;希望大…

计算机设计大赛 深度学习 机器视觉 人脸识别系统 - opencv python

文章目录 0 前言1 机器学习-人脸识别过程人脸检测人脸对其人脸特征向量化人脸识别 2 深度学习-人脸识别过程人脸检测人脸识别Metric Larning 3 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习 机器视觉 人脸识别系统 该项目…

ping 不支持代理,命令行测试外网网址请使用 curl 测试,如何测试?

如果你想通过命令行测试外网网址的可达性&#xff0c;并且因为 ping 命令不支持通过代理服务器进行操作&#xff0c;你可以使用 curl 命令来测试。curl 是一个强大的工具&#xff0c;可以用来传输数据&#xff0c;它支持多种协议&#xff0c;包括 HTTP、HTTPS 等&#xff0c;而…

6个国内可用的chat大模型

文心一言 - 一款适合中国人使用的AI智能助理&#xff0c;能够帮助用户进行对话、生成内容等工作&#xff0c;提高工作效率和创作水平 文心一言 文心一言 App 是一款适合中国人的 AI 智能助理&#xff0c;它的功能点主要包括&#xff1a; 工作生活助理&#xff1a;该应用通过简…