Commit 0130bdb9 authored by runge's avatar runge

x11vnc: -gone, -passwdfile, -o logfile; add view-only to -accept

parent dd26262a
2004-05-21 Karl Runge <runge@karlrunge.com>
* x11vnc: -gone, -passwdfile, -o logfile; add view-only to -accept
2004-05-08 Karl Runge <runge@karlrunge.com> 2004-05-08 Karl Runge <runge@karlrunge.com>
* x11vnc: add -accept some-command/xmessage/popup * x11vnc: add -accept some-command/xmessage/popup
......
2004-05-21 Karl Runge <runge@karlrunge.com>
* -accept: add view-only decision and other improvements.
* add -gone command option for when a client leaves.
Thanks to Jesus Alvarez for these ideas.
* -passwdfile to keep passwd off of cmd line.
* -o logfile send stderr to a logfile.
2004-05-14 Karl Runge <runge@karlrunge.com> 2004-05-14 Karl Runge <runge@karlrunge.com>
* improvements to -accept popup: yes/no buttons and timeout. * improvements to -accept popup: yes/no buttons and timeout.
* less fprintf under -q so '-q -inetd' has no stderr output. * less fprintf under -q so '-q -inetd' has no stderr output.
......
...@@ -131,7 +131,7 @@ ...@@ -131,7 +131,7 @@
#endif #endif
/* date +'"lastmod: %Y-%m-%d";' */ /* date +'"lastmod: %Y-%m-%d";' */
char lastmod[] = "lastmod: 2004-05-14"; char lastmod[] = "lastmod: 2004-05-21";
/* X and rfb framebuffer */ /* X and rfb framebuffer */
...@@ -207,6 +207,7 @@ hint_t *hint_list; ...@@ -207,6 +207,7 @@ hint_t *hint_list;
int shared = 0; /* share vnc display. */ int shared = 0; /* share vnc display. */
char *allow_list = NULL; /* for -allow and -localhost */ char *allow_list = NULL; /* for -allow and -localhost */
char *accept_cmd = NULL; /* for -accept */ char *accept_cmd = NULL; /* for -accept */
char *gone_cmd = NULL; /* for -gone */
int view_only = 0; /* clients can only watch. */ int view_only = 0; /* clients can only watch. */
int inetd = 0; /* spawned from inetd(1) */ int inetd = 0; /* spawned from inetd(1) */
int connect_once = 1; /* disconnect after first connection session. */ int connect_once = 1; /* disconnect after first connection session. */
...@@ -353,6 +354,7 @@ void clean_up_exit (int ret) { ...@@ -353,6 +354,7 @@ void clean_up_exit (int ret) {
XTestDiscard(dpy); XTestDiscard(dpy);
X_UNLOCK; X_UNLOCK;
fflush(stderr);
exit(ret); exit(ret);
} }
...@@ -437,12 +439,19 @@ void set_signals(void) { ...@@ -437,12 +439,19 @@ void set_signals(void) {
X_UNLOCK; X_UNLOCK;
} }
int run_user_command(char *, rfbClientPtr);
int accepted_client = 0; int accepted_client = 0;
void client_gone(rfbClientPtr client) { void client_gone(rfbClientPtr client) {
client_count--; client_count--;
rfbLog("client_count: %d\n", client_count); rfbLog("client_count: %d\n", client_count);
if (gone_cmd) {
rfbLog("client_gone: using cmd for: %s\n", client->host);
run_user_command(gone_cmd, client);
}
if (inetd) { if (inetd) {
rfbLog("viewer exited.\n"); rfbLog("viewer exited.\n");
clean_up_exit(0); clean_up_exit(0);
...@@ -506,7 +515,7 @@ int check_access(char *addr) { ...@@ -506,7 +515,7 @@ int check_access(char *addr) {
* We go through this pain to avoid dependency on libXt. * We go through this pain to avoid dependency on libXt.
*/ */
int ugly_accept_window(char *addr, int timeout) { int ugly_accept_window(char *addr, int X, int Y, int timeout, char *mode) {
#define t2x2_width 16 #define t2x2_width 16
#define t2x2_height 16 #define t2x2_height 16
...@@ -534,22 +543,62 @@ static char t2x2_bits[] = { ...@@ -534,22 +543,62 @@ static char t2x2_bits[] = {
double waited = 0.0; double waited = 0.0;
/* strings and geometries y/n */ /* strings and geometries y/n */
KeyCode key_y, key_n; KeyCode key_y, key_n, key_v;
char str1[100]; char strh[100];
char str2[] = "To accept: press \"y\" or click the \"Yes\" button"; char str1_b[] = "To accept: press \"y\" or click the \"Yes\" button";
char str3[] = "To reject: press \"n\" or click the \"No\" button"; char str2_b[] = "To reject: press \"n\" or click the \"No\" button";
char str4[] = "Yes"; char str3_b[] = "View only: press \"v\" or click the \"View\" button";
char str5[] = "No"; char str1_m[] = "To accept: click the \"Yes\" button";
int x, y, w = 345, h = 125, ret = 0; char str2_m[] = "To reject: click the \"No\" button";
char str3_m[] = "View only: click the \"View\" button";
char str1_k[] = "To accept: press \"y\"";
char str2_k[] = "To reject: press \"n\"";
char str3_k[] = "View only: press \"v\"";
char *str1, *str2, *str3;
char str_y[] = "Yes";
char str_n[] = "No";
char str_v[] = "View";
int x, y, w = 345, h = 150, ret = 0;
int X_sh = 20, Y_sh = 30, dY = 20; int X_sh = 20, Y_sh = 30, dY = 20;
int Ye_x = 20, Ye_y = 0, Ye_w = 40, Ye_h = 20; int Ye_x = 20, Ye_y = 0, Ye_w = 45, Ye_h = 20;
int No_x = 70, No_y = 0, No_w = 40, No_h = 20; int No_x = 75, No_y = 0, No_w = 45, No_h = 20;
int Vi_x = 130, Vi_y = 0, Vi_w = 45, Vi_h = 20;
if (!strcmp(mode, "mouse_only")) {
str1 = str1_m;
str2 = str2_m;
str3 = str3_m;
} else if (!strcmp(mode, "key_only")) {
str1 = str1_k;
str2 = str2_k;
str3 = str3_k;
h -= dY;
} else {
str1 = str1_b;
str2 = str2_b;
str3 = str3_b;
}
if (view_only) {
h -= dY;
}
x = (dpy_x - w)/2; if (X < -dpy_x) {
y = (dpy_y - h)/2; x = (dpy_x - w)/2; /* large negative: center */
if (x < 0) x = 0; if (x < 0) x = 0;
if (y < 0) y = 0; } else if (X < 0) {
x = dpy_x + X - w; /* from lower right */
} else {
x = X; /* from upper left */
}
if (Y < -dpy_y) {
y = (dpy_y - h)/2;
if (y < 0) y = 0;
} else if (Y < 0) {
y = dpy_y + Y - h;
} else {
y = Y;
}
X_LOCK; X_LOCK;
...@@ -593,12 +642,13 @@ static char t2x2_bits[] = { ...@@ -593,12 +642,13 @@ static char t2x2_bits[] = {
XMapWindow(dpy, awin); XMapWindow(dpy, awin);
XFlush(dpy); XFlush(dpy);
sprintf(str1, "x11vnc: accept connection from %s?", addr); sprintf(strh, "x11vnc: accept connection from %s?", addr);
key_y = XKeysymToKeycode(dpy, XStringToKeysym("y")); key_y = XKeysymToKeycode(dpy, XStringToKeysym("y"));
key_n = XKeysymToKeycode(dpy, XStringToKeysym("n")); key_n = XKeysymToKeycode(dpy, XStringToKeysym("n"));
key_v = XKeysymToKeycode(dpy, XStringToKeysym("v"));
while (1) { while (1) {
int out = -1, l1, l2, l3, l4, l5, x, y, tw; int out = -1, x, y, tw, k;
if (XCheckWindowEvent(dpy, awin, evmask, &ev)) { if (XCheckWindowEvent(dpy, awin, evmask, &ev)) {
; /* proceed to handling */ ; /* proceed to handling */
...@@ -623,29 +673,55 @@ static char t2x2_bits[] = { ...@@ -623,29 +673,55 @@ static char t2x2_bits[] = {
while (XCheckTypedEvent(dpy, Expose, &ev)) { while (XCheckTypedEvent(dpy, Expose, &ev)) {
; ;
} }
l1 = strlen(str1); l2 = strlen(str2); k=0;
l3 = strlen(str3); l4 = strlen(str4); l5 = strlen(str5);
/* instructions */
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
strh, strlen(strh));
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
str1, strlen(str1));
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
str2, strlen(str2));
if (! view_only) {
XDrawString(dpy, awin, gc, X_sh, Y_sh+(k++)*dY,
str3, strlen(str3));
}
XDrawString(dpy, awin, gc, X_sh, Y_sh+0*dY, str1, l1); if (!strcmp(mode, "key_only")) {
XDrawString(dpy, awin, gc, X_sh, Y_sh+1*dY, str2, l2); break;
XDrawString(dpy, awin, gc, X_sh, Y_sh+2*dY, str3, l3); }
Ye_y = Y_sh+3*dY; /* buttons */
No_y = Y_sh+3*dY; Ye_y = Y_sh+k*dY;
No_y = Y_sh+k*dY;
Vi_y = Y_sh+k*dY;
XDrawRectangle(dpy, awin, gc, Ye_x, Ye_y, Ye_w, Ye_h); XDrawRectangle(dpy, awin, gc, Ye_x, Ye_y, Ye_w, Ye_h);
XDrawRectangle(dpy, awin, gc, No_x, No_y, No_w, No_h); XDrawRectangle(dpy, awin, gc, No_x, No_y, No_w, No_h);
if (! view_only) {
XDrawRectangle(dpy, awin, gc, Vi_x, Vi_y,
Vi_w, Vi_h);
}
tw = XTextWidth(font_info, str4, l4); tw = XTextWidth(font_info, str_y, strlen(str_y));
tw = (Ye_w - tw)/2; tw = (Ye_w - tw)/2;
if (tw < 0) tw = 1; if (tw < 0) tw = 1;
XDrawString(dpy, awin, gc, Ye_x+tw, Ye_y+Ye_h-5, XDrawString(dpy, awin, gc, Ye_x+tw, Ye_y+Ye_h-5,
str4, l4); str_y, strlen(str_y));
tw = XTextWidth(font_info, str5, l5); tw = XTextWidth(font_info, str_n, strlen(str_n));
tw = (No_w - tw)/2; tw = (No_w - tw)/2;
if (tw < 0) tw = 1; if (tw < 0) tw = 1;
XDrawString(dpy, awin, gc, No_x+tw, No_y+No_h-5, XDrawString(dpy, awin, gc, No_x+tw, No_y+No_h-5,
str5, l5); str_n, strlen(str_n));
if (! view_only) {
tw = XTextWidth(font_info, str_v,
strlen(str_v));
tw = (Vi_w - tw)/2;
if (tw < 0) tw = 1;
XDrawString(dpy, awin, gc, Vi_x+tw, Vi_y+Vi_h-5,
str_v, strlen(str_v));
}
break; break;
...@@ -659,20 +735,29 @@ static char t2x2_bits[] = { ...@@ -659,20 +735,29 @@ static char t2x2_bits[] = {
case ButtonPress: case ButtonPress:
x = ev.xbutton.x; x = ev.xbutton.x;
y = ev.xbutton.y; y = ev.xbutton.y;
if (x > No_x && x < No_x+No_w && y > No_y if (!strcmp(mode, "key_only")) {
;
} else if (x > No_x && x < No_x+No_w && y > No_y
&& y < No_y+No_h) { && y < No_y+No_h) {
out = 0; out = 0;
} else if (x > Ye_x && x < Ye_x+Ye_w && y > Ye_y } else if (x > Ye_x && x < Ye_x+Ye_w && y > Ye_y
&& y < Ye_y+Ye_h) { && y < Ye_y+Ye_h) {
out = 1; out = 1;
} else if (! view_only && x > Vi_x && x < Vi_x+Vi_w
&& y > Vi_y && y < Vi_y+Ye_h) {
out = 2;
} }
break; break;
case KeyPress: case KeyPress:
if (ev.xkey.keycode == key_y) { if (!strcmp(mode, "mouse_only")) {
;
} else if (ev.xkey.keycode == key_y) {
out = 1; out = 1;
} else if (ev.xkey.keycode == key_n) { } else if (ev.xkey.keycode == key_n) {
out = 0; out = 0;
} else if (! view_only && ev.xkey.keycode == key_v) {
out = 2;
} }
break; break;
default: default:
...@@ -692,13 +777,173 @@ static char t2x2_bits[] = { ...@@ -692,13 +777,173 @@ static char t2x2_bits[] = {
return ret; return ret;
} }
/*
* utility to run a user supplied command setting some RFB_ env vars.
* used by, e.g., accept_client() and client_gone()
*/
int run_user_command(char *cmd, rfbClientPtr client) {
char *dpystr = DisplayString(dpy);
static char *display_env = NULL;
static char env_rfb_client_id[100];
static char env_rfb_client_ip[100];
static char env_rfb_client_port[100];
static char env_rfb_x11vnc_pid[100];
char *addr = client->host;
int rc, fromlen, fromport;
struct sockaddr_in from;
if (addr == NULL || addr[0] == '\0') {
addr = "unknown-host";
}
/* set RFB_CLIENT_ID to semi unique id for command to use */
sprintf(env_rfb_client_id, "RFB_CLIENT_ID=%d", (int) client);
putenv(env_rfb_client_id);
/* set RFB_CLIENT_IP to IP addr for command to use */
sprintf(env_rfb_client_ip, "RFB_CLIENT_IP=%s", addr);
putenv(env_rfb_client_ip);
/* set RFB_X11VNC_PID to our pid for command to use */
sprintf(env_rfb_x11vnc_pid, "RFB_X11VNC_PID=%d", (int) getpid());
putenv(env_rfb_x11vnc_pid);
/* set RFB_CLIENT_PORT to peer port for command to use */
fromlen = sizeof(from);
memset(&from, 0, sizeof(from));
fromport = -1;
if (!getpeername(client->sock, (struct sockaddr *)&from, &fromlen)) {
fromport = ntohs(from.sin_port);
}
sprintf(env_rfb_client_port, "RFB_CLIENT_PORT=%d", fromport);
putenv(env_rfb_client_port);
/*
* Better set DISPLAY to the one we are polling, if they
* want something trickier, they can handle on their own
* via environment, etc. XXX really should save/restore old.
*/
if (display_env == NULL) {
display_env = (char *) malloc(strlen(dpystr)+10);
}
sprintf(display_env, "DISPLAY=%s", dpystr);
putenv(display_env);
rfbLog("running command:\n");
rfbLog(" %s\n", cmd);
rc = system(cmd);
if (rc >= 256) {
rc = rc/256;
}
rfbLog("command returned: %d\n", rc);
sprintf(env_rfb_client_id, "RFB_CLIENT_ID=");
putenv(env_rfb_client_id);
sprintf(env_rfb_client_ip, "RFB_CLIENT_IP=");
putenv(env_rfb_client_ip);
sprintf(env_rfb_client_port, "RFB_CLIENT_PORT=");
putenv(env_rfb_client_port);
sprintf(env_rfb_x11vnc_pid, "RFB_X11VNC_PID=");
putenv(env_rfb_x11vnc_pid);
return rc;
}
/*
* process a "yes:0,no:*,view:3" type action list comparing to command
* return code rc. * means the default action with no other match.
*/
int action_match(char *action, int rc) {
char *p, *q, *s = strdup(action);
int cases[4], i, result;
char *labels[4];
labels[1] = "yes";
labels[2] = "no";
labels[3] = "view";
rfbLog("accept_client: process action line: %s\n",
action);
for (i=1; i <= 3; i++) {
cases[i] = -2;
}
p = strtok(s, ",");
while (p) {
if ((q = strchr(p, ':')) != NULL) {
int in, k;
*q = '\0';
q++;
if (strstr(p, "yes") == p) {
k = 1;
} else if (strstr(p, "no") == p) {
k = 2;
} else if (strstr(p, "view") == p) {
k = 3;
} else {
rfbLog("bad action line: %s\n", action);
clean_up_exit(1);
}
if (*q == '*') {
cases[k] = -1;
} else if (sscanf(q, "%d", &in) == 1) {
if (in < 0) {
rfbLog("bad action line: %s\n", action);
clean_up_exit(1);
}
cases[k] = in;
} else {
rfbLog("bad action line: %s\n", action);
clean_up_exit(1);
}
} else {
rfbLog("bad action line: %s\n", action);
clean_up_exit(1);
}
p = strtok(NULL, ",");
}
free(s);
result = -1;
for (i=1; i <= 3; i++) {
if (cases[i] == -1) {
rfbLog("accept_client: default action is case=%d %s\n",
i, labels[i]);
result = i;
break;
}
}
if (result == -1) {
rfbLog("accept_client: no default action\n");
}
for (i=1; i <= 3; i++) {
if (cases[i] >= 0 && cases[i] == rc) {
rfbLog("accept_client: matched action is case=%d %s\n",
i, labels[i]);
result = i;
break;
}
}
if (result < 0) {
rfbLog("no action match: %s rc=%d set to no\n", action, rc);
result = 2;
}
return result;
}
/* /*
* Simple routine to prompt the user on the X display whether an incoming * Simple routine to prompt the user on the X display whether an incoming
* client should be allowed to connect or not. If a gui is involved it * client should be allowed to connect or not. If a gui is involved it
* will be running in the environment/context of the X11 DISPLAY. * will be running in the environment/context of the X11 DISPLAY.
* *
* The command supplied via -accept is run as is (i.e. no string * The command supplied via -accept is run as is (i.e. no string
* substitution) with the RFB_CLIENT environment variable set to the * substitution) with the RFB_CLIENT_IP environment variable set to the
* incoming client's numerical IP address. * incoming client's numerical IP address.
* *
* If the external command exits with 0 the client is accepted, otherwise * If the external command exits with 0 the client is accepted, otherwise
...@@ -710,9 +955,11 @@ static char t2x2_bits[] = { ...@@ -710,9 +955,11 @@ static char t2x2_bits[] = {
* popup: use internal X widgets for prompting. * popup: use internal X widgets for prompting.
* *
*/ */
int accept_client(char *addr) { int accept_client(rfbClientPtr client) {
char xmessage[200], *cmd = NULL; char xmessage[200], *cmd = NULL;
static char rfb_client_env[100], *display_env = NULL; char *addr = client->host;
char *action = NULL;
if (accept_cmd == NULL) { if (accept_cmd == NULL) {
return 1; /* no command specified, so we accept */ return 1; /* no command specified, so we accept */
...@@ -722,63 +969,131 @@ int accept_client(char *addr) { ...@@ -722,63 +969,131 @@ int accept_client(char *addr) {
addr = "unknown-host"; addr = "unknown-host";
} }
if (!strcmp(accept_cmd, "xmessage")) { if (strstr(accept_cmd, "popup") == accept_cmd) {
/* make our own command using xmessage(1) */ /* use our builtin popup button */
sprintf(xmessage, "xmessage -buttons yes:0,no:2 -center "
"'x11vnc: accept connection from %s?'", addr); /* (popup|popupkey|popupmouse)[+-X+-Y][:timeout] */
cmd = xmessage;
int ret, timeout = 120;
} else if (strstr(accept_cmd, "popup:") == accept_cmd || int x = -64000, y = -64000;
!strcmp(accept_cmd, "popup")) { char *p, *mode;
int timeout = 120;
char *p; /* extract timeout */
if ((p = strchr(accept_cmd, ':')) != NULL) { if ((p = strchr(accept_cmd, ':')) != NULL) {
int in; int in;
if (sscanf(p+1, "%d", &in) == 1) { if (sscanf(p+1, "%d", &in) == 1) {
timeout = in; timeout = in;
} }
} }
/* extract geometry */
if ((p = strpbrk(accept_cmd, "+-")) != NULL) {
int x1, y1;
if (sscanf(p, "+%d+%d", &x1, &y1) == 2) {
x = x1;
y = y1;
} else if (sscanf(p, "+%d-%d", &x1, &y1) == 2) {
x = x1;
y = -y1;
} else if (sscanf(p, "-%d+%d", &x1, &y1) == 2) {
x = -x1;
y = y1;
} else if (sscanf(p, "-%d-%d", &x1, &y1) == 2) {
x = -x1;
y = -y1;
}
}
/* find mode: mouse, key, or both */
if (strstr(accept_cmd, "popupmouse") == accept_cmd) {
mode = "mouse_only";
} else if (strstr(accept_cmd, "popupkey") == accept_cmd) {
mode = "key_only";
} else {
mode = "both";
}
rfbLog("accept_client: using builtin popup for: %s\n", addr); rfbLog("accept_client: using builtin popup for: %s\n", addr);
if (ugly_accept_window(addr, timeout)) { if ((ret = ugly_accept_window(addr, x, y, timeout, mode))) {
if (ret == 2) {
rfbLog("accept_client: viewonly: %s\n", addr);
client->viewOnly = TRUE;
}
rfbLog("accept_client: popup accepted: %s\n", addr); rfbLog("accept_client: popup accepted: %s\n", addr);
return 1; return 1;
} else { } else {
rfbLog("accept_client: popup rejected: %s\n", addr); rfbLog("accept_client: popup rejected: %s\n", addr);
return 0; return 0;
} }
} else if (!strcmp(accept_cmd, "xmessage")) {
/* make our own command using xmessage(1) */
if (view_only) {
sprintf(xmessage, "xmessage -buttons yes:0,no:2 -center"
" 'x11vnc: accept connection from %s?'", addr);
} else {
sprintf(xmessage, "xmessage -buttons yes:0,no:2,"
"view-only:3 -center" " 'x11vnc: accept connection"
" from %s?'", addr);
action = "yes:0,no:*,view:3";
}
cmd = xmessage;
} else { } else {
/* use the user supplied command: */
cmd = accept_cmd; cmd = accept_cmd;
/* extract any action prefix: yes:N,no:M,view:K */
if (strstr(accept_cmd, "yes:") == accept_cmd) {
char *p;
if ((p = strpbrk(accept_cmd, " \t")) != NULL) {
int i;
cmd = p;
p = accept_cmd;
for (i=0; i<200; i++) {
if (*p == ' ' || *p == '\t') {
xmessage[i] = '\0';
break;
}
xmessage[i] = *p;
p++;
}
xmessage[200-1] = '\0';
action = xmessage;
}
}
} }
if (cmd) { if (cmd) {
int rc; int rc;
char *dpystr = DisplayString(dpy);
/* set RFB_CLIENT to IP addr for command to use */ rfbLog("accept_client: using cmd for: %s\n", addr);
sprintf(rfb_client_env, "RFB_CLIENT=%s", addr); rc = run_user_command(cmd, client);
putenv(rfb_client_env);
/* if (action) {
* Better set DISPLAY to the one we are polling, if they int result;
* want something trickier, they can handle on their own
* via environment, etc. XXX really should save/restore old.
*/
if (display_env == NULL) {
display_env = (char *) malloc(strlen(dpystr)+10);
}
sprintf(display_env, "DISPLAY=%s", dpystr);
putenv(display_env);
rfbLog("accept_client: running command:\n"); if (rc < 0) {
rfbLog(" %s\n", cmd); rfbLog("accept_client: cannot use negative "
rc = system(cmd); "rc: %d, action %s\n", rc, action);
if (rc >= 256) { result = 2;
rc = rc/256; } else {
} result = action_match(action, rc);
rfbLog("accept_client: command returned: %d\n", rc); }
sprintf(rfb_client_env, "RFB_CLIENT="); if (result == 1) {
putenv(rfb_client_env); rc = 0;
} else if (result == 2) {
rc = 1;
} else if (result == 3) {
rc = 0;
rfbLog("accept_client: viewonly: %s\n", addr);
client->viewOnly = TRUE;
} else {
rc = 1; /* NOTREACHED */
}
}
if (rc == 0) { if (rc == 0) {
rfbLog("accept_client: accepted: %s\n", addr); rfbLog("accept_client: accepted: %s\n", addr);
...@@ -1014,7 +1329,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { ...@@ -1014,7 +1329,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
allow_list ? allow_list : "(null)" ); allow_list ? allow_list : "(null)" );
return(RFB_CLIENT_REFUSE); return(RFB_CLIENT_REFUSE);
} }
if (! accept_client(client->host)) { if (! accept_client(client)) {
rfbLog("denying client: %s local user rejected connection.\n", rfbLog("denying client: %s local user rejected connection.\n",
client->host); client->host);
rfbLog("denying client: accept_cmd=\"%s\"\n", rfbLog("denying client: accept_cmd=\"%s\"\n",
...@@ -1024,6 +1339,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) { ...@@ -1024,6 +1339,7 @@ enum rfbNewClientAction new_client(rfbClientPtr client) {
if (view_only) { if (view_only) {
client->clientData = (void *) -1; client->clientData = (void *) -1;
client->viewOnly = TRUE;
} else { } else {
client->clientData = (void *) 0; client->clientData = (void *) 0;
} }
...@@ -1262,7 +1578,8 @@ void tweak_mod(signed char mod, rfbBool down) { ...@@ -1262,7 +1578,8 @@ void tweak_mod(signed char mod, rfbBool down) {
} }
} }
static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym,
rfbClientPtr client) {
KeyCode k; KeyCode k;
int tweak = 0; int tweak = 0;
if (debug_keyboard) { if (debug_keyboard) {
...@@ -1273,6 +1590,9 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr ...@@ -1273,6 +1590,9 @@ static void modifier_tweak_keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr
if (view_only) { if (view_only) {
return; return;
} }
if (client->viewOnly) {
return;
}
#define ADJUSTMOD(sym, state) \ #define ADJUSTMOD(sym, state) \
if (keysym == sym) { \ if (keysym == sym) { \
...@@ -1333,6 +1653,9 @@ static void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) { ...@@ -1333,6 +1653,9 @@ static void keyboard(rfbBool down, rfbKeySym keysym, rfbClientPtr client) {
if (view_only) { if (view_only) {
return; return;
} }
if (client->viewOnly) {
return;
}
last_keyboard_client = client; last_keyboard_client = client;
if (keyremaps) { if (keyremaps) {
...@@ -1669,7 +1992,9 @@ static void pointer(int mask, int x, int y, rfbClientPtr client) { ...@@ -1669,7 +1992,9 @@ static void pointer(int mask, int x, int y, rfbClientPtr client) {
if (view_only) { if (view_only) {
return; return;
} }
if (client->viewOnly) {
return;
}
if (mask >= 0) { if (mask >= 0) {
/* /*
...@@ -2376,6 +2701,9 @@ void watch_xevents() { ...@@ -2376,6 +2701,9 @@ void watch_xevents() {
*/ */
void xcut_receive(char *text, int len, rfbClientPtr cl) { void xcut_receive(char *text, int len, rfbClientPtr cl) {
if (cl->viewOnly) {
return;
}
if (text == NULL || len == 0) { if (text == NULL || len == 0) {
return; return;
} }
...@@ -5419,7 +5747,7 @@ void print_help() { ...@@ -5419,7 +5747,7 @@ void print_help() {
"Once x11vnc establishes connections with the X11 server and starts\n" "Once x11vnc establishes connections with the X11 server and starts\n"
"listening as a VNC server it will print out a string: PORT=XXXX where\n" "listening as a VNC server it will print out a string: PORT=XXXX where\n"
"XXXX is typically 5900 (the default VNC port). One would next run something\n" "XXXX is typically 5900 (the default VNC port). One would next run something\n"
"like this on the local machine: \"vncviewer host:N\" where N is XXXX - 5900.\n" "like this on the local machine: \"vncviewer host:N\" where N is XXXX - 5900.\n"
"\n" "\n"
"By default x11vnc will not allow the screen to be shared and it will\n" "By default x11vnc will not allow the screen to be shared and it will\n"
"exit as soon as a client disconnects. See -shared and -forever below\n" "exit as soon as a client disconnects. See -shared and -forever below\n"
...@@ -5439,68 +5767,113 @@ void print_help() { ...@@ -5439,68 +5767,113 @@ void print_help() {
" as the pointer moves from window to window (slow).\n" " as the pointer moves from window to window (slow).\n"
"-notruecolor Force 8bpp indexed color even if it looks like TrueColor.\n" "-notruecolor Force 8bpp indexed color even if it looks like TrueColor.\n"
"\n" "\n"
"-visual n Experimental option: probably does not do what you think.\n" "-visual n Experimental option: probably does not do what you\n"
" It simply *forces* the visual used for the framebuffer;\n" " think. It simply *forces* the visual used for the\n"
" this may be a bad thing... It is useful for testing and\n" " framebuffer; this may be a bad thing... It is useful for\n"
" for some workarounds. n may be a decimal number, or 0x\n" " testing and for some workarounds. n may be a decimal\n"
" hex. Run xdpyinfo(1) for the values. One may also use\n" " number, or 0x hex. Run xdpyinfo(1) for the values.\n"
" \"TrueColor\", etc. see <X11/X.h> for a list. If the\n" " One may also use \"TrueColor\", etc. see <X11/X.h>\n"
" string ends in \":m\" the visual depth is forced to be m.\n" " for a list. If the string ends in \":m\" for better\n"
" or for worse the visual depth is forced to be m.\n"
"\n" "\n"
"-viewonly Clients can only watch (default %s).\n" "-viewonly All clients can only watch (default %s).\n"
"-shared VNC display is shared (default %s).\n" "-shared VNC display is shared (default %s).\n"
"-forever Keep listening for more connections rather than exiting\n" "-forever Keep listening for more connections rather than exiting\n"
" as soon as the first client(s) disconnect. Same as -many\n" " as soon as the first client(s) disconnect. Same as -many\n"
"-connect string For use with \"vncviewer -listen\" reverse connections. If\n" "-connect string For use with \"vncviewer -listen\" reverse connections.\n"
" string has the form \"host\" or \"host:port\" the connection\n" " If string has the form \"host\" or \"host:port\"\n"
" is made once at startup. Use commas for a list. If string\n" " the connection is made once at startup. Use commas\n"
" contains \"/\" it is a file to periodically check for new\n" " for a list. If string contains \"/\" it is a file to\n"
" hosts. The first line is read and then file is truncated.\n" " periodically check for new hosts. The first line is\n"
" read and then file is truncated.\n"
"-vncconnect Monitor the VNC_CONNECT X property set by vncconnect(1).\n" "-vncconnect Monitor the VNC_CONNECT X property set by vncconnect(1).\n"
"-auth file Set the X authority file to be \"file\", equivalent to\n" "-auth file Set the X authority file to be \"file\", equivalent to\n"
" setting the XAUTHORITY env. var to \"file\" before startup.\n" " setting the XAUTHORITY env. var to \"file\" before startup.\n"
"-allow addr1[,addr2..] Only allow client connections from IP addresses matching\n" "-allow addr1[,addr2..] Only allow client connections from IP addresses matching\n"
" the comma separated list of numerical addresses. Can be\n" " the comma separated list of numerical addresses.\n"
" a prefix, e.g. \"192.168.100.\" to match a simple subnet,\n" " Can be a prefix, e.g. \"192.168.100.\" to match a\n"
" for more control build libvncserver with libwrap support.\n" " simple subnet, for more control build libvncserver with\n"
" libwrap support.\n"
"-localhost Same as -allow 127.0.0.1\n" "-localhost Same as -allow 127.0.0.1\n"
"-accept string Prompt user at the X11 display whether an incoming\n" "-passwdfile filename Specify libvncserver -passwd via the first line of file\n"
" client should be allowed to connect. \"string\" is an\n" " \"filename\" instead of via command line. Note: this\n"
" external command run via system(3). Be sure to quote\n" " is a simple plaintext passwd, see also -rfbauth below.\n"
" \"string\" if it contains spaces, etc. The RFB_CLIENT env.\n" "-accept string Run a command (possibly to prompt the user at the\n"
" variable will be set to the client's IP number. If the\n" " X11 display) to decide whether an incoming client\n"
" external command returns 0 the client is accepted,\n" " should be allowed to connect or not. \"string\" is\n"
" otherwise the client is rejected.\n" " an external command run via system(3) (see below for\n"
" special cases). Be sure to quote \"string\" if it\n"
" contains spaces, etc. The RFB_CLIENT_IP environment\n"
" variable will be set to the incoming client IP number\n"
" and the port in RFB_CLIENT_PORT (or -1 if unavailable).\n"
" The x11vnc process id will be in RFB_X11VNC_PID and a\n"
" client id number in RFB_CLIENT_ID. If the external\n"
" command returns 0 the client is accepted, otherwise\n"
" the client is rejected. See below for an extension to\n"
" accept a client view-only.\n"
"\n"
" If \"string\" is \"popup\" then a builtin popup window\n"
" is used. The popup will time out after 120 seconds,\n"
" use \"popup:N\" to modify the timeout to N seconds\n"
" (use 0 for no timeout)\n"
"\n"
" If \"string\" is \"xmessage\" then an xmessage(1)\n"
" invocation is used for the command.\n"
"\n"
" Both \"popup\" and \"xmessage\" will present an option\n"
" for accepting the client \"View-Only\" (the client\n"
" can only watch). This option will not be presented if\n"
" -viewonly has been specified, in which case the entire\n"
" display is view only.\n"
"\n" "\n"
" If string is \"xmessage\" then an xmessage(1) invocation\n" " If the user supplied command is prefixed with something\n"
" is used for the command. If string is \"popup\" then a\n" " like \"yes:0,no:*,view:3 mycommand ...\" then this\n"
" builtin popup window is used. The popup will time out\n" " associates the numerical command return code with\n"
" after 120 seconds, use \"popup:N\" to modify the timeout\n" " the actions: accept, reject, and accept-view-only,\n"
" to N seconds (use 0 for no timeout)\n" " respectively. Use \"*\" instead of a number to indicate\n"
" the default action (in case the command returns an\n"
" unexpected value). E.g. \"no:*\" is a good choice.\n"
"\n" "\n"
" Note that x11vnc blocks while the external command or\n" " Note that x11vnc blocks while the external command or\n"
" or popup is running (other clients may see no updates\n" " or popup is running (other clients may see no updates\n"
" during this period).\n" " during this period).\n"
"\n"
" More -accept tricks: use \"popupmouse\" to only allow\n"
" mouse clicks in the builtin popup to be recognized.\n"
" Similarly use \"popupkey\" to only recognize keystroke\n"
" responses. All 3 of the popup keywords can be followed\n"
" by +N+M to supply a position for the popup window.\n"
" The default is to center the popup window.\n"
"\n"
"-gone string As -accept string, except to run a user supplied command\n"
" when a client goes away (disconnects). Unlike -accept,\n"
" the command return code is not interpreted by x11vnc.\n"
"\n"
"-inetd Launched by inetd(1): stdio instead of listening socket.\n" "-inetd Launched by inetd(1): stdio instead of listening socket.\n"
" Note: if you are not redirecting stderr to a log file\n" " Note: if you are not redirecting stderr to a log file\n"
" you must also specify -q as the first argument.\n" " you must also specify the -q option.\n"
"\n" "\n"
"-noshm Do not use the MIT-SHM extension for the polling.\n" "-noshm Do not use the MIT-SHM extension for the polling.\n"
" remote displays can be polled this way: be careful\n" " Remote displays can be polled this way: be careful this\n"
" this can use large amounts of network bandwidth. Also\n" " can use large amounts of network bandwidth. This is\n"
" of use if machine has a limited number of shm segments.\n" " also of use if the local machine has a limited number\n"
" of shm segments and -onetile is not sufficient.\n"
"-flipbyteorder Sometimes needed if remotely polled host has different\n" "-flipbyteorder Sometimes needed if remotely polled host has different\n"
" endianness. Ignored unless -noshm is set.\n" " endianness. Ignored unless -noshm is set.\n"
"-blackout string Black out rectangles on the screen. string is a comma\n" "-blackout string Black out rectangles on the screen. string is a comma\n"
" separated list of WxH+X+Y type geometries for each rect.\n" " separated list of WxH+X+Y type geometries for each rect.\n"
"-xinerama If your screen is composed of multiple monitors glued\n" "-xinerama If your screen is composed of multiple monitors\n"
" together via XINERAMA, and that screen is non-rectangular\n" " glued together via XINERAMA, and that screen is\n"
" this option will try to guess the areas to black out.\n" " non-rectangular this option will try to guess the areas\n"
" to black out (if your system has libXinerama).\n"
"\n" "\n"
"-q Be quiet by printing less informational output to stderr.\n" "-o logfile Write stderr messages to file \"logfile\" instead of\n"
" Same as -quiet\n" " to the terminal. Same as -logfile.\n"
"-bg Go into the background after screen setup.\n" "-q Be quiet by printing less informational output to\n"
" Something like this could be useful in a script:\n" " stderr. Same as -quiet.\n"
"-bg Go into the background after screen setup. Messages to\n"
" stderr are lost unless -o logfile is used. Something\n"
" like this could be useful in a script:\n"
" port=`ssh $host \"x11vnc -display :0 -bg\" | grep PORT`\n" " port=`ssh $host \"x11vnc -display :0 -bg\" | grep PORT`\n"
" port=`echo \"$port\" | sed -e 's/PORT=//'`\n" " port=`echo \"$port\" | sed -e 's/PORT=//'`\n"
" port=`expr $port - 5900`\n" " port=`expr $port - 5900`\n"
...@@ -5518,7 +5891,8 @@ void print_help() { ...@@ -5518,7 +5891,8 @@ void print_help() {
"-nofb Ignore framebuffer: only process keyboard and pointer.\n" "-nofb Ignore framebuffer: only process keyboard and pointer.\n"
"-nosel Do not manage exchange of X selection/cutbuffer.\n" "-nosel Do not manage exchange of X selection/cutbuffer.\n"
"-noprimary Do not poll the PRIMARY selection for changes and send\n" "-noprimary Do not poll the PRIMARY selection for changes and send\n"
" back to clients. PRIMARY is set for received changes.\n" " back to clients. PRIMARY is still set on received\n"
" changes, however.\n"
"\n" "\n"
"-nocursor Do not have the viewer show a local cursor.\n" "-nocursor Do not have the viewer show a local cursor.\n"
"-mouse Draw a 2nd cursor at the current X pointer position.\n" "-mouse Draw a 2nd cursor at the current X pointer position.\n"
...@@ -5532,7 +5906,7 @@ void print_help() { ...@@ -5532,7 +5906,7 @@ void print_help() {
"-buttonmap string String to remap mouse buttons. Format: IJK-LMN, this\n" "-buttonmap string String to remap mouse buttons. Format: IJK-LMN, this\n"
" maps buttons I -> L, etc., e.g. -buttonmap 13-31\n" " maps buttons I -> L, etc., e.g. -buttonmap 13-31\n"
"\n" "\n"
" Button presses can also be mapped to keysyms: replace\n" " Button presses can also be mapped to keystrokes: replace\n"
" a button digit on the right of the dash with :<sym>:\n" " a button digit on the right of the dash with :<sym>:\n"
" or :<sym1>+<sym2>: etc. for multiple keys. For example,\n" " or :<sym1>+<sym2>: etc. for multiple keys. For example,\n"
" if the viewing machine has a mouse-wheel (buttons 4 5)\n" " if the viewing machine has a mouse-wheel (buttons 4 5)\n"
...@@ -5540,11 +5914,11 @@ void print_help() { ...@@ -5540,11 +5914,11 @@ void print_help() {
" -buttonmap 12345-123:Prior::Next:\n" " -buttonmap 12345-123:Prior::Next:\n"
" -buttonmap 12345-123:Up+Up+Up::Down+Down+Down:\n" " -buttonmap 12345-123:Up+Up+Up::Down+Down+Down:\n"
"\n" "\n"
" If you include a modifier like \"Shift_L\" the modifier's\n" " If you include a modifier like \"Shift_L\" the\n"
" up/down state is toggled, e.g. to send \"The\" use\n" " modifier's up/down state is toggled, e.g. to send\n"
" :Shift_L+t+Shift_L+h+e: (the 1st one is shift down and\n" " \"The\" use :Shift_L+t+Shift_L+h+e: (the 1st one is\n"
" the 2nd one is shift up). (note: the initial state of\n" " shift down and the 2nd one is shift up). (note: the\n"
" the modifier is ignored and not reset)\n" " initial state of the modifier is ignored and not reset)\n"
" To include button events use \"Button1\", ... etc.\n" " To include button events use \"Button1\", ... etc.\n"
"\n" "\n"
"-nodragging Do not update the display during mouse dragging events\n" "-nodragging Do not update the display during mouse dragging events\n"
...@@ -5561,17 +5935,17 @@ void print_help() { ...@@ -5561,17 +5935,17 @@ void print_help() {
"-debug_pointer Print debugging output for every pointer event.\n" "-debug_pointer Print debugging output for every pointer event.\n"
"-debug_keyboard Print debugging output for every keyboard event.\n" "-debug_keyboard Print debugging output for every keyboard event.\n"
"\n" "\n"
"-defer time Time in ms to wait for updates before sending to\n" "-defer time Time in ms to wait for updates before sending to client\n"
" client [rfbDeferUpdateTime] (default %d).\n" " [rfbDeferUpdateTime] (default %d).\n"
"-wait time Time in ms to pause between screen polls. Used\n" "-wait time Time in ms to pause between screen polls. Used to cut\n"
" to cut down on load (default %d).\n" " down on load (default %d).\n"
"-nap Monitor activity and if low take longer naps between\n" "-nap Monitor activity and if low take longer naps between\n"
" polls to really cut down load when idle (default %s).\n" " polls to really cut down load when idle (default %s).\n"
"-sigpipe string Broken pipe (SIGPIPE) handling. string can be \"ignore\"\n" "-sigpipe string Broken pipe (SIGPIPE) handling. \"string\" can be\n"
" or \"exit\", for the 1st libvncserver will handle the\n" " \"ignore\" or \"exit\". For \"ignore\" libvncserver\n"
" abrupt loss of a client and continue, for the 2nd x11vnc\n" " will handle the abrupt loss of a client and continue,\n"
" will cleanup and exit at the 1st broken connection.\n" " for \"exit\" x11vnc will cleanup and exit at the 1st\n"
" Default is \"ignore\".\n" " broken connection. Default is \"ignore\".\n"
#ifdef LIBVNCSERVER_HAVE_LIBPTHREAD #ifdef LIBVNCSERVER_HAVE_LIBPTHREAD
"-threads Whether or not to use the threaded libvncserver\n" "-threads Whether or not to use the threaded libvncserver\n"
"-nothreads algorithm [rfbRunEventLoop] (default %s).\n" "-nothreads algorithm [rfbRunEventLoop] (default %s).\n"
...@@ -5582,8 +5956,8 @@ void print_help() { ...@@ -5582,8 +5956,8 @@ void print_help() {
"-onetile Do not use the new copy_tiles() framebuffer mechanism,\n" "-onetile Do not use the new copy_tiles() framebuffer mechanism,\n"
" just use 1 shm tile for polling. Same as -old_copytile.\n" " just use 1 shm tile for polling. Same as -old_copytile.\n"
" Limits shm segments used to 3.\n" " Limits shm segments used to 3.\n"
"-gaps n Heuristic to fill in gaps in rows or cols of n or less\n" "-gaps n Heuristic to fill in gaps in rows or cols of n or\n"
" tiles. Used to improve text paging (default %d).\n" " less tiles. Used to improve text paging (default %d).\n"
"-grow n Heuristic to grow islands of changed tiles n or wider\n" "-grow n Heuristic to grow islands of changed tiles n or wider\n"
" by checking the tile near the boundary (default %d).\n" " by checking the tile near the boundary (default %d).\n"
"-fuzz n Tolerance in pixels to mark a tiles edges as changed\n" "-fuzz n Tolerance in pixels to mark a tiles edges as changed\n"
...@@ -5692,6 +6066,8 @@ int main(int argc, char** argv) { ...@@ -5692,6 +6066,8 @@ int main(int argc, char** argv) {
char *use_dpy = NULL; char *use_dpy = NULL;
char *auth_file = NULL; char *auth_file = NULL;
char *arg, *visual_str = NULL; char *arg, *visual_str = NULL;
char *logfile = NULL;
char *passwdfile = NULL;
int pw_loc = -1; int pw_loc = -1;
int dt = 0; int dt = 0;
int bg = 0; int bg = 0;
...@@ -5699,7 +6075,7 @@ int main(int argc, char** argv) { ...@@ -5699,7 +6075,7 @@ int main(int argc, char** argv) {
int got_deferupdate = 0, got_defer = 0; int got_deferupdate = 0, got_defer = 0;
/* used to pass args we do not know about to rfbGetScreen(): */ /* used to pass args we do not know about to rfbGetScreen(): */
int argc2 = 1; char *argv2[100]; int argc2 = 1; char *argv2[128];
argv2[0] = strdup(argv[0]); argv2[0] = strdup(argv[0]);
...@@ -5728,6 +6104,8 @@ int main(int argc, char** argv) { ...@@ -5728,6 +6104,8 @@ int main(int argc, char** argv) {
force_indexed_color = 1; force_indexed_color = 1;
} else if (!strcmp(arg, "-viewonly")) { } else if (!strcmp(arg, "-viewonly")) {
view_only = 1; view_only = 1;
} else if (!strcmp(arg, "-passwdfile")) {
passwdfile = argv[++i];
} else if (!strcmp(arg, "-shared")) { } else if (!strcmp(arg, "-shared")) {
shared = 1; shared = 1;
} else if (!strcmp(arg, "-auth")) { } else if (!strcmp(arg, "-auth")) {
...@@ -5738,6 +6116,8 @@ int main(int argc, char** argv) { ...@@ -5738,6 +6116,8 @@ int main(int argc, char** argv) {
allow_list = "127.0.0.1"; allow_list = "127.0.0.1";
} else if (!strcmp(arg, "-accept")) { } else if (!strcmp(arg, "-accept")) {
accept_cmd = argv[++i]; accept_cmd = argv[++i];
} else if (!strcmp(arg, "-gone")) {
gone_cmd = argv[++i];
} else if (!strcmp(arg, "-many") } else if (!strcmp(arg, "-many")
|| !strcmp(arg, "-forever")) { || !strcmp(arg, "-forever")) {
connect_once = 0; connect_once = 0;
...@@ -5845,6 +6225,8 @@ int main(int argc, char** argv) { ...@@ -5845,6 +6225,8 @@ int main(int argc, char** argv) {
} else if (!strcmp(arg, "-h") || !strcmp(arg, "-help") } else if (!strcmp(arg, "-h") || !strcmp(arg, "-help")
|| !strcmp(arg, "-?")) { || !strcmp(arg, "-?")) {
print_help(); print_help();
} else if (!strcmp(arg, "-o") || !strcmp(arg, "-logfile")) {
logfile = argv[++i];
} else if (!strcmp(arg, "-q") || !strcmp(arg, "-quiet")) { } else if (!strcmp(arg, "-q") || !strcmp(arg, "-quiet")) {
quiet = 1; quiet = 1;
#ifdef LIBVNCSERVER_HAVE_SETSID #ifdef LIBVNCSERVER_HAVE_SETSID
...@@ -5873,16 +6255,39 @@ int main(int argc, char** argv) { ...@@ -5873,16 +6255,39 @@ int main(int argc, char** argv) {
if (!strcmp(arg, "-nevershared")) { if (!strcmp(arg, "-nevershared")) {
got_nevershared = 1; got_nevershared = 1;
} }
/* otherwise copy it for use below. */ /* otherwise copy it for libvncserver use below. */
if (!quiet && !inetd && i != pw_loc && i != pw_loc+1) {
fprintf(stderr, "passing arg to libvncserver: %s\n",
arg);
}
if (argc2 < 100) { if (argc2 < 100) {
argv2[argc2++] = strdup(arg); argv2[argc2++] = strdup(arg);
} }
} }
} }
if (logfile) {
int n;
if ((n = open(logfile, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0) {
fprintf(stderr, "error opening logfile: %s\n", logfile);
perror("open");
exit(1);
}
if (dup2(n, 2) < 0) {
fprintf(stderr, "dup2 failed\n");
perror("dup2");
exit(1);
}
if (n > 2) {
close(n);
}
}
if (! quiet && ! inetd) {
int i;
for (i=1; i < argc2; i++) {
fprintf(stderr, "passing arg to libvncserver: %s\n",
argv2[i]);
if (!strcmp(argv2[i], "-passwd")) {
i++;
}
}
}
/* /*
* If -passwd was used, clear it out of argv. This does not * If -passwd was used, clear it out of argv. This does not
...@@ -5899,6 +6304,26 @@ int main(int argc, char** argv) { ...@@ -5899,6 +6304,26 @@ int main(int argc, char** argv) {
*p++ = '\0'; *p++ = '\0';
} }
} }
} else if (passwdfile) {
char line[512];
FILE *in;
in = fopen(passwdfile, "r");
if (in == NULL) {
fprintf(stderr, "cannot open passwdfile: %s\n",
passwdfile);
perror("fopen");
exit(1);
}
if (fgets(line, 512, in) != NULL) {
line[strlen(line)-1] = '\0';
argv2[argc2++] = "-passwd";
argv2[argc2++] = strdup(line);
} else {
fprintf(stderr, "cannot read passwdfile: %s\n",
passwdfile);
perror("fgets");
exit(1);
}
} }
/* fixup settings that do not make sense */ /* fixup settings that do not make sense */
...@@ -5968,10 +6393,16 @@ int main(int argc, char** argv) { ...@@ -5968,10 +6393,16 @@ int main(int argc, char** argv) {
fprintf(stderr, "shared: %d\n", shared); fprintf(stderr, "shared: %d\n", shared);
fprintf(stderr, "authfile: %s\n", auth_file ? auth_file fprintf(stderr, "authfile: %s\n", auth_file ? auth_file
: "null"); : "null");
fprintf(stderr, "passfile: %s\n", passwdfile ? passwdfile
: "null");
fprintf(stderr, "logfile: %s\n", logfile ? logfile
: "null");
fprintf(stderr, "allow: %s\n", allow_list ? allow_list fprintf(stderr, "allow: %s\n", allow_list ? allow_list
: "null"); : "null");
fprintf(stderr, "accept: %s\n", accept_cmd ? accept_cmd fprintf(stderr, "accept: %s\n", accept_cmd ? accept_cmd
: "null"); : "null");
fprintf(stderr, "gone: %s\n", gone_cmd ? gone_cmd
: "null");
fprintf(stderr, "conn_once: %d\n", connect_once); fprintf(stderr, "conn_once: %d\n", connect_once);
fprintf(stderr, "connect: %s\n", client_connect fprintf(stderr, "connect: %s\n", client_connect
? client_connect : "null"); ? client_connect : "null");
...@@ -6296,7 +6727,9 @@ int main(int argc, char** argv) { ...@@ -6296,7 +6727,9 @@ int main(int argc, char** argv) {
n = open("/dev/null", O_RDONLY); n = open("/dev/null", O_RDONLY);
dup2(n, 0); dup2(n, 0);
dup2(n, 1); dup2(n, 1);
dup2(n, 2); if (! logfile) {
dup2(n, 2);
}
if (n > 2) { if (n > 2) {
close(n); close(n);
} }
......
...@@ -167,7 +167,7 @@ httpCheckFds(rfbScreenInfoPtr rfbScreen) ...@@ -167,7 +167,7 @@ httpCheckFds(rfbScreenInfoPtr rfbScreen)
rfbLog("Rejected HTTP connection from client %s\n", rfbLog("Rejected HTTP connection from client %s\n",
inet_ntoa(addr.sin_addr)); inet_ntoa(addr.sin_addr));
#else #else
flags = fcntl(rfbScreen->httpSock, F_SETFL); flags = fcntl(rfbScreen->httpSock, F_GETFL);
if (flags < 0 || fcntl(rfbScreen->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) { if (flags < 0 || fcntl(rfbScreen->httpSock, F_SETFL, flags | O_NONBLOCK) == -1) {
rfbLogPerror("httpCheckFds: fcntl"); rfbLogPerror("httpCheckFds: fcntl");
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment