#!/bin/sh
###############################################################################
#
#  Package Frontend.
#
#  By: Sulev-Madis Silber <madis555 at hot dot ee>
#
#
###############################################################################

# Configuration file

CONFIG_FILE=%PREFIX%/etc/pkgfe.conf


# Paths

PORTS_PATH=${PORTSDIR:-/usr/ports}

PKGDB_PATH=${PKG_DBDIR:-/var/db/pkg}

TEMP_DIR=${TMPDIR:-/tmp}


# Miscellaneous

PAGER_PROGRAM=${PAGER:-less}


###############################################################################

#
# Returns program name without path.
#
prog()
{
	basename "$0"
}


#
# Returns "s" if value is not "1".
#
plural()
{
	if [ ! "$1" ]
	then
		ierror 'plural: invalid parameters'
	fi
	
	
	if [ "$1" -ne 1 ]
	then
		echo s
	fi
}


#
# Removes "'" from a stream.
#
makesafe()
{
	tr -d "'"
}


#
# Removes file.
#
unlink_file()
{
	if [ ! "$1" ]
	then
		ierror 'unlink_file: invalid parameters'
	fi
	
	
	if [ -f "$1" ]
	then
		rm -f "$1"
	fi
}


#
# Prints error and exits.
#
error()
{
	if [ ! "$1" ]
	then
		ierror 'error: invalid parameters'
	fi
	
	
	echo "`prog`: $1" >&2
	
	cleanexit 1
}


#
# Prints internal error and exits.
#
ierror()
{
	if [ ! "$1" ]
	then
		ierror 'ierror: invalid parameters'
	fi
	
	
	echo "`prog`: internal error: $1" >&2
	
	cleanexit 1
}


#
# Prints error.
#
notice()
{
	if [ ! "$1" ]
	then
		ierror 'notice: invalid parameters'
	fi
	
	
	echo "`prog`: $1" >&2
}


#
# Prints usage and exits.
#
usage()
{
	if [ ! "$1" ]
	then
		ierror 'usage: invalid parameters'
	fi
	
	
	echo "usage: `prog` $1" >&2
	
	cleanexit 1
}


#
# Does clean exit.
#
cleanexit()
{
	del_tempfile
	unlink_file "$lock_file"
	
	exit ${1:-0}
}


#
# Prints error when command fails.
#
exitcode()
{
	if [ ! "$1" -o ! "$2" ]
	then
		ierror 'exitcode: invalid parameters'
	fi
	
	
	echo
	error "command '$1' failed with exit code $2"
	echo
}


#
# Show command before executing it.
#
showcmd()
{
	if [ ! "$1" ]
	then
		ierror 'showcmd: invalid parameters'
	fi
	
	
	echo
	echo "> $1"
}


#
# Checks boolean configuration paramaters.
#
checkyesno()
{
	if [ ! "$1" ]
	then
		ierror 'checkyesno: invalid parameters'
	fi
	
	
	eval local value=\$$1
	
	
	case "$value"
	in
		[Yy][Ee][Ss]|[Tt][Rr][Uu][Ee]|[Oo][Nn]|1)
			
			unset value
			
			return 0
			;;
		
		[Nn][Oo]|[Ff][Aa][Ll][Ss][Ee]|[Oo][Ff][Ff]|0)
			
			unset value
			
			return 1
			;;
		
		*)
			error "variable '$1' is not set properly in '$CONFIG_FILE'"
			;;
	esac
}


#
# Checks if command is failed
# (exit code is greater than zero).
#
cmd_failed()
{
	if [ "$1" -gt 0 ]
	then
		return 0
	else
		return 1
	fi
}


#
# Creates temporary file.
#
make_tempfile()
{
	touch "$temp_file"
	
	if cmd_failed $?
	then
		error "cannot create temp file '$temp_file'"
	fi
}


#
# Deletes temporary file.
#
del_tempfile()
{
	unlink_file "$temp_file"
}


