From 995e8da6536dc25a9ad37e8ef11e9b2f92b48e91 Mon Sep 17 00:00:00 2001 From: BanceDev Date: Wed, 4 Sep 2024 12:20:50 -0400 Subject: history saving implemented --- src/history.c | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/history.h | 24 +++++++++ src/lua_api.c | 2 + src/lush.c | 3 ++ 4 files changed, 192 insertions(+) create mode 100644 src/history.c create mode 100644 src/history.h diff --git a/src/history.c b/src/history.c new file mode 100644 index 0000000..028745e --- /dev/null +++ b/src/history.c @@ -0,0 +1,163 @@ +/* +Copyright (c) 2024, Lance Borden +All rights reserved. + +This software is licensed under the BSD 3-Clause License. +You may obtain a copy of the license at: +https://opensource.org/licenses/BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted under the conditions stated in the BSD 3-Clause +License. + +THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#include "history.h" +#include +#include +#include +#include +#include +#include +#include + +#define MAX_LINES 512 + +static char *get_history_path() { + uid_t uid = getuid(); + struct passwd *pw = getpwuid(uid); + if (!pw) { + perror("retrieve home dir"); + return NULL; + } + + size_t path_length = strlen(pw->pw_dir) + strlen("/.lush/.history") + 1; + char *path = malloc(path_length); + if (!path) { + perror("malloc"); + return NULL; + } + + strcpy(path, pw->pw_dir); + strcat(path, "/.lush/.history"); + + return path; +} + +char *lush_get_past_command(int pos) { + char *path = get_history_path(); + if (access(path, F_OK) != 0) { + // file does not exist + perror("history file check"); + free(path); + return NULL; + } + + // read file from the bottom + FILE *fp = fopen(path, "r"); + if (!fp) { + perror("opening file"); + free(path); + return NULL; + } + char *line = (char *)malloc(1024 * sizeof(char)); + if (line == NULL) { + perror("malloc"); + free(path); + return NULL; + } + int curr_line = 0; + while (fgets(line, 1024, fp)) { + if (curr_line == pos) { + fclose(fp); + return line; + } + curr_line++; + } + + fclose(fp); + free(path); + return line; +} + +void lush_push_history(const char *line) { + char *path = get_history_path(); + // check if the file exists and create if not + if (access(path, F_OK) != 0) { + FILE *fp = fopen(path, "w"); + if (fp == NULL) { + perror("creating file"); + } else { + fclose(fp); + } + } + + FILE *fp = fopen(path, "r"); + if (fp == NULL) { + perror("opening file"); + free(path); + return; + } + + // Count lines + int line_count = 0; + char buffer[1024]; // Adjust buffer size as needed + while (fgets(buffer, sizeof(buffer), fp)) { + line_count++; + } + + // Allocate memory for file content + fseek(fp, 0, SEEK_SET); + char **lines = (char **)malloc(line_count * sizeof(char *)); + if (lines == NULL) { + perror("malloc"); + fclose(fp); + free(path); + return; + } + + // Read lines into memory + int index = 0; + while (fgets(buffer, sizeof(buffer), fp)) { + lines[index] = strdup(buffer); // Allocate and copy each line + if (lines[index] == NULL) { + perror("strdup"); + while (index > 0) + free(lines[--index]); + free(lines); + free(path); + fclose(fp); + return; + } + index++; + } + fclose(fp); + + // Open file for writing + fp = fopen(path, "w"); + if (fp == NULL) { + perror("opening file"); + for (int i = 0; i < index; i++) + free(lines[i]); + free(lines); + free(path); + return; + } + + // Write the new line + fprintf(fp, "%s\n", line); + + // Write the last MAX_LINES lines + for (int i = 0; i < MAX_LINES; i++) { + fprintf(fp, "%s", lines[i]); + free(lines[i]); // Free each line after writing + } + + // Clean up + free(lines); + free(path); + fclose(fp); +} diff --git a/src/history.h b/src/history.h new file mode 100644 index 0000000..9507126 --- /dev/null +++ b/src/history.h @@ -0,0 +1,24 @@ +/* +Copyright (c) 2024, Lance Borden +All rights reserved. + +This software is licensed under the BSD 3-Clause License. +You may obtain a copy of the license at: +https://opensource.org/licenses/BSD-3-Clause + +Redistribution and use in source and binary forms, with or without +modification, are permitted under the conditions stated in the BSD 3-Clause +License. + +THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTIES, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +*/ + +#ifndef HISTORY_H +#define HISTORY_H + +char *lush_get_past_command(int pos); +void lush_push_history(const char* line); + +#endif diff --git a/src/lua_api.c b/src/lua_api.c index 9f4bdc8..1040478 100644 --- a/src/lua_api.c +++ b/src/lua_api.c @@ -16,6 +16,7 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. */ #include "lua_api.h" +#include "history.h" #include "lush.h" #include #include @@ -76,6 +77,7 @@ static int execute_command(lua_State *L, const char *line) { for (int i = 0; args[i]; i++) { free(args[i]); } + lush_push_history(line); free(args); free(commands); return status; diff --git a/src/lush.c b/src/lush.c index facdff2..81f9e64 100644 --- a/src/lush.c +++ b/src/lush.c @@ -17,6 +17,7 @@ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. #include "lush.h" #include "help.h" +#include "history.h" #include "lauxlib.h" #include "lua.h" #include "lua_api.h" @@ -517,6 +518,7 @@ int main() { // Print the prompt printf("[%s@%s:%s] ", username, device_name, prompt_cwd); char *line = lush_read_line(); + lush_push_history(line); printf("\n"); if (line == NULL || strlen(line) == 0) { free(line); @@ -533,6 +535,7 @@ int main() { for (int i = 0; args[i]; i++) { free(args[i]); } + // add last line to history free(cwd); free(args); free(commands); -- cgit v1.2.3-59-g8ed1b