## ## OSSP rc -- Run-command processor samples (manual page) ## Copyright (c) 2000-2002 Cable & Wireless Deutschland GmbH ## Copyright (c) 2000-2002 The OSSP Project ## Copyright (c) 2000-2002 Ralf S. Engelschall ## ## 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 Example Use Cases =head1 DESCRIPTION This documents typical use cases for B. =head1 USE CASE: OpenPKG Runcommand Facility This describes how B is used as the B (http://www.openpkg.org/) runcommand facility. First, the involved files: =over 4 =item F This is just the location of the B program. =item F This is the B configuration file, hardcoded into F at configure/build time with the Autoconf option C<--with-config=/cw/etc/rc.cf>. It is installed at B 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 (C<%common> extensions) This is the B Bourne shell script providing a set of reusable functions. It is installed at B 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 This is the B configuration script where the administrator overrides the variables from the script's C<%config> sections. It it generated (as an empty file) on B bootstrap time and manually edited later to influence the behaviours of the package's runcommand scripts (here F). foo_enable=yes foo_flags="--sample" =item F This is the example runcommand script of an B package C. It is installed by package C 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>/i Locate ${HOME}/.duerc.%{RCFILE:s/^\///:s/[\/]/-/g} # restrictions on RC files RequireUmask 022 RequireOwner ${USER} RequireGroup ${USER:F} # 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] [ ...] # 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 [ ...] # 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 duePathAdd PATH $CWD/bin $CWD/sbin duePathAdd MANPATH $CWD/man duePathAdd INFOPATH $CWD/info duePathAdd LD_LIBRARY_PATH $CWD/lib duePathDel PATH $CWD/bin $CWD/sbin duePathDel MANPATH $CWD/man duePathDel INFOPATH $CWD/info duePathDel LD_LIBRARY_PATH $CWD/lib =item F<$HOME/.dueglobal> duePathAdd PATH /cw/bin /cw/sbin duePathAdd MANPATH /cw/man duePathAdd INFOPATH /cw/info duePathAdd LD_LIBRARY_PATH /cw/lib duePathDel PATH /cw/bin /cw/sbin duePathDel MANPATH /cw/man duePathDel INFOPATH /cw/info duePathDel LD_LIBRARY_PATH /cw/lib ... =cut