ossp-pkg/rc/rc-sample.pod
##
## OSSP rc -- Run-Command Processor samples (manual page)
## Copyright (c) 2002-2003 Cable & Wireless Deutschland GmbH
## Copyright (c) 2002-2003 The OSSP Project <http://www.ossp.org/>
## Copyright (c) 2002-2003 Ralf S. Engelschall <rse@engelschall.com>
##
## Permission to use, copy, modify, and distribute this software for
## any purpose with or without fee is hereby granted, provided that
## the above copyright notice and this permission notice appear in all
## copies.
##
## THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
## WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
## MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
## IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
## CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
## SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
## LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
## USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
## ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
## OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
## OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
## SUCH DAMAGE.
##
=pod
=head1 NAME
rc-sample -- B<OSSP rc> Example Use Cases
=head1 DESCRIPTION
This documents typical use cases for B<OSSP rc>.
=head1 USE CASE: OpenPKG Run-command Facility
This describes how B<OSSP rc> is used as the B<OpenPKG>
(http://www.openpkg.org/) run-command facility.
First, the involved files:
=over 4
=item F</cw/etc/rc>
This is just the location of the B<OSSP rc> program.
=item F</cw/etc/rc.cf>
This is the B<OSSP rc> configuration file, hardcoded into
F</cw/etc/rc> at configure/build time with the Autoconf option
C<--with-config=/cw/etc/rc.cf>. It is installed at B<OpenPKG>
bootstrap time and used read-only.
# how to locate RC files
Locate /cw/etc/rc.d/rc.%{RCFILE:s/^all$/*/}
Locate /cw/local/etc/rc.d/rc.%{RCFILE:s/^all$/*/}
# requirements on RC files
RequireUmask 022
RequireOwner cw
RequireGroup cw
# how to parse RC files
ParseEnvAss (?<=^\s*)([a-zA-Z_][a-zA-Z_0-9]*)=(?:"([^"]*)"|'([^']*)'|(\S+))
ParseSectionDef (?<=^|\n)%([a-zA-Z][a-zA-Z0-9]*)(\s+-[a-zA-Z]\s*\S+)*\s*\n(.+?)(?=\n%%\S+|$)
ParseSectionRef (?<=^\s*|;\s*)@([a-zA-Z][a-zA-Z0-9]*)(\s+[^\n]+)?
ParseSectionParam (?<=^|\s)-([a-zA-Z])\s*(\S+)
NameConfig config
NameCommon common
NameDefault default
NameError error
Execute root %s
Execute !root sudo %s
LineControl yes
=item F</cw/etc/rc.func> (C<%common> extensions)
This is the B<OpenPKG> Bourne shell script providing a set of reusable
functions. It is installed at B<OpenPKG> bootstrap time and used
read-only.
opVarIsYes () {
_var="${1}"
eval "_val=\"\$${_var}\""
case "${_val}" in
[Yy][Ee][Ss] | [Tt][Rr][Uu][Ee] | [Oo][Nn] | 1 )
unset _var _val
return 0
;;
[Nn][Oo] | [Ff][Aa][Ll][Ss][Ee] | [Oo][Ff][Ff] | 0 )
unset _var _val
return 1
;;
*)
opWarn "variable \$${_var} is not set properly."
unset _var _val
return 1
;;
esac
}
opServiceEnabled () {
opVarIsYes ${1}_enable
}
=item F</cw/etc/rc.conf>
This is the B<OpenPKG> configuration script where the administrator
overrides the variables from the script's C<%config> sections. It it
generated (as an empty file) on B<OpenPKG> bootstrap time and manually
edited later to influence the behaviours of the package's run-command
scripts (here F</cw/etc/rc.d/rc.foo>).
foo_enable=yes
foo_flags="--sample"
=item F</cw/etc/rc.d/rc.foo>
This is the example run-command script of an B<OpenPKG> package C<foo>.
It is installed by package C<foo> and used read-only.
#! /cw/etc/rc
%config
foo_enable=yes
foo_flags=""
%common
foo_pidfile=/cw/var/foo/foo.pid
%start -u root -p 100
if opServiceEnabled foo; then
/cw/sbin/foo -p $foo_pidfile -S $foo_flags
fi
%stop -u root -p 100
if opServiceEnabled foo; then
/cw/sbin/foo -p $foo_pidfile -K
fi
%restart -u root -p 100
if opServiceEnabled foo; then
%stop
sleep 1
%start
fi
%env
if opServiceEnabled foo; then
FOO=/cw/sbin/foo
export FOO
fi
=back
With this setup, the following transactions are possible:
$ /cw/etc/rc --query "foo enabled: %{foo_enable}"
foo enabled: yes
$ _
$ /cw/etc/rc --config
Configuration Variable Effective Value Default Value
------------------------ ------------------------- -- -------------------------
foo_enable "yes" == "yes"
foo_flags "--sample" != ""
$ _
$ /cw/etc/rc -v foo start
start: foo
$ _
$ /cw/etc/rc --print foo env
# /cw/etc/rc.d/rc.foo 3
foo_enable=yes
foo_flags=""
# /cw/etc/rc.conf 1
foo_enable=yes
foo_flags="--sample"
# internal 0
. /cw/etc/rc.func
# /cw/etc/rc.d/rc.foo 6
foo_pidfile=/cw/var/foo/foo.pid
# /cw/etc/rc.d/rc.foo 22
if opServiceEnabled foo; then
FOO="The Foo"
export FOO
fi
$ _
$ eval `/cw/etc/rc --eval foo env`
$ print $FOO
The Foo
$ _
=head1 USE CASE: Dynamic User Environment (DUE)
=over 4
=item F<$HOME/.bashrc>
cd () {
eval `$HOME/bin/rc --eval --conf=$HOME/.duecf $PWD leave`
builtin cd ${1+"$@"}
eval `$HOME/bin/rc --eval --conf=$HOME/.duecf $PWD enter`
}
=item F<$HOME/.duecf>
# how to locate RC files
Locate %{RCFILE}/.duerc
Locate ${HOME}/.duerc:m/^<dir path="%{RCFILE}">(.*)<\/dir>/i
Locate ${HOME}/.duerc.%{RCFILE:s/^\///:s/[\/]/-/g}
# restrictions on RC files
RequireUmask 022
RequireOwner ${USER}
RequireGroup ${USER:F<user2group>}
# how to parse RC files
Functions $HOME/.duefunc
=item F<$HOME/.duefunc>
# append (or optionally prepend) one or more directories (optionally
# have to be existing) to a colon-separated path variable. In case a
# directory already exists, it is first removed.
#
# Usage: duePathAdd [-p] [-e] <variable> <dir> [<dir> ...]
# Example: duePathAdd -e PATH /bin /sbin /usr/bin /usr/sbin /usr/ccs/bin
#
duePathAdd () {
_prepend=0
_exists=0
while [ $# -gt 0 ]; do
case $1 in
-p ) _prepend=1; shift ;;
-e ) _exists=1; shift ;;
* ) break ;;
esac
done
_var="$1"
shift
_edit_del=""
_edit_add=""
for _dir in "$@"; do
if [ ".${_exists}" = .1 ] && [ ! -d "${_dir}" ]; then
continue
fi
_edit_del="${_edit_del} -e 's;^${_dir}\$;;' -e 's;^${_dir}:;;'"
_edit_del="${_edit_del} -e 's;:${_dir}:;:;' -e 's;:${_dir}\$;;'"
if [ ".${_prepend}" = .0 ]; then
_edit_add="${_edit_add} -e 's;\$;:${_dir};'"
else
_edit_add="-e 's;^;${_dir}:;' ${_edit_add}"
fi
done
if [ ".${_edit_del}${_edit_add}" != . ]; then
eval "${_var}=\`echo \"\$${_var}\" | sed ${_edit_del} ${_edit_add}\`"
fi
unset _prepend _exists _var _edit_del _edit_add _dir
}
#
# remove one or more directories from a colon-separated path variable
#
# Usage: duePathDel <variable> <dir> [<dir> ...]
# Example: duePathDel PATH /bin /sbin /usr/bin /usr/sbin /usr/ccs/bin
#
duePathDel () {
_var="$1"
shift
_edit=""
for _dir in "$@"; do
_edit="${_edit} -e 's;^${_dir}\$;;' -e 's;^${_dir}:;;'"
_edit="${_edit} -e 's;:${_dir}:;:;' -e 's;:${_dir}\$;;'"
done
eval "${_var}=\`echo \"\$${_var}\" | sed ${_edit}\`"
unset _var _edit _dir
}
=item F</cw/.duerc>
<event name=enter>
duePathAdd PATH $CWD/bin $CWD/sbin
duePathAdd MANPATH $CWD/man
duePathAdd INFOPATH $CWD/info
duePathAdd LD_LIBRARY_PATH $CWD/lib
</event>
<event name=leave>
duePathDel PATH $CWD/bin $CWD/sbin
duePathDel MANPATH $CWD/man
duePathDel INFOPATH $CWD/info
duePathDel LD_LIBRARY_PATH $CWD/lib
</event>
=item F<$HOME/.dueglobal>
<dir path=/cw>
<event name=enter>
duePathAdd PATH /cw/bin /cw/sbin
duePathAdd MANPATH /cw/man
duePathAdd INFOPATH /cw/info
duePathAdd LD_LIBRARY_PATH /cw/lib
</event>
<event name=leave>
duePathDel PATH /cw/bin /cw/sbin
duePathDel MANPATH /cw/man
duePathDel INFOPATH /cw/info
duePathDel LD_LIBRARY_PATH /cw/lib
</event>
</dir>
<dir path=/usr/opkg>
...
</dir>
=cut