pipe-fork-dup-exec не работает

#c #linux #pipe #fork

#c #linux #труба #вилка

Вопрос:

Я пытаюсь создать поддельную оболочку, создав подпроцесс bash и отправив входные данные в него и извлекая из него выходные данные с помощью другого потока. Кажется, мои вызовы write() прошли успешно, но я не могу получить от него никаких выходных данных. Вот мой код и некоторые выходные данные на терминале.

 #include <iostream>
#include <unistd.h> 
#include <istream>
#include <fstream>
#include <sys/types.h>
#include <sys/wait.h>
#include <cstdio>
#include <thread>
#include <cassert>


void read_and_write(int fd) {
    char* buffer = NULL;
    size_t size = 0;
    FILE* fp = fdopen(fd, "r");
    assert(fp);

    loop:
    printf("writing thread openn");
    while (getline(amp;buffer, amp;size, fp) != -1) {
        printf("writingn");
        printf("%s", buffer);
    }
    printf("done_printingn");
    goto loop;

    free(buffer);
}

int main(int argc, char const *argv[]){
    std::string user_in;

    int stderr_pipe[2];
    int stdout_pipe[2];
    int stdin_pipe[2];

    pipe(stderr_pipe);
    pipe(stdout_pipe);
    pipe(stdin_pipe);

    pid_t bash = fork();
    if (bash == -1) {
        perror("fork failed");
        goto cleanup;
    } else if (bash == 0) {
        close(stdin_pipe[1]);
        close(STDIN_FILENO);
        dup2(stdin_pipe[0], STDIN_FILENO);

        close(stdout_pipe[0]);
        close(STDOUT_FILENO);
        dup2(stdout_pipe[1], STDOUT_FILENO);

        close(stderr_pipe[0]);
        close(STDERR_FILENO);
        dup2(stderr_pipe[1], STDERR_FILENO);

        printf("starting shelln");
        execlp("bash", "bash", NULL);
        perror("exec failed");
        goto cleanup;
    } else {
        char* stdout_buffer = NULL;
        char* stderr_buffer = NULL;
        size_t stderr_size = 0;
        size_t stdout_size = 0;
        size_t bytesread_stderr = 0;
        size_t bytesread_stdout = 0;

        close(stdin_pipe[0]);
        close(stdout_pipe[1]);
        close(stderr_pipe[1]);

        std::thread t(read_and_write, stdout_pipe[0]);
        t.detach();

        while (std::getline(std::cin, user_in)) {
            fprintf(stderr, "%sn", "reading ");
            ssize_t bytes = write(stdin_pipe[1], user_in.c_str(), user_in.size());
            printf("%zd bytes writtenn", bytes);
        }

        int status;
        waitpid(bash, amp;status, 0);
        return 0;
    }

    cleanup:    
    return 1;

    return 0;
}
 

Вывод:

 writing thread open
ls 
reading 
2 bytes written
echo hello
reading 
10 bytes written
whoami
reading 
6 bytes written
 

PS Осталось выполнить некоторую очистку, но я просто хочу сначала заставить код работать.

Комментарии:

1. Что касается goto loop . Вопреки распространенному мнению, есть время и место для goto . К сожалению, это не так.

2. Вы не отправляете новые строки в оболочку, so bash видит lsecho hellowhoami , и он еще не видел полную командную строку. Почему вы ожидаете какого-либо ответа?

3. Спасибо, что напомнили мне об этом, это связано с отсутствием новой строки. Что касается того goto loop , что я должен каким-то образом перевести поток в спящий режим, чтобы предотвратить ожидание занятости?