#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[0] == '\0' || input[0] == '#') { continue; } char*** array = malloc(sizeof(char**)); int num_strings = input_format(input, input_size, array); char* first_array = (*array)[0]; // Built in shell commands if(!strncmp(first_array, "exit", 4)) return 0; else if(!strncmp(first_array, "cd", 2)) inbuilt_cd((*array)[1]); else if (!strncmp(first_array, "status", 6)) printf("%d\n", status); else status = run_command(array, num_strings); fflush(stdout); } } int input_format(char* input, size_t input_size, char*** array) { const int max_args = 512; int num_strings = 0; char* pch; *array = malloc(sizeof(char*) * max_args); pch = strtok (input," "); while (pch != NULL) { (*array)[num_strings] = malloc(sizeof(char*) * (strlen(pch) + 1)); strcpy((*array)[num_strings], pch); num_strings++; pch = strtok (NULL, " "); } return num_strings; } void inbuilt_cd(char* args) { if(args) chdir(args); else chdir(getenv("HOME")); } 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(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; if(!background) waitpid(f, &status, 0); free(comb_string); return status; } 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)); } }