简体   繁体   English

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

[英]getting shell command from user input and executing C program

currently working on program which recieves input command for linux shell and executing them creating child process. 目前正在研究接收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;
}

Works with input like ./program command arg but needed to receive various commands with args for example : ./program command arg command arg ..... 可与./program command arg等输入./program command arg但需要接收带有args的各种命令,例如: ./program command arg command arg .....

Any suggestions? 有什么建议么?

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. 我猜您正在做的是,每当您进行分叉时,都需要将argv指针前进到下一个命令/参数对。 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. 我希望我已经理解了您的问题,因为您实际上并未说明您坚持该问题的哪个方面。

argc tells you the size of argv argc告诉您argv的大小

You'd need to extract them from argv using that info. 您需要使用该信息从argv提取它们。

Note that this doesn't solve the problem of commands with different numbers of args. 注意,这不能解决带有不同数量args的命令的问题。

Edit for that reason in reply to comments: 为此修改以回复评论:

You can look at getopt() which would allow you to do this: 您可以查看getopt() ,它可以使您执行此操作:

 ./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. getopt()至少会让您半途而废,然后只需要解析每个集合即可。 Though it's really overkill since that's your only input type. 尽管这确实很过分,因为这是您唯一的输入类型。 Iterating through argv would be just as easy in this case. 在这种情况下,通过argv进行迭代同样容易。

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. 您需要遍历argv并查找逗号以知道命令/ arg集已完成。 Or concat all of argv into a string and use strtok() . 或者将所有argv连接到一个字符串中,然后使用strtok() Kinda ugly IMHO but doable. 有点丑恕我直言,但可行。

A shell is a complex piece of software, I recently had to implement one for an Operating Systems class and it was difficult; Shell是一个复杂的软件,我最近不得不为Operating System类实现一个软件,这很困难。 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() ). 并且我们只需要控制每个输入一个命令(尽管我们也必须实现I / O重定向和管道化,并且必须手动执行路径搜索,然后使用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. 您将要遇到的问题在于,实际上没有任何方法可以判断命令行参数数组中的下一个arg字符串是命令还是上一条命令的参数。 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; ... 区分命令及其args的唯一方法是,如果您知道它将替代command arg command arg ... ,或者每个命令具有其他标准化数量的参数(这不是很有用),或者之间有一个分隔符像分号这样的命令: command arg; command arg arg arg; ... 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: 如果您知道它将交替出现,则可以像这样循环遍历args:

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. 更好的方法是,代替使用命令行参数创建输入提示,然后每行处理一个命令,就像正常的shell使用一样。

I think the question here is parsing argv. 我认为这里的问题是解析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. 您唯一需要的是实现CheckCmd和PushOption / PopOption。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM