diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-11 08:17:27 +0000 |
commit | f215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch) | |
tree | 6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Installer/linux/routines.sh | |
parent | Initial commit. (diff) | |
download | virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.tar.xz virtualbox-f215e02bf85f68d3a6106c2a1f4f7f063f819064.zip |
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Installer/linux/routines.sh')
-rw-r--r-- | src/VBox/Installer/linux/routines.sh | 471 |
1 files changed, 471 insertions, 0 deletions
diff --git a/src/VBox/Installer/linux/routines.sh b/src/VBox/Installer/linux/routines.sh new file mode 100644 index 00000000..7638ee66 --- /dev/null +++ b/src/VBox/Installer/linux/routines.sh @@ -0,0 +1,471 @@ +# $Id: routines.sh $ +# Oracle VM VirtualBox +# VirtualBox installer shell routines +# + +# +# Copyright (C) 2007-2023 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.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, in version 3 of the +# License. +# +# 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, see <https://www.gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-3.0-only +# + +ro_LOG_FILE="" +ro_X11_AUTOSTART="/etc/xdg/autostart" +ro_KDE_AUTOSTART="/usr/share/autostart" + +## Aborts the script and prints an error message to stderr. +# +# syntax: abort message + +abort() +{ + echo 1>&2 "$1" + exit 1 +} + +## Creates an empty log file and remembers the name for future logging +# operations +create_log() +{ + ## The path of the file to create. + ro_LOG_FILE="$1" + if [ "$ro_LOG_FILE" = "" ]; then + abort "create_log called without an argument! Aborting..." + fi + # Create an empty file + echo > "$ro_LOG_FILE" 2> /dev/null + if [ ! -f "$ro_LOG_FILE" -o "`cat "$ro_LOG_FILE"`" != "" ]; then + abort "Error creating log file! Aborting..." + fi +} + +## Writes text to standard error, as standard output is masked. +# +# Syntax: info text +info() +{ + echo 1>&2 "$1" +} + +## Copies standard input to standard error, as standard output is masked. +# +# Syntax: info text +catinfo() +{ + cat 1>&2 +} + +## Writes text to the log file +# +# Syntax: log text +log() +{ + if [ "$ro_LOG_FILE" = "" ]; then + abort "Error! Logging has not been set up yet! Aborting..." + fi + echo "$1" >> $ro_LOG_FILE + return 0 +} + +## Writes test to standard output and to the log file +# +# Syntax: infolog text +infolog() +{ + info "$1" + log "$1" +} + +## Checks whether a module is loaded with a given string in its name. +# +# syntax: module_loaded string +module_loaded() +{ + if [ "$1" = "" ]; then + log "module_loaded called without an argument. Aborting..." + abort "Error in installer. Aborting..." + fi + lsmod | grep -q $1 +} + +## Abort if we are not running as root +check_root() +{ + if [ `id -u` -ne 0 ]; then + abort "This program must be run with administrator privileges. Aborting" + fi +} + +## Abort if dependencies are not found +check_deps() +{ + for i in ${@}; do + type "${i}" >/dev/null 2>&1 || + abort "${i} not found. Please install: ${*}; and try again." + done +} + +## Abort if a copy of VirtualBox is already running +check_running() +{ + VBOXSVC_PID=`pidof VBoxSVC 2> /dev/null` + if [ -n "$VBOXSVC_PID" ]; then + if [ -f /etc/init.d/vboxweb-service ]; then + kill -USR1 $VBOXSVC_PID + fi + sleep 1 + if pidof VBoxSVC > /dev/null 2>&1; then + echo 1>&2 "A copy of VirtualBox is currently running. Please close it and try again." + abort "Please note that it can take up to ten seconds for VirtualBox to finish running." + fi + fi +} + +## Creates a systemd wrapper in /lib for an LSB init script +systemd_wrap_init_script() +{ + self="systemd_wrap_init_script" + ## The init script to be installed. The file may be copied or referenced. + script="$(readlink -f -- "${1}")" + ## Name for the service. + name="$2" + test -x "$script" && test ! "$name" = "" || \ + { echo "$self: invalid arguments" >&2 && return 1; } + test -d /usr/lib/systemd/system && unit_path=/usr/lib/systemd/system + test -d /lib/systemd/system && unit_path=/lib/systemd/system + test -n "${unit_path}" || \ + { echo "$self: systemd unit path not found" >&2 && return 1; } + conflicts=`sed -n 's/# *X-Conflicts-With: *\(.*\)/\1/p' "${script}" | sed 's/\$[a-z]*//'` + description=`sed -n 's/# *Short-Description: *\(.*\)/\1/p' "${script}"` + required=`sed -n 's/# *Required-Start: *\(.*\)/\1/p' "${script}" | sed 's/\$[a-z]*//'` + required_target=`sed -n 's/# *X-Required-Target-Start: *\(.*\)/\1/p' "${script}"` + startbefore=`sed -n 's/# *X-Start-Before: *\(.*\)/\1/p' "${script}" | sed 's/\$[a-z]*//'` + runlevels=`sed -n 's/# *Default-Start: *\(.*\)/\1/p' "${script}"` + servicetype=`sed -n 's/# *X-Service-Type: *\(.*\)/\1/p' "${script}"` + test -z "${servicetype}" && servicetype="forking" + targets=`for i in ${runlevels}; do printf "runlevel${i}.target "; done` + before=`for i in ${startbefore}; do printf "${i}.service "; done` + after=`for i in ${required_target}; do printf "${i}.target "; done; for i in ${required}; do printf "${i}.service "; done` + cat > "${unit_path}/${name}.service" << EOF +[Unit] +SourcePath=${script} +Description=${description} +Before=${targets}shutdown.target ${before} +After=${after} +Conflicts=shutdown.target ${conflicts} + +[Service] +Type=${servicetype} +Restart=no +TimeoutSec=5min +IgnoreSIGPIPE=no +KillMode=process +GuessMainPID=no +RemainAfterExit=yes +ExecStart=${script} start +ExecStop=${script} stop + +[Install] +WantedBy=multi-user.target +EOF +} + +# Checks if systemctl is present and functional (i.e., systemd is the init process). +use_systemd() +{ + systemctl status >/dev/null 2>&1 +} + +## Installs a file containing a shell script as an init script. Call +# finish_init_script_install when all scripts have been installed. +install_init_script() +{ + self="install_init_script" + ## The init script to be installed. The file may be copied or referenced. + script="$1" + ## Name for the service. + name="$2" + + test -x "${script}" && test ! "${name}" = "" || + { echo "${self}: invalid arguments" >&2; return 1; } + # Do not unconditionally silence the following "ln". + test -L "/sbin/rc${name}" && rm "/sbin/rc${name}" + ln -s "${script}" "/sbin/rc${name}" + if test -x "`which systemctl 2>/dev/null`"; then + if use_systemd; then + { systemd_wrap_init_script "$script" "$name"; return; } + fi + fi + if test -d /etc/rc.d/init.d; then + cp "${script}" "/etc/rc.d/init.d/${name}" && + chmod 755 "/etc/rc.d/init.d/${name}" + elif test -d /etc/init.d; then + cp "${script}" "/etc/init.d/${name}" && + chmod 755 "/etc/init.d/${name}" + else + { echo "${self}: error: unknown init type" >&2; return 1; } + fi +} + +## Remove the init script "name" +remove_init_script() +{ + self="remove_init_script" + ## Name of the service to remove. + name="$1" + + test -n "${name}" || + { echo "$self: missing argument"; return 1; } + rm -f "/sbin/rc${name}" + rm -f /lib/systemd/system/"$name".service /usr/lib/systemd/system/"$name".service + rm -f "/etc/rc.d/init.d/$name" + rm -f "/etc/init.d/$name" +} + +## Tell systemd services have been installed or removed. Should not be done +# after each individual one, as systemd can crash if it is done too often +# (reported by the OL team for OL 7.6, may not apply to other versions.) +finish_init_script_install() +{ + if use_systemd; then + systemctl daemon-reload + fi +} + +## Did we install a systemd service? +systemd_service_installed() +{ + ## Name of service to test. + name="${1}" + + test -f /lib/systemd/system/"${name}".service || + test -f /usr/lib/systemd/system/"${name}".service +} + +## Perform an action on a service +do_sysvinit_action() +{ + self="do_sysvinit_action" + ## Name of service to start. + name="${1}" + ## The action to perform, normally "start", "stop" or "status". + action="${2}" + + test ! -z "${name}" && test ! -z "${action}" || + { echo "${self}: missing argument" >&2; return 1; } + if systemd_service_installed "${name}"; then + systemctl -q ${action} "${name}" + elif test -x "/etc/rc.d/init.d/${name}"; then + "/etc/rc.d/init.d/${name}" "${action}" quiet + elif test -x "/etc/init.d/${name}"; then + "/etc/init.d/${name}" "${action}" quiet + fi +} + +## Start a service +start_init_script() +{ + do_sysvinit_action "${1}" start +} + +## Stop the init script "name" +stop_init_script() +{ + do_sysvinit_action "${1}" stop +} + +## Extract chkconfig information from a sysvinit script. +get_chkconfig_info() +{ + ## The script to extract the information from. + script="${1}" + + set `sed -n 's/# *chkconfig: *\([0-9]*\) *\(.*\)/\1 \2/p' "${script}"` + ## Which runlevels should we start in? + runlevels="${1}" + ## How soon in the boot process will we start, from 00 (first) to 99 + start_order="${2}" + ## How soon in the shutdown process will we stop, from 99 (first) to 00 + stop_order="${3}" + test ! -z "${name}" || \ + { echo "${self}: missing name" >&2; return 1; } + expr "${start_order}" + 0 > /dev/null 2>&1 && \ + expr 0 \<= "${start_order}" > /dev/null 2>&1 && \ + test `expr length "${start_order}"` -eq 2 > /dev/null 2>&1 || \ + { echo "${self}: start sequence number must be between 00 and 99" >&2; + return 1; } + expr "${stop_order}" + 0 > /dev/null 2>&1 && \ + expr 0 \<= "${stop_order}" > /dev/null 2>&1 && \ + test `expr length "${stop_order}"` -eq 2 > /dev/null 2>&1 || \ + { echo "${self}: stop sequence number must be between 00 and 99" >&2; + return 1; } +} + +## Add a service to its default runlevels (annotated inside the script, see get_chkconfig_info). +addrunlevel() +{ + self="addrunlevel" + ## Service name. + name="${1}" + + test -n "${name}" || \ + { echo "${self}: missing argument" >&2; return 1; } + systemd_service_installed "${name}" && \ + { systemctl -q enable "${name}"; return; } + if test -x "/etc/rc.d/init.d/${name}"; then + init_d_path=/etc/rc.d + elif test -x "/etc/init.d/${name}"; then + init_d_path=/etc + else + { echo "${self}: error: unknown init type" >&2; return 1; } + fi + get_chkconfig_info "${init_d_path}/init.d/${name}" || return 1 + # Redhat based sysvinit systems + if test -x "`which chkconfig 2>/dev/null`"; then + chkconfig --add "${name}" + # SUSE-based sysvinit systems + elif test -x "`which insserv 2>/dev/null`"; then + insserv "${name}" + # Debian/Ubuntu-based systems + elif test -x "`which update-rc.d 2>/dev/null`"; then + # Old Debians did not support dependencies + update-rc.d "${name}" defaults "${start_order}" "${stop_order}" + # Gentoo Linux + elif test -x "`which rc-update 2>/dev/null`"; then + rc-update add "${name}" default + # Generic sysvinit + elif test -n "${init_d_path}/rc0.d" + then + for locali in 0 1 2 3 4 5 6 + do + target="${init_d_path}/rc${locali}.d/K${stop_order}${name}" + expr "${runlevels}" : ".*${locali}" >/dev/null && \ + target="${init_d_path}/rc${locali}.d/S${start_order}${name}" + test -e "${init_d_path}/rc${locali}.d/"[KS][0-9]*"${name}" || \ + ln -fs "${init_d_path}/init.d/${name}" "${target}" + done + else + { echo "${self}: error: unknown init type" >&2; return 1; } + fi +} + + +## Delete a service from a runlevel +delrunlevel() +{ + self="delrunlevel" + ## Service name. + name="${1}" + + test -n "${name}" || + { echo "${self}: missing argument" >&2; return 1; } + systemctl -q disable "${name}" >/dev/null 2>&1 + # Redhat-based systems + chkconfig --del "${name}" >/dev/null 2>&1 + # SUSE-based sysvinit systems + insserv -r "${name}" >/dev/null 2>&1 + # Debian/Ubuntu-based systems + update-rc.d -f "${name}" remove >/dev/null 2>&1 + # Gentoo Linux + rc-update del "${name}" >/dev/null 2>&1 + # Generic sysvinit + rm -f /etc/rc.d/rc?.d/[SK]??"${name}" + rm -f /etc/rc?.d/[SK]??"${name}" +} + + +terminate_proc() { + PROC_NAME="${1}" + SERVER_PID=`pidof $PROC_NAME 2> /dev/null` + if [ "$SERVER_PID" != "" ]; then + killall -TERM $PROC_NAME > /dev/null 2>&1 + sleep 2 + fi +} + + +# install_python_bindings(pythonbin pythondesc) +# failure: non fatal +install_python_bindings() +{ + pythonbin="$1" + pythondesc="$2" + + # The python binary might not be there, so just exit silently + if test -z "$pythonbin"; then + return 0 + fi + + if test -z "$pythondesc"; then + echo 1>&2 "missing argument to install_python_bindings" + return 1 + fi + + echo 1>&2 "Python found: $pythonbin, installing bindings..." + + # check if python has working distutils + "$pythonbin" -c "from distutils.core import setup" > /dev/null 2>&1 + if test "$?" -ne 0; then + echo 1>&2 "Skipped: $pythondesc install is unusable, missing package 'distutils'" + return 0 + fi + + # Pass install path via environment + export VBOX_INSTALL_PATH + $SHELL -c "cd $VBOX_INSTALL_PATH/sdk/installer && $pythonbin vboxapisetup.py install \ + --record $CONFIG_DIR/python-$CONFIG_FILES" + cat $CONFIG_DIR/python-$CONFIG_FILES >> $CONFIG_DIR/$CONFIG_FILES + rm -f $CONFIG_DIR/python-$CONFIG_FILES + + # Remove files created by Python API setup. + rm -rf $VBOX_INSTALL_PATH/sdk/installer/build +} + +maybe_run_python_bindings_installer() { + VBOX_INSTALL_PATH="${1}" + + # Loop over all usual suspect Python executable names and try installing + # the VirtualBox API bindings. Needs to prevent double installs which waste + # quite a bit of time. + PYTHONS="" + for p in python2.6 python2.7 python2 python3.3 python3.4 python3.5 python3.6 python3.7 python3.8 python3.9 python3.10 python3 python; do + if [ "`$p -c 'import sys +if sys.version_info >= (2, 6) and (sys.version_info < (3, 0) or sys.version_info >= (3, 3)): + print(\"test\")' 2> /dev/null`" != "test" ]; then + continue + fi + # Get python major/minor version, and skip if it was already covered. + # Uses grep -F to avoid trouble with '.' matching any char. + pyvers="`$p -c 'import sys +print("%s.%s" % (sys.version_info[0], sys.version_info[1]))' 2> /dev/null`" + if echo "$PYTHONS" | grep -Fq ":$pyvers:"; then + continue + fi + # Record which version will be installed. If it fails there is no point + # trying with different executable/symlink reporting the same version. + PYTHONS="$PYTHONS:$pyvers:" + install_python_bindings "$p" "Python $pyvers" + done + if [ -z "$PYTHONS" ]; then + echo 1>&2 "Python (2.6, 2.7 or 3.3 and later) unavailable, skipping bindings installation." + return 1 + fi + + return 0 +} |