#!/bin/sh

# usage: $0 ARCH BRANCH [-noclean] [-norestr] [-noplistcheck] [-distfiles] [-fetch-original] [-trybroken] 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_nfs -o ro -3 -i ${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
}

bailout()
{
  chroot=$1
  clean=$2
  error=$3
  pkgname=$4

  echo -n "$pkgname failed unexpectedly 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

clean=1
if [ "x$1" = "x-noclean" ]; then
  clean=0
  shift
fi
norestr=0
if [ "x$1" = "x-norestr" ]; then
  norestr=1
  export NO_RESTRICTED=1
  shift
fi
noplistcheck=0
if [ "x$1" = "x-noplistcheck" ]; then
  noplistcheck=1
  export NOPLISTCHECK=1
  shift
fi
nodistfiles=1
if [ "x$1" = "x-distfiles" ]; then
  export ALWAYS_KEEP_DISTFILES=1
  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=/work
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
export SRCBASE=/usr/src

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

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

# directories to clean
cleandirs="${LOCALBASE} ${X11BASE} /compat /var/db/pkg"

# 15 minutes
export FTP_TIMEOUT=900
export HTTP_TIMEOUT=900

export PATH=/sbin:/bin:/usr/sbin:/usr/bin:${LOCALBASE}/sbin:${LOCALBASE}/bin:${X11BASE}/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

if [ "${use_jail}" = "1" ]; then
  # Figure out jail IP addr
  chrootpid=$(basename ${chroot})
  ipbase=$((${chrootpid}+2))
  ip1=$(($ipbase /(256*256)))
  ip2=$((($ipbase - ($ip1*256*256)) /256))
  ip3=$((($ipbase - ($ip1*256*256) - ($ip2*256))))
fi

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

trap "bailout ${chroot} ${clean} ${error} ${pkgname}" 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

# Don't build in a world-writable standard directory because some ports
# hardcode this path and try to load things from it at runtime, which is
# bad for user security
rm -rf ${chroot}/${WRKDIRPREFIX}
mkdir -p ${chroot}/${WRKDIRPREFIX}

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 

mount_fs ${pb}/${arch}/${branch}/src ${chroot}/usr/src ${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
mkdir -p ${chroot}${LOCALBASE}
mtree -deU -f ${chroot}/usr/src/etc/mtree/BSD.local.dist -p ${chroot}${LOCALBASE} \
  >/dev/null 2>&1

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

if [ ${arch} = "i386" -o ${arch} = "amd64" ]; then
  # JDK ports need linprocfs :(
  mkdir -p ${chroot}/compat/linux/proc
  mount_linprocfs linprocfs ${chroot}/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}"

    # Test for copy failure and bail
    if [ ! -f ${chroot}/tmp/depends/$1 ]; then
      echo "ERROR: Couldn't copy $1"
      bailout ${chroot} ${clean} 255 ${pkgname}
    fi
  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

  if [ "${use_jail}" = 1 ]; then
    ifconfig lo0 alias 127.${ip1}.${ip2}.${ip3}/32
    jail -J ${chroot}/tmp/jail.id ${chroot} jail-${chrootpid} 127.${ip1}.${ip2}.${ip3} /usr/bin/env HTTP_PROXY=${http_proxy} /usr/bin/nice -n $nice /buildscript ${dirname} 2 "$ED" "$PD" "$FD" "$BD" "$RD" > ${chroot}/tmp/${pkgname}.log2 2>&1
    ifconfig lo0 delete 127.${ip1}.${ip2}.${ip3}
  else
    chroot ${chroot} /usr/bin/nice -n $nice /buildscript ${dirname} 2 "$ED" "$PD" "$FD" "$BD" "$RD" > ${chroot}/tmp/${pkgname}.log2 2>&1
  fi

  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

rm -rf ${chroot}/${WRKDIRPREFIX}
exit $error
