Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在c+中实现pipe命令+;_C++_Terminal_Pipe - Fatal编程技术网

C++ 在c+中实现pipe命令+;

C++ 在c+中实现pipe命令+;,c++,terminal,pipe,C++,Terminal,Pipe,我正在尝试制作一个本机支持管道命令的终端。 我曾经尝试过实现这一点,但每当我尝试执行管道命令时,它就会一次又一次地执行,直到我的电脑崩溃——可能是一些内存,但我无法回溯到底是什么导致了它 这个问题是学术作业的一部分 在展示此命令的实现之前,我将解释在管道实现中使用的函数: \u parseCommandLine-接收一个命令char*和一些空数组args-对于每个参数,它在args数组中动态地为其分配空间,最后函数返回参数的数量 \u isBackgroundComamnd和\u removeB

我正在尝试制作一个本机支持管道命令的终端。
我曾经尝试过实现这一点,但每当我尝试执行管道命令时,它就会一次又一次地执行,直到我的电脑崩溃——可能是一些内存,但我无法回溯到底是什么导致了它

这个问题是学术作业的一部分

在展示此命令的实现之前,我将解释在管道实现中使用的函数:
\u parseCommandLine
-接收一个命令char*和一些空数组args-对于每个参数,它在args数组中动态地为其分配空间,最后函数返回参数的数量

\u isBackgroundComamnd
\u removeBackgroundSign
似乎是不言自明的

\u clear\u命令
仅释放参数数组和命令本身

如果你需要澄清更多的功能,让我知道

这是我的实现

void PipeCommand::execute(){
  char* args1[COMMAND_ARGS_MAX_LENGTH];
  char* args2[COMMAND_ARGS_MAX_LENGTH];
  char* command1 = (char*)malloc(COMMAND_ARGS_MAX_LENGTH);
  char* command2 = (char*)malloc(COMMAND_ARGS_MAX_LENGTH);
  char* command1_print = (char*)malloc(COMMAND_ARGS_MAX_LENGTH);
  char* command2_print = (char*)malloc(COMMAND_ARGS_MAX_LENGTH);
  unsigned int cmd_sep_out = string(this->command).find("|");
  unsigned int cmd_sep_err = string(this->command).find("|&");

  strcpy(command1, string(this->command).substr(0, cmd_sep_out).c_str());
  if(cmd_sep_err != string::npos){
    strcpy(command2, string(this->command).substr(cmd_sep_err + 1).c_str());
  } else{
    strcpy(command2, string(this->command).substr(cmd_sep_out + 1).c_str());
  }
  strcpy(command1_print, string(this->command).substr(0, cmd_sep_out).c_str());
  if(cmd_sep_err != string::npos){
    strcpy(command2_print, string(this->command).substr(cmd_sep_err + 1).c_str());
  } else{
    strcpy(command2_print, string(this->command).substr(cmd_sep_out + 1).c_str());
  }

  int args_count1 = _parseCommandLine(command1, args1);
  int args_count2 = _parseCommandLine(command2, args2);

  if (_isBackgroundComamnd(command1)){
    _removeBackgroundSign(command1);
  }
  bool is_bg = false;
  if (_isBackgroundComamnd(command2)){
    _removeBackgroundSign(command2);
    is_bg = true;
  }
  SmallShell& smash = SmallShell::getInstance();
  int smash_pid = getpid();

  int first_fork = fork();
  if(first_fork == -1){
    perror("smash error: fork failed");
    _clear_command(command1, args1, args_count1);
    _clear_command(command2, args2, args_count2);
    free(command1_print);
    free(command2_print);
  }

  if(first_fork == 0){
    if(this->getIsPipe()){
      setpgrp();
    }
    int fd[2];
    if(pipe(fd) == -1){
      perror("smash error: pipe failed");
      _clear_command(command1, args1, args_count1);
      _clear_command(command2, args2, args_count2);
      free(command1_print);
      free(command2_print);
    }
    int second_fork = fork();
    if(second_fork == -1){
      perror("smash error: fork failed");
      _clear_command(command1, args1, args_count1);
      _clear_command(command2, args2, args_count2);
      free(command1_print);
      free(command2_print);
    }
    else if(second_fork == 0){
      setpgrp();
      if(cmd_sep_err != string::npos){
        dup2(fd[1], STDERR_FILENO);
      } else{
        dup2(fd[1], STDOUT_FILENO);
      }
      close(fd[1]);
      close(fd[0]);

      Command* command_obj1 = smash.CreateCommand(command1);

      if(strcmp(args1[0], "showpid") == 0){
        std::cout << "smash pid is " << smash_pid << std::endl;
      } else{
        command_obj1->execute();
      }
      _clear_command(command1, args1, args_count1);
      _clear_command(command2, args2, args_count2);
      free(command1_print);
      free(command2_print);
      delete command_obj1;
      smash.setQuitShell(true);
      return;
    }
    int third_fork = fork();
    if(third_fork == -1){
      perror("smash error: fork failed");
      _clear_command(command1, args1, args_count1);
      _clear_command(command2, args2, args_count2);
      free(command1_print);
      free(command2_print);
    } else if(third_fork == 0){
       setpgrp();
       dup2(fd[0], STDIN_FILENO);
       close(fd[1]);
       close(fd[0]);

       Command* command_obj2 = smash.CreateCommand(command2);
       if(strcmp(args2[0], "showpid") == 0){
        std::cout << "smash pid is " << smash_pid << std::endl;
      } else{
        command_obj2->execute();
      }
      _clear_command(command1, args1, args_count1);
      _clear_command(command2, args2, args_count2);
      free(command1_print);
      free(command2_print);
      delete command_obj2;
      smash.setQuitShell(true);
      return;
    }
    close(fd[1]);
    close(fd[0]);
    waitpid(first_fork, NULL, 0);
    waitpid(second_fork, NULL, 0);
    _clear_command(command1, args1, args_count1);
    _clear_command(command2, args2, args_count2);
    smash.setQuitShell(true);
    return;
  } else{
    this->pid = first_fork;
    if(is_bg){
      smash.getJobs()->addJob(this->command, this->pid, command2_print, false, -1, is_bg);
    } else{
      smash.setForeGroundPID(this->pid);
      smash.setForegroundJID(-1);
      smash.setForegroundCommand(this->command);

      waitpid(this->pid, NULL, WUNTRACED);
      smash.setForeGroundPID(-1);
    }
  }
  _clear_command(command1, args1, args_count1);
  _clear_command(command2, args2, args_count2);
  free(command1_print);
  free(command2_print);
}
执行我的终端并键入
cat file | less

我预计产出:

a
b
c
但不是只得到一次输出,而是

a
b
c

一次又一次直到我的机器崩溃

@YSC可能正确的术语应该只是一个管道,但我的意思是像这样的命令
cat file | less
可能是管道的创建。这可能不太实际,但这是一个学术作业的一部分。编辑我的问题以提及这一切:)@YSC可能正确的术语只是一个管道,但我的意思是像这样的命令
cat file | less
可能创建管道。这可能不太实际,但这是一项学术作业的一部分。编辑我的问题以提及所有内容:)
a
b
c