[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: problems with vnc



On Wed, Mar 25, 1998 at 07:45:51AM -0500, Alex Yukhimets wrote:
> > might be the appropriate software, so I tried to set up my linux
> > box as a vnc server. This was not possible couldn't as the vnc
> > server didn't find any free sockets (I don't remember exactly what
> > the error message was, but something like "you might have already
> > an x session running"?!).
> > 
> > Now I noticed that there seems to be a vnc package in hamm?! Is
> > it possible to use it in bo? Has anybody used vnc under Debian 1.3
> > and encountered similar problems?

You can use it if you upgrade to libc6, otherwise you can get the source
package and compile it for you. The problems you have are all well known and
fixed in the Debian package, but except for the font problem they are easy
to fix using my (heavily patched) vncserver script.

You should start Xvnc with the vncserver script. If you ever need to use
Xvnc, there is something wrong with my vncserver script ;)
 
> No. I am running vnc on a bo machine fine. Are you starting the server
> using "vncserver" script? I don't use the debian package, and therefore
> had to use the fonserver - you should do the same.
> Also, you would have to edit vncserver script a bit- like to change the
> very first line - localtion of perl, also some changes needed inside -read
> the FAQ on the VNC website.

Hi,

here speaks up the new Debian maintainer of vnc. I compiled it for libc6,
and everybody should consider to use my package (because I put a lot of work
in it ;), but if you only have bo and no need for an upgrade, I recommend
you the use of *my* version of vncserver.

I attach it to this mail. Probably you have to change the location of the
Xvnc exectuable, but everything else is now configurable with a
configuration script in /etc/vnc.conf or in the users homedirectory
~/.vncrc.

For example, if you want to use a font server (although I would recommend
the patch from the contrib site of VNC homepage, which is also incorporated
in the Debian version since 3.3.1-4, that allows you to use gzip'ed fonts),
you have to add "start-xfs" to /etc/X11/config and your conf file should
have a line like this:

$fontPath = "tcp/localhost:7100";

I attach a sample vnc.conf file. Note that both files and the patch for
gziped fonts and a viewer for svgalib and man pages are available in hamm
(sorry for the advertisement ;)

Please report further problems also to me, so I can fix my package where
needed.

Marcus

-- 
"Rhubarb is no Egyptian god."        Debian GNU/Linux        finger brinkmd@ 
Marcus Brinkmann                   http://www.debian.org    master.debian.org
Marcus.Brinkmann@ruhr-uni-bochum.de                        for public  PGP Key
http://homepage.ruhr-uni-bochum.de/Marcus.Brinkmann/       PGP Key ID 36E7CD09
# vnc.conf written by Marcus Brinkmann. This file is in the Public Domain.
#
# This is the configuration file for the vncserver package.
# It is perl syntax, but only variable assignment is allowed.
# A semicolon will be added if missing.
# Every value has suitable defaults, so you probably don't need any file.
#
# This file will be sourced by `vncserver' and `vncpasswd'.
# After this file, $(HOME)/.vncrc will be sourced, so values can be
# overwritten on a per-user basis. If you want to reactivate the default
# value there, you have to specify an empty value. For example, $fontPath
# will set to the default value after
#
# $fontPath = "/foo";
# $fontPath = "";
#
# If you are missing something, please let me know.
# Marcus.Brinkmann@ruhr-uni-bochum.de

# System configuration
# --------------------
#
# This section contains entries that should be true for all users.

# $vncClasses should be the path to the java classes of server.
# $vncClasses = "/usr/X11R6/lib/vncserver";

# $XFConfigPath   can be set to the global XF86Config file. This will be
#                 parsed to gain default values for $fontPath and $colorPath.
#                 If you want to disable this feature, point it to an
#                 invalid file, "/foo" for example.
# $XFConfigPath = "/etc/X11/XF86Config";

# $fontPath should a comma seperated list of fonts to be added to the font
#           path. If not specified, and $XFConfigPath is valid, vncserver
#           will read the $fontPath from there. If both are not set, the
#           default will apply.
# Example: $fontPath = "tcp/localhost:7100";     # would make vnc to use xfs.
# Example: $fontPath = "";
#	$fontPath .= "/usr/X11R6/lib/X11/fonts/misc/,";
# 	$fontPath .= "/usr/X11R6/lib/X11/fonts/75dpi/:unscaled,";
# 	$fontPath .= "/usr/X11R6/lib/X11/fonts/100dpi/:unscaled,";
# 	$fontPath .= "/usr/X11R6/lib/X11/fonts/Type1/,";
# 	$fontPath .= "/usr/X11R6/lib/X11/fonts/Speedo/,";
# 	$fontPath .= "/usr/X11R6/lib/X11/fonts/75dpi/,";
# 	$fontPath .= "/usr/X11R6/lib/X11/fonts/100dpi/,";
#	$fontPath .= "/usr/X11R6/lib/X11/fonts/freefont/,";
#	$fontPath .= "/usr/X11R6/lib/X11/fonts/sharefont/";
# I don't know what the default is, though.

# $colorPath should be the RGB file to be used by X. This can also be taken from
#            XF86Config file if specified by $XFConfigPath
# $colorPath = "/usr/X11R6/lib/X11/rgb";

# User configuration
# ------------------
#
# This section contains entries that may change from user to user.

# $vncUserDir contains the filename for the log files directory of Xvnc
#             (the server) and the viewers that are connected to it.
# $vncUserDir = "$ENV{HOME}/.vnc";

# $vncPasswdFile contains the filename of the password file for Xvnc.
# $vncPasswdFile = $vncUserDir . "/passwd";

# $vncStartup points to a script that will be started at the very beginning.
# $vncStartup = "/etc/X11/XSession";

# $xauthorityFile should be the path to the authority file that should be used
#                 by your vnc X server.
# $xauthorityFile = "$ENV{HOME}/.Xauthority";

# $defaultDesktopName should be set to the default name of the desktop.
#                     This can be changed at the command line with -name.
# $defaultDesktopName = "X";

# $geometry sets framebuffer width & height. Default will be calculated if
#           server is started from within a running X servers. Can be changed at
#           the commandline (-geometry). A fixed default will be used if
#           vncserver is not invoked in a running X session.
# Example:  $geometry ="640x480";

# $depth       sets the framebuffer color depth. Must be between 8 and 32.
# $pixelformat sets the default pixelformat.
#              The default will be calculated if none of both is specified
#              and when vncserver is called from within a running X servers.
#              Can be changed at the command line with option -depth.
#              A fixed default value will be used if vncserver is not
#              invoked in a running X session.
# Example:  $depth = "16";
#           $pixelformat = "rgb565";

# $getDefaultFrom sets the display from which you can query the default of
#                 the above three options, if you don't want to start vncserver
#                 from within a running X server. It will be added to the call
#                 of xdpyinfo.
#                 It is useful to get the default from the X server you will
#                 run xvncviewer in.
# Example:  $getDefaultFrom = "-display localhost:0"

# $rfbwait sets the maximum time in msec to wait for vnc client viewer.
# $rfbwait = "120000";
#!/usr/bin/perl
#
#  Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
#
#  This is free software; you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation; either version 2 of the License, or
#  (at your option) any later version.
#
#  This software is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this software; if not, write to the Free Software
#  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
#  USA.
#

#
# vncserver - wrapper script to start an X VNC server.
#

#
# First make sure we're operating in a sane environment.
#

&SanityCheck();

#
# Then source in configuration files, first the site wide one and then the
# user specific one.
#

$Config_file = "/etc/vnc.conf";
&ReadConfigFile();
$Config_file = "$ENV{HOME}/.vncrc";
&ReadConfigFile();

if (!$vncClasses) {
  $vncClasses = "/usr/X11R6/lib/vncserver";
}
if (!$xauthorityFile) {
  $xauthorityFile = "$ENV{HOME}/.Xauthority";
}
if (!$vncUserDir) {
  $vncUserDir = "$ENV{HOME}/.vnc";
}
if (!$vncPasswdFile) {
  $vncPasswdFile = $vncUserDir . "/passwd";
}
if (!$defaultDesktopName) {
  $defaultDesktopName = "X";
}
if (!$rfbwait) {
  $rfbwait = "120000";
}
if (!$vncStartup) {
  $vncStartup = "/etc/X11/Xsession";
}
if (!$XFConfigPath) {
  $XFConfigPath = "/etc/X11/XF86Config";
}
if (!$fontPath) {
  &ReadXFConfigFont;
}
if (!$colorPath) {
  &ReadXFConfigColor;
}
if (!$colorPath) {
  $colorPath = "/usr/X11R6/lib/X11/rgb";
}

if ($geometry) {
  $opt{'-geometry'} = $geometry;
}
if ($depth) {
  $opt{'-depth'} = $depth;
}

chop($host = `uname -n`);

&ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-help",0);

&Usage() if ($opt{'-help'});

&GetXDisplayDefaults();

&CheckGeometryAndDepth();

if (!$opt{'-name'}) {
    $opt{'-name'} = $defaultDesktopName; # default desktop name
}

# Create the user's vnc directory if necessary.

if (!(-e $vncUserDir)) {
    if (!mkdir($vncUserDir,0755)) {
	die "$prog: Could not create $vncUserDir.\n";
    }
}

$desktopLog = "$vncUserDir/".&removeSlashes($opt{'-name'}).".log";
unlink($desktopLog);

    
# Make sure the user has a password.

($z,$z,$mode) = stat("$vncPasswdFile");
if (!(-e "$vncPasswdFile") || ($mode & 077)) {
    warn "\nYou will require a password to access your desktops.\n\n";
    system("vncpasswd $vncPasswdFile"); 
    if (($? >> 8) != 0) {
	exit 1;
    }
}

# Find display number.

if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) {
    $displayNumber = $1;
    shift(@ARGV);
    if (!&CheckDisplayNumber($displayNumber)) {
	die "A VNC server is already running as :$displayNumber\n";
    }
} else {
    $displayNumber = &GetDisplayNumber();
}

