Création du script rc

Le premier script de démarrage important est /etc/init.d/rc. Le script /etc/init.d/rc est créé en lançant la commande suivante:

cat > /etc/init.d/rc << "EOF"
#!/bin/sh
# Début /etc/init.d/rc
#
# Par Jason Pearce  - jason.pearce@linux.org
# Modifié par Gerard Beekmans - gerard@linuxfromscratch.org
# print_error_msg basé sur des idées de Simon Perreault -
# nomis80@videotron.ca
#

#
# Inclut les fonctions déclarées dans le fichier /etc/init.d/functions
#

source /etc/init.d/functions

#
# La fonction print_error_msg affiche un message d'erreur quand survient une
# erreur imprévue qui, pour une raison ou une autre n'a pas été captée par
# l'appel à evaluate_retval ou encore par la vérification d'erreur.
# 

print_error_msg()
{

        echo
        $FAILURE
        echo -n "Vous ne devriez par lire ce message d'erreur. Cela indique "
        echo "qu'il y a une erreur "
        echo -n "imprévue et que le script $i s'est arrêté avec une"
        echo "la valeur de retour "
        echo -n "$error_value une raison inconnue. Si vous êtes capable de "
        echo "relier cette erreur "
        echo -n "à un bogue dans un des fichiers de ce livre, ça serait "
        echo "sympa de nous en "
        echo -n "informer à lfs-dev@linuxfromscratch.org"
        $NORMAL
        echo
        echo
        echo "Pressez une touche pour continuer..."
        read

}

#
# Si vous retirez les commentaires devant la variable debug ci-dessous, aucun
# des scripts ne sera exécuté, seuls les noms des scripts ainsi que leurs
# paramètres seront affichés à l'écran de telle sorte que vous puissiez
# voir comment ils sont appelés par rc.
#

# Retirez les commentaire ci-dessous pour le débogage.
# debug=echo

#
# Lancement du script ou du programme.
# 
startup() {

        $debug "$@"

}   

#
# Ignore CTRL-C seulement dans ce shell, de telle sorte que
# nous puissions interrompre les sous-processus.
#

trap ":" INT QUIT TSTP

#
# Recherche de l'état actuel du niveau d'exécution ("runlevel") et
# du précédent. La variable $RUNLEVEL est renseignée par init pour tous
# ses fils. Ce script tourne en tant que fils d'init.
#

runlevel=$RUNLEVEL

#
# Récupération du premier argument. Si aucun niveau d'exécution n'est
# passé au script, nous ne changerons pas les niveaux d'exécution.
#

[ "$1" != "" ] && runlevel=$1
if [ "$runlevel" = "" ]
then
        echo "Usage: $0 <runlevel>" >&2
        exit 1
fi

#
# Idem pour $PREVLEVEL (voir au-dessous pour $RUNLEVEL). Cette variable
# accueillera la valeur du précédent niveau d'exécution. Si $PREVLEVEL
# n'a pas de valeur, cela signifie qu'il n'y a pas de niveau
# d'exécution précédent, nous mettons alors la valeur du précédent à N.
#

previous=$PREVLEVEL
[ "$previous" = "" ] && previous=N

export runlevel previous

#
# Existe-il un répertoire rc pour le nouveau niveau d'exécution ?
#

if [ -d /etc/rc$runlevel.d ]

then

#
# Si ce n'est pas le cas, on collecte d'abord tous les scripts K*
# dans le nouveau niveau.
#

        if [ $previous != N ]
        then
                for i in /etc/rc$runlevel.d/K*
                do
                [ ! -f $i ] && continue

#
# Le suffixe de la variable contiendra le nom du script sans l'en-tête
# Kxxx
#

                        suffix=${i#/etc/rc$runlevel.d/K[0-9][0-9][0-9]}
#
# S'il y a un script de départ pour ce script K dans le niveau précédent,
# on détermine quel est son chemin complet
#
            previous_start=/etc/rc$previous.d/S[0-9][0-9][0-9]$suffix
#
# S'il n'y a pas de niveau précédent, c'est peut-être parce que quelque chose
# a pu être demarré dans rcS.d (niveau sysinit), donc nous allons déterminer
# le chemin dans cette éventualité.
#

                        sysinit_start=/etc/rcS.d/S[0-9][0-9][0-9]$suffix

#
# Arrêt du service s'il existe un script de départ dans le niveau d'exécution
# précédent ou dans le niveau sysinit. Si previous_start ou sysinit_start
# n'existent pas, la commande "continue" est lancée, cela force le script
# à interrompre cette itération de la boucle for et à continuer avec la
# prochaine itération.
# On se ramène à ce que ça ne lancera pas les commandes après les deux
# prochaines lines et recommencera ci-dessus pour une boucle. Voir
# le manuel de Bash pour plus d'information.
#

                        [ ! -f $previous_start ] &&
[ ! -f $sysinit_start ] && continue

#
# Si nous avons trouvé previous_start ou sysinit_start, lancement du
# script K
#

                        startup $i stop
                        error_value=$?
#
# Si la valeur retournée par le script n'est pas 0, quelque chose s'est mal
# passé avec le vérificateur d'erreur dans le script. La fonction
# print_error_msg est appelée et le message adapté ainsi que la valeur
# retournée par le script K sont affichés à l'écran.
#

                        if [ $error_value != 0 ]
                        then
                                print_error_msg 
                        fi

                done
        fi

#
# Maintenant, lancement du script START pour ce niveau d'exécution
#

        for i in /etc/rc$runlevel.d/S*
        do
                [ ! -f $i ] && continue

                if [ $previous != N ]
        then
#
# Chercher le script de départ dans le niveau d'exécution précédent et
# arrêter le script dans ce niveau.
#

                        suffix=${i#/etc/rc$runlevel.d/S[0-9][0-9][0-9]}
                        stop=/etc/rc$runlevel.d/K[0-9][0-9][0-9]$suffix
                previous_start=/etc/rc$previous.d/S[0-9][0-9][0-9]$suffix
#
# S'il y a un script de départ dans le niveau précédent et aucun script d'arrêt
# dans ce niveau, nous n'avons pas à relancer le service; interruption de cette
# itération et lancement de la suivante.
#

                        [ -f $previous_start ] && [ ! -f $stop ] && continue
                fi

                case "$runlevel" in
                        0|6)

#
# Les niveaux 0 et 6 sont des niveaux d'arrêt et de redémarrage. Nous ne
# commençons pas vraiment quoi que ce soit ici alors nous passons le paramètre
# "stop".
#

                                startup $i stop
                                error_value=$?
#
# Si la valeur retournée par le script n'est pas 0, quelque chose s'est mal
# passé avec le vérificateur d'erreur dans le script. La fonction
# print_error_msg est appelée et le message adapté ainsi que la valeur
# retournée par le script K sont affichés à l'écran.
#

                                if [ $error_value != 0 ]
                                then
                                        print_error_msg
                                fi
                                ;;
                        *)
                                startup $i start
                                error_value=$?
#
# Si la valeur retournée par le script n'est pas 0, quelque chose s'est mal
# passé avec le vérificateur d'erreur dans le script. La fonction
# print_error_msg est appelée et le message adapté ainsi que la valeur
# retournée par le script K sont affichés à l'écran.
#

                                if [ $error_value != 0 ]
                                then
                                        print_error_msg
                                fi
                                ;;
                esac
        done
fi

# Fin /etc/init.d/rc
EOF