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