head	1.3;
access;
symbols
	RELEASE-1_4:1.2.0.2
	GENTOO_1_4_SNAP_2003010800:1.2;
locks; strict;
comment	@# @;


1.3
date	2003.08.15.12.50.15;	author lanius;	state dead;
branches;
next	1.2;

1.2
date	2002.07.03.23.46.03;	author karltk;	state Exp;
branches;
next	1.1;

1.1
date	2002.06.24.23.02.32;	author karltk;	state Exp;
branches;
next	;


desc
@@


1.3
log
@moved to app-portage
@
text
@#!/bin/bash
# useflag v0.3.1
# Script to help users manage USE flags in Gentoo Linux
#
# Distributed under the terms of the GNU General Public License, v2 or later
# Author: Michael Thompson <psionix@@grandecom.net>, (c) 2002

run_name=`basename $0`
use_desc="/usr/portage/profiles/use.desc"
make_conf_dir="/etc"
make_conf="${make_conf_dir}/make.conf"
# Home directory was chosen as the use of /tmp allows for symlink attacks
make_temp="${HOME}/use.make.conf.tmp"
use_cache_parent="/var/cache"
use_cache_dir="${use_cache_parent}/use_desc"
use_cache="${use_cache_dir}/use.cache"
lock_cache="${use_cache_dir}/lock.cache"
changes="0"


# Get flag description
# parm1 = Use flag to get description of
do_get_desc() {
	local parm1=$1
	# Strip the comments and find the flag.
	local out_get_desc=`grep -v "#" ${use_desc} | grep -w -e "${parm1} -"`
	if [ "${out_get_desc}" = "" ]; then
		local lcl_avail=`grep -v "#" ${use_desc} | cut -d ' ' -f1 | \
			grep -w -e "${parm1}"`
		if [ "${lcl_avail}" != "" ]; then
			echo "${parm1} - No description available."
		else
			echo "!!! ${parm1} does not exist."
		fi
	else
		echo "${out_get_desc}"
	fi
}

# Get the contents of the USE variable
# parm1 controls whether or not to include the '-' with each flag
do_get_make() {
	local parm1=$1
	# Get the USE flags from make.conf
	# using `source` now instead of brain-damaged grepping
	source ${make_conf}
	local get_make_out=${USE}
	# If called with "nodashes", then strip the leading dashes
	if [ "${parm1}" = "nodashes" ]; then
		for tr_sucks in ${get_make_out}; do
			if [ "${tr_sucks:0:1}" = "-" ]; then
				local tr_out="${tr_out} ${tr_sucks:1}"
			else
				local tr_out="${tr_out} ${tr_sucks}"
			fi
		done
		get_make_out="${tr_out}"
	fi
	echo "${get_make_out}"
}

# Yes, it's pointless.  But it could be used more than once in the future
# so it's a function.
# Gets the master list of available USE flags from use.desc
do_get_avail() {
	grep -v "#" ${use_desc} | cut -d " " -f1 | tr '\n' ' '
}

# Get deprecated flags.
# parm1 = flag to check for deprecation
# parm2 = list of available flags
do_get_depr() {
	local parm1=$1
	local parm2=${@@:2}
	# This next var can't be local
	get_depr_tmp=`echo "${parm2}" | tr ' ' '\n' | grep -x -e "${parm1}"`
	local ret_code=$?
	if [ "${ret_code}" != "0" ]; then
		echo "${parm1}" | tr '\n' ' '
	fi
}

# Removes a USE flag from make.conf
# parm1 = flag to remove
# use_rm_out = list of available flags
do_use_rm() {
	local parm1=$1
	local use_rm_out=${@@:2}
	# Strip matching USE flags.  Yes, this is ugly, I know.
	use_rm_out=`echo "${use_rm_out}" | tr ' ' '\n' | \
		grep -x -v -e "${parm1}" | tr '\n' ' '`
	# Also strip the inverse. Even uglier...
	if [ "${parm1:0:1}" = "-" ]; then
		use_rm_out=`echo "${use_rm_out}" | tr ' ' '\n' | \
			grep -x -v -e "${parm1:1}" | tr '\n' ' '`
	else
		use_rm_out=`echo "${use_rm_out}" | tr ' ' '\n' | \
			grep -x -v -e "-${parm1}" | tr '\n' ' '`
	fi
	echo "${use_rm_out}"
}

