diff options
Diffstat (limited to 'pkgtools/pkg_alternatives/files')
-rw-r--r-- | pkgtools/pkg_alternatives/files/pkg_alternatives.8 | 289 | ||||
-rw-r--r-- | pkgtools/pkg_alternatives/files/pkg_alternatives.sh | 614 | ||||
-rw-r--r-- | pkgtools/pkg_alternatives/files/wrapper.man | 70 | ||||
-rw-r--r-- | pkgtools/pkg_alternatives/files/wrapper.sh | 64 |
4 files changed, 1037 insertions, 0 deletions
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} "${@}" |