summaryrefslogtreecommitdiff
path: root/nm.c
diff options
context:
space:
mode:
authorczjstmax <jstmaxlol@disroot.org>2026-04-08 23:55:32 +0200
committerczjstmax <jstmaxlol@disroot.org>2026-04-08 23:55:32 +0200
commitdc391b4360aa8bda3df80a781a0e15cf1ca1d69f (patch)
tree04e45affbeff9f4bef6154c367839babc7429486 /nm.c
parentc730c0d69251e625c0364b6fac07c365e8287b36 (diff)
release 2.1
- less memory leaks (if any) - added functionality - *colors*!! Signed-off-by: czjstmax <jstmaxlol@disroot.org>
Diffstat (limited to 'nm.c')
-rw-r--r--nm.c146
1 files changed, 113 insertions, 33 deletions
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, <jstmaxlol at disroot dot org>
- */
+ * von czjstmax, <jstmaxlol at disroot dot org> */
#include <stdio.h>
#include <stdlib.h>
@@ -17,7 +23,7 @@
#include <readline/readline.h>
#include <readline/history.h>
-#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);
+}