为什么 ls 不能与 execvp 一起使用?

ely*_*hiv 2 c linux exec

我有一个作业要求我编写一个迷你 shell - 它将获取要执行的命令,执行它,然后等待更多命令。

当我将命令传递给这个迷你 shell 时,ls .它会打印当前目录的竞赛。当我传递给它时,ls它什么也没打印。为什么?

这是我的代码:

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <stdlib.h>
#include <stdbool.h>
#define MAX_CMD_SIZE 40
char** parse(char*);//will parse the arguments for the execv/excevp commands.

int main(int argc, char** argv)
{
    bool debug = false;
    assert(argc <= 2);
    if (argc == 2)
    {
        //check for string -debug
        debug = true; 
    } 
    if (debug)
        printf("INFO: Father started PID[%d]\n", getpid());
    char *command = malloc(MAX_CMD_SIZE);
    while(true)
    {
        printf("minishell> ");
        fgets(command, MAX_CMD_SIZE, stdin);
        if (strcmp(command, "exit\n") == 0)
            return 0;
        pid_t pid = fork();
        assert(pid >= 0); 
        if (pid == 0) //child
        {
            if (debug)
                printf("INFO: Child started PID[%d]\n", getpid());
            char** buf = parse(command);
            if (debug)
            {
                int i;
                for (i = 0; buf[i]; i++)
                    printf("INFO: buf[%d] = %s\n",i,buf[i]);
            }
            execvp(buf[0],buf);
            return 0;
        }
        else //father
        {
            int status;
            wait(&status);
            if (debug)
                printf("INFO: Child with PID[%d]terminated, continue waiting commands\n", pid);
        }
    }
}

char** parse(char *string)
{
    char** ret = malloc(sizeof(char*));
    ret[0] = strtok(string, " ");
    int i = 0;
    for (; ret[i]; ret[i] = strtok(NULL, " \n"))
    {
        ret = realloc(ret, sizeof(char*) * ++i);
    }

    return ret;
}
Run Code Online (Sandbox Code Playgroud)

dan*_*an3 5

\n您的 parse() 命令在最后一个参数中包含:)

因此,使用单个 ls ,您实际上正在执行ls\n,它不在 PATH 中(当然)

问题是,在第一次strtok()调用时,您仅" "作为分隔符传递。使用" \n"(就像在后续的调用中一样),问题就消失了。

您还可以通过 chomping 来修复它\n

int l = strlen (string);
if (l > 0 && string [l - 1] == '\n') string [l - 1] = '\0';
Run Code Online (Sandbox Code Playgroud)

并且仅用作" "分隔符。