#!/bin/bash
#
# $Revision: 1.83 $, $Date: 2004/03/10 20:28:15 $
#
#
# Function name:	Number of args:	Description of args:
# dml_buttons():	optional	Ok/Anuluj/Edytuj/Powrt/Pomoc/Przywr/Kod/Log/Wyjcie;
# dml_cancel_check():	1 arg		$1 is file to return to;
# dml_edit_check():	1 arg		$1 is file to edit;
# dml_help_check():	1 arg		arg1 is file to view in less;
# dml_check_the_rest():	1 arg		check if exit|source|ok were pressed, 
#					arg1 is file to return to after run_main();
# dml_recover_check():	2 args		copy $1 (backup file) into $2 (current);
# install_if_missing(): 1 arg		$1 is $packets_to_install;
# backup_file(): 	1 arg	 	backup if not backed up already;
# show_message		1 arg		$1 is the message for the user 
# show_verbose_message	optional	$1 is the the extra message for the user, $2(opt) is a shell command
# line_remove():	2 args		$1 is string in line to remove, $2 is the file
# line_replace():	3 or 4 args	$1 is string in line before, $2 is line after, $3 is /the/file
#					$4 is optional separator for s/BAR/bar/ (take care of $BAR=/usr/bin)
#					see comments & examples below
# drop_section():	3 args		$1 is start_match, $2 is end_match, $3 is the file
#					drop_section() drops section between start_match and first occurance 
#					of end_match in $3 file;
# leave_section():	3 args		like drop_section(), but drops all outside start_match & end_match;
# add_user_to_group(): 2 args		adds $1 user to group $2
# svn_garbage_remove(): no args		delete garbage files from svn archive, developers's interna and .svn folders;
#					Better do backup of the $DIR and then see diff -r $DIR $DIR.bak;
# yes_no():		2		Show them the dialog and wait for [t/n] answer. $1 is message, 
#					$2 command to be executed;
# install_packets():	1 arg		$1 is set of packets to install. This func is a poldek's wrapper -
#					poldek won't forgive even one missing package - it simply
#					drops the whole list and doesn't install anything - this func
#					adresses the issue;
#
#   CAREFUL WITH line_replace() !
#
# Be careful about example file below:
# nameserver 192.168.1.100
#
# Say you want to add a new nameserver 192.168.1.1  ->  line_replace "192.168.1.1" "192.168.1.1" /etc/resolv.conf 
# The above call is supposed to	replace old 192.168.1.1 to avoid duplicate entries in /etc/resolv.conf, but 
# 192.168.1.1 matches 192.168.1.100 also - that would cause overwriting 192.168.1.100 into 192.168.1.1 . 
# In such cases use line_replace "192.168.1.1\b" "192.168.1.1" /etc/resolv.conf  (see man perlre for \b)
# 					     ^^
# This aplies to files that may contain strings being substrings of other strings, (i.e. /etc/resolv.conf,
# /etc/hosts): 192.168.1.2 192.168.1.23 192.168.1.230 or ALA_MA_KOTA ALA ALA_MA
#
# Default SEPARATOR is now %. Only if one needs to change string containing % there's a need to set SEPARATOR:
# example usage: line_replace "this is % mark" "this is BAR mark" file SEPARATOR=/
#
# example usage: line_replace "user\@.*" "jasiek\@onet.pl" file
# example usage: line_replace "MOUSETYPE=" "MOUSETYPE=$TYPE" ${FILE_CONF} 
# example usage: line_replace "192.168.1.1\b" "192.168.1.1" /etc/resolv.conf 
# example usage: line_replace "/usr/local/bin/" "/usr/bin/" file  
#
#
#
# Variables list:	Description:
# dml_ok		associated with dml_check_the_rest();
# dml_cancel		associated with dml_cancel_check();
# dml_edit		associated with dml_edit_check();
# dml_help		associated with dml_help_check();
# dml_recover		associated with dml_recover_check();
# dml_source		associated with dml_check_the_rest();
# dml_exit		associated with dml_check_the_rest();
# -----------------------


[ -z $HOME_ETC ] && export HOME_ETC=$HOME

. /etc/pldconf/ustawienia


export KERNEL_VER=`uname -r | cut -b1-3`
export PLDCONF_VERSION=0.3.16
export EXEC_PREFIX=/usr/bin
export DATA_DIR=/usr/share/pldconf
export CONF_DIR=/etc/pldconf
export VF_MNTPOINT=/media/cdrom 
export VF_EJECT=eject
export PATH="$PATH:/usr/X11R6/bin"

[ -z $EDITOR ] && {
which vim 1>/dev/null && export EDITOR=vim || { echo "Run export EDITOR=your_editor and set it in pldconf -> Other"; exit; }
} 

export MODULES_CONFIG=/etc/modules.conf
[ $KERNEL_VER = 2.6 ] && export MODULES_CONFIG=/etc/modprobe.conf

CURRENT_SHELL="`echo $SHELL | cut -f3 -d/`"
case $CURRENT_SHELL in
	zsh) export SHELLRC=zshrc; export SHELLPROFILE=zprofile;;
	bash) export SHELLRC=bashrc; export SHELLPROFILE=bash_profile;;
esac


show_message () {
	echo; echo "$1"; echo
	[ $TIMEOUT_MODE -eq 1 ] && sleep $SLEEP_TIME || { echo '<enter>'; read; }
}

show_verbose_message () {
	[ $VERBOSE_MODE -eq 1 ] && { echo; echo; eval "$2"; echo; echo; show_message "$1"; }
}


line_replace () {
	unset addon
	ORIG_FILE="`mktemp /tmp/pldconf.XXXXXX`"
	[ -f $3 ] || { touch $3; show_verbose_message "$(nls "Creating a missing file $3")"; }
	cp $3 $ORIG_FILE

	# there's no such entry in the given file yet
	cat $3 | egrep "^$1" || { echo "$2" >> $3; addon="$(nls "New entries")"; }

	# entry exists, doing the replace
	if [ -z "$addon" ]; then
		SEPARATOR=%; eval $4
		addon="SEPARATOR=$SEPARATOR"
		perl -pi -e "s$SEPARATOR^$1.*$SEPARATOR$2$SEPARATOR" $3
	fi
	show_verbose_message "$3: $(nls "After changes: $1 to: $2")    $addon" "diff -Nur $ORIG_FILE $3 && egrep --color -C 4 '$2' $3;"
}


line_remove () {
	if [ -f "$2" ]; then
		TMPFILE=`mktemp /tmp/pldconf.XXXXXX` || exit
		ORIG_FILE=`mktemp /tmp/pldconf.XXXXXX` || exit
		cp $2 $ORIG_FILE
		grep -v "$1" "$2" > $TMPFILE
		mv $TMPFILE $2
		show_verbose_message "$2: $(nls "After deleted lines contains: $1")  " "diff -Nur $ORIG_FILE $2 && cat $2;"
	else
		show_verbose_message "$(nls "No file: $2")"
	fi
}

leave_section () {
	ORIG_FILE=`mktemp /tmp/pldconf.XXXXXX`
	cp $3 $ORIG_FILE
	sed -i -n -e "/$1/,/$2/p" $3
	show_verbose_message "$3: leave_section(): $(nls "After changes: $1 to: $2")" "diff -Nur $ORIG_FILE $3"
}

drop_section () {
	ORIG_FILE=`mktemp /tmp/pldconf.XXXXXX`
	cp $3 $ORIG_FILE
	sed -i -e "/$1/,/$2/d" $3
	show_verbose_message "$3: drop_section(): $(nls "After changes: $1 to: $2") " "diff -Nur $ORIG_FILE $3"
}

svn_garbage_remove() {
	svn status --no-ignore
	echo
	for i in `svn status --no-ignore | egrep '^\?|^I' | cut -f7 -d' '`; do 
		echo "rm -rf $i"
		rm -rf "$i"
	done
	
	for i in `find . -type d -name ".*svn"`; do
		echo "rm -rf $i"
		rm -rf $i
	done
}

#dir_string_replace () {
#	 the implementation was a brain damage, below is the right code:
#	 find /tmp -iname "*.html" -o -iname "*.php" -print0 | xargs -0 perl -pi -e 's/from/to/g'
#}


yes_no() {
	echo; echo "$1" 
	echo "[y/n]"
	read a
	[ "X$a" = "Xy" ] && { echo "$(nls "Run $2")"; echo; eval $2; }
}

add_user_to_group() {
	User=$1
	Groups=$2
	for i in `id -Gn $User`; do 
		Groups=$Groups,$i
	done
	usermod -G $Groups $User
	show_verbose_message "$(nls "$User after added to: $2")" "groups $User"
}

