написание оболочки Linux - PullRequest
2 голосов
/ 08 июля 2011

Я пытаюсь выучить Unix C и делаю упражнения для практики. В настоящее время я работаю над написанием своей собственной оболочки, которая работает аналогично оболочке linux bash.

Приведенный ниже код обеспечивает довольно простую оболочку. Теперь он обеспечивает перенаправление ввода / вывода. Я пытаюсь добавить поддержку для трубопроводов. Изначально я просто хочу добавить поддержку для одного канала.

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

В настоящее время оболочка ниже может обрабатывать команды, такие как следующие. ls> abc, cat file2 и т. д.

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

#define TRUE 1

int main(void)
{
   char *arg_list[10];

   int status;

   int counter = 0;

   int counter2 = 0;

   pid_t pid;
   char buf[100];

   char inFile[10];
   char outFile[10];

   int fdIn, fdOut;
   while(TRUE)
   {
      printf("> ");
      if (!fgets(buf, 100, stdin))
      return 0;

      pid = fork();
      switch(pid)
      {
      case -1:
      return 1;

      case 0:
      {
      arg_list[counter] = strtok(buf, " \n");

      counter = 0;

      while(arg_list[counter] != NULL)
      {
       counter++;
       arg_list[counter] = strtok(NULL, " \n");
      }

      counter2 = 0;

      while(arg_list[counter2] != NULL)
     {
       if(!strcmp(arg_list[counter2], "<"))
       {
         if(arg_list[counter2+1] != NULL)
         {
           fdIn = open(arg_list[counter2+1], O_RDONLY);
           dup2(fdIn, STDIN_FILENO);
         }
         else
         {
           printf("No input file specified");
         }
         arg_list[counter2] = 0;
       }
       else if(!strcmp(arg_list[counter2], ">"))
       {
         if(arg_list[counter2+1] != NULL)
         {
         fdOut = open(arg_list[counter2+1], O_CREAT | O_WRONLY | O_TRUNC, 0666);
           dup2(fdOut, STDOUT_FILENO);
         }
         else
         {
           printf("No output file specified");
         }
         arg_list[counter2] = 0;
       }
       counter2++;
     }

    execvp(arg_list[0], arg_list);
    break;
  }

  default:
  waitpid(-1, &status, 0);
  break;
  }
}

  return 0;
}

Если кто-то может указать мне правильное направление, это будет оценено.

Ответы [ 2 ]

3 голосов
/ 09 июля 2011

После использования dup2() (успешно) у вас есть два файловых дескриптора, открытых для одного файла. Вам необходимо закрыть оригинальный дескриптор файла; В исполняемом процессе не должно быть открытых файловых дескрипторов.

Вам также потребуется открыть файлы соответствующим образом перед использованием dup2(). Помимо прочего, это означает, что strtok() не является хорошим выбором, поскольку он разбивает разделитель, но вам необходимо знать, какой файл открыть для чтения, а какой для записи).

Вам также понадобится заполнить список аргументов; он должен содержать только имя команды и нулевой указатель, а не два имени файла.

1 голос
/ 09 июля 2011

Зачем вам нужно проверять тип команды?Оболочки Unix не обрабатывают никаких команд специально;все перенаправления, включая каналы, обрабатываются одинаково.Следует обратить внимание на то, что перенаправления могут произойти в любом месте в команде, поэтому вам следует сначала проанализировать их;попробуйте

>foo ls <bar -la

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

...