У нас есть домашнее задание, где мы должны написать программу, которая принимает два аргумента и выполняет их как команды оболочки, передавая стандартный вывод первой программы в стандартный ввод второй программы.
Это мое решение этого домашнего задания. Этот же файл воспроизводится ниже.
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <unistd.h>
#define SHELL "/bin/sh"
extern int main(int, char*[]);
static int readingend(int, int, const char*);
static int writingend(int, int, const char*);
static int usr1handler();
extern int
main(int argc, char *argv[])
{
int pipefd[2], status;
pid_t rpid, wpid;
if (argc != 3) {
fprintf(stderr, "Invalid argument count\n");
return (EXIT_FAILURE);
}
if (pipe(pipefd)) {
perror("Cannot make a pipe");
return (EXIT_FAILURE);
}
signal(SIGUSR1, (void(*)(int))usr1handler);
if ((rpid = fork()) < 0) {
perror("Cannot fork");
return (EXIT_FAILURE);
}
if (rpid == 0)
return (readingend(pipefd[0], pipefd[1], argv[2]));
if ((wpid = fork()) < 0) {
perror("Cannot fork");
kill(rpid, SIGKILL);
return (EXIT_FAILURE);
}
if (wpid == 0)
return (writingend(pipefd[0], pipefd[1], argv[1]));
close(pipefd[0]);
close(pipefd[1]);
waitpid(rpid, &status, 0);
return (status);
}
static int
readingend(int rfd, int wfd, const char *cmd)
{
close(wfd);
dup2(rfd, STDIN_FILENO);
/* execl() only returns on error */
execl(SHELL, SHELL, "-c", cmd, NULL);
fprintf(stderr, "Cannot execute %s: ", cmd);
perror(NULL);
/* clean up */
kill(getppid(), SIGUSR1);
return (EXIT_FAILURE);
}
static int
writingend(int rfd, int wfd, const char *cmd)
{
close(rfd);
dup2(wfd, STDOUT_FILENO);
execl(SHELL, SHELL, "-c", cmd, NULL);
fprintf(stderr, "Cannot execute %s: ", cmd);
perror(NULL);
/* clean up */
kill(getppid(), SIGUSR1);
return (EXIT_FAILURE);
}
static int
usr1handler()
{
/* child already printed diagnostic */
exit(EXIT_FAILURE);
}
Проблема в том, что при некоторых вызовах первый процесс получает EIO
при чтении со стандартного ввода. Кажется, это происходит только на некоторых оболочках: это происходит с ksh93
и bash
, но не с bosh
. Такая ошибка выглядит следующим образом:
$ LANG=C ./mypipe cat true $ cat: -: Input/output error
Может ли кто-нибудь сказать мне, почему возникает эта ошибка? Что я могу сделать, чтобы эта ошибка больше не появлялась? Ясно, что должен быть способ, поскольку выполнение cat | true
в обычной оболочке дает желаемый результат без каких-либо ложных EIO
.