openpkg/sea.sh

changeset 428
f880f219c566
child 446
85ef9b73028a
     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 +

mercurial