]> git.sesse.net Git - rdpsrv/blob - Xserver/programs/Xserver/hw/vnc/init.c
a55b715496c7013b7b2f699b5212823fd01ed874
[rdpsrv] / Xserver / programs / Xserver / hw / vnc / init.c
1 /*
2  * init.c
3  */
4
5 /*
6  *  Copyright (C) 2002-2003 RealVNC Ltd.
7  *  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.
8  *
9  *  This is free software; you can redistribute it and/or modify
10  *  it under the terms of the GNU General Public License as published by
11  *  the Free Software Foundation; either version 2 of the License, or
12  *  (at your option) any later version.
13  *
14  *  This software is distributed in the hope that it will be useful,
15  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  *  GNU General Public License for more details.
18  *
19  *  You should have received a copy of the GNU General Public License
20  *  along with this software; if not, write to the Free Software
21  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
22  *  USA.
23  */
24
25 /*
26
27 Copyright (c) 1993  X Consortium
28
29 Permission is hereby granted, free of charge, to any person obtaining
30 a copy of this software and associated documentation files (the
31 "Software"), to deal in the Software without restriction, including
32 without limitation the rights to use, copy, modify, merge, publish,
33 distribute, sublicense, and/or sell copies of the Software, and to
34 permit persons to whom the Software is furnished to do so, subject to
35 the following conditions:
36
37 The above copyright notice and this permission notice shall be included
38 in all copies or substantial portions of the Software.
39
40 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
41 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
42 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
43 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
44 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
45 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
46 OTHER DEALINGS IN THE SOFTWARE.
47
48 Except as contained in this notice, the name of the X Consortium shall
49 not be used in advertising or otherwise to promote the sale, use or
50 other dealings in this Software without prior written authorization
51 from the X Consortium.
52
53 */
54
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <stdarg.h>
58 #include <sys/types.h>
59 #include <sys/socket.h>
60 #include <netinet/in.h>
61 #include <netdb.h>
62 #include "X11/X.h"
63 #define NEED_EVENTS
64 #include "X11/Xproto.h"
65 #include "X11/Xos.h"
66 #include "scrnintstr.h"
67 #include "servermd.h"
68 #define PSZ 8
69 #include "cfb.h"
70 #include "mi.h"
71 #include "mibstore.h"
72 #include "colormapst.h"
73 #include "gcstruct.h"
74 #include "input.h"
75 #include "mipointer.h"
76 #include "dixstruct.h"
77 #include "propertyst.h"
78 #include <Xatom.h>
79 #include <errno.h>
80 #include <sys/param.h>
81 #include "dix.h"
82 #include "rfb.h"
83 #include "dispcur.h"
84
85 extern Bool cfb16ScreenInit(ScreenPtr, pointer, int, int, int, int, int);
86 extern Bool cfb32ScreenInit(ScreenPtr, pointer, int, int, int, int, int);
87
88 #define RFB_DEFAULT_WIDTH  640
89 #define RFB_DEFAULT_HEIGHT 480
90 #define RFB_DEFAULT_DEPTH  8
91 #define RFB_DEFAULT_WHITEPIXEL 0
92 #define RFB_DEFAULT_BLACKPIXEL 1
93
94 rfbScreenInfo rfbScreen;
95 int rfbGCIndex;
96
97 static Bool initOutputCalled = FALSE;
98 static Bool noCursor = FALSE;
99 char *desktopName = "x11";
100 Bool rfbTrace = FALSE;
101
102 char rfbThisHost[256];
103
104 Atom VNC_LAST_CLIENT_ID;
105 Atom VNC_CONNECT;
106 Atom VNC_DEFER_UPDATE;
107
108 static HWEventQueueType alwaysCheckForInput[2] = { 0, 1 };
109 static HWEventQueueType *mieqCheckForInput[2];
110
111 static char primaryOrder[4] = "";
112 static int redBits, greenBits, blueBits;
113
114
115 static Bool rfbScreenInit(int index, ScreenPtr pScreen, int argc,
116                           char **argv);
117 static int rfbKeybdProc(DeviceIntPtr pDevice, int onoff);
118 static int rfbMouseProc(DeviceIntPtr pDevice, int onoff);
119 static Bool CheckDisplayNumber(int n);
120
121 static Bool rfbAlwaysTrue();
122 static char *rfbAllocateFramebufferMemory(rfbScreenInfoPtr prfb);
123 static Bool rfbCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y);
124 static void rfbCrossScreen(ScreenPtr pScreen, Bool entering);
125 static void rfbClientStateChange(CallbackListPtr *, pointer myData,
126                                  pointer client);
127
128 static miPointerScreenFuncRec rfbPointerCursorFuncs = {
129     rfbCursorOffScreen,
130     rfbCrossScreen,
131     miPointerWarpCursor
132 };
133
134
135 int inetdSock = -1;
136 static char inetdDisplayNumStr[10];
137
138 extern char buildtime[];
139
140
141 /*
142  * ddxProcessArgument is our first entry point and will be called at the
143  * very start for each argument.  It is not called again on server reset.
144  */
145
146 int
147 ddxProcessArgument (argc, argv, i)
148     int argc;
149     char *argv[];
150     int i;
151 {
152     static Bool firstTime = TRUE;
153
154     if (firstTime)
155     {
156         rfbScreen.width  = RFB_DEFAULT_WIDTH;
157         rfbScreen.height = RFB_DEFAULT_HEIGHT;
158         rfbScreen.depth  = RFB_DEFAULT_DEPTH;
159         rfbScreen.blackPixel = RFB_DEFAULT_BLACKPIXEL;
160         rfbScreen.whitePixel = RFB_DEFAULT_WHITEPIXEL;
161         rfbScreen.pfbMemory = NULL;
162         gethostname(rfbThisHost, 255);
163         firstTime = FALSE;
164     }
165
166     if (strcasecmp (argv[i], "-geometry") == 0) /* -geometry WxH */
167     {
168         if (i + 1 >= argc) UseMsg();
169         if (sscanf(argv[i+1],"%dx%d",
170                    &rfbScreen.width,&rfbScreen.height) != 2) {
171             ErrorF("Invalid geometry %s\n", argv[i+1]);
172             UseMsg();
173         }
174         return 2;
175     }
176
177     if (strcasecmp (argv[i], "-depth") == 0)    /* -depth D */
178     {
179         if (i + 1 >= argc) UseMsg();
180         rfbScreen.depth = atoi(argv[i+1]);
181         return 2;
182     }
183
184     if (strcasecmp (argv[i], "-pixelformat") == 0) {
185         if (i + 1 >= argc) UseMsg();
186         if (sscanf(argv[i+1], "%3s%1d%1d%1d", primaryOrder,
187                    &redBits, &greenBits, &blueBits) < 4) {
188             ErrorF("Invalid pixel format %s\n", argv[i+1]);
189             UseMsg();
190         }
191
192         if (strcasecmp(primaryOrder, "bgr") == 0) {
193             int tmp = redBits;
194             redBits = blueBits;
195             blueBits = tmp;
196         } else if (strcasecmp(primaryOrder, "rgb") != 0) {
197             ErrorF("Invalid pixel format %s\n", argv[i+1]);
198             UseMsg();
199         }
200
201         return 2;
202     }
203
204     if (strcasecmp (argv[i], "-blackpixel") == 0) {     /* -blackpixel n */
205         if (i + 1 >= argc) UseMsg();
206         rfbScreen.blackPixel = atoi(argv[i+1]);
207         return 2;
208     }
209
210     if (strcasecmp (argv[i], "-whitepixel") == 0) {     /* -whitepixel n */
211         if (i + 1 >= argc) UseMsg();
212         rfbScreen.whitePixel = atoi(argv[i+1]);
213         return 2;
214     }
215
216     if (strcasecmp(argv[i], "-rfbport") == 0) { /* -rfbport port */
217         if (i + 1 >= argc) UseMsg();
218         rfbPort = atoi(argv[i+1]);
219         return 2;
220     }
221
222     if (strcasecmp(argv[i], "-rfbwait") == 0) { /* -rfbwait ms */
223         if (i + 1 >= argc) UseMsg();
224         rfbMaxClientWait = atoi(argv[i+1]);
225         return 2;
226     }
227
228     if (strcasecmp(argv[i], "-nocursor") == 0) {
229         noCursor = TRUE;
230         return 1;
231     }
232
233     if (strcasecmp(argv[i], "-rfbauth") == 0) { /* -rfbauth passwd-file */
234         if (i + 1 >= argc) UseMsg();
235         rfbAuthPasswdFile = argv[i+1];
236         return 2;
237     }
238
239     if (strcasecmp(argv[i], "-httpd") == 0) {
240         if (i + 1 >= argc) UseMsg();
241         httpDir = argv[i+1];
242         return 2;
243     }
244
245     if (strcasecmp(argv[i], "-httpport") == 0) {
246         if (i + 1 >= argc) UseMsg();
247         httpPort = atoi(argv[i+1]);
248         return 2;
249     }
250
251     if (strcasecmp(argv[i], "-deferupdate") == 0) {     /* -deferupdate ms */
252         if (i + 1 >= argc) UseMsg();
253         rfbDeferUpdateTime = atoi(argv[i+1]);
254         return 2;
255     }
256
257     if (strcasecmp(argv[i], "-economictranslate") == 0) {
258         rfbEconomicTranslate = TRUE;
259         return 1;
260     }
261
262     if (strcasecmp(argv[i], "-maxrects") == 0) {
263         if (i + 1 >= argc) UseMsg();
264         rfbMaxRects = atoi(argv[i+1]);
265         return 2;
266     }
267
268     if (strcasecmp(argv[i], "-trace") == 0) {
269         rfbTrace = TRUE;
270         return 1;
271     }
272
273     if (strcasecmp(argv[i], "-desktop") == 0) { /* -desktop desktop-name */
274         if (i + 1 >= argc) UseMsg();
275         desktopName = argv[i+1];
276         return 2;
277     }
278
279     if (strcasecmp(argv[i], "-alwaysshared") == 0) {
280         rfbAlwaysShared = TRUE;
281         return 1;
282     }
283
284     if (strcasecmp(argv[i], "-nevershared") == 0) {
285         rfbNeverShared = TRUE;
286         return 1;
287     }
288
289     if (strcasecmp(argv[i], "-dontdisconnect") == 0) {
290         rfbDontDisconnect = TRUE;
291         return 1;
292     }
293
294     if (strcasecmp(argv[i], "-localhost") == 0) {
295         rfbLocalhostOnly = TRUE;
296         return 1;
297     }
298
299     if (strcasecmp(argv[i], "-inetd") == 0) {   /* -inetd */ 
300         int n;
301         for (n = 1; n < 100; n++) {
302             if (CheckDisplayNumber(n))
303                 break;
304         }
305
306         if (n >= 100)
307             FatalError("-inetd: couldn't find free display number");
308
309         sprintf(inetdDisplayNumStr, "%d", n);
310         display = inetdDisplayNumStr;
311
312         /* fds 0, 1 and 2 (stdin, out and err) are all the same socket to the
313            RFB client.  OsInit() closes stdout and stdin, and we don't want
314            stderr to go to the RFB client, so make the client socket 3 and
315            close stderr.  OsInit() will redirect stderr logging to an
316            appropriate log file or /dev/null if that doesn't work. */
317
318         dup2(0,3);
319         inetdSock = 3;
320         close(2);
321
322         return 1;
323     }
324
325     if (inetdSock != -1 && argv[i][0] == ':') {
326         FatalError("can't specify both -inetd and :displaynumber");
327     }
328
329     return 0;
330 }
331
332
333 /*
334  * InitOutput is called every time the server resets.  It should call
335  * AddScreen for each screen (but we only ever have one), and in turn this
336  * will call rfbScreenInit.
337  */
338
339 void
340 InitOutput(screenInfo, argc, argv)
341     ScreenInfo *screenInfo;
342     int argc;
343     char **argv;
344 {
345     initOutputCalled = TRUE;
346
347     rfbLog("Xvnc version %s - built %s\n", XVNCRELEASE, buildtime);
348     rfbLog("Copyright (C) 2002-2003 RealVNC Ltd.\n");
349     rfbLog("Copyright (C) 1994-2000 AT&T Laboratories Cambridge.\n");
350     rfbLog("All Rights Reserved.\n");
351     rfbLog("See http://www.realvnc.com for information on VNC\n");
352     rfbLog("Desktop name '%s' (%s:%s)\n",desktopName,rfbThisHost,display);
353     rfbLog("Protocol version supported %d.%d\n", rfbProtocolMajorVersion,
354            rfbProtocolMinorVersion);
355
356     VNC_LAST_CLIENT_ID = MakeAtom("VNC_LAST_CLIENT_ID",
357                                   strlen("VNC_LAST_CLIENT_ID"), TRUE);
358     VNC_CONNECT = MakeAtom("VNC_CONNECT", strlen("VNC_CONNECT"), TRUE);
359     VNC_DEFER_UPDATE = MakeAtom("VNC_DEFER_UPDATE",
360                                 strlen("VNC_DEFER_UPDATE"), TRUE);
361     rfbInitSockets();
362     if (inetdSock == -1)
363         httpInitSockets();
364    
365
366     /* initialize pixmap formats */
367
368     screenInfo->imageByteOrder = IMAGE_BYTE_ORDER;
369     screenInfo->bitmapScanlineUnit = BITMAP_SCANLINE_UNIT;
370     screenInfo->bitmapScanlinePad = BITMAP_SCANLINE_PAD;
371     screenInfo->bitmapBitOrder = BITMAP_BIT_ORDER;
372     screenInfo->numPixmapFormats = 2;
373
374     screenInfo->formats[0].depth = 1;
375     screenInfo->formats[0].bitsPerPixel = 1;
376     screenInfo->formats[0].scanlinePad = BITMAP_SCANLINE_PAD;
377
378     screenInfo->formats[1].depth = rfbScreen.depth;
379     screenInfo->formats[1].bitsPerPixel = rfbBitsPerPixel(rfbScreen.depth);
380     screenInfo->formats[1].scanlinePad = BITMAP_SCANLINE_PAD;
381
382     rfbGCIndex = AllocateGCPrivateIndex();
383     if (rfbGCIndex < 0) {
384         FatalError("InitOutput: AllocateGCPrivateIndex failed\n");
385     }
386
387     if (!AddCallback(&ClientStateCallback, rfbClientStateChange, NULL)) {
388         rfbLog("InitOutput: AddCallback failed\n");
389         return;
390     }
391
392     /* initialize screen */
393
394     if (AddScreen(rfbScreenInit, argc, argv) == -1) {
395         FatalError("Couldn't add screen");
396     }
397 }
398
399
400 static Bool
401 rfbScreenInit(index, pScreen, argc, argv)
402     int index;
403     ScreenPtr pScreen;
404     int argc;
405     char ** argv;
406 {
407     rfbScreenInfoPtr prfb = &rfbScreen;
408     int dpix = 75, dpiy = 75;
409     int ret;
410     char *pbits;
411     VisualPtr vis;
412     extern int monitorResolution;
413
414     if (monitorResolution != 0) {
415         dpix = monitorResolution;
416         dpiy = monitorResolution;
417     }
418
419     prfb->paddedWidthInBytes = PixmapBytePad(prfb->width, prfb->depth);
420     prfb->bitsPerPixel = rfbBitsPerPixel(prfb->depth);
421     pbits = rfbAllocateFramebufferMemory(prfb);
422     if (!pbits) return FALSE;
423
424     if (prfb->bitsPerPixel > 1) {
425         extern int defaultColorVisualClass;
426         if (defaultColorVisualClass != -1) {
427             cfbSetVisualTypes(prfb->depth, (1 << defaultColorVisualClass), 8);
428         } else {
429             cfbSetVisualTypes(prfb->depth, (1 << TrueColor), 8);
430         }
431     }
432
433     switch (prfb->bitsPerPixel)
434     {
435     case 1:
436         ret = mfbScreenInit(pScreen, pbits, prfb->width, prfb->height,
437                             dpix, dpiy, prfb->paddedWidthInBytes * 8);
438         break;
439     case 8:
440         ret = cfbScreenInit(pScreen, pbits, prfb->width, prfb->height,
441                             dpix, dpiy, prfb->paddedWidthInBytes);
442         break;
443     case 16:
444         ret = cfb16ScreenInit(pScreen, pbits, prfb->width, prfb->height,
445                               dpix, dpiy, prfb->paddedWidthInBytes / 2);
446         break;
447     case 32:
448         ret = cfb32ScreenInit(pScreen, pbits, prfb->width, prfb->height,
449                               dpix, dpiy, prfb->paddedWidthInBytes / 4);
450         break;
451     default:
452         return FALSE;
453     }
454
455     if (!ret) return FALSE;
456
457     if (!AllocateGCPrivate(pScreen, rfbGCIndex, sizeof(rfbGCRec))) {
458         FatalError("rfbScreenInit: AllocateGCPrivate failed\n");
459     }
460
461     prfb->cursorIsDrawn = FALSE;
462     prfb->dontSendFramebufferUpdate = FALSE;
463
464     prfb->CloseScreen = pScreen->CloseScreen;
465     prfb->CreateGC = pScreen->CreateGC;
466     prfb->PaintWindowBackground = pScreen->PaintWindowBackground;
467     prfb->PaintWindowBorder = pScreen->PaintWindowBorder;
468     prfb->CopyWindow = pScreen->CopyWindow;
469     prfb->ClearToBackground = pScreen->ClearToBackground;
470     prfb->RestoreAreas = pScreen->RestoreAreas;
471
472     pScreen->CloseScreen = rfbCloseScreen;
473     pScreen->CreateGC = rfbCreateGC;
474     pScreen->PaintWindowBackground = rfbPaintWindowBackground;
475     pScreen->PaintWindowBorder = rfbPaintWindowBorder;
476     pScreen->CopyWindow = rfbCopyWindow;
477     pScreen->ClearToBackground = rfbClearToBackground;
478     pScreen->RestoreAreas = rfbRestoreAreas;
479
480     pScreen->InstallColormap = rfbInstallColormap;
481     pScreen->UninstallColormap = rfbUninstallColormap;
482     pScreen->ListInstalledColormaps = rfbListInstalledColormaps;
483     pScreen->StoreColors = rfbStoreColors;
484
485     pScreen->SaveScreen = rfbAlwaysTrue;
486
487     rfbDCInitialize(pScreen, &rfbPointerCursorFuncs);
488
489     if (noCursor) {
490         pScreen->DisplayCursor = rfbAlwaysTrue;
491         prfb->cursorIsDrawn = TRUE;
492     }
493
494     pScreen->blackPixel = prfb->blackPixel;
495     pScreen->whitePixel = prfb->whitePixel;
496
497     for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++)
498         ;
499
500     if (!vis) {
501         rfbLog("rfbScreenInit: couldn't find root visual\n");
502         exit(1);
503     }
504
505     if (strcmp(primaryOrder, "") == 0) {
506       if (prfb->depth == 16) { /* use rgb565 for depth 16 */
507         strcpy(primaryOrder, "rgb");
508         redBits = 5;
509         greenBits = 6;
510         blueBits = 5;
511       } else if (prfb->depth == 24) { /* use rgb888 for depth 24 */
512         strcpy(primaryOrder, "rgb");
513         redBits = 8;
514         greenBits = 8;
515         blueBits = 8;
516       }
517     }
518
519     if (strcasecmp(primaryOrder, "rgb") == 0) {
520         vis->offsetBlue = 0;
521         vis->blueMask = (1 << blueBits) - 1;
522         vis->offsetGreen = blueBits;
523         vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen;
524         vis->offsetRed = vis->offsetGreen + greenBits;
525         vis->redMask = ((1 << redBits) - 1) << vis->offsetRed;
526     } else if (strcasecmp(primaryOrder, "bgr") == 0) {
527         rfbLog("BGR format %d %d %d\n", blueBits, greenBits, redBits);
528         vis->offsetRed = 0;
529         vis->redMask = (1 << redBits) - 1;
530         vis->offsetGreen = redBits;
531         vis->greenMask = ((1 << greenBits) - 1) << vis->offsetGreen;
532         vis->offsetBlue = vis->offsetGreen + greenBits;
533         vis->blueMask = ((1 << blueBits) - 1) << vis->offsetBlue;
534     }
535
536     rfbServerFormat.bitsPerPixel = prfb->bitsPerPixel;
537     rfbServerFormat.depth = prfb->depth;
538     rfbServerFormat.bigEndian = !(*(char *)&rfbEndianTest);
539     rfbServerFormat.trueColour = (vis->class == TrueColor);
540     if (rfbServerFormat.trueColour) {
541         rfbServerFormat.redMax = vis->redMask >> vis->offsetRed;
542         rfbServerFormat.greenMax = vis->greenMask >> vis->offsetGreen;
543         rfbServerFormat.blueMax = vis->blueMask >> vis->offsetBlue;
544         rfbServerFormat.redShift = vis->offsetRed;
545         rfbServerFormat.greenShift = vis->offsetGreen;
546         rfbServerFormat.blueShift = vis->offsetBlue;
547     } else {
548         rfbServerFormat.redMax
549             = rfbServerFormat.greenMax = rfbServerFormat.blueMax = 0;
550         rfbServerFormat.redShift
551             = rfbServerFormat.greenShift = rfbServerFormat.blueShift = 0;
552     }
553
554     if (prfb->bitsPerPixel == 1)
555     {
556         ret = mfbCreateDefColormap(pScreen);
557     }
558     else
559     {
560         ret = cfbCreateDefColormap(pScreen);
561     }
562
563     return ret;
564
565 } /* end rfbScreenInit */
566
567
568
569 /*
570  * InitInput is also called every time the server resets.  It is called after
571  * InitOutput so we can assume that rfbInitSockets has already been called.
572  */
573
574 void
575 InitInput(argc, argv)
576     int argc;
577     char *argv[];
578 {
579     DeviceIntPtr p, k;
580     k = AddInputDevice(rfbKeybdProc, TRUE);
581     p = AddInputDevice(rfbMouseProc, TRUE);
582     RegisterKeyboardDevice(k);
583     RegisterPointerDevice(p);
584     miRegisterPointerDevice(screenInfo.screens[0], p);
585     mieqInit((DevicePtr)k, (DevicePtr)p);
586     mieqCheckForInput[0] = checkForInput[0];
587     mieqCheckForInput[1] = checkForInput[1];
588     SetInputCheck(&alwaysCheckForInput[0], &alwaysCheckForInput[1]);
589 }
590
591
592 static int
593 rfbKeybdProc(pDevice, onoff)
594     DeviceIntPtr pDevice;
595     int onoff;
596 {
597     KeySymsRec          keySyms;
598     CARD8               modMap[MAP_LENGTH];
599     DevicePtr pDev = (DevicePtr)pDevice;
600
601     switch (onoff)
602     {
603     case DEVICE_INIT: 
604         KbdDeviceInit(pDevice, &keySyms, modMap);
605         InitKeyboardDeviceStruct(pDev, &keySyms, modMap,
606                                  (BellProcPtr)rfbSendBell,
607                                  (KbdCtrlProcPtr)NoopDDA);
608             break;
609     case DEVICE_ON: 
610         pDev->on = TRUE;
611         KbdDeviceOn();
612         break;
613     case DEVICE_OFF: 
614         pDev->on = FALSE;
615         KbdDeviceOff();
616         break;
617     case DEVICE_CLOSE:
618         if (pDev->on)
619             KbdDeviceOff();
620         break;
621     }
622     return Success;
623 }
624
625 static int
626 rfbMouseProc(pDevice, onoff)
627     DeviceIntPtr pDevice;
628     int onoff;
629 {
630     BYTE map[6];
631     DevicePtr pDev = (DevicePtr)pDevice;
632
633     switch (onoff)
634     {
635     case DEVICE_INIT:
636         PtrDeviceInit();
637         map[1] = 1;
638         map[2] = 2;
639         map[3] = 3;
640         map[4] = 4;
641         map[5] = 5;
642         InitPointerDeviceStruct(pDev, map, 5, miPointerGetMotionEvents,
643                                 PtrDeviceControl,
644                                 miPointerGetMotionBufferSize());
645         break;
646
647     case DEVICE_ON:
648         pDev->on = TRUE;
649         PtrDeviceOn(pDevice);
650         break;
651
652     case DEVICE_OFF:
653         pDev->on = FALSE;
654         PtrDeviceOff();
655         break;
656
657     case DEVICE_CLOSE:
658         if (pDev->on)
659             PtrDeviceOff();
660         break;
661     }
662     return Success;
663 }
664
665
666 Bool
667 LegalModifier(key, pDev)
668     unsigned int key;
669     DevicePtr   pDev;
670 {
671     return TRUE;
672 }
673
674
675 void
676 ProcessInputEvents()
677 {
678     rfbCheckFds();
679     httpCheckFds();
680     if (*mieqCheckForInput[0] != *mieqCheckForInput[1]) {
681         mieqProcessInputEvents();
682         miPointerUpdate();
683     }
684 }
685
686
687 static Bool CheckDisplayNumber(int n)
688 {
689     char fname[32];
690     int sock;
691     struct sockaddr_in addr;
692
693     sock = socket(AF_INET, SOCK_STREAM, 0);
694     addr.sin_family = AF_INET;
695     addr.sin_addr.s_addr = htonl(INADDR_ANY);
696     addr.sin_port = htons(6000+n);
697     if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
698         close(sock);
699         return FALSE;
700     }
701     close(sock);
702
703     sprintf(fname, "/tmp/.X%d-lock", n);
704     if (access(fname, F_OK) == 0)
705         return FALSE;
706
707     sprintf(fname, "/tmp/.X11-unix/X%d", n);
708     if (access(fname, F_OK) == 0)
709         return FALSE;
710
711     sprintf(fname, "/usr/spool/sockets/X11/%d", n);
712     if (access(fname, F_OK) == 0)
713         return FALSE;
714
715     return TRUE;
716 }
717
718
719 void
720 rfbRootPropertyChange(PropertyPtr pProp)
721 {
722     if ((pProp->propertyName == XA_CUT_BUFFER0) && (pProp->type == XA_STRING)
723         && (pProp->format == 8))
724     {
725         rfbGotXCutText(pProp->data, pProp->size);
726     }
727     else if ((pProp->propertyName == VNC_CONNECT) && (pProp->type == XA_STRING)
728              && (pProp->format == 8))
729     {
730         if (pProp->size == 0) {
731           rfbClientPtr cl, nextCl;
732           rfbLog("VNC_CONNECT message: disconnecting all clients\n");
733           for (cl = rfbClientHead; cl; cl = nextCl) {
734             nextCl = cl->next;
735             rfbCloseSock(cl->sock);
736           }
737         } else {
738           int i;
739           rfbClientPtr cl;
740           int port = 5500;
741           char *host = (char *)Xalloc(pProp->size+1);
742           memcpy(host, pProp->data, pProp->size);
743           host[pProp->size] = 0;
744           for (i = 0; i < pProp->size; i++) {
745             if (host[i] == ':') {
746               port = atoi(&host[i+1]);
747               host[i] = 0;
748             }
749           }
750
751           cl = rfbReverseConnection(host, port);
752
753           free(host);
754         }
755         return;
756     }
757     else if ((pProp->propertyName == VNC_DEFER_UPDATE) &&
758              (pProp->type == XA_STRING) && (pProp->format == 8))
759     {
760       char *str = (char *)Xalloc(pProp->size+1);
761       memcpy(str, pProp->data, pProp->size);
762       str[pProp->size] = 0;
763       rfbDeferUpdateTime = atoi(str);
764       free(str);
765     }
766 }
767
768
769 int
770 rfbBitsPerPixel(depth)
771     int depth;
772 {
773     if (depth == 1) return 1;
774     else if (depth <= 8) return 8;
775     else if (depth <= 16) return 16;
776     else return 32;
777 }
778
779
780 static Bool
781 rfbAlwaysTrue()
782 {
783     return TRUE;
784 }
785
786
787 static char *
788 rfbAllocateFramebufferMemory(prfb)
789     rfbScreenInfoPtr prfb;
790 {
791     if (prfb->pfbMemory) return prfb->pfbMemory; /* already done */
792
793     prfb->sizeInBytes = (prfb->paddedWidthInBytes * prfb->height);
794
795     prfb->pfbMemory = (char *)Xalloc(prfb->sizeInBytes);
796
797     return prfb->pfbMemory;
798 }
799
800
801 static Bool
802 rfbCursorOffScreen (ppScreen, x, y)
803     ScreenPtr   *ppScreen;
804     int         *x, *y;
805 {
806     return FALSE;
807 }
808
809 static void
810 rfbCrossScreen (pScreen, entering)
811     ScreenPtr   pScreen;
812     Bool        entering;
813 {
814 }
815
816 static void
817 rfbClientStateChange(cbl, myData, clt)
818     CallbackListPtr *cbl;
819     pointer myData;
820     pointer clt;
821 {
822     dispatchException &= ~DE_RESET;     /* hack - force server not to reset */
823 }
824
825 void
826 ddxGiveUp()
827 {
828     Xfree(rfbScreen.pfbMemory);
829     if (initOutputCalled) {
830         char unixSocketName[256];
831         sprintf(unixSocketName,"/tmp/.X11-unix/X%s",display);
832         unlink(unixSocketName);
833         sprintf(unixSocketName,"/usr/spool/sockets/X11/%s",display);
834         unlink(unixSocketName);
835     }
836 }
837
838 void
839 AbortDDX()
840 {
841     ddxGiveUp();
842 }
843
844 void
845 OsVendorInit()
846 {
847 }
848
849 void
850 OsVendorFatalError()
851 {
852 }
853
854 #ifdef DDXTIME /* from ServerOSDefines */
855 CARD32
856 GetTimeInMillis()
857 {
858     struct timeval  tp;
859
860     X_GETTIMEOFDAY(&tp);
861     return(tp.tv_sec * 1000) + (tp.tv_usec / 1000);
862 }
863 #endif
864
865 void
866 ddxUseMsg()
867 {
868     ErrorF("\nXvnc version %s - built %s\n\n", XVNCRELEASE, buildtime);
869     ErrorF("-geometry WxH          set framebuffer width & height\n");
870     ErrorF("-depth D               set framebuffer depth\n");
871     ErrorF("-pixelformat format    set pixel format (BGRnnn or RGBnnn)\n");
872     ErrorF("-rfbport port          TCP port for RFB protocol\n");
873     ErrorF("-rfbwait time          max time in ms to wait for RFB client\n");
874     ErrorF("-nocursor              don't put up a cursor\n");
875     ErrorF("-rfbauth passwd-file   use authentication on RFB protocol\n");
876     ErrorF("-httpd dir             serve files via HTTP from here\n");
877     ErrorF("-httpport port         port for HTTP\n");
878     ErrorF("-deferupdate time      time in ms to defer updates "
879                                                              "(default 40)\n");
880     ErrorF("-economictranslate     less memory-hungry translation\n");
881     ErrorF("-maxrects num          max number of rectangles in an update "
882                                                              "(default 50)\n");
883     ErrorF("-desktop name          VNC desktop name (default x11)\n");
884     ErrorF("-alwaysshared          always treat new clients as shared\n");
885     ErrorF("-nevershared           never treat new clients as shared\n");
886     ErrorF("-dontdisconnect        don't disconnect existing clients when a "
887                                                              "new non-shared\n"
888            "                       connection comes in (refuse new connection "
889                                                                  "instead)\n");
890     ErrorF("-localhost             only allow connections from localhost\n");
891     ErrorF("-inetd                 Xvnc is launched by inetd\n");
892     exit(1);
893 }
894
895 /*
896  * rfbLog prints a time-stamped message to the log file (stderr).
897  */
898
899 void rfbLog(char *format, ...)
900 {
901     va_list args;
902     char buf[256];
903     time_t clock;
904
905     va_start(args, format);
906
907     time(&clock);
908     strftime(buf, 255, "%d/%m/%y %T ", localtime(&clock));
909     fprintf(stderr, buf);
910
911     vfprintf(stderr, format, args);
912     fflush(stderr);
913
914     va_end(args);
915 }
916
917 void rfbLogPerror(char *str)
918 {
919     rfbLog("");
920     perror(str);
921 }