$vncPort = 5900 + $displayNumber;

        
# Make an X server cookie

srand(time+$$);
$cookie = "";
for (1..16) {
    $cookie .= sprintf("%02x", int(rand(256)));
}
    
system("xauth -f $xauthorityFile add $host:$displayNumber . $cookie");
system("xauth -f $xauthorityFile add $host/unix:$displayNumber . $cookie");

# Now start the X VNC Server

$cmd = "Xvnc :$displayNumber";
$cmd .= " -desktop " . &quotedString($opt{'-name'});
$cmd .= " -httpd $vncClasses";
$cmd .= " -auth $xauthorityFile";
$cmd .= " -geometry $opt{'-geometry'}" if ($opt{'-geometry'});
$cmd .= " -depth $opt{'-depth'}" if ($opt{'-depth'});
$cmd .= " -pixelformat $opt{'-pixelformat'}" if ($opt{'-pixelformat'});
$cmd .= " -rfbwait $rfbwait";
$cmd .= " -rfbauth $vncPasswdFile";
$cmd .= " -rfbport $vncPort";
$cmd .= " -fp $fontPath" if ($fontPath);
$cmd .= " -co $colorPath" if ($colorPath);

foreach $arg (@ARGV) {
    $cmd .= " " . &quotedString($arg);
}
$cmd .= " >> " . &quotedString($desktopLog) . " 2>&1";

system("$cmd &");

sleep(3); # give Xvnc a chance to start up

warn "\nNew '$opt{'-name'}' desktop is $host:$displayNumber\n\n";

# Run the X startup script.

warn "Starting applications specified in $vncStartup\n";
warn "Log file is $desktopLog\n\n";

$ENV{DISPLAY}= "$host:$displayNumber";
$ENV{VNCDESKTOP}= $opt{'-name'};

system("$vncStartup >> " . &quotedString($desktopLog) . " 2>&1 &") if ($vncStartup);

exit;

#########################################################################
#
# code submitted from Manoj Srivastava. Thank you, Manoj!
#
# ReadConfigFile reads in a config file and sets variables according to it.
#

sub ReadConfigFile
{
  open(CONFIG, "$Config_file") || return;
  my $lineno = 0;
  while (<CONFIG>) {
      chomp;
      $lineno++;
      s/\#.*//og;
      next if /^\s*$/og;
      $_ .= ";" unless /;\s*$/;
      if (/^\s*([^=]+)\s*=\s*(\S.*)$/o) {
          my $ret = eval {"$1=$2"};
          if ($@) {
              print STDERR "Error parsing config file $Config_file!\n";
              print STDERR "$lineno:$_\n";
          }
      }
  }
}