# Adds a USE flag to make.conf
# parm1 = flag to add
# use_add_out = list of available flags
do_use_add() {
	local parm1=$1
	local use_add_out=${@@:2}
	# First strip existing flags (matching or inverse), then add.
	# This is not the best way to do this.  Better would be to replace a
	#  flag if it already exists.  That turned out to be a real PITA.
	#  Maybe in a later version...
	use_add_out=`do_use_rm ${parm1} ${use_add_out}`
	use_add_out="${use_add_out} ${parm1}"
	echo "${use_add_out}"
}

# Adds a flag to the locked flag cache
# Pass list of flags to lock as parameter.
do_lock_flags() {
	local flag_list=$@@
	# Merge the new list of flags flags that are already locked.
	if [ -r ${lock_cache} ]; then
		local lock_old=`cat ${lock_cache}`
	fi
	flag_list="${lock_old} ${flag_list}"
	# Remove duplicates.
	echo "${flag_list}" | tr ' ' '\n' | sort | uniq | tr '\n' ' '
}

# Writes the list of locked flags to the cache file
# Pass list of flags to write as parameter.
do_write_lock() {
	local write_flags=$@@
	if [ -r ${make_conf} ]; then
		local make_prune=`do_get_make nodashes`
	else
		do_report_err ${make_conf} read
	fi
	# Be sure and remove any locked flags that no longer exist in USE.
	for prune in ${write_flags}; do
		local prune_test=`do_get_depr ${prune} ${make_prune}`
		if [ "$prune_test" = "" ]; then
			local new_cache="${prune} ${new_cache}"
		fi
	done
	if [ -w ${use_cache_parent} ]; then
		mkdir -p ${use_cache_dir}
		chmod 700 ${use_cache_dir}
		echo "${new_cache}" > ${lock_cache}
		chmod 600 ${lock_cache}
	else
		do_report_err ${lock_cache} write
	fi
}

# Writes new USE variable to make.conf
# Pass new list of USE flags as parameter.
do_write_make() {
	local use_write="USE=\"$@@\""
	local old_use="USE=\"`do_get_make dashes`\""
	if [ -w ${make_conf} ] && [ -w ${make_conf_dir} ]; then
		local use_write="USE=\"$@@\""
		local old_use=`grep "USE=\"" ${make_conf} | grep -v "#"`
		local start_line=`grep -n "USE=\"" ${make_conf} | \
			grep -v "#" | cut -d ":" -f1`
		if [ "${old_use:0-1}" != "\\" ]; then
			sed -e "s/${old_use}/${use_write}/" ${make_conf} > \
				${make_temp}
		else
			sed -e "s/${old_use}\\/${use_write}/" ${make_conf} > \
				${make_temp}
		fi
		let start_line="${start_line} + 1"
		if [ "${old_use:0-1}" != "\"" ]; then
			del_line=`head -n ${start_line} ${make_temp} | \
				tail -n 1`
			until [ "${del_line:0-1}" != "\\" ]; do
				let del_length="${#del_line} - 1"
				del_line="${del_line:0:${del_length}}"
				grep -v -w "${del_line}" ${make_temp} > \
					${make_temp}.2
				mv ${make_temp}.2 ${make_temp}
				del_line=`head -n ${start_line} \
					${make_temp} | tail -n 1`
			done
			let del_length="${#del_line} - 1"
			del_line="${del_line:0:${del_length}}"
			grep -v -x "${del_line}\"" ${make_temp} > \
				${make_temp}.2
			mv ${make_temp}.2 ${make_temp}
		fi
		mv ${make_temp} ${make_conf}
	else
		do_report_err ${make_conf} write
	fi
}

# Reports a read/write error and exits
# parm1 = File to report on
# parm2 = read, write, etc
do_report_err() {
	local parm1=$1
	local parm2=$2
	if [ "${parm2}" = "read" ]; then
		echo "!!! Could not read ${parm1}"
		echo -n "!!! Verify that file exists and that you have "
		echo "appropriate permissions."
	elif [ "${parm2}" = "write" ]; then
		echo "!!! Could not write ${parm1}"
		echo "!!! Got root?"
	elif [ "${parm2}" = "nolock" ]; then
		echo "!!! Could not read ${parm1}"
		echo -n "!!! You have no locked flags or you have "
		echo "insufficient permissions."
	fi
	exit 1
}


# The main section of the script
# desc:
# This is the feature for getting USE descriptions.
if [ "$1" = "desc" ] || [ "$1" = "-i" ]; then
	if [ -r ${use_desc} ]; then
		for flag in ${@@:2}; do
			do_get_desc ${flag}
		done
	else
		do_report_err ${use_desc} read
	fi

# show:
# This is the feature for showing the contents of the USE variable.
elif [ "$1" = "show" ] || [ "$1" = "-s" ]; then
	if [ -r ${make_conf} ]; then
		do_get_make dashes
	else
		do_report_err ${make_conf} read
	fi

# del:
# This is the feature for removing a USE flag.
elif [ "$1" = "del" ] || [ "$1" = "-d" ]; then
	if [ -r ${make_conf} ]; then
		make_use=`do_get_make dashes`
	else
		do_report_err ${make_conf} read
	fi
	for flag in ${@@:2}; do
		# Strip leading dashes.
		if [ "${flag:0:1}" = "-" ]; then
			flag="${flag:1}"
		fi
		del_test1=`do_get_depr ${flag} ${make_use}`
		del_test2=`do_get_depr -${flag} ${make_use}`
		if [ "${del_test1}" = "" ] || [ "${del_test2}" = "" ]; then
			changes="1"
			make_use=`do_use_rm ${flag} ${make_use}`
		else
			echo "!!! ${flag} is not in your USE variable."
		fi
	done
	if [ "${changes}" != "0" ]; then
		do_write_make ${make_use}
		# Prune deleted USE flags from lock cache
		lock_flags=`do_lock_flags $2`
		do_write_lock ${lock_flags}
	fi

# add:
# This is the feature for explicitly enabling or disabling a USE flag.
elif [ "$1" = "add" ] || [ "$1" = "-a" ]; then
	if [ -r ${make_conf} ]; then
		make_use=`do_get_make dashes`
	else
		do_report_err ${make_conf} read
	fi
	for flag in ${@@:2}; do
		changes="1"
		make_use=`do_use_add ${flag} ${make_use}`
	done
	if [ "${changes}" != "0" ]; then
		do_write_make ${make_use}
	fi

# lock:
# This is the feature to lock a deprecated USE flag to prevent removal
elif [ "$1" = "lock" ] || [ "$1" = "-l" ]; then
	if [ -r ${make_conf} ]; then
		make_use=`do_get_make nodashes`
	else
		do_report_err ${make_conf} read
	fi
	for flag in ${@@:2}; do
		# Strip leading dashes.
		if [ "${flag:0:1}" = "-" ]; then
			flag="${flag:1}"
		fi
		lock_test=`do_get_depr ${flag} ${make_use}`
		if [ "${lock_test}" = "" ]; then
			lock_flags="${lock_flags} ${flag}"
		else
			echo "!!! ${flag} is not in your USE variable."
		fi
	done
	lock_out=`do_lock_flags ${lock_flags}`
	do_write_lock ${lock_out}

# unlock:
# This is the feature to unlock a deprecated USE flag to allow removal
elif [ "$1" = "unlock" ] || [ "$1" = "-k" ]; then
	if [ -r ${lock_cache} ]; then
		lock_out=`cat ${lock_cache}`
	else
		do_report_err nolock
	fi
	for flag in ${@@:2}; do
		# Strip leading dashes.
		if [ "${flag:0:1}" = "-" ]; then
			flag="${flag:1}"
		fi
		lock_flag_check=`do_get_depr ${flag} ${lock_out}`
		if [ "${lock_flag_check}" = "" ]; then
			lock_out=`do_use_rm ${flag} ${lock_out}`
		else
			echo "!!! ${flag} is not a locked flag."
		fi
	done
	do_write_lock ${lock_out}

# showlock:
# This feature prints a list of USE flags that have been locked
elif [ "$1" = "showlock" ] || [ "$1" = "-w" ]; then
	if [ -r ${lock_cache} ]; then
		cat ${lock_cache}
	else
		do_report_err nolock
	fi

# update:
# This is the feature to update your USE by removing deprecated flags and
#  handling new flags.
elif [ "$1" = "update" ] || [ "$1" = "-u" ]; then
	if [ -r ${make_conf} ]; then
		# Get our USE but strip leading dashes
		make_use=`do_get_make nodashes`
	else
		do_report_err ${make_conf} read
	fi
	# Get available USE flags from use.desc
	if [ -r ${use_desc} ]; then
		use_avail=`do_get_avail`
	else
		do_report_err ${use_desc} read
	fi
	# First we check for deprecated flags.
	echo "Your USE variable currently looks like this:"
	echo
	echo `do_get_make dashes`
	echo
	# Print the list of locked flags if any exist.
	if [ -r ${lock_cache} ]; then
		lock_test=`cat ${lock_cache} | tr -d ' '`
		if [ "${lock_test}" != "" ]; then
			echo "The following flags are locked:"
			cat ${lock_cache}
			echo
		fi
	fi
	echo
	echo "*** Checking for deprecated USE flags ..."
	echo
	for check_flag in ${make_use}; do
		depr_ret=`do_get_depr ${check_flag} ${use_avail}`
		flag_depr="${flag_depr}${depr_ret}"
	done
	# Filter out locked flags
	if [ -r ${lock_cache} ] && [ "${lock_test}" != "" ]; then
		lock_list=`cat ${lock_cache}`
		for check_locks in ${flag_depr}; do
			lock_ret=`do_get_depr ${check_locks} ${lock_list}`
			lock_out="${lock_out}${lock_ret}"
		done
		flag_depr="${lock_out}"
	fi
	make_use=`do_get_make dashes`
	if [ "${flag_depr}" = "" ]; then
		echo "!!! No deprecated flags were found."
	else
		echo "The following USE flags appear to be deprecated:"
		echo "${flag_depr}"
		echo
		echo "How would you like to handle them?"
		echo "1) Handle them individually"
		echo "2) Remove all deprecated flags"
		echo "3) Don't remove any deprecated flags"
		echo "4) Lock all deprecated flags"
		echo
		echo -n "Type (1, 2, 3, or 4): "
		while [ "${luser_input}" = "" ]; do
			read luser_input
			case ${luser_input} in
			"2")
				changes="1"
				for flag in ${flag_depr}; do
					make_use=`do_use_rm \
						${flag} ${make_use}`
				done
				echo
				echo -n "*** All deprecated flags were "
				echo "removed."
				;;
			"3")
				echo
				echo "*** No flags were removed."
				;;
			"1")
				for flag in ${flag_depr}; do
					echo -n "${flag} appears to be "
					echo -n "deprecated.  Remove it? "
					echo -n "[Y]es/[N]o/[L]ock : "
					luser_yn=""
					while [ "${luser_yn}" = "" ]; do
						read luser_yn
						case ${luser_yn} in
						"y" | "Y")
							changes="1"
							make_use=`do_use_rm \
								${flag} \
								${make_use}`
							;;
						"n" | "N")
							;;
						"l" | "L")
							wlk="${flag} ${wlk}"
							;;
						*)
							luser_yn=""
							;;
						esac
					done
				done
				echo
				echo -n "*** All deprecated flags "
				echo "processed."
				;;
			"4")
				wlk="${flag_depr}"
				echo
				echo "*** All deprecated flags were locked."
				;;
			*)
				luser_input=""
				;;
			esac
		done
	fi
	if [ "${wlk}" != "" ]; then
		do_write_lock ${wlk}
	fi
	# Now we check for new flags.
	echo
	echo
	echo "*** Checking for new USE flags ..."
	echo
	# Load up our cached USE flags for comparison with use.desc
	# Create the cache if it does not exist
	if [ -w ${use_cache} ]; then
		use_old=`cat ${use_cache}`
		echo "${use_avail}" > ${use_cache}
		chmod 600 ${use_cache}
	elif [ -w ${use_cache_parent} ]; then
		mkdir -p ${use_cache_dir}
		chmod 700 ${use_cache_dir}
		echo "${use_avail}" > ${use_cache}
		chmod 600 ${use_cache}
		use_old=""
	else
		do_report_err ${use_cache} write
	fi
	# Grab the contents of the USE variable.
	make_cand=`do_get_make nodashes`
	# Build a list of flags that do not exist in the USE variable.
	for flag in ${use_avail}; do
		new_cand="${new_cand}`do_get_depr ${flag} ${make_cand}`"
	done
	# Filter that list through the cached master list of flags.
	for flag in ${new_cand}; do
		new_flags="${new_flags}`do_get_depr ${flag} ${use_old}`"
	done
	if [ "${new_flags}" = "" ]; then
		echo "!!! No new USE flags are available."
	else
		echo "The following new USE flags are available:"
		echo "${new_flags}"
		echo
		echo "How would you like to handle them?"
		echo "1) Handle them individually"
		echo "2) Use Portage defaults (do not add to USE)"
		echo "3) Explicitly enable all new flags"
		echo "4) Explicitly disable all new flags"
		echo
		echo -n "Type (1, 2, 3, or 4): "
		luser_input=""
		while [ "${luser_input}" = "" ]; do
			read luser_input
			case ${luser_input} in
			"1")
				for h_flag in ${new_flags}; do
					do_get_desc ${h_flag}
					echo -n "How would you like to handle "
					echo -n "${h_flag}? [e]nable, "
					echo -n "[d]isable, [u]se default : "
					luser_handle=""
					while [ "${luser_handle}" = "" ]; do
						read luser_handle
						case ${luser_handle} in
						"e" | "E")
							changes="1"
							make_use=`do_use_add \
								${h_flag} \
								${make_use}`
							echo
							;;
						"d" | "D")
							changes="1"
							make_use=`do_use_add \
								"-${h_flag}" \
								${make_use}`
							echo
							;;
						"u" | "U")
							echo
							;;
						*)
							luser_handle=""
							;;
						esac
					done
				done
				echo -n "*** All new flags have been "
				echo "processed."
				;;
			"2")
				echo
				echo -n "*** No new flags were added to "
				echo "your USE."
				;;
			"3")
				changes="1"
				for h_flag in ${new_flags}; do
					make_use=`do_use_add ${h_flag} \
						${make_use}`
				done
				echo
				echo -n "*** All new flags were enabled in "
				echo "your USE."
				;;
			"4")
				changes="1"
				for h_flag in ${new_flags}; do
					make_use=`do_use_add \
						"-${h_flag}" ${make_use}`
				done
				echo
				echo -n "*** All new flags were disabled in "
				echo "your USE."
				;;
			*)
				luser_input=""
				;;
			esac
		done
	fi
	# Write the changes if necessary.
	if [ "${changes}" != "0" ]; then
		do_write_make ${make_use}
		# Prune any locked flags that do not exist in the USE variable
		lock_prot=`do_lock_flags fakeflag`
		do_write_lock ${lock_prot}
	fi
	echo
	echo
	echo "*** Script finished ..."

# Display USAGE statement for unhandled parameters
else
	echo "Usage:"
	echo "	${run_name} action [flag] [...]"
	echo
	echo "Actions:"
	echo "-s, show	Displays the contents of the USE variable."
	echo "-i, desc	Displays a description of one or more USE flags."
	echo -n "-a, add		Adds the specified flag(s) to the USE "
	echo "variable."
	echo -n "-d, del		Deletes the specified flag(s) from "
	echo "the USE variable."
	echo "-l, lock	Locks the specified flag(s) to prevent deprecation."
	echo -n "-k, unlock 	Unlocks the specified flags to allow "
	echo "deprecation."
	echo "-w, showlock 	Displays a list of locked flags."
	echo -n "-u, update 	Interactively updates the USE variable to "
	echo "reflect changes"
	echo "		to use.desc."
	echo
	exit 1
fi
exit 0

@


1.2
log
@Fixes #4172.
@
text
@@


1.1
log
@Fixes #2900.
@
text
@d2 1
a2 1
# useflag v0.3.0
d45 3
a47 2
	local get_make_out=`grep "USE=\"" ${make_conf} | grep -v "#" | \
		cut -d "\"" -f2 -s`
d69 2
a70 2
# Get depreciated flags.
# parm1 = flag to check for depreciation
d163 31
a193 4
		cat ${make_conf} | \
			sed -e "s/${old_use}/${use_write}/" > ${make_temp}
		cp ${make_temp} ${make_conf}
		rm ${make_temp}
d288 1
a288 1
# This is the feature to lock a depreciated USE flag to prevent removal
d311 1
a311 1
# This is the feature to unlock a depreciated USE flag to allow removal
d342 1
a342 1
# This is the feature to update your USE by removing depreciated flags and
d357 1
a357 1
	# First we check for depreciated flags.
d372 1
a372 1
	echo "*** Checking for depreciated USE flags ..."
d389 1
a389 1
		echo "!!! No depreciated flags were found."
d391 1
a391 1
		echo "The following USE flags appear to be depreciated:"
d396 3
a398 3
		echo "2) Remove all depreciated flags"
		echo "3) Don't remove any depreciated flags"
		echo "4) Lock all depreciated flags"
d411 1
a411 1
				echo -n "*** All depreciated flags were "
d421 1
a421 1
					echo -n "depreciated.  Remove it? "
d445 1
a445 1
				echo -n "*** All depreciated flags "
d451 1
a451 1
				echo "*** All depreciated flags were locked."
d599 1
a599 1
	echo "-l, lock	Locks the specified flag(s) to prevent depreciation."
d601 1
a601 1
	echo "depreciation."
@

