为什么执行ls时没有输出?

Why is no output produced when executing ls?

我正在尝试编写一个程序来执行 argv 中给出的任何内容。但是,当我实际上 运行 execvp 时,它没有给出任何输出,也没有产生任何错误。这是我的程序。

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

int main (int argc, char * argv[]) {
    char * args[argc];
    for (int i = 0; i < argc - 1; ++i) 
        args[i] = strdup(argv[i+1]);
    args[argc-1] = malloc(1);
    *args[argc-1] = '[=10=]';
    printf("%s\n", args[argc-1]);
    int rc = fork();
    if (rc == 0)
        execvp(args[0], args);
}

当我 运行 ./exec ls 时产生的输出只是一个空行。但是,如果我 运行 一个将 ls 硬编码到数组中的程序,它就可以正常工作。为什么这个程序没有列出目录的内容?

假装有必要复制参数并使用 fork(),并观察如果您 运行:

./exec ls

那么您只想在对 execvp() 的调用中使用索引 1 中的参数,然后您将得到如下代码:

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

int main (int argc, char *argv[])
{
    char *args[argc];
    for (int i = 0; i < argc - 1; ++i)
    {
        if ((args[i] = strdup(argv[i+1])) == NULL)
        {
            fprintf(stderr, "%s: failed to allocate memory for '%s'\n",
                    argv[0], argv[i+1]);
            exit(EXIT_FAILURE);
        }
    }
    args[argc-1] = NULL;

    int rc = fork();
    if (rc == 0)
    {
        execvp(args[0], args);
        fprintf(stderr, "%s: failed to execute '%s'\n", argv[0], args[0]);
        exit(EXIT_FAILURE);
    }
    else if (rc < 0)
    {
        fprintf(stderr, "%s: failed to fork\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    return 0;
}

父进程在退出之前确实应该为子进程 wait()。该代码可能应该包含一个函数来转储参数列表的内容。这是代码的修订版本,它不使用 strdup() 尽管它仍然是分叉的。它使用了我的 SOQ (Stack Overflow Questions) repository on GitHub as files stderr.c and stderr.h in the src/libsoq 子目录中可用的一些代码。这些简化了错误处理——错误报告使用单个函数调用而不是像以前那样使用多行代码。

#include <unistd.h>
#include <sys/wait.h>
#include "stderr.h"

int main (int argc, char *argv[])
{
    err_setarg0(argv[0]);
    if (argc <= 1)
        err_usage("cmd [arg ...]");

    int rc = fork();
    if (rc == 0)
    {
        execvp(argv[1], &argv[1]);
        err_syserr("failed to execute '%s': ", argv[1]);
    }
    else if (rc < 0)
        err_syserr("failed to fork: ");

    int corpse;
    int status;
    while ((corpse = wait(&status)) > 0)
    {
        if (corpse != rc)
            err_remark("unexpected child PID %d status 0x%.4X\n", corpse, status);
    }
    if (WIFEXITED(status))
        rc = WEXITSTATUS(status);
    else if (WIFSIGNALED(status))
        rc = 128 + WTERMSIG(status);
    else
        rc = 255;   /* Something weird happened! */

    return rc;
}

当然,如果你不使用fork(),你也不需要wait()。这从根本上减少了代码:

#include <unistd.h>
#include "stderr.h"

int main (int argc, char *argv[])
{
    err_setarg0(argv[0]);
    if (argc <= 1)
        err_usage("cmd [arg ...]");
    execvp(argv[1], &argv[1]);
    err_syserr("failed to execute '%s': ", argv[1]);
}