Xterm пейджър - изход от два терминала - използване на тръба и dup2

Опитвам се да внедря пейджър в C, искам кодът да отвори друг терминал (xterm) и да отпечата някои резултати в него.

Така че първо създавам канал и разклонявам главната програма, детето ще изпълни xterm с командата tail, основната програма ще изведе нещата в канала и детето, преди да изпълни xterm, ще дублира, асоциира канала с дескриптора на файла stdin на дете.

Може да съм разбрал погрешно използването на pipe и dup2, защото кодът ми не работи.

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;
}

Засега въвеждам нещо в родителя и нищо не се отпечатва и в двата процеса. И така, как да създам комуникация между xterm и родителския процес?

Редактиране: извадка от моята програма:

#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];
}

В основни линии:

verbosity(VERBM_XTERMO);

Последваха няколко обаждания до verbose. Можете да видите в init_outputxterm опит за писане в xterm веднага след създаването на xterm, както в решението. Но всичко се показва само след като излязох от програмата, като затворих брутално основния терминал, правейки дъщерния процес сирак (ако изляза с Ctrl-C детето също се убива).


person Nicolas Scotto Di Perto    schedule 07.04.2016    source източник


Отговори (1)


Самият Xterm не чете от stdin, така че подаването на данни към него няма да има ефект. Но можете да отворите наименуван канал и да прочетете с tail -f /tmp/mypipe от него, например така:

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;
}

Това ще отвори канал с име /tmp/mypipe. Родителският процес записва данни в него и tail -f-процесът в xterm ще ги изведе впоследствие.

person Ctx    schedule 07.04.2016
comment
Може би пътят до вашия tail е различен или тръбата /tmp/mypipe не е създадена правилно по някаква причина? - person Ctx; 07.04.2016
comment
Работи, благодаря! Проблемът дойде от моя мениджър на прозорци за подреждане, i3, тъй като главният терминал беше стартиран в плаващ режим и i3 не знаеше как да управлява отворения прозорец, това се решава чрез стартиране на главния терминал в режим на подреждане. - person Nicolas Scotto Di Perto; 07.04.2016
comment
Не знам защо, но в пълната ми програма изходът дойде в подчинения дъщерен терминал само когато излязох от програмата... Опитах и ​​write, и fprintf, комбинирани с fflush, въпреки че работи в обикновен main с кода по-горе . Моята програма има многопоточност, може ли проблема да идва от това? Не мисля така, защото това е същият проблем като printf, който има достъп до stdin. - person Nicolas Scotto Di Perto; 07.04.2016
comment
Можете ли да предоставите минимален примерен код? Или във вашия въпрос по-горе, или като нов въпрос - person Ctx; 07.04.2016
comment
Може би tail все пак не е толкова подходящ за тази задача... Просто използвайте cat /tmp/mypipe, за да избегнете проблеми с буферирането - person Ctx; 07.04.2016