11.1Snia/*- 21.1Snia * Copyright (c) 2017 Baptiste Daroussin <bapt@FreeBSD.org> 31.1Snia * All rights reserved. 41.1Snia * 51.1Snia * Redistribution and use in source and binary forms, with or without 61.1Snia * modification, are permitted provided that the following conditions 71.1Snia * are met: 81.1Snia * 1. Redistributions of source code must retain the above copyright 91.1Snia * notice, this list of conditions and the following disclaimer 101.1Snia * in this position and unchanged. 111.1Snia * 2. Redistributions in binary form must reproduce the above copyright 121.1Snia * notice, this list of conditions and the following disclaimer in the 131.1Snia * documentation and/or other materials provided with the distribution. 141.1Snia * 151.1Snia * THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR 161.1Snia * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 171.1Snia * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 181.1Snia * IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT, 191.1Snia * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 201.1Snia * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 211.1Snia * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 221.1Snia * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 231.1Snia * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 241.1Snia * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 251.1Snia */ 261.1Snia 271.1Snia#include <sys/cdefs.h> 281.1Snia#include <sys/wait.h> 291.1Snia 301.1Snia#include <err.h> 311.1Snia#include <paths.h> 321.1Snia#include <signal.h> 331.1Snia#include <stdio.h> 341.1Snia#include <stdlib.h> 351.1Snia#include <unistd.h> 361.1Snia 371.1Snia#include "pr.h" 381.1Snia#include "diff.h" 391.1Snia#include "xmalloc.h" 401.1Snia 411.1Snia#define _PATH_PR "/usr/bin/pr" 421.1Snia 431.1Sniastruct pr * 441.1Sniastart_pr(char *file1, char *file2) 451.1Snia{ 461.1Snia int pfd[2]; 471.1Snia pid_t pid; 481.1Snia char *header; 491.1Snia struct pr *pr; 501.1Snia 511.1Snia pr = xcalloc(1, sizeof(*pr)); 521.1Snia 531.1Snia xasprintf(&header, "%s %s %s", diffargs, file1, file2); 541.1Snia signal(SIGPIPE, SIG_IGN); 551.1Snia fflush(stdout); 561.1Snia rewind(stdout); 571.1Snia if (pipe(pfd) == -1) 581.1Snia err(2, "pipe"); 591.1Snia switch ((pid = fork())) { 601.1Snia case -1: 611.1Snia status |= 2; 621.1Snia free(header); 631.1Snia err(2, "No more processes"); 641.1Snia case 0: 651.1Snia /* child */ 661.1Snia if (pfd[0] != STDIN_FILENO) { 671.1Snia dup2(pfd[0], STDIN_FILENO); 681.1Snia close(pfd[0]); 691.1Snia } 701.1Snia close(pfd[1]); 711.1Snia execl(_PATH_PR, _PATH_PR, "-h", header, (char *)0); 721.1Snia _exit(127); 731.1Snia default: 741.1Snia 751.1Snia /* parent */ 761.1Snia if (pfd[1] != STDOUT_FILENO) { 771.1Snia pr->ostdout = dup(STDOUT_FILENO); 781.1Snia dup2(pfd[1], STDOUT_FILENO); 791.1Snia close(pfd[1]); 801.1Snia } 811.1Snia close(pfd[0]); 821.1Snia rewind(stdout); 831.1Snia free(header); 841.1Snia pr->kq = kqueue(); 851.1Snia if (pr->kq == -1) 861.1Snia err(2, "kqueue"); 871.1Snia pr->e = xmalloc(sizeof(struct kevent)); 881.1Snia EV_SET(pr->e, pid, EVFILT_PROC, EV_ADD, NOTE_EXIT, 0, NULL); 891.1Snia if (kevent(pr->kq, pr->e, 1, NULL, 0, NULL) == -1) 901.1Snia err(2, "kevent"); 911.1Snia } 921.1Snia return (pr); 931.1Snia} 941.1Snia 951.1Snia/* close the pipe to pr and restore stdout */ 961.1Sniavoid 971.1Sniastop_pr(struct pr *pr) 981.1Snia{ 991.1Snia if (pr == NULL) 1001.1Snia return; 1011.1Snia 1021.1Snia fflush(stdout); 1031.1Snia if (pr->ostdout != STDOUT_FILENO) { 1041.1Snia close(STDOUT_FILENO); 1051.1Snia dup2(pr->ostdout, STDOUT_FILENO); 1061.1Snia close(pr->ostdout); 1071.1Snia } 1081.1Snia if (kevent(pr->kq, NULL, 0, pr->e, 1, NULL) == -1) 1091.1Snia err(2, "kevent"); 1101.1Snia close(pr->kq); 1111.1Snia free(pr); 1121.1Snia} 113