【问题标题】:Simple Linux Shell - execvp() failing简单的 Linux Shell - execvp() 失败
【发布时间】:2015-01-13 00:56:11
【问题描述】:

我需要一些关于类的简单 shell 的帮助,但我担心我不太了解 execvp() 函数的工作原理。

shell 不做太多事情,不支持管道、重定向、脚本或任何类似的东西。它只读取一个命令,读取选项(命令作为选项[0]),然后分叉。

它工作了几次,然后开始给我关于无法找到命令的错误。此处发布的其他类似问题与管道或重定向有关。

请原谅noobcode,它不漂亮,但我希望它清晰:

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

#define OPT_AMT 10

const size_t SIZE = 256;
int i = 0;
int o = 0;

int main(void) {

    // initializing data

    int exit = 0;
    char cwd[SIZE];
    char cmd[SIZE];
    char input[SIZE * OPT_AMT];
    char *opt[OPT_AMT];
    getcwd(cwd, SIZE);

    // main loop

    while (exit == 0) {
        // reset everything
        o = 1;
        i = 0;
        cmd[0] = "\0";
        while (i < OPT_AMT) {
            opt[i++] = "\0";
        }

        // get input
        printf("%s $ ", cwd);
        scanf("%s", cmd);
        gets(input);
        opt[0] = cmd;

        char *t = strtok(input, " ");
        while (t != NULL) {
            opt[o++] = t;
            t = strtok(NULL, " ");
        }

        // if exit, exit
        if (strcmp(cmd, "exit") == 0) {
            exit = 1;
        }
        // else fork and execute
        else {
            pid_t pID = fork();

            if (pID == 0) { // child process
                execvp(cmd, opt);
            } else if (pID < 0) { // failed to fork
                printf("\nFailed to fork\n");
            } else { // parent process
                wait(0);
            }
        }
    }

    // cleanup

    printf("\nFinished!  Exiting...\n");
    return 0;
}

有什么明显的错误吗?我最近添加了退出条件和重置选项数组。

另外,这是我的第一个问题,所以请提醒我我可能违反的任何规则。

【问题讨论】:

  • 不要使用gets()。它本质上是不安全的,它甚至不再是 C 的一部分。请改用fgets(),如有必要,不要忘记删除末尾的换行符。

标签: c shell exec execvp


【解决方案1】:

对于初学者来说,这个

cmd[0] = "\0";

应该是

cmd[0] = '\0';

听取编译器的警告。

要启用它们,请使用选项-Wall -Wextra -pedantic(用于 gcc)。


另外,您最好将opt 的元素初始化为指向“无”,即NULL,但指向文字"\0"

    while (i < OPT_AMT) {
        opt[i++] = NULL;
    }

因为execvp() 要求opt 是一个NULL 终止的C-“字符串”数组(感谢Paul 提及/措辞相关背景)。


另外^2:不要使用gets(),因为它是邪恶的,甚至不再是 C 标准的一部分。而不是

gets(input);

使用

fgets(input, sizeof input, stdin);

gets() 很容易让用户溢出传递的(输入)缓冲区。 (在没有保罗的情况下,我想到了这一点,顺便说一句...... ;-))

【讨论】:

  • 确实,execvp() 要求 opt 是一个以NULL 结尾的字符串列表。
  • 谢谢大家,我做了更改,但它给了我同样的错误。这是否与 fgets 中的换行符有关?
  • @Will:如果你采取一些步骤来弄清楚你的程序在做什么,你真的会帮助自己很多,比如printf()ing cmd的值,以及每个元素opt,在你的execvp() 调用之前,这样你就可以真正看到你传递给它的内容。这样做可以回答大多数此类问题。
  • @Will:使用调试器跟踪代码并检查所涉及变量的(中间)值也可能会有所帮助。
  • 好的,所以它与gets() 一起工作得很好,我只需要更深入地研究一下fgets()。感谢@alk 和@Paul_Griffiths 的帮助!
猜你喜欢
  • 2023-03-07
  • 1970-01-01
  • 2015-04-14
  • 1970-01-01
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 2021-06-01
  • 2014-05-08
相关资源
最近更新 更多