void execute_sequence_command(command_t c) { int status; pid_t pid = fork(); if(pid > 0) { // Parent process waitpid(pid, &status, 0); c->status = status; } else if(pid == 0) { //Child process pid = fork(); if( pid > 0) { // The child continues waitpid(pid, &status, 0); execute_simple_command (c->u.command[1]); _exit(c->u.command[1]->status); } else if( pid == 0) { // The child of the child now runs execute_simple_command (c->u.command[0]); _exit(c->u.command[0]->status); } else error(1, 0, "Could not fork"); } else error(1, 0, "Could not fork"); }
void execute_command (command_t c, int time_travel) { /* FIXME: Replace this with your implementation. You may need to add auxiliary functions and otherwise modify the source code. You can also use external functions defined in the GNU C Library. */ if(c == NULL) return; if(time_travel ==1) execute_time_travel(c); else { switch(c->type) { case SIMPLE_COMMAND: execute_simple_command(c); break; case PIPE_COMMAND: printf("pipe;"); execute_pipe_command(c); break; default: break; } } }
int exec_command(command_t c, int time_travel) { switch(c->type) { case AND_COMMAND: execute_and_command(c); break; case OR_COMMAND: execute_or_command(c); break; case PIPE_COMMAND: execute_pipe_command(c); break; case SEQUENCE_COMMAND: execute_sequence_command(c); break; case SIMPLE_COMMAND: execute_simple_command(c); break; case SUBSHELL_COMMAND: execute_subshell_command(c); break; default: error(1, 0, "Invalid command type"); } }
int execute_command (command_t c, bool a) { if (!a) { switch(c->type){ case AND_COMMAND: return execute_and_command(c); break; case OR_COMMAND: return execute_or_command(c); break; case SEQUENCE_COMMAND: return execute_sequence_command(c); break; case PIPE_COMMAND: return execute_pipe_command(c); break; case SIMPLE_COMMAND: return execute_simple_command(c); break; case SUBSHELL_COMMAND: return execute_command(c->u.subshell_command, 0); break; } } }
void execute_command (command_t c, int time_travel) { /* FIXME: Replace this with your implementation. You may need to add auxiliary functions and otherwise modify the source code. You can also use external functions defined in the GNU C Library. */ if(c == NULL) return; if(time_travel ==1) execute_time_travel(c); else { switch(c->type) { case SIMPLE_COMMAND: execute_simple_command(c); break; case AND_COMMAND: execute_and_command(c); break; case OR_COMMAND: execute_or_command(c); break; case PIPE_COMMAND: execute_pipe_command(c); break; case SUBSHELL_COMMAND: execute_subshell_command(c); break; case SEQUENCE_COMMAND: execute_sequence_command(c); break; case WHILE_COMMAND: execute_while_command(c); break; case FOR_COMMAND: execute_for_command(c); break; case UNTIL_COMMAND: execute_until_command(c); break; case IF_COMMAND: execute_if_command(c); break; case NOT_COMMAND: execute_not_command(c); break; default: error(1,0, "Error: Unknown command!"); break; } //error (1, 0, "command execution not yet implemented"); } }
int main(int argc, char** argv) { char cwd[MAX_DIRNAME]; /* Current working directory */ char command_line[MAX_COMMAND]; /* The command */ char *tokens[MAX_TOKEN]; /* Command tokens (program name, * parameters, pipe, etc.) */ while (1) { /* Display prompt */ getcwd(cwd, MAX_DIRNAME-1); printf("%s> ", cwd); /* Read the command line */ fgets(command_line, MAX_COMMAND, stdin); /* Strip the new line character */ if (command_line[strlen(command_line) - 1] == '\n') { command_line[strlen(command_line) - 1] = '\0'; } /* Parse the command into tokens */ parse_line(command_line, tokens); /* Check for empty command */ if (!(*tokens)) { continue; } /* Construct chain of commands, if multiple commands */ command *cmd = construct_command(tokens); // print_command(cmd, 0); int exitcode = 0; if (cmd->scmd) { exitcode = execute_simple_command(cmd->scmd); if (exitcode == -1) { release_command(cmd); break; } } else { exitcode = execute_complex_command(cmd); if (exitcode == -1) { release_command(cmd); break; } } release_command(cmd); } return 0; }
int main(int argc, char** argv) { char cwd[MAX_DIRNAME]; /* Current working directory */ char command_line[MAX_COMMAND]; /* The command */ char *tokens[MAX_TOKEN]; /* Command tokens (program name, parameters, pipe, etc.) */ while (1) { /* Display prompt */ getcwd(cwd, MAX_DIRNAME-1); printf("%s> ", cwd); /* Read the command line */ gets(command_line); /* Parse the command into tokens */ parse_line(command_line, tokens); /* Empty command */ if (!(*tokens)) continue; /* Exit */ if (strcmp(tokens[0], "exit") == 0) exit(0); /* Construct chain of commands, if multiple commands */ command *cmd = construct_command(tokens); int exitcode = 0; if (cmd->scmd) { exitcode = execute_simple_command(cmd->scmd); if (exitcode == -1) break; } else { exitcode = execute_complex_command(cmd); if (exitcode == -1) break; } release_command(cmd); } return 0; }
/** * Executes a complex command. A complex command is two commands chained * together with a pipe operator. */ int execute_complex_command(command *c){ if (c->scmd){ execute_simple_command(c->scmd); }else{ int pfd[2]; if(pipe(pfd) == -1) { perror("Pipe failed"); exit(1); } if(fork() == 0) //first fork { close(1); //closing stdout dup(pfd[1]); //replacing stdout with pipe write close(pfd[0]); //closing pipe read close(pfd[1]); execute_complex_command(c->cmd1); exit(1); } if(fork() == 0) //creating 2nd child { close(0); //closing stdin dup(pfd[0]); //replacing stdin with pipe read close(pfd[1]); //closing pipe write close(pfd[0]); execute_complex_command(c->cmd2); exit(1); } close(pfd[0]); close(pfd[1]); wait(0); wait(0); return 0; } return 0; }
void execute_wrapper(command_t c) { switch(c->type){ case (SIMPLE_COMMAND): execute_simple_command(c); break; case (AND_COMMAND): case (OR_COMMAND): execute_and_or_command(c); break; case (SEQUENCE_COMMAND): execute_sequence_command(c); break; case (PIPE_COMMAND): execute_pipe_command(c); break; case (SUBSHELL_COMMAND): execute_subshell_command(c); break; } }
void execute_command (command_t c, int time_travel) { /* FIXME: Replace this with your implementation. You may need to add auxiliary functions and otherwise modify the source code. You can also use external functions defined in the GNU C Library. */ if(c == NULL) return; //printf("Enter%d\n", c->type); if (!time_travel) { switch(c->type) { case SIMPLE_COMMAND: execute_simple_command(c); break; case AND_COMMAND: execute_and_command(c); break; case OR_COMMAND: execute_or_command(c); break; case PIPE_COMMAND: execute_pipe_command(c); break; case SEQUENCE_COMMAND: execute_sequence_command(c); break; case SUBSHELL_COMMAND: execute_subshell_command(c); break; default: error(1, 0, "Incorrect Command Type"); } } }
void recursive_execute_command (command_t c, bool timetravel, bool pipe_output) { // If we've finished running, there is nothing left to do if(c == NULL || c->finished_running) return; // Otherwise, check to see if we are done and return if(c->running) { close_command_exec_resources (c, timetravel); return; } // Copy any specified file descriptors down to the children switch (c->type) { case SEQUENCE_COMMAND: case AND_COMMAND: case OR_COMMAND: case PIPE_COMMAND: c->u.command[0]->fd_read_from = c->fd_read_from; c->u.command[0]->fd_writing_to = c->fd_writing_to; c->u.command[1]->fd_read_from = c->fd_read_from; c->u.command[1]->fd_writing_to = c->fd_writing_to; break; case SUBSHELL_COMMAND: c->u.subshell_command->fd_read_from = c->fd_read_from; c->u.subshell_command->fd_writing_to = c->fd_writing_to; break; case SIMPLE_COMMAND: break; default: break; } // Execute commands based on tokens and properly set the status up the tree switch (c->type) { case SEQUENCE_COMMAND: // Run the second command after the first has finished. The only // time a sequence command is encountered its in a subshell, so we // won't be parallelizing anyway. recursive_execute_command (c->u.command[0], timetravel, pipe_output); if(c->u.command[0]->finished_running) recursive_execute_command (c->u.command[1], timetravel, pipe_output); break; case SUBSHELL_COMMAND: { // Store a copy to stdin and stdout in case the shell wants to redirect input/output int fd_old_stdin = dup (STDIN_FILENO); int fd_old_stdout = dup (STDOUT_FILENO); if(fd_old_stdin < 0 || fd_old_stdout < 0) show_error(c->line_number, "Too many files open!", NULL); if(c->input != NULL) { char *input_path = get_redirect_file_path (c->input); int fd_in = open (input_path, O_RDONLY); free (input_path); if(fd_in == -1) show_error (c->line_number, "Error opening input file", c->input); dup2 (fd_in, STDIN_FILENO); close (fd_in); } if(c->output != NULL) { char *output_path = get_redirect_file_path (c->output); int fd_out = open (c->output, O_WRONLY | O_CREAT | O_TRUNC, // Data from the file will be truncated S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); // By default bash in posix mode will create files as rw-r--r-- free (output_path); if(fd_out == -1) show_error (c->line_number, "Error opening output file", c->output); dup2 (fd_out, STDOUT_FILENO); close (fd_out); } // Status of SUBSHELL_COMMAND is the same as the command inside it recursive_execute_command (c->u.subshell_command, timetravel, pipe_output); c->fd_writing_to = c->u.subshell_command->fd_writing_to; // Reset stdin and stdout dup2 (fd_old_stdin, STDIN_FILENO); dup2 (fd_old_stdout, STDOUT_FILENO); close (fd_old_stdin); close (fd_old_stdout); break; } case AND_COMMAND: recursive_execute_command (c->u.command[0], timetravel, pipe_output); if(command_status (c->u.command[0]) == 0) recursive_execute_command (c->u.command[1], timetravel, pipe_output); break; case OR_COMMAND: recursive_execute_command (c->u.command[0], timetravel, pipe_output); if(command_status (c->u.command[0]) != 0) recursive_execute_command (c->u.command[1], timetravel, pipe_output); break; case PIPE_COMMAND: recursive_execute_command (c->u.command[0], timetravel, true); // Set the next command to read from the opened pipe c->u.command[1]->fd_read_from = c->u.command[0]->fd_writing_to; recursive_execute_command (c->u.command[1], timetravel, pipe_output); c->fd_writing_to = c->u.command[1]->fd_writing_to; break; case SIMPLE_COMMAND: execute_simple_command (c, pipe_output); break; default: break; } // Check to see if we are done. If not this will properly set up the run flags. // Close the resources if and only if we aren't in a nested pipe // otherwise it's possible to cause a deadlock! Everything will get recursively // freed in a higher frame anyways. if(!pipe_output) close_command_exec_resources (c, timetravel); }