Remove x11vnc subdir.

The new x11vnc repo is at https://github.com/LibVNC/x11vnc.
pull/1/head
Christian Beier 9 years ago
parent 8d2db0486d
commit 498d222976

@ -1,5 +0,0 @@
.deps
Makefile
Makefile.in
x11vnc

File diff suppressed because it is too large Load Diff

@ -1,45 +0,0 @@
/*
Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
All rights reserved.
This file is part of x11vnc.
x11vnc 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.
x11vnc 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 x11vnc; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
or see <http://www.gnu.org/licenses/>.
In addition, as a special exception, Karl J. Runge
gives permission to link the code of its release of x11vnc with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables. You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL". If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version.
*/
#ifndef _X11VNC_8TO24_H
#define _X11VNC_8TO24_H
/* -- 8to24.h -- */
extern int multivis_count;
extern int multivis_24count;
extern void check_for_multivis(void);
extern void bpp8to24(int, int, int, int);
extern void mark_8bpp(int);
#endif /* _X11VNC_8TO24_H */

File diff suppressed because it is too large Load Diff

@ -1,43 +0,0 @@
if HAVE_SYSTEM_LIBVNCSERVER
LDADD = @SYSTEM_LIBVNCSERVER_LIBS@ @WSOCKLIB@
else
LDADD = ../libvncserver/libvncserver.la ../libvncclient/libvncclient.la @WSOCKLIB@
endif
if OSX
FRAMEWORKS = -framework ApplicationServices -framework Carbon -framework IOKit -framework Cocoa
if OSX_OPENGL
FRAMEWORKS += -framework OpenGL
if HAVE_X11
GL = /System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
FRAMEWORKS += -dylib_file $(GL):$(GL)
endif
endif
x11vnc_LDFLAGS = $(FRAMEWORKS)
x11vnc_CFLAGS = -ObjC
endif
SUBDIRS = misc
DIST_SUBDIRS = misc
desktopdir = $(datadir)/applications
desktop_DATA = x11vnc.desktop
man_MANS=x11vnc.1
EXTRA_DIST=ChangeLog README RELEASE-NOTES tkx11vnc $(man_MANS) $(desktop_DATA)
if CYGIPC
LD_CYGIPC=-lcygipc
endif
bin_PROGRAMS=x11vnc
x11vnc_SOURCES = 8to24.c appshare.c avahi.c cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c linuxfb.c macosx.c macosxCG.c macosxCGP.c macosxCGS.c macosx_opengl.c options.c pm.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c sslcmds.c sslhelper.c uinput.c unixpw.c user.c userinput.c util.c v4l.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c 8to24.h allowed_input_t.h avahi.h blackout_t.h cleanup.h connections.h cursor.h enc.h enums.h gui.h help.h inet.h keyboard.h linuxfb.h macosx.h macosxCG.h macosxCGP.h macosxCGS.h macosx_opengl.h nox11.h nox11_funcs.h options.h params.h pm.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h sslcmds.h sslhelper.h ssltools.h tkx11vnc.h uinput.h unixpw.h user.h userinput.h util.h v4l.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h
if HAVE_SYSTEM_LIBVNCSERVER
INCLUDES_LIBVNCSERVER = @SYSTEM_LIBVNCSERVER_CFLAGS@
else
INCLUDES_LIBVNCSERVER = -I${top_srcdir}
endif
INCLUDES = $(INCLUDES_LIBVNCSERVER) @X_CFLAGS@ @AVAHI_CFLAGS@
x11vnc_LDADD=$(LDADD) @SSL_LIBS@ @CRYPT_LIBS@ @X_LIBS@ @AVAHI_LIBS@ $(LD_CYGIPC)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -1,46 +0,0 @@
/*
Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
All rights reserved.
This file is part of x11vnc.
x11vnc 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.
x11vnc 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 x11vnc; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
or see <http://www.gnu.org/licenses/>.
In addition, as a special exception, Karl J. Runge
gives permission to link the code of its release of x11vnc with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables. You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL". If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version.
*/
#ifndef _X11VNC_ALLOWED_INPUT_T_H
#define _X11VNC_ALLOWED_INPUT_T_H
/* -- allowed_input_t.h -- */
typedef struct allowed_input {
int keystroke;
int motion;
int button;
int clipboard;
int files;
} allowed_input_t;
#endif /* _X11VNC_ALLOWED_INPUT_T_H */

File diff suppressed because it is too large Load Diff

