2016-04-07 16 views
0

Ich versuche, einen Pager in C zu implementieren, ich möchte den Code ein anderes Terminal öffnen (xterm) und einige Ausgaben in es drucken.Xterm Pager - zwei Terminal-Ausgang - mit Rohr und dup2

Also erstelle ich zuerst eine Pipe und fork das Hauptprogramm, das Kind wird xterm mit dem Tail-Befehl ausführen, das Hauptprogramm wird Dinge in der Pipe ausgeben und das Kind vor der Ausführung von xterm wird die Pipe mit der stdin verbinden Dateibeschreibung des Kindes.

Ich habe möglicherweise die Verwendung von pipe und dup2 missverstanden, weil mein Code nicht funktioniert.

int p[2]; 
pipe(p); 
char buff[512]; 
switch (fork()) { 
    case -1: 
     fprintf(stderr, "Fork error.\n"); 
     break; 
    case 0: 
     dup2(p[0], 0); 
     close(p[0]); 
     close(p[1]); 
     execlp("xterm", "xterm", "tail", NULL); 
     break; 
    default: 
     scanf("%s", buff); 
     write(p[1], buff, strlen(buff)); 
     getchar(); 
     break; 
} 

Für jetzt tippe ich etwas in den Eltern und nichts wird in beiden Prozess gedruckt. Also, wie erstelle ich eine Kommunikation zwischen Xterm und dem übergeordneten Prozess?

Edit: eine Probe von meinem Programm:

#define VERBM_NOVERB 0 
#define VERBM_STDOUT 1 
#define VERBM_XTERMO 2 

static int fd_xterm = -1; 

void init_outputxterm() { 
    mkfifo("/tmp/mypipe", 0600); 
    switch (fork()) { 
     case -1: 
      fprintf(stderr, "Fork error.\n"); 
      break; 
     case 0: 
      execlp("xterm", "xterm", "-e", "/usr/bin/tail -f /tmp/mypipe", NULL); 
      printf("FAILURE\n"); 
      exit(EXIT_FAILURE); 
      break; 
     default: 
      if ((fd_xterm = open("/tmp/mypipe", O_WRONLY)) == -1) { 
       fprintf(stderr, "Can't open pipe"); 
       exit(1); 
      } 
      write(fd_xterm, "yayay\n", 6); 
      dprintf(fd_xterm, "Hello world\n"); 
      getchar(); 
      break; 
    } 
} 

void verbose_xterm(char *format, ...) { 
    dprintf(fd_xterm, BOLD UNDERLINED "verbose - " RESET); 
    va_list aptr; 
    va_start(aptr, format); 
    dprintf(fd_xterm, format, aptr); 
    va_end(aptr); 
} 


void verbose_stdout(char *format, ...) { 
    printf(BOLD UNDERLINED "verbose - " RESET); 
    va_list aptr; 
    va_start(aptr, format); 
    vprintf(format, aptr); 
    va_end(aptr); 
} 

void verbose_noverb(char *format, ...) { 
} 

void (*verbose)(char *format, ...) = verbose_stdout; 


void (*verbose_mode[])(char *, ...) = { 
    verbose_noverb, 
    verbose_stdout, 
    verbose_xterm 
}; 

void verbosity(int mode) { 
    if (mode == VERBM_XTERMO) 
     init_outputxterm(); 
    verbose = verbose_mode[mode]; 
} 

Im Haupt:

verbosity(VERBM_XTERMO); 

Gefolgt von mehreren Anrufen zu verbose. Sie können in init_outputxterm ein Tentavie in Xterm kurz nach der Erstellung von Xterm, wie in der Lösung zu schreiben. Aber alles wird erst angezeigt, nachdem ich das Programm beendet habe, indem ich das Hauptterminal brutal geschlossen habe, damit das Kind Waisenkind wird (wenn ich mit Ctrl-C aufhöre, wird das Kind ebenfalls getötet).

Antwort

1

Xterm selbst liest nicht von der Standardeingabe, daher hat das Eingeben von Daten keinen Effekt. Aber man konnte eine Named Pipe öffnen und mit tail -f/tmp/meinepipe davon, zum Beispiel wie folgt lauten:

mkfifo("/tmp/mypipe", 0600); 
switch (fork()) { 
    case -1: 
     fprintf(stderr, "Fork error.\n"); 
     break; 
    case 0: 
     execlp("xterm", "xterm", "-e", "/usr/bin/tail -f /tmp/mypipe", NULL); 
     exit(EXIT_FAILURE); 
     break; 
    default: 
     ; 
     char buff[512]; 
     int fd = open("/tmp/mypipe", O_WRONLY); 
     scanf("%s", buff); 
     write(fd, buff, strlen(buff)); 
     getchar(); 
     break; 
} 

Dieses eine Named Pipe /tmp/mypipe geöffnet. Der übergeordnete Prozess schreibt Daten in ihn und der tail -f-Prozess im xterm wird ihn anschließend ausgeben.

+0

Ich weiß nicht warum, aber xterm öffnet einfach und schließt sofort mit diesem Code ... –

+0

Vielleicht ist der Pfad zu deinem 'tail' anders oder die Pipe'/tmp/mypipe' wurde aus irgendeinem Grund nicht korrekt erstellt ? – Ctx

+0

Es funktioniert, danke! Das Problem kam von meinem tiling window manager, i3, weil das Hauptterminal im Floating-Modus gestartet wurde und i3 nicht wusste, wie das Pop-up-Fenster zu verwalten ist. Das wird gelöst, indem das Hauptterminal im Tiling-Modus läuft. –