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) {
|
||||