int execute_builtin(cmd_t* cmd, job_list_t* jobs, history_t* hist) { // List jobs. if (strcmp(cmd->args[0], "jobs") == 0) { add_to_history(hist, cmd); return builtin_jobs(jobs); } // List history. if (strcmp(cmd->args[0], "history") == 0) { int exit_code = builtin_history(hist); add_to_history(hist, cmd); return exit_code; } // Exit. if (strcmp(cmd->args[0], "exit") == 0) { return builtin_exit(); } // Change directory. if (strcmp(cmd->args[0], "cd") == 0) { int exit_code = builtin_cd(cmd); if (exit_code == 0) { add_to_history(hist, cmd); } return exit_code; } // Print working directory. if (strcmp(cmd->args[0], "pwd") == 0) { add_to_history(hist, cmd); return builtin_pwd(); } // Bring to foreground. if (strcmp(cmd->args[0], "fg") == 0) { int exit_code = builtin_fg(cmd, jobs); if (exit_code == 0) { add_to_history(hist, cmd); } return exit_code; } // Execute from history. char* endptr = NULL; long num = strtol(cmd->args[0], &endptr, 10); if (*endptr == '\0' && !(num == 0 && errno == EINVAL)) { // Do not save to history to avoid confusion. int exit_code = builtin_exec_from_history(cmd, jobs, hist); freecmd(cmd); return exit_code; } // Command not found. return COMMAND_NOT_FOUND; }
TEST builtin_cd_dotdot(void) { char *argv[] = {"cd", ".."}; int argc = sizeof(argv) / sizeof(argv[0]); char *old_path = getcwd(NULL, 0); int cd_exit_status = builtin_cd(-1, -1, argc, argv); char *new_path = getcwd(NULL, 0); ASSERT_EQ(0, cd_exit_status); ASSERT(strcmp(old_path, new_path) > 0); free(old_path); free(new_path); PASS(); }
TEST builtin_cd_permission_denied(void) { char *argv[] = {"cd", "/root"}; int argc = sizeof(argv) / sizeof(argv[0]); char *old_path = getcwd(NULL, 0); int cd_exit_status = builtin_cd(-1, -1, argc, argv); char *new_path = getcwd(NULL, 0); ASSERT_EQ(1, cd_exit_status); ASSERT_STR_EQ(old_path, new_path); free(old_path); free(new_path); PASS(); }
TEST builtin_cd_no_such_directory(void) { char *argv[] = {"cd", "non_existing_direcotry"}; int argc = sizeof(argv) / sizeof(argv[0]); char *old_path = getcwd(NULL, 0); int cd_exit_status = builtin_cd(-1, -1, argc, argv); char *new_path = getcwd(NULL, 0); ASSERT_EQ(1, cd_exit_status); ASSERT_STR_EQ(old_path, new_path); free(old_path); free(new_path); PASS(); }
void script_process(char* script) { // Split script in independent pipelines char* array[10]; int numPipelines = gettokens(script, array, 10, ";"); // run script commands int i; for(i = 0; i < numPipelines; ++i) { // expand environment variables and substitute command line char pointer // with the one with expanded environment variables (if necesary) // char* expanded = expand_envVars(array[i]); // if(expanded) array[i] = expanded; array[i] = environment_expand(array[i]); // move commands to background (if necesary) background(array[i]); // Exec `cd` (it's a built-in, but must change shell environment itself, // so we check and exec for it directly here) if(builtin_cd(array[i])) { free(array[i]); continue; } // Set environment variable if(environment_set(array[i])) { free(array[i]); continue; } // run foreground command pipeline_process(array[i]); // free line created by environment variables expansion free(array[i]); } }
/** * Command node: fork synchronously and call exec */ static int do_command(CommandNode *node) { pid_t child; if (strcmp(node->command, "cd") == 0) return builtin_cd(node->arguments); if (((child = fork())) == 0) { /* child process */ setup_redirections(node); replace_process(node->command, node->arguments); /* noreturn */ } else { /* parent process */ return check_wait(child); } return 1; }
void execute(struct parsed_line *p) { int status; extern void execute_one_subcommand(struct parsed_line *p); for (; p; p = p->next) { if (p->conntype == CONN_OR && laststatus == 0) { /* last command succeeded, so don't do this one */ } else if (p->conntype == CONN_AND && laststatus) { /* last command failed, so don't do this one */ } else { /* * "exit" and "cd" are handled specially to avoid the fork(). * Ideally the check should be later to make i/o redirection and * piping work, but we'd have to fudge the forking that way. */ if (p->pl && strcmp(p->pl->argv[0], "exit") == 0) { laststatus = builtin_exit(p->pl->argv); } else if (p->pl && strcmp(p->pl->argv[0], "cd") == 0) { laststatus = builtin_cd(p->pl->argv); } else { fflush(stdout); switch (fork()) { case -1: perror("fork"); laststatus = 127; break; case 0: /* child */ execute_one_subcommand(p); break; default: /* parent */ wait(&status); laststatus = status >> 8; } } } } }