我正在尝试用C ++编写一个microshell,它将接受1或2个args并在UNIX中运行它们。我的shell需要两个由||分割的args很好,但是当我只运行一个时,我得到一个巨大的叉错误。我的shell会寻找||作为管道而不仅仅是|。先感谢您!
一些功能命令是:
cat filename ||排序
ls -l ||少
代码:
#include <iomanip>
#include <iostream>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <errno.h>
#include <stdio.h>
using namespace std;
void getParms (char[], char* [], char* []);
int main()
{
char command[160];
pid_t pid1 = 1, pid2 = 1;
cout << "myshell> ";
cin.getline(command, 160);
while (strcmp(command, "q") != 0 && strcmp(command, "quit") != 0 && pid1 > 0 && pid2 > 0)
{
char* arg1[6];
char* arg2[6];
char path1[21], path2[21];
int pipefd[2];
arg1[0]=NULL;
arg2[0]=NULL;
getParms(command, arg1, arg2);
if (pipe(pipefd) < 0)
{
perror ("Pipe");
exit (-1);
}
//cerr <<"This is arg2"<<arg2[0]<<endl;
pid1 = fork();
if (pid1 < 0)
{
perror ("Fork");
exit (-1);
}
if (pid1 == 0)
{
//cout<<"Child 1"<<endl;
//cerr<<arg1[0]<<endl;
if(arg2[0] != NULL)
{
close(pipefd[0]);
close(1);
dup(pipefd[1]);
close(pipefd[1]);
}
strcpy(path1, "/bin/");
strcat(path1, arg1[0]);
if (execvp(path1, arg1) < 0)
{
strcpy(path1, "/usr/bin/");
strncat(path1, arg1[0], strlen(arg1[0]));
if (execvp(path1, arg1) < 0)
{
cout<<"Couldn't execute "<<arg1[0]<<endl;
exit (127);
}
}
if(arg2[0]== NULL)
{ // Parent process
close (pipefd[0]); //read
close (pipefd[1]); //write
waitpid(pid1, NULL, 0); // Waits for child2
cout << "myshell> ";
cin.getline(command, 160);
}
}
else if(arg2[0] != NULL)
{
//cerr<<"Child 2"<<endl;
pid2 = fork();
if (pid2 < 0)
{
perror ("Fork");
exit (-1);
}
if (pid2 == 0)
{
close(pipefd[1]);
close(0);
dup(pipefd[0]);
close(pipefd[0]);
strcpy(path2, "/bin/");
strncat(path2, arg2[0], strlen(arg2[0]));
if (execvp(path2, arg2) < 0)
{
strcpy(path2, "/usr/bin/");
strncat(path2, arg2[0], strlen(arg2[0]));
if (execvp(path2, arg2) < 0)
{
cout<<"Couldn't execute "<<arg2[0]<<endl;
exit (127);
}
}
}
else
{ // Parent process
//cerr<<"in last 2 else"<<endl;
close (pipefd[0]); //read
close (pipefd[1]); //write
waitpid(pid2, NULL, 0); // Waits for child2
cout << "myshell> ";
cin.getline(command, 160);
}
}
}
return 0;
}
/****************************************************************
FUNCTION: void getParms (char [], char* [], char* [])
ARGUMENTS: char str[] which holds full command
char* args[] args2[] which will hold the individual commands
RETURNS: N/A
****************************************************************/
void getParms(char str[], char* args[], char* args2[])
{
char* index;
int i= 0;
int j= 0;
index = strtok(str, " ");
//cerr<<"before first while"<<endl;
// While the token isn't NULL or pipe
while (index != NULL && strstr(index,"||") == NULL)
{
args[i] = index;
index = strtok(NULL, " ");
i++;
}
args[i] = (char*) NULL; // makes last element Null
//cerr<<" getParms before ||"<<endl;
if(index != NULL && strcmp(index,"||") != 0)
{
//cerr<<"after checking for ||"<<endl;
index = strtok(NULL," ");
while (index != NULL)
{
args2[j] = index;
index = strtok(NULL," ");
j++;
}
}
//cerr<<"After second IF"<<endl;
args2[j] = (char*) NULL; // makes last element Null
}
答案 0 :(得分:0)
你的问题是主while
循环不会转到你有另一个命令提示的任何if-else
语句 - 反复执行相同的语句。当您使用双管道时,它会转到else if(arg2[0] != NULL)
,父进程会显示一个新提示。
尝试从while
语句中的主if-else
循环中删除命令的提示,并将提示移动到循环的开头,如下所示:
//Move these two below into the while loop
//cout << "myshell> ";
//cin.getline(command, 160);
while (strcmp(command, "q") != 0 && strcmp(command, "quit") != 0 && pid1 > 0 && pid2 > 0)
{
cout << "myshell> ";
cin.getline(command, 160);
//...
}
尽量不要对同一件事进行多次调用。如果你有几个,你需要改变它可能会变得混乱。