12151Seric #
22151Seric /*
32151Seric 	Program to convert release 3 (or release 2 or even 1) SCCS files
42151Seric 	to release 4 SCCS files.
52151Seric 	Usage:
62151Seric 		scv arg ...
72151Seric 	arg is any argument acceptable as an SCCS file
82151Seric 	name argument to the get command. E.g.:
92151Seric 		scv mysccsdir
102151Seric 	will convert every release 3 (or 2 or 1 but NOT 4) SCCS file in the
112151Seric 	directory "mysccsdir".
122151Seric */
132151Seric # include	"../hdr/defines.h"
142151Seric # include	"dir.h"
152151Seric 
16*33423Sbostic SCCSID(@(#)scv.c	4.7);
172151Seric 
182160Seric 
192151Seric /*
202151Seric 	Release 3 SCCS File Structures  (2.1  78/06/05 17:31:17)
212151Seric 	See osccsfile(V).
222151Seric */
232151Seric 
242151Seric struct Header {
252151Seric 	short  Hmagicno;
262151Seric 	char Htype[10];
272151Seric 	char Hpers[14];
282151Seric 	char Hdesc[100];
292151Seric 	short  Hfloor;
302151Seric 	short  Hceil;
312151Seric 	short  Hsw[5];
322151Seric 	short  Hrdef;
332151Seric 	char Hulist[32];
342151Seric 	char Hexpand[50];
352151Seric 	short  Hash;
362151Seric };
372151Seric #define MAGICNO (7)
382151Seric #define HASHADDR (226)
392151Seric 
402151Seric 
412151Seric struct Reltab {
422151Seric 	short  Rrel;
432151Seric 	short  Rlevs;
442151Seric };
452151Seric 
462151Seric 
472151Seric struct Deltab {
482151Seric 	short  Drel;
492151Seric 	short  Dlev;
502151Seric 	char Dtype;	/*'D': delta,'P','U': non-prop,'I': incl,'E': excl */
512151Seric 	char Dfill;	/* Used to be option letter */
522151Seric /* compiler once forced unfortunate alignment here.
532151Seric /* also, fp-11c high/low long goof strikes again.
542151Seric /*	long  Ddatetime;
552151Seric */
562151Seric 	short Ddthi,Ddtlo;
576173Seric 	char Dpgmr[SZLNAM];
582151Seric 	char Dhist[200];
592151Seric };
602151Seric 
612151Seric 
622151Seric struct Control {
632151Seric 	short  Crel;
642151Seric 	short  Clev;
652151Seric 	char Cctl;	/* -11: ins, -12: del, -13: end */
662151Seric };
672151Seric #define SIZEOFCONTROL (5)
682151Seric #define OINS (-11)
692151Seric #define ODEL (-12)
702151Seric #define OEND (-13)
712151Seric 
722151Seric 
732151Seric struct Line {
742151Seric 	char Lline [256];
752151Seric };
762151Seric 
772151Seric 
782151Seric /*
792151Seric 	Structure for use with buffered I/O routines opnl, opnr,
802151Seric 	getl and getr.
812151Seric */
822151Seric struct Ibufr {
832151Seric 	short  Ifildes;
842151Seric 	char *Irecptr;
852151Seric 	char *Iend;
862151Seric 	char Ibuff1[256];
872151Seric 	char Ibuff2[512];
882151Seric 	char Ibuff3[2];
892151Seric 	short  Ilen;
902151Seric 	short  Ihflag;
912151Seric 	short  Ihcnt;
922151Seric 	short  Ihtot;
932151Seric };
942151Seric 
952151Seric 
962151Seric /*
972151Seric 	Structure for use with buffered I/O routines crtr, crtl, putl,
982151Seric 	putr, flshr and buflsh.
992151Seric */
1002151Seric struct Obufr {
1012151Seric 	short  Ofildes;
1022151Seric 	char *Orecptr;
1032151Seric 	char *Oend;
1042151Seric 	char Obuff1[512];
1052151Seric 	short  Ohflag;
1062151Seric 	short  Ohcnt;
1072151Seric };
1082151Seric 
1092151Seric 
1102151Seric /*
1112151Seric  * structure to access an
1122151Seric  * shorteger in bytes
1132151Seric  */
1142151Seric struct
1152151Seric {
1162151Seric 	char	lobyte;
1172151Seric 	char	hibyte;
1182151Seric };
1192151Seric 
1202151Seric 
1212151Seric /*
1222151Seric  * structure to access an shorteger
1232151Seric  */
1242151Seric struct
1252151Seric {
1262151Seric 	short	shorteg;
1272151Seric };
1282151Seric 
1292151Seric 
1302151Seric /*
1312151Seric  * structure to access a long as shortegers
1322151Seric  */
1332151Seric struct {
1342151Seric 	short	hiword;
1352151Seric 	short	loword;
1362151Seric };
1372151Seric 
1382151Seric 
1392151Seric /*
1402151Seric 	Structure for referencing pieces of localtime().
1412151Seric */
1422151Seric struct Time {
1432151Seric 	short	Tseconds;
1442151Seric 	short	Tminutes;
1452151Seric 	short	Thours;
1462151Seric 	short	Tday_month;
1472151Seric 	short	Tmonth;
1482151Seric 	short	Tyear;
1492151Seric 	short	Tday_week;
1502151Seric 	short	Tday_year;
1512151Seric 	short	Tflag;
1522151Seric };
1532151Seric /*
1542151Seric 	SCCS Internal Structures (used by get and delta).     (2.1)
1552151Seric */
1562151Seric 
1572151Seric struct Apply {
1582151Seric 	short    Adt;		/* pseudo date-time */
1592151Seric 	short    Acode;		/* APPLY, NOAPPLY or EMPTY */
1602151Seric };
1612151Seric #define APPLY	  (1)
1622151Seric #define NOAPPLY  (-1)
1632151Seric #define EMPTY	  (0)
1642151Seric 
1652151Seric 
1662151Seric struct Queue {
1672151Seric 	struct Queue *Qnext;
1682151Seric 	short    Qrel;		/* release */
1692151Seric 	short    Qlev;		/* level */
1702151Seric 	short    Qdt;		/* pseudo date-time */
1712151Seric 	short    Qkeep;		/* keep switch setting */
1722151Seric };
1732151Seric #define YES	 (1)
1742151Seric #define NO	(-1)
1752151Seric 
1762151Seric #define SIZEOFPfile (50)
1772151Seric 
1782151Seric 
1792151Seric struct Packet {
1802151Seric 	char	Pfile[SIZEOFPfile];	/* file name containing module */
1812151Seric /*
1822151Seric 			Note: the order of the next two words
1832151Seric 				can not___ be changed!
1842151Seric 			This is because the release and level together
1852151Seric 			are treated as a long.
1862151Seric */
1872151Seric 	short	Prel;		/* specified release (-1 = not spec.) */
1882151Seric 	short	Plev;		/* specified level (-1 = not spec.)*/
1892151Seric 	char	Pverbose;	/* verbose flags (see #define's below) */
1902151Seric 	char	Pupd;		/* update flag (!0 = update mode) */
1912151Seric 	long    Pcutoff;	/* specified cutoff date-time */
1922151Seric 	struct	Header	Phdr;	/* header from module */
1932151Seric 	short	Plnno;		/* line number of current line */
1942151Seric 	short	Precno;		/* record number of current rec */
1952151Seric 	char	Pwrttn;		/* written flag (!0 = written) */
1962151Seric 	char	Pkeep;		/* keep switch for readmod() */
1972151Seric 	struct	Apply **Papply;	/* ptr to apply array */
1982151Seric 	struct	Queue *Pq;	/* ptr to control queue */
1992151Seric 	struct	Ibufr Pibuf;	/* input buffer */
2002151Seric 	long	Pcdt;		/* date/time of newest applied delta */
2012151Seric 	char	*Plfile;	/* 0 = no l-file; else ptr to l arg */
2022151Seric 	char	Punack;		/* !0 if unacknowledged non-prop deltas */
2032151Seric 	char	Pnoprop;	/* !0 if new delta is to be non-prop */
2042151Seric 	short	Pirel;		/* rel which inserted current rec */
2052151Seric 	short	Pilev;		/* lev which inserted current rec */
2062151Seric };
2072151Seric /*
2082151Seric 	Masks for Pverbose
2092151Seric */
2102151Seric 
2112151Seric # define RLACCESS	(1)
2122151Seric # define NLINES		(2)
2132151Seric # define DOLIST		(4)
2142151Seric # define UNACK		(8)
2152151Seric # define NEWRL		(16)
2162151Seric # define WARNING	(32)
2172151Seric 
2182151Seric /*
2192151Seric 	size of login name
2202151Seric */
2212151Seric 
2222151Seric 
2232151Seric USXALLOC();
2242151Seric 
main(argc,argv)2252151Seric main(argc,argv)
2262151Seric char **argv;
2272151Seric {
2282151Seric 	register short i;
2292151Seric 	register char *p;
2302151Seric 	extern conv();
2312151Seric 	extern short Fcnt;
2322151Seric 
2332151Seric 	setsig();
2342151Seric 	Fflags = FTLMSG | FTLCLN | FTLJMP;
2352151Seric 	for (i = 1; i < argc; i++)
2362151Seric 		if (p = argv[i])
2372151Seric 			odo_file(p,conv);
2382151Seric 	exit(Fcnt ? 1 : 0);
2392151Seric }
2402151Seric 
2412151Seric 
2422151Seric struct packet npkt;
2432151Seric 
conv(ofile)2442151Seric conv(ofile)
2452151Seric char *ofile;
2462151Seric {
2472151Seric 	struct Packet opkt;
2482151Seric 	struct deltab *dt;
2492151Seric 	char **hists;
2502151Seric 	short **rlp;
2512151Seric 	char statstr[32];
2522151Seric 	short ndels;
2532151Seric 	char *line;
2542151Seric 	short n;
2552151Seric 	char *p;
2562151Seric 
2572151Seric 	if (setjmp(Fjmp))
2582151Seric 		return;
2592151Seric 	printf("%s:\n",ofile);
2602151Seric 	ckpfile(auxf(ofile,'p'));
26119943Ssam 	bzero(&opkt,sizeof(opkt));
2622151Seric 	opnr(&opkt.Pibuf,ofile);
2632151Seric 	dohead(&opkt);
2642151Seric 	rlp = 0;
2652151Seric 	ndels = doreltab(&opkt,&rlp);
2662151Seric 	hists = alloc((ndels + 1) * sizeof(*hists));
2672151Seric 	dt = alloc((ndels + 1) * sizeof(*dt));
2682151Seric 	dodelt(&opkt,dt,hists,ndels);
2692151Seric 	fixup(dt,ndels,rlp);
2702151Seric 	sinit(&npkt,ofile,0);
2712151Seric 	npkt.p_upd = 1;
2722151Seric 	line = npkt.p_line;
273*33423Sbostic 	sprintf(line,"%c%c00000\n",CTLCHAR,HEAD);
274*33423Sbostic 	putline(&npkt,line);
2752151Seric 	statstr[0] = 0;
2762151Seric 	for (n = ndels; n; n--) {
2772151Seric 		if (!statstr[0])
2782151Seric 			newstats(&npkt,statstr,"?");
2792151Seric 		else
2802151Seric 			putline(&npkt,statstr);
2812151Seric 		putline(&npkt,del_ba(&dt[n],line));
282*33423Sbostic 		sprintf(line,"%c%c %s\n",CTLCHAR,COMMENTS,hists[n]);
283*33423Sbostic 		putline(&npkt,line);
284*33423Sbostic 		sprintf(line,CTLSTR,CTLCHAR,EDELTAB);
285*33423Sbostic 		putline(&npkt,line);
2862151Seric 	}
287*33423Sbostic 	sprintf(line,CTLSTR,CTLCHAR,BUSERNAM);
288*33423Sbostic 	putline(&npkt,line);
2892151Seric 	dousers(opkt.Phdr.Hulist,&npkt);
290*33423Sbostic 	sprintf(line,CTLSTR,CTLCHAR,EUSERNAM);
291*33423Sbostic 	putline(&npkt,line);
292*33423Sbostic 	if (*(p = opkt.Phdr.Htype)) {
293*33423Sbostic 		sprintf(line,"%c%c %c %s\n",CTLCHAR,FLAG,TYPEFLAG,p);
294*33423Sbostic 		putline(&npkt,line);
295*33423Sbostic 	}
296*33423Sbostic 	if (n = opkt.Phdr.Hfloor) {
297*33423Sbostic 		sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG,FLORFLAG,n);
298*33423Sbostic 		putline(&npkt,line);
299*33423Sbostic 	}
300*33423Sbostic 	if (n = opkt.Phdr.Hceil) {
301*33423Sbostic 		sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG,CEILFLAG,n);
302*33423Sbostic 		putline(&npkt,line);
303*33423Sbostic 	}
304*33423Sbostic 	if (n = opkt.Phdr.Hrdef) {
305*33423Sbostic 		sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG,DEFTFLAG,n);
306*33423Sbostic 		putline(&npkt,line);
307*33423Sbostic 	}
308*33423Sbostic 	sprintf(line,CTLSTR,CTLCHAR,BUSERTXT);
309*33423Sbostic 	putline(&npkt,line);
310*33423Sbostic 	if (*(p = opkt.Phdr.Hpers)) {
311*33423Sbostic 		sprintf(line,"%s\n",p);
312*33423Sbostic 		putline(&npkt,line);
313*33423Sbostic 	}
314*33423Sbostic 	if (*(p = opkt.Phdr.Hdesc)) {
315*33423Sbostic 		sprintf(line,"%s\n",p);
316*33423Sbostic 		putline(&npkt,line);
317*33423Sbostic 	}
318*33423Sbostic 	sprintf(line,CTLSTR,CTLCHAR,EUSERTXT);
319*33423Sbostic 	putline(&npkt,line);
3202151Seric 	dobod(&opkt,&npkt,rlp,line);
3212151Seric 	convflush(&npkt);
3222151Seric 	close(opkt.Pibuf.Ifildes);
3232151Seric 	for (n = ndels; n; n--)
3242151Seric 		free(hists[n]);
3252151Seric 	free(hists);
3262151Seric 	free(dt);
3272151Seric /* [compiler bug, ignore this for now ]
3282151Seric 	if (rlp) {
3292151Seric 		for (n = (short) (*rlp); n; n--)
3302151Seric 			if (rlp[n])
3312151Seric 				free(rlp[n]);
3322151Seric 		free(rlp);
3332151Seric 	}
3342151Seric */
3352151Seric 	rename(auxf(npkt.p_file,'x'),npkt.p_file);
3362151Seric 	xrm(&npkt);
3372151Seric }
3382151Seric 
3392151Seric 
getline()3402151Seric getline()
3412151Seric {
3422151Seric }
3432151Seric 
3442151Seric 
clean_up()3452151Seric clean_up()
3462151Seric {
3472151Seric 	xrm(&npkt);
3482151Seric }
3492151Seric 
3502151Seric 
3512151Seric 
3522151Seric fixup(dt,ndels,rlp)
3532151Seric struct deltab *dt;
3542151Seric short ndels;
3552151Seric short **rlp;
3562151Seric {
3572151Seric 	short m, n;
3582151Seric 	short maxr;
3592151Seric 	short seqcnt;
3602151Seric 	short pred;
3612151Seric 	register struct deltab *p1, *p2;
3622151Seric 	register short *brp;
3632151Seric 
3642151Seric 	for (m = ndels; m; m--) {
3652151Seric 		p1 = &dt[m];
3662151Seric 		if (p1->d_sid.s_lev > 1) {
3672151Seric 			for (n = m - 1; n; n--) {
3682151Seric 				if (p1->d_sid.s_rel == dt[n].d_sid.s_rel)
3692151Seric 					break;
3702151Seric 			}
3712151Seric 			pred = n;
3722151Seric 		}
3732151Seric 		else {
3742151Seric 			maxr = pred = 0;
3752151Seric 			for (n = m - 1; n; n--) {
3762151Seric 				p2 = &dt[n];
3772151Seric 				if (p1->d_sid.s_rel > p2->d_sid.s_rel &&
3782151Seric 					p2->d_type == 'D' &&
3792151Seric 					p2->d_sid.s_rel > maxr) {
3802151Seric 						maxr = p2->d_sid.s_rel;
3812151Seric 						pred = n;
3822151Seric 				}
3832151Seric 			}
3842151Seric 		}
3852151Seric 		p1->d_pred = pred;
3862151Seric 		rlp[p1->d_sid.s_rel][p1->d_sid.s_lev] = m;
3872151Seric 	}
3882151Seric 	brp = alloca(n = (ndels + 1) * sizeof(*brp));
38919943Ssam 	bzero(brp,n);
3902151Seric 	for (m = 1; m <= ndels; m++) {
3912151Seric 		p1 = &dt[m];
3922151Seric 		if (p1->d_type != 'D') {
3932151Seric 			seqcnt = 0;
3942151Seric 			p2 = &dt[p1->d_pred];
3952151Seric 			p1->d_type = 'D';
3962151Seric 			p1->d_sid.s_rel = p2->d_sid.s_rel;
3972151Seric 			p1->d_sid.s_lev = p2->d_sid.s_lev;
3982151Seric 			p1->d_sid.s_br = ++brp[p1->d_pred];
3992151Seric 			p1->d_sid.s_seq = ++seqcnt;
4002151Seric 			pred = m;
4012151Seric 			for (n = m + 1; n <= ndels; n++) {
4022151Seric 				if (dt[n].d_pred == pred) {
4032151Seric 					p2 = &dt[n];
4042151Seric 					p2->d_type = 'D';
4052151Seric 					p2->d_sid.s_rel = p1->d_sid.s_rel;
4062151Seric 					p2->d_sid.s_lev = p1->d_sid.s_lev;
4072151Seric 					p2->d_sid.s_br = p1->d_sid.s_br;
4082151Seric 					p2->d_sid.s_seq = ++seqcnt;
4092151Seric 					pred = n;
4102151Seric 				}
4112151Seric 			}
4122151Seric 		}
4132151Seric 	}
4142151Seric }
4152151Seric 
4162151Seric 
4172151Seric 
4182151Seric struct	names {
4192151Seric 	struct	names	*n_next;
4202151Seric 	char	n_name[SZLNAM];
4212151Seric 	short	n_uid;
4222151Seric };
4232151Seric 
4242151Seric struct names *names;
4252151Seric 
dousers(up,pkt)4262151Seric dousers(up,pkt)
4272151Seric register char *up;
4282151Seric struct packet *pkt;
4292151Seric {
4302151Seric 	short i, j;
4312151Seric 	register char mask, c;
4322151Seric 	char *p;
4332151Seric 	char str[16];
4342151Seric 
4352151Seric 	for (i = 0; i < 32; i++)
4362151Seric 		if (c = *up++) {
4372151Seric 			j = 0;
43832772Sbostic 			for (mask = 1; mask; mask <<= 1) {
439*33423Sbostic 				if ((c & mask) && (p = getlnam(i * SZLNAM + j))) {
440*33423Sbostic 					sprintf(str,"%s\n",p);
441*33423Sbostic 					putline(pkt,str);
442*33423Sbostic 				}
4432151Seric 				j++;
4442151Seric 			}
4452151Seric 		}
4462151Seric }
4472151Seric 
4482151Seric 
getlnam(uid)4492151Seric getlnam(uid)
4502151Seric short uid;
4512151Seric {
4522151Seric 	char str[128];
4532151Seric 	register struct names *cur, *prev;
4542151Seric 	register char *p;
4552151Seric 
4562151Seric 	for (cur = &names; cur = (prev = cur)->n_next; )
4572151Seric 		if (cur->n_uid == uid)
4582151Seric 			return(cur->n_name);
4592151Seric 	if (getpw(uid,str))
4602151Seric 		return(0);
4612151Seric 	prev->n_next = cur = alloc(sizeof(*cur));
4622151Seric 	cur->n_next = 0;
4632151Seric 	cur->n_uid = uid;
4642151Seric 	for (p = str; *p++ != ':'; )
4652151Seric 		;
4662151Seric 	*--p = 0;
4672151Seric 	str[SZLNAM] = 0;
4682151Seric 	copy(str,cur->n_name);
4692151Seric 	return(cur->n_name);
4702151Seric }
4712151Seric 
4722151Seric 
4732151Seric 
4742151Seric /*
4752151Seric 	Routine to process the module header. All that's necessary is
4762151Seric 	to slide it shorto the packet.
4772151Seric */
4782151Seric 
dohead(pkt)4792151Seric dohead(pkt)
4802151Seric register struct Packet *pkt;
4812151Seric {
4822151Seric 	register struct Header *hdr;
4832151Seric 
4842151Seric 	if(rdrec(pkt) == 1) fatal("premature eof (58)");
4852151Seric 	hdr = pkt->Pibuf.Irecptr;
4862151Seric 	if(hdr->Hmagicno != MAGICNO) fatal("not an SCCS file (53)");
48719943Ssam 	bcopy(hdr,&pkt->Phdr,sizeof(*hdr));
4882151Seric }
4892151Seric 
4902151Seric 
doreltab(pkt,rlp)4912151Seric doreltab(pkt,rlp)
4922151Seric register struct Packet *pkt;
4932151Seric register short ***rlp;
4942151Seric {
4952151Seric 	short n;
4962151Seric 	short sz;
4972151Seric 	register struct Reltab *rt;
4982151Seric 
4992151Seric 	n = 0;
5002151Seric 	while (rdrec(pkt) != 1 && (rt = pkt->Pibuf.Irecptr)->Rrel) {
5012151Seric 		if (n == 0) {
5022151Seric 			*rlp = alloc(sz = (rt->Rrel + 1) * sizeof(**rlp));
50319943Ssam 			bzero(*rlp,sz);
5042151Seric 			**rlp = rt->Rrel;
5052151Seric 		}
5062151Seric 		(*rlp)[rt->Rrel] = alloc((rt->Rlevs + 1) * sizeof(***rlp));
5072151Seric 		(*rlp)[rt->Rrel][0] = rt->Rlevs;
50832772Sbostic 		n += rt->Rlevs;
5092151Seric 	}
5102151Seric 	return(n);
5112151Seric }
5122151Seric 
5132151Seric 
5142151Seric dodelt(pkt,dt,hists,ndels)
5152151Seric struct Packet *pkt;
5162151Seric register struct deltab *dt;
5172151Seric char **hists;
5182151Seric short ndels;
5192151Seric {
5202151Seric 	short n;
5212151Seric 	register struct deltab *ndt;
5222151Seric 	register struct Deltab *odt;
5232151Seric 
5242151Seric 	for (; rdrec(pkt) != 1 && (odt = pkt->Pibuf.Irecptr)->Drel; --ndels) {
5252151Seric 		if (!(odt->Dtype == 'D' || odt->Dtype == 'P' || odt->Dtype == 'U')) {
5262151Seric 			++ndels;
5272151Seric 			continue;
5282151Seric 		}
5292151Seric 		if (!ndels)
5302151Seric 			return(fatal("internal error in dodeltab"));
5312151Seric 		ndt = &dt[ndels];
5322151Seric 		ndt->d_type = odt->Dtype;
53319943Ssam 		bcopy(odt->Dpgmr,ndt->d_pgmr,sizeof(ndt->d_pgmr));
5342151Seric 		ndt->d_datetime = (odt->Ddthi<<16)+(unsigned)odt->Ddtlo;
5352151Seric 		ndt->d_sid.s_rel = odt->Drel;
5362151Seric 		ndt->d_sid.s_lev = odt->Dlev;
5372151Seric 		ndt->d_sid.s_br = 0;
5382151Seric 		ndt->d_sid.s_seq = 0;
5392151Seric 		ndt->d_serial = ndels;
5402151Seric 		ndt->d_pred = 0;
5412151Seric 		n = size(odt->Dhist);
5422151Seric 		n++;
54332772Sbostic 		n &= ~1;
5442151Seric 		if (odt->Dtype == 'P' || odt->Dtype == 'U') {
5452151Seric 			hists[ndels] = alloc(n + 16);
5462151Seric 			sprintf(hists[ndels],"[was %d.%d] ",odt->Drel,odt->Dlev);
5472151Seric 		}
5482151Seric 		else {
5492151Seric 			hists[ndels] = alloc(n);
5502151Seric 			hists[ndels][0] = 0;
5512151Seric 		}
55219943Ssam 		bcopy(odt->Dhist,index(hists[ndels], '\0'),n);
5532151Seric 	}
5542151Seric 	if (ndels) {
5552151Seric 		fatal("in dodelt");
5562151Seric 	}
5572151Seric }
5582151Seric 
5592151Seric 
5602151Seric dobod(opkt,npkt,rlp,line)
5612151Seric struct Packet *opkt;
5622151Seric struct packet *npkt;
5632151Seric short **rlp;
5642151Seric char *line;
5652151Seric {
5662151Seric 	register struct Control *octl;
5672151Seric 	register char *p, c;
5682151Seric 
5692151Seric 	while (rdrec(opkt) != 1 && (octl = opkt->Pibuf.Irecptr)->Crel) {
570*33423Sbostic 		if (octlrec(octl,opkt->Pibuf.Ilen)) {
571*33423Sbostic 			sprintf(line,"%c%c %u\n",CTLCHAR,"EDI"[octl->Cctl-OEND],rlp[octl->Crel][octl->Clev]);
572*33423Sbostic 			putline(npkt,line);
573*33423Sbostic 		}
5742151Seric 		else {
5752151Seric 			c = (p = octl)[opkt->Pibuf.Ilen];
5762151Seric 			p[opkt->Pibuf.Ilen] = 0;
577*33423Sbostic 			sprintf(line,"%s\n",p);
578*33423Sbostic 			putline(npkt,line);
5792151Seric 			p[opkt->Pibuf.Ilen] = c;
5802151Seric 		}
5812151Seric 	}
5822151Seric }
5832151Seric 
5842151Seric 
octlrec(ctl,len)5852151Seric octlrec(ctl,len)
5862151Seric register struct Control *ctl;
5872151Seric short len;
5882151Seric {
5892151Seric 	register short ch;
5902151Seric 
5912151Seric 	if (len==SIZEOFCONTROL &&
5922151Seric 		((ch=ctl->Cctl)==OINS || ch==ODEL || ch==OEND))
5932151Seric 			return(1);
5942151Seric 	return(0);
5952151Seric }
5962151Seric 
5972151Seric 
rdrec(pkt)5982151Seric rdrec(pkt)
5992151Seric register struct Packet *pkt;
6002151Seric {
6012151Seric 	register n;
6022151Seric 
6032151Seric 	if ((n = getr(&pkt->Pibuf)) != 1)
6042151Seric 		pkt->Precno++;
6052151Seric 	return(n);
6062151Seric }
6072151Seric 
6082151Seric 
xwrite(a,b,c)6092151Seric xwrite(a,b,c)
6102151Seric {
6112151Seric 	return(write(a,b,c));
6122151Seric }
6132151Seric 
6142151Seric 
6152151Seric 
6162151Seric 
6172151Seric # define CALL(p,func,cnt)	Ffile=p; (*func)(p); cnt++;
6182151Seric short	nfiles;
6192151Seric char	had_dir;
6202151Seric char	had_standinp;
6212151Seric 
6222151Seric 
odo_file(p,func)6232151Seric odo_file(p,func)
6242151Seric register char *p;
6252151Seric short (*func)();
6262151Seric {
6272151Seric 	extern char *Ffile;
6282151Seric 	char str[FILESIZE];
6292151Seric 	char ibuf[FILESIZE];
6302151Seric 	FILE *iop;
6312151Seric 	struct dir dir[2];
6322151Seric 	register char *s;
6332151Seric 	short fd;
6342151Seric 
6352151Seric 	if (p[0] == '-') {
6362151Seric 		had_standinp = 1;
6372151Seric 		while (gets(ibuf) != NULL) {
6382151Seric 			if (osccsfile(ibuf)) {
6392151Seric 				CALL(ibuf,func,nfiles);
6402151Seric 			}
6412151Seric 		}
6422151Seric 	}
6432151Seric 	else if (exists(p) && (Statbuf.st_mode & S_IFMT) == S_IFDIR) {
6442151Seric 		had_dir = 1;
6452151Seric 		Ffile = p;
6462151Seric 		if((iop = fopen(p,"r")) == NULL)
6472151Seric 			return;
6482151Seric 		dir[1].d_ino = 0;
6492151Seric 		fread(dir,sizeof(dir[0]),1,iop);   /* skip "."  */
6502151Seric 		fread(dir,sizeof(dir[0]),1,iop);   /* skip ".."  */
6512151Seric 		while(fread(dir,sizeof(dir[0]),1,iop) == 1) {
6522151Seric 			if(dir[0].d_ino == 0) continue;
6532151Seric 			sprintf(str,"%s/%s",p,dir[0].d_name);
6542151Seric 			if(osccsfile(str)) {
6552151Seric 				CALL(str,func,nfiles);
6562151Seric 			}
6572151Seric 		}
6582151Seric 		fclose(iop);
6592151Seric 	}
6602151Seric 	else {
6612151Seric 		CALL(p,func,nfiles);
6622151Seric 	}
6632151Seric }
6642151Seric 
6652151Seric 
osccsfile(file)6662151Seric osccsfile(file)
6672151Seric register char *file;
6682151Seric {
6692151Seric 	register short ff, result;
6702151Seric 	short magic[2];
6712151Seric 
6722151Seric 	result = (ff=open(file,0)) > 0
6732151Seric 	  && read(ff,magic,4) == 4
6742151Seric 	  && magic[1] == MAGICNO;
6752151Seric 	close(ff);
6762151Seric 	return(result);
6772151Seric }
6782151Seric 
6792151Seric 
6802151Seric 
6812151Seric /*
6822151Seric 	Routine to write out either the current line in the packet
6832151Seric 	(if newline is zero) or the line specified by newline.
6842151Seric 	A line is actually written (and the x-file is only
6852151Seric 	opened) if pkt->p_upd is non-zero.  When the current line from
6862151Seric 	the packet is written, pkt->p_wrttn is set non-zero, and
6872151Seric 	further attempts to write it are ignored.  When a line is
6882151Seric 	read shorto the packet, pkt->p_wrttn must be turned off.
6892151Seric */
6902151Seric 
6912151Seric short	Xcreate;
6922151Seric FILE	*Xiop;
6932151Seric 
6942151Seric 
putline(pkt,newline)6952151Seric putline(pkt,newline)
6962151Seric register struct packet *pkt;
6972151Seric char *newline;
6982151Seric {
6992151Seric 	static char obf[BUFSIZ];
7002151Seric 	char *xf;
7012151Seric 	register char *p;
7022151Seric 
7032151Seric 	if(pkt->p_upd == 0) return;
7042151Seric 
7052151Seric 	if(!Xcreate) {
7062151Seric 		stat(pkt->p_file,&Statbuf);
7072151Seric 		xf = auxf(pkt->p_file,'x');
7082151Seric 		Xiop = xfcreat(xf,Statbuf.st_mode);
7092151Seric 		setbuf(Xiop,obf);
7102151Seric 		chown(xf,(Statbuf.st_gid<<8)|Statbuf.st_uid);
7112151Seric 	}
7122151Seric 	if (newline)
7132151Seric 		p = newline;
7142151Seric 	else {
7152151Seric 		if(!pkt->p_wrttn++)
7162151Seric 			p = pkt->p_line;
7172151Seric 		else
7182151Seric 			p = 0;
7192151Seric 	}
7202151Seric 	if (p) {
7212151Seric 		fputs(p,Xiop);
7222151Seric 		if (Xcreate)
7232151Seric 			while (*p)
72432772Sbostic 				pkt->p_nhash += *p++;
7252151Seric 	}
7262151Seric 	Xcreate = 1;
7272151Seric }
7282151Seric 
7292151Seric 
convflush(pkt)7302151Seric convflush(pkt)
7312151Seric register struct packet *pkt;
7322151Seric {
7332151Seric 	register char *p;
7342151Seric 	char hash[6];
7352151Seric 
7362151Seric 	if (pkt->p_upd == 0)
7372151Seric 		return;
7382151Seric 	putline(pkt,0);
7392151Seric 	rewind(Xiop);
7402151Seric 	sprintf(hash,"%5u",pkt->p_nhash&0xFFFF);
7412151Seric 	zeropad(hash);
7422151Seric 	fprintf(Xiop,"%c%c%s\n",CTLCHAR,HEAD,hash);
7432151Seric 	fclose(Xiop);
7442151Seric }
7452151Seric 
7462151Seric 
7472151Seric xrm(pkt)
7482151Seric struct packet *pkt;
7492151Seric {
7502151Seric 	if (Xiop)
7512151Seric 		fclose(Xiop);
7522151Seric 	if(Xcreate)
7532151Seric 		unlink(auxf(pkt,'x'));
7542151Seric 	Xiop = Xcreate = 0;
7552151Seric }
7562151Seric 
7572151Seric 
7582151Seric char bpf[] "bad p-file (216)";
7592151Seric 
rdpfile(f,rp,un)7602151Seric rdpfile(f,rp,un)
7612151Seric char f[], un[];
7622151Seric short *rp;
7632151Seric {
7642151Seric 	register short fd, i;
7652151Seric 	register char *p;
7662151Seric 	char s[65], *name;
7672151Seric 
7682151Seric 	fd = xopen(f,0);
7692151Seric 	if ((i=read(fd,s,64))<=0)
7702151Seric 		fatal(bpf);
7712151Seric 	close(fd);
7722151Seric 	p = s;
7732151Seric 	p[i] = 0;
7742151Seric 	for (; *p != ' '; p++)
7752151Seric 		if (*p == 0)
7762151Seric 			fatal(bpf);
7772151Seric 	*p = 0;
7782151Seric 	if ((*rp=patoi(s)) == -1)
7792151Seric 		fatal(bpf);
7802151Seric 	++p;
7812151Seric 	while (*p++ == ' ') ;
7822151Seric 	name = --p;
7832151Seric 	for (; *p != '\n'; p++)
7842151Seric 		if (*p == 0)
7852151Seric 			fatal(bpf);
7862151Seric 	*p = 0;
7872151Seric 	if ((p-name)>SZLNAM)
7882151Seric 		fatal(bpf);
7892151Seric 	copy(name,un);
7902151Seric }
7912151Seric 
7922151Seric 
ckpfile(file)7932151Seric ckpfile(file)
7942151Seric register char *file;
7952151Seric {
7962151Seric 	short r;
7972151Seric 	char un[SZLNAM];
7982151Seric 
7992151Seric 	if(exists(file)) {
8002151Seric 		rdpfile(file,&r,un);
801*33423Sbostic 		sprintf(Error,"being edited at release %d by `%s' (scv1)",r,un));
802*33423Sbostic 		fatal(Error);
8032151Seric 	}
8042151Seric }
8052151Seric 
8062151Seric 
8072151Seric /*
8082151Seric 	Bottom level read routines for release 3 SCCS files.
8092151Seric 
8102151Seric 	Usage:
8112151Seric 		struct Ibufr ib;
8122151Seric 		...
8132151Seric 		opnr(&ib,"filename");
8142151Seric 		...
8152151Seric 		if(getr(&ib) == 1) [end-of-file];
8162151Seric 		[ib.Irecptr is addr of record (always on word boundary)]
8172151Seric 		[ib.Ilen is length]
8182151Seric 
8192151Seric 	Address HASHADDR of the file must contain a 1-word stored hash count.
8202151Seric 	If this count is non-zero, then on end-of-file a computed hash count
8212151Seric 	is compared with it and a fatal error is issued if they aren't equal.
8222151Seric */
8232151Seric 
opnr(buf,file)8242151Seric opnr(buf,file)
8252151Seric register struct Ibufr *buf;
8262151Seric char file[];
8272151Seric {
8282151Seric 	buf->Ifildes = xopen(file,0);
8292151Seric 	buf->Irecptr = buf->Ibuff2 + 2;
8302151Seric 	buf->Iend = buf->Irecptr + 510;
8312151Seric 	buf->Ilen = 510;
8322151Seric 	buf->Ibuff3[1] = -128;
8332151Seric 	buf->Ihcnt = buf->Ihtot = buf->Ihflag = 0;
8342151Seric }
8352151Seric 
8362151Seric 
getr(buf)8372151Seric getr(buf)
8382151Seric register struct Ibufr *buf;
8392151Seric {
8402151Seric 	register char *p, *q;
8412151Seric 	short *w;
8422151Seric 	short i, n;
8432151Seric 
84432772Sbostic 	buf->Irecptr += buf->Ilen + !(buf->Ilen & 1);
8452151Seric 
8462151Seric 	i = 0;
8472151Seric 	while(1) {
8482151Seric 		buf->Ilen = 0;
8492151Seric 		buf->Ilen = *buf->Irecptr + 128;
8502151Seric 
8512151Seric 		if(buf->Irecptr <= buf->Iend - (buf->Ilen+!(buf->Ilen&1)))
8522151Seric 			return(++buf->Irecptr);
8532151Seric 
8542151Seric 		if(i++ == 1) return(1);
8552151Seric 
8562151Seric 		q = buf->Irecptr;
85732772Sbostic 		p = buf->Irecptr -= 512;
8582151Seric 
8592151Seric 		while(q <= buf->Iend) *p++ = *q++;
8602151Seric 
8612151Seric 		if((n = read(buf->Ifildes,buf->Ibuff2,512)) <= 0)
8622151Seric 			return(1);
8632151Seric 
8642151Seric 		buf->Iend = buf->Ibuff2 + n - 1;
8652151Seric 		*(buf->Iend + 1) = -128;
8662151Seric 
8672151Seric 		w = buf->Ibuff2;
8682151Seric 		if(buf->Ihflag == 0) {
8692151Seric 			buf->Ihflag = 1;
8702151Seric 			buf->Ihtot = w[HASHADDR>>1];
8712151Seric 			w[HASHADDR>>1] = 0;
8722151Seric 		}
8732151Seric 		if(n < 512) buf->Ibuff2[n] = 0;
8742151Seric 
87532772Sbostic 		buf->Ihcnt += sumr(w,&w[(n&1?n-1:n-2)>>1]);
8762151Seric 
8772151Seric 		if(n<512 && buf->Ihtot && buf->Ihcnt != buf->Ihtot)
8782151Seric 			fatal("corrupted file (201)");
8792151Seric 	}
8802151Seric }
8812151Seric 
8822151Seric 
sumr(from,to)8832151Seric sumr(from,to)
8842151Seric register short *from, *to;
8852151Seric {
8862151Seric 	register short sum;
8872151Seric 
8882151Seric 	for (sum=0; from<=to; )
88932772Sbostic 		sum += *from++;
8902151Seric 	return(sum);
8912151Seric }
892