#!/bin/sh

# usage: $0 ARCH BRANCH [-noclean] [-norestr] [-plistcheck] [-nodummy] PKGNAME.tgz DIRNAME [DEPENDENCY.tgz ...]

mount_fs()
{
    fs=$1
    mntpt=$2
    master=$3

    if [ ${disconnected} = 1 ]; then
	mount -t nullfs -r ${fs} ${mntpt}
    else
	mount -o nfsv3,intr -r ${master}:${fs} ${mntpt}
    fi
}

copypkg()
{
    pb=$1
    host=$2
    from=$3
    to=$4
    http_proxy=$5

    if [ ${host} = $(hostname) ]; then
	cp ${pb}/${arch}/${branch}/packages/All/${from} ${to}
    else
	if [ ! -z "${http_proxy}" ]; then
		env HTTP_PROXY=${http_proxy} fetch -m -o ${to} http://${host}/errorlogs/${arch}-${branch}-packages-latest/All/${from}
	else
	    fetch -m -o ${to} http://${host}/errorlogs/${arch}-${branch}-packages-latest/All/${from}
	fi
    fi
}

kill_procs()
{
  dir=$1

  pids="XXX"
  while [ ! -z "${pids}" ]; do
    pids=$(fstat -f "$dir" | tail +2 | awk '{print $3}' | sort -u)
    if [ ! -z "${pids}" ]; then
      echo "Killing off pids in ${dir}"
      ps -p $pids
      kill -KILL ${pids} 2> /dev/null
      sleep 2
    fi
  done
}

cleanup_mount() {
  chroot=$1
  mount=$2

  if [ -d ${chroot}${mount} ]; then
    mdir=$(fstat -f ${chroot}${mount} | head -2 | tail -1 | awk '{print $5}')
    if [ "${mdir}" = "MOUNT" ]; then
      umount ${chroot}${mount} || echo "Cleanup of ${chroot}${mount} failed!"
    fi
    if [ "${mdir}" = "${chroot}${mount}" ]; then
      kill_procs ${chroot}${mount}
      umount ${chroot}${mount} || echo "Cleanup of ${chroot}${mount} failed!"
    fi
  fi
}

