Mon, 28 Jan 2013 17:37:18 +0100
Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.
1 ##
2 ## sea -- Shell Execution Archive
3 ## Copyright (c) 2012 Ralf S. Engelschall <rse@engelschall.com>
4 ##
5 ## This program is free software; you can redistribute it and/or modify
6 ## it under the terms of the GNU General Public License as published by
7 ## the Free Software Foundation; either version 2 of the License, or
8 ## (at your option) any later version.
9 ##
10 ## This program is distributed in the hope that it will be useful,
11 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
12 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 ## General Public License for more details.
14 ##
15 ## You should have received a copy of the GNU General Public License
16 ## along with this program; if not, write to the Free Software
17 ## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
18 ## USA, or contact Ralf S. Engelschall <rse@engelschall.com>.
19 ##
20 ## NOTICE: Given that you include this file verbatim into your own
21 ## source tree, you are justified in saying that it remains separate
22 ## from your package, and that this way you are simply just using GNU
23 ## shtool. So, in this situation, there is no requirement that your
24 ## package itself is licensed under the GNU General Public License in
25 ## order to take advantage of GNU shtool.
26 ##
28 ##
29 ## COMMAND LINE PARSING
30 ##
32 str_usage="[-h|--help] [-o|--output <file>] <script> [<file-or-dir> ...]"
33 arg_spec="1+"
34 opt_spec="h.o:"
35 opt_alias="h:help,o:output"
36 opt_h=no
37 opt_o=""
39 # parse argument specification string
40 eval `echo $arg_spec |\
41 sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'`
43 # parse option specification string
44 eval `echo $opt_spec |\
45 sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'`
47 # parse option alias string
48 eval `echo $opt_alias |\
49 sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'`
51 # interate over argument line
52 opt_PREV=''
53 while [ $# -gt 0 ]; do
54 # special option stops processing
55 if [ ".$1" = ".--" ]; then
56 shift
57 break
58 fi
60 # determine option and argument
61 opt_ARG_OK=no
62 if [ ".$opt_PREV" != . ]; then
63 # merge previous seen option with argument
64 opt_OPT="$opt_PREV"
65 opt_ARG="$1"
66 opt_ARG_OK=yes
67 opt_PREV=''
68 else
69 # split argument into option and argument
70 case "$1" in
71 --[a-zA-Z0-9]*=*)
72 eval `echo "x$1" |\
73 sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'`
74 opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
75 eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
76 ;;
77 --[a-zA-Z0-9]*)
78 opt_OPT=`echo "x$1" | cut -c4-`
79 opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'`
80 eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}"
81 opt_ARG=''
82 ;;
83 -[a-zA-Z0-9]*)
84 eval `echo "x$1" |\
85 sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \
86 -e 's/";\(.*\)$/"; opt_ARG="\1"/'`
87 ;;
88 -[a-zA-Z0-9])
89 opt_OPT=`echo "x$1" | cut -c3-`
90 opt_ARG=''
91 ;;
92 *)
93 break
94 ;;
95 esac
96 fi
98 # eat up option
99 shift
101 # determine whether option needs an argument
102 eval "opt_MODE=\$opt_MODE_${opt_OPT}"
103 if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then
104 if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then
105 opt_PREV="$opt_OPT"
106 continue
107 fi
108 fi
110 # process option
111 case $opt_MODE in
112 '.' )
113 # boolean option
114 eval "opt_${opt_OPT}=yes"
115 ;;
116 ':' )
117 # option with argument (multiple occurances override)
118 eval "opt_${opt_OPT}=\"\$opt_ARG\""
119 ;;
120 '+' )
121 # option with argument (multiple occurances append)
122 eval "opt_${opt_OPT}=\"\$opt_${opt_OPT} \$opt_ARG\""
123 ;;
124 * )
125 echo "$0: ERROR: unknown option: \`$opt_OPT'" 1>&2
126 exit 1
127 ;;
128 esac
129 done
130 if [ ".$opt_PREV" != . ]; then
131 echo "$0: ERROR: missing argument to option \`$opt_PREV'" 1>&2
132 exit 1
133 fi
135 # process help option
136 if [ ".$opt_h" = .yes ]; then
137 echo "Usage: $0 $str_usage"
138 exit 0
139 fi
141 # complain about incorrect number of arguments
142 case $arg_MODE in
143 '=' )
144 if [ $# -ne $arg_NUMS ]; then
145 echo "$0: ERROR: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2
146 exit 1
147 fi
148 ;;
149 '+' )
150 if [ $# -lt $arg_NUMS ]; then
151 echo "$0: ERROR: invalid number of arguments (at least $arg_NUMS expected)" 1>&2
152 exit 1
153 fi
154 ;;
155 esac
157 ##
158 ## MAIN
159 ##
161 # we required at least the control script
162 script="$1"
163 shift
165 # determine output file
166 sea="$opt_o"
167 if [ ".$sea" = . ]; then
168 sea=`echo "$script" | sed -e 's;\.[^.][^.]*$;;' -e 's;$;.sea;'`
169 fi
171 # wrap into a self-extracting distribution file
172 tmpdir="${TMPDIR-/tmp}"
173 tmpfile="$tmpdir/sea.tmp.$$"
174 rm -f $tmpfile
175 set -o noclobber
176 ( sed <$0 \
177 -e '1,/^____/d' \
178 -e "s;@script@;$script;g"
179 echo . | awk '{
180 for (i = 0; i < 2048/8; i++) {
181 printf(" ");
182 }
183 }'
184 ) >$tmpfile
185 dd bs=2048 count=1 if=$tmpfile of=$sea 2>/dev/null
186 rm -f $tmpfile
187 tar cf - "$script" "$@" 2>/dev/null >>$sea
189 # graceful termination
190 # (before the shell discovers that we carry the wrapper with us below)
191 exit 0
193 ##
194 ## WRAPPER SCRIPT
195 ##
197 ______________________________________________________________________________
198 #!/bin/sh
199 #![OpenPKG]
200 ##
201 ## THIS IS AN AUTOGENERATED SHELL WRAPPER ARCHIVE
202 ##
204 # establish sane environment
205 PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin"
206 LC_CTYPE=C
207 export LC_CTYPE
208 umask 022
210 # passthrough
211 if [ $# -eq 1 -a ".$1" = ".--tar" ]; then
212 # passthrough attached payload on stdout
213 dd if="$0" bs=2048 skip=1 2>/dev/null
214 rc=$?
215 else
216 # extract attached payload
217 rm -rf "$0.d" >/dev/null 2>&1
218 mkdir "$0.d" || exit $?
219 dd if="$0" bs=2048 skip=1 2>/dev/null | \
220 (cd "$0.d" && tar xf - 2>/dev/null)
221 if [ ! -f "$0.d/@script@" ]; then
222 echo "$0: ERROR: failed to unpack attached payload into directory \"$0.d\"" 1>&2
223 rm -rf "$0.d" >/dev/null 2>&1 || true
224 exit 1
225 fi
227 # passthrough execution to control script
228 (cd "$0.d" && exec sh "./@script@" ${1+"$@"})
229 rc=$?
231 # cleanup
232 rm -rf "$0.d" >/dev/null 2>&1 || true
233 fi
235 # terminate gracefully
236 # (before the shell discovers that we carry MBs of raw data with us below)
237 exit $rc
239 # the payload tarball is appended in raw format directly to the end
240 # of this script, just leaded by padding whitespaces which make sure
241 # that the tarball data starts at the predefined offset of 2KB. This
242 # allows us to unpack the tarball by just skipping the leading 2KB.