Anzeige:
Seite 2 von 3 ErsteErste 123 LetzteLetzte
Ergebnis 16 bis 30 von 43

Thema: GNU Readline & Telnet Client & Pseudo Terminal

  1. #16
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Zitat Zitat von 7.e.Q
    Wie kriege ich es hin, daß entweder Putty keine CRs braucht (muss automatisch passieren, also ohne den Haken in den Optionen), oder daß mein Programm automatisch an jedes NL ein CR dranhängt (möglichst auch automatisch und nicht zufuß)?
    IIRC, musst du im Telnet-Protokoll immer NL CR senden, egal, wie das BS einen Newline anzeigt. Deine Schreibroutine muss also immer empfangene NL CR zu NL machen und zu sendende NL zu NL CR.

    EDIT: Daß es ein VT100 ist, teile ich Readline bereits mit
    rl_terminal_name = "VT100";
    Sicher, dass das reicht, und du das nicht per rl_reset_terminal machen musst?

    TerminalMasterSettings.c_iflag &= ~(ICANON|ECHO);
    Du schaltest ICANON und ECHO aus. ~ ist binäres NOT.

    TerminalMasterSettings.c_iflag |= ICANON|ECHO;
    Damit schaltest du sie an.
    Beispiel: ICANON sei 00000001b
    ECHO sei 00000010b
    c_iflag sei 00110011

    ICANON|ECHO => 00000011b, ~(ICANON|ECHO) = 11111100b, c_iflags &= ... -> 00110000b
    andere Richtung dürfte auch klar sein

  2. #17
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    Hi,

    @Joghurt: ich danke dir ganz herzlich für deine Unterstützung! Jetzt funktioniert soweit alles.

    Das große Problem des blockierenden Readlines rührte nur von einer einzigen Ursache her. Ich habe keine .inputrc in meinem Programm nachgeladen gehabt, und er nimmt dann anscheinend die vom System. In der .inputrc vom System steht drin:

    set convert-meta off

    Das führte letztendlich zum Blockieren von Readline. Neue explizite .inputrc für mein Programm gebaut, darin convert-meta auf "on" gesetzt, jetzt reagiert er mit der Ausgabe einer ~, wenn er eine Escape Sequenz nicht kennt. Trotzdem musste ich die Übergabe von Escape Sequenzen programmintern puffern, sprich, wenn ein ESC reinkommt (0x1B), musste ich danach nochmal manuell ein read() auf dem Socket machen und daraus eine verständliche ESC Sequenz für das Terminal zusammen bauen. Funktioniert so aber. Jetzt hab ich alles, History, Funktionstasten, Autocompletion... fast alles, was ich wollte.

    Nur ein winzig kleines Problem oder vielmehr eine Lästigkeit, als ein Problem habe ich noch:

    das Echo der Eingabe kommt immer ca. eine halbe Sekunde verzögert. Nicht so tragisch, da er trotzdem immer alles akzeptiert. Aber es stört doch ein wenig bei der Eingabe, bzw. beim Bearbeiten der Kommandozeile. Wie bekommt man das weg? Dann bin ich damit zumindest endgültig zufrieden.

    Aber ich wäre nicht ich, wenn nicht...

    Jetzt kommt was neues dazu:
    ich möchte, daß bestimmte Dinge an der oberen und unteren Zeile des Telnet-Fensters angezeigt werden. Beispielsweise möchte ich, daß die F-Tasten Belegung, ähnlich wie beim Midnight Commander, in der untersten Zeile angezeigt wird. In der obersten Zeile möchte ich einen bestimmten Text anzeigen lassen. Aber Achtung: NCurses verwende ich bereits auf einer anderen Konsole, um dort lokal auf dem Gerät eine Überwachungsoberfläche anzuzeigen. Das ganze sieht dann in etwa so aus:


    Die Überwachungskonsole

    Die Remotekonsole schaut z.Z. so aus:


    Die Remotekonsole
    Geändert von 7.e.Q (23-05-2005 um 08:45 Uhr)

  3. #18
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    man newscr

    Betreffs des delays: ich denke, der kommt einfach dadurch zustande, dass die Zeichen immer von Socket zum virtuellen Terminal zu readline und zurück gesendet werden, ich denke, damit musst du leben.
    Geändert von Joghurt (23-05-2005 um 11:55 Uhr)

  4. #19
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    Hallo mal wieder, alten Thread mal wieder ausgraben...

    also ich hab immernoch das Problem, daß Readline ab und an mal blockiert. Das darf nicht passieren. Beispielsweise blockiert Readline, wenn ich im Eingabefenster sowas wie ê oder á oder so eingebe. Also irgendwas mit diesen sogenannten "deadkeys". Gebe ich allerdings ´ oder ^ gefolgt von einem Blank ein, blockiert Readline nicht.

    Ein anderer Punkt, an dem readline blockiert, ist wenn ich folgendes mache:

    - Zeile eingeben
    - Enter drücken
    - Cursor rauf (vorigen Befehl aus der History holen)
    - weitere Zeichen bei vorigem Befehl anhängen
    - Enter drücken
    -> Readline blockiert

    Kurz gesagt, verändere ich einen aus der History geholten Befehl vor dem erneuten Abschicken, blockiert Readline nach Drücken von Enter.


    Worin können diese Probleme begründet sein?

    Meine inputrc
    Code:
    # /etc/inputrc:
    # $Header: /home/cvsroot/gentoo-src/rc-scripts/etc/inputrc,v 1.7 2003/10/13 22:30:09 azarah Exp $
    
    # do not bell on tab-completion
    #set bell-style none
    
    set meta-flag on
    set convert-meta off
    set output-meta off
    
    # Completed names which are symbolic links to
    # directories have a slash appended.
    set mark-symlinked-directories on
    
    $if mode=emacs
    
    # for linux console and RH/Debian xterm
    "\e[1~": beginning-of-line
    "\e[4~": end-of-line
    #"\e[5~": beginning-of-history
    #"\e[6~": end-of-history
    "\e[5~": history-search-backward
    "\e[6~": history-search-forward
    "\e[3~": delete-char
    "\e[2~": quoted-insert
    "\e[5C": forward-word
    "\e[5D": backward-word
    
    # for rxvt
    "\e[8~": end-of-line
    
    # for non RH/Debian xterm, can't hurt for RH/DEbian xterm
    "\eOH": beginning-of-line
    "\eOF": end-of-line
    
    # for freebsd console
    "\e[H": beginning-of-line
    "\e[F": end-of-line
    $endif
    
    # fix Home and End for German users
    "\e[7~": beginning-of-line
    "\e[8~": end-of-line

    EDIT:

    Neues zum Thema: es half, die Funktion

    rl_getc

    selbst zu schreiben, also den Zeiger rl_getc_function umzubiegen. Das half zumindest, die blockierenden Reads beim Einlesen von unbekannten Zeichen zu unterbinden.

    Jetzt stellte sich heraus, daß meine vorhin beschriebenen Probleme unterschiedlicher Natur sind, jedoch die selbe Wirkung haben (ich hasse sowas). Das zweite Problem ist, daß Readline beim Einlesen einer Kommandozeile aus der History, die nachträglich über die Eingabe modifiziert wurde, in der Funktion rl_prep_terminal hängen bleibt. Genauer gesagt bei dem Aufruf tcsetattr.

    Backtrace aus gdb:
    Code:
    #0  0x4024cf99 in tcsetattr () from /lib/libc.so.6
    #1  0x400695c1 in _set_tty_settings () from /lib/libreadline.so.4
    #2  0x400695e6 in set_tty_settings () from /lib/libreadline.so.4
    #3  0x4006970d in rl_prep_terminal () from /lib/libreadline.so.4
    #4  0x4007544a in _rl_callback_newline () from /lib/libreadline.so.4
    #5  0x40075534 in rl_callback_read_char () from /lib/libreadline.so.4
    #6  0x080675e6 in main (argc=1, argv=0xbffffd84) at main.cxx:854
    Geändert von 7.e.Q (28-07-2005 um 13:35 Uhr)

  5. #20
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Rufst du jetzt rl_reset_terminal auf oder nicht?

  6. #21
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    Ich meine ja. Ich muss das morgen mal überprüfen. Komme von hier aus (zuhause) nicht an den Sourcecode heran.

  7. #22
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    Ein Mal, ja. Beim Initialisieren. Muss ich das kontinuierlich aufrufen?

  8. #23
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    *push* dumdidum....

  9. #24
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Zitat Zitat von 7.e.Q
    Ein Mal, ja. Beim Initialisieren. Muss ich das kontinuierlich aufrufen?
    Eigentlich nur, nachdem du rl_terminal_name verändert hast.

  10. #25
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Da du das Programm ja eh unter die GPL stellen musst, kannst du die momentane Version ja einfach schonmal irgendwo hochladen, dann können dir sicherlich mehr Leute helfen.

    Außerdem würde ich vorschlagen, dass du Readline einmal selbst mit Debugginginfo compilierst, und dann mal schaust, an welcher Stelle genau es hängt.

  11. #26
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    Stimmt... ich weiß, daß ich den Source laut GPL zur Verfügung stellen muss. MIR ist das bekannt. Meinem Chef offenbar noch nicht. Das muss ich dem also vorher verklickern, damit's hier keinen Stunk gibt, desderwegen.

    Außerdem muss ich das wohl vorher noch durch dokumentieren, sonst begreift das keiner. Und zuletzt muss ich sagen, daß mit dem Programm alleine eh niemand was anfangen kann, weil es hier für unser System proprietär ist.

    Readline mit Debuginfos zu kompilieren werde ich mal ausprobieren. Ich halte dich (euch) auf dem Laufenden.

  12. #27
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    Also gdb sagt mir, daß Readline an der folgenden Position (Frame #0) steht:

    Code:
    #0  0x4024ef99 in tcsetattr () from /lib/libc.so.6
    #1  0x400699b5 in _set_tty_settings (tty=40, tiop=0xbfb29c00) at ../rltty.c:540
    #2  0x400699da in set_tty_settings (tty=40, tiop=0xbfb29c00) at ../rltty.c:550
    #3  0x40069b44 in rl_prep_terminal (meta_flag=1) at ../rltty.c:667
    #4  0x40075bde in _rl_callback_newline () at ../callback.c:75
    #5  0x40075cc8 in rl_callback_read_char () at ../callback.c:132
    #6  0x08067642 in CMain::MainLoop (this=0x8089660, argc=1, argv=0xbffffd84) at CMain.cxx:679
    #7  0x0804b16e in main (argc=1, argv=0xbffffd84) at main.cxx:148
    Es hat sich strukturell etwas am Source geändert. Ich habe die main() in die Klasse CMain ausgegliedert und sie MailLoop genannt. Diese rufe ich von der neuen main() aus nur noch auf. Hat nur was mit besserem Programmierstil zu tun.

    Also die Stelle, die der Debugger noch in dem Source meines Programms anzeigt, sieht wie folgt aus:

    Code:
    				if(FD_ISSET(InfoServer->InternalTerminalMasterFD(), &LocalFDSet) )
    				{
    //					fprintf(stderr," * entering into readline\n");
    					rl_callback_read_char();
    //					fprintf(stderr," * returning from readline\n");
    				}
    Also wenn Daten zum Lesen auf der Masterseite des PTY verfügbar sind, welches als Standardkonsole für Readline initialisiert wurde, wird die Funktion rl_callback_read_char aufgerufen, welche dann die verfügbaren Zeichen aus dem Terminal holt und sie an Readline übergibt.

    Aus irgendeinem Grund bleibt Readline nur nach Änderung und Eingabe (durch ENTER) einer aus der History geholten Befehlszeile an oben genannter Stelle hängen. Hole ich eine Befehlszeile aus der History und gebe sie über ENTER an Readline zurück OHNE sie zu ändern, läuft das Programm problemlos weiter.

  13. #28
    Registrierter Benutzer
    Registriert seit
    25.10.2004
    Beiträge
    819
    Lass das Programm mal mit strace laufen, dann sieht man leichter, womit tcsetattr aufgerufen wird.

  14. #29
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    Wollte dir vorhin noch schreiben, was strace ausgibt, doch irgendwie war hier alles down... morgen also.
    Geändert von 7.e.Q (10-08-2005 um 09:13 Uhr)

  15. #30
    Registrierter Benutzer
    Registriert seit
    02.07.2004
    Beiträge
    456
    So... also alles, was strace nach dem letzten select() ausgibt, bis hin zum Absturz:

    Code:
    rt_sigprocmask(SIG_BLOCK, NULL, [], 8)  = 0
    fcntl64(40, F_GETFL)                    = 0x802 (flags O_RDWR|O_NONBLOCK)
    fcntl64(40, F_SETFL, O_RDONLY|O_NONBLOCK) = 0
    read(40, "\r", 1)                       = 1
    fcntl64(40, F_SETFL, O_RDWR)            = 0
    write(40, "\n", 1)                      = 1
    rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
    ioctl(40, SNDCTL_TMR_STOP or TCSETSW, {B38400 opost isig icanon echo ...}) = 0
    rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
    rt_sigaction(SIGWINCH, {0x400337b0, [], 0}, {0x4007353d, [], SA_RESTART}, 8) = 0
    time(NULL)                              = 1123652289
    write(45, "\n", 1)                      = 1
    write(45, "\r", 1)                      = 1
    time(NULL)                              = 1123652289
    open("/etc/ists_tcp.conf", O_RDONLY)    = 46
    fstat64(46, {st_mode=S_IFREG|0644, st_size=87, ...}) = 0
    old_mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x40018000
    read(46, "[MSGCOLORS]\nURGENT= 36 49\nHEADLI"..., 4096) = 87
    read(46, "", 4096)                      = 0
    close(46)                               = 0
    munmap(0x40018000, 4096)                = 0
    write(45, "\33", 1)                     = 1
    write(45, "[", 1)                       = 1
    write(45, "3", 1)                       = 1
    write(45, "6", 1)                       = 1
    write(45, ";", 1)                       = 1
    write(45, "4", 1)                       = 1
    write(45, "9", 1)                       = 1
    write(45, "m", 1)                       = 1
    write(45, "U", 1)                       = 1
    write(45, "n", 1)                       = 1
    write(45, "k", 1)                       = 1
    write(45, "n", 1)                       = 1
    write(45, "o", 1)                       = 1
    write(45, "w", 1)                       = 1
    write(45, "n", 1)                       = 1
    write(45, " ", 1)                       = 1
    write(45, "c", 1)                       = 1
    write(45, "o", 1)                       = 1
    write(45, "m", 1)                       = 1
    write(45, "m", 1)                       = 1
    write(45, "a", 1)                       = 1
    write(45, "n", 1)                       = 1
    write(45, "d", 1)                       = 1
    write(45, " ", 1)                       = 1
    write(45, "\'", 1)                      = 1
    write(45, "s", 1)                       = 1
    write(45, "d", 1)                       = 1
    write(45, "c", 1)                       = 1
    write(45, "d", 1)                       = 1
    write(45, "\'", 1)                      = 1
    write(45, ".", 1)                       = 1
    write(45, " ", 1)                       = 1
    write(45, "T", 1)                       = 1
    write(45, "r", 1)                       = 1
    write(45, "y", 1)                       = 1
    write(45, " ", 1)                       = 1
    write(45, "\'", 1)                      = 1
    write(45, "h", 1)                       = 1
    write(45, "e", 1)                       = 1
    write(45, "l", 1)                       = 1
    write(45, "p", 1)                       = 1
    write(45, "\'", 1)                      = 1
    write(45, "\n", 1)                      = 1
    write(45, "\r", 1)                      = 1
    write(45, "\33", 1)                     = 1
    write(45, "[", 1)                       = 1
    write(45, "3", 1)                       = 1
    write(45, "9", 1)                       = 1
    write(45, ";", 1)                       = 1
    write(45, "4", 1)                       = 1
    write(45, "9", 1)                       = 1
    write(45, "m", 1)                       = 1
    write(40, "\10", 1)                     = 1
    rt_sigprocmask(SIG_BLOCK, [INT], [], 8) = 0
    ioctl(40, TIOCGWINSZ, {ws_row=0, ws_col=0, ws_xpixel=0, ws_ypixel=0}) = 0
    ioctl(40, TIOCSWINSZ, {ws_row=0, ws_col=0, ws_xpixel=0, ws_ypixel=0}) = 0
    ioctl(40, SNDCTL_TMR_TIMEBASE or TCGETS, {B38400 opost isig icanon echo ...}) = 0
    ioctl(40, SNDCTL_TMR_STOP or TCSETSW
    Das merkwürdige ist, daß der letzte ioctl anscheinend nicht komplett ausgeführt werden kann. Jedenfalls bleibt strace in der Ausgabe dieses Aufrufs stecken.
    Geändert von 7.e.Q (10-08-2005 um 07:43 Uhr) Grund: Irrtum...

Lesezeichen

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •