Я использовал pipe и dup2 для перенаправления файловых дескрипторов, но после первой команды второй execvp застрял, я использовал цикл for, чтобы обвести несколько команд. Я почти уверен, что токенизация и буфер работают. Если я запускаю первую команду, он работает, но для второй команды он просто застрял после первой команды.
#include <fstream>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>
#include <fcntl.h>
using namespace std;
char buffer[10][500];
char *args[50];
int fd[20];
void tokenFnc(int counter);
//int counter = 0;
int main(int argc, char *argv[])
{
string input;
cout << "myshell$";
getline(cin, input);
int k = 0;
int counter = 0;
int status_code;
for (unsigned i = 0; i <= input.size(); i++)
{
if (i > 0 && input[i] == ' ' && input[i - 1] == '|')
{
continue;
}
if (input[i] == '|')
{
counter++;
k = 0;
}
else
{
buffer[counter][k] = input[i];
k++;
}
}
// int fd[(counter-1)*2];
for (int i = 0; i < counter; i++)
{
pipe(fd + i * 2);
}
counter += 1; //how many commands
for (int i = 0; i < counter; i++)
{
if (pipe(fd) == -1)
{
perror("pipe failed");
return 1;
}
tokenFnc(i);
int rc = fork();
if (rc < 0)
{ // fork creation fail
perror("fork failed\n");
return 1;
}
if (rc == 0)
{ //child process
if (i == 0 && counter > 1)
dup2(fd[1], 1);
if (i > 0 && i != counter - 1)
{
dup2(fd[(i - 1) * 2], 0);
dup2(fd[(2 * i) + 1], 1);
}
if (i == counter - 1 && counter > 1)
dup2(fd[(i - 1) * 2], 0);
for (int k = 0; k < (counter - 1) * 2; k++)
{
close(fd[k]);
}
status_code = execvp(args[0], (char *const *)args);
if (status_code == -1)
{ //error handling
perror("Child process terminated fail");
return 1;
}
}
}
int status;
for (int i = 0; i < counter; i++)
{
pid_t pid = wait(&status);
if (pid == -1)
{
perror("wait exective fail \n");
return 1;
}
printf("process %i exits with %i\n", pid, status);
}
return 0;
}
void tokenFnc(int counter)
{
int tokenCount = 0;
char delim[] = " ";
// cout << counter << endl;
// cout << "The token are: " << endl;
char *token = strtok(buffer[counter], delim);
while (token)
{
// cout << token << " ";
token = strtok(NULL, delim);
tokenCount++;
}
// cout << endl;
int pos = 0;
for (int i = 0; i < tokenCount; i++)
{
args[i] = (char *)&buffer[counter][pos];
pos += strlen(args[i]) + 1;
// cout << args[i] << ", ";
}
args[tokenCount] = (char *)nullptr;
// cout << endl;
}