1162Sroot # include	"../hdr/defines.h"
2162Sroot # include	"../hdr/had.h"
3162Sroot 
4*6636Ssam SCCSID(@(#)delta.c	4.4);
5162Sroot USXALLOC();
6162Sroot 
7162Sroot char	Diffpgm[]	"/usr/local/bdiff";
8162Sroot FILE	*Diffin;
9162Sroot int	Debug	0;
10162Sroot struct packet gpkt;
11162Sroot struct sid sid;
12162Sroot int	num_files;
13162Sroot char	had[26];
14162Sroot char	*ilist, *elist, *glist;
15162Sroot char	*Comments, *Mrs;
16162Sroot int	Domrs;
17162Sroot int verbosity;
18162Sroot int	Did_id;
19162Sroot long	Szqfile;
20162Sroot char	Pfilename[FILESIZE];
21162Sroot FILE	*Xiop;
22162Sroot int	Xcreate;
23162Sroot 
24162Sroot main(argc,argv)
25162Sroot int argc;
26162Sroot register char *argv[];
27162Sroot {
28162Sroot 	register int i;
29162Sroot 	register char *p;
30162Sroot 	char c;
31162Sroot 	int testmore;
32162Sroot 	extern delta();
33162Sroot 	extern int Fcnt;
34162Sroot 
35162Sroot 	Fflags = FTLEXIT | FTLMSG | FTLCLN;
36162Sroot 	for(i=1; i<argc; i++)
37162Sroot 		if(argv[i][0] == '-' && (c=argv[i][1])) {
38162Sroot 			p = &argv[i][2];
39162Sroot 			testmore = 0;
40162Sroot 			switch (c) {
41162Sroot 
42162Sroot 			case 'r':
43162Sroot 				if (!p[0]) {
44162Sroot 					argv[i] = 0;
45162Sroot 					continue;
46162Sroot 				}
47162Sroot 				chksid(sid_ab(p,&sid),&sid);
48162Sroot 				break;
49162Sroot 			case 'g':
50162Sroot 				glist = p;
51162Sroot 				break;
52162Sroot 			case 'y':
53162Sroot 				Comments = p;
54162Sroot 				break;
55162Sroot 			case 'm':
56162Sroot 				Mrs = p;
57162Sroot 				break;
58162Sroot 			case 'p':
59162Sroot 			case 'n':
60162Sroot 			case 's':
61162Sroot 				testmore++;
62162Sroot 				break;
63162Sroot 			default:
64162Sroot 				fatal("unknown key letter (cm1)");
65162Sroot 			}
66162Sroot 
67162Sroot 			if (testmore) {
68162Sroot 				testmore = 0;
69162Sroot 				if (*p)
70162Sroot 					fatal(sprintf(Error,
71162Sroot 					  "value after %c arg (cm7)",c));
72162Sroot 			}
73162Sroot 			if (had[c - 'a']++)
74162Sroot 				fatal("key letter twice (cm2)");
75162Sroot 			argv[i] = 0;
76162Sroot 		}
77162Sroot 		else num_files++;
78162Sroot 
79162Sroot 	if(num_files == 0)
80162Sroot 		fatal("missing file arg (cm3)");
81162Sroot 	if (!HADS)
82162Sroot 		verbosity = -1;
83162Sroot 	setsig();
84162Sroot 	Fflags =& ~FTLEXIT;
85162Sroot 	Fflags =| FTLJMP;
86162Sroot 	for (i=1; i<argc; i++)
87162Sroot 		if (p=argv[i])
88162Sroot 			do_file(p,delta);
89162Sroot 	exit(Fcnt ? 1 : 0);
90162Sroot }
91162Sroot 
92162Sroot 
93162Sroot delta(file)
94162Sroot {
95162Sroot 	static int first 1;
96162Sroot 	register char *p;
97162Sroot 	int n, linenum;
98162Sroot 	char type;
99162Sroot 	register int ser;
100162Sroot 	extern char had_dir, had_standinp;
101162Sroot 	extern char *Sflags[];
102162Sroot 	char dfilename[FILESIZE];
103162Sroot 	char gfilename[FILESIZE];
104162Sroot 	char line[512];
105162Sroot 	FILE *gin;
106162Sroot 	struct stats stats;
107162Sroot 	struct pfile *pp;
108162Sroot 	int inserted, deleted, orig;
109162Sroot 	int newser;
110162Sroot 	int status;
111162Sroot 	int diffloop;
112162Sroot 	int difflim;
113162Sroot 
114162Sroot 	if (setjmp(Fjmp))
115162Sroot 		return;
116162Sroot 	if (first) {
117162Sroot 		first = 0;
118162Sroot 		dohist(file);
119162Sroot 	}
120162Sroot 	sinit(&gpkt,file,1);
121162Sroot 	if (lockit(auxf(gpkt.p_file,'z'),2,getpid()))
122162Sroot 		fatal("cannot create lock file (cm4)");
123162Sroot 	gpkt.p_reopen = 1;
124162Sroot 	gpkt.p_stdout = stdout;
125162Sroot 	copy(auxf(gpkt.p_file,'g'),gfilename);
126162Sroot 	gin = xfopen(gfilename,0);
127162Sroot 	pp = rdpfile(&gpkt,&sid);
128162Sroot 	gpkt.p_cutoff = pp->pf_date;
129162Sroot 	ilist = pp->pf_ilist;
130162Sroot 	elist = pp->pf_elist;
131162Sroot 
132162Sroot 	if (dodelt(&gpkt,&stats,0,0) == 0)
133162Sroot 		fmterr(&gpkt);
134162Sroot 	if ((ser = sidtoser(&pp->pf_gsid,&gpkt)) == 0 ||
135162Sroot 		sidtoser(&pp->pf_nsid,&gpkt))
136162Sroot 			fatal("invalid sid in p-file (de3)");
137162Sroot 	doie(&gpkt,ilist,elist,glist);
138162Sroot 	setup(&gpkt,ser);
139162Sroot 	finduser(&gpkt);
140162Sroot 	doflags(&gpkt);
141162Sroot 	move(&pp->pf_nsid,&gpkt.p_reqsid,sizeof(gpkt.p_reqsid));
142162Sroot 	permiss(&gpkt);
143162Sroot 	flushto(&gpkt,EUSERTXT,1);
144162Sroot 	gpkt.p_chkeof = 1;
145162Sroot 	copy(auxf(gpkt.p_file,'d'),dfilename);
146162Sroot 	gpkt.p_gout = xfcreat(dfilename,0444);
147162Sroot 	while(readmod(&gpkt)) {
148162Sroot 		chkid(gpkt.p_line);
149162Sroot 		fputs(gpkt.p_line,gpkt.p_gout);
150162Sroot 	}
151162Sroot 	fclose(gpkt.p_gout);
152162Sroot 	orig = gpkt.p_glnno;
153162Sroot 	gpkt.p_glnno = 0;
154162Sroot 	gpkt.p_verbose = verbosity;
155162Sroot 	Did_id = 0;
156162Sroot 	while (fgets(line,sizeof(line),gin) != NULL && !chkid(line))
157162Sroot 		;
158162Sroot 	fclose(gin);
159162Sroot 	if (gpkt.p_verbose && (num_files > 1 || had_dir || had_standinp))
160162Sroot 		fprintf(gpkt.p_stdout,"\n%s:\n",gpkt.p_file);
161162Sroot 	if (!Did_id)
162162Sroot 		if (Sflags[IDFLAG - 'a'])
163162Sroot 			fatal("no id keywords (cm6)");
164162Sroot 		else if (gpkt.p_verbose)
165162Sroot 			fprintf(stderr,"No id keywords (cm7)\n");
166162Sroot 
167162Sroot 	/*
168162Sroot 	The following while loop executes 'bdiff' on g-file and
169162Sroot 	d-file. If 'bdiff' fails (usually because segmentation
170162Sroot 	limit it is using is too large for 'diff'), it is
171162Sroot 	invoked again, with a lower segmentation limit.
172162Sroot 	*/
173162Sroot 	difflim = 3500;
174162Sroot 	diffloop = 0;
175162Sroot 	while (1) {
176162Sroot 		inserted = deleted = 0;
177162Sroot 		gpkt.p_glnno = 0;
178162Sroot 		gpkt.p_upd = 1;
179162Sroot 		gpkt.p_wrttn = 1;
180162Sroot 		getline(&gpkt);
181162Sroot 		gpkt.p_wrttn = 1;
182162Sroot 		newser = mkdelt(&gpkt,&pp->pf_nsid,&pp->pf_gsid,
183162Sroot 						diffloop,orig);
184162Sroot 		diffloop = 1;
185162Sroot 		flushto(&gpkt,EUSERTXT,0);
186162Sroot 		Diffin = dodiff(auxf(gpkt.p_file,'g'),dfilename,difflim);
187162Sroot 		while (n = getdiff(&type,&linenum)) {
188162Sroot 			if (type == INS) {
189162Sroot 				inserted =+ n;
190162Sroot 				insert(&gpkt,linenum,n,newser);
191162Sroot 			}
192162Sroot 			else {
193162Sroot 				deleted =+ n;
194162Sroot 				delete(&gpkt,linenum,n,newser);
195162Sroot 			}
196162Sroot 		}
197162Sroot 		fclose(Diffin);
198162Sroot 		if (gpkt.p_iop)
199162Sroot 			while (readmod(&gpkt))
200162Sroot 				;
201162Sroot 		wait(&status);
202162Sroot 		if (status) {		/* diff failed */
203162Sroot 			/*
204162Sroot 			Check top byte (exit code of child).
205162Sroot 			*/
206162Sroot 			if (((status >> 8) & 0377) == 32) /* 'execl' failed */
207162Sroot 				fatal(sprintf(Error,
208162Sroot 						"cannot execute '%s' (de12)",
209162Sroot 						Diffpgm));
210162Sroot 			/*
211162Sroot 			Re-try.
212162Sroot 			*/
213162Sroot 			if (difflim =- 500) {	/* reduce segmentation */
214162Sroot 				fprintf(stderr,
215162Sroot 			"'%s' failed, re-trying, segmentation = %d (de13)\n",
216162Sroot 					Diffpgm,difflim);
217162Sroot 				fclose(Xiop);	/* set up */
218162Sroot 				Xiop = 0;	/* for new x-file */
219162Sroot 				Xcreate = 0;
220162Sroot 				/*
221162Sroot 				Re-open s-file.
222162Sroot 				*/
223162Sroot 				gpkt.p_iop = xfopen(gpkt.p_file,0);
224162Sroot 				setbuf(gpkt.p_iop,gpkt.p_buf);
225162Sroot 				/*
226162Sroot 				Reset counters.
227162Sroot 				*/
228162Sroot 				gpkt.p_slnno = 0;
229162Sroot 				gpkt.p_ihash = 0;
230162Sroot 				gpkt.p_chash = 0;
231162Sroot 				gpkt.p_nhash = 0;
232162Sroot 				gpkt.p_keep = 0;
233162Sroot 			}
234162Sroot 			else
235162Sroot 				/* tried up to 500 lines, can't go on */
236162Sroot 				fatal("diff failed (de4)");
237162Sroot 		}
238162Sroot 		else {		/* no need to try again, worked */
239162Sroot 			break;			/* exit while loop */
240162Sroot 		}
241162Sroot 	}
242162Sroot 	unlink(dfilename);
243162Sroot 	stats.s_ins = inserted;
244162Sroot 	stats.s_del = deleted;
245162Sroot 	stats.s_unc = orig - deleted;
246162Sroot 	if (gpkt.p_verbose) {
247162Sroot 		fprintf(gpkt.p_stdout,"%u inserted\n",stats.s_ins);
248162Sroot 		fprintf(gpkt.p_stdout,"%u deleted\n",stats.s_del);
249162Sroot 		fprintf(gpkt.p_stdout,"%u unchanged\n",stats.s_unc);
250162Sroot 	}
251162Sroot 	flushline(&gpkt,&stats);
252162Sroot 	rename(auxf(gpkt.p_file,'x'),gpkt.p_file);
253162Sroot 	if (Szqfile)
254162Sroot 		rename(auxf(&gpkt.p_file,'q'),Pfilename);
255162Sroot 	else {
256162Sroot 		xunlink(Pfilename);
257162Sroot 		xunlink(auxf(&gpkt.p_file,'q'));
258162Sroot 	}
259162Sroot 	clean_up(0);
260162Sroot 	if (!HADN) {
261162Sroot 		setuid(getuid());
262162Sroot 		unlink(gfilename);
263162Sroot 	}
264162Sroot }
265162Sroot 
266162Sroot 
267162Sroot mkdelt(pkt,sp,osp,diffloop,orig_nlines)
268162Sroot struct packet *pkt;
269162Sroot struct sid *sp, *osp;
270162Sroot int diffloop;
271162Sroot int orig_nlines;
272162Sroot {
273162Sroot 	extern long Timenow;
274162Sroot 	struct deltab dt;
275162Sroot 	char str[128];
276162Sroot 	int newser;
277162Sroot 	extern char *Sflags[];
278162Sroot 	register char *p;
279162Sroot 	int ser_inc, opred, nulldel;
280162Sroot 
281162Sroot 	if (!diffloop && pkt->p_verbose) {
282162Sroot 		sid_ba(sp,str);
283162Sroot 		fprintf(pkt->p_stdout,"%s\n",str);
284162Sroot 	}
285162Sroot 	putline(pkt,sprintf(str,"%c%c00000\n",CTLCHAR,HEAD));
286162Sroot 	newstats(pkt,str,"0");
287162Sroot 	move(sp,&dt.d_sid,sizeof(dt.d_sid));
288162Sroot 
289162Sroot 	/*
290162Sroot 	Check if 'null' deltas should be inserted
291162Sroot 	(only if 'null' flag is in file and
292162Sroot 	releases are being skipped) and set
293162Sroot 	'nulldel' indicator appropriately.
294162Sroot 	*/
295162Sroot 	if (Sflags[NULLFLAG - 'a'] && (sp->s_rel > osp->s_rel + 1) &&
296162Sroot 			!sp->s_br && !sp->s_seq &&
297162Sroot 			!osp->s_br && !osp->s_seq)
298162Sroot 		nulldel = 1;
299162Sroot 	else
300162Sroot 		nulldel = 0;
301162Sroot 	/*
302162Sroot 	Calculate how many serial numbers are needed.
303162Sroot 	*/
304162Sroot 	if (nulldel)
305162Sroot 		ser_inc = sp->s_rel - osp->s_rel;
306162Sroot 	else
307162Sroot 		ser_inc = 1;
308162Sroot 	/*
309162Sroot 	Find serial number of the new delta.
310162Sroot 	*/
311162Sroot 	newser = dt.d_serial = maxser(pkt) + ser_inc;
312162Sroot 	/*
313162Sroot 	Find old predecessor's serial number.
314162Sroot 	*/
315162Sroot 	opred = sidtoser(osp,pkt);
316162Sroot 	if (nulldel)
317162Sroot 		dt.d_pred = newser - 1;	/* set predecessor to 'null' delta */
318162Sroot 	else
319162Sroot 		dt.d_pred = opred;
320162Sroot 	dt.d_datetime = Timenow;
3216173Seric 	substr(logname(),dt.d_pgmr,0,LNLNAM);
322162Sroot 	dt.d_type = 'D';
323162Sroot 	del_ba(&dt,str);
324162Sroot 	putline(pkt,str);
325162Sroot 	if (ilist)
326162Sroot 		mkixg(pkt,INCLUSER,INCLUDE);
327162Sroot 	if (elist)
328162Sroot 		mkixg(pkt,EXCLUSER,EXCLUDE);
329162Sroot 	if (glist)
330162Sroot 		mkixg(pkt,IGNRUSER,IGNORE);
331162Sroot 	if (Mrs) {
332162Sroot 		if (!(p = Sflags[VALFLAG - 'a']))
333162Sroot 			fatal("MRs not allowed (de8)");
334162Sroot 		if (*p && !diffloop && valmrs(pkt,p))
335162Sroot 			fatal("invalid MRs (de9)");
336162Sroot 		putmrs(pkt);
337162Sroot 	}
338162Sroot 	else if (Sflags[VALFLAG - 'a'])
339162Sroot 		fatal("MRs required (de10)");
340162Sroot 	putline(pkt,sprintf(str,"%c%c ",CTLCHAR,COMMENTS));
341162Sroot 	putline(pkt,Comments);
342162Sroot 	putline(pkt,"\n");
343162Sroot 	putline(pkt,sprintf(str,CTLSTR,CTLCHAR,EDELTAB));
344162Sroot 	if (nulldel)			/* insert 'null' deltas */
345162Sroot 		while (--ser_inc) {
346162Sroot 			putline(pkt,sprintf(str,"%c%c %s/%s/%05u\n",
347162Sroot 				CTLCHAR, STATS,
348162Sroot 				"00000", "00000", orig_nlines));
349162Sroot 			dt.d_sid.s_rel =- 1;
350162Sroot 			dt.d_serial =- 1;
351162Sroot 			if (ser_inc != 1)
352162Sroot 				dt.d_pred =- 1;
353162Sroot 			else
354162Sroot 				dt.d_pred = opred;	/* point to old pred */
355162Sroot 			del_ba(&dt,str);
356162Sroot 			putline(pkt,str);
357162Sroot 			putline(pkt,sprintf(str,"%c%c ",CTLCHAR,COMMENTS));
358162Sroot 			putline(pkt,"AUTO NULL DELTA\n");
359162Sroot 			putline(pkt,sprintf(str,CTLSTR,CTLCHAR,EDELTAB));
360162Sroot 		}
361162Sroot 	return(newser);
362162Sroot }
363162Sroot 
364162Sroot 
365162Sroot mkixg(pkt,reason,ch)
366162Sroot struct packet *pkt;
367162Sroot int reason;
368162Sroot char ch;
369162Sroot {
370162Sroot 	int n;
371162Sroot 	char str[512];
372162Sroot 
373162Sroot 	putline(pkt,sprintf(str,"%c%c",CTLCHAR,ch));
374162Sroot 	for (n = maxser(pkt); n; n--) {
375162Sroot 		if (pkt->p_apply[n].a_reason == reason)
376162Sroot 			putline(pkt,sprintf(str," %u",n));
377162Sroot 	}
378162Sroot 	putline(pkt,"\n");
379162Sroot }
380162Sroot 
381162Sroot 
382162Sroot putmrs(pkt)
383162Sroot struct packet *pkt;
384162Sroot {
385162Sroot 	register char **argv;
386162Sroot 	char str[64];
387162Sroot 	extern char *Varg[];
388162Sroot 
389162Sroot 	for (argv = &Varg[VSTART]; *argv; argv++)
390162Sroot 		putline(pkt,sprintf(str,"%c%c %s\n",CTLCHAR,MRNUM,*argv));
391162Sroot }
392162Sroot 
393162Sroot 
394162Sroot rdpfile(pkt,sp)
395162Sroot register struct packet *pkt;
396162Sroot struct sid *sp;
397162Sroot {
398162Sroot 	char *user;
399162Sroot 	struct pfile pf;
400162Sroot 	static struct pfile goodpf;
401162Sroot 	char line[512];
402*6636Ssam 	int cnt, root;
403162Sroot 	FILE *in, *out;
404162Sroot 
405162Sroot 	cnt = -1;
406162Sroot 	user = logname();
407162Sroot 	zero(&goodpf,sizeof(goodpf));
408162Sroot 	in = xfopen(auxf(pkt->p_file,'p'),0);
409162Sroot 	out = xfcreat(auxf(pkt->p_file,'q'),0644);
410*6636Ssam 	root = getuid() == 0;
411162Sroot 	while (fgets(line,sizeof(line),in) != NULL) {
412162Sroot 		pf_ab(line,&pf,1);
413*6636Ssam 		if (root || equal(pf.pf_user,user)) {
414162Sroot 			if (sp->s_rel == 0) {
415162Sroot 				if (++cnt) {
416162Sroot 					fclose(out);
417162Sroot 					fclose(in);
418162Sroot 					fatal("missing -r argument (de1)");
419162Sroot 				}
420162Sroot 				move(&pf,&goodpf,sizeof(pf));
421162Sroot 				continue;
422162Sroot 			}
423162Sroot 			else if (sp->s_rel == pf.pf_gsid.s_rel &&
424162Sroot 				sp->s_lev == pf.pf_gsid.s_lev &&
425162Sroot 				sp->s_br == pf.pf_gsid.s_br &&
426162Sroot 				sp->s_seq == pf.pf_gsid.s_seq) {
427162Sroot 					move(&pf,&goodpf,sizeof(pf));
428162Sroot 					continue;
429162Sroot 			}
430162Sroot 		}
431162Sroot 		fputs(line,out);
432162Sroot 	}
433162Sroot 	fflush(out);
434162Sroot 	fstat(fileno(out),&Statbuf);
435162Sroot 	Szqfile = Statbuf.st_size;
436162Sroot 	copy(auxf(pkt->p_file,'p'),Pfilename);
437162Sroot 	fclose(out);
438162Sroot 	fclose(in);
439162Sroot 	if (!goodpf.pf_user[0])
440162Sroot 		fatal("not in p-file (de2)");
441162Sroot 	return(&goodpf);
442162Sroot }
443162Sroot 
444162Sroot 
445162Sroot dodiff(newf,oldf,difflim)
446162Sroot char *newf, *oldf;
447162Sroot int difflim;
448162Sroot {
449162Sroot 	register int i;
450162Sroot 	int pfd[2];
451162Sroot 	FILE *iop;
452162Sroot 	extern char Diffpgm[];
453162Sroot 	char num[10];
454162Sroot 
455162Sroot 	xpipe(pfd);
456162Sroot 	if ((i = fork()) < 0) {
457162Sroot 		close(pfd[0]);
458162Sroot 		close(pfd[1]);
459162Sroot 		fatal("cannot fork, try again (de11)");
460162Sroot 	}
461162Sroot 	else if (i == 0) {
462162Sroot 		close(pfd[0]);
463162Sroot 		close(1);
464162Sroot 		dup(pfd[1]);
465162Sroot 		close(pfd[1]);
466162Sroot 		for (i = 5; i < 15; i++)
467162Sroot 			close(i);
468162Sroot 		sprintf(num,"%d",difflim);
469162Sroot 		execl(Diffpgm,Diffpgm,oldf,newf,num,"-s",0);
470162Sroot 		close(1);
471162Sroot 		exit(32);	/* tell parent that 'execl' failed */
472162Sroot 	}
473162Sroot 	else {
474162Sroot 		close(pfd[1]);
475162Sroot 		iop = fdfopen(pfd[0],0);
476162Sroot 		return(iop);
477162Sroot 	}
478162Sroot }
479162Sroot 
480162Sroot 
481162Sroot getdiff(type,plinenum)
482162Sroot register char *type;
483162Sroot register int *plinenum;
484162Sroot {
485162Sroot 	char line[512];
486162Sroot 	register char *p;
487162Sroot 	int num_lines;
488162Sroot 	static int chg_num, chg_ln;
489162Sroot 	int lowline, highline;
490162Sroot 
491162Sroot 	if ((p = rddiff(line,512)) == NULL)
492162Sroot 		return(0);
493162Sroot 
494162Sroot 	if (*p == '-') {
495162Sroot 		*type = INS;
496162Sroot 		*plinenum = chg_ln;
497162Sroot 		num_lines = chg_num;
498162Sroot 	}
499162Sroot 	else {
500162Sroot 		p = linerange(p,&lowline,&highline);
501162Sroot 		*plinenum = lowline;
502162Sroot 
503162Sroot 		switch(*p++) {
504162Sroot 		case 'd':
505162Sroot 			num_lines = highline - lowline + 1;
506162Sroot 			*type = DEL;
5072167Seric 			skiplines(line,num_lines);
508162Sroot 			break;
509162Sroot 
510162Sroot 		case 'a':
511162Sroot 			linerange(p,&lowline,&highline);
512162Sroot 			num_lines = highline - lowline + 1;
513162Sroot 			*type = INS;
514162Sroot 			break;
515162Sroot 
516162Sroot 		case 'c':
517162Sroot 			chg_ln = lowline;
518162Sroot 			num_lines = highline - lowline + 1;
519162Sroot 			linerange(p,&lowline,&highline);
520162Sroot 			chg_num = highline - lowline + 1;
521162Sroot 			*type = DEL;
5222167Seric 			skiplines(line,num_lines);
523162Sroot 			break;
524162Sroot 		}
525162Sroot 	}
526162Sroot 
527162Sroot 	return(num_lines);
528162Sroot }
529162Sroot 
530162Sroot 
531162Sroot insert(pkt,linenum,n,ser)
532162Sroot register struct packet *pkt;
533162Sroot register int linenum;
534162Sroot register int n;
535162Sroot int ser;
536162Sroot {
537162Sroot 	char str[512];
538162Sroot 
539162Sroot 	after(pkt,linenum);
540162Sroot 	putline(pkt,sprintf(str,"%c%c %u\n",CTLCHAR,INS,ser));
541162Sroot 	for (++n; --n; ) {
542162Sroot 		rddiff(str,sizeof(str));
543162Sroot 		putline(pkt,&str[2]);
544162Sroot 	}
545162Sroot 	putline(pkt,sprintf(str,"%c%c %u\n",CTLCHAR,END,ser));
546162Sroot }
547162Sroot 
548162Sroot 
549162Sroot delete(pkt,linenum,n,ser)
550162Sroot register struct packet *pkt;
551162Sroot register int linenum;
552162Sroot int n;
553162Sroot register int ser;
554162Sroot {
555162Sroot 	char str[512];
556162Sroot 
557162Sroot 	before(pkt,linenum);
558162Sroot 	putline(pkt,sprintf(str,"%c%c %u\n",CTLCHAR,DEL,ser));
559162Sroot 	after(pkt,linenum + n - 1);
560162Sroot 	putline(pkt,sprintf(str,"%c%c %u\n",CTLCHAR,END,ser));
561162Sroot }
562162Sroot 
563162Sroot 
564162Sroot after(pkt,n)
565162Sroot register struct packet *pkt;
566162Sroot register int n;
567162Sroot {
568162Sroot 	before(pkt,n);
569162Sroot 	if (pkt->p_glnno == n)
570162Sroot 		putline(pkt,0);
571162Sroot }
572162Sroot 
573162Sroot 
574162Sroot before(pkt,n)
575162Sroot register struct packet *pkt;
576162Sroot register int n;
577162Sroot {
578162Sroot 	while (pkt->p_glnno < n) {
579162Sroot 		if (!readmod(pkt))
580162Sroot 			break;
581162Sroot 	}
582162Sroot }
583162Sroot 
584162Sroot 
585162Sroot linerange(cp,low,high)
586162Sroot register char *cp;
587162Sroot register int *low, *high;
588162Sroot {
589162Sroot 	cp = satoi(cp,low);
590162Sroot 	if (*cp == ',')
591162Sroot 		cp = satoi(++cp,high);
592162Sroot 	else
593162Sroot 		*high = *low;
594162Sroot 
595162Sroot 	return(cp);
596162Sroot }
597162Sroot 
598162Sroot 
599162Sroot skiplines(lp,num)
600162Sroot register char *lp;
601162Sroot register int num;
602162Sroot {
603162Sroot 	for (++num;--num;)
604162Sroot 		rddiff(lp,512);
605162Sroot }
606162Sroot 
607162Sroot 
608162Sroot rddiff(s,n)
609162Sroot register char *s;
610162Sroot register int n;
611162Sroot {
612162Sroot 	register int r;
613162Sroot 
614162Sroot 	if ((r = fgets(s,n,Diffin)) != NULL && HADP)
615162Sroot 		fputs(s,gpkt.p_stdout);
616162Sroot 	return(r);
617162Sroot }
618162Sroot 
619162Sroot 
620162Sroot enter(pkt,ch,n,sidp)
621162Sroot struct packet *pkt;
622162Sroot char ch;
623162Sroot int n;
624162Sroot struct sid *sidp;
625162Sroot {
626162Sroot 	char str[32];
627162Sroot 	register struct apply *ap;
628162Sroot 
629162Sroot 	sid_ba(sidp,str);
630162Sroot 	ap = &pkt->p_apply[n];
631162Sroot 	if (pkt->p_cutoff > pkt->p_idel[n].i_datetime)
632162Sroot 		switch(ap->a_code) {
633162Sroot 
634162Sroot 		case EMPTY:
635162Sroot 			switch (ch) {
636162Sroot 			case INCLUDE:
637162Sroot 				condset(ap,APPLY,INCLUSER);
638162Sroot 				break;
639162Sroot 			case EXCLUDE:
640162Sroot 				condset(ap,NOAPPLY,EXCLUSER);
641162Sroot 				break;
642162Sroot 			case IGNORE:
643162Sroot 				condset(ap,EMPTY,IGNRUSER);
644162Sroot 				break;
645162Sroot 			}
646162Sroot 			break;
647162Sroot 		case APPLY:
648162Sroot 			fatal("internal error in delta/enter() (de5)");
649162Sroot 			break;
650162Sroot 		case NOAPPLY:
651162Sroot 			fatal("internal error in delta/enter() (de6)");
652162Sroot 			break;
653162Sroot 		default:
654162Sroot 			fatal("internal error in delta/enter() (de7)");
655162Sroot 			break;
656162Sroot 		}
657162Sroot }
658162Sroot 
659162Sroot 
660162Sroot escdodelt()	/* dummy routine for dodelt() */
661162Sroot {
662162Sroot }
663162Sroot 
664162Sroot 
665162Sroot clean_up(n)
666162Sroot {
667162Sroot 	if (gpkt.p_file[0])
668162Sroot 		unlockit(auxf(gpkt.p_file,'z'),getpid());
669162Sroot 	xrm(&gpkt);
670162Sroot 	xfreeall();
671162Sroot }
672