voidrun_cmd(cmd *cmd_){ switch (cmd_->type) { case CMD_TYPE_EXEC: { exec_cmd *ecmd = static_cast<exec_cmd *>(cmd_); // process alias if (alias_map.count(ecmd->argv[0]) != 0) { vector<string> arg0_replace = string_split(alias_map.at(ecmd->argv[0]), WHITE_SPACE); //仍需拆分成多个指令 //用新的拆分后的指令替换原指令 ecmd->argv.erase(ecmd->argv.begin()); for (vector<string>::reverse_iterator it = arg0_replace.rbegin(); it < arg0_replace.rend(); it++) { ecmd->argv.insert(ecmd->argv.begin(), (*it)); } } // prepare vector<string> for execvp // execp函数参数不能是string,去除指令序列中的空格,在序列最后加入NULL(execp函数参数要求) vector<char *> argv_c_str; for (int i = 0; i < ecmd->argv.size(); i++) { string arg_trim = trim(ecmd->argv[i]); if (arg_trim.length() > 0) { // skip blank string char *tmp = newchar[MAX_ARGV_LEN]; strcpy(tmp, arg_trim.c_str()); argv_c_str.push_back(tmp); } } argv_c_str.push_back(NULL); char **argv_c_arr = &argv_c_str[0]; // vscode made wrong marco expansion here // second argument is ok for char** rather than char *const (*(*)())[] int execvp_ret = execvp(argv_c_arr[0], argv_c_arr); if (execvp_ret < 0) panic("execvp failed"); break; } case CMD_TYPE_PIPE: { pipe_cmd *pcmd = static_cast<pipe_cmd *>(cmd_); pipe_wrap(pipe_fd); // fork twice to run lhs and rhs of pipe if (fork_wrap() == 0) { // i'm a child, let's satisfy lhs close(pipe_fd[0]); dup2_wrap(pipe_fd[1], fileno(stdout)); // lhs_stdout -> pipe_write // close the original ones run_cmd(pcmd->left); close(pipe_fd[1]); } if (fork_wrap() == 0) { // i'm also a child, let's satisfy rhs close(pipe_fd[1]); dup2_wrap(pipe_fd[0], fileno(stdin)); // pipe_read -> rhs_stdin run_cmd(pcmd->right); close(pipe_fd[0]); } // really good. now we have lhs_stdout -> pipe -> rhs_stdin // if fork > 0, then i'm the father // let's wait for my children close(pipe_fd[0]); close(pipe_fd[1]); int wait_status_1, wait_status_2; wait(&wait_status_1); wait(&wait_status_2); check_wait_status(wait_status_1); check_wait_status(wait_status_2); break; } case CMD_TYPE_REDIR_IN: case CMD_TYPE_REDIR_OUT: { redirect_cmd *rcmd = static_cast<redirect_cmd *>(cmd_); if (fork_wrap() == 0) { // i'm a child, let's satisfy the file being redirected to (or from) rcmd->fd = open_wrap(rcmd->file.c_str(), rcmd->type == CMD_TYPE_REDIR_IN ? REDIR_IN_OFLAG : REDIR_OUT_OFLAG); dup2_wrap(rcmd->fd, rcmd->type == CMD_TYPE_REDIR_IN ? fileno(stdin) : fileno(stdout)); run_cmd(rcmd->cmd_); close(rcmd->fd); } // if fork > 0, then i'm the father // let's wait for my children int wait_status; wait(&wait_status); check_wait_status(wait_status); break; } default: panic("unknown or null cmd type", true, 1); } }