pseudo terminals
-
Hallo!
Ich möchte einen Terminal-Emulator für den Framebuffer schreiben und beschäftige mich gerade mit pseudo terminals. Aus
man pty
konnte ich bereits das folgende zusammenschreiben:int mfd = posix_openpt(O_RDWR); if(mfd == -1) return 0; if(grantpt(mfd) == -1) return 0; if(unlockpt(mfd) == -1) return 0; char *slave = ptsname(mfd); if(!slave) return 0; int sfd = open(slave, O_RDWR); if(sfd == -1) return 0;
Weiter komme ich aber nicht. In den kurzen Manpages steht leider nicht mehr und ich kann auch kein Beispielcode finden. Ich hab mir mal den Sources von xterm angeschaut, werde aber nicht schlau daraus.
Die master-Seite ist einigermaßen klar: Da lese ich die Daten, die auf den Bildschirm sollen und schreibe die Daten, die von der Tastatur kommen. Aber wie kann ich die slave-Seite mit einem Prozess (zum Beispiel sh) verbinden?Danke im Voraus.
MfG
-
So, ich bin jetzt trotz der schlechten Doku ein bisschen weiter:
#include <stdio.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <fcntl.h> #include <sys/wait.h> #include <termios.h> int main(int argc, char *argv[]) { int mfd = posix_openpt(O_RDWR); if(mfd == -1) return 0; if(grantpt(mfd) == -1) return 0; if(unlockpt(mfd) == -1) return 0; char *slave = ptsname(mfd); if(!slave) return 0; int sfd = open(slave, O_RDWR); if(sfd == -1) return 0; pid_t pid = fork(); if(pid == -1) return 0; if(!pid) { dup2(sfd, 0); dup2(sfd, 1); dup2(sfd, 2); execl("/bin/sh", NULL); } else { struct termios term_attr; if (tcgetattr(STDIN_FILENO, &term_attr) != 0) return 0; int old_flags = term_attr.c_lflag; term_attr.c_lflag &= ~ECHO; if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr) != 0) return 0; fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK); fcntl(mfd, F_SETFL, fcntl(mfd, F_GETFL) | O_NONBLOCK); char *c = new char[1]; while(waitpid(pid, NULL, WNOHANG) == 0) { int r = read(STDIN_FILENO, c, 1); if(r != EAGAIN && r > 0) write(mfd, c, 1); r = read(mfd, c, 1); if(r != EAGAIN && r > 0) write(STDOUT_FILENO, c, 1); } delete[] c; term_attr.c_lflag = old_flags; tcsetattr(STDIN_FILENO, TCSAFLUSH, &term_attr); } return 0; }
Funktioniert soweit ganz gut. Um signale (Ctrl-C) und so kümmere ich mich später. Mein Problem ist jetzt, dass ich nicht sofort sehe, was ich eingebe, sondern erst, nachdem ich Enter gedrückt habe. Eine Untersuchung mit ddd hat ergeben, dass die Daten überhaupt erst mit read gelesen werden, wenn ich die Eingabetaste gedrückt habe. Wie kann ich das ändern?
-