【Linux】文件重定向与实现支持文件重定向的minishell

news2024/12/23 9:46:37


目录

0.前提

​编辑

1.重定向

1.1重定向的本质

1.2dup2

1.3模拟实现输出重定向 >

1.4模拟实现追加重定向 >>

1.5模拟实现输入重定向 <

2.让minishell支持重定向


0.前提

文件描述符的分配规则:

在文件描述符表里面,从小到大按照顺序寻找最小的且没有被占用的fd。


1.重定向

1.1重定向的本质

上层使用的fd不变,在内核中更改fd对应的struct file*的地址。

1.2dup2

让newfd变成oldfd的拷贝,如果需要关闭newfd.

1.3模拟实现输出重定向 >

1.4模拟实现追加重定向 >>

1.5模拟实现输入重定向 <

2.让minishell支持重定向

#include<stdio.h>
#include<string.h>
#include<assert.h>
#include<unistd.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<fcntl.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<errno.h>

#define B_NUM 1024
#define ARGV_NUM 10
#define NONE_REDIR 0
#define INPUT_REDIR 1
#define OUTPUT_REDIR 2
#define APPEND_REDIR 3



char buffer[B_NUM];
char* myargv[ARGV_NUM];
int quitcode=0;
int quitsignal=0;

int redirType=NONE_REDIR;
char* refilename=NULL;


void Commandcheck(char* command)
{
  assert(command);
  //判断是否有重定向,有是哪种
  char* begin=command;
  char* end=command+sizeof command-1;
  
  while(begin<end)
  //while((*begin)!='\0')
  {
    if(*begin=='>')
    {
      *begin='\0';
      begin++;
      if(*begin=='>')
      {
         redirType=APPEND_REDIR;
         begin+=2;
         refilename=begin;
      }
      else{
        redirType=OUTPUT_REDIR;
        refilename=(++begin);
        break;
      }
    }
    if(*begin=='<')
    {
      *begin='\0';
       redirType=INPUT_REDIR;
       begin+=2;
       refilename=begin;
       break;
    }
    begin++;
  }
  return ;
}

int main()
{

  while(1)
  {
    redirType=NONE_REDIR;
    refilename=NULL;
    errno=0;
   
    printf("【用户名@服务器 当前目录】$");
    fflush(stdout);

    char* s=fgets(buffer,sizeof (buffer)-1,stdin);
    assert(s!=NULL);
    buffer[strlen (buffer)-1]=0;
    (void)s;
   
    //和重定向区分开
    Commandcheck(buffer);
    
   // printf("切割成功:命令 %s 文件 %s\n",buffer,refilename);


    //切割字符串
    myargv[0]=strtok(buffer," ");
    int i=0;

    if(myargv[0] != NULL && strcmp(myargv[0], "ls") == 0)
    {
      myargv[++i] = (char*)"--color=auto";
    }

    while(myargv[i]!=NULL)
    {
      myargv[++i]=strtok(NULL," ");
    }

    //实现cd功能
    if(myargv[0] != NULL &&strcmp(myargv[0],"cd")==0)
    {
      if(myargv[1]!=NULL)
      {

        chdir(myargv[1]);
      }
      continue;
    }
    //实现echo $?功能
    if(myargv[0]!=NULL&&myargv[1]!=NULL&&strcmp(myargv[0],"echo")==0)
    {
      if(strcmp(myargv[1],"$?")==0)
      {
        //输出上一个进程的退出码
        printf("退出码为:%d\n",quitcode);

      }
      else
      {
        printf("%s\n",myargv[1]);
      }
      continue;

    }

    pid_t id =fork();
    assert(id!=-1);
    if(id==0)
    {
      //子进程

      //如果有文件打开文件
      switch(redirType)
      {
        case NONE_REDIR:
          break;
        case INPUT_REDIR:
          {
          int fd=open(refilename,O_RDONLY);
            if(fd < 0){           
               perror("open");
               exit(errno);
            }
          dup2(fd,0);
          }
          break;
        case OUTPUT_REDIR:
        case APPEND_REDIR:
          {
            
          int flag=O_WRONLY|O_CREAT;
          if(redirType==OUTPUT_REDIR)
          {
            flag|=O_TRUNC;
          }
          else{
            flag|=O_APPEND;
          }
          umask(0);
          int fd=open(refilename,flag,0666);
            if(fd < 0){            
               perror("open");
               exit(errno);
            }
          dup2(fd,1);
          }
          break;
       default:
          break;

      }


      //程序替换
      execvp(myargv[0],myargv); 
      //如果走到这里表示替换失败
      exit(1);
    }

   //父进程
   int status=0;
   pid_t ret= waitpid(id,&status,0);
   assert(ret > 0);
   (void)ret;
   quitcode=(status>>8)&0XFF;
   quitsignal= (status & 0x7F);

  }
  return 0;
}

