当 EOF 输入 C 时,Shell 会无休止地循环

Shell endlessly loops when EOF is entered C

提问人:Collin Meese 提问时间:10/1/2018 更新时间:10/1/2018 访问量:359

问:

我是一个新的C程序员,正在尝试创建自己的shell。shell 本身运行良好并正确处理我的命令,但是当用户在命令行中输入 EOF 字符作为输入时,我的 shell 只是无限循环。我的代码以及我已经尝试过的内容发布在下面(我也是使用 GDB 和 Valgrind 的新手,但两者似乎都不能帮助我找到问题)。

我已经尝试过:

  1. 下面的当前实现尝试捕获 getline 的返回值,并处理它返回 -1 的情况(读取 EOF 时)。但是,这只会导致 shell 无休止地循环提示
  2. 我用以下代码完全替换了我的函数调用:

    if (fgets(command_line, MAX_CANON, stdin) == NULL) {
      printf("\nTo quit, please use the exit command: exit.\n");
    }
    

据我所知,上述替换应处理用户输入的 EOF 字符。但是,这种使用 fgets 的实现也会导致无休止的命令提示符循环。

以下是我目前的实现,在上面的 #1 中有所提及:

在 main 中调用的函数以读取用户的输入:

char *read_command_line(void)
{
    //Declare an integer to hold the length of the string, a line to hold our output, and a variable getline can use to hold the generated buffer
    int len;
    char *line = NULL;
    ssize_t bufsize = 0;

    //Get the line from stdin 
    int retval = getline(&line, &bufsize, stdin);

    if(retval == -1)
    {
        line = NULL;
        return line;
    }

    //Determine the length of the line and set a null terminating byte to end the string and get rid of the trailing return
    len = strlen(line); 
    line[len - 1] = '\0';

    //Finally return the read in line
    return line;
}

我的 shell while 循环的开头,其中读入了行:

//BEGIN SHELL
  while (go)
  {
    //Signals are handled in the main.c  
    //Print the prompt
    char cwd_loop[max_buf_size];
    getcwd(cwd_loop, sizeof(cwd_loop));
    printf("\n%s [%s]:> ", prompt_prefix, cwd_loop);

    commandline = read_command_line();  

    if(commandline == NULL)
    {
        continue;
    }
C shell fgets eof getline

评论

0赞 klutt 10/1/2018
line[strlen(line) - 1]似乎有点不对劲。根据定义,此操作不应更改任何内容。
0赞 Collin Meese 10/1/2018
@broman 好调用,我似乎忘记了 getline 返回一个已经以 null 结尾的字符串。我将删除这些无用的代码。谢谢你的建议。
0赞 klutt 10/1/2018
嗯,不止于此。这不仅是无用的。如果字符串未终止,则该函数将根本不起作用。所做的是返回第一个字符的索引。strlenstrlen\0

答:

1赞 chqrlie 10/1/2018 #1

当输入流已关闭时,不应继续提示和读取进一步的输入,如返回或返回所示。只需跳出循环,就好像输入了命令一样。getline()-1fgets()NULLexit

评论

0赞 Collin Meese 10/1/2018
谢谢,输入流关闭对我来说很有意义,我在上面没有考虑到这一点。是否可以重新打开输入流,然后在 while 循环中发出 continue,以便在用户输入 EOF 时,我们不会退出,而只是再次提示?我现在也会考虑自己重新打开封闭的输入流。再次感谢。
1赞 Some programmer dude 10/1/2018 #2

从您的代码

commandline = read_command_line();  

if(commandline == NULL)
{
    continue;
}

如果返回一个 null 指针,如果出现类似 的错误,它会这样做,那么你继续循环,让它再次迭代。这一次将再次返回一个空指针,并且您永远这样继续下去。read_command_lineEOFread_command_line

如果返回 null 指针,则应断开循环。read_command_line

评论

0赞 Collin Meese 10/1/2018
啊,好吧,这很有道理。我现在已经这样做了,以防止将来出现任何问题,但我的主要目标是以一种允许 shell 优雅地恢复提示用户而无需他们再次运行程序的方式实现处理。希望我能够通过更多的研究来解决这个问题。感谢您的建议
0赞 that other guy 10/1/2018
这相当于编写一个 GUI 工具,每次点击“文件 -> 退出”时都会“优雅地”重新启动,这样就不需要用户手动重新调用它。