%PDF- %PDF-
Mini Shell

Mini Shell

Direktori : /usr/local/sbin/
Upload File :
Create Path :
Current File : //usr/local/sbin/portmaster

#!/bin/sh

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

trap trap_exit INT

umask 022

progcmd="$0"				# actual invocation of this program for search in ps output
progname="${0##*/}"			# program name in messages
program="$(realpath $0 || echo $0)"	# full path to program for recursive calls

PKG_CMD="/usr/local/sbin/pkg-static"

# 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
	[ `id -u` -eq 0 ] && unset PM_SU_CMD PM_SU_VERBOSE
fi

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

version () {
	echo '' ; echo "===>>> Version 3.20"
}

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`

	while read pid ppid pgid command; do
		[ "$pid" -gt 25 ] || continue
		case "$ppid" in
		1)	case "$command" in
			*" $progcmd "*) 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
			*" $progcmd "*) pm_kill $pid ;;
			*'make -DBATCH checksum'*|*'/fetch '*|\[sh\]) pm_kill $pid ;;
			esac ;;
		esac
	done <<-EOF
	$(ps -axo pid,ppid,pgid,command | sed '1d')
	EOF

}

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
				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 pm_isdir "$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 -maxdepth 2 -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 [ -n "$PM_NO_CONFIRM" ]; then
			PAGER=cat
		fi
		(
		$PKG_CMD query "===>>> pkg-message for %n-%v\n%M" $DISPLAY_LIST
		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
		pm_pkg_delete_s $build_deps_il
		echo ''
	fi

	if [ -n "$1" -a -n "${PM_NEEDS_UPDATE# }" -a -n "$PM_BUILDING" -a -z "$FETCH_ONLY" ]; then
		echo "$progname <flags>${PM_NEEDS_UPDATE}" > ~/portmasterfail.txt
		echo ''
		echo "===>>> You can restart from the point of failure with this command line:"
		echo "       $progname <flags>${PM_NEEDS_UPDATE}"
		echo ''
		echo "This command has been saved to ~/portmasterfail.txt"
		echo ''
	fi
}

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()

target_part	() { [ -z "${1##*:*}" ] && echo "${1#*:}" || echo install; }
flavor_part	() { local tmp="${1%%:*}"; [ -z "${tmp##*@*}" ] && echo "${tmp#*@}"; }
dir_part	() { local tmp="${1%%:*}"; echo "${tmp%%@*}"; }
export_flavor	() { if [ -n "$1" ]; then export FLAVOR="$1"; else unset FLAVOR; fi; }

pm_cd     () { builtin cd $1 2>/dev/null || return 1; }
pm_cd_pd  () { [ -n "$PM_INDEX_ONLY" ] && return 2;
			local dir=$pd/$(dir_part $1);
			builtin cd $dir 2>/dev/null ||
			fail "Cannot cd to port directory: $dir"; }
pm_isdir	() { builtin test -d "$1"; }
pm_isdir_pd	() { local dir=$(dir_part "$1");
			builtin test -n "$dir" -a -d "$pd/$dir"; }
pm_kill   () { 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; }
pm_islocked	() { local locked; [ -n "$1" ] && locked=`$PKG_CMD query %k "$1"` &&
			[ "$locked" = 1 ] || [ -e "$pdb/$1/+IGNOREME" ]; }

# 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   () {
	for f in "$@"; do
		if [ "$($PKG_CMD query %k $f)" = 1 ]; then
			was_locked=1
			$PKG_CMD unlock -qy $f
		fi
	done
	$PM_SU_CMD /usr/local/sbin/pkg-static delete -yf "$@";
	for d in $* ; do
	    pm_rm_s -rf $pdb/$d
	done
}
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
			pd=`pm_make_b -f/usr/share/mk/bsd.port.mk -V PORTSDIR 2>/dev/null` || pd=""
			[ -z "$pd" ] && pm_isdir /usr/ports && pd=/usr/ports
		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
			pm_isdir /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 pm_isdir /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" ] && pm_isdir /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
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 "    [--backup-format=<fmt>] [--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 "$progname [Common flags] <full name of port directory in $pdb>"
	echo "$progname [Common flags] <full path to $pd/foo/bar>"
	echo "$progname [Common flags] <glob pattern of directories in $pdb>"
	echo "$progname [Common flags] [--update-if-newer] Multiple full names/paths"
	echo "         from $pdb|$pd and/or multiple globs from $pdb"
	echo ''
	echo "$progname [Common flags] . [Use in $pd/foo/bar to build that port]"
	echo ''
	echo "$progname [Common flags] -a"
	echo ''
	echo "$progname --show-work [-Gv] [-m <args>] <single port, as above>"
	echo ''
	echo "$progname [Common flags] -o <new port dir in $pd> <installed port>"
	echo "$progname [Common flags] [-R] -r <name/glob of port directory in $pdb>"
	echo '         (-r <port> can be specified multiple times)'
	echo ''
	echo "$progname -l"
	echo "$progname [--index-only [-t]] -L"
	echo ''
	echo "$progname --list-origins"
	echo ''
	echo "$progname --try-broken"
	echo ''
	echo "$progname [--force-config|-G] [-P|-PP] [-aftv] -F"
	echo ''
	echo "$progname [-n|y] [-b] [-D|d] -e <name/glob of a single port in $pdb>"
	echo "$progname [-n|y] [-b] [-D|d] -s"
	echo ''
	echo "$progname [-n|y] [-t] --clean-distfiles"
	echo ''
	echo "$progname [-n|y] [--index|--index-only] --clean-packages"
	echo ''
	echo "$progname [-n|y] [--index|--index-only] [-v] --check-depends"
	echo ''
	echo "$progname [-n|y] [-v] --check-port-dbdir"
	echo ''
	echo "$progname -h|--help"
	echo "$progname --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 '--try-broken do not skip ports marked as broken'
	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`

	glob_dirs=`$PKG_CMD query -g "%n-%v" ${pattern}\*`
	case "$glob_dirs" in
	# Match a newline in multiple responses from find
	*'
'*)		return 2 ;;
	'')	;;
	*)	return ;;
	esac

	unset glob_dirs
	return 1
}

match_flavor () {
	local origin=$(dir_part $1)
	local flavor	# =$(flavor_part $1)
	local iport="$2"
	local dir="$pd/$origin"

	if [ -d "$dir" ]; then
	local IFS=' '
	local pkgname=${iport%-*}
	local flavors=$(pm_make -C "$dir" -V FLAVORS)
	for flavor in $flavors; do
		local p=$(pm_make -C "$dir" FLAVOR=$flavor -V PKGNAME)
		if [ -n "$p" -a "${p%-*}" = "$pkgname" ]; then
			echo "$origin@$flavor"
			return
		fi
	done
	fi
	echo "$1"	# should not be reached!
}

origin_from_pdb () {
	local flavor pkgname origin_flavor

	pkgname="$1"
	flavor=$($PKG_CMD annotate -Sq "$pkgname" flavor)
	
	if origin_flavor=$($PKG_CMD query '%o'"${flavor:+@$flavor}" "$pkgname" 2>/dev/null); then
		match_flavor $origin_flavor $pkgname
		return 0
	fi

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

	if pm_islocked "$pkgname"; then
		if [ -n "$PM_VERBOSE" -o -n "$LIST_ORIGINS" ]; then
			# An error above doesn't necessarily mean there's
			# a problem in +MANIFEST, so don't mention it
			echo "	===>>> No origin available for $pkgname" >&2
			echo "	===>>> $pdb/$pkgname/+IGNOREME exists or the package is locked" >&2
			echo '' >&2
		fi
		return 2
	else
		# Same as above
		echo "	===>>> No origin available for $pkgname" >&2
		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 ;;
	--backup-format=*)	BACKUP_FORMAT=${var#--backup-format=}
				export BACKUP_FORMAT ;;
	--package-format=*)	PACKAGE_FORMAT=${var#--package-format=}
				export PACKAGE_FORMAT ;;
#	--flavor=*)		PM_FLAVOR=${var#--flavor=} ;;
	--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 ;;
	--try-broken)		TRY_BROKEN=try_broken; PM_MAKE_ARGS="$PM_MAKE_ARGS -DTRYBROKEN" ;;
	--*)			echo "Illegal option $var" ; echo ''
				echo "===>>> Try $progname --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 'BCDFGHIKLPRabde: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" ;;
	I)	NON_INTERACTIVE=Iopt; ARGS="-I $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 ;; # -o should take a parameter and $OPTARG should be assigned here
	p)	fail 'The -p option has been deprecated' ;;
	r)	PM_URB=ropt
		if [ -d "$pdb/$OPTARG" ] && $PKG_CMD 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)	fail "$OPTARG is not installed" ;;
			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 $progname --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 "$NO_ACTION" ] && PM_NO_MAKE_CONFIG=no_action PM_FORCE_CONFIG=""
[ -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_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

		PM_INDEX_PORTS=`$PKG_CMD 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" ] && pm_isdir "$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 ! pm_isdir "$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" ]

#=============== cache some build parameters in the environment ===============
SCRIPTSDIR="$pd/Mk/Scripts" PORTSDIR="$pd" MAKE=make . "$pd/Mk/Scripts/ports_env.sh" > /dev/null

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

# find installed port for given origin (with optional @flavor) in the pkg DB
# return values:
# 0 - package name has been printed to STDOUT
# 1 - no matching installed packages found
iport_from_origin () {
	local origin flavor pkgname_l pkgname pkgflavor

	origin=$(dir_part "$1")
	flavor=$(flavor_part "$1")
	if [ -z "$flavor" ]; then
		unset FLAVOR
		flavor=$(pm_make -C "${pd}/${origin}" -V FLAVOR)
	fi
	pkgname_l=$(echo $($PKG_CMD query '%n-%v' $origin)) || return 1
	# if multiple flavors registered then fall back to $FLAVOR if no flavor has been passed in $1
	[ "${pkgname_l}" != "${pkgname_l#* }" ] && : ${flavor:=$FLAVOR}
	for pkgname in $pkgname_l; do
		pkgflavor=$($PKG_CMD annotate -Sq "$pkgname" flavor)
		if [ "$pkgflavor" = "$flavor" ]; then
			echo $pkgname
			return 0
		fi
	done
	return 1
}

# 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
}

# Find the new origin for moved ports
# Set global variable moved_npd on success
# Return values:
# 0 - The new origin has been stored in the global variable moved_npd
# 1 - The port has not been moved to a new origin
find_moved_port () {
	# Global: moved_npd
	local sf iport flag IFS moved reason

	sf=$(dir_part "$1")	# Search for origin without flavor
	iport="$2"		# initial package name
	flag="$3"		# optional flag "nonfatal"

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

	if [ -z "$moved_npd" ]; then
		if [ -z "$reason" ]; then
			echo ''
			echo "	===>>> No $pd/$sf exists, and no information"
			echo "	===>>> about $sf 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 $1` || return 1
		pm_islocked $iport || return 1
	fi
	return 0
}

all_pkgs_by_origin () {
	namesorigins=`$PKG_CMD query -a "%n-%v %o"`
	echo "$namesorigins"
	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 ! pm_isdir_pd "$origin"; then
			find_moved_port $origin $iport nonfatal >/dev/null
			[ -n "$moved_npd" ] || continue
			origin=$moved_npd
		fi

		origin="${pd}/"$(dir_part $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|base/*) continue ;; esac

		pm_isdir "$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"
	roots=`   $PKG_CMD query -e "%#d = 0 && %#r = 0" "%n-%v"`
	trunks=`  $PKG_CMD query -e "%#d = 0 && %#r > 0" "%n-%v"`
	branches=`$PKG_CMD query -e "%#d > 0 && %#r > 0" "%n-%v"`
	leaves=`  $PKG_CMD 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_CMD query -a "%n-%v" | wc -w))
}

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 origin

	origin=$(dir_part $1)
	line=`grep -m1 "|${PM_IPD}/${origin}|" $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
}

#=============== 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 ''

		origin=`$PKG_CMD 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 pm_isdir_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 ! $PKG_CMD 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
				unset port_ver
				continue
			fi

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

			unset port_ver

			if $PKG_CMD info -e $pkg_dir; then
				echo "	===>>> ${package##*/} matches the installed version"
			else
				echo "	===>>> ${package##*/} is not installed"
			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
	$PKG_CMD check -dn
	exit 0
fi

if [ -n "$CHECK_PORT_DBDIR" ]; then
	pm_isdir "$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 ''
	while read pkg origin; do
		if ! pm_isdir_pd "$origin"; then
			find_moved_port $origin $pkg nonfatal >/dev/null
			[ -n "$moved_npd" ] || continue
			origin=$(dir_part $moved_npd)
		fi

		if ! pm_cd $pd/$origin; then
			echo "	===>>> $pd/$origin does not exist for $pkg"
			continue
		fi
		unique_list="${unique_list}`pm_make -V OPTIONS_NAME | tr '\n' ':'`"
	done <<-EOF
	$(all_pkgs_by_origin)
	EOF

	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
	$PKG_CMD query -e '%#r = 0' '%o'

	exit 0
fi

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

check_state () {
	# Global: state
	local state_set makevars

	[ -z "$TRY_BROKEN" ] && makevars="FORBIDDEN BROKEN IGNORE" || makevars="FORBIDDEN"
	if egrep -ql '^(FORBIDDEN|BROKEN|IGNORE)' Makefile; then
		for state in $makevars; 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
}

find_new_port () {
	# Global: new_port
	local portdir flavor

	[ -n "$new_port" ] && return

	portdir=$(dir_part "$1")
	flavor=$(flavor_part "$1")
	if pm_cd_pd $portdir; then
		new_port=`FLAVOR=$flavor pm_make -V PKGNAME`
	else
		new_port=`parse_index $portdir name` ||
			fail "No entry for $portdir in $PM_INDEX"
	fi
}

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

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

	iport=$1
	originflavor=${2:-`origin_from_pdb $iport`} || return 0
	flavor=$(flavor_part "$originflavor")
	export_flavor $flavor
	origin=$(dir_part "$originflavor")

	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 $originflavor || 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" ] && pm_isdir "$pd/$origin"; then
		if ! pm_cd $pd/$origin; then # <se> cannot happen - see pm_isdir test above
			if pm_islocked "$iport"; then
				echo "	===>>> Warning: Unable to cd to $pd/$origin"
				echo "	===>>> Continuing due to $pdb/$iport/+IGNOREME or the package being locked"
				echo ''
				CUR_DEPS="${CUR_DEPS}${iport}:${originflavor}:"
				return 0
			else
				fail "Cannot cd to port directory: $pd/$origin"
			fi
		fi
		port_ver=`FLAVOR=$flavor 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 pm_islocked "$iport"; then
				echo "	===>>> Continuing due to $pdb/$iport/+IGNOREME or the package being locked"
				echo ''
				CUR_DEPS="${CUR_DEPS}${iport}:${originflavor}:"
				return 0
			else
				do_update=do_update_moved
				new_port=""
				find_new_port "$moved_npd" && port_ver=$new_port
			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 $originflavor || do_update=upd_fm_eq
				unset port_ver
			fi
		else
			case `$PKG_CMD 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 $originflavor || do_update=upd_fm_ne; }
		fi
	fi

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

	if [ -n "$LIST_PLUS" ]; then
		if [ -z "$moved_npd" ]; then
			echo "	===>>> New version available: $port_ver"
			if pm_islocked "$iport"; then
				echo "	===>>> +IGNOREME file is present for $1 or the package is locked"
			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 ! pm_isdir "$pbu"; then
		pm_sv Creating $pbu
		pm_mkdir_s $pbu
	fi
	export pbu
}

pm_pkg_create () {
	local pkgdir backup format_option

	init_packages

	[ -z "$BACKUP_FORMAT" -a -n "$PACKAGE_FORMAT" ] && export BACKUP_FORMAT=$PACKAGE_FORMAT
	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
		format_option=${PACKAGE_FORMAT:+-f $PACKAGE_FORMAT}
		echo "===>>> Creating a package for new version $2"
	else
		pkgdir=$1 ; echo ''
		format_option=${BACKUP_FORMAT:+-f $BACKUP_FORMAT}
		echo "===>>> Creating a backup package for old version $2"
		backup=backup
	fi

	pm_cd $pkgdir || fail "Cannot cd into $pkgdir to create a package"
	if $PM_SU_CMD $PKG_CMD create $format_option $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=$2.pkg

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

				pm_cd_pd $portdir
				pkg_latest_file=`pm_make -V PKGLATESTFILE`
				$PM_SU_CMD install -lr $1/All/$pkg ${pkg_latest_file}
			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
		local d=$(dir_part $1)
		# Old method, for now
		if pm_cd $pd/$d; then
			dist_list=`pm_make_b -V OPTIONS_FILE`
			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
			local dd=$(echo "$d" | tr "/" "_")
			dist_list="$port_dbdir/${dd##*/}/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 pm_isdir "$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 pm_isdir_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 pm_isdir "$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 $progname [-y] --clean-distfiles for a full cleanup"
		echo ''
		return 3
	fi
	return 0
}