backup_file () {
	# backup first time only
	[ `id -nu` = root ] && BACKUP_DIR=${CONF_DIR} || BACKUP_DIR=$HOME_ETC/.pldconf
	[ -f "$BACKUP_DIR/`basename $1`" ] || {
		show_verbose_message "$(nls "Backup $1 in $BACKUP_DIR/")"
		mkdir -p $BACKUP_DIR
		cp $1 $BACKUP_DIR/
	}
}

dml_buttons () {
	echo $@ | grep Ok 1>&2 >/dev/null && echo "<button id=dml_ok caption=$(nls "Ok")>"
	echo $@ | grep Anuluj 1>&2 >/dev/null && echo "<button id=dml_cancel caption=$(nls "Cancel")>"
	echo $@ | grep Powrt 1>&2 >/dev/null && echo "<button id=dml_cancel caption=$(nls "Back")>"
	echo $@ | grep Edytuj 1>&2 >/dev/null && echo "<button id=dml_edit caption=$(nls "Edit")>"
	echo $@ | grep Pomoc 1>&2 >/dev/null && echo "<button id=dml_help caption=$(nls "Help")>"
	echo $@ | grep Przywr 1>&2 >/dev/null && echo "<button id=dml_recover caption=$(nls "Restore")>"
	echo "<br><button id=dml_source caption='$(nls "Show source")'><button id=dml_exit caption=$(nls "Exit")>" 
}

dml_cancel_check() {
	[ "X$dml_cancel" = "Xyes" ] && { remove_tmp; exec $1; }
}

dml_edit_check() {
	[ "X$dml_edit" = "Xyes" ] && { $EDITOR $1; exec $0; }
}

dml_help_check() {
	[ -n "$LANG" ] && clang="`echo $LANG`"
	[ "X$dml_help" =  "Xyes" ] && { [ -f "$1.$clang" ] && $PLDCONF_PAGER "$1.$clang" || $PLDCONF_PAGER "$1"; exec $0; }
}

dml_recover_check(){
	[ "X$dml_recover" = "Xyes" ] && { show_verbose_message "$(nls "Copy $1 to $2")"; cp $1 $2; setup_perms; exec $0; }
}

dml_check_the_rest() {
	[ "X$dml_source" =  "Xyes" ] && { $EDITOR $0; exec $0; }
	[ "X$dml_ok" = "Xyes" ] && { run_main 2>/dev/null; remove_tmp; exec $1; }
	[ "X$dml_exit" = "Xyes" ] && { remove_tmp; exit; }
}

install_if_missing() {
	[ "X$ERRORS_HANDLE" = "XALWAYS_IGNORE" ]  && return 0 #This is specially for RO filesystems (PLD LiveCD guys)
	packets_to_install="$1"
	
	rpm -q $packets_to_install 1>&2 >/dev/null
	if [ $? -ne 0 ]; then
		echo; echo; echo "$(nls "At least one of the packages is missing:")"
		echo "$packets_to_install"; echo 
		[ `id -nu` != root ] && { show_message "$(nls "Only root can install packets...")"; return 1; }

		if [ "X$ERRORS_HANDLE" = "XALWAYS_ASK" ]; then
			cat << EOF
<enter>	-$(nls "install")
n	- $(nls "don't install")
a	- $(nls "auto correct all errors")
w	- $(nls "turn off warnings and never fix errors (not recommended)")
$(nls "This options can be changed in pldconf -> pldconf settings")
$(nls "<ctrl+c> exit")
EOF

			read input
			case $input in
				n)
				return 1
				;;
				a)
				line_replace "export ERRORS_HANDLE" "export ERRORS_HANDLE=ALWAYS_FIX" ${CONF_DIR}/ustawienia
				export ERRORS_HANDLE=ALWAYS_FIX
				;;
				w)
				line_replace "export ERRORS_HANDLE" "export ERRORS_HANDLE=ALWAYS_IGNORE" ${CONF_DIR}/ustawienia
				export ERRORS_HANDLE=ALWAYS_IGNORE
				return 0 	
				;;
			esac
		fi

		# we enter here after <enter> or automatically with $ERRORS_HANDLE != {ALWAYS_IGNORE,ALWAYS_ASK}
		install_packets "$packets_to_install" 
		rpm -q $packets_to_install 1>&2 >/dev/null
		return $? # callers may like to check the return value, 0 means all packets are succesfully installed
	fi
}

