blob: 7fc10511a961e8d8626dbd21d8ccb024ba5e0eb0 [file] [log] [blame]
#include <error.h>
#include <stdio.h>
#include <assert.h>
#include <atomic.h>
int readline(char *buf, size_t buf_l, const char *prompt, ...)
{
static spinlock_t readline_lock = SPINLOCK_INITIALIZER_IRQSAVE;
int i, c, echoing, retval;
va_list ap;
spin_lock_irqsave(&readline_lock);
va_start(ap, prompt);
if (prompt != NULL)
vcprintf(prompt, ap);
va_end(ap);
i = 0;
echoing = iscons(0);
while (1) {
c = getchar();
if (c < 0) {
printk("read error: %d\n", c);
retval = i;
break;
} else if (c == '\b' || c == 0x7f) {
if (i > 0) {
if (echoing)
cputchar(c);
i--;
}
continue;
} else if (c == '\n' || c == '\r') {
/* sending a \n regardless, since the serial port gives
* us a \r for carriage returns. (probably won't get a
* \r anymore) */
if (echoing)
cputchar('\n');
assert(i <= buf_l - 1);
/* never write to buf_l - 1 til the end */
buf[i++] = c;
retval = i;
break;
} else if (c >= ' ' && i < buf_l - 1) {
if (echoing)
cputchar(c);
buf[i++] = c;
}
}
spin_unlock_irqsave(&readline_lock);
return retval;
}