/* Quatrième version du shell yash */
/* Tient compte du & final */
/* Tient compte des redirections <, > */
/* Tient compte des pipes */
#include <fcntl.h>
char cmd[100]; /* La commande lue */
int cmdlg; /* sa taille */
char *targs[20]; /* Les éléments de la commande */
int nb; /* Nb d'éléments dans la commande */
char **args; /* Pointeur de travail vers args */
char *prompt="Commande: ";
int batch; /* indique si on est en mode batch */
int tube[2]; /* tube pour la présence du | */
int status;
/* Rien de changé */
main()
{
while(1)
{
readcmd();
if( strncmp(cmd,"exit",cmdlg)==0 ) exit(0);
decoderCommande();
if (nb>0)
{
traiterBatch();
executerCommande();
}
}
exit(1);
}
/* Rien de changé */
readcmd()
{
write(1,prompt,strlen(prompt));
cmdlg = read(0,cmd,100);
cmd[cmdlg-1]=0;
}
/* Rien de changé */
/* si ce n'est que targs et args pointent vers les élements */
decoderCommande()
{
char *p = cmd;
char *c,*t;
nb = 0;
while (*p != '\0')
{
c = p;
while (*c!=' ' && *c !='\0') c++;
/* copier string */
targs[nb] = (char *) malloc(c-p+1);
t = targs[nb];
for (;p!=c;) *(t++) = *(p++);
*t = '\0';
nb++;
/* Passer les blancs */
while (*p==' ') p++;
}
if (nb==0) return(1);
targs[nb] = 0;
args = targs;
}
traiterBatch()
{
if (strcmp(*(args+nb-1),"&")==0) {
batch = 1;
nb--;
*(args+nb) = 0;
}
else
batch = 0;
}
traiterRedirection()
{
int i,fd;
/* Examiner chaque argument */
for (i=1; i<nb; i++)
{
/* Est-ce qu'il commence par < */
if (**(args+i)=='<')
{
fd = open( *(args+i)+1, O_RDONLY );
if (fd==-1)
printf("%s n'existe pas.\n", *(args+i)+1);
suppressArg(i);
close(0);
dup(fd);
close(fd);
}
/* Est-ce qu'il commence par > */
if (**(args+i)=='>')
{
fd = creat( *(args+i)+1, 0666 );
if (fd==-1)
printf("impossible de créer %s\n", *(args+i)+1);
suppressArg(i);
close(1);
dup(fd);
close(fd);
}
}
}
executerCommande()
{
int pid;
int res;
pid = fork();
if (pid==0)
executerCommande2();
if (!batch)
pid = wait(&res);
}
executerCommande2()
{
int pid;
int pospipe;
/* tester Pipe */
pospipe = traiterPipe();
if (pospipe<nb)
{
/* Pipe */
status = pipe(tube);
pid = fork();
if (pid==0)
{
/* Fils : execute la premier partie de la commande */
/* Rediriger la sortie */
close(1);
dup(tube[1]);
/* Fermer les descripteurs inutiles */
close(tube[0]);
close(tube[1]);
/* Lancer la commande */
execvp( *args, args );
printf("Impossible d'exécuter : %s\n",*args);
}
/* Pere : executer 2eme commande */
/* Rediriger l'entree */
close(0);
dup(tube[0]);
/* Fermer les descripteurs inutiles */
close(tube[0]);
close(tube[1]);
/* Recursion: Car il est possible qu'il y aie plusieurs | */
/* dans la meme commande */
/* On se positionne a la commande suivante et appel recursif */
args = args + pospipe + 1;
nb = nb - pospipe - 1;
executerCommande2();
}
else
{
/* Pas de pipe */
traiterRedirection();
execvp( *args, args );
printf("Impossible d'exécuter : %s\n",*args);
}
}
/* Cherche et renvoie la position de | */
/* Si pas trouve -> renvoie nb, nb d'éléments */
int traiterPipe()
{
int i;
/* Chercher | */
for (i=0; i<nb; i++)
{
if(**(args+i)=='|')
{
*(args+i) = 0;
return(i);
}
}
return(nb);
}
/* Supprime l'élément i */
suppressArg(int n)
{
int i;
for (i=n; i<nb; i++)
{
*(args+i) = *(args+i+1);
}
nb--;
}