En guise de rappel sur le langage C, jouons avec les pointeurs... Mais aussi habituons-nous à consulter le manuel de référence 1 et terminons par une réflexion philosophique sur les vertus des appels systèmes comparées aux mérites des fonctions.
Le modèle proposé comporte une erreur, cependant le compilateur accepte cette erreur et mieux, il la corrige (dans les dernières versions du compilateur), donc la compilation et même l’exécution (ce qui est nouveau) se passent bien.
Ce n’est pas une erreur de syntaxe, mais une mauvaise utilisation de pointeur. Examinez le code pour trouver l’erreur et corriger le code afin qu’il soit plus correct.
Résultat attendu :
Fichier xyz: Mode 81ED Taille: 24576 Octets Proprietaire: dupont
Voyez-vous un problème?
Notez que l’explication ici n’est pas du tout la même que celle qui oppose getpwuid()à getpwuid_r().
Un petit shell rien qu’à nous (mais pas très performant).
Travaillez de manière progressive, n’essayez pas de résoudre tous les problèmes à la fois, suivez consciencieusement les consignes de chaque question.
Note : Dans cet exercice on vous demande d’utiliser la valeur retournée par la fonction signal(). On ne veut pas une bidouilles à base de booléen en variable globale ou autre truc du genre... et il n’y a pas non plus besoin de if... Réfléchissez!
Copier le texte du programme 5_1-zomb.c. Compilez, lancez en background, puis faites ps -el après 5 secondes. Vous constatez qu’il existe un processus zomb et que ce dernier a un fils dont l’état est marqué Z et le nom est [defunct]. Ce processus est un zombie process. On ne peut plus s’en débarrasser sans tuer le processus père (avec kill).
Modifier le programme pour qu’à la mort du processus fils, ce dernier ne reste pas en zombie. Vous utiliserez pour cela la fonction signal() et dans un premier temps, le wait() aura NULL comme seul argument.
Quand un processus se termine, le paramètre du exit() de terminaison (il y a toujours un exit(), même si on ne le précise pas explicitement) peut être récupéré par le processus père, dans l’argument du wait(). Ce paramètre peut donner des indications sur la terminaison correcte ou incorrecte du fils. C’est ainsi que toutes les commandes UNIX rendent une information pouvant être testée par l’utilisateur : 0 pour une terminaison correcte (assimilé à VRAI par les shells) et différent de 0 lorsque le travail n’a pas pu être mené à bien par la commande (assimilé à FAUX). Cette valeur est accessible par $? en Bourne Shell ou par $status en C-Shell. Essayez par exemple grep obelix /etc/passwd puis echo $status (ou echo $?). Puis recommencez avec root au lieu de obelix.
Prenez le modèle 5_2-zomb_exit.c. Le paramètre du exit du fils est fourni au programme en premier argument de la ligne de commande (argv[1]). Modifiez ce modèle de manière à récupérer le code de exit du fils dans le père à l’aide de l’argument du wait(). La modification inclura aussi l’obtention par le père du numéro de signal reçu si le fils se termine sur un signal.
Testez le code en lançant le programme avec pour argument un nombre compris entre 0 et 255.
Modifiez la valeur du sleep() dans le fils en lui donnant la valeur 30s. Vous aurez ainsi le temps de retrouver avec ps le numéro du fils dans une autre fenêtre. Tuez le fils en lui envoyant un signal.
Ce programme lit simplement le terminal et donc bloque en lecture en fonctionnement normal. Si on lui passe l’argument true, il appelle fcntl() pour positionner le flag O_NONBLOCK afin de ne plus bloquer.
Compléter l’ébauche fournie pour réaliser le positionnement du flag. (Prier d’ajouter ce flag sans écraser ceux déjà présents.) Vérifier l’effet en utilisant en parallèle le gestionnnaire graphique de processus. Vous pouvez aussi vérifier le fonctionnement en lançant l’exécution via la commande de traçage strace. La commande top donne aussi des indications intéressantes.
Écrire un programme qui crée un tube de communication puis un fils. Le père lit le clavier (fichier standard d’entrée) et écrit dans le tube ce qu’il a lu. Le père est paramétré de telle manière que son fichier standard de sortie soit le tube. Le fils lit son standard d’entrée et il est paramétré de telle manière que celui-ci soit le tube. Il affiche à l’écran ce qu’il a lu.
Vous devez donc créer un tube, puis un fils. Dans les deux processus vous devez tout de suite faire une redirection, standard de sortie dans le père, standard d’entrée dans le fils.
Nous allons développer une petite application qui chiffre un mot de passe entré au clavier. Le chiffrement utilise la fonction classique crypt(). Cette dernière utilise une clé de chiffrement constituée par une chaîne de 2 caractères pouvant être les lettres de l’alphabet en minuscule ou majuscule, un chiffre entre 0 et 9 ou les caractères «.» et «/», soit 64 caractères possibles. Pour calculer la clé on place les caractères dans un tableau et on fait deux fois un tirage aléatoire entre 0 et 63. On utilisera la fonction random() pour faire le tirage, cette fonction rend un entier long, il suffira de prendre le modulo 64 de cet entier.
Pour que le résultat soit vraiment aléatoire il est nécessaire d’armer le dispositif avant le tirage avec la fonction srandom() qui, elle aussi, a besoin d’une graine de départ. Un bon moyen de trouver une graine très variable est de prendre la date en microsecondes avec la fonction gettimeofday().
1.Par exemple : man malloc
2.Note pour les utilisateurs d’Ubuntu : Ubuntu a un comportement non standard et mal documenté concernant le core dump. Certains développeurs ont eu l’idée géniale de détourner la génération de core dump pour envoyer des rapports de bug aux développeurs des applications qui ont plantées (à condition que ce soit une application Ubuntu). C’est le paquet apport qui fait ça. Il est vaguement désactivé par défaut, mais possiblement bloque tout de même la génération des fichiers core dump. Pour retrouver un système Unix conforme à POSIX, soit supprimer
ce paquet apport, soit faire :
sudo sysctl kernel.core_pattern=core
(Voir le man core.)
3.En fait, une telle fonction existe déjà dans la libc (faire man getpass), mais c’est plus rigolo d’essayer de la programmer soi-même, non ?