Bonjour,

Je suis en train de faire les exercices suivants :

Exercice 1 : redirection de la sortie standard¶

Un shell classique permet de rediriger les entrées/sorties standards vers d'autres fichiers, en utilisant les ca*ractères spéciaux < et >. Cette fonctionnalité n'a cependant pas besoin d'être interne au shell : elle peut être implantée avec une syntaxe différente, comme une commande externe.

On vous demande donc d'écrire un programme redir1 qui prenne au minimum deux arguments :

un nom de fichier (existant ou non)

une commande

tous les arguments suivants sont considérés comme des arguments de la commande

Il ouvre en écriture le fichier dont le nom lui est passé en premier argument, et redirige sa propre sortie standard (descripteur de fichier 1) vers ce fichier, à l'aide de la fonction dup2(2). Ensuite, il exécute la commande passée en deuxième arguments, en lui passant tous les arguments suivants le cas échéant.

Notez que si le fichier n'existe pas, il doit être créé ; s'il existe, son contenu doit être remplacé.

On notera que le paramètre argv de la fonction main respecte le format attendu par la fonction execvp(3)@ : il se termine par un pointeur NULL. On rappelle également que si @t est un tableau, t+n est le même ta*bleau privé de ses n premières cases.

Exercice 2 : redirections généralisées¶

En partant du programme redir1 de l'exercice précédent, vous écrirez un programme dont le comportement variera selon le nom sous lequel il est appelé (disponible dans le paramètre argv[0] de la fonction main).

Plus précisément :

s'il est appelé redir0 il redirigera l'entrée standard

s'il est appelé redir1 il redirigera la sortie standard

s'il est appelé redir2 il redirigera l'erreur standard

dans tous les autres cas, il se terminera avec un message d'erreur et un statut différent de zéro.

Notez que, pour lancer votre programme sous des noms différents, vous pouvez au choix :

copier votre fichier exécutable sous les différents noms

créer des liens physiques de votre exécutable sous les différents noms

créer des liens symboliques de votre exécutable sous les différents noms

Dans le rapport, vous discuterez des avantages et des inconvénients des trois options.
Voilà mon code :

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
 
/* Le programme a au minimum deux arguments :
 * - un nom de fichier, existant ou non ;
 * - une commande ;
 * - tous les arguments suivants sont considérés comme des paramètres de la commande.
 * Le programme ouvre en écriture le fichier dont le nom est passé en premier argument sur la ligne de commande
 * et redirige sa propre sortie standard (descripteur de fichier = 1) vers ce fichier à l’aide de l’appel système dup2(2).
 * Ensuite, le programme exécute la commande passée en deuxième argument en lui passant tous les arguments suivants le cas échéant.
 * Si le nom passé en premier argument correspond au nom d’un fichier existant, alors le contenu de ce fichier est écrasé. Sinon, le fichier est créé.
 */
 
#include <unistd.h> // dup2(2),execvp(3),close(2)
#include <sys/types.h> // open(2)
#include <sys/stat.h> // open(2)
#include <fcntl.h> // open(2)
#include <stdio.h>   // perror(3)
#include <string.h>
 
int main(int argn,char** argv)
{
   int desc_fic;
 
   // deux arguments au minimum
   if(argn<3)
   {
      perror("Usage : ./sortie_standard nom_fichier commande [parametres_commande]\n");
      return 1;
   }
 
   // On ouvre le fichier en écriture seulement.
   desc_fic=open(argv[1],O_WRONLY);
   // Si le fichier existe, alors le contenu de ce fichier est écrasé, sinon il est crée en écriture seulement avec des droits en lecture et en écriture pour l'utilisateur.
   if(desc_fic==-1)
   {
      desc_fic=open(argv[1],O_CREAT|O_WRONLY,00600); // 600 = r+w pour l'utilisateur
      // Si on ne réussit pas à créer le fichier destination, on affiche l'erreur et on retourne une valeur non nulle.
      if(desc_fic==-1)
      {
         perror("erreur d'ouverture en ecriture du fichier (creation)\n");
         return 2;
      }
   }
   else
   {
      close(desc_fic);
      desc_fic=open(argv[1],O_CREAT|O_WRONLY|O_TRUNC,00600);
      // Si on ne réussit pas à créer le fichier destination, on affiche l'erreur et on retourne une valeur non nulle.
      if(desc_fic==-1)
      {
         perror("erreur d'ouverture en ecriture du fichier (remise a zero)\n");
         return 2;
      }
   }
 
   // On substitue au descripteur de fichier de la sortie standard le descripteur de fichier ouvert dans le programme.
 
   if(strcmp(argv[0],"redir1")==0) dup2(desc_fic,1);
   else if(strcmp(argv[0],"redir0")==0) dup2(desc_fic,0);
   else if(strcmp(argv[0],"redir2")==0) dup2(desc_fic,2);
 
   // On ferme le fichier.
   close(desc_fic);
 
   //Lorsqu'un programme appelle la fonction execvp(3), le processus cesse immédiatement d'exécuter ce programme et commence l'exécution d'un autre depuis le début, en supposant que l'appel à execvp se déroule correctement.
   // Le premier argument doit pointer sur le nom du fichier associé au programme à exécuter.
   // Le deuxième argument est un tableau de pointeurs qui doit se terminer par un pointeur NULL. Il constitue les arguments disponibles pour le programme à exécuter.
	if(execvp(argv[2],argv+2)==-1) // argv+2 est le tableau de chaînes de caractères argv privé de ses deux premières chaînes
   {
      perror("Erreur : commande incorrecte\n");
      return 3;
   }
 
   return 0;
}
Est-ce que vous pouvez me dire comment je peux tester mon programme pour la redirection de l'entrée standard ? Et aussi, quels sont les avantages et inconvénients du renommage de fichier, du lien symbolique, ou du lien physique ? Merci !