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

发布于 2024-11-05 19:36:17 字数 833 浏览 1 评论 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 .....

有什么建议吗?

currently working on program which recieves input command for linux shell and executing them creating child process.

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

Works with input like ./program command arg but needed to receive various commands with args for example : ./program command arg command arg .....

Any suggestions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

阳光下慵懒的猫 2024-11-12 19:36:18

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

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

A shell is a complex piece of software, I recently had to implement one for an Operating Systems class and it was difficult; and we only had to control one command per input (though we did also have to implement I/O redirection, and piping, and had to do path searching manually then execute with execv()).

The problem you are going to have lies in that there really isn't any way to tell if the next arg string in the array of command line parameters is a command or argument to a previous command. The only ways that you can differentiate commands and their args is if you know that it will alternate command arg command arg ..., or have some other standardized number of arguments per command (which isn't very useful) or have a deliminator between commands like a semicolon: command arg; command arg arg arg; ...

In the case that you know it will alternate then you can just loop through the args like so:

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

A better way to do this, would be instead of using command line parameters create an input prompt then process one command per line, just like normal shell usage.

红尘作伴 2024-11-12 19:36:18

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

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

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

You don't actually say what your problem is, but my guess is that you are having problems working out how each forked process will consume the parameters.

I guess what you do is that each time you fork you need to advance the argv pointer to the next command/arg pair. This forking loop terminates when the command is the zero terminator.

I hope I have understood your question because you haven't actually stated what aspect of this problem you are stuck on.

温柔戏命师 2024-11-12 19:36:18

argc 告诉您 argv 的大小,

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

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

为此原因进行编辑以回复评论:

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

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

问题是您需要能够区分您的命令/参数集。 getopt() 至少可以让你完成一半,然后你只需要解析每个集合。尽管这确实有点矫枉过正,因为这是您唯一的输入类型。在这种情况下,迭代 argv 也同样容易。

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

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

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

argc tells you the size of argv

You'd need to extract them from argv using that info.

Note that this doesn't solve the problem of commands with different numbers of args.

Edit for that reason in reply to comments:

You can look at getopt() which would allow you to do this:

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

The problem is you need to be able to differentiate between your command/arg sets. getopt() would at least get you half way there, then you just need to parse each set. Though it's really overkill since that's your only input type. Iterating through argv would be just as easy in this case.

Another option would be to separate them with a delimiter:

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

You'd need to iterate through argv and look for the comma to know a command/arg set was complete. Or concat all of argv into a string and use strtok(). Kinda ugly IMHO but doable.

执手闯天涯 2024-11-12 19:36:18

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

I think the question here is parsing argv.

Here is a dummy logical flow:

    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 */
                }
            }
        } 
    }

The only thing you need here is to realize CheckCmd and PushOption/PopOption.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文