From 6fa5bf0832efe8a894f612968c5afe1ad91f3a03 Mon Sep 17 00:00:00 2001 From: Baptiste Daroussin <bapt@FreeBSD.org> Date: Sat, 9 Jun 2018 20:24:17 +0000 Subject: [PATCH] Isolate the pr(1) related code in its own source files This keeps diffreg.c closer to what it is supposed to do: diffing regular files. It also allows my code to get a proper license --- usr.bin/diff/Makefile | 2 +- usr.bin/diff/diffreg.c | 86 ++-------------------------- usr.bin/diff/pr.c | 124 +++++++++++++++++++++++++++++++++++++++++ usr.bin/diff/pr.h | 38 +++++++++++++ 4 files changed, 169 insertions(+), 81 deletions(-) create mode 100644 usr.bin/diff/pr.c create mode 100644 usr.bin/diff/pr.h diff --git a/usr.bin/diff/Makefile b/usr.bin/diff/Makefile index 18c4495cf1c7..a9f79d3d81e1 100644 --- a/usr.bin/diff/Makefile +++ b/usr.bin/diff/Makefile @@ -3,7 +3,7 @@ .include <src.opts.mk> PROG= diff -SRCS= diff.c diffdir.c diffreg.c xmalloc.c +SRCS= diff.c diffdir.c diffreg.c xmalloc.c pr.c HAS_TESTS= SUBDIR.${MK_TESTS}+= tests diff --git a/usr.bin/diff/diffreg.c b/usr.bin/diff/diffreg.c index b7a0135bdf12..84cb4ac58c21 100644 --- a/usr.bin/diff/diffreg.c +++ b/usr.bin/diff/diffreg.c @@ -70,11 +70,7 @@ __FBSDID("$FreeBSD$"); #include <sys/capsicum.h> -#include <sys/procdesc.h> #include <sys/stat.h> -#include <sys/types.h> -#include <sys/event.h> -#include <sys/wait.h> #include <capsicum_helpers.h> #include <ctype.h> @@ -88,15 +84,11 @@ __FBSDID("$FreeBSD$"); #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <unistd.h> -#include <limits.h> -#include <signal.h> +#include "pr.h" #include "diff.h" #include "xmalloc.h" -#define _PATH_PR "/usr/bin/pr" - /* * diff - compare two files. */ @@ -260,13 +252,9 @@ diffreg(char *file1, char *file2, int flags, int capsicum) { FILE *f1, *f2; int i, rval; - int ostdout = -1; - int pr_pd, kq; - struct kevent *e; + struct pr *pr = NULL; cap_rights_t rights_ro; - e = NULL; - kq = -1; f1 = f2 = NULL; rval = D_SAME; anychange = 0; @@ -324,52 +312,8 @@ diffreg(char *file1, char *file2, int flags, int capsicum) goto closem; } - if (lflag) { - /* redirect stdout to pr */ - int pfd[2]; - pid_t pid; - char *header; - - xasprintf(&header, "%s %s %s", diffargs, file1, file2); - signal(SIGPIPE, SIG_IGN); - fflush(stdout); - rewind(stdout); - pipe(pfd); - switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) { - case -1: - status |= 2; - free(header); - err(2, "No more processes"); - case 0: - /* child */ - if (pfd[0] != STDIN_FILENO) { - dup2(pfd[0], STDIN_FILENO); - close(pfd[0]); - } - close(pfd[1]); - execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); - _exit(127); - default: - - /* parent */ - if (pfd[1] != STDOUT_FILENO) { - ostdout = dup(STDOUT_FILENO); - dup2(pfd[1], STDOUT_FILENO); - close(pfd[1]); - } - close(pfd[0]); - rewind(stdout); - free(header); - kq = kqueue(); - if (kq == -1) - err(2, "kqueue"); - e = xmalloc(sizeof(struct kevent)); - EV_SET(e, pr_pd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, - NULL); - if (kevent(kq, e, 1, NULL, 0, NULL) == -1) - err(2, "kevent"); - } - } + if (lflag) + pr = start_pr(file1, file2); if (capsicum) { cap_rights_init(&rights_ro, CAP_READ, CAP_FSTAT, CAP_SEEK); @@ -443,26 +387,8 @@ diffreg(char *file1, char *file2, int flags, int capsicum) ixnew = xreallocarray(ixnew, len[1] + 2, sizeof(*ixnew)); check(f1, f2, flags); output(file1, f1, file2, f2, flags); - if (ostdout != -1 && e != NULL) { - /* close the pipe to pr and restore stdout */ - int wstatus; - - fflush(stdout); - if (ostdout != STDOUT_FILENO) { - close(STDOUT_FILENO); - dup2(ostdout, STDOUT_FILENO); - close(ostdout); - } - if (kevent(kq, NULL, 0, e, 1, NULL) == -1) - err(2, "kevent"); - wstatus = e[0].data; - close(kq); - if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) - errx(2, "pr exited abnormally"); - else if (WIFSIGNALED(wstatus)) - errx(2, "pr killed by signal %d", - WTERMSIG(wstatus)); - } + if (pr != NULL) + stop_pr(pr); closem: if (anychange) { diff --git a/usr.bin/diff/pr.c b/usr.bin/diff/pr.c new file mode 100644 index 000000000000..eaf6e37f9f4f --- /dev/null +++ b/usr.bin/diff/pr.c @@ -0,0 +1,124 @@ +/*- + * Copyright (c) 2017 Baptiste Daroussin <bapt@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/procdesc.h> +#include <sys/wait.h> + +#include <err.h> +#include <paths.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> + +#include "pr.h" +#include "diff.h" +#include "xmalloc.h" + +#define _PATH_PR "/usr/bin/pr" + +struct pr * +start_pr(char *file1, char *file2) +{ + int pfd[2]; + int pr_pd; + pid_t pid; + char *header; + struct pr *pr; + + pr = xcalloc(1, sizeof(*pr)); + + xasprintf(&header, "%s %s %s", diffargs, file1, file2); + signal(SIGPIPE, SIG_IGN); + fflush(stdout); + rewind(stdout); + pipe(pfd); + switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) { + case -1: + status |= 2; + free(header); + err(2, "No more processes"); + case 0: + /* child */ + if (pfd[0] != STDIN_FILENO) { + dup2(pfd[0], STDIN_FILENO); + close(pfd[0]); + } + close(pfd[1]); + execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); + _exit(127); + default: + + /* parent */ + if (pfd[1] != STDOUT_FILENO) { + pr->ostdout = dup(STDOUT_FILENO); + dup2(pfd[1], STDOUT_FILENO); + close(pfd[1]); + close(pfd[1]); + } + close(pfd[0]); + rewind(stdout); + free(header); + pr->kq = kqueue(); + if (pr->kq == -1) + err(2, "kqueue"); + pr->e = xmalloc(sizeof(struct kevent)); + EV_SET(pr->e, pr_pd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, + NULL); + if (kevent(pr->kq, pr->e, 1, NULL, 0, NULL) == -1) + err(2, "kevent"); + } + return (pr); +} + +/* close the pipe to pr and restore stdout */ +void +stop_pr(struct pr *pr) +{ + int wstatus; + + if (pr == NULL) + return; + + fflush(stdout); + if (pr->ostdout != STDOUT_FILENO) { + close(STDOUT_FILENO); + dup2(pr->ostdout, STDOUT_FILENO); + close(pr->ostdout); + } + if (kevent(pr->kq, NULL, 0, pr->e, 1, NULL) == -1) + err(2, "kevent"); + wstatus = pr->e[0].data; + close(pr->kq); + if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) + errx(2, "pr exited abnormally"); + else if (WIFSIGNALED(wstatus)) + errx(2, "pr killed by signal %d", + WTERMSIG(wstatus)); +} diff --git a/usr.bin/diff/pr.h b/usr.bin/diff/pr.h new file mode 100644 index 000000000000..e442d5fd4423 --- /dev/null +++ b/usr.bin/diff/pr.h @@ -0,0 +1,38 @@ +/*- + * Copyright (c) 2017 Baptiste Daroussin <bapt@FreeBSD.org> + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer + * in this position and unchanged. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +#include <sys/event.h> + +struct pr { + int ostdout; + int kq; + struct kevent *e; +}; + +struct pr *start_pr(char *file1, char *file2); +void stop_pr(struct pr *);