+#!/bin/sh
+
+# General shell functions
+
+# Return codes definitions
+EXIT_CODE_SUCCESS=0
+EXIT_CODE_FAILURE=1
+EXIT_CODE_WARNING=2
+
+# Setup default values for environment
+umask 022
+export PATH="/tools/bin:/tools/sbin:/bin:/sbin"
+
+## Screen Dimensions
+# Find current screen size
+if [ -z "${COLUMNS}" ]; then
+ COLUMNS=$(stty size)
+ COLUMNS=${COLUMNS##* }
+fi
+
+# When using remote connections, such as a serial port, stty size returns 0
+if [ "${COLUMNS}" = "0" ]; then
+ COLUMNS=80
+fi
+
+# The starting position for displaying the "X" sign inside the check box [ ]
+CHECK_POSITION=2
+SET_CHECK_POSITION="echo -en \\033[${CHECK_POSITION}G"
+
+# NORMAL prints text in normal color
+NORMAL="\\033[0;39m"
+# SUCCESS prints text in a green colour
+SUCCESS="echo -en \\033[1;32m"
+# WARNING prints text in a yellow colour
+WARNING="echo -en \\033[1;33m"
+# FAILURE prints text in a red colour
+FAILURE="echo -en \\033[1;31m"
+# Brackets are blue
+BRACKET="\\033[1;34m"
+
+# Set the console_loglevel to display only error messages (0,1,2 and 3)
+# KERN_EMERG "<0>" /* system is unusable */
+# KERN_ALERT "<1>" /* action must be taken immediately */
+# KERN_CRIT "<2>" /* critical conditions */
+# KERN_ERR "<3>" /* error conditions */
+# KERN_WARNING "<4>" /* warning conditions */
+# KERN_NOTICE "<5>" /* normal but significant condition */
+# KERN_INFO "<6>" /* informational */
+# KERN_DEBUG "<7>" /* debug-level messages */
+# Examples:
+# LOGLEVEL="1" --> Prevents all messages, expect panic messages, from
+# appearing on the console.
+# LOGLEVEL="8" --> Allow all messages to appear on the console.
+LOGLEVEL="4"
+
+# Timezone
+export TZ="America/Montreal"
+
+INIT_LOG_PATH="/var/log/hvinit"
+INIT_LOG_FILE="$INIT_LOG_PATH/init.log"
+
+# Arguments: Message string(s) to display
+display_checkbox_msg()
+{
+ local LABEL="${*}"
+
+ echo -en "${BRACKET}[ ${BRACKET}]${NORMAL} ${LABEL} "
+}
+
+# The print_status prints a coloured "X" letter inside the checkbox to the left
+# of the screen (the checkbox is displayed with the cmd_run_log_box function).
+print_status()
+{
+ if [ ${#} = 0 ]; then
+ # If no parameters are given, print usage information.
+ echo "Usage: print_status {success|warning|failure}"
+ return ${EXIT_CODE_FAILURE}
+ fi
+
+ case "$1" in
+ success)
+ ${SUCCESS}
+ ;;
+ warning)
+ ${WARNING}
+ ;;
+ failure)
+ ${FAILURE}
+ ;;
+ *)
+ echo "Usage: print_status {success|warning|failure}"
+ return ${EXIT_CODE_FAILURE}
+ ;;
+ esac
+ echo -n "X"
+ echo -en "${NORMAL}"
+ echo
+}
+
+# Argument #1: message d'erreur
+boot_failure()
+{
+ $FAILURE
+ echo
+ echo $1
+ echo
+ echo "sulogin will now be started. When you logout, the system"
+ echo "will reboot."
+ echo
+ echo -en "${NORMAL}"
+ /sbin/sulogin
+ /sbin/reboot -f
+}
+
+# Write a message to the log file.
+msg_log()
+{
+ echo "<$*>" >> ${INIT_LOG_FILE}
+ return ${EXIT_CODE_SUCCESS}
+}
+
+# Display a message with an orange warning box [X]
+msg_box_nolog()
+{
+ STRING=$1
+ display_checkbox_msg "${STRING}"
+ ${SET_CHECK_POSITION}
+ print_status warning
+}
+
+# Write the command and it's arguments to the log file, without running the command.
+log_script_name()
+{
+ echo ">>> Script: $* <<<" >> ${INIT_LOG_FILE}
+ return ${EXIT_CODE_SUCCESS}
+}
+
+# Write the command and it's arguments to the log file, and run the command.
+cmd_run_log()
+{
+ echo "[$*]" >> ${INIT_LOG_FILE}
+ ${*} 1>> ${INIT_LOG_FILE} 2>&1
+ return ${?}
+}
+
+# Display the action name, run a command, log its output and display it's
+# status
+# First argument: action name (string)
+# Remaining arguments: command name with it's options
+cmd_run_log_box()
+{
+ STRING=$1
+ display_checkbox_msg "${STRING}"
+ shift
+ ${SET_CHECK_POSITION}
+ $* 1>> ${INIT_LOG_FILE} 2>&1
+ ERROR_CODE=${?}
+ if [ $ERROR_CODE = 0 ]; then
+ print_status success
+ else
+ print_status failure
+ fi
+
+ return $ERROR_CODE
+}
+
+# Display the action name, run a command, log its output and display it's
+# status
+# First argument: action name (string)
+# Remaining arguments: command name with it's options
+# Error codes returned by the command:
+# 0 = success
+# 1 = warning
+# 2 = failure
+cmd_run_log_box_warn()
+{
+ STRING=$1
+ display_checkbox_msg "${STRING}"
+ shift
+ ${SET_CHECK_POSITION}
+ $* 1>> ${INIT_LOG_FILE} 2>&1
+ ERROR_CODE=${?}
+ if [ $ERROR_CODE = ${EXIT_CODE_SUCCESS} ]; then
+ print_status success
+ elif [ $ERROR_CODE = ${EXIT_CODE_WARNING} ]; then
+ print_status warning
+ else
+ print_status failure
+ fi
+
+ return $ERROR_CODE
+}
+
+
+# Display the action name, run a command, log its output and display it's
+# status
+# If something went wrong during the checks of one of the partitions,
+# fsck will exit with a return value greater than 1
+# First argument: action name (string)
+# Remaining arguments: command name with it's options
+# Error codes returned by the command:
+# 0 = success
+# 1 = warning
+# >1 = failure
+cmd_run_log_box_warn_checkfs()
+{
+ STRING=$1
+ display_checkbox_msg "${STRING}"
+ shift
+ ${SET_CHECK_POSITION}
+ $* 1>> ${INIT_LOG_FILE} 2>&1
+ ERROR_CODE=${?}
+ if [ $ERROR_CODE = ${EXIT_CODE_SUCCESS} ]; then
+ print_status success
+ elif [ $ERROR_CODE = 1 ]; then
+ print_status warning
+ ERROR_CODE=${EXIT_CODE_WARNING}
+ else
+ print_status failure
+ ERROR_CODE=${EXIT_CODE_FAILURE}
+ fi
+
+ return $ERROR_CODE
+}
+
+
+# Display the action name, run a command and display it's status (no log).
+# First argument: action name (string)
+# Remaining arguments: command name with it's options
+cmd_run_nolog_box()
+{
+ STRING=$1
+ display_checkbox_msg "${STRING}"
+ shift
+ ${SET_CHECK_POSITION}
+ $* 1>> /dev/null 2>&1
+ ERROR_CODE=${?}
+ if [ $ERROR_CODE = 0 ]; then
+ print_status success
+ else
+ print_status failure
+ fi
+
+ return $ERROR_CODE
+}
+
+# loadproc() starts a process (often a daemon) with proper error checking
+loadproc()
+{
+ # If no parameters are given, print usage information.
+ if [ ${#} = 0 ]; then
+ msg_log "Usage: loadproc {program}"
+ return ${EXIT_CODE_FAILURE}
+ fi
+
+ # Find the basename of the first parameter (the daemon's name without the
+ # path that was provided so /usr/sbin/syslogd becomes plain 'syslogd' after
+ # basename ran).
+ base=$(/usr/bin/basename ${1})
+
+ # the pidlist variable will contain the output of the pidof command. pidof
+ # will try to find the PID's that belong to a certain string; $base in
+ # this case.
+ pidlist=$(pidof -o $$ -o $PPID -o %PPID -x ${base})
+ pid=""
+ for apid in ${pidlist}; do
+ if [ -d /proc/${apid} ]; then
+ pid="${pid} ${apid}"
+ fi
+ done
+
+ # If the $pid variable contains anything (from the previous for loop) it
+ # means the daemon is already running.
+ if [ ! -n "${pid}" ]; then
+ # Empty $pid variable means it's not running, so we run "$@" (all
+ # parameters given to this function from the script) and then check
+ # the return value.
+ "$@"
+
+ if [ ${?} -ne 0 ]; then
+ return ${EXIT_CODE_FAILURE}
+ else
+ return ${EXIT_CODE_SUCCESS}
+ fi
+ else
+ # The variable $pid was not empty, meaning it was already running.
+ msg_log "Already running"
+ return ${EXIT_CODE_WARNING}
+ fi
+}
+
+# killproc() kills a process with proper error checking
+# Arg. #1: Name of process to kill
+# Arg. #2: Optional signal to kill the process with (like -HUP, -TERM, -KILL, etc)
+killproc()
+{
+ # If no parameters are given, print usage information.
+ if [ $# -lt 1 ]; then
+ msg_log "Usage: killproc {program} [signal]"
+ return ${EXIT_CODE_FAILURE}
+ fi
+
+ killproc_path ${1} /var/run ${2}
+
+ return ${?}
+}
+
+# killproc_path() kills a process with proper error checking
+# Arg. #1: Name of process to kill
+# Arg. #2: Base directory containing PID file
+# Arg. #3: Optional signal to kill the process with (like -HUP, -TERM, -KILL, etc)
+killproc_path()
+{
+ # If no parameters are given, print usage information.
+ if [ $# -lt 2 ]; then
+ msg_log "Usage: killproc_path {program} {pid-directory} [signal]"
+ return ${EXIT_CODE_FAILURE}
+ fi
+
+ # Find the basename of the first parameter (the daemon's name without the
+ # path).
+ base=$(/usr/bin/basename ${1})
+
+ piddir=${2}
+
+ # Check if we gave a signal to kill the process with (like -HUP, -TERM,
+ # -KILL, etc) to this function (the third parameter).
+ if [ "${3}" != "" ]; then
+ killlevel=-${3}
+ else
+ nolevel=1
+ fi
+
+ # The pidlist variable will contains the output of the pidof command. pidof
+ # will try to find the PID's that belong to a certain string; $base in this
+ # case.
+ pidlist=$(pidof -o $$ -o $PPID -o %PPID -x ${base})
+ pid=""
+ for apid in ${pidlist}
+ do
+ if [ -d /proc/${apid} ]; then
+ pid="${pid} ${apid}"
+ fi
+ done
+
+ # If $pid contains something from the previous for loop it means one or
+ # more PID's were found that belongs to the processes to be killed.
+ if [ -n "${pid}" ]; then
+ # If no kill level was specified we'll try -TERM first and then sleep
+ # for 2 seconds to allow the kill to be completed.
+ if [ "${nolevel}" = 1 ]; then
+ cmd_run_log kill -TERM ${pid}
+
+ # If after -TERM the PID still exists we'll wait 2 seconds before
+ # trying to kill it with -KILL. If the PID still exist after that,
+ # wait two more seconds. If the PIDs still exist by then it's safe
+ # to assume that we cannot kill these PIDs.
+ if /bin/ps h ${pid} >/dev/null 2>&1; then
+ cmd_run_log sleep 2
+ if /bin/ps h ${pid} > /dev/null 2>&1; then
+ cmd_run_log kill -KILL ${pid}
+ if /bin/ps h ${pid} > /dev/null 2>&1; then
+ cmd_run_log sleep 2
+ fi
+ fi
+ fi
+ /bin/ps h ${pid} >/dev/null 2>&1
+ if [ ${?} = 0 ]; then
+ # If after the -KILL it still exists it can't be killed for
+ # some reason.
+ return ${EXIT_CODE_FAILURE}
+ else
+ # It was killed, remove possible stale PID file in ${piddir}.
+ /bin/rm -f ${piddir}/${base}.pid
+ return ${EXIT_CODE_SUCCESS}
+ fi
+ else
+ # A kill level was provided. Kill with the provided kill level and
+ # wait for 2 seconds to allow the kill to be completed.
+ /bin/kill ${killlevel} ${pid}
+ if /bin/ps h ${pid} > /dev/null 2>&1; then
+ cmd_run_log sleep 2
+ fi
+ /bin/ps h ${pid} >/dev/null 2>&1
+ if [ ${?} = 0 ]; then
+ # If ps' return value is 0 it means it ran ok which indicates
+ # that the PID still exists. This means the process wasn't
+ # killed properly with the signal provided.
+ return ${EXIT_CODE_FAILURE}
+ else
+ # If the return value was 1 or higher it means the PID didn't
+ # exist anymore which means it was killed successfully. Remove
+ # possible stale PID file.
+ /bin/rm -f ${piddir}/${base}.pid
+ return ${EXIT_CODE_SUCCESS}
+ fi
+ fi
+ else
+ # The PID didn't exist so we can't attempt to kill it.
+ msg_log "Not running"
+ return ${EXIT_CODE_WARNING}
+ fi
+}
+
+# reloadproc() sends a signal to a daemon telling it to reload it's
+# configuration file. This is almost identical to the killproc function with
+# the exception that it won't try to kill it with a -KILL signal (aka -9).
+# Arg. #1: Name of process to reload
+# Arg. #2: Optional signal to reload the process with (like -HUP)
+reloadproc()
+{
+ # If no parameters are given, print usage information.
+ if [ ${#} = 0 ]; then
+ msg_log "Usage: reloadproc {program} [signal]"
+ return ${EXIT_CODE_FAILURE}
+ fi
+
+ # Find the basename of the first parameter (the daemon's name without
+ # the path that was provided so /usr/sbin/syslogd becomes plain 'syslogd'
+ # after basename ran).
+ base=$(/usr/bin/basename ${1})
+
+ # Check if we gave a signal to send to the process (like -HUP) to this
+ # function (the second parameter). If no second parameter was provided set
+ # the nolevel variable. Else set the killlevel variable to the value of $2
+ # (the second parameter).
+ if [ -n "${2}" ]; then
+ killlevel="-${2}"
+ else
+ killlevel="-SIGHUP"
+ fi
+
+ # The pidlist variable will contains the output of the pidof command. pidof
+ # will try to find the PID's that belong to a certain string; $base in this
+ # case.
+ pidlist=$(pidof -o $$ -o $PPID -o %PPID -x ${base})
+ pid=""
+ for apid in ${pidlist}
+ do
+ if [ -d /proc/${apid} ]; then
+ pid="${pid} ${apid}"
+ fi
+ done
+
+ # If $pid contains something from the previous for loop it means one or
+ # more PID's were found that belongs to the processes to be reloaded.
+ if [ -n "${pid}" ]; then
+ /bin/kill ${killlevel} ${pid}
+
+ if [ ${?} -ne 0 ]; then
+ sleep 2
+ if statusproc ${base} | grep "not running" 1> /dev/null 2>&1; then
+ return ${EXIT_CODE_FAILURE}
+ fi
+ fi
+ else
+ # If $pid is empty no PID's have been found that belong to the process.
+ msg_log "Not running"
+ return ${EXIT_CODE_WARNING}
+ fi
+
+ return ${EXIT_CODE_SUCCESS}
+}
+
+
+# statusproc_path() will try to find out if a process is running or not.
+# Arg. #1: Name of process to check
+statusproc()
+{
+ # If no parameters are given, print usage information.
+ if [ $# -lt 1 ]; then
+ msg_log "Usage: statusproc {program}"
+ return ${EXIT_CODE_FAILURE}
+ fi
+
+ statusproc_path ${1} /var/run
+
+ return ${?}
+}
+
+
+# statusproc_path() will try to find out if a process is running or not.
+# Arg. #1: Name of process to check
+# Arg. #2: Base directory containing PID file
+statusproc_path()
+{
+ # If no parameters are given, print usage information.
+ if [ $# -lt 2 ]; then
+ msg_log "Usage: status {program} {pid-directory}"
+ return ${EXIT_CODE_FAILURE}
+ fi
+
+ # Find the basename of the first parameter (the daemon's name without the
+ # path).
+ base=$(/usr/bin/basename ${1})
+
+ piddir=${2}
+
+ # $pid will contain a list of PID's that belong to a process.
+ pid=$(pidof -o $$ -o $PPID -o %PPID -x ${base})
+ if [ -n "${pid}" ]; then
+ # If $pid contains something, the process is running, print the content
+ # of the $pid variable.
+ echo "${base} running with Process ID ${pid}"
+ return ${EXIT_CODE_SUCCESS}
+ fi
+
+ # If $pid doesn't contain it check if a PID file exists and inform the
+ # user about this stale file.
+ if [ -f ${piddir}/${base}.pid ]; then
+ pid=$(head -1 ${piddir}/${base}.pid)
+ if [ -n "${pid}" ]; then
+ echo "${base} not running but ${piddir}/${base}.pid exists"
+ return ${EXIT_CODE_FAILURE}
+ fi
+ else
+ echo "${base} is not running"
+ fi
+}