如何在无需用户输入的情况下刷新标准输入? [英] How to flush stdin without requiring user input?

查看:79
本文介绍了如何在无需用户输入的情况下刷新标准输入?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试模拟命令行外壳.用户输入他们想输入的shell命令,例如/bin/pwd 和代码是为了执行它.

I'm trying to simulate a command line shell. The user inputs a shell command they want to input, e.g. /bin/pwd and the code is meant to execute it.

将缓冲区设置为读取固定数量的字符(例如,假设20个字符).

The buffer is set to read a fixed number of chars (let's say 20 for example).

如果用户输入的字符超过20个,则需要清除多余的字符,然后Shell才再次循环.

In the case that the user inputs more than 20 chars, the excess characters need to be flushed before the shell loops again.

我一直在尝试这样做:

int garbageCollector; 
while ((garbageCollector = getchar()) != '\n' && garbageCollector != EOF);

但是问题是 getChar()要求您首先输入一个字符.

But the problem is getChar() requires you to input a char first.

是否有一种不需要用户输入任何内容的刷新标准输入的方法?

Is there a way to flush stdin that doesn't require user to input anything?

while (1) {

    // Prompt user for input
    ssize_t readIn = read(STDIN_FILENO, buffer, BUF_SIZE + 1);
    if (readIn < 0) {
        perror("read() failed");
        return 2;
    } 

    // Null-terminate and remove line return
    buffer[readIn - 1] = '\0'; 

    char program[strlen(buffer)];
    strcpy(program, buffer);
    printf("program is: %s\n", program);

    // Flush stdin
    int garbageCollector; 
    while ((garbageCollector = getchar()) != '\n' && garbageCollector != EOF);

    // Create child process
    child = fork();
    if (child < 0) {
        perror("fork() failed");
        return 3;
    }

    // Start alarm that is triggered after timeout exceeded
    // which then kills child process
    signal(SIGALRM, killChild);
    alarm(timeout); 

    if (child == 0) { // Child
        char* av[] = { program, NULL };
        execve(program, av, NULL);  

    } else {  // Parent
        wait(NULL);
        alarm(0);  // Reset alarm if program executed
    }

    memset(buffer, 0, BUF_SIZE); // Flush buffer
}

推荐答案

如果不考虑非POSIX可移植性(请注意,这不适用于Windows-但我看到您使用的是fork(),它也不会与Windows一起使用),您可以暂时制作要刷新非阻塞文件并从中读取所有输入的文件描述符:

If non-POSIX portability is not a concern (note that this will not work with Windows - but I see you're using fork() which also will not work with Windows), you could temporarily make the file descriptor you're attempting to flush non-blocking and read all input from it:

int flush_in(FILE *file)
{
    int ch;
    int flags;
    int fd;

    fd = fileno(file);
    flags = fcntl(fd, F_GETFL, 0);
    if (flags < 0) {
        return -1;
    }
    if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
        return -1;
    }
    do {
        ch = fgetc(file);
    } while (ch != EOF);
    clearerr(file);
    if (fcntl(fd, F_SETFL, flags)) {
        return -1;
    }
    return 0;
}

然后您将调用 flush_in(stdin).

这篇关于如何在无需用户输入的情况下刷新标准输入?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