1#! /helper/script/for/moderni/sh 2IFS=''; set -fCu # safe mode 3 4# This is a helper script called by the '-exec' primary of 'find' in the 5# var/loop/find module. It turns its arguments into assignments for the main 6# shell to eval. 7# 8# --- begin license --- 9# Copyright (c) 2019 Martijn Dekker <martijn@inlv.org>, Groningen, Netherlands 10# 11# Permission to use, copy, modify, and/or distribute this software for any 12# purpose with or without fee is hereby granted, provided that the above 13# copyright notice and this permission notice appear in all copies. 14# 15# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 16# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 17# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 18# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 19# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 20# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 21# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 22# --- end license --- 23 24# If the pipe is broken, the -exec'ed shell will get SIGPIPE but the 'find' utility itself won't. 25# To avoid 'find' going haywire, our -exec'ed shell must trap SIGPIPE and kill its parent PID, which 26# is the 'find' utility. Also add a fallback check for I/O error in 'put', in case SIGPIPE is ignored. 27 28trap 'trap - PIPE; kill -s PIPE $PPID $$' PIPE 29 30interrupt_find() { 31 kill -s PIPE $$ # this will also kill our $PPID (the 'find' utility) through the trap 32 kill -s TERM $PPID $$ # SIGPIPE is ignored: loop/find.mm will OK this if WRN_NOSIGPIPE was detected, or die() 33 DIE "signals ignored" # both SIGPIPE and SIGTERM are ignored: fatal; loop/find.mm will die() 34} 35 36DIE() { 37 echo "LOOP find: $@" >&2 38 kill -s KILL $PPID $$ 39} 40 41# Check that either the variable or the xargs option was exported to here, but not both. 42 43case ${_loop_PATH+A}${_loop_AUX+O}${_loop_V+K}${_loop_xargs+K} in 44( AOK ) ;; 45( * ) echo "die 'LOOP find: internal error'" >&8 || DIE "internal error" 46 interrupt_find ;; 47esac 48 49PATH=${_loop_PATH} 50 51# Use modernish shell-quoting (via awk) to guarantee one loop iteration 52# command per line, so the main shell can safely 'read -r' and 'eval' any 53# possible file names from the FIFO. 54 55awk -f ${_loop_AUX}/find.awk -- "$@" >&8 56e=$? 57case $e in 58( 0 ) ;; 59( 126 ) DIE "system error: awk could not be executed" ;; 60( 127 ) DIE "system error: awk could not be found" ;; 61( 129 | 1[3-9]? | [!1]?? | ????* ) 62 sig=$(kill -l $e 2>/dev/null) 63 sig=${sig#[sS][iI][gG]} 64 case $sig in 65 ( [pP][iI][pP][eE] ) 66 interrupt_find ;; # propagate SIGPIPE upwards 67 ( '' | [0-9]* ) 68 DIE "system error: awk exited with status $e" ;; 69 ( * ) DIE "system error: awk was killed by SIG$sig" ;; 70 esac ;; 71( * ) # other nonzero exit status: presume write error from awk 72 interrupt_find ;; 73esac 74