diff --git a/include/90s.h b/include/90s.h index 808dd45..98c1631 100644 --- a/include/90s.h +++ b/include/90s.h @@ -1,5 +1,7 @@ -#ifndef RUSH_H_ -#define RUSH_H_ +#ifndef S_H_ +#define S_H_ + +#define VERSION "1.0.0" #include diff --git a/include/color.h b/include/color.h deleted file mode 100644 index 34ea889..0000000 --- a/include/color.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef COLOR_H_ -#define COLOR_H_ - -const char *lavender = "174;174;255"; -const char *pink = "255;210;239"; -const char *blue = "137;180;250"; - -char *color_text(char str[], const char *color); - -#endif diff --git a/include/commands.h b/include/commands.h index 4c5d8ac..1ae8f07 100644 --- a/include/commands.h +++ b/include/commands.h @@ -1,7 +1,6 @@ #ifndef COMMANDS_H_ #define COMMANDS_H_ -char *replace_absolute_home(char *str); int num_builtins(void); bool is_builtin(char *command); int execute(char **args, int fd, int options); diff --git a/src/90s.c b/src/90s.c index f5b8c1c..35774b5 100644 --- a/src/90s.c +++ b/src/90s.c @@ -9,507 +9,526 @@ #include #include -#include "color.h" #include "constants.h" #include "history.h" #include "commands.h" -void *memalloc(size_t size) { - void *ptr = malloc(size); - if (!ptr) { - fputs("90s: Error allocating memory\n", stderr); - exit(EXIT_FAILURE); - } - return ptr; +void *memalloc(size_t size) +{ + void *ptr = malloc(size); + if (!ptr) { + fputs("90s: Error allocating memory\n", stderr); + exit(EXIT_FAILURE); + } + return ptr; } -void change_terminal_attribute(int option) { - static struct termios oldt, newt; - tcgetattr(STDIN_FILENO, &oldt); - if (option) { - newt = oldt; - newt.c_lflag &= ~(ICANON | ECHO); // allows getchar without pressing enter key and echoing the character twice - tcsetattr(STDIN_FILENO, TCSANOW, &newt); // set settings to stdin - } else { - tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // restore to old settings - } +void change_terminal_attribute(int option) +{ + static struct termios oldt, newt; + tcgetattr(STDIN_FILENO, &oldt); + if (option) { + newt = oldt; + newt.c_lflag &= ~(ICANON | ECHO); // allows getchar without pressing enter key and echoing the character twice + tcsetattr(STDIN_FILENO, TCSANOW, &newt); // set settings to stdin + } else { + tcsetattr(STDIN_FILENO, TCSANOW, &oldt); // restore to old settings + } } -char **setup_path_variable(void) { - char *envpath = getenv("PATH"); - if (envpath == NULL) { - fprintf(stderr, "90s: PATH environment variable is missing\n"); - exit(EXIT_FAILURE); - } - char *path_cpy = memalloc(sizeof(char) * (strlen(envpath) + 1)); - char *path = memalloc(sizeof(char) * (strlen(envpath) + 1)); - strcpy(path_cpy, envpath); - strcpy(path, envpath); - int path_count = 0; - while (*path_cpy != '\0') { - // count number of : to count number of elements - if (*path_cpy == ':') { - path_count++; - } - path_cpy++; - } - path_count += 2; // adding one to be correct and one for terminator - char **paths = memalloc(sizeof(char *) * path_count); - char *token = strtok(path, ":"); - int counter = 0; - while (token != NULL) { - paths[counter] = token; // set element to the pointer of start of path - token = strtok(NULL, ":"); - counter++; - } - paths[counter] = NULL; - return paths; +char **setup_path_variable(void) +{ + char *envpath = getenv("PATH"); + if (envpath == NULL) { + fprintf(stderr, "90s: PATH environment variable is missing\n"); + exit(EXIT_FAILURE); + } + char *path_cpy = memalloc(strlen(envpath) + 1); + char *path = memalloc(strlen(envpath) + 1); + strcpy(path_cpy, envpath); + strcpy(path, envpath); + int path_count = 0; + while (*path_cpy != '\0') { + // count number of : to count number of elements + if (*path_cpy == ':') { + path_count++; + } + path_cpy++; + } + path_count += 2; // adding one to be correct and one for terminator + char **paths = memalloc(sizeof(char *) * path_count); + char *token = strtok(path, ":"); + int counter = 0; + while (token != NULL) { + paths[counter] = token; // set element to the pointer of start of path + token = strtok(NULL, ":"); + counter++; + } + paths[counter] = NULL; + return paths; } -bool find_command(char **paths, char *command) { - if (strncmp(command, "", 1) == 0) { - return false; - } - while (*paths != NULL) { - char current_path[PATH_MAX]; - current_path[0] = '\0'; - sprintf(current_path, "%s/%s", *paths, command); - if (access(current_path, X_OK) == 0) { - // command is executable - return true; - } else { - if (is_builtin(command)) { - return true; - } - } - paths++; - } - return false; +bool find_command(char **paths, char *command) +{ + if (strncmp(command, "", 1) == 0) { + return false; + } + while (*paths != NULL) { + char current_path[PATH_MAX]; + current_path[0] = '\0'; + sprintf(current_path, "%s/%s", *paths, command); + if (access(current_path, X_OK) == 0) { + // command is executable + return true; + } else { + if (is_builtin(command)) { + return true; + } + } + paths++; + } + return false; } -void shiftleft(int chars) { - printf("\033[%dD", chars); +void shiftleft(int chars) +{ + printf("\033[%dD", chars); } -void shiftright(int chars) { - printf("\033[%dC", chars); +void shiftright(int chars) +{ + printf("\033[%dC", chars); } -void clearline(void) { - printf("\033[K"); // clear line to the right of cursor +void clearline(void) +{ + printf("\033[K"); // clear line to the right of cursor } -void highlight(char *buffer, char **paths) { - char *cmd_part = strchr(buffer, ' '); - char *command_without_arg = NULL; - int cmd_len = 0; - bool valid; +void highlight(char *buffer, char **paths) +{ + char *cmd_part = strchr(buffer, ' '); + char *command_without_arg = NULL; + int cmd_len = 0; + bool valid; - if (cmd_part != NULL) { - cmd_len = cmd_part - buffer; - char *cmd = memalloc(sizeof(char) * (cmd_len + 1)); - command_without_arg = memalloc(sizeof(char) * (cmd_len + 1)); - for (int i = 0; i < (cmd_part - buffer); i++) { - cmd[i] = buffer[i]; - } - strcpy(command_without_arg, cmd); - cmd[cmd_len] = '\0'; - command_without_arg[cmd_len] = '\0'; - valid = find_command(paths, cmd); - free(cmd); - } else { - valid = find_command(paths, buffer); - } + if (cmd_part != NULL) { + cmd_len = cmd_part - buffer; + char *cmd = memalloc(cmd_len + 1); + command_without_arg = memalloc(cmd_len + 1); + for (int i = 0; i < (cmd_part - buffer); i++) { + cmd[i] = buffer[i]; + } + strcpy(command_without_arg, cmd); + cmd[cmd_len] = '\0'; + command_without_arg[cmd_len] = '\0'; + valid = find_command(paths, cmd); + free(cmd); + } else { + valid = find_command(paths, buffer); + } - if (valid) { - if (command_without_arg != NULL) { - buffer += cmd_len; - printf("\x1b[38;2;166;227;161m%s\x1b[0m\x1b[38;2;255;255;255m%s\x1b[0m", command_without_arg, buffer); // print green as valid command, but only color the command, not the arguments - buffer -= cmd_len; - } else { - printf("\x1b[38;2;166;227;161m%s\x1b[0m", buffer); // print green as valid command - } - } else { - if (command_without_arg != NULL) { - buffer += cmd_len; - printf("\x1b[38;2;243;139;168m%s\x1b[0m\x1b[38;2;255;255;255m%s\x1b[0m", command_without_arg, buffer); // print red as invalid command, but only color the command, not the arguments - buffer -= cmd_len; - } else { - printf("\x1b[38;2;243;139;168m%s\x1b[0m", buffer); // print red as invalid command - } - } + if (valid) { + if (command_without_arg != NULL) { + buffer += cmd_len; + printf("\x1b[32m%s\x1b[37m%s\x1b[m", command_without_arg, buffer); // print green as valid command, but only color the command, not the arguments + buffer -= cmd_len; + } else { + printf("\x1b[32m%s\x1b[m", buffer); // print green as valid command + } + } else { + if (command_without_arg != NULL) { + buffer += cmd_len; + printf("\x1b[31m%s\x1b[37m%s\x1b[m", command_without_arg, buffer); // print red as invalid command, but only color the command, not the arguments + buffer -= cmd_len; + } else { + printf("\x1b[31m%s\x1b[m", buffer); // print red as invalid command + } + } fflush(stdout); - free(command_without_arg); + free(command_without_arg); } -char *readline(char **paths) { - int bufsize = RL_BUFSIZE; - int position = 0; - char *buffer = memalloc(sizeof(char) * bufsize); +char *readline(char **paths) +{ + int bufsize = RL_BUFSIZE; + int position = 0; + char *buffer = memalloc(bufsize); - bool moved = false; - bool backspaced = false; - bool navigated = false; - bool insertatmiddle = false; - bool replaced = false; + bool moved = false; + bool backspaced = false; + bool navigated = false; + bool insertatmiddle = false; + bool replaced = false; - buffer[0] = '\0'; - while (1) { - int c = getchar(); // read a character - int buf_len = strlen(buffer); - - // check each character user has input - switch (c) { - case EOF: - exit(EXIT_SUCCESS); - case 10: { - // enter/new line feed - if (buf_len == 0) { - return NULL; - } - // check if command includes !! - if (strstr(buffer, "!!") != NULL) { - char *last_command = read_command(1); - if (last_command != NULL) { - // replace !! with the last command - char *replace = strstr(buffer, "!!"); - int replace_len = strlen(replace); - int last_command_len = strlen(last_command); - int buffer_len = strlen(buffer); - if (last_command_len > replace_len) { - buffer = realloc(buffer, buffer_len + last_command_len - replace_len + 1); - if (!buffer) { - fprintf(stderr, "90s: Error allocating memory\n"); - exit(EXIT_FAILURE); - } - } - memmove(replace + last_command_len, replace + replace_len, buffer_len - (replace - buffer) - replace_len + 1); - memcpy(replace, last_command, last_command_len); - position += last_command_len - replace_len; - shiftright(last_command_len - replace_len); - replaced = true; - break; - } - } else { - buffer[buf_len] = '\0'; - // clear all characters after the command - for (int start = buf_len + 1; buffer[start] != '\0'; start++) { - buffer[start] = '\0'; - } - printf("\n"); // give space for response - position = 0; - return buffer; - } - } - case 127: // backspace - if (buf_len >= 1) { - position--; - for (int i = position; i < buf_len; i++) { - // shift the buffer - buffer[i] = buffer[i + 1]; - } - backspaced = true; - moved = false; - } - break; - case 27: // arrow keys comes at three characters, 27, 91, then 65-68 - if (getchar() == 91) { - int arrow_key = getchar(); - if (arrow_key == 65) { // up - // read history file and fill prompt with latest command - char *last_command = read_command(1); - if (last_command != NULL) { - strcpy(buffer, last_command); - } - navigated = true; - moved = false; - break; - } else if (arrow_key == 66) { // down - char *last_command = read_command(0); - if (last_command != NULL) { - strcpy(buffer, last_command); - } - navigated = true; - moved = false; - break; - } else if (arrow_key == 67) { // right - if (position < buf_len) { - shiftright(1); - position++; - } - moved = true; - break; - } else if (arrow_key == 68) { // left - if (position >= 1) { - shiftleft(1); - position--; - } - moved = true; - break; - } - } - default: - if (c > 31 && c < 127) { - if (position == buf_len) { - // Append character to the end of the buffer - buffer[buf_len] = c; - buffer[buf_len + 1] = '\0'; - moved = false; - navigated = false; - } else { - // Insert character at the current position - memmove(&buffer[position + 1], &buffer[position], buf_len - position + 1); - buffer[position] = c; - shiftright(1); - insertatmiddle = true; - } - position++; - } - } + buffer[0] = '\0'; + while (1) { + int c = getchar(); // read a character + int buf_len = strlen(buffer); - buf_len = strlen(buffer); + // check each character user has input + switch (c) { + case EOF: + exit(EXIT_SUCCESS); + case 10: { + // enter/new line feed + if (buf_len == 0) { + return NULL; + } + // check if command includes !! + if (strstr(buffer, "!!") != NULL) { + char *last_command = read_command(1); + if (last_command != NULL) { + // replace !! with the last command + char *replace = strstr(buffer, "!!"); + int replace_len = strlen(replace); + int last_command_len = strlen(last_command); + int buffer_len = strlen(buffer); + if (last_command_len > replace_len) { + buffer = realloc(buffer, buffer_len + last_command_len - replace_len + 1); + if (!buffer) { + fprintf(stderr, "90s: Error allocating memory\n"); + exit(EXIT_FAILURE); + } + } + memmove(replace + last_command_len, replace + replace_len, buffer_len - (replace - buffer) - replace_len + 1); + memcpy(replace, last_command, last_command_len); + position += last_command_len - replace_len; + shiftright(last_command_len - replace_len); + replaced = true; + break; + } + } else { + buffer[buf_len] = '\0'; + // clear all characters after the command + for (int start = buf_len + 1; buffer[start] != '\0'; start++) { + buffer[start] = '\0'; + } + printf("\n"); // give space for response + position = 0; + return buffer; + } + } + case 127: // backspace + if (buf_len >= 1) { + position--; + for (int i = position; i < buf_len; i++) { + // shift the buffer + buffer[i] = buffer[i + 1]; + } + backspaced = true; + moved = false; + } + break; + case 27: // arrow keys comes at three characters, 27, 91, then 65-68 + if (getchar() == 91) { + int arrow_key = getchar(); + if (arrow_key == 65) { // up + // read history file and fill prompt with latest command + char *last_command = read_command(1); + if (last_command != NULL) { + strcpy(buffer, last_command); + } + navigated = true; + moved = false; + break; + } else if (arrow_key == 66) { // down + char *last_command = read_command(0); + if (last_command != NULL) { + strcpy(buffer, last_command); + } + navigated = true; + moved = false; + break; + } else if (arrow_key == 67) { // right + if (position < buf_len) { + shiftright(1); + position++; + } + moved = true; + break; + } else if (arrow_key == 68) { // left + if (position >= 1) { + shiftleft(1); + position--; + } + moved = true; + break; + } + } + default: + if (c > 31 && c < 127) { + if (position == buf_len) { + // Append character to the end of the buffer + buffer[buf_len] = c; + buffer[buf_len + 1] = '\0'; + moved = false; + navigated = false; + } else { + // Insert character at the current position + memmove(&buffer[position + 1], &buffer[position], buf_len - position + 1); + buffer[position] = c; + shiftright(1); + insertatmiddle = true; + } + position++; + } + } - if (replaced) { - shiftleft(buf_len); - clearline(); - } + buf_len = strlen(buffer); - if (navigated && buf_len >= 1) { - if (position > 0) { - shiftleft(position); // move cursor to the beginning - clearline(); - } - position = buf_len; - } + if (replaced) { + shiftleft(buf_len); + clearline(); + } - if (moved) { - moved = false; - continue; - } + if (navigated && buf_len >= 1) { + if (position > 0) { + shiftleft(position); // move cursor to the beginning + clearline(); + } + position = buf_len; + } - if (!navigated && !replaced) { - if (position != buf_len) { - // not at normal place - if (backspaced) { - shiftleft(position + 1); - } else { - shiftleft(position); // move cursor to the beginning - } - } else if (buf_len > 1) { - if (backspaced) { - shiftleft(buf_len + 1); // move cursor to the beginning - } else { - shiftleft(buf_len - 1); // move cursor to the beginning - } - } else if (buf_len == 1) { - if (backspaced) { - shiftleft(2); - } - } else if (buf_len == 0) { - if (backspaced) { - shiftleft(1); - } - } - clearline(); - } else { - navigated = false; - } + if (moved) { + moved = false; + continue; + } - highlight(buffer, paths); + if (!navigated && !replaced) { + if (position != buf_len) { + // not at normal place + if (backspaced) { + shiftleft(position + 1); + } else { + shiftleft(position); // move cursor to the beginning + } + } else if (buf_len > 1) { + if (backspaced) { + shiftleft(buf_len + 1); // move cursor to the beginning + } else { + shiftleft(buf_len - 1); // move cursor to the beginning + } + } else if (buf_len == 1) { + if (backspaced) { + shiftleft(2); + } + } else if (buf_len == 0) { + if (backspaced) { + shiftleft(1); + } + } + clearline(); + } else { + navigated = false; + } - if (backspaced) { - if (buf_len != position) { - shiftleft(buf_len - position); - } - backspaced = false; - } - if (insertatmiddle) { - shiftleft(buf_len - position); // move cursor back to where it was - insertatmiddle = false; - } - if (replaced) { - replaced = false; - } + highlight(buffer, paths); - // If we have exceeded the buffer, reallocate. - if ((buf_len + 1) >= bufsize) { - bufsize += RL_BUFSIZE; - buffer = realloc(buffer, bufsize); - if (!buffer) { - fprintf(stderr, "90s: Error allocating memory\n"); - exit(EXIT_FAILURE); - } - } - } + if (backspaced) { + if (buf_len != position) { + shiftleft(buf_len - position); + } + backspaced = false; + } + if (insertatmiddle) { + shiftleft(buf_len - position); // move cursor back to where it was + insertatmiddle = false; + } + if (replaced) { + replaced = false; + } + + // If we have exceeded the buffer, reallocate. + if ((buf_len + 1) >= bufsize) { + bufsize += RL_BUFSIZE; + buffer = realloc(buffer, bufsize); + if (!buffer) { + fprintf(stderr, "90s: Error allocating memory\n"); + exit(EXIT_FAILURE); + } + } + } } // split line into arguments -char **argsplit(char *line) { - int bufsize = TOK_BUFSIZE, position = 0; - char **tokens = memalloc(bufsize * sizeof(char*)); - char *token; +char **argsplit(char *line) +{ + int bufsize = TOK_BUFSIZE, position = 0; + char **tokens = memalloc(sizeof(char *) * bufsize); + char *token; - token = strtok(line, TOK_DELIM); - while (token != NULL) { - tokens[position] = token; - position++; + token = strtok(line, TOK_DELIM); + while (token != NULL) { + tokens[position] = token; + position++; - if (position >= bufsize) { - bufsize += TOK_BUFSIZE; - tokens = realloc(tokens, bufsize * sizeof(char*)); - if (!tokens) { - fprintf(stderr, "90s: Error allocating memory\n"); - exit(EXIT_FAILURE); - } - } + if (position >= bufsize) { + bufsize += TOK_BUFSIZE; + tokens = realloc(tokens, sizeof(char *) * bufsize); + if (!tokens) { + fprintf(stderr, "90s: Error allocating memory\n"); + exit(EXIT_FAILURE); + } + } - token = strtok(NULL, TOK_DELIM); - } - tokens[position] = NULL; - return tokens; + token = strtok(NULL, TOK_DELIM); + } + tokens[position] = NULL; + return tokens; } -char **modifyargs(char **args) { - int num_arg = 0; +char **modifyargs(char **args) +{ + int num_arg = 0; - // check if command is ls, diff, or grep, if so, add --color=auto to the arguments - // this is to make ls, diff, and grep have color without user typing it - // this is to make the shell more user friendly - while (args[num_arg] != NULL) { - num_arg++; - } - for (int i = 0; i < num_arg; i++) { - // makes ls and diff and grep have color without user typing it - if (strncmp(args[i], "ls", 2) == 0 || strncmp(args[i], "diff", 4) == 0 || strncmp(args[i], "grep", 4) == 0) { - for (int j = num_arg; j > i; j--) { - args[j + 1] = args[j]; - } - args[i + 1] = "--color=auto"; - num_arg++; - } - } + // check if command is ls, diff, or grep, if so, add --color=auto to the arguments + // this is to make ls, diff, and grep have color without user typing it + // this is to make the shell more user friendly + while (args[num_arg] != NULL) { + num_arg++; + } + for (int i = 0; i < num_arg; i++) { + // makes ls and diff and grep have color without user typing it + if (strncmp(args[i], "ls", 2) == 0 || strncmp(args[i], "diff", 4) == 0 || strncmp(args[i], "grep", 4) == 0) { + for (int j = num_arg; j > i; j--) { + args[j + 1] = args[j]; + } + args[i + 1] = "--color=auto"; + num_arg++; + } + } - return args; + return args; } -char *trimws(char *str) { +char *trimws(char *str) +{ char *end; while (isspace((unsigned char) *str)) - str++; + str++; if(*str == 0) return str; end = str + strlen(str) - 1; while (end > str && isspace((unsigned char) *end)) - end--; + end--; *(end+1) = 0; return str; } -char ***pipe_argsplit(char *line) { - char ***cmdv = memalloc(sizeof(char **) * 128); // 127 commands, 1 for NULL - char **cmds = memalloc(sizeof(char *) * 128); // 127 arguments, 1 for NULL - int num_arg = 0; - char *pipe = strtok(line, "|"); - while (pipe != NULL) { - pipe = trimws(pipe); - cmds[num_arg] = strdup(pipe); - pipe = strtok(NULL, "|"); - num_arg++; - } - cmds[num_arg] = NULL; +char ***pipe_argsplit(char *line) +{ + char ***cmdv = memalloc(sizeof(char **) * 128); // 127 commands, 1 for NULL + char **cmds = memalloc(sizeof(char *) * 128); // 127 arguments, 1 for NULL + int num_arg = 0; + char *pipe = strtok(line, "|"); + while (pipe != NULL) { + pipe = trimws(pipe); + cmds[num_arg] = strdup(pipe); + pipe = strtok(NULL, "|"); + num_arg++; + } + cmds[num_arg] = NULL; - for (int i = 0; i < num_arg; i++) { - char **splitted = argsplit(cmds[i]); - cmdv[i] = modifyargs(splitted); + for (int i = 0; i < num_arg; i++) { + char **splitted = argsplit(cmds[i]); + cmdv[i] = modifyargs(splitted); - } - cmdv[num_arg] = NULL; - free(cmds); - return cmdv; + } + cmdv[num_arg] = NULL; + free(cmds); + return cmdv; } // continously prompt for command and execute it -void command_loop(char **paths) { - char *line; - char **args; - int status = 1; +void command_loop(char **paths) +{ + char *line; + char **args; + int status = 1; - while (status) { - time_t t = time(NULL); - struct tm* current_time = localtime(&t); // get current time - char timestr[256]; - char cwdstr[PATH_MAX]; - if (strftime(timestr, sizeof(timestr), "[%H:%M:%S]", current_time) == 0) { // format time string - return; - } - if (getcwd(cwdstr, sizeof(cwdstr)) == NULL) { // get current working directory - return; - } - char time[256]; - strcpy(time, timestr); - char *modtime = memalloc(sizeof(char) * 256); - modtime = color_text(time, lavender); // lavender colored time string - char *cwd = memalloc(sizeof(char) * (PATH_MAX + 2)); - sprintf(cwd, "[%s]", cwdstr); - cwd = replace_absolute_home(cwd); - cwd = color_text(cwd, pink); // pink colored current directory - char *arrow = memalloc(sizeof(char) * 32); - strcpy(arrow, "ยป"); - arrow = color_text(arrow, blue); - printf("%s %s %s ", modtime, cwd, arrow); + while (status) { + /* Get current time */ + time_t t = time(NULL); + struct tm *current_time = localtime(&t); + char timestr[256]; + /* Format time string */ + if (strftime(timestr, sizeof(timestr), "[%H:%M:%S]", current_time) == 0) { + return; + } + char cwd[PATH_MAX]; + /* Get current working directory */ + if (getcwd(cwd, PATH_MAX) == NULL) { + return; + } + char *home = getenv("HOME"); + size_t home_len = strlen(home); + + int i = 0, j = 0; + /* Check if cwd starts with home */ + if (home && strncmp(cwd, home, home_len) == 0) { + cwd[j++] = '~'; + i += home_len; + } + while (cwd[i] != '\0') { + cwd[j++] = cwd[i++]; + } + cwd[j] = '\0'; + + /* Blue time string, pink time, teal arrow */ + printf("\033[34m%s\033[m \033[35m[%s] \033[36m>\033[m ", timestr, cwd); fflush(stdout); - cmd_count = 0; // upward arrow key resets command count - line = readline(paths); - if (line == NULL) { - printf("\n"); - continue; - } - save_command_history(line); - bool has_pipe = false; - for (int i = 0; line[i] != '\0'; i++) { - if (line[i] == '|') { - has_pipe = true; - break; - } - } - if (has_pipe) { - char ***pipe_args = pipe_argsplit(line); - status = execute_pipe(pipe_args); - while (*pipe_args != NULL) { - free(*pipe_args); - pipe_args++; - } - } else { - args = argsplit(line); - args = modifyargs(args); - status = execute(args, STDOUT_FILENO, OPT_FGJ); - free(args); - } - free(line); - free(modtime); - free(cwd); - free(arrow); - }; + cmd_count = 0; // upward arrow key resets command count + line = readline(paths); + if (line == NULL) { + printf("\n"); + continue; + } + save_command_history(line); + bool has_pipe = false; + for (int i = 0; line[i] != '\0'; i++) { + if (line[i] == '|') { + has_pipe = true; + break; + } + } + if (has_pipe) { + char ***pipe_args = pipe_argsplit(line); + status = execute_pipe(pipe_args); + while (*pipe_args != NULL) { + free(*pipe_args); + pipe_args++; + } + } else { + args = argsplit(line); + args = modifyargs(args); + status = execute(args, STDOUT_FILENO, OPT_FGJ); + free(args); + } + free(line); + }; } -void quit_sig(int sig) { - exit(EXIT_SUCCESS); +void quit_sig(int sig) +{ + exit(EXIT_SUCCESS); } -int main(int argc, char **argv) { - // setup - signal(SIGINT, quit_sig); - signal(SIGTERM, quit_sig); - signal(SIGQUIT, quit_sig); - check_history_file(); - char **paths = setup_path_variable(); - change_terminal_attribute(1); // turn off echoing and disabling getchar requires pressing enter key to return +int main(int argc, char **argv) +{ + // setup + signal(SIGINT, quit_sig); + signal(SIGTERM, quit_sig); + signal(SIGQUIT, quit_sig); + check_history_file(); + char **paths = setup_path_variable(); + change_terminal_attribute(1); // turn off echoing and disabling getchar requires pressing enter key to return - command_loop(paths); + command_loop(paths); - // cleanup - free(paths); - change_terminal_attribute(0); // change back to default settings - return EXIT_SUCCESS; + // cleanup + free(paths); + change_terminal_attribute(0); // change back to default settings + return EXIT_SUCCESS; } diff --git a/src/color.c b/src/color.c deleted file mode 100644 index ae7a1ae..0000000 --- a/src/color.c +++ /dev/null @@ -1,18 +0,0 @@ -#include -#include -#include - -#include "90s.h" - -// color str in place -char *color_text(char *str, const char *color) { - int size = snprintf(NULL, 0, "\x1b[38;2;%sm%s\x1b[0m", color, str) + 1; // calculate size that is needed for colored string - if (size < 0) { - fprintf(stderr, "90s: snprintf failed\n"); - exit(EXIT_FAILURE); - } - char *buf = memalloc(size); - - snprintf(buf, size, "\x1b[38;2;%sm%s\x1b[0m", color, str); // format string to buf - return buf; -} diff --git a/src/commands.c b/src/commands.c index 2c26e2a..6616043 100644 --- a/src/commands.c +++ b/src/commands.c @@ -13,7 +13,7 @@ int execute(char **args); -// Function declarations for builtin commands +/* Builtin commands */ int cd(char **args); int help(char **args); int quit(char **args); @@ -23,7 +23,6 @@ int source(char **args); int j(char **args); int bg(char **args); -// List of builtin commands' names char *builtin_cmds[] = { "cd", "help", @@ -38,7 +37,7 @@ char *builtin_cmds[] = { int (*builtin_func[]) (char **) = { &cd, &help, - &quit, // cant name it exit as it is taken + &quit, /* Can't name it exit as it is taken */ &history, &export, &source, @@ -53,12 +52,13 @@ char *shortcut_dirs[] = { }; char *shortcut_expand_dirs[] = { - "~/.nky/Coding/C/90s", + "~/.nky/git/90s", "~/.local/bin", "/usr/local/bin", }; -char *gethome(void) { +char *gethome(void) +{ char *home = getenv("HOME"); if (home == NULL) { fprintf(stderr, "Error: HOME environment variable not set.\n"); @@ -67,14 +67,15 @@ char *gethome(void) { return home; } -char *replace_home_dir(char *str) { +char *replace_home_dir(char *str) +{ char *home_path = gethome(); int path_len = strlen(str); int home_len = strlen(home_path); // Allocate memory for the new path - char* new_path = memalloc(sizeof(char) * (path_len + home_len + 1)); + char* new_path = memalloc(path_len + home_len + 1); int i = 0, j = 0; while (str[i] != '\0') { @@ -93,37 +94,14 @@ char *replace_home_dir(char *str) { return new_path; } -char *replace_absolute_home(char *str) { - char *home_path = gethome(); - - int path_len = strlen(str); - int home_len = strlen(home_path); - - // Allocate memory for the new path - char* new_path = memalloc(sizeof(char) * (path_len - home_len + 2)); - - int i = 0, j = 0; - while (str[i] != '\0') { - if (strncmp(&str[i], home_path, home_len) == 0) { - // Copy HOME environment variable value - new_path[j++] = '~'; - i += home_len; - } else { - new_path[j++] = str[i++]; - } - } - - new_path[j] = '\0'; - return new_path; -} - // number of built in commands int num_builtins(void) { return sizeof(builtin_cmds) / sizeof(char *); } // autojump -int j(char **args) { +int j(char **args) +{ if (args[1] == NULL) { fprintf(stderr, "90s: not enough arguments\n"); return -1; @@ -143,7 +121,9 @@ int j(char **args) { return 1; } -// change directory +/* + * Change directory + */ int cd(char **args) { int i = 0; if (args[1] == NULL) { @@ -166,9 +146,12 @@ int cd(char **args) { return 1; } -// show help menu -int help(char **args) { - printf("90s %f\n", VERSION); +/* + * Show help menu + */ +int help(char **args) +{ + printf("90s %s\n", VERSION); printf("Built in commands:\n"); for (int i = 0; i < num_builtins(); i++) { @@ -180,11 +163,14 @@ int help(char **args) { return 1; } -int quit(char **args) { - return 0; // exit prompting loop, which also the shell +int quit(char **args) +{ + /* Exit prompt loop */ + return 0; } -int history(char **args) { +int history(char **args) +{ char **history = get_all_history(true); for (int i = 0; history[i] != NULL; ++i) { @@ -196,8 +182,10 @@ int history(char **args) { return 1; } -int export(char **args) { - args++; // skip the command +int export(char **args) +{ + /* Skip the command */ + args++; while (*args != NULL) { char *variable = strtok(*args, "=\n"); char *value = strtok(NULL, "=\n"); @@ -215,7 +203,8 @@ int export(char **args) { return 1; } -int source(char **args) { +int source(char **args) +{ if (args[1] == NULL) { fprintf(stderr, "90s: not enough arguments\n"); return -1; @@ -245,7 +234,8 @@ int source(char **args) { return status; // Indicate success } -int bg(char **args) { +int bg(char **args) +{ if (args[1] == NULL) { fprintf(stderr, "90s: not enough arguments\n"); return -1; @@ -263,7 +253,9 @@ int bg(char **args) { printf("Job %i: %s\n", job_index, search->command); return 1; } -bool is_builtin(char *command) { + +bool is_builtin(char *command) +{ for (int i = 0; i < num_builtins(); i++) { if (strcmp(command, builtin_cmds[i]) == 0) { return true; @@ -272,7 +264,8 @@ bool is_builtin(char *command) { return false; } -int launch(char **args, int fd, int options) { +int launch(char **args, int fd, int options) +{ int is_bgj = (options & OPT_BGJ) ? 1 : 0; int redirect_stdout = (options & OPT_STDOUT) ? 1 : 0; int redirect_stdin = (options & OPT_STDIN) ? 1 : 0; @@ -325,7 +318,8 @@ int launch(char **args, int fd, int options) { return 1; } // execute built in commands or launch commands and wait it to terminate, return 1 to keep shell running -int execute(char **args) { +int execute(char **args) +{ if (args[0] == NULL) { // An empty command was entered. return 1; } @@ -407,7 +401,8 @@ int execute(char **args) { } // execute_pipe with as many pipes as needed -int execute_pipe(char ***args) { +int execute_pipe(char ***args) +{ int pipefd[2]; pid_t pid; int in = 0; diff --git a/src/history.c b/src/history.c index 6756964..7c00983 100644 --- a/src/history.c +++ b/src/history.c @@ -13,7 +13,8 @@ FILE *history_file; char *histfile_path; int cmd_count = 0; -FILE *open_history_file(char *mode) { +FILE *open_history_file(char *mode) +{ history_file = fopen(histfile_path, mode); if (history_file == NULL) { fprintf(stderr, "90s: Error opening history file\n"); @@ -21,7 +22,9 @@ FILE *open_history_file(char *mode) { } return history_file; } -void check_history_file(void) { + +void check_history_file(void) +{ char *env_home; env_home = getenv("XDG_CONFIG_HOME"); if (env_home == NULL) { @@ -48,7 +51,8 @@ void check_history_file(void) { } } -void save_command_history(char *args) { +void save_command_history(char *args) +{ history_file = open_history_file("a+"); char cmd[RL_BUFSIZE]; cmd[0] = '\0'; @@ -60,8 +64,10 @@ void save_command_history(char *args) { fclose(history_file); } -char *read_command(int direction) { - if (direction == 1) { // up +char *read_command(int direction) +{ + /* Up */ + if (direction == 1) { cmd_count++; } else { // down if (cmd_count == 0) { @@ -84,7 +90,8 @@ char *read_command(int direction) { return history[num_history - cmd_count]; } -int is_duplicate(char **history, int line_count, char *line) { +int is_duplicate(char **history, int line_count, char *line) +{ for (int i = 0; i < line_count; ++i) { if (strcmp(history[i], line) == 0) { return 1; @@ -93,9 +100,10 @@ int is_duplicate(char **history, int line_count, char *line) { return 0; } -char **get_all_history(bool check) { +char **get_all_history(bool check) +{ history_file = open_history_file("r"); - char **history = memalloc(MAX_HISTORY * sizeof(char*)); + char **history = memalloc(MAX_HISTORY * sizeof(char *)); char buffer[RL_BUFSIZE]; int line_count = 0; diff --git a/src/job.c b/src/job.c index 0ac6a74..8c0b8f5 100644 --- a/src/job.c +++ b/src/job.c @@ -13,7 +13,8 @@ typedef struct job { job *jobs = NULL; -int num_jobs(void) { +int num_jobs(void) +{ job *current = jobs; int count = 0; while (current != NULL) { @@ -23,7 +24,8 @@ int num_jobs(void) { return count; } -int add_job(pid_t pid, char *command, bool status) { +int add_job(pid_t pid, char *command, bool status) +{ job *current = jobs; job *new_job = memalloc(sizeof(job)); new_job->pid = pid; @@ -45,7 +47,8 @@ int add_job(pid_t pid, char *command, bool status) { return index; } -job *get_job(int index) { +job *get_job(int index) +{ job *current = jobs; if (index == 0) { return current;