#!/bin/sh
# original mktexlsr -- create or rebuild ls-R.
# 
# (If you change or delete the word `original' on the previous line,
# installation won't write this script over yours.)
#
# Suitable for calling from cron, as in:
# 0 * * * * cd /your/texmf/root && /usr/local/texlive/bin/mktexlsr
# 
# Originally written as `texhash' by Thomas Esser
# <te@dbs.uni-hannover.de>, Okt., 1994.
# Public domain.

version='$Id: mktexlsr 14402 2009-07-23 17:09:15Z karl $'
progname=`echo $0 | sed 's%.*/%%'`
usage="Usage: $progname [OPTION]... [DIR]...

MKTEXLSR=true; export MKTEXLSR
set -o noclobber

Rebuild ls-R filename databases used by TeX.  If one or more arguments
DIRS are given, these are used as the directories in which to build
ls-R. Else all directories in the search path for ls-R files
(\$TEXMFDBS) are used.

Options:
  --dry-run  do not actually update anything
  --help     display this help and exit 
  --quiet    cancel --verbose
  --silent   same as --quiet
  --verbose  explain what is being done
  --version  output version information and exit
  
If standard input is a terminal, --verbose is on by default.

For more information, see the &lsquo;Filename database&rsquo; section of
Kpathsea manual available at http://tug.org/kpathsea.

Report bugs to tex-k@tug.org.
"

# MS-DOS and MS-Windows define $COMSPEC or $ComSpec and use `;' to separate
# directories in path lists whereas Unix uses `:'.  Make an exception for
# Cygwin, which pretends to be UNIX.
# Create a variable that holds the right character to be used by the scripts.
DOSISH=no
case `uname -s` in
  CYGWIN*|Cygwin*|cygwin*) ;;
  *) if test -n "$COMSPEC" || test -n "$ComSpec"; then DOSISH=yes; fi
esac
if test "$DOSISH" = "no"; then SEP=':'; else SEP=';';fi

# Add the location of the script to the PATH if necessary.  This must
# be done before kpsewhich can be called, and thus cannot be put into
# mktex.opt.
dirname=`echo $0 | sed 's%/*[^/][^/]*$%%'`
case "$SEP$PATH$SEP" in
   *$SEP$dirname$SEP*)  dirname="" ;;
