xref: /csrg-svn/usr.bin/patch/patch.c (revision 26977)
124294Smckusick #ifndef lint
2*26977Svan static char sccsid[] = "@(#)patch.c	5.7 (Berkeley) 03/29/86";
324294Smckusick #endif not lint
424294Smckusick 
524294Smckusick /* patch - a program to apply diffs to original files
624294Smckusick  *
724294Smckusick  * $Header: patch.c,v 1.3 85/03/26 15:07:43 lwall Exp $
824294Smckusick  *
924294Smckusick  * Copyright 1984, Larry Wall
1024294Smckusick  *
1124294Smckusick  * This program may be copied as long as you don't try to make any
1224294Smckusick  * money off of it, or pretend that you wrote it.
1324294Smckusick  *
1424294Smckusick  * $Log:	patch.c,v $
1524295Smckusick  * 85/08/15 van%ucbmonet@berkeley
1624295Smckusick  * Changes for 4.3bsd diff -c.
1724295Smckusick  *
1824294Smckusick  * Revision 1.3  85/03/26  15:07:43  lwall
1924294Smckusick  * Frozen.
2024294Smckusick  *
2124294Smckusick  * Revision 1.2.1.9  85/03/12  17:03:35  lwall
2224294Smckusick  * Changed pfp->_file to fileno(pfp).
2324294Smckusick  *
2424294Smckusick  * Revision 1.2.1.8  85/03/12  16:30:43  lwall
2524294Smckusick  * Check i_ptr and i_womp to make sure they aren't null before freeing.
2624294Smckusick  * Also allow ed output to be suppressed.
2724294Smckusick  *
2824294Smckusick  * Revision 1.2.1.7  85/03/12  15:56:13  lwall
2924294Smckusick  * Added -p option from jromine@uci-750a.
3024294Smckusick  *
3124294Smckusick  * Revision 1.2.1.6  85/03/12  12:12:51  lwall
3224294Smckusick  * Now checks for normalness of file to patch.
3324294Smckusick  *
3424294Smckusick  * Revision 1.2.1.5  85/03/12  11:52:12  lwall
3524294Smckusick  * Added -D (#ifdef) option from joe@fluke.
3624294Smckusick  *
3724294Smckusick  * Revision 1.2.1.4  84/12/06  11:14:15  lwall
3824294Smckusick  * Made smarter about SCCS subdirectories.
3924294Smckusick  *
4024294Smckusick  * Revision 1.2.1.3  84/12/05  11:18:43  lwall
4124294Smckusick  * Added -l switch to do loose string comparison.
4224294Smckusick  *
4324294Smckusick  * Revision 1.2.1.2  84/12/04  09:47:13  lwall
4424294Smckusick  * Failed hunk count not reset on multiple patch file.
4524294Smckusick  *
4624294Smckusick  * Revision 1.2.1.1  84/12/04  09:42:37  lwall
4724294Smckusick  * Branch for sdcrdcf changes.
4824294Smckusick  *
4924294Smckusick  * Revision 1.2  84/11/29  13:29:51  lwall
5024294Smckusick  * Linted.  Identifiers uniqified.  Fixed i_ptr malloc() bug.  Fixed
5124294Smckusick  * multiple calls to mktemp().  Will now work on machines that can only
5224294Smckusick  * read 32767 chars.  Added -R option for diffs with new and old swapped.
5324294Smckusick  * Various cosmetic changes.
5424294Smckusick  *
5524294Smckusick  * Revision 1.1  84/11/09  17:03:58  lwall
5624294Smckusick  * Initial revision
5724294Smckusick  *
5824294Smckusick  */
5924294Smckusick 
6024294Smckusick #define DEBUGGING
6124294Smckusick 
6224294Smckusick /* shut lint up about the following when return value ignored */
6324294Smckusick 
6424294Smckusick #define Signal (void)signal
6524294Smckusick #define Unlink (void)unlink
6624294Smckusick #define Lseek (void)lseek
6724294Smckusick #define Fseek (void)fseek
6824294Smckusick #define Fstat (void)fstat
6924294Smckusick #define Pclose (void)pclose
7024294Smckusick #define Close (void)close
7124294Smckusick #define Fclose (void)fclose
7224294Smckusick #define Fflush (void)fflush
7324294Smckusick #define Sprintf (void)sprintf
7424294Smckusick #define Mktemp (void)mktemp
7524294Smckusick #define Strcpy (void)strcpy
7624294Smckusick #define Strcat (void)strcat
7724294Smckusick 
7824294Smckusick #include <stdio.h>
7924294Smckusick #include <assert.h>
8024294Smckusick #include <sys/types.h>
8124294Smckusick #include <sys/stat.h>
8224294Smckusick #include <ctype.h>
8324294Smckusick #include <signal.h>
8424294Smckusick 
8524294Smckusick /* constants */
8624294Smckusick 
8724294Smckusick #define TRUE (1)
8824294Smckusick #define FALSE (0)
8924294Smckusick 
90*26977Svan #define MAXHUNKSIZE 2000
9124294Smckusick #define MAXLINELEN 1024
9224294Smckusick #define BUFFERSIZE 1024
9324294Smckusick #define ORIGEXT ".orig"
9424294Smckusick #define SCCSPREFIX "s."
9524294Smckusick #define GET "get -e %s"
9624294Smckusick #define RCSSUFFIX ",v"
9724294Smckusick #define CHECKOUT "co -l %s"
9824294Smckusick 
9924294Smckusick /* handy definitions */
10024294Smckusick 
10124294Smckusick #define Null(t) ((t)0)
10224294Smckusick #define Nullch Null(char *)
10324294Smckusick #define Nullfp Null(FILE *)
10424294Smckusick 
10524294Smckusick #define Ctl(ch) (ch & 037)
10624294Smckusick 
10724294Smckusick #define strNE(s1,s2) (strcmp(s1,s2))
10824294Smckusick #define strEQ(s1,s2) (!strcmp(s1,s2))
10924294Smckusick #define strnNE(s1,s2,l) (strncmp(s1,s2,l))
11024294Smckusick #define strnEQ(s1,s2,l) (!strncmp(s1,s2,l))
11124294Smckusick 
11224294Smckusick /* typedefs */
11324294Smckusick 
11424294Smckusick typedef char bool;
11524294Smckusick typedef long LINENUM;			/* must be signed */
11624294Smckusick typedef unsigned MEM;			/* what to feed malloc */
11724294Smckusick 
11824294Smckusick /* globals */
11924294Smckusick 
12024294Smckusick int Argc;				/* guess */
12124294Smckusick char **Argv;
12224294Smckusick 
12324294Smckusick struct stat filestat;			/* file statistics area */
12424294Smckusick 
12524294Smckusick char serrbuf[BUFSIZ];			/* buffer for stderr */
12624294Smckusick char buf[MAXLINELEN];			/* general purpose buffer */
12724294Smckusick FILE *pfp = Nullfp;			/* patch file pointer */
12824294Smckusick FILE *ofp = Nullfp;			/* output file pointer */
12924294Smckusick FILE *rejfp = Nullfp;			/* reject file pointer */
13024294Smckusick 
13124294Smckusick LINENUM input_lines = 0;		/* how long is input file in lines */
13224294Smckusick LINENUM last_frozen_line = 0;		/* how many input lines have been */
13324294Smckusick 					/* irretractibly output */
13424294Smckusick 
13524294Smckusick #define MAXFILEC 2
13624294Smckusick int filec = 0;				/* how many file arguments? */
13724294Smckusick char *filearg[MAXFILEC];
13824294Smckusick 
13924294Smckusick char *outname = Nullch;
14024294Smckusick char rejname[128];
14124294Smckusick 
14224294Smckusick char *origext = Nullch;
14324294Smckusick 
14424294Smckusick char TMPOUTNAME[] = "/tmp/patchoXXXXXX";
14524294Smckusick char TMPINNAME[] = "/tmp/patchiXXXXXX";	/* you might want /usr/tmp here */
14624294Smckusick char TMPREJNAME[] = "/tmp/patchrXXXXXX";
14724294Smckusick char TMPPATNAME[] = "/tmp/patchpXXXXXX";
14824294Smckusick 
14924294Smckusick LINENUM last_offset = 0;
15024294Smckusick #ifdef DEBUGGING
15124294Smckusick int debug = 0;
15224294Smckusick #endif
15324294Smckusick bool verbose = TRUE;
15424294Smckusick bool reverse = FALSE;
15526490Sbloom bool noreverse = FALSE;
15626490Sbloom bool skip_this_patch = FALSE;
15724294Smckusick bool usepath = FALSE;
15824294Smckusick bool canonicalize = FALSE;
15924294Smckusick 
16024294Smckusick #define CONTEXT_DIFF 1
16124294Smckusick #define NORMAL_DIFF 2
16224294Smckusick #define ED_DIFF 3
16324295Smckusick #define NEW_CONTEXT_DIFF 4
16424294Smckusick int diff_type = 0;
16524294Smckusick 
16624294Smckusick int do_defines = 0;			/* patch using ifdef, ifndef, etc. */
16724294Smckusick char if_defined[128];			/* #ifdef xyzzy */
16824294Smckusick char not_defined[128];			/* #ifndef xyzzy */
16924294Smckusick char else_defined[] = "#else\n";	/* #else */
17024294Smckusick char end_defined[128];			/* #endif xyzzy */
17124294Smckusick 
17224294Smckusick char *revision = Nullch;		/* prerequisite revision, if any */
17324294Smckusick 
17424294Smckusick /* procedures */
17524294Smckusick 
17624294Smckusick LINENUM locate_hunk();
17724294Smckusick bool patch_match();
17824294Smckusick bool similar();
17924294Smckusick char *malloc();
18024294Smckusick char *savestr();
18124294Smckusick char *strcpy();
18224294Smckusick char *strcat();
18324294Smckusick char *sprintf();		/* usually */
18424294Smckusick int my_exit();
18524294Smckusick bool rev_in_string();
18624294Smckusick char *fetchname();
18724294Smckusick long atol();
18824294Smckusick long lseek();
18924294Smckusick char *mktemp();
19024294Smckusick 
19124294Smckusick /* patch type */
19224294Smckusick 
19324294Smckusick bool there_is_another_patch();
19424294Smckusick bool another_hunk();
19524294Smckusick char *pfetch();
19624294Smckusick int pch_line_len();
19724294Smckusick LINENUM pch_first();
19824294Smckusick LINENUM pch_ptrn_lines();
19924294Smckusick LINENUM pch_newfirst();
20024294Smckusick LINENUM pch_repl_lines();
20124294Smckusick LINENUM pch_end();
20224294Smckusick LINENUM pch_context();
20324294Smckusick LINENUM pch_hunk_beg();
20424294Smckusick char pch_char();
20524294Smckusick char *pfetch();
20624294Smckusick char *pgets();
20724294Smckusick 
20824294Smckusick /* input file type */
20924294Smckusick 
21024294Smckusick char *ifetch();
21124294Smckusick 
21224294Smckusick /* apply a context patch to a named file */
21324294Smckusick 
21424294Smckusick main(argc,argv)
21524294Smckusick int argc;
21624294Smckusick char **argv;
21724294Smckusick {
21824294Smckusick     LINENUM where;
21924294Smckusick     int hunk = 0;
22024294Smckusick     int failed = 0;
22124294Smckusick     int i;
22224294Smckusick 
22324294Smckusick     setbuf(stderr,serrbuf);
22424294Smckusick     for (i = 0; i<MAXFILEC; i++)
22524294Smckusick 	filearg[i] = Nullch;
22624294Smckusick     Mktemp(TMPOUTNAME);
22724294Smckusick     Mktemp(TMPINNAME);
22824294Smckusick     Mktemp(TMPREJNAME);
22924294Smckusick     Mktemp(TMPPATNAME);
23024294Smckusick 
23124294Smckusick     /* parse switches */
23224294Smckusick     Argc = argc;
23324294Smckusick     Argv = argv;
23424294Smckusick     get_some_switches();
23524294Smckusick 
23624294Smckusick     /* make sure we clean up /tmp in case of disaster */
23724294Smckusick     set_signals();
23824294Smckusick 
23924294Smckusick     for (
24024294Smckusick 	open_patch_file(filearg[1]);
24124294Smckusick 	there_is_another_patch();
24224294Smckusick 	reinitialize_almost_everything()
24324294Smckusick     ) {					/* for each patch in patch file */
24424294Smckusick 
24524294Smckusick 	if (outname == Nullch)
24624294Smckusick 	    outname = savestr(filearg[0]);
24724294Smckusick 
24824294Smckusick 	/* initialize the patched file */
24924294Smckusick 	init_output(TMPOUTNAME);
25024294Smckusick 
25124294Smckusick 	/* for ed script just up and do it and exit */
25224294Smckusick 	if (diff_type == ED_DIFF) {
25324294Smckusick 	    do_ed_script();
25424294Smckusick 	    continue;
25524294Smckusick 	}
25624294Smckusick 
25724294Smckusick 	/* initialize reject file */
25824294Smckusick 	init_reject(TMPREJNAME);
25924294Smckusick 
26024294Smckusick 	/* find out where all the lines are */
26124294Smckusick 	scan_input(filearg[0]);
26224294Smckusick 
26324294Smckusick 	/* from here on, open no standard i/o files, because malloc */
26424294Smckusick 	/* might misfire */
26524294Smckusick 
26624294Smckusick 	/* apply each hunk of patch */
26724294Smckusick 	hunk = 0;
26824294Smckusick 	failed = 0;
26924294Smckusick 	while (another_hunk()) {
27024294Smckusick 	    hunk++;
27124294Smckusick 	    where = locate_hunk();
27224294Smckusick 	    if (hunk == 1 && where == Null(LINENUM)) {
27324294Smckusick 					/* dwim for reversed patch? */
27424294Smckusick 		pch_swap();
27524294Smckusick 		reverse = !reverse;
27624294Smckusick 		where = locate_hunk();	/* try again */
27724294Smckusick 		if (where == Null(LINENUM)) {
27824294Smckusick 		    pch_swap();		/* no, put it back to normal */
27924294Smckusick 		    reverse = !reverse;
28026490Sbloom 		} else if (noreverse) {
28126490Sbloom 		    pch_swap();		/* put it back to normal */
28226490Sbloom 		    reverse = !reverse;
28326490Sbloom 		    say("Ignoring previously applied (or reversed) patch.\n");
28426490Sbloom 		    skip_this_patch = TRUE;
28524294Smckusick 		}
28624294Smckusick 		else {
28724294Smckusick 		    say("%seversed (or previously applied) patch detected!  %s -R.\n",
28824294Smckusick 			reverse ? "R" : "Unr",
28924294Smckusick 			reverse ? "Assuming" : "Ignoring");
29024294Smckusick 		}
29124294Smckusick 	    }
29226490Sbloom 	    if (where == Null(LINENUM) || skip_this_patch) {
29324294Smckusick 		abort_hunk();
29424294Smckusick 		failed++;
29524294Smckusick 		if (verbose)
29624294Smckusick 		    say("Hunk #%d failed.\n",hunk);
29724294Smckusick 	    }
29824294Smckusick 	    else {
29924294Smckusick 		apply_hunk(where);
30024294Smckusick 		if (verbose)
30124294Smckusick 		    if (last_offset)
30224294Smckusick 			say("Hunk #%d succeeded (offset %d line%s).\n",
30324294Smckusick 			  hunk,last_offset,last_offset==1?"":"s");
30424294Smckusick 		    else
30524294Smckusick 			say("Hunk #%d succeeded.\n", hunk);
30624294Smckusick 	    }
30724294Smckusick 	}
30824294Smckusick 
30924294Smckusick 	assert(hunk);
31024294Smckusick 
31124294Smckusick 	/* finish spewing out the new file */
31224294Smckusick 	spew_output();
31324294Smckusick 
31424294Smckusick 	/* and put the output where desired */
31524294Smckusick 	ignore_signals();
31624294Smckusick 	move_file(TMPOUTNAME,outname);
31724294Smckusick 	Fclose(rejfp);
31824294Smckusick 	rejfp = Nullfp;
31924294Smckusick 	if (failed) {
32024294Smckusick 	    if (!*rejname) {
32124294Smckusick 		Strcpy(rejname, outname);
32224294Smckusick 		Strcat(rejname, ".rej");
32324294Smckusick 	    }
32424294Smckusick 	    say("%d out of %d hunks failed--saving rejects to %s\n",
32524294Smckusick 		failed, hunk, rejname);
32624294Smckusick 	    move_file(TMPREJNAME,rejname);
32724294Smckusick 	}
32824294Smckusick 	set_signals();
32924294Smckusick     }
33024294Smckusick     my_exit(0);
33124294Smckusick }
33224294Smckusick 
33324294Smckusick reinitialize_almost_everything()
33424294Smckusick {
33524294Smckusick     re_patch();
33624294Smckusick     re_input();
33724294Smckusick 
33824294Smckusick     input_lines = 0;
33924294Smckusick     last_frozen_line = 0;
34024294Smckusick 
34124294Smckusick     filec = 0;
34224294Smckusick     if (filearg[0] != Nullch) {
34324294Smckusick 	free(filearg[0]);
34424294Smckusick 	filearg[0] = Nullch;
34524294Smckusick     }
34624294Smckusick 
34724294Smckusick     if (outname != Nullch) {
34824294Smckusick 	free(outname);
34924294Smckusick 	outname = Nullch;
35024294Smckusick     }
35124294Smckusick 
35224294Smckusick     last_offset = 0;
35324294Smckusick 
35424294Smckusick     diff_type = 0;
35524294Smckusick 
35624294Smckusick     if (revision != Nullch) {
35724294Smckusick 	free(revision);
35824294Smckusick 	revision = Nullch;
35924294Smckusick     }
36024294Smckusick 
36124294Smckusick     reverse = FALSE;
36226490Sbloom     skip_this_patch = FALSE;
36324294Smckusick 
36424294Smckusick     get_some_switches();
36524294Smckusick 
36624294Smckusick     if (filec >= 2)
36724294Smckusick 	fatal("You may not change to a different patch file.\n");
36824294Smckusick }
36924294Smckusick 
37024294Smckusick get_some_switches()
37124294Smckusick {
37224294Smckusick     register char *s;
37324294Smckusick 
37424294Smckusick     rejname[0] = '\0';
37524294Smckusick     if (!Argc)
37624294Smckusick 	return;
37724294Smckusick     for (Argc--,Argv++; Argc; Argc--,Argv++) {
37824294Smckusick 	s = Argv[0];
37924294Smckusick 	if (strEQ(s,"+")) {
38024294Smckusick 	    return;			/* + will be skipped by for loop */
38124294Smckusick 	}
38224294Smckusick 	if (*s != '-' || !s[1]) {
38324294Smckusick 	    if (filec == MAXFILEC)
38424294Smckusick 		fatal("Too many file arguments.\n");
38524294Smckusick 	    filearg[filec++] = savestr(s);
38624294Smckusick 	}
38724294Smckusick 	else {
38824294Smckusick 	    switch (*++s) {
38924294Smckusick 	    case 'b':
39024294Smckusick 		origext = savestr(Argv[1]);
39124294Smckusick 		Argc--,Argv++;
39224294Smckusick 		break;
39324294Smckusick 	    case 'c':
39424294Smckusick 		diff_type = CONTEXT_DIFF;
39524294Smckusick 		break;
39624294Smckusick 	    case 'd':
39724294Smckusick 		if (chdir(Argv[1]) < 0)
39824294Smckusick 		    fatal("Can't cd to %s.\n",Argv[1]);
39924294Smckusick 		Argc--,Argv++;
40024294Smckusick 		break;
40124294Smckusick 	    case 'D':
40224294Smckusick 	    	do_defines++;
40324294Smckusick 		Sprintf(if_defined, "#ifdef %s\n", Argv[1]);
40424294Smckusick 		Sprintf(not_defined, "#ifndef %s\n", Argv[1]);
40524294Smckusick 		Sprintf(end_defined, "#endif %s\n", Argv[1]);
40624294Smckusick 		Argc--,Argv++;
40724294Smckusick 		break;
40824294Smckusick 	    case 'e':
40924294Smckusick 		diff_type = ED_DIFF;
41024294Smckusick 		break;
41124294Smckusick 	    case 'l':
41224294Smckusick 		canonicalize = TRUE;
41324294Smckusick 		break;
41424294Smckusick 	    case 'n':
41524294Smckusick 		diff_type = NORMAL_DIFF;
41624294Smckusick 		break;
41724294Smckusick 	    case 'o':
41824294Smckusick 		outname = savestr(Argv[1]);
41924294Smckusick 		Argc--,Argv++;
42024294Smckusick 		break;
42124294Smckusick 	    case 'p':
42224294Smckusick 		usepath = TRUE;	/* do not strip path names */
42324294Smckusick 		break;
42424294Smckusick 	    case 'r':
42524294Smckusick 		Strcpy(rejname,Argv[1]);
42624294Smckusick 		Argc--,Argv++;
42724294Smckusick 		break;
42824294Smckusick 	    case 'R':
42924294Smckusick 		reverse = TRUE;
43024294Smckusick 		break;
43126490Sbloom 	    case 'N':
43226490Sbloom 		noreverse = TRUE;
43326490Sbloom 		break;
43424294Smckusick 	    case 's':
43524294Smckusick 		verbose = FALSE;
43624294Smckusick 		break;
43724294Smckusick #ifdef DEBUGGING
43824294Smckusick 	    case 'x':
43924294Smckusick 		debug = atoi(s+1);
44024294Smckusick 		break;
44124294Smckusick #endif
44224294Smckusick 	    default:
44324294Smckusick 		fatal("Unrecognized switch: %s\n",Argv[0]);
44424294Smckusick 	    }
44524294Smckusick 	}
44624294Smckusick     }
44724294Smckusick }
44824294Smckusick 
44924294Smckusick LINENUM
45024294Smckusick locate_hunk()
45124294Smckusick {
45224294Smckusick     register LINENUM first_guess = pch_first() + last_offset;
45324294Smckusick     register LINENUM offset;
45424294Smckusick     LINENUM pat_lines = pch_ptrn_lines();
45524294Smckusick     register LINENUM max_pos_offset = input_lines - first_guess
45624294Smckusick 				- pat_lines + 1;
45724294Smckusick     register LINENUM max_neg_offset = first_guess - last_frozen_line - 1
45824294Smckusick 				- pch_context();
45924294Smckusick 
46024294Smckusick     if (!pat_lines)			/* null range matches always */
46124294Smckusick 	return first_guess;
46224294Smckusick     if (max_neg_offset >= first_guess)	/* do not try lines < 0 */
46324294Smckusick 	max_neg_offset = first_guess - 1;
46424294Smckusick     if (first_guess <= input_lines && patch_match(first_guess,(LINENUM)0))
46524294Smckusick 	return first_guess;
46624294Smckusick     for (offset = 1; ; offset++) {
46724294Smckusick 	bool check_after = (offset <= max_pos_offset);
46824294Smckusick 	bool check_before = (offset <= max_pos_offset);
46924294Smckusick 
47024294Smckusick 	if (check_after && patch_match(first_guess,offset)) {
47124294Smckusick #ifdef DEBUGGING
47224294Smckusick 	    if (debug & 1)
47324294Smckusick 		printf("Offset changing from %d to %d\n",last_offset,offset);
47424294Smckusick #endif
47524294Smckusick 	    last_offset = offset;
47624294Smckusick 	    return first_guess+offset;
47724294Smckusick 	}
47824294Smckusick 	else if (check_before && patch_match(first_guess,-offset)) {
47924294Smckusick #ifdef DEBUGGING
48024294Smckusick 	    if (debug & 1)
48124294Smckusick 		printf("Offset changing from %d to %d\n",last_offset,-offset);
48224294Smckusick #endif
48324294Smckusick 	    last_offset = -offset;
48424294Smckusick 	    return first_guess-offset;
48524294Smckusick 	}
48624294Smckusick 	else if (!check_before && !check_after)
48724294Smckusick 	    return Null(LINENUM);
48824294Smckusick     }
48924294Smckusick }
49024294Smckusick 
49124294Smckusick /* we did not find the pattern, dump out the hunk so they can handle it */
49224294Smckusick 
49324294Smckusick abort_hunk()
49424294Smckusick {
49524294Smckusick     register LINENUM i;
49624294Smckusick     register LINENUM pat_end = pch_end();
49724294Smckusick     /* add in last_offset to guess the same as the previous successful hunk */
49824294Smckusick     int oldfirst = pch_first() + last_offset;
49924294Smckusick     int newfirst = pch_newfirst() + last_offset;
50024294Smckusick     int oldlast = oldfirst + pch_ptrn_lines() - 1;
50124294Smckusick     int newlast = newfirst + pch_repl_lines() - 1;
50224294Smckusick 
50324294Smckusick     fprintf(rejfp,"***************\n");
50424294Smckusick     for (i=0; i<=pat_end; i++) {
50524294Smckusick 	switch (pch_char(i)) {
50624294Smckusick 	case '*':
507*26977Svan 	    if (diff_type == NEW_CONTEXT_DIFF)
508*26977Svan 		fprintf(rejfp,"*** %d,%d ****\n", oldfirst, oldlast);
509*26977Svan 	    else
510*26977Svan 		fprintf(rejfp,"*** %d,%d\n", oldfirst, oldlast);
51124294Smckusick 	    break;
51224294Smckusick 	case '=':
51324294Smckusick 	    fprintf(rejfp,"--- %d,%d -----\n", newfirst, newlast);
51424294Smckusick 	    break;
51524294Smckusick 	case '\n':
51624294Smckusick 	    fprintf(rejfp,"%s", pfetch(i));
51724294Smckusick 	    break;
51824294Smckusick 	case ' ': case '-': case '+': case '!':
51924294Smckusick 	    fprintf(rejfp,"%c %s", pch_char(i), pfetch(i));
52024294Smckusick 	    break;
52124294Smckusick 	default:
52224294Smckusick 	    say("Fatal internal error in abort_hunk().\n");
52324294Smckusick 	    abort();
52424294Smckusick 	}
52524294Smckusick     }
52624294Smckusick }
52724294Smckusick 
52824294Smckusick /* we found where to apply it (we hope), so do it */
52924294Smckusick 
53024294Smckusick apply_hunk(where)
53124294Smckusick LINENUM where;
53224294Smckusick {
53324294Smckusick     register LINENUM old = 1;
53424294Smckusick     register LINENUM lastline = pch_ptrn_lines();
53524294Smckusick     register LINENUM new = lastline+1;
53624294Smckusick     register int def_state = 0;	/* -1 = ifndef, 1 = ifdef */
53724294Smckusick 
53824294Smckusick     where--;
53924294Smckusick     while (pch_char(new) == '=' || pch_char(new) == '\n')
54024294Smckusick 	new++;
54124294Smckusick 
54224294Smckusick     while (old <= lastline) {
54324294Smckusick 	if (pch_char(old) == '-') {
54424294Smckusick 	    copy_till(where + old - 1);
54524294Smckusick 	    if (do_defines) {
54624294Smckusick 		if (def_state == 0) {
54724294Smckusick 		    fputs(not_defined, ofp);
54824294Smckusick 		    def_state = -1;
54924294Smckusick 		} else
55024294Smckusick 		if (def_state == 1) {
55124294Smckusick 		    fputs(else_defined, ofp);
55224294Smckusick 		    def_state = 2;
55324294Smckusick 		}
55424294Smckusick 		fputs(pfetch(old), ofp);
55524294Smckusick 	    }
55624294Smckusick 	    last_frozen_line++;
55724294Smckusick 	    old++;
55824294Smckusick 	}
55924294Smckusick 	else if (pch_char(new) == '+') {
56024294Smckusick 	    copy_till(where + old - 1);
56124294Smckusick 	    if (do_defines) {
56224294Smckusick 		if (def_state == -1) {
56324294Smckusick 		    fputs(else_defined, ofp);
56424294Smckusick 		    def_state = 2;
56524294Smckusick 		} else
56624294Smckusick 		if (def_state == 0) {
56724294Smckusick 		    fputs(if_defined, ofp);
56824294Smckusick 		    def_state = 1;
56924294Smckusick 		}
57024294Smckusick 	    }
57124294Smckusick 	    fputs(pfetch(new),ofp);
57224294Smckusick 	    new++;
57324294Smckusick 	}
57424294Smckusick 	else {
57524294Smckusick 	    if (pch_char(new) != pch_char(old)) {
57624294Smckusick 		say("Out-of-sync patch, lines %d,%d\n",
57724294Smckusick 		    pch_hunk_beg() + old - 1,
57824294Smckusick 		    pch_hunk_beg() + new - 1);
57924294Smckusick #ifdef DEBUGGING
58024294Smckusick 		printf("oldchar = '%c', newchar = '%c'\n",
58124294Smckusick 		    pch_char(old), pch_char(new));
58224294Smckusick #endif
58324294Smckusick 		my_exit(1);
58424294Smckusick 	    }
58524294Smckusick 	    if (pch_char(new) == '!') {
58624294Smckusick 		copy_till(where + old - 1);
58724294Smckusick 		if (do_defines) {
58824294Smckusick 		   fputs(not_defined,ofp);
58924294Smckusick 		   def_state = -1;
59024294Smckusick 		}
59124294Smckusick 		while (pch_char(old) == '!') {
59224294Smckusick 		    if (do_defines) {
59324294Smckusick 			fputs(pfetch(old),ofp);
59424294Smckusick 		    }
59524294Smckusick 		    last_frozen_line++;
59624294Smckusick 		    old++;
59724294Smckusick 		}
59824294Smckusick 		if (do_defines) {
59924294Smckusick 		    fputs(else_defined, ofp);
60024294Smckusick 		    def_state = 2;
60124294Smckusick 		}
60224294Smckusick 		while (pch_char(new) == '!') {
60324294Smckusick 		    fputs(pfetch(new),ofp);
60424294Smckusick 		    new++;
60524294Smckusick 		}
60624294Smckusick 		if (do_defines) {
60724294Smckusick 		    fputs(end_defined, ofp);
60824294Smckusick 		    def_state = 0;
60924294Smckusick 		}
61024294Smckusick 	    }
61124294Smckusick 	    else {
61224294Smckusick 		assert(pch_char(new) == ' ');
61324294Smckusick 		old++;
61424294Smckusick 		new++;
61524294Smckusick 	    }
61624294Smckusick 	}
61724294Smckusick     }
61824294Smckusick     if (new <= pch_end() && pch_char(new) == '+') {
61924294Smckusick 	copy_till(where + old - 1);
62024294Smckusick 	if (do_defines) {
62124294Smckusick 	    if (def_state == 0) {
62224294Smckusick 	    	fputs(if_defined, ofp);
62324294Smckusick 		def_state = 1;
62424294Smckusick 	    } else
62524294Smckusick 	    if (def_state == -1) {
62624294Smckusick 		fputs(else_defined, ofp);
62724294Smckusick 		def_state = 2;
62824294Smckusick 	    }
62924294Smckusick 	}
63024294Smckusick 	while (new <= pch_end() && pch_char(new) == '+') {
63124294Smckusick 	    fputs(pfetch(new),ofp);
63224294Smckusick 	    new++;
63324294Smckusick 	}
63424294Smckusick     }
63524294Smckusick     if (do_defines && def_state) {
63624294Smckusick 	fputs(end_defined, ofp);
63724294Smckusick     }
63824294Smckusick }
63924294Smckusick 
64024294Smckusick do_ed_script()
64124294Smckusick {
64224294Smckusick     FILE *pipefp, *popen();
64324294Smckusick     bool this_line_is_command = FALSE;
64424294Smckusick     register char *t;
64524294Smckusick     long beginning_of_this_line;
64624294Smckusick 
64724294Smckusick     Unlink(TMPOUTNAME);
64824294Smckusick     copy_file(filearg[0],TMPOUTNAME);
64924294Smckusick     if (verbose)
65024294Smckusick 	Sprintf(buf,"/bin/ed %s",TMPOUTNAME);
65124294Smckusick     else
65224294Smckusick 	Sprintf(buf,"/bin/ed - %s",TMPOUTNAME);
65324294Smckusick     pipefp = popen(buf,"w");
65424294Smckusick     for (;;) {
65524294Smckusick 	beginning_of_this_line = ftell(pfp);
65624294Smckusick 	if (pgets(buf,sizeof buf,pfp) == Nullch) {
65724294Smckusick 	    next_intuit_at(beginning_of_this_line);
65824294Smckusick 	    break;
65924294Smckusick 	}
66024294Smckusick 	for (t=buf; isdigit(*t) || *t == ','; t++) ;
66124294Smckusick 	this_line_is_command = (isdigit(*buf) &&
66224294Smckusick 	  (*t == 'd' || *t == 'c' || *t == 'a') );
66324294Smckusick 	if (this_line_is_command) {
66424294Smckusick 	    fputs(buf,pipefp);
66524294Smckusick 	    if (*t != 'd') {
66624294Smckusick 		while (pgets(buf,sizeof buf,pfp) != Nullch) {
66724294Smckusick 		    fputs(buf,pipefp);
66824294Smckusick 		    if (strEQ(buf,".\n"))
66924294Smckusick 			break;
67024294Smckusick 		}
67124294Smckusick 	    }
67224294Smckusick 	}
67324294Smckusick 	else {
67424294Smckusick 	    next_intuit_at(beginning_of_this_line);
67524294Smckusick 	    break;
67624294Smckusick 	}
67724294Smckusick     }
67824294Smckusick     fprintf(pipefp,"w\n");
67924294Smckusick     fprintf(pipefp,"q\n");
68024294Smckusick     Fflush(pipefp);
68124294Smckusick     Pclose(pipefp);
68224294Smckusick     ignore_signals();
68324294Smckusick     move_file(TMPOUTNAME,outname);
68424294Smckusick     set_signals();
68524294Smckusick }
68624294Smckusick 
68724294Smckusick init_output(name)
68824294Smckusick char *name;
68924294Smckusick {
69024294Smckusick     ofp = fopen(name,"w");
69124294Smckusick     if (ofp == Nullfp)
69224294Smckusick 	fatal("patch: can't create %s.\n",name);
69324294Smckusick }
69424294Smckusick 
69524294Smckusick init_reject(name)
69624294Smckusick char *name;
69724294Smckusick {
69824294Smckusick     rejfp = fopen(name,"w");
69924294Smckusick     if (rejfp == Nullfp)
70024294Smckusick 	fatal("patch: can't create %s.\n",name);
70124294Smckusick }
70224294Smckusick 
70324294Smckusick move_file(from,to)
70424294Smckusick char *from, *to;
70524294Smckusick {
70624294Smckusick     char bakname[512];
70724294Smckusick     register char *s;
70824294Smckusick     int fromfd;
70924294Smckusick     register int i;
71024294Smckusick 
71124294Smckusick     /* to stdout? */
71224294Smckusick 
71324294Smckusick     if (strEQ(to,"-")) {
71424294Smckusick #ifdef DEBUGGING
71524294Smckusick 	if (debug & 4)
71624294Smckusick 	    say("Moving %s to stdout.\n",from);
71724294Smckusick #endif
71824294Smckusick 	fromfd = open(from,0);
71924294Smckusick 	if (fromfd < 0)
72024294Smckusick 	    fatal("patch: internal error, can't reopen %s\n",from);
72124294Smckusick 	while ((i=read(fromfd,buf,sizeof buf)) > 0)
72224294Smckusick 	    if (write(1,buf,i) != 1)
72324294Smckusick 		fatal("patch: write failed\n");
72424294Smckusick 	Close(fromfd);
72524294Smckusick 	return;
72624294Smckusick     }
72724294Smckusick 
72824294Smckusick     Strcpy(bakname,to);
72924294Smckusick     Strcat(bakname,origext?origext:ORIGEXT);
73024294Smckusick     if (stat(to,&filestat) >= 0) {	/* output file exists */
73124294Smckusick 	dev_t to_device = filestat.st_dev;
73224294Smckusick 	ino_t to_inode  = filestat.st_ino;
73324294Smckusick 	char *simplename = bakname;
73424294Smckusick 
73524294Smckusick 	for (s=bakname; *s; s++) {
73624294Smckusick 	    if (*s == '/')
73724294Smckusick 		simplename = s+1;
73824294Smckusick 	}
73924294Smckusick 	/* find a backup name that is not the same file */
74024294Smckusick 	while (stat(bakname,&filestat) >= 0 &&
74124294Smckusick 		to_device == filestat.st_dev && to_inode == filestat.st_ino) {
74224294Smckusick 	    for (s=simplename; *s && !islower(*s); s++) ;
74324294Smckusick 	    if (*s)
74424294Smckusick 		*s = toupper(*s);
74524294Smckusick 	    else
74624294Smckusick 		Strcpy(simplename, simplename+1);
74724294Smckusick 	}
74824294Smckusick 	while (unlink(bakname) >= 0) ;	/* while() is for benefit of Eunice */
74924294Smckusick #ifdef DEBUGGING
75024294Smckusick 	if (debug & 4)
75124294Smckusick 	    say("Moving %s to %s.\n",to,bakname);
75224294Smckusick #endif
75324294Smckusick 	if (link(to,bakname) < 0) {
75424294Smckusick 	    say("patch: can't backup %s, output is in %s\n",
75524294Smckusick 		to,from);
75624294Smckusick 	    return;
75724294Smckusick 	}
75824294Smckusick 	while (unlink(to) >= 0) ;
75924294Smckusick     }
76024294Smckusick #ifdef DEBUGGING
76124294Smckusick     if (debug & 4)
76224294Smckusick 	say("Moving %s to %s.\n",from,to);
76324294Smckusick #endif
76424294Smckusick     if (link(from,to) < 0) {		/* different file system? */
76524294Smckusick 	int tofd;
76624294Smckusick 
76724294Smckusick 	tofd = creat(to,0666);
76824294Smckusick 	if (tofd < 0) {
76924294Smckusick 	    say("patch: can't create %s, output is in %s.\n",
77024294Smckusick 	      to, from);
77124294Smckusick 	    return;
77224294Smckusick 	}
77324294Smckusick 	fromfd = open(from,0);
77424294Smckusick 	if (fromfd < 0)
77524294Smckusick 	    fatal("patch: internal error, can't reopen %s\n",from);
77624294Smckusick 	while ((i=read(fromfd,buf,sizeof buf)) > 0)
77724294Smckusick 	    if (write(tofd,buf,i) != i)
77824294Smckusick 		fatal("patch: write failed\n");
77924294Smckusick 	Close(fromfd);
78024294Smckusick 	Close(tofd);
78124294Smckusick     }
78224294Smckusick     Unlink(from);
78324294Smckusick }
78424294Smckusick 
78524294Smckusick copy_file(from,to)
78624294Smckusick char *from, *to;
78724294Smckusick {
78824294Smckusick     int tofd;
78924294Smckusick     int fromfd;
79024294Smckusick     register int i;
79124294Smckusick 
79224294Smckusick     tofd = creat(to,0666);
79324294Smckusick     if (tofd < 0)
79424294Smckusick 	fatal("patch: can't create %s.\n", to);
79524294Smckusick     fromfd = open(from,0);
79624294Smckusick     if (fromfd < 0)
79724294Smckusick 	fatal("patch: internal error, can't reopen %s\n",from);
79824294Smckusick     while ((i=read(fromfd,buf,sizeof buf)) > 0)
79924294Smckusick 	if (write(tofd,buf,i) != i)
80024294Smckusick 	    fatal("patch: write (%s) failed\n", to);
80124294Smckusick     Close(fromfd);
80224294Smckusick     Close(tofd);
80324294Smckusick }
80424294Smckusick 
80524294Smckusick copy_till(lastline)
80624294Smckusick register LINENUM lastline;
80724294Smckusick {
80824294Smckusick     if (last_frozen_line > lastline)
80924294Smckusick 	say("patch: misordered hunks! output will be garbled.\n");
81024294Smckusick     while (last_frozen_line < lastline) {
81124294Smckusick 	dump_line(++last_frozen_line);
81224294Smckusick     }
81324294Smckusick }
81424294Smckusick 
81524294Smckusick spew_output()
81624294Smckusick {
81724294Smckusick     copy_till(input_lines);		/* dump remainder of file */
81824294Smckusick     Fclose(ofp);
81924294Smckusick     ofp = Nullfp;
82024294Smckusick }
82124294Smckusick 
82224294Smckusick dump_line(line)
82324294Smckusick LINENUM line;
82424294Smckusick {
82524294Smckusick     register char *s;
82624294Smckusick 
82724294Smckusick     for (s=ifetch(line,0); putc(*s,ofp) != '\n'; s++) ;
82824294Smckusick }
82924294Smckusick 
83024294Smckusick /* does the patch pattern match at line base+offset? */
83124294Smckusick 
83224294Smckusick bool
83324294Smckusick patch_match(base,offset)
83424294Smckusick LINENUM base;
83524294Smckusick LINENUM offset;
83624294Smckusick {
83724294Smckusick     register LINENUM pline;
83824294Smckusick     register LINENUM iline;
83924294Smckusick     register LINENUM pat_lines = pch_ptrn_lines();
84024294Smckusick 
84124294Smckusick     for (pline = 1, iline=base+offset; pline <= pat_lines; pline++,iline++) {
84224294Smckusick 	if (canonicalize) {
84324294Smckusick 	    if (!similar(ifetch(iline,(offset >= 0)),
84424294Smckusick 			 pfetch(pline),
84524294Smckusick 			 pch_line_len(pline) ))
84624294Smckusick 		return FALSE;
84724294Smckusick 	}
84824294Smckusick 	else if (strnNE(ifetch(iline,(offset >= 0)),
84924294Smckusick 		   pfetch(pline),
85024294Smckusick 		   pch_line_len(pline) ))
85124294Smckusick 	    return FALSE;
85224294Smckusick     }
85324294Smckusick     return TRUE;
85424294Smckusick }
85524294Smckusick 
85624294Smckusick /* match two lines with canonicalized white space */
85724294Smckusick 
85824294Smckusick bool
85924294Smckusick similar(a,b,len)
86024294Smckusick register char *a, *b;
86124294Smckusick register int len;
86224294Smckusick {
86324294Smckusick     while (len) {
86424294Smckusick 	if (isspace(*b)) {		/* whitespace (or \n) to match? */
86524294Smckusick 	    if (!isspace(*a))		/* no corresponding whitespace? */
86624294Smckusick 		return FALSE;
86724294Smckusick 	    while (len && isspace(*b) && *b != '\n')
86824294Smckusick 		b++,len--;		/* skip pattern whitespace */
86924294Smckusick 	    while (isspace(*a) && *a != '\n')
87024294Smckusick 		a++;			/* skip target whitespace */
87124294Smckusick 	    if (*a == '\n' || *b == '\n')
87224294Smckusick 		return (*a == *b);	/* should end in sync */
87324294Smckusick 	}
87424294Smckusick 	else if (*a++ != *b++)		/* match non-whitespace chars */
87524294Smckusick 	    return FALSE;
87624294Smckusick 	else
87724294Smckusick 	    len--;			/* probably not necessary */
87824294Smckusick     }
87924294Smckusick     return TRUE;			/* actually, this is not reached */
88024294Smckusick 					/* since there is always a \n */
88124294Smckusick }
88224294Smckusick 
88324294Smckusick /* input file with indexable lines abstract type */
88424294Smckusick 
88524294Smckusick bool using_plan_a = TRUE;
88624294Smckusick static long i_size;			/* size of the input file */
88724294Smckusick static char *i_womp;			/* plan a buffer for entire file */
88824294Smckusick static char **i_ptr;			/* pointers to lines in i_womp */
88924294Smckusick 
89024294Smckusick static int tifd = -1;			/* plan b virtual string array */
89124294Smckusick static char *tibuf[2];			/* plan b buffers */
89224294Smckusick static LINENUM tiline[2] = {-1,-1};	/* 1st line in each buffer */
89324294Smckusick static LINENUM lines_per_buf;		/* how many lines per buffer */
89424294Smckusick static int tireclen;			/* length of records in tmp file */
89524294Smckusick 
89624294Smckusick re_input()
89724294Smckusick {
89824294Smckusick     if (using_plan_a) {
89924294Smckusick 	i_size = 0;
90024294Smckusick 	/*NOSTRICT*/
90124294Smckusick 	if (i_ptr != Null(char**))
90224294Smckusick 	    free((char *)i_ptr);
90324294Smckusick 	if (i_womp != Nullch)
90424294Smckusick 	    free(i_womp);
90524294Smckusick 	i_womp = Nullch;
90624294Smckusick 	i_ptr = Null(char **);
90724294Smckusick     }
90824294Smckusick     else {
90924294Smckusick 	using_plan_a = TRUE;		/* maybe the next one is smaller */
91024294Smckusick 	Close(tifd);
91124294Smckusick 	tifd = -1;
91224294Smckusick 	free(tibuf[0]);
91324294Smckusick 	free(tibuf[1]);
91424294Smckusick 	tibuf[0] = tibuf[1] = Nullch;
91524294Smckusick 	tiline[0] = tiline[1] = -1;
91624294Smckusick 	tireclen = 0;
91724294Smckusick     }
91824294Smckusick }
91924294Smckusick 
92024294Smckusick scan_input(filename)
92124294Smckusick char *filename;
92224294Smckusick {
92324294Smckusick     bool plan_a();
92424294Smckusick 
92524294Smckusick     if (!plan_a(filename))
92624294Smckusick 	plan_b(filename);
92724294Smckusick }
92824294Smckusick 
92924294Smckusick /* try keeping everything in memory */
93024294Smckusick 
93124294Smckusick bool
93224294Smckusick plan_a(filename)
93324294Smckusick char *filename;
93424294Smckusick {
93524294Smckusick     int ifd;
93624294Smckusick     register char *s;
93724294Smckusick     register LINENUM iline;
93824294Smckusick 
93924294Smckusick     if (stat(filename,&filestat) < 0) {
94024294Smckusick 	Sprintf(buf,"RCS/%s%s",filename,RCSSUFFIX);
94124294Smckusick 	if (stat(buf,&filestat) >= 0 || stat(buf+4,&filestat) >= 0) {
94224294Smckusick 	    Sprintf(buf,CHECKOUT,filename);
94324294Smckusick 	    if (verbose)
94424294Smckusick 		say("Can't find %s--attempting to check it out from RCS.\n",
94524294Smckusick 		    filename);
94624294Smckusick 	    if (system(buf) || stat(filename,&filestat))
94724294Smckusick 		fatal("Can't check out %s.\n",filename);
94824294Smckusick 	}
94924294Smckusick 	else {
95024294Smckusick 	    Sprintf(buf,"SCCS/%s%s",SCCSPREFIX,filename);
95124294Smckusick 	    if (stat(buf,&filestat) >= 0 || stat(buf+5,&filestat) >= 0) {
95224294Smckusick 		Sprintf(buf,GET,filename);
95324294Smckusick 		if (verbose)
95424294Smckusick 		    say("Can't find %s--attempting to get it from SCCS.\n",
95524294Smckusick 			filename);
95624294Smckusick 		if (system(buf) || stat(filename,&filestat))
95724294Smckusick 		    fatal("Can't get %s.\n",filename);
95824294Smckusick 	    }
95924294Smckusick 	    else
96024294Smckusick 		fatal("Can't find %s.\n",filename);
96124294Smckusick 	}
96224294Smckusick     }
96324294Smckusick     if ((filestat.st_mode & S_IFMT) & ~S_IFREG)
96424294Smckusick 	fatal("%s is not a normal file--can't patch.\n",filename);
96524294Smckusick     i_size = filestat.st_size;
96624294Smckusick     /*NOSTRICT*/
96724294Smckusick     i_womp = malloc((MEM)(i_size+2));
96824294Smckusick     if (i_womp == Nullch)
96924294Smckusick 	return FALSE;
97024294Smckusick     if ((ifd = open(filename,0)) < 0)
97124294Smckusick 	fatal("Can't open file %s\n",filename);
97224294Smckusick     /*NOSTRICT*/
97324294Smckusick     if (read(ifd,i_womp,(int)i_size) != i_size) {
97424294Smckusick 	Close(ifd);
97524294Smckusick 	free(i_womp);
97624294Smckusick 	return FALSE;
97724294Smckusick     }
97824294Smckusick     Close(ifd);
97924294Smckusick     if (i_womp[i_size-1] != '\n')
98024294Smckusick 	i_womp[i_size++] = '\n';
98124294Smckusick     i_womp[i_size] = '\0';
98224294Smckusick 
98324294Smckusick     /* count the lines in the buffer so we know how many pointers we need */
98424294Smckusick 
98524294Smckusick     iline = 0;
98624294Smckusick     for (s=i_womp; *s; s++) {
98724294Smckusick 	if (*s == '\n')
98824294Smckusick 	    iline++;
98924294Smckusick     }
99024294Smckusick     /*NOSTRICT*/
99124294Smckusick     i_ptr = (char **)malloc((MEM)((iline + 2) * sizeof(char *)));
99224294Smckusick     if (i_ptr == Null(char **)) {	/* shucks, it was a near thing */
99324294Smckusick 	free((char *)i_womp);
99424294Smckusick 	return FALSE;
99524294Smckusick     }
99624294Smckusick 
99724294Smckusick     /* now scan the buffer and build pointer array */
99824294Smckusick 
99924294Smckusick     iline = 1;
100024294Smckusick     i_ptr[iline] = i_womp;
100124294Smckusick     for (s=i_womp; *s; s++) {
100224294Smckusick 	if (*s == '\n')
100324294Smckusick 	    i_ptr[++iline] = s+1;	/* these are NOT null terminated */
100424294Smckusick     }
100524294Smckusick     input_lines = iline - 1;
100624294Smckusick 
100724294Smckusick     /* now check for revision, if any */
100824294Smckusick 
100924294Smckusick     if (revision != Nullch) {
101024294Smckusick 	if (!rev_in_string(i_womp)) {
101124294Smckusick 	    ask("This file doesn't appear to be the %s version--patch anyway? [n] ",
101224294Smckusick 		revision);
101324294Smckusick 	    if (*buf != 'y')
101424294Smckusick 		fatal("Aborted.\n");
101524294Smckusick 	}
101624294Smckusick 	else if (verbose)
101724294Smckusick 	    say("Good.  This file appears to be the %s version.\n",
101824294Smckusick 		revision);
101924294Smckusick     }
102024294Smckusick     return TRUE;			/* plan a will work */
102124294Smckusick }
102224294Smckusick 
102324294Smckusick /* keep (virtually) nothing in memory */
102424294Smckusick 
102524294Smckusick plan_b(filename)
102624294Smckusick char *filename;
102724294Smckusick {
102824294Smckusick     FILE *ifp;
102924294Smckusick     register int i = 0;
103024294Smckusick     register int maxlen = 1;
103124294Smckusick     bool found_revision = (revision == Nullch);
103224294Smckusick 
103324294Smckusick     using_plan_a = FALSE;
103424294Smckusick     if ((ifp = fopen(filename,"r")) == Nullfp)
103524294Smckusick 	fatal("Can't open file %s\n",filename);
103624294Smckusick     if ((tifd = creat(TMPINNAME,0666)) < 0)
103724294Smckusick 	fatal("Can't open file %s\n",TMPINNAME);
103824294Smckusick     while (fgets(buf,sizeof buf, ifp) != Nullch) {
103924294Smckusick 	if (revision != Nullch && !found_revision && rev_in_string(buf))
104024294Smckusick 	    found_revision = TRUE;
104124294Smckusick 	if ((i = strlen(buf)) > maxlen)
104224294Smckusick 	    maxlen = i;			/* find longest line */
104324294Smckusick     }
104424294Smckusick     if (revision != Nullch) {
104524294Smckusick 	if (!found_revision) {
104624294Smckusick 	    ask("This file doesn't appear to be the %s version--patch anyway? [n] ",
104724294Smckusick 		revision);
104824294Smckusick 	    if (*buf != 'y')
104924294Smckusick 		fatal("Aborted.\n");
105024294Smckusick 	}
105124294Smckusick 	else if (verbose)
105224294Smckusick 	    say("Good.  This file appears to be the %s version.\n",
105324294Smckusick 		revision);
105424294Smckusick     }
105524294Smckusick     Fseek(ifp,0L,0);		/* rewind file */
105624294Smckusick     lines_per_buf = BUFFERSIZE / maxlen;
105724294Smckusick     tireclen = maxlen;
105824294Smckusick     tibuf[0] = malloc((MEM)(BUFFERSIZE + 1));
105924294Smckusick     tibuf[1] = malloc((MEM)(BUFFERSIZE + 1));
106024294Smckusick     if (tibuf[1] == Nullch)
106124294Smckusick 	fatal("Can't seem to get enough memory.\n");
106224294Smckusick     for (i=1; ; i++) {
106324294Smckusick 	if (! (i % lines_per_buf))	/* new block */
106424294Smckusick 	    if (write(tifd,tibuf[0],BUFFERSIZE) < BUFFERSIZE)
106524294Smckusick 		fatal("patch: can't write temp file.\n");
106624294Smckusick 	if (fgets(tibuf[0] + maxlen * (i%lines_per_buf), maxlen + 1, ifp)
106724294Smckusick 	  == Nullch) {
106824294Smckusick 	    input_lines = i - 1;
106924294Smckusick 	    if (i % lines_per_buf)
107024294Smckusick 		if (write(tifd,tibuf[0],BUFFERSIZE) < BUFFERSIZE)
107124294Smckusick 		    fatal("patch: can't write temp file.\n");
107224294Smckusick 	    break;
107324294Smckusick 	}
107424294Smckusick     }
107524294Smckusick     Fclose(ifp);
107624294Smckusick     Close(tifd);
107724294Smckusick     if ((tifd = open(TMPINNAME,0)) < 0) {
107824294Smckusick 	fatal("Can't reopen file %s\n",TMPINNAME);
107924294Smckusick     }
108024294Smckusick }
108124294Smckusick 
108224294Smckusick /* fetch a line from the input file, \n terminated, not necessarily \0 */
108324294Smckusick char *
108424294Smckusick ifetch(line,whichbuf)
108524294Smckusick register LINENUM line;
108624294Smckusick int whichbuf;				/* ignored when file in memory */
108724294Smckusick {
108824294Smckusick     if (line < 1 || line > input_lines)
108924294Smckusick 	return "";
109024294Smckusick     if (using_plan_a)
109124294Smckusick 	return i_ptr[line];
109224294Smckusick     else {
109324294Smckusick 	LINENUM offline = line % lines_per_buf;
109424294Smckusick 	LINENUM baseline = line - offline;
109524294Smckusick 
109624294Smckusick 	if (tiline[0] == baseline)
109724294Smckusick 	    whichbuf = 0;
109824294Smckusick 	else if (tiline[1] == baseline)
109924294Smckusick 	    whichbuf = 1;
110024294Smckusick 	else {
110124294Smckusick 	    tiline[whichbuf] = baseline;
110224294Smckusick 	    Lseek(tifd,(long)baseline / lines_per_buf * BUFFERSIZE,0);
110324294Smckusick 	    if (read(tifd,tibuf[whichbuf],BUFFERSIZE) < 0)
110424294Smckusick 		fatal("Error reading tmp file %s.\n",TMPINNAME);
110524294Smckusick 	}
110624294Smckusick 	return tibuf[whichbuf] + (tireclen*offline);
110724294Smckusick     }
110824294Smckusick }
110924294Smckusick 
111024294Smckusick /* patch abstract type */
111124294Smckusick 
111224294Smckusick static long p_filesize;			/* size of the patch file */
111324294Smckusick static LINENUM p_first;			/* 1st line number */
111424294Smckusick static LINENUM p_newfirst;		/* 1st line number of replacement */
111524294Smckusick static LINENUM p_ptrn_lines;		/* # lines in pattern */
111624294Smckusick static LINENUM p_repl_lines;		/* # lines in replacement text */
111724294Smckusick static LINENUM p_end = -1;		/* last line in hunk */
111824294Smckusick static LINENUM p_max;			/* max allowed value of p_end */
111924294Smckusick static LINENUM p_context = 3;		/* # of context lines */
112024294Smckusick static LINENUM p_input_line = 0;	/* current line # from patch file */
112124294Smckusick static char *p_line[MAXHUNKSIZE];	/* the text of the hunk */
112224294Smckusick static char p_char[MAXHUNKSIZE];	/* +, -, and ! */
112324294Smckusick static int p_len[MAXHUNKSIZE];		/* length of each line */
112424294Smckusick static int p_indent;			/* indent to patch */
112524294Smckusick static long p_base;			/* where to intuit this time */
112624294Smckusick static long p_start;			/* where intuit found a patch */
112724294Smckusick 
112824294Smckusick re_patch()
112924294Smckusick {
113024294Smckusick     p_first = (LINENUM)0;
113124294Smckusick     p_newfirst = (LINENUM)0;
113224294Smckusick     p_ptrn_lines = (LINENUM)0;
113324294Smckusick     p_repl_lines = (LINENUM)0;
113424294Smckusick     p_end = (LINENUM)-1;
113524294Smckusick     p_max = (LINENUM)0;
113624294Smckusick     p_indent = 0;
113724294Smckusick }
113824294Smckusick 
113924294Smckusick open_patch_file(filename)
114024294Smckusick char *filename;
114124294Smckusick {
114224294Smckusick     if (filename == Nullch || !*filename || strEQ(filename,"-")) {
114324294Smckusick 	pfp = fopen(TMPPATNAME,"w");
114424294Smckusick 	if (pfp == Nullfp)
114524294Smckusick 	    fatal("patch: can't create %s.\n",TMPPATNAME);
114624294Smckusick 	while (fgets(buf,sizeof buf,stdin) != NULL)
114724294Smckusick 	    fputs(buf,pfp);
114824294Smckusick 	Fclose(pfp);
114924294Smckusick 	filename = TMPPATNAME;
115024294Smckusick     }
115124294Smckusick     pfp = fopen(filename,"r");
115224294Smckusick     if (pfp == Nullfp)
115324294Smckusick 	fatal("patch file %s not found\n",filename);
115424294Smckusick     Fstat(fileno(pfp), &filestat);
115524294Smckusick     p_filesize = filestat.st_size;
115624294Smckusick     next_intuit_at(0L);			/* start at the beginning */
115724294Smckusick }
115824294Smckusick 
115924294Smckusick bool
116024294Smckusick there_is_another_patch()
116124294Smckusick {
116224294Smckusick     bool no_input_file = (filearg[0] == Nullch);
116324294Smckusick 
116424294Smckusick     if (p_base != 0L && p_base >= p_filesize) {
116524294Smckusick 	if (verbose)
116624294Smckusick 	    say("done\n");
116724294Smckusick 	return FALSE;
116824294Smckusick     }
116924294Smckusick     if (verbose)
117024294Smckusick 	say("Hmm...");
117124294Smckusick     diff_type = intuit_diff_type();
117224294Smckusick     if (!diff_type) {
117324294Smckusick 	if (p_base != 0L) {
117424294Smckusick 	    if (verbose)
117524294Smckusick 		say("  Ignoring the trailing garbage.\ndone\n");
117624294Smckusick 	}
117724294Smckusick 	else
117824294Smckusick 	    say("  I can't seem to find a patch in there anywhere.\n");
117924294Smckusick 	return FALSE;
118024294Smckusick     }
118124294Smckusick     if (verbose)
118224294Smckusick 	say("  %sooks like %s to me...\n",
118324294Smckusick 	    (p_base == 0L ? "L" : "The next patch l"),
118424294Smckusick 	    diff_type == CONTEXT_DIFF ? "a context diff" :
118524295Smckusick 	    diff_type == NEW_CONTEXT_DIFF ? "a new-style context diff" :
118624294Smckusick 	    diff_type == NORMAL_DIFF ? "a normal diff" :
118724294Smckusick 	    "an ed script" );
118824294Smckusick     if (p_indent && verbose)
118924294Smckusick 	say("(Patch is indented %d space%s.)\n",p_indent,p_indent==1?"":"s");
119024294Smckusick     skip_to(p_start);
119124294Smckusick     if (no_input_file) {
119226490Sbloom 	while (filearg[0] == Nullch) {
119324294Smckusick 	    ask("File to patch: ");
119424294Smckusick 	    filearg[0] = fetchname(buf);
119524294Smckusick 	}
119626490Sbloom 	if (verbose) {
119724294Smckusick 	    say("Patching file %s...\n",filearg[0]);
119824294Smckusick 	}
119924294Smckusick     }
120024294Smckusick     return TRUE;
120124294Smckusick }
120224294Smckusick 
120324294Smckusick intuit_diff_type()
120424294Smckusick {
120524294Smckusick     long this_line = 0;
120624294Smckusick     long previous_line;
120724294Smckusick     long first_command_line = -1;
120824294Smckusick     bool last_line_was_command = FALSE;
120924294Smckusick     bool this_line_is_command = FALSE;
121024295Smckusick     bool last_line_was_stars = FALSE;
121124295Smckusick     bool this_line_is_stars = FALSE;
121224294Smckusick     register int indent;
121324294Smckusick     register char *s, *t;
121424294Smckusick     char *oldname = Nullch;
121524294Smckusick     char *newname = Nullch;
121624294Smckusick     bool no_filearg = (filearg[0] == Nullch);
121724294Smckusick 
121824294Smckusick     Fseek(pfp,p_base,0);
121924294Smckusick     for (;;) {
122024294Smckusick 	previous_line = this_line;
122124294Smckusick 	last_line_was_command = this_line_is_command;
122224295Smckusick 	last_line_was_stars = this_line_is_stars;
122324294Smckusick 	this_line = ftell(pfp);
122424294Smckusick 	indent = 0;
122524294Smckusick 	if (fgets(buf,sizeof buf,pfp) == Nullch) {
122624294Smckusick 	    if (first_command_line >= 0L) {
122724294Smckusick 					/* nothing but deletes!? */
122824294Smckusick 		p_start = first_command_line;
122924294Smckusick 		return ED_DIFF;
123024294Smckusick 	    }
123124294Smckusick 	    else {
123224294Smckusick 		p_start = this_line;
123324294Smckusick 		return 0;
123424294Smckusick 	    }
123524294Smckusick 	}
123624294Smckusick 	for (s = buf; *s == ' ' || *s == '\t'; s++) {
123724294Smckusick 	    if (*s == '\t')
123824294Smckusick 		indent += 8 - (indent % 8);
123924294Smckusick 	    else
124024294Smckusick 		indent++;
124124294Smckusick 	}
124224294Smckusick 	for (t=s; isdigit(*t) || *t == ','; t++) ;
124324294Smckusick 	this_line_is_command = (isdigit(*s) &&
124424294Smckusick 	  (*t == 'd' || *t == 'c' || *t == 'a') );
124524294Smckusick 	if (first_command_line < 0L && this_line_is_command) {
124624294Smckusick 	    first_command_line = this_line;
124724294Smckusick 	    p_indent = indent;		/* assume this for now */
124824294Smckusick 	}
124924294Smckusick 	if (strnEQ(s,"*** ",4))
125024294Smckusick 	    oldname = fetchname(s+4);
125124294Smckusick 	else if (strnEQ(s,"--- ",4)) {
125224294Smckusick 	    newname = fetchname(s+4);
125324294Smckusick 	    if (no_filearg) {
125424294Smckusick 		if (oldname && newname) {
125524294Smckusick 		    if (strlen(oldname) < strlen(newname))
125624294Smckusick 			filearg[0] = oldname;
125724294Smckusick 		    else
125824294Smckusick 			filearg[0] = newname;
125924294Smckusick 		}
126024294Smckusick 		else if (oldname)
126124294Smckusick 		    filearg[0] = oldname;
126224294Smckusick 		else if (newname)
126324294Smckusick 		    filearg[0] = newname;
126424294Smckusick 	    }
126524294Smckusick 	}
126624294Smckusick 	else if (strnEQ(s,"Index:",6)) {
126724294Smckusick 	    if (no_filearg)
126824294Smckusick 		filearg[0] = fetchname(s+6);
126924294Smckusick 					/* this filearg might get limboed */
127024294Smckusick 	}
127124294Smckusick 	else if (strnEQ(s,"Prereq:",7)) {
127224294Smckusick 	    for (t=s+7; isspace(*t); t++) ;
127324294Smckusick 	    revision = savestr(t);
127424294Smckusick 	    for (t=revision; *t && !isspace(*t); t++) ;
127524294Smckusick 	    *t = '\0';
127624294Smckusick 	    if (!*revision) {
127724294Smckusick 		free(revision);
127824294Smckusick 		revision = Nullch;
127924294Smckusick 	    }
128024294Smckusick 	}
128124294Smckusick 	if ((!diff_type || diff_type == ED_DIFF) &&
128224294Smckusick 	  first_command_line >= 0L &&
128324294Smckusick 	  strEQ(s,".\n") ) {
128424294Smckusick 	    p_indent = indent;
128524294Smckusick 	    p_start = first_command_line;
128624294Smckusick 	    return ED_DIFF;
128724294Smckusick 	}
128824295Smckusick 	this_line_is_stars = strnEQ(s,"********",8);
128924295Smckusick 	if ((!diff_type || diff_type == CONTEXT_DIFF) && last_line_was_stars &&
129024295Smckusick 		 strnEQ(s,"*** ",4)) {
129124295Smckusick 	    /* if this is a new context diff the character just before */
129224295Smckusick 	    /* the newline is a '*'. */
129324295Smckusick 	    while (*s != '\n')
129424295Smckusick 		s++;
129524294Smckusick 	    p_indent = indent;
129624295Smckusick 	    p_start = previous_line;
129724295Smckusick 	    return (*(s-1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF);
129824294Smckusick 	}
129924294Smckusick 	if ((!diff_type || diff_type == NORMAL_DIFF) &&
130024294Smckusick 	  last_line_was_command &&
130124294Smckusick 	  (strnEQ(s,"< ",2) || strnEQ(s,"> ",2)) ) {
130224294Smckusick 	    p_start = previous_line;
130324294Smckusick 	    p_indent = indent;
130424294Smckusick 	    return NORMAL_DIFF;
130524294Smckusick 	}
130624294Smckusick     }
130724294Smckusick }
130824294Smckusick 
130924294Smckusick char *
131024294Smckusick fetchname(at)
131124294Smckusick char *at;
131224294Smckusick {
131324294Smckusick     char *s = savestr(at);
131424294Smckusick     char *name;
131524294Smckusick     register char *t;
131624294Smckusick     char tmpbuf[200];
131724294Smckusick 
131824294Smckusick     for (t=s; isspace(*t); t++) ;
131924294Smckusick     name = t;
132024294Smckusick     for (; *t && !isspace(*t); t++)
132124294Smckusick 	if (!usepath)
132224294Smckusick 	    if (*t == '/')
132324294Smckusick 		name = t+1;
132424294Smckusick     *t = '\0';
132524294Smckusick     name = savestr(name);
132624294Smckusick     Sprintf(tmpbuf,"RCS/%s",name);
132724294Smckusick     free(s);
132824294Smckusick     if (stat(name,&filestat) < 0) {
132924294Smckusick 	Strcat(tmpbuf,RCSSUFFIX);
133024294Smckusick 	if (stat(tmpbuf,&filestat) < 0 && stat(tmpbuf+4,&filestat) < 0) {
133124294Smckusick 	    Sprintf(tmpbuf,"SCCS/%s%s",SCCSPREFIX,name);
133224294Smckusick 	    if (stat(tmpbuf,&filestat) < 0 && stat(tmpbuf+5,&filestat) < 0) {
133324294Smckusick 		free(name);
133424294Smckusick 		name = Nullch;
133524294Smckusick 	    }
133624294Smckusick 	}
133724294Smckusick     }
133824294Smckusick     return name;
133924294Smckusick }
134024294Smckusick 
134124294Smckusick next_intuit_at(file_pos)
134224294Smckusick long file_pos;
134324294Smckusick {
134424294Smckusick     p_base = file_pos;
134524294Smckusick }
134624294Smckusick 
134724294Smckusick skip_to(file_pos)
134824294Smckusick long file_pos;
134924294Smckusick {
135024294Smckusick     char *ret;
135124294Smckusick 
135224294Smckusick     assert(p_base <= file_pos);
135324294Smckusick     if (verbose && p_base < file_pos) {
135424294Smckusick 	Fseek(pfp,p_base,0);
135524294Smckusick 	say("The text leading up to this was:\n--------------------------\n");
135624294Smckusick 	while (ftell(pfp) < file_pos) {
135724294Smckusick 	    ret = fgets(buf,sizeof buf,pfp);
135824294Smckusick 	    assert(ret != Nullch);
135924294Smckusick 	    say("|%s",buf);
136024294Smckusick 	}
136124294Smckusick 	say("--------------------------\n");
136224294Smckusick     }
136324294Smckusick     else
136424294Smckusick 	Fseek(pfp,file_pos,0);
136524294Smckusick }
136624294Smckusick 
136724294Smckusick bool
136824294Smckusick another_hunk()
136924294Smckusick {
137024294Smckusick     register char *s;
137124294Smckusick     char *ret;
137224295Smckusick     register int context = 0;
137324294Smckusick 
137424294Smckusick     while (p_end >= 0) {
137524294Smckusick 	free(p_line[p_end--]);
137624294Smckusick     }
137724294Smckusick     assert(p_end == -1);
137824294Smckusick 
137924294Smckusick     p_max = MAXHUNKSIZE;		/* gets reduced when --- found */
138024294Smckusick     if (diff_type == CONTEXT_DIFF) {
138124294Smckusick 	long line_beginning = ftell(pfp);
138224294Smckusick 	LINENUM repl_beginning = 0;
138324294Smckusick 
138424294Smckusick 	ret = pgets(buf,sizeof buf, pfp);
138524294Smckusick 	if (ret == Nullch || strnNE(buf,"********",8)) {
138624294Smckusick 	    next_intuit_at(line_beginning);
138724294Smckusick 	    return FALSE;
138824294Smckusick 	}
138924294Smckusick 	p_context = 100;
139024294Smckusick 	while (p_end < p_max) {
139124294Smckusick 	    ret = pgets(buf,sizeof buf, pfp);
139224294Smckusick 	    if (ret == Nullch) {
139324294Smckusick 		if (p_max - p_end < 4)
139424294Smckusick 		    Strcpy(buf,"  \n");	/* assume blank lines got chopped */
139524294Smckusick 		else
139624294Smckusick 		    fatal("Unexpected end of file in patch.\n");
139724294Smckusick 	    }
139824294Smckusick 	    p_input_line++;
139924294Smckusick 	    if (strnEQ(buf,"********",8))
140024294Smckusick 		fatal("Unexpected end of hunk at line %d.\n",
140124294Smckusick 		    p_input_line);
140224294Smckusick 	    p_char[++p_end] = *buf;
140324294Smckusick 	    switch (*buf) {
140424294Smckusick 	    case '*':
140524294Smckusick 		if (p_end != 0)
140624294Smckusick 		    fatal("Unexpected *** at line %d: %s", p_input_line, buf);
140724294Smckusick 		context = 0;
140824294Smckusick 		p_line[p_end] = savestr(buf);
140924294Smckusick 		for (s=buf; *s && !isdigit(*s); s++) ;
1410*26977Svan 		if (!isdigit(*s))
1411*26977Svan 		    fatal("Malformed patch at line %d: %s", p_input_line, buf);
141224294Smckusick 		p_first = (LINENUM) atol(s);
141324294Smckusick 		while (isdigit(*s)) s++;
141424294Smckusick 		for (; *s && !isdigit(*s); s++) ;
1415*26977Svan 		if (!isdigit(*s))
1416*26977Svan 		    p_ptrn_lines = 1;
1417*26977Svan 		else
1418*26977Svan 		    p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
141924294Smckusick 		break;
142024294Smckusick 	    case '-':
142124294Smckusick 		if (buf[1] == '-') {
142224294Smckusick 		    if (p_end != p_ptrn_lines + 1 &&
142324294Smckusick 			p_end != p_ptrn_lines + 2)
142424294Smckusick 			fatal("Unexpected --- at line %d: %s",
142524294Smckusick 			    p_input_line,buf);
142624294Smckusick 		    repl_beginning = p_end;
142724294Smckusick 		    context = 0;
142824294Smckusick 		    p_line[p_end] = savestr(buf);
142924294Smckusick 		    p_char[p_end] = '=';
143024294Smckusick 		    for (s=buf; *s && !isdigit(*s); s++) ;
1431*26977Svan 		    if (!isdigit(*s))
1432*26977Svan 			fatal("Malformed patch at line %d: %s",
1433*26977Svan 			      p_input_line, buf);
143424294Smckusick 		    p_newfirst = (LINENUM) atol(s);
143524294Smckusick 		    while (isdigit(*s)) s++;
143624294Smckusick 		    for (; *s && !isdigit(*s); s++) ;
1437*26977Svan 		    if (!isdigit(*s))
1438*26977Svan 			p_max = p_newfirst;
1439*26977Svan 		    else
1440*26977Svan 			p_max = ((LINENUM)atol(s));
1441*26977Svan 		    p_max += 1 + p_end - p_newfirst;
1442*26977Svan 		    if (p_max >= MAXHUNKSIZE)
1443*26977Svan 			fatal("Hunk too large (%d lines) at line %d: %s",
1444*26977Svan 			      p_max - p_end, p_input_line, buf);
144524294Smckusick 		    break;
144624294Smckusick 		}
144724294Smckusick 		/* FALL THROUGH */
144824294Smckusick 	    case '+': case '!':
144924294Smckusick 		if (context > 0) {
145024294Smckusick 		    if (context < p_context)
145124294Smckusick 			p_context = context;
145224294Smckusick 		    context = -100;
145324294Smckusick 		}
145424294Smckusick 		p_line[p_end] = savestr(buf+2);
145524294Smckusick 		break;
145624294Smckusick 	    case '\t': case '\n':	/* assume the 2 spaces got eaten */
145724294Smckusick 		p_line[p_end] = savestr(buf);
145824294Smckusick 		if (p_end != p_ptrn_lines + 1) {
145924294Smckusick 		    context++;
146024294Smckusick 		    p_char[p_end] = ' ';
146124294Smckusick 		}
146224294Smckusick 		break;
146324294Smckusick 	    case ' ':
146424294Smckusick 		context++;
146524294Smckusick 		p_line[p_end] = savestr(buf+2);
146624294Smckusick 		break;
146724294Smckusick 	    default:
146824294Smckusick 		fatal("Malformed patch at line %d: %s",p_input_line,buf);
146924294Smckusick 	    }
1470*26977Svan 	    /* set up p_len for strncmp() so we don't have to */
1471*26977Svan 	    /* assume null termination */
1472*26977Svan 	    if (p_line[p_end])
147325795Smckusick 		p_len[p_end] = strlen(p_line[p_end]);
1474*26977Svan 	    else
1475*26977Svan 		p_len[p_end] = 0;
147624294Smckusick 	}
147724294Smckusick 	if (p_end >=0 && !p_ptrn_lines)
147824294Smckusick 	    fatal("No --- found in patch at line %d\n", pch_hunk_beg());
147924294Smckusick 	p_repl_lines = p_end - repl_beginning;
148024294Smckusick     }
148124295Smckusick     else if (diff_type == NEW_CONTEXT_DIFF) {
148224295Smckusick 	long line_beginning = ftell(pfp);
148324295Smckusick 	LINENUM repl_beginning = 0;
148424295Smckusick 	LINENUM fillcnt = 0;
148524295Smckusick 	LINENUM fillsrc;
148624295Smckusick 	LINENUM filldst;
148724295Smckusick 
148824295Smckusick 	ret = pgets(buf,sizeof buf, pfp);
148924295Smckusick 	if (ret == Nullch || strnNE(buf,"********",8)) {
149024295Smckusick 	    next_intuit_at(line_beginning);
149124295Smckusick 	    return FALSE;
149224295Smckusick 	}
149324295Smckusick 	p_context = 0;
149424295Smckusick 	while (p_end < p_max) {
149524295Smckusick 	    ret = pgets(buf,sizeof buf, pfp);
149624295Smckusick 	    if (ret == Nullch) {
149724295Smckusick 		if (p_max - p_end < 4)
149824295Smckusick 		    Strcpy(buf,"  \n");	/* assume blank lines got chopped */
1499*26977Svan 		else
150024295Smckusick 		    fatal("Unexpected end of file in patch.\n");
150124295Smckusick 	    }
150224295Smckusick 	    p_input_line++;
150324295Smckusick 	    p_char[++p_end] = *buf;
150424295Smckusick 	    switch (*buf) {
150526490Sbloom 	    case '*':	/* another hunk */
1506*26977Svan 		if (strnEQ(buf,"********",8))
1507*26977Svan 		    fatal("Unexpected end of hunk at line %d.\n",
1508*26977Svan 			    p_input_line);
1509*26977Svan 
151024295Smckusick 		if (p_end != 0)
151124295Smckusick 		    fatal("Unexpected *** at line %d: %s", p_input_line, buf);
151224295Smckusick 		context = 0;
151324295Smckusick 		p_line[p_end] = savestr(buf);
151424295Smckusick 		for (s=buf; *s && !isdigit(*s); s++) ;
1515*26977Svan 		if (!isdigit(*s))
1516*26977Svan 		    fatal("Malformed patch at line %d: %s", p_input_line, buf);
151724295Smckusick 		p_first = (LINENUM) atol(s);
151824295Smckusick 		while (isdigit(*s)) s++;
151924295Smckusick 		for (; *s && !isdigit(*s); s++) ;
1520*26977Svan 		if (!isdigit(*s))
1521*26977Svan 		    p_ptrn_lines = 1;
1522*26977Svan 		else
1523*26977Svan 		    p_ptrn_lines = ((LINENUM)atol(s)) - p_first + 1;
152424295Smckusick 		break;
152524295Smckusick 	    case '-':
152624295Smckusick 		if (buf[1] == '-') {
152724295Smckusick 		    if (p_end != p_ptrn_lines + 1) {
152824295Smckusick 			if (p_end == 1) {
152924295Smckusick 			    /* `old' lines were omitted - set up to fill them */
153024295Smckusick 			    /* in from 'new' context lines. */
153124295Smckusick 			    p_end = p_ptrn_lines + 1;
153224295Smckusick 			    fillsrc = p_end + 1;
153324295Smckusick 			    filldst = 1;
153424295Smckusick 			    fillcnt = p_ptrn_lines;
153524295Smckusick 			} else
153624295Smckusick 			    fatal("Unexpected --- at line %d: %s",
153724295Smckusick 				p_input_line,buf);
153824295Smckusick 		    }
153924295Smckusick 		    repl_beginning = p_end;
154024295Smckusick 		    p_line[p_end] = savestr(buf);
154124295Smckusick 		    p_char[p_end] = '=';
154224295Smckusick 		    for (s=buf; *s && !isdigit(*s); s++) ;
1543*26977Svan 		    if (!isdigit(*s))
1544*26977Svan 			fatal("Malformed patch at line %d: %s",
1545*26977Svan 			      p_input_line, buf);
154624295Smckusick 		    p_newfirst = (LINENUM) atol(s);
154724295Smckusick 		    while (isdigit(*s)) s++;
154824295Smckusick 		    for (; *s && !isdigit(*s); s++) ;
1549*26977Svan 		    if (!isdigit(*s))
1550*26977Svan 			p_max = p_newfirst;
1551*26977Svan 		    else
1552*26977Svan 			p_max = ((LINENUM)atol(s));
1553*26977Svan 		    p_max += 1 + p_end - p_newfirst;
1554*26977Svan 		    if (p_max >= MAXHUNKSIZE)
1555*26977Svan 			fatal("Hunk too large (%d lines) at line %d: %s",
1556*26977Svan 			      p_max - p_end, p_input_line, buf);
1557*26977Svan 		    if (p_max - p_end == context) {
1558*26977Svan 			/* redundant 'new' context lines were omitted */
1559*26977Svan 			/* set up to fill them in from the the old file's */
1560*26977Svan 			/* context */
1561*26977Svan 			fillsrc = 1;
1562*26977Svan 			filldst = p_end + 1;
1563*26977Svan 			fillcnt = p_max - repl_beginning;
1564*26977Svan 			p_end = p_max;
1565*26977Svan 		    }
156624295Smckusick 		    break;
156724295Smckusick 		}
156824295Smckusick 		/* FALL THROUGH */
156924295Smckusick 	    case '+': case '!':
157024295Smckusick 		if (context > 0 && p_context == 0) {
157124295Smckusick 		    p_context = context;
157224295Smckusick 		}
157324295Smckusick 		p_line[p_end] = savestr(buf+2);
157424295Smckusick 		break;
157524295Smckusick 	    case '\t': case '\n':	/* assume the 2 spaces got eaten */
157624295Smckusick 		p_line[p_end] = savestr(buf);
157724295Smckusick 		if (p_end != p_ptrn_lines + 1) {
157824295Smckusick 		    context++;
157924295Smckusick 		    p_char[p_end] = ' ';
158024295Smckusick 		}
158124295Smckusick 		break;
158224295Smckusick 	    case ' ':
158324295Smckusick 		context++;
158424295Smckusick 		p_line[p_end] = savestr(buf+2);
158524295Smckusick 		break;
158624295Smckusick 	    default:
158724295Smckusick 		fatal("Malformed patch at line %d: %s",p_input_line,buf);
158824295Smckusick 	    }
1589*26977Svan 	    /* set up p_len for strncmp() so we don't have to */
1590*26977Svan 	    /* assume null termination */
1591*26977Svan 	    if (p_line[p_end])
159225795Smckusick 		p_len[p_end] = strlen(p_line[p_end]);
1593*26977Svan 	    else
1594*26977Svan 		p_len[p_end] = 0;
159524295Smckusick 	}
159624295Smckusick 	if (p_end >=0 && !p_ptrn_lines)
159724295Smckusick 	    fatal("No --- found in patch at line %d\n", pch_hunk_beg());
159824295Smckusick 
159924295Smckusick 	/* if there were omitted context lines, fill them in */
160024295Smckusick 	if (fillcnt) {
160124295Smckusick 	    while (fillcnt-- > 0) {
160224295Smckusick 		while (p_char[fillsrc] != ' ')
160324295Smckusick 		    fillsrc++;
1604*26977Svan 		if (p_line[fillsrc])
1605*26977Svan 		    p_line[filldst] = savestr (p_line[fillsrc]);
1606*26977Svan 		else
1607*26977Svan 		    p_line[filldst] = p_line[fillsrc];
160824295Smckusick 		p_char[filldst] = p_char[fillsrc];
160924295Smckusick 		p_len[filldst] = p_len[fillsrc];
161024295Smckusick 		fillsrc++; filldst++;
161124295Smckusick 	    }
1612*26977Svan 	    assert(filldst==p_end+1 || filldst==repl_beginning);
161324295Smckusick 	}
161424295Smckusick 	p_repl_lines = p_end - repl_beginning;
161524295Smckusick     }
161624294Smckusick     else {				/* normal diff--fake it up */
161724294Smckusick 	char hunk_type;
161824294Smckusick 	register int i;
161924294Smckusick 	LINENUM min, max;
162024294Smckusick 	long line_beginning = ftell(pfp);
162124294Smckusick 
162224294Smckusick 	p_context = 0;
162324294Smckusick 	ret = pgets(buf,sizeof buf, pfp);
162424294Smckusick 	p_input_line++;
162524294Smckusick 	if (ret == Nullch || !isdigit(*buf)) {
162624294Smckusick 	    next_intuit_at(line_beginning);
162724294Smckusick 	    return FALSE;
162824294Smckusick 	}
162924294Smckusick 	p_first = (LINENUM)atol(buf);
163024294Smckusick 	for (s=buf; isdigit(*s); s++) ;
163124294Smckusick 	if (*s == ',') {
163224294Smckusick 	    p_ptrn_lines = (LINENUM)atol(++s) - p_first + 1;
163324294Smckusick 	    while (isdigit(*s)) s++;
163424294Smckusick 	}
163524294Smckusick 	else
163624294Smckusick 	    p_ptrn_lines = (*s != 'a');
163724294Smckusick 	hunk_type = *s;
163824294Smckusick 	if (hunk_type == 'a')
163924294Smckusick 	    p_first++;			/* do append rather than insert */
164024294Smckusick 	min = (LINENUM)atol(++s);
164124294Smckusick 	for (; isdigit(*s); s++) ;
164224294Smckusick 	if (*s == ',')
164324294Smckusick 	    max = (LINENUM)atol(++s);
164424294Smckusick 	else
164524294Smckusick 	    max = min;
164624294Smckusick 	if (hunk_type == 'd')
164724294Smckusick 	    min++;
164824294Smckusick 	p_end = p_ptrn_lines + 1 + max - min + 1;
164924294Smckusick 	p_newfirst = min;
165024294Smckusick 	p_repl_lines = max - min + 1;
165124294Smckusick 	Sprintf(buf,"*** %d,%d\n", p_first, p_first + p_ptrn_lines - 1);
165224294Smckusick 	p_line[0] = savestr(buf);
165324294Smckusick 	p_char[0] = '*';
165424294Smckusick 	for (i=1; i<=p_ptrn_lines; i++) {
165524294Smckusick 	    ret = pgets(buf,sizeof buf, pfp);
165624294Smckusick 	    p_input_line++;
165724294Smckusick 	    if (ret == Nullch)
165824294Smckusick 		fatal("Unexpected end of file in patch at line %d.\n",
165924294Smckusick 		  p_input_line);
166024294Smckusick 	    if (*buf != '<')
166124294Smckusick 		fatal("< expected at line %d of patch.\n", p_input_line);
166224294Smckusick 	    p_line[i] = savestr(buf+2);
1663*26977Svan 	    if (p_line[i])
166425795Smckusick 		p_len[i] = strlen(p_line[i]);
1665*26977Svan 	    else
1666*26977Svan 		p_len[i] = 0;
166724294Smckusick 	    p_char[i] = '-';
166824294Smckusick 	}
166924294Smckusick 	if (hunk_type == 'c') {
167024294Smckusick 	    ret = pgets(buf,sizeof buf, pfp);
167124294Smckusick 	    p_input_line++;
167224294Smckusick 	    if (ret == Nullch)
167324294Smckusick 		fatal("Unexpected end of file in patch at line %d.\n",
167424294Smckusick 		    p_input_line);
167524294Smckusick 	    if (*buf != '-')
167624294Smckusick 		fatal("--- expected at line %d of patch.\n", p_input_line);
167724294Smckusick 	}
167824294Smckusick 	Sprintf(buf,"--- %d,%d\n",min,max);
167924294Smckusick 	p_line[i] = savestr(buf);
168024294Smckusick 	p_char[i] = '=';
168124294Smckusick 	for (i++; i<=p_end; i++) {
168224294Smckusick 	    ret = pgets(buf,sizeof buf, pfp);
168324294Smckusick 	    p_input_line++;
168424294Smckusick 	    if (ret == Nullch)
168524294Smckusick 		fatal("Unexpected end of file in patch at line %d.\n",
168624294Smckusick 		    p_input_line);
168724294Smckusick 	    if (*buf != '>')
168824294Smckusick 		fatal("> expected at line %d of patch.\n", p_input_line);
168924294Smckusick 	    p_line[i] = savestr(buf+2);
1690*26977Svan 	    /* set up p_len for strncmp() so we don't have to */
1691*26977Svan 	    /* assume null termination */
1692*26977Svan 	    if (p_line[i])
169325795Smckusick 		p_len[i] = strlen(p_line[i]);
1694*26977Svan 	    else
1695*26977Svan 		p_len[i] = 0;
169624294Smckusick 	    p_char[i] = '+';
169724294Smckusick 	}
169824294Smckusick     }
169924294Smckusick     if (reverse)			/* backwards patch? */
170024294Smckusick 	pch_swap();
170124294Smckusick #ifdef DEBUGGING
170224294Smckusick     if (debug & 2) {
170324294Smckusick 	int i;
170424294Smckusick 	char special;
170524294Smckusick 
170624294Smckusick 	for (i=0; i <= p_end; i++) {
170724294Smckusick 	    if (i == p_ptrn_lines)
170824294Smckusick 		special = '^';
170924294Smckusick 	    else
171024294Smckusick 		special = ' ';
171124294Smckusick 	    printf("%3d %c %c %s",i,p_char[i],special,p_line[i]);
171224294Smckusick 	}
171324294Smckusick     }
171424294Smckusick #endif
171524294Smckusick     return TRUE;
171624294Smckusick }
171724294Smckusick 
171824294Smckusick char *
171924294Smckusick pgets(bf,sz,fp)
172024294Smckusick char *bf;
172124294Smckusick int sz;
172224294Smckusick FILE *fp;
172324294Smckusick {
172424294Smckusick     char *ret = fgets(bf,sz,fp);
172524294Smckusick     register char *s;
172624294Smckusick     register int indent = 0;
172724294Smckusick 
172824294Smckusick     if (p_indent && ret != Nullch) {
172924294Smckusick 	for (s=buf; indent < p_indent && (*s == ' ' || *s == '\t'); s++) {
173024294Smckusick 	    if (*s == '\t')
173124294Smckusick 		indent += 8 - (indent % 7);
173224294Smckusick 	    else
173324294Smckusick 		indent++;
173424294Smckusick 	}
173524294Smckusick 	if (buf != s)
173624294Smckusick 	    Strcpy(buf,s);
173724294Smckusick     }
173824294Smckusick     return ret;
173924294Smckusick }
174024294Smckusick 
174124294Smckusick pch_swap()
174224294Smckusick {
174324294Smckusick     char *tp_line[MAXHUNKSIZE];		/* the text of the hunk */
174424294Smckusick     char tp_char[MAXHUNKSIZE];		/* +, -, and ! */
174524294Smckusick     int tp_len[MAXHUNKSIZE];		/* length of each line */
174624294Smckusick     register LINENUM i, n;
174724294Smckusick     bool blankline = FALSE;
174824294Smckusick     register char *s;
174924294Smckusick 
175024294Smckusick     i = p_first;
175124294Smckusick     p_first = p_newfirst;
175224294Smckusick     p_newfirst = i;
175324294Smckusick 
175424294Smckusick     /* make a scratch copy */
175524294Smckusick 
175624294Smckusick     for (i=0; i<=p_end; i++) {
175724294Smckusick 	tp_line[i] = p_line[i];
175824294Smckusick 	tp_char[i] = p_char[i];
175924294Smckusick 	tp_len[i] = p_len[i];
176024294Smckusick     }
176124294Smckusick 
176224294Smckusick     /* now turn the new into the old */
176324294Smckusick 
176424294Smckusick     i = p_ptrn_lines + 1;
176524294Smckusick     if (tp_char[i] == '\n') {		/* account for possible blank line */
176624294Smckusick 	blankline = TRUE;
176724294Smckusick 	i++;
176824294Smckusick     }
176924294Smckusick     for (n=0; i <= p_end; i++,n++) {
177024294Smckusick 	p_line[n] = tp_line[i];
177124294Smckusick 	p_char[n] = tp_char[i];
177224294Smckusick 	if (p_char[n] == '+')
177324294Smckusick 	    p_char[n] = '-';
177424294Smckusick 	p_len[n] = tp_len[i];
177524294Smckusick     }
177624294Smckusick     if (blankline) {
177724294Smckusick 	i = p_ptrn_lines + 1;
177824294Smckusick 	p_line[n] = tp_line[i];
177924294Smckusick 	p_char[n] = tp_char[i];
178024294Smckusick 	p_len[n] = tp_len[i];
178124294Smckusick 	n++;
178224294Smckusick     }
178324294Smckusick     assert(p_char[0] == '=');
178424294Smckusick     p_char[0] = '*';
178524294Smckusick     for (s=p_line[0]; *s; s++)
178624294Smckusick 	if (*s == '-')
178724294Smckusick 	    *s = '*';
178824294Smckusick 
178924294Smckusick     /* now turn the old into the new */
179024294Smckusick 
179124294Smckusick     assert(tp_char[0] == '*');
179224294Smckusick     tp_char[0] = '=';
179324294Smckusick     for (s=tp_line[0]; *s; s++)
179424294Smckusick 	if (*s == '*')
179524294Smckusick 	    *s = '-';
179624294Smckusick     for (i=0; n <= p_end; i++,n++) {
179724294Smckusick 	p_line[n] = tp_line[i];
179824294Smckusick 	p_char[n] = tp_char[i];
179924294Smckusick 	if (p_char[n] == '-')
180024294Smckusick 	    p_char[n] = '+';
180124294Smckusick 	p_len[n] = tp_len[i];
180224294Smckusick     }
180324294Smckusick     assert(i == p_ptrn_lines + 1);
180424294Smckusick     i = p_ptrn_lines;
180524294Smckusick     p_ptrn_lines = p_repl_lines;
180624294Smckusick     p_repl_lines = i;
180724294Smckusick }
180824294Smckusick 
180924294Smckusick LINENUM
181024294Smckusick pch_first()
181124294Smckusick {
181224294Smckusick     return p_first;
181324294Smckusick }
181424294Smckusick 
181524294Smckusick LINENUM
181624294Smckusick pch_ptrn_lines()
181724294Smckusick {
181824294Smckusick     return p_ptrn_lines;
181924294Smckusick }
182024294Smckusick 
182124294Smckusick LINENUM
182224294Smckusick pch_newfirst()
182324294Smckusick {
182424294Smckusick     return p_newfirst;
182524294Smckusick }
182624294Smckusick 
182724294Smckusick LINENUM
182824294Smckusick pch_repl_lines()
182924294Smckusick {
183024294Smckusick     return p_repl_lines;
183124294Smckusick }
183224294Smckusick 
183324294Smckusick LINENUM
183424294Smckusick pch_end()
183524294Smckusick {
183624294Smckusick     return p_end;
183724294Smckusick }
183824294Smckusick 
183924294Smckusick LINENUM
184024294Smckusick pch_context()
184124294Smckusick {
184224294Smckusick     return p_context;
184324294Smckusick }
184424294Smckusick 
184524294Smckusick pch_line_len(line)
184624294Smckusick LINENUM line;
184724294Smckusick {
184824294Smckusick     return p_len[line];
184924294Smckusick }
185024294Smckusick 
185124294Smckusick char
185224294Smckusick pch_char(line)
185324294Smckusick LINENUM line;
185424294Smckusick {
185524294Smckusick     return p_char[line];
185624294Smckusick }
185724294Smckusick 
185824294Smckusick char *
185924294Smckusick pfetch(line)
186024294Smckusick LINENUM line;
186124294Smckusick {
186224294Smckusick     return p_line[line];
186324294Smckusick }
186424294Smckusick 
186524294Smckusick LINENUM
186624294Smckusick pch_hunk_beg()
186724294Smckusick {
186824294Smckusick     return p_input_line - p_end - 1;
186924294Smckusick }
187024294Smckusick 
187124294Smckusick char *
187224294Smckusick savestr(s)
187324294Smckusick register char *s;
187424294Smckusick {
187524294Smckusick     register char  *rv,
187624294Smckusick                    *t;
187724294Smckusick 
187824294Smckusick     t = s;
187924294Smckusick     while (*t++);
188024294Smckusick     rv = malloc((MEM) (t - s));
188124294Smckusick     if (rv == NULL)
188224294Smckusick 	fatal ("patch: out of memory (savestr)\n");
188324294Smckusick     t = rv;
188424294Smckusick     while (*t++ = *s++);
188524294Smckusick     return rv;
188624294Smckusick }
188724294Smckusick 
188824294Smckusick my_exit(status)
188924294Smckusick int status;
189024294Smckusick {
189124294Smckusick     Unlink(TMPINNAME);
189224294Smckusick     Unlink(TMPOUTNAME);
189324294Smckusick     Unlink(TMPREJNAME);
189424294Smckusick     Unlink(TMPPATNAME);
189524294Smckusick     exit(status);
189624294Smckusick }
189724294Smckusick 
189824294Smckusick #ifdef lint
189924294Smckusick 
190024294Smckusick /*VARARGS ARGSUSED*/
190124294Smckusick say(pat) char *pat; { ; }
190224294Smckusick /*VARARGS ARGSUSED*/
190324294Smckusick fatal(pat) char *pat; { ; }
190424294Smckusick /*VARARGS ARGSUSED*/
190524294Smckusick ask(pat) char *pat; { ; }
190624294Smckusick 
190724294Smckusick #else lint
190824294Smckusick 
190924294Smckusick say(pat,arg1,arg2,arg3)
191024294Smckusick char *pat;
191124294Smckusick int arg1,arg2,arg3;
191224294Smckusick {
191324294Smckusick     fprintf(stderr,pat,arg1,arg2,arg3);
191424294Smckusick     Fflush(stderr);
191524294Smckusick }
191624294Smckusick 
191724294Smckusick fatal(pat,arg1,arg2,arg3)
191824294Smckusick char *pat;
191924294Smckusick int arg1,arg2,arg3;
192024294Smckusick {
192124294Smckusick     say(pat,arg1,arg2,arg3);
192224294Smckusick     my_exit(1);
192324294Smckusick }
192424294Smckusick 
192524294Smckusick ask(pat,arg1,arg2,arg3)
192624294Smckusick char *pat;
192724294Smckusick int arg1,arg2,arg3;
192824294Smckusick {
192924294Smckusick     int ttyfd = open("/dev/tty",2);
193024294Smckusick     int r;
193124294Smckusick 
193224294Smckusick     say(pat,arg1,arg2,arg3);
193324294Smckusick     if (ttyfd >= 0) {
193424294Smckusick 	r = read(ttyfd, buf, sizeof buf);
193524294Smckusick 	Close(ttyfd);
193624294Smckusick     }
193724294Smckusick     else
193824294Smckusick 	r = read(2, buf, sizeof buf);
193924294Smckusick     if (r <= 0)
194024294Smckusick 	buf[0] = 0;
194124294Smckusick }
194224294Smckusick #endif lint
194324294Smckusick 
194424294Smckusick bool
194524294Smckusick rev_in_string(string)
194624294Smckusick char *string;
194724294Smckusick {
194824294Smckusick     register char *s;
194924294Smckusick     register int patlen;
195024294Smckusick 
195124294Smckusick     if (revision == Nullch)
195224294Smckusick 	return TRUE;
195324294Smckusick     patlen = strlen(revision);
195424294Smckusick     for (s = string; *s; s++) {
195524294Smckusick 	if (isspace(*s) && strnEQ(s+1,revision,patlen) &&
195624294Smckusick 		isspace(s[patlen+1] )) {
195724294Smckusick 	    return TRUE;
195824294Smckusick 	}
195924294Smckusick     }
196024294Smckusick     return FALSE;
196124294Smckusick }
196224294Smckusick 
196324294Smckusick set_signals()
196424294Smckusick {
196524294Smckusick     /*NOSTRICT*/
196624294Smckusick     if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
196724294Smckusick 	Signal(SIGHUP, my_exit);
196824294Smckusick     /*NOSTRICT*/
196924294Smckusick     if (signal(SIGINT, SIG_IGN) != SIG_IGN)
197024294Smckusick 	Signal(SIGINT, my_exit);
197124294Smckusick }
197224294Smckusick 
197324294Smckusick ignore_signals()
197424294Smckusick {
197524294Smckusick     /*NOSTRICT*/
197624294Smckusick     Signal(SIGHUP, SIG_IGN);
197724294Smckusick     /*NOSTRICT*/
197824294Smckusick     Signal(SIGINT, SIG_IGN);
197924294Smckusick }
1980