Перенаправление ввода / вывода в пользовательской программе оболочки, написанной на C - PullRequest
0 голосов
/ 23 октября 2018

Я работал над собственным сценарием оболочки и обнаружил небольшую ошибку при перенаправлении вывода с кодом, приведенным ниже.В своем текущем состоянии код работает отлично, но при передаче в execvp args выдает такие ошибки, как: (ls ">" нет такого файла или каталога).Я знаю, что это потому, что он передает целые args [] в родительскую оболочку, которая не работает.Добавление в args [j] = NULL убирает "<" / ">", тем самым исправляя ошибку, но также приводит к тому, что перенаправления больше не работают.Как я могу заставить его не выдавать ошибку, но и работать правильно?Я прочитал несколько версий этого вопроса, но не могу найти ответ.Заранее спасибо за любую помощь.

switch (fork()){
        case -1:
        fprintf(stderr, "error forking");

        case 0://CHILD

        for(int j = 0; j < size; j++){

            if(!strcmp(args[j], "<")){//looking for input character
            ++ext;
            if((in = open(args[j+1], O_RDONLY)) < 0){//open file for reading
                fprintf(stderr, "error opening file\n");
            }
            dup2(in, STDIN_FILENO);//duplicate stdin to input file
            close(in);//close after use
            //args[j] = NULL;
                }//end input chech


            if(!strcmp(args[j],">")){//looking for output character
            ++ext;
                out = creat(args[j+1], 0644);//create new output file           
            dup2(out, STDOUT_FILENO);//redirect stdout to file
            close(out);//close after usere  
        //  args[j] = NULL;
            }//end output check 

            if(!strcmp(args[j], ">>")){//looking for append
            ++ext;
            int append = open(args[j+1],O_CREAT | O_RDWR | O_APPEND, 0644);
                dup2(append, STDOUT_FILENO);
                close(append);
             // args[j] = NULL;
            }                

         }//end loop


        execvp(args[0],args);//execute in parent
        fprintf(stderr, "error in child execi \n");//error
        exit(0);    

         default://PARENT
        wait(&status);  //wait for child to finish  
    }//end switch

1 Ответ

0 голосов
/ 23 октября 2018

Когда вы анализируете перенаправления (например, <, >, >>) и выполняете open/dup2, вам нужно удалить их из списка аргументов, который вы передаете execvp.

Итак, учитывая ваш args, вам необходим список аргументов second (например, args_clean), который вы only копируете по имени программы и ее аргументам.

И вам нужно дополнительное приращение j, чтобы пропустить файл перенаправления в args (то есть просто сделать j + 1 не эквивалентно).


Вот очищенный дочерний код [прошу прощения за бесполезную очистку в стиле]:

char *args_clean[size];
int cleanidx = 0;

for (int j = 0; j < size; j++) {
    if (!strcmp(args[j], "<")) {        // looking for input character
        ++j;
        if ((in = open(args[j], O_RDONLY)) < 0) {   // open file for reading
            fprintf(stderr, "error opening file\n");
        }
        dup2(in, STDIN_FILENO);         // duplicate stdin to input file
        close(in);                      // close after use
        continue;
    }                                   // end input chech

    if (!strcmp(args[j], ">")) {        // looking for output character
        ++j;
        out = creat(args[j], 0644); // create new output file
        dup2(out, STDOUT_FILENO);       // redirect stdout to file
        close(out);                     // close after usere
        continue;
    }                                   // end output check

    if (!strcmp(args[j], ">>")) {       // looking for append
        ++j;
        int append = open(args[j], O_CREAT | O_RDWR | O_APPEND, 0644);

        dup2(append, STDOUT_FILENO);
        close(append);
        continue;
    }

    args_clean[cleanidx++] = args[j];
}                                       // end loop

args_clean[cleanidx] = NULL;
execvp(args_clean[0], args_clean);                  // execute in parent
fprintf(stderr, "error in child execi \n"); // error
exit(0);

Также, смотрите мой ответ здесь о чем-то похожем с каналами: утечка fd, пользовательская оболочка

И, для полной оболочки, см. Мой ответ: Реализация перенаправления ввода / вывода в оболочке Linux с использованием C и посмотрите на встроенную ссылку для вставки

...