#!/bin/sh
# Copyright (C) 2013-2016, Andrea Peluso <sya54m@gmail.com>
# Tutti i diritti riservati.
#
# ___ changelog ___
#
# 2.1.6 (31/10/2016)
# aggiunto misurazione del tempo
#
# 2.1.5 (14/03/2016)
# corretto pulizia vecchio kernel
# aggiornato rilevamento utente
#
# 2.1.4 (08/02/2016)
# corretto aggiornamento bootloader
#
# 2.1.3 (15/12/2015)
# Aggiunto supporto elilo
# Corretto auto rilevazione del bootloader
#
# 2.1.2 (24/11/2015)
# Aggiunto auto esportazione del display per make xconfig
# Aggiunto auto rilevazione del bootloader
#
# 2.1.1 (07/11/2015)
# corretto aggiornamento bootloader su nomi senza tag
#
# 2.1.0 (07/05/2015)
# aggiunto supporto patch non incrementali
# altre piccole modifiche
#
# 2.0.4 (13/04/2015)
# aggiunto supporto kernel diversi da 3.x
#
# 2.0.3 (02/04/2015)
# corretto pulizia vecchio kernel sulle versioni x.x.0
# aggiunto avviso con campanella di sistema a termine compilazione
#
# 2.0.2 (30/09/2014)
# corretto pulizia vecchio kernel sulle versioni x.x.0 e x.x.1
#
# 2.0.1 (02/07/2014)
# corretto aggiornamento bootloader sulle versioni senza fix (x.x.0)
# corretto pulizia vecchio kernel sulle versioni senza fix (x.x.0)
#
# 2.0.0 (28/04/2014)
# rimossa obbligatorietà del parametro versione, rileva dalla rete l'ultima versione stabile
# aggiunta possibilità di specificare il file config anche in caso di non aggiornamento da versione precedente
# aggiunto recupero automatico del config dal vecchio kernel anche se non della stessa serie
# aggiunta informazione sul numero di versione di questo script
# nuovo output di aiuto
# modificata sintassi delle opzioni
#
# 1.2.0 (03/04/2014)
# aggiunto aggiornamento bootloader
# aggiunto eliminazione del vecchio kernel
#
# 1.0.0 (07/12/2013)
# prima versione

TAG=ap

aiuto(){
  echo "Uso: $(basename $0) [OPZIONE]..."
  echo "Procedura automatizzata per la compilazione del kernel Linux."
  echo "Copyright (C) 2013-2016, Andrea Peluso."
  echo -e "\n  -k\tversione del kernel"
  echo -e "  -c\tfile config"
  echo -e "  -v\tstampa le informazioni sulla versione ed esce"
  echo -e "  -h\tmostra questo aiuto ed esce\n"
  echo "Esempi:"
  echo -e "  $(basename $0)\t\t\t\tAggiorna il kernel all'ultima versione stabile"
  echo -e "  $(basename $0) -k 3.14.2\t\tCompila la versione di kernel specificata"
  echo -e "  $(basename $0) -c /home/pippo/config\tCompila la versione di kernel piu' recente utilizzando il config specificato"
  echo -e "\nSegnalare i bug di mkernel a <sya54m@gmail.com>"
  echo -e "Sito web di mkernel: <http://www.sya54m.eu/>\n"
}
if [ "$(whoami)" != "root" ]; then
  echo -e "Permesso negato: eseguire come root.\n"
  exit 1
fi
PRGVER="2.1.6"
VERSION=""
CONFIG=""
while :
do
  case "$1" in
  -k)
    shift
    VERSION=$1
  ;;
  -c)
    shift
    CONFIG=$1
  ;;
  -v)
    echo -e "$(basename $0) $PRGVER\nCopyright (C) 2013-2016, Andrea Peluso."
    exit 0
  ;;
  -h)
    aiuto
    exit 0
  ;;
  -*)
    aiuto
    exit 1
  ;;
  *)
    break
  ;;
  esac
  shift
done
if [ "x$VERSION" == "x" ]; then
  VERSION=$(curl 'https://www.kernel.org/releases.json' |grep -Pom1 '(?<="version": ")[^"]*')
fi
VERSION2=$(echo $VERSION |cut -d. -f1,2)
FIXVERSION=$(echo $VERSION |cut -d. -f3)
if [ $(expr $FIXVERSION \+ 0) -eq 0 ]; then
  FIXVERSION=0
elif [ $FIXVERSION -gt 1 ]; then
  PREVERSION=$VERSION2.$(expr $FIXVERSION - 1)
else
  PREVERSION=$VERSION2
fi
CURVERSION=$(ls -d /usr/src/linux-$VERSION2* |cut -d- -f2 2> /dev/null)
FIXCURVERSION=$(echo $CURVERSION |cut -d. -f3)
if [ $(expr $FIXCURVERSION \+ 0) -eq 0 ]; then
  FIXCURVERSION=0
