parent
def3012663
commit
71f2ec7918
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, |