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

151 lines
3.8 KiB
C
Raw Normal View History

/*
* 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.
*/
#include <libpayload.h>
static char * readline_buffer;
static int readline_bufferlen;
/**
* 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;
}
int getline(char *buffer, int len)
{
readline_buffer = buffer;
readline_bufferlen = len;
readline(NULL);
return strlen(buffer);
}