delete_stale_distfiles () {
	[ -n "$DISTDIR" ] || return # DISTDIR not set because of PM_PACKAGES
	# 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 () {
	[ -n "$DISTDIR" ] || return # DISTDIR not set because of PM_PACKAGES
	# 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 $progname [-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 ! pm_isdir "$pdb/$EXPUNGE" || ! $PKG_CMD info -e $EXPUNGE; then
		find_glob_dirs $EXPUNGE
		case $? in
		1)	fail "No such port: $EXPUNGE" ;;
		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`
	deplist=`$PKG_CMD query "%rn-%rv" $origin`
	if [ -n "$deplist" ]; then
		echo "===>>> Warning: Ports with dependencies on ${EXPUNGE}:"
		echo "$deplist" | sed 's/^/	/'
		get_answer_yn n "\n\t===>>> Delete this dependency data"
		case "$?" in
		0)	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

	echo "===>>> Running pkg delete -f $EXPUNGE"
	pm_pkg_delete_s $EXPUNGE || fail "pkg delete failed"

	echo '' ; echo "===>>> Running $progname -s $ARGS"
	exec "$program" -s $ARGS
	exit 0	# Should not be reached
fi

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

	stale_ports=`$PKG_CMD query -ae '%a = 1' '%?r %n-%v' | awk '/^0 / { print \$2 }'`
	for file in $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 [ -n "$deplist" ]; then
			echo ''
			echo "===>>> Warning: Unrecorded dependencies on ${iport}:"
			for dep in $deplist; do
				dep=${dep%/+CON*} ; echo "	${dep##*/}"
			done
			echo ''
			echo "===>>> Try $progname --check-depends"
			echo ''
			continue
		fi

		echo '' ; $PKG_CMD info -f $iport

		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 "$program" -s $ARGS ;;
		*)	no_del_list="${no_del_list}${iport}:" ;;
		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" ] || ! $PKG_CMD 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 pm_islocked $1; then
		echo ''
		echo "===>>> package is locked or +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;$progname: ${PM_PARENT_PORT}${1}\007"
}

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

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

update_build_l () {
	local originflavor origin flavor iport make_target

	originflavor=$1 ; update_pm_nu $originflavor
	origin=$(dir_part "$originflavor")
	flavor=$(flavor_part "$originflavor")
	iport="$2"
	make_target=$3

	[ -n "$PM_NO_CONFIRM" ] && return

	if [ -z "$iport" ]; then
		case "$build_l" in *\ $origin\\*) return ;; esac
		case $make_target in
		install)
			build_l="${build_l}\tInstall $originflavor\n" ;;
		*)
			build_l="${build_l}\tExecute make $make_target for $originflavor\n" ;;
		esac
		return
	fi

	case "$build_l" in *\ $iport\ *|*\ $iport\\*) return ;; esac

	find_new_port "$originflavor" # sets global variable new_port

	case `$PKG_CMD 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 make_target deps

	make_target=$(target_part "$1")
	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
		("$program" $ARGS $*) || 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` "
}

make_dep_list () {
	local dep_type var_opt

	for dep_type in $*; do
		case $dep_type in
		all-depends-list|build-depends-list)
			var_opt="$var_opt -V PKG_DEPENDS -V EXTRACT_DEPENDS \
				-V PATCH_DEPENDS -V FETCH_DEPENDS -V BUILD_DEPENDS -V LIB_DEPENDS"
			[ "$dep_type" = all-depends-list ] && var_opt="$var_opt -V RUN_DEPENDS" ;;
		run-depends-list)
			var_opt="$var_opt -V RUN_DEPENDS -V LIB_DEPENDS" ;;
		test-depends-list)
			var_opt="$var_opt -V TEST_DEPENDS" ;;
		*)
			fail "make_dep_list: Unsupported option '$dep_type'"
		esac
	done
	[ -n "$var_opt" ] && pm_make $var_opt | tr ' ' '\n' | cut -d: -f2-3 | sort -u
}

gen_dep_list () {
	local list

	if [ -z "$PM_INDEX_ONLY" ]; then
		pm_cd_pd $portdir
		export_flavor $(flavor_part $portdir)
		make_dep_list $*
	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"
}

#
#
# changes PWD!!!
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
			# strip optional make target
			local depdir=${dep%:*}
			# 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
			$PKG_CMD info -e ${depdir#$pd/} &&
				run_dl="$run_dl $depdir" &&
				continue
			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_target in $d_port_list; do
		# strip optional make target
		local d_port=${d_port_target%:*}
		local make_target=$(target_part "$d_port_target")
		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" -a "$make_target" = install ]; then
			local conflicts glob confl_p dir flavor
			dir=$(dir_part $d_port)
			flavor=$(flavor_part $d_port)
			pm_cd "$pd/$dir" || fail "Cannot cd to $dir"
			conflicts=`FLAVOR=$flavor pm_make_b -V CONFLICTS -V CONFLICTS_BUILD -V CONFLICTS_INSTALL`	 
			for glob in $conflicts; do
				confl_p=`$PKG_CMD query -g "%n-%v" $glob 2>/dev/null`
				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}:${originflavor}:"
			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}:${originflavor}:"
					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
			if [ "$make_target" != "install" ]; then
				[ -z "$PM_FIRST_PASS" ] && post_clean_l="$post_clean_l $origin"
				origin="$origin:$make_target"
			fi
			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
			[ "`$PKG_CMD query "%?r" ${dep#$pd/}`" = "1" ] && continue
			[ -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
		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_CMD query "%rn-%rv %ro" ${origin})
		EOF
	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
		$PKG_CMD info -e $req_by || continue

		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" ] || pm_isdir_pd "${port}"; then
				worklist_temp="$worklist_temp $port"
			else
				fail "$pd/${port} does not exist"
			fi ;;
		*)	if pm_isdir "$pdb/$port" && $PKG_CMD info -e $port; then
				worklist_temp="$worklist_temp $port"
			else
				find_glob_dirs $port
				case $? in
				1)	fail "$port is not installed" ;;
				*)	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}"
		($program $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 ! $PKG_CMD info -e $port; then
				numports=$(( $numports - 1 ))
				continue
			fi
			origin=$(origin_from_pdb $port)
			unset PM_OLD_ORIGIN
			if [ -n "$origin" ] && ! pm_isdir_pd "$origin"; then
				export PM_OLD_ORIGIN=$origin
				find_moved_port $origin $port nonfatal && origin=$moved_npd
			fi ;;
		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}"
		("$program" $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
	[ -f Makefile ] || pm_cd
	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" ] && pm_idsdir "$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 $progname, 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 "$OLDPWD"
	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 ! pm_isdir "$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 or the package is locked"
				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 $progname --help" ; echo '' ; safe_exit 1
}

make_target=$(target_part "$1")
post_clean_l=""

# Figure out what we are going to be working on
if [ -z "$REPLACE_ORIGIN" ]; then
	portdir="${1%:*}"
	export_flavor $(flavor_part $portdir)
	[ -n "$portdir" ] && { argv=$portdir ; unset portdir; }
	argv=${argv:-$1} ; argv=${argv%/} ; argv=`globstrip $argv`
	case "$argv" in
	$pd/*)	portdir=${argv#$pd/} ;;
	$pdb/*)	echo '' ; no_valid_port ;;
	/*)	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 ;;
	*)	upg_port=$($PKG_CMD query %n-%v "$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

	[ "$make_target" != install ] && PM_MAKE_ARGS="-DDISABLE_CONFLICTS $PM_MAKE_ARGS"
else
	portdir="${1#$pd/}" ; portdir="${portdir%/}"
	export_flavor $(flavor_part $portdir)
	if [ -z "$PM_INDEX_ONLY" ]; then
		pm_isdir_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` || upg_port=$opd	# <se> $opd is never set???
	arg2=${2#$pd/} ; arg2=${arg2#$pdb/} ; arg2=${arg2%/}

	case "$arg2" in
	*/*)	ro_opd=$arg2 ; ro_upg_port=`iport_from_origin $ro_opd` ;;
	*)	if pm_isdir "$pdb/$arg2" && $PKG_CMD 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
	upg_port="${upg_port:-$ro_upg_port}"
	unset arg2

	if [ -z "$ro_upg_port" ]; then
		$PKG_CMD query -a "%do" | grep -q "^$ro_opd$"
		if [ "$?" -eq 1 ]; then
			echo ''
			echo "===>>> The second argument to -o can be a package name,"
			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" ] && ! pm_isdir_pd "$portdir"; then
	find_moved_port $portdir $upg_port || no_valid_port
	[ -n "$moved_npd" ] || no_valid_port
	flavor=$(flavor_part "$moved_npd")
	export_flavor $flavor
	pm_isdir_pd "$moved_npd" || no_valid_port

	[ "$$" -eq "$PM_PARENT_PID" ] && parent_exit
	[ -z "$upg_port" ] && upg_port="$portdir"
	exec "$program" $ARGS -o $moved_npd $upg_port
	# NOT REACHED
fi

iport_from_pkgname () {
	local dir flavor pkgname

	dir=$(dir_part $1)
	flavor=$(flavor_part $1)
	pkgname=$(FLAVOR=$flavor pm_make -C "$pd/$dir" -V PKGNAME) &&
		$PKG_CMD query "%n-%v" "${pkgname%-*}"
}

if [ -z "$upg_port" -a -z "$REPLACE_ORIGIN" ]; then
	upg_port=`iport_from_origin ${portdir}` ||
		upg_port=`iport_from_pkgname $portdir` ||
		upg_port="$PM_OLD_ORIGIN"
	# || fail "XXX Cannot find installed port '$portdir'"
fi

if pm_islocked "$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 or the package is locked"
				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 or the package is locked, 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 or the package is locked, ignoring"
		echo ''
		safe_exit
	fi
fi

# START

if [ -z "$PM_INDEX_ONLY" ]; then
	pm_cd $(dir_part $pd/$portdir) || no_valid_port
	export_flavor $(flavor_part $portdir)
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" "$make_target"
elif [ -n "$FETCH_ONLY" -a -n "$PM_PACKAGES" ]; then
	update_pm_nu $portdir
fi

# Test for necessary privileges to actually install ports
[ -n "$NO_ACTION" ] || [ "$($PM_SU_CMD id -u)" = 0 ] || fail "Insufficient privileges to install ports (run as root or set PM_SU_CMD)"

# 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 "*|*" $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

	pm_isdir "$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}.pkg" ]; 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}.pkg
	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}.pkg
		if ! $PM_SU_CMD fetch $FETCH_ARGS -o $ppd ${sitepath}${1}.pkg 2>/dev/null; then
			pm_unlink_s ${ppd}/${1}.pkg
			$PM_SU_CMD fetch $FETCH_ARGS -o $ppd ${sitepath}${1}.pkg 2>/dev/null
		fi
	fi
}
	if [ -z "$PACKAGESITE" -a -z "$PM_PACKAGES_LOCAL" ]; then
		release=`uname -r`
		major_rel=${release%.*}
		arch=`uname -p`


		sitepath="${PACKAGEROOT:-"http://pkg.freebsd.org"}/FreeBSD:$major_rel:$arch/latest/All/"
		unset release major_rel arch
	else
		sitepath="${PACKAGESITE%/}"
		sitepath="${sitepath%Latest}"
		sitepath="${sitepath%All}"
	fi

