bryan 4 years ago
parent
commit
abd0f43ad1
1 changed files with 222 additions and 204 deletions
  1. 222 204
      installJRMC

+ 222 - 204
installJRMC

@@ -20,19 +20,18 @@ shopt -s extglob
 #######################################
 #######################################
 installJRMC() {
 installJRMC() {
 
 
-    _scriptversion="0.3"
+    _scriptversion="0.4"
     _boardurl="https://yabb.jriver.com/interact/index.php/board,64.0.html"
     _boardurl="https://yabb.jriver.com/interact/index.php/board,64.0.html"
     _outputdir="$_basedir/output"
     _outputdir="$_basedir/output"
     _createrepo_webroot="/srv/jriver"
     _createrepo_webroot="/srv/jriver"
-    _createrepo_user="$(whoami)"
-    _user="$(whoami)"
-    _available_services=("createrepo" "x11vnc" "mediaserver" "mediacenter" "mediacenter-vncserver")
-    #_available_containers=("mediacenter-vncserver" "createrepo")
+    _exec_user="$(whoami)"
+    _available_services=("jriver-createrepo" "jriver-x11vnc-mediacenter" "jriver-mediaserver" "jriver-mediacenter" "jriver-xvnc-mediacenter")
+    #_available_containers=("mediacenter-xvnc" "createrepo")
 
 
 
 
     _printHelpAndExit() {
     _printHelpAndExit() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         cat <<-'EOF'
         cat <<-'EOF'
 USAGE:
 USAGE:
@@ -55,6 +54,8 @@ OPTIONS
             Restore file location for registration (Default: skip registration)
             Restore file location for registration (Default: skip registration)
         --betapass PASSWORD
         --betapass PASSWORD
             Enter beta team password for access to beta builds
             Enter beta team password for access to beta builds
+        --service-user USER
+            Install systemd services and containers for USER
         --service, -s SERVICE
         --service, -s SERVICE
             See SERVICES section below for a list of possible services to install
             See SERVICES section below for a list of possible services to install
         --container, -c CONTAINER
         --container, -c CONTAINER
@@ -69,33 +70,32 @@ OPTIONS
             Print this script version and exit
             Print this script version and exit
         --debug, -d
         --debug, -d
             Print debug output
             Print debug output
-        --force, -f
-            Force reinstallation and ignore/overwrite previous output
         --help, -h
         --help, -h
             Print help dialog and exit
             Print help dialog and exit
         --uninstall, -u
         --uninstall, -u
             Uninstall JRiver MC, cleanup service files, and remove firewall rules (does not remove library files)
             Uninstall JRiver MC, cleanup service files, and remove firewall rules (does not remove library files)
 
 
     SERVICES
     SERVICES
-        mediaserver
+        jriver-mediaserver
             Enable and start a mediaserver systemd service (requires an existing X server)
             Enable and start a mediaserver systemd service (requires an existing X server)
-        mediacenter
+        jriver-mediacenter
             Enable and start a mediacenter systemd service (requires an existing X server)
             Enable and start a mediacenter systemd service (requires an existing X server)
-        x11vnc
+        jriver-x11vnc-mediacenter
             Enable and start x11vnc for the local desktop (requires an existing X server)
             Enable and start x11vnc for the local desktop (requires an existing X server)
             --vncpass and --display are also valid options (see below)
             --vncpass and --display are also valid options (see below)
-        mediacenter-vncserver
-            Enable and start a vncserver running JRiver Media Center
+        jriver-xvnc-mediacenter
+            Enable and start an Xvnc session running JRiver Media Center
             --vncpass PASSWORD
             --vncpass PASSWORD
-                Set vnc password for x11vnc access. If no password is set, the script will either
-                use existing password stored in ~/.vnc/jrmc_passwd or use no password
+                Set vnc password for x11vnc/Xvnc access. If no password is set, the script
+                will either use existing password stored in ~/.vnc/jrmc_passwd or use no password
             --display DISPLAY
             --display DISPLAY
-                Display to start vncserver/x11vnc (Default: The current display (x11vnc) or next available display (vncserver))
-        createrepo
+                Display to start x11vnc/Xvnc (Default: The current display (x11vnc) or the
+                current display incremented by 1 (Xvnc))
+        jriver-createrepo
             Install hourly service to build latest MC RPM and run createrepo
             Install hourly service to build latest MC RPM and run createrepo
 
 
     CONTAINERS
     CONTAINERS
-        mediacenter-vncserver (Under construction)
+        mediacenter-xvnc (Under construction)
         createrepo (Under construction)
         createrepo (Under construction)
 EOF
 EOF
 
 
@@ -106,15 +106,14 @@ EOF
 
 
     _parseInput() {
     _parseInput() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         # set default behavior
         # set default behavior
-        if [[ $# == 0 ]]; then
+        if [[ $# -eq 0 ]] || [[ $# -eq 1 && "$1" == "--debug" ]]; then
             _repoinstall="true"
             _repoinstall="true"
-            return 1
         fi
         fi
 
 
-        if _input=$(getopt -o +vdhus:c: -l install-repo,install-rpmbuild,rpmbuild,outputdir:,mcversion:,restorefile:,betapass:,service:,version,debug,force,help,uninstall,createrepo,createrepo-webroot:,createrepo-user:,vncpass:,display:,container: -- "$@"); then
+        if _input=$(getopt -o +vdhus:c: -l install-repo,install-rpmbuild,rpmbuild,outputdir:,mcversion:,restorefile:,betapass:,service-user:,service:,version,debug,help,uninstall,createrepo,createrepo-webroot:,createrepo-user:,vncpass:,display:,container: -- "$@"); then
             eval set -- "$_input"
             eval set -- "$_input"
             while true; do
             while true; do
                 case "$1" in
                 case "$1" in
@@ -140,6 +139,9 @@ EOF
                     --betapass)
                     --betapass)
                         shift && _betapass="$1"
                         shift && _betapass="$1"
                         ;;
                         ;;
+                    --service-user)
+                        shift && _service_user="$1"
+                        ;;
                     --service|-s)
                     --service|-s)
                         shift && _services+=("$1")
                         shift && _services+=("$1")
                         ;;
                         ;;
@@ -154,9 +156,6 @@ EOF
                         echo "Debugging on"
                         echo "Debugging on"
                         _debug="true"
                         _debug="true"
                         ;;
                         ;;
-                    --force|-f)
-                        _force="true"
-                        ;;
                     --help|-h)
                     --help|-h)
                         _printHelpAndExit 0
                         _printHelpAndExit 0
                         ;;
                         ;;
