summaryrefslogtreecommitdiffstats
path: root/cpukit
diff options
context:
space:
mode:
authorChris Johns <chrisj@rtems.org>2008-04-03 03:13:24 +0000
committerChris Johns <chrisj@rtems.org>2008-04-03 03:13:24 +0000
commitea90df234adfede1d28070ec8aa1bbb75ca4c1cb (patch)
treefa2716a7a47602bbacb0865e97387bfe54abec7e /cpukit
parentgdb-6.8-rtems4.9-20080331.diff. (diff)
downloadrtems-ea90df234adfede1d28070ec8aa1bbb75ca4c1cb.tar.bz2
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.
Diffstat (limited to 'cpukit')
-rw-r--r--cpukit/ChangeLog12
-rw-r--r--cpukit/libfs/src/nfsclient/src/librtemsNfs.h5
-rw-r--r--cpukit/libfs/src/nfsclient/src/nfs.c6
-rw-r--r--cpukit/libmisc/Makefile.am10
-rw-r--r--cpukit/libmisc/shell/shell.c532
-rw-r--r--cpukit/libmisc/shell/shell.h31
-rw-r--r--cpukit/libmisc/shell/shell_getchar.c176
7 files changed, 648 insertions, 124 deletions
diff --git a/cpukit/ChangeLog b/cpukit/ChangeLog
index 7866fdc8e7..e220fa3e99 100644
--- a/cpukit/ChangeLog
+++ b/cpukit/ChangeLog
@@ -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
diff --git a/cpukit/libfs/src/nfsclient/src/librtemsNfs.h b/cpukit/libfs/src/nfsclient/src/librtemsNfs.h
index 20b6cd71ff..a6b156802d 100644
--- a/cpukit/libfs/src/nfsclient/src/librtemsNfs.h
+++ b/cpukit/libfs/src/nfsclient/src/librtemsNfs.h
@@ -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>
diff --git a/cpukit/libfs/src/nfsclient/src/nfs.c b/cpukit/libfs/src/nfsclient/src/nfs.c
index f3e841cb8f..a15f60f1bd 100644
--- a/cpukit/libfs/src/nfsclient/src/nfs.c
+++ b/cpukit/libfs/src/nfsclient/src/nfs.c
@@ -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).
diff --git a/cpukit/libmisc/Makefile.am b/cpukit/libmisc/Makefile.am
index 6103e3c56d..db79e248cf 100644
--- a/cpukit/libmisc/Makefile.am
+++ b/cpukit/libmisc/Makefile.am
@@ -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
diff --git a/cpukit/libmisc/shell/shell.c b/cpukit/libmisc/shell/shell.c
index e503739f94..de2147e7fc 100644
--- a/cpukit/libmisc/shell/shell.c
+++ b/cpukit/libmisc/shell/shell.c
@@ -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++;
-
- /* evaluate cmd section */
- c = cmd;
- while (*c) {
- if (!isblank(*c))
- break;
- c++;
- }
+ chdir("/"); /* XXX: chdir to getpwent homedir */
+ shell_env->exit_shell = FALSE;
+
+ for (;;) {
+ int cmd;
+
+ /* Prompt section */
+ if (prompt) {
+ rtems_shell_get_prompt(shell_env, prompt,
+ RTEMS_SHELL_PROMPT_SIZE);
+ }
+
+ /* getcmd section */
+ cmd = rtems_shell_line_editor(cmds, cmd_count,
+ RTEMS_SHELL_CMD_SIZE, prompt,
+ stdin, stdout);
+
+ 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 == '\0') /* empty line */
+ continue;
- if (*c == '#') { /* comment character */
- cmd[0] = 0;
- continue;
- }
+ if (*c == '#') { /* comment character */
+ cmds[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);
- }
+ 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(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);
+ /* 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;
}
- /* end exec cmd section */
- if (shell_env->exit_shell)
- break;
- strcpy(last_cmd, cmd);
- cmd[0] = 0;
+ 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 )
diff --git a/cpukit/libmisc/shell/shell.h b/cpukit/libmisc/shell/shell.h
index 2aca183138..10b10bd6ff 100644
--- a/cpukit/libmisc/shell/shell.h
+++ b/cpukit/libmisc/shell/shell.h
@@ -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(
diff --git a/cpukit/libmisc/shell/shell_getchar.c b/cpukit/libmisc/shell/shell_getchar.c
new file mode 100644
index 0000000000..c08a8bfa90
--- /dev/null
+++ b/cpukit/libmisc/shell/shell_getchar.c
@@ -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;
+ }
+ }
+}
+