execve-没有这样的文件或目录?

7

我遇到了一些execve的问题。 我正在尝试制作一个可以像bash shell一样运行的shell,但是我在forked child执行命令时遇到问题。 这里是我为child编写的代码:cmd是用户输入的命令的char *。 但是,当我运行此程序时,perror会报错:

execve error: No such file or directory.

我已经尝试使用简单的“ls”命令运行此程序,应该将路径设置为“/bin/ls”,并执行它(我确认这就是我的“ls”命令所在的位置),但它仍然报错。我做错了什么?谢谢!
if(pid == 0)
{
    // Parse the command
    char * word = strtok(cmd, " ");
    char path[128] = "/bin/";
    strcat(path, word);

    // Execute the process
    char * newenvp[] = { NULL };
    char * newargv[] = { path, NULL };
    ret = execve(path, newargv, newenvp);

    if(ret == -1)
        perror("execve error");

    return EXIT_SUCCESS;
}

你检查过 path 是否包含你认为的内容了吗?特别是考虑到 strtok() 操作方式有些令人恼火,如果不按照它的规则精确操作,很容易产生垃圾数据。 - geekosaur
我看不出有什么问题。为了确保 strtok 执行正确,为什么不加入一个 printf() 来显示 path 的最终内容呢?execve 调用本身看起来很好。 - Ernest Friedman-Hill
为什么要将环境设置为空?你应该使用普通的execv()来使用当前环境,或者将environ作为第三个参数传递给execve()。我怀疑这不是你问题的根源,但这是更好的实践。(此外,通常明智的做法是使用execv(newargv[0], newargv);execve(newargv[0], newargv, environ);。而且没有必要测试任何exec*()函数的返回状态:如果它返回了,那么它失败了;如果它成功了,它就不会返回。) - Jonathan Leffler
2个回答

5
我会尽力为您进行翻译。以下是所需翻译的内容:

我会做的第一件事就是插入:


printf ("[%s]\n", path);

在调用execve之前,应该确认可执行文件是你认为的那个。

只要输入正确且可执行文件确实可用,你的代码看起来没问题。例如,下面这个完整的程序在我的Debian系统上可以正常运行:

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

int main (int argc, char *argv[]) {
    if (argc > 1) {
        char * word = strtok (argv[1], " ");
        char path[128] = "/bin/";
        strcat (path, word);

        char * newenvp[] = { NULL };
        char * newargv[] = { path, NULL };
        printf ("[%s]\n", path);
        int ret = execve (path, newargv, newenvp);
        if (ret == -1) {
            perror("execve error");
        }
    }
    return 0;
}

当我运行./testprog ls时,输出大致如下:
[/bin/ls]
kidsshares.ods  paxwords    birthdays    homeloantracking.gnumeric
shares2011.ods  backup0.sh  development  lexar
accounts.ods    backup1.sh  photos       testprog.c
testprog

找到问题了,谢谢建议!我使用write()打印路径时忽略了缺少空终止符的事实。 - theeggman85

1
如果您不想手动浏览文件系统以查找正确的二进制文件,则可以使用execlp(带有额外的p)。 从man页中:

execlp()execvp()execvpe()函数在指定的文件名不包含斜杠(/)字符时,复制shell在搜索可执行文件方面的操作。 文件在以冒号分隔的目录路径列表中寻找,该列表在PATH环境变量中指定。 如果未定义此变量,则路径列表默认为当前目录,后跟由confstr(_CS_PATH)返回的目录列表。 (这个confstr(3)调用通常返回值“/bin:/usr/bin”。)[...]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接