1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/openpkg/sea.sh Tue Jul 31 12:23:42 2012 +0200 1.3 @@ -0,0 +1,243 @@ 1.4 +## 1.5 +## sea -- Shell Execution Archive 1.6 +## Copyright (c) 2012 Ralf S. Engelschall <rse@engelschall.com> 1.7 +## 1.8 +## This program is free software; you can redistribute it and/or modify 1.9 +## it under the terms of the GNU General Public License as published by 1.10 +## the Free Software Foundation; either version 2 of the License, or 1.11 +## (at your option) any later version. 1.12 +## 1.13 +## This program is distributed in the hope that it will be useful, 1.14 +## but WITHOUT ANY WARRANTY; without even the implied warranty of 1.15 +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1.16 +## General Public License for more details. 1.17 +## 1.18 +## You should have received a copy of the GNU General Public License 1.19 +## along with this program; if not, write to the Free Software 1.20 +## Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, 1.21 +## USA, or contact Ralf S. Engelschall <rse@engelschall.com>. 1.22 +## 1.23 +## NOTICE: Given that you include this file verbatim into your own 1.24 +## source tree, you are justified in saying that it remains separate 1.25 +## from your package, and that this way you are simply just using GNU 1.26 +## shtool. So, in this situation, there is no requirement that your 1.27 +## package itself is licensed under the GNU General Public License in 1.28 +## order to take advantage of GNU shtool. 1.29 +## 1.30 + 1.31 +## 1.32 +## COMMAND LINE PARSING 1.33 +## 1.34 + 1.35 +str_usage="[-h|--help] [-o|--output <file>] <script> [<file-or-dir> ...]" 1.36 +arg_spec="1+" 1.37 +opt_spec="h.o:" 1.38 +opt_alias="h:help,o:output" 1.39 +opt_h=no 1.40 +opt_o="" 1.41 + 1.42 +# parse argument specification string 1.43 +eval `echo $arg_spec |\ 1.44 + sed -e 's/^\([0-9]*\)\([+=]\)/arg_NUMS=\1; arg_MODE=\2/'` 1.45 + 1.46 +# parse option specification string 1.47 +eval `echo $opt_spec |\ 1.48 + sed -e 's/\([a-zA-Z0-9]\)\([.:+]\)/opt_MODE_\1=\2;/g'` 1.49 + 1.50 +# parse option alias string 1.51 +eval `echo $opt_alias |\ 1.52 + sed -e 's/-/_/g' -e 's/\([a-zA-Z0-9]\):\([^,]*\),*/opt_ALIAS_\2=\1;/g'` 1.53 + 1.54 +# interate over argument line 1.55 +opt_PREV='' 1.56 +while [ $# -gt 0 ]; do 1.57 + # special option stops processing 1.58 + if [ ".$1" = ".--" ]; then 1.59 + shift 1.60 + break 1.61 + fi 1.62 + 1.63 + # determine option and argument 1.64 + opt_ARG_OK=no 1.65 + if [ ".$opt_PREV" != . ]; then 1.66 + # merge previous seen option with argument 1.67 + opt_OPT="$opt_PREV" 1.68 + opt_ARG="$1" 1.69 + opt_ARG_OK=yes 1.70 + opt_PREV='' 1.71 + else 1.72 + # split argument into option and argument 1.73 + case "$1" in 1.74 + --[a-zA-Z0-9]*=*) 1.75 + eval `echo "x$1" |\ 1.76 + sed -e 's/^x--\([a-zA-Z0-9-]*\)=\(.*\)$/opt_OPT="\1";opt_ARG="\2"/'` 1.77 + opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'` 1.78 + eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}" 1.79 + ;; 1.80 + --[a-zA-Z0-9]*) 1.81 + opt_OPT=`echo "x$1" | cut -c4-` 1.82 + opt_STR=`echo $opt_OPT | sed -e 's/-/_/g'` 1.83 + eval "opt_OPT=\${opt_ALIAS_${opt_STR}-${opt_OPT}}" 1.84 + opt_ARG='' 1.85 + ;; 1.86 + -[a-zA-Z0-9]*) 1.87 + eval `echo "x$1" |\ 1.88 + sed -e 's/^x-\([a-zA-Z0-9]\)/opt_OPT="\1";/' \ 1.89 + -e 's/";\(.*\)$/"; opt_ARG="\1"/'` 1.90 + ;; 1.91 + -[a-zA-Z0-9]) 1.92 + opt_OPT=`echo "x$1" | cut -c3-` 1.93 + opt_ARG='' 1.94 + ;; 1.95 + *) 1.96 + break 1.97 + ;; 1.98 + esac 1.99 + fi 1.100 + 1.101 + # eat up option 1.102 + shift 1.103 + 1.104 + # determine whether option needs an argument 1.105 + eval "opt_MODE=\$opt_MODE_${opt_OPT}" 1.106 + if [ ".$opt_ARG" = . ] && [ ".$opt_ARG_OK" != .yes ]; then 1.107 + if [ ".$opt_MODE" = ".:" ] || [ ".$opt_MODE" = ".+" ]; then 1.108 + opt_PREV="$opt_OPT" 1.109 + continue 1.110 + fi 1.111 + fi 1.112 + 1.113 + # process option 1.114 + case $opt_MODE in 1.115 + '.' ) 1.116 + # boolean option 1.117 + eval "opt_${opt_OPT}=yes" 1.118 + ;; 1.119 + ':' ) 1.120 + # option with argument (multiple occurances override) 1.121 + eval "opt_${opt_OPT}=\"\$opt_ARG\"" 1.122 + ;; 1.123 + '+' ) 1.124 + # option with argument (multiple occurances append) 1.125 + eval "opt_${opt_OPT}=\"\$opt_${opt_OPT} \$opt_ARG\"" 1.126 + ;; 1.127 + * ) 1.128 + echo "$0: ERROR: unknown option: \`$opt_OPT'" 1>&2 1.129 + exit 1 1.130 + ;; 1.131 + esac 1.132 +done 1.133 +if [ ".$opt_PREV" != . ]; then 1.134 + echo "$0: ERROR: missing argument to option \`$opt_PREV'" 1>&2 1.135 + exit 1 1.136 +fi 1.137 + 1.138 +# process help option 1.139 +if [ ".$opt_h" = .yes ]; then 1.140 + echo "Usage: $0 $str_usage" 1.141 + exit 0 1.142 +fi 1.143 + 1.144 +# complain about incorrect number of arguments 1.145 +case $arg_MODE in 1.146 + '=' ) 1.147 + if [ $# -ne $arg_NUMS ]; then 1.148 + echo "$0: ERROR: invalid number of arguments (exactly $arg_NUMS expected)" 1>&2 1.149 + exit 1 1.150 + fi 1.151 + ;; 1.152 + '+' ) 1.153 + if [ $# -lt $arg_NUMS ]; then 1.154 + echo "$0: ERROR: invalid number of arguments (at least $arg_NUMS expected)" 1>&2 1.155 + exit 1 1.156 + fi 1.157 + ;; 1.158 +esac 1.159 + 1.160 +## 1.161 +## MAIN 1.162 +## 1.163 + 1.164 +# we required at least the control script 1.165 +script="$1" 1.166 +shift 1.167 + 1.168 +# determine output file 1.169 +sea="$opt_o" 1.170 +if [ ".$sea" = . ]; then 1.171 + sea=`echo "$script" | sed -e 's;\.[^.][^.]*$;;' -e 's;$;.sea;'` 1.172 +fi 1.173 + 1.174 +# wrap into a self-extracting distribution file 1.175 +tmpdir="${TMPDIR-/tmp}" 1.176 +tmpfile="$tmpdir/sea.tmp.$$" 1.177 +rm -f $tmpfile 1.178 +set -o noclobber 1.179 +( sed <$0 \ 1.180 + -e '1,/^____/d' \ 1.181 + -e "s;@script@;$script;g" 1.182 + echo . | awk '{ 1.183 + for (i = 0; i < 2048/8; i++) { 1.184 + printf(" "); 1.185 + } 1.186 + }' 1.187 +) >$tmpfile 1.188 +dd bs=2048 count=1 if=$tmpfile of=$sea 2>/dev/null 1.189 +rm -f $tmpfile 1.190 +tar cf - "$script" "$@" 2>/dev/null >>$sea 1.191 + 1.192 +# graceful termination 1.193 +# (before the shell discovers that we carry the wrapper with us below) 1.194 +exit 0 1.195 + 1.196 +## 1.197 +## WRAPPER SCRIPT 1.198 +## 1.199 + 1.200 +______________________________________________________________________________ 1.201 +#!/bin/sh 1.202 +#![OpenPKG] 1.203 +## 1.204 +## THIS IS AN AUTO-GENERATED SHELL-WRAPPER ARCHIVE 1.205 +## 1.206 + 1.207 +# establish sane environment 1.208 +PATH="$PATH:/bin:/sbin:/usr/bin:/usr/sbin" 1.209 +LC_CTYPE=C 1.210 +export LC_CTYPE 1.211 +umask 022 1.212 + 1.213 +# pass-through 1.214 +if [ $# -eq 1 -a ".$1" = ".--tar" ]; then 1.215 + # pass-through attached payload on stdout 1.216 + dd if="$0" bs=2048 skip=1 2>/dev/null 1.217 + rc=$? 1.218 +else 1.219 + # extract attached payload 1.220 + rm -rf "$0.d" >/dev/null 2>&1 1.221 + mkdir "$0.d" || exit $? 1.222 + dd if="$0" bs=2048 skip=1 2>/dev/null | \ 1.223 + (cd "$0.d" && tar xf - 2>/dev/null) 1.224 + if [ ! -f "$0.d/@script@" ]; then 1.225 + echo "$0: ERROR: failed to unpack attached payload into directory \"$0.d\"" 1>&2 1.226 + rm -rf "$0.d" >/dev/null 2>&1 || true 1.227 + exit 1 1.228 + fi 1.229 + 1.230 + # pass-through execution to control script 1.231 + (cd "$0.d" && exec sh "./@script@" ${1+"$@"}) 1.232 + rc=$? 1.233 + 1.234 + # cleanup 1.235 + rm -rf "$0.d" >/dev/null 2>&1 || true 1.236 +fi 1.237 + 1.238 +# terminate gracefully 1.239 +# (before the shell discovers that we carry MBs of raw data with us below) 1.240 +exit $rc 1.241 + 1.242 +# the payload tarball is appended in raw format directly to the end 1.243 +# of this script, just leaded by padding whitespaces which make sure 1.244 +# that the tarball data starts at the pre-defined offset of 2KB. This 1.245 +# allows us to unpack the tarball by just skipping the leading 2KB. 1.246 +