diff options
Diffstat (limited to 'cfe/cfe/main/cfe_console.c')
-rwxr-xr-x | cfe/cfe/main/cfe_console.c | 1190 |
1 files changed, 1190 insertions, 0 deletions
diff --git a/cfe/cfe/main/cfe_console.c b/cfe/cfe/main/cfe_console.c new file mode 100755 index 0000000..a9464f1 --- /dev/null +++ b/cfe/cfe/main/cfe_console.c @@ -0,0 +1,1190 @@ +/* ********************************************************************* + * Broadcom Common Firmware Environment (CFE) + * + * Console Interface File: cfe_console.c + * + * This module contains high-level routines for dealing with + * the console (TTY-style) device. + * + * Author: Mitch Lichtenberg (mpl@broadcom.com) + * + ********************************************************************* + * + * Copyright 2000,2001,2002,2003 + * Broadcom Corporation. All rights reserved. + * + * This software is furnished under license and may be used and + * copied only in accordance with the following terms and + * conditions. Subject to these conditions, you may download, + * copy, install, use, modify and distribute modified or unmodified + * copies of this software in source and/or binary form. No title + * or ownership is transferred hereby. + * + * 1) Any source code used, modified or distributed must reproduce + * and retain this copyright notice and list of conditions + * as they appear in the source file. + * + * 2) No right is granted to use any trade name, trademark, or + * logo of Broadcom Corporation. The "Broadcom Corporation" + * name may not be used to endorse or promote products derived + * from this software without the prior written permission of + * Broadcom Corporation. + * + * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED + * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR + * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT + * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN + * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR + * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF + * THE POSSIBILITY OF SUCH DAMAGE. + ********************************************************************* */ + + +#include <stdarg.h> +#include "lib_types.h" +#include "lib_string.h" +#include "lib_queue.h" +#include "lib_malloc.h" +#include "lib_printf.h" + +#include "cfe_iocb.h" +#include "cfe_devfuncs.h" +#include "cfe_timer.h" +#include "cfe_error.h" +#include "env_subr.h" +#include "cfe_console.h" +#include "cfe.h" + +#include "bsp_config.h" + + +/* + * Escape sequences: + * + * Sequence Descr Emulator + * + * ESC [ A UP xterm + * ESC [ B DOWN xterm + * ESC [ C RIGHT xterm + * ESC [ D LEFT xterm + * + * ESC O P F1 xterm + * ESC O Q F2 xterm + * ESC O R F3 xterm + * ESC O S F4 xterm + * + * ESC [ 1 1 ~ F1 teraterm + * ESC [ 1 2 ~ F2 teraterm + * ESC [ 1 3 ~ F3 teraterm + * ESC [ 1 4 ~ F4 teraterm + * + * ESC [ 1 5 ~ F5 xterm,teraterm + * ESC [ 1 7 ~ F6 xterm,teraterm + * ESC [ 1 8 ~ F7 xterm,teraterm + * ESC [ 1 9 ~ F8 xterm,teraterm + * ESC [ 2 0 ~ F9 xterm,teraterm + * ESC [ 2 1 ~ F10 xterm,teraterm + * ESC [ 2 3 ~ F11 xterm,teraterm + * ESC [ 2 4 ~ F12 xterm,teraterm + * + * ESC [ 5 ~ PGUP xterm + * ESC [ 6 ~ PGDN xterm + * ESC [ F HOME xterm + * ESC [ H END xterm + * + * ESC [ 2 ~ HOME teraterm + * ESC [ 3 ~ PGUP teraterm + * ESC [ 5 ~ END teraterm + * ESC [ 6 ~ PGDN teraterm + * + */ + + +/* ********************************************************************* + * Constants + ********************************************************************* */ + + +#define CTRL(x) ((x)-'@') + +#define GETCHAR(x) while (console_read(&(x),1) != 1) { POLL(); } + +#define XTERM 0 +#define TERATERM 1 + +#define MAXSAVELINES 30 +#define MSGQUEUEMAX 10 /* number of chunks of log to keep */ +#define MSGQUEUESIZE 256 /* size of each chunk of console log */ + + +/* ********************************************************************* + * Structures + ********************************************************************* */ + +typedef struct msgqueue_s { /* saved console log message */ + queue_t link; + int len; + char data[MSGQUEUESIZE]; +} msgqueue_t; + +/* ********************************************************************* + * Globals + ********************************************************************* */ + +#if !CFG_MINIMAL_SIZE +int console_nextsave = 0; +char *console_savedlines[MAXSAVELINES] = {0}; +static char *console_killbuffer = NULL; +queue_t console_msgq = {&console_msgq,&console_msgq}; +static int console_buffer_flg = 0; +static int console_mode = XTERM; + +static void console_flushbuffer(void); +static void console_save(unsigned char *buffer,int length); + +#endif + +#if defined(CONFIG_MIPS_BRCM) +int g_console_abort = 0; +#endif +int console_handle = -1; +static int console_xprint(const char *str); +char *console_name = NULL; +static int console_inreadline = 0; +static int console_redisplay = 0; + +/* ********************************************************************* + * console_log(tmplt,...) + * + * Sort of like printf, but used during things that might be + * called in the polling loop. If you print out a message + * using this call and it happens to be printed while processing + * the console "readline" loop, the readline and the associated + * prompt will be redisplayed. Don't include the \r\n in the + * string to be displayed. + * + * Input parameters: + * tmplt, ... - printf parameters + * + * Return value: + * nothing + ********************************************************************* */ + +void console_log(const char *tmplt,...) +{ + char buffer[256]; + va_list marker; + int count; + + va_start(marker,tmplt); + count = xvsprintf(buffer,tmplt,marker); + va_end(marker); + xprintf("\r%s\033[J\r\n",buffer); + + if (console_inreadline) console_redisplay = 1; +} + +/* ********************************************************************* + * console_open(name) + * + * Open the specified device and make it the console + * + * Input parameters: + * name - name of device + * + * Return value: + * 0 if ok, else return code. + * console_handle contains the console's handle + ********************************************************************* */ + +int console_open(char *name) +{ +#if CFG_MINIMAL_SIZE + if (console_handle != -1) { + console_close(); + } + + console_handle = cfe_open(name); + if (console_handle < 0) return CFE_ERR_DEVNOTFOUND; + +#else + + int flushbuf; + + console_name = NULL; + + if (console_handle != -1) { + console_close(); + } + + flushbuf = console_buffer_flg; + console_buffer_flg = 0; + + console_handle = cfe_open(name); + if (console_handle < 0) return CFE_ERR_DEVNOTFOUND; + + console_name = name; + if (flushbuf) console_flushbuffer(); +#endif + + return 0; +} + +/* ********************************************************************* + * console_close() + * + * Close the console device + * + * Input parameters: + * nothing + * + * Return value: + * 0 + ********************************************************************* */ + +int console_close(void) +{ + if (console_handle != -1) { + cfe_close(console_handle); + } + + console_handle = -1; + + return 0; +} + +/* ********************************************************************* + * console_read(buffer,length) + * + * Read characters from the console. + * + * Input parameters: + * buffer - pointer to buffer to receive characters + * length - total size of the buffer + * + * Return value: + * number of characters received, or <0 if error code + ********************************************************************* */ + +int console_read(char *buffer,int length) +{ + if (console_handle == -1) return -1; + + return cfe_read(console_handle,(unsigned char*)buffer,length); +} + + +/* ********************************************************************* + * console_write(buffer,length) + * + * Write text to the console. If the console is not open and + * we're "saving" text, put the text on the in-memory queue + * + * Input parameters: + * buffer - pointer to data + * length - number of characters to write + * + * Return value: + * number of characters written or <0 if error + ********************************************************************* */ + +int console_write(char *buffer,int length) +{ + int res; + +#if !CFG_MINIMAL_SIZE + /* + * Buffer text if requested + */ + if (console_buffer_flg) { + console_save(buffer,length); + return length; + } +#endif + + /* + * Do nothing if no console + */ + + if (console_handle == -1) return -1; + + /* + * Write text to device + */ + + for (;;) { + res = cfe_write(console_handle,(unsigned char*)buffer,length); + if (res < 0) break; + buffer += res; + length -= res; + if (length == 0) break; + } + + if (res < 0) return -1; + return 0; +} + +/* ********************************************************************* + * console_status() + * + * Return the status of input for the console. + * + * Input parameters: + * nothing + * + * Return value: + * 0 if no characters are available + * 1 if characters are available. + ********************************************************************* */ + +int console_status(void) +{ + if (console_handle == -1) return 0; + + return cfe_inpstat(console_handle); +} + +/* ********************************************************************* + * console_xprint(str) + * + * printf callback for the console device. the "xprintf" + * routine ends up calling this. This routine also cooks the + * output, turning "\n" into "\r\n" + * + * Input parameters: + * str - string to write + * + * Return value: + * number of characters written + ********************************************************************* */ + +static int console_xprint(const char *str) +{ + int count = 0; + int len; + const char *p; + + /* Convert CR to CRLF as we write things out */ + + while ((p = strchr(str,'\n'))) { + console_write((char*)str,p-str); + console_write("\r\n",2); + count += (p-str); + str = p + 1; + } + + len = strlen(str); + console_write((char*)str, len); + count += len; + + return count; +} + + +/* ********************************************************************* + * console_readline_noedit(str,len) + * + * A simple 'gets' type routine for the console. We support + * backspace and carriage return. No line editing support here, + * this routine is used in places where we don't want it. + * + * Input parameters: + * prompt - prompt string + * str - pointer to user buffer + * len - length of user buffer + * + * Return value: + * number of characters read (terminating newline is not + * placed in the buffer) + ********************************************************************* */ + +int console_readline_noedit(char *prompt,char *str,int len) +{ + int reading = 1; + char ch; + int res = -1; + int idx = 0; + + console_inreadline++; + + if (prompt && *prompt) console_write(prompt,strlen(prompt)); + + POLL(); + while (reading) { + + /* + * If someone used console_log (above) or hit Control-C (below), + * redisplay the prompt and the string we've got so far. + */ + + if (console_redisplay) { + if (prompt && *prompt) console_write(prompt,strlen(prompt)); + console_write(str,idx); + console_redisplay = 0; + continue; + } + +#if defined(CONFIG_MIPS_BRCM) + + /* + * If a background process has set the global g_console_abort flag, stop + * reading from the keyboard. + */ + + if (g_console_abort) { + g_console_abort = 0; + break; + } + +#endif + + /* + * if nobody's typed anything, keep polling + */ + + if (console_status() == 0) { + POLL(); + continue; + } + + /* + * Get the char from the keyboard + */ + + res = console_read(&ch,1); + if (res < 0) break; + if (res == 0) continue; + + /* + * And dispatch it + */ + + switch (ch) { + case 3: /* Ctrl-C */ + console_write("^C\r\n",4); + console_redisplay = 1; + idx = 0; + break; + case 0x7f: + case '\b': + if (idx > 0) { + idx--; + console_write("\b \b",3); + } + break; + case 21: /* Ctrl-U */ + while (idx > 0) { + idx--; + console_write("\b \b",3); + } + break; + case '\r': + case '\n': + console_write("\r\n",2); + reading = 0; + break; + default: + if (ch >= ' ') { + if (idx < (len-1)) { + str[idx] = ch; + idx++; + console_write(&ch,1); + } + } + break; + } + } + POLL(); + + console_inreadline--; + + str[idx] = 0; + return idx; +} + + +/* ********************************************************************* + * cfe_set_console(name) + * + * This routine is usually called from the BSP's initialization + * module to set up the console device. We set the xprintf + * callback and open the console device. If we open a special + * magic console device (CFE_BUFFER_CONSOLE) the console subsystem + * will buffer text instead. A later call to cfe_set_console + * with a real console name will cause this text to be flushed. + * + * Input parameters: + * name - name of console device + * + * Return value: + * 0 if ok + * else error code + ********************************************************************* */ + +int cfe_set_console(char *name) +{ + xprinthook = console_xprint; + +#if !CFG_MINIMAL_SIZE + if (strcmp(name,CFE_BUFFER_CONSOLE) == 0) { + console_buffer_flg = 1; + return 0; + } +#endif + + if (name) { + int res; + res = env_setenv("BOOT_CONSOLE",name, + ENV_FLG_BUILTIN | ENV_FLG_READONLY | ENV_FLG_ADMIN); + return console_open(name); + } + return -1; +} + +#if !CFG_MINIMAL_SIZE + +/* ********************************************************************* + * console_flushbuffer() + * + * Flush queued (saved) console messages to the real console + * device. This is used if we need to delay console + * initialization until after other devices are initialized, + * for example, with a VGA console that won't work until + * after PCI initialization. + * + * Input parameters: + * nothing + * + * Return value: + * nothing + ********************************************************************* */ + +static void console_flushbuffer(void) +{ + msgqueue_t *msg; + char *buffer; + int length; + int res; + + /* + * Remove console messages from the queue + */ + + while ((msg = (msgqueue_t *) q_deqnext(&console_msgq))) { + + buffer = msg->data; + length = msg->len; + res = 0; + + /* + * Write each message to the console + */ + + for (;;) { + res = cfe_write(console_handle,buffer,length); + if (res < 0) break; + buffer += res; + length -= res; + if (length == 0) break; + } + + /* + * Free the storage + */ + + KFREE(msg); + } +} + + +/* ********************************************************************* + * console_save(buffer,length) + * + * This is used when we want to generate console output + * before the device is initialized. The console_save + * routine saves a copy of the log messages in a queue + * for later retrieval when the console device is open. + * + * Input parameters: + * buffer - message text to save + * length - number of bytes + * + * Return value: + * nothing + ********************************************************************* */ + +static void console_save(unsigned char *buffer,int length) +{ + msgqueue_t *msg; + + /* + * Get a pointer to the last message in the queue. If + * it's full, preprare to allocate a new one + */ + + msg = (msgqueue_t *) console_msgq.q_prev; + if (q_isempty(&(console_msgq)) || (msg->len == MSGQUEUESIZE)) { + msg = NULL; + } + + /* + * Stuff characters into message chunks till we're done + */ + + while (length) { + + /* + * New chunk + */ + if (msg == NULL) { + + msg = (msgqueue_t *) KMALLOC(sizeof(msgqueue_t),0); + if (msg == NULL) return; + msg->len = 0; + q_enqueue(&console_msgq,(queue_t *) msg); + + /* + * Remove chunks to prevent chewing too much memory + */ + + while (q_count(&console_msgq) > MSGQUEUEMAX) { + msgqueue_t *dropmsg; + dropmsg = (msgqueue_t *) q_deqnext(&console_msgq); + if (dropmsg) KFREE(dropmsg); + } + } + + /* + * Save text. If we run off the end of the buffer, prepare + * to allocate a new one + */ + msg->data[msg->len++] = *buffer++; + length--; + if (msg->len == MSGQUEUESIZE) msg = NULL; + } +} + + +/* ********************************************************************* + * console_readnum(num,ch) + * + * Read digits from the console until we get a non-digit. This + * is used to process escape sequences like ESC [ digits ~ + * + * Input parameters: + * num - where to put returned number + * ch - pointer to character that starts sequence, returns + * character that terminated sequence + * + * Return value: + * nothing + ********************************************************************* */ + +static void console_readnum(int *num,char *ch) +{ + int total = 0; + + for (;;) { + total = (total * 10) + (*ch - '0'); + while (console_read(ch,1) != 1) { POLL(); } + if (!((*ch >= '0') && (*ch <= '9'))) break; + } + + *num = total; +} + + +/* ********************************************************************* + * console_readkey(void) + * + * Very simple ANSI escape sequence parser, returns virtual + * key codes for function keys, arrows, etc. + * + * Hold your lunch, three levels of nested switch statements! :-) + * + * Input parameters: + * nothing + * + * Return value: + * virtual key code + ********************************************************************* */ + +int console_readkey(void) +{ + unsigned char ch; + int num; + + GETCHAR(ch); + + switch (ch) { + case VKEY_ESC: + GETCHAR(ch); + switch (ch) { + case 'O': + GETCHAR(ch); + switch (ch) { + case 'P': + return VKEY_F1; + case 'Q': + return VKEY_F2; + case 'R': + return VKEY_F3; + case 'S': + return VKEY_F4; + } + return (int)ch; + + case '[': + GETCHAR(ch); + if ((ch >= '0') && (ch <= '9')) { + console_readnum(&num,&ch); + if (ch == '~') { + switch (num) { + case 2: + return VKEY_HOME; + case 3: + return VKEY_PGUP; + case 5: + if (console_mode == XTERM) return VKEY_PGUP; + return VKEY_END; + case 6: + if (console_mode == XTERM) return VKEY_PGDN; + return VKEY_PGDN; + case 11: + return VKEY_F1; + case 12: + return VKEY_F2; + case 13: + return VKEY_F3; + case 14: + return VKEY_F4; + case 15: + return VKEY_F5; + case 17: + return VKEY_F6; + case 18: + return VKEY_F7; + case 19: + return VKEY_F8; + case 20: + return VKEY_F9; + case 21: + return VKEY_F10; + case 23: + return VKEY_F11; + case 24: + return VKEY_F12; + } + return (int)ch; + } + } + else { + switch (ch) { + case 'A': + return VKEY_UP; + case 'B': + return VKEY_DOWN; + case 'C': + return VKEY_RIGHT; + case 'D': + return VKEY_LEFT; + case 'F': + return VKEY_HOME; + case 'H': + return VKEY_END; + default: + return (int) ch; + } + } + default: + return (int)ch; + + } + default: + return (int) ch; + } +} + + +/* ********************************************************************* + * console_xxx(...) + * + * Various small routines to write out cursor control sequences. + * + * Input parameters: + * # of iterations, if necessary + * + * Return value: + * nothing + ********************************************************************* */ + +static void console_backspace(int n) +{ + int t; + + for (t = 0; t < n; t++) console_write("\b",1); +} + +static void console_whiteout(int n) +{ + int t; + + for (t = 0; t < n; t++) console_write(" ",1); + for (t = 0; t < n; t++) console_write("\b",1); +} + + +static void console_eraseeol(void) +{ + console_write("\033[K",3); +} + +static void console_crlf(void) +{ + console_write("\r\n",2); +} + +/* ********************************************************************* + * console_readline(str,len) + * + * A simple 'gets' type routine for the console, with line + * editing support. + * + * Input parameters: + * prompt - prompt string + * str - pointer to user buffer + * len - length of user buffer + * + * Return value: + * number of characters read (terminating newline is not + * placed in the buffer) + ********************************************************************* */ + +int console_readline(char *prompt,char *str,int maxlen) +{ + int reading = 1; + int ch; + int idx = 0; + int len = 0; + int t; + int klen; + int recall; + int nosave = 0; + char *x; + char env[10]; + + console_inreadline++; + recall = console_nextsave; + + if (console_savedlines[console_nextsave]) { + KFREE(console_savedlines[console_nextsave]); + console_savedlines[console_nextsave] = NULL; + } + console_savedlines[console_nextsave] = strdup(""); + + if (prompt && *prompt) console_write(prompt,strlen(prompt)); + + POLL(); + while (reading) { + + /* + * If someone used console_log (above) or hit Control-C (below), + * redisplay the prompt and the string we've got so far. + */ + + if (console_redisplay) { + if (prompt && *prompt) console_write(prompt,strlen(prompt)); + console_write(str,idx); + console_redisplay = 0; + continue; + } + +#if defined(CONFIG_MIPS_BRCM) + + /* + * If a background process has set the global g_console_abort flag, stop + * reading from the keyboard. + */ + + if (g_console_abort) { + g_console_abort = 0; + break; + } + +#endif + + /* + * if nobody's typed anything, keep polling + */ + + if (console_status() == 0) { + POLL(); + continue; + } + + /* + * Get the char from the keyboard + */ + + ch = console_readkey(); + if (ch < 0) break; + if (ch == 0) continue; + + /* + * And dispatch it. Lots of yucky character manipulation follows + */ + + switch (ch) { + case CTRL('C'): /* Ctrl-C - cancel line */ + console_write("^C\r\n",4); + console_redisplay = 1; + nosave = 1; + idx = 0; + break; + + case 0x7f: /* Backspace, Delete */ + case CTRL('H'): + if (idx > 0) { + nosave = 0; + len--; + idx--; + console_write("\b",1); + if (len != idx) { + for (t = idx; t < len; t++) str[t] = str[t+1]; + console_write(&str[idx],len-idx); + console_whiteout(1); + console_backspace(len-idx); + } + else { + console_whiteout(1); + } + } + break; + + case CTRL('D'): /* Ctrl-D */ + if ((idx >= 0) && (len != idx)) { + nosave = 0; + len--; + for (t = idx; t < len; t++) str[t] = str[t+1]; + console_write(&str[idx],len-idx); + console_whiteout(1); + console_backspace(len-idx); + } + break; + + case CTRL('B'): /* cursor left */ + case VKEY_LEFT: + if (idx > 0) { + idx--; + console_backspace(1); + } + break; + + case CTRL('F'): /* cursor right */ + case VKEY_RIGHT: + if (idx < len) { + console_write(&str[idx],1); + idx++; + } + break; + + case CTRL('A'): /* cursor to BOL */ + console_backspace(idx); + idx = 0; + break; + + case CTRL('E'): /* cursor to EOL */ + if (len-idx > 0) console_write(&str[idx],len-idx); + idx = len; + break; + + case CTRL('K'): /* Kill to EOL */ + if (idx != len) { + str[len] = '\0'; + if (console_killbuffer) KFREE(console_killbuffer); + console_killbuffer = strdup(&str[idx]); + console_whiteout(len-idx); + len = idx; + nosave = 0; + } + break; + + case CTRL('Y'): /* Yank killed data */ + if (console_killbuffer == NULL) break; + klen = strlen(console_killbuffer); + if (klen == 0) break; + if (len + klen > maxlen) break; + nosave = 0; + for (t = len + klen; t > idx; t--) { + str[t-1] = str[t-klen-1]; + } + for (t = 0; t < klen; t++) str[t+idx] = console_killbuffer[t]; + len += klen; + console_write(&str[idx],len-idx); + idx += klen; + console_backspace(len-idx-1); + break; + + case CTRL('R'): /* Redisplay line */ + str[len] = 0; + console_crlf(); + console_write(prompt,strlen(prompt)); + console_write(str,len); + console_backspace(len-idx); + break; + + case CTRL('U'): /* Cancel line */ + console_backspace(idx); + console_eraseeol(); + if (len > 0) nosave = 1; + idx = 0; + len = 0; + break; + + case CTRL('M'): /* terminate */ + case CTRL('J'): + console_crlf(); + reading = 0; + break; + + case CTRL('P'): + case VKEY_UP: /* recall previous line */ + t = recall; + t--; + if (t < 0) t = MAXSAVELINES-1; + if (console_savedlines[t] == NULL) break; + recall = t; + console_backspace(idx); + strcpy(str,console_savedlines[recall]); + len = idx = strlen(console_savedlines[recall]); + console_eraseeol(); + console_write(str,len); + nosave = (t == ((console_nextsave - 1) % MAXSAVELINES)); + break; + + case CTRL('N'): + case VKEY_DOWN: /* Recall next line */ + t = recall; + t++; + if (t == MAXSAVELINES) t = 0; + if (console_savedlines[t] == NULL) break; + recall = t; + console_backspace(idx); + strcpy(str,console_savedlines[recall]); + len = idx = strlen(console_savedlines[recall]); + console_eraseeol(); + console_write(str,len); + nosave = 1; + break; + + case VKEY_F1: + case VKEY_F2: + case VKEY_F3: + case VKEY_F4: + case VKEY_F5: + case VKEY_F6: + case VKEY_F7: + case VKEY_F8: + case VKEY_F9: + case VKEY_F10: + case VKEY_F11: + case VKEY_F12: + sprintf(env,"F%d",ch-VKEY_F1+1); + x = env_getenv(env); + if (x) { + console_backspace(idx); + strcpy(str,x); + idx = len = strlen(str); + console_eraseeol(); + console_write(str,len); + console_crlf(); + reading = 0; + nosave = 1; + } + /* + * If F12 is undefined, it means "repeat last command" + */ + if (ch == VKEY_F12) { + t = recall; + t--; + if (t < 0) t = MAXSAVELINES-1; + if (console_savedlines[t] == NULL) break; + recall = t; + console_backspace(idx); + strcpy(str,console_savedlines[recall]); + len = idx = strlen(console_savedlines[recall]); + console_eraseeol(); + console_write(str,len); + console_crlf(); + reading = 0; + nosave = 1; + } + break; + + default: /* insert character */ + if (ch >= ' ') { + if (idx < (maxlen-1)) { + nosave = 0; + for (t = len; t > idx; t--) { + str[t] = str[t-1]; + } + str[idx] = ch; + len++; + if (len != idx) { + console_write(&str[idx],len-idx); + console_backspace(len-idx-1); + } + idx++; + } + } + break; + } + } + POLL(); + + console_inreadline--; + + str[len] = 0; + + if ((len != 0) && !nosave) { + if (console_savedlines[console_nextsave]) { + KFREE(console_savedlines[console_nextsave]); + } + console_savedlines[console_nextsave] = strdup(str); + console_nextsave++; + if (console_nextsave == MAXSAVELINES) console_nextsave = 0; + } + + return len; +} + +#else /* CFG_MINIMAL_SIZE */ +/* ********************************************************************* + * console_readline(str,len) + * + * A simple 'gets' type routine for the console, + * just calls the "noedit" variant for minimal code + * size builds. + * + * Input parameters: + * prompt - prompt string + * str - pointer to user buffer + * len - length of user buffer + * + * Return value: + * number of characters read (terminating newline is not + * placed in the buffer) + ********************************************************************* */ + +int console_readline(char *prompt,char *str,int len) +{ + return console_readline_noedit(prompt,str,len); +} + +#endif |