执行调用

时间:2009-12-23 21:56:35

标签: c shell exec

我想通过execve:

在C程序中调用一个shell
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

main()
{
        char* path = "/bin/sh";
        int err = execve(path, &path, NULL);
        printf("%d\n", err);
        printf("%s\n", strerror(errno));
        printf("%x, %x\n", path, &path);
}

然而输出是:

-1
Bad address
80485c0, bf816f4c

3 个答案:

答案 0 :(得分:10)

因为您没有发送NULL终止的参数列表。 你需要:

char* path[2];
path[0] = "/bin/sh";
path[1] = NULL;
int err = execve(path[0], path, NULL);

答案 1 :(得分:5)

execve的第二个参数被定义为以NULL结尾的字符串列表,因此您不能简单地传递path的地址。它需要一个像这样的数组,最后一个条目是NULL:

arg[0] = "/bin/ls"
arg[1] = "-l"
arg[2] = "/usr/include/std*"
arg[3] = NULL

错误指针失败的原因是execve会查看path之后的每个单词以查找参数,并将每个单词视为指针,直到它到达第一个0字。由于path单独存在于堆栈中,因此它会尝试解释堆栈超出path之后发生在内存中的任何垃圾作为字符串指针。

解决方案很简单:您需要构造一个参数数组并添加一个NULL终止符(因为它具有可变长度)。下面的固定示例(处理了一些警告):

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <string.h>

int main()
{
    char* path[] = { "/bin/sh", NULL };

    int err = execve(path[0], path, NULL);

    printf("%d\n", err);
    printf("%s\n", strerror(errno));
    printf("%p, %p\n", path, &path);

    return 0;
}

答案 2 :(得分:0)

请改为尝试:

execl(path, path, NULL)

如果程序是脚本而不是过程映像文件,exec系列函数将自动执行shell。因此,您可以将“path”替换为脚本的路径名。