fi
MAGVERSION=$(echo $VERSION |cut -d. -f1)
if [ "$MAGVERSION" -lt "3" ]; then
  URLVERSION="v$VERSION2"
else
  URLVERSION="v$MAGVERSION.x"
fi
if [ -z "$ARCH" ]; then
  case "$( uname -m )" in
  i?86) ARCH=x86 ;;
     *) ARCH=$( uname -m ) ;;
  esac
fi
NJOBS=$(expr `cat /proc/cpuinfo |grep "siblings" |sort -u |cut -d: -f2` + 1)
CWD=$(pwd)
RVER=$(uname -r |cut -d- -f1)
RTAG=$(uname -r |cut -d- -f2)
RFVER=$(echo $RVER |cut -d. -f3)
if [ $RFVER == "0" ]; then
  RVER0=$(echo $RVER |sed s/..$//)
else
  RVER0=$RVER
fi
cd $CWD
if [ -r /usr/src/linux-$VERSION ]; then
  cd /usr/src/linux-$VERSION
  make clean
  if [ -r $CONFIG ] && [ "x$CONFIG" != "x" ]; then
    cp $CONFIG /usr/src/linux-$VERSION/.config
  fi
elif [ -r /usr/src/linux-$PREVERSION ]; then
  if [ $FIXVERSION -gt 1 ]; then
    if [ ! -f $CWD/patch-$PREVERSION-$FIXVERSION.xz ]; then
      wget https://www.kernel.org/pub/linux/kernel/$URLVERSION/incr/patch-$PREVERSION-$FIXVERSION.xz
    fi
  else
    if [ ! -f $CWD/patch-$VERSION.xz ]; then
      wget https://www.kernel.org/pub/linux/kernel/$URLVERSION/patch-$VERSION.xz
    fi
  fi
  cd /usr/src/linux-$PREVERSION
  make clean
  if [ -r $CONFIG ] && [ "x$CONFIG" != "x" ]; then
    cp $CONFIG /usr/src/linux-$VERSION/.config
  fi
  if [ $FIXVERSION -gt 1 ]; then
    xzcat $CWD/patch-$PREVERSION-$FIXVERSION.xz |patch -p1
  else
    xzcat $CWD/patch-$VERSION.xz |patch -p1
  fi
  if [ ! -f $CWD/patch-$VERSION.xz -a ! -f $CWD/patch-$PREVERSION-$FIXVERSION.xz ]; then
    echo -e "Errore: patch non trovata!\n"
    exit 1
  fi
  cd ..
  mv linux-$PREVERSION linux-$VERSION
elif [ "x$CURVERSION" != "x" ]; then
  if [ ! -f $CWD/patch-$CURVERSION.xz -a $FIXCURVERSION -gt 0 ]; then
    wget https://www.kernel.org/pub/linux/kernel/$URLVERSION/patch-$CURVERSION.xz
  fi
  if [ ! -f $CWD/patch-$VERSION.xz ]; then
    wget https://www.kernel.org/pub/linux/kernel/$URLVERSION/patch-$VERSION.xz
  fi
  cd /usr/src/linux-$CURVERSION
  make clean
  if [ -r $CONFIG ] && [ "x$CONFIG" != "x" ]; then
    cp $CONFIG /usr/src/linux-$VERSION/.config
  fi
  if [ $FIXCURVERSION -gt 0 ]; then
    xzcat $CWD/patch-$CURVERSION.xz |patch -R -p1
    if [ ! -f $CWD/patch-$CURVERSION.xz ]; then
      echo -e "Errore: patch non trovata!\n"
      exit 1
    fi
  fi
  xzcat $CWD/patch-$VERSION.xz |patch -p1
  if [ ! -f $CWD/patch-$VERSION.xz ]; then
    echo -e "Errore: patch non trovata!\n"
    exit 1
  fi
  cd ..
  mv linux-$CURVERSION linux-$VERSION
else
  if [ ! -f $CWD/linux-$VERSION.tar.xz ]; then
    wget https://www.kernel.org/pub/linux/kernel/$URLVERSION/linux-$VERSION.tar.xz
  fi
  cd /usr/src
  tar xf $CWD/linux-$VERSION.tar.xz || exit 1
  if [ -r $CONFIG ] && [ "x$CONFIG" != "x" ]; then
    cp $CONFIG /usr/src/linux-$VERSION/.config
  elif [ -r /usr/src/linux-$RVER0/.config ]; then
    cp /usr/src/linux-$RVER0/.config /usr/src/linux-$VERSION/.config
  elif [ -r /boot/config-huge* ]; then
    cp /boot/config-huge* /usr/src/linux-$VERSION/.config
  else
    if [ $ARCH == "x86_64" ]; then
      wget http://ftp.slackware.com/pub/slackware/slackware64-current/kernels/huge.s/config -O /usr/src/linux-$VERSION/.config
    else
      wget http://ftp.slackware.com/pub/slackware/slackware-current/kernels/hugesmp.s/config -O /usr/src/linux-$VERSION/.config
    fi
  fi
fi
cd /usr/src/linux-$VERSION
utente=$(who |grep ":0" |cut -d" " -f1 |uniq)
if [ "$utente" != "root" -a -n "$DISPLAY" ]; then
	cp /home/$utente/.Xauthority /root/.Xauthority
fi
make xconfig || make gconfig || make menuconfig || make config
INIZIO=$(date +"%s")
make -j$NJOBS || exit 1
TEMPO=$(expr `date +"%s"` - $INIZIO)
make firmware_install
make headers_install
rm -rf /lib/modules/$VERSION-$RTAG* 2> /dev/null
make modules_install
cp System.map /boot/System.map-$VERSION-$TAG
cp arch/$ARCH/boot/bzImage /boot/vmlinuz-$VERSION-$TAG
echo -e "\nTempo di compilazione: $(expr $TEMPO / 60) minuti e $(expr $TEMPO % 60) secondi"
echo -e "\aKernel installato con successo.\nVuoi aggiornare il bootloader? [Si | No] "
while [ true ]
do
  read -n 1 -s bootsn
  if [ $bootsn == "s" -o $bootsn == "S" ]; then
    DIS=$(cat /etc/mtab |grep " / " |cut -d" " -f1 |sed s/.$//)
    MBR=$(dd if=$DIS bs=446 count=1 2> /dev/null |strings)
    if [ -n "`echo $MBR |grep -i grub`" ]; then
      bootconf="/boot/grub/grub.cfg"
    elif [ -n "`echo $MBR |grep -i elilo`" ]; then
      bootconf="/etc/elilo.conf"
    elif [ -n "`echo $MBR |grep -i lilo`" ]; then
      bootconf="/etc/lilo.conf"
    else
      echo -e "Errore nel rilevamento del bootloader.\nSelezione manuale:\n1. LILO\n2. ELILO\n3. GRUB"
      while [ true ]
      do
        read -n 1 -s bootlg
        if [ $bootlg == "1" ]; then
          bootconf="/etc/lilo.conf"
          break
        elif [ $bootlg == "2" ]; then
          bootconf="/etc/elilo.conf"
          break
        elif [ $bootlg == "3" ]; then
          bootconf="/boot/grub/grub.cfg"
          break
        else
          echo "Scelta non valida."
        fi
      done
    fi
    if [ ! -r $bootconf ]; then
      echo -e "\E[031;1mErrore: il file atteso $bootconf non esiste.\E[031;0m"
      exit 1
    fi
    if [ -n "`cat $bootconf |grep $RVER-$RTAG`" ]; then
      sed -i "s|$RVER-$RTAG|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep $RVER-$TAG`" ]; then
      sed -i "s|$RVER-$TAG|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep $RVER0-$RTAG`" ]; then
      sed -i "s|$RVER0-$RTAG|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep $RVER0-$TAG`" ]; then
      sed -i "s|$RVER0-$TAG|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep huge-$RVER`" ]; then
      sed -i "s|huge-$RVER|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep huge-$RVER0`" ]; then
      sed -i "s|huge-$RVER0|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep generic-$RVER`" ]; then
      sed -i "s|generic-$RVER|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep generic-$RVER0`" ]; then
      sed -i "s|generic-$RVER0|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep $RVER`" ]; then
      sed -i "s|$RVER|$VERSION-$TAG|g" $bootconf
    elif [ -n "`cat $bootconf |grep $RVER0`" ]; then
      sed -i "s|$RVER0|$VERSION-$TAG|g" $bootconf
    fi
    if [ $bootconf == "/etc/lilo.conf" ]; then
      /sbin/lilo
    elif [ $bootconf == "/etc/elilo.conf" ]; then
      /sbin/elilo --efiboot
    fi
    echo "Fatto."
    break
  elif [ $bootsn == "n" -o $bootsn == "N" ]; then
    break
  else
    echo "Scelta non valida."
  fi
done
if [ $VERSION != $RVER ] && [ $VERSION != $RVER0 ]; then
  echo -e "Vuoi eliminare il vecchio kernel? [Si | No] "
  while [ true ]
  do
    read -n 1 -s puliscisn
    if [ $puliscisn == "s" -o $puliscisn == "S" ]; then
      rm -rf /lib/modules/$RVER-$RTAG 2> /dev/null
      if [ $RFVER == "0" ]; then
        rm /boot/*-$RVER0-* /boot/*-$RVER0.0-* 2> /dev/null
      else
        rm /boot/*-$RVER-* 2> /dev/null
      fi
      echo "Fatto."
      break
    elif [ $puliscisn == "n" -o $puliscisn == "N" ]; then
      break
    else
      echo "Scelta non valida."
    fi
  done
fi
