aboutsummaryrefslogtreecommitdiff
path: root/scripts/pkg-0.7.0
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/pkg-0.7.0')
-rwxr-xr-xscripts/pkg-0.7.01928
1 files changed, 1928 insertions, 0 deletions
diff --git a/scripts/pkg-0.7.0 b/scripts/pkg-0.7.0
new file mode 100755
index 0000000..889a034
--- /dev/null
+++ b/scripts/pkg-0.7.0
@@ -0,0 +1,1928 @@
+#!/bin/bash
+
+# pkg - Formilux package builder - version 0.7.0 - 2005-10-04
+#
+# Copyright (C) 2001-2005 Benoit Dolez & Willy Tarreau
+# mailto: benoit@ant-computing.com,willy@ant-computing.com
+#
+# This program is licenced under GPLv2 ( http://www.gnu.org/licenses/gpl.txt )
+
+######## Please update this version ########
+PKG_VERSION=0.7.0
+############################################
+
+## WARNING ##
+# This version is not compatible with pkg scripts written for pre-0.2.0 versions
+
+# Usage:
+# pkg <action> [ pkg [ pkg2 ] ]
+#
+# pkg newpkg [ new_pkg [ old_pkg ] ]
+# [new_pkg]=[old_pkg]
+# ex: pkg newpkg openssl-0.9.6g-flx0.1 openssl-0.9.6d-flx0.1
+# pkg newpkg apache apache-1.3
+# pkg newpkg bash
+# pkg newpkg gcc gcc-3*flx*.1
+#
+# pkg setpkg [ new_pkg ]
+# ex: pkg setpkg openssl-0.9.6g-flx0.1
+#
+# pkg { info | cat | edit | unpack } [ pkg ]
+# ex: pkg info
+# pkg info bash
+# pkg edit modutils-2.4
+# pkg cat gzip-1.3
+#
+# pkg { compile,build,prepack,strip,pack,delpack,release,clean }*
+#
+# pkg { patch | unpatch } [ patch_name ]
+#
+# pkg { any_command } [ any_args ]
+#
+
+# don't return stupid names, and we also want dotfiles and use extended globbing
+shopt -s nullglob
+shopt -s dotglob
+shopt -s extglob
+
+# disable pathnames expansion
+set -o noglob
+
+# change the default mask to avoid common security problems
+umask og-w
+
+# set some constants
+KERNDIR=${KERNDIR:-/usr/src/linux}
+FLXHOSTOS=${FLXHOSTOS:-$(uname -s|tr 'A-Z' 'a-z')}
+FLXHOSTARCH=${FLXHOSTARCH:-$(uname -m)}
+FLXHOST=${FLXHOST:-$FLXHOSTARCH-$FLXHOSTOS}
+
+# FLXTARGARCH can be influenced by FLXARCH if defined
+FLXTARGOS=${FLXTARGOS:-$FLXHOSTOS}
+FLXTARGARCH=${FLXTARGARCH:-$FLXARCH}
+FLXTARGARCH=${FLXTARGARCH:-$FLXHOSTARCH}
+FLXTARG=${FLXTARG:-$FLXTARGARCH-$FLXTARGOS}
+FLXARCH=${FLXARCH:-$FLXTARGARCH}
+
+DEVROOT=${DEVROOT:-/var/flx-dev}
+PKGROOT=${PKGROOT:-/var/flx-pkg}
+# use -p1 by default to apply a patch
+PATCH_LEVEL=${PATCH_LEVEL:-1}
+# the suffix that we use to name different builds. It also matches build
+# versions with this name followed by a number (BUILDVER)
+BUILDSFX=${BUILDSFX:-flx}
+BUILDVER=${BUILDVER:-0}
+
+PKGSUFF="tgz"
+CFGSUFF="cfg"
+INSTNAME=".flxdisk"
+LINKNAME=".flxpkg"
+
+FIND_CMD=pkgfilefind
+CURDIR="$(pwd)"
+
+FILE_LIST=
+
+# all the directories that should be ignored by do_pack
+EXCLUDE_LIST=( bin boot dev etc etc/opt home lib lib/modules mnt mnt/disk mnt/cdrom mnt/usb mnt/nfs mnt/floppy opt opt/bin opt/lib opt/sbin proc root root/bin sbin sbin/init.d usr usr/bin usr/lib usr/sbin usr/share usr/share/examples var var/tmp var/run var/cache var/empty var/lib var/log var/spool var/adm )
+
+######
+###### here are some undertermined type functions
+######
+
+# check that this utility's version is at least as high as the version
+# specified in $1. Returns 0 if OK, 1 if inferior.
+
+function check_pkg_version {
+ local version="$1"
+ local major minor patch
+ local mymajor myminor mypatch
+
+ major=${version%%.*}
+ minor=${version#$major.}; minor=${minor%%.*}
+ patch=${version##*.}
+
+ mymajor=${PKG_VERSION%%.*}
+ myminor=${PKG_VERSION#$mymajor.}; myminor=${myminor%%.*}
+ mypatch=${PKG_VERSION##*.}
+
+ if [ -n "$major" ]; then
+ [ "$mymajor" -gt "$major" ] && return 0
+ [ "$mymajor" -lt "$major" ] && return 1
+ else
+ return 0
+ fi
+
+ if [ -n "$minor" ]; then
+ [ "$myminor" -gt "$minor" ] && return 0
+ [ "$myminor" -lt "$minor" ] && return 1
+ else
+ return 0
+ fi
+
+ if [ -n "$patch" ]; then
+ [ "$mypatch" -gt "$patch" ] && return 0
+ [ "$mypatch" -lt "$patch" ] && return 1
+ else
+ return 0
+ fi
+ return 0
+}
+
+
+# find packageable files (that can't be automaticaly created) and return only
+# their relative path to the argument.
+
+function pkgfilefind {
+ local start=${1%%/}
+ local dir
+ local -a exclude_args=( )
+
+ for dir in "${EXCLUDE_LIST[@]}"; do
+ exclude_args=( "${exclude_args[@]}" -and -not -path "${start}/${dir}" )
+ done
+
+ find ${start} -not -path ${start} \( -empty -o \! -type d -o \! -uid 0 -o \! -gid 0 -o \! -perm 0755 \) "${exclude_args[@]}" -printf "%P\n"
+}
+
+
+# resolves a symlink to an absolute location.
+# usage: resolve_link <link_dir> <link_pointer>
+function resolve_link {
+ # prints $1 if $2 is empty, and prints $2 if it starts with a '/'.
+ if [ -z "$2" ]; then
+ dir="$1"
+ elif [ -z "${2##/*}" ]; then
+ dir="$2"
+ else
+ dir="$1/$2"
+ fi
+
+ # resolve '//', '/./', '/.$', '^./' always one at a time, from left to right,
+ # then enclose with '/'
+ while [ -n "$dir" ]; do
+ if [ -z "${dir##./*}" ]; then dir="${dir#./}"
+ elif [ -z "${dir##/*}" ]; then dir="${dir#/}"
+ elif [ -z "${dir%%*/.}" ]; then dir="${dir%/.}"
+ elif [ -z "${dir%%*/}" ]; then dir="${dir%/}"
+ elif [ -z "${dir##*//*}" ]; then dir="${dir/\/\//\/}"
+ elif [ -z "${dir##*/./*}" ]; then dir="${dir/\/.\//\/}"
+ else
+ dir="/$dir/"
+ break;
+ fi
+ done
+
+ # now resolve '/../' from left to right only.
+ while [ -z "${dir##*/../*}" ]; do
+ # if dir goes past root, we must truncate it
+ if [ -z "${dir##/../*}" ]; then
+ dir="/${dir##/../}"
+ else
+ # turn all '/x/../' into '/'
+ odir="$dir"
+ dir="$(echo "$dir" | sed -e 's,/[^/]*/\.\./,/,')"
+ [ "$dir" = "$odir" ] && break
+ fi
+ done
+
+ [ "$dir" = "/" ] || dir="${dir#/}"
+ [ "$dir" = "/" ] || dir="${dir%/}"
+ echo "$dir"
+}
+
+# this function analyses an ELF executable and prints its name along with some
+# informations such as :
+# %N:soname : for libraries, their soname
+# %D:libname : library it depends on (their soname)
+# %P:provide : feature provided by a library, in the form soname/version
+# %R:require : required feature, in the for soname/version
+function elf_get_dep {
+ local elf
+ for elf in "$@"; do
+ $OBJDUMP -p "$elf" | (
+ soname_str=""
+ soname=""
+ needed=""
+ provide=""
+ require=""
+ curreq=""
+ section=""
+ while read; do
+ case "$REPLY" in
+ Dynamic\ Section*)
+ section="dynamic" ;;
+ Version\ defin*)
+ section="definitions" ;;
+ Version\ Refer*)
+ section="references" ;;
+ *)
+ set -- $REPLY
+ if [ "$section" = "dynamic" ]; then
+ if [ "$1" = "NEEDED" ]; then
+ needed="${needed:+$needed }%D:$2"
+ elif [ "$1" = "SONAME" ]; then
+ soname="$2"
+ soname_str="${soname_str:+$soname_str }%N:$2"
+ fi
+ elif [ "$section" = "definitions" ]; then
+ if [ "$#" = "4" -a "$2" = "0x00" ]; then
+ provide="${provide:+$provide }%P:$soname/$4"
+ fi
+ elif [ "$section" = "references" ]; then
+ if [ "$#" = "3" -a "$1" = "required" ]; then
+ curreq="${3%:}"
+ elif [ "$#" = "4" ]; then
+ require="${require:+$require }%R:$curreq/$4"
+ fi
+ fi
+ ;;
+ esac
+ done
+ echo "${elf:+$elf }${soname_str:+$soname_str }${needed:+$needed }${provide:+$provide }${require}"
+ )
+ done
+ return 0
+}
+
+
+######
+###### here are some functions for manipulating package names
+######
+
+# returns the radix from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns 'pkg'
+function get_pkg_radix {
+ echo ${1%%[-_][0-9]*}
+}
+
+# returns the version from a package name. Eg: 'pkg-1.2.3a-flx0.12' returns '1.2.3a'
+function get_pkg_ver {
+ local ver=${1#${1%%[_-][0-9]*}[._-]}
+ ver=${ver%-${BUILDSFX}*}
+ [ "$ver" = "$1" ] || echo $ver
+}
+
+# returns the build number from a package name when appropriate, or empty when
+# there's nothing. Eg: 'pkg-1.2.3a-flx0.12-pkg' returns 'flx0.12'
+function get_build_num {
+ local build=${1##${1%%-${BUILDSFX}*([0-9]).+([0-9])*}} # -flx0.12-pkg
+ build=${build%%${build##-${BUILDSFX}*([0-9]).+([0-9])}} # -flx0.12
+ build=${build#-} # flx0.12
+ [ "$build" != "$1" ] && echo $build
+}
+
+# returns the build number following a known build. Eg: 'flx0.12' returns 'flx0.13'
+function get_next_build {
+ local prefix=${1%%.*}
+ local suffix=${1##*.}
+ echo $prefix.$[$suffix + 1]
+}
+
+# This function accepts a list of versionned names, and returns them sorted by
+# version number. The names must NOT contain any '|' or '~' character, or they
+# will be discarded. Names that don't have any version are also discarded.
+# Note: package names can be full path names.
+function sortnames {
+ local IFS FIELD NUMERIC_VERSION ALPHA_VERSION VERSION
+ local base version rest filename i t file flist
+ local -a list
+
+ # a numeric versions consists in a series of numbers delimited by dots, and
+ # optionnally ending with one or several dots, so that strange namings are
+ # correctly processed. An alphanumeric version consists in everything that
+ # cannot match a numeric version, optionnaly ending with one or more dots.
+ IFS=$'\n'
+ FIELD='\([^|]*\)'
+ NUMERIC_VERSION='\([0-9]\+\(\.[0-9]\+[.]*\)*\)'
+ ALPHA_VERSION='\([^0-9~|.]\+[.]*\)'
+ VERSION="\($NUMERIC_VERSION\|$ALPHA_VERSION\)"
+
+ # make the list appear in the form 'package|version|rest|full_name'
+ list=($(echo "$*" | grep -v "|~" | sed -e "s,$VERSION,\1|," \
+ -e "s,^$FIELD|$VERSION,\1|\2|," \
+ -e "s,^$FIELD|$FIELD|$FIELD$,\1|\2|\3~\1\2\3," \
+ -e "s,^[^|]*|[^|]*$,," \
+ -e 's,^[^|]*/,,'))
+
+ # there's a risk that it doesn't complete for all the list, and that some
+ # elements keep a "rest". But what can we do about it ?
+
+ # we loop on the list if there's at least one element
+ # this will build alternating series of numeric-only and non-numeric
+ # substrings, packed by six.
+ while [ "${list[0]}" ] ; do
+ # now we add sub-version delimiters ','
+ list=( $(for file in ${list[*]} ; do
+ IFS="|~" ; set -- $file
+ base=$1 ; version=$2 ; rest=$3 ; filename=$4
+ if [ -z "$rest" ] ; then
+ IFS="." ; set -- $version
+ # we append a dot to the version for sed below.
+ echo "$base,$1,$2,$3,$4,$5,$6|.~$filename"
+ continue
+ fi
+ IFS="." ; set -- $version
+ echo "$base,$1,$2,$3,$4,$5,$6|$rest~$filename"
+ done | sed -e "s/^$FIELD|\($VERSION\|\.\)/\1|\2|/"))
+ IFS=$'\n'
+ # and we stop once everyone has "|\.|~" (no rest)
+ if echo "${list[*]}" | grep -vq "|\.|~" ; then : ; else break ; fi
+ done
+
+ # now construct a field separator list for 'sort'. Since it's full of bugs,
+ # the only way for it to work is -k1,1 -k2,2n -k3,3n ...
+ # To match most cases, we'll assume that most of our packages will be
+ # numbered NNNNNNAAAAAANNN... (6 numbers, 6 alpha, repeating).
+ IFS=',' ; i=1 ; flist=
+ for t in ${list[0]%%|*} ; do
+ if [ $i -eq 1 -o $[(($i-2)/6)&1] -eq 1 ]; then
+ flist="$flist${flist:+ }-k$i,$i"
+ else
+ flist="$flist${flist:+ }-k$i,$i"n
+ fi
+ i=$[$i+1];
+ done
+
+ IFS=$'\n'$'\t'' '
+ # Do not use '-u' since sort is stupid enough to remove nearly identical
+ # lines !
+ #echo "${list[*]}" | sort -t , -u $flist | cut -f2 -d~
+ echo "${list[*]}" | sort -t , $flist | cut -f2 -d~
+}
+
+
+######
+###### here are some "exported" functions used to ease file manipulation
+######
+
+#
+# usage: set_perm uid:gid mode file...
+function set_perm {
+ local own mode
+ [ $# -gt 2 ] || return 1
+ own=$1 ; shift
+ mode=$1 ; shift
+ chown $own "$@"
+ chmod $mode "$@"
+ return 0
+}
+
+#
+# usage: set_default_perm $ROOTDIR/start_dir
+function set_default_perm {
+ local start_dir=$1
+ local strip_dir=${ROOTDIR%%/}
+ local type executable script
+
+ if [ -z "$1" ]; then
+ echo; echo "### ERROR! set_default_perm called without arguments !!!"
+ echo "### You must specify the root directory to fix."
+ return 1
+ fi
+
+ echo
+ echo "PKG : Fixing permissions in $1 ... "
+ echo " Please wait..."
+ echo " Fixing directories..."
+
+ # first pass : check directories
+ find $start_dir -type d | while read; do
+ case "${REPLY##$strip_dir}" in
+ /|/.)
+ set_perm root:root 755 "$REPLY"
+ ;;
+ /sbin|/sbin/init.d|/usr/sbin)
+ set_perm root:adm 751 "$REPLY"
+ ;;
+ /root)
+ set_perm root:root 700 "$REPLY"
+ ;;
+ /etc/formilux|/var/core)
+ set_perm root:adm 750 "$REPLY"
+ ;;
+ *)
+ if [ ! -u "$REPLY" -a ! -g "$REPLY" -a ! -k "$REPLY" ]; then
+ set_perm root:root 755 "$REPLY"
+ fi
+ ;;
+ esac
+ done
+
+ echo " Fixing special files..."
+ # second pass : check special files (block, char, fifo)
+ find $start_dir -not -xtype d -a -not -xtype f | while read; do
+ if [ -b "$REPLY" -o -c "$REPLY" -o -p "$REPLY" ]; then
+ set_perm root:root 600 "$REPLY"
+ fi
+ done
+
+ echo " Fixing regular files..."
+ # third pass : check regular files
+ find $start_dir -type f | while read; do
+ if [ -u "$REPLY" -o -g "$REPLY" ]; then
+ # remove other r/w on setuid/setgid
+ chmod o-rw "$REPLY"
+ else
+ type=$(file -z "$REPLY")
+ executable=0
+ script=0
+
+ if [ -z "${type//*ELF [0-9][0-9]-bit */}" -o \
+ -z "${type//*ERROR: Corrupt*/}" ]; then
+ executable=1
+ elif [ -z "${type//*script*/}" ]; then
+ script=1
+ fi
+
+ #echo "processing ${REPLY##$strip_dir}"
+ case "${REPLY##$strip_dir}" in
+ /bin/*|/usr/bin/*|/opt/bin/*|/opt/*/bin/*|/sbin/init.d/*)
+ if [ $executable -gt 0 ]; then
+ set_perm root:adm ug-w,o-rw "$REPLY"
+ elif [ $script -gt 0 ]; then
+ set_perm root:adm ugo-w "$REPLY"
+ else
+ set_perm root:adm ugo-w "$REPLY"
+ fi
+ ;;
+ /sbin/*|/usr/sbin/*|/opt/sbin/*|/opt/*/sbin/*)
+ if [ $executable -gt 0 ]; then
+ set_perm root:adm u-sw,g-wx,o-rwx "$REPLY"
+ elif [ $script -gt 0 ]; then
+ set_perm root:adm u-sw,g-swx,o-rwx "$REPLY"
+ else
+ # neither an exec nor a script, no need to execute it !
+ set_perm root:adm ug-swx,o-wx "$REPLY"
+ fi
+ ;;
+ /lib/*.so|/lib/*.so.*|/usr/lib/*.so|/usr/lib/*.so.*|\
+ /opt/lib/*.so|/opt/lib/*.so.*|/opt/*/lib/*.so|/opt/*/lib/*.so.*)
+ set_perm root:adm ug-sw,o-w,+x "$REPLY"
+ ;;
+ /lib/*.[ao]|/usr/lib/*.[ao]|/opt/lib/*.[ao]|/opt/*/lib/*.[ao])
+ set_perm root:adm ugo-swx "$REPLY"
+ ;;
+ /etc/profile.d/*.var)
+ set_perm root:adm 0644 "$REPLY"
+ ;;
+ /etc/profile.d/*)
+ set_perm root:adm 0755 "$REPLY"
+ ;;
+ /boot/*/*|/boot/*|/etc/*/*)
+ set_perm root:adm ug-swx,o-rwx "$REPLY"
+ ;;
+ /etc/*)
+ set_perm root:adm ugo-swx "$REPLY"
+ ;;
+ /*/man/*)
+ set_perm root:man ugo-swx "$REPLY"
+ ;;
+ /usr/doc/*|/usr/share/*/doc/*|/usr/info/*|/usr/share/*/info/*)
+ set_perm root:man ugo-swx "$REPLY"
+ ;;
+ /usr/share/examples/*|/usr/share/examples/*/*)
+ set_perm root:man ugo-swx "$REPLY"
+ ;;
+ *)
+ # chgrp adm if not setgid and group==root
+ # chmod ugo-w if user==root
+ ;;
+ esac
+ fi
+ done
+ echo "PKG : done fixing permissions."
+}
+
+######
+###### here are "exported" functions, which can be used and redefined by build.cfg
+######
+
+# builds everything from a clean start
+function do_build {
+ local ACTION
+ # ACTION will be inherited by other functions
+ for ACTION in clean compile prepack strip pack ; do
+ declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; }
+ declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; }
+ declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; }
+ done
+ return 0
+}
+
+# this function returns one exact package name from a list of potentially
+# interesting ones, classed from higher preference to lower. They are all
+# passed as strings, constituting packages names, or some of the following
+# special names :
+# %P => use current directory as the source for the name
+# %L => use the package pointed to by the ${LINKNAME} link
+# %D => use the default package
+# If several packages match a given pattern, the user is asked to select the
+# desired one.
+# The resulting package name is returned in REPLY, and the package directoryy
+# is returned in PKGDIR whenever possible.
+function get_name {
+ local pattern pkg_name
+ local radix ver build
+ local -a rel_list dev_list sort_list
+ local i search_dir
+
+ REPLY=
+ for pattern in $*; do
+ search_dir=
+ if [ "$pattern" = "%P" ]; then
+ search_dir="${CURDIR%/*}" ; search_dir="/${search_dir#/}"
+ pattern="$(basename $CURDIR)"
+ elif [ "$pattern" = "%L" ]; then
+ if [ -r ".flxpkg/Version" ]; then
+ REPLY="$(cat .flxpkg/Version)"
+ REPLY="${REPLY##*/}"
+ PKGDIR="$CURDIR/.flxpkg/."
+ return
+ elif [ -L ${LINKNAME} -a -d ${LINKNAME}/. ]; then
+ # the link is always an EXACT name, so we return it as-is.
+ pattern="$(readlink ${LINKNAME})"
+ PKGDIR="$pattern/."
+ REPLY="${pattern##*/}"
+ return
+ else
+ continue
+ fi
+ elif [ "$pattern" = "%D" ]; then
+ pattern=default
+ fi
+ radix=$(get_pkg_radix $pattern)
+ ver=$(get_pkg_ver $pattern)
+ build=$(get_build_num $pattern)
+ pkg_name=${radix:-*}-${ver:-*}-${build:-*}
+
+ REPLY=
+ # we loop until pkg_name is empty, which allows recursive choices.
+ while [ "$pkg_name" ]; do
+ # now we'll try to build a list of potentially matching packages for
+ # each pattern. We'll reduce the original name until either we have
+ # a non-empty list or the package name is void.
+ rel_list=( ); dev_list=( )
+ while [ "$pkg_name" -a -z "$rel_list" -a -z "$dev_list" ]; do
+ rel_list=( $(find ${search_dir:+$search_dir/} $PKGROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%p\n" 2>/dev/null) )
+ if [ "$release_only" != "1" ]; then
+ dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${pkg_name} -printf "%p\n" 2>/dev/null) )
+ fi
+
+ if [ -z "${rel_list[*]}" -a -z "${dev_list[*]}" ]; then
+ radix=$(get_pkg_radix $pkg_name)
+ ver=$(get_pkg_ver $pkg_name)
+ build=$(get_build_num $pkg_name)
+
+ if [ "$ver" -a "$ver" != "*" -a "$radix" != "$pkg_name" ]; then
+ if [ "$build" -a "$build" != "*" ]; then
+ pkg_name=${radix}-${ver}-*
+ elif [ "${ver%.*}" != "$ver" ]; then
+ # let's reduce the version precision
+ pkg_name=${radix}-${ver%.*}-*
+ else
+ pkg_name=${radix}-*
+ fi
+ else
+ break
+ fi
+ else
+ break
+ fi
+ done
+
+ # we're prepared to break the big loop, unless someone sets pkg_name again.
+ pkg_name=
+ sort_list=( $(sortnames ${dev_list[*]} ${rel_list[*]}) )
+
+ # if we matched nothing, we jump to the next pattern, and if we matched
+ # exactly one result, we return it immediately.
+ if [ ${#sort_list[*]} -eq 0 ]; then
+ continue
+ elif [ ${#sort_list[*]} -eq 1 ]; then
+ REPLY="${sort_list[0]}"
+ PKGDIR="${REPLY/*}"
+ REPLY="${REPLY##*/}"
+ return
+ fi
+
+ # now, we'll present the possible names to the user.
+ i=0
+ printf " %5d : - None of the following packages -\n" 0
+ while [ $i -lt ${#sort_list[*]} ]; do
+ # we'll display an 'R' in front of released names, or a 'D' for dev.
+ # FIXME : we risk a wrong match here (eg: flx0.1 <-> flx0.10)
+ if [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then
+ printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/}
+ else
+ printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/}
+ fi
+ i=$[$i+1]
+ done
+ echo
+
+ while : ; do
+ echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i
+ if [ -z "$i" ]; then
+ # empty string, we use the last choice which is the preferred one.
+ i=${#sort_list[*]}
+ REPLY="${sort_list[$[$i-1]]}"
+ PKGDIR="${REPLY/*}"
+ REPLY="${REPLY##*/}"
+ return
+ elif [ "${i//[0-9]/}" ]; then
+ # not a plain integer, we'll allow to recursively re-select
+ #pattern=${pattern}*${i}
+ pattern=${i}
+ radix=$(get_pkg_radix $pattern)
+ ver=$(get_pkg_ver $pattern)
+ build=$(get_build_num $pattern)
+ pkg_name=${radix:-*}-${ver:-*}-${build:-*}
+ break;
+ elif [ $i -le 0 ]; then
+ # if the user explicitly replied "0", then he wants other choices.
+ break;
+ elif [ $i -le ${#sort_list[*]} ]; then
+ REPLY="${sort_list[$[$i-1]]}"
+ PKGDIR="${REPLY/*}"
+ REPLY="${REPLY##*/}"
+ return
+ fi
+ done
+ # we get here only either if someone tries to refine the package name or
+ # if he refuses these ones.
+ done
+ done
+ PKGDIR="${REPLY/*}"
+ REPLY="${REPLY##*/}"
+}
+
+# choose a package and make ${LINKNAME} point to it
+function do_setpkg {
+ rm -f ${LINKNAME}
+ ln -s $PKGDIR ${LINKNAME}
+}
+
+
+# look for existing packages, and propose a new version for the current one
+function do_newpkg {
+ local -a rel_list dev_list sort_list
+ local pkg_name new_name
+ local radix ver build
+
+ set -o noglob
+ if [ -e ${LINKNAME} ]; then
+ if [ -L ${LINKNAME} ]; then
+ if [ -d ${LINKNAME}/. ]; then
+ echo "Error! the link '${LINKNAME}' already exists. Please remove it by manually."
+ exit 1
+ else
+ rm -f ${LINKNAME}
+ fi
+ else
+ echo "Error! '${LINKNAME}' already exists and is not a link. Please remove it by manually."
+ exit 1
+ fi
+ fi
+
+ if [ $# -gt 0 ]; then
+ # the user has specified an explicit version string
+ # either it's the complete name, or it's the complete name followed
+ # by an '=' sign preceding the old name.
+ new_name=${1%%=*}
+ if [ $# -gt 1 ]; then
+ pkg_name=$2
+ elif [ "$new_name" != "$1" ]; then
+ pkg_name=${1##*=}
+ fi
+ fi
+
+ if [ -z "$new_name" ]; then
+ # the user has not specified any version string, we'll use the directory
+ # name.
+ new_name=$(basename $CURDIR)
+ fi
+
+ rel_list=( ); dev_list=( )
+
+ # now we'll have to guess the new package name.
+ # The build rev part (flx*.*) will be ignored.
+ # We'll look for existing packages with the exact
+ # name+version, and if found, use this + the first unused build number.
+ # If not found, a new package is created with the exact name and flx0.1
+
+ radix=$(get_pkg_radix $new_name)
+ ver=$(get_pkg_ver $new_name)
+ build=$(get_build_num $new_name)
+ new_name=${radix:-*}-${ver:-*}
+
+ rel_list=( $(find $PKGROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) )
+ dev_list=( $(find $DEVROOT/ -maxdepth 1 -type d -name ${new_name}\* -printf "%p\n" 2>/dev/null) )
+ sort_list=(${rel_list[*]} ${dev_list[*]})
+
+ if [ "${sort_list[*]}" ]; then
+ sort_list=($(IFS=$'\n'; echo "${sort_list[*]%-${BUILDSFX}*([0-9]).+([0-9])*}" | sort -u) )
+ sort_list=( $(sortnames ${sort_list[*]}) )
+ if [ "${radix/*\\**/}" -a "${ver/*\\**/}" ] && \
+ ! (IFS=$'\n';echo "${sort_list[*]}"|grep -q "^$new_name\$"); then
+ # if the package was properly named, and not already listed, let's
+ # propose it on last position.
+ sort_list=( ${sort_list[*]} $new_name )
+ fi
+ # echo "package_list : ${sort_list[*]}"
+
+ # now, we'll present the possible names to the user
+ if [ ${#sort_list[*]} -gt 1 ]; then
+ local i=0
+ echo; echo ">>> Please select the name of the package to create :";echo
+ while [ $i -lt ${#sort_list[*]} ]; do
+ # we'll display an 'R' in front of released names, 'P'
+ # in front of packaged ones, or a 'D' for dev.
+ if [ -e "${sort_list[$i]}/RELEASED" ]; then
+ printf " %5d : [R] %s\n" $[$i+1] ${sort_list[$i]##*/}
+ elif [ "${rel_list[*]/${sort_list[$i]}/}" != "${rel_list[*]}" ]; then
+ printf " %5d : [P] %s\n" $[$i+1] ${sort_list[$i]##*/}
+ else
+ printf " %5d : [D] %s\n" $[$i+1] ${sort_list[$i]##*/}
+ fi
+ i=$[$i+1]
+ done
+
+ echo
+ while : ; do
+ echo -n "Choice [${sort_list[${#sort_list[*]}-1]##*/}]: "; read i
+ if [ -z "$i" ]; then
+ new_name=${sort_list[${#sort_list[*]}-1]}
+ break
+ elif [ "${i//[0-9]/}" ]; then
+ # not a plain integer, we'll take it for the new name
+ new_name=$i
+ break;
+ elif [ $i -ge 1 -a $i -le ${#sort_list[*]} ]; then
+ new_name=${sort_list[$[$i-1]]}
+ break;
+ fi
+ done
+ else
+ new_name=${sort_list[0]}
+ fi
+ # we'll search for all packages starting with the same name and version
+ # in both release and dev dirs. Then we'll be able to deduce the latest
+ # build number used.
+ #sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}*.\* -printf "%f\n" 2>/dev/null|sort -u) )
+ sort_list=( $(find $PKGROOT/ $DEVROOT/ -maxdepth 1 -type d -name ${new_name}-${BUILDSFX}${BUILDVER}.\* -printf "%p\n" 2>/dev/null|sort -u) )
+ if [ ${#sort_list[*]} -eq 0 ]; then
+ # this can happen with new BUILDSFX/BUILDVER
+ new_name=${new_name}-${BUILDSFX}${BUILDVER}.1
+ else
+ sort_list=( $(sortnames ${sort_list[*]} ))
+ new_name=${new_name}-$(get_next_build $(get_build_num ${sort_list[${#sort_list[*]}-1]}))
+ fi
+ else
+ if [ -z "${radix/*\\**/}" -o -z "${ver/*\\**/}" ]; then
+ echo "Error: no existing package matches $new_name, and wildcards"
+ echo "or incomplete names cannot be part of a real name."
+ exit 1
+ fi
+ # we keep new_name since it's syntactically correct
+ new_name=${new_name}-${BUILDSFX}${BUILDVER}.1
+ fi
+
+ #echo "new_name: $new_name"
+
+ # if pkg_name is unspecified, we'll use the current directory name to guess
+ # the source package, else we'll use the explicit name
+ echo; echo ">>> Please select the package to use as a reference :"; echo
+
+ get_name $pkg_name $new_name %P %D
+
+ if [ -z "$REPLY" ]; then
+ echo "No reference package found (even default). Please specify one."
+ exit 1
+ fi
+
+ echo "Using '$REPLY'."
+
+ if [ -e "$PKGROOT/$REPLY/build.cfg" ]; then
+ pkg_name=$PKGROOT/$REPLY
+ else
+ pkg_name=$DEVROOT/$REPLY
+ fi
+
+ # new_name is always relative to DEVROOT
+ #echo "new_name: $new_name ; old_name: $(basename $pkg_name)"
+
+ # we should verify that new_name/released doesn't exist before extracting
+ # anything into it, or even that new_name doesn't exist at all.
+ new_name=$DEVROOT/$new_name
+ if [ -e $new_name ]; then
+ echo "Error! new directory $new_name already exists. Refusing to overwrite."
+ exit 1
+ fi
+
+ rm -f ${LINKNAME} && mkdir -p $new_name && ln -s $new_name ${LINKNAME} && \
+ tar -C $pkg_name --exclude='./compiled/*' --exclude='./RELEASED*' --exclude='./pkg.*' \
+ --exclude='./CFLAGS' --exclude='./.dep' --exclude='./.lst' --exclude='./.tgz' \
+ --exclude='./Version' --one-file-system -cpf - . | tar -C $new_name -xf - || (rmdir $new_name ; rm -f ${LINKNAME})
+ chmod u+rw $new_name/build.cfg
+
+ echo "A new package '$(basename $new_name)' has been created as '$new_name', based on '$(basename $pkg_name)'."
+ echo "The link '${LINKNAME}' now points to it."
+ echo
+ if [ $(find $new_name/patches -type f |wc -l) -gt 0 ]; then
+ echo "*** Warning: there are patches to be applied, use >>>pkg info<<< ***"
+ echo
+ fi
+ set +o noglob
+ return 0
+}
+
+
+function do_edit {
+ if [ -e "$PKGDIR/RELEASED" ]; then
+ echo "Editing $CFGFILE in read-only mode..."
+ vi -R $CFGFILE
+ else
+ echo "Editing $CFGFILE..."
+ vi $CFGFILE
+ fi
+}
+
+function do_cat {
+ cat $CFGFILE
+}
+
+function do_lst {
+ local FPNAME
+
+ FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH
+ cat $FPNAME.lst
+}
+
+function pre_info {
+ echo "Information for package '${EXACTPKG##*/}' (\${EXACTPKG##*/}) :"
+
+ echo " Package name : $PKGRADIX (\$PKGRADIX)"
+ echo " Package version : $PKGVER (\$PKGVER)"
+ echo " Distrib version : $DISTVER (\$DISTVER)"
+ echo -n " Config. file : "
+ if [ -e $CFGFILE ]; then
+ echo "$CFGFILE"
+ else
+ echo "none found."
+ fi
+ echo " Package file : $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF"
+ echo -n " Package size : "
+ if [ -e $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF ]; then
+ echo "$(du -b $PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF |cut -f1) bytes."
+ else
+ echo "does not exist yet."
+ fi
+ if [ -n "${PATCH_LIST}" ]; then
+ echo " Patches list : ${PATCH_LIST}"
+ else
+ echo " Empty patch list."
+ fi
+
+ if [ -e "$PKGDIR/ChangeLog" ]; then
+ echo " Last ChangeLog : $(grep -m 1 '^[0-9]\{4\}' $PKGDIR/ChangeLog)"
+ else
+ echo " No ChangeLog."
+ fi
+
+ if [ -e "$PKGDIR/RELEASED" ]; then
+ echo " Tagged as RELEASED"
+ else
+ echo " UNRELEASED."
+ fi
+
+ return 0
+}
+
+# does only compile, not changing the current config
+function do_compile_only {
+ $FLXMAKE
+ return $?
+}
+
+# new simplified name for 'config_only', which is deprecated, not changing current scripts.
+function do_config {
+ if declare -f do_config_only >/dev/null 2>&1; then
+ do_config_only
+ return $?
+ else
+ return 0
+ fi
+}
+
+# configures and compiles
+function do_compile {
+ ( do_config ) && ( do_compile_only )
+}
+
+# preparatory work for prepack()
+function pre_prepack {
+ if [ "$UID" != "0" -a "$force" != "1" ]; then
+ echo "You must specify '--force' to install as non-root"
+ exit 1
+ fi
+ # WARNING! here, we don't use $ROOTDIR because we don't want to risk
+ # erasing a wrong directory as root !
+ [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}"
+ # permissions are important here because we don't want to get an
+ # inherited setgid or something alike on the root dir
+ [ ! -d "$ROOTDIR" ] && { mkdir -p $ROOTDIR; chown 0:0 $ROOTDIR; chmod 0755 $ROOTDIR; }
+ #mkdir -p "$EXAMPLEDIR"
+ return 0
+}
+
+# build link in /opt directory
+# INPUT: selected path to creation in /opt
+function build_opt {
+ local dir
+
+ if [ -d $ROOTDIR/opt ] ; then (
+ [ $# = 0 ] && set -- bin sbin lib
+ set +o noglob
+ shopt -s nullglob
+ cd $ROOTDIR/opt
+ for dir in $* ; do
+ mkdir $dir
+ dirs=( */$dir )
+ [ -n "${dirs[*]}" ] && find ${dirs[@]}/ -xtype f -perm +111 -exec ln -s ../{} $dir \; -printf "ln -s ../%p $ROOTDIR/opt/$dir\n"
+ done
+ ) fi
+ return 0
+}
+
+# deletes the current prepack directory.
+function do_delpack {
+ # WARNING! here, we don't use $ROOTDIR because we don't want to risk
+ # erasing a wrong directory as root !
+ [ -d "$(pwd)/${INSTNAME}" ] && rm -rf "$(pwd)/${INSTNAME}"
+ return 0
+}
+
+# does a full clean
+function do_clean {
+ make distclean || make mrproper || make clean
+ ( do_delpack )
+ return 0
+}
+
+# applies all the patches to the current sources
+# files which match *.rej and *~ will be deleted
+function do_patch {
+ local i
+ find . -name '*.rej' -o -name '*~' | xargs rm -f
+
+ for i in ${PATCH_LIST}; do
+ [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz"
+ if [ -z "${i##*.gz}" ]; then
+ gzip -cd < $PKGDIR/patches/$i | patch -Np$PATCH_LEVEL
+ else
+ patch -Np$PATCH_LEVEL < $PKGDIR/patches/$i
+ fi
+ done
+
+ if [ -z "$(find . -name '*.rej')" ]; then
+ find . -name '*~' | xargs rm -f
+ fi
+ return 0
+}
+
+# reverts all the patches from the current sources
+# files which match *.rej and *~ will be deleted
+function do_unpatch {
+ local i
+ local UNPATCH_LIST=""
+
+ find . -name '*.rej' -o -name '*~' | xargs rm -f
+
+ for i in ${PATCH_LIST}; do
+ UNPATCH_LIST=( $i ${UNPATCH_LIST[@]} )
+ done
+
+ for i in ${UNPATCH_LIST[@]}; do
+ [ ! -e "$PKGDIR/patches/$i" -a -e "$PKGDIR/patches/$i.gz" ] && i="$i.gz"
+ if [ -z "${i##*.gz}" ]; then
+ gzip -cd < $PKGDIR/patches/$i | patch -RNp$PATCH_LEVEL
+ else
+ patch -RNp$PATCH_LEVEL < $PKGDIR/patches/$i
+ fi
+ done
+
+ if [ -z "$(find . -name '*.rej')" ]; then
+ find . -name '*~' | xargs rm -f
+ fi
+ return 0
+}
+
+# extracts a binary package into $ROOTDIR, to reflect the state prior to pack().
+function do_unpack {
+ local FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.$PKGSUFF
+ mkdir -p $ROOTDIR
+ cd $ROOTDIR
+
+ echo -n "Extracting $FILE into $ROOTDIR ... "
+ tar zUxpf $FILE >/dev/null 2>&1
+ echo "done."
+ return 0
+}
+
+# strips symbols from executables before building the package.
+# Abort if ROOTDIR doesn't exist (thus needing prepack() first).
+function do_strip {
+ if [ ! -d $ROOTDIR ] ; then
+ echo "Error: directory $ROOTDIR doesn't exist. Make sure you did 'prepack'."
+ exit 1
+ fi
+ #find $ROOTDIR/. -type f | xargs file | grep ":.*executable.*not stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1
+ # allow executable and shared (.so), but not relocatable (.o), both stripped or not stripped
+ find $ROOTDIR/. -type f | xargs file | grep ":.*ELF.*\(executable\|\shared\).*stripped" | cut -f1 -d: | xargs ${STRIP} -x --strip-unneeded -R .note -R .comment > /dev/null 2>&1
+ return 0
+}
+
+# forces pack() to strip before starting, even if do_pack() is redefined by the user.
+function pre_pack {
+ # in the mean time, we avoid removing this directory since it could have
+ # been brought legally by an authorized package.
+ #[ $(find $EXAMPLEDIR | wc -l) = 1 ] && rmdir -p $EXAMPLEDIR 2>/dev/null
+ ( do_strip )
+ return 0
+}
+
+# this function finds perl dependencies for a given file.
+# It's only called from _do_pack_files() and do_pack()
+function get_perl_depend {
+ local filename=$1
+ local dep DEP
+ local DEP_FILE=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH.dep
+
+ DEP=$(grep "^\(.*['{\"]\)*[ ]*\(require\|use\) \+['\"]*[a-zA-Z][a-z:/A-Z0-9_-]*[; '\"]" $filename | \
+ sed -e 's/.*\(require\|use\) \+["'\'']\?\([^'\''" };]\+\)["'\'']\?/§§\2§§/g' \
+ -e 's/§§\([^§]\+\)§§[^§]*/ \1/g' | \
+ sed 's@::@/@g')
+ if [ "x$DEP" != "x" ] ; then
+ echo -n "$filename" >> $DEP_FILE
+ for dep in $DEP ; do
+ if [ "x${dep/*.*}" != "x" ] ; then
+ echo -n " $dep.pm" >> $DEP_FILE
+ else
+ echo -n " $dep" >> $DEP_FILE
+ fi
+ done
+ echo >> $DEP_FILE
+ fi
+}
+
+# same as pack, except that it uses files in the current directory as the root
+# entries, and that no strip, link nor compression is performed.
+# Only entries listed in the files pointed to by $* find their way to the archive.
+# This function relies on get_perl_depend().
+function _do_pack_files {
+ local DEP_FILE FPNAME ext
+ local FILE_LIST=$*
+
+ echo -n "Updating timestamps ... "
+ find . -not -type l | xargs touch -m
+ echo "done."
+
+ # full path name of different files
+ FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH
+ DEP_FILE=$FPNAME.dep
+
+ rm -rf $DEP_FILE
+ if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi
+
+ echo -n "Creating $DEP_FILE ... "
+ touch $DEP_FILE
+ ( set +f; shopt -s nullglob ; shopt -s dotglob ; find * -type f -o -type l ) | while read ; do
+ case $REPLY in
+ *.pm|*.pl|*.ph)
+ get_perl_depend $REPLY
+ ;;
+ */man/man*/*.[0-9n])
+ echo "$REPLY \$MAN" >> $DEP_FILE
+ ;;
+ */info/*.info|*/info/*.info-[0-9]*)
+ echo "$REPLY \$INFO" >> $DEP_FILE
+ ;;
+ bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*)
+ flr="$(file $REPLY)"
+ case "$flr" in
+ *\ shell\ *)
+ echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE
+ ;;
+ *perl\ commands*)
+ echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE
+ get_perl_depend $REPLY
+ ;;
+ *:\ symbolic\ link*)
+ echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE
+ ;;
+ *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*)
+ elf_get_dep $REPLY >> $DEP_FILE
+ ;;
+ *\ ELF\ [0-9][0-9]-bit\ *shared\ object*)
+ elf_get_dep $REPLY >> $DEP_FILE
+ ;;
+ esac
+ ;;
+ esac
+ done
+ echo "done."
+
+ echo -n "Creating $FPNAME.lst ... "
+ # we try the special case of the '.' entry which is needed to set the root permissions.
+ # this entry must be set as "." in FILE_LIST.
+ if grep -q '^.[ ]' $FILE_LIST; then
+ set -- $(grep '^.[ ]' $FILE_LIST)
+ owner=${2%%:*}
+ group=${2##*:}
+ echo "d $3 $owner $group 0 -------------------------------- 0 ."
+ fi > $FPNAME.lst
+ (flx sign --no-depth --ignore-dot $(cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,') >> $FPNAME.lst) > /dev/null 2>&1
+ echo "done."
+
+ echo -n "Creating $FPNAME.$PKGSUFF ... "
+
+ # we want everything, including directories.
+ cut -f1 -d' ' $FILE_LIST|sed -e 's,/$,,' | tar -T - --no-recursion --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null
+
+ # create shortcuts ".*" for tgz, dep and lst files
+ for ext in dep lst tgz; do
+ rm -f $PKGDIR/.$ext
+ ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext
+ done
+ echo "done."
+ return 0
+}
+
+
+# packs the prepacked files into a new file located in $DEVROOT.
+# any eventual old package is removed.
+# this function relies on _do_pack_files(), get_perl_depend(),
+function do_pack {
+ local DEP_FILE FPNAME
+ local FILE_LISTS ext
+
+ # normalize the list with an absolute path for each entry
+ for file in $FILE_LIST ; do
+ if [ -z "${file##/*}" ]; then
+ FILE_LISTS="$FILE_LISTS $file"
+ else
+ FILE_LISTS="$FILE_LISTS $CURDIR/$file"
+ fi
+ done
+ # FIXME: is this normal ???
+ if [ ! -d "$ROOTDIR" ] ; then
+ echo "Error: \$ROOTDIR doesn't point to a valid directory : $ROOTDIR"
+ exit 1
+ fi
+ cd $ROOTDIR
+
+ # use the file list when available
+ if [ "$FILE_LISTS" ]; then
+ _do_pack_files $FILE_LISTS
+ return $?
+ fi
+
+## ( find lib -type l -name "lib*.so*" | xargs rm -f ; \
+## find usr/lib -type l -name "lib*.so*" | xargs rm -f ; \
+## ldconfig -nr . ) > /dev/null 2>&1
+
+ echo -n "Updating libraries ... "
+ ldconfig -nr . lib usr/lib opt/*/lib > /dev/null 2>&1
+ echo "done."
+
+ echo -n "Updating timestamps ... "
+ find . ! -type l | xargs touch -m
+ echo "done."
+
+ # full path name of different files
+ FPNAME=$PKGDIR/compiled/${EXACTPKG##*/}-$FLXARCH
+ DEP_FILE=$FPNAME.dep
+
+ # rebuild dependencies file, first is a diff file
+ echo -n "Creating $DEP_FILE ... "
+ rm -rf $DEP_FILE
+ if [ -e $DEP_FILE.diff ] ; then cat $DEP_FILE.diff > $DEP_FILE ; fi
+
+ # build a one shot function 'add' to add dependences
+ oldadd="$(declare -f add)"
+ # usage: add file [...] need file [...]
+ function add {
+ local file files
+ # remove file
+ while [ $# -gt 0 -a "x$1" != xneed ] ; do
+ files=( "$1" "${files[@]}" )
+ shift
+ done
+ [ $# -le 1 ] && return
+ shift
+ for file in "${files}" ; do echo "$file $*" >> $DEP_FILE ; done
+ }
+ # load dependences function
+ declare -f load_deps > /dev/null && ( load_deps )
+ # reset 'add' function
+ unset add
+ # reload old one
+ [ -n "$oldadd" ] && eval "$oldadd"
+
+ touch $DEP_FILE
+ find . \( -type f -o -type l \) -printf "%P\n" | while read ; do
+ case $REPLY in
+ *.pm|*.pl|*.ph)
+ get_perl_depend $REPLY
+ ;;
+ */man/man*/*.[0-9n])
+ if [ "${REPLY/*gz}" ] ; then
+ if [ -L $REPLY ] ; then
+ LINK=$(readlink $REPLY)
+ rm $REPLY
+ ln -s $LINK.gz $REPLY.gz
+ else
+ gzip -f -9 $REPLY
+ chmod 644 $REPLY.gz
+ fi
+ fi
+ echo "$REPLY \$MAN" >> $DEP_FILE
+ ;;
+ */info/*.info|*/info/*.info-[0-9]*)
+ if [ "${REPLY/*gz}" ] ; then
+ gzip -f -9 $REPLY
+ chmod 644 $REPLY.gz
+ fi
+ echo "$REPLY \$INFO" >> $DEP_FILE
+ ;;
+ bin/*|sbin/*|lib/*|*/sbin/*|*/bin/*|*/lib/*|*/libexec/*)
+ flr="$(file $REPLY)"
+ case "$flr" in
+ *\ shell\ *)
+ echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') \$SHELL">>$DEP_FILE
+ ;;
+ *perl\ commands*)
+ echo "$REPLY $(head -1 $REPLY| sed -e 's/^#\! *\([^ ]\+\).*/\1/') ">>$DEP_FILE
+ get_perl_depend $REPLY
+ ;;
+ *:\ symbolic\ link*)
+ echo "$REPLY %L:$(readlink $REPLY)" >> $DEP_FILE
+ ;;
+ *\ ELF\ [0-9][0-9]-bit\ *dynamically\ linked*)
+ elf_get_dep $REPLY >> $DEP_FILE
+ ;;
+ *\ ELF\ [0-9][0-9]-bit\ *shared\ object*)
+ elf_get_dep $REPLY >> $DEP_FILE
+ ;;
+ esac
+ ;;
+ esac
+ done
+ echo "done."
+
+ echo -n "Creating $FPNAME.lst ... "
+ ($FIND_CMD . | xargs flx sign --ignore-dot --no-depth > $FPNAME.lst) > /dev/null 2>&1
+ echo "done."
+
+ echo -n "Creating $FPNAME.$PKGSUFF ... "
+ # we want everything, and directories only if they're empty.
+ # All this without './' we shouldn't get an empty line since .
+ # should contain at least what we want to tar !
+ $FIND_CMD . | tar --no-recursion -T - --numeric-owner -cf - | gzip -9 >$FPNAME.$PKGSUFF 2>/dev/null
+
+ # create shortcuts ".*" for tgz, dep and lst files
+ for ext in dep lst tgz; do
+ rm -f $PKGDIR/.$ext
+ ln -sf compiled/${EXACTPKG##*/}-$FLXARCH.$ext $PKGDIR/.$ext
+ done
+ echo "done."
+ return 0
+}
+
+
+# this function prepares all needed variables to work in a cross-compiler environment
+function set_cross_environment {
+ # Handling of cross-compilers :
+ # - setting CC will force both HOSTCC and FLXCROSSCC
+ # - setting HOSTCC will keep it
+ # - setting FLXCROSS will set CC
+ # - setting FLXCROSSCC will set CC whatever FLXCROSS is.
+
+ if [ -z "$FLX_CROSS_OPT_SET" ]; then
+ CC=${CC:-gcc}
+ CXX=${CXX:-g++}
+ AS=${AS:-as}
+ LD=${LD:-ld}
+ AR=${AR:-ar}
+ NM=${NM:-nm}
+ RANLIB=${RANLIB:-ranlib}
+ STRIP=${STRIP:-strip}
+ OBJDUMP=${OBJDUMP:-objdump}
+
+ HOSTCC=${HOSTCC:-$CC}
+ HOSTCXX=${HOSTCXX:-$CXX}
+ HOSTAS=${HOSTAS:-$AS}
+ HOSTLD=${HOSTLD:-$LD}
+ HOSTAR=${HOSTAR:-$AR}
+ HOSTNM=${HOSTNM:-$NM}
+ HOSTSTRIP=${HOSTSTRIP:-$STRIP}
+ HOSTOBJDUMP=${HOSTOBJDUMP:-$OBJDUMP}
+
+ if [ -n "$FLXCROSS" ]; then
+ CC=${FLXCROSS}${CC} ; CC=${FLXCROSSCC:-$CC}
+ CXX=${FLXCROSS}${CXX} ; CXX=${FLXCROSSCXX:-$CXX}
+ AS=${FLXCROSS}${AS} ; AS=${FLXCROSSAS:-$AS}
+ LD=${FLXCROSS}${LD} ; LD=${FLXCROSSLD:-$LD}
+ AR=${FLXCROSS}${AR} ; AR=${FLXCROSSAR:-$AR}
+ NM=${FLXCROSS}${NM} ; NM=${FLXCROSSNM:-$NM}
+ RANLIB=${FLXCROSS}${RANLIB} ; RANLIB=${FLXCROSSRANLIB:-$RANLIB}
+ STRIP=${FLXCROSS}${STRIP} ; STRIP=${FLXCROSSSTRIP:-$STRIP}
+ OBJDUMP=${FLXCROSS}${OBJDUMP} ; OBJDUMP=${FLXCROSSOBJDUMP:-$OBJDUMP}
+ fi
+ # specify that we don't want to do this again
+ FLX_CROSS_OPT_SET=1
+ fi
+}
+
+# this function sets all needed compiler options
+function set_compiler_options {
+ # now we'll set default ARCH and CPU for the current FLXARCH if none is set.
+ case "$FLXARCH" in
+ i586|"") arch=${arch:-i586} cpu=${cpu:-i686} basearch=${basearch:-i386} ;;
+ i686) arch=${arch:-i686} cpu=${cpu:-i686} basearch=${basearch:-i386} ;;
+ i486) arch=${arch:-i486} cpu=${cpu:-i486} basearch=${basearch:-i386} ;;
+ i386) arch=${arch:-i386} cpu=${cpu:-i386} basearch=${basearch:-i386} ;;
+ parisc) arch=${arch:-1.1} cpu=${cpu:-7100LC} basearch=${basearch:-1.1} ;;
+ sparc) arch=${arch:-sparc} cpu=${cpu:-sparc} basearch=${basearch:-sparc} ;;
+ sparc64) arch=${arch:-ultrasparc} cpu=${cpu:-ultrasparc} basearch=${basearch:-ultrasparc} ;;
+ ev[456]*|arm*|ppc*) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;;
+ *) arch=${arch:-$FLXARCH} cpu=${cpu:-$FLXARCH} basearch=${basearch:-$FLXARCH} ;;
+ esac
+
+ # FIXME: this should go into a per-architecture file
+ case "$FLXARCH" in
+ *86)
+ CC=${CC:-gcc}
+ CXX=${CXX:-g++}
+ FLX_ARCH_CURRENT="$FLXARCH"
+ FLX_ARCH_COMMON="i586"
+ FLX_ARCH_SMALL="$basearch"
+ GCC_ARCH_CURRENT="-march=$arch"
+ GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON"
+ GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL"
+ GCC_CPU_CURRENT="-mcpu=$cpu"
+ GCC_CPU_COMMON="-mcpu=$FLX_ARCH_COMMON"
+ GCC_CPU_SMALL="-mcpu=$FLX_ARCH_SMALL"
+ GCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0"
+ GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0"
+ if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then
+ GCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ GCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps"
+ GCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels"
+ fi
+ ;;
+
+ parisc*)
+ CC=${CC:-gcc}
+ CXX=${CXX:-g++}
+ FLX_ARCH_CURRENT="${FLXARCH##parisc}" ; FLX_ARCH_CURRENT="${FLX_ARCH_CURRENT:-1.1}"
+ FLX_ARCH_COMMON="1.0"
+ FLX_ARCH_SMALL="1.0"
+ GCC_ARCH_CURRENT="-march=$FLX_ARCH_CURRENT"
+ GCC_ARCH_COMMON="-march=$FLX_ARCH_COMMON"
+ GCC_ARCH_SMALL="-march=$FLX_ARCH_SMALL"
+ GCC_CPU_CURRENT="-mschedule=7100LC"
+ GCC_CPU_COMMON="-mschedule=7100"
+ GCC_CPU_SMALL="-mschedule=7100"
+ GCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ GCC_OPT_FAST="-O2 -fno-align-jumps"
+ GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels"
+ ;;
+
+ sparc*)
+ CC=${CC:-gcc}
+ CXX=${CXX:-g++}
+ FLX_ARCH_CURRENT="$FLXARCH"
+ FLX_ARCH_COMMON="$FLXARCH"
+ FLX_ARCH_SMALL="$FLXARCH"
+ GCC_ARCH_CURRENT="-mcpu=$arch"
+ GCC_ARCH_COMMON="-mcpu=$arch"
+ GCC_ARCH_SMALL="-mcpu=$arch"
+ GCC_CPU_CURRENT="-mtune=$cpu"
+ GCC_CPU_COMMON="-mtune=$cpu"
+ GCC_CPU_SMALL="-mtune=$cpu"
+ GCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ GCC_OPT_FAST="-O2 -fno-align-jumps"
+ GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels"
+ ;;
+
+ ev[456]*)
+ CC=${CC:-gcc}
+ CXX=${CXX:-g++}
+ FLX_ARCH_CURRENT="$FLXARCH"
+ FLX_ARCH_COMMON="$FLXARCH"
+ FLX_ARCH_SMALL="$FLXARCH"
+ GCC_ARCH_CURRENT="-mcpu=$arch"
+ GCC_ARCH_COMMON="-mcpu=$arch"
+ GCC_ARCH_SMALL="-mcpu=$arch"
+ GCC_CPU_CURRENT="-mtune=$cpu"
+ GCC_CPU_COMMON="-mtune=$cpu"
+ GCC_CPU_SMALL="-mtune=$cpu"
+ GCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ GCC_OPT_FAST="-O2 -fno-align-jumps"
+ GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels"
+ ;;
+
+ *)
+ CC=${CC:-gcc}
+ CXX=${CXX:-g++}
+ FLX_ARCH_CURRENT="$FLXARCH"
+ FLX_ARCH_COMMON="$FLXARCH"
+ FLX_ARCH_SMALL="$FLXARCH"
+ GCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ GCC_OPT_FAST="-O2 -malign-jumps=0"
+ GCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0"
+ if [ $TESTGCC -gt 0 ] && $CC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then
+ GCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ GCC_OPT_FAST="-O2 -fno-align-jumps"
+ GCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels"
+ fi
+ ;;
+ esac
+
+ case "$FLXHOSTARCH" in
+ *86)
+ HOSTCC=${HOSTCC:-$CC}
+ HOSTCXX=${HOSTCXX:-$CXX}
+ HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0"
+ HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -malign-jumps=0 -malign-loops=0 -malign-functions=0"
+ if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then
+ HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ HOSTCC_OPT_FAST="-O2 -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-jumps"
+ HOSTCC_OPT_SMALL="-Os -momit-leaf-frame-pointer -mpreferred-stack-boundary=2 -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels"
+ fi
+ ;;
+ parisc*)
+ HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST"
+ HOSTCC_OPT_FAST="$GCC_OPT_FAST"
+ HOSTCC_OPT_SMALL="$GCC_OPT_SMALL"
+ ;;
+
+ sparc*)
+ HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST"
+ HOSTCC_OPT_FAST="$GCC_OPT_FAST"
+ HOSTCC_OPT_SMALL="$GCC_OPT_SMALL"
+ ;;
+
+ ev[456]*)
+ HOSTCC_OPT_FASTEST="$GCC_OPT_FASTEST"
+ HOSTCC_OPT_FAST="$GCC_OPT_FAST"
+ HOSTCC_OPT_SMALL="$GCC_OPT_SMALL"
+ ;;
+
+ *)
+ HOSTCC=${HOSTCC:-$CC}
+ HOSTCXX=${HOSTCXX:-$CXX}
+ HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ HOSTCC_OPT_FAST="-O2 -malign-jumps=0"
+ HOSTCC_OPT_SMALL="-Os -malign-jumps=0 -malign-loops=0 -malign-functions=0"
+ if [ $TESTGCC -gt 0 ] && $HOSTCC -fno-align-loops -S -o /dev/null -xc /dev/null >/dev/null 2>&1; then
+ HOSTCC_OPT_FASTEST="-O3 -fomit-frame-pointer"
+ HOSTCC_OPT_FAST="-O2 -fno-align-jumps"
+ HOSTCC_OPT_SMALL="-Os -fno-align-functions -fno-align-loops -fno-align-jumps -fno-align-labels"
+ fi
+ ;;
+ esac
+
+ export FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL
+ export FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG
+ export CC CXX AS LD AR OBJDUMP NM STRIP RANLIB GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL
+ export GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL
+ export GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL
+ export HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL
+
+ return 0
+}
+
+# displays used environment variables
+function print_env {
+ set_cross_environment
+ set_compiler_options
+ for i in FLXHOSTOS FLXHOSTARCH FLXHOST FLXTARGOS FLXTARGARCH FLXTARG \
+ FLX_ARCH_CURRENT FLX_ARCH_COMMON FLX_ARCH_SMALL FLXARCH \
+ FLXCROSS FLXTOOLDIR FLXROOTDIR \
+ AR AS CC CXX LD NM OBJDUMP RANLIB STRIP \
+ GCC_ARCH_CURRENT GCC_ARCH_COMMON GCC_ARCH_SMALL \
+ GCC_CPU_CURRENT GCC_CPU_COMMON GCC_CPU_SMALL \
+ GCC_OPT_FASTEST GCC_OPT_FAST GCC_OPT_SMALL \
+ HOSTCC HOSTCXX \
+ HOSTCC_OPT_FASTEST HOSTCC_OPT_FAST HOSTCC_OPT_SMALL \
+ FLXMAKE FLXPMAKE; do
+ echo "$i=$(eval echo \$$i)"
+ done
+ exit 0
+}
+
+function usage {
+ # this is needed to present current options to the user
+ set_cross_environment
+ set_compiler_options
+
+ echo "PKG version $PKG_VERSION - Formilux package build utility."
+ echo "Usage:"
+ echo " pkg [-options]* <action> [ pkg [ pkg2 ] ]"
+ echo
+ echo " pkg newpkg [ new_pkg [ old_pkg ] ]"
+ echo " pkg newpkg [ newpkg ]=[ old_pkg ]"
+ echo " ex: pkg newpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1 openssl-0.9.6d-${BUILDSFX}${BUILDVER}.1"
+ echo " pkg newpkg =apache-1.3"
+ echo " pkg newpkg bash"
+ echo " pkg newpkg gcc gcc-3*${BUILDSFX}*.1"
+ echo
+ echo " pkg setpkg [ new_pkg ]"
+ echo " ex: pkg setpkg openssl-0.9.6g-${BUILDSFX}${BUILDVER}.1"
+ echo
+ echo " pkg { info | cat | edit | unpack | changelog } [ pkg ]"
+ echo " ex: pkg info"
+ echo " pkg info bash"
+ echo " pkg edit modutils-2.4"
+ echo " pkg cat gzip-1.3"
+ echo
+ echo " pkg { clean | compile | config | compile_only | build }*"
+ echo " pkg { prepack | strip | pack | delpack | release }*"
+ echo
+ echo " pkg { patch | unpatch } [ patch_name ]"
+ echo
+ echo " pkg { any_command } [ any_args ]"
+ echo
+ echo "User variables are :"
+ echo "PKGROOT : directory containing released packages <$PKGROOT>"
+ echo "DEVROOT : directory containing unreleased packages <$DEVROOT>"
+ echo "ROOTDIR : base directory for package installation (not source), <$ROOTDIR>"
+ echo "FLXARCH : architecture to use for the package, <$FLXARCH>"
+ echo "KERNDIR : kernel sources location, if needed, <$KERNDIR>"
+ echo
+ echo "Architecture-specific variables :"
+ echo -e " CURRENT\t|COMMON\t|SMALL"
+ echo -e "FLX_ARCH_ : $FLX_ARCH_CURRENT\t| $FLX_ARCH_COMMON\t| $FLX_ARCH_SMALL"
+ echo -e "GCC_ARCH_ : $GCC_ARCH_CURRENT\t| $GCC_ARCH_COMMON\t| $GCC_ARCH_SMALL"
+ echo -e "GCC_CPU_ : $GCC_CPU_CURRENT\t| $GCC_CPU_COMMON\t| $GCC_CPU_SMALL"
+ echo "GCC_OPT_FASTEST=$GCC_OPT_FASTEST"
+ echo "GCC_OPT_FAST=$GCC_OPT_FAST"
+ echo "GCC_OPT_SMALL=$GCC_OPT_SMALL"
+ echo
+ echo "Use pkg --env to get all variables."
+
+# Those two are not user-settable anymore
+# echo "CFGFILE : force to use of a .pkg, <$CFGFILE>"
+# echo "DISTVER : build version (${BUILDSFX}${BUILDVER}.1)"
+ exit 1
+}
+
+# displays usage
+function do_help {
+ usage
+ return 0
+}
+
+# creates a new changelog entry and prompts the user to add information.
+function do_changelog {
+ # Let's create a new changelog entry
+ (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME";
+ echo ''; echo $'\t* '; echo ''; echo '.' ;
+ echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null
+
+ # we'll ask the user to fill the changelog
+ vi -c ":3" $PKGDIR/ChangeLog
+ return 0
+}
+
+# marks the current package as released
+function do_release {
+ local last_pkg
+
+ echo "#####################################################"
+ echo "# Release command not implemented yet ! Aborting... #"
+ echo "#####################################################"
+ #exit 1
+ # some important checks before things get wrong
+ if [ -z "$PKGROOT" -o -z "$PKGDIR" -o -z "$EXACTPKG" ]; then
+ echo "Critical error : PKGROOT, PKGDIR and EXACTPKG must be set !"
+ exit 1
+ fi
+
+ if ! [ -s "$PKGDIR/.lst" -a -e "$PKGDIR/.dep" -a -s "$PKGDIR/.tgz" ]; then
+ echo "Nothing to be released in this package."
+ echo "Please ensure that .lst, .dep and .tgz exist."
+ exit 1
+ fi
+
+ # first, the destination directory must not exist
+ if [ -d "$PKGROOT/${EXACTPKG##*/}" ]; then
+ if [ -e "$PKGROOT/${EXACTPKG##*/}/RELEASED" ]; then
+ echo "Error: This package already exists."
+ else
+ echo "Error: The package directory $PKGROOT/${EXACTPKG##*/} already exists."
+ fi
+ exit 1
+ fi
+
+ # identify last changelog entry
+ last_pkg=""
+ if [ -e "$PKGDIR/ChangeLog" ]; then
+ last_pkg=$(grep -m 1 $'^[\t ]*\* released' "$PKGDIR/ChangeLog")
+ last_pkg=${last_pkg##*released }
+ fi
+
+ if [ "$last_pkg" != "$EXACTPKG" ]; then
+ # Let's create a new changelog entry
+ touch $PKGDIR/ChangeLog # avoid error message in case it doesn't exist
+ (echo '0a'; date +"%Y/%m/%d %H:%M $LOGNAME@$HOSTNAME";
+ echo ''; echo $'\t'"* released $EXACTPKG";
+ echo ''; echo '.' ; echo '1,$wq') | ed $PKGDIR/ChangeLog >/dev/null
+ fi
+
+ # we'll ask the user to fill the changelog
+ vi -c ":4" $PKGDIR/ChangeLog
+
+#<FIXME.WTA>
+#traiter le cas où PKGROOT/PKGDIR existe déjà mais pour d'autres archi
+#</FIXME>
+
+ if ! mv $PKGDIR $PKGROOT/ ; then
+ echo "Error: cannot move the package to the released directory. Cancelling."
+ # the mv here fails atomically, so nothing's lost in PKGDIR, but we have
+ # to clean a possible partial copy
+ rm -rf $PKGROOT/${EXACTPKG##*/}
+ exit 2
+ fi
+
+ touch $PKGROOT/${EXACTPKG##*/}/RELEASED
+
+ return 0
+}
+
+# usage: install-files <owner> <perm> <dest> file...
+#
+function install-files {
+ local owner="$1" ; shift
+ local perm="$1" ; shift
+ local dst="$1" ; shift
+ local file
+
+ [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}"
+ cp -dpfP "$@" "$ROOTDIR/$dst/" && \
+ ( cd "$ROOTDIR/$dst" && chown -h $owner "${@##*/}" && chmod $perm "${@##*/}" )
+
+ [ -n "$FILE_LIST" ] && for file in "$@"; do echo "$dst/$file $owner $perm"; done >> $FILE_LIST
+}
+
+# usage: install-file <owner> <perm> <file> <dest>
+#
+function install-file {
+ local owner="$1" ; shift
+ local perm="$1" ; shift
+ local src="$1" ; shift
+ local dst="$1" ; shift
+
+ [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}"
+ if cp -dpfP "$src" "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst" \
+ && [ ! -L "$ROOTDIR/$dst" ]; then chmod $perm "$ROOTDIR/$dst"; fi
+
+ [ -n "$FILE_LIST" ] && echo $dst $owner $perm >> $FILE_LIST
+}
+
+# usage: install-dir <owner> <perm> <dir>...
+#
+function install-dir {
+ local owner="$1" ; shift
+ local perm="$1" ; shift
+ local dst
+
+ for dst in "$@"; do
+ mkdir -pm $perm "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst"
+ [ -n "$FILE_LIST" ] && echo $dst $owner $perm >> $FILE_LIST
+ done
+}
+
+# usage: install-ln <owner> <target> <dest>
+#
+function install-ln {
+ local owner="$1" ; shift
+ local target="$1" ; shift
+ local dst="$1" ; shift
+
+ [ -n "${dst##*/*}" -o -d "$ROOTDIR/${dst%/*}" ] || mkdir -p "$ROOTDIR/${dst%/*}"
+ ln -s "$target" "$ROOTDIR/$dst" && chown -h $owner "$ROOTDIR/$dst"
+ [ -n "$FILE_LIST" ] && echo $dst $owner 000 >> $FILE_LIST
+}
+
+
+######
+###### here are some functions used only from main
+######
+
+function known_cmd {
+ declare -f pre_$ACTION > /dev/null && { ( pre_$ACTION $* ) || return $?; }
+ declare -f do_$ACTION > /dev/null && { ( do_$ACTION $* ) || return $?; }
+ declare -f post_$ACTION > /dev/null && { ( post_$ACTION $* ) || return $?; }
+ return 0
+}
+
+
+######
+###### here is the main entry point
+######
+
+# scan the command line
+
+release_only=0
+force=0
+TESTGCC=0
+PRINTUSAGE=0
+PRINTENV=0
+ARGLIST=( )
+ACTION=
+CHAINCMD=1
+
+[ $# -eq 0 ] && PRINTUSAGE=1
+
+while [ $# -gt 0 ] ; do
+ case "$1" in
+ --force )
+ force=1
+ ;;
+ --help|-h)
+ PRINTUSAGE=1
+ ;;
+ --env|-e)
+ PRINTENV=1
+ TESTGCC=1
+ ;;
+ --rel|-r*)
+ release_only=1
+ ;;
+ --)
+ shift
+ ARGLIST=(${ARGLIST[*]} $*)
+ break
+ ;;
+ -* )
+ PRINTUSAGE=1
+ ;;
+ *)
+ ARGLIST=(${ARGLIST[*]} "$1")
+ ;;
+ esac
+ shift
+done
+
+
+#echo "arglist=${ARGLIST[*]}"
+
+[ $PRINTENV -gt 0 ] && print_env
+[ $PRINTUSAGE -gt 0 ] && usage
+[ ${#ARGLIST[*]} -lt 1 ] && usage
+
+# Some actions can be chained, others not. we'll get the longest
+# possible chain, and stop once we encounter a non-chainable action
+
+while [ $CHAINCMD -gt 0 -a ${#ARGLIST[@]} -gt 0 ]; do
+ set -o noglob
+ ACTION=${ARGLIST[0]}
+ TESTGCC=0
+ # unset ARGLIST[0] ### doesn't work in scripts with this shitty bash !!!
+ ARGLIST[0]= ; ARGLIST=( ${ARGLIST[*]} ) # gets expanded with shitty bash !
+
+ case "$ACTION" in
+ newpkg)
+ CHAINCMD=0
+ KNOWNCMD=1
+ # newpkg is the only command which doesn't start by a package lookup.
+ ;;
+ setpkg)
+ CHAINCMD=0
+ KNOWNCMD=1
+ get_name $1 %P default
+ ;;
+ info|edit|cat|unpack|changelog)
+ CHAINCMD=0
+ KNOWNCMD=1
+ get_name ${ARGLIST[0]} %L %P %D
+ [ -d "$PKGDIR" ] || PKGDIR=
+ ;;
+ patch|unpatch)
+ CHAINCMD=0
+ KNOWNCMD=1
+ if [ -r ".flxpkg/Version" ]; then
+ REPLY="$(cat .flxpkg/Version)"
+ REPLY="${REPLY##*/}"
+ PKGDIR="$CURDIR/.flxpkg/."
+ else
+ REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)"
+ PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)"
+ fi
+ # get_name %L
+ ;;
+ compile_only|config|config_only|compile|build)
+ KNOWNCMD=1
+ if [ -r ".flxpkg/Version" ]; then
+ REPLY="$(cat .flxpkg/Version)"
+ REPLY="${REPLY##*/}"
+ PKGDIR="$CURDIR/.flxpkg/."
+ else
+ REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)"
+ PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)"
+ fi
+ TESTGCC=1
+ # get_name %L
+ ;;
+ prepack|strip|pack|delpack|release|clean)
+ KNOWNCMD=1
+ if [ -r ".flxpkg/Version" ]; then
+ REPLY="$(cat .flxpkg/Version)"
+ REPLY="${REPLY##*/}"
+ PKGDIR="$CURDIR/.flxpkg/."
+ else
+ REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)"
+ PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)"
+ fi
+ # get_name %L
+ ;;
+ *)
+ CHAINCMD=0
+ KNOWNCMD=0
+ if [ -r ".flxpkg/Version" ]; then
+ REPLY="$(cat .flxpkg/Version)"
+ REPLY="${REPLY##*/}"
+ PKGDIR="$CURDIR/.flxpkg/."
+ else
+ REPLY="$(basename $(readlink ${LINKNAME}) 2>/dev/null)"
+ PKGDIR="$(readlink ${LINKNAME} 2>/dev/null)"
+ fi
+ # get_name %L
+ ;;
+ esac
+
+ [ $CHAINCMD -gt 0 ] && (echo;echo "===> PKG: starting [$ACTION] <===") >&2
+
+ set +o noglob
+ if [ "$ACTION" != "newpkg" ]; then
+ if [ -z "$REPLY" ]; then
+ echo "Error: package name not found."
+ exit 1
+ fi
+ EXACTPKG="$PKGDIR/$REPLY"
+
+ if [ -z "$PKGDIR" ]; then
+ if [ -e "$PKGROOT/${EXACTPKG##*/}/build.cfg" ]; then
+ PKGDIR="$PKGROOT/${EXACTPKG##*/}"
+ else
+ PKGDIR="$DEVROOT/${EXACTPKG##*/}"
+ fi
+ fi
+ CFGFILE="$PKGDIR/build.cfg"
+ PKGRADIX="$(get_pkg_radix ${EXACTPKG##*/})"
+ PKGVER="$(get_pkg_ver ${EXACTPKG##*/})"
+ DISTVER="$(get_build_num ${EXACTPKG##*/})"
+ ROOTDIR="${ROOTDIR:-$CURDIR/${INSTNAME}}"
+ EXAMPLEDIR="${ROOTDIR}/usr/share/examples"
+
+ # for compatibility with old functions. Not used anywhere outside this script.
+ packver="${EXACTPKG##*/}"
+ pack="$PKGRADIX"
+ fi
+
+ set_cross_environment
+ set_compiler_options
+
+ if [ "$ACTION" != "newpkg" ]; then
+ . $CFGFILE
+ fi
+
+ # FLXMAKE is used for sequential make and FLXPMAKE for parallel make
+ FLXMAKE="${FLXMAKE:-make}"
+ FLXPMAKE="${FLXPMAKE:-$FLXMAKE}"
+
+ export DISTVER PKGRADIX PKGVER FLXMAKE FLXPMAKE PATCH_LIST FILE_LIST
+
+# echo "ACTION=$ACTION, KNOWNCMD=$KNOWNCMD, CHAINCMD=$CHAINCMD"
+# echo "ARGLIST=${ARGLIST[*]}"
+
+ if [ $KNOWNCMD -gt 0 ]; then
+ known_cmd ${ARGLIST[*]} || exit 1
+ else
+ if declare -f do_$ACTION >/dev/null; then
+ ( do_$ACTION ${ARGLIST[*]} ) || exit 1
+ fi
+ fi
+ [ $CHAINCMD -gt 0 ] && (echo "===> PKG: end of [$ACTION] <===";echo) >&2
+
+ # now, we'll loop only if we were in a chainable action
+done
+
+[ $CHAINCMD -gt 0 ] && (echo "===> PKG: [END] <===";echo) >&2
+exit 0
+