| @@ -1,898 +1,899 @@ | | | @@ -1,898 +1,899 @@ |
1 | #!/usr/bin/env perl | | 1 | #!/usr/bin/env perl |
2 | # | | 2 | # |
3 | # Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved. | | 3 | # Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved. |
4 | # Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved. | | 4 | # Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved. |
5 | # Copyright (C) 2002-2003 Constantin Kaplinsky. All Rights Reserved. | | 5 | # Copyright (C) 2002-2003 Constantin Kaplinsky. All Rights Reserved. |
6 | # Copyright (C) 2002-2005 RealVNC Ltd. | | 6 | # Copyright (C) 2002-2005 RealVNC Ltd. |
7 | # Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. | | 7 | # Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved. |
8 | # | | 8 | # |
9 | # This is free software; you can redistribute it and/or modify | | 9 | # This is free software; you can redistribute it and/or modify |
10 | # it under the terms of the GNU General Public License as published by | | 10 | # it under the terms of the GNU General Public License as published by |
11 | # the Free Software Foundation; either version 2 of the License, or | | 11 | # the Free Software Foundation; either version 2 of the License, or |
12 | # (at your option) any later version. | | 12 | # (at your option) any later version. |
13 | # | | 13 | # |
14 | # This software is distributed in the hope that it will be useful, | | 14 | # This software is distributed in the hope that it will be useful, |
15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | | 15 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | | 16 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
17 | # GNU General Public License for more details. | | 17 | # GNU General Public License for more details. |
18 | # | | 18 | # |
19 | # You should have received a copy of the GNU General Public License | | 19 | # You should have received a copy of the GNU General Public License |
20 | # along with this software; if not, write to the Free Software | | 20 | # along with this software; if not, write to the Free Software |
21 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, | | 21 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, |
22 | # USA. | | 22 | # USA. |
23 | # | | 23 | # |
24 | | | 24 | |
25 | # | | 25 | # |
26 | # vncserver - wrapper script to start an X VNC server. | | 26 | # vncserver - wrapper script to start an X VNC server. |
27 | # | | 27 | # |
28 | | | 28 | |
29 | # First make sure we're operating in a sane environment. | | 29 | # First make sure we're operating in a sane environment. |
30 | $exedir = ""; | | 30 | $exedir = ""; |
31 | $slashndx = rindex($0, "/"); | | 31 | $slashndx = rindex($0, "/"); |
32 | if($slashndx>=0) { | | 32 | if($slashndx>=0) { |
33 | $exedir = substr($0, 0, $slashndx+1); | | 33 | $exedir = substr($0, 0, $slashndx+1); |
34 | } | | 34 | } |
35 | | | 35 | |
36 | &SanityCheck(); | | 36 | &SanityCheck(); |
37 | | | 37 | |
38 | # | | 38 | # |
39 | # Global variables. You may want to configure some of these for | | 39 | # Global variables. You may want to configure some of these for |
40 | # your site | | 40 | # your site |
41 | # | | 41 | # |
42 | | | 42 | |
43 | $geometry = "1024x768"; | | 43 | $geometry = "1024x768"; |
44 | #$depth = 16; | | 44 | #$depth = 16; |
45 | | | 45 | |
46 | $vncUserDir = "$ENV{HOME}/.vnc"; | | 46 | $vncUserDir = "$ENV{HOME}/.vnc"; |
47 | $vncUserConfig = "$vncUserDir/config"; | | 47 | $vncUserConfig = "$vncUserDir/config"; |
48 | | | 48 | |
49 | $vncSystemConfigDir = "/etc/tigervnc"; | | 49 | $vncSystemConfigDir = "/etc/tigervnc"; |
50 | $vncSystemConfigDefaultsFile = "$vncSystemConfigDir/vncserver-config-defaults"; | | 50 | $vncSystemConfigDefaultsFile = "$vncSystemConfigDir/vncserver-config-defaults"; |
51 | $vncSystemConfigMandatoryFile = "$vncSystemConfigDir/vncserver-config-mandatory"; | | 51 | $vncSystemConfigMandatoryFile = "$vncSystemConfigDir/vncserver-config-mandatory"; |
52 | | | 52 | |
53 | $skipxstartup = 0; | | 53 | $skipxstartup = 0; |
54 | $xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority"; | | 54 | $xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority"; |
55 | | | 55 | |
56 | $xstartupFile = $vncUserDir . "/xstartup"; | | 56 | $xstartupFile = $vncUserDir . "/xstartup"; |
57 | $defaultXStartup | | 57 | $defaultXStartup |
58 | = ("#!/bin/sh\n\n". | | 58 | = ("#!/bin/sh\n\n". |
59 | "unset SESSION_MANAGER\n". | | 59 | "unset SESSION_MANAGER\n". |
60 | "unset DBUS_SESSION_BUS_ADDRESS\n". | | 60 | "unset DBUS_SESSION_BUS_ADDRESS\n". |
61 | "OS=`uname -s`\n". | | 61 | "OS=`uname -s`\n". |
62 | "if [ \$OS = 'Linux' ]; then\n". | | 62 | "if [ \$OS = 'Linux' ]; then\n". |
63 | " case \"\$WINDOWMANAGER\" in\n". | | 63 | " case \"\$WINDOWMANAGER\" in\n". |
64 | " \*gnome\*)\n". | | 64 | " \*gnome\*)\n". |
65 | " if [ -e /etc/SuSE-release ]; then\n". | | 65 | " if [ -e /etc/SuSE-release ]; then\n". |
66 | " PATH=\$PATH:/opt/gnome/bin\n". | | 66 | " PATH=\$PATH:/opt/gnome/bin\n". |
67 | " export PATH\n". | | 67 | " export PATH\n". |
68 | " fi\n". | | 68 | " fi\n". |
69 | " ;;\n". | | 69 | " ;;\n". |
70 | " esac\n". | | 70 | " esac\n". |
71 | "fi\n". | | 71 | "fi\n". |
72 | "if [ -x /etc/X11/xinit/xinitrc ]; then\n". | | 72 | "if [ -x /etc/X11/xinit/xinitrc ]; then\n". |
73 | " exec /etc/X11/xinit/xinitrc\n". | | 73 | " exec /etc/X11/xinit/xinitrc\n". |
74 | "fi\n". | | 74 | "fi\n". |
75 | "if [ -f /etc/X11/xinit/xinitrc ]; then\n". | | 75 | "if [ -f /etc/X11/xinit/xinitrc ]; then\n". |
76 | " exec sh /etc/X11/xinit/xinitrc\n". | | 76 | " exec sh /etc/X11/xinit/xinitrc\n". |
77 | "fi\n". | | 77 | "fi\n". |
78 | "[ -r \$HOME/.Xresources ] && xrdb \$HOME/.Xresources\n". | | 78 | "[ -r \$HOME/.Xresources ] && xrdb \$HOME/.Xresources\n". |
79 | "xsetroot -solid grey\n". | | 79 | "xsetroot -solid grey\n". |
80 | "xterm -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n". | | 80 | "xterm -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n". |
81 | "twm &\n"); | | 81 | "twm &\n"); |
82 | | | 82 | |
83 | $defaultConfig | | 83 | $defaultConfig |
84 | = ("## Supported server options to pass to vncserver upon invocation can be listed\n". | | 84 | = ("## Supported server options to pass to vncserver upon invocation can be listed\n". |
85 | "## in this file. See the following manpages for more: vncserver(1) Xvnc(1).\n". | | 85 | "## in this file. See the following manpages for more: vncserver(1) Xvnc(1).\n". |
86 | "## Several common ones are shown below. Uncomment and modify to your liking.\n". | | 86 | "## Several common ones are shown below. Uncomment and modify to your liking.\n". |
87 | "##\n". | | 87 | "##\n". |
88 | "# securitytypes=vncauth,tlsvnc\n". | | 88 | "# securitytypes=vncauth,tlsvnc\n". |
89 | "# desktop=sandbox\n". | | 89 | "# desktop=sandbox\n". |
90 | "# geometry=2000x1200\n". | | 90 | "# geometry=2000x1200\n". |
91 | "# localhost\n". | | 91 | "# localhost\n". |
92 | "# alwaysshared\n"); | | 92 | "# alwaysshared\n"); |
93 | | | 93 | |
94 | chop($host = `uname -n`); | | 94 | chop($host = `uname -n`); |
95 | | | 95 | |
96 | if (-d "/etc/X11/fontpath.d") { | | 96 | if (-d "/etc/X11/fontpath.d") { |
97 | $fontPath = "catalogue:/etc/X11/fontpath.d"; | | 97 | $fontPath = "catalogue:/etc/X11/fontpath.d"; |
98 | } | | 98 | } |
99 | | | 99 | |
100 | @fontpaths = ('/usr/share/X11/fonts', '/usr/share/fonts', '/usr/share/fonts/X11/'); | | 100 | @fontpaths = ('/usr/share/X11/fonts', '/usr/share/fonts', '/usr/share/fonts/X11/'); |
101 | if (! -l "/usr/lib/X11") {push(@fontpaths, '/usr/lib/X11/fonts');} | | 101 | if (! -l "/usr/lib/X11") {push(@fontpaths, '/usr/lib/X11/fonts');} |
102 | if (! -l "/usr/X11") {push(@fontpaths, '/usr/X11/lib/X11/fonts');} | | 102 | if (! -l "/usr/X11") {push(@fontpaths, '/usr/X11/lib/X11/fonts');} |
103 | if (! -l "/usr/X11R6") {push(@fontpaths, '/usr/X11R6/lib/X11/fonts');} | | 103 | if (! -l "/usr/X11R6") {push(@fontpaths, '/usr/X11R6/lib/X11/fonts');} |
| | | 104 | if (! -l "/usr/X11R7") {push(@fontpaths, '/usr/X11R7/lib/X11/fonts');} |
104 | push(@fontpaths, '/usr/share/fonts/default'); | | 105 | push(@fontpaths, '/usr/share/fonts/default'); |
105 | | | 106 | |
106 | @fonttypes = ('misc', | | 107 | @fonttypes = ('misc', |
107 | '75dpi', | | 108 | '75dpi', |
108 | '100dpi', | | 109 | '100dpi', |
109 | 'Speedo', | | 110 | 'Speedo', |
110 | 'Type1'); | | 111 | 'Type1'); |
111 | | | 112 | |
112 | foreach $_fpath (@fontpaths) { | | 113 | foreach $_fpath (@fontpaths) { |
113 | foreach $_ftype (@fonttypes) { | | 114 | foreach $_ftype (@fonttypes) { |
114 | if (-f "$_fpath/$_ftype/fonts.dir") { | | 115 | if (-f "$_fpath/$_ftype/fonts.dir") { |
115 | if (! -l "$_fpath/$_ftype") { | | 116 | if (! -l "$_fpath/$_ftype") { |
116 | $defFontPath .= "$_fpath/$_ftype,"; | | 117 | $defFontPath .= "$_fpath/$_ftype,"; |
117 | } | | 118 | } |
118 | } | | 119 | } |
119 | } | | 120 | } |
120 | } | | 121 | } |
121 | | | 122 | |
122 | if ($defFontPath) { | | 123 | if ($defFontPath) { |
123 | if (substr($defFontPath, -1, 1) == ',') { | | 124 | if (substr($defFontPath, -1, 1) == ',') { |
124 | chop $defFontPath; | | 125 | chop $defFontPath; |
125 | } | | 126 | } |
126 | } | | 127 | } |
127 | | | 128 | |
128 | if ($fontPath eq "") { | | 129 | if ($fontPath eq "") { |
129 | $fontPath = $defFontPath; | | 130 | $fontPath = $defFontPath; |
130 | } | | 131 | } |
131 | | | 132 | |
132 | # Check command line options | | 133 | # Check command line options |
133 | | | 134 | |
134 | &ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1, | | 135 | &ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1, |
135 | "-help",0,"-h",0,"--help",0,"-fp",1,"-list",0,"-fg",0,"-autokill",0,"-noxstartup",0,"-xstartup",1); | | 136 | "-help",0,"-h",0,"--help",0,"-fp",1,"-list",0,"-fg",0,"-autokill",0,"-noxstartup",0,"-xstartup",1); |
136 | | | 137 | |
137 | &Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'}); | | 138 | &Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'}); |
138 | | | 139 | |
139 | &Kill() if ($opt{'-kill'}); | | 140 | &Kill() if ($opt{'-kill'}); |
140 | | | 141 | |
141 | &List() if ($opt{'-list'}); | | 142 | &List() if ($opt{'-list'}); |
142 | | | 143 | |
143 | # Uncomment this line if you want default geometry, depth and pixelformat | | 144 | # Uncomment this line if you want default geometry, depth and pixelformat |
144 | # to match the current X display: | | 145 | # to match the current X display: |
145 | # &GetXDisplayDefaults(); | | 146 | # &GetXDisplayDefaults(); |
146 | | | 147 | |
147 | if ($opt{'-geometry'}) { | | 148 | if ($opt{'-geometry'}) { |
148 | $geometry = $opt{'-geometry'}; | | 149 | $geometry = $opt{'-geometry'}; |
149 | } | | 150 | } |
150 | if ($opt{'-depth'}) { | | 151 | if ($opt{'-depth'}) { |
151 | $depth = $opt{'-depth'}; | | 152 | $depth = $opt{'-depth'}; |
152 | $pixelformat = ""; | | 153 | $pixelformat = ""; |
153 | } | | 154 | } |
154 | if ($opt{'-pixelformat'}) { | | 155 | if ($opt{'-pixelformat'}) { |
155 | $pixelformat = $opt{'-pixelformat'}; | | 156 | $pixelformat = $opt{'-pixelformat'}; |
156 | } | | 157 | } |
157 | if ($opt{'-noxstartup'}) { | | 158 | if ($opt{'-noxstartup'}) { |
158 | $skipxstartup = 1; | | 159 | $skipxstartup = 1; |
159 | } | | 160 | } |
160 | if ($opt{'-xstartup'}) { | | 161 | if ($opt{'-xstartup'}) { |
161 | $xstartupFile = $opt{'-xstartup'}; | | 162 | $xstartupFile = $opt{'-xstartup'}; |
162 | } | | 163 | } |
163 | if ($opt{'-fp'}) { | | 164 | if ($opt{'-fp'}) { |
164 | $fontPath = $opt{'-fp'}; | | 165 | $fontPath = $opt{'-fp'}; |
165 | $fpArgSpecified = 1; | | 166 | $fpArgSpecified = 1; |
166 | } | | 167 | } |
167 | | | 168 | |
168 | &CheckGeometryAndDepth(); | | 169 | &CheckGeometryAndDepth(); |
169 | | | 170 | |
170 | # Create the user's vnc directory if necessary. | | 171 | # Create the user's vnc directory if necessary. |
171 | if (!(-e $vncUserDir)) { | | 172 | if (!(-e $vncUserDir)) { |
172 | if (!mkdir($vncUserDir,0755)) { | | 173 | if (!mkdir($vncUserDir,0755)) { |
173 | die "$prog: Could not create $vncUserDir.\n"; | | 174 | die "$prog: Could not create $vncUserDir.\n"; |
174 | } | | 175 | } |
175 | } | | 176 | } |
176 | | | 177 | |
177 | # Find display number. | | 178 | # Find display number. |
178 | if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) { | | 179 | if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) { |
179 | $displayNumber = $1; | | 180 | $displayNumber = $1; |
180 | shift(@ARGV); | | 181 | shift(@ARGV); |
181 | if (!&CheckDisplayNumber($displayNumber)) { | | 182 | if (!&CheckDisplayNumber($displayNumber)) { |
182 | die "A VNC server is already running as :$displayNumber\n"; | | 183 | die "A VNC server is already running as :$displayNumber\n"; |
183 | } | | 184 | } |
184 | } elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/) && ($ARGV[0] !~ /^\+/)) { | | 185 | } elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/) && ($ARGV[0] !~ /^\+/)) { |
185 | &Usage(); | | 186 | &Usage(); |
186 | } else { | | 187 | } else { |
187 | $displayNumber = &GetDisplayNumber(); | | 188 | $displayNumber = &GetDisplayNumber(); |
188 | } | | 189 | } |
189 | | | 190 | |
190 | $vncPort = 5900 + $displayNumber; | | 191 | $vncPort = 5900 + $displayNumber; |
191 | | | 192 | |
192 | if ($opt{'-name'}) { | | 193 | if ($opt{'-name'}) { |
193 | $desktopName = $opt{'-name'}; | | 194 | $desktopName = $opt{'-name'}; |
194 | } else { | | 195 | } else { |
195 | $desktopName = "$host:$displayNumber ($ENV{USER})"; | | 196 | $desktopName = "$host:$displayNumber ($ENV{USER})"; |
196 | } | | 197 | } |
197 | | | 198 | |
198 | my %default_opts; | | 199 | my %default_opts; |
199 | my %config; | | 200 | my %config; |
200 | | | 201 | |
201 | # We set some reasonable defaults. Config file settings | | 202 | # We set some reasonable defaults. Config file settings |
202 | # override these where present. | | 203 | # override these where present. |
203 | $default_opts{desktop} = "edString($desktopName); | | 204 | $default_opts{desktop} = "edString($desktopName); |
204 | $default_opts{auth} = "edString($xauthorityFile); | | 205 | $default_opts{auth} = "edString($xauthorityFile); |
205 | $default_opts{geometry} = $geometry if ($geometry); | | 206 | $default_opts{geometry} = $geometry if ($geometry); |
206 | $default_opts{depth} = $depth if ($depth); | | 207 | $default_opts{depth} = $depth if ($depth); |
207 | $default_opts{pixelformat} = $pixelformat if ($pixelformat); | | 208 | $default_opts{pixelformat} = $pixelformat if ($pixelformat); |
208 | $default_opts{rfbwait} = 30000; | | 209 | $default_opts{rfbwait} = 30000; |
209 | $default_opts{rfbauth} = "$vncUserDir/passwd"; | | 210 | $default_opts{rfbauth} = "$vncUserDir/passwd"; |
210 | $default_opts{rfbport} = $vncPort; | | 211 | $default_opts{rfbport} = $vncPort; |
211 | $default_opts{fp} = $fontPath if ($fontPath); | | 212 | $default_opts{fp} = $fontPath if ($fontPath); |
212 | $default_opts{pn} = ""; | | 213 | $default_opts{pn} = ""; |
213 | | | 214 | |
214 | # Load user-overrideable system defaults | | 215 | # Load user-overrideable system defaults |
215 | LoadConfig($vncSystemConfigDefaultsFile); | | 216 | LoadConfig($vncSystemConfigDefaultsFile); |
216 | | | 217 | |
217 | # Then the user's settings | | 218 | # Then the user's settings |
218 | LoadConfig($vncUserConfig); | | 219 | LoadConfig($vncUserConfig); |
219 | | | 220 | |
220 | # And then override anything set above if mandatory settings exist. | | 221 | # And then override anything set above if mandatory settings exist. |
221 | # WARNING: "Mandatory" is used loosely here! As the man page says, | | 222 | # WARNING: "Mandatory" is used loosely here! As the man page says, |
222 | # there is nothing stopping someone from EASILY subverting the | | 223 | # there is nothing stopping someone from EASILY subverting the |
223 | # settings in $vncSystemConfigMandatoryFile by simply passing | | 224 | # settings in $vncSystemConfigMandatoryFile by simply passing |
224 | # CLI args to vncserver, which trump config files! To properly | | 225 | # CLI args to vncserver, which trump config files! To properly |
225 | # hard force policy in a non-subvertible way would require major | | 226 | # hard force policy in a non-subvertible way would require major |
226 | # development work that touches Xvnc itself. | | 227 | # development work that touches Xvnc itself. |
227 | LoadConfig($vncSystemConfigMandatoryFile, 1); | | 228 | LoadConfig($vncSystemConfigMandatoryFile, 1); |
228 | | | 229 | |
229 | # | | 230 | # |
230 | # Check whether VNC authentication is enabled, and if so, prompt the user to | | 231 | # Check whether VNC authentication is enabled, and if so, prompt the user to |
231 | # create a VNC password if they don't already have one. | | 232 | # create a VNC password if they don't already have one. |
232 | # | | 233 | # |
233 | | | 234 | |
234 | $securityTypeArgSpecified = 0; | | 235 | $securityTypeArgSpecified = 0; |
235 | $vncAuthEnabled = 0; | | 236 | $vncAuthEnabled = 0; |
236 | $passwordArgSpecified = 0; | | 237 | $passwordArgSpecified = 0; |
237 | @vncAuthStrings = ("vncauth", "tlsvnc", "x509vnc"); | | 238 | @vncAuthStrings = ("vncauth", "tlsvnc", "x509vnc"); |
238 | | | 239 | |
239 | # ...first we check our configuration files' settings | | 240 | # ...first we check our configuration files' settings |
240 | if ($config{'securitytypes'}) { | | 241 | if ($config{'securitytypes'}) { |
241 | $securityTypeArgSpecified = 1; | | 242 | $securityTypeArgSpecified = 1; |
242 | foreach $arg2 (split(',', $config{'securitytypes'})) { | | 243 | foreach $arg2 (split(',', $config{'securitytypes'})) { |
243 | if (grep {$_ eq lc($arg2)} @vncAuthStrings) { | | 244 | if (grep {$_ eq lc($arg2)} @vncAuthStrings) { |
244 | $vncAuthEnabled = 1; | | 245 | $vncAuthEnabled = 1; |
245 | } | | 246 | } |
246 | } | | 247 | } |
247 | } | | 248 | } |
248 | | | 249 | |
249 | # ...and finally we check CLI args, which in the case of the topic at | | 250 | # ...and finally we check CLI args, which in the case of the topic at |
250 | # hand (VNC auth or not), override anything found in configuration files | | 251 | # hand (VNC auth or not), override anything found in configuration files |
251 | # (even so-called "mandatory" settings). | | 252 | # (even so-called "mandatory" settings). |
252 | for ($i = 0; $i < @ARGV; ++$i) { | | 253 | for ($i = 0; $i < @ARGV; ++$i) { |
253 | # -SecurityTypes can be followed by a space or "=" | | 254 | # -SecurityTypes can be followed by a space or "=" |
254 | my @splitargs = split('=', $ARGV[$i]); | | 255 | my @splitargs = split('=', $ARGV[$i]); |
255 | if (@splitargs <= 1 && $i < @ARGV - 1) { | | 256 | if (@splitargs <= 1 && $i < @ARGV - 1) { |
256 | push(@splitargs, $ARGV[$i + 1]); | | 257 | push(@splitargs, $ARGV[$i + 1]); |
257 | } | | 258 | } |
258 | if (lc(@splitargs[0]) eq "-securitytypes") { | | 259 | if (lc(@splitargs[0]) eq "-securitytypes") { |
259 | if (@splitargs > 1) { | | 260 | if (@splitargs > 1) { |
260 | $securityTypeArgSpecified = 1; | | 261 | $securityTypeArgSpecified = 1; |
261 | } | | 262 | } |
262 | foreach $arg2 (split(',', @splitargs[1])) { | | 263 | foreach $arg2 (split(',', @splitargs[1])) { |
263 | if (grep {$_ eq lc($arg2)} @vncAuthStrings) { | | 264 | if (grep {$_ eq lc($arg2)} @vncAuthStrings) { |
264 | $vncAuthEnabled = 1; | | 265 | $vncAuthEnabled = 1; |
265 | } | | 266 | } |
266 | } | | 267 | } |
267 | } | | 268 | } |
268 | if ((lc(@splitargs[0]) eq "-password") | | 269 | if ((lc(@splitargs[0]) eq "-password") |
269 | || (lc(@splitargs[0]) eq "-passwordfile" | | 270 | || (lc(@splitargs[0]) eq "-passwordfile" |
270 | || (lc(@splitargs[0]) eq "-rfbauth"))) { | | 271 | || (lc(@splitargs[0]) eq "-rfbauth"))) { |
271 | $passwordArgSpecified = 1; | | 272 | $passwordArgSpecified = 1; |
272 | } | | 273 | } |
273 | } | | 274 | } |
274 | | | 275 | |
275 | if ((!$securityTypeArgSpecified || $vncAuthEnabled) && !$passwordArgSpecified) { | | 276 | if ((!$securityTypeArgSpecified || $vncAuthEnabled) && !$passwordArgSpecified) { |
276 | ($z,$z,$mode) = stat("$vncUserDir/passwd"); | | 277 | ($z,$z,$mode) = stat("$vncUserDir/passwd"); |
277 | if (!(-e "$vncUserDir/passwd") || ($mode & 077)) { | | 278 | if (!(-e "$vncUserDir/passwd") || ($mode & 077)) { |
278 | warn "\nYou will require a password to access your desktops.\n\n"; | | 279 | warn "\nYou will require a password to access your desktops.\n\n"; |
279 | system($exedir."vncpasswd -q $vncUserDir/passwd"); | | 280 | system($exedir."vncpasswd -q $vncUserDir/passwd"); |
280 | if (($? >> 8) != 0) { | | 281 | if (($? >> 8) != 0) { |
281 | exit 1; | | 282 | exit 1; |
282 | } | | 283 | } |
283 | } | | 284 | } |
284 | } | | 285 | } |
285 | | | 286 | |
286 | $desktopLog = "$vncUserDir/$host:$displayNumber.log"; | | 287 | $desktopLog = "$vncUserDir/$host:$displayNumber.log"; |
287 | unlink($desktopLog); | | 288 | unlink($desktopLog); |
288 | | | 289 | |
289 | # Make an X server cookie and set up the Xauthority file | | 290 | # Make an X server cookie and set up the Xauthority file |
290 | # mcookie is a part of util-linux, usually only GNU/Linux systems have it. | | 291 | # mcookie is a part of util-linux, usually only GNU/Linux systems have it. |
291 | $cookie = `mcookie`; | | 292 | $cookie = `mcookie`; |
292 | # Fallback for non GNU/Linux OS - use /dev/urandom on systems that have it, | | 293 | # Fallback for non GNU/Linux OS - use /dev/urandom on systems that have it, |
293 | # otherwise use perl's random number generator, seeded with the sum | | 294 | # otherwise use perl's random number generator, seeded with the sum |
294 | # of the current time, our PID and part of the encrypted form of the password. | | 295 | # of the current time, our PID and part of the encrypted form of the password. |
295 | if ($cookie eq "" && open(URANDOM, '<', '/dev/urandom')) { | | 296 | if ($cookie eq "" && open(URANDOM, '<', '/dev/urandom')) { |
296 | my $randata; | | 297 | my $randata; |
297 | if (sysread(URANDOM, $randata, 16) == 16) { | | 298 | if (sysread(URANDOM, $randata, 16) == 16) { |
298 | $cookie = unpack 'h*', $randata; | | 299 | $cookie = unpack 'h*', $randata; |
299 | } | | 300 | } |
300 | close(URANDOM); | | 301 | close(URANDOM); |
301 | } | | 302 | } |
302 | if ($cookie eq "") { | | 303 | if ($cookie eq "") { |
303 | srand(time+$$+unpack("L",`cat $vncUserDir/passwd`)); | | 304 | srand(time+$$+unpack("L",`cat $vncUserDir/passwd`)); |
304 | for (1..16) { | | 305 | for (1..16) { |
305 | $cookie .= sprintf("%02x", int(rand(256)) % 256); | | 306 | $cookie .= sprintf("%02x", int(rand(256)) % 256); |
306 | } | | 307 | } |
307 | } | | 308 | } |
308 | | | 309 | |
309 | open(XAUTH, "|xauth -f $xauthorityFile source -"); | | 310 | open(XAUTH, "|xauth -f $xauthorityFile source -"); |
310 | print XAUTH "add $host:$displayNumber . $cookie\n"; | | 311 | print XAUTH "add $host:$displayNumber . $cookie\n"; |
311 | print XAUTH "add $host/unix:$displayNumber . $cookie\n"; | | 312 | print XAUTH "add $host/unix:$displayNumber . $cookie\n"; |
312 | close(XAUTH); | | 313 | close(XAUTH); |
313 | | | 314 | |
314 | # Now start the X VNC Server | | 315 | # Now start the X VNC Server |
315 | | | 316 | |
316 | # We build up our Xvnc command with options | | 317 | # We build up our Xvnc command with options |
317 | $cmd = $exedir."Xvnc :$displayNumber"; | | 318 | $cmd = $exedir."Xvnc :$displayNumber"; |
318 | | | 319 | |
319 | foreach my $k (sort keys %config) { | | 320 | foreach my $k (sort keys %config) { |
320 | $cmd .= " -$k $config{$k}"; | | 321 | $cmd .= " -$k $config{$k}"; |
321 | delete $default_opts{$k}; # file options take precedence | | 322 | delete $default_opts{$k}; # file options take precedence |
322 | } | | 323 | } |
323 | | | 324 | |
324 | foreach my $k (sort keys %default_opts) { | | 325 | foreach my $k (sort keys %default_opts) { |
325 | $cmd .= " -$k $default_opts{$k}"; | | 326 | $cmd .= " -$k $default_opts{$k}"; |
326 | } | | 327 | } |
327 | | | 328 | |
328 | # Add color database stuff here, e.g.: | | 329 | # Add color database stuff here, e.g.: |
329 | # $cmd .= " -co /usr/lib/X11/rgb"; | | 330 | # $cmd .= " -co /usr/lib/X11/rgb"; |
330 | | | 331 | |
331 | foreach $arg (@ARGV) { | | 332 | foreach $arg (@ARGV) { |
332 | $cmd .= " " . "edString($arg); | | 333 | $cmd .= " " . "edString($arg); |
333 | } | | 334 | } |
334 | $cmd .= " >> " . "edString($desktopLog) . " 2>&1"; | | 335 | $cmd .= " >> " . "edString($desktopLog) . " 2>&1"; |
335 | | | 336 | |
336 | # Run $cmd and record the process ID. | | 337 | # Run $cmd and record the process ID. |
337 | $pidFile = "$vncUserDir/$host:$displayNumber.pid"; | | 338 | $pidFile = "$vncUserDir/$host:$displayNumber.pid"; |
338 | system("$cmd & echo \$! >$pidFile"); | | 339 | system("$cmd & echo \$! >$pidFile"); |
339 | | | 340 | |
340 | # Give Xvnc a chance to start up | | 341 | # Give Xvnc a chance to start up |
341 | | | 342 | |
342 | sleep(3); | | 343 | sleep(3); |
343 | if ($fontPath ne $defFontPath) { | | 344 | if ($fontPath ne $defFontPath) { |
344 | unless (kill 0, `cat $pidFile`) { | | 345 | unless (kill 0, `cat $pidFile`) { |
345 | if ($fpArgSpecified) { | | 346 | if ($fpArgSpecified) { |
346 | warn "\nWARNING: The first attempt to start Xvnc failed, probably because the font\n"; | | 347 | warn "\nWARNING: The first attempt to start Xvnc failed, probably because the font\n"; |
347 | warn "path you specified using the -fp argument is incorrect. Attempting to\n"; | | 348 | warn "path you specified using the -fp argument is incorrect. Attempting to\n"; |
348 | warn "determine an appropriate font path for this system and restart Xvnc using\n"; | | 349 | warn "determine an appropriate font path for this system and restart Xvnc using\n"; |
349 | warn "that font path ...\n"; | | 350 | warn "that font path ...\n"; |
350 | } else { | | 351 | } else { |
351 | warn "\nWARNING: The first attempt to start Xvnc failed, possibly because the font\n"; | | 352 | warn "\nWARNING: The first attempt to start Xvnc failed, possibly because the font\n"; |
352 | warn "catalog is not properly configured. Attempting to determine an appropriate\n"; | | 353 | warn "catalog is not properly configured. Attempting to determine an appropriate\n"; |
353 | warn "font path for this system and restart Xvnc using that font path ...\n"; | | 354 | warn "font path for this system and restart Xvnc using that font path ...\n"; |
354 | } | | 355 | } |
355 | $cmd =~ s@-fp [^ ]+@@; | | 356 | $cmd =~ s@-fp [^ ]+@@; |
356 | $cmd .= " -fp $defFontPath" if ($defFontPath); | | 357 | $cmd .= " -fp $defFontPath" if ($defFontPath); |
357 | system("$cmd & echo \$! >$pidFile"); | | 358 | system("$cmd & echo \$! >$pidFile"); |
358 | sleep(3); | | 359 | sleep(3); |
359 | } | | 360 | } |
360 | } | | 361 | } |
361 | unless (kill 0, `cat $pidFile`) { | | 362 | unless (kill 0, `cat $pidFile`) { |
362 | warn "Could not start Xvnc.\n\n"; | | 363 | warn "Could not start Xvnc.\n\n"; |
363 | unlink $pidFile; | | 364 | unlink $pidFile; |
364 | open(LOG, "<$desktopLog"); | | 365 | open(LOG, "<$desktopLog"); |
365 | while (<LOG>) { print; } | | 366 | while (<LOG>) { print; } |
366 | close(LOG); | | 367 | close(LOG); |
367 | die "\n"; | | 368 | die "\n"; |
368 | } | | 369 | } |
369 | | | 370 | |
370 | warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n"; | | 371 | warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n"; |
371 | | | 372 | |
372 | # Create the user's xstartup script if necessary. | | 373 | # Create the user's xstartup script if necessary. |
373 | if (! $skipxstartup) { | | 374 | if (! $skipxstartup) { |
374 | if (!(-e "$xstartupFile")) { | | 375 | if (!(-e "$xstartupFile")) { |
375 | warn "Creating default startup script $xstartupFile\n"; | | 376 | warn "Creating default startup script $xstartupFile\n"; |
376 | open(XSTARTUP, ">$xstartupFile"); | | 377 | open(XSTARTUP, ">$xstartupFile"); |
377 | print XSTARTUP $defaultXStartup; | | 378 | print XSTARTUP $defaultXStartup; |
378 | close(XSTARTUP); | | 379 | close(XSTARTUP); |
379 | chmod 0755, "$xstartupFile"; | | 380 | chmod 0755, "$xstartupFile"; |
380 | } | | 381 | } |
381 | } | | 382 | } |
382 | | | 383 | |
383 | # Create the user's config file if necessary. | | 384 | # Create the user's config file if necessary. |
384 | if (!(-e "$vncUserDir/config")) { | | 385 | if (!(-e "$vncUserDir/config")) { |
385 | warn "Creating default config $vncUserDir/config\n"; | | 386 | warn "Creating default config $vncUserDir/config\n"; |
386 | open(VNCUSERCONFIG, ">$vncUserDir/config"); | | 387 | open(VNCUSERCONFIG, ">$vncUserDir/config"); |
387 | print VNCUSERCONFIG $defaultConfig; | | 388 | print VNCUSERCONFIG $defaultConfig; |
388 | close(VNCUSERCONFIG); | | 389 | close(VNCUSERCONFIG); |
389 | chmod 0644, "$vncUserDir/config"; | | 390 | chmod 0644, "$vncUserDir/config"; |
390 | } | | 391 | } |
391 | | | 392 | |
392 | # Run the X startup script. | | 393 | # Run the X startup script. |
393 | if (! $skipxstartup) { | | 394 | if (! $skipxstartup) { |
394 | warn "Starting applications specified in $xstartupFile\n"; | | 395 | warn "Starting applications specified in $xstartupFile\n"; |
395 | } | | 396 | } |
396 | warn "Log file is $desktopLog\n\n"; | | 397 | warn "Log file is $desktopLog\n\n"; |
397 | | | 398 | |
398 | # If the unix domain socket exists then use that (DISPLAY=:n) otherwise use | | 399 | # If the unix domain socket exists then use that (DISPLAY=:n) otherwise use |
399 | # TCP (DISPLAY=host:n) | | 400 | # TCP (DISPLAY=host:n) |
400 | | | 401 | |
401 | if (-e "/tmp/.X11-unix/X$displayNumber" || | | 402 | if (-e "/tmp/.X11-unix/X$displayNumber" || |
402 | -e "/usr/spool/sockets/X11/$displayNumber") | | 403 | -e "/usr/spool/sockets/X11/$displayNumber") |
403 | { | | 404 | { |
404 | $ENV{DISPLAY}= ":$displayNumber"; | | 405 | $ENV{DISPLAY}= ":$displayNumber"; |
405 | } else { | | 406 | } else { |
406 | $ENV{DISPLAY}= "$host:$displayNumber"; | | 407 | $ENV{DISPLAY}= "$host:$displayNumber"; |
407 | } | | 408 | } |
408 | $ENV{VNCDESKTOP}= $desktopName; | | 409 | $ENV{VNCDESKTOP}= $desktopName; |
409 | | | 410 | |
410 | if ($opt{'-fg'}) { | | 411 | if ($opt{'-fg'}) { |
411 | if (! $skipxstartup) { | | 412 | if (! $skipxstartup) { |
412 | system("$xstartupFile >> " . "edString($desktopLog) . " 2>&1"); | | 413 | system("$xstartupFile >> " . "edString($desktopLog) . " 2>&1"); |
413 | } | | 414 | } |
414 | if (kill 0, `cat $pidFile`) { | | 415 | if (kill 0, `cat $pidFile`) { |
415 | $opt{'-kill'} = ':'.$displayNumber; | | 416 | $opt{'-kill'} = ':'.$displayNumber; |
416 | &Kill(); | | 417 | &Kill(); |
417 | } | | 418 | } |
418 | } else { | | 419 | } else { |
419 | if ($opt{'-autokill'}) { | | 420 | if ($opt{'-autokill'}) { |
420 | if (! $skipxstartup) { | | 421 | if (! $skipxstartup) { |
421 | system("($xstartupFile; $0 -kill :$displayNumber) >> " | | 422 | system("($xstartupFile; $0 -kill :$displayNumber) >> " |
422 | . "edString($desktopLog) . " 2>&1 &"); | | 423 | . "edString($desktopLog) . " 2>&1 &"); |
423 | } | | 424 | } |
424 | } else { | | 425 | } else { |
425 | if (! $skipxstartup) { | | 426 | if (! $skipxstartup) { |
426 | system("$xstartupFile >> " . "edString($desktopLog) | | 427 | system("$xstartupFile >> " . "edString($desktopLog) |
427 | . " 2>&1 &"); | | 428 | . " 2>&1 &"); |
428 | } | | 429 | } |
429 | } | | 430 | } |
430 | } | | 431 | } |
431 | | | 432 | |
432 | exit; | | 433 | exit; |
433 | | | 434 | |
434 | ############################################################################### | | 435 | ############################################################################### |
435 | # Functions | | 436 | # Functions |
436 | ############################################################################### | | 437 | ############################################################################### |
437 | | | 438 | |
438 | # | | 439 | # |
439 | # Populate the global %config hash with settings from a specified | | 440 | # Populate the global %config hash with settings from a specified |
440 | # vncserver configuration file if it exists | | 441 | # vncserver configuration file if it exists |
441 | # | | 442 | # |
442 | # Args: 1. file path | | 443 | # Args: 1. file path |
443 | # 2. optional boolean flag to enable warning when a previously | | 444 | # 2. optional boolean flag to enable warning when a previously |
444 | # set configuration setting is being overridden | | 445 | # set configuration setting is being overridden |
445 | # | | 446 | # |
446 | sub LoadConfig { | | 447 | sub LoadConfig { |
447 | local ($configFile, $warnoverride) = @_; | | 448 | local ($configFile, $warnoverride) = @_; |
448 | local ($toggle) = undef; | | 449 | local ($toggle) = undef; |
449 | | | 450 | |
450 | if (stat($configFile)) { | | 451 | if (stat($configFile)) { |
451 | if (open(IN, $configFile)) { | | 452 | if (open(IN, $configFile)) { |
452 | while (<IN>) { | | 453 | while (<IN>) { |
453 | next if /^#/; | | 454 | next if /^#/; |
454 | if (my ($k, $v) = /^\s*(\w+)\s*=\s*(.+)$/) { | | 455 | if (my ($k, $v) = /^\s*(\w+)\s*=\s*(.+)$/) { |
455 | $k = lc($k); # must normalize key case | | 456 | $k = lc($k); # must normalize key case |
456 | if ($warnoverride && $config{$k}) { | | 457 | if ($warnoverride && $config{$k}) { |
457 | print("Warning: $configFile is overriding previously defined '$k' to be '$v'\n"); | | 458 | print("Warning: $configFile is overriding previously defined '$k' to be '$v'\n"); |
458 | } | | 459 | } |
459 | $config{$k} = $v; | | 460 | $config{$k} = $v; |
460 | } elsif ($_ =~ m/^\s*(\S+)/) { | | 461 | } elsif ($_ =~ m/^\s*(\S+)/) { |
461 | # We can't reasonably warn on override of toggles (e.g. AlwaysShared) | | 462 | # We can't reasonably warn on override of toggles (e.g. AlwaysShared) |
462 | # because it would get crazy to do so. We'd have to check if the | | 463 | # because it would get crazy to do so. We'd have to check if the |
463 | # current config file being loaded defined the logical opposite setting | | 464 | # current config file being loaded defined the logical opposite setting |
464 | # (NeverShared vs. AlwaysShared, etc etc). | | 465 | # (NeverShared vs. AlwaysShared, etc etc). |
465 | $toggle = lc($1); # must normalize key case | | 466 | $toggle = lc($1); # must normalize key case |
466 | $config{$toggle} = $k; | | 467 | $config{$toggle} = $k; |
467 | } | | 468 | } |
468 | } | | 469 | } |
469 | close(IN); | | 470 | close(IN); |
470 | } | | 471 | } |
471 | } | | 472 | } |
472 | } | | 473 | } |
473 | | | 474 | |
474 | # | | 475 | # |
475 | # CheckGeometryAndDepth simply makes sure that the geometry and depth values | | 476 | # CheckGeometryAndDepth simply makes sure that the geometry and depth values |
476 | # are sensible. | | 477 | # are sensible. |
477 | # | | 478 | # |
478 | | | 479 | |
479 | sub CheckGeometryAndDepth | | 480 | sub CheckGeometryAndDepth |
480 | { | | 481 | { |
481 | if ($geometry =~ /^(\d+)x(\d+)$/) { | | 482 | if ($geometry =~ /^(\d+)x(\d+)$/) { |
482 | $width = $1; $height = $2; | | 483 | $width = $1; $height = $2; |
483 | | | 484 | |
484 | if (($width<1) || ($height<1)) { | | 485 | if (($width<1) || ($height<1)) { |
485 | die "$prog: geometry $geometry is invalid\n"; | | 486 | die "$prog: geometry $geometry is invalid\n"; |
486 | } | | 487 | } |
487 | | | 488 | |
488 | $geometry = "${width}x$height"; | | 489 | $geometry = "${width}x$height"; |
489 | } else { | | 490 | } else { |
490 | die "$prog: geometry $geometry is invalid\n"; | | 491 | die "$prog: geometry $geometry is invalid\n"; |
491 | } | | 492 | } |
492 | | | 493 | |
493 | if ($depth && (($depth < 8) || ($depth > 32))) { | | 494 | if ($depth && (($depth < 8) || ($depth > 32))) { |
494 | die "Depth must be between 8 and 32\n"; | | 495 | die "Depth must be between 8 and 32\n"; |
495 | } | | 496 | } |
496 | } | | 497 | } |
497 | | | 498 | |
498 | | | 499 | |
499 | # | | 500 | # |
500 | # GetDisplayNumber gets the lowest available display number. A display number | | 501 | # GetDisplayNumber gets the lowest available display number. A display number |
501 | # n is taken if something is listening on the VNC server port (5900+n) or the | | 502 | # n is taken if something is listening on the VNC server port (5900+n) or the |
502 | # X server port (6000+n). | | 503 | # X server port (6000+n). |
503 | # | | 504 | # |
504 | | | 505 | |
505 | sub GetDisplayNumber | | 506 | sub GetDisplayNumber |
506 | { | | 507 | { |
507 | foreach $n (1..99) { | | 508 | foreach $n (1..99) { |
508 | if (&CheckDisplayNumber($n)) { | | 509 | if (&CheckDisplayNumber($n)) { |
509 | return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02 | | 510 | return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02 |
510 | } | | 511 | } |
511 | } | | 512 | } |
512 | | | 513 | |
513 | die "$prog: no free display number on $host.\n"; | | 514 | die "$prog: no free display number on $host.\n"; |
514 | } | | 515 | } |
515 | | | 516 | |
516 | | | 517 | |
517 | # | | 518 | # |
518 | # CheckDisplayNumber checks if the given display number is available. A | | 519 | # CheckDisplayNumber checks if the given display number is available. A |
519 | # display number n is taken if something is listening on the VNC server port | | 520 | # display number n is taken if something is listening on the VNC server port |
520 | # (5900+n) or the X server port (6000+n). | | 521 | # (5900+n) or the X server port (6000+n). |
521 | # | | 522 | # |
522 | | | 523 | |
523 | sub CheckDisplayNumber | | 524 | sub CheckDisplayNumber |
524 | { | | 525 | { |
525 | local ($n) = @_; | | 526 | local ($n) = @_; |
526 | | | 527 | |
527 | socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; | | 528 | socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; |
528 | eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; | | 529 | eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; |
529 | if (!bind(S, sockaddr_in(6000 + $n, &INADDR_ANY))) { | | 530 | if (!bind(S, sockaddr_in(6000 + $n, &INADDR_ANY))) { |
530 | close(S); | | 531 | close(S); |
531 | return 0; | | 532 | return 0; |
532 | } | | 533 | } |
533 | close(S); | | 534 | close(S); |
534 | | | 535 | |
535 | socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; | | 536 | socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n"; |
536 | eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; | | 537 | eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))'; |
537 | if (!bind(S, sockaddr_in(5900 + $n, &INADDR_ANY))) { | | 538 | if (!bind(S, sockaddr_in(5900 + $n, &INADDR_ANY))) { |
538 | close(S); | | 539 | close(S); |
539 | return 0; | | 540 | return 0; |
540 | } | | 541 | } |
541 | close(S); | | 542 | close(S); |
542 | | | 543 | |
543 | if (-e "/tmp/.X$n-lock") { | | 544 | if (-e "/tmp/.X$n-lock") { |
544 | warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n"; | | 545 | warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n"; |
545 | warn "Remove this file if there is no X server $host:$n\n"; | | 546 | warn "Remove this file if there is no X server $host:$n\n"; |
546 | return 0; | | 547 | return 0; |
547 | } | | 548 | } |
548 | | | 549 | |
549 | if (-e "/tmp/.X11-unix/X$n") { | | 550 | if (-e "/tmp/.X11-unix/X$n") { |
550 | warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n"; | | 551 | warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n"; |
551 | warn "Remove this file if there is no X server $host:$n\n"; | | 552 | warn "Remove this file if there is no X server $host:$n\n"; |
552 | return 0; | | 553 | return 0; |
553 | } | | 554 | } |
554 | | | 555 | |
555 | if (-e "/usr/spool/sockets/X11/$n") { | | 556 | if (-e "/usr/spool/sockets/X11/$n") { |
556 | warn("\nWarning: $host:$n is taken because of ". | | 557 | warn("\nWarning: $host:$n is taken because of ". |
557 | "/usr/spool/sockets/X11/$n\n"); | | 558 | "/usr/spool/sockets/X11/$n\n"); |
558 | warn "Remove this file if there is no X server $host:$n\n"; | | 559 | warn "Remove this file if there is no X server $host:$n\n"; |
559 | return 0; | | 560 | return 0; |
560 | } | | 561 | } |
561 | | | 562 | |
562 | return 1; | | 563 | return 1; |
563 | } | | 564 | } |
564 | | | 565 | |
565 | | | 566 | |
566 | # | | 567 | # |
567 | # GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel | | 568 | # GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel |
568 | # format of the current X display being used. If successful, it sets the | | 569 | # format of the current X display being used. If successful, it sets the |
569 | # options as appropriate so that the X VNC server will use the same settings | | 570 | # options as appropriate so that the X VNC server will use the same settings |
570 | # (minus an allowance for window manager decorations on the geometry). Using | | 571 | # (minus an allowance for window manager decorations on the geometry). Using |
571 | # the same depth and pixel format means that the VNC server won't have to | | 572 | # the same depth and pixel format means that the VNC server won't have to |
572 | # translate pixels when the desktop is being viewed on this X display (for | | 573 | # translate pixels when the desktop is being viewed on this X display (for |
573 | # TrueColor displays anyway). | | 574 | # TrueColor displays anyway). |
574 | # | | 575 | # |
575 | | | 576 | |
576 | sub GetXDisplayDefaults | | 577 | sub GetXDisplayDefaults |
577 | { | | 578 | { |
578 | local (@lines, @matchlines, $width, $height, $defaultVisualId, $i, | | 579 | local (@lines, @matchlines, $width, $height, $defaultVisualId, $i, |
579 | $red, $green, $blue); | | 580 | $red, $green, $blue); |
580 | | | 581 | |
581 | $wmDecorationWidth = 4; # a guess at typical size for window manager | | 582 | $wmDecorationWidth = 4; # a guess at typical size for window manager |
582 | $wmDecorationHeight = 24; # decoration size | | 583 | $wmDecorationHeight = 24; # decoration size |
583 | | | 584 | |
584 | return if (!defined($ENV{DISPLAY})); | | 585 | return if (!defined($ENV{DISPLAY})); |
585 | | | 586 | |
586 | @lines = `xdpyinfo 2>/dev/null`; | | 587 | @lines = `xdpyinfo 2>/dev/null`; |
587 | | | 588 | |
588 | return if ($? != 0); | | 589 | return if ($? != 0); |
589 | | | 590 | |
590 | @matchlines = grep(/dimensions/, @lines); | | 591 | @matchlines = grep(/dimensions/, @lines); |
591 | if (@matchlines) { | | 592 | if (@matchlines) { |
592 | ($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/); | | 593 | ($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/); |
593 | | | 594 | |
594 | $width -= $wmDecorationWidth; | | 595 | $width -= $wmDecorationWidth; |
595 | $height -= $wmDecorationHeight; | | 596 | $height -= $wmDecorationHeight; |
596 | | | 597 | |
597 | $geometry = "${width}x$height"; | | 598 | $geometry = "${width}x$height"; |
598 | } | | 599 | } |
599 | | | 600 | |
600 | @matchlines = grep(/default visual id/, @lines); | | 601 | @matchlines = grep(/default visual id/, @lines); |
601 | if (@matchlines) { | | 602 | if (@matchlines) { |
602 | ($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/); | | 603 | ($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/); |
603 | | | 604 | |
604 | for ($i = 0; $i < @lines; $i++) { | | 605 | for ($i = 0; $i < @lines; $i++) { |
605 | if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) { | | 606 | if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) { |
606 | if (($lines[$i+1] !~ /TrueColor/) || | | 607 | if (($lines[$i+1] !~ /TrueColor/) || |
607 | ($lines[$i+2] !~ /depth/) || | | 608 | ($lines[$i+2] !~ /depth/) || |
608 | ($lines[$i+4] !~ /red, green, blue masks/)) | | 609 | ($lines[$i+4] !~ /red, green, blue masks/)) |
609 | { | | 610 | { |
610 | return; | | 611 | return; |
611 | } | | 612 | } |
612 | last; | | 613 | last; |
613 | } | | 614 | } |
614 | } | | 615 | } |
615 | | | 616 | |
616 | return if ($i >= @lines); | | 617 | return if ($i >= @lines); |
617 | | | 618 | |
618 | ($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/); | | 619 | ($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/); |
619 | ($red,$green,$blue) | | 620 | ($red,$green,$blue) |
620 | = ($lines[$i+4] | | 621 | = ($lines[$i+4] |
621 | =~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/); | | 622 | =~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/); |
622 | | | 623 | |
623 | $red = hex($red); | | 624 | $red = hex($red); |
624 | $green = hex($green); | | 625 | $green = hex($green); |
625 | $blue = hex($blue); | | 626 | $blue = hex($blue); |
626 | | | 627 | |
627 | if ($red > $blue) { | | 628 | if ($red > $blue) { |
628 | $red = int(log($red) / log(2)) - int(log($green) / log(2)); | | 629 | $red = int(log($red) / log(2)) - int(log($green) / log(2)); |
629 | $green = int(log($green) / log(2)) - int(log($blue) / log(2)); | | 630 | $green = int(log($green) / log(2)) - int(log($blue) / log(2)); |
630 | $blue = int(log($blue) / log(2)) + 1; | | 631 | $blue = int(log($blue) / log(2)) + 1; |
631 | $pixelformat = "rgb$red$green$blue"; | | 632 | $pixelformat = "rgb$red$green$blue"; |
632 | } else { | | 633 | } else { |
633 | $blue = int(log($blue) / log(2)) - int(log($green) / log(2)); | | 634 | $blue = int(log($blue) / log(2)) - int(log($green) / log(2)); |
634 | $green = int(log($green) / log(2)) - int(log($red) / log(2)); | | 635 | $green = int(log($green) / log(2)) - int(log($red) / log(2)); |
635 | $red = int(log($red) / log(2)) + 1; | | 636 | $red = int(log($red) / log(2)) + 1; |
636 | $pixelformat = "bgr$blue$green$red"; | | 637 | $pixelformat = "bgr$blue$green$red"; |
637 | } | | 638 | } |
638 | } | | 639 | } |
639 | } | | 640 | } |
640 | | | 641 | |
641 | | | 642 | |
642 | # | | 643 | # |
643 | # quotedString returns a string which yields the original string when parsed | | 644 | # quotedString returns a string which yields the original string when parsed |
644 | # by a shell. | | 645 | # by a shell. |
645 | # | | 646 | # |
646 | | | 647 | |
647 | sub quotedString | | 648 | sub quotedString |
648 | { | | 649 | { |
649 | local ($in) = @_; | | 650 | local ($in) = @_; |
650 | | | 651 | |
651 | $in =~ s/\'/\'\"\'\"\'/g; | | 652 | $in =~ s/\'/\'\"\'\"\'/g; |
652 | | | 653 | |
653 | return "'$in'"; | | 654 | return "'$in'"; |
654 | } | | 655 | } |
655 | | | 656 | |
656 | | | 657 | |
657 | # | | 658 | # |
658 | # removeSlashes turns slashes into underscores for use as a file name. | | 659 | # removeSlashes turns slashes into underscores for use as a file name. |
659 | # | | 660 | # |
660 | | | 661 | |
661 | sub removeSlashes | | 662 | sub removeSlashes |
662 | { | | 663 | { |
663 | local ($in) = @_; | | 664 | local ($in) = @_; |
664 | | | 665 | |
665 | $in =~ s|/|_|g; | | 666 | $in =~ s|/|_|g; |
666 | | | 667 | |
667 | return "$in"; | | 668 | return "$in"; |
668 | } | | 669 | } |
669 | | | 670 | |
670 | | | 671 | |
671 | # | | 672 | # |
672 | # Usage | | 673 | # Usage |
673 | # | | 674 | # |
674 | | | 675 | |
675 | sub Usage | | 676 | sub Usage |
676 | { | | 677 | { |
677 | die("\nusage: $prog [:<number>] [-name <desktop-name>] [-depth <depth>]\n". | | 678 | die("\nusage: $prog [:<number>] [-name <desktop-name>] [-depth <depth>]\n". |
678 | " [-geometry <width>x<height>]\n". | | 679 | " [-geometry <width>x<height>]\n". |
679 | " [-pixelformat rgbNNN|bgrNNN]\n". | | 680 | " [-pixelformat rgbNNN|bgrNNN]\n". |
680 | " [-fp <font-path>]\n". | | 681 | " [-fp <font-path>]\n". |
681 | " [-fg]\n". | | 682 | " [-fg]\n". |
682 | " [-autokill]\n". | | 683 | " [-autokill]\n". |
683 | " [-noxstartup]\n". | | 684 | " [-noxstartup]\n". |
684 | " [-xstartup <file>]\n". | | 685 | " [-xstartup <file>]\n". |
685 | " <Xvnc-options>...\n\n". | | 686 | " <Xvnc-options>...\n\n". |
686 | " $prog -kill <X-display>\n\n". | | 687 | " $prog -kill <X-display>\n\n". |
687 | " $prog -list\n\n"); | | 688 | " $prog -list\n\n"); |
688 | } | | 689 | } |
689 | | | 690 | |
690 | | | 691 | |
691 | # | | 692 | # |
692 | # List | | 693 | # List |
693 | # | | 694 | # |
694 | | | 695 | |
695 | sub List | | 696 | sub List |
696 | { | | 697 | { |
697 | opendir(dir, $vncUserDir); | | 698 | opendir(dir, $vncUserDir); |
698 | my @filelist = readdir(dir); | | 699 | my @filelist = readdir(dir); |
699 | closedir(dir); | | 700 | closedir(dir); |
700 | print "\nTigerVNC server sessions:\n\n"; | | 701 | print "\nTigerVNC server sessions:\n\n"; |
701 | print "X DISPLAY #\tPROCESS ID\n"; | | 702 | print "X DISPLAY #\tPROCESS ID\n"; |
702 | foreach my $file (@filelist) { | | 703 | foreach my $file (@filelist) { |
703 | if ($file =~ /$host:(\d+)$\.pid/) { | | 704 | if ($file =~ /$host:(\d+)$\.pid/) { |
704 | chop($tmp_pid = `cat $vncUserDir/$file`); | | 705 | chop($tmp_pid = `cat $vncUserDir/$file`); |
705 | if (kill 0, $tmp_pid) { | | 706 | if (kill 0, $tmp_pid) { |
706 | print ":".$1."\t\t".`cat $vncUserDir/$file`; | | 707 | print ":".$1."\t\t".`cat $vncUserDir/$file`; |
707 | } else { | | 708 | } else { |
708 | unlink ($vncUserDir . "/" . $file); | | 709 | unlink ($vncUserDir . "/" . $file); |
709 | } | | 710 | } |
710 | } | | 711 | } |
711 | } | | 712 | } |
712 | exit; | | 713 | exit; |
713 | } | | 714 | } |
714 | | | 715 | |
715 | | | 716 | |
716 | # | | 717 | # |
717 | # Kill | | 718 | # Kill |
718 | # | | 719 | # |
719 | | | 720 | |
720 | sub Kill | | 721 | sub Kill |
721 | { | | 722 | { |
722 | $opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1 | | 723 | $opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1 |
723 | | | 724 | |
724 | if ($opt{'-kill'} =~ /^:\d+$/) { | | 725 | if ($opt{'-kill'} =~ /^:\d+$/) { |
725 | $pidFile = "$vncUserDir/$host$opt{'-kill'}.pid"; | | 726 | $pidFile = "$vncUserDir/$host$opt{'-kill'}.pid"; |
726 | } else { | | 727 | } else { |
727 | if ($opt{'-kill'} !~ /^$host:/) { | | 728 | if ($opt{'-kill'} !~ /^$host:/) { |
728 | die "\nCan't tell if $opt{'-kill'} is on $host\n". | | 729 | die "\nCan't tell if $opt{'-kill'} is on $host\n". |
729 | "Use -kill :<number> instead\n\n"; | | 730 | "Use -kill :<number> instead\n\n"; |
730 | } | | 731 | } |
731 | $pidFile = "$vncUserDir/$opt{'-kill'}.pid"; | | 732 | $pidFile = "$vncUserDir/$opt{'-kill'}.pid"; |
732 | } | | 733 | } |
733 | | | 734 | |
734 | if (! -r $pidFile) { | | 735 | if (! -r $pidFile) { |
735 | die "\nCan't find file $pidFile\n". | | 736 | die "\nCan't find file $pidFile\n". |
736 | "You'll have to kill the Xvnc process manually\n\n"; | | 737 | "You'll have to kill the Xvnc process manually\n\n"; |
737 | } | | 738 | } |
738 | | | 739 | |
739 | $SIG{'HUP'} = 'IGNORE'; | | 740 | $SIG{'HUP'} = 'IGNORE'; |
740 | chop($pid = `cat $pidFile`); | | 741 | chop($pid = `cat $pidFile`); |
741 | warn "Killing Xvnc process ID $pid\n"; | | 742 | warn "Killing Xvnc process ID $pid\n"; |
742 | | | 743 | |
743 | if (kill 0, $pid) { | | 744 | if (kill 0, $pid) { |
744 | system("kill $pid"); | | 745 | system("kill $pid"); |
745 | sleep(1); | | 746 | sleep(1); |
746 | if (kill 0, $pid) { | | 747 | if (kill 0, $pid) { |
747 | print "Xvnc seems to be deadlocked. Kill the process manually and then re-run\n"; | | 748 | print "Xvnc seems to be deadlocked. Kill the process manually and then re-run\n"; |
748 | print " ".$0." -kill ".$opt{'-kill'}."\n"; | | 749 | print " ".$0." -kill ".$opt{'-kill'}."\n"; |
749 | print "to clean up the socket files.\n"; | | 750 | print "to clean up the socket files.\n"; |
750 | exit | | 751 | exit |
751 | } | | 752 | } |
752 | | | 753 | |
753 | } else { | | 754 | } else { |
754 | warn "Xvnc process ID $pid already killed\n"; | | 755 | warn "Xvnc process ID $pid already killed\n"; |
755 | $opt{'-kill'} =~ s/://; | | 756 | $opt{'-kill'} =~ s/://; |
756 | | | 757 | |
757 | if (-e "/tmp/.X11-unix/X$opt{'-kill'}") { | | 758 | if (-e "/tmp/.X11-unix/X$opt{'-kill'}") { |
758 | print "Xvnc did not appear to shut down cleanly."; | | 759 | print "Xvnc did not appear to shut down cleanly."; |
759 | print " Removing /tmp/.X11-unix/X$opt{'-kill'}\n"; | | 760 | print " Removing /tmp/.X11-unix/X$opt{'-kill'}\n"; |
760 | unlink "/tmp/.X11-unix/X$opt{'-kill'}"; | | 761 | unlink "/tmp/.X11-unix/X$opt{'-kill'}"; |
761 | } | | 762 | } |
762 | if (-e "/tmp/.X$opt{'-kill'}-lock") { | | 763 | if (-e "/tmp/.X$opt{'-kill'}-lock") { |
763 | print "Xvnc did not appear to shut down cleanly."; | | 764 | print "Xvnc did not appear to shut down cleanly."; |
764 | print " Removing /tmp/.X$opt{'-kill'}-lock\n"; | | 765 | print " Removing /tmp/.X$opt{'-kill'}-lock\n"; |
765 | unlink "/tmp/.X$opt{'-kill'}-lock"; | | 766 | unlink "/tmp/.X$opt{'-kill'}-lock"; |
766 | } | | 767 | } |
767 | } | | 768 | } |
768 | | | 769 | |
769 | unlink $pidFile; | | 770 | unlink $pidFile; |
770 | exit; | | 771 | exit; |
771 | } | | 772 | } |
772 | | | 773 | |
773 | | | 774 | |
774 | # | | 775 | # |
775 | # ParseOptions takes a list of possible options and a boolean indicating | | 776 | # ParseOptions takes a list of possible options and a boolean indicating |
776 | # whether the option has a value following, and sets up an associative array | | 777 | # whether the option has a value following, and sets up an associative array |
777 | # %opt of the values of the options given on the command line. It removes all | | 778 | # %opt of the values of the options given on the command line. It removes all |
778 | # the arguments it uses from @ARGV and returns them in @optArgs. | | 779 | # the arguments it uses from @ARGV and returns them in @optArgs. |
779 | # | | 780 | # |
780 | | | 781 | |
781 | sub ParseOptions | | 782 | sub ParseOptions |
782 | { | | 783 | { |
783 | local (@optval) = @_; | | 784 | local (@optval) = @_; |
784 | local ($opt, @opts, %valFollows, @newargs); | | 785 | local ($opt, @opts, %valFollows, @newargs); |
785 | | | 786 | |
786 | while (@optval) { | | 787 | while (@optval) { |
787 | $opt = shift(@optval); | | 788 | $opt = shift(@optval); |
788 | push(@opts,$opt); | | 789 | push(@opts,$opt); |
789 | $valFollows{$opt} = shift(@optval); | | 790 | $valFollows{$opt} = shift(@optval); |
790 | } | | 791 | } |
791 | | | 792 | |
792 | @optArgs = (); | | 793 | @optArgs = (); |
793 | %opt = (); | | 794 | %opt = (); |
794 | | | 795 | |
795 | arg: while (defined($arg = shift(@ARGV))) { | | 796 | arg: while (defined($arg = shift(@ARGV))) { |
796 | foreach $opt (@opts) { | | 797 | foreach $opt (@opts) { |
797 | if ($arg eq $opt) { | | 798 | if ($arg eq $opt) { |
798 | push(@optArgs, $arg); | | 799 | push(@optArgs, $arg); |
799 | if ($valFollows{$opt}) { | | 800 | if ($valFollows{$opt}) { |
800 | if (@ARGV == 0) { | | 801 | if (@ARGV == 0) { |
801 | &Usage(); | | 802 | &Usage(); |
802 | } | | 803 | } |
803 | $opt{$opt} = shift(@ARGV); | | 804 | $opt{$opt} = shift(@ARGV); |
804 | push(@optArgs, $opt{$opt}); | | 805 | push(@optArgs, $opt{$opt}); |
805 | } else { | | 806 | } else { |
806 | $opt{$opt} = 1; | | 807 | $opt{$opt} = 1; |
807 | } | | 808 | } |
808 | next arg; | | 809 | next arg; |
809 | } | | 810 | } |
810 | } | | 811 | } |
811 | push(@newargs,$arg); | | 812 | push(@newargs,$arg); |
812 | } | | 813 | } |
813 | | | 814 | |
814 | @ARGV = @newargs; | | 815 | @ARGV = @newargs; |
815 | } | | 816 | } |
816 | | | 817 | |
817 | | | 818 | |
818 | # Routine to make sure we're operating in a sane environment. | | 819 | # Routine to make sure we're operating in a sane environment. |
819 | sub SanityCheck | | 820 | sub SanityCheck |
820 | { | | 821 | { |
821 | local ($cmd); | | 822 | local ($cmd); |
822 | | | 823 | |
823 | # Get the program name | | 824 | # Get the program name |
824 | ($prog) = ($0 =~ m|([^/]+)$|); | | 825 | ($prog) = ($0 =~ m|([^/]+)$|); |
825 | | | 826 | |
826 | # | | 827 | # |
827 | # Check we have all the commands we'll need on the path. | | 828 | # Check we have all the commands we'll need on the path. |
828 | # | | 829 | # |
829 | | | 830 | |
830 | cmd: | | 831 | cmd: |
831 | foreach $cmd ("uname","xauth") { | | 832 | foreach $cmd ("uname","xauth") { |
832 | for (split(/:/,$ENV{PATH})) { | | 833 | for (split(/:/,$ENV{PATH})) { |
833 | if (-x "$_/$cmd") { | | 834 | if (-x "$_/$cmd") { |
834 | next cmd; | | 835 | next cmd; |
835 | } | | 836 | } |
836 | } | | 837 | } |
837 | die "$prog: couldn't find \"$cmd\" on your PATH.\n"; | | 838 | die "$prog: couldn't find \"$cmd\" on your PATH.\n"; |
838 | } | | 839 | } |
839 | | | 840 | |
840 | if($exedir eq "") { | | 841 | if($exedir eq "") { |
841 | cmd2: | | 842 | cmd2: |
842 | foreach $cmd ("Xvnc","vncpasswd") { | | 843 | foreach $cmd ("Xvnc","vncpasswd") { |
843 | for (split(/:/,$ENV{PATH})) { | | 844 | for (split(/:/,$ENV{PATH})) { |
844 | if (-x "$_/$cmd") { | | 845 | if (-x "$_/$cmd") { |
845 | next cmd2; | | 846 | next cmd2; |
846 | } | | 847 | } |
847 | } | | 848 | } |
848 | die "$prog: couldn't find \"$cmd\" on your PATH.\n"; | | 849 | die "$prog: couldn't find \"$cmd\" on your PATH.\n"; |
849 | } | | 850 | } |
850 | } | | 851 | } |
851 | else { | | 852 | else { |
852 | cmd3: | | 853 | cmd3: |
853 | foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") { | | 854 | foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") { |
854 | for (split(/:/,$ENV{PATH})) { | | 855 | for (split(/:/,$ENV{PATH})) { |
855 | if (-x "$cmd") { | | 856 | if (-x "$cmd") { |
856 | next cmd3; | | 857 | next cmd3; |
857 | } | | 858 | } |
858 | } | | 859 | } |
859 | die "$prog: couldn't find \"$cmd\".\n"; | | 860 | die "$prog: couldn't find \"$cmd\".\n"; |
860 | } | | 861 | } |
861 | } | | 862 | } |
862 | | | 863 | |
863 | if (!defined($ENV{HOME})) { | | 864 | if (!defined($ENV{HOME})) { |
864 | die "$prog: The HOME environment variable is not set.\n"; | | 865 | die "$prog: The HOME environment variable is not set.\n"; |
865 | } | | 866 | } |
866 | | | 867 | |
867 | # | | 868 | # |
868 | # Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an | | 869 | # Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an |
869 | # eval, and if it fails we try 'require "sys/socket.ph"'. If this fails, | | 870 | # eval, and if it fails we try 'require "sys/socket.ph"'. If this fails, |
870 | # we just guess at the values. If you find perl moaning here, just | | 871 | # we just guess at the values. If you find perl moaning here, just |
871 | # hard-code the values of AF_INET and SOCK_STREAM. You can find these out | | 872 | # hard-code the values of AF_INET and SOCK_STREAM. You can find these out |
872 | # for your platform by looking in /usr/include/sys/socket.h and related | | 873 | # for your platform by looking in /usr/include/sys/socket.h and related |
873 | # files. | | 874 | # files. |
874 | # | | 875 | # |
875 | | | 876 | |
876 | chop($os = `uname`); | | 877 | chop($os = `uname`); |
877 | chop($osrev = `uname -r`); | | 878 | chop($osrev = `uname -r`); |
878 | | | 879 | |
879 | eval 'use Socket'; | | 880 | eval 'use Socket'; |
880 | if ($@) { | | 881 | if ($@) { |
881 | eval 'require "sys/socket.ph"'; | | 882 | eval 'require "sys/socket.ph"'; |
882 | if ($@) { | | 883 | if ($@) { |
883 | if (($os eq "SunOS") && ($osrev !~ /^4/)) { | | 884 | if (($os eq "SunOS") && ($osrev !~ /^4/)) { |
884 | $AF_INET = 2; | | 885 | $AF_INET = 2; |
885 | $SOCK_STREAM = 2; | | 886 | $SOCK_STREAM = 2; |
886 | } else { | | 887 | } else { |
887 | $AF_INET = 2; | | 888 | $AF_INET = 2; |
888 | $SOCK_STREAM = 1; | | 889 | $SOCK_STREAM = 1; |
889 | } | | 890 | } |
890 | } else { | | 891 | } else { |
891 | $AF_INET = &AF_INET; | | 892 | $AF_INET = &AF_INET; |
892 | $SOCK_STREAM = &SOCK_STREAM; | | 893 | $SOCK_STREAM = &SOCK_STREAM; |
893 | } | | 894 | } |
894 | } else { | | 895 | } else { |
895 | $AF_INET = &AF_INET; | | 896 | $AF_INET = &AF_INET; |
896 | $SOCK_STREAM = &SOCK_STREAM; | | 897 | $SOCK_STREAM = &SOCK_STREAM; |
897 | } | | 898 | } |
898 | } | | 899 | } |