173 lines
4.6 KiB
C
173 lines
4.6 KiB
C
/*
|
|
* This file is part of the libpayload project.
|
|
*
|
|
* Copyright (C) 2008 coresystems GmbH
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
* FOR ANY 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) ARISING IN ANY WAY
|
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
* SUCH DAMAGE.
|
|
*/
|
|
|
|
/** @file libc/readline.c
|
|
* @brief Simple readline implementation
|
|
*/
|
|
|
|
#include <libpayload.h>
|
|
|
|
static char * readline_buffer;
|
|
static int readline_bufferlen;
|
|
|
|
/**
|
|
* @brief Read a line from the terminal and return it
|
|
* @param prompt A prompt to display on the line
|
|
* @return A pointer to the input string
|
|
*
|
|
* Read a line from the terminal and return it. This readline implementation
|
|
* is rather simple, but it does more than the original readline() because
|
|
* it allows us to have a pre-filled buffer. To pre-fill the buffer, use the
|
|
* getline() function.
|
|
*/
|
|
|
|
char * readline(const char * prompt)
|
|
{
|
|
char *buffer;
|
|
int current, ch, nonspace_seen;
|
|
|
|
if (!readline_buffer || !readline_bufferlen) {
|
|
#define READLINE_BUFFERSIZE 256
|
|
readline_buffer = malloc(READLINE_BUFFERSIZE);
|
|
readline_bufferlen = READLINE_BUFFERSIZE;
|
|
memset(readline_buffer, 0, readline_bufferlen);
|
|
}
|
|
|
|
buffer = readline_buffer;
|
|
|
|
/* print prompt */
|
|
if (prompt) {
|
|
current = 0;
|
|
while (prompt[current]) {
|
|
putchar(prompt[current]);
|
|
current++;
|
|
}
|
|
}
|
|
|
|
/* print existing buffer, if there is one */
|
|
current = 0;
|
|
while (buffer[current]) {
|
|
putchar(buffer[current]);
|
|
current++;
|
|
}
|
|
|
|
while (1) {
|
|
ch = getchar();
|
|
switch (ch) {
|
|
case '\r':
|
|
case '\n':
|
|
/* newline */
|
|
putchar('\n');
|
|
goto out;
|
|
case '\b':
|
|
case '\x7f':
|
|
/* backspace */
|
|
if (current > 0) {
|
|
putchar('\b');
|
|
putchar(' ');
|
|
putchar('\b');
|
|
current--;
|
|
}
|
|
break;
|
|
case 'W' & 0x1f: /* CTRL-W */
|
|
/* word erase */
|
|
nonspace_seen = 0;
|
|
while (current) {
|
|
if (buffer[current - 1] != ' ')
|
|
nonspace_seen = 1;
|
|
putchar('\b');
|
|
putchar(' ');
|
|
putchar('\b');
|
|
current--;
|
|
if (nonspace_seen && (current < readline_bufferlen - 1)
|
|
&& (current > 0) && (buffer[current - 1] == ' '))
|
|
break;
|
|
}
|
|
break;
|
|
case 'U' & 0x1f: /* CTRL-U */
|
|
/* line erase */
|
|
while (current) {
|
|
putchar('\b');
|
|
putchar(' ');
|
|
putchar('\b');
|
|
current--;
|
|
}
|
|
current = 0;
|
|
break;
|
|
default:
|
|
/* all other characters */
|
|
|
|
/* ignore control characters */
|
|
if (ch < 0x20)
|
|
break;
|
|
|
|
/* ignore unprintables */
|
|
if (ch >= 0x7f)
|
|
break;
|
|
|
|
if (current + 1 < readline_bufferlen) {
|
|
/* print new character */
|
|
putchar(ch);
|
|
/* and add it to the array */
|
|
buffer[current] = ch;
|
|
current++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
out:
|
|
if (current >= readline_bufferlen)
|
|
current = readline_bufferlen - 1;
|
|
buffer[current] = '\0';
|
|
|
|
return buffer;
|
|
}
|
|
|
|
/**
|
|
* @brief Read a line from the input and store it in a buffer
|
|
* @param prompt A buffer to store the line in
|
|
* @param len Length of the buffer
|
|
* @return The final length of the string
|
|
* This function allows the user to pass a predefined buffer to
|
|
* readline(). The buffer may be filled with a default value
|
|
* which will be displayed by readline and can be edited as normal.
|
|
* The final input string returned by readline will be returned in
|
|
* the buffer and the function will return the length of the string.
|
|
*/
|
|
|
|
int getline(char *buffer, int len)
|
|
{
|
|
readline_buffer = buffer;
|
|
readline_bufferlen = len;
|
|
readline(NULL);
|
|
return strlen(buffer);
|
|
}
|
|
|