Initial revision
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/vncconfig_unix/Makefile.in b/vncconfig_unix/Makefile.in
new file mode 100644
index 0000000..58277c3
--- /dev/null
+++ b/vncconfig_unix/Makefile.in
@@ -0,0 +1,23 @@
+
+SRCS = vncExt.c vncconfig.cxx
+
+OBJS = vncExt.o vncconfig.o
+
+program = vncconfig
+
+DEP_LIBS = ../tx/libtx.a ../rfb/librfb.a ../network/libnetwork.a \
+ ../rdr/librdr.a
+
+EXTRA_LIBS = @X_PRE_LIBS@ @X_LIBS@ -lX11 -lXext @X_EXTRA_LIBS@
+
+DIR_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/tx @X_CFLAGS@ # X_CFLAGS are really CPPFLAGS
+
+all:: $(program)
+
+$(program): $(OBJS) buildtime.o $(DEP_LIBS)
+ rm -f $(program)
+ $(CXXLD) $(CXXFLAGS) $(LDFLAGS) -o $@ $(OBJS) buildtime.o $(DEP_LIBS) $(LIBS) $(EXTRA_LIBS)
+
+buildtime.o: $(OBJS) $(DEP_LIBS)
+
+# followed by boilerplate.mk
diff --git a/vncconfig_unix/buildtime.c b/vncconfig_unix/buildtime.c
new file mode 100644
index 0000000..a96031c
--- /dev/null
+++ b/vncconfig_unix/buildtime.c
@@ -0,0 +1,18 @@
+/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+char buildtime[] = __DATE__ " " __TIME__;
diff --git a/vncconfig_unix/vncExt.c b/vncconfig_unix/vncExt.c
new file mode 100644
index 0000000..ac1dab3
--- /dev/null
+++ b/vncconfig_unix/vncExt.c
@@ -0,0 +1,316 @@
+/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#include <stdio.h>
+
+#define NEED_REPLIES
+#include <X11/Xlibint.h>
+#define _VNCEXT_PROTO_
+#include "vncExt.h"
+
+static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
+ xEvent* w);
+static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
+ xEvent* w);
+
+static Bool extensionInited = False;
+static XExtCodes* codes = 0;
+
+static Bool checkExtension(Display* dpy)
+{
+ if (!extensionInited) {
+ extensionInited = True;
+ codes = XInitExtension(dpy, VNCEXTNAME);
+ if (!codes) return False;
+ XESetWireToEvent(dpy, codes->first_event + VncExtClientCutTextNotify,
+ XVncExtClientCutTextNotifyWireToEvent);
+ XESetWireToEvent(dpy, codes->first_event + VncExtSelectionChangeNotify,
+ XVncExtSelectionChangeNotifyWireToEvent);
+ }
+ return codes != 0;
+}
+
+Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep)
+{
+ if (!checkExtension(dpy)) return False;
+ *event_basep = codes->first_event;
+ *error_basep = codes->first_error;
+ return True;
+}
+
+Bool XVncExtSetParam(Display* dpy, const char* param)
+{
+ xVncExtSetParamReq* req;
+ xVncExtSetParamReply rep;
+
+ int paramLen = strlen(param);
+ if (paramLen > 255) return False;
+ if (!checkExtension(dpy)) return False;
+
+ LockDisplay(dpy);
+ GetReq(VncExtSetParam, req);
+ req->reqType = codes->major_opcode;
+ req->vncExtReqType = X_VncExtSetParam;
+ req->length += (paramLen + 3) >> 2;
+ req->paramLen = paramLen;
+ Data(dpy, param, paramLen);
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return rep.success;
+}
+
+Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len)
+{
+ xVncExtGetParamReq* req;
+ xVncExtGetParamReply rep;
+
+ int paramLen = strlen(param);
+ *value = 0;
+ *len = 0;
+ if (paramLen > 255) return False;
+ if (!checkExtension(dpy)) return False;
+
+ LockDisplay(dpy);
+ GetReq(VncExtGetParam, req);
+ req->reqType = codes->major_opcode;
+ req->vncExtReqType = X_VncExtGetParam;
+ req->length += (paramLen + 3) >> 2;
+ req->paramLen = paramLen;
+ Data(dpy, param, paramLen);
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ if (rep.success) {
+ *len = rep.valueLen;
+ *value = (char*) Xmalloc (*len+1);
+ _XReadPad(dpy, *value, *len);
+ (*value)[*len] = 0;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return rep.success;
+}
+
+char* XVncExtGetParamDesc(Display* dpy, const char* param)
+{
+ xVncExtGetParamDescReq* req;
+ xVncExtGetParamDescReply rep;
+ char* desc = 0;
+
+ int paramLen = strlen(param);
+ if (paramLen > 255) return False;
+ if (!checkExtension(dpy)) return False;
+
+ LockDisplay(dpy);
+ GetReq(VncExtGetParamDesc, req);
+ req->reqType = codes->major_opcode;
+ req->vncExtReqType = X_VncExtGetParamDesc;
+ req->length += (paramLen + 3) >> 2;
+ req->paramLen = paramLen;
+ Data(dpy, param, paramLen);
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ if (rep.success) {
+ desc = (char*)Xmalloc(rep.descLen+1);
+ _XReadPad(dpy, desc, rep.descLen);
+ desc[rep.descLen] = 0;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return desc;
+}
+
+char** XVncExtListParams(Display* dpy, int* nParams)
+{
+ xVncExtListParamsReq* req;
+ xVncExtListParamsReply rep;
+ char** list = 0;
+ char* ch;
+ int rlen, paramLen, i;
+
+ if (!checkExtension(dpy)) return False;
+
+ LockDisplay(dpy);
+ GetReq(VncExtListParams, req);
+ req->reqType = codes->major_opcode;
+ req->vncExtReqType = X_VncExtListParams;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ if (rep.nParams) {
+ list = (char**)Xmalloc(rep.nParams * sizeof(char*));
+ rlen = rep.length << 2;
+ ch = (char*)Xmalloc(rlen + 1);
+ if (!list || !ch) {
+ if (list) Xfree((char*)list);
+ if (ch) Xfree(ch);
+ _XEatData(dpy, rlen);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return 0;
+ }
+ _XReadPad(dpy, ch, rlen);
+ paramLen = *ch++;
+ for (i = 0; i < rep.nParams; i++) {
+ list[i] = ch;
+ ch += paramLen;
+ paramLen = *ch;
+ *ch++ = 0;
+ }
+ }
+ *nParams = rep.nParams;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return list;
+}
+
+void XVncExtFreeParamList(char** list)
+{
+ if (list) {
+ Xfree(list[0]-1);
+ Xfree((char*)list);
+ }
+}
+
+Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len)
+{
+ xVncExtSetServerCutTextReq* req;
+
+ if (!checkExtension(dpy)) return False;
+
+ LockDisplay(dpy);
+ GetReq(VncExtSetServerCutText, req);
+ req->reqType = codes->major_opcode;
+ req->vncExtReqType = X_VncExtSetServerCutText;
+ req->length += (len + 3) >> 2;
+ req->textLen = len;
+ Data(dpy, str, len);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return True;
+}
+
+Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len)
+{
+ xVncExtGetClientCutTextReq* req;
+ xVncExtGetClientCutTextReply rep;
+
+ if (!checkExtension(dpy)) return False;
+
+ LockDisplay(dpy);
+ GetReq(VncExtGetClientCutText, req);
+ req->reqType = codes->major_opcode;
+ req->vncExtReqType = X_VncExtGetClientCutText;
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ *len = rep.textLen;
+ *str = (char*) Xmalloc (*len+1);
+ _XReadPad(dpy, *str, *len);
+ (*str)[*len] = 0;
+ return True;
+}
+
+Bool XVncExtSelectInput(Display* dpy, Window w, int mask)
+{
+ xVncExtSelectInputReq* req;
+
+ if (!checkExtension(dpy)) return False;
+
+ LockDisplay(dpy);
+ GetReq(VncExtSelectInput, req);
+ req->reqType = codes->major_opcode;
+ req->vncExtReqType = X_VncExtSelectInput;
+ req->window = w;
+ req->mask = mask;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return True;
+}
+
+Bool XVncExtConnect(Display* dpy, char* hostAndPort)
+{
+ xVncExtConnectReq* req;
+ xVncExtConnectReply rep;
+
+ int strLen = strlen(hostAndPort);
+ if (strLen > 255) return False;
+ if (!checkExtension(dpy)) return False;
+
+ LockDisplay(dpy);
+ GetReq(VncExtConnect, req);
+ req->reqType = codes->major_opcode;
+ req->vncExtReqType = X_VncExtConnect;
+ req->length += (strLen + 3) >> 2;
+ req->strLen = strLen;
+ Data(dpy, hostAndPort, strLen);
+ if (!_XReply(dpy, (xReply *)&rep, 0, xFalse)) {
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return False;
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return rep.success;
+}
+
+static Bool XVncExtClientCutTextNotifyWireToEvent(Display* dpy, XEvent* e,
+ xEvent* w)
+{
+ XVncExtClientCutTextEvent* ev = (XVncExtClientCutTextEvent*)e;
+ xVncExtClientCutTextNotifyEvent* wire = (xVncExtClientCutTextNotifyEvent*)w;
+ ev->type = wire->type & 0x7f;
+ ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
+ ev->send_event = (wire->type & 0x80) != 0;
+ ev->display = dpy;
+ ev->window = wire->window;
+ ev->time = wire->time;
+ return True;
+}
+
+static Bool XVncExtSelectionChangeNotifyWireToEvent(Display* dpy, XEvent* e,
+ xEvent* w)
+{
+ XVncExtSelectionChangeEvent* ev = (XVncExtSelectionChangeEvent*)e;
+ xVncExtSelectionChangeNotifyEvent* wire
+ = (xVncExtSelectionChangeNotifyEvent*)w;
+ ev->type = wire->type & 0x7f;
+ ev->serial = _XSetLastRequestRead(dpy,(xGenericReply*)wire);
+ ev->send_event = (wire->type & 0x80) != 0;
+ ev->display = dpy;
+ ev->window = wire->window;
+ ev->selection = wire->selection;
+ return True;
+}
diff --git a/vncconfig_unix/vncExt.h b/vncconfig_unix/vncExt.h
new file mode 100644
index 0000000..de69f4e
--- /dev/null
+++ b/vncconfig_unix/vncExt.h
@@ -0,0 +1,279 @@
+/* Copyright (C) 2002-2003 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+#ifndef _VNCEXT_H_
+#define _VNCEXT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define X_VncExtSetParam 0
+#define X_VncExtGetParam 1
+#define X_VncExtGetParamDesc 2
+#define X_VncExtListParams 3
+#define X_VncExtSetServerCutText 4
+#define X_VncExtGetClientCutText 5
+#define X_VncExtSelectInput 6
+#define X_VncExtConnect 7
+
+#define VncExtClientCutTextNotify 0
+#define VncExtSelectionChangeNotify 1
+#define VncExtClientCutTextMask (1 << VncExtClientCutTextNotify)
+#define VncExtSelectionChangeMask (1 << VncExtSelectionChangeNotify)
+
+#define VncExtNumberEvents 2
+#define VncExtNumberErrors 0
+
+#ifndef _VNCEXT_SERVER_
+
+Bool XVncExtQueryExtension(Display* dpy, int* event_basep, int* error_basep);
+Bool XVncExtSetParam(Display* dpy, const char* param);
+Bool XVncExtGetParam(Display* dpy, const char* param, char** value, int* len);
+char* XVncExtGetParamDesc(Display* dpy, const char* param);
+char** XVncExtListParams(Display* dpy, int* nParams);
+void XVncExtFreeParamList(char** list);
+Bool XVncExtSetServerCutText(Display* dpy, const char* str, int len);
+Bool XVncExtGetClientCutText(Display* dpy, char** str, int* len);
+Bool XVncExtSelectInput(Display* dpy, Window w, int mask);
+Bool XVncExtConnect(Display* dpy, char* hostAndPort);
+
+typedef struct {
+ int type;
+ unsigned long serial;
+ Bool send_event;
+ Display *display;
+ Window window;
+ Time time;
+} XVncExtClientCutTextEvent;
+
+typedef struct {
+ int type;
+ unsigned long serial;
+ Bool send_event;
+ Display *display;
+ Window window;
+ Atom selection;
+} XVncExtSelectionChangeEvent;
+
+#endif
+
+#ifdef _VNCEXT_PROTO_
+
+#define VNCEXTNAME "VNC-EXTENSION"
+
+typedef struct {
+ CARD8 reqType; /* always VncExtReqCode */
+ CARD8 vncExtReqType; /* always VncExtSetParam */
+ CARD16 length B16;
+ CARD8 paramLen;
+ CARD8 pad0;
+ CARD16 pad1 B16;
+} xVncExtSetParamReq;
+#define sz_xVncExtSetParamReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BYTE success;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad0 B32;
+ CARD32 pad1 B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+} xVncExtSetParamReply;
+#define sz_xVncExtSetParamReply 32
+
+
+typedef struct {
+ CARD8 reqType; /* always VncExtReqCode */
+ CARD8 vncExtReqType; /* always VncExtGetParam */
+ CARD16 length B16;
+ CARD8 paramLen;
+ CARD8 pad0;
+ CARD16 pad1 B16;
+} xVncExtGetParamReq;
+#define sz_xVncExtGetParamReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BYTE success;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 valueLen B16;
+ CARD16 pad0 B16;
+ CARD32 pad1 B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+} xVncExtGetParamReply;
+#define sz_xVncExtGetParamReply 32
+
+
+typedef struct {
+ CARD8 reqType; /* always VncExtReqCode */
+ CARD8 vncExtReqType; /* always VncExtGetParamDesc */
+ CARD16 length B16;
+ CARD8 paramLen;
+ CARD8 pad0;
+ CARD16 pad1 B16;
+} xVncExtGetParamDescReq;
+#define sz_xVncExtGetParamDescReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BYTE success;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 descLen B16;
+ CARD16 pad0 B16;
+ CARD32 pad1 B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+} xVncExtGetParamDescReply;
+#define sz_xVncExtGetParamDescReply 32
+
+
+typedef struct {
+ CARD8 reqType; /* always VncExtReqCode */
+ CARD8 vncExtReqType; /* always VncExtListParams */
+ CARD16 length B16;
+} xVncExtListParamsReq;
+#define sz_xVncExtListParamsReq 4
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD16 nParams B16;
+ CARD16 pad1 B16;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+ CARD32 pad6 B32;
+} xVncExtListParamsReply;
+#define sz_xVncExtListParamsReply 32
+
+
+typedef struct {
+ CARD8 reqType; /* always VncExtReqCode */
+ CARD8 vncExtReqType; /* always VncExtSetServerCutText */
+ CARD16 length B16;
+ CARD32 textLen B32;
+} xVncExtSetServerCutTextReq;
+#define sz_xVncExtSetServerCutTextReq 8
+
+
+typedef struct {
+ CARD8 reqType; /* always VncExtReqCode */
+ CARD8 vncExtReqType; /* always VncExtGetClientCutText */
+ CARD16 length B16;
+} xVncExtGetClientCutTextReq;
+#define sz_xVncExtGetClientCutTextReq 4
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 textLen B32;
+ CARD32 pad1 B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+} xVncExtGetClientCutTextReply;
+#define sz_xVncExtGetClientCutTextReply 32
+
+
+typedef struct {
+ CARD8 reqType; /* always VncExtReqCode */
+ CARD8 vncExtReqType; /* always VncExtSelectInput */
+ CARD16 length B16;
+ CARD32 window B32;
+ CARD32 mask B32;
+} xVncExtSelectInputReq;
+#define sz_xVncExtSelectInputReq 12
+
+
+typedef struct {
+ CARD8 reqType; /* always VncExtReqCode */
+ CARD8 vncExtReqType; /* always VncExtConnect */
+ CARD16 length B16;
+ CARD8 strLen;
+ CARD8 pad0;
+ CARD16 pad1 B16;
+} xVncExtConnectReq;
+#define sz_xVncExtConnectReq 8
+
+typedef struct {
+ BYTE type; /* X_Reply */
+ BYTE success;
+ CARD16 sequenceNumber B16;
+ CARD32 length B32;
+ CARD32 pad0 B32;
+ CARD32 pad1 B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+} xVncExtConnectReply;
+#define sz_xVncExtConnectReply 32
+
+
+typedef struct {
+ BYTE type; /* always eventBase + VncExtClientCutTextNotify */
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 window B32;
+ CARD32 time B32;
+ CARD32 pad1 B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+} xVncExtClientCutTextNotifyEvent;
+#define sz_xVncExtClientCutTextNotifyEvent 32
+
+typedef struct {
+ BYTE type; /* always eventBase + VncExtSelectionChangeNotify */
+ BYTE pad0;
+ CARD16 sequenceNumber B16;
+ CARD32 window B32;
+ CARD32 selection B32;
+ CARD32 pad1 B32;
+ CARD32 pad2 B32;
+ CARD32 pad3 B32;
+ CARD32 pad4 B32;
+ CARD32 pad5 B32;
+} xVncExtSelectionChangeNotifyEvent;
+#define sz_xVncExtSelectionChangeNotifyEvent 32
+
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/vncconfig_unix/vncconfig.cxx b/vncconfig_unix/vncconfig.cxx
new file mode 100644
index 0000000..e707ffb
--- /dev/null
+++ b/vncconfig_unix/vncconfig.cxx
@@ -0,0 +1,313 @@
+/* Copyright (C) 2002-2004 RealVNC Ltd. All Rights Reserved.
+ *
+ * This is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this software; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
+ * USA.
+ */
+//
+// VNC server configuration utility
+//
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <signal.h>
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <X11/keysym.h>
+#include "vncExt.h"
+#include <rdr/Exception.h>
+#include <rfb/Configuration.h>
+#include <rfb/Logger_stdio.h>
+#include <rfb/LogWriter.h>
+#include "TXWindow.h"
+#include "TXCheckbox.h"
+
+using namespace rfb;
+
+LogWriter vlog("vncconfig");
+
+StringParameter displayname("display", "The X display", "");
+BoolParameter noWindow("nowin", "Don't display a window", 0);
+BoolParameter iconic("iconic", "Start with window iconified", 0);
+
+#define ACCEPT_CUT_TEXT "AcceptCutText"
+#define SEND_CUT_TEXT "SendCutText"
+
+char* programName = 0;
+Display* dpy;
+int vncExtEventBase, vncExtErrorBase;
+
+static bool getBoolParam(Display* dpy, const char* param) {
+ char* data;
+ int len;
+ if (XVncExtGetParam(dpy, param, &data, &len)) {
+ if (strcmp(data,"1") == 0) return true;
+ }
+ return false;
+}
+
+class VncConfigWindow : public TXWindow, public TXEventHandler,
+ public TXDeleteWindowCallback,
+ public TXCheckboxCallback {
+public:
+ VncConfigWindow(Display* dpy)
+ : TXWindow(dpy, 300, 100), clientCutText(0), clientCutTextLen(0),
+ acceptClipboard(dpy, "Accept clipboard from viewers", this, false, this),
+ sendClipboard(dpy, "Send clipboard to viewers", this, false, this),
+ sendPrimary(dpy, "Send primary selection to viewers", this, false, this)
+ {
+ int y = yPad;
+ acceptClipboard.move(xPad, y);
+ acceptClipboard.checked(getBoolParam(dpy, ACCEPT_CUT_TEXT));
+ y += acceptClipboard.height();
+ sendClipboard.move(xPad, y);
+ sendClipboard.checked(getBoolParam(dpy, SEND_CUT_TEXT));
+ y += sendClipboard.height();
+ sendPrimary.move(xPad, y);
+ sendPrimary.checked(true);
+ sendPrimary.disabled(!sendClipboard.checked());
+ y += sendPrimary.height();
+ setEventHandler(this);
+ toplevel("VNC config", this, 0, 0, 0, iconic);
+ XVncExtSelectInput(dpy, win(),
+ VncExtClientCutTextMask|VncExtSelectionChangeMask);
+ }
+
+ // handleEvent(). If we get a ClientCutTextNotify event from Xvnc, set the
+ // primary and clipboard selections to the clientCutText. If we get a
+ // SelectionChangeNotify event from Xvnc, set the serverCutText to the value
+ // of the new selection.
+
+ virtual void handleEvent(TXWindow* w, XEvent* ev) {
+ if (acceptClipboard.checked()) {
+ if (ev->type == vncExtEventBase + VncExtClientCutTextNotify) {
+ XVncExtClientCutTextEvent* cutEv = (XVncExtClientCutTextEvent*)ev;
+ if (clientCutText)
+ XFree(clientCutText);
+ clientCutText = 0;
+ if (XVncExtGetClientCutText(dpy, &clientCutText, &clientCutTextLen)) {
+ vlog.debug("Got client cut text");
+ XStoreBytes(dpy, clientCutText, clientCutTextLen);
+ ownSelection(XA_PRIMARY, cutEv->time);
+ ownSelection(xaCLIPBOARD, cutEv->time);
+ }
+ }
+ }
+ if (sendClipboard.checked()) {
+ if (ev->type == vncExtEventBase + VncExtSelectionChangeNotify) {
+ XVncExtSelectionChangeEvent* selEv = (XVncExtSelectionChangeEvent*)ev;
+ if (selEv->selection == xaCLIPBOARD ||
+ (selEv->selection == XA_PRIMARY && sendPrimary.checked())) {
+ if (!selectionOwner(selEv->selection))
+ XConvertSelection(dpy, selEv->selection, XA_STRING,
+ selEv->selection, win(), CurrentTime);
+ }
+ }
+ }
+ }
+
+
+ // selectionRequest() is called when we are the selection owner and another X
+ // client has requested the selection. We simply put the server's cut text
+ // into the requested property. TXWindow will handle the rest.
+ bool selectionRequest(Window requestor, Atom selection, Atom property)
+ {
+ if (clientCutText)
+ XChangeProperty(dpy, requestor, property, XA_STRING, 8,
+ PropModeReplace, (unsigned char*)clientCutText,
+ clientCutTextLen);
+ return clientCutText;
+ }
+
+ // selectionNotify() is called when we have requested the selection from the
+ // selection owner.
+ void selectionNotify(XSelectionEvent* ev, Atom type, int format,
+ int nitems, void* data)
+ {
+ if (ev->requestor != win() || ev->target != XA_STRING)
+ return;
+
+ if (data && format == 8) {
+ vlog.debug("setting selection as server cut text");
+ XVncExtSetServerCutText(dpy, (char*)data, nitems);
+ }
+ }
+
+ // TXDeleteWindowCallback method
+ virtual void deleteWindow(TXWindow* w) {
+ exit(1);
+ }
+
+ // TXCheckboxCallback method
+ virtual void checkboxSelect(TXCheckbox* checkbox) {
+ if (checkbox == &acceptClipboard) {
+ XVncExtSetParam(dpy, (acceptClipboard.checked()
+ ? ACCEPT_CUT_TEXT "=1" : ACCEPT_CUT_TEXT "=0"));
+ } else if (checkbox == &sendClipboard) {
+ XVncExtSetParam(dpy, (sendClipboard.checked()
+ ? SEND_CUT_TEXT "=1" : SEND_CUT_TEXT "=0"));
+ sendPrimary.disabled(!sendClipboard.checked());
+ }
+ }
+
+private:
+ char* clientCutText;
+ int clientCutTextLen;
+ TXCheckbox acceptClipboard, sendClipboard, sendPrimary;
+};
+
+static void usage()
+{
+ fprintf(stderr,"usage: %s [-display <display>] [-nowin] [-iconic]\n",
+ programName);
+ fprintf(stderr," %s [-display <display>] -connect <host>[:<port>]\n",
+ programName);
+ fprintf(stderr," %s [-display <display>] -disconnect\n", programName);
+ fprintf(stderr," %s [-display <display>] [-set] <param>=<value> ...\n",
+ programName);
+ fprintf(stderr," %s [-display <display>] -list\n", programName);
+ fprintf(stderr," %s [-display <display>] -get <param>\n", programName);
+ fprintf(stderr," %s [-display <display>] -desc <param>\n",programName);
+ exit(1);
+}
+
+void removeArgs(int* argc, char** argv, int first, int n)
+{
+ if (first + n > *argc) return;
+ for (int i = first + n; i < *argc; i++)
+ argv[i-n] = argv[i];
+ *argc -= n;
+}
+
+int main(int argc, char** argv)
+{
+ programName = argv[0];
+ rfb::initStdIOLoggers();
+ rfb::LogWriter::setLogParams("*:stderr:30");
+
+ // Process vncconfig's own parameters first, then we process the
+ // other arguments when we have the X display.
+ int i;
+ for (i = 1; i < argc; i++) {
+ if (Configuration::setParam(argv[i]))
+ continue;
+
+ if (argv[i][0] == '-' && i+1 < argc &&
+ Configuration::setParam(&argv[i][1], argv[i+1])) {
+ i++;
+ continue;
+ }
+ break;
+ }
+
+ CharArray displaynameStr(displayname.getData());
+ if (!(dpy = XOpenDisplay(displaynameStr.buf))) {
+ fprintf(stderr,"%s: unable to open display \"%s\"\n",
+ programName, XDisplayName(displaynameStr.buf));
+ exit(1);
+ }
+
+ if (!XVncExtQueryExtension(dpy, &vncExtEventBase, &vncExtErrorBase)) {
+ fprintf(stderr,"No VNC extension on display %s\n",
+ XDisplayName(displaynameStr.buf));
+ exit(1);
+ }
+
+ if (i < argc) {
+ for (; i < argc; i++) {
+ if (strcmp(argv[i], "-connect") == 0) {
+ i++;
+ if (i >= argc) usage();
+ if (!XVncExtConnect(dpy, argv[i])) {
+ fprintf(stderr,"connecting to %s failed\n",argv[i]);
+ }
+ } else if (strcmp(argv[i], "-disconnect") == 0) {
+ if (!XVncExtConnect(dpy, "")) {
+ fprintf(stderr,"disconnecting all clients failed\n");
+ }
+ } else if (strcmp(argv[i], "-get") == 0) {
+ i++;
+ if (i >= argc) usage();
+ char* data;
+ int len;
+ if (XVncExtGetParam(dpy, argv[i], &data, &len)) {
+ printf("%.*s\n",len,data);
+ } else {
+ fprintf(stderr,"getting param %s failed\n",argv[i]);
+ }
+ XFree(data);
+ } else if (strcmp(argv[i], "-desc") == 0) {
+ i++;
+ if (i >= argc) usage();
+ char* desc = XVncExtGetParamDesc(dpy, argv[i]);
+ if (desc) {
+ printf("%s\n",desc);
+ } else {
+ fprintf(stderr,"getting description for param %s failed\n",argv[i]);
+ }
+ XFree(desc);
+ } else if (strcmp(argv[i], "-list") == 0) {
+ int nParams;
+ char** list = XVncExtListParams(dpy, &nParams);
+ for (int i = 0; i < nParams; i++) {
+ printf("%s\n",list[i]);
+ }
+ XVncExtFreeParamList(list);
+ } else if (strcmp(argv[i], "-set") == 0) {
+ i++;
+ if (i >= argc) usage();
+ if (!XVncExtSetParam(dpy, argv[i])) {
+ fprintf(stderr,"setting param %s failed\n",argv[i]);
+ }
+ } else if (XVncExtSetParam(dpy, argv[i])) {
+ fprintf(stderr,"set parameter %s\n",argv[i]);
+ } else {
+ usage();
+ }
+ }
+
+ return 0;
+ }
+
+ try {
+ TXWindow::init(dpy,"Vncconfig");
+
+ VncConfigWindow w(dpy);
+ if (!noWindow) w.map();
+
+ while (true) {
+ TXWindow::handleXEvents(dpy);
+ fd_set rfds;
+ FD_ZERO(&rfds);
+ FD_SET(ConnectionNumber(dpy), &rfds);
+ int n = select(FD_SETSIZE, &rfds, 0, 0, 0);
+ if (n < 0) throw rdr::SystemException("select",errno);
+ }
+
+ XCloseDisplay(dpy);
+
+ } catch (rdr::Exception &e) {
+ vlog.error(e.str());
+ }
+
+ return 0;
+}
diff --git a/vncconfig_unix/vncconfig.man b/vncconfig_unix/vncconfig.man
new file mode 100644
index 0000000..9a7d8ce
--- /dev/null
+++ b/vncconfig_unix/vncconfig.man
@@ -0,0 +1,115 @@
+.TH vncconfig 1 "3 June 2003" "RealVNC Ltd" "Virtual Network Computing"
+.SH NAME
+vncconfig \- configure and control a VNC server
+.SH SYNOPSIS
+.B vncconfig
+[\fB\-display\fP \fIXdisplay\fP] [\fB\-nowin\fP] [\fB\-iconic\fP]
+.br
+.B vncconfig
+[\fB\-display\fP \fIXdisplay\fP]
+.B \-connect
+.IR host [: port ]
+.br
+.B vncconfig
+[\fB\-display\fP \fIXdisplay\fP]
+.B \-disconnect
+.br
+.B vncconfig
+[\fB\-display\fP \fIXdisplay\fP]
+.IR param = value " ..."
+.br
+.B vncconfig
+[\fB\-display\fP \fIXdisplay\fP]
+.B \-list
+.br
+.B vncconfig
+[\fB\-display\fP \fIXdisplay\fP]
+\fB\-get\fP \fIparam\fP
+.br
+.B vncconfig
+[\fB\-display\fP \fIXdisplay\fP]
+\fB\-desc\fP \fIparam\fP
+.SH DESCRIPTION
+.B vncconfig
+is used to configure and control a running instance of Xvnc, or any other X
+server with the VNC extension. Note that it cannot be used to control VNC
+servers prior to version 4.
+
+When run with no options, it runs as a kind of "helper" application for Xvnc.
+Its main purpose when run in this mode is to support clipboard transfer to and
+from the VNC viewer(s). Note that without a running instance of
+\fBvncconfig\fP there will be no clipboard support. It puts up a window with
+some checkboxes which can be used to disable clipboard transfers if required
+(in the future there may be more functions available from this window). The
+\fB-nowin\fP flag can be used if you always want clipboard support but don't
+wish to clutter the desktop with this window - alternatively the \fB-iconic\fP
+option can be used to make it iconified by default.
+
+When run in any other mode, \fBvncconfig\fP is a one-shot program used to
+configure or control Xvnc as appropriate. It can be used to tell Xvnc to
+connect or disconnect from listening viewers, and to set and retrieve Xvnc's
+parameters.
+
+Note that the DISPLAY environment variable or the \fB\-display\fP option
+must be set as appropriate to control Xvnc. If you run it on an ordinary X
+server (or on a version 3 Xvnc) you will get an error message saying that there
+is no VNC extension.
+
+.SH OPTIONS
+.TP
+.B \-display \fIXdisplay\fP
+Specifies the Xvnc server to control.
+
+.TP
+.B \-nowin
+When run as a "helper" app, don't put up a window.
+
+.TP
+.B \-iconic
+When run as a "helper" app, make the window iconified at startup.
+
+.TP
+.B \-connect \fIhost\fP[:\fIport\fP]
+Tells an Xvnc server to make a "reverse" connection to a listening VNC viewer
+(normally connections are made the other way round - the viewer connects to the
+server). \fIhost\fP is the host where the listening viewer is running. If it's
+not listening on the default port of 5500, you can specify \fIhost:port\fP
+instead.
+
+.TP
+.B \-disconnect
+This causes Xvnc to disconnect from all viewers so that the VNC desktop is not
+displayed anywhere.
+
+.TP
+.IR param = value
+Sets an Xvnc parameter to the given value. Note that some of Xvnc's parameters
+are read only once at startup so that changing them in this way may not have
+any effect.
+
+.TP
+.B \-list
+Lists all the parameters supported by Xvnc.
+
+.TP
+.B \-get \fIparam\fP
+Prints the current value of the given Xvnc parameter.
+
+.TP
+.B \-desc \fIparam\fP
+Prints a short description of the given Xvnc parameter.
+
+.SH SEE ALSO
+.BR vncpasswd (1),
+.BR vncviewer (1),
+.BR vncserver (1),
+.BR Xvnc (1)
+.br
+http://www.realvnc.com
+
+.SH AUTHOR
+Tristan Richardson, RealVNC Ltd.
+
+VNC was originally developed by the RealVNC team while at Olivetti Research Ltd
+/ AT&T Laboratories Cambridge. It is now being maintained by RealVNC Ltd. See
+http://www.realvnc.com for details.