[X2Go-Commits] [x2goserver] 12/33: x2goserver/lib: new script x2gogetfreeport, consists of duplicated functionality in x2gostartagent.

git-admin at x2go.org git-admin at x2go.org
Wed Jan 10 00:19:23 CET 2018


This is an automated email from the git hooks/post-receive script.

x2go pushed a commit to branch master
in repository x2goserver.

commit ab860507f6c2062b9864ebac05bd83079cf36671
Author: Mihai Moldovan <ionic at ionic.de>
Date:   Thu Jan 4 03:04:50 2018 +0100

    x2goserver/lib: new script x2gogetfreeport, consists of duplicated functionality in x2gostartagent.
    
    Cherry-picked from release/4.0.1.x branch.
---
 debian/changelog               |   2 +
 x2goserver/lib/x2gogetfreeport | 169 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 171 insertions(+)

diff --git a/debian/changelog b/debian/changelog
index 2a280e2..bf9de4c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -295,6 +295,8 @@ x2goserver (4.0.1.23-0x2go1) UNRELEASED; urgency=medium
       substitution.
     - x2goserver/bin/x2gostartagent: some shells do not handle quotes in
       pattern substitutions gracefully. Remove them.
+    - x2goserver/lib: new script x2gogetfreeport, consists of duplicated
+      functionality in x2gostartagent.
   * x2goserver.spec:
     - RPMify x2goserver-xsession description.
     - Remove qt4 stuff, we're not using the framework here.
