2016-04-27 2 views
1

Mein C-Programm führen mehrere Thread im Terminal, die Nachrichten asynchron drucken. Ich möchte, dass ein Thread die Ausgabe von Flüchen anzeigt, aber da es asynchron ist, muss es in einem anderen Terminal sein.Senden von Curses Eingabe an ein anderes Terminal in C über einen Fifo

Meine Idee ist es, die Curses-Ausgabe zu einem FIFO zu schreiben und ein Terminal mit cat fifo zu öffnen.

Aber wie könnte ich die Ausgabe die Flüche wiederherstellen und es in eine Datei ausgeben?

Vielen Dank.

Antwort

1

curses benötigt direkten Zugriff auf das Terminal, um nach Escape-Codes zu suchen, Auflösung usw. zu erkennen. Sie sollten wahrscheinlich einen Thread für die Ausgabe von Curses im aktuellen (Haupt-) Terminal verwenden und alle Debug-Meldungen von anderen Threads umleiten entweder eine Protokolldatei/Rohr/Protokollierung (und sie in den Flüchen präsentieren, wenn Sie wollen)

+0

Ja, aber ich frage mich, wie Flüche Daten Ausgang zu fangen, ich weiß nicht, wie es zu tun. –

+0

Sie sollten nicht, da Flüche direkten Schreibzugriff auf die tty erwarten.Sie können wahrscheinlich den Dateideskriptor an der Stelle 1 hintergehen und ersetzen, nachdem Flüche mit etwas anderem initialisiert wurden, wie eine Pipe –

+0

Sie können 'newterm' anstelle von' initscr' verwenden, um Flüche mit einem anderen Terminal als stdin/stdout zu initialisieren. Sie können es sogar mehrmals aufrufen, um mehrere Terminals zu verwalten. –

2

curses verwendet ein Terminal für seine Eingabe und Ausgabe, also wenn Sie das abfangen wollen und es irgendwo anders als ein Terminal gehen Die einfachste Methode (obwohl nicht trivial) ist die Verwendung eines Pseudo-Terminals. Sie tun das, indem Sie posix_openpt aufrufen, die Ihnen ein pseudoterminal Hauptgerät gibt. Rufen Sie dann grantpt, unlockpt und ptsname an, um den Namen eines Endgeräts zu erhalten, das Sie dann eingeben und an Flüche newterm übergeben können, um das Terminal zu initialisieren.

Sobald das erledigt ist, wird alles, was curses in das Terminal schreibt, vom Master gelesen, und alles, was auf den Master geschrieben ist, wird in Flüche eingegeben. Es ist wie ein Fifo, nur mit all den zusätzlichen Terminalfunktionen, die curses erwartet.

+0

Deine Antwort scheint für meine Frage am nächsten zu sein, aber ich verstehe den letzten Teil nicht: Sobald ich das Pseudoterminal mit fopen geöffnet habe, sollte ich es als Eingabe übergeben und meinen Fifo als Ausgabe übergeben? Der Fifo wird verwendet, um mit dem externen Xterm zu kommunizieren. –

+0

Auch wenn ich newterm rufe, bekomme ich einen 'SCREEN *', der weiß, wie man auf 'WINDOW *' schreibt (mit 'waddch' zum Beispiel), aber wie kann ich auf einen' SCREEN * 'schreiben? –

+0

Sie verwenden 'set_term', um den aktuellen Bildschirm einzustellen, mit dem Sie arbeiten, und dann das globale' WINDOW * stdscr' –

0

ncurses benötigt einen Anschluss, weil er die E/A-Verbindung initialisiert. Ein FIFO wäre nicht geeignet, da es einseitig ist und (siehe zum Beispiel Perform action if input is redirected) wahrscheinlich nicht als Terminal initialisiert werden kann. ncurses verwendet die Umgebungsvariable , um die Terminalbeschreibung nachzuschlagen (das aktuelle Terminal wird in dieser Angelegenheit nicht konsultiert).

Es gibt ein einfaches Beispiel, ditto in ncurses-examples, das xterm für mehrere Eingabe/Ausgabe-Bildschirme verwendet. Das nutzt die pty-Schnittstelle, zum Beispiel

#ifdef USE_XTERM_PTY 
    int amaster; 
    int aslave; 
    char slave_name[1024]; 
    char s_option[sizeof(slave_name) + 80]; 
    const char *xterm_prog = 0; 

    if ((xterm_prog = getenv("XTERM_PROG")) == 0) 
     xterm_prog = "xterm"; 

    if (openpty(&amaster, &aslave, slave_name, 0, 0) != 0 
     || strlen(slave_name) > sizeof(slave_name) - 1) 
     failed("openpty"); 
    if (strrchr(slave_name, '/') == 0) { 
     errno = EISDIR; 
     failed(slave_name); 
    } 
    sprintf(s_option, "-S%s/%d", slave_name, aslave); 
    if (fork()) { 
     execlp(xterm_prog, xterm_prog, s_option, "-title", path, (char *) 0); 
     _exit(0); 
    } 
    fp = fdopen(amaster, "r+"); 
    if (fp == 0) 
     failed(path); 
#else 

und newterm dass Dateideskriptor ncurses weitergeben müssen:

static void 
open_screen(DITTO * target, char **source, int length, int which1) 
{ 
    if (which1 != 0) { 
     target->input = 
      target->output = open_tty(source[which1]); 
    } else { 
     target->input = stdin; 
     target->output = stdout; 
    } 

    target->which1 = which1; 
    target->titles = source; 
    target->length = length; 
    target->fifo.head = -1; 
    target->screen = newterm((char *) 0,  /* assume $TERM is the same */ 
          target->output, 
          target->input); 

    if (target->screen == 0) 
     failed("newterm"); 

    (void) USING_SCREEN(target->screen, init_screen, target); 
} 

Wenn Sie die erste zitierte Abschnitt von ditto lesen, werden Sie feststellen, dass es eine option of xterm verwendet der es ermöglicht, eine Anwendung einen Dateideskriptor zu übergeben:

-Sccn This option allows xterm to be used as an input and output 
      channel for an existing program and is sometimes used in spe- 
      cialized applications. The option value specifies the last few 
      letters of the name of a pseudo-terminal to use in slave mode, 
      plus the number of the inherited file descriptor. If the 
      option contains a "/" character, that delimits the characters 
      used for the pseudo-terminal name from the file descriptor. 
      Otherwise, exactly two characters are used from the option for 
      the pseudo-terminal name, the remainder is the file descriptor. 
      Examples (the first two are equivalent since the descriptor 
      follows the last "/"): 

       -S/dev/pts/123/45 
       -S123/45 
       -Sab34 

      Note that xterm does not close any file descriptor which it did 
      not open for its own use. It is possible (though probably not 
      portable) to have an application which passes an open file 
      descriptor down to xterm past the initialization or the -S 
      option to a process running in the xterm. 

Hier ein Screenshot zeigt, ditto:

enter image description here

+0

Das ist ziemlich ordentlich, aber ich kann nur opencurses verwenden, die ich ncurses nicht kenne, benutzt dieses Beispiel es wirklich? –

+0

Das Beispiel erstellt/arbeitet mit verschiedenen Curses-Implementierungen. Es gibt ifdefs, um ncurses-Erweiterungen zu verwenden, aber der Screenshot hat diese nicht verwendet. (Was ist "opencurses"?). –

+0

Es ist der Name der UNIX-Curses-Bibliothek 'curses.h'. –

Verwandte Themen