#
# Shows menu or checklist using dialog(1).
#
show_dialog()
{
	if [ $# -ne 3 -a $# -ne 4 ]
	then
		ierror 'show_dialog: invalid parameters'
	fi
	
	
	local name text options type stderr_file exitcode selected_options
	
	
	name=$1
	text=$2
	options=$3
	
	type=checklist
	stderr_file="$temp_file"
	
	
	case $4
	in
		''|checklist)
			
			make_tempfile
			;;
		
		menu)
			type=$4
			
			stderr_file=/dev/null
			;;
		
		*)
			ierror 'show_dialog: invalid type'
			;;
	esac
	
	
	if [ ! "$name" ]
	then
		ierror 'show_dialog: name is empty'
		
	elif [ ! "$text" ]
	then
		ierror 'show_dialog: text is empty'
		
	elif [ ! "$options" ]
	then
		ierror 'show_dialog: options is empty'
	fi
	
	
	eval "dialog --title '`prog`: $name'"\
	"--$type '\n$text\n'"\
	"-1 -1 $dialog_list_rows"\
	"$options"\
	"2> '$stderr_file'"
	
	
	exitcode=$?
	
	eval selopt_${name}_exitcode=\$exitcode
	
	unset text options stderr_file exitcode
	
	
	if [ "$type" = checklist ]
	then
		selected_options=`sed 's|"||g' < "$temp_file"`
		
		del_tempfile
		
		
		eval selopt_${name}_values="\$selected_options"
		
		unset selected_options
	fi
	
	unset name type
}


#
# Shows confirm dialog.
#
show_confirm()
{
	if [ ! "$1" -o ! "$2" ]
	then
		ierror 'show_confirm: invalid parameters'
	fi
	
	
	local type package comment packages count dialog_options confirm_message cancel_message
	
	
	type=$1
	packages=$2
	
	
	for package in $packages
	do
		count=$(($count + 1))
		
		
		comment=' '
		
		if [ "$type" = upgrade ]
		then
			if checkyesno upgrade_show_new_version
			then
				comment=`grep "$package" "$status_file" | awk '{print $2}'`
			fi
		fi
		
		dialog_options="$dialog_options '$package' '$comment'"
	done
	
	unset package comment packages
	
	
	case $type
	in
		upgrade)
			confirm_message="Upgrade $count package`plural $count`?"
			
			cancel_message='Upgrade cancelled'
			;;
		
		deinstall)
			confirm_message="Deinstall $count package`plural $count`?\nARE YOU SURE?"
			
			cancel_message='Deinstall cancelled'
			;;
		
		install)
			confirm_message="Install $count package`plural $count`?"
			
			cancel_message='Install cancelled'
			;;
		
		*)
			ierror 'show_confirm: invalid type'
			;;
	esac
	
	unset type count
	
	
	show_dialog confirm "$confirm_message" "$dialog_options" menu
	
	unset dialog_options confirm_message
	
	
	if cmd_failed $selopt_confirm_exitcode
	then
		echo
		echo "$cancel_message"
		echo
		
		cleanexit
	fi
	
	unset cancel_message
}


#
# Shows packages before executing
# install, upgrade or deinstall.
#
show_packages()
{
	if [ ! "$1" -o ! "$2" ]
	then
		ierror 'show_packages: invalid parameters'
	fi
	
	
	local package
	
	
	echo
	echo "$1:"
	echo
	
	shift
	
	
	for package in $*
	do
		echo "$package"
	done
	
	
	echo
	
	unset package
}


#
# Shows package deinstall dialog.
#
package_deinstall()
{
	local packages command exitcode
	
	
	packages=$1
	
	
	if [ ! "$packages" ]
	then
		echo
		echo 'No packages selected for deinstall'
		echo
		
		cleanexit
	fi
	
	
	show_confirm deinstall "$packages"
	
	
	command="${root_command_prefix}pkg_deinstall $packages"
	
	
	if ! checkyesno enable_real_deinstall
	then
		cat <<- EOF
		
		Execute that manually:
		
		$command
		
		EOF
		
		cleanexit
	fi
	
	
	show_packages Deinstalling $packages
	
	unset packages
	
	
	showcmd "$command"
	
	$command
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		exitcode "$command" $exitcode
	else
		unset command exitcode
		
		if checkyesno listup_after_deinstall
		then
			echo
			do_list
		fi
	fi
	
	
	cleanexit
}


