简体   繁体   English

前叉:使用一个arg运行shell时,资源暂时不可用

[英]Fork: Resource temporarily unavailable when running shell with one arg

I am trying to write a microshell in C++ that will take in 1 or 2 args and run them in UNIX. 我正在尝试用C ++写一个微型外壳,它将带有1或2个args并在UNIX中运行它们。 My shell takes two args split by || 我的外壳使用两个||分隔的参数 fine, but when I run only one I get a massive fork error. 很好,但是当我只运行一个时,我得到了一个很大的fork错误。 My shell will look for || 我的外壳会寻找|| as a pipe instead of just |. 作为管道,而不仅仅是|。 Thank you in advance! 先感谢您!

Some Functional commands are: 一些功能命令是:

cat filename || 猫文件名|| sort 分类

ls -l || ls -l || less

Code: 码:

#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
 }

Your problem is that the main while loop is not going to any of the if-else statements in which you have the prompt for another command - the same statement is executed over and over. 您的问题是,主while循环不会进入任何提示您输入其他命令的if-else语句-一次又一次地执行同一条语句。 When you use the double pipe it goes to else if(arg2[0] != NULL) and the parent process shows a new prompt. 当您使用双管道时,转到else if(arg2[0] != NULL) ,并且父进程显示新的提示。

Try removing both prompts for a command from the main while loop in your if-else statement and move the prompt to the beginning of the loop like this: 尝试从if-else语句的主while循环中删除命令的两个提示,然后将提示移动到循环的开头,如下所示:

//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);
    //...
}

Try not to make such redundant calls of the same thing. 尽量不要对同一事物进行此类冗余调用。 If you have a couple of those and you need to change something it can get messy. 如果您有几个,并且您需要更改某些内容,则可能会变得凌乱。

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

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