7fc10511a961e8d8626dbd21d8ccb024ba5e0eb0
[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
35                          * us a \r for carriage returns. (probably won't get a
36                          * \r anymore) */
37                         if (echoing)
38                                 cputchar('\n');
39                         assert(i <= buf_l - 1);
40                         /* never write to buf_l - 1 til the end */
41                         buf[i++] = c;
42                         retval =  i;
43                         break;
44                 } else if (c >= ' ' && i < buf_l - 1) {
45                         if (echoing)
46                                 cputchar(c);
47                         buf[i++] = c;
48                 }
49         }
50         spin_unlock_irqsave(&readline_lock);
51         return retval;
52 }
53