summaryrefslogtreecommitdiff
path: root/sh
diff options
context:
space:
mode:
Diffstat (limited to 'sh')
-rw-r--r--sh/Makefile7
-rw-r--r--sh/functions.sh157
-rwxr-xr-xsh/gendepends.sh58
-rw-r--r--sh/init-common-post.sh22
-rw-r--r--sh/init-functions.sh62
-rwxr-xr-xsh/net.sh566
-rwxr-xr-xsh/rc-functions.sh60
-rwxr-xr-xsh/rc-help.sh262
-rw-r--r--sh/rc-mount.sh70
-rwxr-xr-xsh/runscript.sh74
10 files changed, 1338 insertions, 0 deletions
diff --git a/sh/Makefile b/sh/Makefile
new file mode 100644
index 00000000..ac50fa90
--- /dev/null
+++ b/sh/Makefile
@@ -0,0 +1,7 @@
+DIR = /$(LIB)/rcscripts/sh
+FILES = functions.sh init-functions.sh init-common-post.sh \
+ rc-functions.sh rc-mount.sh
+EXES = gendepends.sh net.sh rc-mount.sh rc-help.sh runscript.sh
+
+TOPDIR = ..
+include $(TOPDIR)/default.mk
diff --git a/sh/functions.sh b/sh/functions.sh
new file mode 100644
index 00000000..d1327ad5
--- /dev/null
+++ b/sh/functions.sh
@@ -0,0 +1,157 @@
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# Please keep this useable by every shell in portage
+
+RC_GOT_FUNCTIONS="yes"
+
+eindent() {
+ if [ -n "${RC_EBUFFER}" ] ; then
+ "${RC_LIBDIR}"/bin/eindent
+ else
+ RC_EINDENT=$((${RC_EINDENT:-0} + 2))
+ [ "${RC_EINDENT}" -gt 40 ] && RC_EINDENT=40
+ export RC_EINDENT
+ fi
+}
+
+eoutdent() {
+ if [ -n "${RC_EBUFFER}" ] ; then
+ "${RC_LIBDIR}"/bin/eoutdent
+ else
+ RC_EINDENT=$((${RC_EINDENT:-0} - 2))
+ [ "${RC_EINDENT}" -lt 0 ] && RC_EINDENT=0
+ fi
+ return 0
+}
+
+# void esyslog(char* priority, char* tag, char* message)
+#
+# use the system logger to log a message
+#
+esyslog() {
+ local pri= tag=
+
+ if [ -x /usr/bin/logger ] ; then
+ pri="$1"
+ tag="$2"
+
+ shift 2
+ [ -z "$*" ] && return 0
+
+ /usr/bin/logger -p "${pri}" -t "${tag}" -- "$*"
+ fi
+
+ return 0
+}
+
+# Safer way to list the contents of a directory,
+# as it do not have the "empty dir bug".
+#
+# char *dolisting(param)
+#
+# print a list of the directory contents
+#
+# NOTE: quote the params if they contain globs.
+# also, error checking is not that extensive ...
+#
+dolisting() {
+ local x= y= mylist= mypath="$*"
+
+ # Here we use file globbing instead of ls to save on forking
+ for x in ${mypath} ; do
+ [ ! -e "${x}" ] && continue
+
+ if [ -L "${x}" -o -f "${x}" ] ; then
+ mylist="${mylist} "${x}
+ elif [ -d "${x}" ] ; then
+ [ "${x%/}" != "${x}" ] && x=${x%/}
+
+ for y in "${x}"/* ; do
+ [ -e "${y}" ] && mylist="${mylist} ${y}"
+ done
+ fi
+ done
+
+ echo "${mylist# *}"
+}
+
+# bool is_older_than(reference, files/dirs to check)
+#
+# return 0 if any of the files/dirs are newer than
+# the reference file
+#
+# EXAMPLE: if is_older_than a.out *.o ; then ...
+is_older_than() {
+ local x= ref="$1"
+ shift
+
+ for x in "$@" ; do
+ [ -e "${x}" ] || continue
+ # We need to check the mtime if it's a directory too as the
+ # contents may have changed.
+ [ "${x}" -nt "${ref}" ] && return 0
+ [ -d "${x}" ] && is_older_than "${ref}" "${x}"/* && return 0
+ done
+
+ return 1
+}
+
+uniqify() {
+ local result=
+ while [ -n "$1" ] ; do
+ case " ${result} " in
+ *" $1 "*) ;;
+ *) result="${result} $1" ;;
+ esac
+ shift
+ done
+ echo "${result# *}"
+}
+
+KV_to_int() {
+ [ -z $1 ] && return 1
+
+ local KV_MAJOR=${1%%.*}
+ local x=${1#*.}
+ local KV_MINOR=${x%%.*}
+ x=${1#*.*.}
+ local KV_MICRO=${x%%-*}
+ local KV_int=$((${KV_MAJOR} * 65536 + ${KV_MINOR} * 256 + ${KV_MICRO} ))
+
+ # We make version 2.2.0 the minimum version we will handle as
+ # a sanity check ... if its less, we fail ...
+ [ "${KV_int}" -lt 131584 ] && return 1
+
+ echo "${KV_int}"
+}
+
+# Setup a basic $PATH. Just add system default to existing.
+# This should solve both /sbin and /usr/sbin not present when
+# doing 'su -c foo', or for something like: PATH= rcscript start
+case "${PATH}" in
+ /lib/rcscripts/bin:/bin:/sbin:/usr/bin:/usr/sbin) ;;
+ /lib/rcscripts/bin:/bin:/sbin:/usr/bin:/usr/sbin:*) ;;
+ *) export PATH="/lib/rcscripts/bin:/bin:/sbin:/usr/bin:/usr/sbin:${PATH}" ;;
+esac
+
+for arg in "$@" ; do
+ case "${arg}" in
+ --nocolor|--nocolour)
+ export RC_NOCOLOR="yes"
+ ;;
+ esac
+done
+
+if [ "${RC_NOCOLOR}" != "yes" -a -z "${GOOD}" ] ; then
+ if color_terminal ; then
+ GOOD=$'\e[32;01m'
+ WARN=$'\e[33;01m'
+ BAD=$'\e[31;01m'
+ HILITE=$'\e[36;01m'
+ BRACKET=$'\e[34;01m'
+ NORMAL=$'\e[0m'
+ fi
+fi
+
+# vim: set ts=4 :
diff --git a/sh/gendepends.sh b/sh/gendepends.sh
new file mode 100755
index 00000000..aa494f03
--- /dev/null
+++ b/sh/gendepends.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# Shell wrapper to list our dependencies
+# Copyright 2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+. /etc/init.d/functions.sh
+
+need() {
+ [ -n "$*" ] && echo "${SVCNAME} ineed $*"
+}
+use() {
+ [ -n "$*" ] && echo "${SVCNAME} iuse $*"
+}
+before() {
+ [ -n "$*" ] && echo "${SVCNAME} ibefore $*"
+}
+after() {
+ [ -n "$*" ] && echo "${SVCNAME} iafter $*"
+}
+provide() {
+ [ -n "$*" ] && echo "${SVCNAME} iprovide $*"
+}
+depend() {
+ :
+}
+
+cd /etc/init.d
+for SVCNAME in * ; do
+ [ -x "${SVCNAME}" ] || continue
+ case "${SVCNAME}" in
+ *.sh) continue ;;
+ esac
+
+ SVCNAME=${SVCNAME##*/}
+ (
+ if . /etc/init.d/"${SVCNAME}" ; then
+ rc_c=${SVCNAME%%.*}
+ if [ -n "${rc_c}" -a "${rc_c}" != "${SVCNAME}" ] ; then
+ [ -e /etc/conf.d/"${rc_c}" ] && . /etc/conf.d/"${rc_c}"
+ fi
+ unset rc_c
+
+ [ -e /etc/conf.d/"${SVCNAME}" ] && . /etc/conf.d/"${SVCNAME}"
+
+ echo "${SVCNAME}"
+ depend
+
+ # Add any user defined depends
+ need ${RC_NEED}
+ use ${RC_USE}
+ before ${RC_BEFORE}
+ after ${RC_AFTER}
+ provide ${RC_PROVIDE}
+ fi
+ )
+done
+
+# vim: set ts=4 :
diff --git a/sh/init-common-post.sh b/sh/init-common-post.sh
new file mode 100644
index 00000000..ec535eb6
--- /dev/null
+++ b/sh/init-common-post.sh
@@ -0,0 +1,22 @@
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# mount $svcdir as something we can write to if it's not rw
+# On vservers, / is always rw at this point, so we need to clean out
+# the old service state data
+if touch "${RC_SVCDIR}/.test" 2>/dev/null ; then
+ rm -rf "${RC_SVCDIR}/.test" \
+ $(ls -d1 "${RC_SVCDIR:-/lib/rcscripts/init.d}"/* 2>/dev/null | \
+ grep -Ev "/(deptree|ksoftlevel)$")
+else
+ mount_svcdir
+fi
+
+echo "sysinit" > "${RC_SVCDIR}/softlevel"
+
+# sysinit is now done, so allow init scripts to run normally
+[ -e /dev/.rcsysinit ] && rm -f /dev/.rcsysinit
+
+exit 0
+
+# vim: set ts=4 :
diff --git a/sh/init-functions.sh b/sh/init-functions.sh
new file mode 100644
index 00000000..59f0eb6b
--- /dev/null
+++ b/sh/init-functions.sh
@@ -0,0 +1,62 @@
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# void try(command)
+#
+# Try to execute 'command', if it fails, drop to a shell.
+#
+try() {
+ local errstr
+ local retval=0
+
+ if [ -c /dev/null ] ; then
+ errstr=$(eval $* 2>&1 >/dev/null)
+ else
+ errstr=$(eval $* 2>&1)
+ fi
+ retval=$?
+ if [ ${retval} -ne 0 ] ; then
+ #splash "critical" &
+ eend 1
+ eerror "The \"$*\" command failed with error:"
+ eerror " ${errstr#*: }"
+ echo
+ eerror "Since this is a critical task, startup cannot continue."
+ echo
+ single_user
+ fi
+
+ return ${retval}
+}
+
+# bool check_statedir(dir)
+#
+# Check that 'dir' exists, if not, drop to a shell.
+#
+check_statedir() {
+ [ -z "$1" ] && return 0
+
+ if [ ! -d "$1" ] ; then
+ if ! mkdir -p "$1" &>/dev/null ; then
+ #splash "critical" &
+ echo
+ eerror "For Gentoo to function properly, \"$1\" needs to exist."
+ if [ "${RC_FORCE_AUTO}" = "yes" ] ; then
+ eerror "Attempting to create \"$1\" for you ..."
+ mount -o remount,rw /
+ mkdir -p "$1"
+ fi
+ if [ ! -d "$1" ] ; then
+ eerror "Please mount your root partition read/write, and execute:"
+ echo
+ eerror " # mkdir -p $1"
+ echo; echo
+ single_user
+ fi
+ fi
+ fi
+
+ return 0
+}
+
+# vim: set ts=4 :
diff --git a/sh/net.sh b/sh/net.sh
new file mode 100755
index 00000000..c839dd4c
--- /dev/null
+++ b/sh/net.sh
@@ -0,0 +1,566 @@
+#!/sbin/runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+MODULESDIR="${RC_LIBDIR}/net"
+MODULESLIST="${RC_SVCDIR}/nettree"
+_config_vars="config"
+
+[ -z "${IN_BACKGROUND}" ] && IN_BACKGROUND=false
+
+depend() {
+ local IFACE=${SVCNAME#*.}
+ local IFVAR=$(echo -n "${IFACE}" | sed -e 's/[^[:alnum:]]/_/g')
+
+ need localmount
+ after bootmisc
+ provide net
+ case "${IFACE}" in
+ lo|lo0) ;;
+ *)
+ after net.lo net.lo0
+ local prov=
+ eval prov=\$RC_NEED_${IFVAR}
+ [ -n "${prov}" ] && need ${prov}
+ eval prov=\$RC_USE_${IFVAR}
+ [ -n "${prov}" ] && use ${prov}
+ eval prov=\$RC_BEFORE_${IFVAR}
+ [ -n "${prov}" ] && before ${prov}
+ eval prov=\$RC_AFTER_${IFVAR}
+ [ -n "${prov}" ] && after ${prov}
+ eval prov=\$RC_PROVIDE_${IFVAR}
+ [ -n "${prov}" ] && provide ${prov}
+ ;;
+ esac
+}
+
+_shell_var() {
+ echo -n "$1" | sed -e 's/[^[:alnum:]]/_/g'
+}
+
+# Credit to David Leverton for this function which handily maps a bash array
+# structure to positional parameters so existing configs work :)
+# We'll deprecate arrays at some point though.
+_get_array() {
+ if [ -n "${BASH}" ] ; then
+ case "$(declare -p "$1" 2>/dev/null)" in
+ "declare -a "*)
+ echo "set -- \"\${$1[@]}\""
+ return
+ ;;
+ esac
+ fi
+
+ echo "eval set -- \"\$$1\""
+}
+
+_wait_for_carrier() {
+ local timeout= efunc=einfon
+
+ _has_carrier && return 0
+
+ eval timeout=\$carrier_timeout_${IF_VAR}
+ timeout=${timeout:-5}
+
+ [ -n "${RC_EBUFFER}" ] && efunc=einfo
+ ${efunc} "Waiting for carrier (${timeout} seconds) "
+ while [ ${timeout} -gt 0 ] ; do
+ sleep 1
+ if _has_carrier ; then
+ [ -z "${RC_EBUFFER}" ] && echo
+ return 0
+ fi
+ timeout=$((${timeout} - 1))
+ [ -z "${RC_EBUFFER}" ] && echo -n "."
+ done
+
+ echo
+ return 1
+}
+
+_netmask2cidr() {
+ local i= len=0
+
+ local IFS=.
+ for i in $1; do
+ while [ ${i} != "0" ] ; do
+ len=$((${len} + 1))
+ i=$((${i} >> 1))
+ done
+ done
+
+ echo "${len}"
+}
+
+_configure_variables() {
+ local var= v= t=
+
+ for var in ${_config_vars} ; do
+ local v=
+ for t in "$@" ; do
+ eval v=\$${var}_${t}
+ if [ -n "${v}" ] ; then
+ eval ${var}_${IFVAR}=\$${var}_${t}
+ continue 2
+ fi
+ done
+ done
+}
+
+_show_address() {
+ einfo "received address $(_get_inet_address "${IFACE}")"
+}
+
+# Basically sorts our modules into order and saves the list
+_gen_module_list() {
+ local x= f=
+ if [ -s "${MODULESLIST}" -a "${MODULESLIST}" -nt "${MODULESDIR}" ] ; then
+ local update=false
+ for x in "${MODULESDIR}"/* ; do
+ [ -e "${x}" ] || continue
+ if [ "${x}" -nt "${MODULESLIST}" ] ; then
+ update=true
+ break
+ fi
+ done
+ ${update} || return 0
+ fi
+
+ einfo "Caching network module dependencies"
+ # Run in a subshell to protect the main script
+ (
+ after() {
+ eval ${MODULE}_after="\"\${${MODULE}_after}\${${MODULE}_after:+ }$*\""
+ }
+
+ before() {
+ local mod=${MODULE}
+ local MODULE=
+ for MODULE in "$@" ; do
+ after "${mod}"
+ done
+ }
+
+ program() {
+ if [ "$1" = "start" -o "$1" = "stop" ] ; then
+ local s="$1"
+ shift
+ eval ${MODULE}_program_${s}="\"\${${MODULE}_program_${s}}\${${MODULE}_program_${s}:+ }$*\""
+ else
+ eval ${MODULE}_program="\"\${${MODULE}_program}\${${MODULE}_program:+ }$*\""
+ fi
+ }
+
+ provide() {
+ eval ${MODULE}_provide="\"\${${MODULE}_provide}\${${MODULE}_provide:+ }$*\""
+ local x
+ for x in $* ; do
+ eval ${x}_providedby="\"\${${MODULE}_providedby}\${${MODULE}_providedby:+ }${MODULE}\""
+ done
+ }
+
+ for MODULE in "${MODULESDIR}"/* ; do
+ sh -n "${MODULE}" || continue
+ . "${MODULE}" || continue
+ MODULE=${MODULE#${MODULESDIR}/}
+ MODULE=${MODULE%.sh}
+ eval ${MODULE}_depend
+ MODULES="${MODULES} ${MODULE}"
+ done
+
+ VISITED=
+ SORTED=
+ visit() {
+ case " ${VISITED} " in
+ *" $1 "*) return ;;
+ esac
+ VISITED="${VISITED} $1"
+
+ eval AFTER=\$${1}_after
+ for MODULE in ${AFTER} ; do
+ eval PROVIDEDBY=\$${MODULE}_providedby
+ if [ -n "${PROVIDEDBY}" ] ; then
+ for MODULE in ${PROVIDEDBY} ; do
+ visit "${MODULE}"
+ done
+ else
+ visit "${MODULE}"
+ fi
+ done
+
+ eval PROVIDE=\$${1}_provide
+ for MODULE in ${PROVIDE} ; do
+ visit "${MODULE}"
+ done
+
+ eval PROVIDEDBY=\$${1}_providedby
+ [ -z "${PROVIDEDBY}" ] && SORTED="${SORTED} $1"
+ }
+
+ for MODULE in ${MODULES} ; do
+ visit "${MODULE}"
+ done
+
+ > "${MODULESLIST}"
+ i=0
+ for MODULE in ${SORTED} ; do
+ eval PROGRAM=\$${MODULE}_program
+ eval PROGRAM_START=\$${MODULE}_program_start
+ eval PROGRAM_STOP=\$${MODULE}_program_stop
+ #for x in ${PROGRAM} ; do
+ # [ -x "${x}" ] || continue 2
+ #done
+ eval PROVIDE=\$${MODULE}_provide
+ echo "module_${i}='${MODULE}'" >> "${MODULESLIST}"
+ echo "module_${i}_program='${PROGRAM}'" >> "${MODULESLIST}"
+ echo "module_${i}_program_start='${PROGRAM_START}'" >> "${MODULESLIST}"
+ echo "module_${i}_program_stop='${PROGRAM_STOP}'" >> "${MODULESLIST}"
+ echo "module_${i}_provide='${PROVIDE}'" >> "${MODULESLIST}"
+ i=$((${i} + 1))
+ done
+ echo "module_${i}=" >> "${MODULESLIST}"
+ )
+
+ return 0
+}
+
+_load_modules() {
+ # Ensure our list is up to date
+ _gen_module_list
+
+ local starting=$1 mymods=
+
+ MODULES=
+ if [ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ] ; then
+ eval mymods=\$modules_${IFVAR}
+ [ -z "${mymods}" ] && mymods=${modules}
+ fi
+
+ . "${MODULESLIST}"
+ local i=-1 x= mod= f= provides=
+ while true ; do
+ i=$((${i} + 1))
+ eval mod=\$module_${i}
+ [ -z "${mod}" ] && break
+ [ -e "${MODULESDIR}/${mod}.sh" ] || continue
+
+ eval set -- \$module_${i}_program
+ if [ -n "$1" ] ; then
+ x=
+ for x in "$@" ; do
+ [ -x "${x}" ] && break
+ done
+ [ -x "${x}" ] || continue
+ fi
+ if ${starting} ; then
+ eval set -- \$module_${i}_program_start
+ else
+ eval set -- \$module_${i}_program_stop
+ fi
+ if [ -n "$1" ] ; then
+ x=
+ for x in "$@" ; do
+ [ -x "${x}" ] && break
+ done
+ [ -x "${x}" ] || continue
+ fi
+
+ eval provides=\$module_${i}_provide
+ if ${starting} ; then
+ case " ${mymods} " in
+ *" !${mod} "*) continue ;;
+ *" !${provides} "*) [ -n "${provides}" ] && continue ;;
+ esac
+ fi
+ MODULES="${MODULES}${MODULES:+ }${mod}"
+
+ # Now load and wrap our functions
+ if ! . "${MODULESDIR}/${mod}.sh" ; then
+ eend 1 "${SVCNAME}: error loading module \`${mod}'"
+ exit 1
+ fi
+
+ [ -z "${provides}" ] && continue
+
+ # Wrap our provides
+ local f=
+ for f in pre_start start post_start ; do
+ eval "${provides}_${f}() { type ${mod}_${f} >/dev/null 2>/dev/null || return 0; ${mod}_${f} \"\$@\"; }"
+ done
+
+ eval module_${mod}_provides="${provides}"
+ eval module_${provides}_providedby="${mod}"
+ done
+
+ # Wrap our preferred modules
+ for mod in ${mymods} ; do
+ case " ${MODULES} " in
+ *" ${mod} "*)
+ eval x=\$module_${mod}_provides
+ [ -z "${x}" ] && continue
+ for f in pre_start start post_start ; do
+ eval "${x}_${f}() { type ${mod}_${f} >/dev/null 2>/dev/null || return 0; ${mod}_${f} \"\$@\"; }"
+ done
+ eval module_${x}_providedby="${mod}"
+ ;;
+ esac
+ done
+
+ # Finally remove any duplicated provides from our list if we're starting
+ # Otherwise reverse the list
+ local LIST="${MODULES}" p=
+ MODULES=
+ if ${starting} ; then
+ for mod in ${LIST} ; do
+ eval x=\$module_${mod}_provides
+ if [ -n "${x}" ] ; then
+ eval p=\$module_${x}_providedby
+ [ "${mod}" != "${p}" ] && continue
+ fi
+ MODULES="${MODULES}${MODULES:+ }${mod}"
+ done
+ else
+ for mod in ${LIST} ; do
+ MODULES="${mod}${MODULES:+ }${MODULES}"
+ done
+ fi
+
+ veinfo "Loaded modules: ${MODULES}"
+}
+
+_load_config() {
+ eval "$(_get_array "config_${IFVAR}")"
+ if [ "${IFACE}" = "lo" -o "${IFACE}" = "lo0" ] ; then
+ set -- "127.0.0.1/8" "$@"
+ else
+ if [ $# -eq 0 ] ; then
+ ewarn "No configuration specified; defaulting to DHCP"
+ set -- "dhcp"
+ fi
+ fi
+
+ # We store our config in an array like vars
+ # so modules can influence it
+ config_index=0
+ for cmd in "$@" ; do
+ eval config_${config_index}="'${cmd}'"
+ config_index=$((${config_index} + 1))
+ done
+ # Terminate the list
+ eval config_${config_index}=
+
+ config_index=0
+ eval $(_get_array fallback_${IFVAR})
+ for cmd in "$@" ; do
+ eval fallback_${config_index}="'${cmd}'"
+ config_index=$((${config_index} + 1))
+ done
+ # Terminate the list
+ eval fallback_${config_index}=
+
+ # Don't set to zero, so any net modules don't have to do anything extra
+ config_index=-1
+}
+
+start() {
+ local IFACE=${SVCNAME#*.} oneworked=false module=
+ local IFVAR=$(_shell_var "${IFACE}") cmd= metric=0 our_metric=$metric
+
+ einfo "Bringing up interface ${IFACE}"
+ eindent
+
+ if [ -z "${MODULES}" ] ; then
+ local MODULES=
+ _load_modules true
+ fi
+
+ _up 2>/dev/null
+
+ if type preup >/dev/null 2>/dev/null ; then
+ ebegin "Running preup"
+ eindent
+ preup || return 1
+ eoutdent
+ fi
+
+ for module in ${MODULES} ; do
+ if type "${module}_pre_start" >/dev/null 2>/dev/null ; then
+ if ! ${module}_pre_start ; then
+ eend 1
+ exit 1
+ fi
+ fi
+ done
+
+ local config= config_index=
+ _load_config
+ config_index=0
+
+ if [ -n "${our_metric}" ] ; then
+ metric=${our_metric}
+ elif [ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ] ; then
+ metric=$((${metric} + $(_ifindex)))
+ fi
+
+ while true ; do
+ eval config=\$config_${config_index}
+ [ -z "${config}" ] && break
+
+ set -- "${config}"
+ ebegin "$1"
+ eindent
+ case "$1" in
+ noop)
+ if [ -n "$(_get_inet_address)" ] ; then
+ oneworked=true
+ break
+ fi
+ ;;
+ null) : ;;
+ [0-9]*|*:*) _add_address ${config} ;;
+ *)
+ if type "${config}_start" >/dev/null 2>/dev/null ; then
+ "${config}"_start
+ else
+ eerror "nothing provides \`${config}'"
+ fi
+ ;;
+ esac
+ if eend $? ; then
+ oneworked=true
+ else
+ eval config=\$fallback_${IFVAR}
+ if [ -n "${config}" ] ; then
+ einfo "Trying fallback configuration"
+ eval config_${config_index}=\$fallback_${IFVAR}
+ eval fallback_${config_index}=
+ config_index=$((${config_index} - 1))
+ fi
+ fi
+ eoutdent
+ config_index=$((${config_index} + 1))
+ done
+
+ if ! ${oneworked} ; then
+ if type failup >/dev/null 2>/dev/null ; then
+ ebegin "Running failup"
+ eindent
+ failup
+ eoutdent
+ fi
+ return 1
+ fi
+
+ local hidefirstroute=false first=true routes=
+ eval "$(_get_array "routes_${IFVAR}")"
+ if [ "${IFACE}" = "lo" -o "${IFACE}" = "lo0" ] ; then
+ set -- "127.0.0.0/8 via 127.0.0.1" "$@"
+ hidefirstroute=true
+ fi
+ for cmd in "$@" ; do
+ if ${first} ; then
+ first=false
+ einfo "Adding routes"
+ fi
+ eindent
+ ebegin "${cmd}"
+ # Work out if we're a host or a net if not told
+ case "${cmd}" in
+ *" -net "*|*" -host "*) ;;
+ *" netmask "*) cmd="-net ${cmd}" ;;
+ *)
+ case "${cmd%% *}" in
+ *.*.*.*/32) cmd="-host ${cmd}" ;;
+ *.*.*.*/*|0.0.0.0|default) cmd="-net ${cmd}" ;;
+ *) cmd="-host ${cmd}" ;;
+ esac
+ ;;
+ esac
+ if ${hidefirstroute} ; then
+ _add_route ${cmd} >/dev/null 2>/dev/null
+ hidefirstroute=false
+ else
+ _add_route ${cmd} >/dev/null
+ fi
+ eend $?
+ eoutdent
+ done
+
+ for module in ${MODULES} ; do
+ if type "${module}_post_start" >/dev/null 2>/dev/null ; then
+ if ! ${module}_post_start ; then
+ eend 1
+ exit 1
+ fi
+ fi
+ done
+
+ if type postup >/dev/null 2>/dev/null ; then
+ ebegin "Running postup"
+ eindent
+ postup
+ eoutdent
+ fi
+
+ return 0
+}
+
+stop() {
+ local IFACE=${SVCNAME#*.} module=
+ local IFVAR=$(_shell_var "${IFACE}") opts=
+
+ einfo "Bringing down interface ${IFACE}"
+ eindent
+
+ if [ -z "${MODULES}" ] ; then
+ local MODULES=
+ _load_modules false
+ fi
+
+ if type predown >/dev/null 2>/dev/null ; then
+ ebegin "Running predown"
+ eindent
+ predown || return 1
+ eoutdent
+ fi
+
+ for module in ${MODULES} ; do
+ if type "${module}_pre_stop" >/dev/null 2>/dev/null ; then
+ if ! ${module}_pre_stop ; then
+ eend 1
+ exit 1
+ fi
+ fi
+ done
+
+ for module in ${MODULES} ; do
+ if type "${module}_stop" >/dev/null 2>/dev/null ; then
+ ${module}_stop
+ fi
+ done
+
+ _delete_addresses "${IFACE}"
+
+ for module in ${MODULES} ; do
+ if type "${module}_post_stop" >/dev/null 2>/dev/null ; then
+ ${module}_post_stop
+ fi
+ done
+
+ [ "${IN_BACKGROUND}" != "true" ] && \
+ [ "${IFACE}" != "lo" -a "${IFACE}" != "lo0" ] && \
+ _down 2>/dev/null
+
+ [ -x /sbin/resolvconf ] && resolvconf -d "${IFACE}"
+
+ if type predown >/dev/null 2>/dev/null ; then
+ ebegin "Running postdown"
+ eindent
+ postdown
+ eoutdent
+ fi
+
+ return 0
+}
+
+# vim: set ts=4 :
diff --git a/sh/rc-functions.sh b/sh/rc-functions.sh
new file mode 100755
index 00000000..586471dd
--- /dev/null
+++ b/sh/rc-functions.sh
@@ -0,0 +1,60 @@
+# Copyright 2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+has_addon() {
+ [ -e "${RC_LIBDIR}/addons/$1.sh" ]
+}
+
+import_addon() {
+ if has_addon "$1" ; then
+ . "${RC_LIBDIR}/addons/$1.sh"
+ return 0
+ fi
+ return 1
+}
+
+start_addon() {
+ ( import_addon "$1-start" )
+}
+
+stop_addon() {
+ ( import_addon "$1-stop" )
+}
+
+is_net_fs() {
+ [ -z "$1" ] && return 1
+
+ local t=$(mountinfo --fstype "$1" )
+ for x in ${RC_NET_FS_LIST} ; do
+ [ "${x}" = "${t}" ] && return 0
+ done
+ return 1
+}
+
+is_union_fs() {
+ [ ! -x /sbin/unionctl ] && return 1
+ unionctl "$1" --list >/dev/null 2>/dev/null
+}
+
+get_bootparam() {
+ local match="$1"
+ [ -z "${match}" -o ! -r /proc/cmdline ] && return 1
+
+ set -- $(cat /proc/cmdline)
+ while [ -n "$1" ] ; do
+ case "$1" in
+ gentoo=*)
+ local params="${1##*=}"
+ local IFS=, x=
+ for x in ${params} ; do
+ [ "${x}" = "${match}" ] && return 0
+ done
+ ;;
+ esac
+ shift
+ done
+
+ return 1
+}
+
+# vim: set ts=4 :
diff --git a/sh/rc-help.sh b/sh/rc-help.sh
new file mode 100755
index 00000000..97ca53f4
--- /dev/null
+++ b/sh/rc-help.sh
@@ -0,0 +1,262 @@
+#!/bin/sh
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+if [ "${RC_NOCOLOR}" = "yes" ] ; then
+ unset BLUE GREEN OFF CYAN
+else
+ BLUE="\033[34;01m"
+ GREEN="\033[32;01m"
+ OFF="\033[0m"
+ CYAN="\033[36;01m"
+fi
+
+myscript=$1
+if [ -z "${myscript}" ] ; then
+ echo "Please execute an init.d script"
+ exit 1
+fi
+
+if [ -L "${myscript}" ] ; then
+ SERVICE=$(readlink "${myscript}")
+else
+ SERVICE=${myscript}
+fi
+SERVICE=${SERVICE##*/}
+
+if [ "$2" = "help" ] ; then
+ BE_VERBOSE="yes"
+ NL="\n"
+else
+ BE_VERBOSE="no"
+ NL=
+fi
+
+default_opts="start stop restart pause zap"
+extra_opts="$(. "${myscript}" 2>/dev/null ; echo "${opts}")"
+
+if [ "${BE_VERBOSE}" = "yes" ] ; then
+printf "
+${GREEN}Gentoo RC-Scripts; ${BLUE}http://www.gentoo.org/${OFF}
+ Copyright 1999-2007 Gentoo Foundation; Distributed under the GPL
+"
+fi
+
+printf "Usage: ${CYAN}${SERVICE}${OFF} [ ${GREEN}flags${OFF} ] < ${GREEN}options${OFF} >
+
+${CYAN}Normal Options:${OFF}"
+
+if [ "${BE_VERBOSE}" = "yes" ] ; then
+printf "
+ ${GREEN}start${OFF}
+ Start service, as well as the services it depends on (if not already
+ started).
+
+ ${GREEN}stop${OFF}
+ Stop service, as well as the services that depend on it (if not already
+ stopped).
+
+ ${GREEN}restart${OFF}
+ Restart service, as well as the services that depend on it.
+
+ Note to developers: If this function is replaced with a custom one,
+ 'svc_start' and 'svc_stop' should be used instead of 'start' and
+ 'stop' to restart the service. This is so that the dependencies
+ can be handled correctly. Refer to the portmap rc-script for an
+ example.
+
+ ${GREEN}conditionalrestart|condrestart${OFF}
+ Same as 'restart', but only if the service has already been started.
+
+ ${GREEN}pause${OFF}
+ Same as 'stop', but the services that depends on it, will not be
+ stopped. This is useful for stopping a network interface without
+ stopping all the network services that depend on 'net'.
+
+ ${GREEN}zap${OFF}
+ Reset a service that is currently stopped, but still marked as started,
+ to the stopped state. Basically for killing zombie services.
+
+ ${GREEN}status${OFF}
+ Prints \"status: started\" if the service is running, else it
+ prints \"status: stopped\".
+
+ Note that if the '--quiet' flag is given, it will return true if the
+ service is running, else false.
+
+ ${GREEN}ineed|iuse${OFF}
+ List the services this one depends on. Consult the section about
+ dependencies for more info on the different types of dependencies.
+
+ ${GREEN}needsme|usesme${OFF}
+ List the services that depend on this one. Consult the section about
+ dependencies for more info on the different types of dependencies.
+
+ ${GREEN}broken${OFF}
+ List the missing or broken dependencies of type 'need' this service
+ depends on.
+"
+
+else
+
+printf " ${GREEN}${default_opts}${OFF}
+ Default init.d options.
+"
+
+fi
+
+if [ -n "${extra_opts}" ] ; then
+printf "
+${CYAN}Additional Options:${OFF}${NL}
+ ${GREEN}${extra_opts}${OFF}
+ Extra options supported by this init.d script.
+"
+fi
+
+printf "
+${CYAN}Flags:${OFF}${NL}
+ ${GREEN}--ifstarted${OFF} Only do actions if service started
+ ${GREEN}--nodeps${OFF} Don't stop or start any dependencies
+ ${GREEN}--quiet${OFF}
+ Suppress output to stdout, except if:${NL}
+ 1) It is a warning, then output to stdout
+ 2) It is an error, then output to stderr${NL}
+ ${GREEN}--verbose${OFF} Output extra information
+ ${GREEN}--debug${OFF} Output debug information
+ ${GREEN}--nocolor${OFF} Suppress the use of colors
+"
+
+if [ "${BE_VERBOSE}" = "yes" ] ; then
+printf "
+${CYAN}Dependencies:${OFF}
+
+ This is the heart of the Gentoo RC-Scripts, as it determines the order
+ in which services gets started, and also to some extend what services
+ get started in the first place.
+
+ The following example demonstrates how to use dependencies in
+ rc-scripts:
+
+ depend() {
+ need foo bar
+ use ray
+ }
+
+ Here we have foo and bar as dependencies of type 'need', and ray of
+ type 'use'. You can have as many dependencies of each type as needed, as
+ long as there is only one entry for each type, listing all its dependencies
+ on one line only.
+
+ ${GREEN}need${OFF}
+ These are all the services needed for this service to start. If any
+ service in the 'need' line is not started, it will be started even if it
+ is not in the current, or 'boot' runlevel, and then this service will be
+ started. If any services in the 'need' line fails to start or is
+ missing, this service will never be started.
+
+ ${GREEN}use${OFF}
+ This can be seen as representing optional services this service depends on
+ that are not critical for it to start. For any service in the 'use' line,
+ it must be added to the 'boot' or current runlevel to be considered a
+ valid 'use' dependency. It can also be used to determine startup order.
+
+ ${GREEN}before${OFF}
+ This, together with the 'after' dependency type, can be used to control
+ startup order. In core, 'before' and 'after' do not denote a dependency,
+ but should be used for order changes that will only be honoured during
+ a change of runlevel. All services listed will get started *after* the
+ current service. In other words, this service will get started *before*
+ all listed services.
+
+ ${GREEN}after${OFF}
+ All services listed will be started *before* the current service. Have a
+ look at 'before' for more info.
+
+ ${GREEN}provide${OFF}
+ This is not really a dependency type, rather it will enable you to create
+ virtual services. This is useful if there is more than one version of
+ a specific service type, system loggers or crons for instance. Just
+ have each system logger provide 'logger', and make all services in need
+ of a system logger depend on 'logger'. This should make things much more
+ generic.
+
+ Note that the 'need', 'use', 'before', and 'after' dependency types accept
+ an '*' as an argument. Having:
+
+ depend() {
+ before *
+ }
+
+ will make the service start first in the current runlevel, and:
+
+ depend() {
+ after *
+ }
+
+ will make the service the last to start.
+
+ You should however be careful how you use this, as I really will not
+ recommend using it with the 'need' or 'use' dependency type ... you have
+ been warned!
+
+${CYAN}'net' Dependency and 'net.*' Services:${OFF}
+
+ Example:
+
+ depend() {
+ need net
+ }
+
+ This is a special dependency of type 'need'. It represents a state where
+ a network interface or interfaces besides lo is up and active. Any service
+ starting with 'net.' will be treated as a part of the 'net' dependency,
+ if:
+
+ 1. It is part of the 'boot' runlevel
+ 2. It is part of the current runlevel
+
+ A few examples are the /etc/init.d/net.eth0 and /etc/init.d/net.lo services.
+"
+fi
+
+printf "
+${CYAN}Configuration files:${OFF}
+"
+
+if [ "${BE_VERBOSE}" = "yes" ] ; then
+printf "
+ There are two files which will be sourced for possible configuration by
+ the rc-scripts. They are (sourced from top to bottom):
+"
+fi
+
+printf " /etc/conf.d/${SERVICE}${NL} /etc/rc.conf"
+
+if [ "${BE_VERBOSE}" = "yes" ] ; then
+printf "
+ You can add extra dependencies to ${SERVICE} by adding some variables to
+ /etc/conf.d/${SERVICE}
+ RC_NEED=\"openvpn ntpd\"
+ RC_USE=\"dns\"
+
+ This makes ${SERVICE} need openvpn and ntpd, while it just uses dns.
+
+ A good example of this is nfsmount needing openvpn if the nfs mounts in
+ /etc/fstab are over the vpn link.
+"
+fi
+
+if [ "${BE_VERBOSE}" = "yes" ] ; then
+printf "\n
+${CYAN}Management:${OFF}
+
+ Services are added and removed via the 'rc-update' tool. Running it without
+ arguments should give sufficient help.
+"
+else
+printf "\n
+For more info, please run '${myscript} help'.
+"
+fi
+
+exit 0
diff --git a/sh/rc-mount.sh b/sh/rc-mount.sh
new file mode 100644
index 00000000..67ea203f
--- /dev/null
+++ b/sh/rc-mount.sh
@@ -0,0 +1,70 @@
+# Copyright 2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+# bool do_unmount(char *cmd, char *no_unmounts, char *nodes, char *fslist)
+# Handy function to handle all our unmounting needs
+# find-mount is a C program to actually find our mounts on our supported OS's
+do_unmount() {
+ local cmd="$1" retval=0 retry=
+ local f_opts="-m -c" f_kill="-s " mnt=
+ if [ "${RC_UNAME}" = "Linux" ] ; then
+ f_opts="-c"
+ f_kill="-"
+ fi
+
+ local mnts="$(mountinfo ${2:+--skip-regex} $2 ${3:+--node-regex} $3 ${4:+--fstype-regex} $4 --reverse \
+ | sed -e "s/'/'\\\\''/g" -e "s/^/'/g" -e "s/$/'/g")"
+ eval set -- ${mnts}
+ for mnt in "$@" ; do
+ case "${cmd}" in
+ umount*)
+ # If we're using the mount (probably /usr) then don't unmount us
+ local pids="$(fuser ${f_opts} "${mnt}" 2>/dev/null)"
+ case " ${pids} " in
+ *" $$ "*)
+ ewarn "We are using ${mnt}, not unmounting"
+ continue
+ ;;
+ esac
+ ebegin "Unmounting ${mnt}"
+ ;;
+ *)
+ ebegin "Remounting ${mnt}"
+ ;;
+ esac
+
+ retry=3
+ while ! ${cmd} "${mnt}" 2>/dev/null ; do
+ # Don't kill if it's us (/ and possibly /usr)
+ local pids="$(fuser ${f_opts} "${mnt}" 2>/dev/null)"
+ case " ${pids} " in
+ *" $$ "*) retry=0 ;;
+ " ") eend 1 "in use but fuser finds nothing"; retry=0 ;;
+ *)
+ local sig="KILL"
+ [ ${retry} -gt 0 ] && sig="TERM"
+ fuser ${f_kill}${sig} -k ${f_opts} "${mnt}" \
+ >/dev/null 2>/dev/null
+ sleep 1
+ retry=$((${retry} - 1))
+ ;;
+ esac
+
+ # OK, try forcing things
+ if [ ${retry} -le 0 ] ; then
+ ${cmd} -f "${mnt}" || retry=-999
+ retry=-999
+ break
+ fi
+ done
+ if [ ${retry} -eq -999 ] ; then
+ eend 1
+ retval=1
+ else
+ eend 0
+ fi
+ done
+ return ${retval}
+}
+
+# vim: set ts=4 :
diff --git a/sh/runscript.sh b/sh/runscript.sh
new file mode 100755
index 00000000..6b679c21
--- /dev/null
+++ b/sh/runscript.sh
@@ -0,0 +1,74 @@
+#!/bin/sh
+# Shell wrapper for runscript
+# Copyright 1999-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+. /etc/init.d/functions.sh
+. "${RC_LIBDIR}"/sh/rc-functions.sh
+
+# Support LiveCD foo
+if [ -r /sbin/livecd-functions.sh ] ; then
+ . /sbin/livecd-functions.sh
+ livecd_read_commandline
+fi
+
+if [ -z "$1" -o -z "$2" ] ; then
+ eerror "${SVCNAME}: not enough arguments"
+ exit 1
+fi
+
+[ "${RC_DEBUG}" = "yes" ] && set -x
+
+# If we're net.eth0 or openvpn.work then load net or openvpn config
+rc_c=${SVCNAME%%.*}
+if [ -n "${rc_c}" -a "${rc_c}" != "${SVCNAME}" ] ; then
+ if [ -e "/etc/conf.d/${rc_c}.${RC_SOFTLEVEL}" ] ; then
+ . "/etc/conf.d/${rc_c}.${RC_SOFTLEVEL}"
+ elif [ -e "/etc/conf.d/${rc_c}" ] ; then
+ . "/etc/conf.d/${rc_c}"
+ fi
+fi
+unset rc_c
+
+# Overlay with our specific config
+if [ -e "/etc/conf.d/${SVCNAME}.${RC_SOFTLEVEL}" ] ; then
+ . "/etc/conf.d/${SVCNAME}.${RC_SOFTLEVEL}"
+elif [ -e "/etc/conf.d/${SVCNAME}" ] ; then
+ . "/etc/conf.d/${SVCNAME}"
+fi
+
+# Load any system overrides
+[ -e /etc/rc.conf ] && . /etc/rc.conf
+
+# Apply any ulimit defined
+[ -n "${RC_ULIMIT}" ] && ulimit ${RC_ULIMIT}
+
+# Load our script
+. $1
+
+shift
+
+while [ -n "$1" ] ; do
+ # See if we have the required function and run it
+ for rc_x in start stop ${opts} ; do
+ if [ "${rc_x}" = "$1" ] ; then
+ if type "$1" >/dev/null 2>/dev/null ; then
+ unset rc_x
+ "$1" || exit $?
+ shift
+ continue 2
+ else
+ if [ "${rc_x}" = "start" -o "${rc_x}" = "stop" ] ; then
+ exit 0
+ else
+ eerror "${SVCNAME}: function \`$1' defined but does not exist"
+ exit 1
+ fi
+ fi
+ fi
+ done
+ eerror "${SVCNAME}: unknown function \`$1'"
+ exit 1
+done
+
+# vim: set ts=4 :