Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
从用户输入获取shell命令并执行C程序_C_Linux_Fork_Execvp - Fatal编程技术网

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

从用户输入获取shell命令并执行C程序,c,linux,fork,execvp,C,Linux,Fork,Execvp,目前正在开发一个程序,该程序接收LinuxShell的输入命令并执行它们,创建子进程 #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

目前正在开发一个程序,该程序接收LinuxShell的输入命令并执行它们,创建子进程

#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,但需要接收带有arg的各种命令,例如:./program command arg command arg


有什么建议吗?

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

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

我希望我已经理解了你的问题,因为你还没有真正说明你在这个问题的哪个方面遇到了麻烦。

argc告诉你argv的大小

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

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

因此,在回复评论时编辑:

您可以查看getopt,它允许您执行以下操作:

 ./program -c "command arg1 arg2" -c "command arg1" ...
问题是您需要能够区分命令集/参数集。getopt至少可以让您达到一半,然后您只需要解析每个集合。虽然这真的太过分了,因为那是你唯一的输入类型。在这种情况下,通过argv进行迭代也同样容易

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

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

您需要遍历argv并查找逗号,才能知道命令/arg集已完成。或者将所有argv转换成字符串并使用strtok。有点难看,但可行

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

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

如果您知道它将交替,那么您可以像这样在arg中循环:

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

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

我认为这里的问题是解析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。

但是我想让用户使用任意数量的带参数的命令,当然我必须改变这一点,如果argc>2,但在不知道用户想要输入的命令数量的情况下,我不知道如何处理。你要么需要将它们作为单个命令传入,引用的参数,例如../program command arg arg command2 arg arg arg,然后解析每个字符串,或者使用一个分隔符,让您知道一个命令/arg集何时完成并实际遍历arg。。。你也许可以用getopt做这件事,已经有一段时间了。。。看起来,我还有其他方法来处理while,比如:`while1{printfShell->;getsline;printf\n;parseline,argv;if strcmpargv[0],exit==0 exit0;executeargv;}“但这样看起来就像一个shell,但我假装用户可以在同一行中使用args执行各种命令。