diff options
Diffstat (limited to 'payloads/libpayload/libc/readline.c')
-rw-r--r-- | payloads/libpayload/libc/readline.c | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/payloads/libpayload/libc/readline.c b/payloads/libpayload/libc/readline.c new file mode 100644 index 0000000000..9c6a6a651d --- /dev/null +++ b/payloads/libpayload/libc/readline.c @@ -0,0 +1,150 @@ +/* + * 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); +} + |