Browse Source

Implementing history load/store

Yann Weber 1 year ago
parent
commit
0d4b246520
6 changed files with 186 additions and 7 deletions
  1. 11
    4
      Makefile.am
  2. 18
    2
      asmsh.c
  3. 107
    0
      history.c
  4. 41
    0
      history.h
  5. 6
    1
      tests/regen.sh
  6. 3
    0
      tests/samples/sample.history

+ 11
- 4
Makefile.am View File

@@ -1,22 +1,29 @@
1 1
 bin_PROGRAMS = asmsh child
2 2
 
3 3
 libcheck_asmsh_a_SOURCES = mmap_parse.c asm_env.c compile.c logger.c \
4
-			   completion.c shell.c shell_cmds.c shell_sym.c
4
+			   completion.c shell.c shell_cmds.c shell_sym.c \
5
+			   history.c
5 6
 
6 7
 asmsh_SOURCES = asmsh.c $(libcheck_asmsh_a_SOURCES)
7 8
 child_SOURCES = child.s
8 9
 
10
+asmsh_LDADD=child_bin.o
9 11
 asmsh_LDFLAGS=-g -O2
10 12
 
11
-CCASFLAGS=-g -O0
13
+AM_CFLAGS=-Wall
14
+AM_CCASFLAGS=-g -O0
12 15
 child_LDFLAGS=-nostdlib
13 16
 
14 17
 child$(EXEEXT): $(child_SOURCES:.s=.o)
15
-	ld -g -o $@ $^
18
+	$(LD) -s -o $@ $^
19
+
20
+child_bin.o: child$(EXEEXT)
21
+	$(LD) -r -b binary -o $@ $<
16 22
 
17 23
 SUBDIRS = 
18 24
 if CHECK
19 25
 noinst_LIBRARIES = libcheck_asmsh.a
26
+libcheck_asmsh_a_LDDADD=child_bin.o
20 27
 
21 28
 if HAVE_GCOV
22 29
 libcheck_asmsh_a_CFLAGS = @CFLAGS@ -fprofile-arcs -ftest-coverage
@@ -34,7 +41,7 @@ LCOV_HTML=lcov_html
34 41
 TO_LOCAL_CLEAN += $(LCOV_INFO) $(LCOV_HTML)
35 42
 
36 43
 $(LCOV_INFO): gcov
37
-	$(LCOV) --capture --no-recursion --directory . --output-file $@
44
+	$(LCOV) --base-directory $(top_builddir) --capture --no-recursion --directory . --output-file $@
38 45
 
39 46
 $(LCOV_HTML): $(LCOV_INFO)
40 47
 	genhtml $< --output-directory $@

+ 18
- 2
asmsh.c View File

@@ -23,6 +23,7 @@
23 23
 #include "logger.h"
24 24
 #include "shell.h"
25 25
 #include "completion.h"
26
+#include "history.h"
26 27
 
27 28
 int main(int argc, char *argv[], char *envp[])
