writing linux shell

帅比萌擦擦* 提交于 2019-12-10 11:18:32

问题


I am trying to learn Unix C and doing some exercises for practice. I am currently working on writing my own shell that works similar to the linux bash shell.

The code I have below provides for a fairly basic shell. It now provides I/O redirection. I am trying to add support for piping. Initially, I just want to add support for a single pipe.

I have tried to go through some tutorials online but can't quite figure out where to start.

Currently, the shell below can handle commands commands such as the following. ls > abc, cat< file1 > file2, etc.

#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;
}

If somebody can point me in the right direction, that would be appreciated.


回答1:


After you use dup2() (successfully), you have two file descriptors open for the one file. You need to close the original file descriptor; the executed process should not have the extra file descriptors open.

You are also going to need to open the files in the appropriate way before using dup2(). Amongst other things, that means strtok() is not a good choice because it blats out the delimiter but you need to know which file to open for reading and which for writing).

You are also going to need to fettle the argument list; it should contain just the command name and a null pointer, not the two file names.




回答2:


Why do you need to check the type of command? Unix shells don't treat any commands specially; all redirections, including pipes, are handled the same way. One thing to watch out for is that redirections can happen anywhere in a command, so you should parse them out first; try

>foo ls <bar -la

in a shell sometime. (Pipes are an obvious exception to this, since they also delimit commands; syntactically | is the same as ;, although semantically there is redirection involved in addition.)



来源:https://stackoverflow.com/questions/6629686/writing-linux-shell

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!