Возьмите вывод команды bash и передайте его в качестве аргумента командной строки исполняемому файлу ac (pipe) - PullRequest
0 голосов
/ 04 декабря 2018

Я пытаюсь создать собственную оболочку в c, и когда я запускаю

pwd |./show

он примет вывод pwd и передаст его в качестве аргумента командной строки для ./show, и это должно быть с использованием каналов.

Я прочитал любой соответствующий вопрос, который мог найтино я не могу заставить его работать.

Пока что я думаю, что успешно направляю вывод в канал, но я не знаю, как передать его ./show.Я печатал его только для того, чтобы убедиться, что он проходит через канал.

        if(option == 2){

        getArgs(&A,args,directory,&size);

        pipe(fd);
        pid = fork();

        if(!pid){
            dup2(fd[1],STDOUT_FILENO); //output into pipe
            close(fd[0]);
            close(fd[1]);

            com=args[0];
            for(i=1;i<(size-2);i++){
              com=concat(com," ");
              com=concat(com,args[i]);
            }

            readCommand(args,directory,com,(size-1));
            return 1;
        }

        close(fd[1]);

        int nbytes = read(fd[0], foo, sizeof(foo));
        printf("Output: (%.*s)\n", nbytes, foo);

    }

exec происходит внутри readCommand, поэтому здесь он

      void readCommand(char *args[10],char *directory,char *com, int i){

    if(execl(directory, args[i],args[i+1], NULL)==-1){
        execl("/bin/sh", "/bin/sh", "-c", com, NULL);
        perror("execlp");
    }
    else{
        execl(directory, args[0],args[1],args[2],args[3],args[4], NULL); //max number of args=4
        perror("execlp");
    }
  }

Я ранее пытался заставить его работать с двумя вилками, но тогда я не уверен, что перенаправил вывод правильно, и кажется, что он выходит из строя еще сильнее.Я могу также включить этот код, если он полезен.

Помощь приветствуется, мой срок истекает через несколько часов ...

Обновление: после прочтения ответа я обновил код

if(option == 2){

        getArgs(&A,args,directory,&size);

        pipe(fd);

        if (!fork()) {
            pipe(fd);

            if(!fork()) {

                dup2(fd[1], 1);
                close(fd[0]);
                close(fd[1]);

                execlp(args[0], args[0], NULL);
            }
            else {

                dup2(fd[0], 0);
                close(fd[0]);
                close(fd[1]);

                execlp(args[size-1], args[size-1], NULL);
            }
        }
        wait(NULL);
    }

Теперь я напечатал пустую строку, а затем запрос новой команды.

1 Ответ

0 голосов
/ 04 декабря 2018

Вам нужно разделить два процесса с конвейером между ними.Ваша оболочка не должна пытаться читать или писать в канал.

Вот полный пример, который жестко кодирует ваш конвейер, чтобы продемонстрировать, как его настроить:

#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>

int main() {
  char* producer="pwd";
  char* consumer="./show";
  int fds[2];

  printf("Going to run the equivalent of '%s | %s'\n", producer, consumer);
  // Create a child that will become the consumer
  if (!fork()) {
    pipe(fds);
    // Create another child to be the producer
    if(!fork()) {
      // Set up stdout to be the pipe
      dup2(fds[1], 1);
      close(fds[0]);
      close(fds[1]);
      // Execute the producer
      execlp(producer, producer, NULL);
    } else {
      // Set up stdin to be the pipe
      dup2(fds[0], 0);
      close(fds[0]);
      close(fds[1]);
      // Execute the consumer
      execlp(consumer, consumer, NULL);
    }
  }
  // Wait for the consumer to finish
  wait(NULL);
  printf("The pipeline is done, the \"shell\" is exiting\n");
}

Вот реализация show:

#!/bin/sh
echo "Here's the data $0 read: $(cat)"

Вот результат реальной оболочки:

$ pwd
/tmp

$ pwd | ./show
Here's the data ./show read: /tmp

Вот результат при запуске этого примера:

$ gcc foo.c -o foo && ./foo
Going to run the equivalent of 'pwd | ./show'
Here's the data ./show read: /tmp
The pipeline is done, the "shell" is exiting
...