从字符串运行带有execlp()的shell命令

时间:2014-02-05 04:15:04

标签: c linux shell

我试图让我的程序使用exelp()运行shell命令。用户基本上输入一个shell命令,该命令在新shell中由exelp()存储然后执行。

让我们说用户输入“ ls -l / bin / ?? ”,然后由变量command[]捕获。如何在shell环境中执行此文本字符串。

我最接近了解如何执行此操作的方法是execlp("/bin/sh", "-c", command, (char *)NULL);,其中/bin/sh启动迷你shell,-c启用shell来获取字符串,最后一个参数只是先前捕获的字符串。我知道system()是一个选项,但我想用execlp来做这个教育目的。

这里我错过了什么?提前谢谢。

2 个答案:

答案 0 :(得分:0)

也许你在问如何在你的C程序中将shell单词扩展为参数子序列。见glob(7)

然后考虑glob(3)wordexp(3)

你应该意识到当你输入ls -l /bin/??时,外壳有责任扩展??; /bin/ls程序execve(2) - 使用扩展结果

或者,您可以将其留给由system(3)popen(3)函数启动的/bin/sh -c shell。如果您将一些用户输入传递给这些函数,请注意code injection并适当引用任何用户输入。想象一下,你运行一个由ls -l和一些用户输入组成的字符串;如果恶意用户将a; rm -rf $HOME作为文件名,那么如果你不引用它会很抱歉(因为没有预防措施,你的程序将构建ls -l a; rm -rf $HOME命令字符串,然后将该字符串传递给{{ 1}}或system然后灾难发生。)

答案 1 :(得分:-1)

您将const char**而不是const char *作为tird参数

尝试execlp("/bin/sh", "-c", "ls", "-l", "/bin/", 0) 或者使用“-c”作为第一个参数创建另一个char **,然后使用execv

我猜它正在编译,因为两个参数都是指针,但它们的类型错误

修改

当你像调用execlp一样。 正如你所说的命令是const char[],但在定义中你只需要const char* 就好像你像这样调用函数

execlp(const char*, const char*, const char **, char*) //wrong obviously

所以你有两个解决方案。 第一个使用bin / sh -c来连接所有参数并将其传递给execlp

int main(int argc, char **av)
{
  char  **args;
  int   i;
  char  *cmd;
  size_t size;

  args = malloc(sizeof(char*) * (4));
  args[0] = "sh";
  args[1] = "-c";
  i = 1;
  size = 0;
  cmd = malloc(1);
  *cmd = '\0';
  while (i < argc)
    {
      cmd = realloc(cmd, strlen(cmd) + 1 + strlen(av[i]));
      strcat(&(cmd[size]), av[i]);
      size += strlen(cmd);
      strcat(&(cmd[size]), " ");
      size++;
      i++;
    }
  args[2] = cmd;
  execvp("/bin/sh", args);
}

但它不是很干净

最好的方法(对我而言更合乎逻辑)我认为在你的case / bin / ls中找到二进制文件的地址然后使用execvp传递它

类似的东西:

char *get_binary_addr(const char* fct)
{
  return "/bin/ls"; //ofc you will parse your /bin to find binary addr
}

int main(int argc, char **av)
{
  char  **args;

  args = malloc(sizeof(char*) * argc);
  memcpy(&(args[0]), &(av[1]), argc * sizeof(char*));
  execvp(get_binary_addr(av[0]), args);
}