diff options
author | Chris Johns <chrisj@rtems.org> | 2008-04-03 03:13:24 +0000 |
---|---|---|
committer | Chris Johns <chrisj@rtems.org> | 2008-04-03 03:13:24 +0000 |
commit | ea90df234adfede1d28070ec8aa1bbb75ca4c1cb (patch) | |
tree | fa2716a7a47602bbacb0865e97387bfe54abec7e /cpukit | |
parent | gdb-6.8-rtems4.9-20080331.diff. (diff) | |
download | rtems-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 '')
-rw-r--r-- | cpukit/ChangeLog | 12 | ||||
-rw-r--r-- | cpukit/libfs/src/nfsclient/src/librtemsNfs.h | 5 | ||||
-rw-r--r-- | cpukit/libfs/src/nfsclient/src/nfs.c | 6 | ||||
-rw-r--r-- | cpukit/libmisc/Makefile.am | 10 | ||||
-rw-r--r-- | cpukit/libmisc/shell/shell.c | 532 | ||||
-rw-r--r-- | cpukit/libmisc/shell/shell.h | 31 | ||||
-rw-r--r-- | cpukit/libmisc/shell/shell_getchar.c | 176 |
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; + } + } +} + |