Como ler o buffer de entrada do terminal imediatamente após pressionar a tecla

Quero ler as teclas de seta no meu programa c e substituí-las (imediatamente no próprio terminal) por alguma outra string. Estou tentando implementar a funcionalidade do histórico do bash como nos terminais unix. Eu escrevi esse código.

int
main(int argc, char *argv[])
{
    char c;
    char str[1024];
    int i = 0;
    while((c = fgetc(stdin)) != '\n'){
      if(((int)c) == 27){
        c=fgetc(stdin);
        c=fgetc(stdin);
        if (c == 'A')
        {
          printf("%c[A%c[2K",27, 27);
          printf("UP");
        }
      }
      str[i++] = c;
    }
    printf("\n");

  return 0;
}

Mas isso não funciona porque os terminais aguardam uma nova linha ou EOF enviar o buffer de entrada para stdin. Então, eu tenho que pressionar a tecla Enter / Return para analisar a entrada do usuário.

Aqui nesteresponda o usuário mencionado para usarsystem ("/bin/stty raw"); mas isso substitui todos os comportamentos padrão do terminal (por exemplo, backspace, delete etc.).

Então, existe alguma maneira de ler / manipular o buffer de entrada dos terminais diretamente e ajustar o próprio buffer se for detectado pressionamento de tecla de seta?

Ambiente - Ubuntu (Linux)

Atualização 1: Existe um método para alterar o sinal / interrupção (o padrão é pressionar a tecla Enter) que faz o terminal enviar a entrada armazenada para o buffer? Isso também pode me ajudar a alcançar o mesmo comportamento.

Código final:

Eu descobri os caracteres ASCII para pressionar teclas específicas, verificando a saída destrace bash

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <termios.h>

#define ESCAPE '\33'
#define BACKSPACE '\177'
#define DELETE '~'

int main(){
    struct termios termios_p;
    struct termios termios_save;
    tcgetattr(0, &termios_p);
    termios_save = termios_p;

    termios_p.c_lflag &= ~(ICANON|ECHO);
    tcsetattr(0,TCSANOW, &termios_p);
    char buff;
    while(read(0, &buff, 1) >= 0){
        if(buff > 0){
            if(buff == ESCAPE){
                read(0, &buff, 1);
                read(0, &buff, 1);
                if(buff == 'A'){
                    write(2, "up", 2);
                }else if(buff == 'B'){
                    write(2, "down", 4);

                }else if(buff == 'C'){
                    write(2, "\33[C", 3);

                }else if(buff == 'D'){
                    write(2, "\10", 2);                    
                }
            }else if(buff == BACKSPACE){
                write(2, "\10\33[1P", 5);
            }else if(buff == DELETE){
                write(2, "\33[1P", 4);
            }else{
                write(2,&buff,1);
            }
            // write(2,&buff,1);
            if(buff == 'q'){
                break;
            }
        }
    }
    tcsetattr(0,TCSANOW, &termios_save);
    return 0;
}

questionAnswers(2)

yourAnswerToTheQuestion