1*6fa5bf08SBaptiste Daroussin /*- 2*6fa5bf08SBaptiste Daroussin * Copyright (c) 2017 Baptiste Daroussin <bapt@FreeBSD.org> 3*6fa5bf08SBaptiste Daroussin * All rights reserved. 4*6fa5bf08SBaptiste Daroussin * 5*6fa5bf08SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 6*6fa5bf08SBaptiste Daroussin * modification, are permitted provided that the following conditions 7*6fa5bf08SBaptiste Daroussin * are met: 8*6fa5bf08SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 9*6fa5bf08SBaptiste Daroussin * notice, this list of conditions and the following disclaimer 10*6fa5bf08SBaptiste Daroussin * in this position and unchanged. 11*6fa5bf08SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 12*6fa5bf08SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 13*6fa5bf08SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 14*6fa5bf08SBaptiste Daroussin * 15*6fa5bf08SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 16*6fa5bf08SBaptiste Daroussin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 17*6fa5bf08SBaptiste Daroussin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 18*6fa5bf08SBaptiste Daroussin * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 19*6fa5bf08SBaptiste Daroussin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 20*6fa5bf08SBaptiste Daroussin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 21*6fa5bf08SBaptiste Daroussin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 22*6fa5bf08SBaptiste Daroussin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 23*6fa5bf08SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 24*6fa5bf08SBaptiste Daroussin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25*6fa5bf08SBaptiste Daroussin */ 26*6fa5bf08SBaptiste Daroussin 27*6fa5bf08SBaptiste Daroussin #include <sys/cdefs.h> 28*6fa5bf08SBaptiste Daroussin __FBSDID("$FreeBSD$"); 29*6fa5bf08SBaptiste Daroussin 30*6fa5bf08SBaptiste Daroussin #include <sys/procdesc.h> 31*6fa5bf08SBaptiste Daroussin #include <sys/wait.h> 32*6fa5bf08SBaptiste Daroussin 33*6fa5bf08SBaptiste Daroussin #include <err.h> 34*6fa5bf08SBaptiste Daroussin #include <paths.h> 35*6fa5bf08SBaptiste Daroussin #include <signal.h> 36*6fa5bf08SBaptiste Daroussin #include <stdio.h> 37*6fa5bf08SBaptiste Daroussin #include <stdlib.h> 38*6fa5bf08SBaptiste Daroussin #include <unistd.h> 39*6fa5bf08SBaptiste Daroussin 40*6fa5bf08SBaptiste Daroussin #include "pr.h" 41*6fa5bf08SBaptiste Daroussin #include "diff.h" 42*6fa5bf08SBaptiste Daroussin #include "xmalloc.h" 43*6fa5bf08SBaptiste Daroussin 44*6fa5bf08SBaptiste Daroussin #define _PATH_PR "/usr/bin/pr" 45*6fa5bf08SBaptiste Daroussin 46*6fa5bf08SBaptiste Daroussin struct pr * 47*6fa5bf08SBaptiste Daroussin start_pr(char *file1, char *file2) 48*6fa5bf08SBaptiste Daroussin { 49*6fa5bf08SBaptiste Daroussin int pfd[2]; 50*6fa5bf08SBaptiste Daroussin int pr_pd; 51*6fa5bf08SBaptiste Daroussin pid_t pid; 52*6fa5bf08SBaptiste Daroussin char *header; 53*6fa5bf08SBaptiste Daroussin struct pr *pr; 54*6fa5bf08SBaptiste Daroussin 55*6fa5bf08SBaptiste Daroussin pr = xcalloc(1, sizeof(*pr)); 56*6fa5bf08SBaptiste Daroussin 57*6fa5bf08SBaptiste Daroussin xasprintf(&header, "%s %s %s", diffargs, file1, file2); 58*6fa5bf08SBaptiste Daroussin signal(SIGPIPE, SIG_IGN); 59*6fa5bf08SBaptiste Daroussin fflush(stdout); 60*6fa5bf08SBaptiste Daroussin rewind(stdout); 61*6fa5bf08SBaptiste Daroussin pipe(pfd); 62*6fa5bf08SBaptiste Daroussin switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) { 63*6fa5bf08SBaptiste Daroussin case -1: 64*6fa5bf08SBaptiste Daroussin status |= 2; 65*6fa5bf08SBaptiste Daroussin free(header); 66*6fa5bf08SBaptiste Daroussin err(2, "No more processes"); 67*6fa5bf08SBaptiste Daroussin case 0: 68*6fa5bf08SBaptiste Daroussin /* child */ 69*6fa5bf08SBaptiste Daroussin if (pfd[0] != STDIN_FILENO) { 70*6fa5bf08SBaptiste Daroussin dup2(pfd[0], STDIN_FILENO); 71*6fa5bf08SBaptiste Daroussin close(pfd[0]); 72*6fa5bf08SBaptiste Daroussin } 73*6fa5bf08SBaptiste Daroussin close(pfd[1]); 74*6fa5bf08SBaptiste Daroussin execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); 75*6fa5bf08SBaptiste Daroussin _exit(127); 76*6fa5bf08SBaptiste Daroussin default: 77*6fa5bf08SBaptiste Daroussin 78*6fa5bf08SBaptiste Daroussin /* parent */ 79*6fa5bf08SBaptiste Daroussin if (pfd[1] != STDOUT_FILENO) { 80*6fa5bf08SBaptiste Daroussin pr->ostdout = dup(STDOUT_FILENO); 81*6fa5bf08SBaptiste Daroussin dup2(pfd[1], STDOUT_FILENO); 82*6fa5bf08SBaptiste Daroussin close(pfd[1]); 83*6fa5bf08SBaptiste Daroussin close(pfd[1]); 84*6fa5bf08SBaptiste Daroussin } 85*6fa5bf08SBaptiste Daroussin close(pfd[0]); 86*6fa5bf08SBaptiste Daroussin rewind(stdout); 87*6fa5bf08SBaptiste Daroussin free(header); 88*6fa5bf08SBaptiste Daroussin pr->kq = kqueue(); 89*6fa5bf08SBaptiste Daroussin if (pr->kq == -1) 90*6fa5bf08SBaptiste Daroussin err(2, "kqueue"); 91*6fa5bf08SBaptiste Daroussin pr->e = xmalloc(sizeof(struct kevent)); 92*6fa5bf08SBaptiste Daroussin EV_SET(pr->e, pr_pd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, 93*6fa5bf08SBaptiste Daroussin NULL); 94*6fa5bf08SBaptiste Daroussin if (kevent(pr->kq, pr->e, 1, NULL, 0, NULL) == -1) 95*6fa5bf08SBaptiste Daroussin err(2, "kevent"); 96*6fa5bf08SBaptiste Daroussin } 97*6fa5bf08SBaptiste Daroussin return (pr); 98*6fa5bf08SBaptiste Daroussin } 99*6fa5bf08SBaptiste Daroussin 100*6fa5bf08SBaptiste Daroussin /* close the pipe to pr and restore stdout */ 101*6fa5bf08SBaptiste Daroussin void 102*6fa5bf08SBaptiste Daroussin stop_pr(struct pr *pr) 103*6fa5bf08SBaptiste Daroussin { 104*6fa5bf08SBaptiste Daroussin int wstatus; 105*6fa5bf08SBaptiste Daroussin 106*6fa5bf08SBaptiste Daroussin if (pr == NULL) 107*6fa5bf08SBaptiste Daroussin return; 108*6fa5bf08SBaptiste Daroussin 109*6fa5bf08SBaptiste Daroussin fflush(stdout); 110*6fa5bf08SBaptiste Daroussin if (pr->ostdout != STDOUT_FILENO) { 111*6fa5bf08SBaptiste Daroussin close(STDOUT_FILENO); 112*6fa5bf08SBaptiste Daroussin dup2(pr->ostdout, STDOUT_FILENO); 113*6fa5bf08SBaptiste Daroussin close(pr->ostdout); 114*6fa5bf08SBaptiste Daroussin } 115*6fa5bf08SBaptiste Daroussin if (kevent(pr->kq, NULL, 0, pr->e, 1, NULL) == -1) 116*6fa5bf08SBaptiste Daroussin err(2, "kevent"); 117*6fa5bf08SBaptiste Daroussin wstatus = pr->e[0].data; 118*6fa5bf08SBaptiste Daroussin close(pr->kq); 119*6fa5bf08SBaptiste Daroussin if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) 120*6fa5bf08SBaptiste Daroussin errx(2, "pr exited abnormally"); 121*6fa5bf08SBaptiste Daroussin else if (WIFSIGNALED(wstatus)) 122*6fa5bf08SBaptiste Daroussin errx(2, "pr killed by signal %d", 123*6fa5bf08SBaptiste Daroussin WTERMSIG(wstatus)); 124*6fa5bf08SBaptiste Daroussin } 125