简体   繁体   English

在C Shell中实现管道(Unix)

[英]Implementing Pipes in a C shell (Unix)

Basically I have created a shell using standard POSIX commands, I want to be able to Implement Piping as well. 基本上,我已经使用标准POSIX命令创建了一个外壳,我也希望能够实现管道。 Right now it handles commands correctly, and can do background processing with &. 现在,它可以正确处理命令,并且可以使用&进行后台处理。 But I need to be able to pipe using | 但是我需要能够使用| and >> as well. 和>>。 For example something like this: cat file1 file2 >> file3 cat file1 file2 | 例如这样的内容:cat file1 file2 >> file3 cat file1 file2 | more more file1 | 更多文件1 | grep stuff grep的东西

Here is the code I have currently. 这是我目前拥有的代码。 I also want to AVOID "SYSTEM" calls. 我也想避免“ SYSTEM”调用。 I know U need to use dup2, but the way I did my code is a bit odd, so im hoping if someone can tell me if it is feasible to implement pipes in this code? 我知道您需要使用dup2,但是我编写代码的方式有点奇怪,所以我希望是否有人可以告诉我在此代码中实现管道是否可行? thanks! 谢谢! I know dup2 is used, but also im def. 我知道使用了dup2,但是我也知道了。 confused at how to implement >> as WELL as | 困惑于如何实现>>以及|

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

using namespace std;


void Execute(char* command[],bool BG)
{
//Int Status is Used Purely for the waitpid, fork() is set up like normal.
    int status;
    pid_t pid = fork();


    switch(pid)
    {
        case  0:
            execvp(command[0], command);

            if(execvp(command[0], command) == -1)
            {
                cout << "Command Not Found" << endl;
                exit(0);
            }

          default:
            if(BG == 0)
            {
                    waitpid(pid, &status, 0);
//Debug             cout << "DEBUG:Child Finished" << endl;
            }


    }

}


bool ParseArg(char* prompt, char* command[], char Readin[],bool BG)
{

    fprintf(stderr, "myshell>");
        cin.getline(Readin,50);
    prompt = strtok(Readin, " ");
    int i = 0;

    while(prompt != NULL)
    {
        command[i] = prompt;
        if(strcmp(command[i], "&") == 0){
//Debug        cout << "& found";
        command[i] = NULL;
        return true;
    }
//Debug        cout << command[i] << " ";
        i++;
        prompt = strtok(NULL, " ");

    }
    return false;
}

void Clean(char* command[])
{
//Clean Array
        for(int a=0; a < 50; a++)
        {
             command[a] = NULL;
        }
}



int main()
{
   char* prompt;
   char* command[50];
   char Readin[50]; 
   bool BG = false;



   while(command[0] != NULL)
   {

        Clean(command);
       BG = ParseArg(prompt, command, Readin, BG);
       if(strcmp(command[0], "exit") == 0 || strcmp(command[0], "quit") == 0 )
       {
             break;
       }

    else
    {
            Execute(command,BG);
    }

   }

   return 1;

}

Pipes and redirections are different, actually. 实际上,管道和重定向是不同的。 To implement a redirection (such as >> ) you have to use dup2 indeed. 要实现重定向(例如>> ),您实际上必须使用dup2 First, open the desired file with appropriate flags (for >> they'll be O_WRONLY|O_CREAT|O_APPEND ). 首先,使用适当的标志打开所需的文件(对于>>它们将为O_WRONLY|O_CREAT|O_APPEND )。 Second, using dup2 , make stdout (file descriptor 1) a copy of this newly opened fd. 其次,使用dup2 ,使stdout(文件描述符1)成为此新打开的fd的副本。 Finally, close newly opened fd. 最后,关闭新打开的fd。

To create a pipe, you'll need a pipe syscall. 要创建管道,您将需要pipe syscall。 Read its manpage, it contains example code. 阅读其手册页,其中包含示例代码。 Then you'll also need dup2 to make file descriptors returned by pipe be stdin for one process and stdout for another, respectively. 然后,您还需要dup2来使pipe返回的文件描述符分别对于一个进程为stdin,对于另一个进程为stdout。

You should be able to implement pipes and output redirection with your shell, but there are a few things I noticed: 您应该能够使用Shell来实现管道和输出重定向,但是我注意到了一些事情:

  • Your code for reading input, parsing, and output are mixed together, you may want to separate this functionality. 您用于读取输入,解析和输出的代码混合在一起,您可能需要分开此功能。
  • strtok won't work very well as a parser for shell commands. strtok作为shell命令的解析器不能很好地工作。 It will work for very simple commands, but you may want to look into creating or finding a better parser. 它适用于非常简单的命令,但是您可能需要研究创建或查找更好的解析器。 A command like echo "hello world" will be problematic with your current parsing method. echo "hello world"这样的命令将对您当前的解析方法造成问题。
  • You may want to create a simple structure for holding your parsed commands. 您可能需要创建一个简单的结构来保存解析的命令。

Here is some pseudocode to get you started: 以下是一些伪代码,可以帮助您入门:

#define MAX_LINE 10000
#define MAX_COMMANDS 100
#define MAX_ARGS 100

// Struct to contain parsed input
struct command
{
    // Change these with IO redirection
    FILE *input; // Should default to STDIN
    FILE *output; // Should default to STDOUT

    int num_commands;
    int num_args[MAX_COMMANDS]; // Number of args for each command
    char* command_list[MAX_COMMANDS]; // Contains the programs to be run
    char* args_list[MAX_COMMANDS][MAX_ARGS]; // The args for each command
    boolean background_task;
    boolean append;
}

int main()
{
    char input[MAX_LINE];

    while (1)
    {
        struct command cmd;

        print_prompt();
        read_input(input);
        parse_input(input, &cmd);
        execute(&cmd);
    }
}

Good luck with this project! 祝这个项目好运!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM