openpkg/sea.sh

Mon, 28 Jan 2013 17:37:18 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Mon, 28 Jan 2013 17:37:18 +0100
changeset 758
a2c6460cfb16
parent 428
f880f219c566
permissions
-rw-r--r--

Correct socket error reporting improvement with IPv6 portable code,
after helpful recommendation by Saúl Ibarra Corretgé on OSips devlist.

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

mercurial