sub ReadXFConfigFont
{
  open(CONFIG, "$XFConfigPath") || return;
  my $lineno = 0;
  while (<CONFIG>) {
      chomp;
      $lineno++;
      s/\#.*//og;
      next if /^\s*$/og;
      if (/^\s*FontPath\s*"(\S.*)"\s*$/o) {
          $fontPath .= "," if $fontPath;
          $fontPath .= $1;
      }
  }
}

sub ReadXFConfigColor
{
  open(CONFIG, "$XFConfigPath") || return;
  my $lineno = 0;
  while (<CONFIG> && !$colorPath) {
      chomp;
      $lineno++;
      s/\#.*//og;
      next if /^\s*$/og;
      if (/^\s*RgbPath\s*"(\S.*)"\s*$/o) {
          $colorPath = $1;
      }
  }
}


###############################################################################
#
# CheckGeometryAndDepth simply makes sure that the geometry and depth values
# are sensible.
#

sub CheckGeometryAndDepth
{
    if ($opt{'-geometry'}) {
	if ($opt{'-geometry'} =~ /^(\d+)x(\d+)$/) {
	    $width = $1; $height = $2;

	    if (($width<1) || ($height<1)) {
		die "$prog: geometry $opt{'-geometry'} is invalid\n";
	    }

	    while (($width % 4)!=0) {
		$width = $width + 1;
	    }

	    while (($height % 2)!=0) {
		$height = $height + 1;
	    }

	    $opt{-geometry} = "${width}x$height";
	} else {
	    die "$prog: geometry $opt{'-geometry'} is invalid\n";
	}
    }

    if ($opt{'-depth'}) {
	if (($opt{'-depth'} < "8") || ($opt{'-depth'} > 32)) {
	    die "Depth must be between 8 and 32\n";
	}
    }
}


#
# GetDisplayNumber gets the lowest available display number.  A display number
# n is taken if something is listening on the VNC server port (5900+n) or the
# X server port (6000+n).
#

sub GetDisplayNumber
{
    foreach $n (1..99) {
	if (&CheckDisplayNumber($n)) {
	    return $n;
	}
    }
    
    die "$prog: no free display number on $host.\n";
}


#
# CheckDisplayNumber checks if the given display number is available.  A
# display number n is taken if something is listening on the VNC server port
# (5900+n) or the X server port (6000+n).
#

sub CheckDisplayNumber
{
    local ($n) = @_;

    socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
    if (!bind(S, pack('S n x12', $AF_INET, 6000 + $n))) {
	close(S);
	return 0;
    }
    close(S);

    socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
    if (!bind(S, pack('S n x12', $AF_INET, 5900 + $n))) {
	close(S);
	return 0;
    }
    close(S);

    return 1;
}


#
# GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel
# format of the current X display being used.  If successful, it sets the
# options as appropriate so that the X VNC server will use the same settings
# (minus an allowance for window manager decorations on the geometry).  Using
# the same depth and pixel format means that the VNC server won't have to
# translate pixels when the desktop is being viewed on this X display (for
# TrueColor displays anyway).
#

