# Installation paths
set(SYSCONF_DIR "${CMAKE_INSTALL_PREFIX}/etc")
set(BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin")
+set(SBIN_DIR "${CMAKE_INSTALL_PREFIX}/sbin")
set(DATA_DIR "${CMAKE_INSTALL_PREFIX}/share")
+set(LIBEXEC_DIR "${CMAKE_INSTALL_PREFIX}/libexec")
set(MAN_DIR "${DATA_DIR}/man")
set(LOCALE_DIR "${DATA_DIR}/locale")
set(DOC_DIR "${CMAKE_INSTALL_PREFIX}/share/doc/${CMAKE_PROJECT_NAME}-${VERSION}")
#cmakedefine HAVE_ACTIVE_DESKTOP_L
#cmakedefine ENABLE_NLS 1
+#cmakedefine LIBEXEC_DIR "@LIBEXEC_DIR@"
#cmakedefine DATA_DIR "@DATA_DIR@"
#cmakedefine LOCALE_DIR "@LOCALE_DIR@"
-DBUILD_STATIC=off \
-DCMAKE_INSTALL_PREFIX:PATH=/usr \
-DSYSCONF_DIR:PATH=/etc \
+ -DLIBEXEC_DIR:PATH=/usr/lib/$(DEB_HOST_MULTIARCH) \
-DUNIT_DIR:PATH=/lib/systemd/system
(cd unix/xserver; \
export PIXMANINCDIR=/usr/include/pixman-1; \
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncconfig
mv $(CURDIR)/debian/tigervncserver/usr/bin/vncpasswd \
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncpasswd
- mv $(CURDIR)/debian/tigervncserver/usr/bin/vncserver \
- $(CURDIR)/debian/tigervncserver/usr/bin/tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/bin/x0vncserver \
$(CURDIR)/debian/tigervncserver/usr/bin/x0tigervncserver
+ mv $(CURDIR)/debian/tigervncserver/usr/sbin/vncsession \
+ $(CURDIR)/debian/tigervncserver/usr/sbin/tigervncsession
+ mv $(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/vncserver \
+ $(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncconfig.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncconfig.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncpasswd.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncpasswd.1
- mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncserver.1 \
- $(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncserver.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0vncserver.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0tigervncserver.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xvnc.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xtigervnc.1
+ mv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncsession.8 \
+ $(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncsession.8
+ mv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncserver.8 \
+ $(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncserver.8
# delete development files
rm -f $(CURDIR)/debian/tigervncserver/usr/lib/xorg/modules/extensions/libvnc.la
# move viewer files to viewer package, rename on the fly
$(CURDIR)/debian/tigervncserver/usr/share/doc/tigervncserver/
rm -rf $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc-*/
# dh_movefiles
+ sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
+ debian/tigervncserver.postinst.in > debian/tigervncserver.postinst
# Build architecture-independent files here.
# Pass -i to all debhelper commands in this target to reduce clutter.
+++ /dev/null
-#!/bin/sh
-
-set -e
-
-if [ "$1" = "configure" ]; then
- MAN=/usr/share/man/man1
- BIN=/usr/bin
- update-alternatives --install \
- $BIN/vncserver vncserver $BIN/tigervncserver 64 \
- --slave \
- $MAN/vncserver.1.gz vncserver.1.gz $MAN/tigervncserver.1.gz
- update-alternatives --install \
- $BIN/Xvnc Xvnc $BIN/Xtigervnc 74 \
- --slave \
- $MAN/Xvnc.1.gz Xvnc.1.gz $MAN/Xtigervnc.1.gz
- update-alternatives --install \
- $BIN/x0vncserver x0vncserver $BIN/x0tigervncserver 74 \
- --slave \
- $MAN/x0vncserver.1.gz x0vncserver.1.gz $MAN/x0tigervncserver.1.gz
- update-alternatives --install \
- $BIN/vncpasswd vncpasswd $BIN/tigervncpasswd 74 \
- --slave \
- $MAN/vncpasswd.1.gz vncpasswd.1.gz $MAN/tigervncpasswd.1.gz
- update-alternatives --install \
- $BIN/vncconfig vncconfig $BIN/tigervncconfig 64 \
- --slave \
- $MAN/vncconfig.1.gz vncconfig.1.gz $MAN/tigervncconfig.1.gz
-fi
-
-#DEBHELPER#
-
-exit 0
--- /dev/null
+#!/bin/sh
+
+set -e
+
+if [ "$1" = "configure" ]; then
+ MAN=/usr/share/man
+ BIN=/usr/bin
+ SBIN=/usr/sbin
+ LIB=/usr/lib/@DEB_HOST_MULTIARCH@
+ update-alternatives --install \
+ $SBIN/vncsession vncsession $SBIN/tigervncsession 64 \
+ --slave \
+ $LIB/vncserver vncserver $LIB/tigervncserver \
+ --slave \
+ $MAN/man8/vncsession.8.gz vncsession.8.gz $MAN/man8/tigervncsession.8.gz \
+ --slave \
+ $MAN/man8/vncserver.8.gz vncserver.8.gz $MAN/man8/tigervncserver.8.gz
+ update-alternatives --install \
+ $BIN/Xvnc Xvnc $BIN/Xtigervnc 74 \
+ --slave \
+ $MAN/man1/Xvnc.1.gz Xvnc.1.gz $MAN/man1/Xtigervnc.1.gz
+ update-alternatives --install \
+ $BIN/x0vncserver x0vncserver $BIN/x0tigervncserver 74 \
+ --slave \
+ $MAN/man1/x0vncserver.1.gz x0vncserver.1.gz $MAN/man1/x0tigervncserver.1.gz
+ update-alternatives --install \
+ $BIN/vncpasswd vncpasswd $BIN/tigervncpasswd 74 \
+ --slave \
+ $MAN/man1/vncpasswd.1.gz vncpasswd.1.gz $MAN/man1/tigervncpasswd.1.gz
+ update-alternatives --install \
+ $BIN/vncconfig vncconfig $BIN/tigervncconfig 64 \
+ --slave \
+ $MAN/man1/vncconfig.1.gz vncconfig.1.gz $MAN/man1/tigervncconfig.1.gz
+fi
+
+#DEBHELPER#
+
+exit 0
if [ "$1" = "remove" ] ; then
BIN=/usr/bin
+ SBIN=/usr/sbin
update-alternatives --remove \
- vncserver $BIN/tigervncserver
+ vncsession $SBIN/tigervncsession
update-alternatives --remove \
Xvnc $BIN/Xtigervnc
update-alternatives --remove \
-DBUILD_STATIC=off \
-DCMAKE_INSTALL_PREFIX:PATH=/usr \
-DSYSCONF_DIR:PATH=/etc \
+ -DLIBEXEC_DIR:PATH=/usr/lib/$(DEB_HOST_MULTIARCH) \
-DUNIT_DIR:PATH=/lib/systemd/system
(cd unix/xserver; \
export PIXMANINCDIR=/usr/include/pixman-1; \
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncconfig
mv $(CURDIR)/debian/tigervncserver/usr/bin/vncpasswd \
$(CURDIR)/debian/tigervncserver/usr/bin/tigervncpasswd
- mv $(CURDIR)/debian/tigervncserver/usr/bin/vncserver \
- $(CURDIR)/debian/tigervncserver/usr/bin/tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/bin/x0vncserver \
$(CURDIR)/debian/tigervncserver/usr/bin/x0tigervncserver
+ mv $(CURDIR)/debian/tigervncserver/usr/sbin/vncsession \
+ $(CURDIR)/debian/tigervncserver/usr/sbin/tigervncsession
+ mv $(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/vncserver \
+ $(CURDIR)/debian/tigervncserver/usr/lib/$(DEB_HOST_MULTIARCH)/tigervncserver
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncconfig.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncconfig.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncpasswd.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncpasswd.1
- mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/vncserver.1 \
- $(CURDIR)/debian/tigervncserver/usr/share/man/man1/tigervncserver.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0vncserver.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/x0tigervncserver.1
mv $(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xvnc.1 \
$(CURDIR)/debian/tigervncserver/usr/share/man/man1/Xtigervnc.1
+ mv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncsession.8 \
+ $(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncsession.8
+ mv $(CURDIR)/debian/tigervncserver/usr/share/man/man8/vncserver.8 \
+ $(CURDIR)/debian/tigervncserver/usr/share/man/man8/tigervncserver.8
# delete development files
rm -f $(CURDIR)/debian/tigervncserver/usr/lib/xorg/modules/extensions/libvnc.la
# move viewer files to viewer package, rename on the fly
$(CURDIR)/debian/tigervncserver/usr/share/doc/tigervncserver/
rm -rf $(CURDIR)/debian/tigervncserver/usr/share/doc/tigervnc-*/
# dh_movefiles
+ sed 's/@DEB_HOST_MULTIARCH@/$(DEB_HOST_MULTIARCH)/g' \
+ debian/tigervncserver.postinst.in > debian/tigervncserver.postinst
# Build architecture-independent files here.
# Pass -i to all debhelper commands in this target to reduce clutter.
+++ /dev/null
-#!/bin/sh
-
-set -e
-
-if [ "$1" = "configure" ]; then
- MAN=/usr/share/man/man1
- BIN=/usr/bin
- update-alternatives --install \
- $BIN/vncserver vncserver $BIN/tigervncserver 64 \
- --slave \
- $MAN/vncserver.1.gz vncserver.1.gz $MAN/tigervncserver.1.gz
- update-alternatives --install \
- $BIN/Xvnc Xvnc $BIN/Xtigervnc 74 \
- --slave \
- $MAN/Xvnc.1.gz Xvnc.1.gz $MAN/Xtigervnc.1.gz
- update-alternatives --install \
- $BIN/x0vncserver x0vncserver $BIN/x0tigervncserver 74 \
- --slave \
- $MAN/x0vncserver.1.gz x0vncserver.1.gz $MAN/x0tigervncserver.1.gz
- update-alternatives --install \
- $BIN/vncpasswd vncpasswd $BIN/tigervncpasswd 74 \
- --slave \
- $MAN/vncpasswd.1.gz vncpasswd.1.gz $MAN/tigervncpasswd.1.gz
- update-alternatives --install \
- $BIN/vncconfig vncconfig $BIN/tigervncconfig 64 \
- --slave \
- $MAN/vncconfig.1.gz vncconfig.1.gz $MAN/tigervncconfig.1.gz
-fi
-
-#DEBHELPER#
-
-exit 0
--- /dev/null
+#!/bin/sh
+
+set -e
+
+if [ "$1" = "configure" ]; then
+ MAN=/usr/share/man
+ BIN=/usr/bin
+ SBIN=/usr/sbin
+ LIB=/usr/lib/@DEB_HOST_MULTIARCH@
+ update-alternatives --install \
+ $SBIN/vncsession vncsession $SBIN/tigervncsession 64 \
+ --slave \
+ $LIB/vncserver vncserver $LIB/tigervncserver \
+ --slave \
+ $MAN/man8/vncsession.8.gz vncsession.8.gz $MAN/man8/tigervncsession.8.gz \
+ --slave \
+ $MAN/man8/vncserver.8.gz vncserver.8.gz $MAN/man8/tigervncserver.8.gz
+ update-alternatives --install \
+ $BIN/Xvnc Xvnc $BIN/Xtigervnc 74 \
+ --slave \
+ $MAN/man1/Xvnc.1.gz Xvnc.1.gz $MAN/man1/Xtigervnc.1.gz
+ update-alternatives --install \
+ $BIN/x0vncserver x0vncserver $BIN/x0tigervncserver 74 \
+ --slave \
+ $MAN/man1/x0vncserver.1.gz x0vncserver.1.gz $MAN/man1/x0tigervncserver.1.gz
+ update-alternatives --install \
+ $BIN/vncpasswd vncpasswd $BIN/tigervncpasswd 74 \
+ --slave \
+ $MAN/man1/vncpasswd.1.gz vncpasswd.1.gz $MAN/man1/tigervncpasswd.1.gz
+ update-alternatives --install \
+ $BIN/vncconfig vncconfig $BIN/tigervncconfig 64 \
+ --slave \
+ $MAN/man1/vncconfig.1.gz vncconfig.1.gz $MAN/man1/tigervncconfig.1.gz
+fi
+
+#DEBHELPER#
+
+exit 0
if [ "$1" = "remove" ] ; then
BIN=/usr/bin
+ SBIN=/usr/sbin
update-alternatives --remove \
- vncserver $BIN/tigervncserver
+ vncsession $SBIN/tigervncsession
update-alternatives --remove \
Xvnc $BIN/Xtigervnc
update-alternatives --remove \
+++ /dev/null
-diff -up tigervnc-1.3.0/unix/vncserver.shebang tigervnc-1.3.0/unix/vncserver
---- tigervnc-1.3.0/unix/vncserver.shebang 2013-07-24 12:22:34.962158378 +0100
-+++ tigervnc-1.3.0/unix/vncserver 2013-07-24 12:22:41.593188190 +0100
-@@ -1,4 +1,4 @@
--#!/usr/bin/env perl
-+#!/usr/bin/perl
- #
- # Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved.
- # Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
Provides: tightvnc = 1.5.0-0.15.20090204svn3586
Obsoletes: tightvnc < 1.5.0-0.15.20090204svn3586
-Patch17: tigervnc-shebang.patch
-
%description
Virtual Network Computing (VNC) is a remote display system which
allows you to view a computing 'desktop' environment not only on the
patch -p1 -b --suffix .vnc < ../xserver120.patch
popd
-# Don't use shebang in vncserver script.
-%patch17 -p1 -b .shebang
-
%build
%ifarch sparcv9 sparc64 s390 s390x
export CFLAGS="$RPM_OPT_FLAGS -fPIC"
%files server
%defattr(-,root,root,-)
+%config(noreplace) %{_sysconfdir}/pam.d/tigervnc
%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-defaults
%config(noreplace) %{_sysconfdir}/tigervnc/vncserver-config-mandatory
+%config(noreplace) %{_sysconfdir}/tigervnc/vncserver.users
%{_unitdir}/vncserver@.service
%{_bindir}/x0vncserver
-%{_bindir}/vncserver
-%{_mandir}/man1/vncserver.1*
+%{_sbindir}/vncsession
+%{_libexecdir}/vncserver
+%{_libexecdir}/vncsession-start
%{_mandir}/man1/x0vncserver.1*
+%{_mandir}/man8/vncserver.8*
+%{_mandir}/man8/vncsession.8*
%files server-minimal
%defattr(-,root,root,-)
.SH SEE ALSO
.BR vncpasswd (1),
.BR vncviewer (1),
-.BR vncserver (1),
-.BR Xvnc (1)
+.BR Xvnc (1),
+.BR vncsession (8)
.br
https://www.tigervnc.org
.SH SEE ALSO
.BR vncviewer (1),
-.BR vncserver (1),
.BR Xvnc (1)
.BR vncconfig (1),
+.BR vncsession (8)
.br
https://www.tigervnc.org
+add_executable(vncsession vncsession.c)
+target_link_libraries(vncsession ${PAM_LIBS})
+
configure_file(vncserver@.service.in vncserver@.service @ONLY)
+configure_file(vncsession-start.in vncsession-start @ONLY)
configure_file(vncserver.in vncserver @ONLY)
-install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncserver DESTINATION ${BIN_DIR})
-install(FILES vncserver.man DESTINATION ${MAN_DIR}/man1 RENAME vncserver.1)
+install(TARGETS vncsession DESTINATION ${SBIN_DIR})
+install(FILES tigervnc.pam DESTINATION ${SYSCONF_DIR}/pam.d RENAME tigervnc)
+install(FILES vncsession.man DESTINATION ${MAN_DIR}/man8 RENAME vncsession.8)
+install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncserver DESTINATION ${LIBEXEC_DIR})
+install(FILES vncserver.man DESTINATION ${MAN_DIR}/man8 RENAME vncserver.8)
install(FILES vncserver-config-defaults vncserver-config-mandatory DESTINATION ${SYSCONF_DIR}/tigervnc)
+install(FILES vncserver.users DESTINATION ${SYSCONF_DIR}/tigervnc)
+
if(INSTALL_SYSTEMD_UNITS)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/vncserver@.service DESTINATION ${UNIT_DIR})
+ install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/vncsession-start DESTINATION ${LIBEXEC_DIR})
endif()
--- /dev/null
+#%PAM-1.0
+# pam_selinux.so close should be the first session rule
+-session required pam_selinux.so close
+session required pam_loginuid.so
+-session required pam_selinux.so open
+session required pam_namespace.so
+session optional pam_keyinit.so force revoke
+session required pam_limits.so
+-session optional pam_systemd.so
+session required pam_unix.so
+-session optional pam_reauthorize.so prepare
if (!&CheckDisplayNumber($displayNumber)) {
die "A VNC server is already running as :$displayNumber\n";
}
-} elsif (@ARGV == 0) {
- $displayNumber = &GetDisplayNumber();
} else {
&Usage();
}
LoadConfig($vncSystemConfigMandatoryFile, 1);
#
-# Check whether VNC authentication is enabled, and if so, prompt the user to
-# create a VNC password if they don't already have one.
+# Check whether VNC authentication is enabled, and if so, check that
+# a VNC password has been created.
#
$securityTypeArgSpecified = 0;
if ((!$securityTypeArgSpecified || $vncAuthEnabled) && !$passwordArgSpecified) {
($z,$z,$mode) = stat("$vncUserDir/passwd");
if (!(-e "$vncUserDir/passwd") || ($mode & 077)) {
- warn "\nYou will require a password to access your desktops.\n\n";
- system($exedir."vncpasswd -q $vncUserDir/passwd");
- if (($? >> 8) != 0) {
- exit 1;
- }
+ die "VNC authentication enabled, but no password file created.\n";
}
}
-$desktopLog = "$vncUserDir/$host:$displayNumber.log";
-unlink($desktopLog);
-
#
# Find a desktop session to run
#
warn "Starting desktop session $sessionname\n";
-warn "Log file is $desktopLog\n\n";
-
-open STDOUT, "> $desktopLog"
-open STDERR, ">&STDOUT"
-
exec(@cmd);
die "Failed to start session.\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+0; # Bruce Mah's workaround for bug in perl 5.005_02
- }
- }
-
- die "$prog: no free display number on $host.\n";
-}
-
-
#
# Load a session desktop file
#
sub Usage
{
- die("\nusage: $prog [:<number>]\n\n");
+ die("\nusage: $prog <display>\n\n");
}
-.TH vncserver 1 "" "TigerVNC" "Virtual Network Computing"
-.SH NAME
-vncserver \- start a VNC server
-.SH SYNOPSIS
-.B vncserver
-.RI [: display# ]
-.SH DESCRIPTION
-.B vncserver
-is used to start a VNC (Virtual Network Computing) desktop.
-.B vncserver
-is a Perl script which simplifies the process of starting an Xvnc server. It
-runs Xvnc with appropriate options and starts a window manager on the VNC
-desktop.
-
-.B vncserver
-can be run with no options at all. In this case it will choose the first
-available display number (usually :1), start Xvnc with that display number,
-and start the default window manager in the Xvnc session. You can also
-specify the display number, in which case vncserver will attempt to start
-Xvnc with that display number and exit if the display number is not
-available. For example:
-
-.RS
-vncserver :13
-.RE
-
-vncserver will exit once the started session exits.
-
-.SH FILES
-Several VNC-related files are found in the directory $HOME/.vnc:
-.TP
-/etc/tigervnc/vncserver-config-defaults
-The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
-and defines options to be passed to Xvnc, they will be used as defaults for
-users. The user's $HOME/.vnc/config overrides settings configured in this file.
-The overall configuration file load order is: this file, $HOME/.vnc/config,
-and then /etc/tigervnc/vncserver-config-mandatory. None are required to exist.
-.TP
-/etc/tigervnc/vncserver-config-mandatory
-The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
-and defines options to be passed to Xvnc, they will override any of the same
-options defined in a user's $HOME/.vnc/config. This file offers a mechanism
-to establish some basic form of system-wide policy. WARNING! There is
-nothing stopping users from constructing their own vncserver-like script
-that calls Xvnc directly to bypass any options defined in
-/etc/tigervnc/vncserver-config-mandatory. The overall configuration file load
-order is: /etc/tigervnc/vncserver-config-defaults, $HOME/.vnc/config, and then
-this file. None are required to exist.
-.TP
-$HOME/.vnc/config
-An optional server config file wherein options to be passed to Xvnc are listed
-to avoid hard-coding them to the physical invocation. List options in this file
-one per line. For those requiring an argument, simply separate the option from
-the argument with an equal sign, for example: "geometry=2000x1200" or
-"securitytypes=vncauth,tlsvnc". Options without an argument are simply listed
-as a single word, for example: "localhost" or "alwaysshared".
-
-The special option
-.B session
-can be used to control which session type will be started. This should match
-one of the files in \fI/usr/share/xsessions\fP. E.g. if there is a file called
-"gnome.desktop", then "session=gnome" would be set to use that session type.
-.TP
-$HOME/.vnc/passwd
-The VNC password file.
-.TP
-$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.log
-The log file for Xvnc and the session.
-
-.SH SEE ALSO
-.BR vncviewer (1),
-.BR vncpasswd (1),
-.BR vncconfig (1),
-.BR Xvnc (1)
-.br
-https://www.tigervnc.org
-
-.SH AUTHOR
-Tristan Richardson, RealVNC Ltd., D. R. Commander and others.
-
-VNC was originally developed by the RealVNC team while at Olivetti
-Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
-implemented by Constantin Kaplinsky. Many other people have since
-participated in development, testing and support. This manual is part
-of the TigerVNC software suite.
+.so man8/vncsession.8
--- /dev/null
+# TigerVNC User assignment
+#
+# This file assigns users to specific VNC display numbers.
+# The syntax is <display>=<username>. E.g.:
+#
+# :2=andrew
+# :3=lisa
+
# The vncserver service unit file
#
# Quick HowTo:
-# 1. Copy this file to /etc/systemd/system/vncserver@.service
-# 2. Switches for vncserver should be entered in ~/.vnc/config rather than
-# hard-coded into this unit file. See the vncserver(1) manpage.
-# 3. Replace <USER> with the desired user
-# ("runuser -l <USER> -c /usr/bin/vncserver %i")
-# 4. Run `systemctl daemon-reload`
-# 5. Run `systemctl enable vncserver@:<display>.service`
+# 1. Add a user mapping to /etc/tigervnc/vncserver.users.
+# 2. Adjust the global or user configuration. See the
+# vncsession(8) manpage for details. (OPTIONAL)
+# 3. Run `systemctl enable vncserver@:<display>.service`
+# 4. Run `systemctl start vncserver@:<display>.service`
#
# DO NOT RUN THIS SERVICE if your local area network is
# untrusted! For a secure way of using VNC, you should
# You can then point a VNC client on hostA at vncdisplay N of localhost and with
# the help of ssh, you end up seeing what hostB makes available on port 590M
#
-# Use "-nolisten tcp" to prevent X connections to your VNC server via TCP.
+# Use "nolisten=tcp" to prevent X connections to your VNC server via TCP.
#
-# Use "-localhost" to prevent remote VNC clients connecting except when
+# Use "localhost" to prevent remote VNC clients connecting except when
# doing so through a secure tunnel. See the "-via" option in the
# `man vncviewer' manual page.
[Service]
Type=forking
-# Clean any existing files in /tmp/.X11-unix environment
-ExecStartPre=/bin/sh -c '@BIN_DIR@/vncserver -kill %i > /dev/null 2>&1 || :'
-ExecStart=/usr/sbin/runuser -l <USER> -c "@BIN_DIR@/vncserver %i"
-PIDFile=/home/<USER>/.vnc/%H%i.pid
-ExecStop=/bin/sh -c '@BIN_DIR@/vncserver -kill %i > /dev/null 2>&1 || :'
+ExecStart=/usr/libexec/vncsession-start %i
+PIDFile=/var/run/vncsession-%i.pid
[Install]
WantedBy=multi-user.target
--- /dev/null
+#!/bin/bash
+#
+# Copyright 2019 Pierre Ossman for Cendio AB
+#
+# 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.
+#
+
+USERSFILE="@SYSCONF_DIR@/tigervnc/vncserver.users"
+
+if [ $# -ne 1 ]; then
+ echo "Syntax:" >&2
+ echo " $0 <display>" >&2
+ exit 1
+fi
+
+if [ ! -f "${USERSFILE}" ]; then
+ echo "Users file ${USERSFILE} missing" >&2
+ exit 1
+fi
+
+DISPLAY="$1"
+
+USER=`grep "^${DISPLAY}=" "${USERSFILE}" 2>/dev/null | head -1 | cut -d = -f 2-`
+
+if [ -z "${USER}" ]; then
+ echo "No user configured for display ${DISPLAY}" >&2
+ exit 1
+fi
+
+exec "@SBIN_DIR@/vncsession" "${USER}" "${DISPLAY}"
--- /dev/null
+/*
+ * Copyright 2018 Pierre Ossman for Cendio AB
+ *
+ * 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.
+ */
+
+#include <config.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <grp.h>
+#include <limits.h>
+#include <pwd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <security/pam_appl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+extern char **environ;
+
+// PAM service name
+const char *SERVICE_NAME = "tigervnc";
+
+// Main script PID
+volatile static pid_t script = -1;
+
+// Daemon completion pipe
+int daemon_pipe_fd = -1;
+
+static int
+begin_daemon(void)
+{
+ int devnull, fds[2];
+ pid_t pid;
+
+ /* Pipe to report startup success */
+ if (pipe(fds) < 0) {
+ perror("pipe");
+ return -1;
+ }
+
+ /* First fork */
+ pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ return -1;
+ }
+
+ if (pid != 0) {
+ ssize_t len;
+ char buf[1];
+
+ close(fds[1]);
+
+ /* Wait for child to finish startup */
+ len = read(fds[0], buf, 1);
+ if (len != 1) {
+ fprintf(stderr, "Failure daemonizing\n");
+ _exit(EX_OSERR);
+ }
+
+ _exit(0);
+ }
+
+ close(fds[0]);
+ daemon_pipe_fd = fds[1];
+
+ /* Detach from terminal */
+ if (setsid() < 0) {
+ perror("setsid");
+ return -1;
+ }
+
+ /* Another fork required to fully detach */
+ pid = fork();
+ if (pid < 0) {
+ perror("fork");
+ return -1;
+ }
+
+ if (pid == 0)
+ _exit(0);
+
+ /* Send all stdio to /dev/null */
+ devnull = open("/dev/null", O_RDWR);
+ if (devnull < 0) {
+ fprintf(stderr, "Failed to open /dev/null: %s\n", strerror(errno));
+ return -1;
+ }
+ if ((dup2(devnull, 0) < 0) ||
+ (dup2(devnull, 1) < 0) ||
+ (dup2(devnull, 2) < 0)) {
+ perror("dup2");
+ return -1;
+ }
+ if (devnull > 2)
+ close(devnull);
+
+ /* Full control of access bits */
+ umask(0);
+
+ /* A safe working directory */
+ if (chdir("/") < 0) {
+ perror("chdir");
+ return -1;
+ }
+
+ return 0;
+}
+
+static void
+finish_daemon(void)
+{
+ write(daemon_pipe_fd, "+", 1);
+ close(daemon_pipe_fd);
+ daemon_pipe_fd = -1;
+}
+
+static void
+sighandler(int sig)
+{
+ if (script > 0) {
+ kill(script, SIGTERM);
+ }
+}
+
+static void
+setup_signals(void)
+{
+ struct sigaction act;
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = sighandler;
+ sigemptyset(&act.sa_mask);
+ act.sa_flags = 0;
+
+ sigaction(SIGHUP, &act, NULL);
+ sigaction(SIGINT, &act, NULL);
+ sigaction(SIGTERM, &act, NULL);
+ sigaction(SIGQUIT, &act, NULL);
+ sigaction(SIGPIPE, &act, NULL);
+}
+
+static int
+conv(int num_msg,
+ const struct pam_message **msg,
+ struct pam_response **resp, void *appdata_ptr)
+{
+ /* Opening a session should not require a conversation */
+ return PAM_CONV_ERR;
+}
+
+static pam_handle_t *
+run_pam(int *pamret, const char *username, const char *display)
+{
+ pam_handle_t *pamh;
+
+ /* Say hello to PAM */
+ struct pam_conv pconv;
+ pconv.conv = conv;
+ pconv.appdata_ptr = NULL;
+ *pamret = pam_start(SERVICE_NAME, username, &pconv, &pamh);
+ if (*pamret != PAM_SUCCESS) {
+ /* pam_strerror requires a pamh argument, but if pam_start
+ fails, pamh is invalid. In practice, at least the Linux
+ implementation of pam_strerror does not use the pamh
+ argument, but let's take care - avoid pam_strerror here. */
+ syslog(LOG_CRIT, "pam_start failed: %d", *pamret);
+ return NULL;
+ }
+
+ /* ConsoleKit and systemd (and possibly others) uses this to
+ determine if the session is local or not. It needs to be set to
+ something that can't be interpreted as localhost. We don't know
+ what the client's address is though, and that might change on
+ reconnects. We also don't want to set it to some text string as
+ that results in a DNS lookup with e.g. libaudit. Let's use a
+ fake IPv4 address from the documentation range. */
+ /* FIXME: This might throw an error on a IPv6-only host */
+ *pamret = pam_set_item(pamh, PAM_RHOST, "203.0.113.20");
+ if (*pamret != PAM_SUCCESS) {
+ syslog(LOG_CRIT, "pam_set_item(PAM_RHOST) failed: %d (%s)",
+ *pamret, pam_strerror(pamh, *pamret));
+ return pamh;
+ }
+
+#ifdef PAM_XDISPLAY
+ /* Let PAM modules use this to tag the session as a graphical one */
+ *pamret = pam_set_item(pamh, PAM_XDISPLAY, display);
+ /* Note: PAM_XDISPLAY is only supported by modern versions of PAM */
+ if (*pamret != PAM_BAD_ITEM && *pamret != PAM_SUCCESS) {
+ syslog(LOG_CRIT, "pam_set_item(PAM_XDISPLAY) failed: %d (%s)",
+ *pamret, pam_strerror(pamh, *pamret));
+ return pamh;
+ }
+#endif
+
+ /* Open session */
+ *pamret = pam_open_session(pamh, PAM_SILENT);
+ if (*pamret != PAM_SUCCESS) {
+ syslog(LOG_CRIT, "pam_open_session failed: %d (%s)",
+ *pamret, pam_strerror(pamh, *pamret));
+ return pamh;
+ }
+
+ return pamh;
+}
+
+static int
+stop_pam(pam_handle_t * pamh, int pamret)
+{
+ /* Close session */
+ if (pamret == PAM_SUCCESS) {
+ pamret = pam_close_session(pamh, PAM_SILENT);
+ if (pamret != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_close_session failed: %d (%s)",
+ pamret, pam_strerror(pamh, pamret));
+ }
+ }
+
+ /* If PAM was OK and we are running on a SELinux system, new
+ processes images will be executed in the root context. */
+
+ /* Say goodbye */
+ pamret = pam_end(pamh, pamret);
+ if (pamret != PAM_SUCCESS) {
+ /* avoid pam_strerror - we have no pamh. */
+ syslog(LOG_ERR, "pam_end failed: %d", pamret);
+ return EX_OSERR;
+ }
+ return pamret;
+}
+
+static char **
+prepare_environ(pam_handle_t * pamh)
+{
+ char **pam_env, **child_env, **entry;
+ int orig_count, pam_count;
+
+ /* This function merges the normal environment with PAM's changes */
+
+ pam_env = pam_getenvlist(pamh);
+ if (pam_env == NULL)
+ return NULL;
+
+ /*
+ * Worst case scenario is that PAM only adds variables, so allocate
+ * based on that assumption.
+ */
+ orig_count = 0;
+ for (entry = environ; *entry != NULL; entry++)
+ orig_count++;
+ pam_count = 0;
+ for (entry = pam_env; *entry != NULL; entry++)
+ pam_count++;
+
+ child_env = calloc(orig_count + pam_count + 1, sizeof(char *));
+ if (child_env == NULL)
+ return NULL;
+
+ memcpy(child_env, environ, sizeof(char *) * orig_count);
+ for (entry = child_env; *entry != NULL; entry++) {
+ *entry = strdup(*entry);
+ if (*entry == NULL) // FIXME: cleanup
+ return NULL;
+ }
+
+ for (entry = pam_env; *entry != NULL; entry++) {
+ size_t varlen;
+ char **orig_entry;
+
+ varlen = strcspn(*entry, "=") + 1;
+
+ /* Check for overwrite */
+ for (orig_entry = child_env; *orig_entry != NULL; orig_entry++) {
+ if (strncmp(*entry, *orig_entry, varlen) != 0)
+ continue;
+
+ free(*orig_entry);
+ *orig_entry = *entry;
+ break;
+ }
+
+ /* New variable? */
+ if (*orig_entry == NULL) {
+ /*
+ * orig_entry will be pointing at the terminating entry,
+ * so we can just tack it on here. The new NULL was already
+ * prepared by calloc().
+ */
+ *orig_entry = *entry;
+ }
+ }
+
+ return child_env;
+}
+
+static void
+switch_user(const char *username, uid_t uid, gid_t gid)
+{
+ // We must change group stuff first, because only root can do that.
+ if (setgid(gid) < 0) {
+ perror(": setgid");
+ _exit(EX_OSERR);
+ }
+
+ // Supplementary groups.
+ if (initgroups(username, gid) < 0) {
+ perror("initgroups");
+ _exit(EX_OSERR);
+ }
+
+ // Set euid, ruid and suid
+ if (setuid(uid) < 0) {
+ perror("setuid");
+ _exit(EX_OSERR);
+ }
+}
+
+static void
+redir_stdio(const char *homedir, const char *display)
+{
+ int fd;
+ char hostname[HOST_NAME_MAX+1];
+ char logfile[PATH_MAX];
+
+ fd = open("/dev/null", O_RDONLY);
+ if (fd == -1) {
+ perror("open");
+ _exit(EX_OSERR);
+ }
+ if (dup2(fd, 0) == -1) {
+ perror("dup2");
+ _exit(EX_OSERR);
+ }
+ close(fd);
+
+ snprintf(logfile, sizeof(logfile), "%s/.vnc", homedir);
+ if (mkdir(logfile, 0755) == -1) {
+ if (errno != EEXIST) {
+ perror("mkdir");
+ _exit(EX_OSERR);
+ }
+ }
+
+ if (gethostname(hostname, sizeof(hostname)) == -1) {
+ perror("gethostname");
+ _exit(EX_OSERR);
+ }
+
+ snprintf(logfile, sizeof(logfile), "%s/.vnc/%s%s.log",
+ homedir, hostname, display);
+ fd = open(logfile, O_CREAT | O_WRONLY | O_TRUNC, 0644);
+ if (fd == -1) {
+ perror("open");
+ _exit(EX_OSERR);
+ }
+ if ((dup2(fd, 1) == -1) || (dup2(fd, 2) == -1)) {
+ perror("dup2");
+ _exit(EX_OSERR);
+ }
+ close(fd);
+}
+
+static void
+close_fds(void)
+{
+ DIR *dir;
+ struct dirent *entry;
+
+ dir = opendir("/proc/self/fd");
+ if (dir == NULL) {
+ perror("opendir");
+ _exit(EX_OSERR);
+ }
+
+ while ((entry = readdir(dir)) != NULL) {
+ int fd;
+ fd = atoi(entry->d_name);
+ if (fd < 3)
+ continue;
+ close(fd);
+ }
+
+ closedir(dir);
+}
+
+static pid_t
+run_script(const char *username, const char *display, char **envp)
+{
+ struct passwd *pwent;
+ pid_t pid;
+ const char *child_argv[3];
+
+ pwent = getpwnam(username);
+ if (pwent == NULL) {
+ syslog(LOG_CRIT, "getpwnam: %s", strerror(errno));
+ return -1;
+ }
+
+ pid = fork();
+ if (pid < 0) {
+ syslog(LOG_CRIT, "fork: %s", strerror(errno));
+ return pid;
+ }
+
+ /* two processes now */
+
+ if (pid > 0)
+ return pid;
+
+ /* child */
+
+ switch_user(pwent->pw_name, pwent->pw_uid, pwent->pw_gid);
+
+ close_fds();
+
+ redir_stdio(pwent->pw_dir, display);
+
+ // execvpe() is not POSIX and is missing from older glibc
+ // First clear out everything
+ while ((environ != NULL) && (*environ != NULL)) {
+ char *var, *eq;
+ var = strdup(*environ);
+ eq = strchr(var, '=');
+ if (eq)
+ *eq = '\0';
+ unsetenv(var);
+ free(var);
+ }
+
+ // Then copy over the desired environment
+ for (; *envp != NULL; envp++)
+ putenv(*envp);
+
+ // Set up some basic environment for the script
+ setenv("HOME", pwent->pw_dir, 1);
+ setenv("SHELL", pwent->pw_shell, 1);
+ setenv("LOGNAME", pwent->pw_name, 1);
+ setenv("USER", pwent->pw_name, 1);
+ setenv("USERNAME", pwent->pw_name, 1);
+
+ child_argv[0] = LIBEXEC_DIR "/vncserver";
+ child_argv[1] = display;
+ child_argv[2] = NULL;
+
+ execvp(child_argv[0], (char*const*)child_argv);
+
+ // execvp failed
+ perror("execvp");
+
+ _exit(EX_OSERR);
+}
+
+int
+main(int argc, char **argv)
+{
+ char pid_file[PATH_MAX];
+ FILE *f;
+
+ const char *username, *display;
+
+ if ((argc != 3) || (argv[2][0] != ':')) {
+ fprintf(stderr, "Syntax:\n");
+ fprintf(stderr, " %s <username> <display>\n", argv[0]);
+ return EX_USAGE;
+ }
+
+ username = argv[1];
+ display = argv[2];
+
+ if (geteuid() != 0) {
+ fprintf(stderr, "This program needs to be run as root!\n");
+ return EX_USAGE;
+ }
+
+ if (getpwnam(username) == NULL) {
+ if (errno == 0)
+ fprintf(stderr, "User \"%s\" does not exist\n", username);
+ else
+ fprintf(stderr, "Cannot look up user \"%s\": %s\n",
+ username, strerror(errno));
+ return EX_OSERR;
+ }
+
+ if (begin_daemon() == -1)
+ return EX_OSERR;
+
+ openlog("vncsession", LOG_PID, LOG_AUTH);
+
+ /* Indicate that this is a graphical user session. We need to do
+ this here before PAM as pam_systemd.so looks at these. */
+ if ((putenv("XDG_SESSION_CLASS=user") < 0) ||
+ (putenv("XDG_SESSION_TYPE=x11") < 0)) {
+ syslog(LOG_CRIT, "putenv: %s", strerror(errno));
+ return EX_OSERR;
+ }
+
+ /* Init PAM */
+ int pamret;
+ pam_handle_t *pamh = run_pam(&pamret, username, display);
+ if (!pamh) {
+ return EX_OSERR;
+ }
+ if (pamret != PAM_SUCCESS) {
+ stop_pam(pamh, pamret);
+ return EX_OSERR;
+ }
+
+ char **child_env;
+ child_env = prepare_environ(pamh);
+ if (child_env == NULL) {
+ syslog(LOG_CRIT, "Failure creating child process environment");
+ stop_pam(pamh, pamret);
+ return EX_OSERR;
+ }
+
+ setup_signals();
+
+ script = run_script(username, display, child_env);
+ if (script == -1) {
+ syslog(LOG_CRIT, "Failure starting vncserver script");
+ stop_pam(pamh, pamret);
+ return EX_OSERR;
+ }
+
+ snprintf(pid_file, sizeof(pid_file),
+ "/var/run/vncsession-%s.pid", display);
+ f = fopen(pid_file, "w");
+ if (f == NULL) {
+ syslog(LOG_ERR, "Failure creating pid file \"%s\": %s",
+ pid_file, strerror(errno));
+ } else {
+ fprintf(f, "%ld\n", (long)getpid());
+ fclose(f);
+ }
+
+ finish_daemon();
+
+ while (1) {
+ int status;
+ pid_t gotpid = waitpid(script, &status, 0);
+ if (gotpid < 0) {
+ if (errno != EINTR) {
+ syslog(LOG_CRIT, "waitpid: %s", strerror(errno));
+ exit(EXIT_FAILURE);
+ }
+ continue;
+ }
+ if (WIFEXITED(status)) {
+ if (WEXITSTATUS(status) != 0) {
+ syslog(LOG_WARNING,
+ "vncsession: vncserver exited with status=%d",
+ WEXITSTATUS(status));
+ }
+ break;
+ }
+ else if (WIFSIGNALED(status)) {
+ syslog(LOG_WARNING,
+ "vncsession: vncserver was terminated by signal %d",
+ WTERMSIG(status));
+ break;
+ }
+ }
+
+ unlink(pid_file);
+
+ stop_pam(pamh, pamret);
+
+ return 0;
+}
--- /dev/null
+.TH vncsession 8 "" "TigerVNC" "Virtual Network Computing"
+.SH NAME
+vncsession \- start a VNC server
+.SH SYNOPSIS
+.B vncsession
+.RI < username >
+.RI <: display# >
+.SH DESCRIPTION
+.B vncsession
+is used to start a VNC (Virtual Network Computing) desktop.
+.B vncsession
+performs all the necessary steps to create a new user session, run Xvnc with
+appropriate options and starts a window manager on the VNC desktop.
+
+.B vncsession
+is rarely called directly and is normally started by the system service
+manager.
+
+.SH FILES
+Several VNC-related files are found in the directory $HOME/.vnc:
+.TP
+/etc/tigervnc/vncserver-config-defaults
+The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
+and defines options to be passed to Xvnc, they will be used as defaults for
+users. The user's $HOME/.vnc/config overrides settings configured in this file.
+The overall configuration file load order is: this file, $HOME/.vnc/config,
+and then /etc/tigervnc/vncserver-config-mandatory. None are required to exist.
+.TP
+/etc/tigervnc/vncserver-config-mandatory
+The optional system-wide equivalent of $HOME/.vnc/config. If this file exists
+and defines options to be passed to Xvnc, they will override any of the same
+options defined in a user's $HOME/.vnc/config. This file offers a mechanism
+to establish some basic form of system-wide policy. WARNING! There is
+nothing stopping users from constructing their own vncsession-like script
+that calls Xvnc directly to bypass any options defined in
+/etc/tigervnc/vncserver-config-mandatory. The overall configuration file load
+order is: /etc/tigervnc/vncserver-config-defaults, $HOME/.vnc/config, and then
+this file. None are required to exist.
+.TP
+$HOME/.vnc/config
+An optional server config file wherein options to be passed to Xvnc are listed
+to avoid hard-coding them to the physical invocation. List options in this file
+one per line. For those requiring an argument, simply separate the option from
+the argument with an equal sign, for example: "geometry=2000x1200" or
+"securitytypes=vncauth,tlsvnc". Options without an argument are simply listed
+as a single word, for example: "localhost" or "alwaysshared".
+
+The special option
+.B session
+can be used to control which session type will be started. This should match
+one of the files in \fI/usr/share/xsessions\fP. E.g. if there is a file called
+"gnome.desktop", then "session=gnome" would be set to use that session type.
+.TP
+$HOME/.vnc/passwd
+The VNC password file.
+.TP
+$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.log
+The log file for Xvnc and the session.
+
+.SH SEE ALSO
+.BR vncviewer (1),
+.BR vncpasswd (1),
+.BR vncconfig (1),
+.BR Xvnc (1)
+.br
+https://www.tigervnc.org
+
+.SH AUTHOR
+Tristan Richardson, RealVNC Ltd., D. R. Commander and others.
+
+VNC was originally developed by the RealVNC team while at Olivetti
+Research Ltd / AT&T Laboratories Cambridge. TightVNC additions were
+implemented by Constantin Kaplinsky. Many other people have since
+participated in development, testing and support. This manual is part
+of the TigerVNC software suite.
number, which means you can use eg. snoopy:2 to refer to display 2 on machine
"snoopy" in both the X world and the VNC world.
-The best way of starting \fBXvnc\fP is via the \fBvncserver\fP script. This
-sets up the environment appropriately and runs some X applications to get you
-going. See the manual page for \fBvncserver\fP(1) for more information.
+The best way of starting \fBXvnc\fP is via \fBvncsession\fP. This sets up the
+environment appropriately and starts a desktop environment. See the manual
+page for \fBvncsession\fP(8) for more information.
.SH OPTIONS
.B Xvnc
.SH SEE ALSO
.BR vncconfig (1),
.BR vncpasswd (1),
-.BR vncserver (1),
.BR vncviewer (1),
+.BR vncsession (8),
.BR Xserver (1),
.BR inetd (1)
.br
.BR Xvnc (1),
.BR vncpasswd (1),
.BR vncconfig (1),
-.BR vncserver (1)
+.BR vncsession (8)
.br
https://www.tigervnc.org