forked from Imagelibrary/rtems
2008-04-03 Chris Johns <chrisj@rtems.org>
* libfs/src/nfsclient/src/librtemsNfs.h, libfs/src/nfsclient/src/nfs.c: Remove CEXP references. CEXP is external to RTEMS and even if in the cpukit it should not cross reference in this way. * libmisc/shell/shell_getchar.c: New. Taken from the monitor. * libmisc/Makefile.am: Add shell_getchar.c and clean up a little in the shell area. * libmisc/shell/shell.c, libmisc/shell/shell.h: Add line editting support.
This commit is contained in:
@@ -1,3 +1,15 @@
|
||||
2008-04-03 Chris Johns <chrisj@rtems.org>
|
||||
|
||||
* libfs/src/nfsclient/src/librtemsNfs.h,
|
||||
libfs/src/nfsclient/src/nfs.c: Remove CEXP references. CEXP is
|
||||
external to RTEMS and even if in the cpukit it should not cross
|
||||
reference in this way.
|
||||
* libmisc/shell/shell_getchar.c: New. Taken from the monitor.
|
||||
* libmisc/Makefile.am: Add shell_getchar.c and clean up a little
|
||||
in the shell area.
|
||||
* libmisc/shell/shell.c, libmisc/shell/shell.h: Add line editting
|
||||
support.
|
||||
|
||||
2008-03-29 Chris Johns <chrisj@rtems.org>
|
||||
|
||||
* librpc/include/rpc/clnt.h: Added the missing __BEGIN_DECLS as
|
||||
|
||||
@@ -70,11 +70,6 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
#ifdef HAVE_CEXP_H
|
||||
#include <cexpHelp.h>
|
||||
#endif
|
||||
|
||||
/* RPCIO driver interface.
|
||||
* If you need RPCIO for other purposes than NFS
|
||||
* you may want to include <rpcio.h>
|
||||
|
||||
@@ -68,17 +68,11 @@
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
|
||||
|
||||
#include <nfs_prot.h>
|
||||
#include <mount_prot.h>
|
||||
|
||||
#include "rpcio.h"
|
||||
|
||||
#ifdef HAVE_CEXP_H
|
||||
#include <cexpHelp.h>
|
||||
#endif
|
||||
|
||||
|
||||
/* Configurable parameters */
|
||||
|
||||
/* Estimated average length of a filename (including terminating 0).
|
||||
|
||||
@@ -71,16 +71,16 @@ libshell_a_SOURCES = shell/cat_file.c shell/cmds.c shell/internal.h \
|
||||
shell/main_echo.c shell/main_exit.c shell/main_help.c shell/main_id.c \
|
||||
shell/main_logoff.c shell/main_ls.c shell/main_mallocinfo.c \
|
||||
shell/main_mdump.c shell/main_medit.c shell/main_mfill.c \
|
||||
shell/main_mkdir.c shell/main_mount.c $(shell_mount_fs) \
|
||||
shell/main_mkdir.c shell/main_mount.c \
|
||||
shell/main_mount_msdos.c shell/main_mmove.c shell/main_msdosfmt.c \
|
||||
shell/main_mwdump.c shell/main_perioduse.c shell/main_pwd.c \
|
||||
shell/main_rm.c shell/main_rmdir.c shell/main_sleep.c \
|
||||
shell/main_stackuse.c shell/main_tty.c shell/main_umask.c \
|
||||
shell/main_unmount.c shell/main_blksync.c shell/main_whoami.c \
|
||||
shell/shell.c shell/shell_cmdset.c shell/shellconfig.c shell/shellconfig.h \
|
||||
shell/shell.h shell/shell_makeargs.c shell/str2int.c shell/write_file.c \
|
||||
shell/utils-cp.c shell/err.c shell/errx.c shell/verr.c shell/verrx.c \
|
||||
shell/vwarn.c shell/vwarnx.c shell/warn.c shell/warnx.c \
|
||||
shell/shell.c shell/shell_cmdset.c shell/shell_getchar.c shell/shellconfig.c \
|
||||
shell/shellconfig.h shell/shell.h shell/shell_makeargs.c shell/str2int.c \
|
||||
shell/write_file.c shell/utils-cp.c shell/err.c shell/errx.c shell/verr.c \
|
||||
shell/verrx.c shell/vwarn.c shell/vwarnx.c shell/warn.c shell/warnx.c \
|
||||
shell/fts.c shell/print_heapinfo.c shell/main_wkspaceinfo.c \
|
||||
shell/shell_script.c
|
||||
if LIBNETWORKING
|
||||
|
||||
@@ -79,11 +79,291 @@ rtems_shell_env_t *rtems_shell_init_env(
|
||||
/*
|
||||
* Get a line of user input with modest features
|
||||
*/
|
||||
int rtems_shell_line_editor(
|
||||
char *cmds[],
|
||||
int count,
|
||||
int size,
|
||||
const char *prompt,
|
||||
FILE *in,
|
||||
FILE *out
|
||||
)
|
||||
{
|
||||
unsigned int extended_key;
|
||||
char c;
|
||||
int col;
|
||||
int last_col;
|
||||
int output;
|
||||
char line[size];
|
||||
char new_line[size];
|
||||
int up;
|
||||
int cmd = -1;
|
||||
int inserting = 1;
|
||||
|
||||
output = (out && isatty(fileno(in)));
|
||||
|
||||
col = last_col = 0;
|
||||
|
||||
tcdrain(fileno(in));
|
||||
if (out)
|
||||
tcdrain(fileno(out));
|
||||
|
||||
if (output && prompt)
|
||||
fprintf(out, "\r%s", prompt);
|
||||
|
||||
line[0] = 0;
|
||||
new_line[0] = 0;
|
||||
|
||||
for (;;) {
|
||||
|
||||
if (output)
|
||||
fflush(out);
|
||||
|
||||
extended_key = rtems_shell_getchar(in);
|
||||
|
||||
if (extended_key == EOF)
|
||||
return -2;
|
||||
|
||||
c = extended_key & RTEMS_SHELL_KEYS_NORMAL_MASK;
|
||||
|
||||
/*
|
||||
* Make the extended_key usable as a boolean.
|
||||
*/
|
||||
extended_key &= ~RTEMS_SHELL_KEYS_NORMAL_MASK;
|
||||
|
||||
up = 0;
|
||||
|
||||
if (extended_key)
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case RTEMS_SHELL_KEYS_END:
|
||||
if (output)
|
||||
fprintf(out,line + col);
|
||||
col = (int) strlen (line);
|
||||
break;
|
||||
|
||||
case RTEMS_SHELL_KEYS_HOME:
|
||||
if (output) {
|
||||
if (prompt)
|
||||
fprintf(out,"\r%s", prompt);
|
||||
}
|
||||
col = 0;
|
||||
break;
|
||||
|
||||
case RTEMS_SHELL_KEYS_LARROW:
|
||||
if (col > 0)
|
||||
{
|
||||
col--;
|
||||
if (output)
|
||||
fputc('\b', out);
|
||||
}
|
||||
break;
|
||||
|
||||
case RTEMS_SHELL_KEYS_RARROW:
|
||||
if ((col < size) && (line[col] != '\0'))
|
||||
{
|
||||
if (output)
|
||||
fprintf(out, "%c", line[col]);
|
||||
col++;
|
||||
}
|
||||
break;
|
||||
|
||||
case RTEMS_SHELL_KEYS_UARROW:
|
||||
if ((cmd >= (count - 1)) || (strlen(cmds[cmd + 1]) == 0)) {
|
||||
if (output)
|
||||
fputc('\x7', out);
|
||||
break;
|
||||
}
|
||||
|
||||
up = 1;
|
||||
|
||||
/* drop through */
|
||||
case RTEMS_SHELL_KEYS_DARROW:
|
||||
|
||||
{
|
||||
int last_cmd = cmd;
|
||||
int clen = strlen (line);
|
||||
|
||||
if (prompt)
|
||||
clen += strlen(prompt);
|
||||
|
||||
if (up) {
|
||||
cmd++;
|
||||
} else {
|
||||
if (cmd < 0) {
|
||||
if (output)
|
||||
fprintf(out, "\x7");
|
||||
break;
|
||||
}
|
||||
else
|
||||
cmd--;
|
||||
}
|
||||
|
||||
if ((last_cmd < 0) || (strcmp(cmds[last_cmd], line) != 0))
|
||||
memcpy (new_line, line, size);
|
||||
|
||||
if (cmd < 0)
|
||||
memcpy (line, new_line, size);
|
||||
else
|
||||
memcpy (line, cmds[cmd], size);
|
||||
|
||||
col = strlen (line);
|
||||
|
||||
if (output) {
|
||||
fprintf(out,"\r%*c", clen, ' ');
|
||||
fprintf(out,"\r%s%s", prompt, line);
|
||||
}
|
||||
else {
|
||||
if (output)
|
||||
fputc('\x7', out);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RTEMS_SHELL_KEYS_DEL:
|
||||
if (line[col] != '\0')
|
||||
{
|
||||
int end;
|
||||
int bs;
|
||||
strcpy (&line[col], &line[col + 1]);
|
||||
if (output) {
|
||||
fprintf(out,"\r%s%s ", prompt, line);
|
||||
end = (int) strlen (line);
|
||||
for (bs = 0; bs < ((end - col) + 1); bs++)
|
||||
fputc('\b', out);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case RTEMS_SHELL_KEYS_INS:
|
||||
inserting = inserting ? 0 : 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (c)
|
||||
{
|
||||
case 1:/*Control-a*/
|
||||
if (output) {
|
||||
if (prompt)
|
||||
fprintf(out,"\r%s", prompt);
|
||||
}
|
||||
col = 0;
|
||||
break;
|
||||
|
||||
case 5:/*Control-e*/
|
||||
if (output)
|
||||
fprintf(out,line + col);
|
||||
col = (int) strlen (line);
|
||||
break;
|
||||
|
||||
case 11:/*Control-k*/
|
||||
if (line[col]) {
|
||||
if (output) {
|
||||
int end = strlen(line);
|
||||
int bs;
|
||||
fprintf(out,"%*c", end - col, ' ');
|
||||
for (bs = 0; bs < (end - col); bs++)
|
||||
fputc('\b', out);
|
||||
}
|
||||
line[col] = '\0';
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x04:/*Control-d*/
|
||||
if (strlen(line))
|
||||
break;
|
||||
case EOF:
|
||||
if (output)
|
||||
fputc(out, '\n');
|
||||
return -2;
|
||||
|
||||
case '\f':
|
||||
if (output) {
|
||||
int end;
|
||||
int bs;
|
||||
fputc('\f',out);
|
||||
fprintf(out,"\r%s%s", prompt, line);
|
||||
end = (int) strlen (line);
|
||||
for (bs = 0; bs < (end - col); bs++)
|
||||
fputc('\b', out);
|
||||
}
|
||||
break;
|
||||
|
||||
case '\b':
|
||||
case '\x7e':
|
||||
case '\x7f':
|
||||
if (col > 0)
|
||||
{
|
||||
int bs;
|
||||
col--;
|
||||
strcpy (line + col, line + col + 1);
|
||||
if (output) {
|
||||
fprintf(out,"\b%s \b", line + col);
|
||||
for (bs = 0; bs < ((int) strlen (line) - col); bs++)
|
||||
fputc('\b', out);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case '\n':
|
||||
case '\r':
|
||||
{
|
||||
/*
|
||||
* Process the command.
|
||||
*/
|
||||
if (output)
|
||||
fprintf(out,"\n");
|
||||
|
||||
/*
|
||||
* Only process the command if we have a command and it is not
|
||||
* repeated in the history.
|
||||
*/
|
||||
if (strlen(line) == 0) {
|
||||
cmd = -1;
|
||||
} else {
|
||||
if ((cmd < 0) || (strcmp(line, cmds[cmd]) != 0)) {
|
||||
if (count > 1)
|
||||
memmove(cmds[1], cmds[0], (count - 1) * size);
|
||||
memmove (cmds[0], line, size);
|
||||
cmd = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return cmd;
|
||||
|
||||
default:
|
||||
if ((col < (size - 1)) && (c >= ' ') && (c <= 'z')) {
|
||||
int end = strlen (line);
|
||||
if (inserting && (col < end) && (end < size)) {
|
||||
int ch, bs;
|
||||
for (ch = end + 1; ch > col; ch--)
|
||||
line[ch] = line[ch - 1];
|
||||
if (output) {
|
||||
fprintf(out, line + col);
|
||||
for (bs = 0; bs < (end - col + 1); bs++)
|
||||
fputc('\b', out);
|
||||
}
|
||||
}
|
||||
line[col++] = c;
|
||||
if (col > end)
|
||||
line[col] = '\0';
|
||||
if (output)
|
||||
fputc(c, out);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return -2;
|
||||
}
|
||||
|
||||
int rtems_shell_scanline(
|
||||
char *line,
|
||||
int size,
|
||||
FILE *in,
|
||||
FILE *out
|
||||
char *line,
|
||||
int size,
|
||||
FILE *in,
|
||||
FILE *out
|
||||
)
|
||||
{
|
||||
int c;
|
||||
@@ -104,16 +384,8 @@ int rtems_shell_scanline(
|
||||
line[col] = 0;
|
||||
c = fgetc(in);
|
||||
switch (c) {
|
||||
case 0x04:/*Control-d*/
|
||||
if (col)
|
||||
break;
|
||||
case EOF:
|
||||
return 0;
|
||||
case '\f':
|
||||
if (doEcho)
|
||||
fputc('\f',out);
|
||||
case 0x03:/*Control-C*/
|
||||
line[0] = 0;
|
||||
case '\n':
|
||||
case '\r':
|
||||
if (doEcho)
|
||||
@@ -148,7 +420,7 @@ int rtems_shell_scanline(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------- *
|
||||
* - The shell TASK
|
||||
* Poor but enough..
|
||||
@@ -363,19 +635,39 @@ rtems_task rtems_shell_task(rtems_task_argument task_argument)
|
||||
rtems_task_delete( RTEMS_SELF );
|
||||
}
|
||||
|
||||
#define RTEMS_SHELL_MAXIMUM_ARGUMENTS 128
|
||||
void rtems_shell_get_prompt(
|
||||
rtems_shell_env_t *shell_env,
|
||||
char *prompt,
|
||||
int size)
|
||||
{
|
||||
char curdir[256];
|
||||
|
||||
/* XXX: show_prompt user adjustable */
|
||||
getcwd(curdir,sizeof(curdir));
|
||||
snprintf(prompt, size - 1, "%s%s[%s] %c ",
|
||||
((shell_env->taskname) ? shell_env->taskname : ""),
|
||||
((shell_env->taskname) ? " " : ""),
|
||||
curdir,
|
||||
geteuid()?'$':'#');
|
||||
}
|
||||
|
||||
#define RTEMS_SHELL_MAXIMUM_ARGUMENTS (128)
|
||||
#define RTEMS_SHELL_CMD_SIZE (128)
|
||||
#define RTEMS_SHELL_CMD_COUNT (32)
|
||||
#define RTEMS_SHELL_PROMPT_SIZE (128)
|
||||
|
||||
rtems_boolean rtems_shell_main_loop(
|
||||
rtems_shell_env_t *shell_env_arg
|
||||
)
|
||||
)
|
||||
{
|
||||
rtems_shell_env_t *shell_env;
|
||||
rtems_shell_cmd_t *shell_cmd;
|
||||
rtems_status_code sc;
|
||||
struct termios term;
|
||||
char curdir[256];
|
||||
char cmd[256];
|
||||
char last_cmd[256]; /* to repeat 'r' */
|
||||
char *prompt = NULL;
|
||||
int cmd;
|
||||
int cmd_count = 1; /* assume a script and so only 1 command line */
|
||||
char *cmds[RTEMS_SHELL_CMD_COUNT];
|
||||
int argc;
|
||||
char *argv[RTEMS_SHELL_MAXIMUM_ARGUMENTS];
|
||||
rtems_boolean result = TRUE;
|
||||
@@ -384,10 +676,12 @@ rtems_boolean rtems_shell_main_loop(
|
||||
FILE *stdinToClose = NULL;
|
||||
FILE *stdoutToClose = NULL;
|
||||
|
||||
memset(cmds, 0, sizeof(cmds));
|
||||
|
||||
rtems_shell_initialize_command_set();
|
||||
|
||||
shell_env =
|
||||
rtems_current_shell_env = rtems_shell_init_env( shell_env_arg );
|
||||
rtems_current_shell_env = rtems_shell_init_env( shell_env_arg );
|
||||
|
||||
/*
|
||||
* @todo chrisj
|
||||
@@ -404,14 +698,14 @@ rtems_boolean rtems_shell_main_loop(
|
||||
|
||||
setuid(0);
|
||||
setgid(0);
|
||||
rtems_current_user_env->euid =
|
||||
rtems_current_user_env->egid = 0;
|
||||
|
||||
rtems_current_user_env->euid = rtems_current_user_env->egid = 0;
|
||||
|
||||
fileno(stdout);
|
||||
|
||||
/* fprintf( stderr,
|
||||
"-%s-%s-\n", shell_env->input, shell_env->output );
|
||||
*/
|
||||
*/
|
||||
|
||||
if (shell_env->output && strcmp(shell_env->output, "stdout") != 0) {
|
||||
if (strcmp(shell_env->output, "stderr") == 0) {
|
||||
@@ -460,111 +754,133 @@ rtems_boolean rtems_shell_main_loop(
|
||||
"shell:cannot set terminal attributes(%s)\n",shell_env->devname);
|
||||
}
|
||||
}
|
||||
cmd_count = RTEMS_SHELL_CMD_COUNT;
|
||||
prompt = malloc(RTEMS_SHELL_PROMPT_SIZE);
|
||||
if (!prompt)
|
||||
fprintf(stderr,
|
||||
"shell:cannot allocate prompt memory\n");
|
||||
}
|
||||
|
||||
setvbuf(stdin,NULL,_IONBF,0); /* Not buffered*/
|
||||
setvbuf(stdout,NULL,_IONBF,0); /* Not buffered*/
|
||||
|
||||
rtems_shell_initialize_command_set();
|
||||
do {
|
||||
/* Set again root user and root filesystem, side effect of set_priv..*/
|
||||
sc = rtems_libio_set_private_env();
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
rtems_error(sc,"rtems_libio_set_private_env():");
|
||||
result = FALSE;
|
||||
break;
|
||||
|
||||
/*
|
||||
* Allocate the command line buffers.
|
||||
*/
|
||||
cmds[0] = calloc (cmd_count, RTEMS_SHELL_CMD_SIZE);
|
||||
if (!cmds[0]) {
|
||||
fprintf(stderr, "no memory for command line buffers\n" );
|
||||
}
|
||||
else {
|
||||
|
||||
memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
|
||||
|
||||
for (cmd = 1; cmd < cmd_count; cmd++) {
|
||||
cmds[cmd] = cmds[cmd - 1] + RTEMS_SHELL_CMD_SIZE;
|
||||
}
|
||||
if (input_file || !rtems_shell_login(stdin,stdout)) {
|
||||
const char *c;
|
||||
strcpy(last_cmd,"");
|
||||
strcpy(cmd,"");
|
||||
if (!input_file) {
|
||||
rtems_shell_cat_file(stdout,"/etc/motd");
|
||||
fprintf(stdout, "\n"
|
||||
"RTEMS SHELL (Ver.1.0-FRC):%s. " \
|
||||
__DATE__". 'help' to list commands.\n",
|
||||
shell_env->devname);
|
||||
|
||||
do {
|
||||
/* Set again root user and root filesystem, side effect of set_priv..*/
|
||||
sc = rtems_libio_set_private_env();
|
||||
if (sc != RTEMS_SUCCESSFUL) {
|
||||
rtems_error(sc,"rtems_libio_set_private_env():");
|
||||
result = FALSE;
|
||||
break;
|
||||
}
|
||||
chdir("/"); /* XXX: chdir to getpwent homedir */
|
||||
shell_env->exit_shell = FALSE;
|
||||
for (;;) {
|
||||
/* Prompt section */
|
||||
if (input_file || !rtems_shell_login(stdin,stdout)) {
|
||||
const char *c;
|
||||
memset (cmds[0], 0, cmd_count * RTEMS_SHELL_CMD_SIZE);
|
||||
if (!input_file) {
|
||||
/* XXX: show_prompt user adjustable */
|
||||
getcwd(curdir,sizeof(curdir));
|
||||
fprintf(stdout, "%s%s[%s] %c ",
|
||||
((shell_env->taskname) ? shell_env->taskname : ""),
|
||||
((shell_env->taskname) ? " " : ""),
|
||||
curdir,
|
||||
geteuid()?'$':'#');
|
||||
rtems_shell_cat_file(stdout,"/etc/motd");
|
||||
fprintf(stdout, "\n"
|
||||
"RTEMS SHELL (Ver.1.0-FRC):%s. " \
|
||||
__DATE__". 'help' to list commands.\n",
|
||||
shell_env->devname);
|
||||
}
|
||||
|
||||
/* getcmd section */
|
||||
if (!rtems_shell_scanline(cmd,sizeof(cmd),stdin,stdout)) {
|
||||
break; /*EOF*/
|
||||
}
|
||||
line++;
|
||||
chdir("/"); /* XXX: chdir to getpwent homedir */
|
||||
shell_env->exit_shell = FALSE;
|
||||
|
||||
/* evaluate cmd section */
|
||||
c = cmd;
|
||||
while (*c) {
|
||||
if (!isblank(*c))
|
||||
break;
|
||||
c++;
|
||||
}
|
||||
|
||||
if (*c == '\0') /* empty line */
|
||||
continue;
|
||||
|
||||
if (*c == '#') { /* comment character */
|
||||
cmd[0] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(cmd,"e")) { /* edit last command */
|
||||
strcpy(cmd,last_cmd);
|
||||
continue;
|
||||
} else if (!strcmp(cmd,"r")) { /* repeat last command */
|
||||
strcpy(cmd,last_cmd);
|
||||
} else if (!strcmp(cmd,"bye") || !strcmp(cmd,"exit")) {
|
||||
fprintf(stdout, "Shell exiting\n" );
|
||||
break;
|
||||
} else if (!strcmp(cmd,"shutdown")) { /* exit application */
|
||||
fprintf(stdout, "System shutting down at user request\n" );
|
||||
exit(0);
|
||||
} else if (!strcmp(cmd,"")) { /* only for get a new prompt */
|
||||
strcpy(last_cmd,cmd);
|
||||
}
|
||||
|
||||
/* exec cmd section */
|
||||
/* TODO:
|
||||
* To avoid user crash catch the signals.
|
||||
* Open a new stdio files with posibility of redirection *
|
||||
* Run in a new shell task background. (unix &)
|
||||
* Resuming. A little bash.
|
||||
*/
|
||||
if (!rtems_shell_make_args(cmd, &argc, argv,
|
||||
RTEMS_SHELL_MAXIMUM_ARGUMENTS)) {
|
||||
shell_cmd = rtems_shell_lookup_cmd(argv[0]);
|
||||
if ( argv[0] == NULL ) {
|
||||
shell_env->errorlevel = -1;
|
||||
} else if ( shell_cmd == NULL ) {
|
||||
shell_env->errorlevel = rtems_shell_script_file( argc, argv );
|
||||
} else {
|
||||
shell_env->errorlevel = shell_cmd->command(argc, argv);
|
||||
for (;;) {
|
||||
int cmd;
|
||||
|
||||
/* Prompt section */
|
||||
if (prompt) {
|
||||
rtems_shell_get_prompt(shell_env, prompt,
|
||||
RTEMS_SHELL_PROMPT_SIZE);
|
||||
}
|
||||
}
|
||||
/* end exec cmd section */
|
||||
|
||||
/* getcmd section */
|
||||
cmd = rtems_shell_line_editor(cmds, cmd_count,
|
||||
RTEMS_SHELL_CMD_SIZE, prompt,
|
||||
stdin, stdout);
|
||||
|
||||
if (shell_env->exit_shell)
|
||||
break;
|
||||
strcpy(last_cmd, cmd);
|
||||
cmd[0] = 0;
|
||||
if (cmd == -1)
|
||||
continue; /* empty line */
|
||||
|
||||
if (cmd == -2)
|
||||
break; /*EOF*/
|
||||
|
||||
line++;
|
||||
|
||||
/* evaluate cmd section */
|
||||
c = cmds[cmd];
|
||||
while (*c) {
|
||||
if (!isblank(*c))
|
||||
break;
|
||||
c++;
|
||||
}
|
||||
|
||||
if (*c == '\0') /* empty line */
|
||||
continue;
|
||||
|
||||
if (*c == '#') { /* comment character */
|
||||
cmds[cmd][0] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!strcmp(cmds[cmd],"bye") || !strcmp(cmds[cmd],"exit")) {
|
||||
fprintf(stdout, "Shell exiting\n" );
|
||||
break;
|
||||
} else if (!strcmp(cmds[cmd],"shutdown")) { /* exit application */
|
||||
fprintf(stdout, "System shutting down at user request\n" );
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/* exec cmd section */
|
||||
/* TODO:
|
||||
* To avoid user crash catch the signals.
|
||||
* Open a new stdio files with posibility of redirection *
|
||||
* Run in a new shell task background. (unix &)
|
||||
* Resuming. A little bash.
|
||||
*/
|
||||
if (!rtems_shell_make_args(cmds[cmd], &argc, argv,
|
||||
RTEMS_SHELL_MAXIMUM_ARGUMENTS)) {
|
||||
shell_cmd = rtems_shell_lookup_cmd(argv[0]);
|
||||
if ( argv[0] == NULL ) {
|
||||
shell_env->errorlevel = -1;
|
||||
} else if ( shell_cmd == NULL ) {
|
||||
shell_env->errorlevel = rtems_shell_script_file(argc, argv);
|
||||
} else {
|
||||
shell_env->errorlevel = shell_cmd->command(argc, argv);
|
||||
}
|
||||
}
|
||||
|
||||
/* end exec cmd section */
|
||||
if (shell_env->exit_shell)
|
||||
break;
|
||||
}
|
||||
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
}
|
||||
fflush( stdout );
|
||||
fflush( stderr );
|
||||
}
|
||||
} while (result && shell_env->forever);
|
||||
} while (result && shell_env->forever);
|
||||
|
||||
free (cmds[0]);
|
||||
}
|
||||
|
||||
if ( stdinToClose )
|
||||
fclose( stdinToClose );
|
||||
if ( stdoutToClose )
|
||||
|
||||
@@ -29,6 +29,31 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Some key labels to define special keys.
|
||||
*/
|
||||
|
||||
#define RTEMS_SHELL_KEYS_EXTENDED (0x8000)
|
||||
#define RTEMS_SHELL_KEYS_NORMAL_MASK (0x00ff)
|
||||
#define RTEMS_SHELL_KEYS_INS (0)
|
||||
#define RTEMS_SHELL_KEYS_DEL (1)
|
||||
#define RTEMS_SHELL_KEYS_UARROW (2)
|
||||
#define RTEMS_SHELL_KEYS_DARROW (3)
|
||||
#define RTEMS_SHELL_KEYS_LARROW (4)
|
||||
#define RTEMS_SHELL_KEYS_RARROW (5)
|
||||
#define RTEMS_SHELL_KEYS_HOME (6)
|
||||
#define RTEMS_SHELL_KEYS_END (7)
|
||||
#define RTEMS_SHELL_KEYS_F1 (8)
|
||||
#define RTEMS_SHELL_KEYS_F2 (9)
|
||||
#define RTEMS_SHELL_KEYS_F3 (10)
|
||||
#define RTEMS_SHELL_KEYS_F4 (11)
|
||||
#define RTEMS_SHELL_KEYS_F5 (12)
|
||||
#define RTEMS_SHELL_KEYS_F6 (13)
|
||||
#define RTEMS_SHELL_KEYS_F7 (14)
|
||||
#define RTEMS_SHELL_KEYS_F8 (15)
|
||||
#define RTEMS_SHELL_KEYS_F9 (16)
|
||||
#define RTEMS_SHELL_KEYS_F10 (17)
|
||||
|
||||
typedef int (*rtems_shell_command_t)(int argc,char * argv[]);
|
||||
|
||||
struct rtems_shell_cmd_tt;
|
||||
@@ -48,6 +73,12 @@ typedef struct {
|
||||
char *alias;
|
||||
} rtems_shell_alias_t;
|
||||
|
||||
/*
|
||||
* The return value has RTEMS_SHELL_KEYS_EXTENDED set if the key
|
||||
* is extended, ie a special key.
|
||||
*/
|
||||
unsigned int rtems_shell_getchar(FILE *in);
|
||||
|
||||
rtems_shell_cmd_t * rtems_shell_lookup_cmd(char * cmd);
|
||||
|
||||
rtems_shell_cmd_t *rtems_shell_add_cmd_struct(
|
||||
|
||||
176
cpukit/libmisc/shell/shell_getchar.c
Normal file
176
cpukit/libmisc/shell/shell_getchar.c
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
*
|
||||
* Handle keys for the shell.
|
||||
*
|
||||
* Author:
|
||||
*
|
||||
* Chris Johns (chrisj@rtems.org)
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <rtems.h>
|
||||
#include <rtems/error.h>
|
||||
#include <rtems/system.h>
|
||||
#include <rtems/shell.h>
|
||||
#include <rtems/shellconfig.h>
|
||||
#include "internal.h"
|
||||
|
||||
/*
|
||||
* Taken from the monitor code.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Translation tables. Not sure if this is the best way to
|
||||
* handle this, how-ever I wish to avoid the overhead of
|
||||
* including a more complete and standard environment such
|
||||
* as ncurses.
|
||||
*/
|
||||
|
||||
struct translation_table
|
||||
{
|
||||
char expecting;
|
||||
struct translation_table *branch;
|
||||
unsigned int key;
|
||||
};
|
||||
|
||||
static struct translation_table trans_one[] =
|
||||
{
|
||||
{ '\x7e', 0, RTEMS_SHELL_KEYS_HOME },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static struct translation_table trans_two[] =
|
||||
{
|
||||
{ '~', 0, RTEMS_SHELL_KEYS_INS },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static struct translation_table trans_three[] =
|
||||
{
|
||||
{ '~', 0, RTEMS_SHELL_KEYS_DEL },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static struct translation_table trans_tab_csi[] =
|
||||
{
|
||||
{ '1', trans_one, 0 },
|
||||
{ '2', trans_two, 0 },
|
||||
{ '3', trans_three, 0 },
|
||||
{ 'A', 0, RTEMS_SHELL_KEYS_UARROW },
|
||||
{ 'B', 0, RTEMS_SHELL_KEYS_DARROW },
|
||||
{ 'D', 0, RTEMS_SHELL_KEYS_LARROW },
|
||||
{ 'C', 0, RTEMS_SHELL_KEYS_RARROW },
|
||||
{ 'F', 0, RTEMS_SHELL_KEYS_END },
|
||||
{ 'H', 0, RTEMS_SHELL_KEYS_HOME },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static struct translation_table trans_tab_O[] =
|
||||
{
|
||||
{ '1', 0, RTEMS_SHELL_KEYS_F1 },
|
||||
{ '2', 0, RTEMS_SHELL_KEYS_F2 },
|
||||
{ '3', 0, RTEMS_SHELL_KEYS_F3 },
|
||||
{ '4', 0, RTEMS_SHELL_KEYS_F4 },
|
||||
{ '5', 0, RTEMS_SHELL_KEYS_F5 },
|
||||
{ '6', 0, RTEMS_SHELL_KEYS_F6 },
|
||||
{ '7', 0, RTEMS_SHELL_KEYS_F7 },
|
||||
{ '8', 0, RTEMS_SHELL_KEYS_F8 },
|
||||
{ '9', 0, RTEMS_SHELL_KEYS_F9 },
|
||||
{ ':', 0, RTEMS_SHELL_KEYS_F10 },
|
||||
{ 'F', 0, RTEMS_SHELL_KEYS_END },
|
||||
{ 'P', 0, RTEMS_SHELL_KEYS_F1 },
|
||||
{ 'Q', 0, RTEMS_SHELL_KEYS_F2 },
|
||||
{ 'R', 0, RTEMS_SHELL_KEYS_F3 },
|
||||
{ 'S', 0, RTEMS_SHELL_KEYS_F4 },
|
||||
{ 'T', 0, RTEMS_SHELL_KEYS_F5 },
|
||||
{ 'U', 0, RTEMS_SHELL_KEYS_F6 },
|
||||
{ 'V', 0, RTEMS_SHELL_KEYS_F7 },
|
||||
{ 'W', 0, RTEMS_SHELL_KEYS_F8 },
|
||||
{ 'X', 0, RTEMS_SHELL_KEYS_F9 },
|
||||
{ 'Y', 0, RTEMS_SHELL_KEYS_F10 },
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
static struct translation_table trans_tab[] =
|
||||
{
|
||||
{ '[', trans_tab_csi, 0 }, /* CSI command sequences */
|
||||
{ 'O', trans_tab_O, 0 }, /* O are the fuction keys */
|
||||
{ 0, 0, 0 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Perform a basic tranlation for some ANSI/VT100 key codes.
|
||||
* This code could do with a timeout on the ESC as it is
|
||||
* now lost from the input stream. It is not* used by the
|
||||
* line editor below so considiered not worth the effort.
|
||||
*/
|
||||
|
||||
unsigned int
|
||||
rtems_shell_getchar (FILE *in)
|
||||
{
|
||||
struct translation_table *translation = 0;
|
||||
for (;;)
|
||||
{
|
||||
char c = fgetc (in);
|
||||
if (c == EOF)
|
||||
return EOF;
|
||||
if (c == 27)
|
||||
translation = trans_tab;
|
||||
else
|
||||
{
|
||||
/*
|
||||
* If no translation happing just pass through
|
||||
* and return the key.
|
||||
*/
|
||||
if (translation)
|
||||
{
|
||||
/*
|
||||
* Scan the current table for the key, and if found
|
||||
* see if this key is a fork. If so follow it and
|
||||
* wait else return the extended key.
|
||||
*/
|
||||
int index = 0;
|
||||
int branched = 0;
|
||||
while ((translation[index].expecting != '\0') ||
|
||||
(translation[index].key != '\0'))
|
||||
{
|
||||
if (translation[index].expecting == c)
|
||||
{
|
||||
/*
|
||||
* A branch is take if more keys are to come.
|
||||
*/
|
||||
if (translation[index].branch == 0)
|
||||
return RTEMS_SHELL_KEYS_EXTENDED | translation[index].key;
|
||||
else
|
||||
{
|
||||
translation = translation[index].branch;
|
||||
branched = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
index++;
|
||||
}
|
||||
/*
|
||||
* Who knows what these keys are, just drop them.
|
||||
*/
|
||||
if (!branched)
|
||||
translation = 0;
|
||||
}
|
||||
else
|
||||
return c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user