<commit_before>// Copyright 2016 <NAME>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cmd-executor.h"

#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <climits>
#include <cstdio>
#include <boost/algorithm/string.hpp>

#include "expr-executor.h"
#include "objects/str-object.h"
#include "stmt-executor.h"
#include "scope-executor.h"
#include "utils/scope-exit.h"
#include "objects/obj-type.h"

namespace seti {
namespace internal {

void SetFdAsync(int fd) {
  int flags;
  if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
          flags = 0;
  fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

std::tuple<std::string, std::string> ReadPipe(int pipe_out, int pipe_err) {
  char buf[PIPE_BUF];
  char buf_err[PIPE_BUF];

  int rd = 0;
  int rd_err = 0;

  SetFdAsync(pipe_out);
  SetFdAsync(pipe_err);

  rd = read(pipe_out, buf, PIPE_BUF);
  rd_err = read(pipe_err, buf_err, PIPE_BUF);

  std::string str_out = "";
  std::string str_err = "";

  if (rd > 0) {
    buf[rd] = '\0';
    str_out += buf;
  }

  if (rd_err > 0) {
    buf_err[rd_err] = '\0';
    str_err += buf_err;
  }

  return std::tuple<std::string, std::string>(str_out, str_err);
}

CmdExprData CmdExecutor::ExecGetResult(CmdFull *node) {
  return ExecCmdGetResult(node->cmd());
}

CmdExprData CmdExecutor::ExecCmdGetResult(Cmd *node)
try {
  switch (node->type()) {
    case AstNode::NodeType::kSimpleCmd: {
      return ExecSimpleCmdWithResult(static_cast<SimpleCmd*>(node));
    } break;

    case AstNode::NodeType::kCmdIoRedirectList: {
      CmdIoRedirectListExecutor cmd_io(this, symbol_table_stack());
      return cmd_io.Exec(static_cast<CmdIoRedirectList*>(node));
    } break;

    case AstNode::NodeType::kCmdPipeSequence: {
      CmdPipeSequenceExecutor cmd_pipe(this, symbol_table_stack());
      return cmd_pipe.Exec(static_cast<CmdPipeSequence*>(node));
    } break;

    case AstNode::NodeType::kCmdAndOr: {
      CmdAndOr* cmd = static_cast<CmdAndOr*>(node);
      return ExecCmdBinOp(cmd);
    } break;

    default: {
      throw RunTimeError(RunTimeError::ErrorCode::INVALID_OPCODE,
                         boost::format("invalid command ast"));
    }
  }
} catch (RunTimeError& e) {
  throw RunTimeError(e.err_code(), e.msg(), node->pos());
}

CmdExprData CmdExecutor::ExecCmdBinOp(CmdAndOr* cmd) {
  CmdExprData lcmd = ExecCmdGetResult(cmd->cmd_left());

  if (cmd->kind() == TokenKind::AND) {
    if (std::get<0>(lcmd) == 0) {
      CmdExprData rcmd = ExecCmdGetResult(cmd->cmd_right());
      std::string str_out = std::get<1>(lcmd) + std::get<1>(rcmd);
      std::string str_err = std::get<2>(lcmd) + std::get<2>(rcmd);
      return CmdExprData(std::get<0>(rcmd),  str_out, str_err);
    }

    std::string str_out = std::get<1>(lcmd);
    std::string str_err = std::get<2>(lcmd);

    // -1 set error on status of operation
    return CmdExprData(-1,  str_out, str_err);
  } else /*TokenKind::OR*/ {
    if (std::get<0>(lcmd) == 0) {
      std::string str_out = std::get<1>(lcmd);
      std::string str_err = std::get<2>(lcmd);
      // -1 set error on status of operation
      return CmdExprData(std::get<0>(lcmd),  str_out, str_err);
    }

    CmdExprData rcmd = ExecCmdGetResult(cmd->cmd_right());
    std::string str_out = std::get<1>(lcmd) + std::get<1>(rcmd);
    std::string str_err = std::get<2>(lcmd) + std::get<2>(rcmd);
    return CmdExprData(std::get<0>(rcmd),  str_out, str_err);
  }
}

int CmdExecutor::ExecCmdBinOp(CmdAndOr* cmd, bool background) {
  int lcmd = ExecCmd(cmd->cmd_left(), background);

  if (cmd->kind() == TokenKind::AND) {
    if (lcmd == 0) {
      int rcmd = ExecCmd(cmd->cmd_right(), background);
      return rcmd;
    }

    return lcmd;
  }

  /*TokenKind::OR*/
  if (lcmd == 0) {
    return lcmd;
  }

  int rcmd = ExecCmd(cmd->cmd_right(), background);
  return rcmd;
}

int CmdExecutor::Exec(CmdFull *node) {
  bool background = node->background();
  return ExecCmd(node->cmd(), background);
}

int CmdExecutor::ExecCmd(Cmd *node, bool background)
try {
  switch (node->type()) {
    case AstNode::NodeType::kSimpleCmd: {
      return ExecSimpleCmd(static_cast<SimpleCmd*>(node), background);
    } break;

    case AstNode::NodeType::kCmdIoRedirectList: {
      CmdIoRedirectListExecutor cmd_io(this, symbol_table_stack());
      return cmd_io.Exec(static_cast<CmdIoRedirectList*>(node), background);
    } break;

    case AstNode::NodeType::kCmdPipeSequence: {
      CmdPipeSequenceExecutor cmd_pipe(this, symbol_table_stack());
      return cmd_pipe.Exec(static_cast<CmdPipeSequence*>(node), background);
    } break;

    case AstNode::NodeType::kCmdAndOr: {
      CmdAndOr* cmd = static_cast<CmdAndOr*>(node);
      if (background) {
        // background all command
        return ExecCmdBinOp(cmd, true);
      } else {
        // as one command must background for other to know the result
        // but the system cant waint, so, create a new process
        // to execute the whole command
        pid_t pid;
        pid = fork ();
        if (pid == 0) {
          int r = ExecCmdBinOp(cmd, true);
          exit(r);
        }

        return 0;
      }
    } break;

    default: {
      throw RunTimeError(RunTimeError::ErrorCode::INVALID_OPCODE,
                         boost::format("invalid command ast"));
    }
  }
} catch (RunTimeError& e) {
  throw RunTimeError(e.err_code(), e.msg(), node->pos());
}

int CmdExecutor::ExecSimpleCmd(SimpleCmd *node, bool background) {
  SimpleCmdExecutor simple_cmd(this, symbol_table_stack());

  std::vector<std::string> cmd_args = simple_cmd.Exec(node);

  Job job(symbol_table_stack());
  Process p(symbol_table_stack(), std::move(cmd_args));
  job.process_.push_back(p);
  job.shell_is_interactive_ = 0;
  job.stderr_ = STDERR_FILENO;
  job.stdout_ = STDOUT_FILENO;
  job.stdin_ = STDIN_FILENO;
  job.LaunchJob(!background);
<commit_msg>fix binary operation for commands<commit_after>// Copyright 2016 <NAME>
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cmd-executor.h"

#include <unistd.h>
#include <unistd.h>
#include <fcntl.h>
#include <climits>
#include <cstdio>
#include <boost/algorithm/string.hpp>

#include "expr-executor.h"
#include "objects/str-object.h"
#include "stmt-executor.h"
#include "scope-executor.h"
#include "utils/scope-exit.h"
#include "objects/obj-type.h"

namespace seti {
namespace internal {

void SetFdAsync(int fd) {
  int flags;
  if (-1 == (flags = fcntl(fd, F_GETFL, 0)))
          flags = 0;
  fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

std::tuple<std::string, std::string> ReadPipe(int pipe_out, int pipe_err) {
  char buf[PIPE_BUF];
  char buf_err[PIPE_BUF];

  int rd = 0;
  int rd_err = 0;

  SetFdAsync(pipe_out);
  SetFdAsync(pipe_err);

  rd = read(pipe_out, buf, PIPE_BUF);
  rd_err = read(pipe_err, buf_err, PIPE_BUF);

  std::string str_out = "";
  std::string str_err = "";

  if (rd > 0) {
    buf[rd] = '\0';
    str_out += buf;
  }

  if (rd_err > 0) {
    buf_err[rd_err] = '\0';
    str_err += buf_err;
  }

  return std::tuple<std::string, std::string>(str_out, str_err);
}

CmdExprData CmdExecutor::ExecGetResult(CmdFull *node) {
  return ExecCmdGetResult(node->cmd());
}

CmdExprData CmdExecutor::ExecCmdGetResult(Cmd *node)
try {
  switch (node->type()) {
    case AstNode::NodeType::kSimpleCmd: {
      return ExecSimpleCmdWithResult(static_cast<SimpleCmd*>(node));
    } break;

    case AstNode::NodeType::kCmdIoRedirectList: {
      CmdIoRedirectListExecutor cmd_io(this, symbol_table_stack());
      return cmd_io.Exec(static_cast<CmdIoRedirectList*>(node));
    } break;

    case AstNode::NodeType::kCmdPipeSequence: {
      CmdPipeSequenceExecutor cmd_pipe(this, symbol_table_stack());
      return cmd_pipe.Exec(static_cast<CmdPipeSequence*>(node));
    } break;

    case AstNode::NodeType::kCmdAndOr: {
      CmdAndOr* cmd = static_cast<CmdAndOr*>(node);
      return ExecCmdBinOp(cmd);
    } break;

    default: {
      throw RunTimeError(RunTimeError::ErrorCode::INVALID_OPCODE,
                         boost::format("invalid command ast"));
    }
  }
} catch (RunTimeError& e) {
  throw RunTimeError(e.err_code(), e.msg(), node->pos());
}

CmdExprData CmdExecutor::ExecCmdBinOp(CmdAndOr* cmd) {
  CmdExprData lcmd = ExecCmdGetResult(cmd->cmd_left());

  if (cmd->kind() == TokenKind::AND) {
    if (std::get<0>(lcmd) == 0) {
      CmdExprData rcmd = ExecCmdGetResult(cmd->cmd_right());
      std::string str_out = std::get<1>(lcmd) + std::get<1>(rcmd);
      std::string str_err = std::get<2>(lcmd) + std::get<2>(rcmd);
      return CmdExprData(std::get<0>(rcmd),  str_out, str_err);
    }

    std::string str_out = std::get<1>(lcmd);
    std::string str_err = std::get<2>(lcmd);

    // -1 set error on status of operation
    return CmdExprData(-1,  str_out, str_err);
  } else /*TokenKind::OR*/ {
    if (std::get<0>(lcmd) == 0) {
      std::string str_out = std::get<1>(lcmd);
      std::string str_err = std::get<2>(lcmd);
      // -1 set error on status of operation
      return CmdExprData(std::get<0>(lcmd),  str_out, str_err);
    }

    CmdExprData rcmd = ExecCmdGetResult(cmd->cmd_right());
    std::string str_out = std::get<1>(lcmd) + std::get<1>(rcmd);
    std::string str_err = std::get<2>(lcmd) + std::get<2>(rcmd);
    return CmdExprData(std::get<0>(rcmd),  str_out, str_err);
  }
}

int CmdExecutor::ExecCmdBinOp(CmdAndOr* cmd, bool background) {
  int lcmd = ExecCmd(cmd->cmd_left(), background);

  if (cmd->kind() == TokenKind::AND) {
    if (lcmd == 0) {
      int rcmd = ExecCmd(cmd->cmd_right(), background);
      return rcmd;
    }

    return lcmd;
  }

  /*TokenKind::OR*/
  if (lcmd == 0) {
    return lcmd;
  }

  int rcmd = ExecCmd(cmd->cmd_right(), background);
  return rcmd;
}

int CmdExecutor::Exec(CmdFull *node) {
  bool background = node->background();
  return ExecCmd(node->cmd(), background);
}

int CmdExecutor::ExecCmd(Cmd *node, bool background)
try {
  switch (node->type()) {
    case AstNode::NodeType::kSimpleCmd: {
      return ExecSimpleCmd(static_cast<SimpleCmd*>(node), background);
    } break;

    case AstNode::NodeType::kCmdIoRedirectList: {
      CmdIoRedirectListExecutor cmd_io(this, symbol_table_stack());
      return cmd_io.Exec(static_cast<CmdIoRedirectList*>(node), background);
    } break;

    case AstNode::NodeType::kCmdPipeSequence: {
      CmdPipeSequenceExecutor cmd_pipe(this, symbol_table_stack());
      return cmd_pipe.Exec(static_cast<CmdPipeSequence*>(node), background);
    } break;

    case AstNode::NodeType::kCmdAndOr: {
      CmdAndOr* cmd = static_cast<CmdAndOr*>(node);
      if (background) {
        // as one command must background for other to know the result
        // but the system cant waint, so, create a new process
        // to execute the whole command
        pid_t pid;
        pid = fork ();
        if (pid == 0) {
          int r = ExecCmdBinOp(cmd, false);
          exit(r);
        }

        return 0;
      } else {
        // background all command
        return ExecCmdBinOp(cmd, false);
      }
    } break;

    default: {
      throw RunTimeError(RunTimeError::ErrorCode::INVALID_OPCODE,
                         boost::format("invalid command ast"));
    }
  }
} catch (RunTimeError& e) {
  throw RunTimeError(e.err_code(), e.msg(), node->pos());
}

int CmdExecutor::ExecSimpleCmd(SimpleCmd *node, bool background) {
  SimpleCmdExecutor simple_cmd(this, symbol_table_stack());

  std::vector<std::string> cmd_args = simple_cmd.Exec(node);

  Job job(symbol_table_stack());
  Process p(symbol_table_stack(), std::move(cmd_args));
  job.process_.push_back(p);
  job.shell_is_interactive_ = 0;
  job.stderr_ = STDERR_FILENO;
  job.stdout_ = STDOUT_FILENO;
  job.stdin_ = STDIN_FILENO;
  job.LaunchJob(!background);

{'fraction_non_alphanumeric': 0.147538413295704, 'fraction_numerical': 0.006898714330511132, 'mean_word_length': 3.64735883424408, 'pattern_counts': {'":': 0, '<': 73, '<?xml version=': 0, '>': 107, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6936912', 'n_tokens_mistral': 4499, 'n_tokens_neox': 4354, 'n_words': 966}