Commit d999a8ea authored by Christian Beier's avatar Christian Beier
parent 7960c687
SUBDIRS=libvncserver examples libvncclient vncterm webclients client_examples test
DIST_SUBDIRS=libvncserver examples libvncclient vncterm webclients client_examples test
SUBDIRS=libvncserver examples libvncclient webclients client_examples test
DIST_SUBDIRS=libvncserver examples libvncclient webclients client_examples test
EXTRA_DIST = CMakeLists.txt rfb/rfbint.h.cmake rfb/rfbconfig.h.cmake
bin_SCRIPTS = libvncserver-config
......
......@@ -598,7 +598,6 @@ AC_CONFIG_FILES([Makefile
libvncserver/Makefile
examples/Makefile
examples/android/Makefile
vncterm/Makefile
webclients/Makefile
webclients/java-applet/Makefile
webclients/java-applet/ssl/Makefile
......
included in LibVNCServer package, autoconf'ed it
SetXCutText implemented
fix for cargs
attributes work.
cursor in LinuxVNC is shown.
paste works
selection works (no cursor trails)
LinuxVNC gets it's dimensions via ioctl TIOCGWINSZ
First working key injection in LinuxVNC!
Added Mouse marking
added screenBuffer (so you have ASCII screen also)
fixed CopyRect for scrolling (need to propagate to libvncserver)
made VNCommand work (no prompt for bash, but else seems ok)
added flag for VNCommand to send input only after a newline
(good for interactive bash)
#include <rfb/keysym.h>
#include "VNConsole.h"
#include "vga.h"
#include <fcntl.h>
#include <sys/ioctl.h>
static int tty=2;
static int tty_inject_device;
void do_key(rfbBool down,rfbKeySym keySym,rfbClientPtr cl)
{
static char isControl=0;
if(down) {
/* if(keySym==XK_Escape)
rfbCloseClient(cl);
else */ if(keySym==XK_Control_L || keySym==XK_Control_R)
isControl++;
else if(tty_inject_device>=0) {
if(keySym==XK_Escape)
keySym=27;
if(isControl) {
if(keySym>='a' && keySym<='z')
keySym-='a'-1;
else if(keySym>='A' && keySym<='Z')
keySym-='A'-1;
else
keySym=0xffff;
}
if(keySym==XK_Tab)
keySym='\t';
else if(keySym==XK_Return)
keySym='\r';
else if(keySym==XK_BackSpace)
keySym=8;
else if(keySym==XK_Home || keySym==XK_KP_Home)
keySym=1;
else if(keySym==XK_End || keySym==XK_KP_End)
keySym=5;
else if(keySym==XK_Up || keySym==XK_KP_Up)
keySym=16;
else if(keySym==XK_Down || keySym==XK_KP_Down)
keySym=14;
else if(keySym==XK_Right || keySym==XK_KP_Right)
keySym=6;
else if(keySym==XK_Left || keySym==XK_KP_Left)
keySym=2;
if(keySym<0x100) {
int ret;
ret=ioctl(tty_inject_device,TIOCSTI,&keySym);
if(ret<0) {
static char device[64];
close(tty_inject_device);
sprintf(device,"/dev/tty%d",tty);
tty_inject_device=open(device,O_WRONLY);
ret=ioctl(tty_inject_device,TIOCSTI,&keySym);
if(ret<0)
rfbErr("Couldn't reopen device %s!\n",device);
}
}
}
} else if(keySym==XK_Control_L || keySym==XK_Control_R)
if(isControl>0)
isControl--;
}
/* these colours are from linux kernel drivers/char/console.c */
unsigned char color_table[] = { 0, 4, 2, 6, 1, 5, 3, 7,
8,12,10,14, 9,13,11,15 };
/* the default colour table, for VGA+ colour systems */
int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
int main(int argc,char **argv)
{
int width=80,height=25;
char *buffer;
vncConsolePtr console;
char tty_device[64],title[128];
int i;
FILE* tty_file;
struct winsize dimensions;
if(argc>1) {
if((tty=atoi(argv[1]))<1) {
rfbErr("Usage: %s [tty_number [vnc args]]\n",argv[0]);
exit(1);
} else {
argv++;
argc--;
}
}
/* getopt goes here! */
sprintf(tty_device,"/dev/tty%d",tty);
if((tty_inject_device=open(tty_device,O_WRONLY))<0) {
rfbErr("Couldn't open tty device %s!\n",tty_device);
exit(1);
}
rfbLog("Using device %s.\n",tty_device);
if(ioctl(tty_inject_device,TIOCGWINSZ,&dimensions)>=0) {
width=dimensions.ws_col;
height=dimensions.ws_row;
}
sprintf(title,"LinuxVNC: /dev/tty%d",tty);
/* console init */
if(!(console=vcGetConsole(&argc,argv,width,height,&vgaFont,TRUE)))
exit(1);
for(i=0;i<16;i++) {
console->screen->colourMap.data.bytes[i*3+0]=default_red[color_table[i]];
console->screen->colourMap.data.bytes[i*3+1]=default_grn[color_table[i]];
console->screen->colourMap.data.bytes[i*3+2]=default_blu[color_table[i]];
}
console->screen->desktopName=title;
console->screen->kbdAddEvent=do_key;
console->selectTimeOut=100000;
console->wrapBottomToTop=TRUE;
#ifdef USE_OLD_VCS
buffer=malloc(width*height);
console->cursorActive=FALSE;
#else
buffer=malloc(width*height*2+4);
console->cursorActive=TRUE;
#endif
/* memcpy(buffer,console->screenBuffer,width*height); */
#ifdef USE_OLD_VCS
sprintf(tty_device,"/dev/vcs%d",tty);
#else
sprintf(tty_device,"/dev/vcsa%d",tty);
#endif
while(rfbIsActive(console->screen)) {
if(!console->currentlyMarking) {
tty_file=fopen(tty_device,"rb");
if(!tty_file) {
rfbErr("cannot open device \"%s\"\n",
tty_device);
exit(1);
}
#ifdef USE_OLD_VCS
fread(buffer,width,height,tty_file);
#else
if(fread(buffer,width*height*2+4,1,tty_file) != 1) {
rfbErr("Error reading framebuffer\n");
exit(1);
}
vcHideCursor(console);
#endif
fclose(tty_file);
for(i=0;i<console->width*console->height;i++) {
if
#ifdef USE_OLD_VCS
(buffer[i]!=console->screenBuffer[i])
#else
(buffer[4+2*i]!=console->screenBuffer[i] ||
buffer[5+2*i]!=console->attributeBuffer[i])
#endif
{
console->x=(i%console->width);
console->y=(i/console->width);
/*
rfbLog("changes: %d,%d (%d!=%d || %d!=%d)\n",
console->x,console->y,
buffer[4+2*i],console->screenBuffer[i],
buffer[5+2*i],console->attributeBuffer[i]);
*/
#ifdef USE_OLD_VCS
vcPutChar(console,buffer[i]);
#else
vcPutCharColour(console,buffer[4+i*2],buffer[5+i*2]&0x7,buffer[5+i*2]>>4);
#endif
}
}
console->x=buffer[2];
console->y=buffer[3];
}
vcProcessEvents(console);
}
return(0);
}
INCLUDES = -I$(top_srcdir)
CONSOLE_SRCS=VNConsole.c
noinst_HEADERS=VNConsole.h vga.h
LDADD=../libvncserver/libvncserver.la @WSOCKLIB@
if LINUX
if ! MINGW
if ! ANDROID
bin_PROGRAMS=linuxvnc
linuxvnc_SOURCES=LinuxVNC.c $(CONSOLE_SRCS)
endif
endif
endif
if ! MINGW
VNCOMMAND=vncommand
endif
noinst_PROGRAMS=example $(VNCOMMAND)
example_SOURCES=example.c $(CONSOLE_SRCS)
vncommand_SOURCES=VNCommand.c $(CONSOLE_SRCS)
In this stage (beta), there are two programs functional:
LinuxVNC <tty number>
monitor a virtual console (text mode) of Linux. You need
root privileges, or at least be in the "tty" group, because
it reads /dev/vcsN and writes /dev/ttyN.
It follows the same idea as WinVNC, x11vnc or OSXvnc, i.e. it
takes an existing desktop and exports it via RFB (VNC), just that
LinuxVNC exports text.
VNCommand <command> <args>
executes <command> redirecting stdin from a vncviewer and stdout &
stderr to the vnc clients. This might be renamed to vncTerm if
there are some term capabilities added (up to now, bash doesn't look
nice). Colours and other ANSI sequences need to be added.
My original plan was to create a program named vncTerm. It was meant to
overcome incompatibilities between different TERMs, but I found "screen" to
be just such a program. Maybe once some time in the future I'll make a
patch for screen to use VNConsole to export it's contents via RFB...
These two programs are a simple application of LibVNCServer with a small
console layer in between (VNConsole). You can use them under the terms
(not vncTerms ;-) of the GPL. They where written by Johannes E. Schindelin.
VNConsole:
LinuxVNC:
VNCommand:
make Control or Alt sequences work.
Find out how to satisfy isatty(). => /dev/ptyN
Fix check if child is alive.
Add command line option for real interactive mode.
done:
.treat colours correctly (use /dev/vcsaN's attributes).
.introduce per cell colours (for attributes)
.fix cursor fuckup when selecting.
.default to paste for right mouse button.
.have an idea how to insert keys
.convert VNCommand to an interactive shell (vncTerm)
.bidirectional pipes (spawn a shell ...)
.mark with mouse (copy text)
.when scrolling, cursor must be hidden!
modifiedRegion which are copied with CopyRect have to be modified also.
#ifdef __STRICT_ANSI__
#define _BSD_SOURCE
#define _POSIX_SOURCE
#endif
#include "VNConsole.h"
#include "vga.h"
#ifdef LIBVNCSERVER_HAVE_FCNTL_H
#include <fcntl.h>
#endif
#ifdef LIBVNCSERVER_HAVE_SYS_TIME_H
#include <sys/time.h>
#endif
#ifdef LIBVNCSERVER_HAVE_UNISTD_H
#include <unistd.h>
#endif
#ifdef LIBVNCSERVER_HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#include <errno.h>
int main(int argc, char **argv)
{
rfbBool interactive=FALSE,sendOnlyWholeLines=TRUE;
int serverArgc,programArg0;
for(serverArgc=1;serverArgc<argc
&& argv[serverArgc][0]=='-' && argv[serverArgc][1]!='-';serverArgc++)
if(!strcmp(argv[serverArgc],"-interactive")) {
interactive=TRUE;
sendOnlyWholeLines=FALSE;
rfbPurgeArguments(&argc,&serverArgc,1,argv);
}
programArg0=serverArgc;
if(programArg0<argc && argv[programArg0][0]=='-' && argv[programArg0][1]=='-')
programArg0++;
argv[argc]=0;
if(programArg0<argc) {
int in[2],out[2],err[2],pid;
if(pipe(in)<0 || pipe(out)<0 || pipe(err)<0) {
rfbErr("Couldn't make pipes!");
return(1);
}
pid=fork();
if(!pid) {
dup2(in[0],0);
dup2(out[1],1);
dup2(err[1],2);
/*setbuf(stdin,NULL);*/
execvp(argv[programArg0],argv+programArg0);
}
{
char buffer[1024];
fd_set fs,fs1/*,ifs,ifs1*/;
struct timeval tv,tv1;
int i,c=1,num_fds,max_fd=out[0],status;
FILE *input_pipe;
vncConsolePtr console=vcGetConsole(&serverArgc,argv,80,25,&vgaFont,FALSE);
if(interactive)
console->doEcho = FALSE;
if(max_fd<err[0])
max_fd=err[0];
FD_ZERO(&fs);
FD_SET(out[0],&fs);
FD_SET(err[0],&fs);
/*FD_SET(0,&fs);*/
tv.tv_sec=0; tv.tv_usec=5000;
input_pipe=fdopen(in[1],"w");
setbuf(input_pipe,NULL);
while(c || waitpid(pid,&status,WNOHANG)==0) {
/* event loop */
vcProcessEvents(console);
/* get input */
if(console->inputCount) {
if(sendOnlyWholeLines) {
for(i=0;i<console->inputCount;i++)
if(console->inputBuffer[i]=='\n') {
i++;
fwrite(console->inputBuffer,i,1,input_pipe);
fflush(input_pipe);
/* fwrite(console->inputBuffer,i,1,stderr); */
if(console->inputCount>i)
memmove(console->inputBuffer,console->inputBuffer+i,console->inputCount-i);
console->inputCount-=i;
i=0;
}
} else {
fwrite(console->inputBuffer,console->inputCount,1,input_pipe);
fflush(input_pipe);
/* fwrite(console->inputBuffer,console->inputCount,1,stderr); */
console->inputCount=0;
}
}
/* process output */
fs1=fs; tv1=tv;
num_fds=select(max_fd+1,&fs1,NULL,NULL,&tv1);
if(num_fds>0) {
/*
if(FD_ISSET(0,&fs1)) {
ch=getchar();
fputc(ch,f);
}
*/
if(FD_ISSET(out[0],&fs1)) {
c=read(out[0],buffer,1024);
for(i=0;i<c;i++)
vcPutChar(console,buffer[i]);
}
if(FD_ISSET(err[0],&fs1)) {
c=read(err[0],buffer,1024);
for(i=0;i<c;i++)
vcPutChar(console,buffer[i]);
}
} else
c=0;
}
}
}
rfbLog("exit\n");
return(0);
}
This diff is collapsed.
#include <rfb/rfb.h>
/* this is now the default */
#define USE_ATTRIBUTE_BUFFER
typedef struct vncConsole {
/* width and height in cells (=characters) */
int width, height;
/* current position */
int x,y;
/* characters */
char *screenBuffer;
#ifdef USE_ATTRIBUTE_BUFFER
/* attributes: colours. If NULL, default to gray on black, else
for each cell an unsigned char holds foreColour|(backColour<<4) */
char *attributeBuffer;
#endif
/* if this is set, the screen doesn't scroll. */
rfbBool wrapBottomToTop;
/* height and width of one character */
int cWidth, cHeight;
/* offset of characters */
int xhot,yhot;
/* colour */
unsigned char foreColour,backColour;
int8_t cx1,cy1,cx2,cy2;
/* input buffer */
char *inputBuffer;
int inputCount;
int inputSize;
long selectTimeOut;
rfbBool doEcho; /* if reading input, do output directly? */
/* selection */
char *selection;
/* mouse */
rfbBool wasRightButtonDown;
rfbBool currentlyMarking;
int markStart,markEnd;
/* should text cursor be drawn? (an underscore at current position) */
rfbBool cursorActive;
rfbBool cursorIsDrawn;
rfbBool dontDrawCursor; /* for example, while scrolling */
rfbFontDataPtr font;
rfbScreenInfoPtr screen;
} vncConsole, *vncConsolePtr;
#ifdef USE_ATTRIBUTE_BUFFER
vncConsolePtr vcGetConsole(int *argc,char **argv,
int width,int height,rfbFontDataPtr font,
rfbBool withAttributes);
#else
vncConsolePtr vcGetConsole(int argc,char **argv,
int width,int height,rfbFontDataPtr font);
#endif
void vcDrawCursor(vncConsolePtr c);
void vcHideCursor(vncConsolePtr c);
void vcCheckCoordinates(vncConsolePtr c);
void vcPutChar(vncConsolePtr c,unsigned char ch);
void vcPrint(vncConsolePtr c,unsigned char* str);
void vcPrintF(vncConsolePtr c,char* format,...);
void vcPutCharColour(vncConsolePtr c,unsigned char ch,
unsigned char foreColour,unsigned char backColour);
void vcPrintColour(vncConsolePtr c,unsigned char* str,
unsigned char foreColour,unsigned char backColour);
void vcPrintFColour(vncConsolePtr c,unsigned char foreColour,
unsigned char backColour,char* format,...);
char vcGetCh(vncConsolePtr c);
char vcGetChar(vncConsolePtr c); /* blocking */
char *vcGetString(vncConsolePtr c,char *buffer,int maxLen);
void vcKbdAddEventProc(rfbBool down,rfbKeySym keySym,rfbClientPtr cl);
void vcPtrAddEventProc(int buttonMask,int x,int y,rfbClientPtr cl);
void vcSetXCutTextProc(char* str,int len, struct _rfbClientRec* cl);
void vcToggleMarkCell(vncConsolePtr c,int pos);
void vcUnmark(vncConsolePtr c);
void vcProcessEvents(vncConsolePtr c);
/* before using this function, hide the cursor */
void vcScroll(vncConsolePtr c,int lineCount);
#include "VNConsole.h"
#include "vga.h"
int main(int argc,char **argv)
{
vncConsolePtr c=vcGetConsole(&argc,argv,80,25,&vgaFont,FALSE);
char buffer[1024];
int i,j,l;
for(j=32;j<256;j+=16) {
vcPrintF(c,"%02x: ",j);
for(i=j;i<j+16;i++)
vcPutChar(c,i);
vcPutChar(c,'\n');
}
i=0;
while(1) {
vcPrintF(c,"%d :> ",i);
vcGetString(c,buffer,1024);
l=strlen(buffer)-1;
while(l>=0 && buffer[l]=='\n')
buffer[l]=0;
if(!strcmp(buffer,"quit"))
return(0);
if(!strcmp(buffer,"s"))
vcScroll(c,2);
if(!strcmp(buffer,"S"))
vcScroll(c,-2);
i++;
}
return(0);
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment