ossp-pkg/rc/rc-sample.pod
1.2
=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, hard-coded 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.
Dirs /cw/etc/rc.d:/cw/local/etc/rc.d
Name rc.%s/rc.*
ConfigDef (?<=^\s*)([a-zA-Z_][a-zA-Z_0-9]*)=("[^"]*"|'[^']*'|\S+)
SectionDef (?<=^|\n)%([a-zA-Z][a-zA-Z0-9]*)(\s+-[a-zA-Z]\s*\S+)\s*\n(.+?)(?=\n%%\S+|$)
ParamDef (?<=^|\s)-([a-zA-Z])\s*(\S+)
SectionRef (?<=^\s*|;\s*)%([a-zA-Z][a-zA-Z0-9]*)(\s+[^\n]+)?
ParamRef \$([0-9])
NameConfig config
NameCommon common
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 use cases 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 `rc --eval --conf=$HOME/.duecf - leave`
builtin cd ${1+"$@"}
eval `rc --eval --conf=$HOME/.duecf - enter`
}
=item F<$HOME/.duecf>
Dirs .:..// # current and all parent dirs
Name .duerc
NameGlobal $HOME/.dueglobal:/etc/dueglobal
RequireUmask 022
RequireOwner %{USER}
RequireGroup %{GROUP}
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>
<directory 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>
</directory>
<directory path=/usr/opkg>
...
</directory>
=cut