【问题标题】:batch processing in a simple shell在一个简单的外壳中进行批处理
【发布时间】:2017-08-03 00:46:31
【问题描述】:

大家好,我正在一个 shell 中创建一个批处理命令函数,该函数从一个 txt 文件中读取并将其通过管道传递给一个子进程以执行。

我遇到了执行问题。我怀疑它与空终止符有关。如果我使用 L 和显式 (char*)NULL 执行,则执行运行。如果我 execvp(argIn[0],argIn) 没有运行并返回-1。如果我使用显式 (char*)NULL 执行 execvp,则会收到错误,无法将 char* 转换为 char* 常量*。我在某处读到它可能是 g++ 编译器给了我错误,但 gcc 编译器不会给我错误。现在它不会用 gcc 编译,所以我不确定这是否属实。但无论如何它不应该需要显式终止符。我不确定我存储的 '\0' 是否正在传递给 exec 权限。当我将它传递给其他函数时它会检查出来,所以也许这不是解决方案。

其次,我的 for 循环不会多次执行,我认为这与第一个解决方案有关。我可以让 execl 使用索引进行分叉,但我无法在下次通过时递增索引以指向正确的标记,因为孩子应该清除我的索引,对吗?

无论如何,为了找出问题所在,我们已经挖掘了 3 周。我的任务失败了。很可能会不及格。我不知道还能尝试什么。因此,我将不胜感激。

我的问题是为什么 exec 函数不会执行程序?我正在传递 execvp(program name, program name, option, option, '\0') 但没有得到结果。

execl(program name, program name[index], option[index+1], option[index+1], (char*)NULL) 并得到结果。他们似乎都遵循参数,但只有一个给了我结果。

#include<string.h>
#include<iostream>
#include<ctype.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>

using namespace std;
int makearg(char s[], char**args[]);

