Forum Programmation.c debutant en programmation systeme--Fork--Exec

Posté par  .
Étiquettes : aucune
0
3
déc.
2009

Bonjour,

Etant debutant dans la programmation systeme, j'essaie de resoudre un exercice sur les processus.


Le but de l'exercice est de faire un programme en ligne de commande prenant pour argument une chaine de la forme : " COMMANDE ARGUMENTS &> FICHIER" qui execute COMMANDE ARGUMENT en dirigeant stdin et stderr vers FICHIER.

exemple:
touch dummy
chmod 200 dummy
./programme "cat *.c &> file.out"

qui devrait envoyer dans file.out tous les fichiers avec extension ".c" et un message d'erreur pour le fichier dummy.

Je dois utiliser les fonctions fork, une version d'exec, strtok, et dup/dup2. (2 versions demandées une avec dup une avec dup2)

J'ai codé la version suivante, mais j'ai un souci lorsque j'appelle une commande utilisant un argumant de la forme *.extension comme dans l'exemple ci dessus, pour le reste je pense que ca marche. Le probleme est que je ne vois pas du tout ou est le probleme. Auriez vous une idée ?


Voici ce que j'obtiens avec mon programme:

$ ./programme "cat *.c &> file.out"
$ cat file.out
cat: *.c: Aucun fichier ou dossier de ce type

#include stdlib.h

#include stdio.h
#include unistd.h
#include errno.h
#include sys/wait.h
#include string.h
#include fcntl.h


void usage()
{
fprintf(stderr,"Usage: execute \"command argument &> file\"\n");
exit(1);
}
int main(int argc, char * argv[])
{
char *command,*currStr;
char * fileName;
int fd,i;
char ** arg=NULL;
pid_t exc=0;

if (argc!=2) usage();

command = strtok(argv[1],"&>");
fileName = strtok(NULL,"&> ");


currStr = strtok(command," ");
i=1;
do{

arg=(char**) realloc(arg,i * sizeof(char*));
arg[i-1]=currStr;
i++;
currStr=strtok(NULL," ");
} while(currStr!=NULL);

arg=(char**) realloc(arg,i * sizeof(char*));
arg[i-1]=NULL;

exc=fork();

if (exc==-1)
{
fprintf(stderr,"error in fork()");
exit(1);
}

if (exc==0)
{
fd=open(fileName,O_WRONLY | O_CREAT | O_APPEND,0644);

if (fd < 0)
{
perror("open");
exit(1);
}
close (STDOUT_FILENO);
close (STDERR_FILENO);
if (dup(fd)
perror ("dup");
exit(1);
}
close(fd);

execvp(arg[0],arg);
printf("brr");
}

wait(NULL);
}
  • # Une petite idée

    Posté par  (site web personnel) . Évalué à 2.

    le shell « a tendance » à transformer les expressions régulières avant de les fournir aux commandes. Par exemple :
    Dans un répertoire contenant deux fichiers :
    a.c
    b.c
    si je fais cat *.c, la commande cat reçoit comme arguments, non pas "*.c" mais "a.c b.c".
    Il me semble que le problème décrit vient de là. Pour éviter que le shell ne fasse la transcription automatique il faut rajouter des quotes : '
    Est-ce que ces considérations résolvent/expliquent partiellement le problème rencontré ?

    « IRAFURORBREVISESTANIMUMREGEQUINISIPARETIMPERAT » — Odes — Horace

    • [^] # Re: Une petite idée

      Posté par  . Évalué à 3.

      à vue de nez c'est plutôt le contraire

      un shell habituel interprète les caractères jokers comme * et les développe en noms de fichiers avant de les envoyer à l'application externe

      ici le programme se contente d'envoyer les astérisques au programme cat qui ne sait pas les interpréter (qui a dit que les chats étaient intelligents ?)
  • # man 3 glob|wordexp

    Posté par  . Évalué à 3.

    Comme souligné précédemment, lorsque tu fais cat *.c, le shell développe le motif en des noms de fichiers existants avant de le donner à manger à cat.
    Pour obtenir un comportement similaire, tu peux utiliser la fonction C ISO fnmatch pour comparer les motifs (à charge pour toi de récupérer les noms de fichiers du répertoire courant), soit la fonction Posix tout-en-un glob.
    Si tu cherches des détails sur le globbing (attention, ce ne sont pas des expressions régulières) ==> man 7 glob
    La version 2001 de Posix offre également la fonction wordexp qui offre l'expansion du tilde et pleins d'autre chose (très pratique pour implémenter un mini shell).


    Autre chose, pour gérer la redirection des flux standards, utilise plutôt dup2, ton code sera plus court et plus explicite.
    dup2(fd,STDOUT_FILENO);
    dup2(fd,STDERR_FILENO);
    • [^] # Re: man 3 glob|wordexp

      Posté par  . Évalué à 1.

      J'ai utilisé wordexp, c'est juste ce que j'avais besoin


      Merci beaucoup !
    • [^] # Re: man 3 glob|wordexp

      Posté par  . Évalué à 0.

      j'ai utilisé wordexp, juste ce que j'avais besoin

      Merci beaucoup pour votre précieuse aide !

Suivre le flux des commentaires

Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.