1*2154Seric /************************************************************************/
2*2154Seric /*									*/
3*2154Seric /*  val -                                                               */
4*2154Seric /*  val [-mname] [-rSID] [-s] [-ytype] file ...                         */
5*2154Seric /*                                                                      */
6*2154Seric /************************************************************************/
7*2154Seric 
8*2154Seric # include	"../hdr/defines.h"
9*2154Seric # include	"../hdr/had.h"
10*2154Seric 
11*2154Seric # define	FILARG_ERR	0200	/* no file name given */
12*2154Seric # define	UNKDUP_ERR	0100	/* unknown or duplicate keyletter */
13*2154Seric # define	CORRUPT_ERR	040	/* corrupt file error code */
14*2154Seric # define	FILENAM_ERR	020	/* file name error code */
15*2154Seric # define	INVALSID_ERR	010	/* invalid or ambiguous SID error  */
16*2154Seric # define	NONEXSID_ERR	04	/* non-existent SID error code */
17*2154Seric # define	TYPE_ERR	02	/* type arg value error code */
18*2154Seric # define	NAME_ERR	01	/* name arg value error code */
19*2154Seric # define	TRUE		1
20*2154Seric # define	FALSE		0
21*2154Seric # define	BLANK(l)	while (!(*l == ' ' || *l == '\t')) l++;
22*2154Seric 
23*2154Seric int	ret_code;	/* prime return code from 'main' program */
24*2154Seric int	inline_err;	/* input line error code (from 'process') */
25*2154Seric int	infile_err;	/* file error code (from 'validate') */
26*2154Seric int	inpstd;		/* TRUE = args from standard input */
27*2154Seric 
28*2154Seric struct packet gpkt;
29*2154Seric 
30*2154Seric char	had[26];	/* had flag used in 'process' function */
31*2154Seric char	path[50];	/* storage for file name value */
32*2154Seric char	sid[50];	/* storage for sid (-r) value */
33*2154Seric char	type[50];	/* storage for type (-y) value */
34*2154Seric char	name[50];	/* storage for name (-m) value */
35*2154Seric char	line[BUFSIZ];
36*2154Seric char	*get_line();	/* function returning ptr to line read */
37*2154Seric char	*getval();	/* function returning adjusted ptr to line */
38*2154Seric char	*alloc();	/* function returning ptr */
39*2154Seric char	*fgets();	/* function returning i/o ptr */
40*2154Seric 
41*2154Seric struct delent {		/* structure for delta table entry */
42*2154Seric 	char type;
43*2154Seric 	char *osid;
44*2154Seric 	char *datetime;
45*2154Seric 	char *pgmr;
46*2154Seric 	char *serial;
47*2154Seric 	char *pred;
48*2154Seric } del;
49*2154Seric 
50*2154Seric SCCSID(@(#)val.c	4.1);
51*2154Seric 
52*2154Seric /* This is the main program that determines whether the command line
53*2154Seric  * comes from the standard input or read off the original command
54*2154Seric  * line.  See VAL(I) for more information.
55*2154Seric */
56*2154Seric main(argc,argv)
57*2154Seric int argc;
58*2154Seric char	*argv[];
59*2154Seric {
60*2154Seric 	FILE	*iop;
61*2154Seric 	register int j;
62*2154Seric 
63*2154Seric 	ret_code = 0;
64*2154Seric 	if (argc == 2 && argv[1][0] == '-' && !(argv[1][1])) {
65*2154Seric 		inpstd = TRUE;
66*2154Seric 		iop = stdin;		/* read from standard input */
67*2154Seric 		while (fgets(line,BUFSIZ,iop) != NULL) {
68*2154Seric 			if (line[0] != '\n') {
69*2154Seric 				repl (line,'\n','\0');
70*2154Seric 				process(line);
71*2154Seric 				ret_code =| inline_err;
72*2154Seric 			}
73*2154Seric 		}
74*2154Seric 	}
75*2154Seric 	else {
76*2154Seric 		inpstd = FALSE;
77*2154Seric 		for (j = 1; j < argc; j++)
78*2154Seric 			sprintf(&(line[strlen(line)]),"%s ",argv[j]);
79*2154Seric 		j = strlen(line) - 1;
80*2154Seric 		line[j > 0 ? j : 0] = NULL;
81*2154Seric 		process(line);
82*2154Seric 		ret_code = inline_err;
83*2154Seric 	}
84*2154Seric 	exit(ret_code);
85*2154Seric }
86*2154Seric 
87*2154Seric 
88*2154Seric /* This function processes the line sent by the main routine.  It
89*2154Seric  * determines which keyletter values are present on the command
90*2154Seric  * line and assigns the values to the correct storage place.  It
91*2154Seric  * then calls validate for each file name on the command line
92*2154Seric  * It will return to main if the input line contains an error,
93*2154Seric  * otherwise it returns any error code found by validate.
94*2154Seric */
95*2154Seric process(p_line)
96*2154Seric char	*p_line;
97*2154Seric {
98*2154Seric 	register int	j;
99*2154Seric 	register int	testklt;
100*2154Seric 	register int	line_sw;
101*2154Seric 
102*2154Seric 	int	silent;
103*2154Seric 	int	num_files;
104*2154Seric 
105*2154Seric 	char	filelist[50][50];
106*2154Seric 	char	*savelinep;
107*2154Seric 	char	c;
108*2154Seric 
109*2154Seric 	silent = FALSE;
110*2154Seric 	path[0] = sid[0] = type[0] = name[0] = 0;
111*2154Seric 	num_files = inline_err = 0;
112*2154Seric 
113*2154Seric 	/*
114*2154Seric 	make copy of 'line' for use later
115*2154Seric 	*/
116*2154Seric 	savelinep = p_line;
117*2154Seric 	/*
118*2154Seric 	clear out had flags for each 'line' processed
119*2154Seric 	*/
120*2154Seric 	for (j = 0; j < 27; j++)
121*2154Seric 		had[j] = 0;
122*2154Seric 	/*
123*2154Seric 	execute loop until all characters in 'line' are checked.
124*2154Seric 	*/
125*2154Seric 	while (*p_line) {
126*2154Seric 		testklt = 1;
127*2154Seric 		NONBLANK(p_line);
128*2154Seric 		if (*p_line == '-') {
129*2154Seric 			p_line =+ 1;
130*2154Seric 			c = *p_line;
131*2154Seric 			p_line++;
132*2154Seric 			switch (c) {
133*2154Seric 				case 's':
134*2154Seric 					testklt = 0;
135*2154Seric 					/*
136*2154Seric 					turn on 'silent' flag.
137*2154Seric 					*/
138*2154Seric 					silent = TRUE;
139*2154Seric 					break;
140*2154Seric 				case 'r':
141*2154Seric 					p_line = getval(p_line,sid);
142*2154Seric 					break;
143*2154Seric 				case 'y':
144*2154Seric 					p_line = getval(p_line,type);
145*2154Seric 					break;
146*2154Seric 				case 'm':
147*2154Seric 					p_line = getval(p_line,name);
148*2154Seric 					break;
149*2154Seric 				default:
150*2154Seric 					inline_err =| UNKDUP_ERR;
151*2154Seric 			}
152*2154Seric 			/*
153*2154Seric 			use 'had' array and determine if the keyletter
154*2154Seric 			was given twice.
155*2154Seric 			*/
156*2154Seric 			if (had[c - 'a']++ && testklt++)
157*2154Seric 				inline_err =| UNKDUP_ERR;
158*2154Seric 		}
159*2154Seric 		else {
160*2154Seric 			/*
161*2154Seric 			assume file name if no '-' preceeded argument
162*2154Seric 			*/
163*2154Seric 			p_line = getval(p_line,filelist[num_files]);
164*2154Seric 			num_files++;
165*2154Seric 		}
166*2154Seric 	}
167*2154Seric 	/*
168*2154Seric 	check if any files were named as arguments
169*2154Seric 	*/
170*2154Seric 	if (num_files == 0)
171*2154Seric 		inline_err =| FILARG_ERR;
172*2154Seric 	/*
173*2154Seric 	check for error in command line.
174*2154Seric 	*/
175*2154Seric 	if (inline_err && !silent) {
176*2154Seric 		if (inpstd)
177*2154Seric 			report(inline_err,savelinep,"");
178*2154Seric 		else report(inline_err,"","");
179*2154Seric 		return;		/* return to 'main' routine */
180*2154Seric 	}
181*2154Seric 	line_sw = 1;		/* print command line flag */
182*2154Seric 	/*
183*2154Seric 	loop through 'validate' for each file on command line.
184*2154Seric 	*/
185*2154Seric 	for (j = 0; j < num_files; j++) {
186*2154Seric 		/*
187*2154Seric 		read a file from 'filelist' and place into 'path'.
188*2154Seric 		*/
189*2154Seric 		sprintf(path,"%s",filelist[j]);
190*2154Seric 		validate(path,sid,type,name);
191*2154Seric 		inline_err =| infile_err;
192*2154Seric 		/*
193*2154Seric 		check for error from 'validate' and call 'report'
194*2154Seric 		depending on 'silent' flag.
195*2154Seric 		*/
196*2154Seric 		if (infile_err && !silent) {
197*2154Seric 			if (line_sw && inpstd) {
198*2154Seric 				report(infile_err,savelinep,path);
199*2154Seric 				line_sw = 0;
200*2154Seric 			}
201*2154Seric 			else report(infile_err,"",path);
202*2154Seric 		}
203*2154Seric 	}
204*2154Seric 	return;		/* return to 'main' routine */
205*2154Seric }
206*2154Seric 
207*2154Seric 
208*2154Seric /* This function actually does the validation on the named file.
209*2154Seric  * It determines whether the file is an SCCS-file or if the file
210*2154Seric  * exists.  It also determines if the values given for type, SID,
211*2154Seric  * and name match those in the named file.  An error code is returned
212*2154Seric  * if any mismatch occurs.  See VAL(I) for more information.
213*2154Seric */
214*2154Seric validate(c_path,c_sid,c_type,c_name)
215*2154Seric char	*c_path;
216*2154Seric char	*c_sid;
217*2154Seric char	*c_type;
218*2154Seric char	*c_name;
219*2154Seric {
220*2154Seric 	register char	*l;
221*2154Seric 	int	goods,goodt,goodn,hadmflag;
222*2154Seric 
223*2154Seric 	infile_err = goods = goodt = goodn = hadmflag = 0;
224*2154Seric 	sinit(&gpkt,c_path);
225*2154Seric 	if (!sccsfile(c_path) || (gpkt.p_iop = fopen(c_path,"r")) == NULL)
226*2154Seric 		infile_err =| FILENAM_ERR;
227*2154Seric 	else {
228*2154Seric 		l = get_line(&gpkt);		/* read first line in file */
229*2154Seric 		/*
230*2154Seric 		check that it is header line.
231*2154Seric 		*/
232*2154Seric 		if (*l++ != CTLCHAR || *l++ != HEAD)
233*2154Seric 			infile_err =| CORRUPT_ERR;
234*2154Seric 
235*2154Seric 		else {
236*2154Seric 			/*
237*2154Seric 			get old file checksum count
238*2154Seric 			*/
239*2154Seric 			satoi(l,&gpkt.p_ihash);
240*2154Seric 			gpkt.p_chash = 0;
241*2154Seric 			if (HADR)
242*2154Seric 				/*
243*2154Seric 				check for invalid or ambiguous SID.
244*2154Seric 				*/
245*2154Seric 				if (invalid(c_sid))
246*2154Seric 					infile_err =| INVALSID_ERR;
247*2154Seric 			/*
248*2154Seric 			read delta table checking for errors and/or
249*2154Seric 			SID.
250*2154Seric 			*/
251*2154Seric 			if (do_delt(&gpkt,goods,c_sid)) {
252*2154Seric 				fclose(gpkt.p_iop);
253*2154Seric 				infile_err =| CORRUPT_ERR;
254*2154Seric 				return;
255*2154Seric 			}
256*2154Seric 
257*2154Seric 			read_to(EUSERNAM,&gpkt);
258*2154Seric 
259*2154Seric 			if (HADY || HADM) {
260*2154Seric 				/*
261*2154Seric 				read flag section of delta table.
262*2154Seric 				*/
263*2154Seric 				while ((l = get_line(&gpkt)) &&
264*2154Seric 					*l++ == CTLCHAR &&
265*2154Seric 					*l++ == FLAG) {
266*2154Seric 					NONBLANK(l);
267*2154Seric 					repl(l,'\n','\0');
268*2154Seric 					if (*l == TYPEFLAG) {
269*2154Seric 						l =+ 2;
270*2154Seric 						if (equal(c_type,l))
271*2154Seric 							goodt++;
272*2154Seric 					}
273*2154Seric 					else if (*l == MODFLAG) {
274*2154Seric 						hadmflag++;
275*2154Seric 						l =+ 2;
276*2154Seric 						if (equal(c_name,l))
277*2154Seric 							goodn++;
278*2154Seric 					}
279*2154Seric 				}
280*2154Seric 				if (*(--l) != BUSERTXT) {
281*2154Seric 					fclose(gpkt.p_iop);
282*2154Seric 					infile_err =| CORRUPT_ERR;
283*2154Seric 					return;
284*2154Seric 				}
285*2154Seric 				/*
286*2154Seric 				check if 'y' flag matched '-y' arg value.
287*2154Seric 				*/
288*2154Seric 				if (!goodt && HADY)
289*2154Seric 					infile_err =| TYPE_ERR;
290*2154Seric 				/*
291*2154Seric 				check if 'm' flag matched '-m' arg value.
292*2154Seric 				*/
293*2154Seric 				if (HADM && !hadmflag) {
294*2154Seric 					if (!equal(auxf(sname(c_path),'g'),c_name))
295*2154Seric 						infile_err =| NAME_ERR;
296*2154Seric 				}
297*2154Seric 				else if (HADM && hadmflag && !goodn)
298*2154Seric 						infile_err =| NAME_ERR;
299*2154Seric 			}
300*2154Seric 			else read_to(BUSERTXT,&gpkt);
301*2154Seric 			read_to(EUSERTXT,&gpkt);
302*2154Seric 			gpkt.p_chkeof = 1;
303*2154Seric 			/*
304*2154Seric 			read remainder of file so 'read_mod'
305*2154Seric 			can check for corruptness.
306*2154Seric 			*/
307*2154Seric 			while (read_mod(&gpkt))
308*2154Seric 				;
309*2154Seric 		}
310*2154Seric 	fclose(gpkt.p_iop);	/* close file pointer */
311*2154Seric 	}
312*2154Seric 	return;		/* return to 'process' function */
313*2154Seric }
314*2154Seric 
315*2154Seric 
316*2154Seric /* This function reads the 'delta' line from the named file and stores
317*2154Seric  * the information into the structure 'del'.
318*2154Seric */
319*2154Seric getdel(delp,lp)
320*2154Seric register struct delent *delp;
321*2154Seric register char *lp;
322*2154Seric {
323*2154Seric 	NONBLANK(lp);
324*2154Seric 	delp->type = *lp++;
325*2154Seric 	NONBLANK(lp);
326*2154Seric 	delp->osid = lp;
327*2154Seric 	BLANK(lp);
328*2154Seric 	*lp++ = '\0';
329*2154Seric 	NONBLANK(lp);
330*2154Seric 	delp->datetime = lp;
331*2154Seric 	BLANK(lp);
332*2154Seric 	NONBLANK(lp);
333*2154Seric 	BLANK(lp);
334*2154Seric 	*lp++ = '\0';
335*2154Seric 	NONBLANK(lp);
336*2154Seric 	delp->pgmr = lp;
337*2154Seric 	BLANK(lp);
338*2154Seric 	*lp++ = '\0';
339*2154Seric 	NONBLANK(lp);
340*2154Seric 	delp->serial = lp;
341*2154Seric 	BLANK(lp);
342*2154Seric 	*lp++ = '\0';
343*2154Seric 	NONBLANK(lp);
344*2154Seric 	delp->pred = lp;
345*2154Seric 	repl(lp,'\n','\0');
346*2154Seric }
347*2154Seric 
348*2154Seric 
349*2154Seric /* This function does a read through the named file until it finds
350*2154Seric  * the character sent over as an argument.
351*2154Seric */
352*2154Seric read_to(ch,pkt)
353*2154Seric register char ch;
354*2154Seric register struct packet *pkt;
355*2154Seric {
356*2154Seric 	register char *n;
357*2154Seric 	while ((n = get_line(pkt)) &&
358*2154Seric 			!(*n++ == CTLCHAR && *n == ch))
359*2154Seric 		;
360*2154Seric 	return;
361*2154Seric }
362*2154Seric 
363*2154Seric 
364*2154Seric /* This function places into a specified destination characters  which
365*2154Seric  * are delimited by either a space, tab or 0.  It obtains the char-
366*2154Seric  * acters from a line of characters.
367*2154Seric */
368*2154Seric char	*getval(sourcep,destp)
369*2154Seric register char	*sourcep;
370*2154Seric register char	*destp;
371*2154Seric {
372*2154Seric 	while (*sourcep != ' ' && *sourcep != '\t' && *sourcep != '\0')
373*2154Seric 		*destp++ = *sourcep++;
374*2154Seric 	*destp = 0;
375*2154Seric 	return(sourcep);
376*2154Seric }
377*2154Seric 
378*2154Seric 
379*2154Seric /* This function will report the error that occured on the command
380*2154Seric  * line.  It will print one diagnostic message for each error that
381*2154Seric  * was found in the named file.
382*2154Seric */
383*2154Seric report(code,inp_line,file)
384*2154Seric register int	code;
385*2154Seric register char	*inp_line;
386*2154Seric register char	*file;
387*2154Seric {
388*2154Seric 	char	percent;
389*2154Seric 	percent = '%';		/* '%' for -m and/or -y messages */
390*2154Seric 	if (*inp_line)
391*2154Seric 		printf("%s\n\n",inp_line);
392*2154Seric 	if (code & NAME_ERR)
393*2154Seric 		printf("    %s: %cM%c, -m mismatch\n",file,percent,percent);
394*2154Seric 	if (code & TYPE_ERR)
395*2154Seric 		printf("    %s: %cY%c, -y mismatch\n",file,percent,percent);
396*2154Seric 	if (code & NONEXSID_ERR)
397*2154Seric 		printf("    %s: SID nonexistent\n",file);
398*2154Seric 	if (code & INVALSID_ERR)
399*2154Seric 		printf("    %s: SID invalid or ambiguous\n",file);
400*2154Seric 	if (code & FILENAM_ERR)
401*2154Seric 		printf("    %s: can't open file or file not SCCS\n",file);
402*2154Seric 	if (code & CORRUPT_ERR)
403*2154Seric 		printf("    %s: corrupted SCCS file\n",file);
404*2154Seric 	if (code & UNKDUP_ERR)
405*2154Seric 		printf("    %s: Unknown or dupilcate keyletter argument\n",file);
406*2154Seric 	if (code & FILARG_ERR)
407*2154Seric 		printf("    %s: missing file argument\n",file);
408*2154Seric 	return;
409*2154Seric }
410*2154Seric 
411*2154Seric 
412*2154Seric /* This function takes as it's argument the SID inputed and determines
413*2154Seric  * whether or not it is valid (e. g. not ambiguous or illegal).
414*2154Seric */
415*2154Seric invalid(i_sid)
416*2154Seric register char	*i_sid;
417*2154Seric {
418*2154Seric 	register int count;
419*2154Seric 	register int digits;
420*2154Seric 	count = digits = 0;
421*2154Seric 	if (*i_sid == '0' || *i_sid == '.')
422*2154Seric 		return (1);
423*2154Seric 	i_sid++;
424*2154Seric 	digits++;
425*2154Seric 	while (*i_sid != '\0') {
426*2154Seric 		if (*i_sid++ == '.') {
427*2154Seric 			digits = 0;
428*2154Seric 			count++;
429*2154Seric 			if (*i_sid == '0' || *i_sid == '.')
430*2154Seric 				return (1);
431*2154Seric 		}
432*2154Seric 		digits++;
433*2154Seric 		if (digits > 5)
434*2154Seric 			return (1);
435*2154Seric 	}
436*2154Seric 	if (*(--i_sid) == '.' )
437*2154Seric 		return (1);
438*2154Seric 	if (count == 1 || count == 3)
439*2154Seric 		return (0);
440*2154Seric 	return (1);
441*2154Seric }
442*2154Seric 
443*2154Seric 
444*2154Seric /*
445*2154Seric 	Routine to read a line into the packet.  The main reason for
446*2154Seric 	it is to make sure that pkt->p_wrttn gets turned off,
447*2154Seric 	and to increment pkt->p_slnno.
448*2154Seric */
449*2154Seric 
450*2154Seric char	*get_line(pkt)
451*2154Seric register struct packet *pkt;
452*2154Seric {
453*2154Seric 	register char *n;
454*2154Seric 	register char *p;
455*2154Seric 
456*2154Seric 	if ((n = fgets(pkt->p_line,sizeof(pkt->p_line),pkt->p_iop)) != NULL) {
457*2154Seric 		pkt->p_slnno++;
458*2154Seric 		for (p = pkt->p_line; *p; )
459*2154Seric 			pkt->p_chash =+ *p++;
460*2154Seric 	}
461*2154Seric 	else {
462*2154Seric 		if (!pkt->p_chkeof)
463*2154Seric 			infile_err =| CORRUPT_ERR;
464*2154Seric 		if (pkt->do_chksum && (pkt->p_chash ^ pkt->p_ihash)&0xFFFF)
465*2154Seric 			infile_err =| CORRUPT_ERR;
466*2154Seric 	}
467*2154Seric 	return(n);
468*2154Seric }
469*2154Seric 
470*2154Seric 
471*2154Seric /*
472*2154Seric 	Does initialization for sccs files and packet.
473*2154Seric */
474*2154Seric 
475*2154Seric sinit(pkt,file)
476*2154Seric register struct packet *pkt;
477*2154Seric register char *file;
478*2154Seric {
479*2154Seric 
480*2154Seric 	zero(pkt,sizeof(*pkt));
481*2154Seric 	copy(file,pkt->p_file);
482*2154Seric 	pkt->p_wrttn = 1;
483*2154Seric 	pkt->do_chksum = 1;	/* turn on checksum check for getline */
484*2154Seric }
485*2154Seric 
486*2154Seric 
487*2154Seric read_mod(pkt)
488*2154Seric register struct packet *pkt;
489*2154Seric {
490*2154Seric 	register char *p;
491*2154Seric 	int ser;
492*2154Seric 	int iord;
493*2154Seric 	register struct apply *ap;
494*2154Seric 
495*2154Seric 	while (get_line(pkt) != NULL) {
496*2154Seric 		p = pkt->p_line;
497*2154Seric 		if (*p++ != CTLCHAR)
498*2154Seric 			continue;
499*2154Seric 		else {
500*2154Seric 			if (!((iord = *p++) == INS || iord == DEL || iord == END)) {
501*2154Seric 				infile_err =| CORRUPT_ERR;
502*2154Seric 				return(0);
503*2154Seric 			}
504*2154Seric 			NONBLANK(p);
505*2154Seric 			satoi(p,&ser);
506*2154Seric 			if (iord == END)
507*2154Seric 				remq(pkt,ser);
508*2154Seric 			else if ((ap = &pkt->p_apply[ser])->a_code == APPLY)
509*2154Seric 				addq(pkt,ser,iord == INS ? YES : NO,iord,ap->a_reason & USER);
510*2154Seric 			else
511*2154Seric 				addq(pkt,ser,iord == INS ? NO : NULL,iord,ap->a_reason & USER);
512*2154Seric 		}
513*2154Seric 	}
514*2154Seric 	if (pkt->p_q)
515*2154Seric 		infile_err =| CORRUPT_ERR;
516*2154Seric 	return(0);
517*2154Seric }
518*2154Seric 
519*2154Seric 
520*2154Seric addq(pkt,ser,keep,iord,user)
521*2154Seric struct packet *pkt;
522*2154Seric int ser;
523*2154Seric int keep;
524*2154Seric int iord;
525*2154Seric {
526*2154Seric 	register struct queue *cur, *prev, *q;
527*2154Seric 
528*2154Seric 	for (cur = &pkt->p_q; cur = (prev = cur)->q_next; )
529*2154Seric 		if (cur->q_sernum <= ser)
530*2154Seric 			break;
531*2154Seric 	if (cur->q_sernum == ser)
532*2154Seric 		infile_err =| CORRUPT_ERR;
533*2154Seric 	prev->q_next = q = alloc(sizeof(*q));
534*2154Seric 	q->q_next = cur;
535*2154Seric 	q->q_sernum = ser;
536*2154Seric 	q->q_keep = keep;
537*2154Seric 	q->q_iord = iord;
538*2154Seric 	q->q_user = user;
539*2154Seric 	if (pkt->p_ixuser && (q->q_ixmsg = chkix(q,&pkt->p_q)))
540*2154Seric 		++(pkt->p_ixmsg);
541*2154Seric 	else
542*2154Seric 		q->q_ixmsg = 0;
543*2154Seric 
544*2154Seric 	setkeep(pkt);
545*2154Seric }
546*2154Seric 
547*2154Seric 
548*2154Seric remq(pkt,ser)
549*2154Seric register struct packet *pkt;
550*2154Seric int ser;
551*2154Seric {
552*2154Seric 	register struct queue *cur, *prev;
553*2154Seric 
554*2154Seric 	for (cur = &pkt->p_q; cur = (prev = cur)->q_next; )
555*2154Seric 		if (cur->q_sernum == ser)
556*2154Seric 			break;
557*2154Seric 	if (cur) {
558*2154Seric 		if (cur->q_ixmsg)
559*2154Seric 			--(pkt->p_ixmsg);
560*2154Seric 		prev->q_next = cur->q_next;
561*2154Seric 		free(cur);
562*2154Seric 		setkeep(pkt);
563*2154Seric 	}
564*2154Seric 	else
565*2154Seric 		infile_err =| CORRUPT_ERR;
566*2154Seric }
567*2154Seric 
568*2154Seric 
569*2154Seric setkeep(pkt)
570*2154Seric register struct packet *pkt;
571*2154Seric {
572*2154Seric 	register struct queue *q;
573*2154Seric 	register struct sid *sp;
574*2154Seric 
575*2154Seric 	for (q = &pkt->p_q; q = q->q_next; )
576*2154Seric 		if (q->q_keep != NULL) {
577*2154Seric 			if ((pkt->p_keep = q->q_keep) == YES) {
578*2154Seric 				sp = &pkt->p_idel[q->q_sernum].i_sid;
579*2154Seric 				pkt->p_inssid.s_rel = sp->s_rel;
580*2154Seric 				pkt->p_inssid.s_lev = sp->s_lev;
581*2154Seric 				pkt->p_inssid.s_br = sp->s_br;
582*2154Seric 				pkt->p_inssid.s_seq = sp->s_seq;
583*2154Seric 			}
584*2154Seric 			return;
585*2154Seric 		}
586*2154Seric 	pkt->p_keep = NO;
587*2154Seric }
588*2154Seric 
589*2154Seric 
590*2154Seric # define apply(qp)	((qp->q_iord == INS && qp->q_keep == YES) || (qp->q_iord == DEL && qp->q_keep == NO))
591*2154Seric 
592*2154Seric chkix(new,head)
593*2154Seric register struct queue *new;
594*2154Seric struct queue *head;
595*2154Seric {
596*2154Seric 	register int retval;
597*2154Seric 	register struct queue *cur;
598*2154Seric 	int firstins, lastdel;
599*2154Seric 
600*2154Seric 	if (!apply(new))
601*2154Seric 		return(0);
602*2154Seric 	for (cur = head; cur = cur->q_next; )
603*2154Seric 		if (cur->q_user)
604*2154Seric 			break;
605*2154Seric 	if (!cur)
606*2154Seric 		return(0);
607*2154Seric 	retval = 0;
608*2154Seric 	firstins = 0;
609*2154Seric 	lastdel = 0;
610*2154Seric 	for (cur = head; cur = cur->q_next; ) {
611*2154Seric 		if (apply(cur)) {
612*2154Seric 			if (cur->q_iord == DEL)
613*2154Seric 				lastdel = cur->q_sernum;
614*2154Seric 			else if (firstins == 0)
615*2154Seric 				firstins = cur->q_sernum;
616*2154Seric 		}
617*2154Seric 		else if (cur->q_iord == INS)
618*2154Seric 			retval++;
619*2154Seric 	}
620*2154Seric 	if (retval == 0) {
621*2154Seric 		if (lastdel && (new->q_sernum > lastdel))
622*2154Seric 			retval++;
623*2154Seric 		if (firstins && (new->q_sernum < firstins))
624*2154Seric 			retval++;
625*2154Seric 	}
626*2154Seric 	return(retval);
627*2154Seric }
628*2154Seric 
629*2154Seric 
630*2154Seric /* This function reads the delta table entries and checks for the format
631*2154Seric  * as specifed in sccsfile(V).  If the format is incorrect, a corrupt
632*2154Seric  * error will be issued by 'val'.  This function also checks
633*2154Seric  * if the sid requested is in the file (depending if '-r' was specified).
634*2154Seric */
635*2154Seric do_delt(pkt,goods,d_sid)
636*2154Seric register struct packet *pkt;
637*2154Seric register int goods;
638*2154Seric register char *d_sid;
639*2154Seric {
640*2154Seric 	char *l;
641*2154Seric 
642*2154Seric 	while(getstats(pkt)) {
643*2154Seric 		if ((l = get_line(pkt)) && *l++ != CTLCHAR || *l++ != BDELTAB)
644*2154Seric 			return(1);
645*2154Seric 		if (HADR && !(infile_err & INVALSID_ERR)) {
646*2154Seric 			getdel(&del,l);
647*2154Seric 			if (equal(d_sid,del.osid) && del.type == 'D')
648*2154Seric 				goods++;
649*2154Seric 		}
650*2154Seric 		while ((l = get_line(pkt)) != NULL)
651*2154Seric 			if (pkt->p_line[0] != CTLCHAR)
652*2154Seric 				break;
653*2154Seric 			else {
654*2154Seric 				switch(pkt->p_line[1]) {
655*2154Seric 				case EDELTAB:
656*2154Seric 					break;
657*2154Seric 				case COMMENTS:
658*2154Seric 				case MRNUM:
659*2154Seric 				case INCLUDE:
660*2154Seric 				case EXCLUDE:
661*2154Seric 				case IGNORE:
662*2154Seric 					continue;
663*2154Seric 				default:
664*2154Seric 					return(1);
665*2154Seric 				}
666*2154Seric 				break;
667*2154Seric 			}
668*2154Seric 		if (l == NULL || pkt->p_line[0] != CTLCHAR)
669*2154Seric 			return(1);
670*2154Seric 	}
671*2154Seric 	if (pkt->p_line[1] != BUSERNAM)
672*2154Seric 		return(1);
673*2154Seric 	if (HADR && !goods && !(infile_err & INVALSID_ERR))
674*2154Seric 		infile_err =| NONEXSID_ERR;
675*2154Seric 	return(0);
676*2154Seric }
677*2154Seric 
678*2154Seric 
679*2154Seric /* This function reads the stats line from the sccsfile */
680*2154Seric getstats(pkt)
681*2154Seric register struct packet *pkt;
682*2154Seric {
683*2154Seric 	register char *p;
684*2154Seric 	p = pkt->p_line;
685*2154Seric 	if (get_line(pkt) == NULL || *p++ != CTLCHAR || *p != STATS)
686*2154Seric 		return(0);
687*2154Seric 	return(1);
688*2154Seric }
689