#!/bin/sh

USER=vscan
GROUP=vscan

# check stat version (3.0 or 5.X?)
if stat -L -c %d.%i / > /dev/null 2>&1; then
  STAT_PARAMS="-L -c %d.%i"
elif stat -L -f %d.%i / > /dev/null 2>&1; then
  STAT_PARAMS="-L -f %d.%i"
else
  STAT_PARAMS="-c %d.%i"
fi

samefile() {
  if [ "`stat $STAT_PARAMS $1`" = "`stat $STAT_PARAMS $2`" ]; then
    return 0
  fi >/dev/null 2>&1
  return 1
}

addfile() {
  cp -pPRf $1 $ROOTPATH/$1 $2
}

addbin() {
  n=0
  for file in "$@"; do
    if [ -f $file ]; then
      n=`expr $n + 1`
      cp -f $file $ROOTPATH/$file
      if ldd $file > /dev/null 2>&1 ; then
        for i in `ldd $file 2>/dev/null | awk '/=> *\(/ {next} {print $3}'`
        do
          mkdir -p "$ROOTPATH/`dirname $i`"
          cp -f "$i" "$ROOTPATH/$i"
        done
      fi
    fi
  done
  if [ "$n" = "0" ]; then
    wecho "Warning: Missing command(s): $@"
  fi
}

addconf() {
  for file in "$@"; do
    if [ -f "$file" ]; then
      if [ "$FORCE" = "YES" ]; then
        addfile $file
      elif [ -f "$ROOTPATH$file" ]; then
        samefile "$file" "$ROOTPATH$file" \
          || wecho "Warning: $file found in $ROOTPATH, update skipped!"
      else
        addfile $file
      fi
    fi
  done
}

adduser() {
  grep ^$1: /etc/passwd >> $ROOTPATH/etc/passwd
}

addgroup() {
  grep ^$1: /etc/group | sed -e 's/:[^:]*$/:/g' >> $ROOTPATH/etc/group
}

addnod() {
  if [ ! -$2 "$ROOTPATH$1" ]; then
    rm -f "$ROOTPATH$1"
    mknod "$ROOTPATH$1" $2 $3 $4
  fi
  chmod $5 "$ROOTPATH$1"
}

wecho() {
  echo "$@"
}

showhelp() {
  echo "Usage:"
  echo "  `basename $0` [chroot_directory] [--mount] [--umount]\\"
  echo "              [--auto] [--help] [--quiet]\\"
  echo "              [--clamav] [--nod] [--esets] [--avg] [--kav] [--bdc]\\"
  echo "              [--bogofilter] [--qsf]\\"
  echo "              [--check filename]"
  echo ""
  echo "Where:"
  echo "  --mount      - mount clamav to chroot"
  echo "  --umount     - umount clamav from chroot"
  echo "  --auto       - select all options automatically"
  echo "  --help       - show this help"
  echo "  --quiet      - be quiet (do not show warnings)"
  echo "  --force      - overwrite configuration files"
  echo "  --clamav     - install clamav"
  echo "  --nod        - install nod32"
  echo "  --esets      - install esets"
  echo "  --avg        - install avglinux"
  echo "  --kav        - install kaspersky"
  echo "  --bdc        - install bitdefender"
  echo "  --bogofilter - install bogofilter"
  echo "  --qsf        - install quick spam filter"
  echo "  --check      - skip chroot update if lock file is missing"
  exit
}

if [ "$1" ]; then
  if echo "$1" | grep -q ^/. >/dev/null; then
    export ROOTPATH="$1"
    shift 1
  else
    eval `grep "^ *CHROOT *=" /etc/sagator.conf \
            | sed 's/^ *CHROOT *= */CHROOT=/'`
    if [ -z "$CHROOT" ]; then
      echo "Chroot not set, skipping mkchroot!"
      showhelp
      exit
    fi
    export ROOTPATH="$CHROOT"
    echo "Updating sagator's chroot at $CHROOT ..."
  fi
else
  showhelp
fi

