feat: history file
This commit is contained in:
@@ -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"
|
||||
|
||||
89
src/msh.c
89
src/msh.c
@@ -8,10 +8,14 @@
|
||||
#include <sys/utsname.h>
|
||||
#include <errno.h>
|
||||
#include <termios.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user