@@ -195,25 +194,27 @@ EOF
 
 
     err() {
     err() {
 
 
-      echo "[$(date +'%Y-%m-%dT%H:%M:%S%z')]: $*" >&2
+      echo "Error: $*" >&2
     }
     }
 
 
 
 
     #######################################
     #######################################
     # Call this at the beginning of every function in order to track
     # Call this at the beginning of every function in order to track
     #######################################
     #######################################
-    _runDebug() {
+    debug() {
 
 
-        [[ -n $_debug ]] && echo "Running: " "$@"
+        [[ -n $_debug ]] && echo "Debug: $*"
     }
     }
 
 
 
 
     #######################################
     #######################################
-    # Prepend this to any command that you wish to execute with sudo (i.e. when _user is NOT root)
+    # Prepend this to any command that you wish to execute with sudo
+    # Requires:
+    #   _exec_user
     #######################################
     #######################################
     _ifSudo() {
     _ifSudo() {
 
 
-        if [[ "$_user" != "root" ]]; then
+        if [[ "$_exec_user" != "root" ]]; then
             sudo "$@"
             sudo "$@"
         else
         else
             "$@"
             "$@"
@@ -221,35 +222,16 @@ EOF
     }
     }
 
 
 
 
-    _checkUser() {
-
-        _runDebug "${FUNCNAME[0]}"
-
-        if [[ "$_user" == "root" ]]; then
-
-            cat <<EOF
-Warning! You are currently running installJRMC as the root user. This is not recommended! When
-running as a regular user, installJRMC will ask you for your sudo password when necessary.
-
-Installation will continue but any systemd services will be installed as system services and you
-may run into permissions issues.
-EOF
-        else
-            [[ -n $_debug ]] && echo "Installing as user: $_user"
-        fi
-    }
-
-
     #######################################
     #######################################
     # Sources /etc/os-release so we know which OS we're running on
     # Sources /etc/os-release so we know which OS we're running on
     # Used in: _buildCommands()
     # Used in: _buildCommands()
     #######################################
     #######################################
     _getOS() {
     _getOS() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
-        if [[ -e /etc/os-release ]]; then
-            source /etc/os-release
+        if [[ -e "/etc/os-release" ]]; then
+            source "/etc/os-release"
         else
         else
             err "No /etc/os-release found"
             err "No /etc/os-release found"
             err "Your OS is unsupported"
             err "Your OS is unsupported"
@@ -290,7 +272,7 @@ EOF
         # Detect OS
         # Detect OS
         _getOS
         _getOS
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         # Agnostic commands
         # Agnostic commands
         _bash_cmd(){ _ifSudo bash -c "$@"; }
         _bash_cmd(){ _ifSudo bash -c "$@"; }
@@ -337,8 +319,8 @@ EOF
             else
             else
                 _createrepo_cmd(){ sudo -u "$_createrepo_user" createrepo -q "$@"; }
                 _createrepo_cmd(){ sudo -u "$_createrepo_user" createrepo -q "$@"; }
             fi
             fi
-            _mkdir_cmd(){ sudo -u "$_createrepo_user" mkdir -p "$@"; }
-            _cp_cmd(){ sudo -u "$_createrepo_user" cp -n "$@"; }
+            _cr_mkdir_cmd(){ sudo -u "$_createrepo_user" mkdir -p "$@"; }
+            _cr_cp_cmd(){ sudo -u "$_createrepo_user" cp -n "$@"; }
         else
         else
             if [[ -d "$_createrepo_webroot/repodata" ]]; then
             if [[ -d "$_createrepo_webroot/repodata" ]]; then
                 _createrepo_cmd(){ createrepo -q --update "$@"; }
                 _createrepo_cmd(){ createrepo -q --update "$@"; }
@@ -351,6 +333,21 @@ EOF
 
 
 
 
     #######################################
     #######################################
+    # Sets default user variables
+    # Requires:
+    #   _exec_user
+    # Globals
+    #   _service_user
+    #   _createrepo_user
+    #######################################
+    _setUser() {
+
+        [[ -z $_service_user ]] && _service_user="$_exec_user"
+        [[ -z $_createrepo_user ]] && _createrepo_user="$_exec_user"
+    }
+
+
+    #######################################
     # Installs a package using the system package manager
     # Installs a package using the system package manager
     # Arguments:
     # Arguments:
     #   One or more package names
     #   One or more package names
@@ -361,7 +358,7 @@ EOF
     #######################################
     #######################################
     _installPackage() {
     _installPackage() {
 
 
-        _runDebug "${FUNCNAME[0]}" "$@"
+        debug "Running: ${FUNCNAME[0]}" "$@"
 
 
         if _input=$(getopt -o +n -l noquery -- "$@"); then
         if _input=$(getopt -o +n -l noquery -- "$@"); then
             eval set -- "$_input"
             eval set -- "$_input"
@@ -407,11 +404,11 @@ EOF
             echo "Installing:" "${_pkg_array[@]}"
             echo "Installing:" "${_pkg_array[@]}"
             if [[ -n $_debug ]]; then
             if [[ -n $_debug ]]; then
                 if ! _pkg_install "${_pkg_array[@]}"; then
                 if ! _pkg_install "${_pkg_array[@]}"; then
-                    err "Failed to install required package"
+                    err "Failed to install package"
                     exit 1
                     exit 1
                 fi
                 fi
             elif ! _pkg_install "${_pkg_array[@]}" > /dev/null 2>&1; then
             elif ! _pkg_install "${_pkg_array[@]}" > /dev/null 2>&1; then
-                err "Failed to install dependency."
+                err "Failed to install package."
                 _printHelpAndExit 1
                 _printHelpAndExit 1
             fi
             fi
         fi
         fi
@@ -442,7 +439,7 @@ EOF
     #######################################
     #######################################
     _packageQuirks() {
     _packageQuirks() {
 
 
-        _runDebug "${FUNCNAME[0]}" "$@"
+        debug "Running: ${FUNCNAME[0]}" "$@"
 
 
         unset _url_pkg
         unset _url_pkg
 
 
@@ -483,7 +480,7 @@ EOF
     #######################################
     #######################################
     _setVersion() {
     _setVersion() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         if [[ -z "$_mcversion" ]]; then
         if [[ -z "$_mcversion" ]]; then
 
 
@@ -540,11 +537,13 @@ EOF
     #######################################
     #######################################
     _sanityChecks() {
     _sanityChecks() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         # Check for bad service name
         # Check for bad service name
-        #
         _checkServices() {
         _checkServices() {
+
+            debug "Running: ${FUNCNAME[0]}"
+
             for _service in "${_services[@]}"; do
             for _service in "${_services[@]}"; do
                 if ! _inArray "$_service" "${_available_services[@]}"; then
                 if ! _inArray "$_service" "${_available_services[@]}"; then
                     echo "Incorrect service type provided"
                     echo "Incorrect service type provided"
@@ -554,33 +553,44 @@ EOF
         }
         }
 
 
 
 
-        _createrepoBuild() {
+        _checkMCInstalled() {
 
 
-            if _inArray "createrepo" "${_services[@]}"; then
-                echo "Incorrect service type provided"
-                _printHelpAndExit 1
-            fi
-        }
+            debug "Running: ${FUNCNAME[0]}"
 
 
+            for _service in "${_services[@]}"; do
+                if [[ "$_service" =~ ^(jriver-mediacenter|jriver-mediaserver|jriver-xvnc-mediacenter)$ ]] \
+                && [[ -z $_repoinstall && -z $_rpminstall ]] \
+                && [[ ! -x $(command -v "mediacenter$_mversion") ]]; then
+                    err "You are attempting to install a service that depends on JRiver Media Center"
+                    err "without installing JRiver Media Center"
+                    err "Automatically enabling --repo-install"
+                    _repoinstall="true"
+                fi
+            done
+        }
 
 
-        _checkMCInstalled() {
 
 
-            if [[ "${_services[*]}" =~ ^(mediacenter|mediaserver|mediacenter-vncserver)$ ]]; then
-                if [[ -z $_repoinstall && -z $_rpminstall ]]; then
-                    if [[ -x $(command -v "mediacenter$_mversion") ]]; then
-                        err "You are attempting to install a service that relies on mediacenter$_mversion but --install-repo/--install-rpmbuild are not set and mediacenter$_mversion is not installed"
-                        _printHelpAndExit 1
-                    fi
-                fi
-            fi
+        _checkUser() {
 
 
+            debug "Running: ${FUNCNAME[0]}"
 
 
+            if [[ "$_exec_user" == "root" && -z "$_service_user" && "${_services[*]}" ]]; then
+                err "Attempting to install services as the root user"
+                err "This is not recommended and we are exiting now to prevent permission hell"
+                err "You can override this safety check by manually specifying --user root"
+                return 1
+            fi
         }
         }
 
 
+
         # Enable/disable sanity checks
         # Enable/disable sanity checks
-        _checkServices
-        _checkMCInstalled
-        #_createrepoBuild
+        if _checkServices && _checkMCInstalled && _checkUser; then
+            debug "Sanity checks passed!"
+            return 0
+        else
+            err "Sanity checks failed!"
+            exit 1
+        fi
     }
     }
 
 
 
 
@@ -591,10 +601,12 @@ EOF
     #######################################
     #######################################
     _installMCFromRepo() {
     _installMCFromRepo() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         echo "Installing latest JRiver Media Center from repo..."
         echo "Installing latest JRiver Media Center from repo..."
 
 
+        local _mcpkg
+
         # Add repositories to OS-specific package managers
         # Add repositories to OS-specific package managers
         if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
         if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
 
 
@@ -604,22 +616,39 @@ name=JRiver Media Center repo by BryanC
 baseurl=https://repos.bryanroessler.com/jriver
 baseurl=https://repos.bryanroessler.com/jriver
 gpgcheck=0
 gpgcheck=0
 EOF'
 EOF'
-            local _mcpkg="MediaCenter"
+            _mcpkg="MediaCenter"
         elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
         elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
             wget -q "http://dist.jriver.com/mediacenter@jriver.com.gpg.key" -O- | _ifSudo apt-key add - > /dev/null 2>&1
             wget -q "http://dist.jriver.com/mediacenter@jriver.com.gpg.key" -O- | _ifSudo apt-key add - > /dev/null 2>&1
             _bash_cmd 'cat <<-EOF > /etc/apt/sources.list.d/jriver.list
             _bash_cmd 'cat <<-EOF > /etc/apt/sources.list.d/jriver.list
 deb [arch=amd64,i386,armhf] http://dist.jriver.com/latest/mediacenter/ jessie main
 deb [arch=amd64,i386,armhf] http://dist.jriver.com/latest/mediacenter/ jessie main
 EOF'
 EOF'
-            local _mcpkg="mediacenter$_mversion"
         fi
         fi
 
 
-        # Update packages and install JRiver Media Center
+        # Update package list
+        if ! _pkg_update; then
+            err "Package update failed!"
+            exit 1
+        fi
+
+        # Find latest mversion to install on Ubuntu/Debian
+        if [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
+            # Try parsing the latest mediacenter?? version from the repo
+            if _mcpkg=$(apt-get install mediacenter?? -s -q0 | grep "selecting" | tail -1| awk '{print $3}'); then
+                _mcpkg="${_mcpkg%\'}"
+                _mcpkg="${_mcpkg#\'}"
+            fi
+            # If that fails, fall back to scraping Interact
+            if ! [[ "$_mcpkg" =~ ^[0-9][0-9]\.[0-9]\.[0-9]\+$ ]]; then
+                _setVersion
+                _mcpkg="mediacenter$_mversion"
+            fi
+        fi
+
+
         if [[ -n $_debug ]]; then
         if [[ -n $_debug ]]; then
-            _pkg_update && \
-            _pkg_install "$_mcpkg"
+            _installPackage "$_mcpkg"
         else
         else
-            _pkg_update > /dev/null 2>&1 && \
-            _pkg_install "$_mcpkg" > /dev/null 2>&1
+            _installPackage "$_mcpkg" > /dev/null 2>&1
         fi
         fi
 
 
         # shellcheck disable=SC2181
         # shellcheck disable=SC2181
@@ -641,7 +670,7 @@ EOF'
     #######################################
     #######################################
     _acquireDeb() {
     _acquireDeb() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         local _debfilename="$_outputdir/SOURCES/MediaCenter-${_mcversion}-amd64.deb"
         local _debfilename="$_outputdir/SOURCES/MediaCenter-${_mcversion}-amd64.deb"
 
 
@@ -692,7 +721,7 @@ EOF'
     #######################################
     #######################################
     _buildRPM() {
     _buildRPM() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         # install build dependencies
         # install build dependencies
         _installPackage wget dpkg rpm-build
         _installPackage wget dpkg rpm-build
@@ -708,13 +737,11 @@ EOF'
             local _build_requires=''
             local _build_requires=''
         fi
         fi
 
 
-        if [[ "$ID" != "centos" ]]; then
+        if [[ "$ID" == "fedora" && -n $_rpminstall ]]; then
+            # TODO: find out why this is required since it's not easily available on CentOS
             local _requires='Requires: pangox-compat >= 0.0.2'
             local _requires='Requires: pangox-compat >= 0.0.2'
-        else
-            local _requires='Requires: libXScrnSaver'
         fi
         fi
 
 
-
         # Create spec file
         # Create spec file
         bash -c "cat <<EOF > $_outputdir/SPECS/mediacenter.spec
         bash -c "cat <<EOF > $_outputdir/SPECS/mediacenter.spec
 Name:    MediaCenter
 Name:    MediaCenter
@@ -742,6 +769,7 @@ Requires: mesa-libGL
 Requires: libglvnd-glx
 Requires: libglvnd-glx
 Requires: pango >= 1.36
 Requires: pango >= 1.36
 $_requires
 $_requires
+Requires: libXScrnSaver
 Requires: xdg-utils
 Requires: xdg-utils
 Requires: libgomp >= 4.9
 Requires: libgomp >= 4.9
 Requires: gstreamer1 >= 1.4.4
 Requires: gstreamer1 >= 1.4.4
@@ -781,7 +809,7 @@ EOF"
         declare -g _mcrpm="$_outputdir/RPMS/x86_64/MediaCenter-$_mcversion.x86_64.rpm"
         declare -g _mcrpm="$_outputdir/RPMS/x86_64/MediaCenter-$_mcversion.x86_64.rpm"
 
 
         # skip rebuilding the rpm if it already exists
         # skip rebuilding the rpm if it already exists
-        if [[ -f "$_mcrpm" && -z "$_force" ]]; then
+        if [[ -f "$_mcrpm" ]]; then
             echo "$_mcrpm already exists. Skipping build step..."
             echo "$_mcrpm already exists. Skipping build step..."
             return 0 # this is fine
             return 0 # this is fine
         else
         else
@@ -814,7 +842,7 @@ EOF"
     #######################################
     #######################################
     _runCreaterepo() {
     _runCreaterepo() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         _installPackage createrepo_c
         _installPackage createrepo_c
 
 
@@ -822,7 +850,7 @@ EOF"
 
 
         # If the webroot does not exist, create it
         # If the webroot does not exist, create it
         if [[ ! -d "$_createrepo_webroot" ]]; then
         if [[ ! -d "$_createrepo_webroot" ]]; then
-            if ! _mkdir_cmd "$_createrepo_webroot"; then
+            if ! _cr_mkdir_cmd "$_createrepo_webroot"; then
                 err "Could not create the createrepo-webroot path!"
                 err "Could not create the createrepo-webroot path!"
                 err "Make sure that the createrepo-webroot is writeable by createrepo-user"
                 err "Make sure that the createrepo-webroot is writeable by createrepo-user"
                 return 1
                 return 1
@@ -830,7 +858,7 @@ EOF"
         fi
         fi
 
 
         # Copy built rpms to webroot
         # Copy built rpms to webroot
-        if ! _cp_cmd "$_rpmfile" "$_createrepo_webroot"; then
+        if ! _cr_cp_cmd "$_rpmfile" "$_createrepo_webroot"; then
             err "Could not copy the RPM to the createrepo-webroot path"
             err "Could not copy the RPM to the createrepo-webroot path"
             err "Make sure that the createrepo-webroot path is writeable by createrepo-user"
             err "Make sure that the createrepo-webroot path is writeable by createrepo-user"
             return 1
             return 1
@@ -855,7 +883,7 @@ EOF"
     #######################################
     #######################################
     _symlinkCerts() {
     _symlinkCerts() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         if [[ ! -f /etc/ssl/certs/ca-certificates.crt && \
         if [[ ! -f /etc/ssl/certs/ca-certificates.crt && \
         -f /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem ]]; then
         -f /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem ]]; then
@@ -878,7 +906,7 @@ EOF"
     #######################################
     #######################################
     _restoreLicense() {
     _restoreLicense() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         local _mjr
         local _mjr
 
 
@@ -913,7 +941,7 @@ EOF"
     #######################################
     #######################################
     _openFirewall() {
     _openFirewall() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         # Create OS-specific port rules based on argument (service) name
         # Create OS-specific port rules based on argument (service) name
         local -a _f_ports # for firewall_cmd
         local -a _f_ports # for firewall_cmd
@@ -921,13 +949,17 @@ EOF"
         if [[ "$1" == "jriver" ]]; then
         if [[ "$1" == "jriver" ]]; then
             _f_ports=("52100-52200/tcp" "1900/udp")
             _f_ports=("52100-52200/tcp" "1900/udp")
             _u_ports="52100:52200/tcp|1900/udp"
             _u_ports="52100:52200/tcp|1900/udp"
-        elif [[ "$1" =~ ^(x11vnc|vncserver)$ ]]; then
+        elif [[ "$1" =~ ^(x11vnc|xvnc)$ ]]; then
             _f_ports=("$_port/tcp")
             _f_ports=("$_port/tcp")
             _u_ports="$_port/tcp"
             _u_ports="$_port/tcp"
+        else
+            err "_openFirewall unrecognized service name"
+            exit 1
         fi
         fi
 
 
         # Open the ports
         # Open the ports
-        if [[ "$ID" =~ ^(fedora|centos)$ ]] && [[ -x $(command -v firewall-cmd) ]]; then
+        if [[ "$ID" =~ ^(fedora|centos)$ ]]; then
+            [[ ! -x $(command -v firewall-cmd) ]] && _installPackage firewalld
             if ! _firewall_cmd --get-services | grep -q "$1"; then
             if ! _firewall_cmd --get-services | grep -q "$1"; then
                 _firewall_cmd --permanent --new-service="$1" > /dev/null 2>&1
                 _firewall_cmd --permanent --new-service="$1" > /dev/null 2>&1
                 _firewall_cmd --permanent --service="$1" --set-description="$1 installed by installJRMC" > /dev/null 2>&1
                 _firewall_cmd --permanent --service="$1" --set-description="$1 installed by installJRMC" > /dev/null 2>&1
@@ -938,7 +970,9 @@ EOF"
                 _firewall-cmd --add-service "$1" --permanent > /dev/null 2>&1
                 _firewall-cmd --add-service "$1" --permanent > /dev/null 2>&1
                 _firewall_cmd --reload > /dev/null 2>&1
                 _firewall_cmd --reload > /dev/null 2>&1
             fi
             fi
-        elif [[ "$ID" =~ ^(ubuntu|debian)$ ]] && [[ -x $(command -v ufw) ]]; then
+        elif [[ "$ID" =~ ^(ubuntu|debian)$ ]]; then
+            # Debian ufw package state is broken on fresh installations
+            [[ ! -x $(command -v ufw) ]] && _installPackage --noquery ufw
             if [[ ! -f "/etc/ufw/applications.d/$1.service" ]]; then
             if [[ ! -f "/etc/ufw/applications.d/$1.service" ]]; then
                 _bash_cmd "cat <<-EOF > /etc/ufw/applications.d/$1.service
                 _bash_cmd "cat <<-EOF > /etc/ufw/applications.d/$1.service
 [$1]
 [$1]
@@ -969,7 +1003,7 @@ EOF"
     #######################################
     #######################################
     _setX11VNCPass() {
     _setX11VNCPass() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         _vncpassfile="$HOME/.vnc/jrmc_passwd"
         _vncpassfile="$HOME/.vnc/jrmc_passwd"
 
 
@@ -997,13 +1031,13 @@ EOF"
 
 
 
 
     #######################################
     #######################################
-    # Create the vncserver password file
+    # Create the Xvnc password file
     # Returns:
     # Returns:
     #   0 if password created sucessfully, 1 if not
     #   0 if password created sucessfully, 1 if not
     #######################################
     #######################################
     _setVNCPass() {
     _setVNCPass() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         _vncpassfile="$HOME/.vnc/jrmc_passwd"
         _vncpassfile="$HOME/.vnc/jrmc_passwd"
 
 
@@ -1031,23 +1065,47 @@ EOF"
 
 
 
 
     #######################################
     #######################################
+    # Set display and port variables
+    # Globals:
+    #   _display
+    #   _displaynum
+    #   _port
+    #######################################
+    _setDisplayAndPort() {
+
+        # Check _display, else DISPLAY, else set to :0 by default
+        [[ -z $_display ]] && _display="${DISPLAY-":0"}"
+
+        _displaynum="${_display#:}" # strip colon
+        _displaynum="${_displaynum%.*}" # strip suffix
+        _port=$(( _displaynum + 5900 ))
+    }
+
+
+    #######################################
     # Create associated service variables based on service name
     # Create associated service variables based on service name
-    # Arguments:
-    #   Requires exactly one argument, the name of the service to parse
+    # Requires:
+    #   _service_user
+    # Globals:
+    #   _service_fname
+    #   _timer_fname
+    #   _service_name
+    #   _timer_name
+    #   _user_specifier
     #######################################
     #######################################
     _servicePrep() {
     _servicePrep() {
 
 
-        if [[ "$_user" == "root" ]]; then
-            _service_fname="/usr/lib/systemd/system/jriver-${1}.service"
-            _timer_fname="/usr/lib/systemd/system/jriver-${1}.timer"
+        if [[ "$_service_user" == "root" ]]; then
+            _service_fname="/usr/lib/systemd/system/${1}.service"
+            _timer_fname="/usr/lib/systemd/system/${1}.timer"
             _service_name="jriver-${1}.service"
             _service_name="jriver-${1}.service"
             _timer_name="jriver-${1}}.timer"
             _timer_name="jriver-${1}}.timer"
             _user_specifier=""
             _user_specifier=""
         else
         else
-            _service_fname="/usr/lib/systemd/system/jriver-${1}@.service"
-            _timer_fname="/usr/lib/systemd/system/jriver-${1}@.timer"
-            _service_name="jriver-${1}@$_user.service"
-            _timer_name="jriver-${1}@$_user.timer"
+            _service_fname="/usr/lib/systemd/system/${1}@.service"
+            _timer_fname="/usr/lib/systemd/system/${1}@.timer"
+            _service_name="${1}@$_service_user.service"
+            _timer_name="${1}@$_service_user.timer"
             _user_specifier="User=%I"
             _user_specifier="User=%I"
         fi
         fi
     }
     }
@@ -1056,11 +1114,9 @@ EOF"
     #######################################
     #######################################
     # SERVICES
     # SERVICES
     #######################################
     #######################################
-    _serviceMediaserver() {
-
-        _runDebug "${FUNCNAME[0]}"
+    _service_jriver-mediaserver() {
 
 
-        [[ -z $_display ]] && _display="${DISPLAY:-":0"}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         _bash_cmd "cat <<-EOF > $_service_fname
         _bash_cmd "cat <<-EOF > $_service_fname
 [Unit]
 [Unit]
@@ -1083,16 +1139,14 @@ WantedBy=graphical.target
 EOF"
 EOF"
         _systemctl_reload && \
         _systemctl_reload && \
         _systemctl_start "$_service_name" && \
         _systemctl_start "$_service_name" && \
-        _systemctl_enable "$_service_name"
+        _systemctl_enable "$_service_name" && \
+        _openFirewall "jriver"
     }
     }
 
 
 
 
-    _serviceMediacenter() {
-
-        _runDebug "${FUNCNAME[0]}"
+    _service_jriver-mediacenter() {
 
 
-        # Set the display to use
-        [[ -z $_display ]] && _display="${DISPLAY:-":0"}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         _bash_cmd "cat <<-EOF > $_service_fname
         _bash_cmd "cat <<-EOF > $_service_fname
 [Unit]
 [Unit]
@@ -1115,37 +1169,29 @@ WantedBy=graphical.target
 EOF"
 EOF"
         _systemctl_reload && \
         _systemctl_reload && \
         _systemctl_start "$_service_name" && \
         _systemctl_start "$_service_name" && \
-        _systemctl_enable "$_service_name"
+        _systemctl_enable "$_service_name" && \
+        _openFirewall "jriver"
     }
     }
 
 
 
 
-    _serviceVNC() {
+    _service_jriver-xvnc-mediacenter() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         _installPackage tigervnc-server
         _installPackage tigervnc-server
 
 
+        local _next_displaynum=$(( _displaynum + 1 ))
+        _next_display=":$_next_displaynum"
+        #local _service_port=$(( _port + 1 ))
+
         _setVNCPass
         _setVNCPass
 
 
         if [[ -n $_novncauth ]]; then
         if [[ -n $_novncauth ]]; then
-            _exec_start_cmd="/usr/bin/vncserver $_display -geometry 1440x900 -alwaysshared -fg -SecurityTypes None -xstartup /usr/bin/mediacenter$_mversion"
+            _exec_start_cmd="/usr/bin/vncserver $_next_display -geometry 1440x900 -alwaysshared -fg -SecurityTypes None -xstartup /usr/bin/mediacenter$_mversion"
         else
         else
-            _exec_start_cmd="/usr/bin/vncserver $_display -geometry 1440x900 -alwaysshared -fg -rfbauth $HOME/.vnc/jrmc_passwd -xstartup /usr/bin/mediacenter$_mversion"
+            _exec_start_cmd="/usr/bin/vncserver $_next_display -geometry 1440x900 -alwaysshared -fg -rfbauth $HOME/.vnc/jrmc_passwd -xstartup /usr/bin/mediacenter$_mversion"
         fi
         fi
 
 
-        # Set the display to use
-        if [[ -z $_display ]]; then
-            # If we are running on existing X server then increment DISPLAY by one
-            if [[ -n $DISPLAY ]]; then
-                _display=$(( ${DISPLAY#:} + 1 ))
-                _display=":$_display"
-            else
-                _display=":0"
-            fi
-        fi
-
-        declare -g _port=$(( ${_display#:} + 5900 ))
-
         _bash_cmd "cat <<-EOF > $_service_fname
         _bash_cmd "cat <<-EOF > $_service_fname
 [Unit]
 [Unit]
 Description=Remote desktop service (VNC)
 Description=Remote desktop service (VNC)
@@ -1154,9 +1200,9 @@ After=syslog.target network.target
 [Service]
 [Service]
 Type=simple
 Type=simple
 $_user_specifier
 $_user_specifier
-ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill $_display > /dev/null 2>&1 || :'
+ExecStartPre=/bin/sh -c '/usr/bin/vncserver -kill $_next_display > /dev/null 2>&1 || :'
 ExecStart=$_exec_start_cmd
 ExecStart=$_exec_start_cmd
-ExecStop=/usr/bin/vncserver -kill $_display
+ExecStop=/usr/bin/vncserver -kill $_next_display
 
 
 [Install]
 [Install]
 WantedBy=multi-user.target
 WantedBy=multi-user.target
@@ -1164,22 +1210,20 @@ EOF"
         _systemctl_reload && \
         _systemctl_reload && \
         _systemctl_start "$_service_name" && \
         _systemctl_start "$_service_name" && \
         _systemctl_enable "$_service_name" && \
         _systemctl_enable "$_service_name" && \
-        echo "vncserver running on localhost:$_port"
+        vncserver --list && \
+        _openFirewall "xvnc" && \
+        _openFirewall "jriver"
     }
     }
 
 
 
 
-    _serviceX11VNC() {
+    _service_jriver-x11vnc-mediacenter() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         _installPackage x11vnc
         _installPackage x11vnc
 
 
         _setX11VNCPass
         _setX11VNCPass
 
 
-        [[ -z $_display ]] && _display="${DISPLAY:-":0"}"
-
-        declare -g _port=$(( ${_display#:} + 5900 ))
-
         # Get current desktop resolution
         # Get current desktop resolution
         # TODO: may need to break this out into its own function and get smarter at identifying multi-monitors
         # TODO: may need to break this out into its own function and get smarter at identifying multi-monitors
         local _res
         local _res
@@ -1209,14 +1253,17 @@ WantedBy=multi-user.target
 EOF"
 EOF"
         _systemctl_reload && \
         _systemctl_reload && \
         _systemctl_start "$_service_name" && \
         _systemctl_start "$_service_name" && \
-        _systemctl_enable "$_service_name"
-        echo "x11vnc running on localhost:$_port"
+        _systemctl_enable "$_service_name" && \
+        echo "x11vnc running on localhost:$_port" && \
+        _openFirewall "x11vnc"
+
+        _service_jriver-mediacenter
     }
     }
 
 
 
 
-    _serviceCreaterepo() {
+    _service_jriver-createrepo() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         _bash_cmd "cat <<-EOF > $_service_fname
         _bash_cmd "cat <<-EOF > $_service_fname
 [Unit]
 [Unit]
@@ -1266,7 +1313,7 @@ EOF"
 
 
     _uninstall() {
     _uninstall() {
 
 
-        _runDebug "${FUNCNAME[0]}"
+        debug "Running: ${FUNCNAME[0]}"
 
 
         read -r -p "Do you really want to uninstall JRiver Media Center? [y/N] " _response
         read -r -p "Do you really want to uninstall JRiver Media Center? [y/N] " _response
         _response=${_response,,}    # tolower
         _response=${_response,,}    # tolower
@@ -1314,26 +1361,17 @@ EOF"
 
 
     __main() {
     __main() {
 
 
-        # Check user
-        _checkUser
-
         # Parse input
         # Parse input
         _parseInput "$@"
         _parseInput "$@"
 
 
-        # Build some OS-specific commands based on the selected OS
-        _buildCommands
-
-        # Set version to install/uninstall
-        _setVersion
-
         # Sanity checks
         # Sanity checks
         _sanityChecks
         _sanityChecks
 
 
-        # Uninstall and exit
-        if [[ -n $_uninstall ]]; then
-            _uninstall
-            exit $?
-        fi
+        # Set user variables
+        _setUser
+
+        # Build some OS-specific commands based on the selected OS
+        _buildCommands
 
 
         # Install MC using package manager
         # Install MC using package manager
         if [[ -n $_repoinstall ]]; then
         if [[ -n $_repoinstall ]]; then
@@ -1344,6 +1382,15 @@ EOF"
             _openFirewall "jriver"
             _openFirewall "jriver"
         fi
         fi
 
 
+        # Set version to install/uninstall
+        _setVersion
+
+        # Uninstall and exit
+        if [[ -n $_uninstall ]]; then
+            _uninstall
+            exit $?
+        fi
+
         # Build RPM from source DEB
         # Build RPM from source DEB
         if [[ -n $_rpmbuild ]]; then
         if [[ -n $_rpmbuild ]]; then
             _acquireDeb
             _acquireDeb
@@ -1367,44 +1414,15 @@ EOF"
         fi
         fi
 
 
         # Install services
         # Install services
+        _setDisplayAndPort
         for _service in "${_services[@]}"; do
         for _service in "${_services[@]}"; do
             _servicePrep "$_service"
             _servicePrep "$_service"
-            case "$_service" in
-                createrepo)
-                    _serviceCreaterepo
-                    ;;
-                x11vnc)
-                    _serviceX11VNC
-                    _openFirewall "x11vnc"
-                    ;;
-                mediaserver)
-                    _serviceMediaserver
-                    ;;
-                mediacenter)
-                    _serviceMediacenter
-                    ;;
-                mediacenter-vncserver)
-                    _serviceVNC
-                    _openFirewall "vncserver"
-                    ;;
-                *)
-            esac
+            "_service_$_service"
         done
         done
 
 
         # Install containers
         # Install containers
         for _container in "${_containers[@]}"; do
         for _container in "${_containers[@]}"; do
-            case "$_container" in
-                createrepo)
-                    _containerCreaterepo
-                    ;;
-                mediacenter-vncserver)
-                    _containerVNC
-                    ;;
-                mediacenter)
-                    _containerMC
-                    ;;
-                *)
-            esac
+            "_container_$_container"
         done
         done
     }
     }
 }
 }