简体   繁体   English

execvp() function 一直返回-1

[英]execvp() function returns -1 all the time

In my code, I'm trying to use the function execvp() to execute a command that I get in my shell but the function always returns -1 that indicates unsuccess, when I replace the function first argument by (for example) "ps" it works fine but when it is (command) it doesn't work, I've checked that command is fine by printing it after getting it from the input line and it is a fine string with no problems, but the function keeps returning me an error!!在我的代码中,我尝试使用 function execvp() 来执行我在 shell 中获得的命令,但是当我将 function 的第一个参数替换为(例如)“ps “它工作正常但是当它是(命令)时它不起作用,我已经通过从输入行获取命令后打印它来检查命令是否正常并且它是一个没有问题的好字符串,但是 function 不断返回我一个错误!

#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define BUFFER_SIZE 100

int main(void)
{
    close(2);
    dup(1);
    char command[BUFFER_SIZE];

    while (1)
    {
        char *arg[3];

        fprintf(stdout, "my-shell> ");
        memset(command, 0, BUFFER_SIZE);
        fgets(command, BUFFER_SIZE, stdin);
        if(strncmp(command, "exit", 4) == 0)
        {
            break;
        }
        arg[0] = command;
        arg[1] = "\0";
        arg[2] = "\0";
        i = execvp(command,arg);
        printf("%d",i);

    }

    return 0;
}

I expect that the problem is in the way that command is passed in the function but after trying so much edites to the code, I still can't figure out what the problem really is!我预计问题出在 function 中传递命令的方式,但在尝试对代码进行如此多的编辑之后,我仍然无法弄清楚问题到底是什么!

There are 3 major problems and 1 minor one that can be picked out of the code shown (plus what I take to be an artefact of reducing your full code to the code in the question, plus some oddities):有 3 个主要问题和 1 个小问题可以从显示的代码中挑选出来(加上我认为是将您的完整代码减少到问题中的代码的人工制品,加上一些奇怪的地方):

  1. The fgets() function includes the newline in the returned string unless the line is too long (a separate problem). fgets() function 在返回的字符串中包含换行符,除非该行太长(一个单独的问题)。 You need to zap that newline:你需要换行:

     command[strcspn(command, "\n")] = '\0';
  2. The code does not parse the line that's entered, so only single word commands can sensibly be entered.该代码不解析输入的行,因此只能输入单个单词命令。 To fix that, you'd have to be prepared to split the line into words using an appropriate algorithm, removing quotes where appropriate, expanding variables and so on.要解决这个问题,您必须准备好使用适当的算法将行拆分为单词,在适当的地方删除引号,扩展变量等等。 That will be part of the later stages of developing your shell.这将是开发 shell 的后期阶段的一部分。

  3. The second argument to execvp() needs to be a NULL-terminated list of strings. execvp()的第二个参数需要是以 NULL 结尾的字符串列表。 You only provide the command name and two empty strings without the null terminator, which gives undefined behaviour.您只提供命令名称和两个没有 null 终止符的空字符串,这会产生未定义的行为。

The minor problem is that using "\0" instead of just "" is pointless.小问题是使用"\0"而不仅仅是""是没有意义的。

The artefact is that there is no fork() in the code, so if the command is executed successfully, the 'shell' is replaced by the command and exits when the replacement exits.人工制品是代码中没有fork() ,因此如果命令成功执行,“shell”将被命令替换并在替换退出时退出。

The close(2); dup(1); close(2); dup(1); close(2); dup(1); sequence is weird — it means standard error refers to the same file descriptor as standard output. Those lines really aren't needed (or desirable).序列很奇怪——这意味着标准错误指的是与标准 output 相同的文件描述符。这些行确实不需要(或不需要)。 Leave the errors separate from standard output.将错误与标准 output 分开。

The memset() is superfluous too. memset()也是多余的。 Using fprintf(stdout, "my-shell> ");使用fprintf(stdout, "my-shell> "); is a funny way of writing printf("my-shell> ");是一种有趣的写法printf("my-shell> "); . . Using strncmp(command, "exit", 4) means that if the user types exit-or-continue , you'll treat it the same as exit , which is far from ideal.使用strncmp(command, "exit", 4)意味着如果用户键入exit-or-continue ,您会将其视为与exit相同,这远非理想。

Putting most of those numerous changes into effect (omitting parsing the command line into separate arguments) leaves:使这些众多更改中的大部分生效(省略将命令行解析为单独的参数)留下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
#include <unistd.h>

#define BUFFER_SIZE 100

int main(void)
{
    char command[BUFFER_SIZE];

    while (1)
    {
        printf("my-shell> ");
        fflush(stdout);
        if (fgets(command, BUFFER_SIZE, stdin) != command)
            break;
        command[strcspn(command, "\n")] = '\0';
        if(strcmp(command, "exit") == 0)
        {
            break;
        }
        int pid = fork();
        if (pid < 0)
        {
            fprintf(stderr, "failed to fork()\n");
            exit(EXIT_FAILURE);
        }
        if (pid == 0)
        {
            /* Child - execute command */
            /* Should break line into command plus arguments */
            char *arg[2];
            arg[0] = command;
            arg[1] = NULL;
            execvp(command, arg);
            fprintf(stderr, "failed to execute command '%s'\n", command);
            exit(EXIT_FAILURE);
        }
        /* Parent - wait for child to finish */
        int corpse;
        int status;
        while ((corpse = wait(&status)) > 0)
        {
            if (corpse == pid)
                break;
            printf("PID %d exited with status 0x%.4X\n", corpse, status);
        }
    }

    return 0;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM