从用户输入获取shell命令并执行C程序

时间:2011-05-05 20:32:22

标签: c linux fork execvp

目前正致力于收集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 个答案:

答案 0 :(得分:0)

你实际上没有说出你的问题是什么,但我的猜测是你在解决每个分叉进程如何使用参数时遇到问题。

我猜你所做的就是每次分叉时你需要将argv指针前进到下一个命令/ arg对。当命令为零终止符时,此分叉循环终止。

我希望我理解你的问题,因为你还没有说明你遇到的这个问题的哪个方面。

答案 1 :(得分:0)

argc告诉您argv

的大小

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

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

因此回复评论进行编辑:

您可以查看允许您执行此操作的getopt()

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

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

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

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

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

答案 2 :(得分:0)

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

您将遇到的问题在于,确实没有办法判断命令行参数数组中的下一个arg字符串是否是前一个命令的命令或参数。你可以区分命令及其args的唯一方法是知道它将交替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使用一样。

答案 3 :(得分: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。