#!/bin/bash
set -e
export LC_ALL=C

dpkg --assert-support-predepends

if [ "$1" = upgrade ]
then
    if [ -f /var/lib/dpkg/info/timezone.postrm ]; then
	rm -f /var/lib/dpkg/info/timezone.postrm
    fi
    if [ -f /var/lib/dpkg/info/timezones.postrm ]; then
	rm -f /var/lib/dpkg/info/timezones.postrm
    fi
    if dpkg --compare-versions "$2" lt 2.1.3-8; then
	if [ -s /etc/timezone ]; then
	    cp -a /etc/timezone /etc/timezone.save
	fi
    fi
    if dpkg --compare-versions "$2" le 2.2.2-4 && test -e /lib/libdb.so.3; then
	# Make upgrades to newer libdb.so.3 easier
	cat /lib/libdb.so.3 > /lib/libdb.so.3.old
    fi
    if dpkg --compare-versions "$2" le 2.1.1-0.1; then
	if [ -f /var/run/utmpd.pid ]; then
	    if kill -TERM `cat /var/run/utmpd.pid` > /dev/null 2>&1
	    then
		if [ -f /var/run/utmp ]; then
		    cp /dev/null /var/run/utmp
		    if grep '^utmp:' /etc/group; then
			chown root:utmp /var/run/utmp
			chmod 664 /var/run/utmp
		    else
			chown root:root /var/run/utmp
			chmod 644 /var/run/utmp
		    fi
		fi
		if [ -f /var/log/wtmp ]; then
		    savelog /var/log/wtmp
		    touch /var/log/wtmp
		    if grep '^utmp:' /etc/group; then
			chown root:utmp /var/log/wtmp
			chmod 664 /var/log/wtmp
		    else
			chown root:root /var/log/wtmp
			chmod 644 /var/log/wtmp
		    fi
		fi
		rm -f /etc/init.d/utmpd
		update-rc.d utmpd remove > /dev/null
	    fi
	fi
	if [ -f /var/run/utmpx ]; then rm -f /var/run/utmpx; fi
	if [ -f /var/log/wtmpx ]; then rm -f /var/log/wtmpx*; fi
	if [ -e /var/run/utmpd.ro ]; then rm -f /var/run/utmpd.ro; fi
	if [ -e /var/run/utmpd.rw ]; then rm -f /var/run/utmpd.rw; fi
    fi

    # NSS authentication trouble guard
    if dpkg --compare-versions $2 lt 2.3.2-2; then
	check="xdm kdm gdm postgresql xscreensaver"
	# Only get the ones that are installed, and configured
	service=$(dpkg -s $check 2> /dev/null | awk 'BEGIN{RS="\n\n";FS="\n"}{if ( $2 ~ /Status: .* installed$/ ) { print $1 } }' | cut -f 2 -d ' ')

	echo
	echo "Name Service Switch update in the C Library: pre-installation question."
	echo
	echo "Running services and programs that are using NSS need to be restarted,"
	echo "otherwise they might not be able to do lookup or authentication any more."
	echo "The installation process is able to restart some services (such as ssh or"
	echo "telnetd), but other programs cannot be restarted automatically.  One such"
	echo "program that needs manual stopping and restart after the glibc upgrade by"
	echo "yourself is xdm - because automatic restart might disconnect your active"
	echo "X11 sessions."
	echo
	echo "Known packages that need to be stopped before the glibc upgrade are:"
	echo "        $check"

	if [ -n "$service" ]; then 
	    echo "This script detects the following services which you are required"
	    echo "to stop before the upgrade:"
	    echo "        $service"
	else
	    echo "This script does not detect any services to stop now."
	fi
	echo
	echo "If you want to interrupt the upgrade now and continue later, please"
	echo "answer No to the question below."
	echo 
	frontend=`echo "$DEBIAN_FRONTEND" | tr '[:upper:]' '[:lower:]'`
	if [ "$frontend" = noninteractive ]; then
	    echo "Non-interactive mode, upgrade glibc forcedly"
	    answer=yes
	else
	    echo -n "Do you want to upgrade glibc now? [Y/n] "
	    read answer
	    case $answer in
		Y*|y*) answer=yes ;;
		N*|n*) answer=no ;;
		*) answer=yes ;;
	    esac
	fi
	echo
	if [ "$answer" = no ]; then
	    echo "Stopped glibc upgrade.  Please retry the upgrade after you have"
	    echo "checked or stopped services by hand."
	    exit 1
	fi
    fi

    # This will keep us from using hwcap libs (optimized) during an
    # upgrade.
    touch /etc/ld.so.nohwcap
    echo glibc >> /etc/ld.so.nohwcap
