1272343Sngie#!/bin/sh
2272343Sngie#
3309466Sngie# $NetBSD: scoped_command,v 1.2 2016/03/27 14:57:50 christos Exp $
4272343Sngie#
5272343Sngie# Copyright (c) 2014 The NetBSD Foundation, Inc.
6272343Sngie# All rights reserved.
7272343Sngie#
8272343Sngie# This code is derived from software contributed to The NetBSD Foundation
9272343Sngie# by Jarmo Jaakkola.
10272343Sngie#
11272343Sngie# Redistribution and use in source and binary forms, with or without
12272343Sngie# modification, are permitted provided that the following conditions
13272343Sngie# are met:
14272343Sngie# 1. Redistributions of source code must retain the above copyright
15272343Sngie#    notice, this list of conditions and the following disclaimer.
16272343Sngie# 2. Redistributions in binary form must reproduce the above copyright
17272343Sngie#    notice, this list of conditions and the following disclaimer in the
18272343Sngie#    documentation and/or other materials provided with the distribution.
19272343Sngie#
20272343Sngie# THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
21272343Sngie# ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
22272343Sngie# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23272343Sngie# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
24272343Sngie# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25272343Sngie# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26272343Sngie# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27272343Sngie# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28272343Sngie# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29272343Sngie# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30272343Sngie# POSSIBILITY OF SUCH DAMAGE.
31272343Sngie#
32272343Sngie
33309466Sngie: ${TEST_SH:=/bin/sh}
34309466Sngie
35309466Sngiesane_sh()
36309466Sngie{
37309466Sngie	set -- ${TEST_SH}
38309466Sngie	case "$#" in
39309466Sngie	(0)   set /bin/sh;;
40309466Sngie	(1|2) ;;
41309466Sngie	(*)   set "$1";;   # Just ignore options if we cannot make them work
42309466Sngie	esac
43309466Sngie
44309466Sngie	case "$1" in
45309466Sngie	/*)	TEST_SH="$1${2+ }$2";;
46309466Sngie	./*)	TEST_SH="${PWD}${1#.}${2+ }$2";;
47309466Sngie	*/*)	TEST_SH="${PWD}/$1${2+ }$2";;
48309466Sngie	*)	TEST_SH="$( command -v "$1" )${2+ }$2";;
49309466Sngie	esac
50309466Sngie}
51309466Sngie
52309466Sngiesane_sh
53309466Sngie
54272343Sngieset -e
55272343Sngie
56272343Sngie# USAGE:
57272343Sngie#   scoped_command scope cmd msg var_suffix
58272343Sngie#
59272343Sngie# Write to stdout a piece of Bourne Shell script with _cmd_ in specific
60272343Sngie# _scope_.  The execution of _cmd_ is bracketed by prints of "before _msg_"
61272343Sngie# and "after _msg_, return value ${?}".  If the generated script uses
62272343Sngie# variables, __var_suffix_ is appended to their names to allow nesting of
63272343Sngie# scripts generated this way.
64272343Sngie#
65272343Sngie# _scope_ should be one of: case, compound, file, for, func, subshell,
66272343Sngie# until, while.
67272343Sngie# _cmd_ is the command line to execute.  Remember proper quoting!
68272343Sngie# _msg_ is text that will be used inside single quotes.
69272343Sngie# _var_suffix_ is a syntactically valid identifier name.
70272343Sngie
71272343Sngie# don't rely on command lists (';')
72272343Sngiecmd="echo 'before ${3}'
73272343Sngie${2}
74272343Sngieecho 'after ${3}, return value:' ${?}"
75272343Sngie
76309466Sngieecho "#!${TEST_SH}"
77272343Sngie
78272343Sngie[ 'func' = "${1}" ] && cat <<EOF
79272343Sngiefunc()
80272343Sngie{
81272343Sngie    echo 'before ${3}'
82272343Sngie    \${1}
83272343Sngie    echo 'after ${3}'
84272343Sngie}
85272343Sngie
86272343Sngieecho 'before function'
87272343Sngiefunc "${2}" "${3}"  # don't rely on 'shift'
88272343Sngieecho 'after function'
89272343SngieEOF
90272343Sngie
91272343Sngie[ 'case' = "${1}" ] && cat <<EOF
92272343Sngieecho 'before case'
93272343Sngiecase 'a' in
94272343Sngie    a)  ${cmd};;
95272343Sngieesac
96272343Sngieecho 'after case'
97272343SngieEOF
98272343Sngie
99272343Sngie[ 'file' = "${1}" ] && cat <<EOF
100272343Sngie${cmd}
101272343SngieEOF
102272343Sngie
103272343Sngie[ 'while' = "${1}" ] && cat <<EOF
104272343Sngieecho 'before while'
105272343Sngiecond_${4}='true true false'
106272343Sngiewhile \${cond_${4}}
107272343Sngiedo
108272343Sngie    cond_${4}="\${cond_${4}#* }"
109272343Sngie    ${cmd}
110272343Sngiedone
111272343Sngieecho 'after while'
112272343SngieEOF
113272343Sngie
114272343Sngie[ 'until' = "${1}" ] && cat <<EOF
115272343Sngieecho 'before until'
116272343Sngiecond_${4}='false false true'
117272343Sngieuntil \${cond_${4}}
118272343Sngiedo
119272343Sngie    cond_${4}="\${cond_${4}#* }"
120272343Sngie    ${cmd}
121272343Sngiedone
122272343Sngieecho 'after until'
123272343SngieEOF
124272343Sngie
125272343Sngie[ 'for' = "${1}" ] && cat <<EOF
126272343Sngieecho 'before for'
127272343Sngiefor i_${4} in 1 2
128272343Sngiedo
129272343Sngie    ${cmd}
130272343Sngiedone
131272343Sngieecho 'after for'
132272343SngieEOF
133272343Sngie
134272343Sngie[ 'subshell' = "${1}" ] && cat <<EOF
135272343Sngie(
136272343Sngie    echo 'subshell start'
137272343Sngie    ${cmd}
138272343Sngie    echo 'subshell end'
139272343Sngie)
140272343SngieEOF
141272343Sngie
142272343Sngie[ 'compound' = "${1}" ] && cat <<EOF
143272343Sngie{
144272343Sngie    echo 'compound start'
145272343Sngie    ${cmd};
146272343Sngie    echo 'compound end'
147272343Sngie}
148272343SngieEOF
149272343Sngie
150272343Sngieexit 0
151