diff --git a/x2goserver/lib/x2gogetfreeport b/x2goserver/lib/x2gogetfreeport
new file mode 100755
index 0000000..2f91297
--- /dev/null
+++ b/x2goserver/lib/x2gogetfreeport
@@ -0,0 +1,169 @@
+#!/bin/bash
+
+# Copyright (C) 2017-2018 X2Go Project - https://wiki.x2go.org
+#
+# This program 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 program 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 program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# Get first free port.
+# Takes a command for ss, the port type, a start andan end port
+# as parameters.
+# If an ss command is not given, a default of "ss" is assumed.
+# If the port type is not given, a default of "lowlevel" is assumed.
+# If the start port is not given, a default of 1 is assumed.
+# If the end port is not given, a default of 65535 is assumed.
+# Valid values for the port type are "lowlevel" and "display".
+# Prints the first free port value on success, or the initial start
+# port number on failure.
+# Returns 0 on success or non-0 on failure.
+typeset ss="${1:-"ss"}"
+typeset type="${2:-"lowlevel"}"
+typeset start="${3:-"1"}"
+typeset end="${4:-"65535"}"
+
+# Check parameter sanity.
+typeset empty_regex='^[[:space:]]*$'
+if [[ -z "${ss}" ]] || [[ "${ss}" =~ ${empty_regex} ]]; then
+	exit "1"
+fi
+typeset -i start_i="${start}"
+typeset -i end_i="${end}"
+if [[ -z "${start}" ]] || [[ "${start}" != "${start_i}" ]] || [[ "${start}" -ne "${start_i}" ]]; then
+	exit "2"
+fi
+if [[ -z "${end}" ]] || [[ "${end}" != "${end_i}" ]] || [[ "${end}" -ne "${end_i}" ]]; then
+	exit "3"
+fi
+[[ "${type}" != 'lowlevel' ]] && [[ "${type}" != 'display' ]] && exit "4"
+
+
+# Skip unnecessary work.
+if [[ "${type}" = 'display' ]]; then
+	typeset -a used_displays
+	typeset -a used_displays_work
+	used_displays=()
+	used_displays_work=()
+	# What this does is very unobvious, so here's how that works:
+	# The -d parameter with an empty string as its argument makes
+	# the read utility process a "line" until the first such delimiter
+	# is found. Since an empty string in C is terminated by a NULL
+	# character, the delimiter will be set to this NULL character.
+	# Hence, assuming that the input string does not contain any
+	# NULL characters, the whole input string will be treated as
+	# one big line.
+	# Then, normal word splitting kicks in and the -a flag tells
+	# read to put all words into elements of the provided array
+	# variable.
+	IFS="${IFS}|" read -r -d '' -a used_displays_work < <("${X2GO_LIB_PATH}/x2gogetdisplays" "${current_host_name}")
+
+	# Filter out any empty or invalid values.
+	typeset -i item_i='0'
+	typeset item=''
+	for item in "${used_displays_work[@]}"; do
+		item_i="${item}"
+
+		[[ -n "${item}" ]] && [[ "${item}" -eq "${item_i}" ]] && [[ "${item}" = "${item_i}" ]] && used_displays+=( "${item}" )
+	done
+fi
+
+# Same algorithm again for the system ports in use, but we cannot really
+# use a function to duplicate code less since arrays and functions don't
+# mix well in bash.
+
+# Get all used in system ports from X2Go database and ss output
+typeset -a used_ports
+typeset -a used_ports_work
+used_ports=()
+used_ports_work=()
+IFS="${IFS}|" read -r -d '' -a used_ports_work < <("${X2GO_LIB_PATH}/x2gogetports" "${current_host_name}";
+						   "${ss}" -nt -all | awk '
+							{
+								n = split ($0, lines, "\n");
+								for (i = 1; i <= n; ++i) {
+									split (lines[i], words, " ");
+									delim = split (words[4], ports, ":");
+									if (delim > 1) {
+										printf ("\n%d\n", ports[delim])
+									}
+								}
+							}')
+
+# Filter out any empty or invalid values.
+item_i='0'
+item=''
+for item in "${used_ports_work[@]}"; do
+	item_i="${item}"
+
+	[[ -n "${item}" ]] && [[ "${item}" -eq "${item_i}" ]] && [[ "${item}" = "${item_i}" ]] && used_ports+=( "${item}" )
+done
+
+typeset -i ret_port="${start}"
+typeset -i ret='1'
+typeset -i work_port='0'
+typeset -i stop_port='65535'
+[[ "${type}" = 'display' ]] && stop_port="$((stop_port - 6000))"
+# Find the next free port number.
+for ((work_port = start; i <= stop_port; ++work_port)); do
+	typeset -i i="0"
+	typeset -i value_found="0"
+
+	if [[ "${type}" = 'display' ]]; then
+		for ((i = 0; i < ${#used_displays[@]}; ++i)); do
+			if [[ "${used_displays[i]}" = "${work_port}" ]]; then
+				# We need to continue with the next port number,
+				# this one is taken.
+				value_found="1"
+				break
+			fi
+		done
+
+		# Check if such a socket is already in use system-wide.
+		if "${ss}" -lxs 2>"/dev/null" | grep -Eqs "(@|)/tmp/.X11-unix/X${work_port}(|-lock) " >"/dev/null"; then
+			continue
+		fi
+	fi
+
+	# Port number taken? Continue with the next one.
+	[[ "${value_found}" -ne "0" ]] && continue
+
+	# Check raw port number. Either to make sure that the corresponding
+	# raw port for the DISPLAY port found is still free, or also in the
+	# general case.
+	typeset -i map_port="${work_port}"
+	[[ "${type}" = 'display' ]] && map_port="$((map_port + 6000))"
+	for ((i = 0; i < ${#used_ports[@]}; ++i)); do
+		if [[ "${used_ports[i]}" = "${map_port}" ]]; then
+			value_found="1"
+			break
+		fi
+	done
+
+	# Port number taken? Continue with the next one.
+	[[ "${value_found}" -ne "0" ]] && continue
+
+	# If the port is a well-known one, don't block it.
+	grep -qs "${work_port}" "/etc/services" &>"/dev/null" && continue
+
+	# Searched the array and got nothing? Great, grab that port number!
+	ret_port="${work_port}"
+	ret='0'
+	break
+done
+
+# At this point, ${ret} and ${ret_port} should be set up correctly.
+# Either to the first free port value if one has been found (and ${ret}
+# to zero) or to the start port value (and ${ret} to one.)
+printf '%d\n' "${ret_port}"
+exit "${ret}"

--
Alioth's /home/x2go-admin/maintenancescripts/git/hooks/post-receive-email on /srv/git/code.x2go.org/x2goserver.git


More information about the x2go-commits mailing list