Browse Source

Extracted shell functionnality from main

Yann Weber 1 year ago
parent
commit
4bf7c63bfe
6 changed files with 183 additions and 50 deletions
  1. 1
    1
      Makefile.am
  2. 20
    46
      asmsh.c
  3. 0
    2
      compile.c
  4. 2
    1
      logger.c
  5. 130
    0
      shell.c
  6. 30
    0
      shell.h

+ 1
- 1
Makefile.am View File

@@ -1,6 +1,6 @@
1 1
 bin_PROGRAMS = asmsh child
2 2
 
3
-libcheck_asmsh_a_SOURCES = mmap_parse.c asm_env.c compile.c logger.c completion.c
3
+libcheck_asmsh_a_SOURCES = mmap_parse.c asm_env.c compile.c logger.c completion.c shell.c
4 4
 
5 5
 asmsh_SOURCES = asmsh.c $(libcheck_asmsh_a_SOURCES)
6 6
 child_SOURCES = child.s

+ 20
- 46
asmsh.c View File

@@ -5,9 +5,8 @@
5 5
 
6 6
 #define CHILD_EXEC_PATH "./child"
7 7
 
8
-#include "asm_env.h"
9 8
 #include "logger.h"
10
-#include "compile.h"
9
+#include "shell.h"
11 10
 #include "completion.h"
12 11
 
13 12
 static void print_regs(asmsh_env_t *env)
@@ -39,12 +38,10 @@ flags: %c%c%c%c|%c%c%c\n\
39 38
 
40 39
 int main(int argc, char *argv[], char *envp[])
41 40
 {
42
-	asmsh_asmc_ctx_t *cctx;
43
-	asmsh_env_t *env;
44
-	asmsh_bytecode_t bcode;
45 41
 	asmsh_logger_t *logger;
42
+	asmsh_t sh;
46 43
 	
47
-	int ret, status;
44
+	int ret;
48 45
 	char *cmd;
49 46
 	char prompt[64];
50 47
 	bzero(prompt, sizeof(prompt));
@@ -52,71 +49,48 @@ int main(int argc, char *argv[], char *envp[])
52 49
 	logger = asmsh_logger_new(ASMSH_INFO);
53 50
 	asmsh_logger_setup(logger);
54 51
 
55
-	if(!(env = asmsh_env(CHILD_EXEC_PATH)))
52
+	if(asmsh_init(&sh, CHILD_EXEC_PATH))
56 53
 	{
57
-		perror("Unable to init asm_env");
54
+		perror("Unable to init shell");
55
+		asmsh_logger_dprint(2, logger);
58 56
 		return 1;
59 57
 	}
60
-	if(!(cctx = asmsh_asmc_ctx_default()))
61
-	{
62
-		perror("Unable to init compilation ctx");
63
-	}
64 58
 
65 59
 	rl_special_prefixes="";
66 60
 	rl_basic_word_break_characters=" \t\n";
67 61
 	rl_attempted_completion_function =  asmsh_rl_completion;
68 62
 
69
-	status = 0;
70
-
71 63
 	while(1)
72 64
 	{
73
-		print_regs(env);
65
+		print_regs(sh.env);
74 66
 		snprintf(prompt, sizeof(prompt)-1,
75 67
 				"asmsh@%p > ",
76
-				env->regs.rip, status >> 8);
68
+				sh.env->regs.rip);
77 69
 		cmd = readline(prompt);
78 70
 		if(!cmd)
79 71
 		{
80 72
 			break;
81 73
 		}
82
-		if(strcmp(cmd, "quit") == 0)
83
-		{
84
-			break;
85
-		}
86
-		bcode.size = 0;
87
-		ret = asmsh_asmc_compile(cctx, cmd, &bcode);
88
-		asmsh_logger_dprint_fmt(2, logger, asmsh_log_lvl_fmt);
89
-		if(ret < 0)
90
-		{
91
-			continue;
92
-		}
93
-		if(!bcode.size)
94
-		{
95
-			asmsh_log_error("No bytecode returned...");
96
-			asmsh_logger_dprint_fmt(2, logger, asmsh_log_lvl_fmt);
97
-			continue;
98
-		}
99
-		if(asmsh_env_write_code(env, &bcode))
100
-		{
101
-			perror("Unable to write instruction");
102
-			goto err;
103
-		}
104
-		ret = asmsh_env_step(env, &status);
74
+		ret = asmsh_exec(&sh, cmd);
105 75
 		asmsh_logger_dprint_fmt(2, logger, asmsh_log_lvl_fmt);
106
-		if(ret)
76
+		if(ret > 0)
107 77
 		{
108
-			dprintf(2, "Child is dead...\n");
78
+			//unrecoverable error or exit (if ret == 1)
79
+			ret--; // exit status
80
+			if(ret)
81
+			{
82
+				dprintf(2, "Exit with status %d\n", ret);
83
+			}
109 84
 			break;
110 85
 		}
86
+		//else if (ret < 0) {} //recoverable errors
111 87
 		add_history(cmd);
112 88
 	}
113 89
 
114
-	asmsh_asmc_ctx_free(cctx);
115
-	asmsh_env_free(env);
116
-	return 0;
90
+	asmsh_cleanup(&sh);
91
+	return ret;
117 92
 
118 93
 err:
119
-	asmsh_asmc_ctx_free(cctx);
120
-	asmsh_env_free(env);
94
+	asmsh_cleanup(&sh);
121 95
 	return 1;
122 96
 }

+ 0
- 2
compile.c View File

@@ -234,8 +234,6 @@ int asmsh_asmc_compile_unsafe(asmsh_asmc_ctx_t *ctx, const char *_instr,
234 234
 	}
235 235
 	if(!WIFEXITED(wstatus))
236 236
 	{
237
-		kill(ctx->child.pid, SIGKILL);
238
-		ctx->child.pid = -1;
239 237
 		if(WIFSTOPPED(wstatus))
240 238
 		{
241 239
 			asmsh_log_error("as stopped...");

+ 2
- 1
logger.c View File

@@ -88,10 +88,11 @@ int asmsh_logger_dprint_fmt(int fd, asmsh_logger_t *logger, asmsh_log_fmt_f *cus
88 88
 				buf[BUF_ALLOC-(2+i)] = '.';
89 89
 			}
90 90
 		}
91
-		res += dprintf(fd, buf); /// TODO check result
91
+		res += dprintf(fd, buf); /// TODO use write & check result
92 92
 		cur = cur->nxt;
93 93
 	}
94 94
 	free(buf);
95
+	logger->nxt = logger->msgs;
95 96
 	return res;
96 97
 }
97 98
 

+ 130
- 0
shell.c View File

@@ -0,0 +1,130 @@
1
+#include "shell.h"
2
+
3
+int asmsh_init(asmsh_t *sh, const char *child_path)
4
+{
5
+	bzero(sh, sizeof(asmsh_t));
6
+	if(!(sh->env = asmsh_env(child_path)))
7
+	{
8
+		asmsh_log_fatal("Unable to start child env");
9
+		goto err;
10
+	}
11
+	if(!(sh->cctx = asmsh_asmc_ctx_default()))
12
+	{
13
+		asmsh_log_fatal("Unable to start compilation context");
14
+		asmsh_env_free(sh->env);
15
+		goto err;
16
+	}
17
+	return 0;
18
+err:
19
+	bzero(sh, sizeof(asmsh_t));
20
+	return -1;
21
+}
22
+
23
+
24
+void asmsh_cleanup(asmsh_t *sh)
25
+{
26
+	if(!sh){ return; }
27
+	if(sh->cctx)
28
+	{
29
+		asmsh_asmc_ctx_free(sh->cctx);
30
+	}
31
+	if(sh->env)
32
+	{
33
+		asmsh_env_free(sh->env);
34
+	}
35
+	bzero(sh, sizeof(asmsh_t));
36
+}
37
+
38
+/** Attempt to compile and step if sucess */
39
+static int _compile_step(asmsh_t *sh, const char *cmd);
40
+/** Attempt to handle given shell internal command (starting with  '.') */
41
+static int _handle_command(asmsh_t *sh, const char *cmd);
42
+int asmsh_exec(asmsh_t *sh, const char *cmd)
43
+{
44
+	if(!cmd)
45
+	{
46
+		errno=EINVAL;
47
+		return -1;
48
+	}
49
+
50
+	int clen, ret;
51
+	//lstrip whitespace
52
+	for(cmd; *cmd && (*cmd == ' ' || *cmd == '\t'); cmd++);
53
+	if(!*cmd) { return 0; }
54
+
55
+	switch(*cmd)
56
+	{
57
+		case '.':
58
+			ret = _handle_command(sh, cmd);
59
+			break;
60
+		default:
61
+			ret = _compile_step(sh, cmd);
62
+			break;
63
+	}
64
+	return ret;
65
+}
66
+
67
+static int _compile_step(asmsh_t *sh, const char *cmd)
68
+{
69
+	int ret, status;
70
+	asmsh_bytecode_t bcode;
71
+
72
+	if(asmsh_asmc_compile(sh->cctx, cmd, &bcode) < 0)
73
+	{
74
+		return -1;
75
+	}
76
+	if(!bcode.size)
77
+	{
78
+		asmsh_log_error("No bytecode returned...");
79
+		return -1;
80
+	}
81
+	sh->last_bcode = bcode;
82
+	if(sh->last_instr) { free(sh->last_instr); }
83
+	sh->last_instr = strdup(cmd);
84
+char buf[256];
85
+int _ret;
86
+_ret = snprintf(buf, 255, "'%s' = 0x", cmd);
87
+for(int _i=0; _i<bcode.size; _i++)
88
+{
89
+	_ret += snprintf(buf+_ret, 255-_ret, "%02x", bcode.bytes[_i]);
90
+}
91
+_ret += snprintf(buf+_ret, 255-_ret, "(%d)", bcode.size);
92
+buf[_ret] = '\0';
93
+asmsh_log_info(buf);
94
+
95
+	if(asmsh_env_write_code(sh->env, &bcode))
96
+	{
97
+		return -1;
98
+	}
99
+
100
+	status=0;
101
+	ret = asmsh_env_step(sh->env, &status);
102
+	if(ret < 0)
103
+	{
104
+		perror("Unable to step");
105
+		asmsh_log_fatal("Error will child step");
106
+		return -1;
107
+	}
108
+	else if(ret > 0)
109
+	{
110
+		asmsh_log_fatal("Child exited with non-zero status");
111
+		return 1+WEXITSTATUS(status);
112
+	}
113
+	return 0;
114
+}
115
+
116
+static int _handle_command(asmsh_t *sh, const char *cmd)
117
+{
118
+	const int clen = strlen(cmd);
119
+
120
+	if(clen <= 1)
121
+	{
122
+		asmsh_log_error("No command given");
123
+		return 0;
124
+	}
125
+	if(strncmp(cmd, ".quit", clen) == 0)
126
+	{
127
+		asmsh_cleanup(sh);
128
+		return 1;
129
+	}
130
+}

+ 30
- 0
shell.h View File

@@ -0,0 +1,30 @@
1
+#ifndef ASMSH_SHELL_H
2
+#define ASMSH_SHELL_H
3
+#include "config.h"
4
+
5
+#include <stdlib.h>
6
+#include <unistd.h>
7
+
8
+#include "asm_env.h"
9
+#include "logger.h"
10
+#include "compile.h"
11
+
12
+typedef struct asmsh_s asmsh_t;
13
+
14
+struct asmsh_s
15
+{
16
+	asmsh_asmc_ctx_t *cctx;
17
+	asmsh_env_t *env;
18
+
19
+	char *last_instr;
20
+	asmsh_bytecode_t last_bcode;
21
+
22
+};
23
+
24
+int asmsh_init(asmsh_t *sh, const char *child_path);
25
+void asmsh_cleanup(asmsh_t *sh);
26
+
27
+/** @return <0 on error 0 on ok 1 on exit */
28
+int asmsh_exec(asmsh_t *sh, const char *cmd);
29
+
30
+#endif

Loading…
Cancel
Save