@ -1,434 +0,0 @@
/*
Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
All rights reserved.
This file is part of x11vnc.
x11vnc 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.
x11vnc 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 x11vnc; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
or see <http://www.gnu.org/licenses/>.
In addition, as a special exception, Karl J. Runge
gives permission to link the code of its release of x11vnc with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables. You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL". If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version.
*/
/* -- avahi.c -- */
#include "x11vnc.h"
#include "connections.h"
#include "cleanup.h"
void avahi_initialise(void);
void avahi_advertise(char *name, char *host, uint16_t port);
void avahi_reset(void);
void avahi_cleanup(void);
static pid_t avahi_pid = 0;
static void kill_avahi_pid(void) {
if (avahi_pid != 0) {
rfbLog("kill_avahi_pid: %d\n", (int) avahi_pid);
kill(avahi_pid, SIGTERM);
avahi_pid = 0;
}
}
static int try_avahi_helper(char *name, char *host, uint16_t port) {
#if LIBVNCSERVER_HAVE_FORK
char *cmd, *p, *path = getenv("PATH"), portstr[32];
int i;
if (!name || !host || !port) {}
/* avahi-publish */
if (no_external_cmds || !cmd_ok("zeroconf")) {
return 0;
}
if (!path) {
return 0;
}
path = strdup(path);
cmd = (char *) malloc(strlen(path) + 100);
sprintf(portstr, "%d", (int) port);
p = strtok(path, ":");
while (p) {
struct stat sbuf;
sprintf(cmd, "%s/avahi-publish", p);
if (stat(cmd, &sbuf) == 0) {
break;
}
sprintf(cmd, "%s/dns-sd", p);
if (stat(cmd, &sbuf) == 0) {
break;
}
sprintf(cmd, "%s/mDNS", p);
if (stat(cmd, &sbuf) == 0) {
break;
}
cmd[0] = '\0';
p = strtok(NULL, ":");
}
free(path);
if (!strcmp(cmd, "")) {
free(cmd);
rfbLog("Could not find an external avahi/zeroconf helper program.\n");
return 0;
}
avahi_pid = fork();
if (avahi_pid < 0) {
rfbLogPerror("fork");
avahi_pid = 0;
free(cmd);
return 0;
}
if (avahi_pid != 0) {
int status;
usleep(500 * 1000);
waitpid(avahi_pid, &status, WNOHANG);
if (kill(avahi_pid, 0) != 0) {
waitpid(avahi_pid, &status, WNOHANG);
avahi_pid = 0;
free(cmd);
return 0;
}
if (! quiet) {
rfbLog("%s helper pid is: %d\n", cmd, (int) avahi_pid);
}
free(cmd);
return 1;
}
for (i=3; i<256; i++) {
close(i);
}
if (strstr(cmd, "/avahi-publish")) {
execlp(cmd, cmd, "-s", name, "_rfb._tcp", portstr, (char *) NULL);
} else {
execlp(cmd, cmd, "-R", name, "_rfb._tcp", ".", portstr, (char *) NULL);
}
exit(1);
#else
if (!name || !host || !port) {}
return 0;
#endif
}
#if !defined(LIBVNCSERVER_HAVE_AVAHI) || !defined(LIBVNCSERVER_HAVE_LIBPTHREAD)
void avahi_initialise(void) {
rfbLog("avahi_initialise: no Avahi support at buildtime.\n");
}
void avahi_advertise(char *name, char *host, uint16_t port) {
char *t;
t = getenv("X11VNC_AVAHI_NAME"); if (t) name = t;
t = getenv("X11VNC_AVAHI_HOST"); if (t) host = t;
t = getenv("X11VNC_AVAHI_PORT"); if (t) port = atoi(t);
if (!try_avahi_helper(name, host, port)) {
rfbLog("avahi_advertise: no Avahi support at buildtime.\n");
avahi = 0;
}
}
void avahi_reset(void) {
kill_avahi_pid();
rfbLog("avahi_reset: no Avahi support at buildtime.\n");
}
void avahi_cleanup(void) {
kill_avahi_pid();
rfbLog("avahi_cleanup: no Avahi support at buildtime.\n");
}
#else
#include <avahi-common/thread-watch.h>
#include <avahi-common/alternative.h>
#include <avahi-client/client.h>
#include <avahi-client/publish.h>
#include <avahi-common/malloc.h>
#include <avahi-common/error.h>
static AvahiThreadedPoll *_poll = NULL;
static AvahiClient *_client = NULL;
static AvahiEntryGroup *_group = NULL;
static int db = 0;
typedef struct {
const char *name;
const char *host;
uint16_t port;
} avahi_service_t;
typedef struct {
char *name;
char *host;
uint16_t port;
} avahi_reg_t;
#define NREG 16
static avahi_reg_t registered[NREG];
void avahi_initialise(void) {
int ret;
static int first = 1;
if (getenv("AVAHI_DEBUG")) {
db = 1;
}
if (first) {
int i;
for (i=0; i<NREG; i++) {
registered[i].name = NULL;
registered[i].host = NULL;
}
first = 0;
}
if (db) fprintf(stderr, "in avahi_initialise\n");
if (_poll) {
if (db) fprintf(stderr, " avahi_initialise: poll not null\n");
return;
}
if (! (_poll = avahi_threaded_poll_new()) ) {
rfbLog("warning: unable to open Avahi poll.\n");
return;
}
_client = avahi_client_new(avahi_threaded_poll_get(_poll),
0, NULL, NULL, &ret);
if (! _client) {
rfbLog("warning: unable to open Avahi client: %s\n",
avahi_strerror(ret));
avahi_threaded_poll_free(_poll);
_poll = NULL;
return;
}
if (avahi_threaded_poll_start(_poll) < 0) {
rfbLog("warning: unable to start Avahi poll.\n");
avahi_client_free(_client);
_client = NULL;
avahi_threaded_poll_free(_poll);
_poll = NULL;
return;
}
if (db) fprintf(stderr, "out avahi_initialise\n");
}
static void _avahi_create_services(char *name, char *host,
uint16_t port);
static void _avahi_entry_group_callback(AvahiEntryGroup *g,
AvahiEntryGroupState state, void *userdata) {
char *new_name;
avahi_service_t *svc = (avahi_service_t *)userdata;
if (db) fprintf(stderr, "in _avahi_entry_group_callback %d 0x%p\n", state, svc);
if (g != _group && _group != NULL) {
rfbLog("avahi_entry_group_callback fatal error (group).\n");
clean_up_exit(1);
}
if (userdata == NULL) {
rfbLog("avahi_entry_group_callback fatal error (userdata).\n");
clean_up_exit(1);
}
switch(state) {
case AVAHI_ENTRY_GROUP_ESTABLISHED:
rfbLog("Avahi group %s established.\n", svc->name);
#if 0 /* is this the segv problem? */
free(svc);
#endif
break;
case AVAHI_ENTRY_GROUP_COLLISION:
new_name = avahi_alternative_service_name(svc->name);
_avahi_create_services(new_name, svc->host, svc->port);
rfbLog("Avahi Entry group collision\n");
avahi_free(new_name);
break;
case AVAHI_ENTRY_GROUP_FAILURE:
rfbLog("Avahi Entry group failure: %s\n",
avahi_strerror(avahi_client_errno(
avahi_entry_group_get_client(g))));
break;
default:
break;
}
if (db) fprintf(stderr, "out _avahi_entry_group_callback\n");
}
static void _avahi_create_services(char *name, char *host, uint16_t port) {
avahi_service_t *svc = (avahi_service_t *)malloc(sizeof(avahi_service_t));
int ret = 0;
if (db) fprintf(stderr, "in _avahi_create_services '%s' '%s' %d\n", name, host, port);
svc->name = name;
svc->host = host;
svc->port = port;
if (!_group) {
if (db) fprintf(stderr, " _avahi_create_services create group\n");
_group = avahi_entry_group_new(_client,
_avahi_entry_group_callback, svc);
}
if (!_group) {
rfbLog("avahi_entry_group_new() failed: %s\n",
avahi_strerror(avahi_client_errno(_client)));
return;
}
ret = avahi_entry_group_add_service(_group, AVAHI_IF_UNSPEC,
AVAHI_PROTO_UNSPEC, 0, name, "_rfb._tcp", NULL, NULL, port, NULL);
if (ret < 0) {
rfbLog("Failed to add _rfb._tcp service: %s\n",
avahi_strerror(ret));
return;
}
ret = avahi_entry_group_commit(_group);
if (ret < 0) {
rfbLog("Failed to commit entry_group:: %s\n",
avahi_strerror(ret));
return;
}
if (db) fprintf(stderr, "out _avahi_create_services\n");
}
void avahi_advertise(char *name, char *host, uint16_t port) {
int i;
char *t;
t = getenv("X11VNC_AVAHI_NAME"); if (t) name = t;
t = getenv("X11VNC_AVAHI_HOST"); if (t) host = t;
t = getenv("X11VNC_AVAHI_PORT"); if (t) port = atoi(t);
if (db) fprintf(stderr, "in avahi_advertise: '%s' '%s' %d\n", name, host, port);
if (!_client) {
if (db) fprintf(stderr, " avahi_advertise client null\n");
return;
}
if (_poll == NULL) {
rfbLog("Avahi poll not initialized.\n");
return;
}
/* well, we just track it ourselves... */
for (i=0; i<NREG; i++) {
if (!registered[i].name) {
continue;
}
if (strcmp(registered[i].name, name)) {
continue;
}
if (strcmp(registered[i].host, host)) {
continue;
}
if (registered[i].port != port) {
continue;
}
if (db) fprintf(stderr, " avahi_advertise already did this one\n");
return;
}
for (i=0; i<NREG; i++) {
if (!registered[i].name) {
registered[i].name = strdup(name);
registered[i].host = strdup(host);
registered[i].port = port;
break;
}
}
avahi_threaded_poll_lock(_poll);
_avahi_create_services(name, host, port >= 5900 ? port : 5900+port);
avahi_threaded_poll_unlock(_poll);
if (db) fprintf(stderr, "out avahi_advertise\n");
}
void avahi_reset(void) {
int i;
if (db) fprintf(stderr, "in avahi_reset\n");
for (i=0; i<NREG; i++) {
if (registered[i].name) {
free(registered[i].name);
registered[i].name = NULL;
}
if (registered[i].host) {
free(registered[i].host);
registered[i].host = NULL;
}
}
if (!_client || !_group) {
if (db) fprintf(stderr, " avahi_reset client/group null\n");
return;
}
avahi_entry_group_reset(_group);
rfbLog("Avahi resetting group.\n");
if (db) fprintf(stderr, "out avahi_reset\n");
}
static void avahi_timeout (int sig) {
rfbLog("sig: %d, avahi_cleanup timed out.\n", sig);
exit(1);
}
void avahi_cleanup(void) {
if (db) fprintf(stderr, "in avahi_cleanup\n");
if (!_client) {
if (db) fprintf(stderr, " avahi_cleanup client null\n");
return;
}
if (db) fprintf(stderr, " avahi_cleanup poll_lock\n");
avahi_threaded_poll_lock(_poll);
if (db) fprintf(stderr, " avahi_cleanup poll_stop\n");
signal(SIGALRM, avahi_timeout);
alarm(3);
avahi_threaded_poll_stop(_poll);
alarm(0);
signal(SIGALRM, SIG_DFL);
if (db) fprintf(stderr, " avahi_cleanup client_free\n");
avahi_client_free(_client);
_client = NULL;
if (db) fprintf(stderr, " avahi_cleanup poll_free\n");
avahi_threaded_poll_free(_poll);
_poll = NULL;
if (db) fprintf(stderr, "out avahi_cleanup\n");
}
#endif

