1#! /install/script/for/moderni/sh
2#
3# This is dotted/sourced by install.sh to bundle a script.
4# See the file LICENSE in the main modernish directory for the licence.
5
6# In case someone tries to run this directly...
7PATH=/dev/null command -v install_file >/dev/null || exit
8
9# ----- functions -----
10
11# Simple function to wrap progressive messages indicating progress.
12column_pos=0
13put_wrap() {
14	let "(column_pos += ${#1}) >= ${COLUMNS:-80}" && putln && column_pos=${#1}
15	put "$1"
16}
17
18# Covert all the tiny cap/*.t scripts into shell functions, and insert them into bin/modernish.
19# (The lib/_install/bin/modernish.bundle.diff patch changed thisshellhas() to use these functions, and to
20# remove --cache and --show because now we can't use lib/modernish/cap/*.t to know what all our IDs are.)
21link_cap_tests() {
22	put_wrap "- Static linking of cap tests:"
23	num_captests=0
24	LOOP for --glob cap in ${opt_D}$installroot/lib/modernish/cap/*.t; DO
25		inc num_captests
26		capname=${cap##*/cap/}
27		capname=${capname%.t}
28		put_wrap "  $capname"
29		str match $capname *[!ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_]* && continue
30		code=$(sed '1 d' $cap)	# omit line 1 = hashbang
31		trim code $CCn		# remove leading blank lines
32		putln "_Msh_CAP_$capname() {" $code "}" >&3
33	DONE 3>$tmpdir/captests
34
35	# This tag was patched in from lib/_install/bin/modernish.bundle.diff.
36	# Now we sed it back out, replacing it with the hardlinked cap tests.
37	sed "/@INSERT_CAPTESTS_HERE@/ {
38		r $tmpdir/captests
39		d
40	}" ${opt_D}$installroot/bin/modernish >| $tmpdir/patched:bin:modernish || die
41
42	# 'sed' doesn't even give an error message or a nonzero status if the 'r'
43	# command fails to read the file, so we have to check the results.
44	num_captests_ok=$(grep -c '^_Msh_CAP_.*() {$' $tmpdir/patched:bin:modernish)
45	if not eq num_captests_ok num_captests; then
46		putln '' "  --  FAIL"
47		die "Static linking FAILED: $num_captests processed, $num_captests_ok linked"
48	fi
49
50	cat $tmpdir/patched:bin:modernish >| ${opt_D}$installroot/bin/modernish || die
51	put_wrap "  --  done ($num_captests)."
52	putln; column_pos=0
53	rm -r ${opt_D}$installroot/lib/modernish/cap <&-
54}
55
56# Generate and install a wrapper script that runs a bundled program with modernish.
57# usage: install_wrapper_script SCRIPTBASENAME SHELLQUOTED_SCRIPTBASENAME
58install_wrapper_script() {
59	install_file - $opt_D/$1 <<-end_of_wrapper
60	#! /bin/sh
61	# Wrapper script to run $2 with bundled modernish
62
63	min_posix='cd -P -- / && ! { ! case x in ( x ) : \${0##*/} || : \$( : ) ;; esac; }'
64	if (eval "\$min_posix") 2>/dev/null; then
65	 	unset -v min_posix
66	else
67	 	# this is an ancient Bourne shell (e.g. Solaris 10)
68	 	sh -c "\$min_posix" 2>/dev/null && exec sh -- "\$0" \${1+"\$@"}
69	 	DEFPATH=\`getconf PATH\` 2>/dev/null || DEFPATH=/usr/xpg4/bin:/bin:/usr/bin:/sbin:/usr/sbin
70	 	PATH=\$DEFPATH:\$PATH
71	 	export PATH
72	 	sh -c "\$min_posix" 2>/dev/null && exec sh -- "\$0" \${1+"\$@"}
73	 	echo "\$0: Can't escape from obsolete shell. Run me with a POSIX shell." >&2
74	 	exit 128
75	fi
76
77	unset -v CDPATH DEFPATH IFS MSH_PREFIX MSH_SHELL	# avoid these being inherited/exported
78	CCn='
79	'
80
81	# Find bundled modernish.
82	# ... First, if \$0 is a symlink, resolve the symlink chain.
83	case \$0 in
84	( */* )	linkdir=\${0%/*} ;;
85	( * )	linkdir=. ;;
86	esac
87	me=\$0
88	while test -L "\$me"; do
89	 	newme=\$(command ls -ld -- "\$me" && echo X)
90	 	case \$newme in
91	 	( *" \$me -> "*\${CCn}X ) ;;
92	 	( * )	echo "\$0: resolve symlink: 'ls -ld' failed" >&2
93	 		exit 128 ;;
94	 	esac
95	 	newme=\${newme#*" \$me -> "}
96	 	newme=\${newme%\${CCn}X}
97	 	case \$newme in
98	 	( /* )	me=\$newme ;;
99	 	( * )	me=\$linkdir/\$newme ;;
100	 	esac
101	 	linkdir=\${me%/*}
102	done
103	# ... Find my absolute and physical directory path.
104	case \$me in
105	( */* )	MSH_PREFIX=\${me%/*} ;;
106	( * )	MSH_PREFIX=. ;;
107	esac
108	case \$MSH_PREFIX in
109	( */* | [!+-]* | *[!0123456789]* )
110	 	MSH_PREFIX=\$(cd -P -- "\$PWD" && cd -- "\$MSH_PREFIX" && pwd -P && echo X) ;;
111	( * )	MSH_PREFIX=\$(cd -P -- "\$PWD" && cd "./\$MSH_PREFIX" && pwd -P && echo X) ;;
112	esac || exit
113	MSH_PREFIX="\${MSH_PREFIX%?X}"${installroot_q:+$installroot_q}
114
115	# Get the system's default path.
116	. "\$MSH_PREFIX/lib/modernish/aux/defpath.sh" || exit
117
118	$(if isset opt_s; then putln \
119		"# Verify preferred shell. Try this path first, then a shell by this name, then others." \
120		"MSH_SHELL=$msh_shell" \
121		". \"\$MSH_PREFIX/lib/modernish/aux/goodsh.sh\" || exit" \
122		"case \$MSH_SHELL in" \
123		"( */${msh_shell##*/} )	;;" \
124		"( * )	echo $2: \"warning: ${msh_shell##*/} shell not usable; running on \$MSH_SHELL\" >&2 ;;" \
125		"esac"
126	else putln \
127		"# Find a good shell." \
128		"unset -v MSH_SHELL" \
129		". \"\$MSH_PREFIX/lib/modernish/aux/goodsh.sh\" || exit"
130	fi)
131
132	# Prefix launch arguments.
133	$(
134		read -r hashbang < $script 1>&1 || die	# the 1>&1 stops ksh93 segfaulting by forcing the cmd subst to fork
135		if str ematch $hashbang "/env[[:blank:]]+modernish"; then
136			# Portable-form script
137			putln "set -- \"\$MSH_PREFIX/bin/modernish\" \"\$MSH_PREFIX\"/bin/$2 \"\$@\""
138		else
139			# Simple-form script
140			putln "set -- \"\$MSH_PREFIX\"/bin/$2 \"\$@\"" \
141				"PATH=\$MSH_PREFIX/bin:\$PATH	# make '. modernish' work"
142		fi
143	)
144
145	# Run bundled script.
146	export "_Msh_PREFIX=\$MSH_PREFIX" "_Msh_SHELL=\$MSH_SHELL" "_Msh_DEFPATH=\$DEFPATH"
147	unset -v MSH_PREFIX MSH_SHELL DEFPATH	# avoid exporting these
148	test -d "\${XDG_RUNTIME_DIR-}" && case \$XDG_RUNTIME_DIR in (/*) ;; (*) ! : ;; esac || unset -v XDG_RUNTIME_DIR
149	test -d "\${TMPDIR-}" && case \$TMPDIR in (/*) ;; (*) ! : ;; esac || unset -v TMPDIR
150	case \${_Msh_SHELL##*/} in
151	(zsh*)	# Invoke zsh as sh from the get-go. Switching to emulation from within a script would be inadequate: this won't
152	 	# remove common lowercase variable names as special -- e.g., "\$path" would still change "\$PATH" when used.
153	 	# The '--emulate sh' cmdline option won't do either, as helper scripts invoked like '\$MSH_SHELL -c ...' would
154	 	# find themselves in native zsh mode again. The only way is to use a 'sh' symlink for the duration of the script.
155	 	user_path=\$PATH
156	 	PATH=\${_Msh_DEFPATH}
157	 	unset -v zshdir
158	 	trap 'rm -rf "\${zshdir-}" &' 0	# BUG_TRAPEXIT compat
159	 	for sig in INT PIPE TERM; do
160	 		trap 'rm -rf "\${zshdir-}"; trap - '"\$sig"' 0; kill -s '"\$sig"' \$\$' "\$sig"
161	 	done
162	 	zshdir=\${XDG_RUNTIME_DIR:-\${TMPDIR:-/tmp}}/_Msh_zsh.\$\$.\$(date +%Y%m%d.%H%M%S).\${RANDOM:-0}
163	 	mkdir -m700 "\$zshdir" || exit
164	 	ln -s "\${_Msh_SHELL}" "\$zshdir/sh" || exit
165	 	_Msh_SHELL=\$zshdir/sh
166	 	PATH=\$user_path
167	 	"\${_Msh_SHELL}" "\$@"	# no 'exec', or the trap won't run
168	 	exit ;;
169	(bash*)	# Avoid inheriting exported functions.
170	 	exec "\${_Msh_SHELL}" -p "\$@" ;;
171	( * )	# Default: just run.
172	 	exec "\${_Msh_SHELL}" "\$@" ;;
173	esac
174	end_of_wrapper
175}
176
177# -------- main ---------
178
179# Prepare shellquoted relative path for insertion in wrapper script.
180not str empty $installroot && shellquote -P installroot_q=$installroot || unset -v installroot_q
181
182# Do "static linking" of all cap tests.
183link_cap_tests
184
185# Install bundled programs, generating a wrapper script for each.
186for script do
187	str begin $script '/' || script=$PWD/$script	# must use absolute path for install_file()
188	script_basename=${script##*/}
189	shellquote script_basename_q=$script_basename
190	install_file $script $opt_D$installroot/bin/$script_basename
191	install_wrapper_script $script_basename $script_basename_q
192done
193
194# Lastly, generate README.
195install_file - $opt_D$installroot/README.modernish <<-end_of_readme
196$(
197	{
198		put "This directory contains "
199		let "$# > 1" && put "the programs "
200		while let "$# > 2"; do
201			shellquote -f program=${1##*/}
202			put "$program, "
203			shift
204		done
205		if let "$# > 1"; then
206			shellquote -f program=${1##*/}
207			put "$program and "
208			shift
209		fi
210		shellquote -f program=${1##*/}
211		put "$program along with a stripped-down copy of modernish $MSH_VERSION, the portable shell" \
212			"programming library that takes the 'hell' out of shell! This way of bundling allows" \
213			"running modernish programs without installing the library system-wide.$CCn"
214	} | fold -s -w 80
215)
216
217This bundled version of modernish should be considered as similar to compiled
218object code. Interactive use is not supported, the documentation and the
219regression test suite are missing, and all the comments are stripped out.
220
221To get the source and try the complete version, head over to:
222https://github.com/modernish/modernish/tree/0.16#readme
223To get this exact version ($MSH_VERSION), look under 'Releases'.
224
225Modernish is Free software, available under the following licence.
226Note that this licence is for modernish itself, NOT the bundled program$(let "$# > 1" && put 's').
227
228----
229Licence for modernish $MSH_VERSION
230
231$(cat $MSH_PREFIX/LICENSE)
232end_of_readme
233
234# End. Return to install.sh.
235