#!/bin/sh

# Copyright (c) 2005-2012 Douglas Barton, All rights reserved
# Please see detailed copyright below

trap trap_exit INT

umask 022

# Initialize crucial values for the parent, and export them for the children
if [ -z "$PM_PARENT_PID" ]; then
	PM_PARENT_PID=$$
	: ${TMPDIR:=/tmp} ; /bin/mkdir -p $TMPDIR
	UPGRADE_TOOL=portmaster

	# /usr/local is needed in the path for make
	PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
	[ -e /usr/X11R6 ] && [ ! -L /usr/X11R6 ] && PATH=$PATH:/usr/X11R6/bin
	[ -n "$CCACHE_PATH" -a -z "$NOCCACHE" ] && PATH="/usr/local/libexec/ccache:$PATH"
	export PM_PARENT_PID TMPDIR UPGRADE_TOOL PATH

	if [ -r /etc/portmaster.rc ]; then
		echo '' ; echo "===>>> WARNING"
		echo '       Your portmaster.rc is in /etc, however support for the file in this'
		echo '       location has been removed.'
		echo '' ; echo '       The proper location for this file is /usr/local/etc'
		exit 1
	fi

	set -o allexport
	# Read a global rc file first
	[ -s /usr/local/etc/portmaster.rc ] && . /usr/local/etc/portmaster.rc

	# Allow the config file to be stored with the script
	[ -s "${0%/*}/portmaster.rc" ] && . ${0%/*}/portmaster.rc

	# Read a local one next, and allow the command line to override
	[ -s "$HOME/.portmasterrc" ] && . $HOME/.portmasterrc
	set +o allexport

	my_environment=`set`

	# If we are already root, unset this to avoid potential conflict
	[ `ps -o uid= $$` -eq 0 ] && unset PM_SU_CMD PM_SU_VERBOSE
fi

#=============== Begin functions we always want to have ===============

version () {
	echo '' ; echo "===>>> Version 3.16"
	#svn='$FreeBSD: user/dougb/portmaster/portmaster 241090 2012-10-01 08:32:05Z dougb $'
}

fail () {
	echo -e "\n===>>> $*" ; echo "===>>> Aborting update"
	[ "$$" -eq "$PM_PARENT_PID" ] && trap_exit fail
	safe_exit 1
}

trap_exit () {
	echo ''		# Helps if the previous message was 'echo -n'
	if [ -n "$portdir" -a -z "$1" ]; then
		echo "===>>> Build/Install for $portdir exiting due to signal"
	elif [ -z "$1" ]; then
		echo "===>>> Exiting due to signal"
	fi

	if [ "$$" -eq "$PM_PARENT_PID" ]; then
		[ -s "$IPC_SAVE" ] && . $IPC_SAVE

		local n=0
		while ps -axo pid,ppid,command | grep -v egrep |
		    egrep -q "(make -DBATCH checksum|/fetch |\[sh\])"; do
			# Protect from infinite loop if there is another fetch
			[ $n -gt 9 ] && break
			n=$(( $n + 1 ))
			kill_bad_children
		done
		if [ -n "$HIDE_BUILD" ]; then
			local logs file
			logs=`echo ${TMPDIR}/port_log-${PM_PARENT_PID}-*`
			case "$logs" in *\*) unset logs ;; esac
			if [ -n "$logs" ]; then
				echo ''
				echo "===>>> Build/Install logs available:"
				for file in $logs; do echo "	$file"; done
				echo ''
			fi
		fi
	else
		# Signal the parent if a child trap'ed, or read the file if we are
		# an intermediate process.
		if ! ls ${TMPDIR}/f-${PM_PARENT_PID}-TEAC\.* >/dev/null 2>&1; then
			pm_mktemp TEAC		# Trap Exit Already Called
		else
			[ -s "$IPC_SAVE" ] && . $IPC_SAVE
		fi
	fi
	safe_exit 1
}

kill_bad_children () {
	local mypgid pid ppid pgid command ; IFS=' '

	mypgid=`ps -o pgid= -p $PM_PARENT_PID`

        [ -z "$displayed_background_msg" ] && echo "===>>> Killing background jobs"
        displayed_background_msg=1

	ps -axo pid,ppid,pgid,command | sed '1d' | while read pid ppid pgid command; do
		[ "$pid" -gt 25 ] || continue
		case "$ppid" in
		1)	case "$command" in
			*" $0 "*) pm_kill $pid ;;
			*'make -DBATCH checksum'*|*'/fetch '*|\[sh\]) pm_kill -9 $pid ;;
			esac ;;
		*)	[ $pgid -eq $mypgid ] || continue
			[ $pid -eq $PM_PARENT_PID ] && continue
			case "$command" in
			*" $0 "*) pm_kill $pid ;;
			*'make -DBATCH checksum'*|*'/fetch '*|\[sh\]) pm_kill $pid ;;
			esac ;;
		esac
	done
}

parent_exit () {
	local need_kbc files f count DISCARD show_list

	[ -s "$DI_FILES" ] && { grep -q '%%%%%%%%%%%%' $DI_FILES || need_kbc=need_kbc_dif; }

	[ -n "$FETCH_ONLY" -a -z "$FETCH_ONLY_DONE" ] && need_kbc=need_kbc_fo

	if [ -z "$1" ]; then
		if [ -n "$PM_URB" -o -n "$PM_FORCE" ]; then
			files=`find $pdb -type f -name PM_UPGRADE_DONE_FLAG`
			if [ -n "$files" ]; then
				pm_sv Deleting \'install complete\' flags
				pm_find_s $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete
				[ -n "$use_pkgng" ] &&
					pm_find_s $pdb -type d -depth 1 -empty ! -path \*\.zfs/\* -delete 2>/dev/null
			fi
		fi
		if [ -z "$BACKUP" -a -z "$NO_BACKUP" -a -n "$NB_DELETE" ]; then
			pm_sv 'Deleting safety packages for successful installs\n'
			pm_cd $pbu || fail "Cannot cd to $pbu"
			pm_rm_s $NB_DELETE
		fi
	else
		need_kbc=need_kbc_ec
	fi

	[ -n "$need_kbc" ] && kill_bad_children

	[ -n "$pbu" ] && pbu=`find $pbu -type d -empty 2>/dev/null`
	if [ -d "$pbu" ]; then
		pm_sv 'Removing empty backup package directory'
		pm_rmdir_s $pbu
	fi

	for f in ${TMPDIR}/f-${PM_PARENT_PID}-*; do
		case "$f" in */f-${PM_PARENT_PID}-\*) continue ;; esac
		/bin/unlink $f
	done

	if [ -n "$PM_WRKDIRPREFIX" ] && [ -n "$PM_BUILDING" -a -z "$1" ]; then
		count=0
		while : ; do
			ps axww | grep '[m]ake clean NOCLEANDEPENDS=ncd' >/dev/null || break
			count=$(( $count + 1 ))
			if [ $count -eq 1 ]; then
				echo "===>>> Waiting for background 'make clean' processes to finish"
				needws=needws
			elif [ $count -eq 10 ]; then
				count=0
			fi
			sleep 2
		done

		pm_v "===>>> Removing empty directories from WRKDIRPREFIX"
		[ -n "$needws" ] && echo '' || pm_v
		find $PM_WRKDIRPREFIX -depth -mindepth 1 -type d -empty -delete 2>/dev/null
	fi

	case "$DISPLAY_LIST" in
	*' '*)	if [ -n "$1" ]; then
			echo "===>>> There are messages from installed ports to display,"
			echo "       but first take a moment to review the error messages"
			echo -n "       above.  Then press Enter when ready to proceed. "
			read DISCARD
			echo ''
		fi

		: ${PAGER:='less -e'}
		( if [ -z "$use_pkgng" ]; then
			for f in $DISPLAY_LIST; do
				echo "===>>> pkg-message for $f"
				cat $pdb/$f/+DISPLAY ; echo ''
			done
		else
			pkg query "===>>> pkg-message for %n-%v\n%M" $DISPLAY_LIST
		fi
		echo "===>>> Done displaying pkg-message files" ; echo '' ) | $PAGER ;;
	esac

	if [ -n "$INSTALLED_LIST" ]; then
		if [ -n "$UPDATE_ALL" -o -n "$PM_MULTI_PORTS" ]; then
			show_list=all
		else
			case "$INSTALLED_LIST" in
			*\\n\\t*)	show_list=all ;;
			*\\n)		show_list=one
					if [ -z "$ilist" ]; then
						ilist="${INSTALLED_LIST#\\t}"
						ilist="${ilist%\\n}"
					fi ;;
			esac
		fi
		if [ -n "$PM_LOG" ]; then
			if [ -w "$PM_LOG" ]; then
				echo '' >> $PM_LOG
			elif [ -e "$PM_LOG" -a ! -w "$PM_LOG" ]; then
				echo "===>>> Warning: $PM_LOG exists, but is not writable"
				unset PM_LOG
			elif [ -e "$PM_LOG" -o -L "$PM_LOG" ]; then
				echo "===>>> Warning: $PM_LOG exists, but is not a regular file"
				unset PM_LOG
			else
				pm_mktemp pm_log ; mv $pm_mktemp_file $PM_LOG
			fi
			[ -n "$PM_LOG" ] && date >> $PM_LOG
		fi
		case "$show_list" in
		all)	echo "===>>> The following actions were performed:"
			echo -e $INSTALLED_LIST
			[ -n "$PM_LOG" ] && echo -e ${INSTALLED_LIST%\\n} >> $PM_LOG ;;
		one)	echo "===>>> $ilist complete" ; echo ''
			[ -n "$PM_LOG" ] && echo "	$ilist" >> $PM_LOG ;;
		esac
	fi

	if [ -n "$build_deps_il" ]; then
		echo "===>>> Deleting installed build-only dependencies"
		cd
		if [ -z "$use_pkgng" ]; then
			for f in $build_deps_il; do
				pm_v "       $f"
				pm_pkg_delete_s $f
			done
		else
			pm_pkg_delete_s $build_deps_il
		fi
		echo ''
	fi

	if [ -n "$1" -a -n "${PM_NEEDS_UPDATE# }" -a -n "$PM_BUILDING" -a -z "$FETCH_ONLY" ]; then
		echo ''
		echo "===>>> You can restart from the point of failure with this command line:"
		echo "       ${0##*/} <flags>${PM_NEEDS_UPDATE}"
		echo ''
	fi
	echo "===>>> Exiting"
}

safe_exit () {
	[ -n "$grep_deps" ] && pm_unlink $grep_deps

	if [ "$$" -eq "$PM_PARENT_PID" ]; then
		parent_exit $1
	else
		# Save state for the parent process to read back in
		> $IPC_SAVE
		if [ -z "$PM_FIRST_PASS" ]; then
			echo "DISPLAY_LIST='$DISPLAY_LIST'" >> $IPC_SAVE
			echo "INSTALLED_LIST='$INSTALLED_LIST'" >> $IPC_SAVE

			[ -n "$PM_DEL_BUILD_ONLY" ] &&
				echo "build_deps_il='$build_deps_il'" >> $IPC_SAVE

			# Do not remove a child from the list if we trapped or failed
			if [ -z "$1" ]; then
				for i in $PM_NEEDS_UPDATE; do
					[ "$i" = "$portdir" ] && continue
					pnu_temp="${pnu_temp}${i} "
				done
				PM_NEEDS_UPDATE=" ${pnu_temp}"
			fi

			[ -z "$NO_BACKUP" -a -z "$BACKUP" ] && echo "NB_DELETE='$NB_DELETE'" >> $IPC_SAVE
		else
			if [ "$PM_BUILD_ONLY_LIST" = pmp_doing_build_deps ]; then
				echo "build_only_dl_g='$build_only_dl_g'" >> $IPC_SAVE
				echo "run_dl_g='$run_dl_g'" >> $IPC_SAVE
				rundep_list=`uniquify_list $rundep_list`
				echo "rundep_list='$rundep_list'" >> $IPC_SAVE
				for f in $rundep_list; do
					eval echo "export $f=\'\$$f\'" >> $IPC_SAVE
					eval echo "export ${f}_p=\'\$${f}_p\'" >> $IPC_SAVE
				done
			fi

			# Do these here so +IGNOREME can modify them
			echo "num_of_deps='$num_of_deps'" >> $IPC_SAVE
			echo "build_l='$build_l'" >> $IPC_SAVE
			[ -z "$NO_DEP_UPDATES" ] && echo 'unset NO_DEP_UPDATES' >> $IPC_SAVE
		fi
		echo "CUR_DEPS='$CUR_DEPS'" >> $IPC_SAVE
		echo "dep_of_deps='$dep_of_deps'" >> $IPC_SAVE
		echo "PM_NEEDS_UPDATE='$PM_NEEDS_UPDATE'" >> $IPC_SAVE
		if [ -n "$INTERACTIVE_UPDATE" ]; then
			echo "INTERACTIVE_YES='$INTERACTIVE_YES'" >> $IPC_SAVE
			echo "INTERACTIVE_NO='$INTERACTIVE_NO'" >> $IPC_SAVE
		fi
		[ -n "$PM_URB" -o -n "$PM_URB_UP" ] && echo "PM_URB_DONE='$PM_URB_DONE'" >> $IPC_SAVE
	fi

	exit ${1:-0}
} # safe_exit()

pm_cd     () { builtin cd $1 2>/dev/null || return 1; }
pm_cd_pd  () { [ -n "$PM_INDEX_ONLY" ] && return 2;
		builtin cd $pd/$1 2>/dev/null ||
		fail "Cannot cd to port directory: $pd/$1"; }
pm_kill   () { /bin/kill $* >/dev/null 2>/dev/null; }
pm_make   () { ( unset -v CUR_DEPS INSTALLED_LIST PM_DEPTH build_l PM_URB_LIST;
		 /usr/bin/nice /usr/bin/make $PM_MAKE_ARGS $*; ); }
pm_make_b () { /usr/bin/make $PM_MAKE_ARGS BEFOREPORTMK=bpm $*; }
pm_mktemp () {
	pm_mktemp_file=`/usr/bin/mktemp -t f-${PM_PARENT_PID}-$1 2>&1` ||
		fail "mktemp for $1 failed:\n       ${pm_mktemp_file#mktemp: }"
}
pm_unlink () { [ -e "$1" ] && /bin/unlink $1; }

# Superuser versions for commands that need root privileges

pm_find_s         () { $PM_SU_CMD /usr/bin/find $*; }
pm_install_s      () { $PM_SU_CMD /usr/bin/install -p -o root -g wheel -m 644 $1 $2; }
pm_make_s         () { ( unset -v CUR_DEPS INSTALLED_LIST PM_DEPTH build_l PM_URB_LIST;
			 $PM_SU_CMD /usr/bin/nice /usr/bin/make $PM_MAKE_ARGS $*; ); }
pm_mkdir_s        () { $PM_SU_CMD /bin/mkdir -p $1; }
pm_pkg_delete_s   () {
	if [ -z "$use_pkgng" ]; then
		$PM_SU_CMD /usr/sbin/pkg_delete -f $*;
	else
		$PM_SU_CMD /usr/local/sbin/pkg delete -yf $*;
		for d in $* ; do
		    pm_rm_s -rf $pdb/$d
		done
	fi
}
pm_rm_s           () { $PM_SU_CMD /bin/rm $*; }
pm_rmdir_s        () { $PM_SU_CMD /bin/rmdir $*; }
pm_unlink_s       () { [ -e "$1" ] && $PM_SU_CMD /bin/unlink $1; }

pm_v              () { [ -n "$PM_VERBOSE" ] && echo -e "$*"; }
pm_sv             () { [ -n "$PM_SU_VERBOSE" ] && echo -e "===>>> SU $*"; }

# Do this here so we can have a reasonably good guess.
# May be modified below.
if [ "$$" -eq "$PM_PARENT_PID" ]; then
	if [ -z "$pd" ]; then
		if [ -z "$PORTSDIR" ]; then
			[ -d /usr/ports ] && pd=/usr/ports
			[ -z "$pd" ] &&
				pd=`pm_make_b -f/usr/share/mk/bsd.port.mk -V PORTSDIR 2>/dev/null`
		else
			pd=$PORTSDIR
		fi
	fi
	if [ -n "$pd" ]; then
		[ ! -r "${pd}/Mk/bsd.port.mk" ] &&
			fail "The ports directory ($pd) does not seem to contain a ports tree"
		export pd
	fi

	if [ -z "$pdb" ]; then
		if [ -z "$PKG_DBDIR" ]; then
			[ -d /var/db/pkg ] && pdb=/var/db/pkg
			[ -z "$pdb" ] &&
				pdb=`pm_make -f/usr/share/mk/bsd.port.mk -V PKG_DBDIR 2>/dev/null`
		else
			pdb=$PKG_DBDIR
		fi
		if [ -z "$pdb" ]; then
			if [ -d /var/db/pkg ]; then
				pdb='/var/db/pkg'
			else
				fail 'The value of PKG_DBDIR cannot be empty'
			fi
		fi
	fi
	export pdb

	[ -z "$port_dbdir" ] && [ -d /var/db/ports ] && port_dbdir=/var/db/ports
	[ -z "$port_dbdir" ] &&
		port_dbdir=`pm_make_b -f/usr/share/mk/bsd.port.mk -V PORT_DBDIR 2>/dev/null`
	[ -n "$port_dbdir" ] && export port_dbdir

	# Detect if pkgng is being used
	use_pkgng=`pm_make_b -f/usr/share/mk/bsd.port.mk -V WITH_PKGNG 2>/dev/null`
	[ -n "$use_pkgng" ] && export use_pkgng
fi

