/**
* 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);
}