summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--pkgtools/pkg_alternatives/DESCR3
-rw-r--r--pkgtools/pkg_alternatives/Makefile57
-rw-r--r--pkgtools/pkg_alternatives/PLIST6
-rw-r--r--pkgtools/pkg_alternatives/files/pkg_alternatives.8289
-rw-r--r--pkgtools/pkg_alternatives/files/pkg_alternatives.sh614
-rw-r--r--pkgtools/pkg_alternatives/files/wrapper.man70
-rw-r--r--pkgtools/pkg_alternatives/files/wrapper.sh64
7 files changed, 1103 insertions, 0 deletions
diff --git a/pkgtools/pkg_alternatives/DESCR b/pkgtools/pkg_alternatives/DESCR
new file mode 100644
index 00000000000..d2c7236144e
--- /dev/null
+++ b/pkgtools/pkg_alternatives/DESCR
@@ -0,0 +1,3 @@
+pkg_alternatives is a tool to manage the alternatives system provided by
+The NetBSD Packages Collection, also known as pkgsrc. It creates, configures
+and destroys generic wrappers used to run programs with similar interfaces.
diff --git a/pkgtools/pkg_alternatives/Makefile b/pkgtools/pkg_alternatives/Makefile
new file mode 100644
index 00000000000..3a3d33afa03
--- /dev/null
+++ b/pkgtools/pkg_alternatives/Makefile
@@ -0,0 +1,57 @@
+# $NetBSD: Makefile,v 1.1.1.1 2005/01/25 13:00:46 jmmv Exp $
+#
+
+DISTNAME= pkg_alternatives-1.0
+CATEGORIES= pkgtools
+MASTER_SITES= # empty
+DISTFILES= # empty
+
+MAINTAINER= jmmv@NetBSD.org
+COMMENT= Generic wrappers for programs with similar interfaces
+
+PKG_INSTALLATION_TYPES= overwrite pkgviews
+
+EXTRACT_ONLY= # empty
+NO_CHECKSUM= YES
+NO_BUILD= YES
+NO_BUILDLINK= YES
+USE_PKGINSTALL= YES
+WRKSRC= ${WRKDIR}
+
+DATADIR= ${PREFIX}/share/pkg_alternatives
+DBDIR= ${PREFIX}/libdata/pkg_alternatives
+
+MAKE_DIRS= ${DBDIR}
+MAKE_DIRS+= ${PKG_SYSCONFDIR}
+
+PKG_SYSCONFSUBDIR= pkg_alternatives
+
+SUBST_CLASSES+= vars
+SUBST_STAGE.vars= do-configure
+SUBST_MESSAGE.vars= "Configuring sources."
+SUBST_FILES.vars= ${WRKSRC}/*
+SUBST_SED.vars= -e 's|@CONFDIR@|${PKG_SYSCONFDIR}|g'
+SUBST_SED.vars+= -e 's|@DATADIR@|${DATADIR}|g'
+SUBST_SED.vars+= -e 's|@DBDIR@|${DBDIR}|g'
+SUBST_SED.vars+= -e 's|@PKG_DBDIR@|${PKG_DBDIR}|g'
+SUBST_SED.vars+= -e 's|@PREFIX@|${PREFIX}|g'
+SUBST_SED.vars+= -e 's|@ROOT_USER@|${ROOT_USER}|g'
+SUBST_SED.vars+= -e 's|@SH@|${SH}|g'
+
+INSTALLATION_DIRS= man/man8 sbin
+
+do-extract:
+ ${CP} ${FILESDIR}/pkg_alternatives.sh ${WRKSRC}
+ ${CP} ${FILESDIR}/pkg_alternatives.8 ${WRKSRC}
+ ${CP} ${FILESDIR}/wrapper.sh ${WRKSRC}
+ ${CP} ${FILESDIR}/wrapper.man ${WRKSRC}
+
+do-install:
+ ${INSTALL_SCRIPT} ${WRKSRC}/pkg_alternatives.sh \
+ ${PREFIX}/sbin/pkg_alternatives
+ ${INSTALL_MAN} ${WRKSRC}/pkg_alternatives.8 ${PREFIX}/man/man8/
+ ${INSTALL_DATA_DIR} ${DATADIR}
+ ${INSTALL_DATA} ${WRKSRC}/wrapper.sh ${DATADIR}/
+ ${INSTALL_DATA} ${WRKSRC}/wrapper.man ${DATADIR}/
+
+.include "../../mk/bsd.pkg.mk"
diff --git a/pkgtools/pkg_alternatives/PLIST b/pkgtools/pkg_alternatives/PLIST
new file mode 100644
index 00000000000..0516798c587
--- /dev/null
+++ b/pkgtools/pkg_alternatives/PLIST
@@ -0,0 +1,6 @@
+@comment $NetBSD: PLIST,v 1.1.1.1 2005/01/25 13:00:46 jmmv Exp $
+man/man8/pkg_alternatives.8
+share/pkg_alternatives/wrapper.man
+share/pkg_alternatives/wrapper.sh
+sbin/pkg_alternatives
+@dirrm share/pkg_alternatives
diff --git a/pkgtools/pkg_alternatives/files/pkg_alternatives.8 b/pkgtools/pkg_alternatives/files/pkg_alternatives.8
new file mode 100644
index 00000000000..3e990da236c
--- /dev/null
+++ b/pkgtools/pkg_alternatives/files/pkg_alternatives.8
@@ -0,0 +1,289 @@
+.\" $NetBSD: pkg_alternatives.8,v 1.1.1.1 2005/01/25 13:00:46 jmmv Exp $
+.\"
+.\" pkg_alternatives - Generic wrappers for programs with similar interfaces
+.\" Copyright (c) 2005 Julio M. Merino Vidal <jmmv@NetBSD.org>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Neither the name of The NetBSD Foundation nor the names of its
+.\" contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" 3. Neither the name of author nor the names of its contributors may
+.\" be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS 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 FOUNDATION OR 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.
+.\"
+.Dd January 25, 2005
+.Dt ALTERNATIVES 8
+.Os
+.Sh NAME
+.Nm pkg_alternatives
+.Nd generic wrappers for programs with similar interfaces
+.Sh SYNOPSIS
+.Nm
+.Op Fl sw
+.Op Fl p Ar prefix
+action
+.Ar arg1 ... argN
+.Sh DESCRIPTION
+.Nm
+is a tool to manage the
+.Em alternatives system
+provided by The NetBSD Packages Collection, also known as pkgsrc.
+It creates, configures and destroys generic wrappers used to run programs
+with similar interfaces.
+.Pp
+Consider, for example, the
+.Xr vi 1
+editor.
+Both
+.Xr nvi 1
+and
+.Xr vim 1
+provide very similar functionality, although neither of them is named
+.Sq vi .
+In this situation, it may be useful to have a
+.Em wrapper
+in place of the generic name which points to one of the multiple
+.Em alternatives
+available.
+.Pp
+The alternatives are classified according to the
+.Em package
+they belong to.
+In other words, a concrete package contains a list of all the wrappers it
+affects by providing alternatives to them.
+This makes things easier to the end user and/or the administrator who has
+to deal with them, as they can manually select a package rather than a
+bunch of wrappers.
+.Pp
+Wrappers are identified by its file name relative to the installation
+prefix, i.e.,
+.Pa @PREFIX@
+if the
+.Fl p
+option is not used.
+In the example above, the wrapper could be identified by the
+.Pa bin/vi
+string.
+The identifier is the string used as the
+.Sq wrapper
+argument in all the actions that require it.
+.Pp
+The generic wrapper scans a list of available alternatives and tries to
+execute them in order; the first one that succeeds is the one used for
+that run.
+This list of alternatives is read from multiple configuration files.
+Each one contains a list of possible alternatives, one per line, with
+optional arguments to them.
+Lines starting with
+.Sq #
+are considered comments and are ignored.
+.Pp
+The following configuration files are read, in strict order, for each
+wrapper (replace the
+.Sq wrapper
+word with the wrapper's absolute file name):
+.Bl -tag -width XXXX
+.It ~/.alternatives/wrapper
+This is called the
+.Em user configuration file
+and is only read when not running as
+.Sq @ROOT_USER@ .
+Otherwise, tools such as
+.Xr sudo 8
+could be used to execute any program in the system.
+This file can be freely edited by the user, either by hand or by using
+the
+.Sq manual
+action described below.
+.It @CONFDIR@/wrapper
+This is called the
+.Em system configuration file
+and is read if found.
+This file can be freely edited by the administrator, either by hand or
+by using the
+.Sq manual
+action described below.
+.It @DATADIR@/wrapper
+This is called the
+.Em database configuration file
+and is always read.
+This file must not be edited by hand; packages providing alternatives
+will take care to (un)register themselves from them when (de)installed.
+.El
+.Ss Options
+The following options are available:
+.Bl -tag -width XpXprefixX
+.It Fl p Ar prefix
+Set installation prefix.
+This affects where wrappers and their manual pages are looked for.
+The prefix defaults to
+.Pa @PREFIX@
+if this flag is not given.
+.It Fl s
+Run in silent mode: no output except for errors.
+.It Fl w
+Operate on wrappers rather than on packages.
+This affects the behavior of all actions.
+.El
+.Ss Actions in package mode
+The following table describes each available action and its behavior when
+working in package mode.
+All these actions are at a higher level than the same actions in wrapper
+mode.
+They always end up using the later at some point, so you should also
+read the next section to be aware of the exact effect of each the command.
+.Bl -tag -width XXXX
+.It auto Ar package
+Removes any manual configuration from each wrapper associated to the given
+package.
+This means that all the affected wrappers are then free to choose whichever
+alternative they prefer.
+.It list
+Lists which of the installed packages provide alternatives.
+Any of the packages shown by this command can then be fed back to the
+.Sq auto
+and
+.Sq manual
+actions.
+.It manual Ar package
+Manually selects all the alternatives that belong to
+.Ar package
+to be the default for their respective wrappers.
+.It rebuild
+Rebuilds the alternatives database, found in
+.Pa @DBDIR@ ,
+based on the contents of the package database, usually available in
+.Pa @PKG_DBDIR@ .
+Basically, it scans the later looking for packages with an
+.Pa +ALTERNATIVES
+file in them, and, for each of those, the
+.Sq register
+action is called with the appropriate file name.
+.It register Ar package wrapper alternative arguments
+Registers a new
+.Ar alternative
+for the given
+.Ar wrapper
+in the specified
+.Ar package .
+If the package does not exist in the database, it is created.
+.Pp
+This action must not be used directly; packages providing alternatives
+will take care to execute it at installation time.
+.It status Ar package
+For each wrapper that belongs to
+.Ar package ,
+shows which alternative will be used by it in the next run.
+It also displays all available candidates for each of them.
+.It unregister Ar package
+Removes the
+.Ar package
+from the database.
+All alternatives associated to it are also removed.
+.Pp
+This action must not be used directly; packages providing alternatives
+will take care to execute it at deinstallation time.
+.El
+.Ss Actions in wrapper mode
+The following table describes each available action and its behavior when
+working in wrapper mode.
+Note that these actions work at a very low level as they are used to manage
+wrappers and alternative commands directly.
+In most situations, you will want to use these actions in package mode.
+.Bl -tag -width XXXX
+.It auto Ar wrapper
+Removes any manual configuration created for the given
+.Ar wrapper .
+That is, if running as
+.Sq @ROOT_USER@ ,
+the system configuration file is deleted; otherwise, the user configuration
+file is removed.
+The effect of this action is that the wrapper is then free to choose any
+alternative it wants.
+.It manual Ar wrapper alternative arguments
+Manually selects the
+.Ar alternative
+for the given
+.Ar wrapper .
+If running as
+.Sq @ROOT_USER@ ,
+the system configuration file is modified; otherwise, the user configuration
+file is changed.
+The effect of this action is that the wrapper will try to use your preferred
+alternatives, regardless of what is installed on the system.
+.It register Ar wrapper alternative arguments
+Registers a new
+.Ar alternative
+for the given
+.Ar wrapper .
+If the wrapper did not exist before, it is created.
+You may optionally pass several
+.Ar arguments
+to the
+.Ar alternative
+program.
+.Pp
+This action should not be used directly; packages providing alternatives
+will take care to execute it at installation time.
+.It status Ar wrapper
+Shows which alternative will be used by the
+.Ar wrapper
+in the next run.
+It also displays all available candidates for it.
+.It unregister Ar wrapper alternative
+Removes the
+.Ar alternative
+from the given
+.Ar wrapper .
+If there are no more alternatives available, the wrapper is removed.
+.Pp
+This action should not be used directly; packages providing alternatives
+will take care to execute it at deinstallation time.
+.El
+.Sh ENVIRONMENT
+.Bl -tag -width PKG_DBDIR
+.It Ev PKG_DBDIR
+Location of the package database directory.
+Defaults to
+.Pa @PKG_DBDIR@ .
+.El
+.Sh FILES
+.Bl -tag -width XXXX
+.It Pa ~/.pkg_alternatives/
+User-specific configuration directory.
+.It Pa @CONFDIR@/
+System-wide configuration directory.
+.It Pa @DATADIR@/
+System-wide configuration database.
+.El
+.Sh DIAGNOSTICS
+.Nm
+exists 0 on success and 1 if an error occurred.
+.Sh SEE ALSO
+.Xr pkg_add 1 ,
+.Xr pkg_delete 1
+.Sh HISTORY
+The
+.Nm
+utility first appeared in pkgsrc-2005Q1.
+.Pp
+This utility was inspired by the alternatives system found in the Debian
+operating system.
+.Sh AUTHORS
+.An Julio M. Merino Vidal Aq jmmv@NetBSD.org
diff --git a/pkgtools/pkg_alternatives/files/pkg_alternatives.sh b/pkgtools/pkg_alternatives/files/pkg_alternatives.sh
new file mode 100644
index 00000000000..86cd6d23e63
--- /dev/null
+++ b/pkgtools/pkg_alternatives/files/pkg_alternatives.sh
@@ -0,0 +1,614 @@
+#!@SH@
+#
+# $NetBSD: pkg_alternatives.sh,v 1.1.1.1 2005/01/25 13:00:46 jmmv Exp $
+#
+# pkg_alternatives - Generic wrappers for programs with similar interfaces
+# Copyright (c) 2005 Julio M. Merino Vidal <jmmv@NetBSD.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name of author nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without alternative prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS 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 FOUNDATION OR 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.
+#
+
+Conf_Dir=@CONFDIR@@PREFIX@
+Data_Dir=@DATADIR@
+Db_Dir=@DBDIR@@PREFIX@
+Prefix=@PREFIX@
+Prog_Name=${0##*/}
+Verbose=yes
+
+: ${PKG_DBDIR:=@PKG_DBDIR@}
+
+# -------------------------------------------------------------------------
+
+# action_auto_package package
+#
+# Configures the given package to be in automatic mode. I.e., it removes
+# local customizations for all related wrappers, so that only the files in
+# the database are taken into account.
+#
+action_auto_package() {
+ validate_args auto ${#} -eq 1
+ validate_package ${1}
+ pkg=${PKG_DBDIR}/${1}*/+ALTERNATIVES
+
+ set -- $(cat ${pkg} | tr ' ' '¬')
+ while [ ${#} -gt 0 ]; do
+ action_auto_wrapper $(echo ${1} | cut -d '¬' -f 1)
+ shift
+ done
+}
+
+# -------------------------------------------------------------------------
+
+# action_auto_wrapper wrapper
+#
+# Configures the given wrapper to be in automatic mode. I.e., it removes
+# local customizations so that only the files in the database are taken
+# into account.
+#
+# wrapper is a path relative to prefix.
+#
+action_auto_wrapper() {
+ validate_args auto ${#} -eq 1
+ validate_wrapper ${1} yes
+
+ conf=$(get_my_config)/${1}
+ if [ -f ${conf} ]; then
+ info "removing configuration from \`${conf}'"
+ rm -f ${conf}
+ rmdir_p ${conf%/*}
+ else
+ info "no existing configuration for \`${1}'; nothing to be done"
+ fi
+}
+
+# -------------------------------------------------------------------------
+
+# action_list_package
+#
+# Lists all available packages that provide alternatives.
+#
+action_list_package() {
+ validate_args list ${#} -eq 0
+
+ info "looking for alternatives in \`${PKG_DBDIR}'"
+ for d in ${PKG_DBDIR}/*; do
+ [ -f ${d}/+ALTERNATIVES ] && echo ${d##${PKG_DBDIR}/}
+ done
+}
+
+# -------------------------------------------------------------------------
+
+# action_list_wrapper
+#
+# Unavailable action.
+#
+action_list_wrapper() {
+ err "the \`list' action cannot be used in wrapper mode"
+}
+
+# -------------------------------------------------------------------------
+
+# action_manual_package package
+#
+# Configures the given package to be the preferred alternative for all the
+# wrappers associated to it.
+#
+action_manual_package() {
+ validate_args manual ${#} -eq 1
+ validate_package ${1}
+ pkg=${PKG_DBDIR}/${1}*/+ALTERNATIVES
+
+ set -- $(cat ${pkg} | tr ' ' '¬')
+ while [ ${#} -gt 0 ]; do
+ action_manual_wrapper $(echo ${1} | tr '¬' ' ')
+ shift
+ done
+}
+
+# -------------------------------------------------------------------------
+
+# action_manual_wrapper wrapper alternative arguments
+#
+# Configures the given wrapper to use the specified alternative.
+# If running as the administrator, the system-wide settings are changed;
+# otherwise, the user-specific settings are affected.
+#
+# wrapper is a path relative to prefix.
+# alternative is an absolute path.
+#
+action_manual_wrapper() {
+ validate_args manual ${#} -ge 2
+ validate_wrapper ${1} yes
+ validate_alternative ${2}
+
+ conf=$(get_my_config)/${1}
+ info "modifying configuration from \`${conf}'"
+ mkdir_p ${conf%/*}
+ shift
+ echo "${*}" >${conf}
+}
+
+# -------------------------------------------------------------------------
+
+# action_rebuild_package
+#
+# Rebuilds the alternatives database from the package database.
+#
+action_rebuild_package() {
+ validate_args list ${#} -eq 0
+
+ info "removing contents of \`@DBDIR@'"
+ rm -rf @DBDIR@/* 2>/dev/null
+ info "looking for alternatives in \`${PKG_DBDIR}'"
+ for d in ${PKG_DBDIR}/*; do
+ if [ -f ${d}/+ALTERNATIVES ]; then
+ action_register_package ${d}/+ALTERNATIVES
+ fi
+ done
+}
+
+# -------------------------------------------------------------------------
+
+# action_rebuild_wrapper
+#
+# Unavailable action.
+#
+action_rebuild_wrapper() {
+ err "the \`rebuild' action cannot be used in wrapper mode"
+}
+
+# -------------------------------------------------------------------------
+
+# action_register_package file
+#
+# Registers all wrapper/alternative pairs listed in the file. This is
+# supposed to be an +ALTERNATIVES file found inside a package in PKG_DBDIR.
+# Each line should follow the semantics expected by action_register_wrapper.
+#
+action_register_package() {
+ validate_args register ${#} -eq 1
+
+ set -- $(cat ${1} | tr ' ' '¬')
+ while [ ${#} -gt 0 ]; do
+ action_register_wrapper $(echo ${1} | tr '¬' ' ')
+ shift
+ done
+}
+
+# -------------------------------------------------------------------------
+
+# action_register_wrapper wrapper alternative arguments
+#
+# Registers a new alternative for the given wrapper in the database.
+# The wrapper and its manual page are created if they do not exist.
+#
+action_register_wrapper() {
+ validate_args register ${#} -ge 2
+ validate_wrapper ${1} no
+ validate_alternative ${2}
+
+ wbase=${1}; shift
+ alt=${1}; shift
+ args=${*}
+
+ wabs=${Prefix}/${wbase}
+ manpage=$(get_manpage ${wbase})
+ dbconf=${Db_Dir}/${wbase}
+ sysconf=${Conf_Dir}/${wbase}
+
+ if [ ! -f ${dbconf} ]; then
+ info "initializing database entry for \`${wbase}'"
+ mkdir_p ${dbconf%/*}
+ touch ${dbconf%/*}
+ fi
+ info "registering alternative \`${alt}' for wrapper \`${wbase}'"
+ if [ -n "${args}" ]; then
+ echo "${alt} ${args}" >>${dbconf}
+ else
+ echo "${alt}" >>${dbconf}
+ fi
+
+ if [ ! -f ${wabs} ]; then
+ info "creating wrapper \`${wbase}'"
+ mkdir_p ${wabs%/*}
+ sed -e "s|__SH__|@SH@|g" \
+ -e "s|__CONF_FILE__|${sysconf}|g" \
+ -e "s|__CREATOR__|${Prog_Name}|g" \
+ -e "s|__DB_FILE__|${dbconf}|g" \
+ -e "s|__ROOT_USER__|@ROOT_USER@|g" \
+ -e "s|__WRAPPER__|${wabs}|g" \
+ <${Data_Dir}/wrapper.sh >${wabs}
+ chmod +x ${wabs}
+ mkdir_p ${manpage%/*}
+ sed -e "s|__CONF_FILE__|${sysconf}|g" \
+ -e "s|__CREATOR__|${Prog_Name}|g" \
+ -e "s|__DB_FILE__|${dbconf}|g" \
+ -e "s|__PREFIX__|${Prefix}|g" \
+ -e "s|__SECTION__|$(get_manpage_sect ${wbase})|g" \
+ -e "s|__TITLE__|$(echo ${wbase##*/} | tr a-z A-Z)|g" \
+ -e "s|__WRAPPER__|${wbase##*/}|g" \
+ -e "s|__WRAPPERBASE__|${wbase}|g" \
+ <${Data_Dir}/wrapper.man >${manpage}
+ fi
+}
+
+# -------------------------------------------------------------------------
+
+# action_status_package package
+#
+# Shows the status of each wrapper associated to the given package.
+#
+action_status_package() {
+ validate_args status ${#} -eq 1
+ validate_package ${1}
+ pkg=${PKG_DBDIR}/${1}*/+ALTERNATIVES
+
+ set -- $(cat ${pkg} | tr ' ' '¬')
+ while [ ${#} -gt 0 ]; do
+ action_status_wrapper $(echo ${1} | cut -d '¬' -f 1)
+ shift
+ done
+}
+
+# -------------------------------------------------------------------------
+
+# action_status_wrapper wrapper
+#
+# Shows the current status for the given wrapper.
+#
+action_status_wrapper() {
+ validate_args status ${#} -eq 1
+ validate_wrapper ${1} yes
+
+ wbase=${1}
+ dbconf=${Db_Dir}/${wbase}
+ sysconf=${Conf_Dir}/${wbase}
+ userconf=~/.pkg_alternatives${Prefix}/${wbase}
+
+ [ $(id -un) = @ROOT_USER@ ] && userconf=
+ alts=$(cat ${userconf} ${sysconf} ${dbconf} 2>/dev/null | grep -v '^#' | \
+ tr ' ' '¬')
+
+ found=
+ for a in ${alts}; do
+ prog=$(echo ${a} | cut -d '¬' -f 1)
+ if [ -x ${prog} ]; then
+ found=$(echo ${a} | tr '¬' ' ')
+ break
+ fi
+ done
+
+ [ -n "${found}" ] ||
+ err "the wrapper \`${wbase}' exists but has no valid alternatives"
+
+ echo "\`${wbase}' points to \`${found}'"
+ for a in $(echo ${alts} | tr ' ' '\n' | sort | uniq); do
+ echo " candidate: $(echo ${a} | tr '¬' ' ')"
+ done
+}
+
+# -------------------------------------------------------------------------
+
+# action_unregister_package file
+#
+# Unregisters the given package (given by its +ALTERNATIVES file) and
+# removes all associated alternatives from their respective wrappers.
+#
+action_unregister_package() {
+ validate_args unregister ${#} -eq 1
+
+ set -- $(cat ${1} | tr ' ' '¬')
+ while [ ${#} -gt 0 ]; do
+ action_unregister_wrapper $(echo ${1} | tr '¬' ' ')
+ shift
+ done
+}
+
+# -------------------------------------------------------------------------
+
+# action_unregister_wrapper wrapper alternative arguments
+#
+# Unregisters an alternative for the given wrapper. The lookup is done
+# based on the alternative name and its arguments. I.e., there must be
+# an exact match. If no alternatives remain after the removal, the wrapper
+# and its manpage are removed.
+#
+action_unregister_wrapper() {
+ validate_args unregister ${#} -ge 2
+ validate_wrapper ${1} yes
+
+ wbase=${1}; shift
+ alt=${1}; shift
+ args=${*}
+
+ manpage=$(get_manpage ${wbase})
+ dbconf=${Db_Dir}/${wbase}
+
+ if [ -n "${args}" ]; then
+ grep -v "^${alt} ${args}$" <${dbconf} >${dbconf}.new
+ else
+ grep -v "^${alt}$" <${dbconf} >${dbconf}.new
+ fi
+ if cmp -s ${dbconf} ${dbconf}.new; then
+ rm -f ${dbconf}.new
+ err "unknown alternative \`${alt}' for wrapper \`${wbase}'"
+ fi
+ mv ${dbconf}.new ${dbconf}
+
+ if ! grep '^/' ${dbconf} >/dev/null; then
+ info "no more alternatives for \`${wbase}'; removing"
+ rm -f ${dbconf} ${Prefix}/${wbase} ${manpage}
+ rmdir_p ${dbconf%/*}
+ rmdir_p ${Prefix}/${wbase%/*}
+ rmdir_p ${manpage%/*}
+ fi
+}
+
+# -------------------------------------------------------------------------
+
+# err message
+#
+# Prints the given error message and exist with an error code.
+#
+err() {
+ echo "${Prog_Name}: ${*}" 1>&2
+ exit 1
+}
+
+# -------------------------------------------------------------------------
+
+# get_my_config
+#
+# Prints the configuration directory for the current user. If root, this
+# is the system-wide configuration directory. Otherwise, it is the user's
+# personal directory.
+#
+get_my_config() {
+ if [ $(id -un) = @ROOT_USER@ ]; then
+ echo ${Conf_Dir}
+ else
+ echo ~/.pkg_alternatives${Prefix}
+ fi
+}
+
+# -------------------------------------------------------------------------
+
+# get_manpage wrapper
+#
+# Prints the absolute path to the manual page associated to wrapper.
+# Does no error checking; validate_wrapper has to be called before this
+# function to ensure wrapper is a valid name.
+#
+get_manpage() {
+ sect=$(get_manpage_sect ${1})
+ echo ${Prefix}/man/man${sect}/${1##*/}.${sect}
+}
+
+# -------------------------------------------------------------------------
+
+# get_manpage_sect wrapper
+#
+# Prints the section number that will be used by the wrapper's manpage.
+# Does no error checking; validate_wrapper has to be called before this
+# function to ensure wrapper is a valid name.
+#
+get_manpage_sect() {
+ case ${1%/*} in
+ bin) echo 1 ;;
+ libexec|sbin) echo 8 ;;
+ esac
+}
+
+# -------------------------------------------------------------------------
+
+# info message
+#
+# Prints the given informative message if running in verbose mode.
+#
+info() {
+ [ ${Verbose} = yes ] && echo "${Prog_Name}: ${*}"
+}
+
+# -------------------------------------------------------------------------
+
+# mkdir_p directory
+#
+mkdir_p() {
+ if [ ! -d ${1} ]; then
+ cnt=2
+ max=$(($(echo ${1} | tr '/' ' ' | wc -w | awk '{ print $1; }') + 1))
+ while [ ${cnt} -le ${max} ]; do
+ mkdir $(echo ${1} | cut -d '/' -f -${cnt}) 2>/dev/null
+ cnt=$((${cnt} + 1))
+ done
+ [ -d ${1} ] || err "cannot create directory \`${1}'"
+ fi
+}
+
+# -------------------------------------------------------------------------
+
+# usage
+#
+# Shows an usage message and exits the program with an error condition.
+#
+usage() {
+ echo "Usage: ${Prog_Name} [-sw] [-p prefix] action [arg1 ... argN]" 1>&2
+ exit 1
+}
+
+# -------------------------------------------------------------------------
+
+# rmdir_p directory
+#
+rmdir_p() {
+ if [ -d ${1} ]; then
+ cnt=$(($(echo ${1} | tr '/' ' ' | wc -w | awk '{ print $1; }') + 1))
+ while [ ${cnt} -gt 1 ]; do
+ rmdir $(echo ${1} | cut -d '/' -f -${cnt}) 2>/dev/null
+ cnt=$((${cnt} - 1))
+ done
+ fi
+}
+
+# -------------------------------------------------------------------------
+
+# validate_alternative name
+#
+# Verifies that the given program name is valid to be used as an
+# alternative.
+#
+validate_alternative() {
+ echo ${1} | grep '^/' >/dev/null || \
+ err "the alternative \`${1}' is not an absolute file name"
+ [ -x ${1} ] || \
+ err "the alternative \`${1}' is not an executable"
+}
+
+# -------------------------------------------------------------------------
+
+# validate_args action argcount operator expected
+#
+# Verifies that the number of arguments passed to the specified action
+# are correct according to its semantics. Prints an error message if
+# incorrect.
+#
+validate_args() {
+ [ ${2} ${3} ${4} ] || \
+ err "incorrect number of arguments for the \`${1}' action"
+}
+
+# -------------------------------------------------------------------------
+
+# validate_package name
+#
+# Verifies that the specified package is valid.
+#
+validate_package() {
+ if [ ! -f ${PKG_DBDIR}/${1}/+ALTERNATIVES ]; then
+ cnt=$(cd ${PKG_DBDIR} && ls -d ${1}-[0-9]* 2>/dev/null | wc -l | \
+ awk '{ print $1; }')
+ if [ "${cnt}" -eq 0 ]; then
+ err "the package \`${1}' is not known"
+ elif [ "${cnt}" -gt 1 ]; then
+ err "multiple matches found for \`${1}'"
+ fi
+
+ # Reached this point, there is a single match for the package,
+ # but it may still be wrong (i.e., no alternatives for it).
+ [ ! -f ${PKG_DBDIR}/${1}*/+ALTERNATIVES ] && \
+ err "no alternatives defined for the \`${1}' package"
+ fi
+}
+
+# -------------------------------------------------------------------------
+
+# validate_wrapper name exists
+#
+# Verifies that the specified wrapper is valid, i.e., if it belongs to a
+# known directory. Also, if the exists parameter is yes, the function
+# ensures that the wrapper already exists (as well as its configuration
+# file in the database).
+#
+validate_wrapper() {
+ case ${1%/*} in
+ bin|libexec|sbin)
+ if [ ${2} = yes ]; then
+ [ -x ${Prefix}/${1} ] || \
+ err "the wrapper \`${1}' does not exist or is not" \
+ "executable"
+ [ -f ${Db_Dir}/${1} ] || \
+ err "the database configuration \`${Db_Dir}/${1}'" \
+ "does not exist"
+ fi
+ ;;
+ *)
+ err "wrapper name \`${1}' is invalid"
+ ;;
+ esac
+}
+
+# -------------------------------------------------------------------------
+
+# warn message
+#
+# Shows a warning message.
+#
+warn() {
+ echo "${Prog_Name}: ${*}" 1>&2
+}
+
+# -------------------------------------------------------------------------
+
+# main
+#
+# Main program code. Does argument parsing and executes the required
+# action.
+#
+main() {
+ args=$(getopt p:sw ${*})
+ [ ${?} -eq 0 ] || usage
+ set -- ${args}
+ what=package
+ while [ ${#} -gt 0 ]; do
+ case ${1} in
+ -p)
+ Prefix=$2; shift
+ Conf_Dir=@CONFDIR@${Prefix}
+ Db_Dir=@DBDIR@${Prefix}
+ ;;
+ -s)
+ Verbose=no
+ ;;
+ -w)
+ what=wrapper
+ ;;
+ --)
+ shift; break
+ ;;
+ esac
+ shift
+ done
+
+ if [ ${#} -eq 0 ]; then
+ usage
+ fi
+
+ action=${1}; shift
+ case ${action} in
+ auto|list|manual|rebuild|register|status|unregister)
+ action_${action}_${what} "${@}"
+ ;;
+ *)
+ err "unknown action \`${action}'"
+ ;;
+ esac
+
+ return 0
+}
+
+main "${@}"
+
+# vim: syntax=sh:expandtab:shiftwidth=4:softtabstop=4
diff --git a/pkgtools/pkg_alternatives/files/wrapper.man b/pkgtools/pkg_alternatives/files/wrapper.man
new file mode 100644
index 00000000000..9f5248b06e4
--- /dev/null
+++ b/pkgtools/pkg_alternatives/files/wrapper.man
@@ -0,0 +1,70 @@
+.\" $NetBSD: wrapper.man,v 1.1.1.1 2005/01/25 13:00:46 jmmv Exp $
+.\"
+.\" pkg_alternatives - Generic wrappers for programs with similar interfaces
+.\" Copyright (c) 2005 Julio M. Merino Vidal <jmmv@NetBSD.org>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Neither the name of The NetBSD Foundation nor the names of its
+.\" contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\" 3. Neither the name of author nor the names of its contributors may
+.\" be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS 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 FOUNDATION OR 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.
+.\"
+.Dd January 25, 2005
+.Dt __TITLE__ __SECTION__
+.Os
+.Sh NAME
+.Nm __WRAPPER__
+.Nd generic wrapper created by the alternatives system
+.Sh SYNOPSIS
+.Nm
+.Op arguments
+.Sh DESCRIPTION
+.Nm
+is a generic wrapper created by the
+.Xr pkg_alternatives 1
+utility.
+Its purpose is to execute a program that provides a similar interface
+to the one expected by the more common name
+.Nm .
+.Pp
+The program to be really run is determined from a list of alternatives.
+You can check which one will be executed, as well as all available
+candidates, by issuing:
+.Bd -literal -offset indent
+$ pkg_alternatives -w status __WRAPPERBASE__
+.Ed
+.Pp
+Once you know which alternative is the chosen one, look at its manual page
+for more information.
+.Sh FILES
+.Bl -tag -width XXXX
+.It ~/.pkg_alternatives__PREFIX__/__WRAPPERBASE__
+User-specific list of candidates.
+.It __CONF_FILE__
+System-wide list of candidates, automatically configured by installed
+packages.
+.It __DB_FILE__
+System-wide list of candidates, manually configured by the administrator.
+.El
+.Sh SEE ALSO
+.Xr pkg_alternatives 1
+.Sh AUTHORS
+.An Julio M. Merino Vidal Aq jmmv@NetBSD.org
diff --git a/pkgtools/pkg_alternatives/files/wrapper.sh b/pkgtools/pkg_alternatives/files/wrapper.sh
new file mode 100644
index 00000000000..e4a757a2801
--- /dev/null
+++ b/pkgtools/pkg_alternatives/files/wrapper.sh
@@ -0,0 +1,64 @@
+#!__SH__
+#
+# $NetBSD: wrapper.sh,v 1.1.1.1 2005/01/25 13:00:46 jmmv Exp $
+#
+# pkg_alternatives - Generic wrappers for programs with similar interfaces
+# Copyright (c) 2005 Julio M. Merino Vidal <jmmv@NetBSD.org>
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions
+# are met:
+# 1. Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+# 2. Redistributions in binary form must reproduce the above copyright
+# notice, this list of conditions and the following disclaimer in
+# the documentation and/or other materials provided with the
+# distribution.
+# 3. Neither the name of author nor the names of its contributors may
+# be used to endorse or promote products derived from this software
+# without alternative prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+# ``AS IS'' AND ANY EXPRESS 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 FOUNDATION OR 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.
+#
+
+wrapper="__WRAPPER__"
+progname="${wrapper##*/} (wrapper)"
+
+if [ ! -f __DB_FILE__ ]; then
+ echo "${progname}: cannot open __DB_FILE__" 1>&2
+ exit 1
+fi
+
+if [ $(id -un) = __ROOT_USER__ ]; then
+ userfile=
+else
+ userfile=~/.pkg_alternatives/${wrapper}
+fi
+alternatives=$(cat ${userfile} __CONF_FILE__ __DB_FILE__ 2>/dev/null | \
+ grep -v "^#" | tr ' ' '¬')
+
+found=
+for a in ${alternatives}; do
+ prog=$(echo ${a} | cut -d '¬' -f 1)
+ if [ -x ${prog} ]; then
+ found=$(echo ${a} | tr '¬' ' ')
+ break
+ fi
+done
+
+if [ -z "${found}" ]; then
+ echo "${progname}: no alternatives found" 1>&2
+ exit 1
+fi
+
+exec ${found} "${@}"