cleanup()
{
  chroot=$1
  noclean=$2
  error=$3
  cleandirs=$4
  pkgname=$5

  #umount ${chroot}/proc

  echo ARCH=${arch}
  if [ ${arch} = "i386" ]; then
    cleanup_mount ${chroot} /compat/linux/proc
  fi

  cleanup_mount ${chroot} /a/ports
  cleanup_mount ${chroot} /usr/opt/doc
  cleanup_mount ${chroot} /usr/src
  cleanup_mount ${chroot} /dev
  test -d ${chroot}/root/.ccache && cleanup_mount ${chroot} /root/.ccache

  if [ $noclean = 0 -o $error = 0 ]; then
    rm -rf ${chroot}/tmp/*
    for dir in ${cleandirs}; do
      if ! rm -rf ${chroot}${dir} >/dev/null 2>&1; then
        chflags -R noschg ${chroot}${dir}
        rm -rf ${chroot}${dir} >/dev/null 2>&1
      fi
    done
    chroot ${chroot} /sbin/ldconfig -R
    if [ ${arch} = "i386" ]; then
	chroot ${chroot} /sbin/ldconfig -aout -R
    fi
    rm -rf ${chroot}/var/db/pkg/*
    rm ${chroot}/used/${pkgname}
    rmdir ${chroot}/used
  fi

  echo -n "$pkgname done on $(hostname) at "
  date

  exit $error
}

# configurable variables
pb=/var/portbuild

arch=$1
shift

# Default niceness value
nice=0

. ${pb}/${arch}/portbuild.conf
. ${pb}/${arch}/portbuild.$(hostname)
. ${pb}/scripts/buildenv

buildroot=${scratchdir}
error=0

branch=$1
chroot=$2
shift 2

noclean=0
if [ "x$1" = "x-noclean" ]; then
  noclean=1
  shift
fi
norestr=0
if [ "x$1" = "x-norestr" ]; then
  norestr=1
  export NO_RESTRICTED=1
  shift
fi
plistcheck=0
if [ "x$1" = "x-plistcheck" ]; then
  plistcheck=1
  export PLISTCHECK=1
  shift
fi
nodummy=0
if [ "x$1" = "x-nodummy" ]; then
  nodummy=1
  export NODUMMY=1
  shift
fi
nodistfiles=1
if [ "x$1" = "x-distfiles" ]; then
  nodistfiles=0
  shift
fi
if [ "x$1" = "x-fetch-original" ]; then
  export FETCH_ORIGINAL=1
  shift
fi
if [ "x$1" = "x-trybroken" ]; then
  export TRYBROKEN=1
  shift
fi

ED=$1
PD=$2
FD=$3
BD=$4
RD=$5

buildenv ${pb} ${arch} ${branch}

# Want to use the /etc/make.conf in the chroot
unset __MAKE_CONF

pkgname=$(basename $6 ${PKGSUFFIX})
dirname=$7
shift 2

echo $pkgname
echo $dirname

export WRKDIRPREFIX=/tmp
export DISTDIR=/tmp/distfiles
export PACKAGES=/tmp/packages

# to catch missing dependencies
#export DEPENDS_TARGET=/usr/bin/true

# don't pass -j, -k etc. to sub-makes
unset MAKEFLAGS
unset PORTSDIR

# wait 1 hour before killing build with no output
export TIMEOUT=7200

# to prevent runaway processes -- 256 meg file size limit, one hour CPU limit
ulimit -f 524288
ulimit -t 3600

# directories to clean
cleandirs="/usr/local /usr/X11R6 /compat /var/db/pkg"

# 15 minutes
export FTP_TIMEOUT=900
export HTTP_TIMEOUT=900

export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/usr/X11R6/bin

echo "building $pkgname in $chroot"

bakdir=${pb}/${arch}/${branch}/tarballs
bindist=${buildroot}/${branch}/tarballs/bindist.tar
bindistlocal=${buildroot}/${branch}/tarballs/bindist-$(hostname).tar
packages=${pb}/${arch}/${branch}/packages

if [ -f ${chroot}/.notready ]; then
  tar -C ${chroot} -xpf ${bindist}
  if [ -f ${bindistlocal} ]; then
    tar -C ${chroot} -xpf ${bindistlocal}
  fi

  # to be able to run ps and killall inside chroot area
  if [ "${branch}" = "4" -o "${branch}" = "4-exp" ]; then
    mkdir -p ${chroot}/libexec
    mkdir -p ${chroot}/lib
    if [ "${arch}" = "i386" ]; then
      cp -p /sbin/mount_linprocfs /sbin/mount /sbin/umount ${chroot}/sbin
      cp -p /lib/libufs.so.2 ${chroot}/lib
    fi
    cp -p /libexec/ld-elf.so.1 ${chroot}/libexec
    cp -p /lib/libkvm.so.2 /lib/libm.so.3 ${chroot}/lib
    if [ -f /lib/libc.so.6 ]; then
      cp -p /lib/libc.so.6 ${chroot}/lib
    else
      cp -p /lib/libc.so.5 ${chroot}/lib
    fi
  elif [ "${branch}" = "6" ]; then
    cp -p /lib/libc.so.5 ${chroot}/lib
  fi
  cp -p /rescue/ps ${chroot}/bin
  cp -p /usr/bin/killall ${chroot}/usr/bin
  rm ${chroot}/.notready
  touch ${chroot}/.ready
fi

# Figure out jail IP addr
#chrootpid=$(basename ${chroot})
#ip1=$(($chrootpid /(256*256)))
#ip2=$((($chrootpid - ($ip1*256*256)) /256))
#ip3=$((($chrootpid - ($ip1*256*256) - ($ip2*256))))

# Set up desired uname version
echo ${OSREL}-${BRANCH} > ${chroot}/usr/bin/UNAME_VERSION

#trap "cleanup ${chroot} ${noclean} ${error} \"${cleandirs}\" ${pkgname}" 1 2 3 9 10 11 15
trap "exit 255" 1 2 3 9 10 11 15

rm -rf ${chroot}/tmp/*
cd ${chroot}/tmp
mkdir -p depends distfiles packages

echo "building ${pkgname} on $(hostname)" | tee ${chroot}/tmp/${pkgname}.log
echo "in directory ${chroot}" | tee -a ${chroot}/tmp/${pkgname}.log

# intentionally set up ${PORTSDIR} with symlink to catch broken ports
mkdir -p ${chroot}/a/ports
rm -rf ${chroot}/usr/ports

if [ ! -z "${ccache_dir}" ]; then
  mkdir -p ${chroot}/root/.ccache/
  mount -o rw -t nullfs ${ccache_dir} ${chroot}/root/.ccache/
fi

mount_fs ${pb}/${arch}/${branch}/ports ${chroot}/a/ports ${master}
ln -sf ../a/ports ${chroot}/usr/ports

mkdir -p ${chroot}/usr/src ${chroot}/usr/opt/doc

mount_fs ${pb}/${arch}/${branch}/src ${chroot}/usr/src ${master}
mount_fs ${pb}/${arch}/${branch}/doc ${chroot}/usr/opt/doc ${master}

mount -t devfs foo ${chroot}/dev

umount -f ${chroot}/compat/linux/proc > /dev/null 2>&1

# just in case...
for dir in ${cleandirs}; do
  if ! rm -rf ${chroot}${dir} >/dev/null 2>&1; then
    chflags -R noschg ${chroot}${dir}
    rm -rf ${chroot}${dir} >/dev/null 2>&1
  fi
done

rm -rf ${chroot}/var/db/pkg/*

mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.root.dist -p ${chroot} \
  >/dev/null 2>&1
mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.var.dist -p ${chroot}/var \
  >/dev/null 2>&1
mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.usr.dist -p ${chroot}/usr \
  >/dev/null 2>&1
mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.local.dist -p ${chroot}/usr/local \
  >/dev/null 2>&1

mkdir ${chroot}/usr/X11R6
if [ $X_WINDOW_SYSTEM = "xfree86-3" ]; then
  mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.x11.dist -p ${chroot}/usr/X11R6 \
    >/dev/null 2>&1
else
  mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.x11-4.dist -p ${chroot}/usr/X11R6 \
    >/dev/null 2>&1
fi

if [ ${arch} = "i386" ]; then
  # JDK ports need linprocfs :(
  mkdir -p ${chroot}/compat/linux/proc
  chroot ${chroot} mount_linprocfs linprocfs /compat/linux/proc
fi

_ldconfig_dirs="/lib /usr/lib /usr/lib/compat"
ldconfig_dirs=""
for i in ${_ldconfig_dirs}; do
  if [ -d ${chroot}/${i} ]; then
    ldconfig_dirs="${ldconfig_dirs} ${i}"
  fi
done
chroot ${chroot} /sbin/ldconfig ${ldconfig_dirs}
if [ ${arch} = "i386" ]; then
	chroot ${chroot} /sbin/ldconfig -aout /usr/lib/aout /usr/lib/compat/aout
fi

set x $ED $FD $PD $BD $RD
shift 1
while [ $# -gt 0 ]; do
  if [ ! -f ${chroot}/tmp/depends/$1 ]; then
    echo "copying package $1 for ${pkgname}"
    copypkg ${pb} ${master} $1 ${chroot}/tmp/depends "${http_proxy}"
  fi
  shift
done

cp -p ${pb}/scripts/buildscript ${chroot}
cp -p ${pb}/scripts/pnohang.${arch} ${chroot}/pnohang

# phase 1, make checksum
# Needs to be chroot not jail so that port can be fetched
chroot ${chroot} /buildscript ${dirname} 1 "$ED" "$PD" "$FD" "$BD" "$RD" 2>&1 | tee -a ${chroot}/tmp/${pkgname}.log
if [ -f ${chroot}/tmp/status ]; then
  error=$(cat ${chroot}/tmp/status)
else
  error=255
fi

if [ "${error}" = 0 ]; then
# make checksum succeeded
# phase 2, make package
  ln -sf ${pkgname}.log2 ${chroot}/tmp/make.log

#  ifconfig lo0 alias 10.${ip1}.${ip2}.${ip3}/32
#  jail ${chroot} jail-${chroot} 10.${ip1}.${ip2}.${ip3} /usr/bin/nice -n $nice /buildscript ${dirname} 2 > ${chroot}/tmp/${pkgname}.log2 2>&1
#  ifconfig lo0 delete 10.${ip1}.${ip2}.${ip3}
  chroot ${chroot} /usr/bin/nice -n $nice /buildscript ${dirname} 2 "$ED" "$PD" "$FD" "$BD" "$RD" > ${chroot}/tmp/${pkgname}.log2 2>&1

  grep pnohang ${chroot}/tmp/${pkgname}.log2
  cat ${chroot}/tmp/${pkgname}.log2 >> ${chroot}/tmp/${pkgname}.log
  rm ${chroot}/tmp/${pkgname}.log2
  error=$(cat ${chroot}/tmp/status)
fi

exit $error
