From dc391b4360aa8bda3df80a781a0e15cf1ca1d69f Mon Sep 17 00:00:00 2001 From: czjstmax Date: Wed, 8 Apr 2026 23:55:32 +0200 Subject: release 2.1 - less memory leaks (if any) - added functionality - *colors*!! Signed-off-by: czjstmax --- nm.c | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 113 insertions(+), 33 deletions(-) (limited to 'nm.c') diff --git a/nm.c b/nm.c index 5450612..9a9cac2 100644 --- a/nm.c +++ b/nm.c @@ -1,10 +1,16 @@ /* noshmore * an extended version of nosh, * the minimal POSIX C shell. - * -> generally: adds some functionality. + * + * # notable changes + * - less memory leaks (almost none) + * - more stable + * - cleaner code (ish) + * - GNU readline + * - command history + * and more fixes and tweaks. * - * von czjstmax, - */ + * von czjstmax, */ #include #include @@ -17,7 +23,7 @@ #include #include -#define NOSHMORE_VERSION 2 +#define NOSHMORE_VERSION 2.1 #define MAX_ALIASES 256 typedef struct { @@ -25,26 +31,62 @@ typedef struct { char *src; } Alias; -Alias aliases[MAX_ALIASES]; -int alias_count = 0; +Alias aliases[MAX_ALIASES]; +int alias_count = 0; -void handlecc(int sig); -Alias CreateAlias(char *dst, char *src); -void FreeAll(); -void FreeAliases(); +char *line = NULL; +char *history_path; +wordexp_t p; -char *line = NULL; -wordexp_t p; +const char *RED = "\x1b[31m"; +const char *WHITE = "\x1b[37m"; +const char *RESET = "\x1b[0m"; +const char *ITALIC = "\x1b[3m"; +const char *UNDERLINE = "\x1b[4m"; + +void HandleCC (int sig); +Alias CreateAlias (char *dst, char *src); +void FreeAll (); +void FreeAliases (); +void Cleanup (); + +void Greet() +{ + printf( + "welcome to %s%snoshmore%s | spinning version %s%s%.1f%s\n" + "type %s%shelp%s for a list of %sbuilt-in%s commands!\n" + , RED, ITALIC, RESET, RED, ITALIC, NOSHMORE_VERSION, RESET + , RED, ITALIC, RESET, ITALIC, RESET + ); +} int main(void) { - signal(SIGINT, handlecc); + atexit(Cleanup); + signal(SIGINT, HandleCC); + using_history(); + char *USER = getenv("USER"); if (!USER) USER = "anon"; + char *HOME = getenv("HOME"); if (!HOME) HOME = "."; + + size_t history_path_len = strlen(HOME) + strlen("/.nshm_hist") + 1; + history_path = malloc(history_path_len); + snprintf(history_path, history_path_len, "%s/.nshm_hist", HOME); + + if (access(history_path, F_OK) == 0) + read_history(history_path); + else { + perror("nsh+! ERROR: couldn't load command history"); + fprintf(stderr, "(%sfirst run? try the %swritehist%s%s command%s)\n", ITALIC, RED, RESET, ITALIC, RESET); + } + + // initialization phase completed, now Greet() the USER + Greet(); while (true) { char prompt[strlen(USER) + strlen("$ ") + 1]; @@ -54,12 +96,14 @@ int main(void) if (!line) break; - if (*line) + if (*line) { add_history(line); + write_history(history_path); + } if (wordexp(line, &p, 0) != 0) { - fprintf(stderr, "nsh+! ERROR while parsing\n"); - free(line); + perror("nsh+! ERROR while parsing input\n"); + FreeAll(); continue; } @@ -69,8 +113,7 @@ int main(void) continue; } if (strcmp(p.we_wordv[0], ":q") == 0 || strcmp(p.we_wordv[0], "exit") == 0) { - FreeAll(); - FreeAliases(); + //Cleanup(); return 0; } else if (strcmp(p.we_wordv[0], "echo") == 0) { @@ -109,34 +152,64 @@ int main(void) FreeAll(); continue; } - if (chdir(p.we_wordv[1])) + if (chdir(p.we_wordv[1])) { perror("nsh+! ERROR: failed to change directory"); + FreeAll(); + } } else if (strcmp(p.we_wordv[0], "clear") == 0) { printf("\033[2J\033[H\033[3J"); fflush(stdout); + FreeAll(); + } + else if (strcmp(p.we_wordv[0], "svhist") == 0 || strcmp(p.we_wordv[0], "writehist") == 0) { + write_history(history_path); + FreeAll(); + } + else if (strcmp(p.we_wordv[0], "readhist") == 0 || strcmp(p.we_wordv[0], "loadhist") == 0) { + if (!read_history(history_path)) + perror("nsh+! ERROR: couldn't load command history"); + FreeAll(); + } + else if (strcmp(p.we_wordv[0], "rmhist") == 0 || strcmp(p.we_wordv[0], "cleanhist") == 0) { + clear_history(); + FreeAll(); } else if (strcmp(p.we_wordv[0], "help") == 0) { printf( - "noshmore\tVERSION(%d)\tALIASES(%d)\n" - "an extended version of nosh, the minimal POSIX C shell.\n" + "%snoshmore%s\tVERSION(%.1f)\tALIASES(%d)\n" + "an extended version of %snosh%s, the minimal POSIX C shell.\n" + "history file path -> '%s%s%s%s'\n" "\n" - "built-ins:\n" - "echo -> outputs a string of text, doesn't need \" enclosure.\n" - " supports '-c' for output without '\\n'" - "clear -> clears screen (and scrollback)\n" - "alias -> creates non-persistent command aliases\n" - " (i.e. alias v vim)\n" - "cd -> change working directory\n" - "help -> prints this screen\n" - "\ngithub repo: github.com/jstmaxlol/noshmore\n" - , NOSHMORE_VERSION, MAX_ALIASES + "## built-ins:\n" + "echo -> outputs a string of text, doesn't need \" enclosure.\n" + " supports '-c' for output without '\\n'\n" + "clear -> clears screen (and scrollback)\n" + "alias -> creates non-persistent command aliases\n" + " (i.e. '%salias v vim%s')\n" + "cd -> change working directory\n" + "writehist -> writes current sesh command history to disk\n" + " aliases: svhist\n" + "readhist -> reads last written sesh command history from disk\n" + " aliases: loadhist\n" + "cleanhist -> clears sesh command history\n" + " aliases: rmhist\n" + "help -> prints this screen\n" + "@ github.com/jstmaxlol/noshmore\n" + , RED, RESET, NOSHMORE_VERSION, MAX_ALIASES + , ITALIC, RESET + , RED, ITALIC, history_path, RESET + , ITALIC, RESET + /* make no mistakes: i know i can just #define RED_FMT(s) RED s RESET + and make this printf() 10x more readable and lovely, but i wont. + */ ); + FreeAll(); } else { for (int i = 0; i < alias_count; i++) { if (strcmp(p.we_wordv[0], aliases[i].dst) == 0) { - char new_line[81920] = {0}; + char new_line[81920] = {0}; // goofy ass size ngl strcat(new_line, aliases[i].src); for (size_t j = 1; j < p.we_wordc; j++) { @@ -159,6 +232,7 @@ int main(void) execvp(p.we_wordv[0], argv); perror("nsh+! ERROR: failed to execvp()"); FreeAll(); + free(history_path); _exit(1); } else if (pid > 0) { @@ -172,7 +246,7 @@ int main(void) } } -void handlecc(int sig) +void HandleCC(int sig) { (void)sig; rl_replace_line("", 0); @@ -205,3 +279,9 @@ void FreeAliases() } +void Cleanup() +{ + FreeAll(); + FreeAliases(); + free(history_path); +} -- cgit v1.3.1