Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


Further text-mode console client enhancements
[palacios.git] / linux_usr / v3_cons_tc.c
1 /* 
2  * V3 Console utility
3  * Taken from Palacios console display in MINIX ( by Erik Van der Kouwe )
4  * (c) Jack lange, 2010
5  * (c) Peter Dinda, 2011 (Scan code encoding)
6  */
7
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <sys/ioctl.h> 
12 #include <errno.h>
13 #include <assert.h>
14 #include <string.h>
15 #include <fcntl.h>
16 #include <unistd.h>
17 #include <curses.h>
18 #include <termios.h>
19 #include <linux/kd.h>
20 #include <linux/keyboard.h>
21
22 #include "v3_ctrl.h"
23 #include "termkey.h"
24
25 static int in_color = 0;
26 static int color8 = 0;
27 #define TRANS_STYLE(x) ( !color8 ? (x) : ((x)&0x7)|(((x)&0x70)>>1))
28
29 static int use_curses = 0;
30 static int debug_enable = 0;
31
32 static int ctrlc_count = 0;
33
34 #define VCONS_EXIT  2
35 #define VCONS_CTRLC 3
36
37 typedef enum { CONSOLE_CURS_SET = 1,
38                CONSOLE_CHAR_SET = 2,
39                CONSOLE_SCROLL = 3,
40                CONSOLE_UPDATE = 4,
41                CONSOLE_RESOLUTION = 5 } console_op_t;
42
43
44
45 static struct {
46     WINDOW * win;
47     int x;
48     int y;
49     int rows;
50     int cols;
51     struct termios termios_old;
52     unsigned char old_kbd_mode;
53 } console;
54
55 static TermKey * tk;
56
57
58 struct cursor_msg {
59     int x;
60     int y;
61 } __attribute__((packed));
62
63 struct character_msg {
64     int x;
65     int y;
66     char c;
67     unsigned char style;
68 } __attribute__((packed));
69
70 struct scroll_msg {
71     int lines;
72 } __attribute__((packed));
73
74 struct resolution_msg {
75     int cols;
76     int rows;
77 } __attribute__((packed));
78
79
80 struct cons_msg {
81     unsigned char op;
82     union {
83         struct cursor_msg cursor;
84         struct character_msg  character;
85         struct scroll_msg scroll;
86         struct resolution_msg resolution;
87     };
88 } __attribute__((packed)); 
89
90
91
92
93 static int handle_char_set(struct character_msg * msg) {
94     char c = msg->c;
95
96     if (debug_enable) {
97         fprintf(stderr, "setting char (%c), at (x=%d, y=%d)\n", c, msg->x, msg->y);
98     }
99
100     if (c == 0) {
101         c = ' ';
102     }
103
104
105     if ((c < ' ') || (c >= 127)) {
106         if (debug_enable) { 
107             fprintf(stderr, "unexpected control character %d\n", c);
108         }
109         c = '?';
110     }
111
112     if (use_curses) {
113         /* clip whatever falls outside the visible area to avoid errors */
114         if ((msg->x < 0) || (msg->y < 0) ||
115             (msg->x > console.win->_maxx) || 
116             (msg->y > console.win->_maxy)) {
117
118             if (debug_enable) { 
119                 fprintf(stderr, "Char out of range (x=%d,y=%d) MAX:(x=%d,y=%d)\n",
120                         msg->x, msg->y, console.win->_maxx, console.win->_maxy);
121             }
122
123             return -1;
124         }
125
126         if ((msg->x == console.win->_maxx) &&
127             (msg->y == console.win->_maxy)) {
128             return -1;
129         }
130
131         if (in_color) {wattron(console.win,  COLOR_PAIR(TRANS_STYLE(msg->style)));}
132         mvwaddch(console.win, msg->y, msg->x, c);
133         if (in_color) {wattroff(console.win, COLOR_PAIR(TRANS_STYLE(msg->style)));}
134
135     } else {
136         //stdout text display
137         while (console.y < msg->y) {
138             printf("\n");
139             console.x = 0;
140             console.y++;
141         }
142
143         while (console.x < msg->x) {
144             printf(" ");
145             console.x++;
146         }
147
148         printf("%c", c);
149         console.x++;
150
151         assert(console.x <= console.cols); 
152
153         if (console.x == console.cols) {
154             printf("\n");
155             console.x = 0;
156             console.y++;
157         }
158     }
159
160     return 0;
161 }
162
163 int handle_curs_set(struct cursor_msg * msg) {
164     if (debug_enable) {
165         fprintf(stderr, "cursor set: (x=%d, y=%d)\n", msg->x, msg->y);
166     }
167
168     if (use_curses) {
169         /* nothing to do now, cursor is set before update to make sure it isn't 
170          * affected by character_set
171          */
172
173         console.x = msg->x;
174         console.y = msg->y;
175     }
176     
177     return 0;
178 }
179
180
181 int handle_scroll(struct scroll_msg * msg) {
182     int lines = msg->lines;
183
184     if (debug_enable) {
185         fprintf(stderr, "scroll: %d lines\n", lines);
186     }
187
188
189     assert(lines >= 0);
190
191     if (use_curses) {
192         while (lines > 0) {
193             scroll(console.win);
194             lines--;
195         }
196     } else {
197         console.y -= lines;     
198     }
199 }
200
201 int handle_text_resolution(struct resolution_msg * msg) {
202     if (debug_enable) {
203         fprintf(stderr, "text resolution: rows=%d, cols=%d\n", msg->rows, msg->cols);
204     }
205
206
207     console.rows = msg->rows;
208     console.cols = msg->cols;
209
210     return 0;
211 }
212
213 int handle_update( void ) {
214     if (debug_enable) {
215         fprintf(stderr, "update\n");
216     }    
217
218     if (use_curses) {
219
220         if ( (console.x >= 0) && (console.y >= 0) &&
221              (console.x <= console.win->_maxx) &&
222              (console.y <= console.win->_maxy) ) {
223
224             wmove(console.win, console.y, console.x);
225
226         }
227
228         wrefresh(console.win);
229     } else {
230         fflush(stdout);
231     }
232 }
233
234
235 int handle_console_msg(int cons_fd) {
236     int ret = 0;
237     struct cons_msg msg;
238
239     ret = read(cons_fd, &msg, sizeof(struct cons_msg));
240
241     switch (msg.op) {
242         case CONSOLE_CURS_SET:
243             //      printf("Console cursor set (x=%d, y=%d)\n", msg.cursor.x, msg.cursor.y);
244             handle_curs_set(&(msg.cursor));
245             break;
246         case CONSOLE_CHAR_SET:
247             handle_char_set(&(msg.character));
248             /*      printf("Console character set (x=%d, y=%d, c=%c, style=%c)\n", 
249               msg.character.x, msg.character.y, msg.character.c, msg.character.style);*/
250             break;
251         case CONSOLE_SCROLL:
252             //  printf("Console scroll (lines=%d)\n", msg.scroll.lines);
253             handle_scroll(&(msg.scroll));
254             break;
255         case CONSOLE_UPDATE:
256             // printf("Console update\n");
257             handle_update();
258             break;
259         case CONSOLE_RESOLUTION:
260             handle_text_resolution(&(msg.resolution));
261             break;
262         default:
263             printf("Invalid console message operation (%d)\n", msg.op);
264             break;
265     }
266
267     return 0;
268 }
269
270
271
272 void handle_exit(void) {
273     if ( debug_enable ) {
274         fprintf(stderr, "Exiting from console terminal\n");
275     }
276
277     if (use_curses) {
278         endwin();
279     }
280
281     termkey_destroy(tk);
282     //    tcsetattr(STDIN_FILENO, TCSANOW, &console.termios_old);
283
284     // ioctl(STDIN_FILENO, KDSKBMODE, K_XLATE);
285 }
286
287
288 #define NO_KEY { 0, 0 }
289
290 struct key_code {
291     unsigned char scan_code;
292     unsigned char capital;
293 };
294
295 static const struct key_code ascii_to_key_code[] = {             // ASCII Value Serves as Index
296     NO_KEY,         NO_KEY,         {0x50, 0},         {0x48, 0},      // 0x00 - 0x03
297     {0x4B, 0},         {0x4D, 0},         NO_KEY,         { 0x0E, 0 }, // 0x04 - 0x07
298     { 0x0E, 0 },    { 0x0F, 0 },    { 0x1C, 0 },    NO_KEY,      // 0x08 - 0x0B
299     NO_KEY,         { 0x1C, 0 },    NO_KEY,         NO_KEY,      // 0x0C - 0x0F
300     NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x10 - 0x13
301     NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x14 - 0x17
302     NO_KEY,         NO_KEY,         NO_KEY,         { 0x01, 0 }, // 0x18 - 0x1B
303     NO_KEY,         NO_KEY,         NO_KEY,         NO_KEY,      // 0x1C - 0x1F
304     { 0x39, 0 },    { 0x02, 1 },    { 0x28, 1 },    { 0x04, 1 }, // 0x20 - 0x23
305     { 0x05, 1 },    { 0x06, 1 },    { 0x08, 1 },    { 0x28, 0 }, // 0x24 - 0x27
306     { 0x0A, 1 },    { 0x0B, 1 },    { 0x09, 1 },    { 0x0D, 1 }, // 0x28 - 0x2B
307     { 0x33, 0 },    { 0x0C, 0 },    { 0x34, 0 },    { 0x35, 0 }, // 0x2C - 0x2F
308     { 0x0B, 0 },    { 0x02, 0 },    { 0x03, 0 },    { 0x04, 0 }, // 0x30 - 0x33
309     { 0x05, 0 },    { 0x06, 0 },    { 0x07, 0 },    { 0x08, 0 }, // 0x34 - 0x37
310     { 0x09, 0 },    { 0x0A, 0 },    { 0x27, 1 },    { 0x27, 0 }, // 0x38 - 0x3B
311     { 0x33, 1 },    { 0x0D, 0 },    { 0x34, 1 },    { 0x35, 1 }, // 0x3C - 0x3F
312     { 0x03, 1 },    { 0x1E, 1 },    { 0x30, 1 },    { 0x2E, 1 }, // 0x40 - 0x43
313     { 0x20, 1 },    { 0x12, 1 },    { 0x21, 1 },    { 0x22, 1 }, // 0x44 - 0x47
314     { 0x23, 1 },    { 0x17, 1 },    { 0x24, 1 },    { 0x25, 1 }, // 0x48 - 0x4B
315     { 0x26, 1 },    { 0x32, 1 },    { 0x31, 1 },    { 0x18, 1 }, // 0x4C - 0x4F
316     { 0x19, 1 },    { 0x10, 1 },    { 0x13, 1 },    { 0x1F, 1 }, // 0x50 - 0x53
317     { 0x14, 1 },    { 0x16, 1 },    { 0x2F, 1 },    { 0x11, 1 }, // 0x54 - 0x57
318     { 0x2D, 1 },    { 0x15, 1 },    { 0x2C, 1 },    { 0x1A, 0 }, // 0x58 - 0x5B
319     { 0x2B, 0 },    { 0x1B, 0 },    { 0x07, 1 },    { 0x0C, 1 }, // 0x5C - 0x5F
320     { 0x29, 0 },    { 0x1E, 0 },    { 0x30, 0 },    { 0x2E, 0 }, // 0x60 - 0x63
321     { 0x20, 0 },    { 0x12, 0 },    { 0x21, 0 },    { 0x22, 0 }, // 0x64 - 0x67
322     { 0x23, 0 },    { 0x17, 0 },    { 0x24, 0 },    { 0x25, 0 }, // 0x68 - 0x6B
323     { 0x26, 0 },    { 0x32, 0 },    { 0x31, 0 },    { 0x18, 0 }, // 0x6C - 0x6F
324     { 0x19, 0 },    { 0x10, 0 },    { 0x13, 0 },    { 0x1F, 0 }, // 0x70 - 0x73
325     { 0x14, 0 },    { 0x16, 0 },    { 0x2F, 0 },    { 0x11, 0 }, // 0x74 - 0x77
326     { 0x2D, 0 },    { 0x15, 0 },    { 0x2C, 0 },    { 0x1A, 1 }, // 0x78 - 0x7B
327     { 0x2B, 1 },    { 0x1B, 1 },    { 0x29, 1 },    { 0x0E, 0 }  // 0x7C - 0x7F
328 };
329
330
331
332 #define writeit(fd,c)  do { if (debug_enable) { fprintf(stderr,"scancode 0x%x\n",(c));} if (write((fd),&(c),1)!=1) { return -1; } } while (0)
333
334
335 int send_scancode_group_to_palacios(int fd, TermKeyKey * kc, struct key_code *k)
336 {
337   unsigned char sc;
338
339   if (kc->modifiers & TERMKEY_KEYMOD_CTRL) {
340     // left ctrl down
341     sc = 0x1d;
342     writeit(fd, sc);
343   }
344
345   if (kc->modifiers & TERMKEY_KEYMOD_ALT) {
346     // left alt down
347     sc = 0x38;
348     writeit(fd, sc);
349   }
350
351   if (k->capital) { 
352     // left shift down
353     sc = 0x2a ; 
354     writeit(fd,sc);
355   }
356
357   sc = k->scan_code;
358   
359   writeit(fd,sc);  // key down
360
361   sc |= 0x80;      // key up
362
363   writeit(fd,sc);
364
365   if (k->capital) { 
366     // left shift up
367     sc = 0x2a | 0x80;
368     writeit(fd,sc);
369   }
370   
371   if (kc->modifiers & TERMKEY_KEYMOD_CTRL) {
372     // left ctrl up
373     sc = 0x1d | 0x80;   
374     writeit(fd,sc);
375   }
376   
377   if (kc->modifiers & TERMKEY_KEYMOD_ALT) {
378     // left alt up
379     sc = 0x38 | 0x80; 
380     writeit(fd, sc);
381   }
382
383   return 0;
384 }
385
386 int handle_key(int fd, TermKeyKey * kc)
387 {
388     unsigned char sc;
389
390     if (debug_enable) {
391         fprintf(stderr,"key '%c'\n",kc->code.number);
392     }
393
394
395     if (kc->code.number<0x80) { 
396         struct key_code k = ascii_to_key_code[kc->code.number];
397
398         if (k.scan_code==0 && k.capital==0) { 
399             if (debug_enable) { 
400                 fprintf(stderr,"Cannot send key '%c' to palacios as it maps to no scancode\n",kc->code.number);
401             }
402             return 0;
403         } else {
404           return send_scancode_group_to_palacios(fd,kc,&k);
405         }
406     } else {
407         if (debug_enable) { 
408             fprintf(stderr,"Cannot send key '%c' to palacios because it is >=0x80\n",kc->code.number);
409         }
410         return 0;
411     }
412 }
413
414
415 static int handle_fnkey (int fd, TermKeyKey * kc) {
416
417     unsigned char sc;
418
419     switch (kc->code.number) {
420         case 0x1:
421             sc = 0x3b;
422             break;
423         case 0x2:
424             sc = 0x3c;
425             break;
426         case 0x3:
427             sc = 0x3d;
428             break;
429         case 0x4:
430             sc = 0x3e;
431             break;
432         case 0x5:
433             sc = 0x3f;
434             break;
435         case 0x6:
436             sc = 0x40;
437             break;
438         case 0x7:
439             sc = 0x41;
440             break;
441         case 0x8:
442             sc = 0x42;
443             break;
444         case 0x9:
445             sc = 0x43;
446             break;
447         case 0xa:
448             sc = 0x44;
449             break;
450         case 0xb:
451             sc = 0x57;
452             break;
453         case 0xc:
454             sc = 0x58;
455             break;
456         default:
457             fprintf(stderr, "Unknown function key <%x>\n", kc->code.number);
458             break;
459     }
460
461     struct key_code k = { sc,  kc->modifiers & TERMKEY_KEYMOD_SHIFT };
462
463     return send_scancode_group_to_palacios(fd,kc,&k);
464
465 }
466
467 static int handle_symkey (int fd, TermKeyKey * kc) {
468     unsigned char sc;
469
470     switch (kc->code.sym) {
471         case TERMKEY_SYM_BACKSPACE:
472             sc = 0xe;
473             break;
474         case TERMKEY_SYM_TAB:
475             sc = 0xf;
476             break;
477         case TERMKEY_SYM_ENTER:
478             sc = 0x1c;
479             break;
480         case TERMKEY_SYM_ESCAPE:
481             sc = 0x1;
482             break;
483         case TERMKEY_SYM_SPACE:
484             sc = 0x39;
485             break;
486         case TERMKEY_SYM_INSERT:
487             sc = 0x52;
488             break;
489         case TERMKEY_SYM_DEL:
490             sc = 0x53;
491             break;
492         case TERMKEY_SYM_UP:
493             sc = 0x48;
494             break;
495         case TERMKEY_SYM_DOWN:
496             sc = 0x50;
497             break;
498         case TERMKEY_SYM_LEFT:
499             sc = 0x4b;
500             break;
501         case TERMKEY_SYM_RIGHT:
502             sc = 0x4d;
503             break;
504         case TERMKEY_SYM_PAGEUP:
505             sc = 0x49;
506             break;
507         case TERMKEY_SYM_PAGEDOWN:
508             sc = 0x51;
509             break;
510         case TERMKEY_SYM_HOME:
511             sc = 0x47;
512             break;
513         case TERMKEY_SYM_END:
514             sc = 0x4f;
515             break;
516         case TERMKEY_SYM_KP0:
517             sc = 0x70;
518             break;
519         case TERMKEY_SYM_KP1:
520             sc = 0x69;
521             break;
522         case TERMKEY_SYM_KP2:
523             sc = 0x72;
524             break;
525         case TERMKEY_SYM_KP3:
526             sc = 0x7a;
527             break;
528         case TERMKEY_SYM_KP4:
529             sc = 0x6b;
530             break;
531         case TERMKEY_SYM_KP5:
532             sc = 0x73;
533             break;
534         case TERMKEY_SYM_KP6:
535             sc = 0x74;
536             break;
537         case TERMKEY_SYM_KP7:
538             sc = 0x6c;
539             break;
540         case TERMKEY_SYM_KP8:
541             sc = 0x75;
542             break;
543         case TERMKEY_SYM_KP9:
544             sc = 0x7d;
545             break;
546         case TERMKEY_SYM_KPENTER:
547             sc = 0x5a;
548             break;
549         case TERMKEY_SYM_KPPLUS:
550             sc = 0x79;
551             break;
552         case TERMKEY_SYM_KPMINUS:
553             sc = 0x7b;
554             break;
555         case TERMKEY_SYM_KPMULT:
556             sc = 0x7c;
557             break;
558         case TERMKEY_SYM_KPDIV:
559             sc = 0x4a;
560             break;
561         default:
562             fprintf(stderr, "Unknown sym key\n");
563             return -1;
564     }
565     
566
567     struct key_code k = { sc,  kc->modifiers & TERMKEY_KEYMOD_SHIFT };
568
569     return send_scancode_group_to_palacios(fd,kc,&k);
570
571
572 }
573
574
575 #define MIN_TTY_COLS  80
576 #define MIN_TTY_ROWS  25
577 int check_terminal_size (void)
578 {
579     unsigned short n_cols = 0;
580     unsigned short n_rows = 0;
581     struct winsize winsz; 
582
583     ioctl (fileno(stdin), TIOCGWINSZ, &winsz);
584     n_cols = winsz.ws_col;
585     n_rows = winsz.ws_row;
586
587     if (n_cols < MIN_TTY_COLS || n_rows < MIN_TTY_ROWS) {
588         printf ("Your window is not large enough.\n");
589         printf ("It must be at least %dx%d, but yours is %dx%d\n",
590                 MIN_TTY_COLS, MIN_TTY_ROWS, n_cols, n_rows);
591     return (-1);
592     }
593
594     /* SUCCESS */
595     return (0);
596 }
597
598
599
600 static void
601 init_colors (void)
602 {
603     unsigned short i;
604
605     if (!has_colors()) {
606       fprintf(stderr,"No color support\n");
607       in_color=0;
608       color8=0;
609       return;
610     }
611     
612     start_color();
613
614     if (can_change_color() && COLORS>=16 && COLOR_PAIRS>=256) {
615       fprintf(stderr, "Modifyable color support with enough colors available\n");
616       // initialize first 16 colors to be the PC colors
617       // then create all the pairings
618       for (i=0;i<16;i++) {
619         unsigned short red, green, blue, intens;
620         // i = IRGB (4 bits)
621         intens = i>>3 & 0x1;
622         red = i>>2 & 0x1;
623         green = i>>1 & 0x1;
624         blue = i>>0 & 0x1;
625         init_color(i, 500*(red+intens), 500*(blue+intens), 500*(green+intens));
626       }
627       for (i=0;i<256;i++) {
628         init_pair(i, i & 0xf, (i >> 4) & 0xf);
629       }
630       in_color = 1;
631       color8 = 0;
632       return;
633     } else {
634       if (COLORS!=8 || COLOR_PAIRS<64) {
635         fprintf(stderr,"Insufficient number of fixed colors (%d) or color pairs (%d)\n",COLORS,COLOR_PAIRS);
636         in_color = 0;
637         color8 = 0;
638         return;
639       } 
640       // We have only the low-intensity colors available, so
641       // map just to these
642       fprintf(stderr,"Only 8 color standard palette available\n");
643       for (i=0;i<64;i++) {
644         // VGA color order:     black, blue, green, cyan, red, magenta, brown, gray
645         // curses color order:  black, red, green, yellow, blue, magenta, cyan, white
646         short map[] = { 0, 4, 2, 6, 1, 5, 3, 7 };
647         unsigned short fg, bg;
648         // discard intensity bit
649         bg = (i>>3 & 0x7);
650         fg = i & 0x7; 
651         init_pair(i, map[fg], map[bg]);
652       }
653       in_color = 1;
654       color8 = 1;
655       return;
656     }
657 }
658
659
660 int main(int argc, char* argv[]) {
661     int vm_fd;
662     int cons_fd;
663     int mouse = 0;
664     int mouse_proto = 0;
665     char buffer[50];
666     char * vm_dev = NULL;
667     struct termios termios;
668     TERMKEY_CHECK_VERSION;
669     TermKeyFormat format = TERMKEY_FORMAT_VIM;
670     tk = termkey_new(0, TERMKEY_FLAG_SPACESYMBOL|TERMKEY_FLAG_CTRLC);
671
672     if (!tk) {
673         fprintf(stderr, "Could not allocate termkey instance\n");
674         exit(EXIT_FAILURE);
675     }
676
677     if (termkey_get_flags(tk) & TERMKEY_FLAG_UTF8) {
678         if (debug_enable) {
679             printf("Termkey in UTF-8 mode\n");
680         }
681     } else if (termkey_get_flags(tk) & TERMKEY_FLAG_RAW) {
682         if (debug_enable) {
683             printf("Termkey in RAW mode\n");
684         }
685     }
686
687     TermKeyResult ret;
688     TermKeyKey key;
689
690     if(mouse) {
691         printf("\033[?%dhMouse mode active\n", mouse);
692         if(mouse_proto)
693             printf("\033[?%dh", mouse_proto);
694     }
695
696     use_curses = 1;
697
698     if (argc < 2) {
699         printf("usage: v3_cons_tc <vm_device>\n\n"
700                "NOTE: to exit the terminal, use CTRL-ALT-\\\n\n");
701         goto exit_err;
702     }
703
704     /* Check for minimum Terminal size at start */
705     if (0 != check_terminal_size()) {
706         printf ("Error: terminal too small!\n");
707         goto exit_err;
708     }
709
710     vm_dev = argv[1];
711
712     vm_fd = open(vm_dev, O_RDONLY);
713
714     if (vm_fd == -1) {
715         printf("Error opening VM device: %s\n", vm_dev);
716         goto exit_err;
717     }
718
719     cons_fd = ioctl(vm_fd, V3_VM_CONSOLE_CONNECT, NULL); 
720
721     /* Close the file descriptor.  */ 
722     close(vm_fd); 
723
724     if (cons_fd < 0) {
725         printf("Error opening stream Console\n");
726         goto exit_err;
727     }
728
729     atexit(handle_exit);
730
731     console.x = 0;
732     console.y = 0;
733
734
735     if (use_curses) {
736
737         gettmode();
738         console.win = initscr();
739
740         if (console.win == NULL) {
741             fprintf(stderr, "Error initialization curses screen\n");
742             exit(-1);
743         }
744
745         scrollok(console.win, 1);
746
747         erase();
748         init_colors();
749     }
750
751
752     raw();
753     noecho();
754     keypad(console.win, TRUE);
755
756
757     while (1) {
758
759         int ret; 
760         int bytes_read = 0;
761         fd_set rset;
762
763         FD_ZERO(&rset);
764         FD_SET(cons_fd, &rset);
765         FD_SET(STDIN_FILENO, &rset);
766
767         ret = select(cons_fd + 1, &rset, NULL, NULL, NULL);
768
769         if (ret == 0) {
770             continue;
771         } else if (ret == -1) {
772             perror("Select returned error...\n");
773             return -1;
774         }
775
776         if (FD_ISSET(cons_fd, &rset)) {
777             if (handle_console_msg(cons_fd) == -1) {
778                 printf("Console Error\n");
779                 return -1;
780             }
781         }
782
783         if (FD_ISSET(STDIN_FILENO, &rset)) {
784
785             ret = termkey_waitkey(tk, &key);
786
787             if(ret == TERMKEY_RES_KEY) {
788
789                 termkey_strfkey(tk, buffer, sizeof buffer, &key, format);
790
791                 switch (key.type) {
792
793                     case TERMKEY_TYPE_UNICODE: {
794                       // should we quit ?
795                       if (key.code.number == '\\' && 
796                           key.modifiers & TERMKEY_KEYMOD_CTRL && 
797                           key.modifiers & TERMKEY_KEYMOD_ALT) {
798                         exit(1);
799                       } else {
800                         int ret = handle_key(cons_fd, &key);
801                         
802                         if (ret < 0) {
803                           printf("Error sending key to console\n");
804                           return -1;
805                         } 
806                       }
807                            break;
808                                                }
809                     case TERMKEY_TYPE_FUNCTION:
810                            handle_fnkey(cons_fd, &key);
811                            break;
812                     case TERMKEY_TYPE_KEYSYM:
813                            handle_symkey(cons_fd, &key);
814                            break;
815                     default:
816                            fprintf(stderr, "Unknown key type\n");
817                 }
818             }
819
820         }
821     }
822
823     erase();
824
825     printf("Console terminated\n");
826
827     close(cons_fd);
828
829     return 0; 
830
831 exit_err:
832     termkey_destroy(tk);
833     return -1;
834 }
835
836