pkgsrc/mk/scripts/shell-lib

385 lines
11 KiB
Text

# $NetBSD: shell-lib,v 1.4 2006/10/22 00:35:26 rillig Exp $
#
# Copyright (c) 2004 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.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by the NetBSD
# Foundation, Inc. and its contributors.
# 4. 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.
#
# 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.
#
######################################################################
# msg_log logfile msg
# Output msg to logfile. If logfile is "stdout" or "stderr"
# then output to there instead.
######################################################################
msg_log()
{
: ${echo=echo}
_msg_log="$1"; shift
case $_msg_log in
stdout) $echo "$@" ;;
stderr) $echo "$@" 1>&2 ;;
*) $echo "$@" >> $_msg_log ;;
esac
}
######################################################################
# die msg
# Output $msg to stderr, and exit with a positive error code.
######################################################################
die()
{
msg_log stderr "$@"
exit 1
}
######################################################################
# check_prog var prog ...
# If $var is empty or unset, then set it to the path of one of
# the program names in the list.
######################################################################
check_prog()
{
: ${test=test}
_ckp_var="$1"; shift
eval _ckp_tmp=\"\$$_ckp_var\"
if $test "x$_ckp_tmp" != "x"; then
return 0
fi
for _ckp_prog do
_ckp_IFS="${IFS}"; IFS=":"
for _ckp_dir in ${PATH}; do
if $test -x "$_ckp_dir/$_ckp_prog"; then
eval $_ckp_var=\""$_ckp_dir/$_ckp_prog"\"
return 1
fi
done
IFS="${_ckp_IFS}"
done
die "$_ckp_var could not be set."
}
######################################################################
# shquote arg
# Returns a backslashed and quoted version of arg in $shquoted.
######################################################################
shquote()
{
: ${echo=echo}
: ${sed=sed}
_shq_arg=$1
_shq_sed="$sed -e 1s/^X//"
_shq_sed_quote_subst='s/\([\`\"$\\]\)/\\\1/g'
case $_shq_arg in
*[\`\"\$\\]*)
shquoted=`$echo "X$_shq_arg" | $_shq_sed -e "$_shq_sed_quote_subst"`
;;
*)
shquoted="$_shq_arg"
;;
esac
case $shquoted in
*[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"")
shquoted="\"$shquoted\""
;;
esac
}
######################################################################
# lock_file -f path [-n token]
# Attempt to create a lockfile at $path. Any directories in the
# path should already exist. If $token is specified, then assume
# that it is unique between machines sharing an NFS mount.
#
# (1) Create globally-unique filename in the same filesystem as the
# lockfile.
# (2) Try to create a hard-link from this file to the lockfile, but
# ignoring any errors.
# (3) If the two files are the same file, then the lock was successfully
# obtained; otherwise, the lock attempt wasn't successful.
######################################################################
lock_file()
{
: ${dirname=dirname}
: ${echo=echo}
: ${link=link}
: ${mkdir=mkdir}
: ${mktemp=mktemp}
: ${rm=rm}
: ${test=test}
: ${touch=touch}
_lf_lockfile=
_lf_nfs=
while $test $# -gt 0; do
case $1 in
-f) _lf_lockfile="$2"; shift ;;
-n) _lf_nfs="$2"; shift ;;
esac
shift
done
if $test -z "$_lf_lockfile"; then
$echo 1>&2 "$0: no lock file specified."
exit
fi
_lf_pid=$$
_lf_lockdir=`$dirname $_lf_lockfile`
_lf_uniqfile=`$mktemp "$_lf_lockdir/.lock.$_lf_nfs.$_lf_pid.XXXXXX" 2>/dev/null` || return 1
if $test -n "$_lf_nfs"; then
{ $echo $_lf_pid; $echo $_lf_nfs; } > $_lf_uniqfile
else
$echo $_lf_pid > $_lf_uniqfile
fi
$link $_lf_uniqfile $_lf_lockfile 2>/dev/null
if $test $_lf_uniqfile -ef $_lf_lockfile; then
_lf_result=0
else
_lf_result=1
fi
$rm -f $_lf_uniqfile
return $_lf_result
}
######################################################################
######################################################################
###
### Queue routines. The queue is implemented as a set of variables
### that is unique to each queue name, thus the use of multiple queues
### is allowed.
###
######################################################################
######################################################################
######################################################################
# init_queue name
# Initialize the named queue.
######################################################################
init_queue()
{
_qname="$1"
eval "_q${_qname}head=1111111111"
eval "_q${_qname}tail=1111111111"
}
######################################################################
# append_queue name item ...
# Append items onto the end of the named queue in FIFO order.
######################################################################
append_queue()
{
: ${test=test}
_qname="$1"; shift
while $test $# -gt 0; do
eval "_qtail=\"\$_q${_qname}tail\""
eval "_q${_qname}${_qtail}=\"\${1}\""
case $_qtail in
*000000000) _qtail=${_qtail%000000000}1 ;;
*) _qtail=${_qtail}0 ;;
esac
eval "_q${_qname}tail=\"\${_qtail}\""
shift
done
}
######################################################################
# prepend_queue name item ...
# Prepend items to the head of the named queue in LIFO order.
######################################################################
prepend_queue()
{
: ${test=test}
_qname="$1"; shift
while $test $# -gt 0; do
eval "_qhead=\"\$_q${_qname}head\""
case $_qhead in
*1) _qhead=${_qhead%1}000000000 ;;
*) _qhead=${_qhead%0} ;;
esac
eval "_q${_qname}${_qhead}=\"\${1}\""
eval "_q${_qname}head=\"\${_qhead}\""
shift
done
}
######################################################################
# head_queue name var
# Return the head of the named queue in $var.
######################################################################
head_queue()
{
_qname="$1"; shift
eval "_qhead=\"\$_q${_qname}head\""
eval "${1}=\"\$_q${_qname}${_qhead}\""
}
######################################################################
# pop_queue name var
# Pop off the head of the named queue and return it in $var.
######################################################################
pop_queue()
{
_qname="$1"; shift
head_queue $_qname $1
case $_qhead in
*000000000) _qhead=${_qhead%000000000}1 ;;
*) _qhead=${_qhead}0 ;;
esac
eval "_q${_qname}head=\"\${_qhead}\""
}
######################################################################
# queue_is_empty name
# Return 0 if the named queue is empty and 1 otherwise.
######################################################################
queue_is_empty()
{
: ${test=test}
_qname="$1"
eval "_qhead=\"\$_q${_qname}head\""
eval "_qtail=\"\$_q${_qname}tail\""
$test "$_qhead" = "$_qtail"
return $?
}
######################################################################
######################################################################
###
### File queue routines. The file queue is implemented as a file
### whose lines represent the queue elements. The file queue name
### is simply the file used for the queue, thus the use of multiple
### queues is allowed.
###
######################################################################
######################################################################
######################################################################
# init_fqueue name
# Initialize the named file queue.
######################################################################
init_fqueue()
{
_fqname="$1"
: > "$_fqname"
}
######################################################################
# append_fqueue name item ...
# Append items onto the end of the named file queue in FIFO order.
######################################################################
append_fqueue()
{
: ${echo=echo}
: ${test=test}
_fqname="$1"; shift
while $test $# -gt 0; do
$echo "$1" >> "$_fqname"
shift
done
}
######################################################################
# prepend_fqueue name item ...
# Prepend items to the head of the named file queue in LIFO order.
######################################################################
prepend_fqueue()
{
: ${cat=cat}
: ${echo=echo}
: ${mv=mv}
_fqname="$1"; shift
_fqtmpfile="$_fqname.$$"
init_queue _fqtmpqueue
prepend_queue _fqtmpqueue "$@"
while ! queue_is_empty _fqtmpqueue; do
pop_queue _fqtmpqueue _fqelt
$echo "$_fqelt" >> "$_fqtmpfile"
done
$cat "$_fqname" >> "$_fqtmpfile"
$mv -f "$_fqtmpfile" "$_fqname"
}
######################################################################
# head_fqueue name var
# Return the head of the named file queue in $var.
######################################################################
head_fqueue()
{
: ${head=head}
_fqname="$1"; shift
_tmp=`$head -n 1 "$_fqname"`
eval "${1}=\"\$_tmp\""
}
######################################################################
# pop_fqueue name var
# Pop off the head of the named file queue and return it in $var.
######################################################################
pop_fqueue()
{
: ${mv=mv}
: ${sed=sed}
_fqname="$1"; shift
_fqtmpfile="$_fqname.$$"
head_fqueue "$_fqname" $1
$sed "1,1d" "$_fqname" >> "$_fqtmpfile"
$mv -f "$_fqtmpfile" "$_fqname"
}
######################################################################
# fqueue_is_empty name
# Return 0 if the named file queue is empty and >0 otherwise.
######################################################################
fqueue_is_empty()
{
: ${test=test}
: ${wc=wc}
_fqname="$1"
if $test -f "$_fqname"; then
_fqlines=`$wc -l < "$_fqname"`
return $_fqlines
else
return 1
fi
}