Add Linux's math64.h
[akaros.git] / kern / src / readline.c
1 #include <error.h>
2 #include <stdio.h>
3 #include <assert.h>
4 #include <atomic.h>
5
6 int readline(char *buf, size_t buf_l, const char *prompt, ...)
7 {
8         static spinlock_t readline_lock = SPINLOCK_INITIALIZER_IRQSAVE;
9         int i, c, echoing, retval;
10         va_list ap;
11
12         spin_lock_irqsave(&readline_lock);
13         va_start(ap, prompt);
14         if (prompt != NULL)
15                 vcprintf(prompt, ap);
16         va_end(ap);
17
18         i = 0;
19         echoing = iscons(0);
20         while (1) {
21                 c = getchar();
22                 if (c < 0) {
23                         printk("read error: %d\n", c);
24                         retval = i;
25                         break;
26                 } else if (c == '\b' || c == 0x7f) {
27                         if (i > 0) {
28                                 if (echoing)
29                                         cputchar(c);
30                                 i--;
31                         }
32                         continue;
33                 } else if (c == '\n' || c == '\r') {
34                         /* sending a \n regardless, since the serial port gives us a \r for
35                          * carriage returns. (probably won't get a \r anymore) */
36                         if (echoing)
37                                 cputchar('\n');
38                         assert(i <= buf_l - 1); /* never write to buf_l - 1 til the end */
39                         buf[i++] = c;
40                         retval =  i;
41                         break;
42                 } else if (c >= ' ' && i < buf_l - 1) {
43                         if (echoing)
44                                 cputchar(c);
45                         buf[i++] = c;
46                 }
47         }
48         spin_unlock_irqsave(&readline_lock);
49         return retval;
50 }
51