@ -1,43 +0,0 @@
/*
Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
All rights reserved.
This file is part of x11vnc.
x11vnc 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.
x11vnc 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 x11vnc; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
or see <http://www.gnu.org/licenses/>.
In addition, as a special exception, Karl J. Runge
gives permission to link the code of its release of x11vnc with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables. You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL". If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version.
*/
#ifndef _X11VNC_AVAHI_H
#define _X11VNC_AVAHI_H
/* -- avahi.h -- */
extern void avahi_initialise(void);
extern void avahi_advertise(char *name, char *host, uint16_t port);
extern void avahi_reset(void);
extern void avahi_cleanup(void);
#endif /* _X11VNC_AVAHI_H */

@ -1,49 +0,0 @@
/*
Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
All rights reserved.
This file is part of x11vnc.
x11vnc 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.
x11vnc 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 x11vnc; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
or see <http://www.gnu.org/licenses/>.
In addition, as a special exception, Karl J. Runge
gives permission to link the code of its release of x11vnc with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables. You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL". If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version.
*/
#ifndef _X11VNC_BLACKOUT_T_H
#define _X11VNC_BLACKOUT_T_H
/* -- blackout_t.h -- */
typedef struct bout {
int x1, y1, x2, y2;
} blackout_t;
#define BO_MAX 32
typedef struct tbout {
blackout_t bo[BO_MAX]; /* hardwired max rectangles. */
int cover;
int count;
} tile_blackout_t;
#endif /* _X11VNC_BLACKOUT_T_H */

