在C shell(Unix)中实现管道
基本上,我已经使用标准POSIX命令创建了一个shell,我希望能够实现管道。现在它可以正确地处理命令,并且可以使用&进行后台处理。但我还需要能够使用|和>>进行管道连接。 例如,类似这样的事情: cat文件1文件2>>文件3 cat文件1文件2 |更多 更多文件1 | grep内容 这是我目前拥有的代码。我还想避免“系统”调用。我知道你需要使用dup2,但我编写代码的方式有点奇怪,所以我希望有人能告诉我在这段代码中实现管道是否可行?谢谢我知道使用了dup2,但也使用了im def。困惑于如何实现>>以及|在C shell(Unix)中实现管道,c,unix,shell,pipe,C,Unix,Shell,Pipe,基本上,我已经使用标准POSIX命令创建了一个shell,我希望能够实现管道。现在它可以正确地处理命令,并且可以使用&进行后台处理。但我还需要能够使用|和>>进行管道连接。 例如,类似这样的事情: cat文件1文件2>>文件3 cat文件1文件2 |更多 更多文件1 | grep内容 这是我目前拥有的代码。我还想避免“系统”调用。我知道你需要使用dup2,但我编写代码的方式有点奇怪,所以我希望有人能告诉我在这段代码中实现管道是否可行?谢谢我知道使用了dup2,但也使用了im def。困惑于如何实
#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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
无效执行(char*命令[],bool BG)
{
//Int Status纯粹用于waitpid,fork()的设置与普通一样。
智力状态;
pid_t pid=fork();
开关(pid)
{
案例0:
execvp(命令[0],命令);
if(execvp(命令[0],命令)=-1)
{
实际上,管道和重定向是不同的。要实现重定向(如>
),您必须使用dup2
。首先,使用适当的标志打开所需的文件(对于>
,它们将是O WRONLY | O|u create | O|u APPEND
)。其次,使用dup2
,创建stdout(文件描述符1)此新打开的fd的副本。最后,关闭新打开的fd
要创建管道,您需要一个pipe
syscall。阅读它的手册页,它包含示例代码。然后您还需要dup2
使pipe
返回的文件描述符分别为一个进程的stdin和另一个进程的stdout。您应该能够使用shell实现管道和输出重定向,b但是我注意到了一些事情:
-
您用于读取输入、解析和输出的代码混合在一起,您可能希望分离此功能。
-
strtok不能很好地用作shell命令的解析器。它可以用于非常简单的命令,但您可能希望创建或找到更好的解析器。像
echo“hello world”
这样的命令会对您当前的解析方法产生问题。
-
您可能需要创建一个简单的结构来保存解析后的命令。
下面是一些伪代码,让您开始:
#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);
}
}
祝你这个项目好运!
你为什么试图避免系统调用?便携性?你可以尽可能地坚持POSIX指定的系统调用。而且,你的shell是C和C++的奇怪组合。你认为我做shell的方式是“可能的”还是应该重新设计我的shell?