diff options
Diffstat (limited to 'xi/bin')
-rwxr-xr-x | xi/bin/ifdown | 100 | ||||
-rwxr-xr-x | xi/bin/ifup | 136 | ||||
-rwxr-xr-x | xi/bin/modules-load | 19 | ||||
-rwxr-xr-x | xi/bin/tmpfiles | 592 |
4 files changed, 847 insertions, 0 deletions
diff --git a/xi/bin/ifdown b/xi/bin/ifdown new file mode 100755 index 0000000..a133c25 --- /dev/null +++ b/xi/bin/ifdown @@ -0,0 +1,100 @@ +#!/bin/bash +######################################################################## +# Begin /sbin/ifdown +# +# Description : Interface Down +# +# Authors : Nathan Coulson - nathan@linuxfromscratch.org +# Kevin P. Fleming - kpfleming@linuxfromscratch.org +# Update : Bruce Dubbs - bdubbs@linuxfromscratch.org +# +# Version : LFS 7.0 +# +# Notes : the IFCONFIG variable is passed to the scripts found +# in the /lib/services directory, to indicate what file the +# service should source to get interface specifications. +# +######################################################################## + +RELEASE="7.0" + +USAGE="Usage: $0 [ -hV ] [--help] [--version] interface" +VERSTR="LFS ifdown, version ${RELEASE}" + +while [ $# -gt 0 ]; do + case "$1" in + --help | -h) help="y"; break ;; + + --version | -V) echo "${VERSTR}"; exit 0 ;; + + -*) echo "ifup: ${1}: invalid option" >&2 + echo "${USAGE}" >& 2 + exit 2 ;; + + *) break ;; + esac +done + +if [ -n "$help" ]; then + echo "${VERSTR}" + echo "${USAGE}" + echo + cat << HERE_EOF +ifdown is used to bring down a network interface. The interface +parameter, e.g. eth0 or eth0:2, must match the trailing part of the +interface specifications file, e.g. /etc/sysconfig/ifconfig.eth0:2. + +HERE_EOF + exit 0 +fi + +file=/etc/sysconfig/ifconfig.${1} + +# Skip backup files +[ "${file}" = "${file%""~""}" ] || exit 0 + +#. /lib/lsb/init-functions + +if [ ! -r "${file}" ]; then + echo "${file} is missing or cannot be accessed." + exit 1 +fi + +. ${file} + +if [ "$IFACE" = "" ]; then + echo "${file} does not define an interface [IFACE]." + exit 1 +fi + +# We only need to first service to bring down the interface +S=`echo ${SERVICE} | cut -f1 -d" "` + +if ip link show ${IFACE} > /dev/null 2>&1; then + if [ -n "${S}" -a -x "/lib/services/${S}" ]; then + IFCONFIG=${file} /lib/services/${S} ${IFACE} down + else + MSG="Unable to process ${file}. Either " + MSG="${MSG}the SERVICE variable was not set " + MSG="${MSG}or the specified service cannot be executed." + echo "$MSG" + exit 1 + fi +else + echo "Interface ${1} doesn't exist." +fi + +# Leave the interface up if there are additional interfaces in the device +link_status=`ip link show ${IFACE} 2>/dev/null` + +if [ -n "${link_status}" ]; then + if [ "$(echo "${link_status}" | grep UP)" != "" ]; then + if [ "$(ip addr show ${IFACE} | grep 'inet ')" == "" ]; then + echo "Bringing down the ${IFACE} interface..." + ip link set ${IFACE} down + #evaluate_retval + fi + fi +fi + +# End /sbin/ifdown diff --git a/xi/bin/ifup b/xi/bin/ifup new file mode 100755 index 0000000..7466150 --- /dev/null +++ b/xi/bin/ifup @@ -0,0 +1,136 @@ +#!/bin/sh +######################################################################## +# Begin /sbin/ifup +# +# Description : Interface Up +# +# Authors : Nathan Coulson - nathan@linuxfromscratch.org +# Kevin P. Fleming - kpfleming@linuxfromscratch.org +# Update : Bruce Dubbs - bdubbs@linuxfromscratch.org +# +# Version : LFS 7.2 +# +# Notes : The IFCONFIG variable is passed to the SERVICE script +# in the /lib/services directory, to indicate what file the +# service should source to get interface specifications. +# +######################################################################## + +up() +{ + if ip link show $1 > /dev/null 2>&1; then + link_status=`ip link show $1` + + if [ -n "${link_status}" ]; then + if ! echo "${link_status}" | grep -q UP; then + ip link set $1 up + fi + fi + + else + echo "Interface ${IFACE} doesn't exist." + exit 1 + fi +} + +RELEASE="7.2" + +USAGE="Usage: $0 [ -hV ] [--help] [--version] interface" +VERSTR="LFS ifup, version ${RELEASE}" + +while [ $# -gt 0 ]; do + case "$1" in + --help | -h) help="y"; break ;; + + --version | -V) echo "${VERSTR}"; exit 0 ;; + + -*) echo "ifup: ${1}: invalid option" >&2 + echo "${USAGE}" >& 2 + exit 2 ;; + + *) break ;; + esac +done + +if [ -n "$help" ]; then + echo "${VERSTR}" + echo "${USAGE}" + echo + cat << HERE_EOF +ifup is used to bring up a network interface. The interface +parameter, e.g. eth0 or eth0:2, must match the trailing part of the +interface specifications file, e.g. /etc/sysconfig/ifconfig.eth0:2. + +HERE_EOF + exit 0 +fi + +file=/etc/sysconfig/ifconfig.${1} + +# Skip backup files +[ "${file}" = "${file%""~""}" ] || exit 0 + +#. /lib/lsb/init-functions + +echo "Bringing up the ${1} interface... " + +if [ ! -r "${file}" ]; then + echo "${file} is missing or cannot be accessed." + exit 1 +fi + +. $file + +if [ "$IFACE" = "" ]; then + echo "${file} does not define an interface [IFACE]." + exit 1 +fi + +# Do not process this service if started by boot, and ONBOOT +# is not set to yes +if [ "${IN_BOOT}" = "1" -a "${ONBOOT}" != "yes" ]; then + echo "skipped" + exit 0 +fi + +for S in ${SERVICE}; do + if [ ! -x "/lib/services/${S}" ]; then + echo "Unable to process ${file}. Either " + echo "${MSG}the SERVICE '${S} was not present " + echo "${MSG}or cannot be executed." + echo "$MSG" + exit 1 + fi +done + +# Create/configure the interface +for S in ${SERVICE}; do + IFCONFIG=${file} /lib/services/${S} ${IFACE} up +done + +# Bring up the interface and any components +for I in $IFACE $INTERFACE_COMPONENTS; do up $I; done + +# Set MTU if requested. Check if MTU has a "good" value. +if test -n "${MTU}"; then + if [[ ${MTU} =~ ^[0-9]+$ ]] && [[ $MTU -ge 68 ]] ; then + for I in $IFACE $INTERFACE_COMPONENTS; do + ip link set dev $I mtu $MTU; + done + else + echo "Invalid MTU $MTU" + fi +fi + +# Set the route default gateway if requested +if [ -n "${GATEWAY}" ]; then + if ip route | grep -q default; then + echo "Gateway already setup; skipping." + else + echo "Setting up default gateway..." + ip route add default via ${GATEWAY} dev ${IFACE} + #evaluate_retval + fi +fi + +# End /sbin/ifup diff --git a/xi/bin/modules-load b/xi/bin/modules-load new file mode 100755 index 0000000..35e73b8 --- /dev/null +++ b/xi/bin/modules-load @@ -0,0 +1,19 @@ +#!/bin/sh +# modules-load [-n] [-v] - modules-load.d(5) compatible kernel module loader + +export PATH=/bin:/sbin + +{ +# Parameters passed as modules-load= or rd.modules-load= in kernel command line. +sed -nr 's/,/\n/;s/(.* |^)(rd\.)?modules-load=([^ ]*).*/\3/p' /proc/cmdline + +# Find files /{etc,run,usr/lib}/modules-load.d/*.conf in that order. +find -L /etc/modules-load.d /run/modules-load.d /usr/lib/modules-load.d \ + -maxdepth 1 -name '*.conf' -printf '%p %P\n' 2>/dev/null | +# Load each basename only once. + sort -k2 -s | uniq -f1 | cut -d' ' -f1 | +# Read the files, output all non-empty, non-comment lines. + tr '\012' '\0' | xargs -0 -r grep -h -v -e '^[#;]' -e '^$' +} | +# Call modprobe on the list of modules +tr '\012' '\0' | xargs -0 -r modprobe -ab "$@" diff --git a/xi/bin/tmpfiles b/xi/bin/tmpfiles new file mode 100755 index 0000000..5e4ee0a --- /dev/null +++ b/xi/bin/tmpfiles @@ -0,0 +1,592 @@ +#!/bin/sh +# This is a reimplementation of the systemd tmpfiles.d code +# Control creation, deletion, and cleaning of volatile and temporary files +# +# Copyright (c) 2012 Gentoo Foundation +# Released under the 2-clause BSD license. +# +# This instance is a pure-POSIX sh version, written by Robin H Johnson +# <robbat2@gentoo.org>, based on the Arch Linux version as of 2012/01/01: +# http://projects.archlinux.org/initscripts.git/tree/arch-tmpfiles +# +# See the tmpfiles.d manpage as well: +# https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html +# This script should match the old manpage +# http://0pointer.de/public/systemd-man/tmpfiles.d.html +# as of 2012/03/12 and also implements some more recent features +# + +DRYRUN=0 + +checkprefix() { + n=$1 + shift + for x in "$@"; do + case ${n} in + ${x}*) return 0 ;; + esac + done + return 1 +} + +warninvalid() { + printf "tmpfiles: ignoring invalid entry on line %d of \`%s'\n" "${LINENUM}" "${FILE}" + error=$(( error+1 )) +} >&2 + +invalid_option() { + printf "tmpfiles: invalid option '%s'\n" "$1" >&2 + exit 1 +} + +dryrun_or_real() { + local dryrun= + if [ ${DRYRUN} -eq 1 ]; then + dryrun="echo" + fi + ${dryrun} "$@" +} + +_chattr() { + local attr="$2" + case ${attr} in + [+-=]*) : ;; + '') return ;; + *) attr="+${attr}" ;; + esac + local IFS= + dryrun_or_real chattr "$1" "${attr}" -- "$3" +} + +_setfacl() { + dryrun_or_real setfacl -P "$1" "$2" "$3" -- "$4" +} + +relabel() { + local path + local paths=$1 mode=$2 uid=$3 gid=$4 + local status + + status=0 + for path in ${paths}; do + if [ -e "${path}" ]; then + if [ -x /sbin/restorecon ]; then + dryrun_or_real restorecon ${CHOPTS} "${path}" || status="$?" + fi + if [ "${uid}" != '-' ]; then + dryrun_or_real chown ${CHOPTS} "${uid}" "${path}" || status="$?" + fi + if [ "${gid}" != '-' ]; then + dryrun_or_real chgrp ${CHOPTS} "${gid}" "${path}" || status="$?" + fi + if [ "${mode}" != '-' ]; then + dryrun_or_real chmod ${CHOPTS} "${mode}" "${path}" || status="$?" + fi + fi + done + return ${status} +} + +splitpath() { + local path=$1 + while [ -n "${path}" ]; do + printf '%s\n' "${path}" + path=${path%/*} + done +} + +_restorecon() { + local path=$1 + if [ -x /sbin/restorecon ]; then + dryrun_or_real restorecon -F "$(splitpath "${path}")" + fi +} + +createdirectory() { + local mode="$1" uid="$2" gid="$3" path="$4" + [ -d "${path}" ] || dryrun_or_real mkdir -p "${path}" + if [ "${uid}" = - ]; then + uid=root + fi + if [ "${gid}" = - ]; then + gid=root + fi + if [ "${mode}" = - ]; then + mode=0755 + fi + dryrun_or_real chown ${uid} "${path}" + dryrun_or_real chgrp ${gid} "${path}" + dryrun_or_real chmod ${mode} "${path}" +} + +createfile() { + local mode="$1" uid="$2" gid="$3" path="$4" + dryrun_or_real touch "${path}" + if [ "${uid}" = - ]; then + uid=root + fi + if [ "${gid}" = - ]; then + gid=root + fi + if [ "${mode}" = - ]; then + mode=0644 + fi + dryrun_or_real chown ${uid} "${path}" + dryrun_or_real chgrp ${gid} "${path}" + dryrun_or_real chmod ${mode} "${path}" +} + +createpipe() { + local mode="$1" uid="$2" gid="$3" path="$4" + dryrun_or_real mkfifo "${path}" + if [ "${uid}" = - ]; then + uid=root + fi + if [ "${gid}" = - ]; then + gid=root + fi + if [ "${mode}" = - ]; then + mode=0644 + fi + dryrun_or_real chown ${uid} "${path}" + dryrun_or_real chgrp ${gid} "${path}" + dryrun_or_real chmod ${mode} "${path}" +} + +_b() { + # Create a block device node if it doesn't exist yet + local path=$1 mode=$2 uid=$3 gid=$4 age=$5 arg=$6 + if [ "${uid}" = - ]; then + uid=root + fi + if [ "${gid}" = - ]; then + gid=root + fi + if [ "${mode}" = - ]; then + mode=0644 + fi + if [ ! -e "${path}" ]; then + dryrun_or_real mknod -m ${mode} "${path}" b "${arg%:*}" "${arg#*:}" + _restorecon "${path}" + dryrun_or_real chown ${uid} "${path}" + dryrun_or_real chgrp ${gid} "${path}" + fi +} + +_c() { + # Create a character device node if it doesn't exist yet + local path=$1 mode=$2 uid=$3 gid=$4 age=$5 arg=$6 + if [ "${uid}" = - ]; then + uid=root + fi + if [ "${gid}" = - ]; then + gid=root + fi + if [ "${mode}" = - ]; then + mode=0644 + fi + if [ ! -e "${path}" ]; then + dryrun_or_real mknod -m ${mode} "${path}" c "${arg%:*}" "${arg#*:}" + _restorecon "${path}" + dryrun_or_real chown ${uid} "${path}" + dryrun_or_real chgrp ${gid} "${path}" + fi +} + +_C() { + # recursively copy a file or directory + local path=$1 mode=$2 uid=$3 gid=$4 age=$5 arg=$6 + if [ ! -e "${path}" ]; then + dryrun_or_real cp -r "${arg}" "${path}" + _restorecon "${path}" + if [ "${uid}" != '-' ]; then + dryrun_or_real chown "${uid}" "${path}" + fi + if [ "${gid}" != '-' ]; then + dryrun_or_real chgrp "${gid}" "${path}" + fi + if [ "${mode}" != '-' ]; then + dryrun_or_real chmod "${mode}" "${path}" + fi + fi +} + +_f() { + # Create a file if it doesn't exist yet + local path=$1 mode=$2 uid=$3 gid=$4 age=$5 arg=$6 + + [ "${CREATE}" -gt 0 ] || return 0 + + if [ ! -e "${path}" ]; then + createfile "${mode}" "${uid}" "${gid}" "${path}" + if [ -n "${arg}" ]; then + _w "$@" + fi + fi +} + +_F() { + # Create or truncate a file + local path=$1 mode=$2 uid=$3 gid=$4 age=$5 arg=$6 + + [ "${CREATE}" -gt 0 ] || return 0 + + dryrun_or_real rm -f "${path}" + createfile "${mode}" "${uid}" "${gid}" "${path}" + if [ -n "${arg}" ]; then + _w "$@" + fi +} + +_d() { + # Create a directory if it doesn't exist yet + local path=$1 mode=$2 uid=$3 gid=$4 + + if [ "${CREATE}" -gt 0 ]; then + createdirectory "${mode}" "${uid}" "${gid}" "${path}" + _restorecon "${path}" + fi +} + +_D() { + # Create or empty a directory + local path=$1 mode=$2 uid=$3 gid=$4 + + if [ -d "${path}" ] && [ "${REMOVE}" -gt 0 ]; then + dryrun_or_real find "${path}" -mindepth 1 -maxdepth 1 -xdev -exec rm -rf {} + + _restorecon "${path}" + fi + + if [ "${CREATE}" -gt 0 ]; then + createdirectory "${mode}" "${uid}" "${gid}" "${path}" + _restorecon "${path}" + fi +} + +_v() { + # Create a subvolume if the path does not exist yet and the file system + # supports this (btrfs). Otherwise create a normal directory. + # TODO: Implement btrfs subvol creation. + _d "$@" +} + +_q() { + # Similar to _v. However, make sure that the subvolume will be assigned + # to the same higher-level quota groups as the subvolume it has + # been created in. + # TODO: Implement btrfs subvol creation. + _d "$@" +} + +_Q() { + # Similar to q. However, instead of copying the higher-level quota + # group assignments from the parent as-is, the lowest quota group + # of the parent subvolume is determined that is not the + # leaf quota group. + # TODO: Implement btrfs subvol creation. + _d "$@" +} + +_a() { + # Set/add file/directory ACL. Lines of this type accept + # shell-style globs in place of normal path names. + # The format of the argument field matches setfacl + local ACTION='--remove-all --set' + [ "${FORCE}" -gt 0 ] && ACTION='--modify' + _setfacl '' "${ACTION}" "$6" "$1" +} + +_A() { + # Recursively set/add file/directory ACL. Lines of this type accept + # shell-syle globs in place of normal path names. + # Does not follow symlinks + local ACTION='--remove-all --set' + [ "${FORCE}" -gt 0 ] && ACTION='--modify' + _setfacl -R "${ACTION}" "$6" "$1" +} + +_h() { + # Set file/directory attributes. Lines of this type accept + # shell-style globs in place of normal path names. + # The format of the argument field matches chattr + _chattr '' "$6" "$1" +} + +_H() { + # Recursively set file/directory attributes. Lines of this type accept + # shell-syle globs in place of normal path names. + # Does not follow symlinks + _chattr -R "$6" "$1" +} + +_L() { + # Create a symlink if it doesn't exist yet + local path=$1 mode=$2 uid=$3 gid=$4 age=$5 arg=$6 + if [ ! -e "${path}" ]; then + dryrun_or_real ln -s "${arg}" "${path}" + fi + _restorecon "${path}" +} + +_p() { + # Create a named pipe (FIFO) if it doesn't exist yet + local path=$1 mode=$2 uid=$3 gid=$4 + + [ "${CREATE}" -gt 0 ] || return 0 + + if [ ! -p "${path}" ]; then + createpipe "${mode}" "${uid}" "${gid}" "${path}" + fi +} + +_x() { + # Ignore a path during cleaning. Use this type to exclude paths from clean-up as + # controlled with the Age parameter. Note that lines of this type do not + # influence the effect of r or R lines. Lines of this type accept shell-style + # globs in place of of normal path names. + : + # XXX: we don't implement this +} + +_X() { + # Ignore a path during cleanup. Use this type to prevent path + # removal as controled with the age parameter. Note that if path is + # a directory, the content of the directory is not excluded from + # clean-up, only the directory itself. + # Lines of this type accept shell-style globs in place of normal path names. + : + # XXX: we don't implement this +} + +_r() { + # Remove a file or directory if it exists. This may not be used to remove + # non-empty directories, use R for that. Lines of this type accept shell-style + # globs in place of normal path names. + local path + local paths=$1 + local status + + [ "${REMOVE}" -gt 0 ] || return 0 + + status=0 + for path in ${paths}; do + if [ -f "${path}" ]; then + dryrun_or_real rm -f "${path}" || status="$?" + elif [ -d "${path}" ]; then + dryrun_or_real rmdir "${path}" || status="$?" + fi + done + return ${status} +} + +_R() { + # Recursively remove a path and all its subdirectories (if it is a directory). + # Lines of this type accept shell-style globs in place of normal path names. + local path + local paths=$1 + local status + + [ "${REMOVE}" -gt 0 ] || return 0 + + status=0 + for path in ${paths}; do + if [ -d "${path}" ]; then + dryrun_or_real rm -rf --one-file-system "${path}" || status="$?" + fi + done + return ${status} +} + +_w() { + # Write the argument parameter to a file, if it exists. + local path=$1 mode=$2 uid=$3 gid=$4 age=$5 arg=$6 + if [ -f "${path}" ]; then + if [ ${DRYRUN} -eq 1 ]; then + echo "echo \"${arg}\" >>\"${path}\"" + else + echo "${arg}" >>"${path}" + fi + fi +} + +_z() { + # Set ownership, access mode and relabel security context of a file or + # directory if it exists. Lines of this type accept shell-style globs in + # place of normal path names. + [ "${CREATE}" -gt 0 ] || return 0 + + relabel "$@" +} + +_Z() { + # Recursively set ownership, access mode and relabel security context of a + # path and all its subdirectories (if it is a directory). Lines of this type + # accept shell-style globs in place of normal path names. + [ "${CREATE}" -gt 0 ] || return 0 + + CHOPTS=-R relabel "$@" +} + +usage() { + printf 'usage: %s [--exclude-prefix=path] [--prefix=path] [--boot] [--create] [--remove] [--clean] [--verbose] [--dry-run]\n' "${0##*/}" + exit "${1:-0}" +} + +version() { + # We don't record the version info anywhere currently. + echo "opentmpfiles" + exit 0 +} + +BOOT=0 CREATE=0 REMOVE=0 CLEAN=0 VERBOSE=0 DRYRUN=0 error=0 LINENO=0 +EXCLUDE= +PREFIX= +FILES= + +while [ $# -gt 0 ]; do + case $1 in + --boot) BOOT=1 ;; + --create) CREATE=1 ;; + --remove) REMOVE=1 ;; + --clean) CLEAN=1 ;; # TODO: Not implemented + --verbose) VERBOSE=1 ;; + --dryrun|--dry-run) DRYRUN=1 ;; + --exclude-prefix=*) EXCLUDE="${EXCLUDE}${1##--exclude-prefix=} " ;; + --prefix=*) PREFIX="${PREFIX}${1##--prefix=} " ;; + -h|--help) usage ;; + --version) version ;; + -*) invalid_option "$1" ;; + *) FILES="${FILES} $1" + esac + shift +done + +if [ $(( CLEAN )) -eq 1 ] ; then + printf '%s clean mode is not implemented\n' "${0##*/}" + exit 1 +fi + +if [ "${CREATE}${REMOVE}" = '00' ]; then + usage 1 >&2 +fi + +# XXX: The harcoding of /usr/lib/ is an explicit choice by upstream +tmpfiles_dirs='/usr/lib/tmpfiles.d /run/tmpfiles.d /etc/tmpfiles.d' +tmpfiles_basenames='' + +if [ -z "${FILES}" ]; then + # Build a list of sorted unique basenames + # directories declared later in the tmpfiles_d array will override earlier + # directories, on a per file basename basis. + # `/etc/tmpfiles.d/foo.conf' supersedes `/usr/lib/tmpfiles.d/foo.conf'. + # `/run/tmpfiles/foo.conf' will always be read after `/etc/tmpfiles.d/bar.conf' + for d in ${tmpfiles_dirs} ; do + [ -d "${d}" ] && for f in "${d}"/*.conf ; do + case "${f##*/}" in + systemd.conf|systemd-*.conf) continue;; + esac + [ -f "${f}" ] && tmpfiles_basenames="${tmpfiles_basenames}\n${f##*/}" + done # for f in ${d} + done # for d in ${tmpfiles_dirs} + # shellcheck disable=SC2059 + FILES="$(printf "${tmpfiles_basenames}" | sort -u )" +fi + +tmpfiles_d='' + +for b in ${FILES} ; do + if [ "${b##*/}" != "${b}" ]; then + # The user specified a path on the command line + # Just pass it through unaltered + tmpfiles_d="${tmpfiles_d} ${b}" + else + real_f='' + for d in ${tmpfiles_dirs} ; do + f=${d}/${b} + [ -f "${f}" ] && real_f=${f} + done + [ -f "${real_f}" ] && tmpfiles_d="${tmpfiles_d} ${real_f}" + fi +done + +error=0 + +# loop through the gathered fragments, sorted globally by filename. +# `/run/tmpfiles/foo.conf' will always be read after `/etc/tmpfiles.d/bar.conf' +FILE= +for FILE in ${tmpfiles_d} ; do + LINENUM=0 + + ### FILE FORMAT ### + # XXX: We ignore the 'Age' parameter + # 1 2 3 4 5 6 7 + # Cmd Path Mode UID GID Age Argument + # d /run/user 0755 root root 10d - + # Mode, UID, GID, Age, Argument may be omitted! + # If Cmd ends with !, the line is only processed if --boot is passed + + # XXX: Upstream says whitespace is NOT permitted in the Path argument. + # But IS allowed when globs are expanded for the x/r/R/z/Z types. + while read -r cmd path mode uid gid age arg rest; do + LINENUM=$(( LINENUM+1 )) + FORCE=0 + + # Unless we have both command and path, skip this line. + if [ -z "${cmd}" ] || [ -z "${path}" ]; then + continue + fi + + case ${cmd} in + \#*) continue ;; + esac + + while [ ${#cmd} -gt 1 ]; do + case ${cmd} in + *!) cmd=${cmd%!}; [ "${BOOT}" -eq "1" ] || continue 2 ;; + *+) cmd=${cmd%+}; FORCE=1; ;; + *) warninvalid ; continue 2 ;; + esac + done + + # whine about invalid entries + case ${cmd} in + f|F|w|d|D|v|p|L|c|C|b|x|X|r|R|z|Z|q|Q|h|H|a|A) ;; + *) warninvalid ; continue ;; + esac + + # fall back on defaults when parameters are passed as '-' + if [ "${mode}" = '-' ] || [ "${mode}" = '' ]; then + case "${cmd}" in + p|f|F) mode=0644 ;; + d|D|v) mode=0755 ;; + C|z|Z|x|r|R|L) ;; + esac + fi + + [ "${uid}" = '-' ] || [ "${uid}" = '' ] && uid=0 + [ "${gid}" = '-' ] || [ "${gid}" = '' ] && gid=0 + [ "${age}" = '-' ] || [ "${age}" = '' ] && age=0 + [ "${arg}" = '-' ] || [ "${arg}" = '' ] && arg='' + set -- "${path}" "${mode}" "${uid}" "${gid}" "${age}" "${arg}" + + [ -n "${EXCLUDE}" ] && checkprefix "${path}" "${EXCLUDE}" && continue + [ -n "${PREFIX}" ] && ! checkprefix "${path}" "${PREFIX}" && continue + + if [ "${FORCE}" -gt 0 ]; then + case ${cmd} in + p|L|c|b) [ -f "${path}" ] && dryrun_or_real rm -f "${path}" + esac + fi + + [ "${VERBOSE}" -eq "1" ] && echo "_${cmd}" "$@" + "_${cmd}" "$@" + rc=$? + if [ "${DRYRUN}" -eq "0" ]; then + [ ${rc} -ne 0 ] && error=$((error + 1)) + fi + done <"${FILE}" +done + +exit ${error} + +# vim: set ts=2 sw=2 sts=2 noet ft=sh: |