28 29
 {
@@ -48,6 +49,9 @@ int main(int argc, char *argv[], char *envp[])
48 49
 	rl_basic_word_break_characters=" \t\n";
49 50
 	rl_attempted_completion_function =  asmsh_rl_completion;
50 51
 
52
+	char * hpath = history_filename_init(NULL);
53
+	load_history(hpath, add_history);
54
+
51 55
 	while(1)
52 56
 	{
53 57
 		snprintf(prompt, sizeof(prompt)-1,
@@ -74,10 +78,22 @@ int main(int argc, char *argv[], char *envp[])
74 78
 		add_history(cmd);
75 79
 	}
76 80
 
81
+end:
77 82
 	asmsh_cleanup(&sh);
83
+
84
+	HIST_ENTRY **hist = history_list();
85
+	int hist_count = 0;
86
+	for(HIST_ENTRY **p=hist; *p;p++){ hist_count++; }
87
+	const char **hstr = alloca((hist_count+1)*sizeof(char*));
88
+	for(int i=0; i<hist_count; i++){ hstr[i] = hist[i]->line; }
89
+	hstr[hist_count]=NULL;
90
+
91
+	save_history(hpath, hstr);
92
+	free(hpath);
93
+
78 94
 	return ret;
79 95
 
80 96
 err:
81
-	asmsh_cleanup(&sh);
82
-	return 1;
97
+	ret = 1;
98
+	goto end;
83 99
 }

+ 107
- 0
history.c View File

@@ -0,0 +1,107 @@
1
+#include "history.h"
2
+
3
+char * history_filename_init(const char *homedir)
4
+{
5
+	const char fmt[] = "%s/.local/share/asmsh";
6
+	char *path;
7
+	int sz;
8
+	int fd = open("/dev/null", O_WRONLY);
9
+	if(!fd)
10
+	{
11
+		perror("Unable to open /dev/null");
12
+		return NULL;
13
+	}
14
+	const char *home = homedir?homedir:getenv("HOME");
15
+	if(!home)
16
+	{
17
+		dprintf(2, "No $HOME variable found\n");
18
+		return NULL;
19
+	}
20
+	sz = dprintf(fd, fmt, home);
21
+	if(sz < 0)
22
+	{
23
+		perror("Not able to format local share folder");
24
+		return NULL;
25
+	}
26
+	
27
+	path = alloca(sz+1);
28
+	sprintf(path, fmt, home);
29
+	path[sz]='\0';
30
+	if(access(path, F_OK) < 0)
31
+	{
32
+		mkdir(path, 0755);
33
+	}
34
+	char *res = malloc(sz+strlen(ASMSH_HISTORY_FILE)+3);
35
+	if(!res)
36
+	{
37
+		perror("Unable tot allocate history filename");
38
+		return NULL;
39
+	}
40
+	sz = sprintf(res, "%s/%s", path, ASMSH_HISTORY_FILE);
41
+	res[sz] = '\0';
42
+	return res;
43
+}
44
+
45
+
46
+int save_history(const char *history_path, const char * const *hists)
47
+{
48
+	int fd = open(history_path, O_WRONLY|O_CREAT|O_TRUNC, 0744);
49
+	if(fd < 0)
50
+	{
51
+		perror("Unable to open history file");
52
+		dprintf(2, "could not save history in %s\n", history_path);
53
+		return -1;
54
+	}
55
+	for(const char * const *hist=hists; *hist; hist++)
56
+	{
57
+		dprintf(fd, "%s\n", *hist);
58
+	}
59
+	close(fd);
60
+	return 0;
61
+}
62
+
63
+int load_history(const char *history_path, add_history_f *add_h)
64
+{
65
+	if(access(history_path, F_OK) < 0) { return 0; }
66
+
67
+	int readed, wanted;
68
+	int fd = open(history_path, O_RDONLY);
69
+	char buf[4096], *cur, *line;
70
+	if(fd < 0)
71
+	{
72
+		perror("Unable to open history file");
73
+		return -1;
74
+	}
75
+
76
+	cur = buf;
77
+	wanted = sizeof(buf)-1;
78
+	do
79
+	{
80
+		readed = read(fd, cur, wanted);
81
+		if(readed < 0)
82
+		{
83
+			perror("Unable to read history file");
84
+			close(fd);
85
+			return -1;
86
+		}
87
+		cur[readed]='\0';
88
+		for(line=cur=buf; *cur; cur++)
89
+		{
90
+			if(*cur=='\n')
91
+			{
92
+				*cur='\0';
93
+				if(cur-line>1 && *line != '#')
94
+				{
95
+					add_h(line);
96
+				}
97
+				line = cur+1;
98
+			}
99
+		}
100
+		if(*line)
101
+		{
102
+			wanted = sizeof(buf) - (strlen(line)+1);
103
+			memmove(buf, line, strlen(line)+1);
104
+		}
105
+	}while(readed && readed == wanted);
106
+	close(fd);
107
+}

+ 41
- 0
history.h View File

@@ -0,0 +1,41 @@
1
+/* Copyright Yann Weber <asmsh@yannweb.net>
2
+   This file is part of asmsh.
3
+
4
+   asmsh is free software: you can redistribute it and/or modify it under the
5
+   terms of the GNU General Public License as published by the Free Software
6
+   Foundation, either version 3 of the License, or any later version.
7
+   
8
+   asmsh is distributed in the hope that it will be useful, but WITHOUT ANY
9
+   WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
10
+   FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
11
+   details.
12
+   
13
+   You should have received a copy of the GNU General Public License along
14
+   with asmsh. If not, see <https://www.gnu.org/licenses/>.
15
+*/
16
+#ifndef ASMSH_HISTORY_H
17
+#define ASMSH_HISTORY_H
18
+#include "config.h"
19
+
20
+#include <fcntl.h>
21
+#include <stdio.h>
22
+#include <stdlib.h>
23
+#include <string.h>
24
+#include <unistd.h>
25
+#include <sys/types.h>
26
+#include <sys/stat.h>
27
+
28
+static const char ASMSH_HISTORY_FILE[] = "asmsh.history";
29
+
30
+typedef void(add_history_f)(const char*);
31
+
32
+/** Return the history filename and create the directory if needed
33
+ * @note the returned string should be freed after use
34
+ * @param const char * if NULL use $HOME
35
+ */
36
+char * history_filename_init(const char *homedir);
37
+
38
+int save_history(const char *history_path, const char* const* hists);
39
+int load_history(const char *history_path, add_history_f *add_h);
40
+
41
+#endif

+ 6
- 1
tests/regen.sh View File

@@ -15,6 +15,8 @@ TESTLIB_NAME=libcheck_asmsh.a
15 15
 TESTLIB=\$(top_builddir)/\$(TESTLIB_NAME)
16 16
 CHILD_NAME=child
17 17
 CHILD=\$(top_builddir)/\$(CHILD_NAME)
18
+CHILD_OBJNAME=child_bin.o
19
+CHILD_OBJ=\$(top_builddir)/\$(CHILD_OBJNAME)
18 20
 
19 21
 BUILT_SOURCES = \$(CHILD)
20 22
 
@@ -27,6 +29,9 @@ clean-local:
27 29
 \$(TESTLIB):
28 30
 	make -C \$(top_builddir) \$(TESTLIB_NAME)
29 31
 
32
+\$(CHILD_OBJ):
33
+	make -C \$(top_builddir) \$(CHILD_OBJNAME)
34
+
30 35
 .PHONY: \$(TESTLIB) \$(CHILD)
31 36
 __EOF__
32 37
 
@@ -35,7 +40,7 @@ do
35 40
 	cat << __EOF__ >> Makefile.am
36 41
 ${p}_SOURCES = ${p}.c
37 42
 ${p}_CFLAGS = @CHECK_CFLAGS@ -fprofile-arcs -ftest-coverage
38
-${p}_LDADD = \$(TESTLIB) @CHECK_LIBS@
43
+${p}_LDADD = \$(TESTLIB) \$(CHILD_OBJ)  @CHECK_LIBS@
39 44
 __EOF__
40 45
 
41 46
 done

+ 3
- 0
tests/samples/sample.history View File

@@ -0,0 +1,3 @@
1
+hello world!
2
+mov $1312, %rax
3
+syscall

Loading…
Cancel
Save