#!/bin/sh # Thomas Esser, 1999, 2002, 2003. public domain. # texlinks: script to maintain symlinks from format to engine. Interprets # the lines given in fmtutil.cnf. # History: # Tue Oct 9 14:23:01 BST 2007 # Added unlink option (-u) to aid OpenBSD package uninstall # Edd Barrett # Sun Aug 28 21:41:06 CEST 2005 # remove special cases for csplain,cslatex,pdfcslatex,pdfcsplain # Fr Apr 8 19:15:05 CEST 2005 # cleanup now has an argument for the return code # So Mär 27 18:52:06 CEST 2005 # honor $TMPDIR, $TEMP and $TMP, not just $TMP # Mon May 10 20:52:48 CEST 2004 # kpseaccess instead of access # Thu Dec 25 22:11:53 CET 2003, te: # add version string # Tue Apr 9 22:46:34 CEST 2002, te: # do not create symlinks for cont-??, metafun and mptopdf test -f /bin/sh5 && test -z "$RUNNING_SH5" \ && { UNAMES=`uname -s`; test "x$UNAMES" = xULTRIX; } 2>/dev/null \ && { RUNNING_SH5=true; export RUNNING_SH5; exec /bin/sh5 $0 ${1+"$@"}; } unset RUNNING_SH5 test -f /bin/bsh && test -z "$RUNNING_BSH" \ && { UNAMES=`uname -s`; test "x$UNAMES" = xAIX; } 2>/dev/null \ && { RUNNING_BSH=true; export RUNNING_BSH; exec /bin/bsh $0 ${1+"$@"}; } unset RUNNING_BSH export PATH # hack around a bug in zsh: test -n "${ZSH_VERSION+set}" && alias -g '${1+"$@"}'='"$@"' cnf=fmtutil.cnf # name of the config file version=1192147136 # seconds since `00:00:00 1970-01-01 UTC' # date '+%s' (with GNU date) progname=texlinks usage='Usage: texlinks [OPTION]... [DIRECTORY]... Create symbolic links format -> engine according to fmtutil setup. Mandatory arguments to long options are mandatory for short options too. -h, --help show this help text --version show version string -f, --cnffile FILE use FILE as config file (default: fmtutil.cnf) -v, --verbose enable verbose messages (default: off) -m, --multiplatform operate in all platform specific directories (default: operate only in directory for this platform) -s, --silent silently skip existing scripts / binaries (default: issue warning) -u, --unlink remove symlinks created by texlinks The DIRECTORY arguments are an optional list of directories in which to operate. If no directories are specified the list of directories depends on the --multiplatform option. Report bugs to tex-k@tug.org.' ############################################################################### # abort(errmsg) # print `errmsg' to stderr and exit with error code 1 ############################################################################### abort() { errmsg "texlinks: $1."; cleanup 1; } # error message to stderr: errmsg() { echo "$@" >&2; } # give message to stderr only if "verbose" mode is on: verbose_echo() { $verbose && errmsg "$@"; } # in verbose mode: show command that is executed: verbose_do() { verbose_echo "$@"; "$@"; } ############################################################################### # cleanup() # clean up the temp area and exit with proper exit status ############################################################################### cleanup() { rc=$1 $needsCleanup && test -n "$tmpdir" && test -d "$tmpdir" \ && { rm -f "$tmpdir"/*; cd /; rmdir "$tmpdir"; } exit $rc } ############################################################################### # setupTmpDir() # set up a temp directory and a trap to remove it ############################################################################### setupTmpDir() { $needsCleanup && return trap 'cleanup 1' 1 2 3 7 13 15 needsCleanup=true (umask 077; mkdir "$tmpdir") \ || abort "could not create directory \`$tmpdir'" } # search a binary along $PATH: check_for_binary() { testbin=$1 set x `echo "$PATH" | sed 's/^:/.:/; s/:$/:./; s/::/:.:/g; s/:/ /g'`; shift for i do if [ -x "$i/$testbin" ]; then echo "$i/$testbin" return 0 fi done return 1 } ############################################################################### # install_link(dest src) # create a symlink like ln -s dest src, but make sure that src is not # an existing binary ############################################################################### install_link() { # make symlink src -> dest dest=$1; src=$2 case $src in */mf) if test "$dest" = mf-nowin; then if test -f $selfautoloc/mfw; then dest=mfw # name for windows-enabled mf, once upon a time verbose_echo "both mfw and mf-nowin exists, $src linked to $dest" fi if test -f $selfautoloc/mf && test -f $selfautoloc/mf-nowin; then # have both mf and mf-nowin binaries. no link. verbose_echo "skipped metafont symlink $src -> $dest (special case)" return fi fi ;; esac case $src in */cont-??|*/metafun|*/mptopdf) verbose_echo "skipped ConTeXtish symlink $src -> $dest (special case)" ;; *) test "x$src" != "x`(ls -ld $src | awk '{print $NF}') 2>/dev/null`" && verbose_do rm -f "$src" if test -f "$src"; then case $silent in true) ;; *) errmsg "install_link $src -> $dest failed: file already exists." ;; esac else verbose_do ln -s "$dest" "$src" fi ;; esac } ############################################################################### # search_symlinkdir() # look if $PATH has only symlinks to the real binaries and find that # directory. Also check if this directory is writable. ############################################################################### search_symlinkdir() { kpsewhich=`check_for_binary kpsewhich` test -z "$kpsewhich" && return 1 symlinkdir=`echo $kpsewhich | sed 's@/*kpsewhich$@@'` kpseaccess -w "$symlinkdir" || return 1 touch "$symlinkdir/tl$$" if test -f "$selfautoloc/tl$$"; then rm -f "$symlinkdir/tl$$" return 1 else rm -f "$symlinkdir/tl$$" return 0 fi } ############################################################################### # upd_symlinkdir() # if $PATH has only symlinks to the real binaries, update that directory # that holds the symlinks ############################################################################### upd_symlinkdir() { search_symlinkdir || return 0 for i in `sed 's@ .*@@' cnf_file_ln.$$`; do install_link "$selfautoloc/$i" "$symlinkdir/$i" done } ############################################################################### # rm_link() # Delete a previously installed link ############################################################################### rm_link() { link=$1; if test -e $link; then if test -h $link; then verbose_do rm -Rf $link else verbose_echo "kept $link, since not a symlink" fi else verbose_echo "skipped $link, non-existent" fi } ############################################################################### # main() # parse commandline arguments, initialize variables, # switch into temp. direcrory, execute desired command ############################################################################### main() { cnf_file= # global variable: full name of the config file dirs= needsCleanup=false multiplatform=false verbose=false unlink=false silent=false thisdir=`pwd` : ${KPSE_DOT=$thisdir}; export KPSE_DOT selfautoloc=`kpsewhich --expand-var='$SELFAUTOLOC'` while case $1 in --h*|-h) echo "$usage"; exit 0;; --version) echo "$progname version $version."; exit 0;; --cnffile|-f) shift; cnf_file=$1;; --v*|-v) verbose=true;; --s*|-s) silent=true;; --m*|-m) multiplatform=true;; --u*|-u) unlink=true;; -*) errmsg "fmtutil: unknown option \`$1' ignored.";; *) break;; esac do test $# -gt 0 && shift; done dirs="$*" # if no cnf_file from command-line, look it up with kpsewhich: test -z "$cnf_file" && cnf_file=`kpsewhich --format='web2c files' $cnf` test -f "$cnf_file" || abort "config file \`$cnf' not found" tmpdir=${TMPDIR-${TEMP-${TMP-/tmp}}}/texlinks.$$ setupTmpDir cd "$tmpdir" || cleanup 1 sed '/^[ ]*#/d; /^[ ]*$/d' $cnf_file \ | awk '{print $1, $2}' > cnf_file_ln.$$ if test -z "$dirs"; then if test $multiplatform = true; then case $selfautoloc in */bin) dirs=$selfautoloc;; *) parent=`kpsewhich --expand-var='$SELFAUTODIR'` dirs=`find $parent -type f -name kpsewhich -print \ | sed 's@/kpsewhich$@@'`;; esac else dirs=$selfautoloc fi fi for d in $dirs; do kpseaccess -w $d \ || { errmsg "$d: no write permissions. Skipping..."; continue; } # cnf_file_ln.$$ has lines with "format engine" pairs set x `cat cnf_file_ln.$$`; shift while test $# != 0; do fmt=$1; engine=$2; shift; shift # Some broken shells destroy the positional arguments when calling a # shellfunction. Therefore, we save and restore them "by hand" in the # main_args_while variable. main_args_while="$@" test "x$fmt" = "x$engine" && continue if test -f "$d/$engine"; then case $unlink in true) rm_link "$d/$fmt";; *) install_link "$engine" "$d/$fmt";; esac else verbose_echo "skipped $d/$engine, engine does not exist" fi # restore positional arguments: set x $main_args_while; shift done done upd_symlinkdir } main ${1+"$@"} # set successful return code cleanup 0