shellUtils.sh 9.16 KB
if [ "x" == "x$__SHELLUTILS__" ]
then
	__SHELLUTILS__="shellUtils"

	# -------------------------------
	# Fehlermeldungen
	_shellUtils_errMsg[1]="Fehler beim Aufruf von \${FUNCNAME}: falsche Parameteranzahl: $#"
	_shellUtils_errMsg[2]="Fehler: Es läuft bereits eine Instanz (\${oldPid}) des scripts"
	_shellUtils_errMsg[3]="Fehler beim Aufruf von doSmbCommand: smbCommand nicht initialisiert"
	_shellUtils_errMsg[4]="Fehler: konnte keine Konfigurations-Datei (\${cName}) finden"
	#_shellUtils_errMsg[2]=
	# -------------------------------

	# -------------------------------
	# Kommandodefinitions Teil
	SH="/bin/bash"
	SMBCLIENT="/usr/bin/smbclient"
	PS="/bin/ps"
	BASENAME="/usr/bin/basename"
	PWDCMD="/bin/pwd"
	CONVERT="/usr/bin/convert"
	ICONV="/usr/bin/iconv"
	ECHO="/bin/echo"
	TEST="/usr/bin/test"
	SED="/usr/bin/sed"
	PRINTF="/usr/bin/printf"
	SORT="/usr/bin/sort"
	FTP="/usr/bin/ftp"
	CONVERT="/usr/bin/convert"
	CJPEG="/usr/bin/cjpeg"
	CAT="/bin/cat"
	MKDIR="/bin/mkdir"
	DATE="/bin/date"
	RM="/bin/rm"
	MAILCMD="/bin/bin/mailto"
	CUT="/usr/bin/cut"
	TR="/usr/bin/tr"
	LOCALE="/usr/bin/locale"
	GREP="/bin/grep"
	WC="/usr/bin/wc"
	MV="/usr/bin/mv"
	CP="/usr/bin/cp"
	EXPR="/usr/bin/expr"
	UNZIP="/usr/bin/unzip"
	XSLTPROC="/usr/bin/xsltproc"
	GAWK="/usr/bin/gawk"
	AWK="/usr/bin/awk"
	LS="/bin/ls"
	TOUCH="/usr/bin/touch"
	RECODE="/usr/bin/recode"
	GETOPT="/usr/bin/getopt"
	# -------------------------------

	# -------------------------------
	# Variablen
	_smbCommand=""
	# -------------------------------

	# -------------------------------
	# Funktionen
	# Aufruf: checkLock lockfile
	function checkLock
	{
		if [ $# -ne 1 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		local filename="$1"

		if [ -e "$filename" ]
		then
			local oldPid="`$CAT "$lockFile"`"
			local scriptName="`$BASENAME $0`"
			local running="`$PS -p "$oldPid" | $SED '1d; /'$scriptName'/!d'`"

			if [ -n "$running" ]
			then
				eval "echo \"${_shellUtils_errMsg[2]}\" >&2"
				exit 2
			fi
		fi

		echo $$ >"$lockFile"

		return $$
	}

	# Aufruf: doSmbCommand share domain user pass
	function initSmbCommand
	{
		if [ $# -ne 4 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		_smbCommand="$SMBCLIENT $1 $4 -U $3 -W $2"
	}

	# Aufruf: doSmbCommand path command
	function doSmbCommand
	{
		if [ $# -lt 1 -o $# -gt 2 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		if [ -z "$_smbCommand" ]
		then
			eval "echo \"${_shellUtils_errMsg[3]}\" >&2"
			exit 3
		fi

		if [ $# -eq 2 ]
		then
			eval "$_smbCommand -D $1 -c \"$2\""
		else
			eval "$_smbCommand -D $1" <&0
		fi
	}

	# Meine Implementation von Hashes fuer die bash verwendet zwei Arrays,
	# deren "Basisname" immer bei den aufrufen der Hash-Funktionen mit
	# angegeben werden muessen. Die beiden Arrays heissen dann 
	# _<<Basisname>>_key und _<<Basisname>>_value und enthalten entsprechen
	# jeweils zu einem Index ein key/value Paar.
	# Die groesste Magie in den Funktionen liegt darin die Arraynamen
	# immer richtig zu erzeugen.
	# Wenn man dieses Hashes benutzt sollte man bedenken, das das
	# Laufzeitverhalten O(n) ist, die Implementierung also nicht sehr
	# performant.
	# PS. O(n) => im unguenstigsten Fall hat man n Schleifendurchlaeufe um
	# auf ein Element in einem Hash mit n Elementen zuzugreifen.
	# Ich mags kaum zugeben aber an manchen Stellen ist das Laufzeitverhalten
	# sogar O(2n). (Es besteht wohl noch dringender Optimirungsbedarf)

	# eine Funktion um einen Hash zu leeren
	# Aufruf: unsetHash hashname
	function unsetHash
	{
		if [ $# -ne 1 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		unset _${1}_key
		unset _${1}_value
	}

	# eine Funktion um einen HashWert zu setzen. ein key und ein value array
	# werden erzeugt. Ueber getHashVal kann man wieder Werte abfragen.
	# Aufruf: setHashVal hashname key value
	function setHashVal
	{
		if [ $# -ne 3 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		getHashVal "${1}" "${2}" >/dev/null 2>&1
		local idx=$?
		eval "_${1}_key[$idx]=\"$2\""
		eval "_${1}_value[$idx]=\"$3\""
	}

	# und eine funktion um über einen key einen Wert aus einem Hash 
	# (siehe setHashVal) zu bekommen.
	# Aufruf: getHashVal hash key
	function getHashVal 
	{ 
		if [ $# -ne 2 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		local i=0
		local count=`getHashSize $1`
		local key=`$ECHO $2 | $SED 's/#/\\\\#/'`

		while [ $i -lt $count ]
		do 
			if eval [ "\${_${1}_key[$i]}" = "$key" ]
			then 
				eval "echo \${_${1}_value[$i]}"
				return $i 
			fi 
		
			i=$((i+1)); 
		done; 

		return $i
	}

	# Aufruf: getHashSize hash
	function getHashSize
	{
		if [ $# -ne 1 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		eval "count=\${#_${1}_key[*]}"
		echo $count

		return $count
	}

	# Aufruf: getHashKeys hash
	function getHashKeys
	{
		if [ $# -ne 1 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		eval "ret=\"\${_${1}_key[0]}\""

		local i=1
		local count=`getHashSize $1`
		while [ $i -lt $count ]
		do
			eval "ret=\"$ret \${_${1}_key[$i]}\""
			i=$((i+1))
		done

		echo $ret

		return $count
	}

	# Funktion um die Zahlrepraesentation eines Monatsname zu bekommen.
	# Also Oktober => 10
	# Abhaengig davon das ein entsprechendes locale installiert ist.
	# Aufruf: getMonthNum Monatsname [locale]
	function getMonthNum
	{
		if [ $# -lt 1 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		if [ $# -eq 2 ]
		then
			LC_ALL=${2}
		fi

		mon=`$LOCALE -c LC_TIME | $SED '5!d;y/;/\n/' |\
			$GREP -n ${1} | $CUT -d\: -f1`

		echo $mon

		return $mon
	}

	# Funkktion um ein Kommando nach einem bestimmten Zeitraum abzubrechen
	# Aufruf: timeout cmd t
	# Retruns: >128 -> falls Timeout, return value von cmd->falls kein Timeout
	function timeout
	{  
		if [ $# -lt 2 ]
		then
			eval "echo \"${_shellUtils_errMsg[1]}\" >&2"
			exit 1
		fi

		# gewuenschtes Kommando als separaten Prozess starten
		$1 <&0 &
		local __cPid=$!

		# subshell starten die gewuenschte Zeit wartet bis sie obigen
		# Prozess killt.
		( sleep $2; kill -9 ${__cPid} ) >/dev/null 2>&1 &
		local __tPid=$!

		# neuen Trap setzen....evtl. vorhande alte Kommandos werden auch
		# ausgefuehrt! (Bei Programmabbruch auch auf jeden Fall beide 
		# Sub-Prozesse killen)
		oldTrap="`trap -p EXIT`"
		oldTrapCmd="`echo $oldTrap | sed 's/^trap -- \(.*\) EXIT$/\1/'`"

		trapCmd="kill -9 ${__cPid} >/dev/null 2>&1"
		trapCmd="${trapCmd};kill -9 ${__cPid} >/dev/null 2>&1"
		trapCmd="${trapCmd};eval $oldTrapCmd"
		trap "${trapCmd}" EXIT

		# warte bis Subprozess mit Kommando endet
		wait ${__cPid} >/dev/null 2>&1
		local __cExit=$?

		# alte trap Kommandos wiederherstellen
		test "$oldTrapCmd" && eval "$oldTrapCmd" || trap '-' EXIT

		# falls sie noch laeuft wartende subshell killen.
		kill -9 $__tPid >/dev/null 2>&1
		return $__cExit
	}
	# -------------------------------

fi

function getCDInfo
{
	local uri device cmd i hello cddb ret diskData tNum

	uri="freedb.freedb.org/~cddb/cddb.cgi"
	device="/dev/cdrom"

	test $# -ge 1 && uri="$1"
	test $# -ge 2 && device="$2"

	hello="hello=${USER}+${HOSTNAME}+test+0.0.1"

	# first get the genre list from server
	eval "`curl -s "http://${uri}?cmd=cddb+lscat&${hello}&proto=6" |\
		sed '1d;$d' | tr -d '\r' | tr '\n' ',' |\
		sed 's/,$//;s/,/" "/g;s/^\(.*\)$/local -a genre=("\1")/'`"

	unset cddbId dTitle dYear dGenre tTitle

	diskData="`cdda2wav -D ${device} -N -J -v toc,sectors 2>&1`"

	cddbId="`echo "$diskData" |\
		sed '/^CDDB/!d;s/^.*0x\(.*\)$/\1/'`"
	dTracks="`echo "$diskData" |\
		sed '/tracks/!d;s/^.*tracks:\([0-9]*\).*$/\1/'`"
	dLength="`echo "$diskData" |\
		sed '/tracks/!d;s/^.*time \([0-9:\.]*\).*$/\1/'`"
	dIndex="`echo "$diskData" |\
		sed '/CDINDEX/!d;s/^.*: *\([a-zA-Z0-9_\.]*-\).*$/\1/'`"
	dText="`echo "$diskData" | sed '
		/CD-Text/!d;s/^[^:]*: *\(.*[^ ]\).*$/\1/'`"
	dExtra="`echo "$diskData" | sed '
		/CD-Extra/!d;s/^[^:]*: *\(.*[^ ]\).*$/\1/'`"

	# search for info in all genres
	for i in "${genre[@]}"
	do
		cmd="cmd=cddb+read+${i}+${cddbId}"
		#wget -O- "http://${uri}?${cmd}&${hello}&proto=6" 2>/dev/null
		cddb="`curl -s "http://${uri}?${cmd}&${hello}&proto=6"`"
	
		ret="`echo "$cddb" | head -c 3`"
		if [ "$ret" != "210" ]
		then
			if [ ${verbose:-0} -ge 3 ]
			then
				debug="`echo "$cddb" | head -n 1`"
				echo $"[ERROR] cddb: ${debug}"
			fi
			continue
		else
			eval "`echo "$cddb" | tr -d '\r' | sed '
				/DTITLE/s/^.*=\(\(.*\) \/ \)*\(.*\)$/dArtist="\2";dTitle="\3"/p
				/DYEAR/s/^.*=\(.*\)$/dYear="\1"/p
				/DGENRE/s/^.*=\(.*\)$/dGenre="\1"/p
				/TTITLE/s/^TTITLE\([0-9]*\)=\(\(.*\) \/ \)*\(.*\)$/tArtist[\1]="\3";tTitle[\1]="\4"/p
				d'`"
			break
		fi
	done

	# Nu pack ich in alle tArtist die leer sind den dArtist.
	i=0
	while [ $i -lt ${#tArtist[@]} ]
	do
		tNum=$((i+1))
		tLength[$i]=`echo "$diskData" | sed '
			/[^0-9]'$tNum'\.(.*:.*)/ !d
			s/.*[^0-9]'$tNum'\.( *\([^)]*\).*$/\1/'`
		tStartSec[$i]=`echo "$diskData" | sed '
			/[^0-9]'$tNum'\.([^:]*)/ !d
			s/.*[^0-9]'$tNum'\.( *\([^)]*\).*$/\1/'`

		test $tNum -eq ${#tArtist[@]} && tNum="lead-out" || tNum=$((tNum+1))

		tEndSec[$i]=`echo "$diskData" | sed '
			/[^0-9]'$tNum'\.*([^:]*)/ !d
			s/.*[^0-9]'$tNum'\.*( *\([^)]*\).*$/\1/'`

		test -z "${tArtist[$i]}" && tArtist[$i]="$dArtist"
		i=$((i+1))
	done
}