routines.sh revision 320484435d67c1fb90dca3e8836d81bf939c8ba2
# Oracle VM VirtualBox
# VirtualBox installer shell routines
#
# Copyright (C) 2007-2010 Oracle Corporation
#
# Oracle Corporation confidential
# All rights reserved
#
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
#
# syntax: create_log logfile
create_log() {
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
#
# Syntax: info text
info() {
echo 1>&2 "$1"
}
# 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 a copy of VirtualBox is already running
check_running() {
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
}
# Do we have bzip2?
check_bzip2() {
if ! ls /bin/bzip2 /usr/bin/bzip2 /usr/local/bin/bzip2 2> /dev/null | grep bzip2 > /dev/null; then
echo 1>&2 "Please install the bzip2 utility."
log "Please install bzip2."
return 1
fi
return 0
}
# Do we have GNU make?
check_gmake() {
make --version 2>&1 | grep GNU > /dev/null
if [ ! $? = 0 ]; then
echo 1>&2 "Please install GNU make."
log "Please install GNU make."
return 1
fi
return 0
}
# Can we find the kernel source?
check_ksource() {
ro_KBUILD_DIR=/lib/modules/`uname -r`/build
if [ ! -d $ro_KBUILD_DIR/include ]; then
ro_KBUILD_DIR=/usr/src/linux
if [ ! -d $ro_KBUILD_DIR/include ]; then
echo 1>&2 "Please install the build and header files for your current Linux kernel."
echo 1>&2 "The current kernel version is `uname -r`"
ro_KBUILD_DIR=""
log "Could not find the Linux kernel header files - the directories"
log " /lib/modules/`uname -r`/build/include and /usr/src/linux/include"
log " do not exist."
return 1
fi
fi
return 0
}
# Is GCC installed?
check_gcc() {
ro_gcc_version=`gcc --version 2> /dev/null | head -n 1`
if [ "$ro_gcc_version" = "" ]; then
echo 1>&2 "Please install the GNU compiler."
log "Please install the GNU compiler."
return 1
fi # GCC installed
return 0
}
# Is bash installed? You never know...
check_bash() {
if [ ! -x /bin/bash ]; then
echo 1>&2 "Please install GNU bash."
log "Please install GNU bash."
return 1
fi
return 0
}
# Is perl installed?
check_perl() {
if [ ! `perl -e 'print "test"' 2> /dev/null` = "test" ]; then
echo 1>&2 "Please install perl."
echo "Please install perl."
return 1
fi
return 0
}
# What type of system are we running on?
check_system_type() {
if [ ! "$ro_SYS_TYPE" = "" ]; then
return 0
elif [ -f /etc/debian_version ]; then
ro_SYS_TYPE=debian
ro_INIT_TYPE=sysv
elif [ -f /etc/gentoo-release ]; then
ro_SYS_TYPE=gentoo
ro_INIT_TYPE=sysv
elif [ -x /sbin/chkconfig ]; then
ro_SYS_TYPE=redhat
ro_INIT_TYPE=sysv
elif [ -x /sbin/insserv ]; then
ro_SYS_TYPE=suse
ro_INIT_TYPE=sysv
elif [ -f /etc/lfs-release -a -d /etc/rc.d/init.d ]; then
ro_SYS_TYPE=lfs
ro_INIT_TYPE=lfs
elif [ -f /etc/pardus-release ]; then
ro_SYS_TYPE=pardus
ro_INIT_TYPE=pardus
elif [ -f /etc/rc.d/rc.local ]; then
ro_SYS_TYPE=unknown
ro_INIT_TYPE=bsd
ro_RC_LOCAL=/etc/rc.d/rc.local
elif [ -f /etc/rc.local ]; then
ro_SYS_TYPE=unknown
ro_INIT_TYPE=bsd
ro_RC_LOCAL=/etc/rc.local
elif [ -d /etc/init.d ]; then
ro_SYS_TYPE=unknown
ro_INIT_TYPE=sysv
else # Perhaps we can determine what we need to know anyway though?
echo 1>&2 "Unable to determine your Linux distribution"
log "Unable to determine the Linux distribution"
return 1
fi
return 0
}
# Hack to handle Mandriva's speedboot runlevel
copy_install_script() {
if [ "$ro_INIT_TYPE" = "sysv" -a -r /etc/sysconfig/speedboot ]; then
cp "$1" "$2" 2>/dev/null
else
sed -e 's/^\(#\s*chkconfig:\s*[0-9]*\)7/\1/' "$1" > "$2"
fi
}
# Installs a file containing a shell script as an init script
#
# syntax: install_init_script file name
#
# where file is the file to be installed and
# name is the name of the new init script
install_init_script() {
self="install_init_script"
script=$1
name=$2
pardus_script=$name-pardus.py
check_system_type
test $? -ne 1 || return 1
test -r "$script" || return 1
test ! "$name" = "" || \
{ log "$self: invalid arguments" && return 1; }
if [ "$ro_INIT_TYPE" = "pardus" ];then
test -r "$pardus_script" || \
{ log "$self: Pardus service script missing" && return 1; }
fi
if [ "$ro_INIT_TYPE" = "sysv" ]; then
copy_install_script "$script" "/etc/init.d/$name"
chmod 755 "/etc/init.d/$name" 2> /dev/null
elif [ "$ro_INIT_TYPE" = "bsd" ]; then
copy_install_script "$script" "/etc/rc.d/rc.$name"
chmod 755 "/etc/rc.d/rc.$name" 2> /dev/null
elif [ "$ro_INIT_TYPE" = "lfs" ]; then
copy_install_script "$script" "/etc/rc.d/init.d/$name"
chmod 755 "/etc/rc.d/init.d/$name" 2> /dev/null
elif [ "$ro_INIT_TYPE" = "pardus" ]; then
copy_install_script "$script" "/usr/sbin/$name"
chmod 755 "/usr/sbin/$name" 2> /dev/null
hav register $name System.Service $pardus_script
else
log "install_init_script: error: unknown init type"
return 1
fi
return 0
}
# Remove the init script "name"
#
# syntax: remove_init_script name
remove_init_script() {
self="remove_init_script"
name=$1
check_system_type
test $? -ne 1 || return 1
test ! "$name" = "" || \
{ log "$self: missing argument" && return 1; }
if [ "$ro_INIT_TYPE" = "sysv" ]; then
rm -f "/etc/init.d/$name" > /dev/null 2>&1
elif [ "$ro_INIT_TYPE" = "bsd" ]; then
rm -f "/etc/rc.d/rc.$name" > /dev/null 2>&1
elif [ "$ro_INIT_TYPE" = "lfs" ]; then
rm -f "/etc/rc.d/init.d/$name" > /dev/null 2>&1
elif [ "$ro_INIT_TYPE" = "pardus" ]; then
hav remove $name
rm -f "/usr/sbin/$name" > /dev/null 2>&1
else
log "remove_init_script: error: unknown init type"
return 1
fi
return 0
}
# Start the init script "name"
#
# syntax: start_init_script name
start_init_script() {
self="start_init_script"
name=$1
check_system_type
test $? -ne 1 || return 1
test ! -z "$name" || \
{ log "$self: missing argument" && return 1; }
if [ "$ro_INIT_TYPE" = "sysv" ]; then
"/etc/init.d/$name" start >> $ro_LOG_FILE 2>&1
elif [ "$ro_INIT_TYPE" = "bsd" ]; then
"/etc/rc.d/rc.$name" start >> $ro_LOG_FILE 2>&1
elif [ "$ro_INIT_TYPE" = "lfs" ]; then
"/etc/rc.d/init.d/$name" start >> $ro_LOG_FILE 2>&1
elif [ "$ro_INIT_TYPE" = "pardus" ]; then
service $name on
else
log "$self: error: unknown init type"
return 1
fi
}
# Stop the init script "name"
#
# syntax: start_init_script name
stop_init_script() {
self=stop_init_script
name=$1
check_system_type
test $? -ne 1 || return 1
test ! -z "$name" || \
{ log "$self: missing argument" && return 1; }
if [ "$ro_INIT_TYPE" = "sysv" ]; then
"/etc/init.d/$name" stop >> $ro_LOG_FILE 2>&1
elif [ "$ro_INIT_TYPE" = "bsd" ]; then
"/etc/rc.d/rc.$name" stop >> $ro_LOG_FILE 2>&1
elif [ "$ro_INIT_TYPE" = "lfs" ]; then
"/etc/rc.d/init.d/$name" stop >> $ro_LOG_FILE 2>&1
elif [ "$ro_INIT_TYPE" = "pardus" ]; then
service $name off
else
log "$self: error: unknown init type"
return 1
fi
return 0
}
# Add a service to a runlevel
#
# syntax: addrunlevel name start_order stop_order
addrunlevel() {
test ! -z "$1" || \
{ log "addrunlevel: missing argument(s)" && return 1; }
check_system_type
# Redhat based systems
if [ "$ro_SYS_TYPE" = "redhat" ]
then
test -x "/sbin/chkconfig" || \
{ log "addrunlevel: /sbin/chkconfig not found" && return 1; }
/sbin/chkconfig --del $1 > /dev/null 2>&1
if /sbin/chkconfig -v > /dev/null 2>&1; then
/sbin/chkconfig --level 35 $1 on || {
log "Cannot add $1 to run levels: 35" && return 1
}
else
/sbin/chkconfig $1 35 || {
log "Cannot add $1 to run levels: 35" && return 1
}
fi
# SUSE-base systems
elif [ "$ro_SYS_TYPE" = "suse" ]
then
test -x /sbin/insserv || {
log "addrunlevel: insserv not found" && return 1;
}
/sbin/insserv -r $1 > /dev/null 2>&1
/sbin/insserv $1 > /dev/null
# Debian/Ubuntu-based systems
elif [ "$ro_SYS_TYPE" = "debian" ]; then
test -x `which update-rc.d` || \
{ log "addrunlevel: update-rc.d not found" && return 1; }
test ! -z "$2" || \
{ log "addrunlevel: missing second argument" && return 1; }
test ! -z "$3" || \
{ log "addrunlevel: missing third argument" && return 1; }
# Debian does not support dependencies currently -- use argument $2
# for start sequence number and argument $3 for stop sequence number
update-rc.d -f $1 remove > /dev/null 2>&1
update-rc.d $1 defaults $2 $3 > /dev/null 2>&1
# Gentoo Linux
elif [ "$ro_SYS_TYPE" = "gentoo" ]; then
test -x `which rc-update` || \
{ log "addrunlevel: update-rc.d not found" && return 1; }
rc-update del $1 > /dev/null 2>&1
rc-update add $1 default > /dev/null 2>&1
# Linux from scratch, by the book
elif [ "$ro_SYS_TYPE" = "lfs" ]; then
test -x /etc/rc.d/init.d/$1 || \
{ log "addrunlevel: name argument must be a script in /etc/rc.d/init.d" && return 1; }
P2=$2
P3=$3
# add leading zero
if [ `expr length "$P2"` -eq 1 ]; then
P2=`expr 0$P2`
fi
if [ `expr length "$P3"` -eq 1 ]; then
P3=`expr 0$P3`
fi
expr "$P2" + 0 > /dev/null 2>&1 && expr 0 \<= "$P2" > /dev/null && \
[ `expr length "$P2"` -eq 2 ] || \
{ log "addrunlevel: start sequence number must be between 00 and 99" && return 1; }
expr "$P3" + 0 > /dev/null 2>&1 && expr 0 \<= "$P3" > /dev/null && \
[ `expr length "$P3"` -eq 2 ] || \
{ log "addrunlevel: stop sequence number must be between 00 and 99" && return 1; }
ln -fs "/etc/rc.d/init.d/$1" "/etc/rc.d/rc0.d/K`expr $P3`$1" > /dev/null 2>&1
ln -fs "/etc/rc.d/init.d/$1" "/etc/rc.d/rc1.d/K`expr $P3`$1" > /dev/null 2>&1
ln -fs "/etc/rc.d/init.d/$1" "/etc/rc.d/rc2.d/S`expr $P2`$1" > /dev/null 2>&1
ln -fs "/etc/rc.d/init.d/$1" "/etc/rc.d/rc3.d/S`expr $P2`$1" > /dev/null 2>&1
ln -fs "/etc/rc.d/init.d/$1" "/etc/rc.d/rc4.d/S`expr $P2`$1" > /dev/null 2>&1
ln -fs "/etc/rc.d/init.d/$1" "/etc/rc.d/rc5.d/S`expr $P2`$1" > /dev/null 2>&1
ln -fs "/etc/rc.d/init.d/$1" "/etc/rc.d/rc6.d/K`expr $P3`$1" > /dev/null 2>&1
# BSD-based systems require changing the rc.local file to start a new service.
elif [ "$ro_INIT_TYPE" = "bsd" ]; then
if ! grep -q $1 $ro_RC_LOCAL
then
echo "# Start $1" >> $ro_RC_LOCAL
echo "# If you do not wish this to be executed here then comment it out," >> $ro_RC_LOCAL
echo "# and the installer will skip it next time." >> $ro_RC_LOCAL
echo "if [ -x /etc/rc.d/rc.$1 ]; then" >> $ro_RC_LOCAL
echo " /etc/rc.d/rc.$1 start" >> $ro_RC_LOCAL
echo "fi" >> $ro_RC_LOCAL
echo "" >> $ro_RC_LOCAL
fi
# Probably most unknown Linux systems will be sysv type ones. These can theoretically
# be handled automatically if people give us information about them.
elif [ "$ro_INIT_TYPE" = "sysv" ]; then
echo 1>&2 "As our installer does not recognize your Linux distribution, we were unable to"
echo 1>&2 "set up the initialization script $1 correctly. The script has been copied"
echo 1>&2 "copied to the /etc/init.d directory. You should set up your system to start"
echo 1>&2 "it at system start, or start it manually before using VirtualBox."
echo 1>&2 ""
echo 1>&2 "If you would like to help us add support for your distribution, please open a"
echo 1>&2 "new ticket on http://www.virtualbox.org/wiki/Bugtracker."
fi
return 0
}
# Delete a service from a runlevel
#
# syntax: delrunlevel name
delrunlevel() {
test ! -z "$1" || \
{ log "delrunlevel: missing argument" && return 1; }
check_system_type
# Redhat-based systems
if [ "$ro_SYS_TYPE" = "redhat" ]
then
test -x "/sbin/chkconfig" || \
{ log "addrunlevel: /sbin/chkconfig not found" && return 1; }
if /sbin/chkconfig --list $1 > /dev/null 2>&1; then
/sbin/chkconfig --del $1 > /dev/null 2>&1 || {
log "Cannot delete $1 from runlevels" && return 1
}
fi
# SUSE-based systems
elif [ "$ro_SYS_TYPE" = "suse" ]
then
test -x /sbin/insserv || {
log "addrunlevel: insserv not found" && return 1;
}
/sbin/insserv -r $1 > /dev/null 2>&1
# Debian/Ubuntu-based systems
elif [ "$ro_SYS_TYPE" = "debian" ]; then
test -x `which update-rc.d` || \
{ log "addrunlevel: update-rc.d not found" && return 1; }
update-rc.d -f $1 remove > /dev/null 2>&1
# Gentoo Linux
elif [ "$ro_SYS_TYPE" = "gentoo" ]; then
test -x `which rc-update` || \
{ log "addrunlevel: update-rc.d not found" && return 1; }
rc-update del "$1" > /dev/null 2>&1
# Linux from scratch, by the book
elif [ "$ro_SYS_TYPE" = "lfs" ]; then
rm "/etc/rc0.d/K??$1" > /dev/null 2>&1
rm "/etc/rc1.d/K??$1" > /dev/null 2>&1
rm "/etc/rc2.d/S??$1" > /dev/null 2>&1
rm "/etc/rc3.d/S??$1" > /dev/null 2>&1
rm "/etc/rc4.d/S??$1" > /dev/null 2>&1
rm "/etc/rc5.d/S??$1" > /dev/null 2>&1
rm "/etc/rc6.d/K??$1" > /dev/null 2>&1
# Unknown sysv-type system
elif [ "$ro_INIT_TYPE" = "sysv" ]; then
echo 1>&2 "Please remove remove references to the initialization script"
echo 1>&2 "/etc/init.d/$1 to complete the uninstallation."
fi
# BSD-type systems will just not start the script if it is not there.
# Assume that BSD users understand their system.
return 0
}
# Do initial setup of an installed service
#
# syntax: setup_init_script name
setup_init_script()
{
self=setup_init_script
name=$1
spaces=`printf " %b" "\t"`
check_system_type
test $? -ne 1 || return 1
test ! -z "$name" ||
{ log "$self: missing argument" && return 1; }
if [ "$ro_INIT_TYPE" = "sysv" ]; then
scriptname="/etc/init.d/$name"
elif [ "$ro_INIT_TYPE" = "bsd" ]; then
scriptname="/etc/rc.d/rc.$name"
elif [ "$ro_INIT_TYPE" = "lfs" ]; then
scriptname="/etc/rc.d/init.d/$name"
elif [ "$ro_INIT_TYPE" = "pardus" ]; then
scriptname="/usr/sbin/$name"
else
log "$self: error: unknown init type"
return 1
fi
# Add the init script to the default runlevel
# This is complicated by the fact that we need to pass older Debian-based
# systems the start and stop order numbers, which we extract from the
# Redhat chkconfig information.
if test "$ro_INIT_TYPE" = "sysv" -a -r "$scriptname"; then
orders=`grep '^#['"$spaces"']*chkconfig:' "$scriptname" |
sed -e 's/^#['"$spaces"']*chkconfig:\s*[0-9]*['"$spaces"']*//'`
expr "$orders" : '[0-9]*['"$spaces"']*[0-9]*$' > /dev/null ||
{
log "$self: bad or missing chkconfig line in init script $scriptname"
return 1
}
# $orders is deliberately not quoted here
addrunlevel "$name" $orders
else
addrunlevel "$name"
fi
test -r "$scriptname" &&
grep -q '^#['"$spaces"']*setup_script['"$spaces"']*$' "$scriptname" &&
"$scriptname" setup
return 0
}
# Do pre-removal cleanup of an installed service
#
# syntax: cleanup_init_script name
cleanup_init()
{
self=cleanup_init_script
name=$1
spaces=`printf " %b" "\t"`
check_system_type
test $? -ne 1 || return 1
test ! -z "$name" || \
{ log "$self: missing argument" && return 1; }
if [ "$ro_INIT_TYPE" = "sysv" ]; then
scriptname="/etc/init.d/$name"
elif [ "$ro_INIT_TYPE" = "bsd" ]; then
scriptname="/etc/rc.d/rc.$name"
elif [ "$ro_INIT_TYPE" = "lfs" ]; then
scriptname="/etc/rc.d/init.d/$name"
elif [ "$ro_INIT_TYPE" = "pardus" ]; then
scriptname="/usr/sbin/$name"
else
log "$self: error: unknown init type"
return 1
fi
test -r "$scriptname" &&
grep -q '^#['"$spaces"']*cleanup_script['"$spaces"']*$' "$scriptname" &&
"$scriptname" cleanup >> $ro_LOG_FILE 2>&1
delrunlevel "$name"
return 0
}
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
}
maybe_run_python_bindings_installer() {
VBOX_INSTALL_PATH=$1
PYTHON=python
if [ ! `python -c 'print "test"' 2> /dev/null` = "test" ]; then
echo 1>&2 "Python not available, skipping bindings installation."
return 1
fi
echo 1>&2 "Python found: $PYTHON, installing bindings..."
# Pass install path via environment
export VBOX_INSTALL_PATH
$SHELL -c "cd $VBOX_INSTALL_PATH/sdk/installer && $PYTHON vboxapisetup.py install"
# remove files created during build
rm -rf $VBOX_INSTALL_PATH/sdk/installer/build
return 0
}