#!/bin/bash version="1.5.2.4" function license_notice { echo " Hello $(whoami) ($UID) @ $HOSTNAME" cat << EOF Noyau (french word for kernel) v$version, written by RIQUER Vincent. It's part of the Labapus (Linux Administration Bash And Perl Scripts) Project. Noyau v$version is aimed to ease the compilation of the Linux kernel. Copyright (C) 2002 RIQUER "script.fan" Vincent This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA EOF } # New experimental code using getopts args="$@" # Credits to Christophe Blaess # Code directly taken from his excellent book "Langages de scripts sous Linux" # edited by Eyrolles while getopts "bcd:e:fikmnprv-:" opt ; do case $opt in b) task=comp ; echo "-b -> Compile, install" ;; c) task=conf ; echo "-c -> Configure, compile, install" ;; d) sources=$OPTARG ; echo "-d -> Sources : $sources" ;; e) EDITOR=$OPTARG ; echo "-e -> editor : $EDITOR" ;; f) noclean=0 ; echo "-f -> don't run mrproper (discouraged unless used together with -m" ;; i) task=inst ; echo "-i -> Install" ;; k) use_proc=0; echo "-k -> use /proc/config.gz" ;; m) task=mod ; echo "-m -> Add modules" ;; n) no_license_notice=0 ;; # Yes, this is a undocumented option # to prevent our script from printing # its license 2 times when launched # as user and using the su capability p) pretend=0 ; echo "-p -> Virtual mode : don't do anything, only print what would have been done" ;; r) task=deb ; echo "-r -> Build debian package of the kernel" ;; v) verbose=0 ; echo "-v -> Verbose" ;; -) case $OPTARG in no-color) color=0 echo "--no-color -> black/white output" ;; text) compile=config echo "--text -> make config" ;; menu) compile=menuconfig echo "--menu -> make menuconfig" ;; x) compile=xconfig echo "--x -> make xconfig" ;; gtk) compile=gconfig echo "--gtk -> make gconfig" ;; deb) task=deb echo "--deb -> make-kpkg" ;; help) cat << EOF usage : -c : configure, then build, then install -b : build, then install -r : build debian package of the kernel -m : add modules to a previously installed kernel -i : install an already compiled kernel -f : don't run make mrproper -k : use /proc/config.gz instead of /root/saved-config. Falls back on /root/saved-config if CONFIG_IKCONFIG_PROC is not set in your kernel. -e : specify your preferred text editor (you may have to edit the config file for your boot loader (default : \$EDITOR or vim) -d : specify a path for kernel sources (default : /usr/src/linux). --no-color : disable colored output --text : configure using make config --menu : configure using make menuconfig --x : configure using make xconfig --gtk : configure using make gconfig -p : don't do anything (for devs and testers) [ these two might ] -v : verbose mode [ need some testing ] --help : you guessed ;) EOF exit 0 ;; esac esac done if [ $noclean ]; then echo "WARNING: The use of -f is discouraged unles you're only adding modules" sleep 5 fi if [ $no_license_notice ]; then echo "Your UID is $UID, you are $(whoami) on $HOSTNAME"; else license_notice; fi; # If $EDITOR is set neither by command line option nor environment, default to # vim MY preferred text editor... nano is fine too ;) ## Yam, you'd better use vim ;) if [[ $EDITOR == "" ]]; then EDITOR='vim'; fi ################################################################################ # Function declarations # ################################################################################ if [ $color ]; then function color { # We do not want colored output so we make color a dummy a=a # function } else function color { setterm $@ } fi function error { # This is called when any important command called by the set +x # script fails echo $'\a' color -background red cat << EOF Exit status of the previously executed command wasn't 0. This means there probably was an error. To prevent undesired effects, I stop when a command returns a non-zero status. Hope you'll be able to resolve the problem, Bye ! EOF color -background black echo -e "\n" exit 1 } function execute { # By using this function as a wrapper, we if [ $pretend ]; then # are able to work in normal, verbose, or echo -e "\n [not executed] $@" # don't-do-anything modes read -p "[ press return ]" elif [ $verbose ];then echo " + $@" bash -c "$@" || error else bash -c "$@" || error fi } function root { read -n 1 -p "Do you want to start a su session now ? [y/n] " echo "" case $REPLY in 'y') su -c "$0 -n $args" ;; 'n') exit 1 ;; *) root ;; esac exit } function whattodo { cat << EOF What do you want me to do ? 1) Configure, compile and install 2) Compile and install 3) Build debian package 4) Add / remove modules 5) Install only EOF read -n 1 case $REPLY in '1') task=conf ;; '2') task=comp ;; '3') task=deb ;; '4') task=mod ;; '5') task=inst ;; *) whattodo ;; esac echo "" } function usage { cat << EOF t - text - for configuration in text mode without ncurses (config) m - menu - for a nice ncurses text mode menu configuration (menuconfig) X - X11 - for a fully graphical configuration. X has to be started. (xconfig) g - GTK - GTK-based config (on 2.6 xconfig is written in QT) (gconfig) EOF read -n 1 -p "Pick one [t/m/X] : " case $REPLY in 't') compile=config ;; 'm') compile=menuconfig ;; 'X') compile=xconfig ;; 'g') compile=gconfig ;; *) echo "" usage ;; esac echo "" } function source_dir { cat << EOF Your kernel sources are not in /usr/src/linux. You should at least have a symbolic link /usr/src/linux pointing to the sources of the kernel you want to compile and use, or else you'll have troubles each time you'll try to compile anything. I can help you create a symlink to your source directory EOF read -p "Where are the unpacked kernel sources ? " echo "" if [ -d $REPLY ]; then sources=$REPLY; else source_dir fi } function edit_xtraver { XTRVER=$(cat $sources/Makefile | grep -x "EXTRAVERSION = .*") XTRVER=${XTRVER#*= } read -n 1 -p "The kernel extraversion is now set to \"$XTRVER\". Do you want to change it ? [y/n] " echo case $REPLY in 'y') read -p "What do you want to change this for ? " echo execute "sed -e s/EXTRAVERSION\ =\ *$XTRVER/EXTRAVERSION\ =\ $REPLY/ $sources/Makefile > Makefile.tmp" execute "mv -f Makefile.tmp $sources/Makefile" edit_xtraver ;; 'n') ;; *) edit_xtraver ;; esac } ## TODO: GNU Grub auto configuration function deb_pkg { ## Path to needed files MAKE_KPKG=$(which make-kpkg) CHANGELOG=debian/changelog APT_get=$(which apt-get) DPKG=$(which dpkg) if [ -z "$DPKG" ]; then echo "You must running on Debian in order to use this backend..." exit 1 fi ## ``make-kpkg'' is needed for debian kernel compilation if [ -z "$MAKE_KPKG" ]; then echo "You must install ``kernel-package'' debian package." function deb_choose_again { read -n 1 -p "Do you want to install this package right now ? [y/n] " echo case $REPLY in y) $APT_GET install kernel-package;; n) exit 1;; *) choose_again;; esac } deb_choose_again fi execute "${MAKE_KPKG} clean" function deb_choose_revision { read -p "Specify a number for revision ? [1-9] " ## TODO: > 9 revision number echo case $REPLY in [1-9]) revision=${REPLY};; *) deb_choose_revision;; esac } ## We need a ``debian/'' directory too if [ ! -d ${sources}/debian ]; then echo "Preparing kernel source tree" rm -rf ${sources}/debian deb_choose_revision execute "${MAKE_KPKG} --revision=${kversion}-$revision debian" echo "." else revision=$(head -n 1 ${sources}/debian/changelog | awk '{print $2}' | sed 's/(\|)//g') if echo "${revision##*-}" | egrep -q '[[:digit:]]'; then echo "You must specify a number for revision" deb_choose_revision fi fi # FIXME: more accurate choice of build packages execute "$MAKE_KPKG --revision=${kversion}-${revision} binary" for pkg in ../kernel-*-${kversion}_${kversion}-${revision}_*.deb; do function deb_choose_pkg { read -n 1 -p "Should i install ``$pkg'' ? [y/n] " echo case $REPLY in 'y') execute "$DPKG -i $pkg";; 'n') continue;; *) deb_choose_pkg;; esac } deb_choose_pkg done } function kernel_version { echo "Checking version of $sources..." if [ -r $sources/Makefile ]; then MAJVER=$(cat $sources/Makefile | grep -x "VERSION = .*") export MAJVER=${MAJVER#*= } PTCHVER=$(cat $sources/Makefile | grep -x "PATCHLEVEL = .*") export PTCHVER=${PTCHVER#*= } SUBLEV=$(cat $sources/Makefile | grep -x "SUBLEVEL = .*") export SUBLEV=${SUBLEV#*= } XTRVER=$(cat $sources/Makefile | grep -x "EXTRAVERSION = .*") export XTRVER=${XTRVER#*= } export kversion="$MAJVER.$PTCHVER.$SUBLEV$XTRVER" fi if [ $? == 0 ]; then read -n 1 -p "The version of the kernel in $sources is $kversion. Is this OK ? [y/n] " echo "" case $REPLY in 'y') ;; 'n') echo "Argh !" function choose_again { read -n 1 -p "Do you want to choose another one ? [y/n] " echo case $REPLY in 'y') source_dir # kernel_version ;; 'n') exit 1 ;; *) choose_again ;; esac } choose_again ;; *) kernel_version ;; esac if [[ $task == "comp" ]] || [[ $task == "conf" ]]; then edit_xtraver; fi else echo "$sources doesn't contain the kernel sources" source_dir fi } function symlink { echo "Do you want me to create a symlink (/usr/src/linux) pointing to $sources ?" read -n 1 -p "[y/n] " echo "" case $REPLY in 'y') execute "ln -s $sources /usr/src/linux" ;; 'n') ;; *) symlink ;; esac } function clean_confirm { if [ -f $sources/.config ]; then cat << EOF I'm going to clean the source directory (make mrproper), but I found a .config file in it. This means you probably have configured this kernel before. If I run make mrproper, the .config will be lost. But - how lucky you are - I can save it now ! EOF if [ ! $use_proc ]; then if [ -f /root/saved-config ]; then if [[ $(md5sum $sources/.config | sed 's/ .*//' ) == $(md5sum /root/saved-config | sed 's/ .*//' ) ]]; then echo "The .config found in $sources and /root/saved-config are identical."; else echo "I found a saved config file /root/saved-config, which is the place where I save config files, but this kernel's .config and /root/saved-config differs." fi else echo -e "I found no saved kernel config. You'd better answer yes to the following\nquestion." fi read -n 1 -p "Do you want me to copy the .config in /root/saved-config ? [y/n] " echo "" case $REPLY in 'y') execute "cp $sources/.config /root/saved-config" echo "Don't worry, it's safe :)" ;; 'n') echo "OK as you wish..." ;; *) clean_confirm ;; esac else echo -e "Anyway, we're going to use /proc/config.gz... No need to save the config, just\nkeep using /proc/config.gz ;)" fi fi } function config_file { read -p "Type the complete path to your saved config file or type none : " case $REPLY in 'none') echo "Starting from default config" ;; *) if [ -r $REPLY ]; then execute "cp $REPLY .config" echo "$REPLY successfully loaded"; else echo "$REPLY : No such file or invalid permissions" config_file fi ;; esac echo "" } function ask_lilo { read -n 1 -p "Do you use LILO ? [y/n] " echo "" case $REPLY in 'y') cat << EOF Now you should add an entry in your /etc/lilo.conf pointing to your old kernel that you should label 'rescue' or anything like this in case the new one don't work. Your new kernel is $kernel Your old kernel is $kernel.old EOF read -n 1 -p "Do you want to edit your /etc/lilo.conf now (RECOMMENDED) ? [y/n] " case $REPLY in 'y') execute "$EDITOR /etc/lilo.conf" ;; 'n') ;; *) echo "" ask_lilo ;; esac color -foreground blue echo "" echo "Reinstalling LILO boot loader" execute lilo ;; 'n') read -n 1 -p "Do you use grub ? [y/n] " echo case $REPLY in 'y') echo read -n 1 -p "Do you want to edit your /boot/grub/grub.conf ?" echo case $REPLY in 'y') execute "$EDITOR /boot/grub/grub.conf";; 'n');; *) echo "" ask_lilo ;; esac esac ;; *) ask_lilo ;; esac } function ask_reboot { echo "" echo "Time needed to compile your kernel :" times echo "" read -n 1 -p "Do you want to reboot now ? [y/n] " case $REPLY in 'y') echo "" # echo "It has taken $(times) to compile the kernel !" execute "/sbin/shutdown -r now \"Thanks for using Noyau v$version. See you soon :)\"" ;; 'n') echo "" # echo "It has taken $(times) to compile the kernel !" echo "Thanks for using Noyau v$version. See you soon :)" ;; *) echo "" ask_reboot ;; esac } ################################################################################ # The code, the real one # ################################################################################ color -foreground blue if [ ! $UID == 0 ]; then color -background red echo -e "\a" echo "You MUST be root to compile the kernel !" color -background black echo "" root; fi if [ ! $task ] ; then # if the user didn't specify anything on the command-line whattodo # We ask him what he wants us to do fi if [ $sources ]; then if [ ! -d $sources ]; then echo "You specified a non-existing directory !" exit 1 fi elif [ -d /usr/src/linux ]; then sources=/usr/src/linux; else source_dir # tell me where the sources are ! symlink fi # But we ask the user if it's the right sources we're going to compile kernel_version cd $sources if [[ $task == "conf" || $task == "mod" ]] ; then # Checking which configure method the user wants us to launch if [ ! $compile ] ; then usage ; fi # We want to clean the source dir, but if the sources have already been # configured, this will erase the .config. We propose to save it. if [ ! $noclean ]; then clean_confirm echo "Cleaning the source directory from any binary" execute "make mrproper > /dev/null 2> /dev/null" fi # Loading old config if it exists, and if we can't find it, we ask the user if # he wants to use a saved config file and which one. if [ $use_proc ] && [ -f /proc/config.gz ]; then execute "gunzip -c /proc/config.gz > .config" elif [ -f /root/saved-config ]; then echo "Loading saved kernel configuration" execute "cp /root/saved-config .config" else echo $'\a' color -background red cat << EOF No saved configuration found, Hoping this is OK. Noyau v$version assumes you saved your last kernel config in /root/saved-config, and copy the configuration to this file when config is over. If you saved your configuration in another place, you can always import it using the "Load saved configuration file" function in the configuration menu. EOF color -background black echo "" config_file fi # this is make config/menuconfig/xconfig echo "Loading configuration interface..." execute "make $compile" color -foreground yellow echo "Saving config in /root/saved-config" execute "cp -f .config /root/saved-config" fi if [[ $task = "comp" || $task = "conf" || $task = "deb" ]] ; then color -foreground black -background white cat << EOF OK, now compiling the sources. Standard output is redirected to /dev/null and errors are logged in /root/erreurs-noyau.log (there are always errors when compiling a kernel, but if the sources are clean and you didn't make any mistakes, it would be fine). Two seperated bips and three unseperated bips will warn you when compilation is finished. I suggests you to take a book or to go to the pub or, if your machine is fast, just make a cup of green tea and put some ginger in it (directly in your Tux decorated mug). You'll see it's delicious :) EOF color -foreground green -background black echo "" echo "" echo "Let's go !" echo "" if [[ $task = "deb" ]]; then echo "=================================MAKE-KPKG=======================================" echo "=================================MAKE-KPKG=======================================" > /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log deb_pkg else if [ $MAJVER -eq "2" ]; then if [ $PTCHVER -le "4" ]; then echo "=================================MAKE DEP=======================================" echo "=================================MAKE DEP=======================================" > /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make dep > /dev/null 2>> /root/erreurs-noyau.log" echo "" >> /root/erreurs-noyau.log echo "===============================MAKE BZIMAGE=====================================" echo "===============================MAKE BZIMAGE=====================================" >> /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make bzImage > /dev/null 2>> /root/erreurs-noyau.log" echo "" >> /root/erreurs-noyau.log echo "===============================MAKE MODULES=====================================" echo "===============================MAKE MODULES=====================================" >> /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make modules > /dev/null 2>> /root/erreurs-noyau.log" echo "" >> /root/erreurs-noyau.log echo "============================MAKE MODULE_INSTALL=================================" echo "============================MAKE MODULE_INSTALL=================================" >> /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make modules_install > /dev/null 2>> /root/erreurs-noyau.log" echo "" >> /root/erreurs-noyau.log elif [ $PTCHVER -eq "6" ]; then echo -e "Detected new 2.6 kernel...\nmaking all then modules_install" echo "======================================MAKE======================================" echo "======================================MAKE======================================" >> /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make > /dev/null 2>> /root/erreurs-noyau.log" echo "" >> /root/erreurs-noyau.log echo "============================MAKE MODULE_INSTALL=================================" echo "============================MAKE MODULE_INSTALL=================================" >> /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make modules_install > /dev/null 2>> /root/erreurs-noyau.log" echo "" >> /root/erreurs-noyau.log else color -background red echo "I don't know this kernel. Try compiling manually or modifying Noyau to support this kernel" color -background black -foreground white exit 1 fi else color -background red echo "I don't know this kernel. Try compiling manually or modifying Noyau to support this kernel" color -background black -foreground white exit 1 fi fi fi if [[ $task = "mod" ]] ; then if [ $PTCHVER -le "4" ]; then echo "=================================MAKE DEP=======================================" echo "=================================MAKE DEP=======================================" >> /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make dep > /dev/null 2>> /root/erreurs-noyau.log" fi echo "===============================MAKE MODULES=====================================" echo "===============================MAKE MODULES=====================================" >> /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make modules > /dev/null 2>> /root/erreurs-noyau.log" echo "" >> /root/erreurs-noyau.log echo "============================MAKE MODULE_INSTALL=================================" echo "============================MAKE MODULE_INSTALL=================================" >> /root/erreurs-noyau.log echo "" >> /root/erreurs-noyau.log execute "make modules_install > /dev/null 2>> /root/erreurs-noyau.log" fi color -foreground blue cat << EOF ====================================== OK ====================================== ================================ DONE COMPILING ================================ EOF if [[ $task = "conf" || $task = "comp" || $task = "inst" ]] ; then # We need to know where does the user saves his kernel. First tests usual # places, then asks the user case $XTRVER in '') if [ -f /vmlinuz ]; then kernel=/vmlinuz; elif [ -f /boot/vmlinuz ]; then kernel=/boot/vmlinuz; elif [ -f /boot/kernel-$(uname -r) ]; then kernel=/boot/kernel-$kversion; else echo "I'm in trouble... I don't know where you want me to put your brand new kernel... ($kversion)" read -p "Where do I have to put it ? " echo kernel=$REPLY fi ;; *) if [ -f /vmlinuz$XTRVER ]; then kernel=/vmlinuz$XTRVER; elif [ -f /boot/vmlinuz$XTRAVER ]; then kernel=/boot/vmlinuz$XTRAVER; elif [ -f /vmlinuz ]; then kernel=/boot/vmlinuz$XTRAVER dontmv='1'; elif [ -f /boot/vmlinuz ]; then kernel=/boot/vmlinuz$XTRAVER dontmv='1'; elif [ -f /boot/kernel-$(uname -r) ]; then kernel=/boot/kernel-$kversion; else echo "I'm in trouble... I don't know where you want me to put your brand new kernel... ($kversion). I suggest you to append the EXTRAVERSION ($XTRVER) to the name." read -p "Where do I have to put it ? " echo kernel=$REPLY fi ;; esac #if [ $XTRAVER != "" ]; then # if [ -f /vmlinuz$XTRAVER ]; then # kernel=/vmlinuz$XTRAVER; # elif [ -f /boot/vmlinuz$XTRAVER ]; then # kernel=/boot/vmlinuz$XTRAVER; # elif [ -f /vmlinuz ]; then # kernel=/vmlinuz$XTRAVER; # elif [ -f /boot/vmlinuz ]; then # kernel=/boot/vmlinuz$XTRAVER; # else # echo "I'm in trouble... I don't know where you want me to put your brand new kernel... ($kversion)" # read -p "Where do I have to put it ? " # echo # kernel=$REPLY # fi #else # if [ -f /vmlinuz ]; then # kernel=/vmlinuz; # elif [ -f /boot/vmlinuz ]; then # kernel=/boot/vmlinuz; # else # echo "I'm in trouble... I don't know where you want me to put your brand new kernel... ($kversion)" # read -p "Where do I have to put it ? " # echo # kernel=$REPLY # fi #fi if [ -f $kernel ]; then execute "mv -f $kernel ${kernel}.old" echo "Your old kernel, which had the same name as the new one, has been moved to ${kernel}.old"; fi execute "cp $sources/arch/i386/boot/bzImage $kernel 2>> /root/erreurs-noyau.log" echo "" >> /root/erreurs-noyau.log if [ -f /boot/System.map-$kversion ]; then execute "mv /boot/System.map-$kversion /boot/System.map-$kversion.old 2>> /root/erreurs-noyau.log" fi echo "" >> /root/erreurs-noyau.log execute "cp $sources/System.map /boot/System.map-$kversion 2>> /root/erreurs-noyau.log" # 5 bips to warn you that compilation is achieved and lilo.conf is opened for # editing echo -n $'\a' sleep 2 echo -n $'\a' sleep 2 echo -n $'\a' sleep 1 echo -n $'\a' sleep 1 echo -n $'\a' ask_lilo ask_reboot elif [[ $task = "mod" ]]; then execute "/sbin/depmod -a" fi color -foreground white