16fa5bf08SBaptiste Daroussin /*- 26fa5bf08SBaptiste Daroussin * Copyright (c) 2017 Baptiste Daroussin <bapt@FreeBSD.org> 36fa5bf08SBaptiste Daroussin * All rights reserved. 46fa5bf08SBaptiste Daroussin * 56fa5bf08SBaptiste Daroussin * Redistribution and use in source and binary forms, with or without 66fa5bf08SBaptiste Daroussin * modification, are permitted provided that the following conditions 76fa5bf08SBaptiste Daroussin * are met: 86fa5bf08SBaptiste Daroussin * 1. Redistributions of source code must retain the above copyright 96fa5bf08SBaptiste Daroussin * notice, this list of conditions and the following disclaimer 106fa5bf08SBaptiste Daroussin * in this position and unchanged. 116fa5bf08SBaptiste Daroussin * 2. Redistributions in binary form must reproduce the above copyright 126fa5bf08SBaptiste Daroussin * notice, this list of conditions and the following disclaimer in the 136fa5bf08SBaptiste Daroussin * documentation and/or other materials provided with the distribution. 146fa5bf08SBaptiste Daroussin * 156fa5bf08SBaptiste Daroussin * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 166fa5bf08SBaptiste Daroussin * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 176fa5bf08SBaptiste Daroussin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 186fa5bf08SBaptiste Daroussin * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 196fa5bf08SBaptiste Daroussin * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 206fa5bf08SBaptiste Daroussin * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 216fa5bf08SBaptiste Daroussin * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 226fa5bf08SBaptiste Daroussin * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 236fa5bf08SBaptiste Daroussin * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 246fa5bf08SBaptiste Daroussin * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 256fa5bf08SBaptiste Daroussin */ 266fa5bf08SBaptiste Daroussin 276fa5bf08SBaptiste Daroussin #include <sys/cdefs.h> 286fa5bf08SBaptiste Daroussin __FBSDID("$FreeBSD$"); 296fa5bf08SBaptiste Daroussin 306fa5bf08SBaptiste Daroussin #include <sys/procdesc.h> 316fa5bf08SBaptiste Daroussin #include <sys/wait.h> 326fa5bf08SBaptiste Daroussin 336fa5bf08SBaptiste Daroussin #include <err.h> 346fa5bf08SBaptiste Daroussin #include <paths.h> 356fa5bf08SBaptiste Daroussin #include <signal.h> 366fa5bf08SBaptiste Daroussin #include <stdio.h> 376fa5bf08SBaptiste Daroussin #include <stdlib.h> 386fa5bf08SBaptiste Daroussin #include <unistd.h> 396fa5bf08SBaptiste Daroussin 406fa5bf08SBaptiste Daroussin #include "pr.h" 416fa5bf08SBaptiste Daroussin #include "diff.h" 426fa5bf08SBaptiste Daroussin #include "xmalloc.h" 436fa5bf08SBaptiste Daroussin 446fa5bf08SBaptiste Daroussin #define _PATH_PR "/usr/bin/pr" 456fa5bf08SBaptiste Daroussin 466fa5bf08SBaptiste Daroussin struct pr * 476fa5bf08SBaptiste Daroussin start_pr(char *file1, char *file2) 486fa5bf08SBaptiste Daroussin { 496fa5bf08SBaptiste Daroussin int pfd[2]; 506fa5bf08SBaptiste Daroussin int pr_pd; 516fa5bf08SBaptiste Daroussin pid_t pid; 526fa5bf08SBaptiste Daroussin char *header; 536fa5bf08SBaptiste Daroussin struct pr *pr; 546fa5bf08SBaptiste Daroussin 556fa5bf08SBaptiste Daroussin pr = xcalloc(1, sizeof(*pr)); 566fa5bf08SBaptiste Daroussin 576fa5bf08SBaptiste Daroussin xasprintf(&header, "%s %s %s", diffargs, file1, file2); 586fa5bf08SBaptiste Daroussin signal(SIGPIPE, SIG_IGN); 596fa5bf08SBaptiste Daroussin fflush(stdout); 606fa5bf08SBaptiste Daroussin rewind(stdout); 61*5a43dca2SBaptiste Daroussin if (pipe(pfd) == -1) 62*5a43dca2SBaptiste Daroussin err(2, "pipe"); 636fa5bf08SBaptiste Daroussin switch ((pid = pdfork(&pr_pd, PD_CLOEXEC))) { 646fa5bf08SBaptiste Daroussin case -1: 656fa5bf08SBaptiste Daroussin status |= 2; 666fa5bf08SBaptiste Daroussin free(header); 676fa5bf08SBaptiste Daroussin err(2, "No more processes"); 686fa5bf08SBaptiste Daroussin case 0: 696fa5bf08SBaptiste Daroussin /* child */ 706fa5bf08SBaptiste Daroussin if (pfd[0] != STDIN_FILENO) { 716fa5bf08SBaptiste Daroussin dup2(pfd[0], STDIN_FILENO); 726fa5bf08SBaptiste Daroussin close(pfd[0]); 736fa5bf08SBaptiste Daroussin } 746fa5bf08SBaptiste Daroussin close(pfd[1]); 756fa5bf08SBaptiste Daroussin execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); 766fa5bf08SBaptiste Daroussin _exit(127); 776fa5bf08SBaptiste Daroussin default: 786fa5bf08SBaptiste Daroussin 796fa5bf08SBaptiste Daroussin /* parent */ 806fa5bf08SBaptiste Daroussin if (pfd[1] != STDOUT_FILENO) { 816fa5bf08SBaptiste Daroussin pr->ostdout = dup(STDOUT_FILENO); 826fa5bf08SBaptiste Daroussin dup2(pfd[1], STDOUT_FILENO); 836fa5bf08SBaptiste Daroussin close(pfd[1]); 846fa5bf08SBaptiste Daroussin close(pfd[1]); 856fa5bf08SBaptiste Daroussin } 866fa5bf08SBaptiste Daroussin close(pfd[0]); 876fa5bf08SBaptiste Daroussin rewind(stdout); 886fa5bf08SBaptiste Daroussin free(header); 896fa5bf08SBaptiste Daroussin pr->kq = kqueue(); 906fa5bf08SBaptiste Daroussin if (pr->kq == -1) 916fa5bf08SBaptiste Daroussin err(2, "kqueue"); 926fa5bf08SBaptiste Daroussin pr->e = xmalloc(sizeof(struct kevent)); 936fa5bf08SBaptiste Daroussin EV_SET(pr->e, pr_pd, EVFILT_PROCDESC, EV_ADD, NOTE_EXIT, 0, 946fa5bf08SBaptiste Daroussin NULL); 956fa5bf08SBaptiste Daroussin if (kevent(pr->kq, pr->e, 1, NULL, 0, NULL) == -1) 966fa5bf08SBaptiste Daroussin err(2, "kevent"); 976fa5bf08SBaptiste Daroussin } 986fa5bf08SBaptiste Daroussin return (pr); 996fa5bf08SBaptiste Daroussin } 1006fa5bf08SBaptiste Daroussin 1016fa5bf08SBaptiste Daroussin /* close the pipe to pr and restore stdout */ 1026fa5bf08SBaptiste Daroussin void 1036fa5bf08SBaptiste Daroussin stop_pr(struct pr *pr) 1046fa5bf08SBaptiste Daroussin { 1056fa5bf08SBaptiste Daroussin int wstatus; 1066fa5bf08SBaptiste Daroussin 1076fa5bf08SBaptiste Daroussin if (pr == NULL) 1086fa5bf08SBaptiste Daroussin return; 1096fa5bf08SBaptiste Daroussin 1106fa5bf08SBaptiste Daroussin fflush(stdout); 1116fa5bf08SBaptiste Daroussin if (pr->ostdout != STDOUT_FILENO) { 1126fa5bf08SBaptiste Daroussin close(STDOUT_FILENO); 1136fa5bf08SBaptiste Daroussin dup2(pr->ostdout, STDOUT_FILENO); 1146fa5bf08SBaptiste Daroussin close(pr->ostdout); 1156fa5bf08SBaptiste Daroussin } 1166fa5bf08SBaptiste Daroussin if (kevent(pr->kq, NULL, 0, pr->e, 1, NULL) == -1) 1176fa5bf08SBaptiste Daroussin err(2, "kevent"); 1186fa5bf08SBaptiste Daroussin wstatus = pr->e[0].data; 1196fa5bf08SBaptiste Daroussin close(pr->kq); 1206fa5bf08SBaptiste Daroussin if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != 0) 1216fa5bf08SBaptiste Daroussin errx(2, "pr exited abnormally"); 1226fa5bf08SBaptiste Daroussin else if (WIFSIGNALED(wstatus)) 1236fa5bf08SBaptiste Daroussin errx(2, "pr killed by signal %d", 1246fa5bf08SBaptiste Daroussin WTERMSIG(wstatus)); 1256fa5bf08SBaptiste Daroussin } 126