<commit_before>#include "command.hpp"

std::vector<int> m_background;

SimpleCommand::SimpleCommand() { /** Used to call malloc for five stuffs here **/ }

void SimpleCommand::insertArgument(char * argument)
{
  std::string as_string(argument);

  auto exists = Command::currentCommand.m_aliases.find(as_string);

  /* exists == m_aliases.end() => we are inserting an alias */
  if (exists != Command::currentCommand.m_aliases.end()) {
	auto to_insert = exists->second;
	for (auto && str : to_insert) {
	  char * toPush = strndup(str.c_str(), str.size());
	  arguments.push_back(toPush); ++numOfArguments;
	}
  } else {
	std::string arga = tilde_expand(as_string);
	std::string arg  = env_expand(arga);
	char * str = strdup(arg.c_str()); int index; char * t_str = str;
	char * temp = (char*) calloc(arg.size() + 1, sizeof(char));
	for (index = 0; *str; ++str) {
	  if (*str == '\\' && *(str + 1) == '\"') {
		temp[index++] = '\"'; ++str;
	  } else if (*str == '\\' && *(str + 1) == '&') {
		temp[index++] = '&'; ++str;
	  } else if (*str == '\\' && *(str + 1) == '#') {
		temp[index++] = '#'; ++str;
	  } else if (*str == '\\' && *(str + 1) == '<') {
		temp[index++] = '<'; ++str;
	  } else if (*str == '\\' && *(str + 1) == '\\' && *(str+2) == '\\') {
		temp[index++] = '\\'; ++str; ++str;
	  } else if (*str == '\\' && *(str + 1) == '\\'){
		temp[index++] = '\\'; ++str;
	  } else if (*str == '\\' && *(str + 1) == ' ') {
		temp[index++] = ' '; ++str;
	  } else {
		temp[index++] = *str;
	  }
	} free(t_str);
	char * toPush = new char[index + 1]; memset(toPush, 0, index + 1);
	strcpy(toPush, temp);
	arguments.push_back(toPush), ++numOfArguments;
	free(temp);
  }
}

inline int eval_to_buffer(char * const* cmd, char * outBuff, size_t buffSize)
{
  int fdpipe[2]; int pid = -1; size_t x = 0;

  if (pipe(fdpipe) < 0) return -1;
  else if ((pid = fork()) < 0) return -1;
  else if (pid == 0) {
	/** Child Process: write into the pipe **/
	close(fdpipe[0]);   // close unused read end
	dup2(fdpipe[1], 1); // stdout to pipe
	dup2(fdpipe[1], 2); // stderr to pipe
	close(fdpipe[1]);

	if (execvp(cmd[0], cmd)) return -1;
	_exit(0);
  } else {
	/** Parent Process: read from the pipe **/
	close(fdpipe[1]);   // close unused write end
	for (memset(outBuff, 0, buffSize);x = read(fdpipe[0], outBuff, buffSize););
	if (x == buffSize) return -1;
	waitpid(pid, NULL, 0);
  } return 0;
}

#define SUBSH_MAX_LEN 4096
void Command::subShell(char * arg)
{
  int fdpipe[2]; int pid = -1; size_t x = 0;
  int gdpipe[2]; const size_t buffSize = SUBSH_MAX_LEN;
  // Run /proc/self/exe with "arg" as input
  if (pipe(fdpipe) < 0) { perror("pipe"); return; }
  else if (pipe(gdpipe) < 0) { perror("pipe"); return; }
  else if ((pid = fork()) < 0) { perror("fork"); return; }
  else if (pid == 0) {
	/** Child Process: write into the pipe **/
	dup2(fdpipe[0], 0); // pipe to stdin
	close(fdpipe[0]);
	dup2(fdpipe[1], 1); // stdout to pipe
	dup2(fdpipe[1], 2); // stderr to pipe
	close(fdpipe[1]);
    
	if (execlp("hsh", "hsh", NULL)) { perror("execlp"); return; }
	_exit(0);
  } else {
	/** Parent Process: read from the pipe **/
	char * outBuff = (char*) alloca(buffSize);
	std::string cmd = std::string(arg) + "\nexit";
	char * _arg = strndup(cmd.c_str(), cmd.size());
	std::thread _thread1([_arg, fdpipe]() {
		for (char * a = _arg; *a && write(fdpipe[1], a, 1); ++a);
	  }); _thread1.join();
	std::thread _thread2([outBuff, buffSize, fdpipe]() {
		size_t x = 0;
		for (memset(outBuff, 0, buffSize);x = read(fdpipe[0], outBuff, buffSize););
	  }); _thread2.join();
	if (x == buffSize) return;
	waitpid(pid, NULL, 0);

	free(_arg); // free already used command input
	char * _cpy = strdup(outBuff); _cpy[strlen(_cpy) - 1] = '\0';
	Command::currentSimpleCommand->insertArgument(_cpy);
  }
}

Command::Command()
{ /** Constructor **/ }

void Command::insertSimpleCommand(std::shared_ptr<SimpleCommand> simpleCommand)
{ simpleCommands.push_back(simpleCommand), ++numOfSimpleCommands; }

void Command::clear()
{
  simpleCommands.clear(),
	background = append = false,
	numOfSimpleCommands = 0,
	outFile.release(), inFile.release(),
	errFile.release(), simpleCommands.shrink_to_fit();
  outSet = inSet = errSet = false;
}<commit_msg>Uh. Ya. So... Subshell is hard @Purdrew2<commit_after>#include "command.hpp"

std::vector<int> m_background;

SimpleCommand::SimpleCommand() { /** Used to call malloc for five stuffs here **/ }

