0

目前正在开发接收linux shell输入命令并执行它们创建子进程的程序。

#include <sys/types.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>

int main(int argc, char * argv[])
{ 
  int pid, status;
  if (argc < 2) {
    printf("Usage: %s command, [arg1 [arg2]...]\n", argv[0]);
    return EXIT_FAILURE;
  }
  printf("Starting %s...\n", argv[1]);
  pid = fork();
  if (pid == 0) {
    execvp(argv[1], &argv[1]);
    perror("execvp");
    return EXIT_FAILURE; // Never get there normally
  } else {
    if (wait(&status) == -1) {
      perror("wait");
      return EXIT_FAILURE;
    }
  }
  return EXIT_SUCCESS;
}

与输入类似./program command arg但需要接收各种带有 args 的命令,例如:./program command arg command arg .....

有什么建议么?

4

4 回答 4

0

您实际上并没有说出您的问题是什么,但我的猜测是您在弄清楚每个分叉进程将如何使用参数时遇到了问题。

我猜您所做的是每次分叉时都需要将argv指针推进到下一个命令/参数对。当命令是零终止符时,此分叉循环终止。

我希望我已经理解了您的问题,因为您实际上并没有说明您遇到这个问题的哪个方面。

于 2011-05-05T20:37:52.960 回答
0

argc告诉你大小argv

您需要从argv使用该信息中提取它们。

请注意,这并不能解决具有不同数量参数的命令的问题。

出于这个原因编辑回复评论:

您可以查看getopt()哪些允许您执行此操作:

 ./program -c "command arg1 arg2" -c "command arg1" ...

问题是您需要能够区分您的命令/参数集。getopt()至少会让你走到一半,然后你只需要解析每一组。虽然这真的是矫枉过正,因为这是你唯一的输入类型。在这种情况下,迭代argv将同样容易。

另一种选择是用分隔符分隔它们:

./program command arg1, command arg1 arg2, ... 

您需要遍历argv并查找逗号以知道命令/参数集已完成。或者将所有 argv 连接成一个字符串并使用strtok(). 恕我直言,有点丑陋但可行。

于 2011-05-05T20:39:04.943 回答
0

shell 是一个复杂的软件,我最近不得不为操作系统类实现一个,这很困难;并且我们只需要控制每个输入的一个命令(尽管我们还必须实现 I/O 重定向和管道,并且必须手动进行路径搜索然后使用 执行execv())。

您将遇到的问题在于,实际上没有任何方法可以判断命令行参数数组中的下一个 arg 字符串是命令还是前一个命令的参数。您可以区分命令及其参数的唯一方法是,如果您知道它将交替command arg command arg ...,或者每个命令有一些其他标准化数量的参数(这不是很有用),或者在命令之间有一个分隔符,如分号:command arg; command arg arg arg; ...

如果您知道它会交替出现,那么您可以像这样循环遍历 args:

for(int i = 1; i < argc; i += 2)
{
   //command is argv[i], arg is argv[i + 1]
}

一个更好的方法是,而不是使用命令行参数创建一个输入提示,然后每行处理一个命令,就像正常的 shell 使用一样。

于 2011-05-05T20:41:25.087 回答
0

我认为这里的问题是解析 argv。

这是一个虚拟的逻辑流程:

    for(i = 1; i < argc; i++)
    {
        isCommand = CheckCmd(argv[i]);  /* check if argv[i] is a command */
        if (isCommand)
        {
            for(; i < argc; i++)
            {
                isCommand = CheckCmd(argv[i]);  /* check if argv[i] is a command */
                if (isNotCommand)
                {
                    PushOption(argv[i]); /* save options */
                } else
                {
                    /* Get Command and options from stack */
                    /* execute command with fork/execv */
                }
            }
        } 
    }

您在这里唯一需要的是实现 CheckCmd 和 PushOption/PopOption。

于 2011-12-06T06:42:07.453 回答