Commit 5c13bd0c authored by runge's avatar runge

x11vnc: -users lurk=, -solid for cde, -gui ez,.. beginner mode.

parent 86ccf267
2005-02-14 Karl Runge <runge@karlrunge.com>
* x11vnc: -users lurk=, -solid for cde, -gui ez,.. beginner mode.
2005-02-10 Karl Runge <runge@karlrunge.com>
* x11vnc: -input option to fine tune allowed client input,
additions to remote control and gui for this.
......
2005-02-14 Karl Runge <runge@karlrunge.com>
* cleanup -users stuff, add "lurk=" mode
* support cde in -solid
* simple gui mode for beginners, -gui ez,...
2005-02-10 Karl Runge <runge@karlrunge.com>
* Add -input to fine tune client input (keystroke, mouse motion,
and button presses). Allow per-client setting via remote cntl.
......
x11vnc README file Date: Thu Feb 10 23:33:03 EST 2005
x11vnc README file Date: Mon Feb 14 14:23:56 EST 2005
The following information is taken from these URLs:
......@@ -889,7 +889,9 @@ ls -l ./x11vnc/x11vnc
the person sitting at the X session types "xhost +localhost" then one
should be able to attach x11vnc to the session (from the same
machine). The person could then type "xhost -localhost" after x11vnc
has connected to go back to the default permissions.
has connected to go back to the default permissions. Also, for some
situations the -users lurk= option may be of use (please read the
documentation on the -users option).
Some Linux distributions or display managers may set XAUTHORITY to a
random local filename. You need to dig out where they have hidden the
......@@ -2246,9 +2248,9 @@ ied)
has been added to allow exact extraction of the mouse cursor shape.
The only issue is the handling of alpha channel transparency in
cursors (they must be approximated). XFIXES is available on recent
Linux Xorg based distros and Solaris 10 express (on Solaris you will
need to add "-L /usr/openwin/sfw/lib -R /usr/openwin/sfw/lib" to
LDFLAGS for configure to enable it).
Linux Xorg based distros and Solaris 10 (on Solaris you will need to
add "-L /usr/openwin/sfw/lib -R /usr/openwin/sfw/lib" to LDFLAGS for
configure to enable it).
Q-43: When using XFIXES cursorshape mode, some of the cursors look
really bad with extra black borders around the cursor and other cruft.
......@@ -3088,8 +3090,8 @@ x11vnc: a VNC server for real X displays
Here are all of x11vnc command line options:
% x11vnc -opts (see below for -help long descriptions)
x11vnc: allow VNC connections to real X11 displays. 0.7.1pre lastmod: 2005-02-0
5
x11vnc: allow VNC connections to real X11 displays. 0.7.1pre lastmod: 2005-02-1
4
x11vnc options:
-display disp -auth file
......@@ -3102,9 +3104,10 @@ x11vnc options:
-timeout n -inetd
-connect string -vncconnect
-novncconnect -allow host1[,host2..]
-localhost -viewpasswd string
-passwdfile filename -storepasswd pass file
-accept string -gone string
-localhost -input string
-viewpasswd string -passwdfile filename
-storepasswd pass file -accept string
-gone string -users list
-noshm -flipbyteorder
-onetile -solid [color]
-blackout string -xinerama
......@@ -3163,8 +3166,8 @@ libvncserver options:
% x11vnc -help
x11vnc: allow VNC connections to real X11 displays. 0.7.1pre lastmod: 2005-02-0
5
x11vnc: allow VNC connections to real X11 displays. 0.7.1pre lastmod: 2005-02-1
4
Typical usage is:
......@@ -3210,7 +3213,8 @@ Options:
environment variable to "disp".
-auth file Set the X authority file to be "file", equivalent to
setting the XAUTHORITY environment variable to "file"
before startup. See Xsecurity(7), xauth(1) man pages.
before startup. Same as -xauth file. See Xsecurity(7),
xauth(1) man pages for more info.
-id windowid Show the window corresponding to "windowid" not
the entire display. New windows like popup menus,
......@@ -3307,10 +3311,13 @@ Options:
-connect string For use with "vncviewer -listen" reverse connections.
If "string" has the form "host" or "host:port"
the connection is made once at startup. Use commas
for a list of host's and host:port's. If "string"
contains "/" it is instead interpreted as a file to
periodically check for new hosts. The first line is
read and then the file is truncated.
for a list of host's and host:port's.
If "string" contains "/" it is instead interpreted
as a file to periodically check for new hosts.
The first line is read and then the file is truncated.
Be careful for this usage mode if x11vnc is running as
root (e.g. via inetd(1) or gdm(1)).
-vncconnect Monitor the VNC_CONNECT X property set by the standard
-novncconnect VNC program vncconnect(1). When the property is
set to "host" or "host:port" establish a reverse
......@@ -3327,14 +3334,30 @@ Options:
each time a new client connects. Lines can be commented
out with the "#" character in the usual way.
-localhost Same as -allow 127.0.0.1
-input string Fine tuning of allowed user input. If "string" does
not contain a comma "," the tuning applies only to
normal clients. Otherwise the part before "," is
for normal clients and the part after for view-only
clients. "K" is for Keystroke input, "M" for
Mouse-motion input, and "B" for Button-click input.
Their presence in the string enables that type of input.
E.g. "-input M" means normal users can only move
the mouse and "-input KMB,M" lets normal users do
anything and enables view-only users to move the mouse.
This option is ignored when a global -viewonly is in
effect (all input is discarded).
-viewpasswd string Supply a 2nd password for view-only logins. The -passwd
(full-access) password must also be supplied.
-passwdfile filename Specify libvncserver -passwd via the first line of
the file "filename" instead of via command line.
If a second non blank line exists in the file it is
taken as a view-only password (i.e. -viewpasswd) Note:
this is a simple plaintext passwd, see also -rfbauth
and -storepasswd below for obfuscated passwords.
If a second non blank line exists in the file it
is taken as a view-only password (i.e. -viewpasswd)
To supply an empty password for either field use the
string "__EMPTY__". Note: -passwdfile is a simple
plaintext passwd, see also -rfbauth and -storepasswd
below for obfuscated passwords. Neither should be
readable by others.
-storepasswd pass file Store password "pass" as the VNC password in the
file "file". Once the password is stored the
program exits. Use the password via "-rfbauth file"
......@@ -3348,6 +3371,11 @@ Options:
otherwise the client is rejected. See below for an
extension to accept a client view-only.
If x11vnc is running as root (say from inetd(1) or from
display managers xdm(1), gdm(1), etc), think about the
security implications carefully before supplying this
option (likewise for the -gone option).
Environment: The RFB_CLIENT_IP environment variable will
be set to the incoming client IP number and the port
in RFB_CLIENT_PORT (or -1 if unavailable). Similarly,
......@@ -3399,6 +3427,74 @@ Options:
in -accept. Unlike -accept, the command return code
is not interpreted by x11vnc. Example: -gone 'xlock &'
-users list If x11vnc is started as root (say from inetd(1) or
from display managers xdm(1), gdm(1), etc), then as
soon as possible after connections to the display are
established try to switch to one of the users in the
comma separated "list". If x11vnc is not running as
root this option is ignored.
Why use this option? In general it is not needed
since x11vnc is already connected to the display and
can perform its primary functions. The option was
added to make some of the *external* utility commands
x11vnc occasionally runs work properly. In particular
under GNOME and KDE to implement the "-solid color"
feature external commands (gconftool-2 and dcop) must be
run as the user owning the desktop session. Since this
option switches userid it also affects the userid used
to run the processes for the -accept and -gone options.
It also affects the ability to read files for options
such as -connect, -allow, and -remap. Note that the
-connect file is also sometimes written to.
So be careful with this option since in many situations
its use can decrease security.
The switch to a user will only take place if the
display can still be successfully opened as that user
(this is primarily to try to guess the actual owner
of the session). Example: "-users fred,wilma,betty".
Note that a malicious user "barney" by quickly using
"xhost +" when logging in may get x11vnc to switch
to user "fred". What happens next?
Under display managers it may be a long time before
the switch succeeds (i.e. a user logs in). To make
it switch immediately regardless if the display
can be reopened prefix the username with the +
character. E.g. "-users +bob" or "-users +nobody".
The latter (i.e. switching immediately to user
"nobody") is probably the only use of this option
that increases security.
To immediately switch to a user *before* connections to
the display are made or any files opened use the "="
character: "-users =bob". That user needs to be able
to open the display of course.
The special user "guess=" means to examine the utmpx
database (see who(1)) looking for a user attached to
the display number (from DISPLAY or -display option)
and try him/her. To limit the list of guesses, use:
"-users guess=bob,betty".
Even more sinister is the special user "lurk=" that
means to try to guess the DISPLAY from the utmpx login
database as well. So it "lurks" waiting for anyone
to log into an X session and then connects to it.
Specify a list of users after the = to limit which
users will be tried. If the first user in the list
is something like ":0" or ":0-2" that indicates a
range of DISPLAY numbers that will be tried (regardless
of whether they are in the utmpx database) for all
users that are logged in. Examples: "-users lurk="
and "-users lurk=:0-1,bob,mary"
Be especially careful using the "guess=" and "lurk="
modes. They are not recommended for use on machines
with untrustworthy local users.
-noshm Do not use the MIT-SHM extension for the polling.
Remote displays can be polled this way: be careful this
can use large amounts of network bandwidth. This is
......@@ -3414,15 +3510,18 @@ Options:
try to change the desktop background to a solid color.
The [color] is optional: the default color is "cyan4".
For a different one specify the X color (rgb.txt name,
e.g. "darkblue" or numerical "#RRGGBB"). Currently
this option only works on GNOME, KDE, and classic X
(i.e. with the background image on the root window).
The "gconftool-2" and "dcop" external commands are
run for GNOME and KDE respectively. Other desktops
won't work, e.g. XFCE (send us the corresponding
commands if you find them). If x11vnc guesses your
desktop incorrectly, you can force it by prefixing
color with "gnome:", "kde:", or "root:".
e.g. "darkblue" or numerical "#RRGGBB").
Currently this option only works on GNOME, KDE, CDE,
and classic X (i.e. with the background image on the
root window). The "gconftool-2" and "dcop" external
commands are run for GNOME and KDE respectively.
Other desktops won't work, e.g. XFCE (send us the
corresponding commands if you find them). If x11vnc is
running as root (inetd(1) or gdm(1)), the -users option
may be needed for GNOME and KDE. If x11vnc guesses
your desktop incorrectly, you can force it by prefixing
color with "gnome:", "kde:", "cde:" or "root:".
-blackout string Black out rectangles on the screen. "string" is a
comma separated list of WxH+X+Y type geometries for
each rectangle.
......@@ -3818,9 +3917,11 @@ Options:
up on the X display in the environment variable DISPLAY.
"gui-opts" can be a comma separated list of items.
Currently there are only two types of items: 1) a gui
mode and 2) the X display the gui should display on.
The gui mode can be "start", "conn", or "wait"
Currently there are these types of items: 1) a gui mode,
a 2) gui "simplicity", and 3) the X display the gui
should display on.
1) The gui mode can be "start", "conn", or "wait"
"start" is the default mode above and is not required.
"conn" means do not automatically start up x11vnc,
but instead just try to connect to an existing x11vnc
......@@ -3828,16 +3929,22 @@ Options:
else (you will later instruct the gui to start x11vnc
or connect to an existing one.)
Note the possible confusion regarding the potentially
2) The gui simplicity is off by default (a power-user
gui with all options is presented) To start with
something less daunting supply the string "simple"
("ez" is an alias for this). Once the gui is
started you can toggle between the two with "Misc ->
simple_gui".
3) Note the possible confusion regarding the potentially
two different X displays: x11vnc polls one, but you
may want the gui to appear on another. For example, if
you ssh in and x11vnc is not running yet you may want
the gui to come back to you via your ssh redirected X
display (e.g. localhost:10).
Examples: "x11vnc -gui", "x11vnc -gui localhost:10",
"x11vnc -gui :10", "x11vnc -gui wait,:10",
"x11vnc -gui <x11vnc-opts...>"
Examples: "x11vnc -gui", "x11vnc -gui ez"
"x11vnc -gui localhost:10", "x11vnc -gui conn,host:0"
If you do not specify a gui X display in "gui-opts"
then the DISPLAY environment variable and -display
......@@ -3935,6 +4042,11 @@ Options:
use "-host" to delete a single host
localhost enable -localhost mode
nolocalhost disable -localhost mode
input:str set -input to "str", empty to disable.
client_input:str set the K, M, B -input on a per-client
basis. select which client as for
disconnect, e.g. client_input:host:MB
or client_input:0x2:K
accept:cmd set -accept "cmd" (empty to disable).
gone:cmd set -gone "cmd" (empty to disable).
noshm enable -noshm mode.
......@@ -4103,13 +4215,13 @@ Options:
xrandr_mode padgeom quiet q noquiet modtweak nomodtweak
xkb noxkb skip_keycodes add_keysyms noadd_keysyms
clear_mods noclear_mods clear_keys noclear_keys
remap repeat norepeat fb nofb bell nobell sel nosel
primary noprimary cursorshape nocursorshape cursorpos
nocursorpos cursor show_cursor noshow_cursor
nocursor xfixes noxfixes alphacut alphafrac
alpharemove noalpharemove alphablend noalphablend
xwarp xwarppointer noxwarp noxwarppointer buttonmap
dragging nodragging pointer_mode pm input_skip speeds
remap repeat norepeat fb nofb bell nobell sel
nosel primary noprimary cursorshape nocursorshape
cursorpos nocursorpos cursor show_cursor noshow_cursor
nocursor xfixes noxfixes alphacut alphafrac alpharemove
noalpharemove alphablend noalphablend xwarp xwarppointer
noxwarp noxwarppointer buttonmap dragging nodragging
pointer_mode pm input_skip input client_input speeds
debug_pointer dp nodebug_pointer nodp debug_keyboard dk
nodebug_keyboard nodk deferupdate defer wait rfbwait
nap nonap sb screen_blank fs gaps grow fuzz snapfb
......@@ -4119,7 +4231,7 @@ Options:
nodontdisconnect desktop noremote
aro= display vncdisplay desktopname http_url auth
rootshift scale_str scaled_x scaled_y scale_numer
users rootshift scale_str scaled_x scaled_y scale_numer
scale_denom scale_fac scaling_noblend scaling_nomult4
scaling_pad scaling_interpolate inetd safer unsafe
passwdfile using_shm logfile o rc norc h help V version
......@@ -4157,10 +4269,13 @@ Options:
Note that if they can modify VNC_CONNECT, they could
also run their own x11vnc and have complete control
of the desktop. If the "-connect /path/to/file"
channel is being used, obviously anyone who can write
to /path/to/file can remotely control x11vnc. So be
sure to protect the X display and that file's write
permissions.
channel is being used, obviously anyone who can
write to /path/to/file can remotely control x11vnc.
So be sure to protect the X display and that file's
write permissions.
To disable the VNC_CONNECT property channel completely
use -novncconnect.
-unsafe If x11vnc is running as root (e.g. inetd or Xsetup for
a display manager) a few remote commands are disabled
......
......@@ -3,7 +3,7 @@
exec wish "$0" "$@"
catch {rename send {}}
#
# Copyright (c) 2004 Karl J. Runge <runge@karlrunge.com>
# Copyright (c) 2004-2005 Karl J. Runge <runge@karlrunge.com>
# All rights reserved.
#
# This is free software; you can redistribute it and/or modify
......@@ -45,9 +45,6 @@ catch {rename send {}}
# R means it is an action only valid in remote mode.
# S means it is an action only valid in startup mode.
# Q means it is an action worth querying after running.
# D means it is a good idea to delay a little before querying
# (i.e. perhaps it causes x11vnc to do a lot of work, new fb)
# No longer used, -sync is used instead.
# P means the string can be +/- appended/deleted (string may not
# be the same after the remote command)
# G means gui internal item
......@@ -66,61 +63,61 @@ Row: Displays Screen Tuning Debugging Misc
Actions
=SA start
=RA stop
=GA attach
=RA detach
=DGA attach
=DRA detach
--
=RA ping
=RA update-all
=GA clear-all
--
=RA stop+quit
=GA Quit
-- D
=DRA stop+quit
=DGA Quit
Help
=GA gui
=DGA gui
=GA all
Clients
=RQA current:
=F connect:
=RQA disconnect:
=DRQA current:
=DF connect:
=DRQA disconnect:
--
accept:
gone:
vncconnect
--
http
-- D
=D http
=F httpdir:
httpport:
enablehttpproxy
Displays
display:
=D display:
=F auth:
desktop:
rfbport:
=D desktop:
=D rfbport:
=0 gui:
Screen
=DRA refresh
=DRA reset
=RA reset
=DRA blacken
--
=D id:
=D sid:
-- D
id:
sid:
=D scale:
--
=D overlay
overlay
overlay_nocursor
--
=D visual:
visual:
flashcmap
notruecolor
--
=DP blackout:
=D xinerama
=P blackout:
xinerama
--
solid
=D solid
solid_color:
--
= xrandr
......@@ -128,8 +125,8 @@ Screen
padgeom:
Keyboard
norepeat
add_keysyms
=D norepeat
=D add_keysyms
skip_keycodes:
modtweak
xkb
......@@ -140,25 +137,27 @@ Keyboard
clear_keys
Pointer
=-C:none,arrow,X,some,most cursor:
=D-C:none,arrow,X,some,most cursor:
noxfixes
noalphablend
--
cursorpos
nocursorshape
=D nocursorshape
--
buttonmap:
--
xwarppointer
Misc
=GD simple-gui
-- D
=F rc:
norc
--
nofb
--
nobell
nosel
=D nobell
=D nosel
noprimary
--
bg
......@@ -178,29 +177,29 @@ Debugging
quiet
--
=GA show-start-cmd
=G debug_gui
=DG debug_gui
Permissions
=RQA lock
=RQA unlock
=DRQA lock
=DRQA unlock
=SQA deny_all
--
=FP allow:
=DFP allow:
localhost
=RA allowonce:
--
-- D
=RA noremote
--
viewonly
shared
forever
=D viewonly
=D shared
=D forever
timeout:
--
input:
--
=SA alwaysshared
=SA nevershared
=SA dontdisconnect
=S alwaysshared
=S nevershared
=S dontdisconnect
--
viewpasswd:
=F passwdfile:
......@@ -212,22 +211,22 @@ Permissions
unsafe
Tuning
=-C:0,1,2,3,4 pointer_mode:
=D-C:0,1,2,3,4 pointer_mode:
input_skip:
nodragging
=D nodragging
--
=D noshm
noshm
flipbyteorder
onetile
--
alphacut:
alphafrac:
alpharemove
--
-- D
speeds:
wait:
=D wait:
defer:
nap
=D nap
screen_blank:
--
fs:
......@@ -357,6 +356,12 @@ Set the -solid color value.
set helptext(xrandr_mode) "
Set the -xrandr mode value.
"
set helptext(simple-gui) "
Toggle between menu items corresponding the most basic ones
and all possible settings. I.e. toggle between a simple gui
and one for power users.
"
set helptext(all) $helpall
......@@ -366,7 +371,7 @@ tkx11vnc is a simple frontend to x11vnc. Nothing fancy, it merely
provides an interface to each of the many x11vnc command line options and
remote control commands. See \"Help -> all\" for much info about x11vnc.
Most menu items have a (?) button one can click on to get more information
All menu items have a (?) button one can click on to get more information
about the option or command.
There are two states tkx11vnc can be in:
......@@ -465,9 +470,60 @@ is feasible). These options overlap with the x11vnc options -shared
and -forever which are hopefully enough for most usage. They may be
specified for x11vnc startup if desired.
"
global beginner_mode
if {$beginner_mode} {
set helptext(gui) "
tkx11vnc is a simple frontend to x11vnc. It is currently running in
\"ez\" or \"simple\" mode. For many more options run it in normal
mode buy toggling \"Misc -> simple_gui\".
All menu items have a (?) button one can click on to get more information
about the option or command.
GUI components:
--- ----------
1) At the top of the gui is a info text label where information will
be posted, e.g. when traversing menu items text indicating how to get
help on the item and its current value will be displayed.
2) Below the info label is the area where the menu buttons, Actions,
Clients, etc., are presented. If a menu item has a checkbox,
it corresponds to a boolean on/off variable. Otherwise it is
either a string variable, or an action not associated with a
variable (for the most part).
3) Below the menu button area is a text label indicating the current x11vnc
X display being polled and the corresponding VNC display name. Both
will be \"(*none*)\" when there is no connection established.
4) Below the x11 and vnc displays text label is a text area there scrolling
information about actions being taken and commands being run is displayed.
To scroll click in the area and use PageUp/PageDown or the arrow keys.
5) At the bottom is an entry area. When one selects a menu item that
requires supplying a string value, the label will be set to the
parameter name and one types in the new value. Then one presses the
\"OK\" button or presses \"Enter\" to set the value. Or you can press
\"Skip\" or \"Escape\" to avoid changing the variable. Some variables
are boolean toggles (for example, \"Permissions -> viewonly\") or Radio
button selections. Selecting these menu items will not activate the
entry area but rather toggle the variable directly.
Cascades Bug: There is a bug not yet worked around for the cascade menus
where the (?) help button gets in the way. To get the mouse over to
the cascade menu click and release mouse to activate the cascade, then
you can click on its items. Dragging with a mouse button held down will
not work (sorry!).
"
}
}
proc center_win {w} {
wm withdraw $w
set x [expr [winfo screenwidth $w]/2 - [winfo reqwidth $w]/2];
......@@ -555,6 +611,10 @@ proc active_when_connected {item} {
if {[opt_match G $item]} {
return 1
} elseif {[opt_match R $item]} {
return 1
} elseif {[opt_match S $item]} {
return 0
} elseif {[is_action $item]} {
if {[opt_match R $item]} {
return 1
......@@ -569,10 +629,27 @@ proc active_when_connected {item} {
}
proc active_when_starting {item} {
global helpremote helptext
global helpremote helptext beginner_mode
if {$beginner_mode} {
if {[opt_match G $item]} {
return 1
}
if {$item == "display"} {
return 1
}
if {$item == "debug_gui"} {
return 1
}
return 0
}
if {[opt_match G $item]} {
return 1
} elseif {[opt_match S $item]} {
return 1
} elseif {[opt_match R $item]} {
return 0
} elseif {[is_action $item]} {
if {[opt_match S $item]} {
return 1
......@@ -1120,8 +1197,10 @@ proc insert_input_window {} {
global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb
append_text "\nUse these checkboxes to set the input permissions, "
append_text "or type in the \"KMB...\"\n-input string manually. "
append_text "Then press \"OK\" or \"Skip\".\n\n"
append_text "or type in the \"KMB...\"\n"
append_text "-input string manually. Then press \"OK\" or \"Skip\".\n"
append_text "(note: an empty setting means use the default behavior, "
append_text "see viewonly)\n\n"
set w "$text_area.wk_f"
catch {destroy $w}
frame $w -bd 1 -relief ridge -cursor {top_left_arrow}
......@@ -1136,7 +1215,7 @@ proc insert_input_window {} {
-pady 1 -command set_kmb_str -text "Mouse Motion"
checkbutton $fl.bb -font $ffont -anchor w -variable vl_bb \
-pady 1 -command set_kmb_str -text "Button Clicks"
label $fr.l -pady 1 -font $ffont -text "View-only clients:"
label $fr.l -pady 1 -font $ffont -text "View-Only clients:"
checkbutton $fr.bk -font $ffont -anchor w -variable vr_bk \
-pady 1 -command set_kmb_str -text "Keystrokes"
checkbutton $fr.bm -font $ffont -anchor w -variable vr_bm \
......@@ -1623,7 +1702,7 @@ proc tail_logfile {} {
set xterm_cmd "xterm -sb -fn $ffont -geometry 80x45 -title x11vnc-logfile -e"
set cmd [split $xterm_cmd]
lappend cmd "tail"
lappend cmd "+1f"
lappend cmd "-3000f"
lappend cmd $logfile
lappend cmd "&"
catch {[eval exec $cmd]}
......@@ -1665,14 +1744,18 @@ proc detach_from_display {} {
# Menu item is an action:
proc do_action {item} {
global menu_var connected_to_x11vnc
global menu_var connected_to_x11vnc beginner_mode
if {[in_debug_mode]} {
append_text "action: \"$item\"\n"
}
if {$item == "ping"} {
if {$beginner_mode} {
try_connect_and_query_all
} else {
try_connect
}
return
} elseif {$item == "start"} {
start_x11vnc
......@@ -1976,7 +2059,7 @@ proc client_dialog {client} {
set sm 0
set sb 0
if {[regexp -nocase {K} $input]} {
append_text "Keystroke"
append_text "Keystrokes"
set sk 1
}
if {[regexp -nocase {M} $input]} {
......@@ -1990,7 +2073,7 @@ proc client_dialog {client} {
if {$sk || $sm} {
append_text ", "
}
append_text "Button-Click"
append_text "Button-Clicks"
set sb 1
}
if {! $sk && ! $sm && ! $sb} {
......@@ -2020,7 +2103,7 @@ proc client_dialog {client} {
} elseif {[regexp -nocase {(disconnect|close)} $val]} {
disconnect_dialog $client
} else {
regsub -all -nocase {[^KMB]} $val ""
regsub -all -nocase {[^KMB]} $val "" val
set item_bool(client_input) 0
push_new_value "client_input" "client_input" "$cid:$val" 0
}
......@@ -2119,6 +2202,10 @@ proc set_widgets {} {
set case $item_case($item)
set menu $menu_m($case)
set entry $item_entry($item)
if {$entry < 0} {
# skip case under beginner_mode
continue
}
set type [$menu type $entry]
if {$type == "separator" || $type == "tearoff"} {
continue
......@@ -2126,102 +2213,52 @@ proc set_widgets {} {
if {$connected_to_x11vnc} {
if {[active_when_connected $item]} {
$menu entryconfigure $entry -state normal
#puts "n-1 $case / $item / $entry"
} else {
$menu entryconfigure $entry -state disabled
#puts "I-1 $case / $item / $entry"
}
} else {
if {[active_when_starting $item]} {
$menu entryconfigure $entry -state normal
#puts "n-2 $case / $item / $entry"
} else {
$menu entryconfigure $entry -state disabled
#puts "I-2 $case / $item / $entry"
}
}
}
}
proc make_widgets {} {
global template
global menu_b menu_m
global item_opts item_bool item_case item_entry menu_var unset_str
global item_cascade
global info_label info_str x11_display vnc_display
global text_area
global entry_box entry_str entry_set entry_label entry_ok entry_browse
global entry_help entry_skip
global bfont ffont
global helptext helpremote helplabel
set label_width 80
set info_label .info
label $info_label -textvariable info_str -bd 2 -relief groove \
-anchor w -width $label_width -font $ffont
pack $info_label -side top -fill x -expand 0
# Extract the Rows:
set row 0;
set colmax 0;
foreach line [split $template "\n"] {
if {[regexp {^Row: (.*)} $line rest]} {
set col 0
foreach case [split $rest] {
if {$case == "" || $case == "Row:"} {
continue
}
set menu_row($case) $row
set menu_col($case) $col
set menu_count($case) 0
proc toggle_simple_gui {} {
global beginner_mode simple_gui_created
global connected_to_x11vnc
lappend cases($col) $case;
set len [string length $case]
if {[info exists max_len($col)]} {
if {$len > $max_len($col)} {
set max_len($col) $len
}
if {$beginner_mode} {
append_text "\nSwitching to simple-gui mode.\n"
} else {
set max_len($col) $len
}
incr col
if {$col > $colmax} {
set colmax $col
}
}
incr row;
}
append_text "\nSwitching to power-user gui mode.\n"
}
# Make frames for the rows and make the menu buttons.
set f ".menuframe"
frame $f
for {set c 0} {$c < $colmax} {incr c} {
set colf "$f.menuframe$c"
frame $colf
pack $colf -side left -fill y
set fbg [$colf cget -background]
foreach case $cases($c) {
set menub "$colf.menu$case";
set menu "$colf.menu$case.menu";
set menu_b($case) $menub
set menu_m($case) $menu
set ul 0
foreach char [split $case ""] {
set char [string tolower $char]
if {![info exists underlined($char)]} {
set underlined($char) 1
break
}
incr ul
}
menubutton $menub -text "$case" -underline $ul \
-anchor w -menu $menu -background $fbg \
-font $bfont
pack $menub -side top -fill x
menu $menu -tearoff 0
}
set simple_gui_created 1
make_menu_items
set_widgets
set_internal_help
if {$connected_to_x11vnc} {
query_all
}
pack $f -side top -fill x
append_text "\n"
}
proc make_menu_items {} {
global template
global menu_b menu_m menu_count
global item_opts item_bool item_case item_entry menu_var unset_str
global item_cascade
global bfont ffont beginner_mode simple_gui_created
global helptext helpremote helplabel
# Now extract the menu items:
# Extract the menu items:
set case "";
foreach line [split $template "\n"] {
if {[regexp {^Row:} $line]} {
......@@ -2229,8 +2266,19 @@ proc make_widgets {} {
}
if {[regexp {^[A-z]} $line]} {
set case [string trim $line]
if {$simple_gui_created} {
set i0 0
if {$case == "Misc"} {
# kludge for simple_gui
set i0 1
}
catch {$menu_m($case) delete $i0 end}
}
set menu_count($case) 0
continue;
}
set item [string trim $line]
regsub -all { *} $item " " item
if {$item == ""} {
......@@ -2252,17 +2300,29 @@ proc make_widgets {} {
}
regsub {:$} $item {} item
if {$item == "-- D"} {
set beginner_sep 1
set item "--"
} else {
set beginner_sep 0
}
set item_opts($item) $opts
set item_case($item) $case
set item_bool($item) $bool
set item_cascade($item) ""
set item_entry($item) $menu_count($case)
if {0} { puts "ITEM: $item - $opts - $case - $bool - $menu_count($case)" }
set mvar 0
set m $menu_m($case)
if {$beginner_mode && ! $beginner_sep && ![opt_match D $item]} {
set item_entry($item) "-1"
continue;
}
if {0} { puts "ITEM: $item\t- $opts\t- $case\t- $bool\t- $menu_count($case)" }
# Create the menu items, its variables, etc., etc.
if {$item == "--"} {
......@@ -2282,7 +2342,8 @@ proc make_widgets {} {
} elseif {$item == "current"} {
# Current clients cascade
set subm $m.cascade$menu_count($case)
set subm $m.current_cascade
catch {destroy $subm}
set item_cascade($item) $subm
update_clients_menu ""
$m add cascade -label "$item" \
......@@ -2300,7 +2361,8 @@ proc make_widgets {} {
# String
if {[regexp -- {-C:(.*)} $item_opts($item) m0 m1]} {
# Radiobutton select
set subm $m.cascade$menu_count($case)
set subm $m.radio_cascade$menu_count($case)
catch {destroy $subm}
menu $subm -tearoff 0 -font $ffont
foreach val [split $m1 ","] {
$subm add radiobutton -label "$val" \
......@@ -2321,6 +2383,13 @@ proc make_widgets {} {
}
set mvar 1
} elseif {$item == "simple-gui"} {
if {! $simple_gui_created} {
$m add checkbutton -label "$item" \
-command "toggle_simple_gui" \
-font $ffont \
-variable beginner_mode
}
} else {
# Boolean
$m add checkbutton -label "$item" \
......@@ -2331,12 +2400,13 @@ proc make_widgets {} {
}
incr menu_count($case)
if {$mvar} {
set menu_var($item) $unset_str
}
}
# Now make the litte "(?)" help buttons
# Now make the little "(?)" help buttons
foreach case [array names menu_m] {
if {$case == "Help"} {
continue;
......@@ -2376,6 +2446,90 @@ proc make_widgets {} {
}
}
}
}
proc make_widgets {} {
global template
global menu_b menu_m menu_count
global item_opts item_bool item_case item_entry menu_var unset_str
global item_cascade
global info_label info_str x11_display vnc_display
global text_area
global entry_box entry_str entry_set entry_label entry_ok entry_browse
global entry_help entry_skip
global bfont ffont beginner_mode
global helptext helpremote helplabel
# Make the top label
set label_width 80
set info_label .info
label $info_label -textvariable info_str -bd 2 -relief groove \
-anchor w -width $label_width -font $ffont
pack $info_label -side top -fill x -expand 0
# Extract the Rows:
set row 0;
set colmax 0;
foreach line [split $template "\n"] {
if {[regexp {^Row: (.*)} $line rest]} {
set col 0
foreach case [split $rest] {
if {$case == "" || $case == "Row:"} {
continue
}
set menu_row($case) $row
set menu_col($case) $col
lappend cases($col) $case;
set len [string length $case]
if {[info exists max_len($col)]} {
if {$len > $max_len($col)} {
set max_len($col) $len
}
} else {
set max_len($col) $len
}
incr col
if {$col > $colmax} {
set colmax $col
}
}
incr row;
}
}
# Make frames for the rows and make the menu buttons.
set f ".menuframe"
frame $f
for {set c 0} {$c < $colmax} {incr c} {
set colf "$f.menuframe$c"
frame $colf
pack $colf -side left -fill y
set fbg [$colf cget -background]
foreach case $cases($c) {
set menub "$colf.menu$case";
set menu "$colf.menu$case.menu";
set menu_b($case) $menub
set menu_m($case) $menu
set ul 0
foreach char [split $case ""] {
set char [string tolower $char]
if {![info exists underlined($char)]} {
set underlined($char) 1
break
}
incr ul
}
menubutton $menub -text "$case" -underline $ul \
-anchor w -menu $menu -background $fbg \
-font $bfont
pack $menub -side top -fill x
menu $menu -tearoff 0
}
}
pack $f -side top -fill x
make_menu_items
# Make the x11 and vnc display label bar:
set df .displayframe
......@@ -2552,9 +2706,9 @@ proc stop_watch {onoff} {
proc double_check_noremote {} {
set msg "\n\n"
append msg "WARNING: setting \"noremote\" will disable ALL remote control commands\n"
append msg "WARNING: (i.e. this gui will be locked out) Do you really want to do this?\n"
append msg "WARNING: If so, press \"OK\", otherwise press \"Skip\"\n"
append msg "*** WARNING: setting \"noremote\" will disable ALL remote control commands (i.e.\n"
append msg "*** WARNING: *this* gui will be locked out). Do you really want to do this?\n"
append msg "*** WARNING: If so, press \"OK\", otherwise press \"Skip\"\n"
append msg "\n"
bell
return [warning_dialog $msg "noremote"]
......@@ -2829,7 +2983,7 @@ proc try_connect {} {
# main:
global env x11vnc_prog x11vnc_cmdline x11vnc_xdisplay x11vnc_connect;
global x11vnc_auth_file
global x11vnc_auth_file beginner_mode simple_gui_created
global helpall helptext helpremote helplabel hostname;
global all_settings reply_xdisplay always_update
global max_text_height max_text_width
......@@ -2920,6 +3074,13 @@ if {[info exists env(X11VNC_AUTH_FILE)]} {
set x11vnc_auth_file ""
}
set simple_gui_created 0
if {[info exists env(X11VNC_SIMPLE_GUI)]} {
set beginner_mode 1
} else {
set beginner_mode 0
}
set hostname [exec uname -n]
#puts [exec env]
......
......@@ -9,7 +9,7 @@
"exec wish \"$0\" \"$@\"\n"
"catch {rename send {}}\n"
"#\n"
"# Copyright (c) 2004 Karl J. Runge <runge@karlrunge.com>\n"
"# Copyright (c) 2004-2005 Karl J. Runge <runge@karlrunge.com>\n"
"# All rights reserved.\n"
"#\n"
"# This is free software; you can redistribute it and/or modify\n"
......@@ -51,9 +51,6 @@
"# R means it is an action only valid in remote mode.\n"
"# S means it is an action only valid in startup mode.\n"
"# Q means it is an action worth querying after running.\n"
"# D means it is a good idea to delay a little before querying \n"
"# (i.e. perhaps it causes x11vnc to do a lot of work, new fb)\n"
"# No longer used, -sync is used instead.\n"
"# P means the string can be +/- appended/deleted (string may not\n"
"# be the same after the remote command)\n"
"# G means gui internal item\n"
......@@ -72,61 +69,61 @@
"Actions\n"
" =SA start\n"
" =RA stop\n"
" =GA attach\n"
" =RA detach\n"
" =DGA attach\n"
" =DRA detach\n"
" --\n"
" =RA ping\n"
" =RA update-all\n"
" =GA clear-all\n"
" --\n"
" =RA stop+quit \n"
" =GA Quit \n"
" -- D\n"
" =DRA stop+quit \n"
" =DGA Quit \n"
"\n"
"Help\n"
" =GA gui\n"
" =DGA gui\n"
" =GA all\n"
"\n"
"Clients\n"
" =RQA current:\n"
" =F connect:\n"
" =RQA disconnect:\n"
" =DRQA current:\n"
" =DF connect:\n"
" =DRQA disconnect:\n"
" --\n"
" accept:\n"
" gone:\n"
" vncconnect\n"
" --\n"
" http\n"
" -- D\n"
" =D http\n"
" =F httpdir:\n"
" httpport:\n"
" enablehttpproxy\n"
"\n"
"Displays\n"
" display:\n"
" =D display:\n"
" =F auth:\n"
" desktop:\n"
" rfbport:\n"
" =D desktop:\n"
" =D rfbport:\n"
" =0 gui:\n"
"\n"
"Screen\n"
" =DRA refresh\n"
" =DRA reset\n"
" =RA reset\n"
" =DRA blacken\n"
" --\n"
" =D id:\n"
" =D sid:\n"
" -- D\n"
" id:\n"
" sid:\n"
" =D scale:\n"
" --\n"
" =D overlay\n"
" overlay\n"
" overlay_nocursor\n"
" --\n"
" =D visual:\n"
" visual:\n"
" flashcmap\n"
" notruecolor\n"
" --\n"
" =DP blackout:\n"
" =D xinerama\n"
" =P blackout:\n"
" xinerama\n"
" --\n"
" solid\n"
" =D solid\n"
" solid_color:\n"
" --\n"
" = xrandr\n"
......@@ -134,8 +131,8 @@
" padgeom:\n"
"\n"
"Keyboard\n"
" norepeat\n"
" add_keysyms\n"
" =D norepeat\n"
" =D add_keysyms\n"
" skip_keycodes:\n"
" modtweak\n"
" xkb\n"
......@@ -146,25 +143,27 @@
" clear_keys\n"
"\n"
"Pointer\n"
" =-C:none,arrow,X,some,most cursor:\n"
" =D-C:none,arrow,X,some,most cursor:\n"
" noxfixes\n"
" noalphablend\n"
" --\n"
" cursorpos\n"
" nocursorshape\n"
" =D nocursorshape\n"
" --\n"
" buttonmap:\n"
" --\n"
" xwarppointer\n"
"\n"
"Misc\n"
" =GD simple-gui\n"
" -- D\n"
" =F rc:\n"
" norc\n"
" --\n"
" nofb\n"
" --\n"
" nobell\n"
" nosel\n"
" =D nobell\n"
" =D nosel\n"
" noprimary\n"
" --\n"
" bg\n"
......@@ -184,29 +183,29 @@
" quiet\n"
" --\n"
" =GA show-start-cmd\n"
" =G debug_gui\n"
" =DG debug_gui\n"
"\n"
"Permissions\n"
" =RQA lock\n"
" =RQA unlock\n"
" =DRQA lock\n"
" =DRQA unlock\n"
" =SQA deny_all\n"
" --\n"
" =FP allow:\n"
" =DFP allow:\n"
" localhost\n"
" =RA allowonce:\n"
" --\n"
" -- D\n"
" =RA noremote\n"
" --\n"
" viewonly\n"
" shared\n"
" forever\n"
" =D viewonly\n"
" =D shared\n"
" =D forever\n"
" timeout:\n"
" --\n"
" input:\n"
" --\n"
" =SA alwaysshared\n"
" =SA nevershared\n"
" =SA dontdisconnect\n"
" =S alwaysshared\n"
" =S nevershared\n"
" =S dontdisconnect\n"
" --\n"
" viewpasswd:\n"
" =F passwdfile:\n"
......@@ -218,22 +217,22 @@
" unsafe\n"
"\n"
"Tuning\n"
" =-C:0,1,2,3,4 pointer_mode:\n"
" =D-C:0,1,2,3,4 pointer_mode:\n"
" input_skip:\n"
" nodragging\n"
" =D nodragging\n"
" --\n"
" =D noshm\n"
" noshm\n"
" flipbyteorder\n"
" onetile\n"
" --\n"
" alphacut:\n"
" alphafrac:\n"
" alpharemove\n"
" --\n"
" -- D\n"
" speeds:\n"
" wait:\n"
" =D wait:\n"
" defer:\n"
" nap\n"
" =D nap\n"
" screen_blank:\n"
" --\n"
" fs:\n"
......@@ -365,6 +364,12 @@
"Set the -xrandr mode value.\n"
"\"\n"
"\n"
" set helptext(simple-gui) \"\n"
"Toggle between menu items corresponding the most basic ones\n"
"and all possible settings. I.e. toggle between a simple gui\n"
"and one for power users.\n"
"\"\n"
"\n"
" set helptext(all) $helpall\n"
"\n"
" set helptext(gui) \"\n"
......@@ -372,7 +377,7 @@
"provides an interface to each of the many x11vnc command line options and\n"
"remote control commands. See \\\"Help -> all\\\" for much info about x11vnc.\n"
"\n"
"Most menu items have a (?) button one can click on to get more information\n"
"All menu items have a (?) button one can click on to get more information\n"
"about the option or command.\n"
"\n"
"There are two states tkx11vnc can be in:\n"
......@@ -472,6 +477,57 @@
"specified for x11vnc startup if desired.\n"
"\n"
"\"\n"
"\n"
"global beginner_mode\n"
"if {$beginner_mode} {\n"
" set helptext(gui) \"\n"
"tkx11vnc is a simple frontend to x11vnc. It is currently running in\n"
"\\\"ez\\\" or \\\"simple\\\" mode. For many more options run it in normal\n"
"mode buy toggling \\\"Misc -> simple_gui\\\".\n"
"\n"
"All menu items have a (?) button one can click on to get more information\n"
"about the option or command.\n"
"\n"
"GUI components: \n"
"--- ----------\n"
"\n"
"1) At the top of the gui is a info text label where information will\n"
"be posted, e.g. when traversing menu items text indicating how to get\n"
"help on the item and its current value will be displayed.\n"
"\n"
"2) Below the info label is the area where the menu buttons, Actions,\n"
"Clients, etc., are presented. If a menu item has a checkbox,\n"
"it corresponds to a boolean on/off variable. Otherwise it is\n"
"either a string variable, or an action not associated with a\n"
"variable (for the most part).\n"
"\n"
"3) Below the menu button area is a text label indicating the current x11vnc\n"
"X display being polled and the corresponding VNC display name. Both\n"
"will be \\\"(*none*)\\\" when there is no connection established.\n"
"\n"
"4) Below the x11 and vnc displays text label is a text area there scrolling\n"
"information about actions being taken and commands being run is displayed.\n"
"To scroll click in the area and use PageUp/PageDown or the arrow keys.\n"
"\n"
"5) At the bottom is an entry area. When one selects a menu item that\n"
"requires supplying a string value, the label will be set to the\n"
"parameter name and one types in the new value. Then one presses the\n"
"\\\"OK\\\" button or presses \\\"Enter\\\" to set the value. Or you can press\n"
"\\\"Skip\\\" or \\\"Escape\\\" to avoid changing the variable. Some variables\n"
"are boolean toggles (for example, \\\"Permissions -> viewonly\\\") or Radio\n"
"button selections. Selecting these menu items will not activate the\n"
"entry area but rather toggle the variable directly.\n"
"\n"
"\n"
"Cascades Bug: There is a bug not yet worked around for the cascade menus\n"
"where the (?) help button gets in the way. To get the mouse over to\n"
"the cascade menu click and release mouse to activate the cascade, then\n"
"you can click on its items. Dragging with a mouse button held down will\n"
"not work (sorry!).\n"
"\n"
"\"\n"
"}\n"
"\n"
"}\n"
"\n"
"proc center_win {w} {\n"
......@@ -561,6 +617,10 @@
"\n"
" if {[opt_match G $item]} {\n"
" return 1\n"
" } elseif {[opt_match R $item]} {\n"
" return 1\n"
" } elseif {[opt_match S $item]} {\n"
" return 0\n"
" } elseif {[is_action $item]} {\n"
" if {[opt_match R $item]} {\n"
" return 1\n"
......@@ -575,10 +635,27 @@
"}\n"
"\n"
"proc active_when_starting {item} {\n"
" global helpremote helptext\n"
" global helpremote helptext beginner_mode\n"
"\n"
" if {$beginner_mode} {\n"
" if {[opt_match G $item]} {\n"
" return 1\n"
" }\n"
" if {$item == \"display\"} {\n"
" return 1\n"
" }\n"
" if {$item == \"debug_gui\"} {\n"
" return 1\n"
" }\n"
" return 0\n"
" }\n"
"\n"
" if {[opt_match G $item]} {\n"
" return 1\n"
" } elseif {[opt_match S $item]} {\n"
" return 1\n"
" } elseif {[opt_match R $item]} {\n"
" return 0\n"
" } elseif {[is_action $item]} {\n"
" if {[opt_match S $item]} {\n"
" return 1\n"
......@@ -1126,8 +1203,10 @@
" global vl_bk vl_bm vl_bb vr_bk vr_bm vr_bb \n"
"\n"
" append_text \"\\nUse these checkboxes to set the input permissions, \"\n"
" append_text \"or type in the \\\"KMB...\\\"\\n-input string manually. \"\n"
" append_text \"Then press \\\"OK\\\" or \\\"Skip\\\".\\n\\n\"\n"
" append_text \"or type in the \\\"KMB...\\\"\\n\"\n"
" append_text \"-input string manually. Then press \\\"OK\\\" or \\\"Skip\\\".\\n\"\n"
" append_text \"(note: an empty setting means use the default behavior, \"\n"
" append_text \"see viewonly)\\n\\n\"\n"
" set w \"$text_area.wk_f\"\n"
" catch {destroy $w}\n"
" frame $w -bd 1 -relief ridge -cursor {top_left_arrow}\n"
......@@ -1142,7 +1221,7 @@
" -pady 1 -command set_kmb_str -text \"Mouse Motion\" \n"
" checkbutton $fl.bb -font $ffont -anchor w -variable vl_bb \\\n"
" -pady 1 -command set_kmb_str -text \"Button Clicks\"\n"
" label $fr.l -pady 1 -font $ffont -text \"View-only clients:\"\n"
" label $fr.l -pady 1 -font $ffont -text \"View-Only clients:\"\n"
" checkbutton $fr.bk -font $ffont -anchor w -variable vr_bk \\\n"
" -pady 1 -command set_kmb_str -text \"Keystrokes\" \n"
" checkbutton $fr.bm -font $ffont -anchor w -variable vr_bm \\\n"
......@@ -1629,7 +1708,7 @@
" set xterm_cmd \"xterm -sb -fn $ffont -geometry 80x45 -title x11vnc-logfile -e\"\n"
" set cmd [split $xterm_cmd]\n"
" lappend cmd \"tail\"\n"
" lappend cmd \"+1f\"\n"
" lappend cmd \"-3000f\"\n"
" lappend cmd $logfile\n"
" lappend cmd \"&\"\n"
" catch {[eval exec $cmd]}\n"
......@@ -1671,14 +1750,18 @@
"\n"
"# Menu item is an action:\n"
"proc do_action {item} {\n"
" global menu_var connected_to_x11vnc\n"
" global menu_var connected_to_x11vnc beginner_mode\n"
"\n"
" if {[in_debug_mode]} {\n"
" append_text \"action: \\\"$item\\\"\\n\"\n"
" }\n"
"\n"
" if {$item == \"ping\"} {\n"
" if {$beginner_mode} {\n"
" try_connect_and_query_all\n"
" } else {\n"
" try_connect\n"
" }\n"
" return\n"
" } elseif {$item == \"start\"} {\n"
" start_x11vnc\n"
......@@ -1982,7 +2065,7 @@
" set sm 0\n"
" set sb 0\n"
" if {[regexp -nocase {K} $input]} {\n"
" append_text \"Keystroke\"\n"
" append_text \"Keystrokes\"\n"
" set sk 1\n"
" }\n"
" if {[regexp -nocase {M} $input]} {\n"
......@@ -1996,7 +2079,7 @@
" if {$sk || $sm} {\n"
" append_text \", \"\n"
" }\n"
" append_text \"Button-Click\"\n"
" append_text \"Button-Clicks\"\n"
" set sb 1\n"
" }\n"
" if {! $sk && ! $sm && ! $sb} {\n"
......@@ -2026,7 +2109,7 @@
" } elseif {[regexp -nocase {(disconnect|close)} $val]} {\n"
" disconnect_dialog $client\n"
" } else {\n"
" regsub -all -nocase {[^KMB]} $val \"\" \n"
" regsub -all -nocase {[^KMB]} $val \"\" val\n"
" set item_bool(client_input) 0\n"
" push_new_value \"client_input\" \"client_input\" \"$cid:$val\" 0\n"
" }\n"
......@@ -2125,6 +2208,10 @@
" set case $item_case($item)\n"
" set menu $menu_m($case)\n"
" set entry $item_entry($item)\n"
" if {$entry < 0} {\n"
" # skip case under beginner_mode \n"
" continue\n"
" }\n"
" set type [$menu type $entry]\n"
" if {$type == \"separator\" || $type == \"tearoff\"} {\n"
" continue\n"
......@@ -2132,102 +2219,52 @@
" if {$connected_to_x11vnc} {\n"
" if {[active_when_connected $item]} {\n"
" $menu entryconfigure $entry -state normal\n"
"#puts \"n-1 $case / $item / $entry\"\n"
" } else {\n"
" $menu entryconfigure $entry -state disabled\n"
"#puts \"I-1 $case / $item / $entry\"\n"
" }\n"
" } else {\n"
" if {[active_when_starting $item]} {\n"
" $menu entryconfigure $entry -state normal\n"
"#puts \"n-2 $case / $item / $entry\"\n"
" } else {\n"
" $menu entryconfigure $entry -state disabled\n"
"#puts \"I-2 $case / $item / $entry\"\n"
" }\n"
" }\n"
" }\n"
"}\n"
"\n"
"proc make_widgets {} {\n"
" global template \n"
" global menu_b menu_m\n"
" global item_opts item_bool item_case item_entry menu_var unset_str\n"
" global item_cascade\n"
" global info_label info_str x11_display vnc_display\n"
" global text_area\n"
" global entry_box entry_str entry_set entry_label entry_ok entry_browse\n"
" global entry_help entry_skip\n"
" global bfont ffont\n"
" global helptext helpremote helplabel\n"
"\n"
" set label_width 80\n"
"\n"
" set info_label .info\n"
" label $info_label -textvariable info_str -bd 2 -relief groove \\\n"
" -anchor w -width $label_width -font $ffont\n"
" pack $info_label -side top -fill x -expand 0\n"
"\n"
" # Extract the Rows:\n"
" set row 0;\n"
" set colmax 0;\n"
" foreach line [split $template \"\\n\"] {\n"
" if {[regexp {^Row: (.*)} $line rest]} {\n"
" set col 0\n"
" foreach case [split $rest] {\n"
" if {$case == \"\" || $case == \"Row:\"} {\n"
" continue\n"
" }\n"
" set menu_row($case) $row\n"
" set menu_col($case) $col\n"
" set menu_count($case) 0\n"
"proc toggle_simple_gui {} {\n"
" global beginner_mode simple_gui_created\n"
" global connected_to_x11vnc\n"
"\n"
" lappend cases($col) $case;\n"
" set len [string length $case]\n"
" if {[info exists max_len($col)]} {\n"
" if {$len > $max_len($col)} {\n"
" set max_len($col) $len\n"
" }\n"
" if {$beginner_mode} {\n"
" append_text \"\\nSwitching to simple-gui mode.\\n\"\n"
" } else {\n"
" set max_len($col) $len\n"
" }\n"
" incr col\n"
" if {$col > $colmax} {\n"
" set colmax $col\n"
" }\n"
" }\n"
" incr row;\n"
" }\n"
" append_text \"\\nSwitching to power-user gui mode.\\n\"\n"
" }\n"
"\n"
" # Make frames for the rows and make the menu buttons.\n"
" set f \".menuframe\"\n"
" frame $f\n"
" for {set c 0} {$c < $colmax} {incr c} {\n"
" set colf \"$f.menuframe$c\"\n"
" frame $colf\n"
" pack $colf -side left -fill y\n"
" set fbg [$colf cget -background]\n"
" foreach case $cases($c) {\n"
" set menub \"$colf.menu$case\";\n"
" set menu \"$colf.menu$case.menu\";\n"
" set menu_b($case) $menub\n"
" set menu_m($case) $menu\n"
" set ul 0\n"
" foreach char [split $case \"\"] {\n"
" set char [string tolower $char]\n"
" if {![info exists underlined($char)]} {\n"
" set underlined($char) 1\n"
" break\n"
" }\n"
" incr ul\n"
" }\n"
" menubutton $menub -text \"$case\" -underline $ul \\\n"
" -anchor w -menu $menu -background $fbg \\\n"
" -font $bfont\n"
" pack $menub -side top -fill x\n"
" menu $menu -tearoff 0\n"
" }\n"
" set simple_gui_created 1\n"
" make_menu_items\n"
" set_widgets\n"
" set_internal_help\n"
" if {$connected_to_x11vnc} {\n"
" query_all\n"
" }\n"
" pack $f -side top -fill x\n"
" append_text \"\\n\"\n"
"}\n"
"\n"
"proc make_menu_items {} {\n"
" global template \n"
" global menu_b menu_m menu_count\n"
" global item_opts item_bool item_case item_entry menu_var unset_str\n"
" global item_cascade\n"
" global bfont ffont beginner_mode simple_gui_created\n"
" global helptext helpremote helplabel\n"
"\n"
" # Now extract the menu items:\n"
" # Extract the menu items:\n"
" set case \"\";\n"
" foreach line [split $template \"\\n\"] {\n"
" if {[regexp {^Row:} $line]} {\n"
......@@ -2235,8 +2272,19 @@
" }\n"
" if {[regexp {^[A-z]} $line]} {\n"
" set case [string trim $line]\n"
"\n"
" if {$simple_gui_created} {\n"
" set i0 0\n"
" if {$case == \"Misc\"} {\n"
" # kludge for simple_gui\n"
" set i0 1\n"
" }\n"
" catch {$menu_m($case) delete $i0 end}\n"
" }\n"
" set menu_count($case) 0\n"
" continue;\n"
" }\n"
"\n"
" set item [string trim $line]\n"
" regsub -all { *} $item \" \" item\n"
" if {$item == \"\"} {\n"
......@@ -2258,17 +2306,29 @@
" }\n"
" regsub {:$} $item {} item\n"
"\n"
" if {$item == \"-- D\"} {\n"
" set beginner_sep 1\n"
" set item \"--\"\n"
" } else {\n"
" set beginner_sep 0\n"
" }\n"
"\n"
" set item_opts($item) $opts\n"
" set item_case($item) $case\n"
" set item_bool($item) $bool\n"
" set item_cascade($item) \"\"\n"
" set item_entry($item) $menu_count($case)\n"
"\n"
" if {0} { puts \"ITEM: $item - $opts - $case - $bool - $menu_count($case)\" }\n"
"\n"
" set mvar 0 \n"
" set m $menu_m($case)\n"
"\n"
" if {$beginner_mode && ! $beginner_sep && ![opt_match D $item]} {\n"
" set item_entry($item) \"-1\"\n"
" continue;\n"
" }\n"
"\n"
" if {0} { puts \"ITEM: $item\\t- $opts\\t- $case\\t- $bool\\t- $menu_count($case)\" }\n"
"\n"
" # Create the menu items, its variables, etc., etc.\n"
"\n"
" if {$item == \"--\"} {\n"
......@@ -2288,7 +2348,8 @@
"\n"
" } elseif {$item == \"current\"} {\n"
" # Current clients cascade\n"
" set subm $m.cascade$menu_count($case)\n"
" set subm $m.current_cascade\n"
" catch {destroy $subm}\n"
" set item_cascade($item) $subm\n"
" update_clients_menu \"\"\n"
" $m add cascade -label \"$item\" \\\n"
......@@ -2306,7 +2367,8 @@
" # String\n"
" if {[regexp -- {-C:(.*)} $item_opts($item) m0 m1]} {\n"
" # Radiobutton select\n"
" set subm $m.cascade$menu_count($case)\n"
" set subm $m.radio_cascade$menu_count($case)\n"
" catch {destroy $subm}\n"
" menu $subm -tearoff 0 -font $ffont\n"
" foreach val [split $m1 \",\"] {\n"
" $subm add radiobutton -label \"$val\" \\\n"
......@@ -2327,6 +2389,13 @@
" }\n"
" set mvar 1\n"
"\n"
" } elseif {$item == \"simple-gui\"} {\n"
" if {! $simple_gui_created} {\n"
" $m add checkbutton -label \"$item\" \\\n"
" -command \"toggle_simple_gui\" \\\n"
" -font $ffont \\\n"
" -variable beginner_mode\n"
" }\n"
" } else {\n"
" # Boolean\n"
" $m add checkbutton -label \"$item\" \\\n"
......@@ -2337,12 +2406,13 @@
" }\n"
"\n"
" incr menu_count($case)\n"
"\n"
" if {$mvar} {\n"
" set menu_var($item) $unset_str\n"
" }\n"
" }\n"
"\n"
" # Now make the litte \"(?)\" help buttons\n"
" # Now make the little \"(?)\" help buttons\n"
" foreach case [array names menu_m] {\n"
" if {$case == \"Help\"} {\n"
" continue;\n"
......@@ -2382,6 +2452,90 @@
" }\n"
" }\n"
" }\n"
"}\n"
"\n"
"proc make_widgets {} {\n"
" global template \n"
" global menu_b menu_m menu_count\n"
" global item_opts item_bool item_case item_entry menu_var unset_str\n"
" global item_cascade\n"
" global info_label info_str x11_display vnc_display\n"
" global text_area\n"
" global entry_box entry_str entry_set entry_label entry_ok entry_browse\n"
" global entry_help entry_skip\n"
" global bfont ffont beginner_mode\n"
" global helptext helpremote helplabel\n"
"\n"
" # Make the top label\n"
" set label_width 80\n"
" set info_label .info\n"
" label $info_label -textvariable info_str -bd 2 -relief groove \\\n"
" -anchor w -width $label_width -font $ffont\n"
" pack $info_label -side top -fill x -expand 0\n"
"\n"
" # Extract the Rows:\n"
" set row 0;\n"
" set colmax 0;\n"
" foreach line [split $template \"\\n\"] {\n"
" if {[regexp {^Row: (.*)} $line rest]} {\n"
" set col 0\n"
" foreach case [split $rest] {\n"
" if {$case == \"\" || $case == \"Row:\"} {\n"
" continue\n"
" }\n"
" set menu_row($case) $row\n"
" set menu_col($case) $col\n"
"\n"
" lappend cases($col) $case;\n"
" set len [string length $case]\n"
" if {[info exists max_len($col)]} {\n"
" if {$len > $max_len($col)} {\n"
" set max_len($col) $len\n"
" }\n"
" } else {\n"
" set max_len($col) $len\n"
" }\n"
" incr col\n"
" if {$col > $colmax} {\n"
" set colmax $col\n"
" }\n"
" }\n"
" incr row;\n"
" }\n"
" }\n"
"\n"
" # Make frames for the rows and make the menu buttons.\n"
" set f \".menuframe\"\n"
" frame $f\n"
" for {set c 0} {$c < $colmax} {incr c} {\n"
" set colf \"$f.menuframe$c\"\n"
" frame $colf\n"
" pack $colf -side left -fill y\n"
" set fbg [$colf cget -background]\n"
" foreach case $cases($c) {\n"
" set menub \"$colf.menu$case\";\n"
" set menu \"$colf.menu$case.menu\";\n"
" set menu_b($case) $menub\n"
" set menu_m($case) $menu\n"
" set ul 0\n"
" foreach char [split $case \"\"] {\n"
" set char [string tolower $char]\n"
" if {![info exists underlined($char)]} {\n"
" set underlined($char) 1\n"
" break\n"
" }\n"
" incr ul\n"
" }\n"
" menubutton $menub -text \"$case\" -underline $ul \\\n"
" -anchor w -menu $menu -background $fbg \\\n"
" -font $bfont\n"
" pack $menub -side top -fill x\n"
" menu $menu -tearoff 0\n"
" }\n"
" }\n"
" pack $f -side top -fill x\n"
"\n"
" make_menu_items\n"
"\n"
" # Make the x11 and vnc display label bar:\n"
" set df .displayframe\n"
......@@ -2558,9 +2712,9 @@
"\n"
"proc double_check_noremote {} {\n"
" set msg \"\\n\\n\"\n"
" append msg \"WARNING: setting \\\"noremote\\\" will disable ALL remote control commands\\n\"\n"
" append msg \"WARNING: (i.e. this gui will be locked out) Do you really want to do this?\\n\"\n"
" append msg \"WARNING: If so, press \\\"OK\\\", otherwise press \\\"Skip\\\"\\n\"\n"
" append msg \"*** WARNING: setting \\\"noremote\\\" will disable ALL remote control commands (i.e.\\n\"\n"
" append msg \"*** WARNING: *this* gui will be locked out). Do you really want to do this?\\n\"\n"
" append msg \"*** WARNING: If so, press \\\"OK\\\", otherwise press \\\"Skip\\\"\\n\"\n"
" append msg \"\\n\"\n"
" bell\n"
" return [warning_dialog $msg \"noremote\"]\n"
......@@ -2835,7 +2989,7 @@
"# main:\n"
"\n"
"global env x11vnc_prog x11vnc_cmdline x11vnc_xdisplay x11vnc_connect;\n"
"global x11vnc_auth_file\n"
"global x11vnc_auth_file beginner_mode simple_gui_created\n"
"global helpall helptext helpremote helplabel hostname;\n"
"global all_settings reply_xdisplay always_update\n"
"global max_text_height max_text_width\n"
......@@ -2926,6 +3080,13 @@
" set x11vnc_auth_file \"\"\n"
"}\n"
"\n"
"set simple_gui_created 0\n"
"if {[info exists env(X11VNC_SIMPLE_GUI)]} {\n"
" set beginner_mode 1\n"
"} else {\n"
" set beginner_mode 0\n"
"}\n"
"\n"
"\n"
"set hostname [exec uname -n]\n"
"#puts [exec env]\n"
......
......@@ -2,7 +2,7 @@
.TH X11VNC "1" "February 2005" "x11vnc " "User Commands"
.SH NAME
x11vnc - allow VNC connections to real X11 displays
version: 0.7.1pre, lastmod: 2005-02-10
version: 0.7.1pre, lastmod: 2005-02-14
.SH SYNOPSIS
.B x11vnc
[OPTION]...
......@@ -274,10 +274,13 @@ Supply a 2nd password for view-only logins. The \fB-passwd\fR
.IP
Specify libvncserver \fB-passwd\fR via the first line of
the file \fIfilename\fR instead of via command line.
If a second non blank line exists in the file it is
taken as a view-only password (i.e. \fB-viewpasswd)\fR Note:
this is a simple plaintext passwd, see also \fB-rfbauth\fR
and \fB-storepasswd\fR below for obfuscated passwords.
If a second non blank line exists in the file it
is taken as a view-only password (i.e. \fB-viewpasswd)\fR
To supply an empty password for either field use the
string "__EMPTY__". Note: \fB-passwdfile\fR is a simple
plaintext passwd, see also \fB-rfbauth\fR and \fB-storepasswd\fR
below for obfuscated passwords. Neither should be
readable by others.
.PP
\fB-storepasswd\fR \fIpass\fR \fIfile\fR
.IP
......@@ -382,44 +385,66 @@ root this option is ignored.
.IP
Why use this option? In general it is not needed
since x11vnc is already connected to the display and
can perform its primary functions. It was added to
make some of the *external* utility commands x11vnc
occasionally runs work properly. In particular under
GNOME and KDE to implement the "\fB-solid\fR \fIcolor\fR" feature
external commands (gconftool-2 and dcop) must be run as
the user owning the desktop session. This option also
affects the userid used to run the processes for the
\fB-accept\fR and \fB-gone\fR options. It also affects the ability
to read files for options such as \fB-connect,\fR \fB-allow,\fR and
\fB-remap.\fR Note that the \fB-connect\fR file is also written to.
can perform its primary functions. The option was
added to make some of the *external* utility commands
x11vnc occasionally runs work properly. In particular
under GNOME and KDE to implement the "\fB-solid\fR \fIcolor\fR"
feature external commands (gconftool-2 and dcop) must be
run as the user owning the desktop session. Since this
option switches userid it also affects the userid used
to run the processes for the \fB-accept\fR and \fB-gone\fR options.
It also affects the ability to read files for options
such as \fB-connect,\fR \fB-allow,\fR and \fB-remap.\fR Note that the
\fB-connect\fR file is also sometimes written to.
.IP
So be careful with this option since in many situations
its use can decrease security.
.IP
The switch to a user will only take place if the display
can still be opened as that user (this is primarily to
try to guess the actual owner of the session). Example:
"\fB-users\fR \fIfred,wilma,betty\fR". Note that a malicious
user "barney" by quickly using "xhost +" when
logging in can get x11vnc to switch to user "fred".
What happens next?
The switch to a user will only take place if the
display can still be successfully opened as that user
(this is primarily to try to guess the actual owner
of the session). Example: "\fB-users\fR \fIfred,wilma,betty\fR".
Note that a malicious user "barney" by quickly using
"xhost +" when logging in may get x11vnc to switch
to user "fred". What happens next?
.IP
Under display managers it may be a long time before
the switch succeeds (i.e. a user logs in). To make
it switch immediately regardless if the display can
be reopened or not prefix the username with the +
it switch immediately regardless if the display
can be reopened prefix the username with the +
character. E.g. "\fB-users\fR \fI+bob\fR" or "\fB-users\fR \fI+nobody\fR".
The latter (i.e. switching immediately to user
"nobody") is probably the only use of this option
that increases security. To switch to a user *before*
connections to the display are made or any files opened
use the "=" character: "\fB-users\fR \fI=username\fR".
.IP
The special user "guess" means to examine the utmpx
database looking for a user attached to the display
number and try him/her. To limit the list of guesses,
use: "\fB-users\fR \fIguess=bob,betty\fR". Be especially careful
using this mode.
that increases security.
.IP
To immediately switch to a user *before* connections to
the display are made or any files opened use the "="
character: "\fB-users\fR \fI=bob\fR". That user needs to be able
to open the display of course.
.IP
The special user "guess=" means to examine the utmpx
database (see
.IR who (1)
) looking for a user attached to
the display number (from DISPLAY or \fB-display\fR option)
and try him/her. To limit the list of guesses, use:
"\fB-users\fR \fIguess=bob,betty\fR".
.IP
Even more sinister is the special user "lurk=" that
means to try to guess the DISPLAY from the utmpx login
database as well. So it "lurks" waiting for anyone
to log into an X session and then connects to it.
Specify a list of users after the = to limit which
users will be tried. If the first user in the list
is something like ":0" or ":0-2" that indicates a
range of DISPLAY numbers that will be tried (regardless
of whether they are in the utmpx database) for all
users that are logged in. Examples: "\fB-users\fR \fIlurk=\fR"
and "\fB-users\fR \fIlurk=:0-1,bob,mary\fR"
.IP
Be especially careful using the "guess=" and "lurk="
modes. They are not recommended for use on machines
with untrustworthy local users.
.PP
\fB-noshm\fR
.IP
......@@ -448,20 +473,20 @@ The [color] is optional: the default color is "cyan4".
For a different one specify the X color (rgb.txt name,
e.g. "darkblue" or numerical "#RRGGBB").
.IP
Currently this option only works on GNOME, KDE, and
classic X (i.e. with the background image on the root
window). The "gconftool-2" and "dcop" external
Currently this option only works on GNOME, KDE, CDE,
and classic X (i.e. with the background image on the
root window). The "gconftool-2" and "dcop" external
commands are run for GNOME and KDE respectively.
Other desktops won't work, e.g. XFCE (send us the
corresponding commands if you find them). If x11vnc
is running as root (
corresponding commands if you find them). If x11vnc is
running as root (
.IR inetd (1)
or
.IR gdm (1)
), the \fB-users\fR
option may be needed for GNOME and KDE. If x11vnc
guesses your desktop incorrectly, you can force it by
prefixing color with "gnome:", "kde:", or "root:".
), the \fB-users\fR option
may be needed for GNOME and KDE. If x11vnc guesses
your desktop incorrectly, you can force it by prefixing
color with "gnome:", "kde:", "cde:" or "root:".
.PP
\fB-blackout\fR \fIstring\fR
.IP
......@@ -1008,9 +1033,11 @@ to start up both the gui and x11vnc with the gui showing
up on the X display in the environment variable DISPLAY.
.IP
"gui-opts" can be a comma separated list of items.
Currently there are only two types of items: 1) a gui
mode and 2) the X display the gui should display on.
The gui mode can be "start", "conn", or "wait"
Currently there are these types of items: 1) a gui mode,
a 2) gui "simplicity", and 3) the X display the gui
should display on.
.IP
1) The gui mode can be "start", "conn", or "wait"
"start" is the default mode above and is not required.
"conn" means do not automatically start up x11vnc,
but instead just try to connect to an existing x11vnc
......@@ -1018,15 +1045,22 @@ process. "wait" means just start the gui and nothing
else (you will later instruct the gui to start x11vnc
or connect to an existing one.)
.IP
Note the possible confusion regarding the potentially
2) The gui simplicity is off by default (a power-user
gui with all options is presented) To start with
something less daunting supply the string "simple"
("ez" is an alias for this). Once the gui is
started you can toggle between the two with "Misc ->
simple_gui".
.IP
3) Note the possible confusion regarding the potentially
two different X displays: x11vnc polls one, but you
may want the gui to appear on another. For example, if
you ssh in and x11vnc is not running yet you may want
the gui to come back to you via your ssh redirected X
display (e.g. localhost:10).
.IP
Examples: "x11vnc \fB-gui",\fR "x11vnc \fB-gui\fR localhost:10",
"x11vnc \fB-gui\fR :10", "x11vnc \fB-gui\fR conn,host:10",
Examples: "x11vnc \fB-gui",\fR "x11vnc \fB-gui\fR ez"
"x11vnc \fB-gui\fR localhost:10", "x11vnc \fB-gui\fR conn,host:0"
.IP
If you do not specify a gui X display in "gui-opts"
then the DISPLAY environment variable and \fB-display\fR
......
......@@ -290,7 +290,7 @@ static int xdamage_base_event_type;
#endif
/* date +'lastmod: %Y-%m-%d' */
char lastmod[] = "0.7.1pre lastmod: 2005-02-10";
char lastmod[] = "0.7.1pre lastmod: 2005-02-14";
/* X display info */
......@@ -977,14 +977,18 @@ char *get_shell(void) {
}
}
int switch_user(char *);
/* -- user.c -- */
int switch_user(char *, int);
int switch_user_env(uid_t, char*, char *, int);
void try_to_switch_users(void);
char *guess_desktop(void);
void switch_user_dummy(void) {
/* tasks for after we switch */
void switch_user_task_dummy(void) {
; /* dummy does nothing */
}
void switch_user_solid_bg(void) {
void switch_user_task_solid_bg(void) {
/* we have switched users, some things to do. */
if (use_solid_bg && client_count) {
solid_bg(0);
......@@ -1017,7 +1021,7 @@ void check_switched_user (void) {
}
if (! did_dummy) {
switch_user_dummy();
switch_user_task_dummy();
did_dummy = 1;
}
if (! did_solid) {
......@@ -1034,7 +1038,7 @@ void check_switched_user (void) {
doit = 1;
}
if (doit) {
switch_user_solid_bg();
switch_user_task_solid_bg();
did_solid = 1;
}
}
......@@ -1044,169 +1048,462 @@ void check_switched_user (void) {
}
}
int guess_user_and_switch(char *str) {
/* utilities for switching users */
char *get_login_list(int with_display) {
char *out;
#if LIBVNCSERVER_HAVE_UTMPX_H
char *q, *dstr, *d = DisplayString(dpy);
char *allowed = NULL;
int i, ret = 0, max = 300;
int i, cnt, max = 200, ut_namesize = 32;
int dpymax = 1000, sawdpy[1000];
struct utmpx *utx;
if (strstr(str, "guess=") == str) {
char *allowed = strchr(str, '=');
allowed++;
}
/* size based on "username:999," * max */
out = (char *) malloc(max * (ut_namesize+1+3+1) + 1);
out[0] = '\0';
/* pick out ":N" */
dstr = strchr(d, ':');
if (! dstr) {
return 0;
}
q = strchr(dstr, '.');
if (q) {
*q = '\0';
for (i=0; i<dpymax; i++) {
sawdpy[i] = 0;
}
/* look over the utmpx entries looking for this display */
setutxent();
for (i=0; i<max; i++) {
char *str;
struct utmpx *utx = getutxent();
cnt = 0;
while (1) {
char *user, *line, *host, *id;
char tmp[10];
int d = -1;
utx = getutxent();
if (! utx) {
break;
}
str = lblanks(utx->ut_user);
if (*str == '\0') {
continue; /* blank user */
if (utx->ut_type != USER_PROCESS) {
continue;
}
if (allowed) {
char *p, *t = strdup(allowed);
int ok = 0;
p = strtok(t, ",");
while (p) {
if (!strcmp(p, utx->ut_user)) {
ok = 1;
user = lblanks(utx->ut_user);
if (*user == '\0') {
continue;
}
p = strtok(NULL, ",");
if (strchr(user, ',')) {
continue; /* unlikely, but comma is our sep. */
}
free(t);
if (! ok) {
line = lblanks(utx->ut_line);
host = lblanks(utx->ut_host);
id = lblanks(utx->ut_id);
if (with_display) {
if (0 && line[0] != ':' && strcmp(line, "dtlocal")) {
/* XXX useful? */
continue;
}
if (line[0] == ':') {
if (sscanf(line, ":%d", &d) != 1) {
d = -1;
}
}
if (d < 0 && host[0] == ':') {
if (sscanf(host, ":%d", &d) != 1) {
d = -1;
}
}
if (d < 0 && id[0] == ':') {
if (sscanf(id, ":%d", &d) != 1) {
d = -1;
}
if (!strcmp(utx->ut_user, "guess")) {
continue; /* never... */
}
/* try the line for leading :N */
str = lblanks(utx->ut_line);
if (strstr(str, dstr) == str) {
int n = strlen(dstr);
if (isdigit(*(str+n))) {
continue; /* :1 vs. :10 */
} else if (switch_user(utx->ut_user)) {
rfbLog("switched to guessed user: %s\n",
utx->ut_user);
ret = 1;
break;
} else {
if (d < 0 || d >= dpymax || sawdpy[d]) {
continue;
}
}
sawdpy[d] = 1;
sprintf(tmp, ":%d", d);
} else {
/* try to eliminate repeats */
int repeat = 0;
char *q;
/* try the host for leading :N */
str = lblanks(utx->ut_host);
if (strstr(str, dstr) == str) {
int n = strlen(dstr);
if (isdigit(*(str+n))) {
continue; /* :1 vs. :10 */
} else if (switch_user(utx->ut_user)) {
rfbLog("switched to guessed user: %s\n",
utx->ut_user);
ret = 1;
q = out;
while ((q = strstr(q, user)) != NULL) {
char *p = q + strlen(user) + strlen(":DPY");
if (q == out || *(q-1) == ',') {
/* bounded on left. */
if (*p == ',' || *p == '\0') {
/* bounded on right. */
repeat = 1;
break;
} else {
}
}
q = p;
}
if (repeat) {
continue;
}
sprintf(tmp, ":DPY");
}
if (*out) {
strcat(out, ",");
}
endutxent();
strcat(out, user);
strcat(out, tmp);
return ret;
cnt++;
if (cnt >= max) {
break;
}
}
endutxent();
#else
return 0;
out = strdup("");
#endif
return out;
}
int switch_user(char *user) {
int force = 0, numerical = 1;
uid_t uid = 0;
char *q, *name, *home;
char **user_list(char *user_str) {
int n, i;
char *p, **list;
if (*user == '+') {
force = 1;
user++;
p = user_str;
n = 1;
while (*p++) {
if (*p == ',') {
n++;
}
}
list = (char **) malloc((n+1)*(sizeof(char *)));
if (!strcmp(user, "guess") || strstr(user, "guess=") == user) {
return guess_user_and_switch(user);
p = strtok(user_str, ",");
i = 0;
while (p) {
list[i++] = p;
p = strtok(NULL, ",");
}
list[i] = NULL;
return list;
}
void user2uid(char *user, uid_t *uid, char **name, char **home) {
int numerical = 1;
char *q;
*uid = (uid_t) -1;
*name = NULL;
*home = NULL;
q = user;
while (*q) {
if (! isdigit(*q)) {
if (! isdigit(*q++)) {
numerical = 0;
break;
}
q++;
}
#if LIBVNCSERVER_HAVE_PWD_H
if (numerical) {
int u = atoi(user);
struct passwd *pw;
if (u > 0) {
uid = (uid_t) u;
if (u < 0) {
return;
}
*uid = (uid_t) u;
}
#if LIBVNCSERVER_HAVE_PWD_H
if (1) {
struct passwd *pw;
if (numerical) {
pw = getpwuid(*uid);
} else {
return 0;
pw = getpwnam(user);
}
pw = getpwuid(uid);
if (pw) {
name = pw->pw_name;
home = pw->pw_dir;
} else {
return 0;
*uid = pw->pw_uid;
*name = pw->pw_name; /* n.b. use immediately */
*home = pw->pw_dir;
}
}
#endif
}
int try_user_and_display(uid_t, char*);
int lurk(char **users) {
uid_t uid;
int success = 0, dmin = -1, dmax = -1;
char *p, *logins, **u;
if ((u = users) != NULL && *u != NULL && *(*u) == ':') {
int len;
char *tmp;
/* extract min and max display numbers */
tmp = *u;
if (strchr(tmp, '-')) {
if (sscanf(tmp, ":%d-%d", &dmin, &dmax) != 2) {
dmin = -1;
dmax = -1;
}
}
if (dmin < 0) {
if (sscanf(tmp, ":%d", &dmin) != 1) {
dmin = -1;
dmax = -1;
} else {
struct passwd *pw = getpwnam(user);
if (pw) {
uid = pw->pw_uid;
name = pw->pw_name;
home = pw->pw_dir;
dmax = dmin;
}
}
if ((dmin < 0 || dmax < 0) || dmin > dmax || dmax > 10000) {
dmin = -1;
dmax = -1;
}
/* get user logins regardless of having a display: */
logins = get_login_list(0);
/*
* now we append the list in users (might as well try
* them) this will probably allow weird ways of starting
* xservers to work.
*/
len = strlen(logins);
u++;
while (*u != NULL) {
len += strlen(*u) + strlen(":DPY,");
u++;
}
tmp = (char *) malloc(len+1);
strcpy(tmp, logins);
/* now concatenate them: */
u = users+1;
while (*u != NULL) {
char *q, chk[100];
snprintf(chk, 100, "%s:DPY", *u);
q = strstr(tmp, chk);
if (q) {
char *p = q + strlen(chk);
if (q == tmp || *(q-1) == ',') {
/* bounded on left. */
if (*p == ',' || *p == '\0') {
/* bounded on right. */
u++;
continue;
}
}
}
if (*tmp) {
strcat(tmp, ",");
}
strcat(tmp, *u);
strcat(tmp, ":DPY");
u++;
}
free(logins);
logins = tmp;
} else {
return 0;
logins = get_login_list(1);
}
p = strtok(logins, ",");
while (p) {
char *user, *name, *home, dpystr[10];
char *q, *t;
int ok = 1, dn;
t = strdup(p); /* bob:0 */
q = strchr(t, ':');
if (! q) {
free(t);
break;
}
#else
return 0;
#endif
*q = '\0';
user = t;
snprintf(dpystr, 10, ":%s", q+1);
if (users) {
u = users;
ok = 0;
while (*u != NULL) {
if (*(*u) == ':') {
u++;
continue;
}
if (!strcmp(user, *u++)) {
ok = 1;
break;
}
}
}
user2uid(user, &uid, &name, &home);
free(t);
if (! uid) {
ok = 0;
}
if (! ok) {
p = strtok(NULL, ",");
continue;
}
for (dn = dmin; dn <= dmax; dn++) {
if (dn >= 0) {
sprintf(dpystr, ":%d", dn);
}
if (try_user_and_display(uid, dpystr)) {
if (switch_user_env(uid, name, home, 0)) {
rfbLog("lurk: now user: %s @ %s\n",
name, dpystr);
started_as_root = 2;
success = 1;
}
set_env("DISPLAY", dpystr);
break;
}
}
if (success) {
break;
}
p = strtok(NULL, ",");
}
free(logins);
return success;
}
void lurk_loop(char *str) {
char *tstr = NULL, **users = NULL;
if (strstr(str, "lurk=") != str) {
exit(1);
}
rfbLog("lurking for logins using: '%s'\n", str);
if (strlen(str) > strlen("lurk=")) {
char *q = strchr(str, '=');
tstr = strdup(q+1);
users = user_list(tstr);
}
while (1) {
if (lurk(users)) {
break;
}
sleep(3);
}
if (tstr) {
free(tstr);
}
if (users) {
free(users);
}
}
int guess_user_and_switch(char *str, int fb_mode) {
char *dstr, *d = DisplayString(dpy);
char *p, *tstr = NULL, *allowed = NULL, *logins, **users = NULL;
int dpy1, ret = 0;
/* pick out ":N" */
dstr = strchr(d, ':');
if (! dstr) {
return 0;
}
if (sscanf(dstr, ":%d", &dpy1) != 1) {
return 0;
}
if (dpy1 < 0) {
return 0;
}
if (! force) {
#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SYS_WAIT_H
if (strstr(str, "guess=") == str && strlen(str) > strlen("guess=")) {
allowed = strchr(str, '=');
allowed++;
tstr = strdup(allowed);
users = user_list(tstr);
}
/* loop over the utmpx entries looking for this display */
logins = get_login_list(1);
p = strtok(logins, ",");
while (p) {
char *user, *q, *t;
int dpy2, ok = 1;
t = strdup(p);
q = strchr(t, ':');
if (! q) {
free(t);
break;
}
*q = '\0';
user = t;
dpy2 = atoi(q+1);
if (users) {
char **u = users;
ok = 0;
while (*u != NULL) {
if (!strcmp(user, *u++)) {
ok = 1;
break;
}
}
}
if (dpy1 != dpy2) {
ok = 0;
}
if (! ok) {
free(t);
p = strtok(NULL, ",");
continue;
}
if (switch_user(user, fb_mode)) {
rfbLog("switched to guessed user: %s\n", user);
free(t);
ret = 1;
break;
}
p = strtok(NULL, ",");
}
if (tstr) {
free(tstr);
}
if (users) {
free(users);
}
if (logins) {
free(logins);
}
return ret;
}
int try_user_and_display(uid_t uid, char *dpystr) {
/* NO strtoks */
#if LIBVNCSERVER_HAVE_FORK && LIBVNCSERVER_HAVE_SYS_WAIT_H && LIBVNCSERVER_HAVE_PWD_H
pid_t pid, pidw;
char *home, *name;
int st;
struct passwd *pw;
pw = getpwuid(uid);
if (pw) {
name = pw->pw_name;
home = pw->pw_dir;
} else {
return 0;
}
/*
* We fork here and try to open the display again as the
* new user. Unreadable XAUTHORITY could be a problem...
* This is not really needed since we have DISPLAY open
* but: 1) is a good indicator this user owns the session
* and 2) some activities do spawn new X apps, e.g.
* xmessage(1), etc.
* This is not really needed since we have DISPLAY open but:
* 1) is a good indicator this user owns the session and 2)
* some activities do spawn new X apps, e.g. xmessage(1), etc.
*/
if ((pid = fork()) > 0) {
;
......@@ -1215,23 +1512,17 @@ int switch_user(char *user) {
rfbLogPerror("fork");
return 0;
} else {
/* child */
Display *dpy2 = 0;
char *xauth = getenv("XAUTHORITY");
#if LIBVNCSERVER_HAVE_SETUID
if (setuid(uid) != 0) {
exit(1); /* fail */
}
#else
int rc;
rc = switch_user_env(uid, name, home, 0);
if (! rc) {
exit(1);
#endif
if (xauth && access(xauth, R_OK) != 0) {
*(xauth-2) = '_'; /* yow */
}
set_env("USER", name);
set_env("LOGNAME", name);
set_env("HOME", home);
fclose(stderr);
dpy2 = XOpenDisplay(DisplayString(dpy));
dpy2 = XOpenDisplay(dpystr);
if (dpy2) {
XCloseDisplay(dpy2);
exit(0); /* success */
......@@ -1240,52 +1531,91 @@ int switch_user(char *user) {
}
}
/* see what the child says: */
pidw = waitpid(pid, &st, 0);
if (pidw == pid && WIFEXITED(st) && WEXITSTATUS(st) == 0) {
force = 1;
/* see what the child says: */
pidw = waitpid(pid, &st, 0);
if (pidw == pid && WIFEXITED(st) && WEXITSTATUS(st) == 0) {
return 1;
}
#endif /* LIBVNCSERVER_HAVE_FORK ... */
return 0;
}
int switch_user(char *user, int fb_mode) {
/* NO strtoks */
int doit = 0;
uid_t uid = 0;
char *name, *home;
if (*user == '+') {
doit = 1;
user++;
}
if (strstr(user, "guess=") == user) {
return guess_user_and_switch(user, fb_mode);
}
user2uid(user, &uid, &name, &home);
if (uid == -1 || uid == 0) {
return 0;
}
if (! doit && dpy) {
/* see if this display works: */
char *dstr = DisplayString(dpy);
doit = try_user_and_display(uid, dstr);
}
if (doit) {
int rc = switch_user_env(uid, name, home, fb_mode);
if (rc) {
started_as_root = 2;
}
#else
force = 1;
#endif
return rc;
} else {
return 0;
}
}
if (force) {
char *xauth = getenv("XAUTHORITY");
int switch_user_env(uid_t uid, char *name, char *home, int fb_mode) {
/* NO strtoks */
char *xauth;
int reset_fb = 0;
#if !LIBVNCSERVER_HAVE_SETUID
return 0;
#else
/*
* OK tricky here, we need to free the shm... otherwise
* we won't be able to delete it as the other user...
*/
#if !LIBVNCSERVER_HAVE_SETUID
return 0;
#else
if (using_shm) {
if (fb_mode == 1 && using_shm) {
reset_fb = 1;
clean_shm(0);
free_tiles();
}
if (setuid(uid) != 0) {
if (using_shm) {
if (reset_fb) {
/* 2 means we did clean_shm and free_tiles */
do_new_fb(2);
}
return 0;
}
#endif
if (using_shm) {
if (reset_fb) {
do_new_fb(2);
}
xauth = getenv("XAUTHORITY");
if (xauth && access(xauth, R_OK) != 0) {
*(xauth-2) = '_'; /* yow */
}
set_env("USER", name);
set_env("LOGNAME", name);
set_env("HOME", home);
return 1;
} else {
return 0;
}
}
void try_to_switch_users(void) {
......@@ -1309,9 +1639,8 @@ void try_to_switch_users(void) {
users = strdup(users_list);
if (strstr(users, "guess=") == users) {
if (switch_user(users)) {
if (switch_user(users, 1)) {
started_as_root = 2;
rfbLog("try_to_switch_users: now %s\n", p);
}
free(users);
return;
......@@ -1319,7 +1648,7 @@ void try_to_switch_users(void) {
p = strtok(users, ",");
while (p) {
if (switch_user(p)) {
if (switch_user(p, 1)) {
started_as_root = 2;
rfbLog("try_to_switch_users: now %s\n", p);
break;
......@@ -6316,6 +6645,17 @@ void check_xevents(void) {
}
sent_some_sel = 1;
}
if (! have_clients) {
/*
* If we don't have clients we can miss the X server
* going away until a client connects.
*/
static time_t last_X_ping = 0;
if (now > last_X_ping + 5) {
last_X_ping = now;
XGetSelectionOwner(dpy, XA_PRIMARY);
}
}
if (XCheckTypedEvent(dpy, MappingNotify, &xev)) {
XRefreshKeyboardMapping((XMappingEvent *) &xev);
......@@ -11566,7 +11906,7 @@ void solid_root(char *color) {
Colormap cmap;
if (subwin || window != rootwin) {
rfbLog("cannot set subwin to solid color, must be root\n");
rfbLog("cannot set subwin to solid color, must be rootwin\n");
return;
}
......@@ -11625,7 +11965,6 @@ void solid_root(char *color) {
iswa.override_redirect = True;
iswa.backing_store = NotUseful;
iswa.save_under = False;
iswa.background_pixmap = None;
iswa.background_pixmap = ParentRelative;
iwin = XCreateWindow(dpy, window, 0, 0, dpy_x, dpy_y, 0, depth,
......@@ -11660,6 +11999,263 @@ void solid_root(char *color) {
XDestroyWindow(dpy, expose);
}
void solid_cde(char *color) {
int wsmax = 16;
static XImage *image[16];
static Window ws_wins[16];
static int nws = -1;
Window expose;
Pixmap pixmap;
XGCValues gcv;
GC gc;
XSetWindowAttributes swa;
Visual visual;
unsigned long mask, pixel;
XColor cdef;
Colormap cmap;
int n;
if (subwin || window != rootwin) {
rfbLog("cannot set subwin to solid color, must be rootwin\n");
return;
}
/* create the "clear" window just for generating exposures */
swa.override_redirect = True;
swa.backing_store = NotUseful;
swa.save_under = False;
swa.background_pixmap = None;
visual.visualid = CopyFromParent;
mask = (CWOverrideRedirect|CWBackingStore|CWSaveUnder|CWBackPixmap);
expose = XCreateWindow(dpy, window, 0, 0, dpy_x, dpy_y, 0, depth,
InputOutput, &visual, mask, &swa);
if (! color) {
/* restore the backdrop windows from the XImage snapshots */
for (n=0; n < nws; n++) {
Window twin;
if (! image[n]) {
continue;
}
twin = ws_wins[n];
if (! twin) {
twin = rootwin;
}
if (! valid_window(twin)) {
continue;
}
pixmap = XCreatePixmap(dpy, twin, dpy_x, dpy_y, depth);
/* draw the image to a pixmap: */
gcv.function = GXcopy;
gcv.plane_mask = AllPlanes;
gc = XCreateGC(dpy, twin, GCFunction|GCPlaneMask, &gcv);
XPutImage(dpy, pixmap, gc, image[n], 0, 0, 0, 0,
dpy_x, dpy_y);
gcv.foreground = gcv.background = BlackPixel(dpy, scr);
gc = XCreateGC(dpy, twin, GCForeground|GCBackground,
&gcv);
rfbLog("restoring CDE ws%d snapshot to 0x%lx\n",
n, twin);
/* set the pixmap as the bg: */
XSetWindowBackgroundPixmap(dpy, twin, pixmap);
XFreePixmap(dpy, pixmap);
XClearWindow(dpy, twin);
XFlush(dpy);
}
/* generate exposures */
XMapWindow(dpy, expose);
XSync(dpy, False);
XDestroyWindow(dpy, expose);
return;
}
if (nws < 0) {
/* need to retrieve snapshots of the ws backgrounds: */
Window iwin, wm_win;
XSetWindowAttributes iswa;
Atom dt_list, wm_info, type;
int format;
unsigned long length, after;
unsigned char *data;
unsigned int * dp;
nws = 0;
/* extract the hidden wm properties about backdrops: */
wm_info = XInternAtom(dpy, "_MOTIF_WM_INFO", True);
if (wm_info == None) {
return;
}
XGetWindowProperty(dpy, rootwin, wm_info, 0L, 10L, False,
AnyPropertyType, &type, &format, &length, &after, &data);
/*
* xprop -notype -root _MOTIF_WM_INFO
* _MOTIF_WM_INFO = 0x2, 0x580028
*/
if (length < 2 || format != 32 || after != 0) {
return;
}
dp = (unsigned int *) data;
wm_win = (Window) *(dp+1); /* 2nd item. */
dt_list = XInternAtom(dpy, "_DT_WORKSPACE_LIST", True);
if (dt_list == None) {
return;
}
XGetWindowProperty(dpy, wm_win, dt_list, 0L, 10L, False,
AnyPropertyType, &type, &format, &length, &after, &data);
nws = length;
if (nws > wsmax) {
nws = wsmax;
}
if (nws < 0) {
nws = 0;
}
rfbLog("special CDE win: 0x%lx, %d workspaces\n", wm_win, nws);
if (nws == 0) {
return;
}
for (n=0; n<nws; n++) {
Atom ws_atom;
char tmp[32];
Window twin;
XWindowAttributes attr;
int i, cnt;
image[n] = NULL;
ws_wins[n] = 0x0;
sprintf(tmp, "_DT_WORKSPACE_INFO_ws%d", n);
ws_atom = XInternAtom(dpy, tmp, False);
if (ws_atom == None) {
continue;
}
XGetWindowProperty(dpy, wm_win, ws_atom, 0L, 100L,
False, AnyPropertyType, &type, &format, &length,
&after, &data);
if (format != 8 || after != 0) {
continue;
}
/*
* xprop -notype -id wm_win
* _DT_WORKSPACE_INFO_ws0 = "One", "3", "0x2f2f4a",
* "0x63639c", "0x103", "1", "0x58044e"
*/
cnt = 0;
twin = 0x0;
for (i=0; i<length; i++) {
if (*(data+i) != '\0') {
continue;
}
cnt++; /* count nulls to indicate field */
if (cnt == 6) {
/* one past the null: */
char *q = (char *) (data+i+1);
unsigned long in;
if (sscanf(q, "0x%lx", &in) == 1) {
twin = (Window) in;
break;
}
}
}
ws_wins[n] = twin;
if (! twin) {
twin = rootwin;
}
XGetWindowAttributes(dpy, twin, &attr);
if (twin != rootwin) {
if (attr.map_state != IsViewable) {
XMapWindow(dpy, twin);
}
XRaiseWindow(dpy, twin);
}
XSync(dpy, False);
/* create image window: */
iswa.override_redirect = True;
iswa.backing_store = NotUseful;
iswa.save_under = False;
iswa.background_pixmap = ParentRelative;
visual.visualid = CopyFromParent;
iwin = XCreateWindow(dpy, twin, 0, 0, dpy_x, dpy_y,
0, depth, InputOutput, &visual, mask, &iswa);
rfbLog("snapshotting CDE backdrop ws%d 0x%lx -> "
"0x%lx ...\n", n, twin, iwin);
XMapWindow(dpy, iwin);
XSync(dpy, False);
image[n] = XGetImage(dpy, iwin, 0, 0, dpy_x, dpy_y,
AllPlanes, ZPixmap);
XSync(dpy, False);
XDestroyWindow(dpy, iwin);
if (twin != rootwin) {
XLowerWindow(dpy, twin);
if (attr.map_state != IsViewable) {
XUnmapWindow(dpy, twin);
}
}
}
}
if (nws == 0) {
return;
}
/* use black for low colors or failure */
pixel = BlackPixel(dpy, scr);
if (depth > 8 || strcmp(color, solid_default)) {
cmap = DefaultColormap (dpy, scr);
if (XParseColor(dpy, cmap, color, &cdef) &&
XAllocColor(dpy, cmap, &cdef)) {
pixel = cdef.pixel;
} else {
rfbLog("error parsing/allocing color: %s\n", color);
}
}
rfbLog("setting solid backgrounds...\n");
for (n=0; n < nws; n++) {
Window twin = ws_wins[n];
if (image[n] == NULL) {
continue;
}
if (! twin) {
twin = rootwin;
}
XSetWindowBackground(dpy, twin, pixel);
}
XMapWindow(dpy, expose);
XSync(dpy, False);
XDestroyWindow(dpy, expose);
}
void solid_gnome(char *color) {
char get_color[] = "gconftool-2 --get "
"/desktop/gnome/background/primary_color";
......@@ -11793,6 +12389,13 @@ char *guess_desktop() {
if (prop != None) {
return "gnome";
}
prop = XInternAtom(dpy, "_MOTIF_WM_INFO", True);
if (prop != None) {
prop = XInternAtom(dpy, "_DT_WORKSPACE_LIST", True);
if (prop != None) {
return "cde";
}
}
return "root";
}
......@@ -11817,6 +12420,8 @@ void solid_bg(int restore) {
solid_gnome(NULL);
} else if (desktop == 2) {
solid_kde(NULL);
} else if (desktop == 3) {
solid_cde(NULL);
}
solid_on = 0;
return;
......@@ -11836,6 +12441,8 @@ void solid_bg(int restore) {
dtname = "gnome";
} else if (strstr(solid_str, "kde:") == solid_str) {
dtname = "kde";
} else if (strstr(solid_str, "cde:") == solid_str) {
dtname = "cde";
} else {
dtname = "root";
}
......@@ -11856,6 +12463,9 @@ void solid_bg(int restore) {
} else if (!strcmp(dtname, "kde")) {
desktop = 2;
solid_kde(color);
} else if (!strcmp(dtname, "cde")) {
desktop = 3;
solid_cde(color);
} else {
desktop = 0;
solid_root(color);
......@@ -14559,7 +15169,8 @@ char gui_code[] = "";
#include "tkx11vnc.h"
#endif
void run_gui(char *gui_xdisplay, int connect_to_x11vnc, pid_t parent) {
void run_gui(char *gui_xdisplay, int connect_to_x11vnc, int simple_gui,
pid_t parent) {
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";
......@@ -14682,8 +15293,10 @@ void run_gui(char *gui_xdisplay, int connect_to_x11vnc, pid_t parent) {
set_env("DISPLAY", gui_xdisplay);
set_env("X11VNC_PROG", program_name);
set_env("X11VNC_CMDLINE", program_cmdline);
if (simple_gui) {
set_env("X11VNC_SIMPLE_GUI", "1");
}
if (auth_file) {
set_env("X11VNC_AUTH_FILE", auth_file);
}
sprintf(cmd, "%s -", wish);
......@@ -14722,6 +15335,7 @@ void do_gui(char *opts) {
char *gui_xdisplay = NULL;
int start_x11vnc = 1;
int connect_to_x11vnc = 0;
int simple_gui = 0;
Display *test_dpy;
if (opts) {
......@@ -14754,6 +15368,8 @@ void do_gui(char *opts) {
} 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 {
fprintf(stderr, "unrecognized gui opt: %s\n", p);
}
......@@ -14804,7 +15420,8 @@ void do_gui(char *opts) {
perror("fork");
clean_up_exit(1);
} else {
run_gui(gui_xdisplay, connect_to_x11vnc, parent);
run_gui(gui_xdisplay, connect_to_x11vnc, simple_gui,
parent);
exit(1);
}
#else
......@@ -14814,7 +15431,7 @@ void do_gui(char *opts) {
#endif
}
if (!start_x11vnc) {
run_gui(gui_xdisplay, connect_to_x11vnc, 0);
run_gui(gui_xdisplay, connect_to_x11vnc, simple_gui, 0);
exit(1);
}
if (old_xauth) {
......@@ -15957,10 +16574,13 @@ static void print_help(int mode) {
" (full-access) password must also be supplied.\n"
"-passwdfile filename Specify libvncserver -passwd via the first line of\n"
" the file \"filename\" instead of via command line.\n"
" If a second non blank line exists in the file it is\n"
" taken as a view-only password (i.e. -viewpasswd) Note:\n"
" this is a simple plaintext passwd, see also -rfbauth\n"
" and -storepasswd below for obfuscated passwords.\n"
" If a second non blank line exists in the file it\n"
" is taken as a view-only password (i.e. -viewpasswd)\n"
" To supply an empty password for either field use the\n"
" string \"__EMPTY__\". Note: -passwdfile is a simple\n"
" plaintext passwd, see also -rfbauth and -storepasswd\n"
" below for obfuscated passwords. Neither should be\n"
" readable by others.\n"
"-storepasswd pass file Store password \"pass\" as the VNC password in the\n"
" file \"file\". Once the password is stored the\n"
" program exits. Use the password via \"-rfbauth file\"\n"
......@@ -16039,44 +16659,64 @@ static void print_help(int mode) {
" \n"
" Why use this option? In general it is not needed\n"
" since x11vnc is already connected to the display and\n"
" can perform its primary functions. It was added to\n"
" make some of the *external* utility commands x11vnc\n"
" occasionally runs work properly. In particular under\n"
" GNOME and KDE to implement the \"-solid color\" feature\n"
" external commands (gconftool-2 and dcop) must be run as\n"
" the user owning the desktop session. This option also\n"
" affects the userid used to run the processes for the\n"
" -accept and -gone options. It also affects the ability\n"
" to read files for options such as -connect, -allow, and\n"
" -remap. Note that the -connect file is also written to.\n"
" can perform its primary functions. The option was\n"
" added to make some of the *external* utility commands\n"
" x11vnc occasionally runs work properly. In particular\n"
" under GNOME and KDE to implement the \"-solid color\"\n"
" feature external commands (gconftool-2 and dcop) must be\n"
" run as the user owning the desktop session. Since this\n"
" option switches userid it also affects the userid used\n"
" to run the processes for the -accept and -gone options.\n"
" It also affects the ability to read files for options\n"
" such as -connect, -allow, and -remap. Note that the\n"
" -connect file is also sometimes written to.\n"
" \n"
" So be careful with this option since in many situations\n"
" its use can decrease security.\n"
" \n"
" The switch to a user will only take place if the display\n"
" can still be opened as that user (this is primarily to\n"
" try to guess the actual owner of the session). Example:\n"
" \"-users fred,wilma,betty\". Note that a malicious\n"
" user \"barney\" by quickly using \"xhost +\" when\n"
" logging in can get x11vnc to switch to user \"fred\".\n"
" What happens next?\n"
" The switch to a user will only take place if the\n"
" display can still be successfully opened as that user\n"
" (this is primarily to try to guess the actual owner\n"
" of the session). Example: \"-users fred,wilma,betty\".\n"
" Note that a malicious user \"barney\" by quickly using\n"
" \"xhost +\" when logging in may get x11vnc to switch\n"
" to user \"fred\". What happens next?\n"
" \n"
" Under display managers it may be a long time before\n"
" the switch succeeds (i.e. a user logs in). To make\n"
" it switch immediately regardless if the display can\n"
" be reopened or not prefix the username with the +\n"
" it switch immediately regardless if the display\n"
" can be reopened prefix the username with the +\n"
" character. E.g. \"-users +bob\" or \"-users +nobody\".\n"
" The latter (i.e. switching immediately to user\n"
" \"nobody\") is probably the only use of this option\n"
" that increases security. To switch to a user *before*\n"
" connections to the display are made or any files opened\n"
" use the \"=\" character: \"-users =username\".\n"
" that increases security.\n"
" \n"
" To immediately switch to a user *before* connections to\n"
" the display are made or any files opened use the \"=\"\n"
" character: \"-users =bob\". That user needs to be able\n"
" to open the display of course.\n"
" \n"
" The special user \"guess\" means to examine the utmpx\n"
" database looking for a user attached to the display\n"
" number and try him/her. To limit the list of guesses,\n"
" use: \"-users guess=bob,betty\". Be especially careful\n"
" using this mode.\n"
" The special user \"guess=\" means to examine the utmpx\n"
" database (see who(1)) looking for a user attached to\n"
" the display number (from DISPLAY or -display option)\n"
" and try him/her. To limit the list of guesses, use:\n"
" \"-users guess=bob,betty\".\n"
" \n"
" Even more sinister is the special user \"lurk=\" that\n"
" means to try to guess the DISPLAY from the utmpx login\n"
" database as well. So it \"lurks\" waiting for anyone\n"
" to log into an X session and then connects to it.\n"
" Specify a list of users after the = to limit which\n"
" users will be tried. If the first user in the list\n"
" is something like \":0\" or \":0-2\" that indicates a\n"
" range of DISPLAY numbers that will be tried (regardless\n"
" of whether they are in the utmpx database) for all\n"
" users that are logged in. Examples: \"-users lurk=\"\n"
" and \"-users lurk=:0-1,bob,mary\"\n"
" \n"
" Be especially careful using the \"guess=\" and \"lurk=\"\n"
" modes. They are not recommended for use on machines\n"
" with untrustworthy local users.\n"
" \n"
"-noshm Do not use the MIT-SHM extension for the polling.\n"
" Remote displays can be polled this way: be careful this\n"
......@@ -16095,16 +16735,16 @@ static void print_help(int mode) {
" For a different one specify the X color (rgb.txt name,\n"
" e.g. \"darkblue\" or numerical \"#RRGGBB\").\n"
"\n"
" Currently this option only works on GNOME, KDE, and\n"
" classic X (i.e. with the background image on the root\n"
" window). The \"gconftool-2\" and \"dcop\" external\n"
" Currently this option only works on GNOME, KDE, CDE,\n"
" and classic X (i.e. with the background image on the\n"
" root window). The \"gconftool-2\" and \"dcop\" external\n"
" commands are run for GNOME and KDE respectively.\n"
" Other desktops won't work, e.g. XFCE (send us the\n"
" corresponding commands if you find them). If x11vnc\n"
" is running as root (inetd(1) or gdm(1)), the -users\n"
" option may be needed for GNOME and KDE. If x11vnc\n"
" guesses your desktop incorrectly, you can force it by\n"
" prefixing color with \"gnome:\", \"kde:\", or \"root:\".\n"
" corresponding commands if you find them). If x11vnc is\n"
" running as root (inetd(1) or gdm(1)), the -users option\n"
" may be needed for GNOME and KDE. If x11vnc guesses\n"
" your desktop incorrectly, you can force it by prefixing\n"
" color with \"gnome:\", \"kde:\", \"cde:\" or \"root:\".\n"
"-blackout string Black out rectangles on the screen. \"string\" is a\n"
" comma separated list of WxH+X+Y type geometries for\n"
" each rectangle.\n"
......@@ -16512,9 +17152,11 @@ static void print_help(int mode) {
" up on the X display in the environment variable DISPLAY.\n"
"\n"
" \"gui-opts\" can be a comma separated list of items.\n"
" Currently there are only two types of items: 1) a gui\n"
" mode and 2) the X display the gui should display on.\n"
" The gui mode can be \"start\", \"conn\", or \"wait\"\n"
" Currently there are these types of items: 1) a gui mode,\n"
" a 2) gui \"simplicity\", and 3) the X display the gui\n"
" should display on.\n"
"\n"
" 1) The gui mode can be \"start\", \"conn\", or \"wait\"\n"
" \"start\" is the default mode above and is not required.\n"
" \"conn\" means do not automatically start up x11vnc,\n"
" but instead just try to connect to an existing x11vnc\n"
......@@ -16522,15 +17164,22 @@ static void print_help(int mode) {
" else (you will later instruct the gui to start x11vnc\n"
" or connect to an existing one.)\n"
"\n"
" Note the possible confusion regarding the potentially\n"
" 2) The gui simplicity is off by default (a power-user\n"
" gui with all options is presented) To start with\n"
" something less daunting supply the string \"simple\"\n"
" (\"ez\" is an alias for this). Once the gui is\n"
" started you can toggle between the two with \"Misc ->\n"
" simple_gui\".\n"
"\n"
" 3) Note the possible confusion regarding the potentially\n"
" two different X displays: x11vnc polls one, but you\n"
" may want the gui to appear on another. For example, if\n"
" you ssh in and x11vnc is not running yet you may want\n"
" the gui to come back to you via your ssh redirected X\n"
" display (e.g. localhost:10).\n"
"\n"
" Examples: \"x11vnc -gui\", \"x11vnc -gui localhost:10\",\n"
" \"x11vnc -gui :10\", \"x11vnc -gui conn,host:10\",\n"
" Examples: \"x11vnc -gui\", \"x11vnc -gui ez\"\n"
" \"x11vnc -gui localhost:10\", \"x11vnc -gui conn,host:0\"\n"
"\n"
" If you do not specify a gui X display in \"gui-opts\"\n"
" then the DISPLAY environment variable and -display\n"
......@@ -17244,65 +17893,65 @@ static void check_rcfile(int argc, char **argv) {
}
}
int main(int argc, char* argv[]) {
int i, len;
int ev, er, maj, min;
char *arg;
int remote_sync = 0;
char *remote_cmd = NULL;
char *query_cmd = NULL;
char *gui_str = NULL;
int pw_loc = -1;
int vpw_loc = -1;
int dt = 0, bg = 0;
int got_rfbwait = 0, got_deferupdate = 0, got_defer = 0;
/* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc = 1; char *argv_vnc[128];
/* if we are root limit some remote commands: */
if (!getuid() || !geteuid()) {
safe_remote_only = 1;
started_as_root = 1;
/* check for '-users =fred' */
void immediate_switch_user(int argc, char* argv[]) {
int i;
for (i=1; i < argc; i++) {
char *u;
int saved;
if (strcmp(argv[i], "-users")) {
continue;
}
if (i == argc - 1) {
fprintf(stderr, "not enough arguments for: "
"-users\n");
fprintf(stderr, "not enough arguments for: -users\n");
exit(1);
}
if (*(argv[i+1]) != '=') {
break;
}
/* wants an immediate switch: =bob */
u = strdup(argv[i+1]);
*u = '+';
if (strstr(u, "+guess") == u) {
fprintf(stderr, "invalid user: %s\n", u);
fprintf(stderr, "invalid user: %s\n", u+1);
exit(1);
}
/* kludge... */
saved = using_shm;
using_shm = 0;
if (!switch_user(u)) {
fprintf(stderr, "Could not switch to user: "
"%s\n", u+1);
if (!switch_user(u, 0)) {
fprintf(stderr, "Could not switch to user: %s\n", u+1);
exit(1);
} else {
fprintf(stderr, "Switched to user: %s\n", u+1);
started_as_root = 2;
}
using_shm = saved;
free(u);
break;
}
}
int main(int argc, char* argv[]) {
int i, len;
int ev, er, maj, min;
char *arg;
int remote_sync = 0;
char *remote_cmd = NULL;
char *query_cmd = NULL;
char *gui_str = NULL;
int pw_loc = -1;
int vpw_loc = -1;
int dt = 0, bg = 0;
int got_rfbwait = 0, got_deferupdate = 0, got_defer = 0;
/* used to pass args we do not know about to rfbGetScreen(): */
int argc_vnc = 1; char *argv_vnc[128];
/* if we are root limit some remote commands, etc: */
if (!getuid() || !geteuid()) {
safe_remote_only = 1;
started_as_root = 1;
/* check for '-users =bob' */
immediate_switch_user(argc, argv);
}
argv_vnc[0] = strdup(argv[0]);
......@@ -17797,12 +18446,20 @@ int main(int argc, char* argv[]) {
exit(1);
}
if (fgets(line, 1024, in) != NULL) {
char *q;
int len = strlen(line);
if (len > 0 && line[len-1] == '\n') {
line[len-1] = '\0';
}
argv_vnc[argc_vnc++] = strdup("-passwd");
if (!strcmp(line, "__EMPTY__")) {
argv_vnc[argc_vnc++] = strdup("");
} else if ((q = strstr(line, "__ENDPASSWD__")) !=NULL) {
*q = '\0';
argv_vnc[argc_vnc++] = strdup(line);
} else {
argv_vnc[argc_vnc++] = strdup(line);
}
pw_loc = 100; /* just for pw_loc check below */
if (fgets(line, 1024, in) != NULL) {
/* try to read viewonly passwd from file */
......@@ -17822,7 +18479,15 @@ int main(int argc, char* argv[]) {
}
}
if (ok) {
if (!strcmp(line, "__EMPTY__")) {
viewonly_passwd = strdup("");
} else if ((q = strstr(line,
"__ENDPASSWD__")) != NULL) {
*q = '\0';
viewonly_passwd = strdup(line);
} else {
viewonly_passwd = strdup(line);
}
} else {
rfbLog("*** not setting"
" viewonly password to the 2nd"
......@@ -17972,6 +18637,8 @@ int main(int argc, char* argv[]) {
fprintf(stderr, " vnc_conn: %d\n", vnc_connect);
fprintf(stderr, " allow: %s\n", allow_list ? allow_list
: "null");
fprintf(stderr, " input: %s\n", allowed_input_str
? allowed_input_str : "null");
fprintf(stderr, " passfile: %s\n", passwdfile ? passwdfile
: "null");
fprintf(stderr, " accept: %s\n", accept_cmd ? accept_cmd
......@@ -18093,6 +18760,14 @@ int main(int argc, char* argv[]) {
use_xkb_modtweak = 0;
#endif
if (users_list && strstr(users_list, "lurk=")) {
if (use_dpy) {
rfbLog("warning: -display does not make sense in "
"\"lurk=\" mode...\n");
}
lurk_loop(users_list);
}
if (use_dpy) {
dpy = XOpenDisplay(use_dpy);
} else if ( (use_dpy = getenv("DISPLAY")) ) {
......
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