From 537a39373cd0bb1867101d5adb07621c17fd0d97 Mon Sep 17 00:00:00 2001 From: Pierre Ossman Date: Fri, 27 Jul 2018 21:39:01 +0200 Subject: [PATCH] Start sessions using session desktop file This is how display managers (e.g. gdm or lightdm) start sessions and is necessary to get the proper set of environment variables. --- unix/vncserver/vncserver | 176 +++++++++++++++++++++++------------ unix/vncserver/vncserver.man | 38 +++----- 2 files changed, 126 insertions(+), 88 deletions(-) diff --git a/unix/vncserver/vncserver b/unix/vncserver/vncserver index ce45ebaf..71d47240 100755 --- a/unix/vncserver/vncserver +++ b/unix/vncserver/vncserver @@ -48,34 +48,8 @@ $vncSystemConfigDir = "/etc/tigervnc"; $vncSystemConfigDefaultsFile = "$vncSystemConfigDir/vncserver-config-defaults"; $vncSystemConfigMandatoryFile = "$vncSystemConfigDir/vncserver-config-mandatory"; -$skipxstartup = 0; $xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority"; -$xstartupFile = $vncUserDir . "/xstartup"; -$defaultXStartup - = ("#!/bin/sh\n\n". - "OS=`uname -s`\n". - "if [ \$OS = 'Linux' ]; then\n". - " case \"\$WINDOWMANAGER\" in\n". - " \*gnome\*)\n". - " if [ -e /etc/SuSE-release ]; then\n". - " PATH=\$PATH:/opt/gnome/bin\n". - " export PATH\n". - " fi\n". - " ;;\n". - " esac\n". - "fi\n". - "if [ -x /etc/X11/xinit/xinitrc ]; then\n". - " exec /etc/X11/xinit/xinitrc\n". - "fi\n". - "if [ -f /etc/X11/xinit/xinitrc ]; then\n". - " exec sh /etc/X11/xinit/xinitrc\n". - "fi\n". - "[ -r \$HOME/.Xresources ] && xrdb \$HOME/.Xresources\n". - "xsetroot -solid grey\n". - "xterm -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n". - "twm\n"); - chop($host = `uname -n`); if (-d "/etc/X11/fontpath.d") { @@ -117,7 +91,7 @@ if ($fontPath eq "") { # Check command line options &ParseOptions("-kill",1,"-help",0,"-h",0,"--help",0,"-list",0, - "-fg",0,"-autokill",0,"-noxstartup",0,"-xstartup",1); + "-fg",0,"-autokill",0); &Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'}); @@ -125,13 +99,6 @@ if ($fontPath eq "") { &List() if ($opt{'-list'}); -if ($opt{'-noxstartup'}) { - $skipxstartup = 1; -} -if ($opt{'-xstartup'}) { - $xstartupFile = $opt{'-xstartup'}; -} - # Create the user's vnc directory if necessary. if (!(-e $vncUserDir)) { if (!mkdir($vncUserDir,0755)) { @@ -223,6 +190,52 @@ if ((!$securityTypeArgSpecified || $vncAuthEnabled) && !$passwordArgSpecified) { $desktopLog = "$vncUserDir/$host:$displayNumber.log"; unlink($desktopLog); +# +# Find a desktop session to run +# + +my $sessionname; +my %session; + +$sessionname = delete $config{'session'}; + +if ($sessionname) { + %session = LoadXSession($sessionname); + if (!%session) { + warn "Could not load configured desktop session $sessionname\n"; + $sessionname = undef; + } +} + +if (!$sessionname) { + foreach $file (glob("/usr/share/xsessions/*.desktop")) { + ($name) = $file =~ /^.*\/(.*)[.]desktop$/; + %session = LoadXSession($name); + if (%session) { + $sessionname = $name; + last; + } + } +} + +if (!$sessionname) { + die "Could not find a desktop session to run\n"; +} + +warn "Using desktop session $sessionname\n"; + +if (!$session{'Exec'}) { + die "No command specified for desktop session\n"; +} + +$ENV{GDMSESSION} = $sessionname; +$ENV{DESKTOP_SESSION} = $sessionname; +$ENV{XDG_SESSION_DESKTOP} = $sessionname; + +if ($session{'DesktopNames'}) { + $ENV{XDG_DESKTOP_NAMES} = $session{'DesktopNames'} =~ s/;/:/gr; +} + # Make an X server cookie and set up the Xauthority file # mcookie is a part of util-linux, usually only GNU/Linux systems have it. $cookie = `mcookie`; @@ -298,21 +311,9 @@ unless (kill 0, `cat $pidFile`) { warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n"; -# Create the user's xstartup script if necessary. -if (! $skipxstartup) { - if (!(-e "$xstartupFile")) { - warn "Creating default startup script $xstartupFile\n"; - open(XSTARTUP, ">$xstartupFile"); - print XSTARTUP $defaultXStartup; - close(XSTARTUP); - chmod 0755, "$xstartupFile"; - } -} - # Run the X startup script. -if (! $skipxstartup) { - warn "Starting applications specified in $xstartupFile\n"; -} +warn "Starting desktop session $sessionname\n"; + warn "Log file is $desktopLog\n\n"; # If the unix domain socket exists then use that (DISPLAY=:n) otherwise use @@ -328,24 +329,16 @@ if (-e "/tmp/.X11-unix/X$displayNumber" || $ENV{VNCDESKTOP}= $desktopName; if ($opt{'-fg'}) { - if (! $skipxstartup) { - system("$xstartupFile >> " . "edString($desktopLog) . " 2>&1"); - } + system("$Xsession $session{'Exec'} >> " . "edString($desktopLog) . " 2>&1"); if (kill 0, `cat $pidFile`) { $opt{'-kill'} = ':'.$displayNumber; &Kill(); } } else { if ($opt{'-autokill'}) { - if (! $skipxstartup) { - system("($xstartupFile; $0 -kill :$displayNumber) >> " - . "edString($desktopLog) . " 2>&1 &"); - } + system("$Xsession $session{'Exec'}; $0 -kill :$displayNumber) >> " . "edString($desktopLog) . " 2>&1 &"); } else { - if (! $skipxstartup) { - system("$xstartupFile >> " . "edString($desktopLog) - . " 2>&1 &"); - } + system("$Xsession $session{'Exec'} >> " . "edString($desktopLog) . " 2>&1 &"); } } @@ -410,6 +403,59 @@ sub GetDisplayNumber } +# +# Load a session desktop file +# +sub LoadXSession { + local ($name) = @_; + my $file, $found_group, %session; + + $file = "/usr/share/xsessions/$name.desktop"; + + if (!stat($file)) { + warn "Could not find session desktop file $file"; + return; + } + + if (!open(IN, $file)) { + warn "Could not open session desktop file $file"; + return; + } + + $found_group = 0; + while (my $line = ) { + next if $line =~ /^#/; + next if $line =~ /^\s*$/; + + if (!$found_group) { + next if $line != "[Desktop Entry]"; + $found_group = 1; + next; + } else { + last if $line =~ /^\[/; + } + + my ($key, $value) = $line =~ /^\s*([]A-Za-z0-9_@\-\[]+)\s*=\s*(.*)$/; + if (!$key) { + warn "Invalid session desktop file $file"; + close(IN); + return; + } + + $value =~ s/\\s/ /g; + $value =~ s/\\n/\n/g; + $value =~ s/\\t/\t/g; + $value =~ s/\\r/\r/g; + $value =~ s/\\\\/\\/g; + + $session{$key} = $value; + } + + close(IN); + + return %session; +} + # # CheckDisplayNumber checks if the given display number is available. A # display number n is taken if something is listening on the VNC server port @@ -496,8 +542,6 @@ sub Usage die("\nusage: $prog [:]\n". " [-fg]\n". " [-autokill]\n". - " [-noxstartup]\n". - " [-xstartup ]\n". "\n". " $prog -kill \n\n". " $prog -list\n\n"); @@ -653,6 +697,16 @@ sub SanityCheck die "$prog: couldn't find \"$cmd\" on your PATH.\n"; } + foreach $cmd ("/etc/X11/xinit/Xsession", "/etc/X11/Xsession") { + if (-x "$cmd") { + $Xsession = $cmd; + last; + } + } + if (not defined $Xsession) { + die "$prog: Couldn't find suitable Xsession.\n"; + } + if($exedir eq "") { cmd2: foreach $cmd ("Xvnc","vncpasswd") { diff --git a/unix/vncserver/vncserver.man b/unix/vncserver/vncserver.man index 9ae43185..f8ce77d5 100644 --- a/unix/vncserver/vncserver.man +++ b/unix/vncserver/vncserver.man @@ -6,9 +6,6 @@ vncserver \- start or stop a VNC server .RI [: display# ] .RB [ \-fg ] .RB [ \-autokill ] -.RB [ \-noxstartup ] -.RB [ \-xstartup -.IR script ] .br .BI "vncserver \-kill :" display# .br @@ -33,9 +30,6 @@ available. For example: vncserver :13 .RE -Editing the file $HOME/.vnc/xstartup allows you to change the applications run -at startup (but note that this will not affect an existing VNC session.) - .SH OPTIONS You can get a list of options by passing \fB\-h\fP as an option to vncserver. @@ -46,8 +40,8 @@ killing the Xvnc process, whose process ID is stored in the file "$HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.pid". The .B \-kill option ignores anything preceding the first colon (":") in the display -argument. Thus, you can invoke "vncserver \-kill $DISPLAY", for example at the -end of your xstartup file after a particular application exits. +argument. Thus, you can invoke "vncserver \-kill $DISPLAY", for example +inside your session to terminate it. . .TP .B \-fg @@ -58,19 +52,8 @@ when launching TigerVNC from within certain grid computing environments. . .TP .B \-autokill -Automatically kill Xvnc whenever the xstartup script exits. In most cases, -this has the effect of terminating Xvnc when the user logs out of the window -manager. -. -.TP -.B \-noxstartup -Do not run the %HOME/.vnc/xstartup script after launching Xvnc. This -option allows you to manually start a window manager in your TigerVNC session. -. -.TP -.B \-xstartup \fIscript\fP -Run a custom startup script, instead of %HOME/.vnc/xstartup, after launching -Xvnc. This is useful to run full-screen applications. +Automatically kill Xvnc whenever the session exits. In most cases, this has +the effect of terminating Xvnc when the user logs out of the window manager. . .TP .B \-list @@ -79,11 +62,6 @@ Lists all VNC desktops started by vncserver. .SH FILES Several VNC-related files are found in the directory $HOME/.vnc: .TP -$HOME/.vnc/xstartup -A shell script specifying X applications to be run when a VNC desktop is -started. If this file does not exist, then vncserver will create a default -xstartup script which attempts to launch your chosen window manager. -.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 @@ -109,12 +87,18 @@ 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 applications started in xstartup. +The log file for Xvnc and the session. .TP $HOME/.vnc/\fIhost\fP:\fIdisplay#\fP.pid Identifies the Xvnc process ID, used by the -- 2.39.5