@ -1,769 +0,0 @@
/*
Copyright (C) 2002-2010 Karl J. Runge <runge@karlrunge.com>
All rights reserved.
This file is part of x11vnc.
x11vnc 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.
x11vnc 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 x11vnc; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA
or see <http://www.gnu.org/licenses/>.
In addition, as a special exception, Karl J. Runge
gives permission to link the code of its release of x11vnc with the
OpenSSL project's "OpenSSL" library (or with modified versions of it
that use the same license as the "OpenSSL" library), and distribute
the linked executables. You must obey the GNU General Public License
in all respects for all of the code used other than "OpenSSL". If you
modify this file, you may extend this exception to your version of the
file, but you are not obligated to do so. If you do not wish to do
so, delete this exception statement from your version.
*/
/* -- cleanup.c -- */
#include "x11vnc.h"
#include "xwrappers.h"
#include "xdamage.h"
#include "remote.h"
#include "keyboard.h"
#include "scan.h"
#include "gui.h"
#include "solid.h"
#include "unixpw.h"
#include "sslcmds.h"
#include "sslhelper.h"
#include "connections.h"
#include "macosx.h"
#include "macosxCG.h"
#include "avahi.h"
#include "screen.h"
#include "xrecord.h"
#include "xevents.h"
#include "uinput.h"
/*
* Exiting and error handling routines
*/
int trapped_xerror = 0;
int trapped_xioerror = 0;
int trapped_getimage_xerror = 0;
int trapped_record_xerror = 0;
XErrorEvent *trapped_xerror_event;
/* XXX CHECK BEFORE RELEASE */
int crash_debug = 0;
void clean_shm(int quick);
void clean_up_exit(int ret);
int trap_xerror(Display *d, XErrorEvent *error);
int trap_xioerror(Display *d);
int trap_getimage_xerror(Display *d, XErrorEvent *error);
char *xerror_string(XErrorEvent *error);
void initialize_crash_handler(void);
void initialize_signals(void);
void unset_signals(void);
void close_exec_fds(void);
int known_sigpipe_mode(char *s);
static int exit_flag = 0;
static int exit_sig = 0;
static void clean_icon_mode(void);
static int Xerror(Display *d, XErrorEvent *error);
static int XIOerr(Display *d);
static void crash_shell_help(void);
static void crash_shell(void);
static void interrupted (int sig);
void clean_shm(int quick) {
int i, cnt = 0;
/*
* to avoid deadlock, etc, under quick=1 we just delete the shm
* areas and leave the X stuff hanging.
*/
if (quick) {
shm_delete(&scanline_shm);
shm_delete(&fullscreen_shm);
shm_delete(&snaprect_shm);
} else {
shm_clean(&scanline_shm, scanline);
shm_clean(&fullscreen_shm, fullscreen);
shm_clean(&snaprect_shm, snaprect);
}
/*
* Here we have to clean up quite a few shm areas for all
* the possible tile row runs (40 for 1280), not as robust
* as one might like... sometimes need to run ipcrm(1).
*/
for(i=1; i<=ntiles_x; i++) {
if (i > tile_shm_count) {
break;
}
if (quick) {
shm_delete(&tile_row_shm[i]);
} else {
shm_clean(&tile_row_shm[i], tile_row[i]);
}
cnt++;
if (single_copytile_count && i >= single_copytile_count) {
break;
}
}
if (!quiet && cnt > 0) {
rfbLog("deleted %d tile_row polling images.\n", cnt);
}
}
static void clean_icon_mode(void) {
if (icon_mode && icon_mode_fh) {
fprintf(icon_mode_fh, "quit\n");
fflush(icon_mode_fh);
fclose(icon_mode_fh);
icon_mode_fh = NULL;
if (icon_mode_file) {
unlink(icon_mode_file);
icon_mode_file = NULL;
}
}
}
/*
* Normal exiting
*/
void clean_up_exit(int ret) {
static int depth = 0;
exit_flag = 1;
if (depth++ > 2) {
exit(ret);
}
if (icon_mode) {
clean_icon_mode();
}
/* remove the shm areas: */
clean_shm(0);
stop_stunnel();
if (use_openssl) {
ssl_helper_pid(0, 0); /* killall */
}
if (ssh_pid > 0) {
kill(ssh_pid, SIGTERM);
ssh_pid = 0;
}
#ifdef MACOSX
if (client_connect_file) {
if (strstr(client_connect_file, "/tmp/x11vnc-macosx-remote")
== client_connect_file) {
unlink(client_connect_file);
}
}
if (macosx_console) {
macosxCG_fini();
}
#endif
if (pipeinput_fh != NULL) {
pclose(pipeinput_fh);
pipeinput_fh = NULL;
}
shutdown_uinput();
if (unix_sock) {
if (unix_sock_fd >= 0) {
rfbLog("deleting unix sock: %s\n", unix_sock);
close(unix_sock_fd);
unix_sock_fd = -1;
unlink(unix_sock);
}
}
if (! dpy) { /* raw_rb hack */
if (rm_flagfile) {
unlink(rm_flagfile);
rm_flagfile = NULL;
}
exit(ret);
}
/* X keyboard cleanups */
delete_added_keycodes(0);
if (clear_mods == 1) {
clear_modifiers(0);
} else if (clear_mods == 2) {
clear_keys();
} else if (clear_mods == 3) {
clear_keys();
clear_locks();
}
if (no_autorepeat) {
autorepeat(1, 0);
}
if (use_solid_bg) {
solid_bg(1);
}
if (ncache || ncache0) {
kde_no_animate(1);
}
X_LOCK;
XTestDiscard_wr(dpy);
#if LIBVNCSERVER_HAVE_LIBXDAMAGE
if (xdamage) {
XDamageDestroy(dpy, xdamage);
}
#endif
#if LIBVNCSERVER_HAVE_LIBXTRAP
if (trap_ctx) {
XEFreeTC(trap_ctx);
}
#endif
/* XXX rdpy_ctrl, etc. cannot close w/o blocking */
XCloseDisplay_wr(dpy);
X_UNLOCK;
fflush(stderr);
if (rm_flagfile) {
unlink(rm_flagfile);
rm_flagfile = NULL;
}
if (avahi) {
avahi_cleanup();
fflush(stderr);
}
exit(ret);
}
/* X11 error handlers */
static XErrorHandler Xerror_def;
static XIOErrorHandler XIOerr_def;
int trap_xerror(Display *d, XErrorEvent *error) {
trapped_xerror = 1;
trapped_xerror_event = error;
if (d) {} /* unused vars warning: */
return 0;
}
int trap_xioerror(Display *d) {
trapped_xioerror = 1;
if (d) {} /* unused vars warning: */
return 0;
}
int trap_getimage_xerror(Display *d, XErrorEvent *error) {
trapped_getimage_xerror = 1;
trapped_xerror_event = error;
if (d) {} /* unused vars warning: */
return 0;
}
/* Are silly Xorg people removing X_ShmAttach from XShm.h? */
/* INDEED! What stupid, myopic morons... */
/* Maintenance Monkeys busy typing at their keyboards... */
#ifndef X_ShmAttach
#define X_ShmAttach 1
#endif
static int Xerror(Display *d, XErrorEvent *error) {
X_UNLOCK;
if (getenv("X11VNC_PRINT_XERROR")) {
fprintf(stderr, "Xerror: major_opcode: %d minor_opcode: %d error_code: %d\n",
error->request_code, error->minor_code, error->error_code);
}
if (xshm_opcode > 0 && error->request_code == xshm_opcode) {
if (error->minor_code == X_ShmAttach) {
char *dstr = DisplayString(dpy);
fprintf(stderr, "\nX11 MIT Shared Memory Attach failed:\n");
fprintf(stderr, " Is your DISPLAY=%s on a remote machine?\n", dstr);
if (strstr(dstr, "localhost:")) {
fprintf(stderr, " Note: DISPLAY=localhost:N suggests a SSH X11 redir to a remote machine.\n");
} else if (dstr[0] != ':') {
fprintf(stderr, " Note: DISPLAY=hostname:N suggests a remote display.\n");
}
fprintf(stderr, " Suggestion, use: x11vnc -display :0 ... for local display :0\n\n");
}
}
interrupted(0);
if (d) {} /* unused vars warning: */
return (*Xerror_def)(d, error);
}
void watch_loop(void);
static int XIOerr(Display *d) {
static int reopen = 0, rmax = 1;
X_UNLOCK;
if (getenv("X11VNC_REOPEN_DISPLAY")) {
rmax = atoi(getenv("X11VNC_REOPEN_DISPLAY"));
}
#if !NO_X11
if (reopen < rmax && getenv("X11VNC_REOPEN_DISPLAY")) {
int db = getenv("X11VNC_REOPEN_DEBUG") ? 1 : 0;
int sleepmax = 10, i;
Display *save_dpy = dpy;
char *dstr = strdup(DisplayString(save_dpy));
reopen++;
if (getenv("X11VNC_REOPEN_SLEEP_MAX")) {
sleepmax = atoi(getenv("X11VNC_REOPEN_SLEEP_MAX"));
}
rfbLog("*** XIO error: Trying to reopen[%d/%d] display '%s'\n", reopen, rmax, dstr);
rfbLog("*** XIO error: Note the reopened state may be unstable.\n");
for (i=0; i < sleepmax; i++) {
usleep (1000 * 1000);
dpy = XOpenDisplay_wr(dstr);
rfbLog("dpy[%d/%d]: %p\n", i+1, sleepmax, dpy);
if (dpy) {
break;
}
}
last_open_xdisplay = time(NULL);
if (dpy) {
rfbLog("*** XIO error: Reopened display '%s' successfully.\n", dstr);
if (db) rfbLog("*** XIO error: '%s' 0x%x\n", dstr, dpy);
scr = DefaultScreen(dpy);
rootwin = RootWindow(dpy, scr);
if (db) rfbLog("*** XIO error: disable_grabserver\n");
disable_grabserver(dpy, 0);
if (db) rfbLog("*** XIO error: xrecord\n");
zerodisp_xrecord();
initialize_xrecord();
if (db) rfbLog("*** XIO error: xdamage\n");
create_xdamage_if_needed(1);
if (db) rfbLog("*** XIO error: do_new_fb\n");
if (using_shm) {
if (db) rfbLog("*** XIO error: clean_shm\n");
clean_shm(1);
}
do_new_fb(1);
if (db) rfbLog("*** XIO error: check_xevents\n");
check_xevents(1);
/* sadly, we can never return... */
if (db) rfbLog("*** XIO error: watch_loop\n");
watch_loop();
clean_up_exit(1);
}
}
#endif
interrupted(-1);
if (d) {} /* unused vars warning: */
return (*XIOerr_def)(d);
}
static char *xerrors[] = {
"Success",
"BadRequest",
"BadValue",
"BadWindow",
"BadPixmap",
"BadAtom",
"BadCursor",
"BadFont",
"BadMatch",
"BadDrawable",
"BadAccess",
"BadAlloc",
"BadColor",
"BadGC",
"BadIDChoice",
"BadName",
"BadLength",
"BadImplementation",
"unknown"
};
static int xerrors_max = BadImplementation;
char *xerror_string(XErrorEvent *error) {
int index = -1;
if (error) {
index = (int) error->error_code;
}
if (0 <= index && index <= xerrors_max) {
return xerrors[index];
} else {
return xerrors[xerrors_max+1];
}
}
static char *crash_stack_command1 = NULL;
static char *crash_stack_command2 = NULL;
static char *crash_debug_command = NULL;
void initialize_crash_handler(void) {
int pid = program_pid;
crash_stack_command1 = (char *) malloc(1000);
crash_stack_command2 = (char *) malloc(1000);
crash_debug_command = (char *) malloc(1000);
snprintf(crash_stack_command1, 500, "echo where > /tmp/gdb.%d;"
" env PATH=$PATH:/usr/local/bin:/usr/sfw/bin:/usr/bin"
" gdb -x /tmp/gdb.%d -batch -n %s %d;"
" rm -f /tmp/gdb.%d", pid, pid, program_name, pid, pid);
snprintf(crash_stack_command2, 500, "pstack %d", program_pid);
snprintf(crash_debug_command, 500, "gdb %s %d", program_name, pid);
}
static void crash_shell_help(void) {
int pid = program_pid;
fprintf(stderr, "\n");
fprintf(stderr, " *** Welcome to the x11vnc crash shell! ***\n");
fprintf(stderr, "\n");
fprintf(stderr, "PROGRAM: %s PID: %d\n", program_name, pid);
fprintf(stderr, "\n");
fprintf(stderr, "POSSIBLE DEBUGGER COMMAND:\n");
fprintf(stderr, "\n");
fprintf(stderr, " %s\n", crash_debug_command);
fprintf(stderr, "\n");
fprintf(stderr, "Press \"q\" to quit.\n");
fprintf(stderr, "Press \"h\" or \"?\" for this help.\n");
fprintf(stderr, "Press \"s\" to try to run some commands to"
" show a stack trace (gdb/pstack).\n");
fprintf(stderr, "\n");
fprintf(stderr, "Anything else is passed to -Q query function.\n");
fprintf(stderr, "\n");
}
static void crash_shell(void) {
char qry[1000], cmd[1000], line[1000];
char *str, *p;
crash_shell_help();
fprintf(stderr, "\ncrash> ");
while (fgets(line, 1000, stdin) != NULL) {
str = lblanks(line);
p = str;
while(*p) {
if (*p == '\n') {
*p = '\0';
}
p++;
}
if (*str == 'q' && *(str+1) == '\0') {
fprintf(stderr, "quiting.\n");
return;
} else if (*str == 'h' && *(str+1) == '\0') {
crash_shell_help();
} else if (*str == '?' && *(str+1) == '\0') {
crash_shell_help();
} else if (*str == 's' && *(str+1) == '\0') {
sprintf(cmd, "sh -c '(%s) &'", crash_stack_command1);
/* crash */
if (no_external_cmds || !cmd_ok("crash")) {
fprintf(stderr, "\nno_external_cmds=%d\n",
no_external_cmds);
goto crash_prompt;
}
fprintf(stderr, "\nrunning:\n\t%s\n\n",
crash_stack_command1);
system(cmd);
usleep(1000*1000);
sprintf(cmd, "sh -c '(%s) &'", crash_stack_command2);
fprintf(stderr, "\nrunning:\n\t%s\n\n",
crash_stack_command2);
system(cmd);
usleep(1000*1000);
} else {
snprintf(qry, 1000, "qry=%s", str);
p = process_remote_cmd(qry, 1);
fprintf(stderr, "\n\nresult:\n%s\n", p);
free(p);
}
crash_prompt:
fprintf(stderr, "crash> ");
}
}
/*
* General problem handler
*/
static void interrupted (int sig) {
exit_sig = sig;
if (exit_flag) {
fprintf(stderr, "extra[%d] signal: %d\n", exit_flag, sig);
exit_flag++;
if (use_threads) {
usleep2(250 * 1000);
} else if (exit_flag <= 2) {
return;
}
if (rm_flagfile) {
unlink(rm_flagfile);
rm_flagfile = NULL;
}
exit(4);
}
exit_flag++;
if (sig == 0) {
fprintf(stderr, "caught X11 error:\n");
if (crash_debug) { crash_shell(); }
} else if (sig == -1) {
fprintf(stderr, "caught XIO error:\n");
} else {
fprintf(stderr, "caught signal: %d\n", sig);
}
if (sig == SIGINT) {
shut_down = 1;
return;
}
if (crash_debug) {
crash_shell();
}
X_UNLOCK;
if (icon_mode) {
clean_icon_mode();
}
/* remove the shm areas with quick=1: */
clean_shm(1);
if (sig == -1) {
/* not worth trying any more cleanup, X server probably gone */
if (rm_flagfile) {
unlink(rm_flagfile);
rm_flagfile = NULL;
}
exit(3);
}
/* X keyboard cleanups */
delete_added_keycodes(0);
if (clear_mods == 1) {
clear_modifiers(0);
} else if (clear_mods == 2) {
clear_keys();
} else if (clear_mods == 3) {
clear_keys();
clear_locks();
}
if (no_autorepeat) {
autorepeat(1, 0);
}
if (use_solid_bg) {
solid_bg(1);
}
if (ncache || ncache0) {
kde_no_animate(1);
}
stop_stunnel();
if (crash_debug) {
crash_shell();
}
if (sig) {
if (rm_flagfile) {
unlink(rm_flagfile);
rm_flagfile = NULL;
}
exit(2);
}
}
static void ignore_sigs(char *list) {
char *str, *p;
int ignore = 1;
if (list == NULL || *list == '\0') {
return;
}
str = strdup(list);
p = strtok(str, ":,");
#define SETSIG(x, y) \
if (strstr(p, x)) { \
if (ignore) { \
signal(y, SIG_IGN); \
} else { \
signal(y, interrupted); \
} \
}
#ifdef SIG_IGN
while (p) {
if (!strcmp(p, "ignore")) {
ignore = 1;
} else if (!strcmp(p, "exit")) {
ignore = 0;
}
/* Take off every 'sig' ;-) */
#ifdef SIGHUP
SETSIG("HUP", SIGHUP);
#endif
#ifdef SIGINT
SETSIG("INT", SIGINT);
#endif
#ifdef SIGQUIT
SETSIG("QUIT", SIGQUIT);
#endif
#ifdef SIGTRAP
SETSIG("TRAP", SIGTRAP);
#endif
#ifdef SIGABRT
SETSIG("ABRT", SIGABRT);
#endif
#ifdef SIGBUS
SETSIG("BUS", SIGBUS);
#endif
#ifdef SIGFPE
SETSIG("FPE", SIGFPE);
#endif
#ifdef SIGSEGV
SETSIG("SEGV", SIGSEGV);
#endif
#ifdef SIGPIPE
SETSIG("PIPE", SIGPIPE);
#endif
#ifdef SIGTERM
SETSIG("TERM", SIGTERM);
#endif
#ifdef SIGUSR1
SETSIG("USR1", SIGUSR1);
#endif
#ifdef SIGUSR2
SETSIG("USR2", SIGUSR2);
#endif
#ifdef SIGCONT
SETSIG("CONT", SIGCONT);
#endif
#ifdef SIGSTOP
SETSIG("STOP", SIGSTOP);
#endif
#ifdef SIGTSTP
SETSIG("TSTP", SIGTSTP);
#endif
p = strtok(NULL, ":,");
}
#endif /* SIG_IGN */
free(str);
}
/* signal handlers */
void initialize_signals(void) {
signal(SIGHUP, interrupted);
signal(SIGINT, interrupted);
signal(SIGQUIT, interrupted);
signal(SIGABRT, interrupted);
signal(SIGTERM, interrupted);
signal(SIGBUS, interrupted);
signal(SIGSEGV, interrupted);
signal(SIGFPE, interrupted);
if (!sigpipe || *sigpipe == '\0' || !strcmp(sigpipe, "skip")) {
;
} else if (strstr(sigpipe, "ignore:") == sigpipe) {
ignore_sigs(sigpipe);
} else if (strstr(sigpipe, "exit:") == sigpipe) {
ignore_sigs(sigpipe);
} else if (!strcmp(sigpipe, "ignore")) {
#ifdef SIG_IGN
signal(SIGPIPE, SIG_IGN);
#endif
} else if (!strcmp(sigpipe, "exit")) {
rfbLog("initialize_signals: will exit on SIGPIPE\n");
signal(SIGPIPE, interrupted);
}
#if NO_X11
return;
#else
X_LOCK;
Xerror_def = XSetErrorHandler(Xerror);
XIOerr_def = XSetIOErrorHandler(XIOerr);
X_UNLOCK;
#endif /* NO_X11 */
}
void unset_signals(void) {
signal(SIGHUP, SIG_DFL);
signal(SIGINT, SIG_DFL);
signal(SIGQUIT, SIG_DFL);
signal(SIGABRT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGBUS, SIG_DFL);
signal(SIGSEGV, SIG_DFL);
signal(SIGFPE, SIG_DFL);
signal(SIGPIPE, SIG_DFL);
}
void close_exec_fds(void) {