esac
case $dirname in
  "") # Do nothing
      ;;
  /* | [A-z]:/*) # Absolute name
      PATH="$dirname$SEP$PATH"
      export PATH ;;
   *)  # Relative name
      PATH="`pwd`/$dirname$SEP$PATH"
      export PATH ;;
esac

# Sometimes the scripts and binaries are located elsewhere check this
# by following the links and extend the path with appropiate dirnames.
   link=`readlink -f $0`
dirname=`echo $link | sed 's%/*[^/][^/]*$%%'`
    cpu=`uname -i|tr '[:upper:]' '[:lower:]' | sed 's/ppc64/ppc/;s/i386/i?86/'`
     os=`uname -s|tr '[:upper:]' '[:lower:]'`
 binary=`echo $dirname | sed "s%share%lib%;s%noarch%${cpu}-${os}%"`
 binary=`echo $binary`
case "$SEP$PATH$SEP" in
   *$SEP$dirname$SEP*)  dirname="" ;;
esac
case $dirname in
  "") # Do nothing
       ;;
  /* | [A-z]:/*) # Absolute name
      PATH="$dirname$SEP$binary$SEP$PATH"
      export PATH ;;
   *)  # Relative name
      PATH="`pwd`/$dirname$SEP`pwd`/$binary$SEP$PATH"
      export PATH ;;
esac

if tty -s; then verbose=true; else verbose=false; fi
dry_run=false
trees=

# A copy of some stuff from mktex.opt, so we can run in the presence of
# terminally damaged ls-R files.
while test $# -gt 0; do
  if test "x$1" = x--help || test "x$1" = x-help; then
    echo "$usage"
    exit 0
  elif test "x$1" = x--version || test "x$1" = x-version; then
    echo "`basename $0` $version"
    kpsewhich --version
    exit 0
  elif test "x$1" = x--verbose || test "x$1" = x-verbose; then
    verbose=true
  elif test "x$1" = x--dry-run || test "x$1" = x-n; then
    dry_run=true
  elif test "x$1" = x--quiet || test "x$1" = x--silent \
       || test "x$1" = x-quiet || test "x$1" = x-silent ; then
    verbose=false
  elif test "x$1" = x--; then
    :
  elif echo "x$1" | grep '^x-' >/dev/null; then
    echo "$progname: unknown option $1, try --help if you need it." >&2
    exit 1
  else
    test -d "$1" || echo "$progname: $1 not a directory." >&2
    trees="$trees $1"  # don't want to update system dirs
  fi
  shift
done

# mktexupd and mktexlsr make sure they're coordinated via this.  A copy
# is found mktex.opt.
ls_R_magic='% ls-R -- filename database for kpathsea; do not change this line.'
# The old string, which should continue to work.
old_ls_R_magic='% ls-R -- maintained by MakeTeXls-R; do not change this line.'

trap 'cd /; test -z "$db_dir_tmp" || rm -rf "$db_dir_tmp"; exit' 0 1 2 3 7 13 15

# Get list of directories from $TEXMFDBS; eliminate duplicates.
{
  if test -n "$trees"; then
    set x $trees
  else
    OIFS=$IFS  # want just a newline
    IFS='
'
    set x `kpsewhich --show-path=ls-R | tr : '
' | sort | uniq`
    IFS=$OIFS
  fi
  shift
}

nobody="$(id -un nobody)"
if test "$(id -ur 2> /dev/null)" = "0" -a -n "$nobody" ; then
    grep -qE 'nobody:[^:]*:[0-9]+:0:0::::' /etc/shadow
    if test $? -eq 0 ; then
	echo "$progname: Warning the password of the user nobody has expired." >&2
	echo "          Please use program \`chage' to set maxdays to 99999." >&2
	echo ""
	exit 1
    fi
    runls () { su $nobody -s /bin/sh -c 'exec -a ls ls -LRa 2>/dev/null'; }
else
    runls () { ls -LRa 2>/dev/null; }
fi

cache="`kpsewhich --expand-var='$VARTEXFONTS'`"
for TEXMFLS_R in "$@"; do
  # Prepend cwd if the directory was relative.
  case "$TEXMFLS_R" in
  "") continue ;;  # Strictly speaking, it is an error if this case is taken.
  /* | [A-z]:/*) ;;
  *)  TEXMFLS_R="`pwd`/$TEXMFLS_R"
  esac
  # Allow for either ls-R and ls-r to exist.  But create ls-R if we're
  # working from scratch.
  if test -f "$TEXMFLS_R/ls-R"; then
    db_file="$TEXMFLS_R/ls-R"
  elif test -f "$TEXMFLS_R/ls-r"; then
    db_file="$TEXMFLS_R/ls-r"
  else
    db_file="$TEXMFLS_R/ls-R"
  fi
  # Follow a possible symlink to get the right filesystem. 
  # The '|| true' construct prevents an sh -e aborting.
  db_readlink=`kpsereadlink "$TEXMFLS_R/ls-R" 2>/dev/null` || true
  case "$db_readlink" in
  "") ;;
  /* | [A-z]:/*) db_file="$db_readlink" ;;
  *)  db_file="$TEXMFLS_R/$db_readlink"
  esac
  db_dir=`echo "$db_file" | sed 's%/[^/][^/]*$%%'` # can't rely on dirname

  # want to be silent if the directory doesn't exist, since the ls-R
  # path ordinarily contains many nonexistent directories.
  test -d "$db_dir" || continue
  if test -w "$db_dir" ; then
    # default
    db_dir_tmp="$db_dir/.lsR.XXXXXX"
  else
    # Escape to writable cache directory
    test -w "$cache" || { echo "$progname: $db_dir: directory not writable. Skipping..." >&2; continue; }
    db_dir_tmp="$cache/.lsR.XXXXXX"
  fi

  if test ! -f "$db_file"; then
    # Note: this script has set the noclobber option at line 18
    > "$db_file" \
	|| { echo "$progname: could not create file '$db_file'. Skipping..." >&2; continue; }
    # Use same permissions as parent directory, minus x,s, or t bits.
    chmod `kpsestat -xst "$db_dir"` "$db_file"
  elif test -w $db_file -a ! -s $db_file ; then
    :  Is writable but empty
  elif test -s "$db_file" \
       && test "x`sed '1s/
$//;1q' \"$db_file\"`" != "x$ls_R_magic" \
       && test "x`sed '1s/
$//;1q' \"$db_file\"`" != "x$old_ls_R_magic"; then
    echo "$progname: $db_file lacks magic string. Skipping..." >&2
    continue
  fi

  # Skip if we cannot write the file:
  kpseaccess -w "$db_file" || { echo "$progname: $db_file: no write permission. Skipping..." >&2; continue; }

  until PERMS=`kpsestat = "$db_file"`; do sleep 1; done
  if test "$PERMS" = "666" -a ! -k "$db_dir" ; then
    echo "$progname: '$db_file' world writable but '$db_dir' not sticky. Skipping..." >&2;
    continue;
  fi

  db_dir_tmp=$(mktemp -d "$db_dir_tmp") \
    || { echo "$progname: could not create directory '$db_dir_tmp'. Skipping..." >&2; continue; }
  db_file_tmp="$db_dir_tmp/lsR$$.tmp"
  rm -f "$db_file_tmp"

  $verbose && echo "$progname: Updating $db_file... " >&2
  $dry_run && continue

  # Note: this script has set the noclobber option at line 18
  echo "$ls_R_magic" >"$db_file_tmp" \
    || { echo "$progname: could not create file '$db_file_tmp'. Skipping..." >&2; continue; }

  # The main task. We put ./: in the output, so top-level files can be
  # found via ls-R. Probably irrelevant in practice.  The sed command
  # inserts the leading ./ for directory names, and removes ., .., and
  # version control entries from the list.  Also omit contents of any
  # the version directories; sed apparently requires that we do that
  # operation in a separate invocation.  We do not try to support colons
  # in directory names.
  # 
  echo "./:" >>"$db_file_tmp"
  vc_dirs='\.\(bzr\|git\|hg\|svn\)\|CVS\|RCS\|_darcs'
  (cd "$TEXMFLS_R" && \runls) \
   | sed -e '/^$/{n;s%^\./%%;s%^%./%;}; /^\.$/d; /^\.\.$/d; /^'$vc_dirs'$/d;' \
         -e '/^[\.\/]*lsR[0-9]*\.tmp:*$/d;/^[\.\/]*'${db_dir_tmp##*/}':*$/d' \
   | sed -e /$vc_dirs'.*:$/,/^$/d' \
   >>"$db_file_tmp"

  # To be really safe, a loop.
  until PERMS=`kpsestat = "$db_file"`; do sleep 1; done
  chmod $PERMS "$db_file_tmp"
  if test -O "$db_file" ; then
    # We're the owner of the $db_file
    mv "$db_file_tmp" "$db_file"
  else
    # Sticky bit is set see line 141
    # Temporary unset the noclobber option at line 20
    set +o noclobber
    cat "$db_file_tmp" > "$db_file"
    set -o noclobber
  fi
  rm -rf "$db_dir_tmp"
done
$verbose && echo "$progname: Done." >&2
exit 0
