blob: 01a565a6982526cc7b97d81b8c0ae49d5a49e113 [file] [log] [blame]
Stefan Reinaueraddf4432008-08-19 17:48:02 +00001/*
2 * This file is part of the libpayload project.
3 *
4 * Copyright (C) 2008 coresystems GmbH
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 */
29
Uwe Hermann31538632008-08-31 22:10:35 +000030/**
31 * @file libc/readline.c
32 * Simple readline implementation
Jordan Crouse617120c2008-08-28 23:11:29 +000033 */
34
Stefan Reinaueraddf4432008-08-19 17:48:02 +000035#include <libpayload.h>
36
Uwe Hermann31538632008-08-31 22:10:35 +000037static char *readline_buffer;
Stefan Reinaueraddf4432008-08-19 17:48:02 +000038static int readline_bufferlen;
39
40/**
Uwe Hermann31538632008-08-31 22:10:35 +000041 * Read a line from the terminal and return it.
Jordan Crouse617120c2008-08-28 23:11:29 +000042 *
Uwe Hermann31538632008-08-31 22:10:35 +000043 * This readline implementation is rather simple, but it does more than the
44 * original readline() because it allows us to have a pre-filled buffer.
45 * To pre-fill the buffer, use the getline() function.
46 *
47 * @param prompt A prompt to display on the line.
48 * @return A pointer to the input string.
Stefan Reinaueraddf4432008-08-19 17:48:02 +000049 */
Uwe Hermann31538632008-08-31 22:10:35 +000050char *readline(const char *prompt)
Stefan Reinaueraddf4432008-08-19 17:48:02 +000051{
52 char *buffer;
53 int current, ch, nonspace_seen;
54
55 if (!readline_buffer || !readline_bufferlen) {
56#define READLINE_BUFFERSIZE 256
57 readline_buffer = malloc(READLINE_BUFFERSIZE);
58 readline_bufferlen = READLINE_BUFFERSIZE;
59 memset(readline_buffer, 0, readline_bufferlen);
60 }
61
62 buffer = readline_buffer;
Jordan Crouse617120c2008-08-28 23:11:29 +000063
Stefan Reinaueraddf4432008-08-19 17:48:02 +000064 /* print prompt */
65 if (prompt) {
66 current = 0;
67 while (prompt[current]) {
68 putchar(prompt[current]);
69 current++;
70 }
71 }
72
73 /* print existing buffer, if there is one */
74 current = 0;
75 while (buffer[current]) {
76 putchar(buffer[current]);
77 current++;
78 }
79
80 while (1) {
81 ch = getchar();
82 switch (ch) {
83 case '\r':
84 case '\n':
85 /* newline */
86 putchar('\n');
87 goto out;
88 case '\b':
89 case '\x7f':
90 /* backspace */
91 if (current > 0) {
92 putchar('\b');
93 putchar(' ');
94 putchar('\b');
95 current--;
96 }
97 break;
98 case 'W' & 0x1f: /* CTRL-W */
99 /* word erase */
100 nonspace_seen = 0;
101 while (current) {
102 if (buffer[current - 1] != ' ')
103 nonspace_seen = 1;
104 putchar('\b');
105 putchar(' ');
106 putchar('\b');
107 current--;
108 if (nonspace_seen && (current < readline_bufferlen - 1)
109 && (current > 0) && (buffer[current - 1] == ' '))
110 break;
111 }
112 break;
113 case 'U' & 0x1f: /* CTRL-U */
114 /* line erase */
115 while (current) {
116 putchar('\b');
117 putchar(' ');
118 putchar('\b');
119 current--;
120 }
121 current = 0;
122 break;
123 default:
124 /* all other characters */
125
126 /* ignore control characters */
127 if (ch < 0x20)
128 break;
129
130 /* ignore unprintables */
131 if (ch >= 0x7f)
132 break;
133
134 if (current + 1 < readline_bufferlen) {
135 /* print new character */
136 putchar(ch);
137 /* and add it to the array */
138 buffer[current] = ch;
139 current++;
140 }
141 }
142 }
143
Stefan Reinaueraddf4432008-08-19 17:48:02 +0000144out:
145 if (current >= readline_bufferlen)
146 current = readline_bufferlen - 1;
147 buffer[current] = '\0';
148
149 return buffer;
150}
151
Jordan Crouse617120c2008-08-28 23:11:29 +0000152/**
Uwe Hermann31538632008-08-31 22:10:35 +0000153 * Read a line from the input and store it in a buffer.
154 *
155 * This function allows the user to pass a predefined buffer to readline().
156 * The buffer may be filled with a default value which will be displayed by
157 * readline() and can be edited as normal.
158 * The final input string returned by readline() will be returned in
Jordan Crouse617120c2008-08-28 23:11:29 +0000159 * the buffer and the function will return the length of the string.
Uwe Hermann31538632008-08-31 22:10:35 +0000160 *
161 * @param buffer Pointer to a buffer to store the line in.
162 * @param len Length of the buffer.
163 * @return The final length of the string.
Jordan Crouse617120c2008-08-28 23:11:29 +0000164 */
Stefan Reinaueraddf4432008-08-19 17:48:02 +0000165int getline(char *buffer, int len)
166{
167 readline_buffer = buffer;
168 readline_bufferlen = len;
169 readline(NULL);
Uwe Hermann31538632008-08-31 22:10:35 +0000170
Stefan Reinaueraddf4432008-08-19 17:48:02 +0000171 return strlen(buffer);
172}