Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • hpc-team/HPCasCode
  • chines/ansible_cluster_in_a_box
2 results
Show changes
Showing
with 2121 additions and 14 deletions
# Returns ethtool statistics for given interfaces
[[inputs.ethtool]]
interval = "60s"
# List of interfaces to pull metrics for
# interface_include = ["mlx0", "p1p1"]
# List of interfaces to ignore when pulling metrics.
interface_exclude = ["eth0", "eth00", "eth1", "eth01", "eth2", "lo", "virbr0", "virbr0-nic"]
# Read metrics about the number of files in /home
[[inputs.filecount]]
directories = ["/home"]
recursive = false
regular_only = false
interval = "60s"
\ No newline at end of file
# Read metrics about the number of files in /home
[[inputs.filecount]]
directories = ["/home"]
recursive = false
regular_only = false
interval = "60s"
\ No newline at end of file
# Read mlx hardware counters
{% if hwcounterlist %}
{% for interface in hwcounterlist %}
[[inputs.multifile]]
name_override = 'infiniband'
base_dir = '/sys/class/infiniband'
interval = '60s'
[[inputs.multifile.tags]]
device = '{{ interface }}'
port = '1'
type = 'hw_counters'
{% for counter in hwcounterlist[interface] | sort %}
[[inputs.multifile.file]]
file = '{{ interface }}/ports/1/hw_counters/{{ counter }}'
conversion = 'int'
{% endfor %}
{% endfor %}
{% endif %}
# Pulls statistics from nvidia GPUs attached to the host
[[inputs.nvidia_smi]]
## Optional: path to nvidia-smi binary, defaults to $PATH via exec.LookPath
# bin_path = "/usr/bin/nvidia-smi"
## Optional: timeout for GPU polling
# timeout = "5s"
\ No newline at end of file
# Telegraf configuration
# Telegraf is entirely plugin driven. All metrics are gathered from the
# declared inputs, and sent to the declared outputs.
# Plugins must be declared in here to be active.
# To deactivate a plugin, comment out the name and any variables.
# Use 'telegraf -config telegraf.conf -test' to see what metrics a config
# file would generate.
# Global tags can be specified here in key="value" format.
[tags]
hostgroup = "{{ hostgroup | default('undefined') }}"
cluster = "{{ clustername | default('undefined') }}"
computenodeclass = "{{ computenodeclass | default('undefined') }}"
# dc = "us-east-1" # will tag all metrics with dc=us-east-1
# rack = "1a"
# Configuration for telegraf agent
[agent]
# Default data collection interval for all plugins
interval = "10s"
# Rounds collection interval to 'interval'
# ie, if interval="10s" then always collect on :00, :10, :20, etc.
round_interval = true
# Default data flushing interval for all outputs. You should not set this below
# interval. Maximum flush_interval will be flush_interval + flush_jitter
flush_interval = "60s"
# Jitter the flush interval by a random amount. This is primarily to avoid
# large write spikes for users running a large number of telegraf instances.
# ie, a jitter of 5s and interval 10s means flushes will happen every 10-15s
flush_jitter = "5s"
# Run telegraf in debug mode
debug = false
# Override default hostname, if empty use os.Hostname()
hostname = ""
## Maximum number of unwritten metrics per output. Increasing this value
## allows for longer periods of output downtime without dropping metrics at the
## cost of higher maximum memory usage.
metric_buffer_limit = 15000
###############################################################################
# OUTPUTS #
###############################################################################
# Configuration for influxdb server to send metrics to
[[outputs.influxdb]]
# The full HTTP or UDP endpoint URL for your InfluxDB instance.
# Multiple urls can be specified but it is assumed that they are part of the same
# cluster, this means that only ONE of the urls will be written to each interval.
# urls = ["udp://localhost:8089"] # UDP endpoint example
urls = ["{{ influxdb_server }}"] # required
# The target database for metrics (telegraf will create it if not exists)
database = "telegraf" # required
# Precision of writes, valid values are n, u, ms, s, m, and h
# note: using second precision greatly helps InfluxDB compression
precision = "s"
insecure_skip_verify = true
# Connection timeout (for the connection with InfluxDB), formatted as a string.
# If not provided, will default to 0 (no timeout)
# timeout = "5s"
# username = "telegraf"
# password = "metricsmetricsmetricsmetrics"
username = "{{ influxdb_user }}"
password = "{{ influxdb_password }}"
# Set the user agent for HTTP POSTs (can be useful for log differentiation)
# user_agent = "telegraf"
# Set UDP payload size, defaults to InfluxDB UDP Client default (512 bytes)
# udp_payload = 512
[outputs.influxdb.tagdrop]
influxdb_database = ["*"]
[[outputs.influxdb]]
urls = ["{{ influxdb_server }}"] # required
database = "slurm" # required
precision = "s"
insecure_skip_verify = true
username = "{{ influxdb_user }}"
password = "{{ influxdb_password }}"
[outputs.influxdb.tagpass]
influxdb_database = ["slurm"]
###############################################################################
# INPUTS #
###############################################################################
# Read metrics about cpu usage
[[inputs.cpu]]
# Whether to report per-cpu stats or not
percpu = true
# Whether to report total system cpu stats or not
totalcpu = true
# Comment this line if you want the raw CPU time metrics
drop = ["time_*"]
# Read metrics about disk usage by mount point
[[inputs.disk]]
{% if 'ComputeNodes' in group_names %}
interval = "60s"
ignore_fs = ["tmpfs", "devtmpfs", "devfs", "overlay", "aufs", "squashfs", "nfsv4", "nfs4"]
{% endif %}
{% if 'LoginNodes' in group_names %}
interval = "60s"
{% endif %}
# By default, telegraf gather stats for all mountpoints.
# Setting mountpoints will restrict the stats to the specified mountpoints.
# mount_points=["/"]
# Read metrics about disk IO by device
[[inputs.diskio]]
# By default, telegraf will gather stats for all devices including
# disk partitions.
# Setting devices will restrict the stats to the specified devices.
# devices = ["sda", "sdb"]
# Uncomment the following line if you do not need disk serial numbers.
# skip_serial_number = true
# Read ethtool for one interface only
[[inputs.ethtool]]
interface_include = ["mlx0"]
fieldpass = ["rx_discards_phy", "tx_discards_phy"]
interval="60s"
# Collect statistics about itself
[[inputs.internal]]
## If true, collect telegraf memory stats.
# collect_memstats = true
interval = "60s"
# Read metrics about memory usage
[[inputs.mem]]
# no configuration
# Read metrics about swap memory usage
[[inputs.swap]]
# no configuration
# Read metrics about system load & uptime
[[inputs.system]]
# no configuration
[[inputs.net]]
# no configuration
[[inputs.netstat]]
# no configuration
[[inputs.exec]]
commands = [
"/opt/telegraf/bin/telegraf_mountstats.py"
]
data_format = "influx"
timeout="4s"
interval="300s"
[[inputs.exec]]
commands = [
"awk -v -f /opt/telegraf/bin/telegraf_softnet_stats.awk /proc/net/softnet_stat"
]
data_format = "influx"
timeout="4s"
interval="600s"
# Both Slurm ManagementNodes will log sdiag stats, but no Compute or Login nodes will
{% if 'ManagementNodes' in group_names %}
[[inputs.exec]]
commands = [
"/opt/telegraf/bin/telegraf_slurmstats.py"
]
data_format = "influx"
timeout="4s"
interval="900s"
[inputs.exec.tags]
influxdb_database="slurm"
{% endif %}
###############################################################################
# SERVICE INPUTS #
###############################################################################
telegraf_install_rpm_url: https://dl.influxdata.com/telegraf/releases/telegraf-1.20.4-1.x86_64.rpm
telegraf_install_deb_url: https://dl.influxdata.com/telegraf/releases/telegraf_1.20.4-1_amd64.deb
---
#https://docs.tenable.com/nessus/Content/InstallNessusAgentLinux.htm
packageurl_Ubuntu: https://www.tenable.com/downloads/api/v1/public/pages/nessus-agents/downloads/17242/download?i_agree_to_tenable_license_agreement=true
packageurl_Rhel: https://www.tenable.com/downloads/api/v1/public/pages/nessus-agents/downloads/17235/download?i_agree_to_tenable_license_agreement=true
package_version: 10.1.1 #NessusAgent-10.1.1-ubuntu1110_amd64.deb
tenableSecretKey: ""
tenableLinkingKey: ""
agentgroup: ""
\ No newline at end of file
---
- name: Install nessus agent debian
apt:
deb: "{{ packageurl_Ubuntu }}"
when: ansible_os_family == 'Debian'
become: true
register: apt_
- name: Install nessus agent rhel
yum:
name: "{{ packageurl_Rhel }}"
state: present
become: true
register: yum_
when: ansible_os_family == "RedHat"
- name: start nessus agent ubuntu
service:
name: nessusagent
state: "{% if apt_.changed %}restarted{% elif not apt_.changed %}started{% endif %}"
enabled: yes
become: true
when: ansible_os_family == 'Debian'
- name: start nessus agent rhel
service:
name: nessusagent
state: "{% if yum_.changed %}restarted{% elif not yum_.changed %}started{% endif %}"
enabled: yes
become: true
when: ansible_os_family == "RedHat"
- name: get nessus agent linking status
command: /opt/nessus_agent/sbin/nessuscli agent status
register: agent_linking_status
become: true
changed_when: false
failed_when: false
- debug:
var: agent_linking_status
- name: link nessus agent
command: '/opt/nessus_agent/sbin/nessuscli agent link --key="{{ tenableLinkingKey }}" --groups="{{ agentgroup }}" --host=cloud.tenable.com --port=443 --name="{{ ansible_hostname }}" '
become: true
when: '"Linked to: cloud.tenable.com:443" not in agent_linking_status.stdout'
register: linking
# unlink via /opt/nessus_agent/sbin/nessuscli agent --help
- debug:
var: linking
---
- name: get kernel version
shell: uname -r
register: uname_r_output
check_mode: no
changed_when: False
- name: remove conflicting packages if kernel is going to changed
block:
- name: Populate service facts
service_facts:
- name: stop lustre
service: name=lustre-client state=stopped
become: true
when: services["lustre-client.service"] is defined
- name: count lustre mounts
shell:
cmd: mount -t lustre | wc -l
register: count_of_lustre_mounts
check_mode: no
become: true
when: services["lustre-client.service"] is defined
- assert:
that:
- "count_of_lustre_mounts.stdout == '0'"
msg: "Number of Lustre mounts is: {{ count_of_lustre_mounts.stdout }}"
when: services["lustre-client.service"] is defined
- name: remove conflicting packages if kernel is going to changed
package:
state: absent
name:
- kmod-lustre-client
- kernel-devel
- lustre-client-modules-dkms
- lustre-client-utils
become: true
- name: remove mellanox packages
package:
state: absent
name:
- mlnx-ofa_kernel
- mlnx-ofa_kernel-devel
- mlnx-ofa_kernel-modules
- libibverbs
- libgpod
- usbmuxd
- libmlx5
- libmlx4
- nvidia-kmod
become: true
when: uname_r_output.stdout != KERNEL_VERSION
- name: install aptitude
apt: name=aptitude state=present
become: true
become_user: root
when: ansible_os_family=="Debian"
#- name: apt-get upgrade
# apt: upgrade=safe
# become: true
# when: ansible_os_family=="Debian"
- name: yum remove
yum:
name:
- ipa-client-common
- kmod-kvdo # found on some older monarch nodes
- iwl*firmware # intel wireless Lan
state: absent
become: true
become_user: root
when: ansible_os_family=="RedHat"
- name: yum upgrade
yum:
name: '*'
state: latest
update_cache: yes
exclude: kernel*,mlnx-ofa_kernel*,kmod-lustre-client*,kmod-mlnx-ofa_kernel*,kmod-lustre-client*,lustre-client*,centos-release*,glusterfs*,redhat-release-server
become: true
become_user: root
when: (( inventory_hostname in groups.ManagementNodes ) or ( inventory_hostname in groups.SQLNodes )) and ansible_os_family=="RedHat"
- name: yum upgrade
yum:
name: '*'
state: latest
update_cache: yes
exclude: kernel*,mlnx-ofa_kernel*,kmod-lustre-client*,kmod-mlnx-ofa_kernel*,kmod-lustre-client*,lustre-client*,centos-release*,redhat-release-server
become: true
become_user: root
when: ( inventory_hostname not in groups.ManagementNodes ) and ( inventory_hostname not in groups.SQLNodes ) and ansible_os_family=="RedHat"
- name: Clear yum pending transaction
command: yum-complete-transaction --cleanup-only
become: true
become_user: root
when: ansible_os_family=="RedHat"
register: yumtransactioncleanup
changed_when: '"No unfinished transactions left." not in yumtransactioncleanup.stdout'
- name: install centos-release
yum:
name:
- centos-release-{{ CENTOS_VERSION }}
state: present
allow_downgrade: true
become: true
when:
- ansible_os_family=="RedHat"
- '"DGX" not in ansible_product_name'
- name: install redhat-release-server
yum:
name:
- redhat-release-server-{{ RHEL_VERSION }}
state: present
allow_downgrade: true
when:
- '"DGX" in ansible_product_name'
- '"RedHat" in ansible_distribution'
become: true
become_user: root
- name: install kernel-devel
yum:
name:
- kernel-devel-{{ KERNEL_VERSION }}
- kernel-{{ KERNEL_VERSION }}
- kernel-headers-{{ KERNEL_VERSION }}
- kernel-tools-{{ KERNEL_VERSION }}
- kernel-tools-libs-{{ KERNEL_VERSION }}
state: present
allow_downgrade: true
become: true
when: ansible_os_family=="RedHat"
- name: get kernel-devel version
shell: rpm -q kernel-devel | cut -f 3,4 -d "-" | sort | tail -n 1
register: rpm_q_output
when: ansible_os_family=="RedHat"
check_mode: no
changed_when: False
args:
warn: False
- name: get kernel-devel version
shell: dpkg -l linux-image* | grep "^ii" | grep "linux-image-[0-9]" | sed 's/\ \ */ /g' | cut -f 2 -d " " | cut -f 3-5 -d "-"
register: dpkg_l_output
when: ansible_os_family=="Debian"
check_mode: no
changed_when: False
- name: get kernel version
shell: uname -r
register: uname_r_output
check_mode: no
changed_when: False
- name: default dont reboot
set_fact:
reboot_now: false
- name: debug1
debug: var=rpm_q_output
- name: debug2
debug: var=uname_r_output
- name: set reboot when kernel has changed
set_fact:
reboot_now: true
when: ansible_os_family=="RedHat" and not uname_r_output.stdout in rpm_q_output.stdout
- name: set reboot when kernel has changed
set_fact:
reboot_now: true
when: ansible_os_family=="Debian" and not uname_r_output.stdout in dpkg_l_output.stdout
- name: debug3
debug: var=reboot_now
- name: restart machine
reboot:
become: true
when: reboot_now
def used(role):
import subprocess
p = subprocess.call("grep {} *".format(role))
return p == 0
with open('roles.txt') as f:
roles = f.readlines()
for r in roles:
print("{},{}".format(r,used(r)))
---
- include_vars: "{{ ansible_os_family }}_{{ ansible_architecture }}.yml"
- name: restart ssh
service: name={{ sshd_name }} state=restarted
become: true
---
- include_vars: "{{ ansible_os_family }}_{{ ansible_architecture }}.yml"
- name: copy ca cert
copy: src=user_ssh_ca.pub dest=/etc/ssh/server_ca.pub owner=root group=root mode=644
become: true
ignore_errors: true
- name: edit sshd_config
lineinfile:
args:
dest: /etc/ssh/sshd_config
line: TrustedUserCAKeys /etc/ssh/server_ca.pub
state: present
become: true
notify: restart ssh
ignore_errors: true
sshd_name: "ssh"
sshd_name: "sshd"
---
#- include_vars: "{{ hostvars[ansible_hostname]['ansible_distribution'] }}_{{ ansible_architecture }}.yml"
- include_vars: "{{ ansible_distribution }}_{{ ansible_architecture }}.yml"
- name: add repos apt
shell: "add-apt-repository -y 'deb {{ item }} {{ ansible_distribution_release }} main' "
sudo: true
with_items: apt_repos
when: ansible_os_family == 'Debian'
- include_vars: "CentOS_7_x86_64.yml"
when: ansible_distribution == "CentOS" and ansible_distribution_major_version == "7"
- name: install system packages apt
apt: name={{ item }} state=installed update_cache=true force=yes
sudo: true
with_items: system_packages
apt: name={{ system_packages }} state=present update_cache=true
become: true
register: apt_status
until: apt_status is success
delay: 6
retries: 10
when: ansible_os_family == 'Debian'
- name: force the use of mate desktop
template:
src: vncserver.ubuntu
dest: /usr/bin/vncserver
owner: root
group: root
mode: u=rxw,g=rx,o=rx
become: true
when: ansible_os_family == 'Debian'
- name: install system packages yum
yum: name={{ item }} state=installed
sudo: true
with_items: system_packages
when: ansible_os_family == 'RedHat'
- name: query the default x-session
shell: update-alternatives --query x-session-manager | grep Value
become: true
check_mode: no
changed_when: false
register: qxsessionmanager
when: ansible_os_family == 'Debian'
- name: make mate the default x-session
shell: update-alternatives --set x-session-manager /usr/bin/mate-session
become: true
when: ansible_os_family == 'Debian' and "mate" not in qxsessionmanager.stdout
#!/usr/bin/perl
#
# Copyright (C) 2009-2010 D. R. Commander. All Rights Reserved.
# Copyright (C) 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
# Copyright (C) 2002-2003 Constantin Kaplinsky. All Rights Reserved.
# Copyright (C) 2002-2005 RealVNC Ltd.
# Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
# USA.
#
#
# vncserver - wrapper script to start an X VNC server.
#
#
# First make sure we're operating in a sane environment.
#
$exedir = "";
$slashndx = rindex($0, "/");
if($slashndx>=0) {
$exedir = substr($0, 0, $slashndx+1);
}
$vncClasses = "";
$xauth = "xauth";
&SanityCheck();
#
# Global variables. You may want to configure some of these for your site.
#
$geometry = "1024x768";
#$depth = 16;
$vncJavaFiles = (((-d "$vncClasses") && "$vncClasses") ||
((-d "/usr/share/vnc/classes") && "/usr/share/vnc/classes") ||
((-d "/usr/local/vnc/classes") && "/usr/local/vnc/classes"));
$vncUserDir = "$ENV{HOME}/.vnc";
$xauthorityFile = "$ENV{XAUTHORITY}" || "$ENV{HOME}/.Xauthority";
$defaultXStartup
= ("#!/bin/sh\n\n".
"unset SESSION_MANAGER\n".
"unset DBUS_SESSION_BUS_ADDRESS\n".
"exec startkde\n");
chop($host = `uname -n`);
if (-d "/etc/X11/fontpath.d") {
$fontPath = "catalogue:/etc/X11/fontpath.d";
}
@fontpaths = ('/usr/share/X11/fonts', '/usr/share/fonts', '/usr/share/fonts/X11/');
if (! -l "/usr/lib/X11") {push(@fontpaths, '/usr/lib/X11/fonts');}
if (! -l "/usr/X11") {push(@fontpaths, '/usr/X11/lib/X11/fonts');}
if (! -l "/usr/X11R6") {push(@fontpaths, '/usr/X11R6/lib/X11/fonts');}
push(@fontpaths, '/usr/share/fonts/default');
@fonttypes = ('misc',
'75dpi',
'100dpi',
'Speedo',
'Type1');
foreach $_fpath (@fontpaths) {
foreach $_ftype (@fonttypes) {
if (-f "$_fpath/$_ftype/fonts.dir") {
if (! -l "$_fpath/$_ftype") {
$defFontPath .= "$_fpath/$_ftype,";
}
}
}
}
if ($defFontPath) {
if (substr($defFontPath, -1, 1) == ',') {
chop $defFontPath;
}
}
if ($fontPath eq "") {
$fontPath = $defFontPath;
}
# Check command line options
&ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1,
"-help",0,"-h",0,"--help",0,"-fp",1,"-list",0,"-fg",0,"-autokill",0);
&Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'});
&Kill() if ($opt{'-kill'});
&List() if ($opt{'-list'});
# Uncomment this line if you want default geometry, depth and pixelformat
# to match the current X display:
# &GetXDisplayDefaults();
if ($opt{'-geometry'}) {
$geometry = $opt{'-geometry'};
}
if ($opt{'-depth'}) {
$depth = $opt{'-depth'};
$pixelformat = "";
}
if ($opt{'-pixelformat'}) {
$pixelformat = $opt{'-pixelformat'};
}
if ($opt{'-fp'}) {
$fontPath = $opt{'-fp'};
$fpArgSpecified = 1;
}
&CheckGeometryAndDepth();
# Create the user's vnc directory if necessary.
if (!(-e $vncUserDir)) {
if (!mkdir($vncUserDir,0755)) {
die "$prog: Could not create $vncUserDir.\n";
}
}
# Check whether VNC authentication is enabled, and if so, prompt the user to
# create a VNC password if they don't already have one.
$securityTypeArgSpecified = 0;
$vncAuthEnabled = 0;
$passwordArgSpecified = 0;
for ($i = 0; $i < @ARGV; ++$i) {
# -SecurityTypes can be followed by a space or "="
my @splitargs = split('=', $ARGV[$i]);
if (@splitargs <= 1 && $i < @ARGV - 1) {
push(@splitargs, $ARGV[$i + 1]);
}
if (lc(@splitargs[0]) eq "-securitytypes") {
if (@splitargs > 1) {
$securityTypeArgSpecified = 1;
}
foreach $arg2 (split(',', @splitargs[1])) {
if (lc($arg2) eq "vncauth" || lc($arg2) eq "tlsvnc"
|| lc($arg2) eq "x509vnc") {
$vncAuthEnabled = 1;
}
}
}
if ((lc(@splitargs[0]) eq "-password")
|| (lc(@splitargs[0]) eq "-passwordfile"
|| (lc(@splitargs[0]) eq "-rfbauth"))) {
$passwordArgSpecified = 1;
}
}
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;
}
}
}
# Find display number.
if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) {
$displayNumber = $1;
shift(@ARGV);
if (!&CheckDisplayNumber($displayNumber)) {
die "A VNC server is already running as :$displayNumber\n";
}
} elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/) && ($ARGV[0] !~ /^\+/)) {
&Usage();
} else {
$displayNumber = &GetDisplayNumber();
}
$vncPort = 5900 + $displayNumber;
$desktopLog = "$vncUserDir/$host:$displayNumber.log";
unlink($desktopLog);
# Make an X server cookie - use mcookie
$cookie = `/usr/bin/mcookie`;
open (XAUTH, "|xauth -f $xauthorityFile source -");
print XAUTH "add $host:$displayNumber . $cookie\n";
print XAUTH "add $host/unix:$displayNumber . $cookie\n";
close XAUTH;
if ($opt{'-name'}) {
$desktopName = $opt{'-name'};
} else {
$desktopName = "$host:$displayNumber ($ENV{USER})";
}
# Now start the X VNC Server
$cmd = $exedir."Xvnc :$displayNumber";
$cmd .= " -desktop " . &quotedString($desktopName);
$cmd .= " -httpd $vncJavaFiles" if ($vncJavaFiles);
$cmd .= " -auth $xauthorityFile";
$cmd .= " -geometry $geometry" if ($geometry);
$cmd .= " -depth $depth" if ($depth);
$cmd .= " -pixelformat $pixelformat" if ($pixelformat);
$cmd .= " -rfbwait 30000";
$cmd .= " -rfbauth $vncUserDir/passwd";
$cmd .= " -rfbport $vncPort";
$cmd .= " -fp $fontPath" if ($fontPath);
$cmd .= " -pn";
# Add color database stuff here, e.g.:
#
# $cmd .= " -co /usr/lib/X11/rgb";
#
foreach $arg (@ARGV) {
$cmd .= " " . &quotedString($arg);
}
$cmd .= " >> " . &quotedString($desktopLog) . " 2>&1";
# Run $cmd and record the process ID.
$pidFile = "$vncUserDir/$host:$displayNumber.pid";
system("$cmd & echo \$! >$pidFile");
# Give Xvnc a chance to start up
sleep(3);
if ($fontPath ne $defFontPath) {
unless (kill 0, `cat $pidFile`) {
if ($fpArgSpecified) {
warn "\nWARNING: The first attempt to start Xvnc failed, probably because the font\n";
warn "path you specified using the -fp argument is incorrect. Attempting to\n";
warn "determine an appropriate font path for this system and restart Xvnc using\n";
warn "that font path ...\n";
} else {
warn "\nWARNING: The first attempt to start Xvnc failed, possibly because the font\n";
warn "catalog is not properly configured. Attempting to determine an appropriate\n";
warn "font path for this system and restart Xvnc using that font path ...\n";
}
$cmd =~ s@-fp [^ ]+@@;
$cmd .= " -fp $defFontPath" if ($defFontPath);
system("$cmd & echo \$! >$pidFile");
sleep(3);
}
}
unless (kill 0, `cat $pidFile`) {
warn "Could not start Xvnc.\n\n";
open(LOG, "<$desktopLog");
while (<LOG>) { print; }
close(LOG);
die "\n";
}
warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n";
# Create the user's xstartup script if necessary.
if (!(-e "$vncUserDir/xstartup")) {
warn "Creating default startup script $vncUserDir/xstartup\n";
open(XSTARTUP, ">$vncUserDir/xstartup");
print XSTARTUP $defaultXStartup;
close(XSTARTUP);
chmod 0755, "$vncUserDir/xstartup";
}
# Run the X startup script.
warn "Starting applications specified in $vncUserDir/xstartup\n";
warn "Log file is $desktopLog\n\n";
# If the unix domain socket exists then use that (DISPLAY=:n) otherwise use
# TCP (DISPLAY=host:n)
if (-e "/tmp/.X11-unix/X$displayNumber" ||
-e "/usr/spool/sockets/X11/$displayNumber")
{
$ENV{DISPLAY}= ":$displayNumber";
} else {
$ENV{DISPLAY}= "$host:$displayNumber";
}
$ENV{VNCDESKTOP}= $desktopName;
system($exedir."vncconfig -iconic >> " . &quotedString($desktopLog) . " 2>&1 &");
if ($opt{'-fg'}) {
system("$vncUserDir/xstartup >> " . &quotedString($desktopLog) . " 2>&1");
if (kill 0, `cat $pidFile`) {
$opt{'-kill'} = ':'.$displayNumber;
&Kill();
}
} else {
if ($opt{'-autokill'}) {
system("($vncUserDir/xstartup; $0 -kill :$displayNumber) >> "
. &quotedString($desktopLog) . " 2>&1 &");
} else {
system("$vncUserDir/xstartup >> " . &quotedString($desktopLog)
. " 2>&1 &");
}
}
exit;
###############################################################################
#
# CheckGeometryAndDepth simply makes sure that the geometry and depth values
# are sensible.
#
sub CheckGeometryAndDepth
{
if ($geometry =~ /^(\d+)x(\d+)$/) {
$width = $1; $height = $2;
if (($width<1) || ($height<1)) {
die "$prog: geometry $geometry is invalid\n";
}
$geometry = "${width}x$height";
} else {
die "$prog: geometry $geometry is invalid\n";
}
if ($depth && (($depth < 8) || ($depth > 32))) {
die "Depth must be between 8 and 32\n";
}
}
#
# GetDisplayNumber gets the lowest available display number. A display number
# n is taken if something is listening on the VNC server port (5900+n) or the
# X server port (6000+n).
#
sub GetDisplayNumber
{
foreach $n (1..99) {
if (&CheckDisplayNumber($n)) {
return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02
}
}
die "$prog: no free display number on $host.\n";
}
#
# CheckDisplayNumber checks if the given display number is available. A
# display number n is taken if something is listening on the VNC server port
# (5900+n) or the X server port (6000+n).
#
sub CheckDisplayNumber
{
local ($n) = @_;
socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
if (!bind(S, pack('S n x12', $AF_INET, 6000 + $n))) {
close(S);
return 0;
}
close(S);
socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
if (!bind(S, pack('S n x12', $AF_INET, 5900 + $n))) {
close(S);
return 0;
}
close(S);
if (-e "/tmp/.X$n-lock") {
warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n";
warn "Remove this file if there is no X server $host:$n\n";
return 0;
}
if (-e "/tmp/.X11-unix/X$n") {
warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n";
warn "Remove this file if there is no X server $host:$n\n";
return 0;
}
if (-e "/usr/spool/sockets/X11/$n") {
warn("\nWarning: $host:$n is taken because of ".
"/usr/spool/sockets/X11/$n\n");
warn "Remove this file if there is no X server $host:$n\n";
return 0;
}
return 1;
}
#
# GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel
# format of the current X display being used. If successful, it sets the
# options as appropriate so that the X VNC server will use the same settings
# (minus an allowance for window manager decorations on the geometry). Using
# the same depth and pixel format means that the VNC server won't have to
# translate pixels when the desktop is being viewed on this X display (for
# TrueColor displays anyway).
#
sub GetXDisplayDefaults
{
local (@lines, @matchlines, $width, $height, $defaultVisualId, $i,
$red, $green, $blue);
$wmDecorationWidth = 4; # a guess at typical size for window manager
$wmDecorationHeight = 24; # decoration size
return if (!defined($ENV{DISPLAY}));
@lines = `xdpyinfo 2>/dev/null`;
return if ($? != 0);
@matchlines = grep(/dimensions/, @lines);
if (@matchlines) {
($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/);
$width -= $wmDecorationWidth;
$height -= $wmDecorationHeight;
$geometry = "${width}x$height";
}
@matchlines = grep(/default visual id/, @lines);
if (@matchlines) {
($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/);
for ($i = 0; $i < @lines; $i++) {
if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) {
if (($lines[$i+1] !~ /TrueColor/) ||
($lines[$i+2] !~ /depth/) ||
($lines[$i+4] !~ /red, green, blue masks/))
{
return;
}
last;
}
}
return if ($i >= @lines);
($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/);
($red,$green,$blue)
= ($lines[$i+4]
=~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/);
$red = hex($red);
$green = hex($green);
$blue = hex($blue);
if ($red > $blue) {
$red = int(log($red) / log(2)) - int(log($green) / log(2));
$green = int(log($green) / log(2)) - int(log($blue) / log(2));
$blue = int(log($blue) / log(2)) + 1;
$pixelformat = "rgb$red$green$blue";
} else {
$blue = int(log($blue) / log(2)) - int(log($green) / log(2));
$green = int(log($green) / log(2)) - int(log($red) / log(2));
$red = int(log($red) / log(2)) + 1;
$pixelformat = "bgr$blue$green$red";
}
}
}
#
# quotedString returns a string which yields the original string when parsed
# by a shell.
#
sub quotedString
{
local ($in) = @_;
$in =~ s/\'/\'\"\'\"\'/g;
return "'$in'";
}
#
# removeSlashes turns slashes into underscores for use as a file name.
#
sub removeSlashes
{
local ($in) = @_;
$in =~ s|/|_|g;
return "$in";
}
#
# Usage
#
sub Usage
{
die("\nusage: $prog [:<number>] [-name <desktop-name>] [-depth <depth>]\n".
" [-geometry <width>x<height>]\n".
" [-pixelformat rgbNNN|bgrNNN]\n".
" [-fp <font-path>]\n".
" [-cc <visual>]\n".
" [-fg]\n".
" [-autokill]\n".
" <Xvnc-options>...\n\n".
" $prog -kill <X-display>\n\n".
" $prog -list\n\n");
}
#
# List
#
sub List
{
opendir(dir, $vncUserDir);
my @filelist = readdir(dir);
closedir(dir);
print "\nTigerVNC server sessions:\n\n";
print "X DISPLAY #\tPROCESS ID\n";
foreach my $file (@filelist) {
if ($file =~ /$host:(\d+)$\.pid/) {
print ":".$1."\t\t".`cat $vncUserDir/$file`;
}
}
exit 1;
}
#
# Kill
#
sub Kill
{
$opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1
if ($opt{'-kill'} =~ /^:\d+$/) {
$pidFile = "$vncUserDir/$host$opt{'-kill'}.pid";
} else {
if ($opt{'-kill'} !~ /^$host:/) {
die "\nCan't tell if $opt{'-kill'} is on $host\n".
"Use -kill :<number> instead\n\n";
}
$pidFile = "$vncUserDir/$opt{'-kill'}.pid";
}
if (! -r $pidFile) {
die "\nCan't find file $pidFile\n".
"You'll have to kill the Xvnc process manually\n\n";
}
$SIG{'HUP'} = 'IGNORE';
chop($pid = `cat $pidFile`);
warn "Killing Xvnc process ID $pid\n";
if (kill 0, $pid) {
system("kill $pid");
sleep(1);
if (kill 0, $pid) {
print "Xvnc seems to be deadlocked. Kill the process manually and then re-run\n";
print " ".$0." -kill ".$opt{'-kill'}."\n";
print "to clean up the socket files.\n";
exit
}
} else {
warn "Xvnc process ID $pid already killed\n";
$opt{'-kill'} =~ s/://;
if (-e "/tmp/.X11-unix/X$opt{'-kill'}") {
print "Xvnc did not appear to shut down cleanly.";
print " Removing /tmp/.X11-unix/X$opt{'-kill'}\n";
unlink "/tmp/.X11-unix/X$opt{'-kill'}";
}
if (-e "/tmp/.X$opt{'-kill'}-lock") {
print "Xvnc did not appear to shut down cleanly.";
print " Removing /tmp/.X$opt{'-kill'}-lock\n";
unlink "/tmp/.X$opt{'-kill'}-lock";
}
}
unlink $pidFile;
exit;
}
#
# ParseOptions takes a list of possible options and a boolean indicating
# whether the option has a value following, and sets up an associative array
# %opt of the values of the options given on the command line. It removes all
# the arguments it uses from @ARGV and returns them in @optArgs.
#
sub ParseOptions
{
local (@optval) = @_;
local ($opt, @opts, %valFollows, @newargs);
while (@optval) {
$opt = shift(@optval);
push(@opts,$opt);
$valFollows{$opt} = shift(@optval);
}
@optArgs = ();
%opt = ();
arg: while (defined($arg = shift(@ARGV))) {
foreach $opt (@opts) {
if ($arg eq $opt) {
push(@optArgs, $arg);
if ($valFollows{$opt}) {
if (@ARGV == 0) {
&Usage();
}
$opt{$opt} = shift(@ARGV);
push(@optArgs, $opt{$opt});
} else {
$opt{$opt} = 1;
}
next arg;
}
}
push(@newargs,$arg);
}
@ARGV = @newargs;
}
#
# Routine to make sure we're operating in a sane environment.
#
sub SanityCheck
{
local ($cmd);
#
# Get the program name
#
($prog) = ($0 =~ m|([^/]+)$|);
#
# Check we have all the commands we'll need on the path.
#
cmd:
foreach $cmd ("uname") {
for (split(/:/,$ENV{PATH})) {
if (-x "$_/$cmd") {
next cmd;
}
}
die "$prog: couldn't find \"$cmd\" on your PATH.\n";
}
if (-x "/usr/X11R6/bin/xauth") {
$xauth = "/usr/X11R6/bin/xauth";
}
else {
cmd1:
foreach $cmd ("xauth") {
for (split(/:/,$ENV{PATH})) {
if (-x "$_/$cmd") {
next cmd1;
}
}
die "$prog: couldn't find \"$cmd\" on your PATH.\n";
}
}
if($exedir eq "") {
cmd2:
foreach $cmd ("Xvnc","vncpasswd") {
for (split(/:/,$ENV{PATH})) {
if (-x "$_/$cmd") {
$vncClasses = "$_/../vnc/classes";
next cmd2;
}
}
die "$prog: couldn't find \"$cmd\" on your PATH.\n";
}
}
else {
cmd3:
foreach $cmd ($exedir."Xvnc",$exedir."vncpasswd") {
for (split(/:/,$ENV{PATH})) {
if (-x "$cmd") {
$vncClasses = $exedir."../vnc/classes";
next cmd3;
}
}
die "$prog: couldn't find \"$cmd\".\n";
}
}
#
# Check the HOME environment variable is set
#
if (!defined($ENV{HOME})) {
die "$prog: The HOME environment variable is not set.\n";
}
# chdir($ENV{HOME});
#
# Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an
# eval, and if it fails we try 'require "sys/socket.ph"'. If this fails,
# we just guess at the values. If you find perl moaning here, just
# hard-code the values of AF_INET and SOCK_STREAM. You can find these out
# for your platform by looking in /usr/include/sys/socket.h and related
# files.
#
chop($os = `uname`);
chop($osrev = `uname -r`);
eval 'use Socket';
if ($@) {
eval 'require "sys/socket.ph"';
if ($@) {
if (($os eq "SunOS") && ($osrev !~ /^4/)) {
$AF_INET = 2;
$SOCK_STREAM = 2;
} else {
$AF_INET = 2;
$SOCK_STREAM = 1;
}
} else {
$AF_INET = &AF_INET;
$SOCK_STREAM = &SOCK_STREAM;
}
} else {
$AF_INET = &AF_INET;
$SOCK_STREAM = &SOCK_STREAM;
}
}
#!/usr/bin/perl
#
# Copyright (C) 2004-2006,2008-2009 Ola Lundqvist <opal@debian.org>
# Copyright (C) 2002-2003 Constantin Kaplinsky. All Rights Reserved.
# Copyright (C) 1999 AT&T Laboratories Cambridge. All Rights Reserved.
#
# This is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this software; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
# USA.
#
#
# vncserver - wrapper script to start an X VNC server.
#
# This file was heavily edited by
# Ola Lundqvist <opal@debian.org>
# Marcus Brinkmann <Marcus.Brinkmann@ruhr-uni-bochum.de>
# Clean option by Dirk Eddelbuettel <edd@debian.org>
# Please report all errors to Debian and not to ORL.
#
# First make sure we're operating in a sane environment.
#
&SanityCheck();
#
# Global variables. You may want to configure some of these for your site.
#
$geometry = "1024x768";
$depth = 24;
$desktopName = "X";
if (-d "/usr/share/tightvnc-java") {
$vncClasses = "/usr/share/tightvnc-java";
}
$vncUserDir = "$ENV{HOME}/.vnc";
#$fontPath = "unix/:7100";
$authType = "-rfbauth $vncUserDir/passwd";
# Here is another example of setting the font path:
# $fontPath = "/usr/lib/X11/fonts/misc/,/usr/lib/X11/fonts/75dpi/";
# X colors database path is optional, uncomment and edit to use:
# $colorPath = "/usr/lib/X11/rgb";
# You might wish to make your vnc directory under /tmp, to make sure
# passwords are always kept on the local filesystem. To do that, just
# uncomment the line below. Note that in this case Xtightvnc's .Xauthority
# file will be searched in the same $vncUserDir directory by default,
# and $ENV{HOME}/.vncstartup will be executed instead of usual
# $vncUserDir/xstartup.
#
# $vncUserDir = "/tmp/$ENV{USER}-vnc";
$defaultXStartup
= ("#!/bin/sh\n\n".
"xrdb \$HOME/.Xresources\n".
"xsetroot -solid grey\n".
"#x-terminal-emulator -geometry 80x24+10+10 -ls -title \"\$VNCDESKTOP Desktop\" &\n".
"#x-window-manager &\n".
"# Fix to make GNOME work\n".
"export XKL_XMODMAP_DISABLE=1\n".
"exec mate-session\n");
$xauthorityFile = "$ENV{XAUTHORITY}";
######## Adding configuration possibility ################
$Config_file = "/etc/vnc.conf";
&ReadConfigFile();
$Config_file = "$ENV{HOME}/.vncrc";
&ReadConfigFile();
if (!$XFConfigPath) {
foreach ("/etc/X11/xorg.conf", "/etc/X11/XF86Config-4", "/etc/X11/XF86Config" ){
$XFConfigPath = $_;
last if ( -e $XFConfigPath );
}
}
if (!$fontPath) {
&ReadXFConfigFont;
}
if (!$fontPath) {
$fontPath = "/usr/share/fonts/X11/misc/,".
"/usr/share/fonts/X11/Type1/,".
"/usr/share/fonts/X11/75dpi/,".
"/usr/share/fonts/X11/100dpi/"
}
if (!$colorPath) {
&ReadXFConfigColor;
}
if (!$colorPath) {
foreach ("/etc/X11/rgb", "/usr/share/X11/rgb", "/usr/X11R6/lib/X11/rgb"){
$colorPath = $_;
last if ( -e "${colorPath}.txt" );
}
}
##########################################################
$vncUserDirUnderTmp = ($vncUserDir =~ m|^/tmp/.+|) ? 1 : 0;
$xstartup = ($vncUserDirUnderTmp) ?
"$ENV{HOME}/.vncstartup" : "$vncUserDir/xstartup";
$xstartup = $vncStartup if ($vncStartup);
unless ($xauthorityFile) {
if ($vncUserDirUnderTmp) {
$xauthorityFile = "$vncUserDir/.Xauthority";
} else {
$xauthorityFile = "$ENV{HOME}/.Xauthority";
}
}
chop($host = `uname -n`);
# Check command line options
&ParseOptions("-geometry",1,"-depth",1,"-pixelformat",1,"-name",1,"-kill",1,
"-help",0,"-h",0,"--help",0,
"-clean",0, "-fp",1,
"-alwaysshared",0, "-nevershared",0,
"-httpport",1,"-basehttpport",1);
&Usage() if ($opt{'-help'} || $opt{'-h'} || $opt{'--help'});
&Kill() if ($opt{'-kill'});
$useClasses = 0;
if (defined $vncClasses) {
if(! -d $vncClasses) {
die "VNC class files can not be found at $vncClasses.";
}
$useClasses = 1;
}
# Uncomment this line if you want default geometry, depth and pixelformat
# to match the current X display:
# &GetXDisplayDefaults();
if ($opt{'-geometry'}) {
$geometry = $opt{'-geometry'};
}
if ($opt{'-depth'}) {
$depth = $opt{'-depth'};
$pixelformat = "";
}
if ($opt{'-pixelformat'}) {
$pixelformat = $opt{'-pixelformat'};
}
if ($opt{'-fp'}) {
@fontPathElements = split(/\s*,\s*/, "$opt{'-fp'}");
$fontPath = '';
foreach $i (0.."$#fontPathElements") {
$tempFontPath = $fontPathElements[$i];
if ($tempFontPath !~ m!^[^/]*/[^/]*:\d+$!) {
$tempFontPath =~ s/:unscaled$//;
if (-r "$tempFontPath/fonts.dir") {
$fontPath .= "$fontPathElements[$i],";
}
} else {
$fontPath .= "$fontPathElements[$i],";
}
}
chop $fontPath;
}
&CheckGeometryAndDepth();
if ($opt{'-name'}) {
$desktopName = $opt{'-name'};
}
# Create the user's vnc directory if necessary.
unless (-e $vncUserDir) {
unless (mkdir($vncUserDir, 0700)) {
die "$prog: Could not create $vncUserDir.\n";
}
}
($z,$z,$mode) = stat("$vncUserDir");
if (!-d _ || !-o _ || ($vncUserDirUnderTmp && ($mode & 0777) != 0700)) {
die "$prog: Wrong type or access mode of $vncUserDir.\n";
}
# Make sure the user has a password.
($z,$z,$mode) = stat("$vncUserDir/passwd");
if (-e _ && (!-f _ || !-o _)) {
die "$prog: Wrong type or ownership on $vncUserDir/passwd.\n";
}
if (!-e _ || ($mode & 077) != 0) {
warn "\nYou will require a password to access your desktops.\n\n";
system("vncpasswd $vncUserDir/passwd");
if (($? & 0xFF00) != 0) {
exit 1;
}
}
# Find display number.
if ((@ARGV > 0) && ($ARGV[0] =~ /^:(\d+)$/)) {
$displayNumber = $1;
shift(@ARGV);
unless (&CheckDisplayNumber($displayNumber)) {
die "A VNC server is already running as :$displayNumber\n";
}
} elsif ((@ARGV > 0) && ($ARGV[0] !~ /^-/)) {
&Usage();
} else {
$displayNumber = &GetDisplayNumber();
}
$vncPort = 5900 + $displayNumber;
$desktopLog = "$vncUserDir/$host:$displayNumber.log";
unlink($desktopLog);
# Make an X server cookie - use as the seed the sum of the current time, our
# PID and part of the encrypted form of the password. Ideally we'd use
# /dev/urandom, but that's only available on Linux.
srand(time+$$+unpack("L",`cat $vncUserDir/passwd`));
$cookie = "";
for (1..16) {
$cookie .= sprintf("%02x", int(rand(256)));
}
system("xauth -f $xauthorityFile add $host:$displayNumber . $cookie");
system("xauth -f $xauthorityFile add $host/unix:$displayNumber . $cookie");
# Now start the X VNC Server
$cmd = "Xtightvnc :$displayNumber";
$cmd .= " -desktop " . &quotedString($desktopName);
if ($useClasses) {
$cmd .= " -httpd $vncClasses";
print ("Found $vncClasses for http connections.\n");
if ($opt{'-httpport'}) {
$cmd .= " -httpport $opt{'-httpport'}";
print ("Listening to $opt{'-httpport'} for http connections.\n");
}
elsif ($opt{'-basehttpport'}) {
my $v = $opt{'-basehttpport'} + $displayNumber;
print ("Listening to $v for http connections.\n");
$cmd .= " -httpport $v";
}
}
$cmd .= " -auth $xauthorityFile";
$cmd .= " -geometry $geometry" if ($geometry);
$cmd .= " -depth $depth" if ($depth);
$cmd .= " -pixelformat $pixelformat" if ($pixelformat);
$cmd .= " -rfbwait 120000";
$cmd .= " $authType";
$cmd .= " -rfbport $vncPort";
$cmd .= " -fp $fontPath" if ($fontPath);
$cmd .= " -co $colorPath" if ($colorPath);
$cmd .= " -alwaysshared" if ($opt{'-alwaysshared'});
$cmd .= " -nevershared" if ($opt{'-nevershared'});
foreach $arg (@ARGV) {
$cmd .= " " . &quotedString($arg);
}
$cmd .= " >> " . &quotedString($desktopLog) . " 2>&1";
# Run $cmd and record the process ID.
$pidFile = "$vncUserDir/$host:$displayNumber.pid";
system("$cmd & echo \$! >$pidFile");
# Give Xtightvnc a chance to start up
sleep(1);
unless (kill 0, `cat $pidFile`) {
warn "Couldn't start Xtightvnc; trying default font path.\n";
warn "Please set correct fontPath in the $prog script.\n";
$cmd =~ s@-fp [^ ]+@@;
system("$cmd & echo \$! >$pidFile");
sleep(1);
}
unless (kill 0, `cat $pidFile`) {
warn "Couldn't start Xtightvnc process.\n\n";
open(LOG, "<$desktopLog");
while (<LOG>) { print; }
close(LOG);
die "\n";
}
warn "\nNew '$desktopName' desktop is $host:$displayNumber\n\n";
# Create the user's xstartup script if necessary.
unless (-e "$xstartup") {
warn "Creating default startup script $xstartup\n";
open(XSTARTUP, ">$xstartup");
print XSTARTUP $defaultXStartup;
close(XSTARTUP);
chmod 0755, "$xstartup";
}
# Run the X startup script.
warn "Starting applications specified in $xstartup\n";
warn "Log file is $desktopLog\n\n";
# If the unix domain socket exists then use that (DISPLAY=:n) otherwise use
# TCP (DISPLAY=host:n)
if (-e "/tmp/.X11-unix/X$displayNumber") {
$ENV{DISPLAY}= ":$displayNumber";
} else {
$ENV{DISPLAY}= "$host:$displayNumber";
}
$ENV{VNCDESKTOP}= $desktopName;
system("$xstartup >> " . &quotedString($desktopLog) . " 2>&1 &");
exit;
############################ Debian functions #################################
# I thank Manoj for the code below.
#
# ReadConfigFile reads in a config file and sets variables according to it.
#
sub ReadConfigFile
{
open(CONFIG, "$Config_file") || return;
my $lineno = 0;
while (<CONFIG>) {
chomp;
$lineno++;
s/\#.*//og;
next if /^\s*$/og;
$_ .= ";" unless /;\s*$/;
if (/^\s*([^=]+)\s*=\s*(\S.*)$/o) {
my $ret = eval "$1=$2";
if ($@) {
print STDERR "Error parsing config file $Config_file!\n";
print STDERR "$lineno:$_\n";
}
}
}
}
sub ReadXFConfigFont
{
open(CONFIG, "$XFConfigPath") || return;
my $lineno = 0;
while (<CONFIG>) {
chomp;
$lineno++;
s/\#.*//og;
next if /^\s*$/og;
if (/^\s*FontPath\s*"(\S.*)"\s*$/o) {
$fontPath .= "," if $fontPath;
$fontPath .= $1;
}
}
}
sub ReadXFConfigColor
{
open(CONFIG, "$XFConfigPath") || return;
my $lineno = 0;
while (<CONFIG> && !$colorPath) {
chomp;
$lineno++;
s/\#.*//og;
next if /^\s*$/og;
if (/^\s*RgbPath\s*"(\S.*)"\s*$/o) {
$colorPath = $1;
}
}
}
########## End of debian functions ###########
###############################################################################
#
# CheckGeometryAndDepth simply makes sure that the geometry and depth values
# are sensible.
#
sub CheckGeometryAndDepth
{
if ($geometry =~ /^(\d+)x(\d+)$/) {
$width = $1; $height = $2;
if (($width<1) || ($height<1)) {
die "$prog: geometry $geometry is invalid\n";
}
while (($width % 4)!=0) {
$width = $width + 1;
}
while (($height % 2)!=0) {
$height = $height + 1;
}
$geometry = "${width}x$height";
} else {
die "$prog: geometry $geometry is invalid\n";
}
if (($depth < 8) || ($depth > 32)) {
die "Depth must be between 8 and 32\n";
}
}
#
# GetDisplayNumber gets the lowest available display number. A display number
# n is taken if something is listening on the VNC server port (5900+n) or the
# X server port (6000+n).
#
sub GetDisplayNumber
{
foreach $n (1..99) {
if (&CheckDisplayNumber($n)) {
return $n+0; # Bruce Mah's workaround for bug in perl 5.005_02
}
}
die "$prog: no free display number on $host.\n";
}
#
# CheckDisplayNumber checks if the given display number is available. A
# display number n is taken if something is listening on the VNC server port
# (5900+n) or the X server port (6000+n).
#
sub CheckDisplayNumber
{
local ($n) = @_;
socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
#unless (bind(S, pack('S n x12', $AF_INET, 6000 + $n))) {
unless (bind(S, sockaddr_in(6000 + $n, &INADDR_ANY))) {
close(S);
return 0;
}
close(S);
socket(S, $AF_INET, $SOCK_STREAM, 0) || die "$prog: socket failed: $!\n";
eval 'setsockopt(S, &SOL_SOCKET, &SO_REUSEADDR, pack("l", 1))';
#unless (bind(S, pack('S n x12', $AF_INET, 5900 + $n))) {
unless (bind(S, sockaddr_in(5900 + $n, &INADDR_ANY))) {
close(S);
return 0;
}
close(S);
if (-e "/tmp/.X$n-lock") {
warn "\nWarning: $host:$n is taken because of /tmp/.X$n-lock\n";
warn "Remove this file if there is no X server $host:$n\n";
return 0;
}
if (-e "/tmp/.X11-unix/X$n") {
warn "\nWarning: $host:$n is taken because of /tmp/.X11-unix/X$n\n";
warn "Remove this file if there is no X server $host:$n\n";
return 0;
}
return 1;
}
#
# GetXDisplayDefaults uses xdpyinfo to find out the geometry, depth and pixel
# format of the current X display being used. If successful, it sets the
# options as appropriate so that the X VNC server will use the same settings
# (minus an allowance for window manager decorations on the geometry). Using
# the same depth and pixel format means that the VNC server won't have to
# translate pixels when the desktop is being viewed on this X display (for
# TrueColor displays anyway).
#
sub GetXDisplayDefaults
{
local (@lines, @matchlines, $width, $height, $defaultVisualId, $i,
$red, $green, $blue);
$wmDecorationWidth = 4; # a guess at typical size for window manager
$wmDecorationHeight = 24; # decoration size
return unless (defined($ENV{DISPLAY}));
@lines = `xdpyinfo 2>/dev/null`;
return if ($? != 0);
@matchlines = grep(/dimensions/, @lines);
if (@matchlines) {
($width, $height) = ($matchlines[0] =~ /(\d+)x(\d+) pixels/);
$width -= $wmDecorationWidth;
$height -= $wmDecorationHeight;
$geometry = "${width}x$height";
}
@matchlines = grep(/default visual id/, @lines);
if (@matchlines) {
($defaultVisualId) = ($matchlines[0] =~ /id:\s+(\S+)/);
for ($i = 0; $i < @lines; $i++) {
if ($lines[$i] =~ /^\s*visual id:\s+$defaultVisualId$/) {
if (($lines[$i+1] !~ /TrueColor/) ||
($lines[$i+2] !~ /depth/) ||
($lines[$i+4] !~ /red, green, blue masks/))
{
return;
}
last;
}
}
return if ($i >= @lines);
($depth) = ($lines[$i+2] =~ /depth:\s+(\d+)/);
($red,$green,$blue)
= ($lines[$i+4]
=~ /masks:\s+0x([0-9a-f]+), 0x([0-9a-f]+), 0x([0-9a-f]+)/);
$red = hex($red);
$green = hex($green);
$blue = hex($blue);
if ($red > $blue) {
$red = int(log($red) / log(2)) - int(log($green) / log(2));
$green = int(log($green) / log(2)) - int(log($blue) / log(2));
$blue = int(log($blue) / log(2)) + 1;
$pixelformat = "rgb$red$green$blue";
} else {
$blue = int(log($blue) / log(2)) - int(log($green) / log(2));
$green = int(log($green) / log(2)) - int(log($red) / log(2));
$red = int(log($red) / log(2)) + 1;
$pixelformat = "bgr$blue$green$red";
}
}
}
#
# quotedString returns a string which yields the original string when parsed
# by a shell.
#
sub quotedString
{
local ($in) = @_;
$in =~ s/\'/\'\"\'\"\'/g;
return "'$in'";
}
#
# removeSlashes turns slashes into underscores for use as a file name.
#
sub removeSlashes
{
local ($in) = @_;
$in =~ s|/|_|g;
return "$in";
}
#
# Usage
#
sub Usage
{
die("TightVNC Server version 1.3.9\n".
"\n".
"Usage: $prog [<OPTIONS>] [:<DISPLAY#>]\n".
" $prog -kill :<DISPLAY#>\n".
"\n".
"<OPTIONS> are Xtightvnc options, or:\n".
"\n".
" -name <DESKTOP-NAME>\n".
" -depth <DEPTH>\n".
" -geometry <WIDTH>x<HEIGHT>\n".
" -httpport number\n".
" -basehttpport number\n".
" -alwaysshared\n".
" -nevershared\n".
" -pixelformat rgb<NNN>\n".
" -pixelformat bgr<NNN>\n".
"\n".
"See vncserver and Xtightvnc manual pages for more information.\n");
}
#
# Kill
#
sub Kill
{
$opt{'-kill'} =~ s/(:\d+)\.\d+$/$1/; # e.g. turn :1.0 into :1
if ($opt{'-kill'} =~ /^:\d+$/) {
$pidFile = "$vncUserDir/$host$opt{'-kill'}.pid";
} else {
if ($opt{'-kill'} !~ /^$host:/) {
die "\nCan't tell if $opt{'-kill'} is on $host\n".
"Use -kill :<number> instead\n\n";
}
$pidFile = "$vncUserDir/$opt{'-kill'}.pid";
}
unless (-r $pidFile) {
die "\nCan't find file $pidFile\n".
"You'll have to kill the Xtightvnc process manually\n\n";
}
$SIG{'HUP'} = 'IGNORE';
chop($pid = `cat $pidFile`);
warn "Killing Xtightvnc process ID $pid\n";
system("kill $pid");
unlink $pidFile;
## If option -clean is given, also remove the logfile
unlink "$vncUserDir/$host$opt{'-kill'}.log" if ($opt{'-clean'});
exit;
}
#
# ParseOptions takes a list of possible options and a boolean indicating
# whether the option has a value following, and sets up an associative array
# %opt of the values of the options given on the command line. It removes all
# the arguments it uses from @ARGV and returns them in @optArgs.
#
sub ParseOptions
{
local (@optval) = @_;
local ($opt, @opts, %valFollows, @newargs);
while (@optval) {
$opt = shift(@optval);
push(@opts,$opt);
$valFollows{$opt} = shift(@optval);
}
@optArgs = ();
%opt = ();
arg: while (defined($arg = shift(@ARGV))) {
foreach $opt (@opts) {
if ($arg eq $opt) {
push(@optArgs, $arg);
if ($valFollows{$opt}) {
if (@ARGV == 0) {
&Usage();
}
$opt{$opt} = shift(@ARGV);
push(@optArgs, $opt{$opt});
} else {
$opt{$opt} = 1;
}
next arg;
}
}
push(@newargs,$arg);
}
@ARGV = @newargs;
}
#
# Routine to make sure we're operating in a sane environment.
#
sub SanityCheck
{
local ($cmd);
#
# Get the program name
#
($prog) = ($0 =~ m|([^/]+)$|);
#
# Check we have all the commands we'll need on the path.
#
cmd:
foreach $cmd ("uname","xauth","Xtightvnc","vncpasswd") {
for (split(/:/,$ENV{PATH})) {
if (-x "$_/$cmd") {
next cmd;
}
}
die "$prog: couldn't find \"$cmd\" on your PATH.\n";
}
#
# Check the HOME and USER environment variables are both set.
#
unless (defined($ENV{HOME})) {
die "$prog: The HOME environment variable is not set.\n";
}
unless (defined($ENV{USER})) {
die "$prog: The USER environment variable is not set.\n";
}
#
# Find socket constants. 'use Socket' is a perl5-ism, so we wrap it in an
# eval, and if it fails we try 'require "sys/socket.ph"'. If this fails,
# we just guess at the values. If you find perl moaning here, just
# hard-code the values of AF_INET and SOCK_STREAM. You can find these out
# for your platform by looking in /usr/include/sys/socket.h and related
# files.
#
chop($os = `uname`);
chop($osrev = `uname -r`);
eval 'use Socket';
if ($@) {
eval 'require "sys/socket.ph"';
if ($@) {
if (($os eq "SunOS") && ($osrev !~ /^4/)) {
$AF_INET = 2;
$SOCK_STREAM = 2;
} else {
$AF_INET = 2;
$SOCK_STREAM = 1;
}
} else {
$AF_INET = &AF_INET;
$SOCK_STREAM = &SOCK_STREAM;
}
} else {
$AF_INET = &AF_INET;
$SOCK_STREAM = &SOCK_STREAM;
}
}
---
system_packages:
- tigervnc-server
- libXcomposite
- libXdamage
- mesa-libEGL
- mesa-libgbm
- harfbuzz
- mesa-libglapi
- graphite2
- xterm
- libpng
- xorg-x11-fonts-100dpi
- xorg-x11-fonts-75dpi
- xorg-x11-fonts-misc
system_group_packages:
- "mate-desktop-environment"
- "graphical-server-environment"