#
# Command:
#  shows help. for more info, look EOF.
#
do_help()
{
	cat <<- EOF
	
	Help of `prog` is now moved to man page,
	see pkgfe(8)
	
	EOF
	
	cleanexit
}


#
# Command:
#  shows list of outdated packages.
#
do_list()
{
	local command exitcode count
	
	
	make_tempfile
	
	
	command="${root_command_prefix}portversion -vl <"
	
	showcmd "$command"
	
	$command > "$temp_file"
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		del_tempfile
		
		exitcode "$command" $exitcode
	fi
	
	unset command exitcode
	
	
	sed 's|<||; s|needs updating (port has ||; s|) *$||; s|) (| |' \
	< "$temp_file" | \
	makesafe > "$status_file"
	
	del_tempfile
	
	
	if ! checkyesno ignore_held
	then
		make_tempfile
		
		cat "$status_file" > "$temp_file"
		
		grep -v '\[held\]' < "$temp_file" > "$status_file"
		
		del_tempfile
	fi
	
	
	count=`wc -l "$status_file" | awk '{print $1}'`
	
	echo
	echo '-----------------------------------'
	echo "Found $count outdated package`plural $count`"
	echo '-----------------------------------'
	echo
	
	
	if [ "$count" -eq 0 -a "$1" = exit-if-none ]
	then
		cleanexit
	fi
	
	unset count
}


#
# Command:
#  updates ports tree using csup(1).
#
do_csup()
{
	local command exitcode
	
	
	check_supfile
	
	
	command="${root_command_prefix}csup $csup_args $csup_supfile"
	
	showcmd "$command"
	
	$command
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		exitcode "$command" $exitcode
	fi
	
	
	command="${root_command_prefix}portsdb -Fu"
	
	echo
	showcmd "$command"
	
	$command
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		exitcode "$command" $exitcode
	fi
	
	unset command exitcode
	
	
	echo
	do_list
}


#
# Command:
#  updates ports tree using portsnap(8).
#
do_portsnap()
{
	local command exitcode
	
	
	command="${root_command_prefix}portsnap fetch"
	
	if ! checkyesno old_portsnap
	then
		command="$command update"
	fi
	
	showcmd "$command"
	
	$command
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		exitcode "$command" $exitcode
	fi
	
	
	if checkyesno old_portsnap
	then
		command="${root_command_prefix}portsnap update"
		
		echo
		showcmd "$command"
		
		$command
		
		
		exitcode=$?
		
		if cmd_failed $exitcode
		then
			exitcode "$command" $exitcode
		fi
	fi
	
	
	command="${root_command_prefix}portsdb -u"
	
	echo
	showcmd "$command"
	
	$command
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		exitcode "$command" $exitcode
	fi
	
	unset command exitcode
	
	
	echo
	do_list
}


#
# Command:
#  fixes package database.
#
do_fixdb()
{
	local command exitcode
	
	
	command="${root_command_prefix}pkgdb -F"
	
	showcmd "$command"
	
	$command
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		exitcode "$command" $exitcode
	fi
	
	unset command exitcode
	
	
	echo
	
	cleanexit
}


#
# Command:
#  does search in ports tree.
#
do_find()
{
	local search_string type
	
	
	search_string=$1
	
	type=name
	
	
	case $search_string
	in
		name|key)
			search_string=$2
			
			type=$1
			;;
	esac
	
	
	if [ ! "$search_string" ]
	then
		usage 'find [name|key] [regex]'
	fi
	
	
	showcmd "cd $PORTS_PATH && make search $type=$search_string"
	
	cd "$PORTS_PATH" || cleanexit 1
	
	
	make_tempfile
	
	make search "$type=$search_string" > "$temp_file"
	
	
	if [ ! -s "$temp_file" ]
	then
		del_tempfile
		
		echo
		error "no matches for '$search_string'"
	fi
	
	unset search_string type
	
	
	clear
	
	"$PAGER_PROGRAM" "$temp_file"
	
	del_tempfile
	
	
	cleanexit
}


#
# Command:
#  does "make config" in port's directory.
#
do_config()
{
	local portpath
	
	
	portname=$1
	
	
	if [ ! "$portname" ]
	then
		usage 'c [port]'
	fi
	
	
	portpath=`whereis -sB "$PORTS_PATH" -f "$portname" | cut -d ' ' -f 2`
	
	
	if [ ! -d "$portpath" ]
	then
		error "port '$portname' not found"
	fi
	
	
	showcmd "cd $portpath && make config"
	
	cd "$portpath" || cleanexit 1
	
	${root_command_prefix}make config
	
	unset portpath
	
	
	cleanexit
}


#
# Command:
#  does search in ports tree
#  and shows install dialog.
#
do_find_install()
{
	local search_string index_file name comments count dialog_options
	
	
	search_string=$1
	
	index_file="$PORTS_PATH/INDEX-`uname -r | cut -d . -f 1`"
	
	
	if [ ! -f "$index_file" ]
	then
		if [ -f "$PORTS_PATH/INDEX" ]
		then
			index_file="$PORTS_PATH/INDEX"
		else
			error "no valid INDEX file found under '$PORTS_PATH'"
		fi
	fi
	
	
	if [ ! "$search_string" ]
	then
		usage 'findi [regex]'
	fi
	
	
	make_tempfile
	
	
	cut -d '|' -f 1,4 "$index_file" | makesafe | grep -iE -- "$search_string" | \
	awk -F '|' '{print $1" "(length($2) > '$findi_description_length' ? substr($2, 0, '$findi_description_length')"..." : $2)}' \
	> "$temp_file"
	
	unset index_file
	
	
	if [ ! -s "$temp_file" ]
	then
		del_tempfile
		
		error "no packages matching '$search_string' found"
	fi
	
	unset search_string
	
	
	count=`wc -l "$temp_file" | awk '{print $1}'`
	
	echo
	echo "$count result`plural $count` found. Generating dialog..."
	echo
	
	
	while read name comments
	do
		dialog_options="$dialog_options '$name' '$comments' OFF"
	done \
	< "$temp_file"
	
	del_tempfile
	
	unset name comments
	
	
	show_dialog find "Found $count package`plural $count`.\nSelect one`plural $count` you want to install" "$dialog_options"
	
	unset count dialog_options
	
	
	if [ ! "$selopt_find_values" ]
	then
		echo
		echo 'No packages selected for install'
		echo
		
		cleanexit
	fi
	
	
	show_confirm install "$selopt_find_values"
	
	
	do_portinstall_portupgrade portinstall $selopt_find_values
}


#
# Command:
#  searches for local packages.
#
do_ls()
{
	local search_string=$1
	
	
	if [ ! "$search_string" ]
	then
		usage 'ls [regex]'
	fi
	
	
	ls -1 "$PKGDB_PATH" | \
	grep -v '^pkgdb\.' | \
	grep -iE -- "$search_string"
	
	
	if cmd_failed $?
	then
		error "no packages matching '$search_string' found"
	fi
	
	unset search_string
	
	
	cleanexit
}


#
# Command:
#  deinstalls not required packages.
#
do_notreq()
{
	local old_wd name count dialog_options
	
	
	old_wd=`pwd`
	
	cd "$PKGDB_PATH" || cleanexit 1
	
	
	for name in `ls -1 | grep -v '^pkgdb\.' | makesafe`
	do
		count=$(($count + 1))
		
		
		if [ ! -f $name/+REQUIRED_BY ]
		then
			dialog_options="$dialog_options '$name' 'no +REQUIRED_BY' OFF"
			
		elif [ ! -s $name/+REQUIRED_BY ]
		then
			dialog_options="$dialog_options '$name' 'empty +REQUIRED_BY' OFF"
		fi
	done
	
	cd "$old_wd" || cleanexit 1
	
	unset old_wd name
	
	
	show_dialog notrequired "Found $count not required package`plural $count`\nSelect one`plural $count` you want to deinstall" "$dialog_options"
	
	unset count dialog_options
	
	
	package_deinstall "$selopt_notrequired_values"
}


#
# Command:
#  deinstalls packages.
#
do_deinst()
{
	local old_wd name count dialog_options
	
	
	old_wd=`pwd`
	
	cd "$PKGDB_PATH" || cleanexit 1
	
	
	for name in `ls -1 | grep -v '^pkgdb\.' | makesafe`
	do
		count=$(($count + 1))
		
		if [ -f $name/+REQUIRED_BY ]
		then
			dialog_options="$dialog_options '$name' 'Required by others' OFF"
		else
			dialog_options="$dialog_options '$name' ' ' OFF"
		fi
	done
	
	cd "$old_wd" || cleanexit 1
	
	unset old_wd name
	
	
	show_dialog deinstall "Found $count package`plural $count`.\nSelect one`plural $count` you want to deinstall" "$dialog_options"
	
	unset count dialog_options
	
	
	package_deinstall "$selopt_deinstall_values"
}


#
# Command:
#  updates portaudit database.
#
do_padb()
{
	local command exitcode
	
	
	command="${root_command_prefix}portaudit -Fd"
	
	showcmd "$command"
	
	$command
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		exitcode "$command" $exitcode
	fi
	
	unset command exitcode
	
	
	echo
}


#
# Command:
#  shows upgrade dialog.
#
do_upgrade()
{
	local name comments count dialog_options
	
	
	if [ ! -s "$status_file" ]
	then
		do_list exit-if-none
	fi
	
	
	count=`wc -l "$status_file" | awk '{print $1}'`
	
	
	while read name comments
	do
		dialog_options="$dialog_options '$name' '< $comments' OFF"
	done \
	< "$status_file"
	
	unset name comments
	

	show_dialog list "Found $count outdated package`plural $count`\nSelect one`plural $count` you want to upgrade" "$dialog_options"
	
	unset count dialog_options
	
	
	if [ ! "$selopt_list_values" ]
	then
		echo
		echo 'No packages selected for upgrade'
		echo
		
		cleanexit
	fi
	
	
	show_confirm upgrade "$selopt_list_values"
	
	
	do_portinstall_portupgrade portupgrade $selopt_list_values
}


#
# Command:
#  runs portinstall(1) or portupgrade(1) with
#  verbose mode and additional arguments.
#
do_portinstall_portupgrade()
{
	local program message command exitcode
	
	
	program=$1
	
	shift
	
	
	case $program
	in
		portinstall)
			message=Installing
			;;
		
		portupgrade)
			message=Upgrading
			;;
		
		*)
			ierror 'do_portinstall_portupgrade: invalid program'
			;;
	esac
	
	
	if [ ! "$*" ]
	then
		ierror 'do_portinstall_portupgrade: arguments cannot be empty'
	fi
	
	
	show_packages $message $*
	
	
	if checkyesno update_portaudit_db
	then
		do_padb
	fi
	
	
	command="$root_command_prefix$program $portupgrade_args $*"
	
	showcmd "$command"
	
	$command
	
	
	exitcode=$?
	
	if cmd_failed $exitcode
	then
		exitcode "$command" $exitcode
		
	elif [ $program = portupgrade ]
	then
		if checkyesno listup_after_upgrade
		then
			echo
			do_list
		fi
	fi
	
	unset program command exitcode
	
	
	cleanexit
}


#
# Command:
#  checks for existence of required programs.
#
do_checkbinaries()
{
	local binary exitcode
	
	
	exitcode=0
	
	
	echo 'Checking for existence of binaries we need...'
	echo
	
	
	for binary in portupgrade portinstall portversion \
	dialog csup portsdb pkgdb portaudit pkg_deinstall \
	"$PAGER_PROGRAM" sed grep cat touch id uname cut \
	portsnap awk wc whereis
	do
		
		which "$binary" > /dev/null
		
		
		if cmd_failed $?
		then
			notice "$binary: program not found"
			
			exitcode=1
		else
			echo "$binary: OK"
		fi
	done
	
	unset binary
	
	
	cleanexit $exitcode
}


#
# Command:
#  shows configuration.
#
do_showconfig()
{
	local default
	
	
	if [ ! -f "$CONFIG_FILE" ]
	then
		notice "configuration file '$CONFIG_FILE' is not found"
		
		default=1
		
	elif [ ! "$root_command_prefix" -a ! -r "$CONFIG_FILE" ]
	then
		notice "configuration file '$CONFIG_FILE' is not readable"
		
		default=1
	fi
	
	
	echo
	
	if [ "$default" ]
	then
		echo 'using default configuration:'
	else
		echo "$CONFIG_FILE:"
	fi
	
	unset default
	
	
	cat <<- EOF
	---------------------------------------------------------------------
	
	portupgrade_logdir="$portupgrade_logdir"
	
	portupgrade_args="$portupgrade_args"
	
	csup_supfile="$csup_supfile"
	
	csup_args="$csup_args"
	
	root_command_prefix="$root_command_prefix"
	
	status_file="$status_file"
	
	lock_file="$lock_file"
	
	temp_file="$temp_file"
	
	dialog_list_rows="$dialog_list_rows"
	
	findi_description_length="$findi_description_length"
	
	listup_after_upgrade="$listup_after_upgrade"
	
	ignore_held="$ignore_held"
	
	update_portaudit_db="$update_portaudit_db"
	
	enable_real_deinstall="$enable_real_deinstall"
	
	listup_after_deinstall="$listup_after_deinstall"
	
	old_portsnap="$old_portsnap"
	
	---------------------------------------------------------------------
	EOF
	
	
	cleanexit
}


#
# Checks boolean variables in configuration file.
#
check_boolean_variables()
{
	local variable
	
	
	for variable in \
	listup_after_upgrade \
	ignore_held \
	update_portaudit_db \
	enable_real_deinstall \
	listup_after_deinstall \
	old_portsnap \
	upgrade_show_new_version
	do
		checkyesno $variable
	done
	
	unset variable
}


#
# Checks numeric variables in configuration file.
#
check_numeric_variables()
{
	local variable value
	
	
	for variable in \
	dialog_list_rows \
	findi_description_length
	do
		eval value=\$$variable
		
		case "$value"
		in
			[0-9]|[0-9][0-9])
				;;
			
			*)
				error "variable '$variable' has invalid or not numeric value in '$CONFIG_FILE'"
				;;
		esac
	done
	
	unset variable value
}


#
# Checks (and creates) status file.
#
check_statusfile()
{
	if [ ! -f "$status_file" ]
	then
		touch "$status_file"
		
		if cmd_failed $?
		then
			error "cannot create status file '$status_file'"
		fi
	fi
}


#
# Checks csup supfile.
#
check_supfile()
{
	if [ ! "$csup_supfile" ]
	then
		error "please define csup_supfile in '$CONFIG_FILE'"
		
	elif [ ! -f "$csup_supfile" ]
	then
		error "supfile '$csup_supfile' is not found"
		
	elif [ ! "$root_command_prefix" -a ! -r "$csup_supfile" ]
	then
		error "supfile '$csup_supfile' is not readable"
	fi
}


#
# Checks portupgrade log directory.
#
check_portupgrade_logdir()
{
	if [ ! "$portupgrade_logdir" ]
	then
		return 0
	fi
	
	
	if [ ! -d "$portupgrade_logdir" ]
	then
		notice "portupgrade log directory '$portupgrade_logdir' is not found"
		
	elif [ ! "$root_command_prefix" -a ! -w "$portupgrade_logdir" ]
	then
		notice "portupgrade log directory '$portupgrade_logdir' is not writable"
	else
		return 0
	fi
	
	
	cat <<- EOF
	
	If you don't want logging,
	comment out following varibles in $CONFIG_FILE:
	
	portupgrade_logdir
	portupgrade_args
	EOF
	
	cleanexit 1
}