# is it a real chroot?
if samefile /etc/passwd "$ROOTPATH/etc/passwd"; then
  echo "Chroot is set to real root! Skipping mkchroot!"
  exit 0
fi

# make directory structure
for i in dev etc bin sbin proc tmp/scand \
         var/spool/sagator/quarantine \
         usr/share/sagator usr/lib usr/bin usr/sbin usr/share/cracklib \
         var/log/sagator var/lib/sagator var/spool var/run \
         var/log/dspam var/lib/dspam; do
  mkdir -p "$ROOTPATH/$i"
done
# symlink for lib, lib64
for lib in lib lib64 usr/lib usr/lib64; do
  if [ -d /$lib ]; then
    if [ -h /$lib -a ! -h $ROOTPATH/$lib ]; then
      if [ -d $ROOTPATH/$lib ]; then
        if [ ! -d $ROOTPATH/usr/$lib ]; then
          mkdir -p $ROOTPATH/usr/$lib
        fi
        echo "Moving contents of $ROOTPATH/$lib to $ROOTPATH/usr/$lib ..."
        mv $ROOTPATH/$lib/* $ROOTPATH/usr/$lib
        rmdir $ROOTPATH/$lib
      fi
      ln -s $(readlink /$lib) "$ROOTPATH/$lib"
    else
      mkdir -p "$ROOTPATH"/$lib
    fi
  fi
done
if [ ! -h /var/log/sagator ]; then
  if [ -d /var/log/sagator ]; then
    rmdir /var/log/sagator
  fi
  ln -sf "$ROOTPATH/var/log/sagator" /var/log/
fi
#if [ ! -e /var/spool/quarantine -a -d "$ROOTPATH/var/spool/quarantine" ]; then
#  ln -sf "$ROOTPATH/var/spool/quarantine" /var/spool/
#fi
if [ ! -e /var/spool/sagator -a -d "$ROOTPATH/var/spool/sagator" ]; then
  ln -sf "$ROOTPATH/var/spool/sagator" /var/spool/
fi
ln -sf ../tmp "$ROOTPATH/var/"
# recursive symlink in chroot
if [ ! -e $ROOTPATH$ROOTPATH ]; then
  mkdir -p `dirname $ROOTPATH$ROOTPATH`
  ln -s / $ROOTPATH$ROOTPATH
fi

cat > "$ROOTPATH/etc/nsswitch.conf" <<EOF
passwd:     files
shadow:     files
group:      files

hosts:      files dns

ethers:     files
netmasks:   files
networks:   files
protocols:  files
rpc:        files
services:   files
EOF

cat > "$ROOTPATH/etc/hosts" <<EOF
127.0.0.1	localhost.localdomain localhost
EOF

rm -f "$ROOTPATH/etc/passwd"
adduser root
adduser $USER

rm -f "$ROOTPATH/etc/group"
addgroup root
addgroup $GROUP

addfile /etc/resolv.conf
rm -f "$ROOTPATH/etc/localtime" # remove broken symlink
addfile /etc/localtime --dereference --force 2> /dev/null

unset FORCE CLAMAV NOD AVG BOGOFILTER QSF BDC KAV
for arg in "$@"; do
  if [ "$arg" = "--quiet" ]; then
    wecho() {
      return
    }
  elif [ "$arg" = "--force" ]; then
    FORCE="YES"
  elif [ "$arg" = "--mount" ]; then
    if [ ! "/var/lib/clamav" -ef "$CHROOT/var/lib/clamav" ]; then
      mount -n --bind /var/lib/clamav $CHROOT/var/lib/clamav \
        > /dev/null 2>&1
    fi
  elif [ "$arg" = "--umount" ]; then
    # try to umount chroot
    umount $CHROOT/var/lib/clamav 2>/dev/null || true
  elif [ "$arg" = "--check" ]; then
    if [ -f /var/lib/sagator-mkchroot ]; then
      rm -f /var/lib/sagator-mkchroot
    else
      # exit now, no need to update chroot
      exit 0
    fi
  elif [ "$arg" = "--auto" ]; then
    if [ ! "`echo /usr/lib*/libclamav.so*`" = '/usr/lib*/libclamav.so*' ]; then
      CLAMAV="YES"
    fi
    if [ -x /opt/nod32/nod32d -o -d /etc/nod32 ]; then
      NOD="YES"
    fi
    if [ -x /opt/esets/esets_daemon -o -d /etc/esets ]; then
      ESETS="YES"
    fi
    if [ -x /opt/bdc/bdc ]; then
      BDC="YES"
    fi
    if ls /opt/kav/*/*/bin/kavscanner >/dev/null 2>/dev/null; then
      KAV="YES"
    fi
    if [ -x /usr/local/bin/avgscan -o -x /opt/grisoft/avg7/bin/avgscan ]; then
      AVG="YES"
    fi
    if [ -x /usr/bin/bogofilter ]; then
      BOGOFILTER="YES"
    fi
    if [ -x /usr/bin/qsf ]; then
      QSF="YES"
    fi
  elif [ "$arg" = "--help" ]; then
    showhelp
  elif [ "$arg" = "--clamav" ]; then
    CLAMAV="YES"
  elif [ "$arg" = "--nod" ]; then
    NOD="YES"
  elif [ "$arg" = "--esets" ]; then
    ESETS="YES"
  elif [ "$arg" = "--avg" ]; then
    AVG="YES"
  elif [ "$arg" = "--kav" ]; then
    KAV="YES"
  elif [ "$arg" = "--bdc" ]; then
    BDC="YES"
  elif [ "$arg" = "--bogofilter" ]; then
    BOGOFILTER="YES"
  elif [ "$arg" = "--qsf" ]; then
    QSF="YES"
  else
    addbin "$arg"
  fi
done

if [ "$CLAMAV" ]; then
  if id -u clamav > /dev/null 2> /dev/null; then
    CLAM_USER='clamav'
  else
    CLAM_USER='vscan'
  fi
  if id -g clamav > /dev/null 2> /dev/null; then
    CLAM_GROUP='clamav'
  else
    CLAM_GROUP='vscan'
  fi
  CLAM_GROUP='clamav'
  adduser $CLAM_USER
  addgroup $CLAM_GROUP
  addbin /usr/bin/clam*scan
  addbin /usr/sbin/clamd
  if [ -d /etc/clamav ]; then
    mkdir -p "$ROOTPATH/etc/clamav"
    addconf /etc/clamav/clamav.conf
    addconf /etc/clamav/clamd.conf
  else
    addconf /etc/clamav.conf
    addconf /etc/clamd.conf
  fi
  mkdir -p "$ROOTPATH/var/log/clamav" "$ROOTPATH/var/run/clamav"
  for clamavdir in /var/lib/clamav /var/clamav; do
    if [ -d $clamavdir ]; then
      mkdir -p "$ROOTPATH$clamavdir"
    fi
  done
  [ "`id -u`" = "0" ] && chown -R $CLAM_USER:$GROUP \
    "$ROOTPATH/var/run/clamav" "$ROOTPATH/var/log/clamav"
  chmod 770 "$ROOTPATH/var/run/clamav"
fi
if [ "$NOD" ]; then
  # NOD2
  if [ -d /etc/nod32 ]; then
    mkdir -p "$ROOTPATH/etc/nod32/license"
    addconf /etc/nod32/license/*
    addconf /etc/nod32/nod32.cfg
    addbin /usr/sbin/nod32*
    addbin /usr/lib*/libnod32pac.so
    samefile /var/lib/nod32 "$ROOTPATH/var/lib/nod32" \
      || cp -rf /var/lib/nod32 "$ROOTPATH/var/lib/"
  fi
fi
if [ "$ESETS" ]; then
  # ESETS
  if [ -d /etc/esets ]; then
    mkdir -p "$ROOTPATH/etc/esets/license"
    addconf /etc/esets/license/*
    addconf /etc/esets/esets.cfg
    addbin /usr/sbin/esets*
    addbin /usr/lib*/libesets_pac.so
    samefile /var/lib/esets "$ROOTPATH/var/lib/esets" \
      || cp -rf /var/lib/esets "$ROOTPATH/var/lib/"
  fi
fi
if [ "$AVG" ]; then
  if [ -x /opt/grisoft/avg7/bin/avgscan ]; then
    mkdir -p $ROOTPATH/opt/grisoft/avg7/{etc,bin,data,var/run}
    addconf /opt/grisoft/avg7/etc/avg.conf
    ln -s /opt/grisoft/avg7/etc/avg.conf $ROOTPATH/etc/avg.conf 2>/dev/null
    addbin /opt/grisoft/avg7/bin/*
    cp -rf /opt/grisoft/avg7/data /opt/grisoft/avg7/var \
      $ROOTPATH/opt/grisoft/avg7/
    chown -R $USER:$GROUP "$ROOTPATH/opt/grisoft/avg7"
    samefile /opt/grisoft/avg7/data "$ROOTPATH/opt/grisoft/avg7/data" \
      || wecho "Warning: Do not forget to update AVG database in $ROOTPATH !"
  else
    mkdir -p "$ROOTPATH/usr/local/bin" "$ROOTPATH/usr/local/lib/avg7"
    addconf /etc/avg.conf
    addbin /usr/local/lib/avg7/avgscan
    addbin /usr/local/lib/avg7/avgupdate
    cp -f /usr/local/lib/avg7/*.* "$ROOTPATH/usr/local/lib/avg7/"
    chown -R $USER:$GROUP "$ROOTPATH/usr/local/lib/avg7"
    samefile "/usr/local/lib/avg7" "$ROOTPATH/usr/local/lib/avg7" \
      || wecho "Warning: Do not forget to update AVG database in $ROOTPATH !"
  fi
fi
if [ "$BDC" ]; then
  mkdir -p "$ROOTPATH/opt/"
  cp -rf /opt/bdc "$ROOTPATH/opt/"
  for i in bdc bdcore.so bdupd.so libfn.so; do
    addbin /opt/bdc/$i
  done
  samefile "/opt/bdc" "$ROOTPATH/opt/bdc" \
    || wecho "Warning: Do not forget to update BDC database in $ROOTPATH !"
  [ -f $ROOTPATH/proc/version ] \
    || wecho "Warning: You need to mount /proc also as $ROOTPATH/proc !"
fi
if [ "$KAV" ]; then
  mkdir -p "$ROOTPATH/opt/"
  mkdir -p "$ROOTPATH/var/db/"
  mkdir -p "$ROOTPATH/var/log/kav"
  chmod 1777 "$ROOTPATH/var/log/kav"
  if [ -d "$ROOTPATH/etc/kav" ]; then
    wecho "Warning: KAV configuration directory already exists, skipping overwrite!"
  else
    cp -pPRf /etc/kav "$ROOTPATH/etc"
  fi
  cp -pPRf /opt/kav "$ROOTPATH/opt/"
  cp -pPRf /var/db/kav "$ROOTPATH/var/db/"
  if [ -d "$ROOTPATH/var/log/kav" ]; then
    cp -pPRf /var/log/kav "$ROOTPATH/var/log/"
  fi
  chmod 666 $ROOTPATH/var/db/kav/5.0/kav4*/keys/application.dat
  samefile "/var/db/kav" "$ROOTPATH/var/db/kav" \
    || wecho "Warning: Do not forget to update KAV database in $ROOTPATH !"
  # create cyclic symlink for chroot
  if [ ! -e "$ROOTPATH$ROOTPATH" ]; then
    mkdir -p `dirname $ROOTPATH$ROOTPATH`
    ln -s / "$ROOTPATH$ROOTPATH"
  fi
fi
if [ "$BOGOFILTER" ]; then
  addbin /usr/bin/bogofilter
  addfile /etc/bogofilter.cf
  echo "bogofilter_dir=/usr/share/bogofilter" >> "$ROOTPATH/etc/bogofilter.cf"
  mkdir -p "$ROOTPATH/usr/share/bogofilter"
  wecho "Run: 'chroot $ROOTPATH /usr/bin/bogofilter -s SPAM -n NOSPAM' to learn"
fi
if [ "$QSF" ]; then
  addbin /usr/bin/qsf
  wecho "Run: Update for QuickSpamFilter database"
fi

echo "/usr/lib" > "$ROOTPATH/etc/ld.so.conf"
if [ "$BDC" ]; then
  echo "/opt/bdc" >> "$ROOTPATH/etc/ld.so.conf"
fi

# cracklib
for i in /usr/share/cracklib/*; do
  [ -e $i ] && addfile $i;
done

# locales
for i in /usr/share/locale/*/LC_MESSAGES/sagator.mo \
         /usr/share/locale/*/LC_MESSAGES/cracklib.mo
do
  if [ -e $i ]; then
    mkdir -p `dirname $ROOTPATH/$i`
    cp -pLRf $i $ROOTPATH/$i
  fi
done
# gconv required for some antivirus, like clamav
for libdir in /usr/lib64 /usr/lib; do
  if [ -d $libdir/gconv ]; then
    cp -arf $libdir/gconv $ROOTPATH$libdir/
  fi
done

# make required devices
addnod "/dev/null" c 1 3 0666
addnod "/dev/zero" c 1 5 0666
addnod "/dev/urandom" c 1 9 0444

if [ -x /usr/sbin/ldconfig ]; then
  addbin /usr/sbin/ldconfig /etc/ld.so.conf
else
  addbin /sbin/ldconfig /etc/ld.so.conf
fi
if [ -f /lib/ld-linux.so.2 ]; then
  # Linux 32-bit
  addbin /lib/ld-linux.so.2 /lib/libdl.so.2
  addbin /lib/libnss_files.so.2 /lib/libnss_dns.so.2
fi
if [ -f /lib64/ld-linux-x86-64.so.2 ]; then
  # Linux 64-bit
  addbin /lib64/ld-linux-x86-64.so.2 /lib64/libdl.so.2
  addbin /lib64/libnss_files.so.2 /lib64/libnss_dns.so.2
fi

if [ -d /libexec ]; then
  # FreeBSD libexec directory
  mkdir -p "$ROOTPATH/libexec"
  addbin /libexec/*
fi

# add archivers
addbin /bin/gzip /usr/bin/gzip
addbin /bin/bzip2 /usr/bin/bzip2
addbin /bin/tar /usr/bin/tar
#addbin /usr/bin/compress /bin/compress
for i in zip lha rar arj zoo ace arc; do
  [ -x /usr/bin/$i ] && addbin /usr/bin/$i
  [ -x /usr/bin/un$i ] && addbin /usr/bin/un$i
done

# create user directories for spamassassin
mkdir -p "$ROOTPATH/.spamassassin" "$ROOTPATH/.pyzor" "$ROOTPATH/.razor"

chroot "$ROOTPATH" ldconfig

chmod 1777 "$ROOTPATH/tmp"
chmod 770 "$ROOTPATH/var/spool/sagator" \
          "$ROOTPATH/tmp/scand" "$ROOTPATH/var/lib/sagator"
if [ "`id -u`" = "0" ]; then
  chown -R $USER:$GROUP \
    "$ROOTPATH/var/log/sagator" "$ROOTPATH/var/lib/sagator" \
    "$ROOTPATH/.spamassassin" "$ROOTPATH/.pyzor" "$ROOTPATH/.razor" \
    "$ROOTPATH/var/log/dspam" "$ROOTPATH/var/lib/dspam" \
    "$ROOTPATH/tmp/scand"
  # do not use recursive chroot on quarantine, too slow
  chown $USER:$GROUP \
    "$ROOTPATH/var/spool/sagator" \
    "$ROOTPATH/var/spool/sagator/quarantine"
fi

# Remove badly created files
[ ! -h "$ROOTPATH/tmp/tmp" ] || rm -f "$ROOTPATH/tmp/tmp"

# Return successful exit status
exit 0
