编写我自己的shell用于在C中重定向和管道

时间:2016-05-12 09:23:54

标签: c shell redirect pipe

我一直在尝试用C语言写一个shell但是在运行ls时我一直遇到e分段错误> test.txt(在实现管道之前它运行得很好)。

这是代码。对不起,如果它太长而且格式不正确。

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/wait.h>
#include <fcntl.h>


#define MAX 1024

/* fonction separe donne en exercise*/
char **separe(char *chaine, const char *separateurs)
{
    char **tab;
    int i, s, m, size = 10;

    tab = malloc(size * sizeof(char*));
    m = 0;
    i = 0;
    while (chaine[i] != 0)
    {
        // saute un séparateur
        for (s = 0; separateurs[s] != 0; s++)
            if (chaine[i] == separateurs[s])
                break;
        if (separateurs[s] != 0)
        {
            chaine[i++] = 0;    // met un fin de chaine à la place du séparateur et avance
            continue;   // les séparateurs n'ont pas été épuisés
        }

        if (chaine[i] != 0)
            tab[m++] = chaine + i;
        if (m == size)
        {
            // si j'atteinds la limite de la taille de mon tableau, je l'agrandis.
            size += 10;
            tab = realloc(tab, size * sizeof(char*));
        }
        // saute les caractères non séparateurs
        for (; chaine[i] != 0; i++)
        {
            for (s = 0; separateurs[s] != 0; s++)
                if (chaine[i] == separateurs[s])
                    break;
            if (separateurs[s] != 0)
                break;  // trouvé un caractère séparateur, j'arrête d'avancer et je passe au mot suivant
        }
    }
    tab[m] = NULL;
    return(tab);
}



void decaler2gauche(char ** tab, int pos)
{
    int i = pos;
    while( tab[i+2] != NULL )
    {
        tab[i] = tab[i+2];
        i++;
    }
    tab[i] = NULL;
}



char** pipetest( char **arg) {

    int sizeTab = 0;
    int k,j;

    char **newtab;

        for (k = 0; arg[k] != NULL; k++)
        {
            sizeTab++;
        }



    int i =0;

        while( arg[i] != NULL )
        {
        if( strncmp(arg[i],"|",1) == 0 )
        {

            for (j=0;j < i ; j++){

                newtab[i] = arg[i];
            }

            break;


        }
        i++;
        }
    newtab[i] = NULL;
    return newtab;
}

char** pipetest2( char **arg) {

    int sizeTab = 0;
    int k , j;


    char **newtab;

        for (k = 0; arg[k] != NULL; k++)
        {
            sizeTab++;
        }



    int i =0;

        while( arg[i] != NULL )
        {
        if( strncmp(arg[i],"|",1) == 0 )
        {

            for ( j= i+1 ; j < sizeTab ; j++ ) {
                newtab[j] = arg[j];
            }

            break;


        }
        i++;
        }
    newtab[sizeTab] = NULL;
    return newtab;
}