sub GetXDisplayDefaults
{
    local (@lines, @matchlines, $width, $height, $defaultVisualId, $i,
	   $red, $green, $blue);

    $wmDecorationWidth = 8;	# a guess at typical size for window manager
    $wmDecorationHeight = 32;	# decoration size

    return if (!$getDefaultFrom && !defined($ENV{DISPLAY}));

    @lines = `xdpyinfo $getDefaultFrom 2>/dev/null`;

    return if ($? != 0);

    if (!$opt{'-geometry'}) {
	@matchlines = grep(/dimensions/, @lines);
	if (@matchlines) {
	    ($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/);

	    $width -= $wmDecorationWidth;
	    $height -= $wmDecorationHeight;

	    $opt{'-geometry'} = "${width}x$height";
	}
    }

    if (!$opt{'-depth'} && !$opt{'-pixelformat'}) {
	@matchlines = grep(/default visual id/, @lines);
	if (@matchlines) {
	    ($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/);

	    for ($i = 0; $i < @lines; $i++) {
		if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) {
		    if (($lines[$i+1] !~ /TrueColor/) ||
			($lines[$i+2] !~ /depth/) ||
			($lines[$i+4] !~ /red, green, blue masks/))
		    {
			return;
		    }
		    last;
		}
	    }

	    return if ($i >= @lines);

	    ($opt{'-depth'}) = ($lines[$i+2] =~ /depth:\s+(\d+)/);
	    ($red,$green,$blue)
		= ($lines[$i+4]
		   =~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/);

	    $red = hex($red);
	    $green = hex($green);
	    $blue = hex($blue);

	    if ($red > $blue) {
		$red = int(log($red) / log(2)) - int(log($green) / log(2));
		$green = int(log($green) / log(2)) - int(log($blue) / log(2));
		$blue = int(log($blue) / log(2)) + 1;
		$opt{'-pixelformat'} = "rgb$red$green$blue";
	    } else {
		$blue = int(log($blue) / log(2)) - int(log($green) / log(2));
		$green = int(log($green) / log(2)) - int(log($red) / log(2));
		$red = int(log($red) / log(2)) + 1;
		$opt{'-pixelformat'} = "bgr$blue$green$red";
	    }
	}
    }
}


#
# quotedString returns a string which yields the original string when parsed
# by a shell.
#

sub quotedString
{
    local ($in) = @_;

    $in =~ s/\'/\'\"\'\"\'/g;

    return "'$in'";
}


#
# removeSlashes turns slashes into underscores for use as a file name.
#               turns also spaces and tabs into underscores (Marcus).
#

sub removeSlashes
{
    local ($in) = @_;

    $in =~ s|[/ 	]|_|g;		# space and tab

    return "$in";
}


#
# Usage
#

sub Usage
{
    die("usage: $prog [:<number>] [-name <desktop-name>] [-depth <depth>]\n".
	"                 [-geometry <width>x<height>]\n".
	"                 [-pixelformat rgbNNN|bgrNNN]\n".
	"                 <Xvnc-options>...\n");
}


#
# ParseOptions takes a list of possible options and a boolean indicating
# whether the option has a value following, and sets up an associative array
# %opt of the values of the options given on the command line. It removes all
# the arguments it uses from @ARGV and returns them in @optArgs.
#

sub ParseOptions
{
    local (@optval) = @_;
    local ($opt, @opts, %valFollows, @newargs);

    while (@optval) {
	$opt = shift(@optval);
	push(@opts,$opt);
	$valFollows{$opt} = shift(@optval);
    }

    @optArgs = ();
    %opt = ();

    arg: while ($arg = shift(@ARGV)) {
	foreach $opt (@opts) {
	    if ($arg eq $opt) {
		push(@optArgs, $arg);
		if ($valFollows{$opt}) {
		    if (@ARGV == 0) {
			&Usage();
		    }
		    $opt{$opt} = shift(@ARGV);
		    push(@optArgs, $opt{$opt});
		} else {
		    $opt{$opt} = 1;
		}
		next arg;
	    }
	}
	push(@newargs,$arg);
    }

    @ARGV = @newargs;
}


#
# Routine to make sure we're operating in a sane environment.
#

sub SanityCheck
{
    local ($cmd);

    #
    # Get the program name
    #

    ($prog) = ($0 =~ m|([^/]+)$|);

    #
    # Check we have all the commands we'll need on the path.
    #

 cmd:
    foreach $cmd ("uname","xauth","Xvnc","vncpasswd") {
	for (split(/:/,$ENV{PATH})) {
	    if (-x "$_/$cmd") {
		next cmd;
	    }
	}
	die "$prog: couldn't find \"$cmd\" on your PATH.\n";
    }

    #
    # Check the HOME environment variable is set
    #

    if (!defined($ENV{HOME})) {
	die "$prog: The HOME environment variable is not set.\n";
    }

    #
    # Check for socket constants and attempt to define suitable defaults
    #

    chop($os = `uname`);

    use Socket;
    if ($@) {
	if ($os eq "SunOS") {
	    $AF_INET = 2;
	    $SOCK_STREAM = 2;
	} else {
	    $AF_INET = 2;
	    $SOCK_STREAM = 1;
	}
    } else {
	$AF_INET = &AF_INET;
	$SOCK_STREAM = &SOCK_STREAM;
    }
}

Reply to: