x11vnc: the big split.

pull/1/head
runge 18 years ago
parent def3012663
commit 71f2ec7918

@ -1,3 +1,7 @@
2006-01-08 Karl Runge <runge@karlrunge.com>
* x11vnc: the big split. (and -afteraccept and -passwdfile read:..)
* examples/pnmshow24.c: fix typo.
2006-01-08 Karl Runge <runge@karlrunge.com>
* libvncclient/vncviewer.c: fix non-jpeg/libz builds.
* examples/pnmshow24.c: fix non-ALLOW24BPP builds.

@ -4,7 +4,8 @@
#ifndef LIBVNCSERVER_ALLOW24BPP
int main() {
printf("I need the ALLOW24BPP LibVNCSever flag to work\n");
printf("I need the ALLOW24BPP LibVNCServer flag to work\n");
exit(1);
}
#else

@ -1,3 +1,6 @@
2006-01-08 Karl Runge <runge@karlrunge.com>
* x11vnc: the big split. opts: -afteraccept and -passwdfile read:
2005-12-24 Karl Runge <runge@karlrunge.com>
* x11vnc: enhance -passwdfile features, filetransfer on by default,
call rfbRegisterTightVNCFileTransferExtension() earlier.

@ -13,7 +13,7 @@ endif
if HAVE_X
bin_PROGRAMS=x11vnc
x11vnc_SOURCES=x11vnc.c tkx11vnc.h
x11vnc_SOURCES = cleanup.c connections.c cursor.c gui.c help.c inet.c keyboard.c options.c pointer.c rates.c remote.c scan.c screen.c selection.c solid.c user.c userinput.c util.c win_utils.c x11vnc.c x11vnc_defs.c xdamage.c xevents.c xinerama.c xkb_bell.c xrandr.c xrecord.c xwrappers.c allowed_input_t.h blackout_t.h cleanup.h connections.h cursor.h enums.h gui.h help.h inet.h keyboard.h options.h params.h pointer.h rates.h remote.h scan.h screen.h scrollevent_t.h selection.h solid.h tkx11vnc.h user.h userinput.h util.h win_utils.h winattr_t.h x11vnc.h xdamage.h xevents.h xinerama.h xkb_bell.h xrandr.h xrecord.h xwrappers.h
INCLUDES=@X_CFLAGS@
x11vnc_LDADD=@X_LIBS@ $(LD_CYGIPC) $(LDADD)
endif

File diff suppressed because it is too large Load Diff

@ -0,0 +1,12 @@
#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;
} allowed_input_t;
#endif /* _X11VNC_ALLOWED_INPUT_T_H */

@ -0,0 +1,17 @@
#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 */

@ -0,0 +1,427 @@
/* -- 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"
/*
* 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);
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;
if (raw_fb) quick = 1; /* raw_fb hack */
/*
* 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) {
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) {
exit_flag = 1;
if (icon_mode) {
clean_icon_mode();
}
/* remove the shm areas: */
clean_shm(0);
if (! dpy) exit(ret); /* raw_rb hack */
/* X keyboard cleanups */
delete_added_keycodes(0);
if (clear_mods == 1) {
clear_modifiers(0);
} else if (clear_mods == 2) {
clear_keys();
}
if (no_autorepeat) {
autorepeat(1, 0);
}
if (use_solid_bg) {
solid_bg(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(dpy);
X_UNLOCK;
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;
}
static int Xerror(Display *d, XErrorEvent *error) {
X_UNLOCK;
interrupted(0);
if (d) {} /* unused vars warning: */
return (*Xerror_def)(d, error);
}
static int XIOerr(Display *d) {
X_UNLOCK;
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);
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);
}
fprintf(stderr, "crash> ");
}
}
/*
* General problem handler
*/
static void interrupted (int sig) {
exit_sig = sig;
if (exit_flag) {
exit_flag++;
if (use_threads) {
usleep2(250 * 1000);
} else if (exit_flag <= 2) {
return;
}
exit(4);
}
exit_flag++;
if (sig == 0) {
fprintf(stderr, "caught X11 error:\n");
} 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;
}
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 */
exit(3);
}
/* X keyboard cleanups */
delete_added_keycodes(0);
if (clear_mods == 1) {
clear_modifiers(0);
} else if (clear_mods == 2) {
clear_keys();
}
if (no_autorepeat) {
autorepeat(1, 0);
}
if (use_solid_bg) {
solid_bg(1);
}
if (crash_debug) {
crash_shell();
}
if (sig) {
exit(2);
}
}
/* 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 (!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);
}
X_LOCK;
Xerror_def = XSetErrorHandler(Xerror);
XIOerr_def = XSetIOErrorHandler(XIOerr);
X_UNLOCK;
}
int known_sigpipe_mode(char *s) {
/*
* skip, ignore, exit
*/
if (strcmp(s, "skip") && strcmp(s, "ignore") &&
strcmp(s, "exit")) {
return 0;
} else {
return 1;
}
}

@ -0,0 +1,25 @@
#ifndef _X11VNC_CLEANUP_H
#define _X11VNC_CLEANUP_H
/* -- cleanup.h -- */
extern int trapped_xerror;
extern int trapped_xioerror;
extern int trapped_getimage_xerror;
extern int trapped_record_xerror;
extern XErrorEvent *trapped_xerror_event;
extern int crash_debug;
extern void clean_shm(int quick);
extern void clean_up_exit (int ret);
extern int trap_xerror(Display *d, XErrorEvent *error);
extern int trap_xioerror(Display *d);
extern int trap_getimage_xerror(Display *d, XErrorEvent *error);
extern char *xerror_string(XErrorEvent *error);
extern void initialize_crash_handler(void);
extern void initialize_signals(void);
extern int known_sigpipe_mode(char *s);
#endif /* _X11VNC_CLEANUP_H */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,26 @@
#ifndef _X11VNC_CONNECTIONS_H
#define _X11VNC_CONNECTIONS_H
/* -- connections.h -- */
extern char vnc_connect_str[];
extern Atom vnc_connect_prop;
extern int all_clients_initialized(void);
extern char *list_clients(void);
extern int new_fb_size_clients(rfbScreenInfoPtr s);
extern void close_all_clients(void);
extern void close_clients(char *str);
extern void set_client_input(char *str);
extern void set_child_info(void);
extern void reverse_connect(char *str);
extern void set_vnc_connect_prop(char *str);
extern void read_vnc_connect_prop(void);
extern void check_connect_inputs(void);
extern void check_gui_inputs(void);
extern enum rfbNewClientAction new_client(rfbClientPtr client);
extern void start_client_info_sock(char *host_port_cookie);
extern void send_client_info(char *str);
extern void check_new_clients(void);
#endif /* _X11VNC_CONNECTIONS_H */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,33 @@
#ifndef _X11VNC_CURSOR_H
#define _X11VNC_CURSOR_H
/* -- cursor.h -- */
extern int xfixes_present;
extern int use_xfixes;
extern int got_xfixes_cursor_notify;
extern int cursor_changes;
extern int alpha_threshold;
extern double alpha_frac;
extern int alpha_remove;
extern int alpha_blend;
extern int alt_arrow;
extern int alt_arrow_max;
extern void first_cursor(void);
extern void setup_cursors_and_push(void);
extern void initialize_xfixes(void);
extern int known_cursors_mode(char *s);
extern void initialize_cursors_mode(void);
extern int get_which_cursor(void);
extern void restore_cursor_shape_updates(rfbScreenInfoPtr s);
extern void disable_cursor_shape_updates(rfbScreenInfoPtr s);
extern int cursor_shape_updates_clients(rfbScreenInfoPtr s);
extern int cursor_pos_updates_clients(rfbScreenInfoPtr s);
extern void cursor_position(int x, int y);
extern void set_no_cursor(void);
extern int set_cursor(int x, int y, int which);
extern int check_x11_pointer(void);
#endif /* _X11VNC_CURSOR_H */

@ -0,0 +1,22 @@
#ifndef _X11VNC_ENUMS_H
#define _X11VNC_ENUMS_H
/* -- enums.h -- */
enum {
LR_UNSET = 0,
LR_UNKNOWN,
LR_DIALUP,
LR_BROADBAND,
LR_LAN
};
enum scroll_types {
SCR_NONE = 0,
SCR_MOUSE,
SCR_KEY,
SCR_FAIL,
SCR_SUCCESS
};
#endif /* _X11VNC_ENUMS_H */

@ -0,0 +1,638 @@
/* -- gui.c -- */
#include "x11vnc.h"
#include "xevents.h"
#include "win_utils.h"
#include "remote.h"
#include "cleanup.h"
#include "tkx11vnc.h"
#define SYSTEM_TRAY_REQUEST_DOCK 0
#define SYSTEM_TRAY_BEGIN_MESSAGE 1
#define SYSTEM_TRAY_CANCEL_MESSAGE 2
#define XEMBED_VERSION 0
#define XEMBED_MAPPED (1 << 0)
int icon_mode = 0; /* hack for -gui tray */
char *icon_mode_file = NULL;
FILE *icon_mode_fh = NULL;
int icon_mode_socks[ICON_MODE_SOCKS];
int tray_manager_ok = 0;
Window tray_request = None;
Window tray_window = None;
int tray_unembed = 0;
char *get_gui_code(void);
int tray_embed(Window iconwin, int remove);
void do_gui(char *opts, int sleep);
static Window tweak_tk_window_id(Window win);
static int tray_manager_running(Display *d, Window *manager);
static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc,
int simple_gui, pid_t parent, char *gui_opts);
char *get_gui_code(void) {
return gui_code;
}
static Window tweak_tk_window_id(Window win) {
char *name = NULL;
Window parent, new;
/* hack for tk, does not report outermost window */
new = win;
parent = parent_window(win, &name);
if (parent && name != NULL) {
lowercase(name);
if (strstr(name, "wish") || strstr(name, "x11vnc")) {
new = parent;
rfbLog("tray_embed: using parent: %s\n", name);
}
}
if (name != NULL) {
XFree(name);
}
return new;
}
int tray_embed(Window iconwin, int remove) {
XEvent ev;
XErrorHandler old_handler;
Window manager;
Atom xembed_info;
Atom tatom;
XWindowAttributes attr;
long info[2] = {XEMBED_VERSION, XEMBED_MAPPED};
long data = 0;
if (remove) {
if (!valid_window(iconwin, &attr, 1)) {
return 0;
}
iconwin = tweak_tk_window_id(iconwin);
trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror);
/*
* unfortunately no desktops seem to obey this
* part of the XEMBED spec yet...
*/
XReparentWindow(dpy, iconwin, rootwin, 0, 0);
XSetErrorHandler(old_handler);
if (trapped_xerror) {
trapped_xerror = 0;
return 0;
}
trapped_xerror = 0;
return 1;
}
xembed_info = XInternAtom(dpy, "_XEMBED_INFO", False);
if (xembed_info == None) {
return 0;
}
if (!tray_manager_running(dpy, &manager)) {
return 0;
}
memset(&ev, 0, sizeof(ev));
ev.xclient.type = ClientMessage;
ev.xclient.window = manager;
ev.xclient.message_type = XInternAtom(dpy, "_NET_SYSTEM_TRAY_OPCODE",
False);
ev.xclient.format = 32;
ev.xclient.data.l[0] = CurrentTime;
ev.xclient.data.l[1] = SYSTEM_TRAY_REQUEST_DOCK;
ev.xclient.data.l[2] = iconwin;
ev.xclient.data.l[3] = 0;
ev.xclient.data.l[4] = 0;
if (!valid_window(iconwin, &attr, 1)) {
return 0;
}
iconwin = tweak_tk_window_id(iconwin);
ev.xclient.data.l[2] = iconwin;
XUnmapWindow(dpy, iconwin);
trapped_xerror = 0;
old_handler = XSetErrorHandler(trap_xerror);
XSendEvent(dpy, manager, False, NoEventMask, &ev);
XSync(dpy, False);
if (trapped_xerror) {
XSetErrorHandler(old_handler);
trapped_xerror = 0;
return 0;
}
XChangeProperty(dpy, iconwin, xembed_info, xembed_info, 32,
PropModeReplace, (unsigned char *)&info, 2);
/* kludge for KDE evidently needed... */
tatom = XInternAtom(dpy, "KWM_DOCKWINDOW", False);
XChangeProperty(dpy, iconwin, tatom, tatom, 32, PropModeReplace,
(unsigned char *)&data, 1);
tatom = XInternAtom(dpy, "_KDE_NET_WM_SYSTEM_TRAY_WINDOW_FOR", False);
XChangeProperty(dpy, iconwin, tatom, XA_WINDOW, 32, PropModeReplace,
(unsigned char *)&data, 1);
XSetErrorHandler(old_handler);
trapped_xerror = 0;
return 1;
}
static int tray_manager_running(Display *d, Window *manager) {
char tray_string[100];
Atom tray_manager;
Window tray_win;
if (manager) {
*manager = None;
}
sprintf(tray_string, "_NET_SYSTEM_TRAY_S%d", scr);
tray_manager = XInternAtom(d, tray_string, True);
if (tray_manager == None) {
return 0;
}
tray_win = XGetSelectionOwner(d, tray_manager);
if (manager) {
*manager = tray_win;
}
if (tray_win == None) {
return 0;
} else {
return 1;
}
}
static char *gui_geometry = NULL;
static int icon_in_tray = 0;
static char *icon_mode_embed_id = NULL;
static char *icon_mode_font = NULL;
static char *icon_mode_params = NULL;
static void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int start_x11vnc,
int simple_gui, pid_t parent, char *gui_opts) {
char *x11vnc_xdisplay = NULL;
char extra_path[] = ":/usr/local/bin:/usr/bin/X11:/usr/sfw/bin"
":/usr/X11R6/bin:/usr/openwin/bin:/usr/dt/bin";
char cmd[100];
char *wish = NULL, *orig_path, *full_path, *tpath, *p;
char *old_xauth = NULL;
int try_max = 4, sleep = 300;
pid_t mypid = getpid();
FILE *pipe, *tmpf;
if (*gui_code == '\0') {
rfbLog("gui: gui not compiled into this program.\n");
exit(0);
}
if (getenv("DISPLAY") != NULL) {
/* worst case */
x11vnc_xdisplay = strdup(getenv("DISPLAY"));
}
if (use_dpy) {
/* better */
x11vnc_xdisplay = strdup(use_dpy);
}
if (connect_to_x11vnc) {
int rc, i;
rfbLogEnable(1);
if (! client_connect_file) {
if (getenv("XAUTHORITY") != NULL) {
old_xauth = strdup(getenv("XAUTHORITY"));
} else {
old_xauth = strdup("");
}
dpy = XOpenDisplay(x11vnc_xdisplay);
if (! dpy && auth_file) {
set_env("XAUTHORITY", auth_file);
dpy = XOpenDisplay(x11vnc_xdisplay);
}
if (! dpy && ! x11vnc_xdisplay) {
/* worstest case */
x11vnc_xdisplay = strdup(":0");
dpy = XOpenDisplay(x11vnc_xdisplay);
}
if (! dpy) {
rfbLog("gui: could not open x11vnc "
"display: %s\n", NONUL(x11vnc_xdisplay));
exit(1);
}
scr = DefaultScreen(dpy);
rootwin = RootWindow(dpy, scr);
initialize_vnc_connect_prop();
}
usleep(2200*1000);
fprintf(stderr, "\n");
if (!quiet) {
rfbLog("gui: trying to contact a x11vnc server at X"
" display %s ...\n", NONUL(x11vnc_xdisplay));
}
for (i=0; i<try_max; i++) {
usleep(sleep*1000);
if (!quiet) {
rfbLog("gui: pinging %s try=%d ...\n",
NONUL(x11vnc_xdisplay), i+1);
}
rc = send_remote_cmd("qry=ping", 1, 1);
if (rc == 0) {
break;
}
if (parent && mypid != parent && kill(parent, 0) != 0) {
rfbLog("gui: parent process %d has gone"
" away: bailing out.\n", parent);
rc = 1;
break;
}
}
set_env("X11VNC_XDISPLAY", x11vnc_xdisplay);
if (getenv("XAUTHORITY") != NULL) {
set_env("X11VNC_AUTH_FILE", getenv("XAUTHORITY"));
}
if (rc == 0) {
rfbLog("gui: ping succeeded.\n");
set_env("X11VNC_CONNECT", "1");
} else {
rfbLog("gui: could not connect to: '%s', try"
" again manually.\n", x11vnc_xdisplay);
}
if (client_connect_file) {
set_env("X11VNC_CONNECT_FILE", client_connect_file);
}
if (dpy) {
XCloseDisplay(dpy);
dpy = NULL;
}
if (old_xauth) {
if (*old_xauth == '\0') {
/* wasn't set, hack it out if it is now */
char *xauth = getenv("XAUTHORITY");
if (xauth) {
*(xauth-2) = '_'; /* yow */
}
} else {
set_env("XAUTHORITY", old_xauth);
}
free(old_xauth);
}
rfbLogEnable(0);
}
orig_path = getenv("PATH");
if (! orig_path) {
orig_path = strdup("/bin:/usr/bin:/usr/bin/X11");
}
full_path = (char *) malloc(strlen(orig_path)+strlen(extra_path)+1);
strcpy(full_path, orig_path);
strcat(full_path, extra_path);
tpath = strdup(full_path);
p = strtok(tpath, ":");
while (p) {
char *try;
struct stat sbuf;
char *wishes[] = {"wish", "wish8.3", "wish8.4", "wish8.5",
"wish8.0"};
int nwishes = 3, i;
try = (char *) malloc(strlen(p) + 1 + strlen("wish8.4") + 1);
for (i=0; i<nwishes; i++) {
sprintf(try, "%s/%s", p, wishes[i]);
if (stat(try, &sbuf) == 0) {
/* assume executable, should check mode */
wish = wishes[i];
}
}
free(try);
if (wish) {
break;
}
p = strtok(NULL, ":");
}
free(tpath);
if (!wish) {
wish = strdup("wish");
}
set_env("PATH", full_path);
set_env("DISPLAY", gui_xdisplay);
set_env("X11VNC_PROG", program_name);
set_env("X11VNC_CMDLINE", program_cmdline);
set_env("X11VNC_WISHCMD", wish);
if (simple_gui) {
set_env("X11VNC_SIMPLE_GUI", "1");
}
if (gui_opts) {
set_env("X11VNC_GUI_PARAMS", gui_opts);
}
if (gui_geometry) {
set_env("X11VNC_GUI_GEOM", gui_geometry);
}
if (start_x11vnc) {
set_env("X11VNC_STARTED", "1");
}
if (icon_mode) {
set_env("X11VNC_ICON_MODE", "1");
if (icon_mode_file) {
set_env("X11VNC_CLIENT_FILE", icon_mode_file);
}
if (icon_in_tray) {
if (tray_manager_ok) {
set_env("X11VNC_ICON_MODE", "TRAY:RUNNING");
} else {
set_env("X11VNC_ICON_MODE", "TRAY");
}
} else {
set_env("X11VNC_ICON_MODE", "ICON");
}
if (icon_mode_params) {
char *p, *str = strdup(icon_mode_params);
p = strtok(str, ":-/,.+");
while (p) {
if(strstr(p, "setp") == p) {
set_env("X11VNC_ICON_SETPASS", "1");
} else if(strstr(p, "noadvanced") == p) {
set_env("X11VNC_ICON_NOADVANCED", "1");
} else if(strstr(p, "minimal") == p) {
set_env("X11VNC_ICON_MINIMAL", "1");
} else if (strstr(p, "0x") == p) {
set_env("X11VNC_ICON_EMBED_ID", p);
icon_mode_embed_id = strdup(p);
}
p = strtok(NULL, ":-/,.+");
}
free(str);
}
}
if (icon_mode_font) {
set_env("X11VNC_ICON_FONT", icon_mode_font);
}
if (no_external_cmds) {
fprintf(stderr, "cannot run external commands in -nocmds "
"mode:\n");
fprintf(stderr, " \"%s\"\n", "gui + wish");
fprintf(stderr, " exiting.\n");
fflush(stderr);
exit(1);
}
tmpf = tmpfile();
if (tmpf == NULL) {
/* if no tmpfile, use a pipe */
if (icon_mode_embed_id) {
if (strlen(icon_mode_embed_id) < 20) {
strcat(cmd, " -use ");
strcat(cmd, icon_mode_embed_id);
}
}
pipe = popen(cmd, "w");
if (! pipe) {
fprintf(stderr, "could not run: %s\n", cmd);
perror("popen");
}
fprintf(pipe, "%s", gui_code);
pclose(pipe);
} else {
/*
* we prefer a tmpfile since then this x11vnc process
* will then be gone, otherwise the x11vnc program text
* will still be in use.
*/
int n = fileno(tmpf);
fprintf(tmpf, "%s", gui_code);
fflush(tmpf);
rewind(tmpf);
dup2(n, 0);
close(n);
if (icon_mode_embed_id) {
execlp(wish, wish, "-", "-use", icon_mode_embed_id,
(char *) NULL);
} else {
execlp(wish, wish, "-", (char *) NULL);
}
fprintf(stderr, "could not exec wish: %s -\n", wish);
perror("execlp");
}
exit(0);
}
void do_gui(char *opts, int sleep) {
char *s, *p;
char *old_xauth = NULL;
char *gui_xdisplay = NULL;
int got_gui_xdisplay = 0;
int start_x11vnc = 1;
int connect_to_x11vnc = 0;
int simple_gui = 0, none_gui = 0;
Display *test_dpy;
if (opts) {
s = strdup(opts);
} else {
s = strdup("");
}
if (use_dpy) {
/* worst case */
gui_xdisplay = strdup(use_dpy);
}
if (getenv("DISPLAY") != NULL) {
/* better */
gui_xdisplay = strdup(getenv("DISPLAY"));
}
p = strtok(s, ",");
while(p) {
if (*p == '\0') {
;
} else if (strchr(p, ':') != NULL) {
/* best */
if (gui_xdisplay) {
free(gui_xdisplay);
}
gui_xdisplay = strdup(p);
got_gui_xdisplay = 1;
} else if (!strcmp(p, "wait")) {
start_x11vnc = 0;
connect_to_x11vnc = 0;
} else if (!strcmp(p, "none")) {
none_gui = 1;
} else if (!strcmp(p, "conn") || !strcmp(p, "connect")) {
start_x11vnc = 0;
connect_to_x11vnc = 1;
} else if (!strcmp(p, "ez") || !strcmp(p, "simple")) {
simple_gui = 1;
} else if (strstr(p, "iconfont") == p) {
char *q;
if ((q = strchr(p, '=')) != NULL) {
icon_mode_font = strdup(q+1);
}
} else if (!strcmp(p, "full")) {
;
} else if (strstr(p, "tray") == p || strstr(p, "icon") == p) {
char *q;
icon_mode = 1;
if ((q = strchr(p, '=')) != NULL) {
icon_mode_params = strdup(q+1);
if (strstr(icon_mode_params, "setp")) {
deny_all = 1;
}
}
if (strstr(p, "tray") == p) {
icon_in_tray = 1;
}
} else if (strstr(p, "geom") == p) {
char *q;
if ((q = strchr(p, '=')) != NULL) {
gui_geometry = strdup(q+1);
}
} else {
fprintf(stderr, "unrecognized gui opt: %s\n", p);
}
p = strtok(NULL, ",");
}
free(s);
if (none_gui) {
if (!start_x11vnc) {
exit(0);
}
return;
}
if (start_x11vnc) {
connect_to_x11vnc = 1;
}
if (icon_mode && !got_gui_xdisplay) {
/* for tray mode, prefer the polled DISPLAY */
if (use_dpy) {
if (gui_xdisplay) {
free(gui_xdisplay);
}
gui_xdisplay = strdup(use_dpy);
}
}
if (! gui_xdisplay) {
fprintf(stderr, "error: cannot determine X DISPLAY for gui"
" to display on.\n");
exit(1);
}
if (!quiet) {
fprintf(stderr, "starting gui, trying display: %s\n",
gui_xdisplay);
}
test_dpy = XOpenDisplay(gui_xdisplay);
if (! test_dpy && auth_file) {
if (getenv("XAUTHORITY") != NULL) {
old_xauth = strdup(getenv("XAUTHORITY"));
}
set_env("XAUTHORITY", auth_file);
test_dpy = XOpenDisplay(gui_xdisplay);
}
if (! test_dpy) {
if (! old_xauth && getenv("XAUTHORITY") != NULL) {
old_xauth = strdup(getenv("XAUTHORITY"));
}
set_env("XAUTHORITY", "");
test_dpy = XOpenDisplay(gui_xdisplay);
}
if (! test_dpy) {
fprintf(stderr, "error: cannot connect to gui X DISPLAY: %s\n",
gui_xdisplay);
exit(1);
}
if (icon_mode && icon_in_tray) {
if (tray_manager_running(test_dpy, NULL)) {
tray_manager_ok = 1;
} else {
tray_manager_ok = 0;
}
}
XCloseDisplay(test_dpy);
if (start_x11vnc) {
#if LIBVNCSERVER_HAVE_FORK
/* fork into the background now */
int p;
pid_t parent = getpid();
if (icon_mode) {
char tf[100];
double dn = dnow();
struct stat sbuf;
/* FIXME */
dn = dn - ((int) dn);
sprintf(tf, "/tmp/x11vnc.tray%d%d", (int) (1000000*dn),
(int) getpid());
unlink(tf);
/* race begins.. */
if (stat(tf, &sbuf) == 0) {
icon_mode = 0;
} else {
icon_mode_fh = fopen(tf, "w");
if (! icon_mode_fh) {
icon_mode = 0;
} else {
chmod(tf, 0400);
icon_mode_file = strdup(tf);
fprintf(icon_mode_fh, "none\n");
fprintf(icon_mode_fh, "none\n");
fflush(icon_mode_fh);
if (! got_connect_once) {
/* want -forever for tray */
connect_once = 0;
}
}
}
}
if ((p = fork()) > 0) {
; /* parent */
} else if (p == -1) {
fprintf(stderr, "could not fork\n");
perror("fork");
clean_up_exit(1);
} else {
if (sleep > 0) {
usleep(sleep * 1000 * 1000);
}
run_gui(gui_xdisplay, connect_to_x11vnc, start_x11vnc,
simple_gui, parent, opts);
exit(1);
}
#else
fprintf(stderr, "system does not support fork: start "
"x11vnc in the gui.\n");
start_x11vnc = 0;
#endif
}
if (!start_x11vnc) {
run_gui(gui_xdisplay, connect_to_x11vnc, start_x11vnc,
simple_gui, 0, opts);
exit(1);
}
if (old_xauth) {
set_env("XAUTHORITY", old_xauth);
}
}

@ -0,0 +1,19 @@
#ifndef _X11VNC_GUI_H
#define _X11VNC_GUI_H
/* -- gui.h -- */
extern int icon_mode;
extern char *icon_mode_file;
extern FILE *icon_mode_fh;
extern int icon_mode_socks[];
extern int tray_manager_ok;
extern Window tray_request;
extern Window tray_window;
extern int tray_unembed;
extern char *get_gui_code(void);
extern int tray_embed(Window iconwin, int remove);
extern void do_gui(char *opts, int sleep);
#endif /* _X11VNC_GUI_H */

File diff suppressed because it is too large Load Diff

@ -0,0 +1,10 @@
#ifndef _X11VNC_HELP_H
#define _X11VNC_HELP_H
/* -- help.h -- */
extern void print_help(int mode);
extern void xopen_display_fail_message(char *disp);
extern void nopassword_warning_msg(int gotloc);
#endif /* _X11VNC_HELP_H */

@ -0,0 +1,259 @@
/* -- inet.c -- */
#include "x11vnc.h"
/*
* Simple utility to map host name to dotted IP address. Ignores aliases.
* Up to caller to free returned string.
*/
char *host2ip(char *host);
char *raw2host(char *raw, int len);
char *raw2ip(char *raw);
char *ip2host(char *ip);
int dotted_ip(char *host);
int get_remote_port(int sock);
int get_local_port(int sock);
char *get_remote_host(int sock);
char *get_local_host(int sock);
char *ident_username(rfbClientPtr client);
static int get_port(int sock, int remote);
static char *get_host(int sock, int remote);
char *host2ip(char *host) {
struct hostent *hp;
struct sockaddr_in addr;
char *str;
if (! host_lookup) {
return NULL;
}
hp = gethostbyname(host);
if (!hp) {
return NULL;
}
memset(&addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = *(unsigned long *)hp->h_addr;
str = strdup(inet_ntoa(addr.sin_addr));
return str;
}
char *raw2host(char *raw, int len) {
char *str;
#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
struct hostent *hp;
if (! host_lookup) {
return strdup("unknown");
}
hp = gethostbyaddr(raw, len, AF_INET);
if (!hp) {
return strdup(inet_ntoa(*((struct in_addr *)raw)));
}
str = strdup(hp->h_name);
#else
str = strdup("unknown");
#endif
return str;
}
char *raw2ip(char *raw) {
return strdup(inet_ntoa(*((struct in_addr *)raw)));
}
char *ip2host(char *ip) {
char *str;
#if LIBVNCSERVER_HAVE_NETDB_H && LIBVNCSERVER_HAVE_NETINET_IN_H
struct hostent *hp;
in_addr_t iaddr;
if (! host_lookup) {
return strdup("unknown");
}
iaddr = inet_addr(ip);
if (iaddr == htonl(INADDR_NONE)) {
return strdup("unknown");
}
hp = gethostbyaddr((char *)&iaddr, sizeof(in_addr_t), AF_INET);
if (!hp) {
return strdup("unknown");
}
str = strdup(hp->h_name);
#else
str = strdup("unknown");
#endif
return str;
}
int dotted_ip(char *host) {
char *p = host;
while (*p != '\0') {
if (*p == '.' || isdigit(*p)) {
p++;
continue;
}
return 0;
}
return 1;
}
static int get_port(int sock, int remote) {
struct sockaddr_in saddr;
unsigned int saddr_len;
int saddr_port;
saddr_len = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
saddr_port = -1;
if (remote) {
if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
saddr_port = ntohs(saddr.sin_port);
}
} else {
if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
saddr_port = ntohs(saddr.sin_port);
}
}
return saddr_port;
}
int get_remote_port(int sock) {
return get_port(sock, 1);
}
int get_local_port(int sock) {
return get_port(sock, 0);
}
static char *get_host(int sock, int remote) {
struct sockaddr_in saddr;
unsigned int saddr_len;
int saddr_port;
char *saddr_ip_str = NULL;
saddr_len = sizeof(saddr);
memset(&saddr, 0, sizeof(saddr));
saddr_port = -1;
#if LIBVNCSERVER_HAVE_NETINET_IN_H
if (remote) {
if (!getpeername(sock, (struct sockaddr *)&saddr, &saddr_len)) {
saddr_ip_str = inet_ntoa(saddr.sin_addr);
}
} else {
if (!getsockname(sock, (struct sockaddr *)&saddr, &saddr_len)) {
saddr_ip_str = inet_ntoa(saddr.sin_addr);
}
}
#endif
if (! saddr_ip_str) {
saddr_ip_str = "unknown";
}
return strdup(saddr_ip_str);
}
char *get_remote_host(int sock) {
return get_host(sock, 1);
}
char *get_local_host(int sock) {
return get_host(sock, 0);
}
char *ident_username(rfbClientPtr client) {
ClientData *cd = (ClientData *) client->clientData;
char *str, *newhost, *user = NULL, *newuser = NULL;
int len;
if (cd) {
user = cd->username;
}
if (!user || *user == '\0') {
char msg[128];
int n, sock, ok = 0;
if ((sock = rfbConnectToTcpAddr(client->host, 113)) < 0) {
rfbLog("could not connect to ident: %s:%d\n",
client->host,</