90s

Minimalist, customizable shell written in C99 with syntax highlighting
git clone https://codeberg.org/night0721/90s
Log | Files | Refs | README | LICENSE

commit 5a67fcb3b5cb52dbd96acdc8972af276d9c78463
parent a058bd3ae8ac709309d4ddd9f3037d694b87bdbf
Author: night0721 <[email protected]>
Date:   Sat, 10 Feb 2024 17:29:58 +0000

fix history navigation bug and improve code by memalloc

Diffstat:
Mcolor.c | 8+++-----
Mhistory.c | 40++++++++++++++--------------------------
Mhistory.h | 2++
Mrush.c | 80++++++++++++++++++++++++++++++++++---------------------------------------------
Mrush.h | 3+++
5 files changed, 56 insertions(+), 77 deletions(-)

diff --git a/color.c b/color.c @@ -2,6 +2,8 @@ #include <string.h> #include <stdlib.h> +#include "rush.h" + // color str in place void 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 @@ -9,11 +11,7 @@ void color_text(char str[], const char *color) { fprintf(stderr, "rush: snprintf failed\n"); exit(EXIT_FAILURE); } - char *buf = malloc(size); - if (buf == NULL) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } + char *buf = memalloc(size); snprintf(buf, size, "\x1b[38;2;%sm%s\x1b[0m", color, str); // format string to buf strcpy(str, buf); diff --git a/history.c b/history.c @@ -6,12 +6,21 @@ #include <linux/limits.h> #include "history.h" +#include "rush.h" #include "constants.h" FILE *history_file; char *histfile_path; int cmd_count = 0; +FILE *open_history_file(char *mode) { + history_file = fopen(histfile_path, mode); + if (history_file == NULL) { + fprintf(stderr, "rush: Error opening history file\n"); + exit(EXIT_FAILURE); + } + return history_file; +} void check_history_file() { char *env_home; env_home = getenv("XDG_CONFIG_HOME"); @@ -26,11 +35,7 @@ void check_history_file() { int env_home_len = strlen(env_home); int histfilename_len = strlen(HISTFILE); int path_len = env_home_len + histfilename_len + 2; // 2 for slash and null byte - histfile_path = malloc(sizeof(char) * path_len); - if (histfile_path == NULL) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } + histfile_path = memalloc(sizeof(char) * path_len); histfile_path[0] = '\0'; // initialise string // concatenate home and history file name to a path strcat(histfile_path, env_home); @@ -38,21 +43,13 @@ void check_history_file() { strcat(histfile_path, HISTFILE); histfile_path[path_len - 1] = '\0'; if (access(histfile_path, F_OK) != 0) { // check for file existence - history_file = fopen(histfile_path, "w"); // read and write, if doesn't exist, create - if (history_file == NULL) { - fprintf(stderr, "rush: Error opening history file\n"); - exit(EXIT_FAILURE); - } + history_file = open_history_file("w"); // read and write, if doesn't exist, create fclose(history_file); } } void save_command_history(char *args) { - history_file = fopen(histfile_path, "a+"); - if (history_file == NULL) { - fprintf(stderr, "rush: Error opening history file\n"); - exit(EXIT_FAILURE); - } + history_file = open_history_file("a+"); char cmd[RL_BUFSIZE]; cmd[0] = '\0'; strcat(cmd, args); @@ -97,17 +94,8 @@ int is_duplicate(char **history, int line_count, char *line) { } char **get_all_history(bool check) { - history_file = fopen(histfile_path, "r"); - if (history_file == NULL) { - fprintf(stderr, "rush: Error opening history file\n"); - exit(EXIT_FAILURE); - } - - char **history = malloc(MAX_HISTORY * sizeof(char*)); - if (history == NULL) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } + history_file = open_history_file("r"); + char **history = memalloc(MAX_HISTORY * sizeof(char*)); char buffer[RL_BUFSIZE]; int line_count = 0; diff --git a/history.h b/history.h @@ -1,6 +1,8 @@ #ifndef HISTORY_H_ #define HISTORY_H_ +extern int cmd_count; + void save_command_history(char *args); void check_history_file(); char *read_command(int direction); diff --git a/rush.c b/rush.c @@ -14,6 +14,15 @@ #include "history.h" #include "commands.h" +void *memalloc(size_t size) { + void *ptr = memalloc(size); + if (!ptr) { + fputs("rush: Error allocating memory\n", stderr); + exit(EXIT_FAILURE); + } + return ptr; +} + void quit_sig(int sig) { exit(0); } @@ -36,12 +45,8 @@ char **setup_path_variable() { fprintf(stderr, "rush: PATH environment variable is missing\n"); exit(EXIT_FAILURE); } - char *path_cpy = malloc(sizeof(char) * (strlen(envpath) + 1)); - char *path = malloc(sizeof(char) * (strlen(envpath) + 1)); - if (path_cpy == NULL || path == NULL) { - fprintf(stderr, "rush: Error allocating memory\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; @@ -53,11 +58,7 @@ char **setup_path_variable() { path_cpy++; } path_count += 2; // adding one to be correct and one for terminator - char **paths = malloc(sizeof(char *) * path_count); - if (paths == NULL) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } + char **paths = memalloc(sizeof(char *) * path_count); char *token = strtok(path, ":"); int counter = 0; while (token != NULL) { @@ -110,12 +111,8 @@ void highlight(char *buffer, char **paths) { if (cmd_part != NULL) { cmd_len = cmd_part - buffer; - char *cmd = malloc(sizeof(char) * (cmd_len + 1)); - command_without_arg = malloc(sizeof(char) * (cmd_len + 1)); - if (cmd == NULL || command_without_arg == NULL) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } + 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]; } @@ -151,17 +148,13 @@ void highlight(char *buffer, char **paths) { char *readline(char **paths) { int bufsize = RL_BUFSIZE; int position = 0; - char *buffer = malloc(sizeof(char) * bufsize); + char *buffer = memalloc(sizeof(char) * bufsize); bool moved = false; bool backspaced = false; bool navigated = false; bool insertatmiddle = false; bool replaced = false; - if (!buffer) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } buffer[0] = '\0'; while (1) { @@ -356,14 +349,9 @@ char *readline(char **paths) { // split line into arguments char **argsplit(char *line) { int bufsize = TOK_BUFSIZE, position = 0; - char **tokens = malloc(bufsize * sizeof(char*)); + char **tokens = memalloc(bufsize * sizeof(char*)); char *token; - if (!tokens) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } - token = strtok(line, TOK_DELIM); while (token != NULL) { tokens[position] = token; @@ -387,14 +375,21 @@ char **argsplit(char *line) { 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++; } - // makes ls and diff and grep have color without user typing it - if (strncmp(args[0], "ls", 2) == 0 || strncmp(args[0], "diff", 4) == 0 || strncmp(args[0], "grep", 4) == 0) { - args[num_arg] = "--color=auto"; - num_arg++; - args[num_arg] = NULL; + 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; @@ -414,16 +409,8 @@ char *trimws(char *str) { } char ***pipe_argsplit(char *line) { - char ***cmdv = malloc(sizeof(char **) * 128); // 127 commands, 1 for NULL - if (cmdv == NULL) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } - char **cmds = malloc(sizeof(char *) * 128); // 127 arguments, 1 for NULL - if (cmds == NULL) { - fprintf(stderr, "rush: Error allocating memory\n"); - exit(EXIT_FAILURE); - } + 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) { @@ -437,6 +424,7 @@ char ***pipe_argsplit(char *line) { for (int i = 0; i < num_arg; i++) { char **splitted = argsplit(cmds[i]); cmdv[i] = modifyargs(splitted); + } cmdv[num_arg] = NULL; free(cmds); @@ -463,14 +451,14 @@ void command_loop(char **paths) { char time[256]; strcpy(time, timestr); color_text(time, lavender); // lavender colored time string - char *cwd = malloc(sizeof(char) * (PATH_MAX + 2)); + char *cwd = memalloc(sizeof(char) * (PATH_MAX + 2)); sprintf(cwd, "[%s]", cwdstr); color_text(cwd, pink); // pink colored current directory char arrow[32] = "ยป"; color_text(arrow, blue); printf("%s %s %s ", time, cwd, arrow); - + cmd_count = 0; // upward arrow key resets command count line = readline(paths); save_command_history(line); bool has_pipe = false; @@ -490,7 +478,7 @@ void command_loop(char **paths) { } else { args = argsplit(line); args = modifyargs(args); - status = execute(args); + status = execute(args, STDOUT_FILENO, OPT_FGJ); free(args); } free(line); diff --git a/rush.h b/rush.h @@ -1,6 +1,9 @@ #ifndef RUSH_H_ #define RUSH_H_ +#include <stdio.h> + +void *memalloc(size_t size); char **argsplit(char *line); #endif