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_BLACK "\x1b[30m"
|
||||||
#define ANSI_FG_RED "\x1b[31m"
|
#define ANSI_FG_RED "\x1b[31m"
|
||||||
#define ANSI_FG_GREEN "\x1b[32m"
|
#define ANSI_FG_GREEN "\x1b[32m"
|
||||||
|
|||||||
89
src/msh.c
89
src/msh.c
@@ -8,10 +8,14 @@
|
|||||||
#include <sys/utsname.h>
|
#include <sys/utsname.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "ansi.h"
|
#include "ansi.h"
|
||||||
|
|
||||||
#define ESC \x1B
|
|
||||||
|
#define HISTORY_FILE_NAME "/history.log"
|
||||||
|
#define LOCAL_SHARE_DIRNAME "/.local/share/msh"
|
||||||
|
|
||||||
|
|
||||||
const int LINESIZE = 512;
|
const int LINESIZE = 512;
|
||||||
@@ -156,6 +160,9 @@ int main(int argc, char** argv) {
|
|||||||
char* host;
|
char* host;
|
||||||
|
|
||||||
struct utsname uts = {};
|
struct utsname uts = {};
|
||||||
|
char* sharedir = NULL;
|
||||||
|
char* historyfilepath = NULL;
|
||||||
|
FILE* historyfile = NULL;
|
||||||
|
|
||||||
user = secure_getenv("USER");
|
user = secure_getenv("USER");
|
||||||
|
|
||||||
@@ -176,6 +183,68 @@ int main(int argc, char** argv) {
|
|||||||
// disable echo and icanon (don't wait for newline)
|
// disable echo and icanon (don't wait for newline)
|
||||||
term.c_lflag &= ~(ECHO | ICANON);
|
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
|
// Main loop
|
||||||
while(1) {
|
while(1) {
|
||||||
@@ -284,9 +353,9 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
print_prompt:
|
print_prompt:
|
||||||
// Manual echo
|
// 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++) {
|
for (int j = 0; j < linelen - cursor; j++) {
|
||||||
printf("\x1b[D");
|
printf(ANSI_ESC "[D");
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
@@ -297,6 +366,9 @@ print_prompt:
|
|||||||
|
|
||||||
line[linelen] = 0;
|
line[linelen] = 0;
|
||||||
|
|
||||||
|
fprintf(historyfile, "%s\n", line);
|
||||||
|
fflush(historyfile);
|
||||||
|
|
||||||
// Split into tokens
|
// Split into tokens
|
||||||
for (tokenwork = line, i = 0; ; tokenwork = NULL, i++) {
|
for (tokenwork = line, i = 0; ; tokenwork = NULL, i++) {
|
||||||
token = strtok(tokenwork, " \t");
|
token = strtok(tokenwork, " \t");
|
||||||
@@ -342,6 +414,17 @@ print_prompt:
|
|||||||
|
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
if (sharedir != NULL) {
|
||||||
|
free(sharedir);
|
||||||
|
}
|
||||||
|
if (historyfilepath != NULL) {
|
||||||
|
free(historyfilepath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (historyfile != NULL) {
|
||||||
|
fflush(historyfile);
|
||||||
|
fclose(historyfile);
|
||||||
|
}
|
||||||
tcsetattr(fileno(stdin), 0, &orig_term);
|
tcsetattr(fileno(stdin), 0, &orig_term);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user