1162Sroot # include	"../hdr/defines.h"
2162Sroot # include	"../hdr/had.h"
3*44892Sbostic # include	"pathnames.h"
4162Sroot 
5*44892Sbostic static char Sccsid[] = "@(#)delta.c	4.11	07/02/90";
6162Sroot USXALLOC();
7162Sroot 
815766Sralph # ifdef LOGDELTA
9*44892Sbostic char	*LogFile = _PATH_SCCSLOG;
1015766Sralph FILE	*Logf;
1115766Sralph # endif
1215766Sralph 
1315766Sralph char	Diffpgm[] = "/usr/local/bdiff";
14162Sroot FILE	*Diffin;
1530501Slepreau int	Debug = 0;
16162Sroot struct packet gpkt;
17162Sroot struct sid sid;
18162Sroot int	num_files;
19162Sroot char	had[26];
20162Sroot char	*ilist, *elist, *glist;
21162Sroot char	*Comments, *Mrs;
22162Sroot int	Domrs;
2315766Sralph int	verbosity;
24162Sroot int	Did_id;
25162Sroot long	Szqfile;
26162Sroot char	Pfilename[FILESIZE];
27162Sroot FILE	*Xiop;
28162Sroot int	Xcreate;
29162Sroot 
30162Sroot main(argc,argv)
31162Sroot int argc;
32162Sroot register char *argv[];
33162Sroot {
34162Sroot 	register int i;
35162Sroot 	register char *p;
36162Sroot 	char c;
37162Sroot 	int testmore;
38162Sroot 	extern delta();
39162Sroot 	extern int Fcnt;
40162Sroot 
41162Sroot 	Fflags = FTLEXIT | FTLMSG | FTLCLN;
42162Sroot 	for(i=1; i<argc; i++)
43162Sroot 		if(argv[i][0] == '-' && (c=argv[i][1])) {
44162Sroot 			p = &argv[i][2];
45162Sroot 			testmore = 0;
46162Sroot 			switch (c) {
47162Sroot 
48162Sroot 			case 'r':
49162Sroot 				if (!p[0]) {
50162Sroot 					argv[i] = 0;
51162Sroot 					continue;
52162Sroot 				}
53162Sroot 				chksid(sid_ab(p,&sid),&sid);
54162Sroot 				break;
55162Sroot 			case 'g':
56162Sroot 				glist = p;
57162Sroot 				break;
58162Sroot 			case 'y':
59162Sroot 				Comments = p;
60162Sroot 				break;
61162Sroot 			case 'm':
62162Sroot 				Mrs = p;
63162Sroot 				break;
64162Sroot 			case 'p':
65162Sroot 			case 'n':
66162Sroot 			case 's':
67162Sroot 				testmore++;
68162Sroot 				break;
69162Sroot 			default:
70162Sroot 				fatal("unknown key letter (cm1)");
71162Sroot 			}
72162Sroot 
73162Sroot 			if (testmore) {
74162Sroot 				testmore = 0;
7533423Sbostic 				if (*p) {
7633423Sbostic 					sprintf(Error, "value after %c arg (cm7)",c);
7733423Sbostic 					fatal(Error);
7833423Sbostic 				}
79162Sroot 			}
80162Sroot 			if (had[c - 'a']++)
81162Sroot 				fatal("key letter twice (cm2)");
82162Sroot 			argv[i] = 0;
83162Sroot 		}
84162Sroot 		else num_files++;
85162Sroot 
8615766Sralph 	if (num_files == 0)
87162Sroot 		fatal("missing file arg (cm3)");
88162Sroot 	if (!HADS)
89162Sroot 		verbosity = -1;
9015766Sralph # ifdef LOGDELTA
9115815Sralph 	Logf = fopen(LogFile, "a");
9215766Sralph # endif
93162Sroot 	setsig();
9430501Slepreau 	Fflags &= ~FTLEXIT;
9530501Slepreau 	Fflags |= FTLJMP;
96162Sroot 	for (i=1; i<argc; i++)
97162Sroot 		if (p=argv[i])
98162Sroot 			do_file(p,delta);
9915766Sralph # ifdef LOGDELTA
10015815Sralph 	if (Logf != NULL)
10115815Sralph 		fclose(Logf);
10215766Sralph # endif
103162Sroot 	exit(Fcnt ? 1 : 0);
104162Sroot }
105162Sroot 
106162Sroot 
107162Sroot delta(file)
10815766Sralph char *file;
109162Sroot {
11030501Slepreau 	static int first = 1;
111162Sroot 	register char *p;
112162Sroot 	int n, linenum;
113162Sroot 	char type;
114162Sroot 	register int ser;
115162Sroot 	extern char had_dir, had_standinp;
116162Sroot 	extern char *Sflags[];
117162Sroot 	char dfilename[FILESIZE];
118162Sroot 	char gfilename[FILESIZE];
119162Sroot 	char line[512];
120162Sroot 	FILE *gin;
121162Sroot 	struct stats stats;
122162Sroot 	struct pfile *pp;
123162Sroot 	int inserted, deleted, orig;
124162Sroot 	int newser;
125162Sroot 	int status;
126162Sroot 	int diffloop;
127162Sroot 	int difflim;
128162Sroot 
129162Sroot 	if (setjmp(Fjmp))
130162Sroot 		return;
131162Sroot 	if (first) {
132162Sroot 		first = 0;
133162Sroot 		dohist(file);
134162Sroot 	}
135162Sroot 	sinit(&gpkt,file,1);
136162Sroot 	if (lockit(auxf(gpkt.p_file,'z'),2,getpid()))
137162Sroot 		fatal("cannot create lock file (cm4)");
138162Sroot 	gpkt.p_reopen = 1;
139162Sroot 	gpkt.p_stdout = stdout;
140162Sroot 	copy(auxf(gpkt.p_file,'g'),gfilename);
141162Sroot 	gin = xfopen(gfilename,0);
142162Sroot 	pp = rdpfile(&gpkt,&sid);
143162Sroot 	gpkt.p_cutoff = pp->pf_date;
144162Sroot 	ilist = pp->pf_ilist;
145162Sroot 	elist = pp->pf_elist;
146162Sroot 
147162Sroot 	if (dodelt(&gpkt,&stats,0,0) == 0)
148162Sroot 		fmterr(&gpkt);
149162Sroot 	if ((ser = sidtoser(&pp->pf_gsid,&gpkt)) == 0 ||
150162Sroot 		sidtoser(&pp->pf_nsid,&gpkt))
151162Sroot 			fatal("invalid sid in p-file (de3)");
152162Sroot 	doie(&gpkt,ilist,elist,glist);
153162Sroot 	setup(&gpkt,ser);
154162Sroot 	finduser(&gpkt);
155162Sroot 	doflags(&gpkt);
15619941Ssam 	bcopy(&pp->pf_nsid,&gpkt.p_reqsid,sizeof(gpkt.p_reqsid));
157162Sroot 	permiss(&gpkt);
158162Sroot 	flushto(&gpkt,EUSERTXT,1);
159162Sroot 	gpkt.p_chkeof = 1;
160162Sroot 	copy(auxf(gpkt.p_file,'d'),dfilename);
161162Sroot 	gpkt.p_gout = xfcreat(dfilename,0444);
162162Sroot 	while(readmod(&gpkt)) {
163162Sroot 		chkid(gpkt.p_line);
164162Sroot 		fputs(gpkt.p_line,gpkt.p_gout);
165162Sroot 	}
166162Sroot 	fclose(gpkt.p_gout);
167162Sroot 	orig = gpkt.p_glnno;
168162Sroot 	gpkt.p_glnno = 0;
169162Sroot 	gpkt.p_verbose = verbosity;
170162Sroot 	Did_id = 0;
171162Sroot 	while (fgets(line,sizeof(line),gin) != NULL && !chkid(line))
172162Sroot 		;
173162Sroot 	fclose(gin);
174162Sroot 	if (gpkt.p_verbose && (num_files > 1 || had_dir || had_standinp))
175162Sroot 		fprintf(gpkt.p_stdout,"\n%s:\n",gpkt.p_file);
176162Sroot 	if (!Did_id)
177162Sroot 		if (Sflags[IDFLAG - 'a'])
178162Sroot 			fatal("no id keywords (cm6)");
179162Sroot 		else if (gpkt.p_verbose)
180162Sroot 			fprintf(stderr,"No id keywords (cm7)\n");
181162Sroot 
182162Sroot 	/*
183162Sroot 	The following while loop executes 'bdiff' on g-file and
184162Sroot 	d-file. If 'bdiff' fails (usually because segmentation
185162Sroot 	limit it is using is too large for 'diff'), it is
186162Sroot 	invoked again, with a lower segmentation limit.
187162Sroot 	*/
188162Sroot 	difflim = 3500;
189162Sroot 	diffloop = 0;
190162Sroot 	while (1) {
191162Sroot 		inserted = deleted = 0;
192162Sroot 		gpkt.p_glnno = 0;
193162Sroot 		gpkt.p_upd = 1;
194162Sroot 		gpkt.p_wrttn = 1;
195162Sroot 		getline(&gpkt);
196162Sroot 		gpkt.p_wrttn = 1;
197162Sroot 		newser = mkdelt(&gpkt,&pp->pf_nsid,&pp->pf_gsid,
198162Sroot 						diffloop,orig);
199162Sroot 		diffloop = 1;
200162Sroot 		flushto(&gpkt,EUSERTXT,0);
201162Sroot 		Diffin = dodiff(auxf(gpkt.p_file,'g'),dfilename,difflim);
202162Sroot 		while (n = getdiff(&type,&linenum)) {
203162Sroot 			if (type == INS) {
20430501Slepreau 				inserted += n;
205162Sroot 				insert(&gpkt,linenum,n,newser);
206162Sroot 			}
207162Sroot 			else {
20830501Slepreau 				deleted += n;
209162Sroot 				delete(&gpkt,linenum,n,newser);
210162Sroot 			}
211162Sroot 		}
212162Sroot 		fclose(Diffin);
213162Sroot 		if (gpkt.p_iop)
214162Sroot 			while (readmod(&gpkt))
215162Sroot 				;
216162Sroot 		wait(&status);
217162Sroot 		if (status) {		/* diff failed */
218162Sroot 			/*
219162Sroot 			Check top byte (exit code of child).
220162Sroot 			*/
22133423Sbostic 			if (((status >> 8) & 0377) == 32) { /* 'execl' failed */
22233423Sbostic 				sprintf(Error, "cannot execute '%s' (de12)", Diffpgm);
22333423Sbostic 				fatal(Error);
22433423Sbostic 			}
225162Sroot 			/*
226162Sroot 			Re-try.
227162Sroot 			*/
22832771Sbostic 			if (difflim -= 500) {	/* reduce segmentation */
229162Sroot 				fprintf(stderr,
230162Sroot 			"'%s' failed, re-trying, segmentation = %d (de13)\n",
231162Sroot 					Diffpgm,difflim);
232162Sroot 				fclose(Xiop);	/* set up */
233162Sroot 				Xiop = 0;	/* for new x-file */
234162Sroot 				Xcreate = 0;
235162Sroot 				/*
236162Sroot 				Re-open s-file.
237162Sroot 				*/
238162Sroot 				gpkt.p_iop = xfopen(gpkt.p_file,0);
239162Sroot 				setbuf(gpkt.p_iop,gpkt.p_buf);
240162Sroot 				/*
241162Sroot 				Reset counters.
242162Sroot 				*/
243162Sroot 				gpkt.p_slnno = 0;
244162Sroot 				gpkt.p_ihash = 0;
245162Sroot 				gpkt.p_chash = 0;
246162Sroot 				gpkt.p_nhash = 0;
247162Sroot 				gpkt.p_keep = 0;
248162Sroot 			}
249162Sroot 			else
250162Sroot 				/* tried up to 500 lines, can't go on */
251162Sroot 				fatal("diff failed (de4)");
252162Sroot 		}
253162Sroot 		else {		/* no need to try again, worked */
254162Sroot 			break;			/* exit while loop */
255162Sroot 		}
256162Sroot 	}
257162Sroot 	unlink(dfilename);
258162Sroot 	stats.s_ins = inserted;
259162Sroot 	stats.s_del = deleted;
260162Sroot 	stats.s_unc = orig - deleted;
261162Sroot 	if (gpkt.p_verbose) {
262162Sroot 		fprintf(gpkt.p_stdout,"%u inserted\n",stats.s_ins);
263162Sroot 		fprintf(gpkt.p_stdout,"%u deleted\n",stats.s_del);
264162Sroot 		fprintf(gpkt.p_stdout,"%u unchanged\n",stats.s_unc);
265162Sroot 	}
266162Sroot 	flushline(&gpkt,&stats);
267162Sroot 	rename(auxf(gpkt.p_file,'x'),gpkt.p_file);
268162Sroot 	if (Szqfile)
269162Sroot 		rename(auxf(&gpkt.p_file,'q'),Pfilename);
270162Sroot 	else {
271162Sroot 		xunlink(Pfilename);
272162Sroot 		xunlink(auxf(&gpkt.p_file,'q'));
273162Sroot 	}
274162Sroot 	clean_up(0);
275162Sroot 	if (!HADN) {
276162Sroot 		setuid(getuid());
277162Sroot 		unlink(gfilename);
278162Sroot 	}
279162Sroot }
280162Sroot 
281162Sroot 
282162Sroot mkdelt(pkt,sp,osp,diffloop,orig_nlines)
283162Sroot struct packet *pkt;
284162Sroot struct sid *sp, *osp;
285162Sroot int diffloop;
286162Sroot int orig_nlines;
287162Sroot {
288162Sroot 	extern long Timenow;
289162Sroot 	struct deltab dt;
290162Sroot 	char str[128];
291162Sroot 	int newser;
292162Sroot 	extern char *Sflags[];
293162Sroot 	register char *p;
294162Sroot 	int ser_inc, opred, nulldel;
295162Sroot 
296162Sroot 	if (!diffloop && pkt->p_verbose) {
297162Sroot 		sid_ba(sp,str);
298162Sroot 		fprintf(pkt->p_stdout,"%s\n",str);
299162Sroot 	}
30033423Sbostic 	sprintf(str,"%c%c00000\n",CTLCHAR,HEAD);
30133423Sbostic 	putline(pkt,str);
302162Sroot 	newstats(pkt,str,"0");
30319941Ssam 	bcopy(sp,&dt.d_sid,sizeof(dt.d_sid));
304162Sroot 
305162Sroot 	/*
306162Sroot 	Check if 'null' deltas should be inserted
307162Sroot 	(only if 'null' flag is in file and
308162Sroot 	releases are being skipped) and set
309162Sroot 	'nulldel' indicator appropriately.
310162Sroot 	*/
311162Sroot 	if (Sflags[NULLFLAG - 'a'] && (sp->s_rel > osp->s_rel + 1) &&
312162Sroot 			!sp->s_br && !sp->s_seq &&
313162Sroot 			!osp->s_br && !osp->s_seq)
314162Sroot 		nulldel = 1;
315162Sroot 	else
316162Sroot 		nulldel = 0;
317162Sroot 	/*
318162Sroot 	Calculate how many serial numbers are needed.
319162Sroot 	*/
320162Sroot 	if (nulldel)
321162Sroot 		ser_inc = sp->s_rel - osp->s_rel;
322162Sroot 	else
323162Sroot 		ser_inc = 1;
324162Sroot 	/*
325162Sroot 	Find serial number of the new delta.
326162Sroot 	*/
327162Sroot 	newser = dt.d_serial = maxser(pkt) + ser_inc;
328162Sroot 	/*
329162Sroot 	Find old predecessor's serial number.
330162Sroot 	*/
331162Sroot 	opred = sidtoser(osp,pkt);
332162Sroot 	if (nulldel)
333162Sroot 		dt.d_pred = newser - 1;	/* set predecessor to 'null' delta */
334162Sroot 	else
335162Sroot 		dt.d_pred = opred;
336162Sroot 	dt.d_datetime = Timenow;
3376173Seric 	substr(logname(),dt.d_pgmr,0,LNLNAM);
338162Sroot 	dt.d_type = 'D';
339162Sroot 	del_ba(&dt,str);
340162Sroot 	putline(pkt,str);
34115766Sralph # ifdef LOGDELTA
34215815Sralph 	if (Logf != NULL) {
34315815Sralph 		if (pkt->p_file[0] != '/') {
34415815Sralph 			char buf[1024];
34515766Sralph 
34615815Sralph 			if (getwd(buf) != NULL)
34715815Sralph 				fprintf(Logf, "%s/", buf);
34815815Sralph 		}
34915815Sralph 		fprintf(Logf, "%s:\n%s%s\n", pkt->p_file, str + 5, Comments);
35015766Sralph 	}
35115766Sralph # endif
352162Sroot 	if (ilist)
353162Sroot 		mkixg(pkt,INCLUSER,INCLUDE);
354162Sroot 	if (elist)
355162Sroot 		mkixg(pkt,EXCLUSER,EXCLUDE);
356162Sroot 	if (glist)
357162Sroot 		mkixg(pkt,IGNRUSER,IGNORE);
358162Sroot 	if (Mrs) {
359162Sroot 		if (!(p = Sflags[VALFLAG - 'a']))
360162Sroot 			fatal("MRs not allowed (de8)");
361162Sroot 		if (*p && !diffloop && valmrs(pkt,p))
362162Sroot 			fatal("invalid MRs (de9)");
363162Sroot 		putmrs(pkt);
364162Sroot 	}
365162Sroot 	else if (Sflags[VALFLAG - 'a'])
366162Sroot 		fatal("MRs required (de10)");
36733423Sbostic 	sprintf(str,"%c%c ",CTLCHAR,COMMENTS);
36833423Sbostic 	putline(pkt,str);
369162Sroot 	putline(pkt,Comments);
370162Sroot 	putline(pkt,"\n");
37133423Sbostic 	sprintf(str,CTLSTR,CTLCHAR,EDELTAB);
37233423Sbostic 	putline(pkt,str);
373162Sroot 	if (nulldel)			/* insert 'null' deltas */
374162Sroot 		while (--ser_inc) {
37533423Sbostic 			sprintf(str,"%c%c %s/%s/%05u\n", CTLCHAR, STATS, "00000", "00000", orig_nlines);
37633423Sbostic 			putline(pkt,str);
37732771Sbostic 			dt.d_sid.s_rel -= 1;
37832771Sbostic 			dt.d_serial -= 1;
379162Sroot 			if (ser_inc != 1)
38032771Sbostic 				dt.d_pred -= 1;
381162Sroot 			else
382162Sroot 				dt.d_pred = opred;	/* point to old pred */
383162Sroot 			del_ba(&dt,str);
384162Sroot 			putline(pkt,str);
38533423Sbostic 			sprintf(str,"%c%c ",CTLCHAR,COMMENTS);
38633423Sbostic 			putline(pkt,str);
387162Sroot 			putline(pkt,"AUTO NULL DELTA\n");
38833423Sbostic 			sprintf(str,CTLSTR,CTLCHAR,EDELTAB);
38933423Sbostic 			putline(pkt,str);
390162Sroot 		}
391162Sroot 	return(newser);
392162Sroot }
393162Sroot 
394162Sroot 
395162Sroot mkixg(pkt,reason,ch)
396162Sroot struct packet *pkt;
397162Sroot int reason;
398162Sroot char ch;
399162Sroot {
400162Sroot 	int n;
401162Sroot 	char str[512];
402162Sroot 
40333423Sbostic 	sprintf(str,"%c%c",CTLCHAR,ch);
40433423Sbostic 	putline(pkt,str);
405162Sroot 	for (n = maxser(pkt); n; n--) {
40633423Sbostic 		if (pkt->p_apply[n].a_reason == reason) {
40733423Sbostic 			sprintf(str," %u",n);
40833423Sbostic 			putline(pkt,str);
40933423Sbostic 		}
410162Sroot 	}
411162Sroot 	putline(pkt,"\n");
412162Sroot }
413162Sroot 
414162Sroot 
415162Sroot putmrs(pkt)
416162Sroot struct packet *pkt;
417162Sroot {
418162Sroot 	register char **argv;
419162Sroot 	char str[64];
420162Sroot 	extern char *Varg[];
421162Sroot 
42233423Sbostic 	for (argv = &Varg[VSTART]; *argv; argv++) {
42333423Sbostic 		sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv);
42433423Sbostic 		putline(pkt,str);
42533423Sbostic 	}
426162Sroot }
427162Sroot 
428162Sroot 
429162Sroot rdpfile(pkt,sp)
430162Sroot register struct packet *pkt;
431162Sroot struct sid *sp;
432162Sroot {
433162Sroot 	char *user;
434162Sroot 	struct pfile pf;
435162Sroot 	static struct pfile goodpf;
436162Sroot 	char line[512];
4376636Ssam 	int cnt, root;
438162Sroot 	FILE *in, *out;
439162Sroot 
440162Sroot 	cnt = -1;
441162Sroot 	user = logname();
44219941Ssam 	bzero(&goodpf,sizeof(goodpf));
443162Sroot 	in = xfopen(auxf(pkt->p_file,'p'),0);
444162Sroot 	out = xfcreat(auxf(pkt->p_file,'q'),0644);
4456636Ssam 	root = getuid() == 0;
446162Sroot 	while (fgets(line,sizeof(line),in) != NULL) {
447162Sroot 		pf_ab(line,&pf,1);
4486636Ssam 		if (root || equal(pf.pf_user,user)) {
449162Sroot 			if (sp->s_rel == 0) {
450162Sroot 				if (++cnt) {
451162Sroot 					fclose(out);
452162Sroot 					fclose(in);
453162Sroot 					fatal("missing -r argument (de1)");
454162Sroot 				}
45519941Ssam 				bcopy(&pf,&goodpf,sizeof(pf));
456162Sroot 				continue;
457162Sroot 			}
458162Sroot 			else if (sp->s_rel == pf.pf_gsid.s_rel &&
459162Sroot 				sp->s_lev == pf.pf_gsid.s_lev &&
460162Sroot 				sp->s_br == pf.pf_gsid.s_br &&
461162Sroot 				sp->s_seq == pf.pf_gsid.s_seq) {
46219941Ssam 					bcopy(&pf,&goodpf,sizeof(pf));
463162Sroot 					continue;
464162Sroot 			}
465162Sroot 		}
466162Sroot 		fputs(line,out);
467162Sroot 	}
468162Sroot 	fflush(out);
469162Sroot 	fstat(fileno(out),&Statbuf);
470162Sroot 	Szqfile = Statbuf.st_size;
471162Sroot 	copy(auxf(pkt->p_file,'p'),Pfilename);
472162Sroot 	fclose(out);
473162Sroot 	fclose(in);
474162Sroot 	if (!goodpf.pf_user[0])
475162Sroot 		fatal("not in p-file (de2)");
476162Sroot 	return(&goodpf);
477162Sroot }
478162Sroot 
479162Sroot 
480162Sroot dodiff(newf,oldf,difflim)
481162Sroot char *newf, *oldf;
482162Sroot int difflim;
483162Sroot {
484162Sroot 	register int i;
485162Sroot 	int pfd[2];
486162Sroot 	FILE *iop;
487162Sroot 	extern char Diffpgm[];
488162Sroot 	char num[10];
489162Sroot 
490162Sroot 	xpipe(pfd);
491162Sroot 	if ((i = fork()) < 0) {
492162Sroot 		close(pfd[0]);
493162Sroot 		close(pfd[1]);
494162Sroot 		fatal("cannot fork, try again (de11)");
495162Sroot 	}
496162Sroot 	else if (i == 0) {
497162Sroot 		close(pfd[0]);
49819941Ssam 		dup2(pfd[1], 1);
49919941Ssam 		if (pfd[1] != 1)
50019941Ssam 			close(pfd[1]);
50119941Ssam 		for (i = getdtablesize(); i > 4; i--)
502162Sroot 			close(i);
503162Sroot 		sprintf(num,"%d",difflim);
504162Sroot 		execl(Diffpgm,Diffpgm,oldf,newf,num,"-s",0);
505162Sroot 		close(1);
506162Sroot 		exit(32);	/* tell parent that 'execl' failed */
507162Sroot 	}
508162Sroot 	else {
509162Sroot 		close(pfd[1]);
51019941Ssam 		iop = fdopen(pfd[0],"r");
511162Sroot 		return(iop);
512162Sroot 	}
513162Sroot }
514162Sroot 
515162Sroot 
516162Sroot getdiff(type,plinenum)
517162Sroot register char *type;
518162Sroot register int *plinenum;
519162Sroot {
520162Sroot 	char line[512];
521162Sroot 	register char *p;
522162Sroot 	int num_lines;
523162Sroot 	static int chg_num, chg_ln;
524162Sroot 	int lowline, highline;
525162Sroot 
52619941Ssam 	if ((p = rddiff(line,sizeof (line))) == NULL)
527162Sroot 		return(0);
528162Sroot 
529162Sroot 	if (*p == '-') {
530162Sroot 		*type = INS;
531162Sroot 		*plinenum = chg_ln;
532162Sroot 		num_lines = chg_num;
533162Sroot 	}
534162Sroot 	else {
535162Sroot 		p = linerange(p,&lowline,&highline);
536162Sroot 		*plinenum = lowline;
537162Sroot 
538162Sroot 		switch(*p++) {
539162Sroot 		case 'd':
540162Sroot 			num_lines = highline - lowline + 1;
541162Sroot 			*type = DEL;
5422167Seric 			skiplines(line,num_lines);
543162Sroot 			break;
544162Sroot 
545162Sroot 		case 'a':
546162Sroot 			linerange(p,&lowline,&highline);
547162Sroot 			num_lines = highline - lowline + 1;
548162Sroot 			*type = INS;
549162Sroot 			break;
550162Sroot 
551162Sroot 		case 'c':
552162Sroot 			chg_ln = lowline;
553162Sroot 			num_lines = highline - lowline + 1;
554162Sroot 			linerange(p,&lowline,&highline);
555162Sroot 			chg_num = highline - lowline + 1;
556162Sroot 			*type = DEL;
5572167Seric 			skiplines(line,num_lines);
558162Sroot 			break;
559162Sroot 		}
560162Sroot 	}
561162Sroot 
562162Sroot 	return(num_lines);
563162Sroot }
564162Sroot 
565162Sroot 
566162Sroot insert(pkt,linenum,n,ser)
567162Sroot register struct packet *pkt;
568162Sroot register int linenum;
569162Sroot register int n;
570162Sroot int ser;
571162Sroot {
572162Sroot 	char str[512];
573162Sroot 
574162Sroot 	after(pkt,linenum);
57533423Sbostic 	sprintf(str,"%c%c %u\n",CTLCHAR,INS,ser);
57633423Sbostic 	putline(pkt,str);
577162Sroot 	for (++n; --n; ) {
578162Sroot 		rddiff(str,sizeof(str));
579162Sroot 		putline(pkt,&str[2]);
580162Sroot 	}
58133423Sbostic 	sprintf(str,"%c%c %u\n",CTLCHAR,END,ser);
58233423Sbostic 	putline(pkt,str);
583162Sroot }
584162Sroot 
585162Sroot 
586162Sroot delete(pkt,linenum,n,ser)
587162Sroot register struct packet *pkt;
588162Sroot register int linenum;
589162Sroot int n;
590162Sroot register int ser;
591162Sroot {
592162Sroot 	char str[512];
593162Sroot 
594162Sroot 	before(pkt,linenum);
59533423Sbostic 	sprintf(str,"%c%c %u\n",CTLCHAR,DEL,ser);
59633423Sbostic 	putline(pkt,str);
597162Sroot 	after(pkt,linenum + n - 1);
59833423Sbostic 	sprintf(str,"%c%c %u\n",CTLCHAR,END,ser);
59933423Sbostic 	putline(pkt,str);
600162Sroot }
601162Sroot 
602162Sroot 
603162Sroot after(pkt,n)
604162Sroot register struct packet *pkt;
605162Sroot register int n;
606162Sroot {
607162Sroot 	before(pkt,n);
608162Sroot 	if (pkt->p_glnno == n)
609162Sroot 		putline(pkt,0);
610162Sroot }
611162Sroot 
612162Sroot 
613162Sroot before(pkt,n)
614162Sroot register struct packet *pkt;
615162Sroot register int n;
616162Sroot {
617162Sroot 	while (pkt->p_glnno < n) {
618162Sroot 		if (!readmod(pkt))
619162Sroot 			break;
620162Sroot 	}
621162Sroot }
622162Sroot 
623162Sroot 
624162Sroot linerange(cp,low,high)
625162Sroot register char *cp;
626162Sroot register int *low, *high;
627162Sroot {
628162Sroot 	cp = satoi(cp,low);
629162Sroot 	if (*cp == ',')
630162Sroot 		cp = satoi(++cp,high);
631162Sroot 	else
632162Sroot 		*high = *low;
633162Sroot 
634162Sroot 	return(cp);
635162Sroot }
636162Sroot 
637162Sroot 
638162Sroot skiplines(lp,num)
639162Sroot register char *lp;
640162Sroot register int num;
641162Sroot {
642162Sroot 	for (++num;--num;)
643162Sroot 		rddiff(lp,512);
644162Sroot }
645162Sroot 
646162Sroot 
647162Sroot rddiff(s,n)
648162Sroot register char *s;
649162Sroot register int n;
650162Sroot {
651162Sroot 	register int r;
652162Sroot 
653162Sroot 	if ((r = fgets(s,n,Diffin)) != NULL && HADP)
654162Sroot 		fputs(s,gpkt.p_stdout);
655162Sroot 	return(r);
656162Sroot }
657162Sroot 
658162Sroot 
659162Sroot enter(pkt,ch,n,sidp)
660162Sroot struct packet *pkt;
661162Sroot char ch;
662162Sroot int n;
663162Sroot struct sid *sidp;
664162Sroot {
665162Sroot 	char str[32];
666162Sroot 	register struct apply *ap;
667162Sroot 
668162Sroot 	sid_ba(sidp,str);
669162Sroot 	ap = &pkt->p_apply[n];
670162Sroot 	if (pkt->p_cutoff > pkt->p_idel[n].i_datetime)
671162Sroot 		switch(ap->a_code) {
672162Sroot 
673162Sroot 		case EMPTY:
674162Sroot 			switch (ch) {
675162Sroot 			case INCLUDE:
676162Sroot 				condset(ap,APPLY,INCLUSER);
677162Sroot 				break;
678162Sroot 			case EXCLUDE:
679162Sroot 				condset(ap,NOAPPLY,EXCLUSER);
680162Sroot 				break;
681162Sroot 			case IGNORE:
682162Sroot 				condset(ap,EMPTY,IGNRUSER);
683162Sroot 				break;
684162Sroot 			}
685162Sroot 			break;
686162Sroot 		case APPLY:
687162Sroot 			fatal("internal error in delta/enter() (de5)");
688162Sroot 			break;
689162Sroot 		case NOAPPLY:
690162Sroot 			fatal("internal error in delta/enter() (de6)");
691162Sroot 			break;
692162Sroot 		default:
693162Sroot 			fatal("internal error in delta/enter() (de7)");
694162Sroot 			break;
695162Sroot 		}
696162Sroot }
697162Sroot 
698162Sroot 
699162Sroot escdodelt()	/* dummy routine for dodelt() */
700162Sroot {
701162Sroot }
702162Sroot 
703162Sroot 
704162Sroot clean_up(n)
705162Sroot {
706162Sroot 	if (gpkt.p_file[0])
707162Sroot 		unlockit(auxf(gpkt.p_file,'z'),getpid());
708162Sroot 	xrm(&gpkt);
709162Sroot 	xfreeall();
710162Sroot }
711