int run_cmd(int argc, char *argv[]) { char last_bg_pid[50], msg[50]; if (argv[0] == NULL) { /* ignore the blank line. */ return 1; } else if (strcmp(argv[0], "quit") == 0) { /* quit the shell. */ if (argv[1] != NULL) { if (!isalpha(*argv[1])){ cmd_exit_status = atoi(argv[1]); } } exit_status = cmd_exit_status; return 0; } else if (strcmp(argv[0], "echo") == 0) { /* echo: print all the words after the echo command. */ cmd_exit_status = echo(argc, argv); } else if ((strcmp(argv[0], "cd") == 0) || (strcmp(argv[0], "chdir") == 0)) { /* change the working directory.*/ cmd_exit_status = changeDirectory(argc, argv); } else if (strcmp(argv[0], "set") == 0) { /* Set variable by the given value.*/ cmd_exit_status = setVariable(argc, argv); } else if (strcmp(argv[0], "wait") == 0) { if (argv[1] == NULL) { printf("wait <PID>\n"); cmd_exit_status = 1; } else { cmd_exit_status = wait_cmd((pid_t) atoi(argv[1])); } } else if (strcmp(argv[0], "unset") == 0) { /* do unset */ cmd_exit_status = unset_cmd(argc, argv); } else { /* Command not found. Look for external command to run. */ cmd_exit_status = run_external_cmd(argv); } sprintf(msg, "Command exited with exit status %d", cmd_exit_status); debug(msg); sprintf(last_bg_pid, "%d", background_pid); setenv("!", last_bg_pid, 1); return 1; }
bg_task launch_background_cmd(int task_id, std::vector<std::string> args) { timeval t; gettimeofday(&t, nullptr); int pipefd[2]; if (0 == pipe(pipefd)) { pid_t watcher_pid = fork(); switch (watcher_pid) { case -1: // Error { std::cerr << "Error on fork(): " << strerror(errno) << "\n"; return bg_task{-2, process_info{-1, t}, process_info{}}; } break; case 0: // Child process { close(pipefd[0]); // Close read end auto info = launch_cmd(args); write(pipefd[1], &info, sizeof(process_info)); wait_cmd(info); std::exit(EXIT_SUCCESS); } break; default: // Parent process { close(pipefd[1]); // Close write end process_info info; read(pipefd[0], &info, sizeof(process_info)); return bg_task{task_id, process_info{watcher_pid, t}, info}; } break; } } else { std::cerr << "Error on pipe(): " << strerror(errno) << "\n"; return bg_task{-1, process_info{-1, t}, process_info{}}; } }
static void send_and_wait_cmd(struct netdev *nd, int cmd) { outw(cmd, Command); wait_cmd(nd); }
int main(int /* argc */, char* /* argv */[]) { auto bg_tasks = std::map<int, bg_task>(); timeval start; gettimeofday(&start, nullptr); int next_task_id = 0; bool quit = false; while (not quit) { std::string line; std::cout << get_current_dir_name() << "> "; std::cout.flush(); if (not std::getline(std::cin, line) || line == "exit") { std::cout << std::endl; quit = true; } else { auto is_whitespace = [](char c){ return std::isspace(c) != 0; }; auto begin = std::find_if_not(line.begin(), line.end(), is_whitespace); auto end = line.end(); auto result = begin; std::vector<std::string> args; while (begin != end) { result = std::find(begin, end, ' '); args.emplace_back(begin, result); begin = std::find_if_not(result, end, is_whitespace); } if (not args.empty()) { if (args.back() == "&") { args.pop_back(); auto task = launch_background_cmd(next_task_id++, args); std::cout << task << std::endl; bg_tasks[task.exec_proc.id] = task; } else if (args[0] == "cd") { cd(args[1]); } else if (args[0] == "aptaches") { check_processes(bg_tasks); // for (std::map<int, bg_task>::const_iterator it=bg_tasks.begin(); it!=bg_tasks.end(); ++it) { for (auto pair : bg_tasks) { std::cout << pair.second << std::endl; } } else { wait_cmd(launch_cmd(args)); } } } } /* Kill everything in bg_tasks */ check_processes(bg_tasks); for (auto pair : bg_tasks) { kill(pair.second.exec_proc.id, SIGTERM); } }