void SimpleCommand::insertArgument(char * argument)
{
  std::string as_string(argument);

  auto exists = Command::currentCommand.m_aliases.find(as_string);

  /* exists == m_aliases.end() => we are inserting an alias */
  if (exists != Command::currentCommand.m_aliases.end()) {
	auto to_insert = exists->second;
	for (auto && str : to_insert) {
	  char * toPush = strndup(str.c_str(), str.size());
	  arguments.push_back(toPush); ++numOfArguments;
	}
  } else {
	std::string arga = tilde_expand(as_string);
	std::string arg  = env_expand(arga);
	char * str = strdup(arg.c_str()); int index; char * t_str = str;
	char * temp = (char*) calloc(arg.size() + 1, sizeof(char));
	for (index = 0; *str; ++str) {
	  if (*str == '\\' && *(str + 1) == '\"') {
		temp[index++] = '\"'; ++str;
	  } else if (*str == '\\' && *(str + 1) == '&') {
		temp[index++] = '&'; ++str;
	  } else if (*str == '\\' && *(str + 1) == '#') {
		temp[index++] = '#'; ++str;
	  } else if (*str == '\\' && *(str + 1) == '<') {
		temp[index++] = '<'; ++str;
	  } else if (*str == '\\' && *(str + 1) == '\\' && *(str+2) == '\\') {
		temp[index++] = '\\'; ++str; ++str;
	  } else if (*str == '\\' && *(str + 1) == '\\'){
		temp[index++] = '\\'; ++str;
	  } else if (*str == '\\' && *(str + 1) == ' ') {
		temp[index++] = ' '; ++str;
	  } else {
		temp[index++] = *str;
	  }
	} free(t_str);
	char * toPush = new char[index + 1]; memset(toPush, 0, index + 1);
	strcpy(toPush, temp);
	arguments.push_back(toPush), ++numOfArguments;
	free(temp);
  }
}

inline int eval_to_buffer(char * const* cmd, char * outBuff, size_t buffSize)
{
  int fdpipe[2]; int pid = -1; size_t x = 0;

  if (pipe(fdpipe) < 0) return -1;
  else if ((pid = fork()) < 0) return -1;
  else if (pid == 0) {
	/** Child Process: write into the pipe **/
	close(fdpipe[0]);   // close unused read end
	dup2(fdpipe[1], 1); // stdout to pipe
	dup2(fdpipe[1], 2); // stderr to pipe
	close(fdpipe[1]);

	if (execvp(cmd[0], cmd)) return -1;
	_exit(0);
  } else {
	/** Parent Process: read from the pipe **/
	close(fdpipe[1]);   // close unused write end
	for (memset(outBuff, 0, buffSize);x = read(fdpipe[0], outBuff, buffSize););
	if (x == buffSize) return -1;
	waitpid(pid, NULL, 0);
  } return 0;
}

#define SUBSH_MAX_LEN 4096
void Command::subShell(char * arg)
{
  int cmd_pipe[2]; int out_pipe[2]; pid_t pid;
  int tmpin = dup(0); int tmpout = dup(1); int tmperr = dup(2);
  
  if (pipe(cmd_pipe) == -1) {
	perror("cmd_pipe");
	return;
  } else if (pipe(out_pipe) == -1) {
	perror("out_pipe");
	return;
  } else if ((pid = fork()) == -1) {
	perror("subshell fork");
	return;
  } else if (pid == 0) {
	/* Child Process */
	close(out_pipe[0]); /* close the read end of the out pipe */
	close(cmd_pipe[1]); /* close the write end of the cmd pipe */

	dup2(out_pipe[1], 1); close(out_pipe[1]); /* out_pipe[1] -> stdout */
	dup2(cmd_pipe[0], 0); close(cmd_pipe[0]); /* cmd_pipe[0] -> stdin  */

	execlp("/proc/self/exe", "/proc/self/exe", NULL);
	perror("subshell exec");
	_exit(1);
  } else if (pid != 0) {
	char * buff = (char*) calloc(SUBSH_MAX_LEN, sizeof(char));
	register char * c = NULL;
	
	/* Parent Process */
	close(out_pipe[1]); /* close the write end of the out pipe */
	close(cmd_pipe[0]); /* close the read end of the cmd pipe */

	/* write the command to the write end of the cmd pipe */
	for (c = arg; *c && write(cmd_pipe[1], c++, 1););

	waitpid(pid, NULL, 0);
	
	/* read from the out pipe and store in a buffer */
	for (c = buff; read(out_pipe[0], c++, 1););
	
	size_t buff_len = c - buff; /* this is the number of characters read */

	/* Push the buffer onto stdin */
	for (int b = 0; (ungetc(buff[b++], stdin) != EOF) && buff_len--;);
  }

  /* restore default IO */
  dup2(tmpin, 0); dup2(tmpout, 1); dup2(tmperr, 2);
}

Command::Command()
{ /** Constructor **/ }

void Command::insertSimpleCommand(std::shared_ptr<SimpleCommand> simpleCommand)
{ simpleCommands.push_back(simpleCommand), ++numOfSimpleCommands; }

void Command::clear()
{
  simpleCommands.clear(),
	background = append = false,
	numOfSimpleCommands = 0,
	outFile.release(), inFile.release(),
	errFile.release(), simpleCommands.shrink_to_fit();
  outSet = inSet = errSet = false;
}
{'fraction_non_alphanumeric': 0.21681004417577307, 'fraction_numerical': 0.01813531736805394, 'mean_word_length': 3.7010928961748633, 'pattern_counts': {'":': 0, '<': 18, '<?xml version=': 0, '>': 14, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, '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': '1252250', 'n_tokens_mistral': 3417, 'n_tokens_neox': 3281, 'n_words': 836}