fi

# Sanity check.
# If there are versions of glibc outside of the normal installation
# location (/lib, /lib64, etc.) then things may break very badly
# as soon as ld.so is replaced by a new version.  This check is not
# foolproof, but it's pretty accurate.  This script ignores old
# libc4 or libc5.
check_dirs () {
  for dir in $*; do
    # Handle /lib in LD_LIBRARY_PATH.
    if expr $dir : "/lib.*" > /dev/null; then
      continue
    fi
    # Skip ia32-libs package on ia64, and similar libraries
    # (not sure why these get added to /etc/ld.so.conf)
    if expr $dir : "/emul/.*" > /dev/null; then
      continue
    fi
    if test -d $dir; then
      output=$(ls $dir | egrep '^lib(c|m|pthread|rt|dl)\.so\.[^/]*$' |\
	       egrep -v '^lib[cm]\.so\.[45].*$' 2>/dev/null)
      if test -n "$output"; then
	echo "These libraries were found in $dir:"
	echo "$output"
	return 0
      fi
    fi
  done
  return 1
}

if [ "$1" != abort-upgrade ]
then
  dirs="/usr/local/lib /usr/local/lib32 /usr/local/lib64"
  if ! test -L /usr; then
    dirs="$dirs /usr/lib /usr/lib32 /usr/lib64"
  fi
  if check_dirs $dirs; then
    echo
    echo "A copy of glibc was found in an unexpected directory."
    echo "It is not safe to upgrade the C library in this situation;"
    echo "please remove that copy of the C library and try again."
    exit 1
  fi

  if test -n "$LD_LIBRARY_PATH"; then
    dirs=$(echo $LD_LIBRARY_PATH | sed 's/:/ /')
    if check_dirs $dirs; then
      echo
      echo "Another copy of the C library was found via LD_LIBRARY_PATH."
      echo "It is not safe to upgrade the C library in this situation;"
      echo "please remove the directory from LD_LIBRARY_PATH and try again."
      exit 1
    fi
  fi
  if test -e /etc/ld.so.conf; then
    dirs=$(echo $(cat /etc/ld.so.conf))
    if check_dirs $dirs; then
      echo
      echo "Another copy of the C library was found via /etc/ld.so.conf."
      echo "It is not safe to upgrade the C library in this situation;"
      echo "please remove the directory from /etc/ld.so.conf and try again."
      exit 1
    fi
  fi
fi

if [ "$1" != abort-upgrade ] && [ "`uname -s`" = Linux ]
then
    # Test to make sure z < 255, in x.y.z-n form of kernel version
    # Also make sure we don't trip on x.y.zFOO-n form
    #kernel_rev=$(uname -r | tr -- - . | cut -d. -f3 | tr -d '[:alpha:]')
    kernel_rev=$(uname -r | sed 's/\([0-9]*\.[0-9]*\.\)\([0-9]*\)\(.*\)/\2/')
    if [ "$kernel_rev" -ge 255 ]
    then
        echo WARNING: Your kernel version indicates a revision number
        echo of 255 or greater.  Glibc has a number of built in
        echo assumptions that this revision number is less than 255.
        echo If you\'ve built your own kernel, please make sure that any 
        echo custom version numbers are appended to the upstream
        echo kernel number with a dash or some other delimiter.

        exit 1
    fi

    # sanity checking for the appropriate kernel on each architecture.
    realarch=`uname -m`
    kernel_ver=`uname -r`

    # intel i386 requires a recent kernel
    if [ "$realarch" = i386 ]
    then
	if dpkg --compare-versions "$kernel_ver" lt 2.4.24
	then
	    echo WARNING: This machine has i386 class processor.
	    echo Debian sarge and later, you need to use at least a 2.4.24
	    echo or 2.6.0 kernel on i386.  Please upgrade your kernel
	    echo before installing glibc.
	    echo The reason is that "bswap" instruction is not supported
	    echo on i386 class processors, and newer kernel can emulate
	    echo such lacking instructions.
	    exit 1
	fi
    fi

    # SPARC sun4m requires a recent kernel
    if [ "$realarch" = sparc ]
    then
	cputype=`egrep '^type.*:.*sun4m' /proc/cpuinfo 2> /dev/null` || true

	if [ "$cputype" != "" ]
	then
	    if dpkg --compare-versions "$kernel_ver" lt 2.4.21
	    then
		echo WARNING: You have a cpu which requires kernel 2.4.21
		echo or greater in order to install this version of glibc.
		echo Please upgrade the kernel before installing this package.
		echo
		echo You should be able to install the latest version of the
		echo sparc kernel-image in order to satisfy this need. You
		echo can also download and compile the latest kernel source
		echo yourself from a kernel mirror \(see http://www.kernel.org/\).
		exit 1
	    fi
	else
	    if dpkg --compare-versions "$kernel_ver" lt 2.2.0 #should be safe
	    then
		echo WARNING: This version of glibc suggests atleast a
		echo 2.2.0 kernel in order to work properly. 2.0.x kernels
		echo will not be able to support certain functions and
		echo may cause problems. 2.2 kernels have proven to be much
		echo more reliable than 2.0.x kernels on the sparc platform
		echo anyway, so an upgrade is suggested. If you have a 2.1.x
		echo kernel is is suggested you upgrade to the latest 2.2
		echo release, since it is more stable and fixes many bugs.
		exit 1
	    fi
	fi
    fi
    # HPPA boxes require latest fixes in the kernel to function properly.
    if [ "$realarch" = parisc ]
    then
	if dpkg --compare-versions "$kernel_ver" lt 2.4.17
	then
		echo WARNING: This version of glibc requires that you be running
		echo atleast a 2.4.17 kernel in order to work properly. Earlier
		echo kernels did not provide the proper functionality in order 
		echo for the system to be stable. 
		exit 1
	fi
    fi
    # parisc64 boxes require latest fixes in the kernel 2.4.19-pa17 or later
    # (in 2.4.x), 2.5.53-pa3 or later (in 2.5.x), to function properly.
    # Note that parisc64 kernel version scheme is "`uname -r`-64".
    if [ "$realarch" = parisc64 ]
    then
	if [ $kernel_ver = ${kernel_ver/pa/} ]
	then
	    if dpkg --compare-versions "$kernel_ver" lt 2.4.19-64
	    then
		echo WARNING: This version of glibc requires that you be
		echo running at least a 2.4.19-64 to work properly.
		echo Earlier kernels did not provide the proper functionality
		echo in order for the system to be stable. 
		exit 1
	    fi
	else
	    if dpkg --compare-versions "$kernel_ver" lt 2.4.19-pa17
	    then
		echo WARNING: This version of glibc requires that you be
		echo running at least a 2.4.19-pa17 in \(2.4\) or 2.5.53-pa3 
		echo \(in 2.5\) to work properly.
		echo Earlier kernels did not provide the proper functionality
		echo in order for the system to be stable. 
		exit 1
	    fi
	fi
    fi

    if [ "$realarch" = mips ] \
	&& [ "`dpkg --print-installation-architecture`" = mips ]
    then
	# MIPS (but not mipsel) require a kernel update for the msq fixes.
	if dpkg --compare-versions "$kernel_ver" lt 2.4.22
	then
		echo WARNING: System V message queues require kernel 2.4.22 to
		echo work correctly on this architecture.  Some programs
		echo "(including perl) may not operate correctly."
		exit 1
	fi
    fi

    # amd64 requires 2.6 kernel because we drop to support linuxthreads
    if [ "$realarch" = x86_64 ] \
	&& [ "`dpkg --print-installation-architecture`" = amd64 ]
    then
	if dpkg --compare-versions "$kernel_ver" lt 2.6.0
	then
	    echo WARNING: POSIX threads library NPTL requires 2.6 and
	    echo later kernel on amd64.  If you use 2.4 kernel, please
	    echo upgrade your kernel before installing glibc.
	    exit 1
	fi
    fi
fi



exit 0
