1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <console.h>
4 #include <string.h>
5 
6 #include <sys/module.h>
7 #include <sys/exec.h>
8 
9 #define INFO_PRINT(fmt, args...)	printf("[COM32] " fmt, ##args)
10 
11 #define MAX_COMMAND_SIZE 	80	// Maximum size of the cmd line
12 #define COMMAND_DELIM		" \t\n"	// Whitespace delimiters
13 #define MAX_COMMAND_ARGS	(MAX_COMMAND_SIZE/2)	// Maximum argument count for
14 												 // program execution
15 
16 /**
17  * print_help - Display usage instructions on the screen.
18  */
print_help(void)19 static void print_help(void)
20 {
21     printf("List of available commands:\n");
22     printf("exit - exits the program\n");
23     printf("help - shows this message\n");
24     printf("load <library>... - loads the libraries into the environment\n");
25     printf("spawn <executable> <args> - launches an executable module\n");
26     printf
27 	("unload <library>... - unloads the libraries from the environment\n");
28     printf("list - prints the currently loaded modules\n");
29 }
30 
31 /**
32  * print_prompt - Display the command prompt.
33  */
print_prompt(void)34 static void print_prompt(void)
35 {
36     printf("\nelflink> ");
37 }
38 
39 /**
40  * read_command - Read a new command from the standard input.
41  * @cmd: the buffer to store the command
42  * @size: the maximum size of the string that can be stored in the buffer
43  *
44  * If the command is larger than the specified size, it is truncated.
45  */
read_command(char * cmd,int size)46 static void read_command(char *cmd, int size)
47 {
48     char *nl = NULL;
49     fgets(cmd, size, stdin);
50 
51     // Strip the newline
52     nl = strchr(cmd, '\n');
53 
54     if (nl != NULL)
55 	*nl = '\0';
56 }
57 
58 /**
59  * process_spawn - Handles the execution of a 'spawn' command.
60  *
61  * The command line is in the internal buffer of strtok.
62  */
process_spawn(void)63 static void process_spawn(void)
64 {
65     // Compose the command line
66     char **cmd_line = malloc((MAX_COMMAND_ARGS + 1) * sizeof(char *));
67     int argc = 0, result;
68     char *crt_arg;
69 
70     do {
71 	crt_arg = strtok(NULL, COMMAND_DELIM);
72 	if (crt_arg != NULL && strlen(crt_arg) > 0) {
73 	    cmd_line[argc] = crt_arg;
74 	    argc++;
75 	} else {
76 	    break;
77 	}
78     } while (argc < MAX_COMMAND_ARGS);
79 
80     cmd_line[argc] = NULL;
81 
82     if (cmd_line[0] == NULL) {
83 	printf("You must specify an executable module.\n");
84     } else {
85 	result = spawnv(cmd_line[0], cmd_line);
86 
87 	printf("Spawn returned %d\n", result);
88     }
89 
90     free(cmd_line);
91 }
92 
93 /**
94  * process_library - Handles the execution of the 'load' and 'unload' commands.
95  * @load: contains 1 if the libraries are to be loaded, 0 for unloading.
96  *
97  * The command line is in the internal buffer of strtok.
98  */
process_library(int load)99 static void process_library(int load)
100 {
101     char *crt_lib;
102     int result;
103 
104     while ((crt_lib = strtok(NULL, COMMAND_DELIM)) != NULL) {
105 	if (strlen(crt_lib) > 0) {
106 	    if (load)
107 		result = load_library(crt_lib);
108 	    else
109 		result = unload_library(crt_lib);
110 
111 	    if (result == 0) {
112 		printf("Library '%s' %sloaded successfully.\n", crt_lib,
113 		       load ? "" : "un");
114 	    } else {
115 		printf("Could not %sload library '%s': error %d\n",
116 		       load ? "" : "un", crt_lib, result);
117 	    }
118 	}
119     }
120 }
121 
122 /**
123  * process_list - Handles the execution of the 'list' command.
124  *
125  */
process_list(void)126 static void process_list(void)
127 {
128     struct elf_module *module;
129     struct module_dep *crt_dep;
130 
131     for_each_module(module) {
132 	printf("%s (%dK, %s, %s) : ", module->name, module->module_size >> 10,
133 	       module->shallow ? "shallow" : "regular",
134 	       module->main_func == NULL ? "library" : "program");
135 
136 	list_for_each_entry(crt_dep, &module->required, list) {
137 	    printf("%s ", crt_dep->module->name);
138 	}
139 
140 	printf("\n");
141     }
142 }
143 
144 /**
145  * process_command - Recognizes the requested command and executes it.
146  * @cmd: the command to be executed.
147  *
148  * Returns 1 if the command was 'exit', 0 otherwise.
149  */
process_command(char * cmd)150 static int process_command(char *cmd)
151 {
152     char *cmd_name;
153 
154     cmd_name = strtok(cmd, COMMAND_DELIM);
155 
156     if (strcmp(cmd_name, "exit") == 0) {
157 	printf("Goodbye!\n");
158 	return 1;
159     } else if (strcmp(cmd_name, "help") == 0) {
160 	print_help();
161     } else if (strcmp(cmd_name, "load") == 0) {
162 	process_library(1);
163     } else if (strcmp(cmd_name, "spawn") == 0) {
164 	process_spawn();
165     } else if (strcmp(cmd_name, "unload") == 0) {
166 	process_library(0);
167     } else if (strcmp(cmd_name, "list") == 0) {
168 	process_list();
169     } else {
170 	printf("Unknown command. Type 'help' for a list of valid commands.\n");
171     }
172 
173     return 0;
174 }
175 
176 /**
177  * The entry point of 'test_com32' COM module.
178  */
main(int argc,char ** argv)179 int main(int argc, char **argv)
180 {
181     int done = 0;
182     int res;
183     char command[MAX_COMMAND_SIZE] = { 0 };
184 
185     // Open a standard r/w console
186     openconsole(&dev_stdcon_r, &dev_stdcon_w);
187 
188     res = exec_init();
189     if (res != 0) {
190 	printf("Failed to initialize the execution environment.\n");
191 	return res;
192     } else {
193 	printf("Execution environment initialized successfully.\n");
194     }
195 
196     printf("\nFor a list of available commands, type 'help'.\n");
197 
198     do {
199 	print_prompt();
200 	read_command(command, MAX_COMMAND_SIZE);
201 	done = process_command(command);
202 
203     } while (!done);
204 
205     exec_term();
206 
207     return 0;
208 }
209