diff --git a/smallsh/main.c b/smallsh/main.c index fbd9ddc..762dcaf 100644 --- a/smallsh/main.c +++ b/smallsh/main.c @@ -1,25 +1,54 @@ #include "main.h" +volatile sig_atomic_t stop_flag = 0; +int stop_msg = 0; + int main() { + /* + struct sigaction sa; + sa.sa_handler = sigstop_handle; + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + */ + + signal(SIGINT, sigint_handle); + signal(SIGTSTP, sigstop_handle); + int status = 0; size_t input_size = 2048; size_t getline_len; char* input = malloc(sizeof(char) * input_size); while(1) { + + clean_children(); + + //signal handling + if(stop_msg) { + if(stop_flag) + printf("Entering Stop Mode: Background Processes Do Not Work (&)\n"); + else + printf("Exiting Stop Mode: Background Processes Now Work (&)\n"); + stop_msg = 0; + } + + printf(": "); fflush(stdout); getline_len = getline(&input, &input_size, stdin); input[getline_len - 1] = '\0'; + expand_dollar(input, input_size); + // Ignore whitespace or comments - if(input == NULL || + if(input[0] == '\0' || input[0] == '#') { continue; } + char*** array = malloc(sizeof(char**)); int num_strings = input_format(input, input_size, array); @@ -73,13 +102,95 @@ int run_command(char*** array, int num_array) { char* comb_string = malloc(sizeof(char) * 100); sprintf(comb_string, "/usr/bin/"); strcat(comb_string, (*array)[0]); + + + //Check to see if the process is ran in the background + int background = 0; + if(!strncmp("&", (*array)[num_array - 1], 1)) { + if(!stop_flag) + background = 1; + (*array)[num_array - 1] = NULL; + } + + // Check to see if the process has output redirected + int redirect_o = 0; + char* redirect_o_str = NULL; + for(int i = 0; i < num_array; i++) { + + if((*array)[i] == NULL) + continue; + + if(!strncmp((*array)[i], ">", 1)) { + redirect_o = 1; + redirect_o_str = (*array)[i+1]; + + (*array)[i] = NULL; + (*array)[i+1] = NULL; + + break; + } + } + + sterilize_array(array, num_array); + + // Check to see if the process has input redirected + int redirect_i = 0; + char* redirect_i_str = NULL; + for(int i = 0; i < num_array; i++) { + + if((*array)[i] == NULL) + continue; + + if(!strncmp((*array)[i], "<", 1)) { + redirect_i = 1; + redirect_i_str = (*array)[i+1]; + + (*array)[i] = NULL; + (*array)[i+1] = NULL; + + break; + } + } + + sterilize_array(array, num_array); + int f = fork(); pid_t pid; - if(!f) + if(!f) { + if(redirect_o) { + int fd = open(redirect_o_str, O_WRONLY | O_CREAT, 0666); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + + } + else if(background) { + int fd = open("/dev/null", O_WRONLY, 0666); + //Direct to dev null + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + } + + if(redirect_i) { + int fd = open(redirect_i_str, O_RDONLY); + dup2(fd, STDIN_FILENO); + } + else if(background) { + int fd = open("/dev/null", O_RDONLY); + dup2(fd, STDIN_FILENO); + } + pid = execv(comb_string, (*array)); + perror(comb_string); + exit(1); + } + else if(background){ + printf("background pid is %d\n", f); + } + int status; - waitpid(pid, &status, 0); + if(!background) + waitpid(f, &status, 0); free(comb_string); @@ -88,5 +199,67 @@ int run_command(char*** array, int num_array) { } +void expand_dollar(char* input, size_t input_size) { + char pid[20]; + int pid_size = sprintf(pid, "%d", getpid()); + char* buffer = malloc(sizeof(char*) * (pid_size + input_size + 1)); + char* dollar; + + dollar = strstr(input, "$$"); + while(dollar != NULL) { + + dollar[0] = '%'; + dollar[1] = 's'; + sprintf(buffer, input, pid); + strcpy(input, buffer); + dollar = strstr(input, "$$"); + } +} + +void sterilize_array(char*** array, size_t num_array) { + + for(int i = 0; i < num_array; i++) { + + //check to see if it can be the end of the array + if((*array)[i] == NULL) { + int is_end = 1; + //check if there is any more non-null values in the array + for(int j = i; j < num_array; j++) { + if((*array)[j]) + is_end = 0; + } + + if(!is_end) { + + //shift the array by 1 bit + for(int j = i; j < num_array; j++) { + (*array)[j] = (*array)[j+1]; + + } + } + } + } +} + +void sigint_handle() { +} + +void sigstop_handle(int n) { + stop_flag = !stop_flag; + stop_msg = !stop_msg; +} + +void clean_children() { + + // Clean up any child process that has not been cleaned + int pid = 43110; + while(pid >0) { + int status; + pid = waitpid(0, &status, WNOHANG); + + if(pid > 0) + printf("\nbackground pid %d is done: exit value %d\n", pid, WEXITSTATUS(status)); + } +} diff --git a/smallsh/main.h b/smallsh/main.h index 1795bdf..ad14ecc 100644 --- a/smallsh/main.h +++ b/smallsh/main.h @@ -7,9 +7,16 @@ #include "string.h" #include "unistd.h" #include "sys/wait.h" +#include "fcntl.h" +#include "signal.h" int input_format(char*, size_t, char***); void inbuilt_cd(char*); int run_command(char***, int); +void expand_dollar(char*, size_t); +void sterilize_array(char***, size_t); +void sigint_handle(); +void sigstop_handle(); +void clean_children(); #endif