1 #include <rfb/keysym.h>
2 #include "VNConsole.h"
3 #include "vga.h"
4 #include <fcntl.h>
5 #include <sys/ioctl.h>
6 
7 static int tty=2;
8 static int tty_inject_device;
9 
do_key(rfbBool down,rfbKeySym keySym,rfbClientPtr cl)10 void do_key(rfbBool down,rfbKeySym keySym,rfbClientPtr cl)
11 {
12   static char isControl=0;
13 
14   if(down) {
15     /* if(keySym==XK_Escape)
16       rfbCloseClient(cl);
17     else */ if(keySym==XK_Control_L || keySym==XK_Control_R)
18       isControl++;
19     else if(tty_inject_device>=0) {
20       if(keySym==XK_Escape)
21 	keySym=27;
22       if(isControl) {
23 	if(keySym>='a' && keySym<='z')
24 	  keySym-='a'-1;
25 	else if(keySym>='A' && keySym<='Z')
26 	  keySym-='A'-1;
27 	else
28 	  keySym=0xffff;
29       }
30 
31       if(keySym==XK_Tab)
32 	keySym='\t';
33       else if(keySym==XK_Return)
34 	keySym='\r';
35       else if(keySym==XK_BackSpace)
36 	keySym=8;
37       else if(keySym==XK_Home || keySym==XK_KP_Home)
38 	keySym=1;
39       else if(keySym==XK_End || keySym==XK_KP_End)
40 	keySym=5;
41       else if(keySym==XK_Up || keySym==XK_KP_Up)
42 	keySym=16;
43       else if(keySym==XK_Down || keySym==XK_KP_Down)
44 	keySym=14;
45       else if(keySym==XK_Right || keySym==XK_KP_Right)
46 	keySym=6;
47       else if(keySym==XK_Left || keySym==XK_KP_Left)
48 	keySym=2;
49 
50       if(keySym<0x100) {
51 	int ret;
52 	ret=ioctl(tty_inject_device,TIOCSTI,&keySym);
53 	if(ret<0) {
54 	  static char device[64];
55 	  close(tty_inject_device);
56 	  sprintf(device,"/dev/tty%d",tty);
57 	  tty_inject_device=open(device,O_WRONLY);
58 	  ret=ioctl(tty_inject_device,TIOCSTI,&keySym);
59 	  if(ret<0)
60 	    rfbErr("Couldn't reopen device %s!\n",device);
61 	}
62       }
63     }
64   } else if(keySym==XK_Control_L || keySym==XK_Control_R)
65     if(isControl>0)
66       isControl--;
67 }
68 
69 /* these colours are from linux kernel drivers/char/console.c */
70 unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
71 				       8,12,10,14, 9,13,11,15 };
72 /* the default colour table, for VGA+ colour systems */
73 int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
74     0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
75 int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
76     0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
77 int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
78     0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
79 
main(int argc,char ** argv)80 int main(int argc,char **argv)
81 {
82   int width=80,height=25;
83   char *buffer;
84   vncConsolePtr console;
85   char tty_device[64],title[128];
86   int i;
87   FILE* tty_file;
88   struct winsize dimensions;
89 
90   if(argc>1) {
91     if((tty=atoi(argv[1]))<1) {
92       rfbErr("Usage: %s [tty_number [vnc args]]\n",argv[0]);
93       exit(1);
94     } else {
95       argv++;
96       argc--;
97     }
98   }
99 
100   /* getopt goes here! */
101 
102   sprintf(tty_device,"/dev/tty%d",tty);
103   if((tty_inject_device=open(tty_device,O_WRONLY))<0) {
104     rfbErr("Couldn't open tty device %s!\n",tty_device);
105     exit(1);
106   }
107   rfbLog("Using device %s.\n",tty_device);
108 
109   if(ioctl(tty_inject_device,TIOCGWINSZ,&dimensions)>=0) {
110     width=dimensions.ws_col;
111     height=dimensions.ws_row;
112   }
113 
114   sprintf(title,"LinuxVNC: /dev/tty%d",tty);
115 
116   /* console init */
117   if(!(console=vcGetConsole(&argc,argv,width,height,&vgaFont,TRUE)))
118     exit(1);
119 
120   for(i=0;i<16;i++) {
121     console->screen->colourMap.data.bytes[i*3+0]=default_red[color_table[i]];
122     console->screen->colourMap.data.bytes[i*3+1]=default_grn[color_table[i]];
123     console->screen->colourMap.data.bytes[i*3+2]=default_blu[color_table[i]];
124   }
125   console->screen->desktopName=title;
126   console->screen->kbdAddEvent=do_key;
127   console->selectTimeOut=100000;
128   console->wrapBottomToTop=TRUE;
129 #ifdef USE_OLD_VCS
130   buffer=malloc(width*height);
131   console->cursorActive=FALSE;
132 #else
133   buffer=malloc(width*height*2+4);
134   console->cursorActive=TRUE;
135 #endif
136   /* memcpy(buffer,console->screenBuffer,width*height); */
137 
138 #ifdef USE_OLD_VCS
139   sprintf(tty_device,"/dev/vcs%d",tty);
140 #else
141   sprintf(tty_device,"/dev/vcsa%d",tty);
142 #endif
143 
144   while(rfbIsActive(console->screen)) {
145     if(!console->currentlyMarking) {
146       tty_file=fopen(tty_device,"rb");
147       if(!tty_file) {
148 	rfbErr("cannot open device \"%s\"\n",
149 		tty_device);
150 	exit(1);
151       }
152 #ifdef USE_OLD_VCS
153       fread(buffer,width,height,tty_file);
154 #else
155       fread(buffer,width*height*2+4,1,tty_file);
156       vcHideCursor(console);
157 #endif
158       fclose(tty_file);
159 
160       for(i=0;i<console->width*console->height;i++) {
161 	if
162 #ifdef USE_OLD_VCS
163 	 (buffer[i]!=console->screenBuffer[i])
164 #else
165 	 (buffer[4+2*i]!=console->screenBuffer[i] ||
166 	  buffer[5+2*i]!=console->attributeBuffer[i])
167 #endif
168 	  {
169 	    console->x=(i%console->width);
170 	    console->y=(i/console->width);
171 	    /*
172 	      rfbLog("changes: %d,%d (%d!=%d || %d!=%d)\n",
173 	      console->x,console->y,
174 	      buffer[4+2*i],console->screenBuffer[i],
175 	      buffer[5+2*i],console->attributeBuffer[i]);
176 	    */
177 
178 #ifdef USE_OLD_VCS
179 	    vcPutChar(console,buffer[i]);
180 #else
181 	    vcPutCharColour(console,buffer[4+i*2],buffer[5+i*2]&0x7,buffer[5+i*2]>>4);
182 #endif
183 	  }
184       }
185       console->x=buffer[2];
186       console->y=buffer[3];
187     }
188     vcProcessEvents(console);
189   }
190   return(0);
191 }
192