Introduction FAQ TD 1 TD 2 TD 3 TD 4 TD 5 TD 6 TD 7 TD 8
N'oubliez pas de mettre à jour votre archive en téléchargeant
l'archive forum.tar.gz et en y insérant
vos fichiers client.c
, server.c
et
common.c
.
call_pager
) Lorsque l'utilisateur demande à lire un message, notre client ne se contente pas d'écrire le contenu du message sur la sortie standard: il appelle un autre programme, le paginateur (pager), et lui fournit le contenu du message. Le paginateur affiche alors le message par page et permet à l'utilisateur de circuler facilement dans le message.
Pour effectuer cette opération, notre client utilise actuellement
une fonction call_pager(nom_du_fichier)
:
extern int call_pager(char *filename);
qui appelle le paginateur, dont le nom est soit contenu dans la
variable d'environnement PAGER
, soit dans la constante
PAGER
de forum.h
. Le paginateur ne reçoit
pas d'argument, ce qui le force à lire sur son entrée standard le
contenu du message. Finalement, la fonction retourne 0 si tout s'est
bien passé.
Écrivez votre propre fonction call_pager
pour votre
client.
Nouveaux appels système à utiliser: pipe
,
dup
.
Solution: call_pager.c
client_shm_write
) Lorsque l'utilisateur a écrit un nouveau message dans un fichier,
le client doit transférer ce message au serveur pour que celui-ci le
place dans le répertoire des messages. Cette opération est effectuée
en utilisant un segment de mémoire partagé : au démarrage, le serveur
crée un fichier partagé /forum_[login]_shm
(où
[login]
est l'identifiant retourné par
getlogin
, ou contenu dans les variables d'environnement
LOGNAME
ou USER
). Ce fichier est placé en
mémoire par le client, dans un segment de mémoire partagé de taille
MAX_MSG
(voir common.h
), puis utilisé pour y
copier chaque message à transmettre.
Lorsqu'un message doit être envoyé, le client écrit dans ce segment de mémoire le contenu du fichier, préfixé par deux octects indiquant la taille du message, en commençant par l'octect de signification moindre (LSB, Least Significant Byte first).
Pour effectuer cette tâche l'envoi du message, le client appelle
une fonction client_shm_write(filename)
:
extern int client_shm_write(char *filename);
qui écrit le contenu du fichier filename
dans la
mémoire partagée, et retourne 0 lorsque tout s'est bien passé, et une
valeur négative sinon. Vous allez redéfinir cette fonction pour votre
client.
Vous ferez cependant attention à vérifier systématiquement que
filename
n'est pas NULL
. En effet, la
fonction client_shm_write
est appelée au début et à la
fin du programme avec un argument NULL
pour
respectivement initialiser puis terminer la mémoire partagée.
Vous pourrez, dans une première version, effectuer tout le travail au moment où un fichier est fourni en argument. Dans une seconde version, vous pourrez profiter des phases d'initialisaton et de terminaison pour diminuer le travail effectué à chaque appel.
Appels systèmes à utiliser: mmap
,
shm_open
, msync
, munmap
. On
pourra par ailleurs profiter de l'option -v
du serveur
pour obtenir quelques informations sur ce qu'il lit dans la mémoire
partagée.
Solution: client_shm_write.c
server_shm_read
) Le serveur utilise symmétriquement une fonction
server_shm_read(int last_num)
:
extern int server_shm_read(int last_num)
pour lire les messages que les clients écrivent dans la mémoire
partagée. Comme pour le client, cette fonction est appelée une fois à
l'initialisation et à la terminaison du serveur, avec comme argument
-1
. A l'initialisation, le serveur crée le fichier de
partage qui est utilisé par les clients, et le place immédiatement en
mémoire.
Définissez la fonction server_shm_read
de votre
propre client.
search_articles
) Le client permet maintenant de rechercher des mots dans les
messages. En utilisant la commnade f mot
, le client
affiche, pour chaque message contenant le mot mot
, le
numéro du message et la première ligne contenant ce mot (ou les 100
premiers caractères).
Pour effectuer cette opération, le client appelle une fonction
search_articles(directory, mot)
:
extern void search_articles(char *directory, char* mot)
qui scanne le répertoire directory
pour trouver des
articles(fichiers dont le nom est un nombre), et appelle la commande
externe grep
sur chaque article trouvé. Il utilise alors
le résultat et la sortie de la commande pour afficher le résultat pour
l'article traité.
Ecrivez votre propre fonction search_articles
dans
votre client.