注意:每次父进程循环都要记得刷新 redirType 、redirFile、errno 


最后

加油

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1431962.html

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

相关文章

linux中的mtime,ctime,atime

目录 结论 文件 touch新文件 调整文件内容 echo直接修改 vi修改 修改文件属性 调整归属 调整权限 读取文件 目录 增加文件 调整目录下文件属性 访问目录下文件 删除文件 结论 mtime&#xff1a;文件内容的修改时间&#xff08;不含权限、属组修改&#xff09; …

计算机网络-封装成帧透明传输(组帧方法)

文章目录 数据链路层功能概述封装成帧透明传输组帧方法字符计数法字符填充法零比特填充法违规编码法 字符填充法为啥复杂和不兼容 数据链路层功能概述 类似老板让小秘书送文件给别的公司&#xff0c;小秘书告诉傻子怎么把该文件送到别的公司的小秘书&#xff0c;然后别的公司的…

基于springboot就业信息管理系统源码和论文

随着信息化时代的到来&#xff0c;管理系统都趋向于智能化、系统化&#xff0c;就业信息管理系统也不例外&#xff0c;但目前国内仍都使用人工管理&#xff0c;市场规模越来越大&#xff0c;同时信息量也越来越庞大&#xff0c;人工管理显然已无法应对时代的变化&#xff0c;而…

挑战杯 python 机器视觉 车牌识别 - opencv 深度学习 机器学习

1 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 基于python 机器视觉 的车牌识别系统 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;3分 &#x1f9ff; 更多资…

【王者荣耀】:背后的技术之谜,揭秘游戏背后的实现奥秘!

目录 1、引言 2、游戏引擎 3、网络技术 4、图形渲染 5、操作控制 6、AI算法 7、数据管理 8、安全防护 9、优化与性能 10、未来发展 11、结语 1、引言 随着智能手机的普及和移动互联网的发展&#xff0c;手机游戏已经成为人们日常娱乐的重要组成部分。而在众多手机游…

Oracle Server一台价值百万的服务器内存更换过程

数据库代码敲多了&#xff0c;看乏了吧&#xff01; 带各位DBA看看你们的数据库运行在什么样的硬件上。 1、故障现象 事发时2号位置报警 登录ILO发现内存报警 查看详细信息 查看详细报警 2、关于ORACLE 服务器DIMM 备用 默认情况下在 Oracle ILOM 中启用 DIMM 备用。由 DIMM 提…

MySQL的原生API实现插入数据后在可视化工具上不显示的问题解决

显示表中有两行数据&#xff0c;该表也设置了主键和唯一索引 点进表里看却没有数据 问题原因出现在这里&#xff0c;虽然很多常用的数据库连接池都会开启自动提交&#xff0c;但ibatis的SqlSession使用sessionFactory.openSession()创建时&#xff0c;默认的自动提交是false&am…

vcruntime140.dll最新的修复方法,一键修复vcruntime140.dll的手段

在这篇文章中&#xff0c;我们将深入探讨并详细介绍各种修复vcruntime140.dll文件缺失或损坏问题的方法。鉴于此类问题广泛存在并影响了众多用户&#xff0c;本文目的是向大家展示不同的修复策略&#xff0c;希望能够帮助每个人解决这些棘手的技术难题。下面一起来看看vcruntim…

02-单例模式 ( Singleton Pattern )

单例模式 单例模式设计要点单例模式基础实现摘要实现范例 单例模式的几种实现方式1. 懒汉式&#xff0c;线程不安全2. 懒汉式&#xff0c;线程安全3. 饿汉式4. 双检锁/双重校验锁&#xff08;DCL&#xff0c;即 double-checked locking&#xff09;5. 登记式/静态内部类6. 枚举…

更新npm镜像源:淘宝镜像已过期,及时切换!

