#!/bin/sh
#
# $Id: mkcdroot,v 1.18 2002/08/21 03:13:11 bsd Exp $
#
# Copyright 2001, 2002  Brian S. Dean <bsd@bsdhome.com>
# All Rights Reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the distribution.
#
# THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY
# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
# OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
# BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
# USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
# DAMAGE.
# 
# Author : Brian Dean
# Date   : 15 April, 2001
#

PROG=`basename $0`
CDROOT_LIBDIR=LIBDIR_VALUE
PAUSE=1


#--------------------------------------------------------------------
# Operational defaults
#--------------------------------------------------------------------

DEF_BASE=/scratch/cdroot/cdroot # Prefix to <NewRootPath>
DEF_SRCTREE=/usr/src   # head of the source tree
DEF_DOWORLD=1          # perform an installworld
DEF_DOKERN=1           # perform a buildkernel installkernel
DEF_DOFDBOOT=1         # generate a 2.88 boot floppy image
DEF_DOETCSRC=1         # populate /etc from /usr/src ($SRCTREE)
DEF_DOETC=1            # populate /etc with new files
DEF_DOSRC=0            # populate /usr/src on the CD from the host system sources
DEF_DOOBJ=0            # copy /usr/obj from the host system
DEF_DOPORTS=0          # copy /usr/ports from the host system
DEF_DOINSTPORTS=0      # install standard ports
DEF_DOINSTPKGS=0       # install standard packages
DEF_KERNCONF=CDROOT    # default kernel configuration file
DEF_BOOTOPTS=""        # default options to pass to the kernel
DEF_PKGDIR=/scratch/pub/FreeBSD/ports/i386/packages-4-stable/Latest
DEF_PKGLIST="XFree86 pdksh ddup"

BASE=$DEF_BASE
SRCTREE=$DEF_SRCTREE
DOWORLD=$DEF_DOWORLD
DOKERN=$DEF_DOKERN
DOFDBOOT=$DEF_DOFDBOOT
DOETCSRC=$DEF_DOETCSRC
DOETC=$DEF_DOETC
DOSRC=$DEF_DOSRC
DOOBJ=$DEF_DOOBJ
DOPORTS=$DEF_DOPORTS
DOINSTPORTS=$DEF_DOINSTPORTS
DOINSTPKGS=$DEF_DOINSTPKGS
KERNCONF=$DEF_KERNCONF
BOOTOPTS=$DEF_BOOTOPTS
PKGDIR=${DEF_PKGDIR}
PKGLIST=${DEF_PKGLIST}



#--------------------------------------------------------------------
# Support Functions
#--------------------------------------------------------------------

# Print negated "true"/"false", useful for diplaying default settings
# for -no* options, i.e., -nosrc.
tf_neg () {
  if [ "$1" -eq 1 ]; then
    echo "false"
  else
    echo "true"
  fi
}

# Print "yes"/"no", useful for diplaying default settings of 1/0 based
# flags
yn () {
  if [ "$1" -eq 1 ]; then
    echo "yes"
  else
    echo "no"
  fi
}

# function for error checking
ckrc () {
  rc=$?
  if [ "$rc" -ne 0 ]; then
    echo -n "$PROG: $1 failed, rc=$rc"
    if [ "$2" = "exit" ]; then
      echo "aborting";
      exit 1;
    fi
    echo
  fi
}

# install resolv.conf for name lookups; this is needed for installing
#  ports, etc., in a chroot'd environment on $DESTDIR
neednamelookups () {
  if [ ! -f $DESTDIR/etc/resolv.conf ]; then
    if [ -f /etc/resolv.conf ]; then
      cp /etc/resolv.conf $DESTDIR/etc/resolv.conf
    fi
  fi
}

# Create directories if they don't alread exist
domkdir () {
  for dir in $*; do
    if [ ! -d $dir ]; then
      echo "mkdir $dir"
      rm -f $dir
      mkdir -p $dir
    fi
  done
}

# Attempt to install a requested port
installport () {
  neednamelookups
  while [ "$#" -ge 1 ]; do
    DIR=$1; shift
    while [ "$#" -ge 1 ]; do
      PORT=$1; shift
      echo "Installing $DIR/$PORT ..."
      chroot $DESTDIR \
        /bin/sh -c "unset DESTDIR; cd /usr/ports/$DIR/$PORT && make install"
    done
  done
}

doworld () {
  # Perform an installworld targeting the new root
  DESTDIR="$1"
  echo "DOWORLD: DESTDIR=$DESTDIR"
  cd $SRCTREE
  mkdir ${DESTDIR}/dist
  make installworld DESTDIR=$DESTDIR
}

dokern () {
  # Build and install a kernel for the new root
  DESTDIR="$1"
  echo "DOKERN: DESTDIR=$DESTDIR"
  (cd $SRCTREE &&
   make buildkernel installkernel KERNCONF=${KERNCONF} \
     DESTDIR=$DESTDIR)
}

dosrc () {
  # populate ${DESTDIR}/usr/src from ${SRCTREE}
  DESTDIR="$1"
  echo "populate ${DESTDIR}/usr/src from ${SRCTREE}"
  mkdir -p ${DESTDIR}/usr/src && (cd ${DESTDIR}/usr/src &&
    cp -rpv ${SRCTREE}/. .)
}


doetcsrc() {
  DESTDIR="$1"
  echo "DOETCSRC: DESTDIR=$DESTDIR"
  echo "Populate /etc"
  (cd $SRCTREE/etc && make DESTDIR=$DESTDIR distrib-dirs &&
   make DESTDIR=$DESTDIR distribution)
  echo "Making devices"
  chroot $DESTDIR /bin/sh -c "(cd /dev && sh MAKEDEV all ad0s1a da0s1a)"
  echo "Remove /etc/rc.system"
  if [ -f ${DESTDIR}/rc.system ]; then
    rm ${DESTDIR}/etc/rc.system
  fi

  echo "Installing password files"
  chroot $DESTDIR /bin/sh -c "pwd_mkdb -p /etc/master.passwd"

  echo "Generating login capabilities database"
  chroot $DESTDIR /bin/sh -c "/usr/bin/cap_mkdb /etc/login.conf"

  echo "Creating aliases database"
  chroot $DESTDIR /bin/sh -c "unset $DESTDIR; /usr/bin/newaliases"

  echo "Create /etc/objformat"
  echo "OBJFORMAT=elf" > $DESTDIR/etc/objformat

  echo "Create /etc/fstab"
  echo "" > $DESTDIR/etc/fstab

  echo "Enable logins on /dev/ttyd0"
  tfile=/tmp/ttys.$$
  cat $DESTDIR/etc/ttys | sed 's+^ttyd0	"/usr/libexec/getty std.9600"	dialup	off secure+ttyd0   "/usr/libexec/getty std.9600"   dialup  on  secure+g' > $tfile && cp $tfile $DESTDIR/etc/ttys
  rm -f $tfile

  echo "Enable hardware flow control by default on std.9600"
  tfile=/tmp/gettytab.$$
  cat $DESTDIR/etc/gettytab | sed 's+^	:np:sp#9600:$+	:np:sp#9600:hw:+g' > $tfile && cp $tfile $DESTDIR/etc/gettytab
  rm -f $tfile
}


dofdboot () {
  DESTDIR="$1"
  echo "DOFDBOOT: DESTDIR=$DESTDIR"
  echo "Generating 2.88 MB boot floppy image"
  KERNELIMG=${DESTDIR}/kernel

  umount /mnt > /dev/null 2>&1
  vnconfig -u /dev/vn0 > /dev/null 2>&1

  echo "Initialize boot floppy image"
  dd if=/dev/zero of=${DESTDIR}/boot/boot.fd bs=1024 count=2880
  vnconfig -s labels -c /dev/vn0 ${DESTDIR}/boot/boot.fd
  disklabel -Brw /dev/vn0c minimum2
  newfs -o space -T minimum2 /dev/vn0c
  mount /dev/vn0c /mnt

  echo "Copy kernel from ${KERNELIMG} to the boot floppy"
  cp ${KERNELIMG} /tmp/kernel
  gzip /tmp/kernel
  cp /tmp/kernel.gz /mnt
  rm /tmp/kernel.gz
  mkdir /mnt/boot
  mkdir /mnt/boot/defaults
  echo "Copy boot1, boot2, and loader to boot floppy"
  (cd ${DESTDIR}/boot && cp -p boot1 boot2 loader /mnt/boot)
  echo "Create boot.config"
  echo "-P" > /mnt/boot.config
  echo "-P" > ${DESTDIR}/boot.config
  echo "Create loader.rc"
  cat <<EOF > /mnt/boot/loader.rc
echo "BSD CDROM ROOT IMAGE"
echo "LOADING KERNEL"
load /kernel
boot -C $BOOTOPTS
EOF
  cat <<EOF > ${DESTDIR}/boot/loader.rc
echo "BSD NO-EMULATION CDROM ROOT IMAGE"
echo "LOADING KERNEL"
load /kernel
boot -C $BOOTOPTS
EOF
  umount /mnt
}


installcvsup () {
  DESTDIR="$1"
  # Provide a cvsup supfile to keep /usr/ports up to date
  if [ ! -f $DESTDIR/root/ports-supfile ]; then
    echo "Install ports cvsup file"
    cat <<_EOD_ > $DESTDIR/root/ports-supfile
#       cvsup -g -L 2 ports-supfile

*default host=cvsup8.FreeBSD.org
*default base=/usr
*default prefix=/usr
*default release=cvs tag=.
*default delete use-rel-suffix
*default compress
ports-all
_EOD_
  fi

  # Fetch cvsup if it is not yet installed
  if [ ! -f $DESTDIR/usr/local/bin/cvsup ]; then
    echo "Install cvsup"
    cd $DESTDIR/root && \
      fetch ${CVSUPLOC}/${CVSUP} && \
      chroot $DESTDIR /bin/sh -c "unset DESTDIR; cd /root && pkg_add -v ${CVSUP} && rm -f ${CVSUP}"
  fi
}


updateports () {
  DESTDIR="$1"
  echo "Update /usr/ports"
  if [ ! -f /usr/local/bin/cvsup ]; then
    echo
    echo "You must install the cvsup package first."
    echo
    exit 1
  fi
  neednamelookups
  chroot $DESTDIR /bin/sh -c \
     "unset DESTDIR; cd /root && cvsup -g -L 2 ports-supfile"
}






# Display usage information
printusage () {
  cat <<EOF

Usage: $PROG <options>

Create a new read only root area starting at $DEF_BASE.
The following options are supported:

    -base        : Override the root install location
                   [default=$DEF_BASE]

    -srctree     : Override the location of the source tree
                   [default=$DEF_SRCTREE]

    -noworld     : do not perform an "installworld"
                   [default=`tf_neg $DEF_DOWORLD`]

    -nokern      : do not perform a "buildkernel installkernel"
                   [default=`tf_neg $DEF_DOKERN`]

    -nofdboot    : do not generate a 2.88 boot floppy
                   [default=`tf_neg $DEF_DOFDBOOT`]

    -noetcsrc    : do not populate /etc from $SRCTREE
                   [default=`tf_neg $DEF_DOETCSRC`]

    -noetc       : do not populate /etc with new files
                   [default=`tf_neg $DEF_DOETC`]

    -nosrc       : do not populate /usr/src from the host system
                   [default=`tf_neg $DEF_DOSRC`]

    -noobj       : do not populate /usr/obj from the host system
                   [default=`tf_neg $DEF_DOOBJ`]

    -noports     : do not populate /usr/ports from the host system
                   [default=`tf_neg $DEF_DOPORTS`]

    -noinstports : do not attempt to install standard ports
                   [default=`tf_neg $DEF_DOINSTPORTS`]

    -noinstpkgs  : do not attempt to install standard packages
                   [default=`tf_neg $DEF_DOINSTPKGS`]

    -pkgdir      : directory where packages are located
                   [default=$DEF_PKGDIR]

    -pkglist     : set list of packages to install
                   [default=$DEF_PKGLIST]

    -kernconf    : override the default kernel config file for building/installing
                   [default=$DEF_KERNCONF]

    -bootopts    : override the default kernel options passed by the loader
                   [default=$DEF_BOOTOPTS]

    -now         : do not pause for 5 seconds before performing actions

EOF
}


#------------------------------------------------------------
# check for command line options
#------------------------------------------------------------

while [ "$#" -ne 0 ]; do
  VAL=1
  case $1 in
    -no*)
      VAL=0;
      ;;
  esac
  case $1 in
    -base)
      BASE="$2"
      shift; shift
      ;;
    -srctree)
      SRCTREE="$2"
      shift; shift
      ;;
    -noworld|-world)
     DOWORLD=$VAL
     shift
     ;;
    -nokern|-kern)
     DOKERN=$VAL
     shift
     ;;
    -nofdboot|-fdboot)
      DOFDBOOT=$VAL
      shift
      ;;
    -noetcsrc|-etcsrc)
     DOETCSRC=$VAL
     shift
     ;;
    -noetc|-etc)
     DOETC=$VAL
     shift
     ;;
    -nosrc|-src)
      DOSRC=$VAL
      shift
      ;;
    -noobj|-obj)
      DOOBJ=$VAL
      shift
      ;;
    -noports|-ports)
      DOPORTS=$VAL
      shift
      ;;
    -noinstports|-instports)
      DOINSTPORTS=$VAL
      shift
      ;;
    -noinstpkgs|-instpkgs)
      DOINSTPKGS=$VAL
      shift
      ;;
    -pkgdir)
      PKGDIR=$2
      shift; shift
      ;;
    -pkglist)
      PKGLIST=$2
      shift; shift
      ;;
    -kernconf)
      KERNCONF="$2"
      shift; shift
      ;;
    -bootopts)
      BOOTOPTS="$2"
      shift; shift
      ;;
    -now)
      PAUSE=0
      shift
      ;;
    *)
      echo
      echo "$PROG: unknown option \"$1\""
      printusage
      exit 1
      ;;
  esac
done

if [ "$#" -ne 0 ]; then
  printusage
  exit 1
fi

if [ $DOINSTPKGS -eq 1 -a $DOINSTPORTS -eq 1 ]; then
cat <<EOF

You have selected to install applications from both ports and
packages.  These installation options are incompatible.  Applications
can be installed from either ports or packages, but not both.

EOF

  exit 1
fi


if [ -z "${SRCTREE}" ]; then
  echo
  echo "$PROG: you must specify the top of your source tree (-srctree)"
  echo
  exit 1
fi

export DESTDIR=/$BASE

if [ ! -d $DESTDIR ]; then
  echo
  echo "$PROG: Root location \"${DESTDIR}\" does not exist"
  echo "$PROG: Please create \"$DESTDIR \" and try again."
  echo
  exit 1
fi

DESTDIR=`echo $DESTDIR | sed 's+//+/+g'`

#----------------------------------------------------------------------
# Print out the current installation options and give the operator
# a chance to exit before we charge off and do something drastic
#----------------------------------------------------------------------
cat <<EOF

  $PROG: Installation Options:

    root area                            [-base]      = $DESTDIR
    source tree                          [-srctree]   = $SRCTREE
    perform basic install (installworld) [-world]     = `yn $DOWORLD`
    build and install a kernel           [-kern]      = `yn $DOKERN`
    generate a boot floppy               [-fdboot]    = `yn $DOFDBOOT`
    populate /etc from source            [-etcsrc]    = `yn $DOETCSRC`
    populate /etc with new files         [-etc]       = `yn $DOETC`
    install /usr/src                     [-src]       = `yn $DOSRC`
    install /usr/obj                     [-obj]       = `yn $DOOBJ`
    install /usr/ports                   [-ports]     = `yn $DOPORTS`
    install applications from ports      [-instports] = `yn $DOINSTPORTS`
    install applications from packages   [-instpkgs]  = `yn $DOINSTPKGS`
    package list to install              [-pkglist]   = $PKGLIST
    package directory                    [-pkgdir]    = $PKGDIR
    kernel config file                   [-kernconf]  = $KERNCONF
    kernel boot options                  [-bootopts]  = $BOOTOPTS

EOF

if [ "$PAUSE" -ne 0 ]; then
  timeout=5
  while [ $timeout -ne 0 ]; do
    printf "\r                                                          "
    printf "\rProceeding in $timeout seconds, press <CTRL>-C to cancel "
    sleep 1
    timeout=`expr $timeout - 1`
  done
  echo
  echo
fi

#----------------------------------------------------------------------
# Populate the most basic components of the OS if requested
#----------------------------------------------------------------------

if [ "$DOWORLD" -eq 1 ]; then
  doworld ${DESTDIR}
  ckrc world exit
fi

if [ "$DOKERN" -eq 1 ]; then
  dokern ${DESTDIR}
  ckrc kernel exit
fi

if [ "$DOETCSRC" -eq 1 ]; then
  doetcsrc ${DESTDIR}
  ckrc etcsrc exit
fi

if [ "$DOETC" -eq 1 ]; then
  echo "Create /etc/rc.conf"
  cat <<EOF > $DESTDIR/etc/rc.conf
# /etc/rc.conf
#
# Generated by $PROG, `date`
#

# The options below can be overridden by entries on a floppy disk.
# Create a ufs filesystem on a floppy disk, create an etc directory,
# and put overrides there.  Files are copied from the floppy:/etc and
# replaces files here at boot time.  If you override this file,
# /etc/rc.conf, you should not change the options immediately below.

moused_enable=YES
moused_type=ps/2
moused_port=/dev/psm0

root_rw_mount=NO                 # let /etc/rc know that root is ro
update_motd=NO                   # don't try to update /etc/motd
diskless_mount=/etc/cdroot_mount # custom disk mounting program

#
#                 ********** WARNING **********
#
# These next two options are dangerous and can result in the loss of
# data on either ad0 or da0.  Use with EXTREME caution.
#

# If cdroot_uselocaldisk is set to YES, then the /etc/cdroot_mount
# program looks for either ad0 or da0.  If one of these is found, then
# it will be used to hold swap, /var, /tmp, and /local.
#

# The disk is initialized from scratch if the first fdisk slice does
# not contain a valid FreeBSD label.  If a label is present, the
# filesystems are fsck'd and used as is.  You can force the disk to be
# re-initialized each time by specifying cdroot_force_diskinit=YES.

cdroot_uselocaldisk=NO   # use a local disk for swap, /var, /tmp, /local
cdroot_force_diskinit=NO # alway re-initialize the local disk
EOF

  echo "Make sure /etc/mail/local-host-names exists"
  touch ${DESTDIR}/etc/mail/local-host-names

  echo "Install /etc/cdroot_mount"
  cp ${CDROOT_LIBDIR}/cdroot_mount ${DESTDIR}/etc

  echo "Install /etc/cdroot_initdisk"
  cp ${CDROOT_LIBDIR}/cdroot_initdisk ${DESTDIR}/etc

  echo "Install /etc/inst"
  cp ${CDROOT_LIBDIR}/cdroot_inst ${DESTDIR}/etc/inst

  echo "Install /etc/rc.replacement"
  if [ ! -f "${DESTDIR}/etc/rc.system" ]; then
    cp -p ${DESTDIR}/etc/rc ${DESTDIR}/etc/rc.system
  fi
  cp ${CDROOT_LIBDIR}/rc.replacement ${DESTDIR}/etc/rc

  echo "Stash a copy of /dev/MAKEDEV into /etc"
  cp -p ${DESTDIR}/dev/MAKEDEV ${DESTDIR}/etc

  echo "Create /etc/install/dists.dat and pkgs.dat"
  if [ ! -d ${DESTDIR}/etc/install ]; then
    mkdir ${DESTDIR}/etc/install
  fi
  if [ ! -f ${DESTDIR}/etc/install/dists.dat ]; then
    cat <<EOF > ${DESTDIR}/etc/install/dists.dat
bin catpages compat22 compat3x compat4x crypto dict doc games info
manpages ports proflibs src
EOF
  else
    echo "${DESTDIR}/etc/install/dists.dat already present, not replaced"
  fi

  if [ ! -f ${DESTDIR}/etc/install/pkgs.dat ]; then
    cat <<EOF > ${DESTDIR}/etc/install/pkgs.dat
XFree86-4.1.0_4
emacs-20.7
pdksh-5.2.14
EOF
  else
    echo "${DESTDIR}/etc/install/pkgs.dat already present, not replaced"
  fi

fi


if [ ! -f ${DESTDIR}/usr/hosts.db -a -f /usr/hosts.db ]; then
  echo "install /usr/hosts.db"
  cp -p /usr/hosts.db ${DESTDIR}/usr/hosts.db
fi



if [ "$DOFDBOOT" -eq 1 ]; then
  dofdboot ${DESTDIR}
  ckrc fdboot exit
fi


if [ "$DOSRC" -eq 1 ]; then
  dosrc ${DESTDIR}
  ckrc "populate ${DESTDIR}/usr/src from $SRCTREE" exit
fi


#----------------------------------------------------------------------
# Several following commands depend on the current working directory
# being the new root area
#----------------------------------------------------------------------
cd $DESTDIR || exit 1

# Create needed directories relative to the new root
domkdir local usr/local usr/local/etc/rc.d


#----------------------------------------------------------------------
# Install requested packages
#----------------------------------------------------------------------
if [ $DOINSTPKGS -eq 1 ]; then
  echo "Copying packages to the chroot'd area ..."
  if [ ! -d "${DESTDIR}/tmp/pkgs" ]; then
    mkdir ${DESTDIR}/tmp/pkgs
    ckrc "create temporary package directory" exit
  fi
  cp -p $PKGDIR/* ${DESTDIR}/tmp/pkgs
  ckrc "copy packages to temporary package directory" exit
  for PKG in $PKGLIST; do
    echo "Installing package $PKG ..."
    chroot ${DESTDIR} /bin/sh -c "unset DESTDIR; \
                                 pkg_add -v /tmp/pkgs/$PKG.tgz"
  done
  rm -rf ${DESTDIR}/tmp/pkgs
  ckrc "removal of temporary package directory"
fi


#----------------------------------------------------------------------
# Update /usr/ports if requested to do so
#----------------------------------------------------------------------
if [ "$DOPORTS" -eq 1 ]; then
  updateports ${DESTDIR}
fi


#----------------------------------------------------------------------
# Try and provide a working /bin/ksh
#----------------------------------------------------------------------
if [ -d "${DESTDIR}/usr/ports/shells/pdksh" -a ! -f /bin/ksh ]; then
  installport shells pdksh
fi

if [ ! -f ${DESTDIR}/bin/ksh ]; then
  if [ -f "${DESTDIR}/usr/local/bin/ksh" ]; then
    cp -p ${DESTDIR}/usr/local/bin/ksh ${DESTDIR}/bin/ksh
  elif [ -f /usr/local/bin/ksh ]; then
    cp -p /usr/local/bin/ksh ${DESTDIR}/bin/ksh
  elif [ -f /bin/ksh ]; then
    cp -p /bin/ksh ${DESTDIR}/bin/ksh
  fi
fi

if [ -f ${DESTDIR}/bin/ksh ]; then
  grep '^/bin/ksh' ${DESTDIR}/etc/shells > /dev/null 2>&1
  rc=$?
  if [ "$rc" -ne 0 ]; then
    echo "/bin/ksh" >> ${DESTDIR}/etc/shells
  fi
fi


#----------------------------------------------------------------------
# Attempt to install the standard ports if requested
#----------------------------------------------------------------------
if [ $DOINSTPORTS -eq 1 ]; then
  # ports that require X11
  installport x11           XFree86
  installport editors       emacs20
  installport graphics      xv
  installport net           ethereal

  # Non-X11 ports
  installport mail          mutt procmail
  installport net           cvsup
  installport security      sudo
  installport shells        pdksh
  installport sysutils      lsof
fi




syntax highlighted by Code2HTML, v. 0.9.1