pr.c revision 1.1
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