#!/bin/bash set -e PROGNAME=$(basename $0) # Globals VERBOSELEVEL=20 main() { ERRMSG_MODE=echo debug 10 "main: sanity checks ..." [ "X$DISPLAY" != X ] || error "DISPLAY: not set (are you logged in on the console?)" type -p gxmessage || error "gxmessage: not found (do you need to install it?)" ERRMSG_MODE=gxmessage type -p Xvnc || error "Xvnc: not found (do you need to install it?)" type -p vncviewer || error "vncviewer: not found (do you need to install it?)" debug 10 "main: determining if VNC server is running ..." # Assign a different VNC server ID for each user (probably) VNC_DISPLAY_ID=$(echo "$(echo $LOGNAME | sum | awk '{ print $1 }') % 64" | bc -q) # Lock files for existing servers and viewers XVNC_SERVER_LOCK_FILE=/tmp/$PROGNAME.vnc-server-$VNC_DISPLAY_ID.lock XVNC_VIEWER_LOCK_FILE=/tmp/$PROGNAME.vnc-viewer-$VNC_DISPLAY_ID.lock # Is a server running? if ! XVNC_SERVER_PID=`cat $XVNC_SERVER_LOCK_FILE 2>/dev/null`; then VNC_SERVER_IS_RUNNING_FLAG=false elif [ ! -d /proc/$XVNC_SERVER_PID ]; then VNC_SERVER_IS_RUNNING_FLAG=false else VNC_SERVER_IS_RUNNING_FLAG=true fi debug 10 "main: VNC_SERVER_IS_RUNNING_FLAG=$VNC_SERVER_IS_RUNNING_FLAG" # If a server is not running then start one, with the same # geometry as a reference window (firefox). if $VNC_SERVER_IS_RUNNING_FLAG; then debug 10 "main: VNC is running, no action necessary" # 'xlsclients -al' returns the wrong window ID for Firefox. The best # I've found is run 'xwininfo -root -tree' and search for 'Navigator'. elif ! XWININFO_ROOT_TREE_OUTPUT="$(xwininfo -root -tree)"; then debug 10 "main: xwininfo -root -tree: failed" error "failed to run 'xwininfo -root -tree' (please seek developer assistance)" elif ! REFERENCE_WINDOW_ID=$(echo "$XWININFO_ROOT_TREE_OUTPUT" | sed -n 's/ *\(0x[^ ]*\).*"Navigator".*/\1/p'); then debug 10 "main: sed: failed" error "failed run 'sed ...' (please seek developer assistance)" elif [ "X$REFERENCE_WINDOW_ID" = X ]; then debug 10 "main: no window ID found" error "failed to get Firefox's window ID (do you need to run firefox?)" elif ! REFERENCE_WINDOW_XWININFO_OUTPUT=$(xwininfo -id $REFERENCE_WINDOW_ID); then debug 10 "main: xwininfo -id $REFERENCE_WINDOW_ID: failed" error "failed to run 'xwininfo -id $REFERENCE_WINDOW_ID' ((please seek developer assistance)" else info "starting vnc server ..." REFERENCE_WINDOW_GEOMETRY=$(echo "$REFERENCE_WINDOW_XWININFO_OUTPUT" | sed -n 's/.*-geometry \([^+]*\).*/\1/p') sh -c "echo \$\$ > $XVNC_SERVER_LOCK_FILE; exec Xvnc :$VNC_DISPLAY_ID -localhost -geometry $REFERENCE_WINDOW_GEOMETRY -query localhost 2>/dev/null" & fi debug 10 "main: determining if VNC viewer is running ..." # Is a viewer running? (We will *always* # start a new viewer, but we need to know # if a viewer is already running in order # to know if we need to kill it or not). if ! XVNC_VIEWER_PID=`cat $XVNC_VIEWER_LOCK_FILE 2>/dev/null`; then VNC_VIEWER_IS_RUNNING_FLAG=false elif [ ! -d /proc/$XVNC_VIEWER_PID ]; then VNC_VIEWER_IS_RUNNING_FLAG=false else VNC_VIEWER_IS_RUNNING_FLAG=true fi debug 10 "main: VNC_VIEWER_IS_RUNNING_FLAG=$VNC_VIEWER_IS_RUNNING_FLAG" # If a viewer is running then kill it. if $VNC_VIEWER_IS_RUNNING_FLAG; then debug 10 "main: killing existing vnc viewer ..." kill $XVNC_VIEWER_PID sleep 1 fi # Start a new viewer. debug 10 "main: starting vnc viewer ..." sh -c "echo \$\$ > $XVNC_VIEWER_LOCK_FILE; exec vncviewer -FullColour localhost:$VNC_DISPLAY_ID 2>/dev/null" & } # Standard message functions debug() { [ $VERBOSELEVEL -lt $1 ] || echo "$PROGNAME: DEBUG[$1]: $2" >&2; } info() { [ $VERBOSELEVEL -lt 3 ] || echo "$PROGNAME: INFO: $1" >&2; } warning() { [ $VERBOSELEVEL -lt 2 ] || echo "$PROGNAME: WARNING: $1" >&2; } error() { [ $VERBOSELEVEL -lt 1 ] || if [ $ERRMSG_MODE = echo ]; then echo "$PROGNAME: ERROR: $1" >&2; else gxmessage -name $PROGNAME -buttons "GTK_STOCK_OK:0" "ERROR: $1"; fi; exit 1; } internal() { echo "$PROGNAME: INTERNAL ERROR: $1" >&2; exit 2; } main "$@"