diff --git a/src/ansi.h b/src/ansi.h index df9ef99..40ee8c7 100644 --- a/src/ansi.h +++ b/src/ansi.h @@ -1,4 +1,6 @@ +#define ANSI_ESC "\x1b" + #define ANSI_FG_BLACK "\x1b[30m" #define ANSI_FG_RED "\x1b[31m" #define ANSI_FG_GREEN "\x1b[32m" diff --git a/src/msh.c b/src/msh.c index 20651be..468a1ae 100644 --- a/src/msh.c +++ b/src/msh.c @@ -8,10 +8,14 @@ #include #include #include +#include +#include #include "ansi.h" -#define ESC \x1B + +#define HISTORY_FILE_NAME "/history.log" +#define LOCAL_SHARE_DIRNAME "/.local/share/msh" const int LINESIZE = 512; @@ -156,6 +160,9 @@ int main(int argc, char** argv) { char* host; struct utsname uts = {}; + char* sharedir = NULL; + char* historyfilepath = NULL; + FILE* historyfile = NULL; user = secure_getenv("USER"); @@ -176,6 +183,68 @@ int main(int argc, char** argv) { // disable echo and icanon (don't wait for newline) term.c_lflag &= ~(ECHO | ICANON); + char* homedir = secure_getenv("HOME"); + + if (homedir == NULL) { + fprintf(stderr, "Error: $HOME is not specified\n"); + retval = 1; + goto cleanup; + } + + sharedir = malloc(strlen(homedir) + strlen(LOCAL_SHARE_DIRNAME) + 1); + if (sharedir == NULL) { + retval = 1; + goto cleanup; + } + sharedir = strcpy(sharedir, homedir); + if (sharedir == NULL) { + retval = 1; + goto cleanup; + } + sharedir = strcat(sharedir, LOCAL_SHARE_DIRNAME); + if (sharedir == NULL) { + retval = 1; + goto cleanup; + } + + result = mkdir(sharedir, S_IRWXU); + if (result != 0 && errno != EEXIST) { + fprintf(stderr, "Error: %s\n", strerror(errno)); + retval = 1; + goto cleanup; + } + + + historyfilepath = malloc(strlen(sharedir) + strlen(HISTORY_FILE_NAME) + 1); + if (historyfilepath == NULL) { + retval = 1; + goto cleanup; + } + historyfilepath = strcpy(historyfilepath, sharedir); + if (historyfilepath == NULL) { + retval = 1; + goto cleanup; + } + historyfilepath = strcat(historyfilepath, HISTORY_FILE_NAME); + if (historyfilepath == NULL) { + retval = 1; + goto cleanup; + } + + int historyfilefd = open(historyfilepath, O_CREAT | O_APPEND | O_WRONLY, S_IRUSR | S_IWUSR); + if (historyfilefd == -1) { + fprintf(stderr, "Error: could not open history file: %s\n", strerror(errno)); + retval = 1; + goto cleanup; + } + + historyfile = fdopen(historyfilefd, "w"); + if (historyfile == NULL) { + fprintf(stderr, "Error: could not open history file fd: %s\n", strerror(errno)); + retval = 1; + goto cleanup; + } + // Main loop while(1) { @@ -284,9 +353,9 @@ int main(int argc, char** argv) { print_prompt: // Manual echo - printf("\x1b[2K\x1b[0G%s%s", prompt, line); + printf(ANSI_ESC "[2K" ANSI_ESC "[0G" "%s%s", prompt, line); for (int j = 0; j < linelen - cursor; j++) { - printf("\x1b[D"); + printf(ANSI_ESC "[D"); } fflush(stdout); } @@ -296,6 +365,9 @@ print_prompt: tcsetattr(fileno(stdin), 0, &orig_term); line[linelen] = 0; + + fprintf(historyfile, "%s\n", line); + fflush(historyfile); // Split into tokens for (tokenwork = line, i = 0; ; tokenwork = NULL, i++) { @@ -342,6 +414,17 @@ print_prompt: cleanup: + if (sharedir != NULL) { + free(sharedir); + } + if (historyfilepath != NULL) { + free(historyfilepath); + } + + if (historyfile != NULL) { + fflush(historyfile); + fclose(historyfile); + } tcsetattr(fileno(stdin), 0, &orig_term); return retval; }