/* la fonction main*/
int main(int argc, char *argv[]) {

    char cmd[MAX];
    char **commande;            //ici on met la commande
    char *newcommande[MAX];         // ici on met la commande apres avoir verifie le contenu de commande
    int i, j, k,t,a, fd, fd2, raison ;  // les variables utilise
    char *tmp, *new_path , *new_path1 , *new_path2;
    char *ge_path, *path, **tab;
    int test;
    int status , status2;           // la variable test pour le access 
    char **commande1;
    char **commande2;

    pid_t pid , pid2;
    // récupère la valeur de $PATH
    ge_path = getenv("PATH");
    // crée une copie locale modifiable
    // (on ne doit pas modifier la zone mémoire renvoyée par getenv)
    path = malloc(strlen(ge_path) + 1);


    strcpy(path, ge_path);

    tab = separe(path, ":");

    while (1) {


        int copy = 0;
        int paste = 0;
        int piping = 0;
        int fdout;
        int fdin;
        int tabfd[2];


        printf("myshell > ");
        fgets(cmd, MAX, stdin);

        commande = separe(cmd, " \n");

        /* Cette boucle verifie si la commande passe en parametre est dans le PAth ou pas*/
        for (i = 0; tab[i] != NULL; i++)
        {

            char tmp[MAX];
            sprintf(tmp, "%s/%s", tab[i], commande[0]);


            if ((test = access(tmp, X_OK)) == 0)

            {
                new_path = tmp;
                break;
            }

        }


        char* fileNameIn;
        char* fileNameOut;

        for (j = 0; commande[j] != NULL; j++)
        {
            if (strcmp(commande[j], ">") == 0) //out
            {
                fileNameOut = commande[j + 1];
                fdout = open(fileNameOut, O_CREAT | O_WRONLY | O_TRUNC, 0666);
                if (fdout == -1)
                {
                    perror("open\n");
                    exit(1);
                }
                decaler2gauche(commande,j);
                copy = 1;
            }
             if (strcmp(commande[j], "<") == 0) //in
            {
                fileNameIn = commande[j + 1];
                printf("%s\n", fileNameIn);
                fdin = open(fileNameIn, O_RDONLY);
                if (fdin == -1)
                {
                    perror("open\n");
                    exit(1);
                }
                paste = 1;
                decaler2gauche(commande,j);
            }

             if (strcmp(commande[j], "|") == 0) // pipe {
             {   
                 piping = 1;

             }


            newcommande[j] = commande[j];

        }



        if (piping) {

            commande1=pipetest(newcommande);
            commande2=pipetest2(newcommande);



            for (i = 0; tab[i] != NULL; i++)
        {

            char tmp[MAX];
            sprintf(tmp, "%s/%s", tab[i], commande1[0]);


            if ((test = access(tmp, X_OK)) == 0)

            {
                new_path1 = tmp;
                break;
            }

        }


            for (i = 0; tab[i] != NULL; i++)
        {

            char tmp[MAX];
            sprintf(tmp, "%s/%s", tab[i], commande2[0]);


            if ((test = access(tmp, X_OK)) == 0)

            {
                new_path2 = tmp;
                break;
            }

        }




            pipe(tabfd);

            switch (pid=fork()) {

            case -1: // le cas d erreur
            perror("fork");
            exit(1);

            case 0:// le fils   

                close(1);
                dup(tabfd[1]);


                if (paste)
            {


                if (dup2(fdin, 0) == -1)
                {
                    perror("dup2 fdin \n");
                    exit(1);
                }
            }

                if (copy)
            {
                if (dup2(fdout, 1) == -1)
                {
                    perror("dup2 fdin \n");
                    exit(1);
                }
            }

            execv(new_path1, commande1);


            perror("cmd");
            exit(1);


            default :
                wait(&status2);
                break;

            }


            switch (pid2=fork()) {

            case -1: // le cas d erreur
            perror("fork");
            exit(1);

            case 0:// le fils   

                close(0);
                dup(tabfd[0]);


                if (paste)
            {


                if (dup2(fdin, 0) == -1)
                {
                    perror("dup2 fdin \n");
                    exit(1);
                }
            }

                if (copy)
            {
                if (dup2(fdout, 1) == -1)
                {
                    perror("dup2 fdin \n");
                    exit(1);
                }
            }

            execv(new_path2, commande2);


            perror("cmd");
            exit(1);


            default :
                wait(&status);
                break;

            }


            close(tabfd[0]);
            close(tabfd[1]);



        }

    else {


        switch (pid = fork())
        {

        case -1: // le cas d erreur
            perror("fork");
            exit(1);

        case 0:// le fils



            if (paste)
            {
                if (dup2(fdin, STDIN_FILENO) == -1)
                {
                    perror("dup2 fdin \n");
                    exit(1);
                };
            }

            if (copy)
            {
                if (dup2(fdout, STDOUT_FILENO) == -1)
                {
                    perror("dup2 fdin \n");
                    exit(1);
                };
            }

            execv(new_path, commande);


            perror("cmd");
            exit(1);


        default:

                    wait(&status);
                    break ; 

        }

        }



        free(commande);
        free(tmp);
    }
    free(tab);
    //free(commande);
    free(path);
    free(new_path);

    exit(0);
}

0 个答案:

没有答案