How to handle key input with select()?

I am trying to implement a terminal emulator in C + SDL2 with a PTY, and this is how it has to be implemented:

fd_set readable;
int maxfd = pty->master;
for (;;) {
        FD_ZERO(&readable); //clear fd_set 'readable'
        FD_SET(pty->master, &readable); //add 'pty' fd to 'readable'
        //here I would theoretically want to add a fd of SDL key input.

        //waits until any file descriptor from 'readable' can be read
        if (select(maxfd + 1, &readable, NULL, NULL, NULL) == -1) { 
                //error
        }

        if (FD_ISSET(pty->master, &readable)) { //if 'pty' is readable
                //handle PTY input (A.K.A terminal output)
        }
}

However, I want it to include key input from SDL2, to then feed through the PTY.
So how could I collect key input while select() is running?

I would set the timeout parameter to a relatively small value (perhaps a few milliseconds), then you can loop calling select() and SDL_PollEvent() until one or the other returns a keypress.

1 Like

Thank you, that worked!
This is what I have in my program now:

fd_set readable;
int maxfd = pty->master;

struct timeval tv;
tv.tv_sec = 0;
tv.tv_usec = 0;
//select will not wait at all

for (;;) {
        FD_ZERO(&readable); //clear fd_set 'readable'
        FD_SET(pty->master, &readable); //add 'pty' fd to 'readable'
        
        SDL_Event event;
        if (SDL_PollEvent(event) {
                //detect keypress here
        }

        //waits until any file descriptor from 'readable' can be read
        int select_val = select(maxfd + 1, &readable, NULL, NULL, &tv);
        if (select_val == -1) {
                //error
        } else if (select_val > 0) {
                //read character here
        }
}

Do be careful that if you set the timeout to zero your program may loop using 100% CPU time until a key is pressed; you definitely don’t want that!

1 Like

Good idea, thanks!
I set the tv.tv_usec variable to 10000, and it works the same.