install_packets() {
	packets_list=$1
	show_verbose_message "poldek -vU $packets_list"	
	poldek_log=`mktemp /tmp/pldconf_poldek_log.XXXXXX` || exit
	poldek -vU $packets_list --log=$poldek_log
	if [ $? -ne 0 ]; then
		for i in $packets_list; do
			if [ -n "`echo $i | grep \*`" ]; then # theme_packs* 
				separate_install_set="$separate_install_set $i"
			else
				grep "nie znaleziono $i" $poldek_log || 
				grep "$i not found" $poldek_log || 
				install_set="$install_set $i"
			fi
		done
		[ -n "$install_set" ] && poldek -vU $install_set 
		[ -n "$separate_install_set" ] && poldek -vU $separate_install_set
		show_message "$(nls "Some packages missing in source - only available packages installed")"
	fi
	rm $poldek_log
}
setup_perms() {
	chmod 640 /etc/{modprobe.conf,modules.conf} 2>/dev/null
	chmod 644 /etc/{modules,fstab,hosts,poldek.conf,resolv.conf,inittab,profile,group} 2>/dev/null
	chmod 644 /boot/grub/menu.lst 2>/dev/null
	chmod 700 /etc/sysconfig/ 2>/dev/null
	chmod 644 /etc/sysconfig/{i18n,interfaces/ifcfg-*,mouse,hdparm,clock,rdate,clock} 2>/dev/null
}

count_prefix()
{
	prefix_to_transform="$1"
	PREFIX=32 
	for k in "255.255.255.255" "255.255.255.254" "255.255.255.252" "255.255.255.248" \
		"255.255.255.240" "255.255.255.224" "255.255.255.192" "255.255.255.128" \
		"255.255.255.0" "255.255.254.0" "255.255.252.0" "255.255.248.0" "255.255.240.0" \
		"255.255.224.0" "255.255.192.0" "255.255.128.0" "255.255.0.0" "255.254.0.0" \
		"255.252.0.0" "255.248.0.0" "255.240.0.0" "255.224.0.0" "255.192.0.0" "255.128.0.0" \
		"255.0.0.0" "254.0.0.0" "252.0.0.0" "248.0.0.0" "240.0.0.0" "224.0.0.0" \
		"192.0.0.0" "128.0.0.0" "0.0.0.0 0"; do
		[ "$prefix_to_transform" = "$k" ] && return # PREFIX is setup right now
		let PREFIX--
	done
}

# borrowed (not to say stolen) from rc-scripts
nls() {
	typeset msg_echo old_nls_domain text message
	msg_echo='\n'
	old_nls_domain="${NLS_DOMAIN}"
	while [ "${1}" != "${1##-}" ] || [ "${1}" != "${1##+}" ]; do
		case "${1}" in
			--nls-domain)
			shift
			NLS_DOMAIN="$1"
			shift
			;;
			-n)
			msg_echo=''
			shift
			;;
		esac
	done
	message="$1"
	shift
	# empty message, so we return --misiek
	if [ -z "$message" ]; then
		NLS_DOMAIN="$old_nls_domain"
		echo -en "$msg_echo"
		return
	fi

	message="`echo $message | sed -e 's/[\]//g'`"

	if [ -x /bin/gettext -o -x /usr/bin/gettext ]; then
		text="$(gettext -e --domain=pldconf "$message")"

		printf "${text}" "${@}"
	else
		printf "${message}" "${@}"
	fi

	echo -en "$msg_echo"
	NLS_DOMAIN="$old_nls_domain"
}

remove_tmp () {
	rm -rf /tmp/pldconf.* 2>/dev/null
	rm -rf ~/tmp/pldconf.* 2>/dev/null
}

pci_dev () {
	for m in `pcidev /m $1`; do 
		modprobe $m >& /dev/null && line_replace "$m" "$m" /etc/modules
	done
}

export -f  dml_buttons dml_cancel_check dml_edit_check dml_help_check dml_recover_check dml_check_the_rest install_if_missing line_replace line_remove backup_file show_message show_verbose_message install_packets leave_section drop_section yes_no svn_garbage_remove add_user_to_group setup_perms count_prefix nls remove_tmp pci_dev
