#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
, что я должен каким-то образом перевести поток в спящий режим, чтобы предотвратить ожидание занятости?