1 1.1 christos #!/bin/sh 2 1.1 christos # 3 1.3 kre # $NetBSD: scoped_command,v 1.3 2018/12/04 09:47:25 kre Exp $ 4 1.1 christos # 5 1.1 christos # Copyright (c) 2014 The NetBSD Foundation, Inc. 6 1.1 christos # All rights reserved. 7 1.1 christos # 8 1.1 christos # This code is derived from software contributed to The NetBSD Foundation 9 1.1 christos # by Jarmo Jaakkola. 10 1.1 christos # 11 1.1 christos # Redistribution and use in source and binary forms, with or without 12 1.1 christos # modification, are permitted provided that the following conditions 13 1.1 christos # are met: 14 1.1 christos # 1. Redistributions of source code must retain the above copyright 15 1.1 christos # notice, this list of conditions and the following disclaimer. 16 1.1 christos # 2. Redistributions in binary form must reproduce the above copyright 17 1.1 christos # notice, this list of conditions and the following disclaimer in the 18 1.1 christos # documentation and/or other materials provided with the distribution. 19 1.1 christos # 20 1.1 christos # THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 21 1.1 christos # ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 22 1.1 christos # TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 23 1.1 christos # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 24 1.1 christos # BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25 1.1 christos # CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26 1.1 christos # SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27 1.1 christos # INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28 1.1 christos # CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29 1.1 christos # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30 1.1 christos # POSSIBILITY OF SUCH DAMAGE. 31 1.1 christos # 32 1.1 christos 33 1.2 christos : ${TEST_SH:=/bin/sh} 34 1.2 christos 35 1.2 christos sane_sh() 36 1.2 christos { 37 1.2 christos set -- ${TEST_SH} 38 1.2 christos case "$#" in 39 1.2 christos (0) set /bin/sh;; 40 1.2 christos (1|2) ;; 41 1.2 christos (*) set "$1";; # Just ignore options if we cannot make them work 42 1.2 christos esac 43 1.2 christos 44 1.2 christos case "$1" in 45 1.2 christos /*) TEST_SH="$1${2+ }$2";; 46 1.2 christos ./*) TEST_SH="${PWD}${1#.}${2+ }$2";; 47 1.2 christos */*) TEST_SH="${PWD}/$1${2+ }$2";; 48 1.2 christos *) TEST_SH="$( command -v "$1" )${2+ }$2";; 49 1.2 christos esac 50 1.2 christos } 51 1.2 christos 52 1.2 christos sane_sh 53 1.2 christos 54 1.1 christos set -e 55 1.1 christos 56 1.1 christos # USAGE: 57 1.1 christos # scoped_command scope cmd msg var_suffix 58 1.1 christos # 59 1.1 christos # Write to stdout a piece of Bourne Shell script with _cmd_ in specific 60 1.1 christos # _scope_. The execution of _cmd_ is bracketed by prints of "before _msg_" 61 1.1 christos # and "after _msg_, return value ${?}". If the generated script uses 62 1.1 christos # variables, __var_suffix_ is appended to their names to allow nesting of 63 1.1 christos # scripts generated this way. 64 1.1 christos # 65 1.1 christos # _scope_ should be one of: case, compound, file, for, func, subshell, 66 1.1 christos # until, while. 67 1.1 christos # _cmd_ is the command line to execute. Remember proper quoting! 68 1.1 christos # _msg_ is text that will be used inside single quotes. 69 1.1 christos # _var_suffix_ is a syntactically valid identifier name. 70 1.1 christos 71 1.1 christos # don't rely on command lists (';') 72 1.1 christos cmd="echo 'before ${3}' 73 1.1 christos ${2} 74 1.3 kre echo 'after ${3}, return value:' \${?}" 75 1.1 christos 76 1.2 christos echo "#!${TEST_SH}" 77 1.1 christos 78 1.1 christos [ 'func' = "${1}" ] && cat <<EOF 79 1.1 christos func() 80 1.1 christos { 81 1.1 christos echo 'before ${3}' 82 1.1 christos \${1} 83 1.1 christos echo 'after ${3}' 84 1.1 christos } 85 1.1 christos 86 1.1 christos echo 'before function' 87 1.1 christos func "${2}" "${3}" # don't rely on 'shift' 88 1.1 christos echo 'after function' 89 1.1 christos EOF 90 1.1 christos 91 1.1 christos [ 'case' = "${1}" ] && cat <<EOF 92 1.1 christos echo 'before case' 93 1.1 christos case 'a' in 94 1.1 christos a) ${cmd};; 95 1.1 christos esac 96 1.1 christos echo 'after case' 97 1.1 christos EOF 98 1.1 christos 99 1.1 christos [ 'file' = "${1}" ] && cat <<EOF 100 1.1 christos ${cmd} 101 1.1 christos EOF 102 1.1 christos 103 1.1 christos [ 'while' = "${1}" ] && cat <<EOF 104 1.1 christos echo 'before while' 105 1.1 christos cond_${4}='true true false' 106 1.1 christos while \${cond_${4}} 107 1.1 christos do 108 1.1 christos cond_${4}="\${cond_${4}#* }" 109 1.1 christos ${cmd} 110 1.1 christos done 111 1.1 christos echo 'after while' 112 1.1 christos EOF 113 1.1 christos 114 1.1 christos [ 'until' = "${1}" ] && cat <<EOF 115 1.1 christos echo 'before until' 116 1.1 christos cond_${4}='false false true' 117 1.1 christos until \${cond_${4}} 118 1.1 christos do 119 1.1 christos cond_${4}="\${cond_${4}#* }" 120 1.1 christos ${cmd} 121 1.1 christos done 122 1.1 christos echo 'after until' 123 1.1 christos EOF 124 1.1 christos 125 1.1 christos [ 'for' = "${1}" ] && cat <<EOF 126 1.1 christos echo 'before for' 127 1.1 christos for i_${4} in 1 2 128 1.1 christos do 129 1.1 christos ${cmd} 130 1.1 christos done 131 1.1 christos echo 'after for' 132 1.1 christos EOF 133 1.1 christos 134 1.1 christos [ 'subshell' = "${1}" ] && cat <<EOF 135 1.1 christos ( 136 1.1 christos echo 'subshell start' 137 1.1 christos ${cmd} 138 1.1 christos echo 'subshell end' 139 1.1 christos ) 140 1.1 christos EOF 141 1.1 christos 142 1.1 christos [ 'compound' = "${1}" ] && cat <<EOF 143 1.1 christos { 144 1.1 christos echo 'compound start' 145 1.1 christos ${cmd}; 146 1.1 christos echo 'compound end' 147 1.1 christos } 148 1.1 christos EOF 149 1.1 christos 150 1.1 christos exit 0 151