#
# Checks (and creates) lock file.
#
check_lockfile()
{
	if [ -f "$lock_file" ]
	then
		notice "lock file '$lock_file' exists"
		
		cat <<- EOF
		
		This probably means that you have
		another `prog` session running.
		If there are no active sessions,
		then it's probably a result of
		unfinished session. In this case,
		you must delete the file manually,
		before you can run `prog` again.
		EOF
		
		cleanexit 1
	fi
	
	
	touch "$lock_file"
	
	if cmd_failed $?
	then
		error "cannot create lock file '$lock_file'"
	fi
}


#
# Checks for privileges.
#
check_privs()
{
	if [ `id -u` -gt 0 ]
	then
		if [ ! "$root_command_prefix" ]
		then
			notice 'please switch to root'
			
			cat <<- EOF
			
			Alternatively, define root_command_prefix
			in $CONFIG_FILE
			EOF
			
			cleanexit 1
		fi
	else
		root_command_prefix=
	fi
}


###############################################################################

if [ `uname -s` != FreeBSD ]
then
	error 'requires FreeBSD'
fi


if [ -f "$CONFIG_FILE" -a -r "$CONFIG_FILE" ]
then
	. "$CONFIG_FILE"
fi


: ${portupgrade_logdir=""}
: ${portupgrade_args="-v"}
: ${csup_supfile=""}
: ${csup_args="-L 2"}
: ${root_command_prefix="sudo "}
: ${status_file="$TEMP_DIR/`prog`.status"}
: ${lock_file="$TEMP_DIR/`prog`.lock"}
: ${temp_file="$TEMP_DIR/`prog`.tmp"}
: ${dialog_list_rows="10"}
: ${findi_description_length="26"}
: ${listup_after_upgrade="YES"}
: ${ignore_held="YES"}
: ${update_portaudit_db="YES"}
: ${enable_real_deinstall="NO"}
: ${listup_after_deinstall="YES"}
: ${old_portsnap="NO"}
: ${upgrade_show_new_version="NO"}


check_boolean_variables

check_numeric_variables

check_privs


check_portupgrade_logdir


check_lockfile

check_statusfile


trap 'cleanexit 1' 1 2 15 30 31


###############################################################################

case $1
in
	'')
		do_upgrade
		;;
	
	listup|list)
		
		do_list
		cleanexit
		;;
	
	cvsup|cvs|csup)
		
		do_csup
		cleanexit
		;;
	
	portsnap|snap)
		
		do_portsnap
		cleanexit
		;;
	
	all)
		do_csup
		do_upgrade
		;;
	
	snap+run)
		
		do_portsnap
		do_upgrade
		;;
	
	listup+run|list+run)
		
		do_list
		do_upgrade
		;;
	
	fixdb|fix)
		
		do_fixdb
		;;
	
	find|portfind)
		
		shift
		do_find "$1" "$2"
		;;
	
	config|conf|c)
		
		shift
		do_config "$1"
		;;
	
	findi|findv)
		
		shift
		do_find_install "$1"
		;;
	
	ls|lspkg)
		
		shift
		do_ls "$1"
		;;
	
	chkreq|notreq|noreq)
		
		do_notreq
		;;
	
	deinst|deins)
		
		do_deinst
		;;
	
	padb)
		do_padb
		cleanexit
		;;
	
	install|i)
		
		shift
		
		if [ ! "$*" ]
		then
			usage 'i [port]'
		fi
		
		do_portinstall_portupgrade portinstall $*
		;;
	
	upgrade|u)
		
		shift
		
		if [ ! "$*" ]
		then
			usage 'u [port]'
		fi
		
		do_portinstall_portupgrade portupgrade $*
		;;
	
	chkbin)
		do_checkbinaries
		;;
	
	showconf)
		
		do_showconfig
		;;
	
	help)
		do_help
		;;
	
	*)
		error "invalid parameter '$1'"
		;;
esac

cleanexit
