1
我一直在这个项目上工作了一段时间。目的是制作一个可以完成所有shell命令(除cd之外)的正常运行的shell。它几乎做了我希望它做的所有事情,除了一些事情。首先,当我将'&'表示后台处理时,它会执行此操作,但不会打印另一个myshell>行。我仍然可以输入内容,但是myshell>永远不会显示,无论我在哪里放置另一个cout < <“myshell>”;。Myshell分段错误,获取输入可能存在问题?
另一个问题是,如果我按下回车键,使得myString为空,很多次,它会以seg故障使程序崩溃。另外,在我执行'&'后台处理并按回车让myshell>恢复后,它会打印一个myshell>,然后在下一次输入中选择seg错误。如果我没有解释清楚,我很抱歉,但这真的让我发疯。如果您有任何建议,请告诉我。
#include <stdio.h>
#include <iostream>
#include <unistd.h>
#include <cstdlib>
#include <cstring>
#include <sys/types.h>
#include <cstdio>
#include <sys/wait.h>
#include <stdio.h>
/*Function that parses the command the user inputs.
It takes myArgv and myString as inputs.
It returns the value of exitcond, which is used to see if the user wants to exit or not.
Also, this is where myString is tokenized using strok()*/
int parseCommand(char *myArgv[10], char myString[255])
{
int exitcond=0;
if((strcmp(myArgv[0], "exit") == 0)||(strcmp(myArgv[0], "quit")==0))
{
exitcond = 1;
return exitcond;
}
int i;
char *token;
token = strtok(myString," ");
i=0;
while (token != NULL)
{
myArgv[i] = token;
token = strtok(NULL," ");
i++;
}
/*
* Set the last entry our new argv to a null char
* (see man execvp to understand why).
*/
myArgv[i] = '\0';
return exitcond;
}
/*Function that gets the command from the user and sees if they want
background processing or not (presence of '&').
It takes inputs of choose and myString. choose is the variable for
whether background processing is necessary or not, while myString is
an empty character array.
It outputs the value of the choose variable for lter use.*/
int getCommand(int choose, char myString[255])
{
int i;
choose=0;
fgets(myString, 256, stdin);
if (myString[0]=='\0')
{
choose=0;
return choose;
}
for (i=0; myString[i]; i++)
{
if (myString[i]== '&')
{
choose=1;
myString[i]=' ';
}
if (myString[i] == '\n')
{
myString[i] = '\0';
}
}
return choose;
}
/*Main function where all the calling of other functions and processes
is done. This is where the user enters and exits the shell also. All
usage of fork, pid, waitpid and execvp is done here.*/
int main()
{
using namespace std;
int exitCondition=0, i=0, status;
char myString[255];
char *token, *myArgv[10];
pid_t pid, waiting;
int bg=0;
while (!exitCondition)
{
/* print a prompt and allow the user to enter a stream of characters */
cout << "myshell> ";
bg=0;
int choose=0;
bg=getCommand(choose,myString);
exitCondition=parseCommand(myArgv,myString);
if(exitCondition==1)
{
cout<<"Thank you for using my shell.\n";
}
else {
/* while (myString[0]=='\0')
{
cout<<"myshell> ";
bg=getCommand(choose,myString);
}*/
/* The user has a command, so spawn it in a child process */
pid = fork();
if (pid == -1)
{
/* to understand why this is here, see man 2 fork */
cout << "A problem arose, the shell failed to spawn a child process" << endl;
return(1);
}
else if (pid == 0)
{
// Child process
execvp(myArgv[0],myArgv);
cout << "Bad command or file name, please try again!\n" << endl;
return 0;
} else {
/* This makes sure that the spawned process is run in the foreground,
because the user did not choose background */
if(bg==0)
{
waitpid(pid,NULL,0);
}
}
}
}
return 0;
}
运行你的'valgrind'计划将帮助您跟踪段错误。 – immibis
是我运行的外部程序,还是它的一部分? – whoisthis88
外部程序:http://valgrind.org/如果它没有与你的开发工具一起安装,它通常在任何* nix发行版的仓库中可用。 Windows ...并非如此。可能对使用'fork'的人来说不是问题。 – user4581301