1*2131Seric /*************************************************************************/
2*2131Seric /*									 */
3*2131Seric /*	prs [-d<dataspec>] [-r<sid>] [-c<cutoff>] [-a]			 */
4*2131Seric /*	    [-y<reverse-cutoff>] file ...				 */
5*2131Seric /*									 */
6*2131Seric /*************************************************************************/
7*2131Seric 
8*2131Seric /*
9*2131Seric 	Program to print parts or all of an SCCS file
10*2131Seric 	in user supplied format.
11*2131Seric 	Arguments to the program may appear in any order
12*2131Seric 	and consist of keyletters, which begin with '-',
13*2131Seric 	and named files.
14*2131Seric 
15*2131Seric 	If a direcory is given as an argument, each
16*2131Seric 	SCCS file within the directory is processed as if
17*2131Seric 	it had been specifically named. If a name of '-'
18*2131Seric 	is given, the standard input is read for a list
19*2131Seric 	of names of SCCS files to be processed.
20*2131Seric 	Non-SCCS files are ignored.
21*2131Seric */
22*2131Seric 
23*2131Seric # include "../hdr/defines.h"
24*2131Seric # include "../hdr/had.h"
25*2131Seric 
26*2131Seric SCCSID(@(#)prs.c	1.3);
27*2131Seric 
28*2131Seric char	had[26];
29*2131Seric char	Getpgm[]	"/usr/local/get";
30*2131Seric char	Sid[32];
31*2131Seric char	Mod[16];
32*2131Seric char	*Type;
33*2131Seric char	Deltadate[18];
34*2131Seric char	*Deltatime;
35*2131Seric char	tempskel[]	"/tmp/prXXXXXX";	/* used to generate temp
36*2131Seric 						   file names
37*2131Seric 						*/
38*2131Seric char	untmp[32], uttmp[32], cmtmp[32];
39*2131Seric char	mrtmp[32], bdtmp[32];
40*2131Seric FILE	*UNiop;
41*2131Seric FILE	*UTiop;
42*2131Seric FILE	*CMiop;
43*2131Seric FILE	*MRiop;
44*2131Seric FILE	*BDiop;
45*2131Seric char	line[BUFSIZ];
46*2131Seric int	num_files;
47*2131Seric long	cutoff;
48*2131Seric long	revcut;
49*2131Seric char	*dataspec;
50*2131Seric char	iline[BUFSIZ], xline[BUFSIZ], gline[BUFSIZ];
51*2131Seric char	*maket();
52*2131Seric struct	packet	gpkt;
53*2131Seric struct	sid	sid;
54*2131Seric struct	time	*Dtime;
55*2131Seric 
56*2131Seric main(argc,argv)
57*2131Seric int argc;
58*2131Seric char *argv[];
59*2131Seric {
60*2131Seric 	register int j;
61*2131Seric 	register char *p;
62*2131Seric 	char c;
63*2131Seric 	extern prs();
64*2131Seric 	extern int Fcnt;
65*2131Seric 
66*2131Seric 	/*
67*2131Seric 	Set flags for 'fatal' to issue message, call clean-up
68*2131Seric 	routine, and terminate processing.
69*2131Seric 	*/
70*2131Seric 	Fflags = FTLMSG | FTLCLN | FTLEXIT;
71*2131Seric 
72*2131Seric 
73*2131Seric 	/*
74*2131Seric 	The following loop processes keyletters and arguments.
75*2131Seric 	Note that these are processed only once for each
76*2131Seric 	invocation of 'main'.
77*2131Seric 	*/
78*2131Seric 	for (j = 1; j < argc; j++)
79*2131Seric 		if (argv[j][0] == '-' && (c = argv[j][1])) {
80*2131Seric 			p = &argv[j][2];
81*2131Seric 			switch (c) {
82*2131Seric 
83*2131Seric 			case 'r':	/* delta cutoff */
84*2131Seric 				if (*p) {
85*2131Seric 					if (invalid(p))
86*2131Seric 						fatal("invalid sid (co8)");
87*2131Seric 					sid_ab(p,&sid);
88*2131Seric 				}
89*2131Seric 				break;
90*2131Seric 
91*2131Seric 			case 'c':	/* time cutoff */
92*2131Seric 				if (*p && date_ab(p,&cutoff))
93*2131Seric 					fatal("bad date/time (cm5)");
94*2131Seric 				break;
95*2131Seric 
96*2131Seric 			case 'y':	/* reverse time cutoff */
97*2131Seric 				if (*p && date_ab(p,&revcut))
98*2131Seric 					fatal ("bad date/time (cm5)");
99*2131Seric 				break;
100*2131Seric 
101*2131Seric 			case 'a':
102*2131Seric 				if (*p)
103*2131Seric 					fatal("value after a arg (cm7)");
104*2131Seric 				break;
105*2131Seric 			case 'd':	/* dataspec line */
106*2131Seric 				dataspec = p;
107*2131Seric 				break;
108*2131Seric 			default:
109*2131Seric 				fatal("unknown key letter (cm1)");
110*2131Seric 			}
111*2131Seric 
112*2131Seric 			if (had[c - 'a']++)
113*2131Seric 				fatal("key letter twice (cm2)");
114*2131Seric 			argv[j] = 0;
115*2131Seric 		}
116*2131Seric 		else
117*2131Seric 			num_files++;
118*2131Seric 
119*2131Seric 	if (num_files == 0)
120*2131Seric 		fatal("missing file arg (cm3)");
121*2131Seric 
122*2131Seric 	if (!HADD)
123*2131Seric 		exit(0);
124*2131Seric 	if (HADC && HADY)
125*2131Seric 		fatal("both 'c' and 'y' keyletters specified (prs2)");
126*2131Seric 
127*2131Seric 	setsig();
128*2131Seric 
129*2131Seric 	/*
130*2131Seric 	Change flags for 'fatal' so that it will return to this
131*2131Seric 	routine (main) instead of terminating processing.
132*2131Seric 	*/
133*2131Seric 	Fflags =& ~FTLEXIT;
134*2131Seric 	Fflags =| FTLJMP;
135*2131Seric 
136*2131Seric 	/*
137*2131Seric 	Call 'prs' routine for each file argument.
138*2131Seric 	*/
139*2131Seric 	for (j = 1; j < argc; j++)
140*2131Seric 		if (p = argv[j])
141*2131Seric 			do_file(p,prs);
142*2131Seric 
143*2131Seric 	exit(Fcnt ? 1 : 0);
144*2131Seric }
145*2131Seric 
146*2131Seric 
147*2131Seric prs(file)
148*2131Seric register	char	*file;
149*2131Seric {
150*2131Seric 	int	n;
151*2131Seric 	extern	char	had_dir, had_standinp;
152*2131Seric 
153*2131Seric 	if (setjmp(Fjmp))
154*2131Seric 		return;
155*2131Seric 	sinit(&gpkt,file,1);	/* init packet and open SCCS file */
156*2131Seric 
157*2131Seric 	gpkt.p_reqsid.s_rel = sid.s_rel;
158*2131Seric 	gpkt.p_reqsid.s_lev = sid.s_lev;
159*2131Seric 	gpkt.p_reqsid.s_br = sid.s_br;
160*2131Seric 	gpkt.p_reqsid.s_seq = sid.s_seq;
161*2131Seric 	gpkt.p_cutoff = cutoff;
162*2131Seric 	gpkt.p_reopen = 1;
163*2131Seric 
164*2131Seric 	/*
165*2131Seric 	read delta table entries checking only for format error
166*2131Seric 	*/
167*2131Seric 	deltblchk(&gpkt);
168*2131Seric 
169*2131Seric 	/*
170*2131Seric 	create auxiliary file for User Name Section
171*2131Seric 	*/
172*2131Seric 
173*2131Seric 	aux_create(UNiop,untmp,EUSERNAM);
174*2131Seric 
175*2131Seric 	doflags(&gpkt);
176*2131Seric 
177*2131Seric 	/*
178*2131Seric 	create auxiliary file for the User Text section
179*2131Seric 	*/
180*2131Seric 
181*2131Seric 	aux_create(UTiop,uttmp,EUSERTXT);
182*2131Seric 
183*2131Seric 	/*
184*2131Seric 	indicate to 'getline' that EOF is okay
185*2131Seric 	*/
186*2131Seric 	gpkt.p_chkeof = 1;
187*2131Seric 
188*2131Seric 	/*
189*2131Seric 	read body of SCCS file and create temp file for it
190*2131Seric 	*/
191*2131Seric 	while(read_mod(&gpkt))
192*2131Seric 		;
193*2131Seric 
194*2131Seric 	if (num_files > 1 || had_dir || had_standinp)
195*2131Seric 		printf("\n%s:\n",gpkt.p_file);
196*2131Seric 	/*
197*2131Seric 	Here, file has already been re-opened (by 'getline')
198*2131Seric 	*/
199*2131Seric 	getline(&gpkt);		/* skip over header line */
200*2131Seric 
201*2131Seric 	/*
202*2131Seric 	call dodeltbl to read delta table entries
203*2131Seric 	*/
204*2131Seric 
205*2131Seric 	dodeltbl(&gpkt);
206*2131Seric 
207*2131Seric 	clean_up();
208*2131Seric 
209*2131Seric 	return;
210*2131Seric }
211*2131Seric 
212*2131Seric 
213*2131Seric dodeltbl(pkt)
214*2131Seric register struct packet *pkt;
215*2131Seric {
216*2131Seric 	int	n;
217*2131Seric 	struct	deltab	dt;
218*2131Seric 	struct	stats	stats;
219*2131Seric 
220*2131Seric 	/*
221*2131Seric 	Read entire delta table.
222*2131Seric 	*/
223*2131Seric 	while (getstats(pkt,&stats)) {
224*2131Seric 		if (getadel(pkt,&dt) != BDELTAB)
225*2131Seric 			fmterr(pkt);
226*2131Seric 
227*2131Seric 		/*
228*2131Seric 		Read rest of delta entry.
229*2131Seric 		*/
230*2131Seric 		while ((n = getline(pkt)) != NULL)
231*2131Seric 			if (pkt->p_line[0] != CTLCHAR)
232*2131Seric 				break;
233*2131Seric 			else {
234*2131Seric 				switch (pkt->p_line[1]) {
235*2131Seric 				case EDELTAB:
236*2131Seric 					scanspec(dataspec,&dt,&stats);
237*2131Seric 					break;
238*2131Seric 				case INCLUDE:
239*2131Seric 					getit(iline,n);
240*2131Seric 					continue;
241*2131Seric 				case EXCLUDE:
242*2131Seric 					getit(xline,n);
243*2131Seric 					continue;
244*2131Seric 				case IGNORE:
245*2131Seric 					getit(gline,n);
246*2131Seric 					continue;
247*2131Seric 				case MRNUM:
248*2131Seric 				case COMMENTS:
249*2131Seric 					continue;
250*2131Seric 				default:
251*2131Seric 					fmterr(pkt);
252*2131Seric 				}
253*2131Seric 				break;
254*2131Seric 			}
255*2131Seric 		if (n == NULL || pkt->p_line[0] != CTLCHAR)
256*2131Seric 			fmterr(pkt);
257*2131Seric 	}
258*2131Seric }
259*2131Seric 
260*2131Seric 
261*2131Seric /*
262*2131Seric  * The scanspec procedure scans the dataspec searching for ID keywords.
263*2131Seric  * When a keyword is found the value is replaced and printed on the
264*2131Seric  * standard output. Any character that is not an ID keyword is printed
265*2131Seric  * immediately.
266*2131Seric */
267*2131Seric 
268*2131Seric static	char	Zkeywd[5]	"@(#)";
269*2131Seric scanspec(spec,dtp,statp)
270*2131Seric char spec[];
271*2131Seric struct	deltab	*dtp;
272*2131Seric struct	stats	*statp;
273*2131Seric {
274*2131Seric 
275*2131Seric 	extern	char	*Sflags[];
276*2131Seric 	register char *lp;
277*2131Seric 	register char	*k;
278*2131Seric 	union {
279*2131Seric 		char	str[2];
280*2131Seric 		int	istr;
281*2131Seric 	} u;
282*2131Seric 	register	char	c;
283*2131Seric 
284*2131Seric 	idsetup(&dtp->d_sid,&gpkt,&dtp->d_datetime);
285*2131Seric 	for(lp = spec; *lp != 0; lp++) {
286*2131Seric 		if(lp[0] == ':' && lp[1] != 0 && lp[2] == ':') {
287*2131Seric 			c = *++lp;
288*2131Seric 			switch (c) {
289*2131Seric 			case 'I':	/* SID */
290*2131Seric 				printf("%s",Sid);
291*2131Seric 				break;
292*2131Seric 			case 'R':	/* Release number */
293*2131Seric 				printf("%u",dtp->d_sid.s_rel);
294*2131Seric 				break;
295*2131Seric 			case 'L':	/* Level number */
296*2131Seric 				printf("%u",dtp->d_sid.s_lev);
297*2131Seric 				break;
298*2131Seric 			case 'B':	/* Branch number */
299*2131Seric 				if (dtp->d_sid.s_br != 0)
300*2131Seric 					printf("%u",dtp->d_sid.s_br);
301*2131Seric 				break;
302*2131Seric 			case 'S':	/* Sequence number */
303*2131Seric 				if (dtp->d_sid.s_seq != 0)
304*2131Seric 					printf("%u",dtp->d_sid.s_seq);
305*2131Seric 				break;
306*2131Seric 			case 'D':	/* Date delta created */
307*2131Seric 				printf("%s",Deltadate);
308*2131Seric 				break;
309*2131Seric 			case 'T':	/* Time delta created */
310*2131Seric 				printf("%s",Deltatime);
311*2131Seric 				break;
312*2131Seric 			case 'P':	/* Programmer who created delta */
313*2131Seric 				printf("%s",dtp->d_pgmr);
314*2131Seric 				break;
315*2131Seric 			case 'C':	/* Comments */
316*2131Seric 				break;
317*2131Seric 			case 'Y':	/* Type flag */
318*2131Seric 				printf("%s",Type);
319*2131Seric 				break;
320*2131Seric 			case 'M':	/* Module name */
321*2131Seric 				printf("%s",Mod);
322*2131Seric 				break;
323*2131Seric 			case 'W':	/* Form of what string */
324*2131Seric 				printf("%s",Zkeywd);
325*2131Seric 				printf("%s",Mod);
326*2131Seric 				putchar('\t');
327*2131Seric 				printf("%s",Sid);
328*2131Seric 				break;
329*2131Seric 			case 'A':	/* Form of what string */
330*2131Seric 				printf("%s",Zkeywd);
331*2131Seric 				printf("%s ",Type);
332*2131Seric 				printf("%s ",Mod);
333*2131Seric 				printf("%s",Sid);
334*2131Seric 				printf("%s",Zkeywd);
335*2131Seric 				break;
336*2131Seric 			case 'Z':	/* what string constructor */
337*2131Seric 				printf("%s",Zkeywd);
338*2131Seric 				break;
339*2131Seric 			case 'F':	/* File name */
340*2131Seric 				printf("%s",sname(gpkt.p_file));
341*2131Seric 				break;
342*2131Seric 			default:
343*2131Seric 				putchar(':');
344*2131Seric 				putchar(c);
345*2131Seric 				putchar(':');
346*2131Seric 				break;
347*2131Seric 			}
348*2131Seric 			lp++;
349*2131Seric 		}
350*2131Seric 		else if(lp[0] == ':' && lp[1] != 0 && lp[2] !=0 && lp[3] == ':') {
351*2131Seric 			if (lp[1] == ':') {
352*2131Seric 				putchar(':');
353*2131Seric 				*lp =+ 2;
354*2131Seric 				continue;
355*2131Seric 			}
356*2131Seric 			u.str[0] = *++lp;
357*2131Seric 			u.str[1] = *++lp;
358*2131Seric 			switch (u.istr) {
359*2131Seric 			case 'Dl':	/* Delta line statistics */
360*2131Seric 				printf("%05d",statp->s_ins);
361*2131Seric 				putchar('/');
362*2131Seric 				printf("%05d",statp->s_del);
363*2131Seric 				putchar('/');
364*2131Seric 				printf("%05d",statp->s_unc);
365*2131Seric 				break;
366*2131Seric 			case 'Li':	/* Lines inserted by delta */
367*2131Seric 				printf("%05d",statp->s_ins);
368*2131Seric 				break;
369*2131Seric 			case 'Ld':	/* Lines deleted by delta */
370*2131Seric 				printf("%05d",statp->s_del);
371*2131Seric 				break;
372*2131Seric 			case 'Lu':	/* Lines unchanged by delta */
373*2131Seric 				printf("%05d",statp->s_unc);
374*2131Seric 				break;
375*2131Seric 			case 'DT':	/* Delta type */
376*2131Seric 				printf("%c",dtp->d_type);
377*2131Seric 				break;
378*2131Seric 			case 'Dy':	/* Year delta created */
379*2131Seric 				printf("%02d",Dtime->t_year);
380*2131Seric 				break;
381*2131Seric 			case 'Dm':	/* Month delta created */
382*2131Seric 				printf("%02d",(Dtime->t_month + 1));
383*2131Seric 				break;
384*2131Seric 			case 'Dd':	/* Day delta created */
385*2131Seric 				printf("%02d",Dtime->t_day_month);
386*2131Seric 				break;
387*2131Seric 			case 'Th':	/* Hour delta created */
388*2131Seric 				printf("%02d",Dtime->t_hours);
389*2131Seric 				break;
390*2131Seric 			case 'Tm':	/* Minutes delta created */
391*2131Seric 				printf("%02d",Dtime->t_minutes);
392*2131Seric 				break;
393*2131Seric 			case 'Ts':	/* Seconds delta created */
394*2131Seric 				printf("%02d",Dtime->t_seconds);
395*2131Seric 				break;
396*2131Seric 			case 'DS':	/* Delta sequence number */
397*2131Seric 				printf("%d",dtp->d_serial);
398*2131Seric 				break;
399*2131Seric 			case 'DP':	/* Predecessor delta sequence number */
400*2131Seric 				printf("%d",dtp->d_pred);
401*2131Seric 				break;
402*2131Seric 			case 'DI':	/* Deltas included,excluded,ignored */
403*2131Seric 				printf("%s",iline);
404*2131Seric 				putchar('/');
405*2131Seric 				printf("%s",xline);
406*2131Seric 				putchar('/');
407*2131Seric 				printf("%s",gline);
408*2131Seric 				break;
409*2131Seric 			case 'Di':	/* Deltas included */
410*2131Seric 				printf("%s",iline);
411*2131Seric 				break;
412*2131Seric 			case 'Dx':	/* Deltas excluded */
413*2131Seric 				printf("%s",xline);
414*2131Seric 				break;
415*2131Seric 			case 'Dg':	/* Deltas ignored */
416*2131Seric 				printf("%s",gline);
417*2131Seric 				break;
418*2131Seric 			case 'MR':	/* MR numbers */
419*2131Seric 				break;
420*2131Seric 			case 'UN':	/* User names */
421*2131Seric 				printfile(untmp);
422*2131Seric 				break;
423*2131Seric 			case 'MF':	/* MR validation flag */
424*2131Seric 				if (Sflags[VALFLAG - 'a'])
425*2131Seric 					printf("yes");
426*2131Seric 				else printf("no");
427*2131Seric 				break;
428*2131Seric 			case 'MP':	/* MR validation program */
429*2131Seric 				if (!(k = Sflags[VALFLAG - 'a']))
430*2131Seric 					printf("none");
431*2131Seric 				else printf("%s",k);
432*2131Seric 				break;
433*2131Seric 			case 'KF':	/* Keyword err/warn flag */
434*2131Seric 				if (Sflags[IDFLAG - 'a'])
435*2131Seric 					printf("yes");
436*2131Seric 				else printf("no");
437*2131Seric 				break;
438*2131Seric 			case 'BF':	/* Branch flag */
439*2131Seric 				if (Sflags[BRCHFLAG - 'a'])
440*2131Seric 					printf("yes");
441*2131Seric 				else printf("no");
442*2131Seric 				break;
443*2131Seric 			case 'FB':	/* Floor Boundry */
444*2131Seric 				if (k = Sflags[FLORFLAG - 'a'])
445*2131Seric 					printf("%s",k);
446*2131Seric 				else printf("none");
447*2131Seric 				break;
448*2131Seric 			case 'CB':	/* Ceiling Boundry */
449*2131Seric 				if (k = Sflags[CEILFLAG - 'a'])
450*2131Seric 					printf("%s",k);
451*2131Seric 				else printf("none");
452*2131Seric 				break;
453*2131Seric 			case 'Ds':	/* Default SID */
454*2131Seric 				if (k = Sflags[DEFTFLAG - 'a'])
455*2131Seric 					printf("%s",k);
456*2131Seric 				else printf("none");
457*2131Seric 				break;
458*2131Seric 			case 'ND':	/* Null delta */
459*2131Seric 				if (Sflags[NULLFLAG - 'a'])
460*2131Seric 					printf("yes");
461*2131Seric 				else printf("no");
462*2131Seric 				break;
463*2131Seric 			case 'FD':	/* File descriptive text */
464*2131Seric 				printfile(uttmp);
465*2131Seric 				break;
466*2131Seric 			case 'BD':	/* Entire file body */
467*2131Seric 				printfile(bdtmp);
468*2131Seric 				break;
469*2131Seric 			case 'GB':	/* Gotten body from 'get' */
470*2131Seric 				getbody(&dtp->d_sid,&gpkt);
471*2131Seric 				break;
472*2131Seric 			default:
473*2131Seric 				putchar(':');
474*2131Seric 				printf("%c",u.istr);
475*2131Seric 				putchar(':');
476*2131Seric 				break;
477*2131Seric 			}
478*2131Seric 			lp++;
479*2131Seric 		}
480*2131Seric 		else {
481*2131Seric 			c = *lp;
482*2131Seric 			if (c == '\\') {
483*2131Seric 				switch(*++lp) {
484*2131Seric 				case 'n':	/* for newline */
485*2131Seric 					putchar('\n');
486*2131Seric 					break;
487*2131Seric 				case ':':	/* for wanted colon */
488*2131Seric 					putchar(':');
489*2131Seric 					break;
490*2131Seric 				case 't':	/* for tab */
491*2131Seric 					putchar('\t');
492*2131Seric 					break;
493*2131Seric 				case 'b':	/* for backspace */
494*2131Seric 					putchar('\b');
495*2131Seric 					break;
496*2131Seric 				case 'r':	/* for carriage return */
497*2131Seric 					putchar('\r');
498*2131Seric 					break;
499*2131Seric 				case 'f':	/* for form feed */
500*2131Seric 					putchar('\f');
501*2131Seric 					break;
502*2131Seric 				case '\\':	/* for backslash */
503*2131Seric 					putchar('\\');
504*2131Seric 					break;
505*2131Seric 				case '\'':	/* for single quote */
506*2131Seric 					putchar('\'');
507*2131Seric 					break;
508*2131Seric 				default:	/* unknown case */
509*2131Seric 					putchar('\\');
510*2131Seric 					putchar(*lp);
511*2131Seric 					break;
512*2131Seric 				}
513*2131Seric 			}
514*2131Seric 			else putchar(*lp);
515*2131Seric 		}
516*2131Seric 	}
517*2131Seric 	/*
518*2131Seric 	zero out first char of global string lines in case
519*2131Seric 	a value is not gotten in next delta table entry
520*2131Seric 	*/
521*2131Seric 	iline[0] = xline[0] = gline[0] = 0;
522*2131Seric 	putchar('\n');
523*2131Seric 	return;
524*2131Seric }
525*2131Seric 
526*2131Seric 
527*2131Seric clean_up()
528*2131Seric {
529*2131Seric 	unlink(untmp);
530*2131Seric 	unlink(uttmp);
531*2131Seric 	unlink(bdtmp);
532*2131Seric }
533*2131Seric 
534*2131Seric 
535*2131Seric /* This function takes as it's argument the SID inputed and determines
536*2131Seric  * whether or not it is valid (e. g. not ambiguous or illegal).
537*2131Seric */
538*2131Seric invalid(i_sid)
539*2131Seric register char	*i_sid;
540*2131Seric {
541*2131Seric 	register int count;
542*2131Seric 	register int digits;
543*2131Seric 	count = digits = 0;
544*2131Seric 	if (*i_sid == '0' || *i_sid == '.')
545*2131Seric 		return (1);
546*2131Seric 	i_sid++;
547*2131Seric 	digits++;
548*2131Seric 	while (*i_sid != '\0') {
549*2131Seric 		if (*i_sid++ == '.') {
550*2131Seric 			digits = 0;
551*2131Seric 			count++;
552*2131Seric 			if (*i_sid == '0' || *i_sid == '.')
553*2131Seric 				return (1);
554*2131Seric 		}
555*2131Seric 		digits++;
556*2131Seric 		if (digits > 5)
557*2131Seric 			return (1);
558*2131Seric 	}
559*2131Seric 	if (*(--i_sid) == '.' )
560*2131Seric 		return (1);
561*2131Seric 	if (count == 1 || count == 3)
562*2131Seric 		return (0);
563*2131Seric 	return (1);
564*2131Seric }
565*2131Seric 
566*2131Seric 
567*2131Seric deltblchk(pkt)
568*2131Seric register struct packet *pkt;
569*2131Seric {
570*2131Seric 	int	n;
571*2131Seric 	struct	deltab	dt;
572*2131Seric 	struct	stats	stats;
573*2131Seric 
574*2131Seric 	/*
575*2131Seric 	Read entire delta table.
576*2131Seric 	*/
577*2131Seric 	while (getstats(pkt,&stats)) {
578*2131Seric 		if (getadel(pkt,&dt) != BDELTAB)
579*2131Seric 			fmterr(pkt);
580*2131Seric 
581*2131Seric 		/*
582*2131Seric 		Read rest of delta entry.
583*2131Seric 		*/
584*2131Seric 		while ((n = getline(pkt)) != NULL)
585*2131Seric 			if (pkt->p_line[0] != CTLCHAR)
586*2131Seric 				break;
587*2131Seric 			else {
588*2131Seric 				switch (pkt->p_line[1]) {
589*2131Seric 				case EDELTAB:
590*2131Seric 					break;
591*2131Seric 				case INCLUDE:
592*2131Seric 				case EXCLUDE:
593*2131Seric 				case IGNORE:
594*2131Seric 				case MRNUM:
595*2131Seric 				case COMMENTS:
596*2131Seric 					continue;
597*2131Seric 				default:
598*2131Seric 					fmterr(pkt);
599*2131Seric 				}
600*2131Seric 				break;
601*2131Seric 			}
602*2131Seric 		if (n == NULL || pkt->p_line[0] != CTLCHAR)
603*2131Seric 			fmterr(pkt);
604*2131Seric 	}
605*2131Seric 	if (pkt->p_line[1] != BUSERNAM)
606*2131Seric 		fmterr(pkt);
607*2131Seric }
608*2131Seric 
609*2131Seric 
610*2131Seric getstats(pkt,statp)
611*2131Seric register struct packet *pkt;
612*2131Seric register struct stats *statp;
613*2131Seric {
614*2131Seric 	register char *p;
615*2131Seric 
616*2131Seric 	p = pkt->p_line;
617*2131Seric 	if (getline(pkt) == NULL || *p++ != CTLCHAR || *p++ != STATS)
618*2131Seric 		return(0);
619*2131Seric 	NONBLANK(p);
620*2131Seric 	p = satoi(p,&statp->s_ins);
621*2131Seric 	p = satoi(++p,&statp->s_del);
622*2131Seric 	satoi(++p,&statp->s_unc);
623*2131Seric 	return(1);
624*2131Seric }
625*2131Seric 
626*2131Seric 
627*2131Seric getadel(pkt,dt)
628*2131Seric register struct packet *pkt;
629*2131Seric register struct deltab *dt;
630*2131Seric {
631*2131Seric 	if (getline(pkt) == NULL)
632*2131Seric 		fmterr(pkt);
633*2131Seric 	return(del_ab(pkt->p_line,dt,pkt));
634*2131Seric }
635*2131Seric 
636*2131Seric 
637*2131Seric 
638*2131Seric char	*maket(file)
639*2131Seric char	*file;
640*2131Seric {
641*2131Seric 	FILE *iop;
642*2131Seric 
643*2131Seric 	copy(tempskel,file);
644*2131Seric 	iop = xfcreat(mktemp(file),0644);
645*2131Seric 
646*2131Seric 	return(iop);
647*2131Seric }
648*2131Seric 
649*2131Seric 
650*2131Seric printfile(file)
651*2131Seric register	char	*file;
652*2131Seric {
653*2131Seric 	register	char	*p;
654*2131Seric 	FILE	*iop;
655*2131Seric 
656*2131Seric 	iop = xfopen(file,0);
657*2131Seric 	while ((p = fgets(line,sizeof(line),iop)) != NULL)
658*2131Seric 		printf("%s",p);
659*2131Seric 	fclose(iop);
660*2131Seric }
661*2131Seric 
662*2131Seric 
663*2131Seric read_mod(pkt)
664*2131Seric register struct packet *pkt;
665*2131Seric {
666*2131Seric 	register char *p;
667*2131Seric 	int ser;
668*2131Seric 	int iord;
669*2131Seric 	register struct apply *ap;
670*2131Seric 
671*2131Seric 	BDiop = maket(bdtmp);
672*2131Seric 	while (getline(pkt) != NULL) {
673*2131Seric 		p = pkt->p_line;
674*2131Seric 		fputs(p,BDiop);
675*2131Seric 		if (*p++ != CTLCHAR)
676*2131Seric 			continue;
677*2131Seric 		else {
678*2131Seric 			if (!((iord = *p++) == INS || iord == DEL || iord == END))
679*2131Seric 				fmterr(pkt);
680*2131Seric 			NONBLANK(p);
681*2131Seric 			satoi(p,&ser);
682*2131Seric 			if (iord == END)
683*2131Seric 				remq(pkt,ser);
684*2131Seric 			else if ((ap = &pkt->p_apply[ser])->a_code == APPLY)
685*2131Seric 				addq(pkt,ser,iord == INS ? YES : NO,iord,ap->a_reason & USER);
686*2131Seric 			else
687*2131Seric 				addq(pkt,ser,iord == INS ? NO : NULL,iord,ap->a_reason & USER);
688*2131Seric 		}
689*2131Seric 	}
690*2131Seric 	fclose(BDiop);
691*2131Seric 	if (pkt->p_q)
692*2131Seric 		fatal("premature eof (co5)");
693*2131Seric 	return(0);
694*2131Seric }
695*2131Seric 
696*2131Seric 
697*2131Seric getbody(gsid,pkt)
698*2131Seric struct	sid	*gsid;
699*2131Seric struct packet *pkt;
700*2131Seric {
701*2131Seric 	int	i;
702*2131Seric 	int	status;
703*2131Seric 	extern	char	Getpgm[];
704*2131Seric 	char	str[128];
705*2131Seric 	char	rarg[20];
706*2131Seric 	char	filearg[80];
707*2131Seric 
708*2131Seric 	sid_ba(gsid,str);
709*2131Seric 	sprintf(rarg,"%s",str);
710*2131Seric 	sprintf(filearg,"%s",pkt->p_file);
711*2131Seric 	/*
712*2131Seric 	fork here so 'getbody' can execute 'get' to
713*2131Seric 	print out gotten body :GB:
714*2131Seric 	*/
715*2131Seric 	if ((i = fork()) < 0)
716*2131Seric 		fatal("cannot fork, try again");
717*2131Seric 	if (i = 0) {
718*2131Seric 		/*
719*2131Seric 		perform 'get' and redirect output
720*2131Seric 		to standard output
721*2131Seric 		*/
722*2131Seric 		execl(Getpgm,Getpgm,"-s","-p","-r",rarg,filearg,0);
723*2131Seric 		fatal(sprintf(Error,"cannot execute '%s'",Getpgm));
724*2131Seric 	}
725*2131Seric 	else {
726*2131Seric 		wait(&status);
727*2131Seric 		return;
728*2131Seric 	}
729*2131Seric }
730*2131Seric 
731*2131Seric 
732*2131Seric getit(str,cp)
733*2131Seric register	char	*str, *cp;
734*2131Seric {
735*2131Seric 	cp =+ 2;
736*2131Seric 	NONBLANK(cp);
737*2131Seric 	cp[length(cp) - 1] = '\0';
738*2131Seric 	sprintf(str,"%s",cp);
739*2131Seric }
740*2131Seric 
741*2131Seric 
742*2131Seric aux_create(iop,file,delchar)
743*2131Seric FILE	*iop;
744*2131Seric char	*file;
745*2131Seric char	delchar;
746*2131Seric {
747*2131Seric 
748*2131Seric 	int	n;
749*2131Seric 	int	text;
750*2131Seric 	/*
751*2131Seric 	create auxiliary file for the named section
752*2131Seric 	*/
753*2131Seric 
754*2131Seric 	text = 0;
755*2131Seric 	iop = maket(file);
756*2131Seric 	while ((n = getline(&gpkt)) != NULL && gpkt.p_line[0] != CTLCHAR) {
757*2131Seric 		text = 1;
758*2131Seric 		fputs(n,iop);
759*2131Seric 	}
760*2131Seric 	/*
761*2131Seric 	check to see that delimiter found is correct
762*2131Seric 	*/
763*2131Seric 	if (n == NULL || gpkt.p_line[0] != CTLCHAR || gpkt.p_line[1] != delchar)
764*2131Seric 		fmterr(&gpkt);
765*2131Seric 	if (!text)
766*2131Seric 		fprintf(iop,"No entries\n");
767*2131Seric 	fclose(iop);
768*2131Seric }
769*2131Seric 
770*2131Seric 
771*2131Seric idsetup(gsid,pkt,bdate)
772*2131Seric struct	sid	*gsid;
773*2131Seric struct	packet	*pkt;
774*2131Seric long	*bdate;
775*2131Seric {
776*2131Seric 
777*2131Seric 	register	char	*p;
778*2131Seric 	extern	struct	time	*localtime();
779*2131Seric 
780*2131Seric 	date_ba(bdate,Deltadate);
781*2131Seric 
782*2131Seric 	Deltatime = &Deltadate[9];
783*2131Seric 	Deltadate[8] = 0;
784*2131Seric 
785*2131Seric 	sid_ba(gsid,Sid);
786*2131Seric 
787*2131Seric 	Dtime = localtime(bdate);
788*2131Seric 
789*2131Seric 	if (p = Sflags[MODFLAG - 'a'])
790*2131Seric 		copy(p,Mod);
791*2131Seric 	else sprintf(Mod,"%s",sname(pkt->p_file));
792*2131Seric 
793*2131Seric 	if (!(Type = Sflags[TYPEFLAG - 'a']))
794*2131Seric 		Type = "none";
795*2131Seric }
796