coreboot-kgpe-d16/payloads/libpayload/libc/readline.c

173 lines
4.5 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
* Simple readline implementation
*/
#include <libpayload.h>
static char *readline_buffer;
static int readline_bufferlen;
/**
* 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.
*
* @param prompt A prompt to display on the line.
* @return A pointer to the input string.
*/
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;
}
/**
* Read a line from the input and store it in a buffer.
*
* 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.
*
* @param buffer Pointer to a buffer to store the line in.
* @param len Length of the buffer.
* @return The final length of the string.
*/
int getline(char *buffer, int len)
{
readline_buffer = buffer;
readline_bufferlen = len;
readline(NULL);
return strlen(buffer);
}