#!/bin/sh # $Id$ # # utils.sh -- utility routines for the installation scripts. # Do not call directly. # # Copyright (c) Sebastian Rahtz 2003, 2004, 2005. # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA # 02110-1301, USA. # # Send bug reports or suggestions to tex-live@tug.org. ################################################################ # Basic IO: ################################################################ ################################################################ # read: called with the name of a variable and (optionally) a # different message text. Keeps the old value of the # variable, if the empty string in entered. ################################################################ gets() { gets_var=$1; gets_text=${2-$gets_var} eval old=\$$gets_var eval $echon \""New value for $gets_text [$old]: "\" read $gets_var eval test -z \"\$$gets_var\" && eval $gets_var=\'$old\' } ################################################################ # getopt: get a menu choice. # $1: string with valid characters # $2: message for prompting ################################################################ getopt() { chars=$1; msg=$2 while true; do #$echon "$msg ([$chars]): " $echon "$msg: " >&2 read ans ans=`echo $ans | tr '[a-z]' '[A-Z]'` case "$ans" in [$chars]) echo "$ans" return esac done } getoptallcase() { chars=$1; msg=$2 while true; do #$echon "$msg ([$chars]): " $echon "$msg: " >&2 read ans case "$ans" in [$chars]) echo "$ans" return esac done } ################################################################ # toggle: given the name of a variable, toogle switches between # the values ' ' and X. ################################################################ toggle() { if eval test \"\$$1\" = X; then eval $1=\' \' else eval $1=X fi } ################################################################ # This tricky function displays the value of a variable that can # contain newline characters. Variables will be expanded, too. # Arguments: # 1: the name of the variable ################################################################ textvar_show() { OLDIFS=$IFS; IFS=''; eval echo \"`eval echo \\$${1}`\" IFS=$OLDIFS } readln() { $echon 'Press return to continue... ' read foo } helpme() { var=$1 cls textvar_show $var 2>&1 | $PAGER echo readln } ################################################################ # Use the yesno functions to ask the user a simple yes/no # question. # Arguments: # $1: test to display for the question (" (Y/N)? " will # automatically be appended). ################################################################ yesno() { while true; do $echon "$1 (Y/N)? " read ans case $ans in y|Y) return 0;; n|N) return 1;; esac done } ################################################################ # A set of functions the might do an echo without linefeed in # the end. Function find_echo sets the variable "echon" to a # suitable function. ################################################################ echo_a() { echo -n "$@"; } echo_b() { echo "$@\c"; } echo_c() { echo -e "$@\c"; } echo_d() { /bin/echo -n "$@"; } echo_e() { /bin/echo "$@\c"; } echo_f() { /bin/echo -e "$@\c"; } ################################################################ # Test which of the above functions does the trick. We set # the variable "echon" to the first function that works # correctly. ################################################################ find_echo() { for i in a b c d e f; do test "`echo_$i c``echo_$i a`" = ca && echon=echo_$i && return done echon=echo } ################################################################ # a replacement for xargs (for systems that dont have it) ################################################################ mxargs() { ( COUNT=25 COUNTP=26 TEMP=${TMP-/tmp} TMPA=$TEMP/.tmp_xargs_a.$$ TMPB=$TEMP/.tmp_xargs_b.$$ trap "rm -f $TMPA $TMPB; trap '' 0; exit 0" 0 1 2 15 cat > $TMPA while test -s $TMPA; do args=`sed -n "1,${COUNT}p" <$TMPA` "$@" $args mv $TMPA $TMPB sed -n "${COUNTP},\$p" <$TMPB >$TMPA done ) } ################################################################ # search for a binary in PATH, find all occurences ################################################################ find_in_path() { fip_testbin=$1 fip_result="" case "$fip_testbin" in /*) test -x "$fip_testbin" && test -f "$fip_testbin" && fip_result="$fip_result $fip_testbin";; *) OLDIFS=$IFS; IFS=:; eval set $PATH; IFS=$OLDIFS for fip_this_dir do test -x "$fip_this_dir/$fip_testbin" && test -f "$fip_this_dir/$fip_testbin" && fip_result="$fip_result $fip_this_dir/$fip_testbin" done esac echo $fip_result } ################################################################ # search for a tar that either understands -I or -T ################################################################ test_tar() { testtar_tmp=${TMP-/tmp}/.testtar.$$ TARS="`find_in_path gtar` `find_in_path tar`" test -z "$TARS" && return ( exec 3>&1 1>/dev/null 2>&1 trap "cd /; rm -rf $testtar_tmp; trap '' 0; exit 0" 0 1 2 15 mkdir $testtar_tmp; cd $testtar_tmp mkdir a b tar cf test.tar a b rmdir a b echo a > list for TAR in $TARS; do $TAR -x -f test.tar -T list >/dev/null 2>&1 if test -d a && test ! -d b; then echo "$TAR -T" >&3 break fi rmdir a b >/dev/null 2>&1 $TAR -x -f test.tar -I list >/dev/null 2>&1 if test -d a && test ! -d b; then echo "$TAR -I" >&3 break fi done ) } ################################################################ # if we find a good tar: use it. Else use xargs (or even mxargs) ################################################################ find_tar() { XARGS=`find_in_path xargs | sed 's/ .*//'` test -x "$XARGS" || XARGS=mxargs set x `test_tar`; shift if test -n "$1"; then GOODTAR=true TARPROG=$1; TAROPT=$2 else GOODTAR=false TARPROG=tar; TAROPT="" fi } ################################################################ # utility functions: ################################################################ bad_sh() { /bin/sh -c 'exit 1' retval=$? if test "$retval" != 1; then echo echo 'Your /bin/sh is completely broken. A simple program like' echo echo " /bin/sh -c 'exit 1'; echo \$?" echo echo "gives a wrong result." echo echo 'Your shell is likely to break some scripts of TeX Live. Please' echo 'update your /bin/sh first and try to install TeX Live later.' echo 'GNU bash 1.14.5 will do, whereas bash 1.14.3 is known to have' echo 'problems.' echo exit 1 fi } warning() { echo "$@" } cls() { test "$debug" = true || clear } check_for_binary() { testbin=$1 case "$testbin" in /*) test -x "$testbin" && test -f "$testbin"; return;; *) OLDIFS=$IFS; IFS=:; eval set $PATH; IFS=$OLDIFS for this_dir do test -x "$this_dir/$testbin" && test -f "$this_dir/$testbin" && return 0 done return 1;; esac } require_binaries() { for this_bin do check_for_binary $this_bin || fatal "program '$this_bin' not found in PATH" done } unset_vars() { for var in $envvars; do unset $var done } unset_vars() { for var in $envvars; do unset $var done } mkdirhier() { case $1 in /*) cd /;; esac OLDIFS=$IFS; IFS=/; eval set $1; IFS=$OLDIFS for i do test -d $i || mkdir $i || break cd $i || break done } # fill a string with blanks: setlength() { var=$1 length=$2 eval value=\"\$$var\" l=`expr "$value" : '.*'` test $l -lt $length || return d=`expr $length - $l` OLDIFS=$IFS; IFS='' substr=`awk 'END {print substr(" ", 1, ANZ)}' ANZ=$d > $msg <<" echo case `getopt TRQ 'What shall we do now: ry again, econfigure, uit'` in T) return;; R) menu_main;; Q) exit 1;; esac } warn() { msg=$1 cls echo "Oops, I am in trouble here! The problem was:" >&2 echo ">> $msg <<" >&2 echo >&2 case `getopt CQ 'What shall we do now: continue, uit'` in C) return;; Q) exit 1;; esac } fatal() { echo; echo echo "ERROR: $@." echo "This was a fatal error. Installation aborted." $debug && read foo exit 1 } show_error() { test $? = 0 && return cls echo 'WARNING: the last command returned an error.' if yesno 'Do you want to see the errorlog'; then cat $ERRLOG | $PAGER readln fi cls } locate_binaries() { require_binaries touch sed awk gzip ln rm ls tar tr mkdir cat `echo $PAGER | sed 's@ .*@@'` pwd } # convert standard names to our binary names. platform_guess() { sys=`(cd ${TMP-/tmp}; sh ${OVERRIDE_GUESS-$CDDIR}/config.guess)` system=`echo $sys | sed 's/-[^-]*-/-/'` case $system in *86-cygwin*) Sys=i386_cgywin;; *86-darwin*) Sys=i386_darwin;; *86-freebsd*) Sys=i386_freebsd;; *86-linux*) Sys=i386_linux;; *86_64*-linux*) Sys=x86_64_linux;; alpha*-linux*) Sys=alpha_linux;; mips-irix*) Sys=mips_irix;; powerpc-aix*) Sys=powerpc_aix;; powerpc-*darwin*) Sys=powerpc_darwin;; sparc-solaris*) Sys=sparc_solaris;; sparc*-linux*) Sys=sparc_linux;; # *86-openbsd*) Sys=i386_openbsd;; # alphaev*-osf*) Sys=alphaev5_osf;; esac this_system=$Sys }