#	sitepath="${sitepath%/}/${portdir%/*}/" # may be required for local packages

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

	if [ -n "$LOCAL_PACKAGEDIR" ]; then
		pm_v "===>>> ... checking: ${LOCAL_PACKAGEDIR}/All/${new_port}.pkg"
		if [ -r "${LOCAL_PACKAGEDIR}/All/${new_port}.pkg" ]; then
			local_package=${LOCAL_PACKAGEDIR}/All/${new_port}.pkg
			latest_pv=${local_package##*/}
		fi
		if [ -z "$latest_pv" -a -z "$PM_INDEX_ONLY" ]; then
			s=`pm_make -V PKGLATESTFILE`

			echo "===>>> ... checking: ${s}"
			if [ -r "${s}" ]; then
				local_package=${s}
				latest_pv=`readlink ${s}`
				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(8) 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%%\.pkg*}
	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
			case `$PKG_CMD 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
		case `$PKG_CMD 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
	export_flavor $(flavor_part $portdir)
	[ -z "$DONT_PRE_CLEAN" ] && { pm_make_s 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"

# Return flavor for named pkg (must be executed in port directory!)
pkg_flavor () {
	local pkg="$1" flavor starttime
	pm_make pretty-flavors-package-names | sed -ne 's!^\([A-Za-z0-9_]*\): *'$pkg'$!\1!p';
}
	export_flavor=$(pkg_flavor $new_port)
	if [ -n "$HIDE_BUILD" ] && [ -n "$(pm_make -V LICENSE)" ] && [ -z "$(pm_make -V DISABLE_LICENSES)" ]; then
		pm_make extract ask-license || fail "make extract ask-license failed for $portdir"
	fi
	if [ "$make_target" = "extract" -o "$make_target" = "patch" ]; then
		eval pm_make -DNO_DEPENDS $make_target $port_log_args || fail "make $make_target failed for $portdir"
		safe_exit
	fi
	starttime=$(date "+%s")
	eval pm_make build $port_log_args || fail "make build failed for $portdir"
	[ "$make_target" = "build" ] && safe_exit
	echo "===>>> Building the port required $(( `date "+%s"` - $starttime )) seconds"

	pm_sv Running make stage
	# Defining NO_DEPENDS ensures that we will control the installation
	# of the depends, not bsd.port.mk.
	eval pm_make -DNO_DEPENDS stage $port_log_args || fail "make stage failed for $portdir"
	[ "$make_target" = "stage" ] && safe_exit
else
	[ -z "$local_package" ] && {
		fetch_package $latest_pv || fail "Fetch for ${latest_pv}.pkg 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

	# the invocation of init_packages should be redundant, but pbu is not defined, without???
	[ -z "$NO_BACKUP" ] && init_packages && 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
		for file in `$PKG_CMD query %Fp $UPGRADE_PORT |
		    sort - $pm_mktemp_file | uniq -d`; do
			temp="${temp}$file "
		done
		if [ -n "$temp" ]; then
			if ! pm_isdir "$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 # <se> not always true for port moved to flavored version with no version update???
		# Delete any existing versions of the old port
		np_orphan=`$PKG_CMD query "%a" $ro_upg_port`
		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 [ "${np_orphan:-1}" -eq 1 ]; then
			np_orphan=`$PKG_CMD 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 () {
	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.
#	export_flavor $(flavor_part "$portdir")
	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 from: ${ppd}/${latest_pv}.pkg"
	if $PM_SU_CMD $PKG_CMD add --accept-missing --force ${ppd}/${latest_pv}.pkg; then
		if [ -n "$PM_DELETE_PACKAGES" ]; then
			pm_v "===>>> Deleting ${latest_pv}.pkg"
			pm_unlink_s ${ppd}/${latest_pv}.pkg
		fi
	else
		install_failed ${latest_pv}.pkg
	fi
fi

if [ "$was_locked" = 1 ]; then
	$PKG_CMD lock -qy "$new_port"
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" ] && pm_isdir "$LOCALBASE_COMPAT"; then
	unset files
	for file in `$PKG_CMD query %Fp $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 `pm_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 pm_isdir "$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

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_FORMAT:+PKG_COMPRESSION_FORMAT=$PACKAGE_FORMAT} 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
	flavor=$(flavor_part $portdir)
	for dir in $post_clean_l; do
		pm_v "===>>> Running 'make clean' for special build dependency $dir"
		(pm_make_s -C "$pd/$dir" ${flavor:+FLAVOR=$flavor} clean NOCLEANDEPENDS=ncd2 >/dev/null)&
	done
	pm_v "===>>> Running 'make clean' in the background"
	(pm_make_s ${flavor:+FLAVOR=$flavor} clean NOCLEANDEPENDS=ncd2 >/dev/null)&
	pm_v
fi
if [ -n "$ro_opd" ]; then
	echo "===>>> Updating dependency entry for $new_port in each dependent port"
	$PM_SU_CMD $PKG_CMD set -yo $ro_opd:$portdir
fi


if [ -n "$upg_port" ]; then
	upg_port=$(dir_part $upg_port)
	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"
[ -n "`$PKG_CMD 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.

Zerion Mini Shell 1.0