Changeset View
Changeset View
Standalone View
Standalone View
usr.bin/diff/pr.c
| Show All 39 Lines | |||||
| #include "xmalloc.h" | #include "xmalloc.h" | ||||
| #define _PATH_PR "/usr/bin/pr" | #define _PATH_PR "/usr/bin/pr" | ||||
| struct pr * | struct pr * | ||||
| start_pr(char *file1, char *file2) | start_pr(char *file1, char *file2) | ||||
| { | { | ||||
| int pfd[2]; | int pfd[2]; | ||||
| int pr_pd; | |||||
| pid_t pid; | pid_t pid; | ||||
| char *header; | char *header; | ||||
| struct pr *pr; | struct pr *pr; | ||||
| pr = xcalloc(1, sizeof(*pr)); | pr = xcalloc(1, sizeof(*pr)); | ||||
| xasprintf(&header, "%s %s %s", diffargs, file1, file2); | xasprintf(&header, "%s %s %s", diffargs, file1, file2); | ||||
| signal(SIGPIPE, SIG_IGN); | signal(SIGPIPE, SIG_IGN); | ||||
| fflush(stdout); | fflush(stdout); | ||||
| rewind(stdout); | |||||
| if (pipe(pfd) == -1) | if (pipe(pfd) == -1) | ||||
| err(2, "pipe"); | err(2, "pipe"); | ||||
| switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) { | switch ((pid = pdfork(&pr->procd, PD_CLOEXEC))) { | ||||
| case -1: | case -1: | ||||
| status |= 2; | |||||
| free(header); | |||||
| err(2, "No more processes"); | err(2, "No more processes"); | ||||
| case 0: | case 0: | ||||
| /* child */ | /* child */ | ||||
| if (pfd[0] != STDIN_FILENO) { | if (pfd[0] != STDIN_FILENO) { | ||||
| dup2(pfd[0], STDIN_FILENO); | dup2(pfd[0], STDIN_FILENO); | ||||
| close(pfd[0]); | close(pfd[0]); | ||||
| } | } | ||||
| close(pfd[1]); | close(pfd[1]); | ||||
| execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); | execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); | ||||
| _exit(127); | _exit(127); | ||||
| default: | default: | ||||
| pr->pidfd = pr_pd; | |||||
| /* parent */ | /* parent */ | ||||
| if (pfd[1] != STDOUT_FILENO) { | if (pfd[1] == STDOUT_FILENO) { | ||||
| pr->ostdout = dup(STDOUT_FILENO); | pr->ostdout = STDOUT_FILENO; | ||||
| dup2(pfd[1], STDOUT_FILENO); | } else { | ||||
| if ((pr->ostdout = dup(STDOUT_FILENO)) < 0 || | |||||
| dup2(pfd[1], STDOUT_FILENO) < 0) { | |||||
| err(2, "stdout"); | |||||
| } | |||||
| close(pfd[1]); | close(pfd[1]); | ||||
| } | } | ||||
| close(pfd[0]); | close(pfd[0]); | ||||
| rewind(stdout); | |||||
| free(header); | free(header); | ||||
| } | } | ||||
| return (pr); | return (pr); | ||||
| } | } | ||||
| /* close the pipe to pr and restore stdout */ | /* close the pipe to pr and restore stdout */ | ||||
| void | void | ||||
| stop_pr(struct pr *pr) | stop_pr(struct pr *pr) | ||||
| { | { | ||||
| int wstatus; | int wstatus; | ||||
| if (pr == NULL) | if (pr == NULL) | ||||
| return; | return; | ||||
| fflush(stdout); | fflush(stdout); | ||||
| if (pr->ostdout != STDOUT_FILENO) { | if (pr->ostdout != STDOUT_FILENO) { | ||||
| close(STDOUT_FILENO); | |||||
| dup2(pr->ostdout, STDOUT_FILENO); | dup2(pr->ostdout, STDOUT_FILENO); | ||||
| close(pr->ostdout); | close(pr->ostdout); | ||||
| } | } | ||||
| while (pdwait(pr->pidfd, &wstatus, WEXITED, NULL, NULL) == -1) { | while (pdwait(pr->procd, &wstatus, WEXITED, NULL, NULL) == -1) { | ||||
| if (errno != EINTR) | if (errno != EINTR) | ||||
| err(2, "pdwait"); | err(2, "pdwait"); | ||||
| } | } | ||||
| close(pr->procd); | |||||
| free(pr); | free(pr); | ||||
| if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) | if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) | ||||
| errx(2, "pr exited abnormally"); | errx(2, "pr exited abnormally"); | ||||
| else if (WIFSIGNALED(wstatus)) | else if (WIFSIGNALED(wstatus)) | ||||
| errx(2, "pr killed by signal %d", | errx(2, "pr killed by signal %d", | ||||
| WTERMSIG(wstatus)); | WTERMSIG(wstatus)); | ||||
| } | } | ||||