/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <fatal.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <wait.h>
/*
* This program segments two files into pieces of <= seglim lines
* (which is passed as a third argument or defaulted to some number)
* and then executes diff upon the pieces. The output of
* 'diff' is then processed to make it look as if 'diff' had
* processed the files whole. The reason for all this is that seglim
* is a reasonable upper limit on the size of files that diff can
* process.
* NOTE -- by segmenting the files in this manner, it cannot be
* guaranteed that the 'diffing' of the segments will generate
* a minimal set of differences.
* This process is most definitely not equivalent to 'diffing'
* the files whole, assuming 'diff' could handle such large files.
*
* 'diff' is executed by a child process, generated by forking,
* and communicates with this program through pipes.
*/
static int fflags;
static void fixnum(char *);
static void fatal(char *);
static void setsig(void);
static void setsig1(int);
static char *prognam;
int
{
pid_t i;
int status;
/*
* Set flags for 'fatal' so that it will clean up,
* produce a message, and terminate.
*/
setsig();
fatal("arg count");
fatal("both files standard input");
else
}
else
}
seglim = 3500;
if (argc > 3) {
else {
fatal("non-numeric limit");
}
}
linenum = 0;
/* Allocate the buffers and initialize their lengths */
fatal("Out of memory");
/*
* The following while-loop will prevent any lines
* common to the beginning of both files from being
* sent to 'diff'. Since the running time of 'diff' is
* non-linear, this will help improve performance.
* If, during this process, both files reach EOF, then
* the files are equal and the program will terminate.
* If either file reaches EOF before the other, the
* program will generate the appropriate 'diff' output
* itself, since this can be easily determined and will
* avoid executing 'diff' completely.
*/
for (;;) {
return (0);
if (!olp) {
/*
* The entire old file is a prefix of the
* new file. Generate the appropriate "append"
* 'diff'-like output, which is of the form:
* nan, n
* where 'n' represents a line-number.
*/
}
if (!nlp) {
/*
* The entire new file is a prefix of the
* old file. Generate the appropriate "delete"
* 'diff'-like output, which is of the form:
* n, ndn
* where 'n' represents a line-number.
*/
}
linenum++;
else
break;
}
/*
* Here, first 'linenum' lines are equal.
* The following while-loop segments both files into
* seglim segments, forks and executes 'diff' on the
* segments, and processes the resulting output of
* 'diff', which is read from a pipe.
*/
for (;;) {
/* If both files are at EOF, everything is done. */
return (0);
if (!olp) {
/*
* Generate appropriate "append"
* output without executing 'diff'.
*/
}
if (!nlp) {
/*
* Generate appropriate "delete"
* output without executing 'diff'.
*/
}
/*
* Create a temporary file to hold a segment
* from the old file, and write it.
*/
otcnt = 0;
fatal("Can not write to temporary file");
}
otcnt++;
}
/*
* Create a temporary file to hold a segment
* from the new file, and write it.
*/
ntcnt = 0;
fatal("Can not write to temporary file");
}
ntcnt++;
}
/* Create pipes and fork. */
fatal("Can not create pipe");
fatal("Can not fork, try again");
} else if (i == (pid_t)0) { /* child process */
(void) close(1);
/* Execute 'diff' on the segment files. */
/*
* Exit code here must be > 1.
* Parent process treats exit code of 1 from the child
* as non-error because the child process "diff" exits
* with a status of 1 when a difference is encountered.
* The error here is a true error--the parent process
* needs to detect it and exit with a non-zero status.
*/
(void) close(1);
"Can not execute '%s'", diff);
fatal_num = 2;
} else { /* parent process */
/* Process 'diff' output. */
else
}
/* EOF on pipe. */
if (status&~0x100) {
"'%s' failed", diff);
}
}
/* Remove temporary files. */
}
}
/* Routine to save remainder of a file. */
static void
{
char *lp;
while (lp) {
linenum++;
}
}
/* Routine to write out data saved by 'saverest' and to remove the file. */
static void
{
}
}
static void
{
while (*lp) {
switch (*lp) {
case 'a':
case 'c':
case 'd':
case ',':
case '\n':
lp++;
break;
default:
}
}
}
static void
{
/* Save lines of new file. */
else
(void) printf("\n");
/* Output saved lines, as 'diff' would. */
exit(0);
}
static void
{
/* Save lines of old file. */
else
/* Output saved lines, as 'diff' would. */
exit(0);
}
static void
clean_up()
{
}
static FILE *
{
int fd;
}
return (iop);
}
static void
/*
* General purpose error handler.
*
* The argument to fatal is a pointer to an error message string.
* The action of this routine is driven completely from
* the "fflags" global word (see <fatal.h>).
*
* The FTLMSG bit controls the writing of the error
* message on file descriptor 2. A newline is written
* after the user supplied message.
*
* If the FTLCLN bit is on, clean_up is called.
*/
{
clean_up();
}
static void
setsig()
/*
* General-purpose signal setting routine.
* All non-ignored, non-caught signals are caught.
* If a signal other than hangup, interrupt, or quit is caught,
* a "user-oriented" message is printed on file descriptor 2.
* If hangup, interrupt or quit is caught, that signal
* is set to ignore.
* Termination is like that of "fatal",
* via "clean_up()"
*/
{
void (*act)(int);
int j;
for (j = 1; j < ONSIG; j++) {
continue;
continue;
}
}
static void
{
clean_up();
exit(1);
}
static char *
{
sum = 0;
while (isdigit(*p))
return (p);
}
/*
* Read a line of data from a file. If the current buffer is not large enough
* to contain the line, double the size of the buffer and continue reading.
* Loop until either the entire line is read or until there is no more space
* to be malloc'd.
*/
static char *
{
char *bufp;
return (bufp);
fatal("Out of memory");
break;
} else
fatal("Read error");
} else
}
return (bufp);
}