你好&#xff0c;我是小白Coding日志&#xff0c;一个热爱技术的程序员。在这里&#xff0c;我分享自己在编程和技术世界中的学习心得和体会。希望我的文章能够给你带来一些灵感和帮助。欢迎来到我的博客&#xff0c;一起在技术的世界里探索前行吧&#xff01; 前言 就在昨天…

使用PHPStudy搭建Cloudreve网盘服务

文章目录 1、前言2、本地网站搭建2.1 环境使用2.2 支持组件选择2.3 网页安装2.4 测试和使用2.5 问题解决 3、本地网页发布3.1 cpolar云端设置3.2 cpolar本地设置 4、公网访问测试5、结语 1、前言 自云存储概念兴起已经有段时间了&#xff0c;各互联网大厂也纷纷加入战局&#…

【2024.2.4练习】国王游戏

题目描述 题目思路 涉及排列组合求最优解问题&#xff0c;数据大考虑是否满足某种贪心策略。 假设不除以右手的数字&#xff0c;那么获得金币数量最多的显然为最后一个人。左手数字最大的应排在最后一位。在右手有数字的情况下&#xff0c;不妨也尝试从最后一个人开始排。 假…

Python---Pycharm安装各种库(第三方库)

一、前言 Pycharm中&#xff0c;通常需要安装很多第三方库&#xff0c;才可以使用相应的拓展功能&#xff0c;这篇文档给你介绍Pycharm中的常用库&#xff0c;以及安装的两种方法!二、Pycharm常用库的介绍 Pycharm是一款非常流行的Python集成开发环境&#xff08;IDE&#xff…

VSCODE使用ssh远程连接时启动服务器失败问题

错误情况 ping服务器的ip可通并且使用terminal可以ssh连接到远程服务器。但使用vscode的remote-ssh时&#xff0c;在「输出」栏出现了一直报 Waiting for server log… 的情况&#xff01; 解决方法一 重置服务器设置&#xff0c;包括以下手段&#xff1a; 1.清理服务器端的…

RV1126 ext4 img格式的文件系统制作

&#xff08;1&#xff09;制作镜像文件,用dd工具创建12G大小空的镜像文件 dd if/dev/zero ofmedia.img bs512 count25165824#bs512表示每块读写512字节的数据#count25165824表示拷贝25165824次 &#xff08;2&#xff09;可以查看制作的镜像 hexdump -C media.img ll media…

浅谈Zookeeper及windows下详细安装步骤

1. Zookeeper介绍 1.1 分布式系统面临的问题 分布式系统是一个硬件或软件组件分布在不同的网络计算机上&#xff0c;彼此之间仅仅通过消息传递进行通信和协调的系统。 面临的问题&#xff1a;系统每个节点之间信息同步及共享 以一个小团队为例,面临的问题 通过网络进行信息…

2024契约锁新春年会|拓百城·聚万力·共价值

契约锁全国各地的伙伴齐聚上海前滩香格里拉&#xff0c;携手开启“2024联结伙伴 深耕百城 聚焦大客户”的新征程&#xff01; 年会精彩看点回顾2023持续向上发展&#xff0c;感恩客户伙伴的支持&#xff01; 这一年&#xff0c;电子签章成为组织数字化建设中的刚性需求&#…

idea常用设置

1、内存优化 根据自己电脑本身的内存&#xff0c;对idea安装包里bin目录下的idea64.exe.vmoptions文件进行修改 -server -Xms256m -Xmx2048m -XX:MaxPermSize1024m -XX:ReservedCodeCacheSize256m -ea -Dsun.io.useCanonCachesfalse -Djava.Net.preferIPv4Stacktrue -Djsse.e…

nginx日志格式脚本

​ Nginx日志主要分为两种&#xff1a; access_log&#xff08;访问日志&#xff09;&#xff1a;记录客户端请求的信息&#xff0c;可以指定 log_format。 error_log&#xff08;错误日志&#xff09;&#xff1a;记录应用程序问题等信息&#xff0c;不可以指定log_format …

【数据结构 09】哈希

哈希算法&#xff1a;哈希也叫散列、映射&#xff0c;将任意长度的输入通过散列运算转化为固定长度的输出&#xff0c;该输出就是哈希值&#xff08;散列值&#xff09;。 哈希映射是一种压缩映射&#xff0c;通常情况下&#xff0c;散列值的空间远小于输入值的空间。 哈希运…