--- services.sh 2005-03-23 10:16:38.000000000 +0000 +++ vmware-linux-tools 2005-10-30 20:58:12.576719779 +0000 @@ -1,338 +1,26 @@ -#!/bin/sh +#!/sbin/runscript # # Copyright (C) 1998-2002 VMware, Inc. All Rights Reserved. +# Updated by stuart@gentoo.org to support Gentoo Linux # -# This script manages the services needed to run VMware software - -# Basic support for IRIX style chkconfig -# chkconfig: 3 90 08 -# description: Manages the services needed to run VMware software - -# Basic support for the Linux Standard Base Specification 1.0.0 (to be used by -# insserv for exemple) -### BEGIN INIT INFO -# Provides: VMware_Tools -# Required-Start: -# Required-Stop: $network -# Default-Start: 3 5 -# Default-Stop: -# Description: Manages the services needed to run VMware Tools -### END INIT INFO - -# BEGINNING_OF_TMPDIR_DOT_SH -#!/bin/sh - -# Create a temporary directory +# $Header: /var/cvsroot/gentoo-x86/app-emulation/vmware-linux-tools/files/5.0.0/vmware-linux-tools,v 1.1 2005/04/30 21:26:48 stuart Exp $ # -# They are a lot of small utility programs to create temporary files in a -# secure way, but none of them is standard. So I wrote this --hpreg -make_tmp_dir() { - local dirname="$1" # OUT - local prefix="$2" # IN - local tmp - local serial - local loop - - tmp="${TMPDIR:-/tmp}" - - # Don't overwrite existing user data - # -> Create a directory with a name that didn't exist before - # - # This may never succeed (if we are racing with a malicious process), but at - # least it is secure - serial=0 - loop='yes' - while [ "$loop" = 'yes' ]; do - # Check the validity of the temporary directory. We do this in the loop - # because it can change over time - if [ ! -d "$tmp" ]; then - echo 'Error: "'"$tmp"'" is not a directory.' - echo - exit 1 - fi - if [ ! -w "$tmp" -o ! -x "$tmp" ]; then - echo 'Error: "'"$tmp"'" should be writable and executable.' - echo - exit 1 - fi - - # Be secure - # -> Don't give write access to other users (so that they can not use this - # directory to launch a symlink attack) - if mkdir -m 0755 "$tmp"'/'"$prefix$serial" >/dev/null 2>&1; then - loop='no' - else - serial=$(($serial + 1)) - if [ "$(($serial % 200))" = '0' ]; then - echo 'Warning: The "'"$tmp"'" directory may be under attack.' - echo - fi - fi - done - - eval "$dirname"'="$tmp"'"'"'/'"'"'"$prefix$serial"' -} -# END_OF_TMPDIR_DOT_SH - -vmware_etc_dir=/etc/vmware-tools - -# Since this script is installed, our main database should be installed too and -# should contain the basic information -vmware_db="$vmware_etc_dir"/locations -if [ ! -r "$vmware_db" ]; then - echo 'Warning: Unable to find '"`vmware_product_name`""'"'s main database '"$vmware_db"'.' - echo - - exit 1 -fi - -# BEGINNING_OF_DB_DOT_SH -#!/bin/sh - -# -# Manage an installer database -# - -# Add an answer to a database in memory -db_answer_add() { - local dbvar="$1" # IN/OUT - local id="$2" # IN - local value="$3" # IN - local answers - local i - - eval "$dbvar"'_answer_'"$id"'="$value"' - - eval 'answers="$'"$dbvar"'_answers"' - # There is no double quote around $answers on purpose - for i in $answers; do - if [ "$i" = "$id" ]; then - return - fi - done - answers="$answers"' '"$id" - eval "$dbvar"'_answers="$answers"' -} - -# Remove an answer from a database in memory -db_answer_remove() { - local dbvar="$1" # IN/OUT - local id="$2" # IN - local new_answers - local answers - local i - - eval 'unset '"$dbvar"'_answer_'"$id" - - new_answers='' - eval 'answers="$'"$dbvar"'_answers"' - # There is no double quote around $answers on purpose - for i in $answers; do - if [ "$i" != "$id" ]; then - new_answers="$new_answers"' '"$i" - fi - done - eval "$dbvar"'_answers="$new_answers"' -} - -# Load all answers from a database on stdin to memory (_answer_* -# variables) -db_load_from_stdin() { - local dbvar="$1" # OUT - - eval "$dbvar"'_answers=""' - - # read doesn't support -r on FreeBSD 3.x. For this reason, the following line - # is patched to remove the -r in case of FreeBSD tools build. So don't make - # changes to it. -- Jeremy Bar - while read -r action p1 p2; do - if [ "$action" = 'answer' ]; then - db_answer_add "$dbvar" "$p1" "$p2" - elif [ "$action" = 'remove_answer' ]; then - db_answer_remove "$dbvar" "$p1" - fi - done -} - -# Load all answers from a database on disk to memory (_answer_* -# variables) -db_load() { - local dbvar="$1" # OUT - local dbfile="$2" # IN - - db_load_from_stdin "$dbvar" < "$dbfile" -} - -# Iterate through all answers in a database in memory, calling with -# id/value pairs and the remaining arguments to this function -db_iterate() { - local dbvar="$1" # IN - local func="$2" # IN - shift 2 - local answers - local i - local value - - eval 'answers="$'"$dbvar"'_answers"' - # There is no double quote around $answers on purpose - for i in $answers; do - eval 'value="$'"$dbvar"'_answer_'"$i"'"' - "$func" "$i" "$value" "$@" - done -} - -# If it exists in memory, remove an answer from a database (disk and memory) -db_remove_answer() { - local dbvar="$1" # IN/OUT - local dbfile="$2" # IN - local id="$3" # IN - local answers - local i - - eval 'answers="$'"$dbvar"'_answers"' - # There is no double quote around $answers on purpose - for i in $answers; do - if [ "$i" = "$id" ]; then - echo 'remove_answer '"$id" >> "$dbfile" - db_answer_remove "$dbvar" "$id" - return - fi - done -} - -# Add an answer to a database (disk and memory) -db_add_answer() { - local dbvar="$1" # IN/OUT - local dbfile="$2" # IN - local id="$3" # IN - local value="$4" # IN - - db_remove_answer "$dbvar" "$dbfile" "$id" - echo 'answer '"$id"' '"$value" >> "$dbfile" - db_answer_add "$dbvar" "$id" "$value" -} - -# Add a file to a database on disk -# 'file' is the file to put in the database (it may not exist on the disk) -# 'tsfile' is the file to get the timestamp from, '' if no timestamp -db_add_file() { - local dbfile="$1" # IN - local file="$2" # IN - local tsfile="$3" # IN - local date - - if [ "$tsfile" = '' ]; then - echo 'file '"$file" >> "$dbfile" - else - date=`date -r "$tsfile" '+%s' 2> /dev/null` - if [ "$date" != '' ]; then - date=' '"$date" - fi - echo 'file '"$file$date" >> "$dbfile" - fi -} - -# Add a directory to a database on disk -db_add_dir() { - local dbfile="$1" # IN - local dir="$2" # IN - - echo 'directory '"$dir" >> "$dbfile" -} -# END_OF_DB_DOT_SH - -db_load 'vmdb' "$vmware_db" - -# This comment is a hack to prevent RedHat distributions from outputing -# "Starting " when running this startup script. -# We just need to write the word daemon followed by a space --hpreg. - -# This defines echo_success() and echo_failure() on RedHat -if [ -r "$vmdb_answer_INITSCRIPTSDIR"'/functions' ]; then - . "$vmdb_answer_INITSCRIPTSDIR"'/functions' -fi - -# This defines $rc_done and $rc_failed on S.u.S.E. -if [ -f /etc/rc.config ]; then - # Don't include the entire file: there could be conflicts - rc_done=`(. /etc/rc.config; echo "$rc_done")` - rc_failed=`(. /etc/rc.config; echo "$rc_failed")` -else - # Make sure the ESC byte is literal: Ash does not support echo -e - rc_done=' done' - rc_failed='failed' -fi - -# -# Global variables -# -vmmemctl="vmmemctl" -vmxnet="vmxnet" -vmhgfs="vmhgfs" -GUESTD_PID_FILE='/var/run/vmware-guestd.pid' - -# -# Utilities -# - -# BEGINNING_OF_IPV4_DOT_SH -#!/bin/sh - -# -# IPv4 address functions -# -# Thanks to Owen DeLong for pointing me at bash's arithmetic -# expansion ability, which is a lot faster than using 'expr' --hpreg -# - -# Compute the subnet address associated to a couple IP/netmask -ipv4_subnet() { - local ip="$1" - local netmask="$2" - - # Split quad-dotted addresses into bytes - # There is no double quote around the back-quoted expression on purpose - # There is no double quote around $ip and $netmask on purpose - set -- `IFS='.'; echo $ip $netmask` - - echo $(($1 & $5)).$(($2 & $6)).$(($3 & $7)).$(($4 & $8)) -} +# This script manages the services needed to run VMware software -# Compute the broadcast address associated to a couple IP/netmask -ipv4_broadcast() { - local ip="$1" - local netmask="$2" - - # Split quad-dotted addresses into bytes - # There is no double quote around the back-quoted expression on purpose - # There is no double quote around $ip and $netmask on purpose - set -- `IFS='.'; echo $ip $netmask` +VMWARE_ETC_DIR=/etc/vmware-tools +VMWARE_BIN_DIR=/usr/bin +VMWARE_SBIN_DIR=/usr/sbin +VMWARE_LIB_DIR=/usr/lib/vmware-tools - echo $(($1 | (255 - $5))).$(($2 | (255 - $6))).$(($3 | (255 - $7))).$(($4 | (255 - $8))) -} -# END_OF_IPV4_DOT_SH +VMWARE_GUESTD_PID=/var/run/vmware-guestd.pid +VMWARE_GUESTD_BIN=${VMWARE_SBIN_DIR}/vmware-guestd +VMWARE_CHECKVM_BIN=${VMWARE_SBIN_DIR}/vmware-checkvm -# Are we running in a VM? -vmware_inVM() { - "$vmdb_answer_SBINDIR"/vmware-checkvm >/dev/null 2>&1 -} +VMWARE_CONFIG_TOOLS=${VMWARE_BIN_DIR}/vmware-config-tools.pl -# This is a function in case a future product name contains language-specific -# escape characters. -vmware_product_name() { - echo 'VMware Tools' - exit 0 -} +VMWARE_VMHGFS_MOD=vmhgfs -# -# Count the number of running virtual machines -# by looking at the number of references to the -# $driver module. -# -countVMs() { - # Beware of module dependancies here. An exact match is important - /sbin/lsmod | awk 'BEGIN {n = 0;} {if ($1 == "'"$driver"'") n = $3;} END {print n;}' -} +VMWARE_NOT_CONFIGURED=${VMWARE_ETC_DIR}/not_configured # Is a given module loaded? isLoaded() { @@ -341,413 +29,65 @@ /sbin/lsmod | awk 'BEGIN {n = "no";} {if ($1 == "'"$module"'") n = "yes";} END {print n;}' } -# Build a Linux kernel integer version -kernel_version_integer() { - echo $(((($1 * 256) + $2) * 256 + $3)) -} - -# Get the running kernel integer version -get_version_integer() { - local version_uts - local v1 - local v2 - local v3 - - version_uts=`uname -r` - - # There is no double quote around the back-quoted expression on purpose - # There is no double quote around $version_uts on purpose - set `IFS='.'; echo $version_uts` - v1="$1" - v2="$2" - v3="$3" - # There is no double quote around the back-quoted expression on purpose - # There is no double quote around $v3 on purpose - set `IFS='-ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz'; echo $v3` - v3="$1" - - kernel_version_integer "$v1" "$v2" "$v3" -} - -vmware_failed() { - if [ "`type -t 'echo_failure' 2>/dev/null`" = 'function' ]; then - echo_failure - else - echo -ne "$rc_failed" - fi -} - -vmware_success() { - if [ "`type -t 'echo_success' 2>/dev/null`" = 'function' ]; then - echo_success - else - echo -ne "$rc_done" - fi -} - -# Execute a macro -vmware_exec() { - local msg="$1" # IN - local func="$2" # IN - shift 2 - - echo -n ' '"$msg" - - # On Caldera 2.2, SIGHUP is sent to all our children when this script exits - # I wanted to use shopt -u huponexit instead but their bash version - # 1.14.7(1) is too old - # - # Ksh does not recognize the SIG prefix in front of a signal name - if [ "$VMWARE_DEBUG" = 'yes' ]; then - (trap '' HUP; "$func" "$@") - else - (trap '' HUP; "$func" "$@") >/dev/null 2>&1 - fi - if [ "$?" -gt 0 ]; then - vmware_failed - echo - return 1 - fi - - vmware_success - echo - return 0 -} - -# Execute a macro in the background -vmware_bg_exec() { - local msg="$1" # IN - local func="$2" # IN - shift 2 - - if [ "$VMWARE_DEBUG" = 'yes' ]; then - # Force synchronism when debugging - vmware_exec "$msg" "$func" "$@" - else - echo -n ' '"$msg"' (background)' - - # On Caldera 2.2, SIGHUP is sent to all our children when this script exits - # I wanted to use shopt -u huponexit instead but their bash version - # 1.14.7(1) is too old - # - # Ksh does not recognize the SIG prefix in front of a signal name - (trap '' HUP; "$func" "$@") 2>&1 | logger -t 'VMware[init]' -p daemon.err & - - vmware_success - echo - return 0 - fi -} - -# -# Macro definitions -# -# Note: -# . Each daemon must be started from its own directory to avoid busy devices -# . Each PID file doesn't need to be added to the installer database, because -# it is going to be automatically removed when it becomes stale (after a -# reboot). It must go directly under /var/run, or some distributions -# (RedHat 6.0) won't clean it -# - -# Terminate a process synchronously -vmware_synchrone_kill() { - local pid="$1" # IN - local signal="$2" # IN - local second - - kill -"$signal" "$pid" - - # Wait a bit to see if the dirty job has really been done - for second in 0 1 2 3 4 5 6 7 8 9 10; do - if [ ! -d /proc/"$pid" ]; then - # Success - return 0 - fi - - sleep 1 - done - - # Timeout - return 1 -} - -# Kill the process associated to a pidfile -vmware_stop_pidfile() { - local pidfile="$1" # IN - local pid - - pid=`cat "$pidfile" 2>/dev/null` - if [ "$pid" = '' ]; then - # The file probably does not exist or is empty. Success - return 0 - fi - # Keep only the first number we find, because some Samba pid files are really - # trashy: they end with NUL characters - # There is no double quote around $pid on purpose - set $pid - pid="$1" - - # First try a nice SIGTERM - if vmware_synchrone_kill "$pid" 15; then - return 0 - fi - - # Then send a strong SIGKILL - if vmware_synchrone_kill "$pid" 9; then - return 0 - fi - - return 1 -} - -# Be sure we enable DMA on all the disks for best performance. -vmware_start_dma() { - if [ -x /sbin/hdparm ]; then - /sbin/hdparm -d 1 /dev/hda > /dev/null 2>&1 - /sbin/hdparm -d 1 /dev/hdb > /dev/null 2>&1 - /sbin/hdparm -d 1 /dev/hdc > /dev/null 2>&1 - /sbin/hdparm -d 1 /dev/hdd > /dev/null 2>&1 - fi - - exit 0 -} - -vmware_load_module() { +vmware_tools_load_module() { if [ "`isLoaded "$1"`" = 'yes' ]; then /sbin/rmmod "$1" fi /sbin/insmod -s -f "/lib/modules/`uname -r`/misc/$1.o" >/dev/null 2>&1 || /sbin/insmod -s -f "$1" >/dev/null 2>&1 || exit 1 - exit 0 } -vmware_unload_module() { +vmware_tools_unload_module() { if [ "`isLoaded "$1"`" = 'yes' ]; then /sbin/rmmod "$1" >/dev/null 2>&1 || exit 1 fi - exit 0 } -# Start the virtual ethernet kernel service -vmware_start_vmxnet() { - # only load vmxnet if it's not already loaded - if [ "`isLoaded "$vmxnet"`" = 'no' ]; then - vmware_load_module $vmxnet - fi +depend () +{ + before checkfs } -# Stop the virtual ethernet kernel service -# XXX Might want to stop the network in case the device is -# configured. -vmware_stop_vmxnet() { - vmware_unload_module $vmxnet -} +checkconfig () +{ + if [ -f $VMWARE_NOT_CONFIGURED ]; then + eerror "Please run $VMWARE_CONFIG_TOOLS first" + eend 1 + return 1 + fi -vmware_switch() { - "$vmdb_answer_BINDIR"/vmware-config-tools.pl --switch - exit 0 + if ! $VMWARE_CHECKVM_BIN > /dev/null 2>&1 ; then + eerror "Not running inside vmware" + eend 1 + return 1 + fi } -# Start the guest virtual memory manager -vmware_start_vmmemctl() { - vmware_load_module $vmmemctl -} +start () +{ + checkconfig || exit 1 -# Stop the guest virtual memory manager -vmware_stop_vmmemctl() { - vmware_unload_module $vmmemctl -} + ebegin "Loading vmware filesystem" + vmware_tools_load_module $VMWARE_VMHGFS_MOD + eend $? -# Start the guest filesystem driver -vmware_start_vmhgfs() { - # only load vmhgfs if it's not already loaded - if [ "`isLoaded "$vmhgfs"`" = 'no' ]; then - vmware_load_module $vmhgfs - fi -} + ebegin "Starting vmware guestd" + start-stop-daemon -b --quiet -m --pidfile ${VMWARE_GUESTD_PID} --start --startas ${VMWARE_GUESTD_BIN} + eend $? -# Unmount all hgfs filesystems left mounted -vmware_unmount_vmhgfs() { - # This emulates 'umount -a -t vmware-hgfs' but with /proc/mounts instead of /etc/mtab - cat /proc/mounts | while read dev path fs rest; do - case "$fs" in - vmware-hgfs) - umount "$path" - ;; - *) - ;; - esac - done } -# Stop the guest filesystem driver -vmware_stop_vmhgfs() { - vmware_unmount_vmhgfs - vmware_unload_module $vmhgfs -} +stop () +{ + ebegin "Stopping vmware guestd" + start-stop-daemon --stop --pidfile ${VMWARE_GUESTD_PID} -x ${VMWARE_GUESTD_BIN} + eend $? -# -# Note: -# . Each daemon must be started from its own directory to avoid busy devices -# . Each PID file doesn't need to be added to the installer database, because -# it is going to be automatically removed when it becomes stale (after a -# reboot). It must go directly under /var/run, or some distributions -# (RedHat 6.0) won't clean it -# - -# Start the guest OS daemon -vmware_start_guestd() { - cd "$vmdb_answer_SBINDIR" && "$vmdb_answer_SBINDIR"/vmware-guestd \ - --background "$GUESTD_PID_FILE" -} - -# Stop the guest OS daemon -vmware_stop_guestd() { - if vmware_stop_pidfile "$GUESTD_PID_FILE"; then - rm -f "$GUESTD_PID_FILE" - fi -} - -is_ESX_running() { - if "$vmdb_answer_SBINDIR"/vmware-checkvm -p | grep -q ESX; then - echo yes - else - echo no - fi + ebegin "Unloading vmware filesystem" + vmware_tools_unload_module $VMWARE_VMHGFS_MOD + eend $? } -is_vmhgfs_needed() { - local min_kver=`kernel_version_integer '2' '4' '0'` - local run_kver=`get_version_integer` - if [ "`is_ESX_running`" = 'yes' ]; then - echo no - else - if [ $min_kver -le $run_kver -a "$vmdb_answer_VMHGFS_CONFED" = 'yes' ]; then - echo yes - else - echo no - fi - fi +reload () +{ + stop ; start } - -is_vmmemctl_needed() { - if [ "`is_ESX_running`" = 'yes' -a "$vmdb_answer_VMMEMCTL_CONFED" = 'yes' ]; then - echo yes - else - echo no - fi -} - -is_vmxnet_needed() { - cat /proc/bus/pci/devices | grep -qi "^[0-9a-f]* 15ad0720 " - if [ "$?" -eq 0 -a "$vmdb_answer_VMXNET_CONFED" = 'yes' ]; then - echo yes - else - echo no - fi -} - -# See how we were called. -case "$1" in - start) - exitcode='0' - if vmware_inVM; then - if [ -e "$vmware_etc_dir"/not_configured ]; then - echo "`vmware_product_name`"' is installed, but it has not been ' - echo '(correctly) configured for the running kernel.' - echo 'To (re-)configure it, invoke the following command: ' - echo "$vmdb_answer_BINDIR"'/vmware-config-tools.pl.' - echo - exit 1 - fi - - echo 'Starting VMware Tools services in the virtual machine:' - vmware_exec 'Switching to guest configuration:' vmware_switch - exitcode=$(($exitcode + $?)) - - if [ "`is_vmhgfs_needed`" = 'yes' ]; then - vmware_exec 'Guest filesystem driver:' vmware_start_vmhgfs - exitcode=$(($exitcode + $?)) - fi - - if [ "`is_vmmemctl_needed`" = 'yes' ]; then - vmware_exec 'Guest memory manager:' vmware_start_vmmemctl - exitcode=$(($exitcode + $?)) - fi - - if [ "`is_vmxnet_needed`" = 'yes' ]; then - vmware_exec 'Guest vmxnet fast network device:' vmware_start_vmxnet - exitcode=$(($exitcode + $?)) - fi - - vmware_exec 'DMA setup:' vmware_start_dma - exitcode=$(($exitcode + $?)) - - vmware_exec 'Guest operating system daemon:' vmware_start_guestd - exitcode=$(($exitcode + $?)) - else - echo 'Starting VMware Tools services on the host:' - vmware_exec 'Switching to host config:' vmware_switch - exitcode=$(($exitcode + $?)) - fi - - if [ "$exitcode" -gt 0 ]; then - # Set the 'not configured' flag - touch "$vmware_etc_dir"'/not_configured' - chmod 644 "$vmware_etc_dir"'/not_configured' - db_add_file "$vmware_db" "$vmware_etc_dir"'/not_configured' \ - "$vmware_etc_dir"'/not_configured' - exit 1 - fi - ;; - - stop) - exitcode='0' - - if vmware_inVM; then - echo 'Stopping VMware Tools services in the virtual machine:' - vmware_exec 'Guest operating system daemon:' vmware_stop_guestd - exitcode=$(($exitcode + $?)) - - if [ "`is_vmhgfs_needed`" = 'yes' ]; then - vmware_exec 'Guest filesystem driver:' vmware_stop_vmhgfs - exitcode=$(($exitcode + $?)) - fi - - if [ "`is_vmmemctl_needed`" = 'yes' ]; then - vmware_exec 'Guest memory manager:' vmware_stop_vmmemctl - exitcode=$(($exitcode + $?)) - fi - - if [ "`is_vmxnet_needed`" = 'yes' ]; then - if [ -x "$vmdb_answer_INITSCRIPTSDIR"'/network' ]; then - "$vmdb_answer_INITSCRIPTSDIR"/network stop - fi - vmware_exec 'Guest vmxnet fast network device:' vmware_stop_vmxnet - exitcode=$(($exitcode + $?)) - fi - else - echo -n 'Skipping VMware Tools services shutdown on the host:' - vmware_success - echo - fi - if [ "$exitcode" -gt 0 ]; then - exit 1 - fi - - ;; - - status) - status "vmware-guestd" - ;; - - restart) - "$0" stop && "$0" start - ;; - - *) - echo "Usage: `basename "$0"` {start|stop|status|restart}" - exit 1 -esac - -exit 0