int main(int argc, char *argv[])
{
    char **argIn;
    int argCount;
    int pos = 0;
    char str[500];
    pid_t pid = fork();

    for(int i = 0; i < 4; i++)
    {
            if(pid == 0)
            {
                while(fgets(str, 500, stdin) != NULL)
                    {
                        cout << "String loaded: " << str;
                        argCount = makearg(str, &argIn);
                execvp(argIn[0],argIn); //nothing exec
//              execl(argIn[0],argIn[0],argIn[1],argIn[2],(char*)NULL); //exec but requires index. 
        else if(pid < 0)
        {
                   perror("fork() error");
                   exit(-1);
        }
        else if(pid > 0)
        {
            cout << "Parent waiting" << endl;
            wait(NULL);
        }
    }
    return 0;
}



int makearg(char s[], char**args[])
{
    int counter = 1;
    int tokenLen = 1;
    int i = 0;
    int j = 0;
    int k = 0;
    char arg1[50];
    char * arg2;

    strcpy(arg1, s);
    //Count white space.
    while (arg1[j] != '\0')
    {
        if (arg1[j] == ' ' || arg1[j] == '\0' || arg1[j] == '\n')
        {
            counter++;
        }
        j++;
    }

    //Allocate the number of rows to be pointed to.
    args[0] = (char**) malloc(counter + 1);
    if(args[0] == NULL)
        exit(1);


    //Allocate the size of the c string arrays
    j = 0;
    while(arg1[j] != '\0')
    {
        if (arg1[j] == ' ' || arg1[j] == '\0' || arg1[j] == '\n')
        {
            (*args)[i] = (char*)(malloc(tokenLen));
            if((*args)[i] == NULL)
                exit(1);

            tokenLen = 0;
            i++;
        }

        j++;
        tokenLen++;
    }

    (*args)[i] = (char*)(malloc(tokenLen));
    if ((*args)[i] == NULL)
        exit(1);

    //reset values
    i = 0;
    j = 0;

    //Set arg2 to point to args row head. Transfer values from arg1 to arg2.
    arg2 = ((*args)[i]);
    while(arg1[j] != '\0')
    {
        if (arg1[j] != ' ' && arg1[j] != '\0' && arg1[j] != '\n')
        {
            arg2[k] = arg1[j];
            k++;
        }
        else
        {
            arg2[k] = '\0';
            i++;
            k = 0;
            arg2 = ((*args)[i]);
        }
        j++;

    }

    arg2[k] = '\0';

    if (counter < 1)
    {
        return -1;
    }

    return counter;
}

【问题讨论】:

  • 什么。是你的问题吗?
  • 问题是。给定所描述的参数,为什么 exec 函数不起作用。
  • 会发生什么而不是“某事执行”?
  • 另外你为什么不知道你使用的是哪种语言?
  • @cba1067950 这不是拖钓!没有语言 c/c++,选择一个认真

标签: c++ shell


【解决方案1】:

我获取了您发布的代码,对其进行了更新以修复构建错误并运行。我执行了简单的命令“ls”,但收到了消息

String loaded: ls
ls: cannot access '': No such file or directory

这表明makearg 工作不正常。然后,我添加了一个函数来帮助诊断问题。

void printArguments(char **args)
{
   for ( int j = 0; args[j] != NULL; ++j )
   {
      printf("args[%d]: %s\n", j, args[j]);
   }
}

并在调用makearg 之后添加了来自main 的调用。

        argCount = makearg(str, &argIn);
        printArguments(argIn);

我得到了输出:

String loaded: ls
args[0]: ls
args[1]: 
ls: cannot access '': No such file or directory

这表明makearg 没有正确处理行尾。它创建一个空参数。

我添加了几个函数来从左侧和右侧修剪空格。之后,子进程就可以正确执行“ls”了。

这是更新后的程序。

#include<string.h>
#include<iostream>
#include<ctype.h>
#include<stdlib.h>
#include<stdio.h>
#include<sys/types.h>
#include<sys/wait.h>
#include<unistd.h>

using namespace std;
int makearg(char s[], char**args[]);

void printArguments(char **args)
{
   for ( int j = 0; args[j] != NULL; ++j )
   {
      printf("args[%d]: %s\n", j, args[j]);
   }
}

int main(int argc, char *argv[])
{
   char **argIn;
   int argCount;
   char str[500];
   pid_t pid = fork();

   for(int i = 0; i < 4; i++)
   {
      if(pid == 0)
      {
         while(fgets(str, 500, stdin) != NULL)
         {
            cout << "String loaded: " << str;
            argCount = makearg(str, &argIn);
            printArguments(argIn);
            execvp(argIn[0],argIn); //nothing exec
         }
      }
      else if(pid < 0)
      {
         perror("fork() error");
         exit(-1);
      }
      else if(pid > 0)
      {
         cout << "Parent waiting" << endl;
         wait(NULL);
      }
   }
   return 0;
}

void trimWhiteSpacesLeft(char s[])
{
   int i = 0;

   for ( ; isspace(s[i]); ++i );

   if ( i == 0 )
   {
      return;
   }

   int j = 0;
   for (; s[i] != '\0'; ++j, ++i )
   {
      s[j] = s[i];
   }
   s[j] = '\0';
}

void trimWhiteSpacesRight(char s[])
{
   int len = strlen(s);
   int i = len-1;
   for ( ; i >= 0; --i )
   {
      if ( !isspace(s[i]) )
      {
         break;
      }
   }
   s[i+1] = '\0';
}

int makearg(char s[], char**args[])
{
   int counter = 1;
   int tokenLen = 1;
   int i = 0;
   int j = 0;
   int k = 0;
   char arg1[50];
   char * arg2;

   strcpy(arg1, s);

   // Trim whitespaces from both ends.
   trimWhiteSpacesLeft(arg1);
   trimWhiteSpacesRight(arg1);

   //Count white space.
   while (arg1[j] != '\0')
   {
      if (arg1[j] == ' ' || arg1[j] == '\0' )
      {
         counter++;
      }
      j++;
   }

   //Allocate the number of rows to be pointed to.
   args[0] = (char**) malloc(counter + 1);
   if(args[0] == NULL)
      exit(1);


   //Allocate the size of the c string arrays
   j = 0;
   while(arg1[j] != '\0')
   {
      if (arg1[j] == ' ' || arg1[j] == '\0' || arg1[j] == '\n')
      {
         (*args)[i] = (char*)(malloc(tokenLen));
         if((*args)[i] == NULL)
            exit(1);

         tokenLen = 0;
         i++;
      }

      j++;
      tokenLen++;
   }

   (*args)[i] = (char*)(malloc(tokenLen));
   if ((*args)[i] == NULL)
      exit(1);

   //reset values
   i = 0;
   j = 0;

   //Set arg2 to point to args row head. Transfer values from arg1 to arg2.
   arg2 = ((*args)[i]);
   while(arg1[j] != '\0')
   {
      if (arg1[j] != ' ' && arg1[j] != '\0' && arg1[j] != '\n')
      {
         arg2[k] = arg1[j];
         k++;
      }
      else
      {
         arg2[k] = '\0';
         i++;
         k = 0;
         arg2 = ((*args)[i]);
      }
      j++;

   }

   arg2[k] = '\0';

   if (counter < 1)
   {
      return -1;
   }

   return counter;
}

【讨论】:

  • 好的,谢谢。我会试试的。只需快速澄清您在左侧装饰中以 ; 结尾的 for 语句如果没有括号,那是否只包含函数的其余部分?
  • @cba1067950,我不确定你的困惑在哪里。顺便说一句,我修复了函数trimWhiteSpacesLeft 中的一个错误。在我最初的帖子中,我使用了s[i] = s[j];,它必须是s[j] = s[i];
  • 通常 for 循环是 for(parameters){ code } 但你有一个 for(parameters);没有括号,末尾有分号。抱歉,我从来没有这样看过。我不知道那是怎么回事。 :(
  • @cba1067950, for ( ; isspace(s[i]); ++i ); 等价于for ( ; isspace(s[i]); ++i ) { }。这是一个空主体的for 循环。循环中发生的唯一有用的事情是i 的值是循环结束时字符串中第一个非空白字符的索引。
猜你喜欢
  • 2014-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-16
  • 2022-10-04
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多