summaryrefslogtreecommitdiff
path: root/pkgtools/pkgtasks/files/shells.subr
diff options
context:
space:
mode:
Diffstat (limited to 'pkgtools/pkgtasks/files/shells.subr')
-rw-r--r--pkgtools/pkgtasks/files/shells.subr292
1 files changed, 292 insertions, 0 deletions
diff --git a/pkgtools/pkgtasks/files/shells.subr b/pkgtools/pkgtasks/files/shells.subr
new file mode 100644
index 00000000000..cffbf333031
--- /dev/null
+++ b/pkgtools/pkgtasks/files/shells.subr
@@ -0,0 +1,292 @@
+# Copyright (c) 2017 The NetBSD Foundation, Inc.
+# All rights reserved.
+#
+# This code is derived from software contributed to The NetBSD Foundation
+# by Johnny C. Lam.
+#
+# 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.
+#
+# 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.
+#
+# NAME
+# shells.subr -- shell database management for packages
+#
+# SYNOPSIS
+# task_shells [-s] add | remove
+# task_shells check-add | check-remove
+#
+# DESCRIPTION
+# The task_shells function supports four actions: "add", "remove",
+# "check-add", and "check-remove".
+#
+# The available options are as follows:
+#
+# -s Silent; don't write to standard output.
+#
+# The task_shells function reads standard input line by line and
+# looks for lines of the form:
+#
+# # SHELL: <shell_path> [<shelldb_path>]
+#
+# If any of the paths are relative, then they are assumed to be
+# relative to ${PKG_PREFIX}.
+#
+# The "add" action adds shell paths to the shell database.
+#
+# The "remove" action removes shell paths from the shell database.
+#
+# The "check-add" action will check whether shell paths are missing
+# from the shell database and writes an informative message noting
+# the missing shell paths.
+#
+# The "check-remove" action will check whether shell paths are
+# still present in the shell database and writes an informative
+# message noting the existing paths.
+#
+# RETURN VALUES
+# The "add" and "remove" actions return 0 if they are successful
+# for all shell paths, and >0 if an error occurs.
+#
+# The "check-add" and "check-remove" actions return >0 if they
+# write informative messages, and return 0 otherwise.
+#
+# ENVIRONMENT
+# The following variables are used if they are set:
+#
+# MV The name or path to the mv(1) utility.
+#
+# PKGNAME
+# The name of the package.
+#
+# PKG_DESTDIR
+# A "destdir" prefix that is prepended to all filesystem
+# paths. The default value is the empty string.
+#
+# PKG_REGISTER_SHELLS
+# If ${PKG_REGISTER_SHELLS} is a "truthy" value, then the
+# "add" and "remove" actions are allowed to modify the shell
+# databases as needed.
+#
+# PKG_PREFIX
+# The installation prefix of the package. The default is
+# "/usr/pkg".
+#
+# RM The name or path to the rm(1) utility.
+#
+# TASK_MSG
+# String prepended to all normal message written to
+# standard output.
+#
+
+__task_shells__="yes"
+__task_shells_init__="_task_shells_init"
+
+task_load cleanup
+task_load echo
+task_load lock
+task_load maketemp
+task_load match
+task_load quote
+task_load truthy
+
+task_shells()
+{
+ : ${MV:=mv}
+
+ : ${PKG_PREFIX:=/usr/pkg}
+ : ${PKGNAME:=${0##*/}}
+
+ : ${PKG_REGISTER_SHELLS:=yes}
+ : ${TASK_MSG:=""}
+
+ local arg
+ local echo="task_echo"
+ local OPTIND=1
+ while getopts ":s" arg "$@"; do
+ case $arg in
+ s) echo=":" ;;
+ *) return 127 ;;
+ esac
+ done
+ shift $(( ${OPTIND} - 1 ))
+ [ $# -gt 0 ] || return 127
+
+ local action="$1"; shift
+ case $action in
+ add|remove|check-add|check-remove)
+ : "valid actions" ;;
+ *) return 0 ;;
+ esac
+
+ # Guard against ${PKG_PREFIX} == "/".
+ local prefix
+ case ${PKG_PREFIX}/ in
+ //) prefix= ;;
+ *) prefix=${PKG_PREFIX} ;;
+ esac
+
+ local register_shells="yes"
+ task_is_truthy "${PKG_REGISTER_SHELLS}" || register_shells=
+
+ local result line_result
+ local quoted
+ local lock lock_quoted
+ local temp temp_quoted
+
+ result=0
+ local hash tag shell shelldb
+ while read hash tag shell shelldb; do
+ # Filter for "# SHELL:".
+ case $hash/$tag in
+ "#/SHELL:")
+ : "use this line" ;;
+ *) continue ;;
+ esac
+
+ # Canonicalize paths.
+ case $shell in
+ "") # skip lines without any required args
+ continue ;;
+ [!/]*) shell="$prefix/$shell" ;;
+ esac
+ case $shelldb in
+ "") shelldb="/etc/shells" ;;
+ [!/]*) shelldb="$prefix/$shelldb" ;;
+ esac
+ shelldb="${PKG_DESTDIR}$shelldb"
+
+ line_result=0
+ case $action in
+ add|remove)
+ lock="$shelldb.lock"
+ task_quote "$lock"
+ lock_quoted=$quoted
+ __task_shells_locks__="$lock_quoted $__task_shells_locks__"
+ task_lock "$lock" || line_result=1 ;;
+ esac
+ if [ $line_result -eq 0 ]; then
+ case $action in
+ add) if [ -n "$register_shells" ]; then
+ if [ -f "$shelldb" ] && task_match -qw "$shell" < $shelldb; then
+ $echo "${TASK_MSG}! shell already added: $shell"
+ else
+ temp=$( task_maketemp "$shelldb.pkgtasks.XXXXXXXXXX" )
+ if [ -n "$temp" ]; then
+ task_quote "$temp"
+ temp_quoted="$quoted"
+ __task_shells_temps__="$__task_shells_temps__ $temp_quoted"
+ if [ ! -f "$shelldb" ]; then
+ echo "$shell"
+ else
+ task_match -vw "$shell" < $shelldb
+ echo "$shell"
+ fi > $temp
+ # rename(2) is atomic.
+ if ${MV} -f "$temp" "$shelldb"; then
+ $echo "${TASK_MSG}> shell added: $shell"
+ __task_shells_temps__=${__task_shells_temps__% $temp_quoted}
+ else
+ $echo "${TASK_MSG}! shell not added: $shell"
+ line_result=1
+ fi
+ else
+ $echo "${TASK_MSG}! cannot create temporary file for $shelldb"
+ line_result=1
+ fi
+ fi
+ fi ;;
+ remove) if [ -n "$register_shells" ]; then
+ if [ -f "$shelldb" ] && task_match -qw "$shell" < $shelldb; then
+ temp=$( task_maketemp "$shelldb.pkgtasks.XXXXXXXXXX" )
+ if [ -n "$temp" ]; then
+ task_quote "$temp"
+ temp_quoted="$quoted"
+ __task_shells_temps__="$__task_shells_temps__ $temp_quoted"
+ task_match -vw "$shell" < $shelldb > $temp
+ # rename(2) is atomic.
+ if ${MV} -f "$temp" "$shelldb"; then
+ $echo "${TASK_MSG}> shell removed: $shell"
+ __task_shells_temps__=${__task_shells_temps__% $temp_quoted}
+ else
+ $echo "${TASK_MSG}! shell not removed: $shell"
+ line_result=1
+ fi
+ else
+ $echo "${TASK_MSG}! cannot create temporary file for $shelldb"
+ line_result=1
+ fi
+ else
+ $echo "${TASK_MSG}! shell already removed: $shell"
+ fi
+ fi ;;
+ check-add)
+ if [ -f "$shelldb" ] && task_match -qw "$shell" < $shelldb; then
+ : "shell already added"
+ else
+ task_echo "!!! INFO: ${PKGNAME}: Add shell \"$shell\" to $shelldb."
+ line_result=1
+ fi ;;
+ check-remove)
+ if [ -f "$shelldb" ] && task_match -qw "$shell" < $shelldb; then
+ task_echo "!!! INFO: ${PKGNAME}: Remove shell \"$shell\" from $shelldb."
+ line_result=1
+ fi ;;
+ esac
+ fi
+ case $action in
+ add|remove)
+ task_lock -r "$lock"
+ __task_shells_locks__=${__task_shells_locks__#$lock_quoted } ;;
+ esac
+ [ $line_result -eq 0 ] || result=1
+ done
+
+ _task_shells_cleanup
+ return $result
+}
+
+_task_shells_cleanup()
+{
+ : ${RM:=rm}
+
+ eval set -- $__task_shells_temps__
+ local file
+ for file; do
+ ${RM} -f "$file"
+ done
+ __task_shells_temps__=
+
+ eval set -- $__task_shells_locks__
+ local lockfile
+ for lockfile; do
+ task_lock -r "$lockfile"
+ done
+ __task_shells_locks__=
+}
+
+_task_shells_init()
+{
+ task_cleanup_add_hook _task_shells_cleanup
+}
+
+# Static variable for temporary files that should be removed in an error occurs.
+__task_shells_temps__=
+# Static variable for locks that should be released if an error occurs.
+__task_shells_locks__=