/** * esh.c * * Error SHell for HybOS * * Exports: * None. * * Imports: * None. * * Description: * Since esh is called on a new thread in user-space and not in * kernel-space, imports and exports are not necessary. All the * kernel needs to know is what functions to call when the * keyboard buffer has been filled (this even happens when the * user presses the EOL key, which is the ENTER key on either * the keypad or the "normal" keyboard). */ #include <stdlib.h> #include <stdio.h> #include <string.h> #include <stdbool.h> #include <esh/esh.h> void dumpheapk(void); ESHCOMMANDS eshCommands[COMMAND_COUNT]; /** * keyDown() * * This function is called when a key is pressed and is called * on a new thread which resides in user-space so that esh * cannot lock up the kernel. * * @param unsigned Which key was pressed. See keyboard.h * * @return void */ void keyDown(unsigned key) { key = key; /* to shut gcc up */ } /** * keyUp() * * This function is called when a key is released. * * @param unsigned Which key was released. See keyboard.h * * @return void */ void keyUp(unsigned key) { key = key; /* to shut gcc up */ } void initCommands(void) { eshCommands[0].minparams = 0; eshCommands[0].maxparams = 0; strcpy(eshCommands[0].command, "dumpheap\0"); strcpy(eshCommands[0].params[0], "-h\0"); strcpy(eshCommands[0].description, "Print listing of heap usage and status.\0"); eshCommands[1].minparams = 1; eshCommands[1].maxparams = MAX_PARAMS; strcpy(eshCommands[1].params[0], "-h\0"); strcpy(eshCommands[1].command, "echo\0"); strcpy(eshCommands[1].description, "Echo a line of text to the terminal.\0"); /*this will be called with either "help" or "help command" */ eshCommands[2].minparams = 0; eshCommands[2].maxparams = 1; strcpy(eshCommands[2].params[0], "-h\0"); strcpy(eshCommands[2].command, "help\0"); strcpy(eshCommands[2].description, "Displays general help menu or help on specific command.\0"); /* -r|-h [time] */ eshCommands[3].minparams = 1; eshCommands[3].maxparams = 2; strcpy(eshCommands[3].command, "shutdown\0"); strcpy(eshCommands[3].params[0], "-r\0"); strcpy(eshCommands[3].params[1], "-h\0"); strcpy(eshCommands[3].params[2], "NOW\0"); strcpy(eshCommands[3].description, "Halt or restart the system.\0"); /* clear screen */ eshCommands[4].minparams = 0; eshCommands[4].maxparams = 0; strcpy(eshCommands[4].params[0], "-h\0"); strcpy(eshCommands[4].command, "cls\0"); strcpy(eshCommands[4].description, "Clears the terminal of all output.\0"); /* print working directory */ eshCommands[5].minparams = 0; eshCommands[5].maxparams = 0; strcpy(eshCommands[5].params[0], "-h\0"); strcpy(eshCommands[5].command, "pwd\0"); strcpy(eshCommands[5].description, "Prints the current working directory.\0"); } /** * mapCommand() * * Used internally by esh to map a command to it's zero-based * index of commands. * * @param char * the entire line of the command * * @return int index of command entry if found, otherwise -1 */ int mapCommand(char *cmd) { int i; /* for our loops */ int params; /* number of parameters found for the command */ int previdx; /* previous index */ char cmdName[MAX_LEN]; /* name of the command */ i = 0; previdx = 0; params = 0; /** * Loop while cmd[i] is not a space */ i = 0; for(i = 0; i < (int)strlen(cmd); i++) { if(cmd[i] == ' ') break; } strncpy(cmdName, cmd, i); cmdName[i] = '\0'; for(i = 0; i < COMMAND_COUNT; i++) { if(!strcmp(eshCommands[i].command, cmdName)) return i; } return -1; } /** * isParam() * * Determines if the supplied parameter is valid for the * given command. * * @param int index of command * @param char * command string * * @return bool true if parameter is valid, false otherwise */ bool isParam(int argc, char *argv) { int i; for(i = 0; i < MAX_PARAMS; i++) { if(!strcmp(eshCommands[argc].params[i], argv)) return true; } return false; } /** * mapParams() * * Maps each parameter to the pars struct * * @param char * Buffer from the command line * @param struct Parameter structure * * @return int Number of command line parameters (arguments) parsed */ int mapParams(char *buf, ESHCURRCOMMAND *pars) { int i; /* for our loops */ int previdx; /* previous index */ int idx; /* current index */ int j; /* loops */ i = 0; j = 0; previdx = 0; pars->count = 0; previdx = mapCommand(buf); if(previdx == -1) return 0; strcpy(pars->param[0], eshCommands[previdx].command); j++; pars->count++; i = 0; idx = 0; for(i = 0; i < (int)strlen(buf); i++) { /* we have encountered a seperator */ if(buf[i] == ' ') { if(j > MAX_PARAMS) break; i++; /* skip one space */ idx = i; if(buf[i] == '"') { i++; idx++; while(buf[i] != '"' && i != (int)strlen(buf)) i++; strncpy(pars->param[j], &buf[idx], (i - idx)); pars->param[j][i - idx] = '\0'; idx = i; j++; pars->count++; } else { while(buf[i] != ' ' && i != (int)strlen(buf)) i++; strncpy(pars->param[j], &buf[idx], i - idx); pars->param[j][i - idx] = '\0'; i = idx; j++; pars->count++; } } } return pars->count; } /** * processCommand() * * This function is called when the user has pressed * the ENTER key. * * @param char * The contents of the current buffer or NULL if empty * @param int Size of the buffer (number of characters) * * @return void */ void processCommand(char *line, int count) { int i; int cmd; /* stores the numeric index of the command */ ESHCURRCOMMAND params; count = count; /* to shut gcc up */ /*for(i = 0; i < MAX_PARAMS; i++) params.param[i][0] = '\0';*/ params.param[0][0] = '\0'; initCommands(); cmd = mapCommand(line); mapParams(line, ¶ms); switch(cmd) { case 0: /* dumpheap */ dumpheapk(); //testheap(); break; case 1: /* echo */ for(i = 1; i < params.count; i++) printf("%s", params.param[i]); printf("\n"); break; case 2: /* help */ if(params.count == 1) { printf("HybOS EShell Commands:\n"); for(i = 0; i < COMMAND_COUNT; i++) if(strlen(eshCommands[i].command) > 0) printf("%10s %-s\n", eshCommands[i].command, eshCommands[i].description); } else { cmd = mapCommand(params.param[0]); mapParams(params.param[1], ¶ms); //if(isParam(cmd, params.param[1])) if(cmd != -1) { printf("Usage: %s %s\n", params.param[0], eshCommands[cmd].params[1]); } else printf("esh: '%s' not found.\n", params.param[1]); } break; default: if(strlen(params.param[0]) > 0 && strcmp(params.param[0], "help")) printf("esh: '%s' not found.\n", params.param[0]); else printf("esh: '%s' not found.\n", &line[0]); break; } /*for(i = 0; i < params.count; i++) printf("param[%i]: %s\n", i, params.param[i]);*/ //if(isParam(3, ¶ms.param[1])) // printf("valid parameter\n"); //else // printf("invalid parameter\n"); return; if(!strcmp(line, "dumpheap")) dumpheapk(); else if(!strncmp(line, "echo", 4)) printf("%s\n", line[4] == ' ' ? &line[5] : &line[4]); else if(!strcmp(line, "help")) { printf("HybOS EShell Commands:\n"); printf("dumpheap\tPrint listing of heap usage and status\n"); printf("testheap\tTest the heap and print out results\n"); printf("shutdown -r\tRestart the system.\n"); printf("pwd\t\tPrint the current working directory.\n"); } else if(!strncmp(line, "shutdown", 8)) { if(strlen(line) > 9 && !strncmp(&line[9], "-r", 2)) { printf("\nSystem shutdown from vtty%u\n", get_current_vc()); printf("Restarting..."); //reboot(); } else { if((strlen(line) > 9) && (strlen(&line[9]) > 0)) printf("shutdown: Invalid argument \"%s\".\n", &line[9]); else printf("Usage: shutdown -r\n"); } } else if((strlen(line) > 0) && (!strcmp(line, "cls"))) { printf("\x1B[2J"); } else if((strlen(line) >= 8) && (!strcmp(line, "testheap"))) { //testheap(); } else if((strlen(line) > 0) && (!strcmp(line, "pwd"))) printf("/\n"); else if(strlen(line) > 0) printf("eshell: \"%s\" not found.\n", line); }