usage () {
	local pd pdb port_dbdir

	[ -z "$pd" ] && pd=/usr/ports
	[ -z "$pdb" ] && pdb=/var/db/pkg
	[ -z "$port_dbdir" ] && port_dbdir=/var/db/ports

	version
	echo ''
	echo 'Usage:'
	echo "Common flags: [--force-config -CGHKgntvw -[B|b] -[f|i] -[D|d]]"
	echo "    [[[--packages|-P]|[--packages-only|-PP]] | [--packages-build]]"
	echo "    [--packages-if-newer] [--delete-build-only] [--always-fetch]"
	echo "    [--local-packagedir=<path>] [--packages-local] [--delete-packages]"
	echo "    [--no-confirm] [--no-term-title] [--no-index-fetch]"
	echo "    [--index|--index-first|--index-only] [-m <arguments for make>]"
	echo "    [-x <glob pattern to exclude from building>]"
	echo "${0##*/} [Common flags] <full name of port directory in $pdb>"
	echo "${0##*/} [Common flags] <full path to $pd/foo/bar>"
	echo "${0##*/} [Common flags] <glob pattern of directories in $pdb>"
	echo "${0##*/} [Common flags] [--update-if-newer] Multiple full names/paths"
	echo "         from $pdb|$pd and/or multiple globs from $pdb"
	echo ''
	echo "${0##*/} [Common flags] . [Use in $pd/foo/bar to build that port]"
	echo ''
	echo "${0##*/} [Common flags] -a"
	echo ''
	echo "${0##*/} --show-work [-Gv] [-m <args>] <single port, as above>"
	echo ''
	echo "${0##*/} [Common flags] -o <new port dir in $pd> <installed port>"
	echo "${0##*/} [Common flags] [-R] -r <name/glob of port directory in $pdb>"
	echo '         (-r <port> can be specified multiple times)'
	echo ''
	echo "${0##*/} -l"
	echo "${0##*/} [--index-only [-t]] -L"
	echo ''
	echo "${0##*/} --list-origins"
	echo ''
	echo "${0##*/} [--force-config|-G] [-P|-PP] [-aftv] -F"
	echo ''
	echo "${0##*/} [-n|y] [-b] [-D|d] -e <name/glob of a single port in $pdb>"
	echo "${0##*/} [-n|y] [-b] [-D|d] -s"
	echo ''
	echo "${0##*/} [-n|y] [-t] --clean-distfiles"
	echo ''
	echo "${0##*/} [-n|y] [--index|--index-only] --clean-packages"
	echo ''
	echo "${0##*/} [-n|y] [--index|--index-only] [-v] --check-depends"
	echo ''
	echo "${0##*/} [-n|y] [-v] --check-port-dbdir"
	echo ''
	echo "${0##*/} -h|--help"
	echo "${0##*/} --version"
	echo ''
	echo "--force-config run 'make config' for all ports (overrides -G)"
	echo "-C prevents 'make clean' from being run before building"
	echo "-G prevents 'make config'"
	echo "-H hide details of the port build and install in a log file"
	echo "-K prevents 'make clean' from being run after building"
	echo '-B prevents creation of the backup package for the installed port'
	echo '-b create and keep a backup package of an installed port'
	echo '-g create a package of the new port'
	echo '-n run through all steps, but do not make or install any ports'
	echo '-t recurse dependencies thoroughly, using all-depends-list'
	echo '-v verbose output'
	echo '-w save old shared libraries before deinstall'
	echo '[-R] -f always rebuild ports (overrides -i)'
	echo '-i interactive update mode -- ask whether to rebuild ports'
	echo '-D no cleaning of distfiles'
	echo '-d always clean distfiles'
	echo "-m <arguments for the 'make' command line>"
	echo "-x <avoid building or updating ports that match this pattern>"
	echo '   Can be specified more than once'
	echo ''
	echo '--no-confirm do not ask user to confirm list of ports to be'
	echo '   installed and/or updated before proceeding'
	echo '--no-term-title do not update the xterm title bar'
	echo ''
	echo '--no-index-fetch skip fetching the INDEX file'
	echo '--index use INDEX-[7-9] exclusively to check if a port is up to date'
	echo '--index-first use the INDEX for status, but double-check with the port'
	echo '--index-only do not try to use /usr/ports'
	echo ''
	echo '--delete-build-only delete ports that are build-only dependencies'
	echo '   after a successful run, only if installed this run'
	echo ''
	echo '--update-if-newer (only for multiple ports listed on command line)'
	echo '   do not rebuild/reinstall if the installed version is up to date'
	echo ''
	echo '-P|--packages use packages, but build port if not available'
	echo '-PP|--packages-only fail if no package is available'
	echo '--packages-build use packages for all build dependencies'
	echo '--packages-if-newer use package if newer than installed even'
	echo '   if the package is not the latest according to the ports tree'
	echo '--always-fetch fetch package even if it already exists locally'
	echo '--local-packagedir=<path> where local packages can be found,'
	echo '   will fall back to fetching if no local version exists'
	echo '--packages-local use packages from --local-packagedir only'
	echo '--delete-packages after installing from a package, delete it'
	echo ''
	echo '-a check all ports, update as necessary'
	echo ''
	echo '--show-work list what ports are and would be installed'
	echo ''
	echo '-o replace the installed port with a port from a different origin'
	echo '[-R] -r rebuild port, and all ports that depend on it'
	echo '-R used with -[rf] to skip ports updated on a previous run'
	echo ''
	echo '-l list all installed ports by category'
	echo '-L list all installed ports by category, and search for updates'
	echo ''
	echo "--list-origins list directories from $pd for root and leaf ports"
	echo ''
	echo '[--force-config|-G] [-aftv] -F fetch distfiles only'
	echo ''
	echo '-n answer no to all user prompts for the features below'
	echo '-y answer yes to all user prompts for the features below'
	echo ''
	echo '[-n|y] [-b] [-D|d] -e expunge one port via pkg_delete, and remove its distfiles'
	echo '[-n|y] [-b] [-D|d] -s clean out stale ports that used to be depended on'
	echo ''
	echo '[-t] [-n] --clean-distfiles offer to delete stale distfiles'
	echo '[-t] -y --clean-distfiles delete stale distfiles without prompting'
	echo '   with -t distfile is valid from any port, not just those installed'
	echo ''
	echo '[--index|--index-only] [-n] --clean-packages offer to delete stale packages'
	echo '[--index|--index-only] -y --clean-packages delete without prompting'
	echo '   --index-only is required if no ports tree is available'
	echo ''
	echo '[-n|y] [-v] --check-depends cross-check and update dependency info for all ports'
	echo ''
	echo "[-n|y] [-v] --check-port-dbdir check for stale entries in $port_dbdir"
	echo ''
	echo '-h|--help display this help message'
	echo '--version display the version number'
	echo ''
	echo 'Please see the portmaster(8) man page for more information'
	safe_exit ${1:-1}
}

globstrip () { local in ; in=${1%[*]} ; in=${in%\\} ; echo $in ; }

# Takes a pattern as input
# Return values:
# 0 - Matched one and only one directory in $pdb
# 1 - No match
# 2 - Matched multiple directories
#
find_glob_dirs () {
	# Global: glob_dirs
	local pattern

	pattern=`globstrip $1`

	if [ -z "$use_pkgng" ]; then
		glob_dirs=`find $pdb -depth 1 -type d -name ${pattern}\*`
	else
		glob_dirs=`pkg query -g "%n-%v" ${pattern}\*`
	fi
	case "$glob_dirs" in
	# Match a newline in multiple responses from find
	*'
'*)		return 2 ;;
	'')	;;
	*)	return ;;
	esac

	unset glob_dirs
	return 1
}

origin_from_pdb () {
	local o

	if [ -z "$use_pkgng" ]; then
		o=`grep -m1 '@comment ORIGIN:' $pdb/$1/+CONTENTS 2>/dev/null` && {
			echo ${o#@comment ORIGIN:}; return 0; }
	else
		pkg info -qo $1 2>/dev/null && return 0
	fi

	case "$1" in bsdpan-*) return 3 ;; esac

	if [ -e "$pdb/$1/+IGNOREME" ] && ( [ -z "$use_pkgng" ] || pkg info -e $1 ); then
		if [ -n "$PM_VERBOSE" -o -n "$LIST_ORIGINS" ]; then
			if [ -z "$use_pkgng" ]; then
				echo "	===>>> No ORIGIN in $pdb/$1/+CONTENTS" >&2
			else
				# An error above doesn't necessarily mean there's
				# a problem in +MANIFEST, so don't mention it
				echo "	===>>> No origin available for $1" >&2
			fi
			echo "	===>>> $pdb/$1/+IGNOREME exists" >&2
			echo '' >&2
		fi
		return 2
	else
		if [ -z "$use_pkgng" ]; then
			echo "	===>>> No ORIGIN in $pdb/$1/+CONTENTS" >&2
		else
			# Same as above
			echo "	===>>> No origin available for $1" >&2
		fi
		echo '' >&2
	fi
	return 1
}

#=============== End functions we always want to have ===============
#=============== Begin Command Line Option Processing ===============

packages_init () {
	local e1 e2 e3

	e1="The -P/--packages and -PP/--packages-only options are mutually exclusive"
	e2="The --packages-build option and the -P[P] options are mutually exclusive"
	e3="The --packages-if-newer and -PP/--packages-only options are mutually exclusive"

	case "$1" in
	first)	[ "$PM_PACKAGES" = only ] && fail $e1
		[ -n "$PM_PACKAGES_BUILD" ] && fail $e2
		[ -z "$PM_PACKAGES" ] && { PM_PACKAGES=first ; export PM_PACKAGES; } ;;
	only)	[ "$PM_PACKAGES" = first ] && fail $e1
		[ "$PM_PACKAGES" = newer ] && fail $e3
		[ -n "$PM_PACKAGES_BUILD" ] && fail $e2 ;;
	build)	case "$PM_PACKAGES" in first|only) fail $e2 ;; esac ;;
	newer)	[ "$PM_PACKAGES" = only ] && fail $e3
		[ -z "$PM_PACKAGES" -a -z "$PM_PACKAGES_BUILD" ] && {
			PM_PACKAGES=newer ; export PM_PACKAGES; } ;;
	local)	[ -z "$PM_PACKAGES" -a -z "$PM_PACKAGES_BUILD" ] && {
			PM_PACKAGES=local ; export PM_PACKAGES; } ;;
	esac
}

cross_idx () {
	local e1

	e1='The --index, --index-first, and --index-only options are mutually exclusive'

	case "$*" in
	*--index*--index*)	fail $e1 ;;
	index\ *)		[ -n "$PM_INDEX_FIRST" -o -n "$PM_INDEX_ONLY" ] && fail $e1 ;;
	first\ *)		[ -n "$PM_INDEX_ONLY" ] && fail $e1 ;;
	only\ *)		[ -n "$PM_INDEX_FIRST" ] && fail $e1 ;;
	esac
}

for var in "$@" ; do
	case "$var" in
	-PP[A-Za-z0-9]*|-*[A-Za-z0-9]PP*)
				fail "The -PP option must stand alone" ;;
	--packages)		packages_init first ;;
	-PP|--packages-only)	packages_init only
				PM_PACKAGES=only ; export PM_PACKAGES ;;
	--packages-build)	packages_init build
				unset PM_PACKAGES
				PM_PACKAGES_BUILD=pmp_build
				export PM_PACKAGES_BUILD ;;
	--packages-if-newer)	packages_init newer
				PM_PACKAGES_NEWER=pmp_newer
				export PM_PACKAGES_NEWER ;;
	--packages-local)	packages_init local
				PM_PACKAGES_LOCAL=pmp_local
				export PM_PACKAGES_LOCAL ;;
	--always-fetch)		PM_ALWAYS_FETCH=pm_always_fetch
				export PM_ALWAYS_FETCH ;;
	--local-packagedir=*)	LOCAL_PACKAGEDIR=${var#--local-packagedir=}
				export LOCAL_PACKAGEDIR ;;
	--delete-packages)	PM_DELETE_PACKAGES=pm_delete_packages
				export PM_DELETE_PACKAGES ;;
	-[A-Za-z0-9]*)		newopts="$newopts $var" ;;
	--update-if-newer)	PM_UPDATE_IF_NEWER=pm_update_if_newer
				export PM_UPDATE_IF_NEWER ;;
	--delete-build-only)	PM_DEL_BUILD_ONLY=pm_dbo
				export PM_DEL_BUILD_ONLY ;;
	--no-confirm)		PM_NO_CONFIRM=pm_no_confirm
				export PM_NO_CONFIRM ;;
	--no-term-title)	PM_NO_TERM_TITLE=pm_no_term_title
				export PM_NO_TERM_TITLE ;;
	--no-index-fetch)	PM_NO_INDEX_FETCH=pm_no_index_fetch ;;
	--index)		cross_idx "index $*" ; PM_INDEX=pm_index ; export PM_INDEX ;;
	--index-first)		cross_idx "first $*" ; PM_INDEX=pm_index
				PM_INDEX_FIRST=pm_index_first
				export PM_INDEX PM_INDEX_FIRST ;;
	--index-only)		cross_idx "only $*" ; PM_INDEX=pm_index
				PM_INDEX_ONLY=pm_index_only
				export PM_INDEX PM_INDEX_ONLY ;;
	--help)			usage 0 ;;
	--version)		version ; exit 0 ;;
	--clean-distfiles)	CLEAN_DISTFILES=clean_distfiles ;;
	--clean-distfiles-all)	echo "===>>> The -all form is deprecated, please use -y instead"
				CLEAN_DISTFILES=clean_distfiles ; PM_YES=yopt ;;
	--clean-packages)	CLEAN_PACKAGES=clean_packages ;;
	--clean-packages-all)	echo "===>>> The -all form is deprecated, please use -y instead"
				CLEAN_PACKAGES=clean_packages ; PM_YES=yopt ;;
	--check-depends)	CHECK_DEPENDS=check_depends ;;
	--check-port-dbdir)	CHECK_PORT_DBDIR=check_port_dbdir ;;
	--list-origins)		LIST_ORIGINS=list_origins ;;
	--show-work)		SHOW_WORK=show ; PM_THOROUGH=thorough ;;
	--force-config)		export PM_FORCE_CONFIG=pm_force_config ;;
	--*)			echo "Illegal option $var" ; echo ''
				echo "===>>> Try ${0##*/} --help"; exit 1 ;;
	*)			newopts="$newopts $var" ;;
	esac
done

[ -n "$PM_INDEX" -a -n "$CHECK_PORT_DBDIR" ] &&
	fail 'The --index* and --check-port-dbdir options are mutually exclusive'

[ -n "$PM_PACKAGES_LOCAL" -a -z "$LOCAL_PACKAGEDIR" ] &&
	fail 'The --packages-local option requires --local-packagedir to be defined'

set -- $newopts
unset var newopts

# Save switches for potential child processes
while getopts 'BCDFGHKLPRabde:fghilm:nop:r:stvwx:y' COMMAND_LINE_ARGUMENT ; do
	case "${COMMAND_LINE_ARGUMENT}" in
	B)	NO_BACKUP=Bopt; ARGS="-B $ARGS" ;;
	C)	DONT_PRE_CLEAN=Copt; ARGS="-C $ARGS" ;;
	D)	DONT_SCRUB_DISTFILES=Dopt; ARGS="-D $ARGS" ;;
	F)	FETCH_ONLY=Fopt; ARGS="-F $ARGS" ;;
	G)	[ -z "$PM_FORCE_CONFIG" ] && {
			PM_NO_MAKE_CONFIG=Gopt; ARGS="-G $ARGS"; } ;;
	H)	HIDE_BUILD=Hopt; ARGS="-H $ARGS" ;;
	K)	DONT_POST_CLEAN=Kopt; ARGS="-K $ARGS" ;;
	L)	LIST_PLUS=Lopt ;;
	P)	packages_init first ;;
	R)	RESTART=Ropt ; ARGS="-R $ARGS" ;;
	a)	UPDATE_ALL=aopt ;;
	b)	BACKUP=bopt; ARGS="-b $ARGS" ;;
	d)	ALWAYS_SCRUB_DISTFILES=dopt; ARGS="-d $ARGS" ;;
	e)	EXPUNGE=$OPTARG ;;
	f)	export PM_FORCE=fopt ;;
	g)	MAKE_PACKAGE=gopt; ARGS="-g $ARGS" ;;
	h)	usage 0 ;;
	i)	INTERACTIVE_UPDATE=iopt; ARGS="-i $ARGS" ;;
	l)	LIST=lopt ;;
	m)	export PM_MAKE_ARGS=$OPTARG	# For 'make checksum'
		ARGS="-m $PM_MAKE_ARGS $ARGS" ;;
	n)	NO_ACTION=nopt; ARGS="-n $ARGS" ;;
	o)	REPLACE_ORIGIN=oopt ;;
	p)	fail 'The -p option has been deprecated' ;;
	r)	PM_URB=ropt
		if [ -d "$pdb/$OPTARG" ] && ( [ -z "$use_pkgng" ] || pkg info -e $OPTARG ); then
			glob_dirs=$OPTARG
		else
			case "$OPTARG" in */*) fail 'The argument to -r must be a package name, or a glob pattern' ;; esac
			find_glob_dirs $OPTARG
			case $? in
			1)	if [ -z "$use_pkgng" ]; then
					fail "$pdb/$OPTARG does not exist"
				else
					fail "$OPTARG is not installed"
				fi ;;
			2)	fail 'The argument to -r must match only one port' ;;
			esac
		fi
		PM_URB_IPORTS="${PM_URB_IPORTS}${glob_dirs##*/} "
		PM_URB_ORIGINS="${PM_URB_ORIGINS}`origin_from_pdb ${glob_dirs##*/}` "
		unset glob_dirs ;;
	s)	CLEAN_STALE=sopt ;;
	t)	PM_THOROUGH=topt; ARGS="-t $ARGS" ;;
	v)	PM_VERBOSE=vopt; ARGS="-v $ARGS" ;;
	w)	SAVE_SHARED=wopt; ARGS="-w $ARGS" ;;
	x)	case "$OPTARG" in
		-*)	fail 'The -x option requires an argument' ;;
		esac
		PM_EXCL="${PM_EXCL}`globstrip ${OPTARG}` " ;;
	y)	PM_YES=yopt; ARGS="-y $ARGS" ;;
	*)	echo '' ; echo "===>>> Try ${0##*/} --help"; exit 1 ;;
	esac
done
shift $(( $OPTIND - 1 ))

[ -n "$PM_YES" -a -n "$NO_ACTION" ] && fail 'The -y and -n options are mutually exclusive'

[ -n "$PM_EXCL" ] && export PM_EXCL

test_command_line () {
	local var envar

	for var in $my_environment; do
		case "$var" in
		${1}=*)	envar=$1 ;;
		${2}=*)	envar=$2 ;;
		esac
	done

	if [ -n "$envar" ]; then
		unset $envar
		return 0
	fi

	return 1
}

# Error checking for getopts
[ -n "$PM_FORCE" -a -n "$INTERACTIVE_UPDATE" ] &&
	fail "The -f and -i options are mutually exclusive"
if [ -n "$BACKUP" -a -n "$NO_BACKUP" ]; then
	test_command_line NO_BACKUP BACKUP ||
		fail "The -b and -B options are mutually exclusive"
fi
if [ -n "$ALWAYS_SCRUB_DISTFILES" -a -n "$DONT_SCRUB_DISTFILES" ]; then
	test_command_line ALWAYS_SCRUB_DISTFILES DONT_SCRUB_DISTFILES ||
		fail "The -d and -D options are mutually exclusive"
fi

[ -n "$PM_NO_MAKE_CONFIG" -a -n "$PM_FORCE_CONFIG" ] && unset PM_NO_MAKE_CONFIG

if [ -n "$LIST" -o -n "$LIST_PLUS" ]; then
	if [ -n "$FETCH_ONLY" -o -n "$RESTART" -o -n "$UPDATE_ALL" -o \
	    -n "$EXPUNGE" -o -n "$PM_FORCE" -o -n "$NO_ACTION" -o \
	    -n "$REPLACE_ORIGIN" -o -n "$PM_URB" -o -n "$CLEAN_STALE" ]; then
		fail 'The -[lL] options are not compatible with -FRaefnors'
	fi
	[ $# -gt 0 ] && fail 'The -[lL] options are not compatible with updates or installs'
fi

[ -n "$PM_PACKAGES" -a -n "$FETCH_ONLY" ] && export PM_NO_CONFIRM=pm_no_confirm

unset my_environment COMMAND_LINE_ARGUMENT
unset -f packages_init cross_idx test_command_line

#=============== End Command Line Option Processing ===============

# Update based on options chosen above
if [ "$$" -eq "$PM_PARENT_PID" ]; then
	# Continue error checking in parent only
	[ -n "$PM_URB" -o -n "$UPDATE_ALL" ] && [ -n "$1" ] &&
	    fail 'The -[ar] options are not compatible with other updates'

	if [ -n "$PM_PACKAGES" -o -n "$PM_PACKAGES_BUILD" ]; then
		if [ -n "$use_pkgng" ]; then
			unset PM_PACKAGES PM_PACKAGES_BUILD PM_PACKAGES_LOCAL PM_PACKAGES_NEWER PM_ALWAYS_FETCH PM_DELETE_PACKAGES
			echo "===>>> Package installation support cannot be used with pkgng yet,"
			echo "       it will be disabled"
			echo ''
		fi
		[ `/sbin/sysctl -n kern.osreldate 2>/dev/null` -lt 600400 ] &&
			fail Package installation support requires FreeBSD 6.4 or newer
	fi

	if [ -n "$PM_INDEX" ] &&
	    [ -z "$LIST" -a -z "$LIST_ORIGINS" -a -z "$EXPUNGE" -a -z "$CLEAN_STALE" ]; then
		if [ -z "$INDEXFILE" ]; then
			ver=`uname -r`
			INDEXFILE=INDEX-${ver%%\.*}
			unset ver
		fi

		[ -z "$INDEXDIR" -a -n "$PM_INDEX_ONLY" -a -z "$pd" ] && INDEXDIR="$TMPDIR"

		PM_INDEX="${INDEXDIR:=$pd}/${INDEXFILE}"

		if [ -z "$PM_NO_INDEX_FETCH" ]; then
			: ${FETCHINDEX:='fetch -am -o'}
			: ${MASTER_SITE_INDEX:='http://www.FreeBSD.org/ports/'}

			do_index_fetch=yes_index_fetch

			index_time=`stat -f '%Um' ${PM_INDEX}.bz2 2>/dev/null`

			if [ -n "$index_time" ]; then
				# If root, this will succeed either way
				if $FETCHINDEX ${PM_INDEX}.bz2 ${MASTER_SITE_INDEX}${INDEXFILE}.bz2 2>/dev/null; then
					unset do_index_fetch
					newindex="${PM_INDEX}.bz2"
				fi
			fi

			if [ -n "$do_index_fetch" ] ||
			    [ ${index_time:-0} -ne `stat -f '%Um' ${PM_INDEX}.bz2 2>/dev/null` ]; then
				dli=`/usr/bin/mktemp -d ${TMPDIR}/d-${PM_PARENT_PID}-index 2>/dev/null` ||
					fail "Could not create a temporary directory for index in $TMPDIR"
				if [ -n "$do_index_fetch" ]; then
					ift="$FETCHINDEX ${dli}/${INDEXFILE}.bz2 ${MASTER_SITE_INDEX}${INDEXFILE}.bz2"
					$ift || fail Could not perform $ift
					unset ift
					newindex="${dli}/${INDEXFILE}.bz2"
				fi

				bunzip2 --keep < $newindex > ${dli}/$INDEXFILE
				if [ -w "${INDEXDIR}/" ]; then
					pm_unlink $PM_INDEX
					mv ${dli}/$INDEXFILE $PM_INDEX
					if [ -n "$do_index_fetch" ]; then
						pm_unlink ${PM_INDEX}.bz2
						mv ${dli}/${INDEXFILE}.bz2 ${PM_INDEX}.bz2
					fi
				else
					pm_sv 'Installing new INDEX file'
					pm_install_s ${dli}/$INDEXFILE $PM_INDEX
					[ -n "$do_index_fetch" ] &&
						pm_install_s ${dli}/${INDEXFILE}.bz2 ${PM_INDEX}.bz2
				fi
				rm -rf $dli ; unset dli
			fi
			unset FETCHINDEX MASTER_SITE_INDEX do_index_fetch index_time newindex
		else
			[ -r "$PM_INDEX" ] ||
				fail "The --no-index-fetch option was used, but $PM_INDEX does not exist"
		fi
		unset INDEXFILE INDEXDIR

		if [ -z "$use_pkgng" ]; then
			pkg_version="pkg_version"
		else
			pkg_version="pkg version"
		fi
		PM_INDEX_PORTS=`$pkg_version -Ivl\< $PM_INDEX | cut -f1 -d\<`
		export PM_INDEX_PORTS

		if [ -z "$pd" -o "$pd" != /usr/ports ]; then
			PM_IPD=`head -1 $PM_INDEX | cut -f 2 -d\|`
			PM_IPD=${PM_IPD%/*}
			PM_IPD=${PM_IPD%/*}

			[ -n "$PM_INDEX_ONLY" ] && pd=$PM_IPD
		else
			PM_IPD=$pd
		fi
		export PM_IPD
	fi	# [ -n "$PM_INDEX" ]

	if [ -z "$EXPUNGE" -a -z "$CLEAN_STALE" ]; then
		if [ -n "$pd" ]; then
			export pd
		elif [ -z "$LIST" -a -z "$LIST_ORIGINS" ]; then
			fail 'The value of PORTSDIR cannot be empty'
		fi
	else
		if [ -n "$pd" ] && [ -d "$pd" ]; then
			export pd
		else
			if [ -z "$DONT_SCRUB_DISTFILES" ]; then
				pm_v "===>>> There is no ports tree, so using -D option"
				unset ALWAYS_SCRUB_DISTFILES
				DONT_SCRUB_DISTFILES=Dopt_es; ARGS="-D $ARGS"
			fi
		fi
	fi

	if [ -z "$DISTDIR" -a "$PM_PACKAGES" != only -a -z "$CHECK_DEPENDS" -a \
	    -z "$CHECK_PORT_DBDIR" -a -z "$LIST_ORIGINS" ]; then
		if ! DISTDIR=`pm_make_b -f/usr/share/mk/bsd.port.mk -V DISTDIR 2>/dev/null`; then
			if [ ! -d "$PWD" ]; then
				echo ''
				echo "===>>> Your current working directory no longer seems to exist"
				fail 'Try: cd'
			fi
		fi
	fi

	[ -n "$DISTDIR" ] && { DISTDIR="${DISTDIR%/}/"; export DISTDIR; }

	if [ -n "$PM_PACKAGES_BUILD" -o -n "$PM_DEL_BUILD_ONLY" ]; then
		PM_BUILD_ONLY_LIST=pm_bol
		export PM_BUILD_ONLY_LIST
	fi
fi	# [ "$$" -eq "$PM_PARENT_PID" ]

#=============== Begin functions relevant to --features and main ===============

iport_from_origin () {
	local sn dir

	if [ -n "$use_pkgng" ]; then
		pkg info -qO ${1} || return 1
		return
	fi
	sn=${1#*/} ; sn=${sn%-*} ; sn=${sn%%[0-9]*}

	if ! dir=`grep -l "@comment ORIGIN:${1}$" $pdb/${sn}*/+CONTENTS 2>/dev/null`; then
		if ! dir=`grep -l "@comment ORIGIN:${1}$" $pdb/*/+CONTENTS 2>/dev/null`; then
			dir=`pkg_info -q -O $1` ; [ -n "$dir" ] || return 1
		fi
	fi

	# It should not happen that more than one port meets this
	# requirement, but it can if the pkg data is corrupted.
	dir="${dir%%/+CONTENTS*}"
	echo ${dir#$pdb/}
}

check_regular_file () {
	[ ! -L "$1" -a -f "$1" ] || fail "ERROR: $1 is not a regular file!"
}

strip_to_iport () {
	local in

	while read in; do
		in="${in%/+CONTENTS}"
		in="${in##*/}"
		echo $in
	done
}

# Redundant with pkgng
check_dependency_files () {
	[ -n "$use_pkgng" ] && return
	# Global: grep_deps
	local origin iport ro_opd

	origin=$1 ; iport=$2

	# egrep hates + in file names
	case "$origin" in *+*) origin=`echo $origin | sed 's#\+#\\\\+#g'` ;; esac
	case "$ro_opd" in
	'')	ro_opd=a/a ;;
	*+*)	ro_opd=`echo $ro_opd | sed 's#\+#\\\\+#g'` ;; esac

	# Always rely on the grep'ed dependencies instead of +REQUIRED_BY
	pm_mktemp grep-deps-${iport} ; grep_deps=$pm_mktemp_file
	find $pdb -depth 2 -name +CONTENTS -exec egrep -l "DEPORIGIN:($origin|$ro_opd)$" {} + |
	    strip_to_iport | sort -u > $grep_deps

	if [ ! -s "$grep_deps" ]; then
		if [ -s "$pdb/$iport/+REQUIRED_BY" ]; then
			# No actual dependencies exist, so this file is stale
			# Zero it out so that -s mode can find it
			pm_v "	===>>> No installed ports depend on $iport"
			pm_v "	===>>> Emptying +REQUIRED_BY file.  Try ${0##*/} -s"

			check_regular_file $pdb/$iport/+REQUIRED_BY
			$PM_SU_CMD truncate -s0 $pdb/$iport/+REQUIRED_BY
		fi
		/bin/unlink $grep_deps ; unset grep_deps
	fi
}

# Takes default value, optional value, and message as input
# Return values:
# 0 - Default value chosen
# 1 - Optional value chosen
#
get_answer_g () {
	local default option answer

	default=$1 ; option=$2 ; shift 2

	while : ; do
		echo -e "${*} [${default}] \c"
		read answer
		echo ''

		case "$answer" in
		[A-Z])	answer=`echo $answer | tr [:upper:] [:lower:]` ;;
		esac

		case "$answer" in
		${default}|'')	return 0 ;;
		${option})	return 1 ;;
		*)	echo "	===>>> $answer is not a valid response" ; echo '' ;;
		esac
	done
}

# Takes a default value and message as input
# Return values:
# 0 - Answer is "Yes"
# 1 - Answer is "No"
#
get_answer_yn () {
	local default option

	default=$1 ; shift

	[ "$default" = 'y' ] && option=n || option=y

	if [ -z "$PM_YES" -a -z "$NO_ACTION" ]; then
		get_answer_g $default $option "${*}? y/n"
		case "${?}${default}" in
		0y|1n)	return 0 ;;
		0n|1y)	return 1 ;;
		esac
	else
		[ -n "$PM_YES" ] && return 0
		return 1
	fi
}

# redundant with pkgng
update_contents () {
	[ -n "$use_pkgng" ] && return
	local IFS delete contents origin n_port old_origin iport
	local o_seen line d_missing d_origin d_iport prev_line answer

# To prevent words in a line being treated individually
IFS='
'
	[ "$1" = 'delete' ] && { delete=delete ; shift; }

	contents=$1 ; origin=$2 ; n_port=$3 ; old_origin=$4
	iport=${contents#$pdb/} ; iport=${iport%/+CONTENTS}
	pm_mktemp contents-${iport}

	if [ -z "$delete" ]; then o_seen=':'; else o_seen=":${origin}:"; fi

	for line in `cat $contents`; do
		if [ -n "$d_missing" ]; then
			unset d_missing
			d_origin=${line#*DEPORIGIN:}

			case "$o_seen" in *:${d_origin}:*)
				unset prev_line line ; continue ;; esac
			o_seen="${o_seen}${d_origin}:"

			if [ "$d_origin" = "$old_origin" ]; then
				d_iport=$n_port
				d_origin=$origin
			else
				d_iport=`iport_from_origin $d_origin`
			fi

			if [ -n "$d_iport" ]; then
				pm_v "	===>>> Updating @pkgdep for $d_origin"
			else
				echo ''
				echo "	===>>> $d_origin is listed as a dependency"
				echo "	===>>> but there is no installed version"
				echo ''
				if [ -n "$CHECK_DEPENDS" ]; then
					get_answer_yn n "\t===>>> Delete this dependency data"
					case "$?" in 0) unset prev_line line ; continue ;; esac
				else
					echo "	===>>> Try ${0##*/} --check-depends"
					echo ''
				fi
			fi

			# Could be fixed or not, but if we get here write it
			# so we can warn the user again later if we need to.
			echo "@pkgdep $d_iport" >> $pm_mktemp_file
			echo "@comment DEPORIGIN:$d_origin" >> $pm_mktemp_file
			unset prev_line
			continue
		fi
		case "$line" in
		"@comment DEPORIGIN:$origin"|"@comment DEPORIGIN:$old_origin")
			d_origin=${line#*DEPORIGIN:}
			unset prev_line line

			case "$o_seen" in *:${d_origin}:*) continue ;; esac
			o_seen="${o_seen}${d_origin}:"

			echo "@pkgdep $n_port" >> $pm_mktemp_file
			echo "@comment DEPORIGIN:$origin" >> $pm_mktemp_file ;;
		'@comment DEPORIGIN:'*)
			d_origin=${line#*DEPORIGIN:}
			case "$o_seen" in *:${d_origin}:*)
				unset prev_line line ; continue ;; esac
			o_seen="${o_seen}${d_origin}:" ;;
		'@pkgdep '|@pkgdep) d_missing=d_missing ;;
		@pkgdep*)	d_iport="${line#@pkgdep }"
				[ -d "$pdb/$d_iport" ] || d_missing=dm2 ;;
		esac
		[ -n "$prev_line" ] && echo $prev_line >> $pm_mktemp_file
		prev_line=$line
	done
	[ -n "$prev_line" ] && echo $prev_line >> $pm_mktemp_file

	if ! cmp -s $contents $pm_mktemp_file; then
		check_regular_file $contents
		pm_v "	===>>> Installing the new +CONTENTS file"
		pm_install_s $pm_mktemp_file $contents
	fi

	/bin/unlink $pm_mktemp_file ; unset pm_mktemp_file
}

find_moved_port () {
	# Global: moved_npd
	local sf iport IFS l reason

	sf=$1	# Search for
	iport=$2

	# To avoid having each word of the reason treated separately
	IFS='
'
	for l in `grep "^$sf|" $pd/MOVED`; do
		case "$l" in
		${sf}\|\|*) [ -n "$iport" ] || iport=`iport_from_origin $sf`
			if [ -e "$pdb/$iport/+IGNOREME" ] && ( [ -z "$use_pkgng" ] || pkg info -e $iport ); then
				if [ -n "$PM_VERBOSE" ]; then
					echo ''
					echo "	===>>> The $sf port has been deleted"
					echo "	===>>> Reason: ${l##*|}"
					echo "	===>>> Skipping it due to +IGNOREME file"
					echo ''
				fi
				return 0
			else
				reason=${l##*|}
				[ "$3" != 'nonfatal' ] &&
					fail "The $sf port has been deleted: $reason"
			fi ;;
		${sf}\|*) moved_npd=${l#*\|}	# New port directory
			moved_npd=${moved_npd%%\|*}
			echo ''
			echo "	===>>> The $sf port moved to $moved_npd"
			echo "	===>>> Reason: ${l##*|}"
			echo ''
			find_moved_port $moved_npd ;;
		esac
	done

	if [ -z "$moved_npd" ]; then
		if [ -z "$reason" ]; then
			echo ''
			echo "	===>>> No $pd/$1 exists, and no information"
			echo "	===>>> about $1 can be found in $pd/MOVED"
		else	# Only reached in LIST_PLUS
			echo "	===>>> The $sf port has been deleted: $reason"
		fi
		echo ''

		[ -n "$iport" ] || iport=`iport_from_origin $sf`
		[ -e "$pdb/$iport/+IGNOREME" ] && ( [ -z "$use_pkgng" ] || pkg info -e $iport ) || return 1
	fi
	return 0
}

all_pkgs_by_origin () {
	if [ -z "$use_pkgng" ]; then
		local pkg iport origin

		for pkg in ${pdb}/* ; do
			[ -d $pkg ] || continue
			iport=${pkg#$pdb/}

			origin=`origin_from_pdb $iport` || continue
			echo $iport $origin
		done
	else
		pkg query -a "%n-%v %o"
	fi
	return
}

read_distinfos () {
	local iport origin distinfo s f discard

	echo '############' > $DI_FILES		# Make the file > 0 bytes
	echo "===>>> Gathering distinfo list for installed ports"
	echo ''

	all_pkgs_by_origin | while read iport origin; do
		if [ ! -d "$pd/$origin" ]; then
			find_moved_port $origin $iport nonfatal >/dev/null
			[ -n "$moved_npd" ] || continue
			origin=$moved_npd
		fi

		origin="${pd}/${origin}"

		if [ -s "${origin}/distinfo" ]; then
			distinfo="${origin}/distinfo"
		else
			pm_cd $origin || continue
			distinfo=`pm_make -V DISTINFO_FILE`

			# Do not make this error fatal unless using
			# --clean-distfiles. This will prevent accidentally
			# killing other background processes when running
			# in the background itself.
			if [ -z "$distinfo" ]; then
				if [ -z "$CLEAN_DISTFILES" ]; then
					continue
				else
					fail "No DISTINFO_FILE in $origin"
				fi
			fi
		fi

		if [ -s "$distinfo" ]; then
			while read s f discard; do
				case "$s" in
				SHA256) f=${f#(} ; echo ${f%)} >> $DI_FILES ;;
				esac
			done < $distinfo
		fi
	done

	# Tell safe_exit that we are done
	pm_unlink ${DI_FILES}-e
	sed -i -e 1s/############/%%%%%%%%%%%%/ $DI_FILES
	pm_unlink ${DI_FILES}-e
}

read_distinfos_all () {
	local origin distinfo s f discard

	echo '############' > $DI_FILES		# Make the file > 0 bytes
	echo "===>>> Gathering distinfo list for all ports"
	echo '       (This will take several minutes)'
	echo ''

	for origin in ${pd}/*/*; do
		case "${origin#$pd/}" in
		Mk/*|T*|distfiles/*|packages/*|*/[Mm]akefile*|CVS/*|*/CVS) continue ;; esac

		[ -d "$origin" ] || continue

		if [ -s "${origin}/distinfo" ]; then
			distinfo="${origin}/distinfo"
		else
			pm_cd $origin || continue
			distinfo=`pm_make -V DISTINFO_FILE`
			[ -n "$distinfo" ] ||
				{ echo ''; echo "===>>> No DISTINFO_FILE in $origin"; echo ''; }
		fi

		if [ -s "$distinfo" ]; then
			while read s f discard; do
				case "$s" in
				SHA256) f=${f#(} ; echo ${f%)} >> $DI_FILES ;;
				esac
			done < $distinfo
		fi
	done

	# Tell safe_exit that we are done
	pm_unlink ${DI_FILES}-e
	sed -i -e 1s/############/%%%%%%%%%%%%/ $DI_FILES
	pm_unlink ${DI_FILES}-e
}

ports_by_category () {
	# Global: num_roots num_trunks num_branches num_leaves num_ports
	local pkg

	pm_v "===>>> Sorting ports by category"

	if [ -z "$use_pkgng" ]; then
		num_roots=0; num_trunks=0; num_branches=0; num_leaves=0
		for pkg in $pdb/*; do
			if [ -s "$pkg/+REQUIRED_BY" ]; then
				if grep -ql '^@pkgdep ' $pkg/+CONTENTS 2>/dev/null; then
					branches="$branches ${pkg#$pdb/}"
					num_branches=$(( $num_branches + 1 ))
				else
					trunks="$trunks ${pkg#$pdb/}"
					num_trunks=$(( $num_trunks + 1 ))
				fi
			else
				if grep -ql '^@pkgdep ' $pkg/+CONTENTS 2>/dev/null; then
					leaves="$leaves ${pkg#$pdb/}"
					num_leaves=$(( $num_leaves + 1 ))
				else
					[ -d "$pkg" ] || continue
					roots="$roots ${pkg#$pdb/}"
					num_roots=$(( $num_roots + 1 ))
				fi
			fi
		done

		num_ports=$(( $num_roots + $num_trunks + $num_branches + $num_leaves ))
	else
		roots=`   pkg query -e "%#d = 0 && %#r = 0" "%n-%v"`
		trunks=`  pkg query -e "%#d = 0 && %#r > 0" "%n-%v"`
		branches=`pkg query -e "%#d > 0 && %#r > 0" "%n-%v"`
		leaves=`  pkg query -e "%#d > 0 && %#r = 0" "%n-%v"`

		num_roots=$(echo    $(echo $roots    | wc -w))
		num_trunks=$(echo   $(echo $trunks   | wc -w))
		num_branches=$(echo $(echo $branches | wc -w))
		num_leaves=$(echo   $(echo $leaves   | wc -w))

		num_ports=$(echo $(pkg query -a "%n-%v" | wc -w))
	fi
}

delete_empty_dist_subdirs () {
	# Get back to somewhere safe so we do not
	# delete our CWD out from under ourselves
	pm_cd $DISTDIR || fail "Cannot cd into $DISTDIR"
	find $DISTDIR -depth -mindepth 1 -type d \( -empty -and ! -path \*\.zfs/\* \) -delete
}

init_packages_var () {
	# Global: PACKAGES

	[ -n "$PACKAGES" ] && return

	PACKAGES=`pm_make -f/usr/share/mk/bsd.port.mk -V PACKAGES 2>/dev/null`
	if [ -z "$PACKAGES" ]; then
		if [ -d "${pd}/packages" -a -w "${pd}/packages" ]; then
			PACKAGES="${pd}/packages"
		else
			if [ -d "${pd}/" -a -w "${pd}/" ]; then
				PACKAGES="${pd}/packages"
			else
				fail 'The value of PACKAGES cannot be empty and the directory must be writable'
			fi
		fi
	fi
	export PACKAGES
}

parse_index () {
	local line

	line=`grep -m1 "|${PM_IPD}/${1}|" $PM_INDEX` || return 1

	case "$2" in
	name)		echo ${line%%|*} ;;
	localbase)	echo $line | cut -f 3 -d\| ;;
	comment)	echo $line | cut -f 4 -d\| ;;
	descr)		echo $line | cut -f 5 -d\| ;;
	maintainer)	echo $line | cut -f 6 -d\| ;;
	category)	echo $line | cut -f 7 -d\| ;;
	b-deps)		echo $line | cut -f 8 -d\| ;;
	r-deps)		echo $line | cut -f 9 -d\| ;;
	www)		echo $line | cut -f 10 -d\| ;;
	esac
}

# Redundant with pkgng
update_required_by () {
	[ -n "$use_pkgng" ] && /bin/unlink $grep_deps && unset grep_deps && return
	# Global: needws
	local do_update

	if [ -e "$pdb/$1/+REQUIRED_BY" ]; then
		sort $pdb/$1/+REQUIRED_BY | cmp -s $grep_deps - || do_update=do_update
		check_regular_file $pdb/$1/+REQUIRED_BY
	else
		do_update=do_update2
	fi
 	if [ -n "$do_update" ]; then
		pm_v "	===>>> Updating $1/+REQUIRED_BY"
		needws=needws_urb
		pm_install_s $grep_deps $pdb/$1/+REQUIRED_BY
	fi

	/bin/unlink $grep_deps && unset grep_deps
}

#=============== End functions relevant to --features and main ===============
#=============== Begin code relevant only to --features ===============

if [ -n "$CLEAN_DISTFILES" ]; then
	[ -n "$DISTDIR" ] || fail 'There is no DISTDIR to clean'

	# Set the file name here since we are usually called in a subshell
	pm_mktemp DI-FILES ; DI_FILES=$pm_mktemp_file

	if [ -z "$PM_THOROUGH" ]; then
		read_distinfos
	else
		read_distinfos_all
	fi

	echo "===>>> Checking for stale distfiles" ; echo ''
	for df in `find $DISTDIR -type f | sort`; do
		f=${df#$DISTDIR}
		if ! grep -ql ^$f $DI_FILES; then
			get_answer_yn n "\t===>>> Delete stale file: $f"
			case "$?" in
			0)	echo "       Deleting $f" ; echo ''
				/bin/unlink $df ;;
			*)	continue ;;
			esac
		fi
	done

	delete_empty_dist_subdirs
	safe_exit
fi

if [ -n "$CLEAN_PACKAGES" ]; then
	init_packages_var

	echo "===>>> Checking for stale packages"
	for package in `find $PACKAGES -type f | sort`; do
		pkg_dir=${package##*/} ; pkg_dir=${pkg_dir%\.*} ; echo ''

		[ -n "$use_pkgng" ] &&
			origin=`pkg query -F $package "%o" 2>/dev/null` ||
			origin=`tar -O -zxvf $package '+CONTENTS' 2>/dev/null | grep '@comment ORIGIN:'` ||
			origin=`tar -O -zxvf $package '+MANIFEST' 2>/dev/null | grep '^origin:'` ||
			fail "Empty origin in $package"
		origin=${origin#@comment ORIGIN:}
		origin=${origin#origin: }

		if [ -z "$PM_INDEX" ]; then
			if [ -d "$pd/$origin" ]; then
				pm_cd $pd/$origin && port_ver=`pm_make -V PKGNAME`
				[ -n "$port_ver" ] || fail "Is $pd/$origin/Makefile missing?"
			else
				echo "===>>> The origin for ${package##*/} ($origin) is missing"
			fi
		else
			if ! port_ver=`parse_index $origin name`; then
				echo "===>>> Cannot determine latest version of ${package##*/} from $PM_INDEX"
			fi
		fi

		if [ -n "$port_ver" ]; then
			if [ "$port_ver" = "$pkg_dir" ]; then
				echo "===>>> ${package##*/} is up to date"
				if [ -z "$use_pkgng" ]; then
					if [ ! -d "${pdb}/${pkg_dir}" ]; then
						echo "	===>>> $pkg_dir is not installed"
						echo "	===>>> Path: ${package}"
						get_answer_yn y "\n\t===>>> Delete stale package: ${package##*/}"
						case "$?" in
						0)	echo "	===>>> Deleting $package"
							pm_unlink_s $package ;;
						esac
					fi
				else
					if ! pkg info -e $pkg_dir; then
						echo "	===>>> $pkg_dir is not installed"
						echo "	===>>> Path: ${package}"
						get_answer_yn y "\n\t===>>> Delete stale package: ${package##*/}"
						case "$?" in
						0)	echo "	===>>> Deleting $package"
							pm_unlink_s $package ;;
						esac
					fi
				fi
				unset port_ver
				continue
			fi

			echo "===>>> Package version: $pkg_dir"
			echo "       Latest version:  $port_ver"

			unset port_ver

			if [ -z "$use_pkgng" ]; then
				if [ -d "${pdb}/${pkg_dir}" ]; then
					echo "	===>>> ${package##*/} matches the installed version"
				else
					echo "	===>>> ${package##*/} is not installed"
				fi
			else
				if pkg info -e $pkg_dir; then
					echo "	===>>> ${package##*/} matches the installed version"
				else
					echo "	===>>> ${package##*/} is not installed"
				fi
			fi
		fi

		echo "	===>>> Path: ${package}"

		get_answer_yn n "\n\t===>>> Delete stale package: ${package##*/}"
		case "$?" in
		0)	echo "	===>>> Deleting $package"
			pm_unlink_s $package ;;
		esac
	done
	echo '' ; echo ''

	echo "===>>> Deleting stale symlinks"
	pm_cd $PACKAGES || fail "Cannot cd to $PACKAGES"
	for link in `find . -type l | sort` ; do
		if [ ! -e "$link" ]; then
			echo "	===>>> ${link#./}"
			$PM_SU_CMD /bin/unlink $link
		fi
	done
	echo '' ; echo ''

	empty_dirs=`find . -type d -empty -print | sort`
	case "$empty_dirs" in
	\.|'')	echo "===>>> No empty directories in $PACKAGES" ;;
	*)	echo "===>>> Deleting empty directories"
		for dir in $empty_dirs; do
			echo "	===>>> ${dir#\.\/}"
		done
		pm_find_s . -type d -empty -delete ;;
	esac
	echo ''

	safe_exit
fi	# [ -n "$CLEAN_PACKAGES" ]

if [ -n "$CHECK_DEPENDS" ]; then
	if [ -n "$use_pkgng" ]; then
		# TODO
		pkg check -adv
		exit
	fi
	PM_VERBOSE=pmv_check_depends
IFS='
'
	for pkg in $pdb/*; do
		[ -d "$pkg" ] || continue

		iport=${pkg#$pdb/}

		echo "===>>> Checking $iport"

		if [ ! -r "$pkg/+CONTENTS" ]; then
			echo "	===>>> Warning: No +CONTENTS file!"
			continue
		fi

		origin=`origin_from_pdb $iport` || continue

		if [ -z "$PM_INDEX_ONLY" ]; then
			if [ -n "$pd" ] && [ ! -d "$pd/$origin" ]; then
				missing=missing
			fi
		else
			parse_index $origin name >/dev/null || missing=missing
		fi
		if [ -n "$missing" ]; then
			echo "	===>>> $pd/$origin does not exist"
			echo "	===>>> This port should probably be updated"
			unset missing
			continue
		fi

		check_dependency_files $origin $iport
		[ -s "$grep_deps" ] && update_required_by $iport

		update_contents $pkg/+CONTENTS
	done
	exit 0
fi

if [ -n "$CHECK_PORT_DBDIR" ]; then
	[ -d "$port_dbdir" ] ||
		fail 'PORT_DBIR is empty, or the directory $port_dbdir does not exist'

	unique_list=':'

	echo "===>>> Building list of installed port names"; echo ''
	if [ -z "$use_pkgng" ]; then
		for pkg in $pdb/*; do
			[ -d $pkg ] || continue

			iport=${pkg#$pdb/}
			origin=`origin_from_pdb $iport` || continue

			if [ ! -d "$pd/$origin" ]; then
				find_moved_port $origin $iport nonfatal >/dev/null
				[ -n "$moved_npd" ] || continue
				origin=$moved_npd
			fi

			if ! pm_cd $pd/$origin; then
				echo "	===>>> $pd/$origin does not exist for $pkg"
				continue
			fi
			unique_list="${unique_list}`make -V UNIQUENAME`:"
		done
	else
		while read pkg origin; do
			if [ ! -d "$pd/$origin" ]; then
				find_moved_port $origin $pkg nonfatal >/dev/null
				[ -n "$moved_npd" ] || continue
				origin=$moved_npd
			fi

			if ! pm_cd $pd/$origin; then
				echo "	===>>> $pd/$origin does not exist for $pkg"
				continue
			fi
			unique_list="${unique_list}`make -V UNIQUENAME`:"
		done << EOF
`pkg query -a "%n-%v %o"`
EOF
	fi

	echo "===>>> Checking $port_dbdir"

	[ -n "$PM_VERBOSE" ] && { print='-print'; echo '';
		echo "===>>> Deleting empty directories (if any)"; }
	pm_find_s $port_dbdir -type d -empty $print -delete
	pm_v

	for dir in ${port_dbdir}/*; do
		dbdir=${dir#$port_dbdir/}

		[ -n "$PM_VERBOSE" ] && echo -n "===>>> Checking ${dbdir}: "
		case "$unique_list" in
		*:${dbdir}:*)	pm_v "Ok" ;;
		*)	pm_v
			echo "	===>>> $dbdir does not seem to be installed"
			get_answer_yn n "\n\t===>>> Delete ${dir}"
			case "$?" in 0) pm_rm_s -rf $dir ;; esac
			echo '' ;;
		esac
	done
	exit 0
fi

if [ -n "$LIST_ORIGINS" ]; then
	ports_by_category

	for iport in $roots $leaves; do
		origin=`origin_from_pdb $iport` || continue
		echo $origin
	done

	exit 0
fi

#=============== End code relevant only to --features ===============
#=============== Begin functions for getopts features and main ===============

check_state () {
	# Global: state
	local state_set

	if egrep -ql '^(FORBIDDEN|DEPRECATED|BROKEN|IGNORE)' Makefile; then
		for state in FORBIDDEN DEPRECATED BROKEN IGNORE; do
			state_set=`pm_make -V $state`
			if [ -n "$state_set" ]; then
				echo "	===>>> This port is marked $state"
				echo -e "\t===>>> $state_set\n\n"
				return 1
			fi
		done
	fi
	return 0
}

# Takes $iport and $origin as arguments
#
check_force_multi () {
	if [ -n "$PM_FORCE" ]; then
		check_restart_and_udf $1 || return 1
	elif [ -n "$PM_URB_UP" ]; then
		case " $PM_URB_LIST " in *" $1 "*) check_restart_and_udf $1 || return 1 ;;
		esac
	elif [ -n "$PM_MULTI_PORTS" ]; then
		case "$PM_MULTI_PORTS" in
		*:${1}:*)	return 1 ;;
		*:${2}:*)	return 1 ;;
		esac
	fi
}

check_for_updates () {
	# Global: num_updates
	local nf iport origin port_ver do_update skip

	[ "$1" = 'list' -o "$1" = 'multi' ] && { nf=nonfatal; shift; }

	iport=$1 ; origin=${2:-`origin_from_pdb $iport`} || return 0

	if [ -n "$PM_INDEX" ]; then
		case "$PM_INDEX_PORTS" in
		*${iport}*)	port_ver=`parse_index $origin name` ||
					fail "No entry for $origin in $PM_INDEX"
				do_update=upd_idx ;;
		esac

		[ -z "$do_update" -a -z "$LIST_PLUS" ] && {
			check_force_multi $iport $origin || do_update=upd_fm_idx; }

		if [ -z "$do_update" -a -n "$PM_INDEX_ONLY" -a -n "$PM_THOROUGH" ]; then
			port_ver=`parse_index $origin name` || {
				echo "	===>>> $pd/$origin does not exist in $PM_INDEX";
				echo "	===>>> This port should probably be updated"; }
		else
			[ -n "$PM_INDEX_FIRST" ] || skip=index_skip
		fi
	fi

	if [ -z "$do_update" -a -z "$skip" -a -z "$PM_INDEX_ONLY" ] && [ -d "$pd/$origin" ]; then
		if ! pm_cd $pd/$origin; then
			if [ -e "$pdb/$iport/+IGNOREME" ] && ( [ -z "$use_pkgng" ] || pkg info -e $iport ); then
				echo "	===>>> Warning: Unable to cd to $pd/$origin"
				echo "	===>>> Continuing due to $pdb/$iport/+IGNOREME"
				echo ''
				CUR_DEPS="${CUR_DEPS}${iport}:${origin}:"
				return 0
			else
				fail "Cannot cd to port directory: $pd/$origin"
			fi
		fi
		port_ver=`pm_make -V PKGNAME`
		[ -z "$port_ver" ] && fail "Is $pd/$origin/Makefile missing?"
	elif [ -z "$do_update" -a -z "$skip" -a -z "$PM_INDEX_ONLY" ]; then
		find_moved_port $origin $iport $nf

		# If the port has moved and no +IGNOREME, we have to update it
		if [ -n "$moved_npd" ]; then
			if [ -e "$pdb/$iport/+IGNOREME" ] && ( [ -z "$use_pkgng" ] || pkg info -e $iport ); then
				echo "	===>>> Continuing due to $pdb/$iport/+IGNOREME"
				echo ''
				CUR_DEPS="${CUR_DEPS}${iport}:${origin}:"
				return 0
			else
				do_update=do_update_moved
			fi
		fi
	fi

	if [ -z "$do_update" -a -n "$port_ver" ]; then
		if [ "$iport" = "$port_ver" ]; then
			if [ -n "$LIST_PLUS" -a -z "$PM_INDEX_ONLY" ]; then
				check_state
				return 0
			elif [ -n "$LIST" ]; then
				return 0
			else
				check_force_multi $iport $origin || do_update=upd_fm_eq
				unset port_ver
			fi
		else
			local pkg_version
			if [ -z "$use_pkgng" ]; then
				pkg_version="pkg_version"
			else
				pkg_version="pkg version"
			fi
			case `$pkg_version -t $iport $port_ver` in
			\<)	do_update=upd_lt ;;
			=)	;;	# Can be reached if same version with different options
			\>)	if [ -n "$PM_VERBOSE" ]; then
					echo "	===>>> Port version $port_ver does not"
					echo "	===>>> seem newer than installed $iport"
				fi ;;
			*)	fail "$pkg_version -t $iport $port_ver gave an unexpected result"
			esac

			[ -z "$do_update" ] && {
				check_force_multi $iport $origin || do_update=upd_fm_ne; }
		fi
	fi

	if [ -z "$do_update" ]; then
		[ -z "$LIST_PLUS" ] && CUR_DEPS="${CUR_DEPS}${iport}:${origin}:"
		return 0
	fi

	if [ -n "$LIST_PLUS" ]; then
		if [ -z "$moved_npd" ]; then
			echo "	===>>> New version available: $port_ver"
			if [ -e "$pdb/$iport/+IGNOREME" ] && ( [ -z "$use_pkgng" ] || pkg info -e $iport ); then
				echo "	===>>> +IGNOREME file is present for $1"
			fi
			pm_cd_pd $origin && check_state
			num_updates=$(( $num_updates + 1 ))
		else
			unset moved_npd
		fi
		return 0
	elif [ -n "$PM_UPDATE_IF_NEWER" ]; then
		return 1
	fi

	# No need for check_exclude here because it is already
	# run in the places that call check_for_updates().
	check_interactive $iport $port_ver || return 0
	update_port $iport $port_ver || return 1
	return 0
}

init_packages () {
	# Global: pbu

	[ -n "$FETCH_ONLY" ] && return

	init_packages_var

	[ -n "$NO_BACKUP" ] && return

	pbu=$PACKAGES/portmaster-backup

	if [ ! -d "$pbu" ]; then
		pm_sv Creating $pbu
		pm_mkdir_s $pbu
	fi
	export pbu
}

pm_pkg_create () {
	local pkgdir backup

	init_packages

	if [ "$1" = "$PACKAGES" ]; then
		for pkgdir in All Latest ${portdir%/*}; do
			pm_mkdir_s ${PACKAGES}/${pkgdir} ||
				fail "Cannot mkdir -p ${PACKAGES}/${pkgdir}"
		done
		pkgdir=${PACKAGES}/All
		echo "===>>> Creating a package for new version $2"
	else
		pkgdir=$1 ; echo ''
		echo "===>>> Creating a backup package for old version $2"
		backup=backup
	fi

	pm_cd $pkgdir || fail "Cannot cd into $pkgdir to create a package"
	local pkg_create
	if [ -z "$use_pkgng" ]; then
		pkg_create="pkg_create -b"
	else
		pkg_create="pkg create "
	fi
	if $PM_SU_CMD $pkg_create $2; then
		if [ "$1" = "$pbu" ]; then
			if [ -n "$BACKUP" ]; then
				echo "	===>>> Package saved to $1" ; echo ''
			else
				local pkg ; pkg=`echo $2.*`
				NB_DELETE="${NB_DELETE}${pkg} "
			fi
		elif [ "$1" = "$PACKAGES" ]; then
			local pkg ; pkg=`echo $2.*`

			if [ -z "$PM_INDEX_ONLY" ]; then
				local latest_link

				pm_cd_pd $portdir
				latest_link=`pm_make -V LATEST_LINK`
				cd ${1}/Latest
				$PM_SU_CMD ln -sf ../All/$pkg ${latest_link}.tbz
			fi

			cd ${1}/${portdir%/*}
			$PM_SU_CMD ln -sf ../All/$pkg $pkg
			echo "  ===>>> Package saved to ${1}/All" ; echo ''
		fi
	else
		local answer

		while : ; do
			echo -e "\n===>>> Package creation failed for ${2}!\n"

			[ -n "$backup" -a -n "$PM_IGNORE_FAILED_BACKUP_PACKAGE" ] && return

			echo "===>>> Ignore this error  [i]"
			echo "===>>> Abort update       [a]"
			echo "===>>> Retry              [r]"
			echo -e "\n===>>> How would you like to proceed? [i] \c"
			read answer ; echo ''

			case "$answer" in
			''|[iI]) break ;;
			[aA])	fail "Package creation failed for $2" ;;
			[rR])	pm_pkg_create $1 $2 ; break ;;
			*)	echo "	===>>> $answer is not a valid response" ;;
			esac
		done
		unset answer
	fi
}

find_dl_distfiles () {
	# Global: dist_list dist_list_files

	# We need to define these for use in the deletion/update process.
	if [ -s "${pdb}/${upg_port}/distfiles" ]; then
		dist_list="${pdb}/${upg_port}/distfiles"
	else
		# Old method, for now
		if pm_cd $pd/$1; then
			dist_list=`pm_make_b -V OPTIONSFILE`
			dist_list="${dist_list%options}distfiles"
		else
			# The port might have moved, etc.; so take a stab at it,
			# but do not take a chance with a possibly wrong answer
			dist_list="$port_dbdir/${1##*/}/distfiles"
		fi
		[ -s "$dist_list" ] || { unset dist_list ; return 0; }
	fi

	[ -n "$DONT_SCRUB_DISTFILES" ] && return 0

	local line
	while read line; do
		case "$line" in
		DISTFILE*)	line=${line#DISTFILE:} ; line=${line%%:*}
				dist_list_files="${dist_list_files}${line#*/} " ;;
		esac
	done < $dist_list

	# Clean up after the old method
	case "$dist_list" in
	${port_dbdir}*)
		pm_sv Deleting $dist_list
		pm_unlink_s $dist_list

		local dir=`find ${dist_list%/distfiles} -type d -empty 2>/dev/null`
		if [ -d "$dir" ]; then
			pm_sv Deleting empty $dir directory
			pm_rmdir_s $dir
		fi

		unset dist_list ;;
	esac
}

check_di_files () {
	# Global: distfiles_checked

	if [ -s "$DI_FILES" ]; then
		if grep -ql ^${port_subdir}${1} $DI_FILES; then
			distfiles_checked="${distfiles_checked}${1}:"
			pm_v "===>>> Keeping distfile, valid for another port: $1"
			return 0
		fi
	fi

	return 1
}

find_and_delete_distfiles () {
	# Global: distfiles_checked
	local file answer

	for file in ${1}*; do
		# This generally means the pattern did not match
		case "$file" in
		*\*)	[ "$1" = "${1%[_-]*}" ] && return 0
			# This will happen for files like foo-bar_baz-1.23
			find_and_delete_distfiles ${1%[_-]*} ;;
		esac

		case "$distfiles_checked" in *:${file}:*) continue ;; esac
		[ -f "$file" ] || continue

		case "$distfiles" in
		*" ${file} "*)
			distfiles_checked="${distfiles_checked}${file}:"
			pm_v "===>>> Keeping current distfile: ${port_subdir}${file}"
			continue ;;	# Do not delete current version
		*)	check_di_files $file && continue

			if [ -n "$ALWAYS_SCRUB_DISTFILES" -o -n "$delete_all" ]; then
				echo "===>>> Deleting stale distfile: ${port_subdir}${file}"
				pm_unlink $file
				continue
			fi

			get_answer_g n y "\n===>>> Delete ${port_subdir}${file}? y/n"
			case "$?" in
			1)	pm_unlink $file ;;
			0)	distfiles_checked="${distfiles_checked}${file}:" ;;
			esac ;;
		esac
	done
}

make_distfiles () {
	# Global: distfiles

	# Even if there are no distfiles there will be a space returned
	distfiles=`pm_make -V ALLFILES` ; distfiles=${distfiles%% }
	if [ -n "$distfiles" ]; then
		distfiles=" $distfiles "
	else
		unset distfiles
	fi
}

make_port_subdir () {
	# Global: port_subdir full_port_subdir

	port_subdir=`pm_make -V DIST_SUBDIR`
	port_subdir="${port_subdir:+${port_subdir}/}"
	full_port_subdir="${DISTDIR}${port_subdir}"
}

set_distfiles_and_subdir () {
	[ -z "$dist_list_files" ] && find_dl_distfiles $1

	if [ -d "$pd/$1" ]; then
		pm_cd_pd $1
	else
		return 1
	fi

	[ -n "$distfiles" ] || make_distfiles

	# Ports may have no distfiles
	[ -z "$dist_list_files" -a -z "$distfiles" ] && return 2

	[ -n "$full_port_subdir" ] || make_port_subdir

	if [ -d "$full_port_subdir" ]; then
		pm_cd $full_port_subdir || fail "cd to $full_port_subdir failed!"
	else
		echo ''
		echo "===>>> $full_port_subdir does not exist, therefore we"
		echo '       will assume that all relevant distfiles are gone.'
		echo ''
		echo "       Try ${0##*/} [-y] --clean-distfiles for a full cleanup"
		echo ''
		return 3
	fi
	return 0
}

delete_stale_distfiles () {
	# Global: distfiles_checked
	local file answer

	set_distfiles_and_subdir $1 || return 0
	distfiles_checked=':'

	# If these two match, it means that the distfiles in the
	# file are the current set, so do not delete them.
	if [ ! " $dist_list_files" = "$distfiles" ]; then
		for file in $dist_list_files; do
			[ -f "$file" ] || continue

			case "$distfiles" in
			*" ${file} "*)
				distfiles_checked="${distfiles_checked}${file}:"
				pm_v "===>>> Keeping current distfile: ${port_subdir}${file}"
				continue ;;	# Do not delete current version
			esac

			check_di_files $file && continue

			if [ -n "$ALWAYS_SCRUB_DISTFILES" -o -n "$delete_all" ]; then
				echo "===>>> Deleting stale distfile: ${port_subdir}${file}"
				pm_unlink $file
				continue
			fi

			get_answer_g n y "\n===>>> Delete ${port_subdir}${file}? y/n"
			case "$?" in
			1)	pm_unlink $file ;;
			0)	distfiles_checked="${distfiles_checked}${file}:" ;;
			esac
		done
	fi

	# Eventually we will hide this behind an "aggressive distfile purge"
	# flag, but until the DISTFILE stuff is well populated
	# keep doing it both ways.
	for file in $distfiles $dist_list_files; do
		find_and_delete_distfiles ${file%[-]*}-[0-9]
	done

	pm_v "===>>> Distfile cleaning complete\n"
}

delete_all_distfiles () {
	# Global: delete_all DISTDIR
	local origin rc delete_current

	# In case we are called more than once
	unset delete_all dist_list dist_list_files
	origin=$1

	set_distfiles_and_subdir $origin ; rc=$?
	case "$rc" in
	1)	echo ''
		echo "===>>> No $pd/$origin exists to find the distfile list"
		echo "       Try ${0##*/} [-y] --clean-distfiles for a full cleanup"
		echo ''
		if [ -n "$dist_list_files" ]; then
			local answer f

			answer=y
			if [ -z "$ALWAYS_SCRUB_DISTFILES" ]; then
				echo "===>>> However, the list of files from $dist_list"
				get_answer_g n y "       should be current.  Delete the files on this list? y/n"
				case "$?" in 0)	answer=n ;; esac
			fi

			case "$answer" in
			[yY])	for f in $dist_list_files; do
					if [ -f "$f" ]; then
						echo "       Deleting ${port_subdir}${f}"
						/bin/unlink $f
					fi
				done ;;
			esac
		fi
		return 0 ;;
	2)	echo "===>>> This port has no distfiles" ; return 0 ;;
	3)	return 0 ;;	# port_subdir does not exist
	esac

	if [ -n "$ALWAYS_SCRUB_DISTFILES" ]; then
		echo "===>>> Deleting all distfiles for $origin"
		delete_all=delete_all
	else
		echo "===>>> Delete old and new distfiles for $origin"
		get_answer_g n y "       without prompting? y/n"
		case "$?" in
		1)	delete_all=delete_all2 ;;
		0)	get_answer_g n y "===>>> Delete the current distfiles? y/n"
			case "$?" in 1)	delete_current=delete_current ;; esac ;;
		esac
	fi

	if [ -n "$delete_all" -o -n "$delete_current" ]; then
		# Doing this now means less work in delete_stale()
		[ -n "$distfiles" ] && eval rm -f $distfiles
	fi
	delete_stale_distfiles $origin
	delete_empty_dist_subdirs
}

#=============== End functions for getopts features and main ===============
#=============== Begin code relevant only to getopts features ===============

if [ -n "$LIST" -o -n "$LIST_PLUS" ]; then
	ports_by_category ; pm_v
	num_updates=0

	echo "===>>> Root ports (No dependencies, not depended on)"
	for iport in $roots; do
		echo "===>>> $iport"
		[ -n "$LIST_PLUS" ] && check_for_updates list $iport
	done
	echo "===>>> $num_roots root ports"
	echo ''
	echo "===>>> Trunk ports (No dependencies, are depended on)"
	for iport in $trunks; do
		echo "===>>> $iport"
		[ -n "$LIST_PLUS" ] && check_for_updates list $iport
	done
	echo "===>>> $num_trunks trunk ports"
	echo ''
	echo "===>>> Branch ports (Have dependencies, are depended on)"
	for iport in $branches; do
		echo "===>>> $iport"
		[ -n "$LIST_PLUS" ] && check_for_updates list $iport
	done
	echo "===>>> $num_branches branch ports"
	echo ''
	echo "===>>> Leaf ports (Have dependencies, not depended on)"
	for iport in $leaves; do
		echo "===>>> $iport"
		[ -n "$LIST_PLUS" ] && check_for_updates list $iport
	done
	echo "===>>> $num_leaves leaf ports"
	echo ''
	echo "===>>> $num_ports total installed ports"

	if [ "$num_updates" -gt 1 ]; then
		echo "	===>>> $num_updates have new versions available"
	elif [ "$num_updates" -eq 1 ]; then
		echo "	===>>> 1 has a new version available"
	elif [ -n "$LIST_PLUS" ]; then
		echo "	===>>> There are no new versions available"
	fi

	exit 0
fi

if [ -n "$EXPUNGE" ]; then
	if [ ! -d "$pdb/$EXPUNGE" ] || ( [ -n "$use_pkgng" ] && ! pkg info -e $EXPUNGE ); then
		find_glob_dirs $EXPUNGE
		case $? in
		1)	if [ -z "$use_pkgng" ]; then
				fail "No such directory/port: $pdb/$EXPUNGE"
			else
				fail "No such port: $EXPUNGE"
			fi ;;
		2)	echo "===>>> $EXPUNGE matched multiple ports"
			fail "The -e option works with only one port at a time" ;;
		0)	EXPUNGE=${glob_dirs#$pdb/}
			unset glob_dirs ;;
		esac
	fi

	origin=`origin_from_pdb $EXPUNGE`
	if [ -z "$use_pkgng" ]; then
		deplist=`find $pdb -depth 2 -name +CONTENTS -exec grep -l DEPORIGIN:$origin$ {} +`
	else
		deplist=`pkg query "%rn-%rv" $origin`
	fi
	if [ -n "$deplist" ]; then
		echo "===>>> Warning: Ports with dependencies on ${EXPUNGE}:"
		if [ -z "$use_pkgng" ]; then
			for dep in $deplist; do
				dep=${dep%/+CON*} ; echo "	${dep##*/}"
			done
		else
			echo "$deplist" | sed 's/^/	/'
		fi
		get_answer_yn n "\n\t===>>> Delete this dependency data"
		case "$?" in
		0)	[ -n "$use_pkgng" ] && exit 1 #TODO
			for f in $deplist; do
				update_contents delete $f $origin
			done ;;
		*)	exit 1 ;;
		esac
	fi

	[ -n "$BACKUP" ] && { init_packages ; pm_pkg_create $pbu $EXPUNGE; }
	[ -z "$DONT_SCRUB_DISTFILES" ] && delete_all_distfiles $origin

	if [ -z "$use_pkgng" ]; then
		pkg_delete="pkg_delete"
	else
		pkg_delete="pkg delete"
	fi
	echo "===>>> Running $pkg_delete -f $EXPUNGE"
	pm_pkg_delete_s $EXPUNGE || fail "$pkg_delete failed"

	echo '' ; echo "===>>> Running ${0##*/} -s $ARGS"
	exec $0 -s $ARGS
	exit 0	# Should not be reached
fi

if [ -n "$CLEAN_STALE" ]; then
	[ -z "$no_del_list" ] && export no_del_list=':'

	if [ -z "$use_pkgng" ]; then
		find_stale_ports="find $pdb -type f -name \+REQUIRED_BY -empty"
	else
		find_stale_ports="pkg query -ae '%a = 1' '%?r %n-%v' | awk '/^0/ { print \$2 }'"
	fi
	for file in `eval $find_stale_ports` ; do
		iport="${file%/+REQUIRED_BY}" ; iport=${iport#$pdb/}

		case "$no_del_list" in *:${iport}:*) continue ;; esac

		origin=`origin_from_pdb $iport`
		deplist=""
		if [ -z "$use_pkgng" ]; then
			deplist=`find $pdb -depth 2 -name +CONTENTS -exec grep -l DEPORIGIN:$origin$ {} +`
		fi
		if [ -n "$deplist" ]; then
			echo ''
			echo "===>>> Warning: Unrecorded dependencies on ${iport}:"
			for dep in $deplist; do
				dep=${dep%/+CON*} ; echo "	${dep##*/}"
			done
			echo ''
			echo "===>>> Try ${0##*/} --check-depends"
			echo ''
			continue
		fi

		if [ -z "$use_pkgng" ]; then
			echo '' ; pkg_info $iport
			pkg_delete="pkg_delete"
		else
			echo '' ; pkg info -f $iport
			pkg_delete="pkg delete"
		fi

		get_answer_yn n "\t===>>> ${iport} is no longer depended on, delete"
		case "$?" in
		0)	[ -n "$BACKUP" ] && { init_packages ; pm_pkg_create $pbu $iport; }
			[ -z "$DONT_SCRUB_DISTFILES" ] && delete_all_distfiles $origin

			echo "===>>> Running $pkg_delete -f $iport"
			pm_pkg_delete_s $iport || fail "$pkg_delete failed"

			exec $0 -s $ARGS ;;
		*)	if [ -z "$use_pkgng" ]; then
				get_answer_yn n "\t===>>> Delete this dependency data"
				case "$?" in
				0)	pm_unlink_s $file ;;
				*)	no_del_list="${no_del_list}${iport}:" ;;
				esac
			else
				no_del_list="${no_del_list}${iport}:"
			fi ;;
		esac
	done
	exit 0
fi

#=============== End code relevant only to getopts features ===============

[ -z "$DISTDIR" -a "$PM_PACKAGES" != only -a -z "$DONT_SCRUB_DISTFILES" ] &&
	fail 'The value of DISTDIR cannot be empty'

#=============== Begin functions for main ===============

already_done () {
	echo "===>>> The update for $1 is already done" ; echo ''
}

check_restart_and_udf () {
	# RESTART will usually be empty, and we don't want
	# to go out to the disk if we don't have to.
	[ -z "$RESTART" ] && return 1

	if [ ! -e "$pdb/${1}/PM_UPGRADE_DONE_FLAG" ] || ( [ -n "$use_pkgng" ] && ! pkg info -e $1 ); then
		return 1
	else
		already_done $1
	fi
}

check_interactive () {
	[ -n "$INTERACTIVE_UPDATE" ] || return 0

	local update_to

	[ -n "$2" ] && update_to=" to $2"

	case "$INTERACTIVE_YES" in *:${1}:*) return 0 ;; esac
	case "$INTERACTIVE_NO" in *:${1}:*) return 1 ;; esac

	if [ -e "$pdb/$1/+IGNOREME" ] && ( [ -z "$use_pkgng" ] || pkg info -e $1 ); then
		echo ''
		echo "===>>> +IGNOREME file is present for $1"
		echo ''
		get_answer_g n y "===>>> Update ${1}${update_to}? y/n"

		case "$?" in
		1)	INTERACTIVE_YES="${INTERACTIVE_YES}${1}:" ;;
		0)	INTERACTIVE_NO="${INTERACTIVE_NO}${1}:" ; return 1 ;;
		esac
	else
		get_answer_g y n "===>>> Update ${1}${update_to}? y/n"

		case "$?" in
		0)	INTERACTIVE_YES="${INTERACTIVE_YES}${1}:" ;;
		1)	INTERACTIVE_NO="${INTERACTIVE_NO}${1}:" ; return 1 ;;
		esac
	fi
}

check_exclude () {
	[ -n "$PM_EXCL" ] || return 0

	local pat

	for pat in $PM_EXCL; do
		case "$1" in
		*${pat}*)
			if [ -n "$PM_VERBOSE" ]; then
				echo "===>>> Skipping $1"
				echo "       because it matches the pattern: *${pat}*"
				echo ''
			fi
			return 1 ;;
		esac
	done

	return 0
}

check_fetch_only () {
	[ -n "$FETCH_ONLY" ] || return 0
	[ -z "$1" -a -n "$PM_PACKAGES" ] && return 0

	local count nf fetches

	echo ''
	count=0
	while nf=`ls ${TMPDIR}/f-${PM_PARENT_PID}-fetchlog-* 2>/dev/null | wc -l`; do
		nf=${nf##* }
		[ $nf -eq 0 ] && break
		fetches=fetches ; [ $nf -eq 1 ] && fetches=fetch

		count=$(( $count + 1 ))
		if [ $count -eq 1 ]; then
			echo "===>>> Waiting for $nf distfile $fetches to finish"
		elif [ $count -eq 3 ]; then
			count=0
		fi
		sleep 2
	done
	echo "===>>> ${1:-Distfile} fetching is complete"
	FETCH_ONLY_DONE=fetch_only_done
	safe_exit
}

term_printf () {
	case "$1" in
	'')	[ -n "$PM_MULTI_PORTS" ] && echo -e "\n===>>> ${PM_PARENT_PORT}" ;;
	*\>\>*)	echo -e "\n===>>> ${PM_PARENT_PORT}${1}" ;;
	esac

	[ -n "$PM_NO_TERM_TITLE" ] && return
	case "$TERM" in cons*) return ;; esac

	printf "\033]0;${0##*/}: ${PM_PARENT_PORT}${1}\007"
}

update_pm_nu () {
	case "$PM_NEEDS_UPDATE" in *\ $1\ *) return ;; esac

	PM_NEEDS_UPDATE="${PM_NEEDS_UPDATE}${1} "
}

find_new_port () {
	# Global: new_port

	[ -n "$new_port" ] && return

	if pm_cd_pd $1; then
		new_port=`pm_make -V PKGNAME`
	else
		new_port=`parse_index $1 name` ||
			fail "No entry for $1 in $PM_INDEX"
	fi
}

update_build_l () {
	local origin iport

	origin=$1 ; update_pm_nu $origin

	[ -n "$PM_NO_CONFIRM" ] && return

	if [ -z "$2" ]; then
		case "$build_l" in *\ $origin\\*) return ;; esac
		build_l="${build_l}\tInstall $origin\n"
		return
	else
		iport=$2
		case "$build_l" in *\ $iport\ *|*\ $iport\\*) return ;; esac
	fi

	find_new_port $origin

	local pkg_version
	if [ -z "$use_pkgng" ]; then
		pkg_version="pkg_version"
	else
		pkg_version="pkg version"
	fi
	case `$pkg_version -t $iport $new_port 2>/dev/null` in
	\<)	build_l="${build_l}\tUpgrade $iport to $new_port\n" ;;
	=)	build_l="${build_l}\tRe-install $iport\n" ;;
	\>)	build_l="${build_l}\tDowngrade $iport to $new_port\n" ;;
	*)	build_l="${build_l}\tUpgrade $iport\n" ;;
	esac
}

update_port () {
	local deps

	if [ -n "$2" ]; then
		echo "===>>> Launching child to update $1 to $2"
	else
		if [ -z "$FETCH_ONLY" ]; then
			case "$1" in
			*/*)	echo "===>>> Launching child to install ${1#$pd/}" ;;
			*)	echo "===>>> Launching child to reinstall $1" ;;
			esac
		else
			if [ "$PM_PACKAGES" != 'only' ]; then
				echo "===>>> Launching child to check distfiles for $1"
			else
				echo "===>>> Launching child to check package files for $1"
			fi
		fi
	fi

	dep_of_deps=$(( $dep_of_deps + 1 ))

	[ -n "$PM_FIRST_PASS" ] && [ ! \( -n "$PM_FORCE" -a -n "$PM_ALL_FETCH" \) ] &&
		num_of_deps=$(( $num_of_deps + 1 ))

	deps="(${dep_of_deps}/${num_of_deps})"

	term_printf " ${PM_DEPTH#* }>> ${1#$pd/} ${deps}"

	[ -n "$doing_dep_check" -o \( -n "$UPDATE_ALL" -a -n "$PM_FIRST_PASS" \) ] &&
		unset NO_DEP_UPDATES

	if [ -z "$NO_ACTION" -o -n "$PM_FIRST_PASS" ]; then
		($0 $ARGS $1) || update_failed=update_failed
		. $IPC_SAVE && > $IPC_SAVE
		[ -n "$update_failed" ] && fail "Update for $1 failed"
	else
		pm_v "===>>> Build canceled due to -n flag"
	fi

	if [ -n "$UPDATE_ALL" ]; then
		# Fix terminal titlebar in case of a long delay between ports to update
		term_printf " (${num_of_deps})"
		echo -e "===>>> Returning to update check of installed ports\n"
	elif [ -n "$PM_URB" ]; then
		return 0
	elif [ -n "$PM_FIRST_PASS" -a -z "$PM_PACKAGES" ]; then
		echo "===>>> Continuing initial dependency check for $portdir"
	else
		term_printf " ${PM_DEPTH#* }${deps}"
		echo -e  "\n===>>> Returning to dependency check for $portdir"
	fi
	return 0
} # update_port()

uniquify_list () {
	local ul_item ul_temp_list

	for ul_item in "$@"; do
		case "$ul_temp_list" in
		*" $ul_item "*) ;;
		*)	ul_temp_list=" $ul_temp_list $ul_item " ;;
		esac
	done

	echo $ul_temp_list
}

clean_build_only_list () {
	local dep temp_bodlg

	for dep in $build_only_dl_g; do
		case "$run_dl_g" in
		*" ${dep} "*)	;;
		*)	temp_bodlg="$temp_bodlg $dep" ;;
		esac
	done

	build_only_dl_g=" `uniquify_list $temp_bodlg` "
}

gen_dep_list () {
	local list

	if [ -z "$PM_INDEX_ONLY" ]; then
		pm_cd_pd $portdir
		list=`pm_make $* | sort -u`
	else
		local temp_list l

		case "$*" in
		'build-depends-list run-depends-list'|all-depends-list)
			temp_list="`parse_index $portdir b-deps` `parse_index $portdir r-deps`" ;;
		build-depends-list) temp_list=`parse_index $portdir b-deps` ;;
		run-depends-list) temp_list=`parse_index $portdir r-deps` ;;
		esac

		temp_list=`uniquify_list $temp_list`

		for l in $temp_list ; do
			list="$list `grep -m1 ^${l}\| $PM_INDEX | cut -f 2 -d \|`"
		done

		list=" $list "
	fi

	echo "$list"
}

dependency_check () {
	# Global: doing_dep_check
	# Global: run_dl_g build_only_dl_g

	local d_port_list

	# Print a message here because sometimes list generation takes
	# a long time to return.
	if [ -z "$PM_INDEX_ONLY" ]; then
		echo "===>>> Gathering dependency list for $portdir from ports"
	else
		echo "===>>> Gathering dependency list for $portdir from ${PM_INDEX##*/}"
	fi
	d_port_list=`gen_dep_list $1`

	if [ -z "$d_port_list" ]; then
		echo -e "===>>> No dependencies for $portdir\n"
		[ -n "$SHOW_WORK" ] && safe_exit
		return 0
	else
		if [ -n "$SHOW_WORK" ]; then
			echo ''
		else
			pm_v "===>>> Starting dependency check"
		fi
	fi

	if [ "$PM_BUILD_ONLY_LIST" = pmp_doing_build_deps ]; then
		local rundeps dep varname run_dl build_only_dl

		rundeps=`gen_dep_list run-depends-list`

		for dep in $d_port_list; do
			# If the port is already installed, do not mark
			# it as a build-only dependency, or it will be
			# installed by package and/or removed
			if [ -z "$use_pkgng" ]; then
				iport_from_origin ${dep#$pd/} >/dev/null &&
					run_dl="$run_dl $dep" &&
					continue
			else
				pkg info -e ${dep#$pd/} &&
					run_dl="$run_dl $dep" &&
					continue
			fi
			case "$rundeps" in
			*" ${dep} "*|*${dep}*)
				varname=`echo ${dep#$pd/} | sed 's#[-+/\.]#_#g'`
				rundep_list="$rundep_list $varname"
				eval $varname=\"$portdir \$$varname\"
				eval ${varname}_p=$dep
				eval export $varname ${varname}_p

				run_dl="$run_dl $dep" ;;
			*)	build_only_dl="$build_only_dl $dep" ;;
			esac
		done

		if [ -z "$PM_THOROUGH" ]; then
			d_port_list="$build_only_dl $run_dl"
		else
			build_only_dl=`gen_dep_list build-depends-list`
		fi

		run_dl_g="$run_dl_g $run_dl "

		for dep in $build_only_dl; do
			case "$build_only_dl_g" in
			*" ${dep} "*)	;;
			*) build_only_dl_g="$build_only_dl_g $dep " ;;
			esac
		done

		clean_build_only_list
	fi

	local d_port origin iport

	# Do not export, for THIS parent process only
	[ -n "$PM_FIRST_PASS" ] && doing_dep_check=doing_dep_check
	for d_port in $d_port_list; do
		origin="${d_port#$pd/}"
		if [ -n "$SHOW_WORK" ]; then
			iport=`iport_from_origin $origin`
			case "$iport" in
			'') echo "===>>> NOT INSTALLED		$origin" ;;
			*)  echo "===>>> Installed $origin" ;;
			esac
			continue
		fi

		pm_v "===>>> Checking dependency: $origin"

		# Do this first to catch out of date dependencies
		[ -n "$PM_FIRST_PASS" ] &&
			case "$PM_NEEDS_UPDATE" in *\ $origin\ *) continue ;; esac

		[ -z "$PM_URB_UP" ] &&
			case "$CUR_DEPS" in *:${origin}:*) continue ;; esac

		if [ -z "$PM_INDEX_ONLY" ]; then
			local conflicts glob confl_p

			conflicts=''
			if pm_cd $d_port; then
				if grep -ql ^CONFLICTS Makefile ; then
					conflicts=`pm_make_b -V CONFLICTS`
					conflicts="$conflicts `pm_make_b -V CONFLICTS_BUILD`"
					conflicts="$conflicts `pm_make_b -V CONFLICTS_INSTALL`"
				fi
			else
				fail "Cannot cd to $d_port"
			fi
			for glob in $conflicts; do
				if [ -z "$use_pkgng" ]; then
					confl_p=`pkg_info -I $glob 2>/dev/null`
				else
					confl_p=`pkg query -g "%n-%v" $glob 2>/dev/null`
				fi
				if [ -n "$confl_p" ]; then
					confl_p=${confl_p%% *}
					d_port="$pd/`origin_from_pdb $confl_p`"

					if [ "${d_port#$pd/}" = "$portdir" ]; then
						echo -e "\n===>>> $origin seems to depend on $portdir"
						echo '       which looks like a dependency loop'
						fail "Try pkg_updating $portdir"
					fi

					echo ''
					echo "===>>> The dependency for ${origin}"
					echo "       seems to be handled by $confl_p"
					echo ''
				fi
			done
		fi

		# In case d_port changed above
		origin="${d_port#$pd/}" ; iport=`iport_from_origin ${origin}`

		check_exclude ${iport:-$origin} || continue

		if [ -n "$PM_FORCE" -a -n "$iport" ]; then
			if ! check_restart_and_udf $iport; then
				echo "===>>> Forcing update for $pd/$origin"
				update_port $iport
			else
				CUR_DEPS="${CUR_DEPS}${iport}:${origin}:"
			fi
			continue
		elif [ -n "$PM_URB_UP" -a -n "$iport" ]; then
			case "$PM_URB_DONE" in
			*:${iport}:*) already_done $iport ; continue ;; esac

			case " $PM_URB_LIST " in *" $iport "*)
				check_interactive $iport || continue
				if ! check_restart_and_udf $iport; then
					update_port $iport
				else
					CUR_DEPS="${CUR_DEPS}${iport}:${origin}:"
					PM_URB_DONE="${PM_URB_DONE}${upg_port}:"
				fi
				continue ;;
			esac
		fi

		if [ -n "$iport" ]; then
			# No check_interactive here because we want to tell
			# the user whether or not there is a new version first
			check_for_updates $iport $origin || fail 'Update failed'
		else
			check_interactive $origin || continue
			update_port $origin
		fi
	done
	[ -n "$PM_FIRST_PASS" ] && unset doing_dep_check

	if [ -n "$SHOW_WORK" ]; then
		safe_exit
	elif [ -n "$PM_FIRST_PASS" -a -z "$PM_PACKAGES" ]; then
		echo -e "===>>> Initial dependency check complete for $portdir\n"
	else
		echo "===>>> Dependency check complete for $portdir"
		local deps ; deps="(${dep_of_deps}/${num_of_deps})"
		case "$PM_DEPTH" in
		*\>\>*)	term_printf " ${PM_DEPTH#* }${deps}" ; echo '' ;;
		*)	if [ "$PM_PARENT_PORT" = All ]; then
				term_printf " >> ${upg_port:-$portdir}${deps}"
			elif [ -n "$PM_URB_UP" ]; then
				term_printf " >> ${upg_port:-$portdir} ${deps}"
				echo ''
			else
				term_printf ; echo ''		# multiport
			fi ;;
		esac
	fi
} # dependency_check()

post_first_pass () {
	local action

	if [ ${num_of_deps:-0} -gt 0 ]; then
		term_printf " >> (${num_of_deps})"

		if [ -z "$PM_NO_CONFIRM" ]; then
			local answer

			echo ''
			echo "===>>> The following actions will be taken if you choose to proceed:"
			echo -e "$build_l"
			get_answer_g y n "===>>> Proceed? y/n"
			case "$?" in
			1)	echo ''
				echo "===>>> If you would like to upgrade or install some, but not"
				echo "       all of the above try adding '-i' to the command line."
				safe_exit 1 ;;
			esac
			unset build_l
		fi
	else
		term_printf
	fi

	# Only when -a or multi and user said no to update +IGNOREME(s)
	[ "$PM_NEEDS_UPDATE" = ' ' ] && return

	action=build
	if [ -n "$FETCH_ONLY" ]; then
		action='fetch'
	elif [ "$PM_PACKAGES" = only ]; then
		action=install
	elif [ -n "$PM_PACKAGES" ]; then
		action='build and/or install'
	fi

	echo ''; echo "===>>> Starting $action for $* <<<==="; echo ''

	unset PM_FIRST_PASS PM_NO_CONFIRM

	dep_of_deps=0

	if [ -n "$PM_BUILD_ONLY_LIST" ]; then
		local var real_rundep deplist dep temp_bodlg

		for var in $rundep_list ; do
			real_rundep=no

			eval deplist=\$$var
			for dep in $deplist ; do
				case "$build_only_dl_g" in
				*" $pd/$dep "*) ;;
				*)	real_rundep=yes ; break ;;
				esac
			done

			[ "$real_rundep" = 'no' ] &&
				eval build_only_dl_g=\"${build_only_dl_g}\$${var}_p \"
			eval unset $var ${var}_p
		done

		for dep in $build_only_dl_g; do
			if [ -z "$use_pkgng" ]; then
				[ $(find $pdb -depth 2 -name +CONTENTS -exec grep -l "@comment DEPORIGIN:${dep#$pd/}$" {} +|wc -l) -gt 0 ] && continue
			else
				[ "`pkg query "%?r" ${dep#$pd/}`" = "1" ] && continue
			fi
			[ -n "$PM_DEL_BUILD_ONLY" ] &&
				iport_from_origin ${dep#$pd/} >/dev/null && continue
			temp_bodlg="$temp_bodlg $dep"
		done

		build_only_dl_g=" `uniquify_list $temp_bodlg` "

		unset run_dl_g rundep_list
		PM_BUILD_ONLY_LIST=pm_bol
	fi
}

init_term_printf () {
	PM_PARENT_PORT=$1
	[ -z "$num_of_deps" ] && num_of_deps=0
	[ -z "$dep_of_deps" ] && dep_of_deps=0
	export PM_PARENT_PORT num_of_deps dep_of_deps

	term_printf
}

if [ -n "$PM_URB" ]; then
	[ -n "$RESTART" ] && PM_UPDATE_IF_NEWER=pm_update_if_newer_urb

urb_update () {
	# Global: PM_URB_UP
	local verb origin req_by req_by_o

	verb=Checking ; [ -n "$1" ] && verb=Updating

	export PM_URB_UP=pm_urb_up

	init_term_printf "$verb ports that depend on $PM_URB_IPORTS" ; echo ''
	PM_PARENT_PORT="$verb dependent ports"

	for origin in $PM_URB_ORIGINS; do
		if [ -z "$use_pkgng" ]; then
			for req_by in `find $pdb -depth 2 -name +CONTENTS -exec grep -l DEPORIGIN:${origin}$ {} +`; do
				req_by="${req_by%/+CONTENTS}"
				req_by="${req_by##*/}"

				case " $PM_URB_IPORTS" in *" $req_by "*) continue ;; esac
				case " $PM_URB_ORIGINS" in *" `origin_from_pdb $req_by` "*) continue ;; esac

				PM_URB_LIST="${PM_URB_LIST} ${req_by}"
			done
		else
			while read req_by req_by_o; do
				case " $PM_URB_IPORTS" in *" $req_by "*) continue ;; esac
				case " $PM_URB_ORIGINS" in *" $req_by_o "*) continue ;; esac
				PM_URB_LIST="${PM_URB_LIST} ${req_by}"
			done << EOF
`pkg query "%rn-%rv %ro" ${origin}`
EOF
		fi
	done

	if [ -n "$PM_URB_LIST" ]; then
		PM_URB_LIST="`uniquify_list $PM_URB_LIST`"
		export PM_URB_LIST
	else
		echo "===>>> No ports depend on $PM_URB_IPORTS" ; echo ''
	fi

	for req_by in $PM_URB_LIST; do
		# Probably not needed, but JIC
		if [ -z "$use_pkgng" ]; then
			[ -d "$pdb/$req_by" ] || continue
		else
			pkg info -e $req_by || continue
		fi

		pm_v "===>>> $req_by depends on $PM_URB_IPORTS"

		case "$PM_URB_DONE" in
		*:${req_by}:*) already_done $req_by ; continue ;; esac

		check_exclude $req_by || continue
		check_interactive $req_by || continue

		# Shortcut, since check_for will force it
		if [ -z "$RESTART" -a -z "$PM_FORCE" ]; then
			update_port $req_by
		else
			check_for_updates $req_by || fail 'Update failed'
		fi
		echo "===>>> Returning to list of ports depending on $PM_URB_IPORTS"
	done
	echo ''
	echo "===>>> $verb done for ports that depend on $PM_URB_IPORTS"
	echo ''
	unset PM_URB_UP PM_URB_LIST PM_URB_DONE
}
fi

multiport () {
	# Global
	PM_MULTI_PORTS=':' ; export PM_MULTI_PORTS

	local port worklist_temp iport worklist portlist numports origin num

	# Expand globs and check that the directories exist
	for port in "$@"; do
		port=${port#$pdb/}
		case "$port" in
		*/*)	port=${port#$pd/}
			if [ -n "$PM_INDEX_ONLY" ] || [ -d "$pd/${port}" ]; then
				worklist_temp="$worklist_temp $port"
			else
				fail "$pd/${port} does not exist"
			fi ;;
		*)	if [ -d "$pdb/$port" ] && ( [ -z "$use_pkgng" ] || pkg info -e $port ); then
				worklist_temp="$worklist_temp $port"
			else
				find_glob_dirs $port
				case $? in
				1)	if [ -z "$use_pkgng" ]; then
						fail "$pdb/$port does not exist"
					else
						fail "$port is not installed"
					fi ;;
				*)	local dir
					for dir in $glob_dirs; do
					worklist_temp="$worklist_temp ${dir#$pdb/}"
					done ;;
				esac
				unset glob_dirs
			fi ;;
		esac
	done

	numports=0
	for port in $worklist_temp; do
		check_exclude $port || continue
		check_interactive $port || continue

		if [ -n "$PM_UPDATE_IF_NEWER" ]; then
			case "$port" in
			*/*)	iport=`iport_from_origin $port` ;;
			*)	iport=$port ;;
			esac

			if [ -n "$iport" ] && check_for_updates multi $iport; then
				if [ -n "$PM_URB" -a -n "$RESTART" ]; then
					echo ''
					echo "===>>> $iport is up to date, skipping rebuild due to -R flag"
					udl_prime="${udl_prime}${iport}:"
				elif [ -n "$PM_VERBOSE" ]; then
					echo ''
					echo "===>>> $port is up to date, skipping"
				fi
				continue
			fi
		fi

		numports=$(( $numports + 1 ))
		worklist="$worklist $port"
		portlist="${portlist}\t${port}\n"
		PM_MULTI_PORTS="${PM_MULTI_PORTS}${port}:"
	done
	unset PM_UPDATE_IF_NEWER

	if [ -z "$worklist" ]; then
		if [ -z "$PM_URB" ]; then
			echo ''
			echo "===>>> All listed ports are up to date, exiting" ; echo ''
			safe_exit
		fi
	else
		echo ''
		echo "===>>> Working on:"
		echo -e $portlist
	fi
	unset portlist

	[ -n "$DI_FILES" ] && (read_distinfos)&

	# First Pass
	if [ -n "$PM_BUILD_ONLY_LIST" ]; then
		PM_BUILD_ONLY_LIST=pmp_doing_build_deps
		for port in $worklist; do
			case "$port" in
			*/*)	run_dl_g="$run_dl_g ${pd}/${port} " ;;
			*)	run_dl_g="$run_dl_g ${pd}/`origin_from_pdb $port` " ;;
			esac
		done
	fi

	[ -n "$PM_URB" ] && export PM_URB

	num=0
	for port in $worklist; do
		case "$port" in
		*/*)	origin=$port ;;
		*)	origin=`origin_from_pdb $port` ;;
		esac

		case "$PM_NEEDS_UPDATE" in
		*\ $origin\ *) numports=$(( $numports - 1 ))
			pm_v "===>>> $port already encountered as a dependency\n"
			continue ;;
		esac

		num=$(( $num + 1 ))
		init_term_printf "$port ${num}/${numports}"
		($0 $ARGS $port) || update_failed=update_failed
		. $IPC_SAVE && > $IPC_SAVE
		[ -n "$update_failed" ] && fail "Update for $port failed"

		case "$PM_NEEDS_UPDATE" in
		*\ $origin\ *)	continue ;;	# Handle +IGNOREME in child
		*)		numports=$(( $numports - 1 )) ;;
		esac
	done

	if [ -n "$PM_URB" ]; then
		unset PM_URB ; PM_URB=pm_urb_post_first_pass
		PM_URB_DONE=":${udl_prime}" ; export PM_URB_DONE
		urb_update
	fi

	PM_PARENT_PORT="Total ports: $numports"

	check_fetch_only
	post_first_pass multiple ports

	[ -n "$PM_URB" ] && export PM_URB

	export PM_BUILDING=pmbuildingmultiport
	num=0
	for port in $worklist; do
		case "$port" in
		*/*)	origin=$port ;;
		*)	# If an installed version does not exist at this
			# point it probably got updated as a dependency
			if [ -z "$use_pkgng" ]; then
				if [ ! -d "$pdb/$port" ]; then
					numports=$(( $numports - 1 ))
					continue
				fi
			else
				if ! pkg info -e $port; then
					numports=$(( $numports - 1 ))
					continue
				fi
			fi
			origin=`origin_from_pdb $port` ;;
		esac

		case "$PM_NEEDS_UPDATE" in
		*\ $origin\ *)	;;		# Ok to proceed
		*)		continue ;;	# Already updated as a dependency
		esac

		num=$(( $num + 1 ))
		init_term_printf "$port ${num}/${numports}"
		($0 $ARGS $port) || update_failed=update_failed
		. $IPC_SAVE && > $IPC_SAVE
		[ -n "$update_failed" ] && fail "Update for $port failed"
	done

	if [ -n "$PM_URB" ]; then
		unset PM_URB ; PM_URB=pm_urb_post_build
		PM_URB_DONE=":${udl_prime}" ; export PM_URB_DONE
		urb_update urb_update_after_build
	fi

	if [ "$PM_PACKAGES" != 'only' ]; then
		check_fetch_only
	else
		check_fetch_only Package
	fi
	safe_exit
}

make_config () {
	local config_type

	config_type=config-conditional
	[ -n "$PM_FORCE_CONFIG" ] && config_type=config
	pm_sv Running \'make $config_type\'
	pm_cd_pd $portdir
	pm_make_s $config_type
}

#=============== End functions for main ===============

# INIT Parent

if [ "$$" -eq "$PM_PARENT_PID" -a -z "$SHOW_WORK" ]; then
	CUR_DEPS=':' ; DISPLAY_LIST='' ; INSTALLED_LIST=''
	PM_DEPTH='' ; pm_mktemp IPC_SAVE ; IPC_SAVE=$pm_mktemp_file
	PM_FIRST_PASS=pm_first_pass ; PM_NEEDS_UPDATE=' '	# Used with -F for multiport and -a
	export CUR_DEPS DISPLAY_LIST INSTALLED_LIST PM_DEPTH IPC_SAVE PM_FIRST_PASS PM_NEEDS_UPDATE

	if [ -n "$LOCALBASE" ]; then
		LOCALBASE_COMPAT="$LOCALBASE/lib/compat/pkg"
	elif [ -z "$FETCH_ONLY" ]; then
		PLB=`pm_make_b -f/usr/share/mk/bsd.port.mk -V LOCALBASE 2>/dev/null`
		if [ -n "$PLB" ]; then
			LOCALBASE_COMPAT="$PLB/lib/compat/pkg"
		else
			[ -n "$PM_INDEX" ] && PLB=`head -1 $PM_INDEX | cut -f 3 -d\| 2>/dev/null`
			if [ -n "$PLB" ] && [ -d "$PLB" ]; then
				LOCALBASE_COMPAT="${PLB}/lib/compat/pkg"
			else
				echo "===>>> Unable to determine the value of LOCALBASE"
				echo "       Try setting it in the environment, or /etc/make.conf"
				fail 'The value of LOCALBASE cannot be empty'
			fi
		fi
		unset PLB
	fi
	export LOCALBASE_COMPAT

	if [ -n "$INTERACTIVE_UPDATE" ]; then
		INTERACTIVE_YES=':' ; INTERACTIVE_NO=':'
		export INTERACTIVE_YES INTERACTIVE_NO
	fi

	if [ -n "$PM_URB" -o -n "$PM_FORCE" ]; then
		if [ -z "$RESTART" ]; then
			files=`find $pdb -type f -name PM_UPGRADE_DONE_FLAG`
			if [ -n "$files" ]; then
				echo "===>>> There are 'install complete' flags from a previous"
				get_answer_g n y "       -[rf] run of ${0##*/}, delete them? y/n"
				case "$?" in
				1)	pm_sv Deleting \'install complete\' flags
					pm_find_s $pdb -type f -name PM_UPGRADE_DONE_FLAG -delete ;;
				0)	get_answer_g n y "===>>> Enable the -R option? y/n"
					case "$?" in 1) RESTART=Ropt ; ARGS="-R $ARGS" ;; esac ;;
				esac
			fi
		fi
	fi

	if [ -z "$FETCH_ONLY" ]; then
		NO_DEP_UPDATES=no_dep_updates ; build_l=''
		export NO_DEP_UPDATES build_l

		pm_cd_pd Mk && PM_WRKDIRPREFIX=`pm_make_b -V WRKDIRPREFIX` && pm_cd -
	fi

	if [ -n "$PM_BUILD_ONLY_LIST" ]; then
		run_dl_g='' ; build_only_dl_g='' ; rundep_list=''
		export run_dl_g build_only_dl_g rundep_list
	fi
	if [ -n "$PM_DEL_BUILD_ONLY" ]; then
		build_deps_il='' ; export build_deps_il
	fi

	[ -z "$NO_BACKUP" ] && init_packages
	[ -z "$NO_BACKUP" -a -z "$BACKUP" ] && export NB_DELETE
	if [ -n "$MAKE_PACKAGE" -a -z "$FETCH_ONLY" ]; then
		init_packages_var

		if [ ! -d "$PACKAGES" ]; then
			pm_sv Creating $PACKAGES
			pm_mkdir_s $PACKAGES
		fi
	fi

	# Set the file name here so it's visible to the children
	if [ -z "$DONT_SCRUB_DISTFILES" -a -z "$FETCH_ONLY" -a -z "$PM_PACKAGES" ]; then
		pm_mktemp DI-FILES ; DI_FILES=$pm_mktemp_file ; export DI_FILES
	fi

	[ -n "$PM_URB" ] && multiport $PM_URB_IPORTS
	[ $# -gt 1 -a -z "$REPLACE_ORIGIN" ] && multiport "$@"
fi

# This has to come after the initialization, it uses all the same stuff
if [ -n "$UPDATE_ALL" ]; then
all_first_pass () {
	local iport origin

	for iport in "$@"; do
		[ -z "$FETCH_ONLY" ] && pm_v "===>>> $iport"

		case "$CUR_DEPS" in *:${iport}:*) continue ;; esac

		origin=`origin_from_pdb $iport` || {
			case "$?" in
			3) ;;
			2)	pm_v "	===>>> No ORIGIN for $iport, and +IGNOREME is present"
				echo "	===>>> Skipping"
				echo '' ;;
			*)	fail 'Cannot continue' ;;
			esac;

			# Prevent the user from getting reprompted during build
			CUR_DEPS="${CUR_DEPS}${iport}:";
			continue; }

		case "$PM_NEEDS_UPDATE" in *\ $origin\ *) continue ;; esac

		[ -n "$PM_BUILD_ONLY_LIST" ] && run_dl_g="$run_dl_g ${pd}/${origin} "

		check_exclude $iport || continue

		PM_DEPTH="$iport "
		check_for_updates $iport $origin || fail 'Update failed'
	done
}
	[ -n "$DI_FILES" ] && (read_distinfos)&

	ports_by_category
	if [ -n "$FETCH_ONLY" ]; then
		# UPDATE_ALL is not exported
		export PM_ALL_FETCH=pm_all_fetch
		[ -n "$PM_FORCE" ] && num_of_deps=$num_ports
	fi
	unset num_ports

	init_term_printf All

	echo "===>>> Starting check of installed ports for available updates"

	[ -n "$PM_BUILD_ONLY_LIST" ] && PM_BUILD_ONLY_LIST=pmp_doing_build_deps

	pm_v "\n===>>> Root ports: $num_roots" ; unset num_roots
	all_first_pass $roots

	pm_v "\n===>>> Trunk ports: $num_trunks" ; unset num_trunks
	all_first_pass $trunks

	pm_v "\n===>>> Branch ports: $num_branches" ; unset num_branches
	all_first_pass $branches

	pm_v "\n===>>> Leaf ports: $num_leaves" ; unset num_leaves
	all_first_pass $leaves

	check_fetch_only
	if [ -n "$NO_DEP_UPDATES" ]; then
		echo '' ; echo "===>>> All ports are up to date" ; echo ''
		safe_exit
	fi

	post_first_pass 'ports that need updating'

	[ -n "$PM_BUILD_ONLY_LIST" ] && clean_build_only_list

	export PM_BUILDING=pmbuildingall

	unset roots trunks branches leaves

	for origin in $PM_NEEDS_UPDATE; do
		case "$PM_NEEDS_UPDATE" in
		*\ $origin\ *)	update_port $origin ;;
		*)		continue ;;	# Already updated as a dependency
		esac
	done

	echo "===>>> Update check of installed ports complete" ; echo ''
	safe_exit
fi	# [ -n "$UPDATE_ALL" ]

no_valid_port () {
	echo "===>>> No valid installed port, or port directory given"
	echo "===>>> Try ${0##*/} --help" ; echo '' ; safe_exit 1
}

# Figure out what we are going to be working on
if [ -z "$REPLACE_ORIGIN" ]; then
	[ -n "$portdir" ] && { argv=$portdir ; unset portdir; }
	argv=${argv:-$1} ; argv=${argv%/} ; argv=`globstrip $argv`
	case "$argv" in
	$pd/*)	portdir=${argv#$pd/} ;;
	$pdb/*)	if [ -z "$use_pkgng" ]; then
			upg_port=${argv#$pdb/}
		else
			echo '' ; no_valid_port
		fi ;;
	/*)	echo '' ; no_valid_port ;;
	*/*)	portdir=$argv ;;
	\.|'')	portdir="$PWD"
		while : ; do
			case "$portdir" in
			/)	echo ''; no_valid_port ;;
			*/*/*)	portdir="${portdir#*/}" ;;
			*/*)	break ;;
			*)	echo '' ; no_valid_port ;;
			esac
		done ;;
	*)	[ -d "$pdb/$argv" ] && \
			( [ -z "$use_pkgng" ] || pkg info -e $argv ) && \
			upg_port=$argv ;;
	esac

	if [ -z "$portdir" -a -z "$upg_port" ]; then
		find_glob_dirs $argv
		case $? in
		1)	echo '' ; no_valid_port ;;
		2)	multiport $glob_dirs ;;
		0)	upg_port=${glob_dirs#$pdb/} ;;
		esac
		unset glob_dirs
	fi
	unset argv
else
	portdir="${1#$pd/}" ; portdir="${portdir%/}"
	if [ -z "$PM_INDEX_ONLY" ]; then
		[ -d "$pd/$portdir" ] || missing=missing
	else
		parse_index $portdir name >/dev/null || missing=missing
	fi

	if [ -n "$missing" ]; then
		echo ''
		echo "===>>> The first argument to -o must be a directory in $pd"
		echo '' ; no_valid_port
	fi

	upg_port=`iport_from_origin $portdir`

	arg2=${2#$pd/} ; arg2=${arg2#$pdb/} ; arg2=${arg2%/}

	case "$arg2" in
	*/*)	ro_opd=$arg2 ; ro_upg_port=`iport_from_origin $ro_opd` ;;
	*)	if [ -d "$pdb/$arg2" ] && ( [ -z "$use_pkgng" ] || pkg info -e $arg2 ); then
			ro_upg_port=$arg2
		else
			find_glob_dirs $arg2 && ro_upg_port=${glob_dirs#$pdb/}
			unset glob_dirs
		fi
		if [ -n "$ro_upg_port" ]; then
			ro_opd=`origin_from_pdb $ro_upg_port`
		else
			ro_opd=$arg2
		fi
	esac
	unset arg2

	if [ -z "$ro_upg_port" ]; then
		if [ -z "$use_pkgng" ]; then
			[ $(find $pdb -depth 2 -name +CONTENTS -exec grep -l "DEPORIGIN:$ro_opd$" {} +|wc -l) -gt 0 ]
		else
			pkg query -a "%do" | grep -q "^$ro_opd$"
		fi
		if [ "$?" -eq 1 ]; then
			echo ''
			if [ -z "$use_pkgng" ]; then
				echo "===>>> The second argument to -o can be a port in $pdb,"
			else
				echo "===>>> The second argument to -o can be a package name,"
			fi
			echo "       or a port directory from $pd"
			echo ''
			echo "       $ro_opd does not seem to be installed,"
			echo '       or listed as a dependency'
			echo '' ; no_valid_port
		fi
	fi

	PM_MAKE_ARGS="-DDISABLE_CONFLICTS $PM_MAKE_ARGS"
fi

if [ -n "$upg_port" -a -z "$portdir" ]; then
	portdir=`origin_from_pdb $upg_port` || {
	case "$?" in
	3)	echo ''; echo "===>>> BSDPAN ports cannot be upgraded with portmaster"
		echo "       (${upg_port})"; echo ''; safe_exit 1 ;;
	2)	pm_v "	===>>> No ORIGIN for $upg_port, and +IGNOREME is present\n"
		safe_exit 1 ;;
	*)	fail 'Cannot continue' ;;
	esac ; }
elif [ -z "$portdir" ]; then
	no_valid_port
fi

if [ -z "$PM_INDEX_ONLY" ] && [ ! -d "$pd/$portdir" ]; then
	find_moved_port $portdir $upg_port || no_valid_port
	[ -n "$moved_npd" ] || no_valid_port
	[ -d "$pd/$moved_npd" ] || no_valid_port

	[ "$$" -eq "$PM_PARENT_PID" ] && parent_exit
	exec $0 $ARGS -o $moved_npd $upg_port
fi
[ -z "$upg_port" -a -z "$REPLACE_ORIGIN" ] && upg_port=`iport_from_origin ${portdir}`

if [ -e "$pdb/$upg_port/+IGNOREME" ] && ( [ -z "$use_pkgng" ] || pkg info -e $upg_port ); then
	# Adding to CUR_DEPS means we will not get here in the build
	if [ -z "$PM_BUILDING" ]; then
		# Only need to prompt for this once if -ai
		case "$INTERACTIVE_YES" in
		*:${upg_port}:*) ;;	# Let it build
		*)	if [ -z "$FETCH_ONLY" ]; then
				echo ''
				echo "===>>> $upg_port has an +IGNOREME file"
				get_answer_g n y "\t===>>> Update anyway? y/n"
				case "$?" in
				1)	;;	# Let it build
				0)	CUR_DEPS="${CUR_DEPS}${upg_port}:${portdir}:"
					if [ ${dep_of_deps:-0} -gt 0 ]; then
						dep_of_deps=$(( $dep_of_deps - 1 ))
						[ -n "$PM_FIRST_PASS" ] &&
							num_of_deps=$(( $num_of_deps - 1 ))
					fi
					safe_exit ;;
				esac
			else
				echo ''
				echo "===>>> $upg_port has an +IGNOREME file, ignoring"
				echo ''
				CUR_DEPS="${CUR_DEPS}${upg_port}:${portdir}:"
				safe_exit
			fi ;;
		esac
	elif [ -n "$PM_URB_UP" ]; then
		echo ''
		echo "===>>> $upg_port has an +IGNOREME file, ignoring"
		echo ''
		safe_exit
	fi
fi

# START

if [ -z "$PM_INDEX_ONLY" ]; then
	pm_cd $pd/$portdir || no_valid_port
else
	new_port=`parse_index $portdir name` ||
		fail "No entry for $portdir in $PM_INDEX"
fi
unset -f no_valid_port

if [ -z "$PM_DEPTH" ]; then
	PM_DEPTH="${upg_port:-$portdir} "
	[ -z "$PM_PARENT_PORT" ] && init_term_printf ${upg_port:-$portdir}
else
	PM_DEPTH="${PM_DEPTH}>> ${upg_port:-$portdir} "
fi

echo ''
[ -n "$upg_port" ] && echo "===>>> Currently installed version: $upg_port"

echo "===>>> Port directory: $pd/$portdir" ; echo ''

if [ -n "$PM_FIRST_PASS" -a -z "$FETCH_ONLY" ]; then
	if [ -z "$PM_INDEX_ONLY" ]; then
		if ! check_state; then
			check_state_fail=check_state_fail
			if [ -n "$PM_FORCE_CONFIG" ]; then
				sleep 4
				make_config
				check_state && unset check_state_fail
			fi
			if [ -n "$check_state_fail" ]; then
				echo "	===>>> If you are sure you can build it, remove the"
				echo "	       $state line in the Makefile and try again."
				safe_exit 1
			fi
		fi
	fi

	update_build_l $portdir $upg_port
elif [ -n "$FETCH_ONLY" -a -n "$PM_PACKAGES" ]; then
	update_pm_nu $portdir
fi

# Do these things first time through
if [ -z "$PM_INDEX_ONLY" -a -z "$PM_BUILDING" -a -z "$SHOW_WORK" -a -z "$NO_ACTION" ]; then
	# Do not start this in the background until we are sure we are going to proceed
	[ "$$" -eq "$PM_PARENT_PID" -a -n "$DI_FILES" ] && (read_distinfos)&

	# Handle the problem of manual fetching
	[ -z "$PM_PACKAGES" ] && master_sites=`pm_make -V MASTER_SITES`

	if [ -n "$master_sites" ]; then
		# PATCHFILES may get added after the first pass, but we want to
		# do as much of this as we can, as early as we can, and
		# patch files are usually small anyway.
		make_distfiles

		# Make sure that different ports using the same distfiles
		# do not clobber each other's fetchs
		for file in $distfiles; do
			case "$file" in */*) file=`echo $file | sed s#/#_#g` ;; esac
			if ! ls ${TMPDIR}/f-${PM_PARENT_PID}-${file}-* >/dev/null 2>&1; then
				pm_mktemp ${file}-${portdir#*/} >/dev/null
			else
				[ -n "$FETCH_ONLY" ] &&
					echo "===>>> Skipping $file due to previous fetch for it"
				DONT_FETCH=dont_fetch
				break
			fi
		done

		if [ -z "$DONT_FETCH" -a -n "$distfiles" ]; then
			echo "===>>> Launching 'make checksum' for $portdir in background"
			pm_mktemp fetchlog-${portdir#*/} ; fetchlog=$pm_mktemp_file
			(pm_make -DBATCH checksum >> $fetchlog 2>&1 && {
			    rm -f ${TMPDIR}/f-${PM_PARENT_PID}-*-${portdir#*/}.*; exit 0; }
			    allfiles=`pm_make -V ALLFILES`
			    pm_make delete-distfiles RESTRICTED_FILES="${allfiles}" \
				>> $fetchlog 2>&1 &&
				    echo "===>>> RE-STARTING FETCH <<<===" >> $fetchlog
			    pm_make -DBATCH checksum >> $fetchlog 2>&1
			    rm -f ${TMPDIR}/f-${PM_PARENT_PID}-*-${portdir#*/}.* )&
		fi
		unset master_sites distfiles file DONT_FETCH fetchlog
	elif [ -n "$FETCH_ONLY" ]; then
		echo "===>>> No distfiles to fetch"
	fi

	if [ -z "$FETCH_ONLY" -a ! "$PM_PACKAGES" = only ]; then
		TESTINT=`grep -l ^IS_INTERACTIVE Makefile` &&
		    TESTINT=`pm_make_b -V IS_INTERACTIVE`
	else
		[ -n "$PM_ALL_FETCH" ] && safe_exit
	fi
	if [ -n "$TESTINT" ]; then
		echo ''
		echo "===>>> Warning: $portdir is interactive, and will likely"
		echo "       require attention during the build"
		echo ''
		echo -n "===>>> Press the [Enter] or [Return] key to continue "
		read DISCARD
		echo ''
		unset TESTINT DISCARD
	fi
fi	# [ -z "$PM_INDEX_ONLY" -a -z "$PM_BUILDING" -a -z "$SHOW_WORK" -a -z "$NO_ACTION" ]

if [ -n "$PM_FIRST_PASS" ]; then
	[ "$$" -eq "$PM_PARENT_PID" -a -n "$PM_BUILD_ONLY_LIST" ] &&
		PM_BUILD_ONLY_LIST=pmp_doing_build_deps

	if [ -z "$PM_PACKAGES" ]; then
		[ -z "$PM_NO_MAKE_CONFIG" ] && make_config

		dep_check_type='build-depends-list run-depends-list'
		[ -n "$PM_THOROUGH" ] && dep_check_type=all-depends-list
	else
		dep_check_type=run-depends-list
	fi

	dependency_check "$dep_check_type"

	[ -n "$PM_URB" -o -n "$PM_URB_UP" ] &&
		PM_URB_DONE="${PM_URB_DONE}${upg_port}:"

	[ "$$" -eq "$PM_PARENT_PID" ] || safe_exit

	check_fetch_only
	post_first_pass $portdir
fi	# [ -n "$PM_FIRST_PASS" ]

[ -z "$PM_BUILDING" ] && export PM_BUILDING=pmbuildingmain

pm_cd_pd $portdir

if [ -n "$PM_BUILD_ONLY_LIST" ]; then
	case "$build_only_dl_g" in
	*" $pd/$portdir "*)
		[ -n "$PM_PACKAGES_BUILD" ] && PM_PACKAGES_BUILD=doing_build_only_dep
		[ -n "$PM_DEL_BUILD_ONLY" ] && PM_DEL_BUILD_ONLY=doing_build_only_dep ;;
	*)	[ -n "$PM_PACKAGES_BUILD" ] && PM_PACKAGES_BUILD=pmp_build
		[ -n "$PM_DEL_BUILD_ONLY" ] && PM_DEL_BUILD_ONLY=pm_dbo ;;
	esac
fi

if [ -z "$NO_DEP_UPDATES" ]; then
	if [ -z "$PM_THOROUGH" ]; then
		if [ -z "$PM_PACKAGES" ]; then
			echo "===>>> Starting check for build dependencies"
			dependency_check build-depends-list
		fi
	else
		echo "===>>> Starting check for all dependencies"

		if [ -z "$PM_PACKAGES" ]; then
			dependency_check all-depends-list
		else
			dependency_check run-depends-list
		fi
	fi
	pm_cd_pd $portdir
elif [ "$$" -eq "$PM_PARENT_PID" ]; then
	echo "===>>> All dependencies are up to date"
	echo ''
fi

if [ -n "$NO_ACTION" -a -z "$PM_FIRST_PASS" ]; then
	pm_v "===>>> Build canceled due to -n flag"
	safe_exit
fi

find_new_port $portdir

if [ -n "$PM_PACKAGES" -o "$PM_PACKAGES_BUILD" = doing_build_only_dep ]; then
	case `pm_make_b -V PT_NO_INSTALL_PACKAGE` in
	'')	pm_package_time=yes ;;
	*)	if [ "$PM_PACKAGES" = 'only' ]; then
			echo "===>>> The -PP/--packages-only option was specified, but"
			echo "       PT_NO_INSTALL_PACKAGE is defined for $portdir"
			fail These 2 options are mutually exclusive
		fi
		echo "===>>> PT_NO_INSTALL_PACKAGE is set, building port"
		echo '' ;;
	esac
fi

if [ -n "$pm_package_time" ]; then
	unset pm_package_time

fetch_package () {
	# Global: ppd FETCH_ARGS
	local do_fetch

	if [ -z "$ppd" ]; then
		init_packages_var
		ppd=$PACKAGES/portmaster-download
		export ppd
	fi

	[ -d "$ppd" ] || { pm_sv Creating $ppd; pm_mkdir_s $ppd; }

	if [ -z "$FETCH_ARGS" ]; then
		FETCH_ARGS=`pm_make -f/usr/share/mk/bsd.port.mk -V FETCH_ARGS 2>/dev/null`
		[ -n "$FETCH_ARGS" ] || FETCH_ARGS='-ApRr'
		export FETCH_ARGS
	fi

	if [ -z "$PM_ALWAYS_FETCH" ]; then
		if [ -r "${ppd}/${1}.tbz" ]; then
			pm_v "===>>> Package exists, skipping fetch"
			return 0
		else
			do_fetch=do_fetch_no_package
		fi
	else
		do_fetch=do_fetch_always_fetch
		pm_unlink_s ${ppd}/${1}.tbz
	fi

	if [ -n "$do_fetch" ]; then
		if [ -n "$PM_VERBOSE" ]; then
			if [ -n "$2" ]; then
				echo "===>>> Trying to fetch $1 directly"
			else
				echo "===>>> Starting package fetch"
			fi
		fi

		pm_sv Fetching ${1}.tbz
		if ! $PM_SU_CMD fetch $FETCH_ARGS -o $ppd ${sitepath}${1}.tbz 2>/dev/null; then
			pm_unlink_s ${ppd}/${1}.tbz
			$PM_SU_CMD fetch $FETCH_ARGS -o $ppd ${sitepath}${1}.tbz 2>/dev/null
		fi
	fi
}
	if [ -z "$PACKAGESITE" -a -z "$PM_PACKAGES_LOCAL" ]; then
		release=`uname -r`

		case "$release" in
		[789]\.[0-9]-STABLE|[789]\.[0-9]-PRERELEASE)
				release=packages-${release%%\.*}-stable ;;
		[789]\.[0-9]-RELEASE*)
				release=packages-${release%-RELEASE*}-release ;;
		9\.0-CURRENT*)	release=packages-9-current ;;
		10\.0-CURRENT*)	release=packages-10-current ;;
		*RC[0-9]*)	release=${release%-RC[0-9]}
				release=packages-${release}-release ;;
		*BETA[0-9]*)	release=${release%-BETA[0-9]}
				release=packages-${release}-release ;;
		esac

		sitepath="${PACKAGEROOT:-"http://ftp.freebsd.org"}/pub/FreeBSD/ports/`uname -p`/${release}/"
		unset release
	else
		sitepath="${PACKAGESITE%/}"
		sitepath="${sitepath%Latest}"
		sitepath="${sitepath%All}"
	fi

	sitepath="${sitepath%/}/${portdir%/*}/"

	echo "===>>> Checking package repository for latest available version"

	if [ -n "$LOCAL_PACKAGEDIR" ]; then
		if [ -r "${LOCAL_PACKAGEDIR}/All/${new_port}.tbz" ]; then
			local_package=${LOCAL_PACKAGEDIR}/All/${new_port}.tbz
			latest_pv=${local_package##*/}
		fi
		if [ -z "$latest_pv" -a -z "$PM_INDEX_ONLY" ]; then
			s=`pm_make -V LATEST_LINK`
			if [ -r "${LOCAL_PACKAGEDIR}/Latest/${s}.tbz" ]; then
				local_package=${LOCAL_PACKAGEDIR}/Latest/${s}.tbz
				latest_pv=`readlink ${LOCAL_PACKAGEDIR}/Latest/${s}.tbz`
				latest_pv=${latest_pv##*/}
			else
				pm_v "===>>> No local package for ${new_port}, attempting fetch"
			fi
		fi
	fi

	if [ -z "$latest_pv" -a -z "$PM_PACKAGES_LOCAL" ]; then
		dirlist=`echo ${TMPDIR}/f-${PM_PARENT_PID}-dl-${portdir%/*}\.*`
		if [ ! -r "$dirlist" ]; then
			pm_unlink $dirlist		# JIC
			pm_mktemp dl-${portdir%/*} ; dirlist=$pm_mktemp_file
			fetch -q -o - ${sitepath} 2>/dev/null |
			    sed -e "s#%2[cC]#,#g" -e "s#%2[bB]#+#g" > $dirlist
		fi

		for s in ${new_port%\.*} ${new_port%%\.*} ${new_port%-*}; do
			latest_pv=`grep -m1 "href=\"${s}" $dirlist`
			[ -n "$latest_pv" ] && break
		done
	fi
	unset dirlist s

	[ -z "$latest_pv" -a -z "$PM_PACKAGES_LOCAL" ] && {
		fetch_package $new_port try && latest_pv=$new_port; }

	ponly_err="Try --packages-if-newer, or do not use -PP/--packages-only"

	if [ -z "$latest_pv" ]; then
		echo "===>>> Package and/or archive not found at:"
		if [ -n "$LOCAL_PACKAGEDIR" ]; then
			echo "	$LOCAL_PACKAGEDIR"
			[ -z "$PM_PACKAGES_LOCAL" ] && echo '	or'
		fi
		[ -z "$PM_PACKAGES_LOCAL" ] && echo "	${sitepath}"
		echo ''
		echo "       Check the pkg_add(1) man page for information"
		echo "       on setting the PACKAGESITE environment variable"
		[ "$PM_PACKAGES" = only -a -z "$FETCH_ONLY" ] && fail $ponly_err
		if [ -n "$FETCH_ONLY" ]; then
			while : ; do
				echo -e "\n===>>> There is no valid package to install\n"
				echo "===>>> Abort update         [a]"
				echo "===>>> Retry fetch          [r]"
				echo "===>>> Continue if possible [c]"
				echo -e "\n===>>> How would you like to proceed? [a] \c"
				read answer ; echo ''

				case "$answer" in
				''|[aA]) fail "No package exists for $new_port" ;;
				[rR])	if fetch_package $new_port try ; then
						latest_pv=$new_port
						break
					fi ;;
				[cC])	safe_exit ;;
				*)	echo "	===>>> $answer is not a valid response" ;;
				esac
			done
			unset answer
		fi
	else
		latest_pv=${latest_pv#*href=\"}
		latest_pv=${latest_pv%%\.tbz*}
	fi

notnewer () {
	echo ''
	echo "===>>> The newest available package ($latest_pv)"
	echo "       is not newer than the installed version ($upg_port)"

	unset local_package
}
	if [ "$latest_pv" = "$new_port" ]; then
		use_package=up_equal
		pm_v "===>>> Available package ($latest_pv) matches the current version"
	elif [ -n "$latest_pv" -a -n "$PM_PACKAGES_NEWER" ]; then
		if [ -n "$upg_port" ]; then
			if [ -z "$use_pkgng" ]; then
				pkg_version="pkg_version"
			else
				pkg_version="pkg version"
			fi
			case `$pkg_version -t $upg_port $latest_pv` in
			\<)	use_package=up_newer
				pm_v "===>>> Available package ($latest_pv)"
				pm_v "       is newer than installed ($upg_port)" ;;
			=)	if [ -n "$PM_FORCE" ]; then
					use_package=up_force
				else
					notnewer
				fi ;;
			*)	notnewer ;;
			esac
		else
			use_package=up_no_installed
			pm_v "===>>> There is a package available ($latest_pv)"
		fi
	elif [ -n "$latest_pv" ]; then
		if [ -z "$use_pkgng" ]; then
			pkg_version="pkg_version"
		else
			pkg_version="pkg version"
		fi
		case `$pkg_version -t $new_port $latest_pv` in
		\<)	# Could happen if ports tree is out of date
			use_package=up_old_tree
			pm_v "===>>> Available package ($latest_pv)"
			pm_v "       is newer than ports tree ($new_port)" ;;
		=)	;;	# Should not be reached
		*)	# Packages like autoconf-2.1* vs. 2.6* can be false neg.
			fetch_package $new_port try
			if [ $? -eq 0 ]; then
				latest_pv=$new_port
				use_package=up_auto
			else
				echo ''
				echo "===>>> The newest available package ($latest_pv)"
				echo "       is older than the version in ports ($new_port)"
				if [ "$PM_PACKAGES" = only ]; then
					if [ -n "$PM_FORCE" ]; then
						use_package=up_force2
						echo "===>>> Installing anyway due to -f"
					else
						fail $ponly_err
					fi
				fi
			fi ;;
		esac
	fi
	unset ponly_err ; unset -f notnewer

	if [ -n "$use_package" ]; then
		new_port=$latest_pv
	else
		if [ "$PM_PACKAGES" = only ]; then
			fail "There is no valid package to install"
		else
			echo ''
			[ -n "$FETCH_ONLY" ] && safe_exit
			echo "===>>> There is no valid package to install, building port instead"
			echo ''
		fi
	fi
fi	# [ -n "$pm_package_time" ]

if [ -z "$use_package" ]; then
	if [ -n "$PM_PACKAGES" ]; then
		[ -z "$PM_NO_MAKE_CONFIG" ] && make_config

		if [ -z "$PM_THOROUGH" ]; then
			echo "===>>> Starting check for build dependencies"
			dependency_check build-depends-list
		fi
	fi

	pm_cd_pd $portdir
	[ -z "$DONT_PRE_CLEAN" ] && { pm_make clean NOCLEANDEPENDS=ncd ||
		fail 'make clean failed'; }

	fl_read=`echo ${TMPDIR}/f-${PM_PARENT_PID}-fetchlog-${portdir#*/}.*`
	count=0
	while [ -f "$fl_read" ]; do
		count=$(( $count + 1 ))
		if [ $count -eq 1 ]; then
			echo "===>>> Waiting on fetch & checksum for $portdir <<<==="
			tail -10 $fl_read 2>/dev/null
			echo '' ; echo ''
		elif [ $count -eq 3 ]; then
			count=0
		fi
		sleep 2
	done
	unset count fl_read

	if [ -n "$HIDE_BUILD" ]; then
		port_log=`/usr/bin/mktemp -t port_log-${PM_PARENT_PID}-${portdir#*/}` ||
			fail "mktemp for port_log-${PM_PARENT_PID}-${portdir#*/} failed"
		port_log_args=">> $port_log 2>&1"
		echo "===>>> Logging build to $port_log"
	fi

	[ -n "$PM_NO_MAKE_CONFIG" ] && PM_MAKE_ARGS="$PM_MAKE_ARGS -D_OPTIONS_OK"

	eval pm_make $port_log_args || fail "make failed for $portdir"
else
	[ -z "$local_package" ] && {
		fetch_package $latest_pv || fail "Fetch for ${latest_pv}.tbz failed"; }
fi

# Ignore if no old port exists, or -F
if [ -n "$upg_port" -o -n "$ro_upg_port" ] && [ -z "$FETCH_ONLY" ]; then
	UPGRADE_PORT="${ro_upg_port:-$upg_port}"
	UPGRADE_PORT_VER=`echo $UPGRADE_PORT | sed 's#.*-\(.*\)#\1#'`
	export UPGRADE_PORT UPGRADE_PORT_VER

	[ -z "$NO_BACKUP" ] && pm_pkg_create $pbu $UPGRADE_PORT

	if [ -n "$SAVE_SHARED" ]; then
		pm_mktemp ldconfig
		ldconfig -r | sed 's#.* ##' |
		    grep -v ^$LOCALBASE_COMPAT > $pm_mktemp_file

		unset temp
		if [ -z "$use_pkgng" ]; then
			pkglist="pkg_info -q -L"
		else
			pkglist="pkg query %Fp"
		fi
		for file in `$pkglist $UPGRADE_PORT |
		    sort - $pm_mktemp_file | uniq -d`; do
			temp="${temp}$file "
		done
		if [ -n "$temp" ]; then
			if [ ! -d "$LOCALBASE_COMPAT" ]; then
				pm_sv "Creating $LOCALBASE_COMPAT for -w"
				pm_mkdir_s $LOCALBASE_COMPAT
			fi

			pm_sv 'Copying old shared libraries for -w'
			$PM_SU_CMD cp -p $temp ${LOCALBASE_COMPAT}/
			pm_sv Running ldconfig
			$PM_SU_CMD /etc/rc.d/ldconfig start > /dev/null
		fi

		/bin/unlink $pm_mktemp_file ; unset pm_mktemp_file temp file
	fi

	find_dl_distfiles $portdir

	if [ -n "$REPLACE_ORIGIN" -a -n "$ro_upg_port" ]; then
		# Delete any existing versions of the old port
		if [ -n "$use_pkgng" ]; then
			np_orphan=`pkg query "%a" $ro_upg_port`
		fi
		pm_sv "Running pkg_delete for $ro_upg_port"
		pm_pkg_delete_s $ro_upg_port
	fi

	# Could be empty if -o
	if [ -n "$upg_port" ]; then
		case " $PM_PRESERVE_PORTS " in
		*" $portdir "*)
			preserve_port=`echo $portdir | sed 's#[-+/\.]#_#g'`
			eval preserve_port_files="\$${preserve_port}_files"
		preserve_dir=`/usr/bin/mktemp -d ${TMPDIR}/d-${PM_PARENT_PID}-${preserve_port} 2>/dev/null` ||
				fail "Could not create a temporary directory for $preserve_port in $TMPDIR"
			for file in $preserve_port_files; do
				cp -p $file ${preserve_dir}/ ||
				    fail "Cannot copy $file, which is in \$${preserve_port}_files"
			done
			unset preserve_port files
		esac

		# If $ro_upg_port was non-automatic, keep its state
		if [ -n "$use_pkgng" -a "${np_orphan:-1}" -eq 1 ]; then
			np_orphan=`pkg query "%a" $upg_port`
		fi
		pm_sv "Running pkg_delete for $upg_port"
		pm_pkg_delete_s $upg_port
	fi

	echo ''
	pm_cd_pd $portdir
fi

if [ -z "$PM_THOROUGH" -a -z "$NO_DEP_UPDATES" ]; then
	echo "===>>> Starting check for runtime dependencies"
	dependency_check run-depends-list
	pm_cd_pd $portdir
fi

if [ -n "$FETCH_ONLY" ]; then		# Only reached here if using packages
	CUR_DEPS="${CUR_DEPS}${new_port}:${portdir}:"

	if [ "$$" -eq "$PM_PARENT_PID" ]; then
		check_fetch_only Package
	else
		safe_exit
	fi
fi

install_failed () {
	local upg_port

	upg_port="${ro_upg_port:-$upg_port}"

	if [ -z "$NO_BACKUP" -a -n "$upg_port" ]; then
		echo ''
		echo "===>>> A backup package for $upg_port should"
		echo "       be located in $pbu"
	fi
	fail "Installation of $1 ($portdir) failed"
}

if [ -z "$use_package" ]; then
	pm_sv Running make install

	if [ -z "$PM_SU_UNSET_PORT_LOG_ARGS" ]; then
		[ -n "$HIDE_BUILD" ] && echo "===>>> Logging install to $port_log"
	else
		unset port_log_args
	fi

	if [ -z "$np_orphan" -a -z "$UPDATE_ALL" -a -z "$REPLACE_ORIGIN" -a -z "$PM_URB" ]; then
		if [ -n "$PM_MULTI_PORTS" ]; then
			case "$PM_MULTI_PORTS" in
			*:${upg_port:-NONE}:*)	np_orphan=0 ;;
			*:${portdir}:*)		np_orphan=0 ;;
			esac
		else
			[ "$$" -eq "$PM_PARENT_PID" ] && np_orphan=0
		fi
	fi
	[ "${np_orphan:-1}" -eq 1 ] && PM_MAKE_ARGS="${PM_MAKE_ARGS} -DINSTALLS_DEPENDS"
	unset np_orphan
	# Defining NO_DEPENDS ensures that we will control the installation
	# of the depends, not bsd.port.mk.
	eval pm_make_s -DNO_DEPENDS install $port_log_args || install_failed $new_port
else
	[ -n "$local_package" ] && ppd=${LOCAL_PACKAGEDIR}/All

	echo "===>>> Installing package"
	if $PM_SU_CMD pkg_add --no-deps --force ${ppd}/${latest_pv}.tbz; then
		if [ -n "$PM_DELETE_PACKAGES" ]; then
			pm_v "===>>> Deleting ${latest_pv}.tbz"
			pm_unlink_s ${ppd}/${latest_pv}.tbz
		fi
	else
		install_failed ${latest_pv}.tbz
	fi
fi

if [ -z "$use_pkgng" ]; then
	for file in $preserve_port_files; do
		mv $file ${file}-new
		mv ${preserve_dir}/${file##*/} $file
		oldmd5="MD5:`md5 -q $file`"
	
		pm_mktemp contents
		while read left right; do
			case "$left" in
			@cwd)		short_file="${file#${right}/}" ;;
			$short_file)	found_it=found_it ; continue;;
			@comment)	if [ -n "$found_it" ]; then
						echo -e "${short_file}-new\n$left $right"
						echo -e "$short_file\n@comment $oldmd5"
						unset found_it
						continue
					fi ;;
			esac
			echo "$left $right"
		done < $pdb/$new_port/+CONTENTS > $pm_mktemp_file
		pm_install_s $pm_mktemp_file $contents
		pm_unlink $pm_mktemp_file
		unset file oldmd5 pm_mktemp_file left right short_file
	done
fi
if [ -n "$preserve_dir" ]; then
	rmdir $preserve_dir 2>/dev/null
	unset preserve_dir preserve_port_files
fi

echo ''

[ "$PM_DEL_BUILD_ONLY" = doing_build_only_dep ] &&
	build_deps_il="$build_deps_il $new_port"

# Remove saved libs that match newly installed files

temp=`find $LOCALBASE_COMPAT -type d -empty 2>/dev/null`
if [ -z "$temp" ] && [ -d "$LOCALBASE_COMPAT" ]; then
	unset files
	if [ -z "$use_pkgng" ]; then
		pkglist="pkg_info -q -L"
	else
		pkglist="pkg query %Fp"
	fi
	for file in `$pkglist $new_port`; do
		[ -f "${LOCALBASE_COMPAT}/${file##*/}" ] &&
			files="${files}${LOCALBASE_COMPAT}/${file##*/} "
	done

	if [ -n "$files" ]; then
		pm_sv Removing old shared libraries, and running ldconfig
		pm_rm_s `make -V FILES:O:u FILES="$files"`
		$PM_SU_CMD /etc/rc.d/ldconfig start > /dev/null
	fi
	unset temp file files
fi

[ -z "$temp" ] && temp=`find $LOCALBASE_COMPAT -type d -empty 2>/dev/null`
if [ -d "$temp" ]; then
	pm_sv Deleting the empty $LOCALBASE_COMPAT
	pm_rmdir_s $temp
fi
unset temp

# This will serve for *delete*distfiles() as well
[ -z "$use_package" ] && make_distfiles
if [ -n "$distfiles" ]; then
	# Implement storage of distfile information in the way that
	# it will (hopefully, soon?) be implemented in bsd.port.mk
	# See http://www.freebsd.org/cgi/query-pr.cgi?pr=106483
	dist_list="${pdb}/${new_port}/distfiles"

	make_port_subdir

	if [ -s distinfo ]; then
		distinfo=distinfo
	else
		distinfo=`pm_make -V DISTINFO_FILE`
		[ -n "$distinfo" ] || fail "No DISTINFO_FILE in $portdir"
	fi

	pm_mktemp dist_list
	echo '# Added by portmaster' > $pm_mktemp_file
	for file in $distfiles; do
		while read line ; do
			case "$line" in
			SHA256\ \(${port_subdir}${file}\)*) sha256=${line##* }
				[ -z "$size" ] && continue
				echo "DISTFILE:${port_subdir}${file}:SIZE=${size}:SHA256=${sha256}" \
					>> $pm_mktemp_file ; unset sha256 size ; break ;;
			SIZE\ \(${port_subdir}${file}\)*)
				[ -z "$sha256" ] && { size=${line##* } ; continue; }
				echo "DISTFILE:${port_subdir}${file}:SIZE=${line##* }:SHA256=${sha256}" \
					>> $pm_mktemp_file ; unset sha256 ; break ;;
			esac
		done < $distinfo

		# Make sure any new distfiles get added to the list
		[ -n "$DI_FILES" -a ! "$$" -eq "$PM_PARENT_PID" ] &&
			echo "${port_subdir}${file}" >> $DI_FILES
	done

	pm_sv "Installing $dist_list\n"
	pm_mkdir_s ${dist_list%/*}
	pm_install_s $pm_mktemp_file $dist_list
	/bin/unlink $pm_mktemp_file ; unset distinfo pm_mktemp_file file line
fi

# pkgng does not need this
if [ -z "$use_pkgng" -a -n "$use_package" ]; then
	if grep -q DEPORIGIN $pdb/$new_port/+CONTENTS; then
		echo -e "===>>> Updating dependencies for $new_port to match installed versions\n"
		update_contents $pdb/$new_port/+CONTENTS ; pm_v

		while read atc s; do
			case "$atc" in
			@pkgdep)	[ -n "$s" ] && pkgdep=$s ;;
			@comment)	[ -n "$pkgdep" ] || continue
					check_dependency_files ${s#DEPORIGIN:} $pkgdep
					[ -s "$grep_deps" ] && update_required_by $pkgdep
					unset pkgdep ;;
			esac
		done < $pdb/$new_port/+CONTENTS
		[ -n "$needws" ] && { pm_v; unset needws; }
		unset atc s
	fi
fi

if [ -n "$MAKE_PACKAGE" ]; then
	if [ -z "$use_package" ]; then
		echo "===>>> Creating a package for new version $new_port"
		pm_make_s -D_OPTIONS_OK package >/dev/null || fail "Package creation of $new_port failed"
		echo "	===>>> Package saved to $PACKAGES/All" ; echo ''
	else
		pm_pkg_create $PACKAGES $new_port
	fi
fi

if [ -z "$use_package" -a -z "$DONT_POST_CLEAN" ]; then
	pm_v "===>>> Running 'make clean' in the background"
	(pm_make_s clean NOCLEANDEPENDS=ncd2 >/dev/null)&
	pm_v
fi

if [ -z "$use_pkgng" ]; then
	check_dependency_files $portdir $new_port
	if [ -s "$grep_deps" ]; then
		echo -e "===>>> Updating dependency entry for $new_port in each dependent port\n"
		while read d_port; do
			pm_v "===>>> $d_port"
			dp_cont=$pdb/$d_port/+CONTENTS
			[ -e "$dp_cont" ] || continue
	
			if [ -n "$ro_opd" ] && grep -ql "DEPORIGIN:$ro_opd$" $dp_cont; then
				update_contents $dp_cont $portdir $new_port $ro_opd
			fi
			# Do this one last so it can get deleted as a duplicate
			# if ro_opd is present.
			if grep -ql "DEPORIGIN:$portdir$" $dp_cont; then
				update_contents $dp_cont $portdir $new_port
			fi
		done < $grep_deps
		unset d_port dp_cont ; pm_v
	
		update_required_by $new_port
		[ -n "$needws" ] && { pm_v; unset needws; }
	fi
else
	if [ -n "$ro_opd" ]; then
		echo "===>>> Updating dependency entry for $new_port in each dependent port"
		pkg set -yo $ro_opd:$portdir
	fi
fi


if [ -n "$upg_port" ]; then
	if [ ! "$upg_port" = "$new_port" ]; then
		ilist="Upgrade of $upg_port to $new_port"
	else
		ilist="Re-installation of $upg_port"
	fi
else
	ilist="Installation of $portdir ($new_port)"
fi

if [ "$$" -ne "$PM_PARENT_PID" -o -n "$PM_URB" ]; then
	echo "===>>> $ilist succeeded" ; echo ''
fi

INSTALLED_LIST="${INSTALLED_LIST}\t${ilist}\n"
[ -z "$use_pkgng" -a -e "$pdb/$new_port/+DISPLAY" ] || ( [ -n "$use_pkgng" ] && [ -n "`pkg query %M $new_port`" ] ) &&
	DISPLAY_LIST="${DISPLAY_LIST}$new_port "
CUR_DEPS="${CUR_DEPS}${new_port}:${portdir}:"

[ -n "$HIDE_BUILD" -a -n "$port_log" ] && pm_unlink $port_log

[ -n "$PM_URB" -o -n "$PM_URB_UP" ] && PM_URB_DONE="${PM_URB_DONE}${new_port}:"
[ -n "$PM_URB" -o -n "$PM_URB_UP" -o -n "$PM_FORCE" ] &&
	pm_mkdir_s $pdb/$new_port &&
	$PM_SU_CMD touch $pdb/$new_port/PM_UPGRADE_DONE_FLAG

if [ -z "$DONT_SCRUB_DISTFILES" ]; then
	delete_stale_distfiles $portdir
	if [ -n "$ro_opd" ]; then
		delete_all_distfiles $ro_opd
	fi
fi

safe_exit

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#  Copyright (c) 2005-2012 Douglas Barton
#  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 THE AUTHOR AND CONTRIBUTORS ``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 THE AUTHOR OR CONTRIBUTORS 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.
