scoped_command revision 1.2 1 1.1 christos #!/bin/sh
2 1.1 christos #
3 1.2 christos # $NetBSD: scoped_command,v 1.2 2016/03/27 14:57:50 christos 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.1 christos 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