Skip to content

Instantly share code, notes, and snippets.

@clausecker
Created June 1, 2014 20:01
Show Gist options
  • Select an option

  • Save clausecker/fcf6f96a2e7667387243 to your computer and use it in GitHub Desktop.

Select an option

Save clausecker/fcf6f96a2e7667387243 to your computer and use it in GitHub Desktop.
#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);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment