1*2151Seric #
2*2151Seric /*
3*2151Seric 	Program to convert release 3 (or release 2 or even 1) SCCS files
4*2151Seric 	to release 4 SCCS files.
5*2151Seric 	Usage:
6*2151Seric 		scv arg ...
7*2151Seric 	arg is any argument acceptable as an SCCS file
8*2151Seric 	name argument to the get command. E.g.:
9*2151Seric 		scv mysccsdir
10*2151Seric 	will convert every release 3 (or 2 or 1 but NOT 4) SCCS file in the
11*2151Seric 	directory "mysccsdir".
12*2151Seric */
13*2151Seric # include	"../hdr/defines.h"
14*2151Seric # include	"dir.h"
15*2151Seric 
16*2151Seric 
17*2151Seric /*
18*2151Seric 	Release 3 SCCS File Structures  (2.1  78/06/05 17:31:17)
19*2151Seric 	See osccsfile(V).
20*2151Seric */
21*2151Seric 
22*2151Seric struct Header {
23*2151Seric 	short  Hmagicno;
24*2151Seric 	char Htype[10];
25*2151Seric 	char Hpers[14];
26*2151Seric 	char Hdesc[100];
27*2151Seric 	short  Hfloor;
28*2151Seric 	short  Hceil;
29*2151Seric 	short  Hsw[5];
30*2151Seric 	short  Hrdef;
31*2151Seric 	char Hulist[32];
32*2151Seric 	char Hexpand[50];
33*2151Seric 	short  Hash;
34*2151Seric };
35*2151Seric #define MAGICNO (7)
36*2151Seric #define HASHADDR (226)
37*2151Seric 
38*2151Seric 
39*2151Seric struct Reltab {
40*2151Seric 	short  Rrel;
41*2151Seric 	short  Rlevs;
42*2151Seric };
43*2151Seric 
44*2151Seric 
45*2151Seric struct Deltab {
46*2151Seric 	short  Drel;
47*2151Seric 	short  Dlev;
48*2151Seric 	char Dtype;	/*'D': delta,'P','U': non-prop,'I': incl,'E': excl */
49*2151Seric 	char Dfill;	/* Used to be option letter */
50*2151Seric /* compiler once forced unfortunate alignment here.
51*2151Seric /* also, fp-11c high/low long goof strikes again.
52*2151Seric /*	long  Ddatetime;
53*2151Seric */
54*2151Seric 	short Ddthi,Ddtlo;
55*2151Seric 	char Dpgmr[8];
56*2151Seric 	char Dhist[200];
57*2151Seric };
58*2151Seric 
59*2151Seric 
60*2151Seric struct Control {
61*2151Seric 	short  Crel;
62*2151Seric 	short  Clev;
63*2151Seric 	char Cctl;	/* -11: ins, -12: del, -13: end */
64*2151Seric };
65*2151Seric #define SIZEOFCONTROL (5)
66*2151Seric #define OINS (-11)
67*2151Seric #define ODEL (-12)
68*2151Seric #define OEND (-13)
69*2151Seric 
70*2151Seric 
71*2151Seric struct Line {
72*2151Seric 	char Lline [256];
73*2151Seric };
74*2151Seric 
75*2151Seric 
76*2151Seric /*
77*2151Seric 	Structure for use with buffered I/O routines opnl, opnr,
78*2151Seric 	getl and getr.
79*2151Seric */
80*2151Seric struct Ibufr {
81*2151Seric 	short  Ifildes;
82*2151Seric 	char *Irecptr;
83*2151Seric 	char *Iend;
84*2151Seric 	char Ibuff1[256];
85*2151Seric 	char Ibuff2[512];
86*2151Seric 	char Ibuff3[2];
87*2151Seric 	short  Ilen;
88*2151Seric 	short  Ihflag;
89*2151Seric 	short  Ihcnt;
90*2151Seric 	short  Ihtot;
91*2151Seric };
92*2151Seric 
93*2151Seric 
94*2151Seric /*
95*2151Seric 	Structure for use with buffered I/O routines crtr, crtl, putl,
96*2151Seric 	putr, flshr and buflsh.
97*2151Seric */
98*2151Seric struct Obufr {
99*2151Seric 	short  Ofildes;
100*2151Seric 	char *Orecptr;
101*2151Seric 	char *Oend;
102*2151Seric 	char Obuff1[512];
103*2151Seric 	short  Ohflag;
104*2151Seric 	short  Ohcnt;
105*2151Seric };
106*2151Seric 
107*2151Seric 
108*2151Seric /*
109*2151Seric  * structure to access an
110*2151Seric  * shorteger in bytes
111*2151Seric  */
112*2151Seric struct
113*2151Seric {
114*2151Seric 	char	lobyte;
115*2151Seric 	char	hibyte;
116*2151Seric };
117*2151Seric 
118*2151Seric 
119*2151Seric /*
120*2151Seric  * structure to access an shorteger
121*2151Seric  */
122*2151Seric struct
123*2151Seric {
124*2151Seric 	short	shorteg;
125*2151Seric };
126*2151Seric 
127*2151Seric 
128*2151Seric /*
129*2151Seric  * structure to access a long as shortegers
130*2151Seric  */
131*2151Seric struct {
132*2151Seric 	short	hiword;
133*2151Seric 	short	loword;
134*2151Seric };
135*2151Seric 
136*2151Seric 
137*2151Seric /*
138*2151Seric 	Structure for referencing pieces of localtime().
139*2151Seric */
140*2151Seric struct Time {
141*2151Seric 	short	Tseconds;
142*2151Seric 	short	Tminutes;
143*2151Seric 	short	Thours;
144*2151Seric 	short	Tday_month;
145*2151Seric 	short	Tmonth;
146*2151Seric 	short	Tyear;
147*2151Seric 	short	Tday_week;
148*2151Seric 	short	Tday_year;
149*2151Seric 	short	Tflag;
150*2151Seric };
151*2151Seric /*
152*2151Seric 	SCCS Internal Structures (used by get and delta).     (2.1)
153*2151Seric */
154*2151Seric 
155*2151Seric struct Apply {
156*2151Seric 	short    Adt;		/* pseudo date-time */
157*2151Seric 	short    Acode;		/* APPLY, NOAPPLY or EMPTY */
158*2151Seric };
159*2151Seric #define APPLY	  (1)
160*2151Seric #define NOAPPLY  (-1)
161*2151Seric #define EMPTY	  (0)
162*2151Seric 
163*2151Seric 
164*2151Seric struct Queue {
165*2151Seric 	struct Queue *Qnext;
166*2151Seric 	short    Qrel;		/* release */
167*2151Seric 	short    Qlev;		/* level */
168*2151Seric 	short    Qdt;		/* pseudo date-time */
169*2151Seric 	short    Qkeep;		/* keep switch setting */
170*2151Seric };
171*2151Seric #define YES	 (1)
172*2151Seric #define NO	(-1)
173*2151Seric 
174*2151Seric #define SIZEOFPfile (50)
175*2151Seric 
176*2151Seric 
177*2151Seric struct Packet {
178*2151Seric 	char	Pfile[SIZEOFPfile];	/* file name containing module */
179*2151Seric /*
180*2151Seric 			Note: the order of the next two words
181*2151Seric 				can not___ be changed!
182*2151Seric 			This is because the release and level together
183*2151Seric 			are treated as a long.
184*2151Seric */
185*2151Seric 	short	Prel;		/* specified release (-1 = not spec.) */
186*2151Seric 	short	Plev;		/* specified level (-1 = not spec.)*/
187*2151Seric 	char	Pverbose;	/* verbose flags (see #define's below) */
188*2151Seric 	char	Pupd;		/* update flag (!0 = update mode) */
189*2151Seric 	long    Pcutoff;	/* specified cutoff date-time */
190*2151Seric 	struct	Header	Phdr;	/* header from module */
191*2151Seric 	short	Plnno;		/* line number of current line */
192*2151Seric 	short	Precno;		/* record number of current rec */
193*2151Seric 	char	Pwrttn;		/* written flag (!0 = written) */
194*2151Seric 	char	Pkeep;		/* keep switch for readmod() */
195*2151Seric 	struct	Apply **Papply;	/* ptr to apply array */
196*2151Seric 	struct	Queue *Pq;	/* ptr to control queue */
197*2151Seric 	struct	Ibufr Pibuf;	/* input buffer */
198*2151Seric 	long	Pcdt;		/* date/time of newest applied delta */
199*2151Seric 	char	*Plfile;	/* 0 = no l-file; else ptr to l arg */
200*2151Seric 	char	Punack;		/* !0 if unacknowledged non-prop deltas */
201*2151Seric 	char	Pnoprop;	/* !0 if new delta is to be non-prop */
202*2151Seric 	short	Pirel;		/* rel which inserted current rec */
203*2151Seric 	short	Pilev;		/* lev which inserted current rec */
204*2151Seric };
205*2151Seric /*
206*2151Seric 	Masks for Pverbose
207*2151Seric */
208*2151Seric 
209*2151Seric # define RLACCESS	(1)
210*2151Seric # define NLINES		(2)
211*2151Seric # define DOLIST		(4)
212*2151Seric # define UNACK		(8)
213*2151Seric # define NEWRL		(16)
214*2151Seric # define WARNING	(32)
215*2151Seric 
216*2151Seric /*
217*2151Seric 	size of login name
218*2151Seric */
219*2151Seric 
220*2151Seric 
221*2151Seric USXALLOC();
222*2151Seric 
223*2151Seric main(argc,argv)
224*2151Seric char **argv;
225*2151Seric {
226*2151Seric 	register short i;
227*2151Seric 	register char *p;
228*2151Seric 	extern conv();
229*2151Seric 	extern short Fcnt;
230*2151Seric 
231*2151Seric 	setsig();
232*2151Seric 	Fflags = FTLMSG | FTLCLN | FTLJMP;
233*2151Seric 	for (i = 1; i < argc; i++)
234*2151Seric 		if (p = argv[i])
235*2151Seric 			odo_file(p,conv);
236*2151Seric 	exit(Fcnt ? 1 : 0);
237*2151Seric }
238*2151Seric 
239*2151Seric 
240*2151Seric struct packet npkt;
241*2151Seric 
242*2151Seric conv(ofile)
243*2151Seric char *ofile;
244*2151Seric {
245*2151Seric 	struct Packet opkt;
246*2151Seric 	struct deltab *dt;
247*2151Seric 	char **hists;
248*2151Seric 	short **rlp;
249*2151Seric 	char statstr[32];
250*2151Seric 	short ndels;
251*2151Seric 	char *line;
252*2151Seric 	short n;
253*2151Seric 	char *p;
254*2151Seric 
255*2151Seric 	if (setjmp(Fjmp))
256*2151Seric 		return;
257*2151Seric 	printf("%s:\n",ofile);
258*2151Seric 	ckpfile(auxf(ofile,'p'));
259*2151Seric 	zero(&opkt,sizeof(opkt));
260*2151Seric 	opnr(&opkt.Pibuf,ofile);
261*2151Seric 	dohead(&opkt);
262*2151Seric 	rlp = 0;
263*2151Seric 	ndels = doreltab(&opkt,&rlp);
264*2151Seric 	hists = alloc((ndels + 1) * sizeof(*hists));
265*2151Seric 	dt = alloc((ndels + 1) * sizeof(*dt));
266*2151Seric 	dodelt(&opkt,dt,hists,ndels);
267*2151Seric 	fixup(dt,ndels,rlp);
268*2151Seric 	sinit(&npkt,ofile,0);
269*2151Seric 	npkt.p_upd = 1;
270*2151Seric 	line = npkt.p_line;
271*2151Seric 	putline(&npkt,sprintf(line,"%c%c00000\n",CTLCHAR,HEAD),0);
272*2151Seric 	statstr[0] = 0;
273*2151Seric 	for (n = ndels; n; n--) {
274*2151Seric 		if (!statstr[0])
275*2151Seric 			newstats(&npkt,statstr,"?");
276*2151Seric 		else
277*2151Seric 			putline(&npkt,statstr);
278*2151Seric 		putline(&npkt,del_ba(&dt[n],line));
279*2151Seric 		putline(&npkt,sprintf(line,"%c%c %s\n",CTLCHAR,COMMENTS,
280*2151Seric 			hists[n]));
281*2151Seric 		putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,EDELTAB));
282*2151Seric 	}
283*2151Seric 	putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,BUSERNAM));
284*2151Seric 	dousers(opkt.Phdr.Hulist,&npkt);
285*2151Seric 	putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,EUSERNAM));
286*2151Seric 	if (*(p = opkt.Phdr.Htype))
287*2151Seric 		putline(&npkt,sprintf(line,"%c%c %c %s\n",CTLCHAR,FLAG,
288*2151Seric 			TYPEFLAG,p));
289*2151Seric 	if (n = opkt.Phdr.Hfloor)
290*2151Seric 		putline(&npkt,sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG,
291*2151Seric 			FLORFLAG,n));
292*2151Seric 	if (n = opkt.Phdr.Hceil)
293*2151Seric 		putline(&npkt,sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG,
294*2151Seric 			CEILFLAG,n));
295*2151Seric 	if (n = opkt.Phdr.Hrdef)
296*2151Seric 		putline(&npkt,sprintf(line,"%c%c %c %d\n",CTLCHAR,FLAG,
297*2151Seric 			DEFTFLAG,n));
298*2151Seric 	putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,BUSERTXT));
299*2151Seric 	if (*(p = opkt.Phdr.Hpers))
300*2151Seric 		putline(&npkt,sprintf(line,"%s\n",p));
301*2151Seric 	if (*(p = opkt.Phdr.Hdesc))
302*2151Seric 		putline(&npkt,sprintf(line,"%s\n",p));
303*2151Seric 	putline(&npkt,sprintf(line,CTLSTR,CTLCHAR,EUSERTXT));
304*2151Seric 	dobod(&opkt,&npkt,rlp,line);
305*2151Seric 	convflush(&npkt);
306*2151Seric 	close(opkt.Pibuf.Ifildes);
307*2151Seric 	for (n = ndels; n; n--)
308*2151Seric 		free(hists[n]);
309*2151Seric 	free(hists);
310*2151Seric 	free(dt);
311*2151Seric /* [compiler bug, ignore this for now ]
312*2151Seric 	if (rlp) {
313*2151Seric 		for (n = (short) (*rlp); n; n--)
314*2151Seric 			if (rlp[n])
315*2151Seric 				free(rlp[n]);
316*2151Seric 		free(rlp);
317*2151Seric 	}
318*2151Seric */
319*2151Seric 	rename(auxf(npkt.p_file,'x'),npkt.p_file);
320*2151Seric 	xrm(&npkt);
321*2151Seric }
322*2151Seric 
323*2151Seric 
324*2151Seric getline()
325*2151Seric {
326*2151Seric }
327*2151Seric 
328*2151Seric 
329*2151Seric clean_up()
330*2151Seric {
331*2151Seric 	xrm(&npkt);
332*2151Seric }
333*2151Seric 
334*2151Seric 
335*2151Seric 
336*2151Seric fixup(dt,ndels,rlp)
337*2151Seric struct deltab *dt;
338*2151Seric short ndels;
339*2151Seric short **rlp;
340*2151Seric {
341*2151Seric 	short m, n;
342*2151Seric 	short maxr;
343*2151Seric 	short seqcnt;
344*2151Seric 	short pred;
345*2151Seric 	register struct deltab *p1, *p2;
346*2151Seric 	register short *brp;
347*2151Seric 
348*2151Seric 	for (m = ndels; m; m--) {
349*2151Seric 		p1 = &dt[m];
350*2151Seric 		if (p1->d_sid.s_lev > 1) {
351*2151Seric 			for (n = m - 1; n; n--) {
352*2151Seric 				if (p1->d_sid.s_rel == dt[n].d_sid.s_rel)
353*2151Seric 					break;
354*2151Seric 			}
355*2151Seric 			pred = n;
356*2151Seric 		}
357*2151Seric 		else {
358*2151Seric 			maxr = pred = 0;
359*2151Seric 			for (n = m - 1; n; n--) {
360*2151Seric 				p2 = &dt[n];
361*2151Seric 				if (p1->d_sid.s_rel > p2->d_sid.s_rel &&
362*2151Seric 					p2->d_type == 'D' &&
363*2151Seric 					p2->d_sid.s_rel > maxr) {
364*2151Seric 						maxr = p2->d_sid.s_rel;
365*2151Seric 						pred = n;
366*2151Seric 				}
367*2151Seric 			}
368*2151Seric 		}
369*2151Seric 		p1->d_pred = pred;
370*2151Seric 		rlp[p1->d_sid.s_rel][p1->d_sid.s_lev] = m;
371*2151Seric 	}
372*2151Seric 	brp = alloca(n = (ndels + 1) * sizeof(*brp));
373*2151Seric 	zero(brp,n);
374*2151Seric 	for (m = 1; m <= ndels; m++) {
375*2151Seric 		p1 = &dt[m];
376*2151Seric 		if (p1->d_type != 'D') {
377*2151Seric 			seqcnt = 0;
378*2151Seric 			p2 = &dt[p1->d_pred];
379*2151Seric 			p1->d_type = 'D';
380*2151Seric 			p1->d_sid.s_rel = p2->d_sid.s_rel;
381*2151Seric 			p1->d_sid.s_lev = p2->d_sid.s_lev;
382*2151Seric 			p1->d_sid.s_br = ++brp[p1->d_pred];
383*2151Seric 			p1->d_sid.s_seq = ++seqcnt;
384*2151Seric 			pred = m;
385*2151Seric 			for (n = m + 1; n <= ndels; n++) {
386*2151Seric 				if (dt[n].d_pred == pred) {
387*2151Seric 					p2 = &dt[n];
388*2151Seric 					p2->d_type = 'D';
389*2151Seric 					p2->d_sid.s_rel = p1->d_sid.s_rel;
390*2151Seric 					p2->d_sid.s_lev = p1->d_sid.s_lev;
391*2151Seric 					p2->d_sid.s_br = p1->d_sid.s_br;
392*2151Seric 					p2->d_sid.s_seq = ++seqcnt;
393*2151Seric 					pred = n;
394*2151Seric 				}
395*2151Seric 			}
396*2151Seric 		}
397*2151Seric 	}
398*2151Seric }
399*2151Seric 
400*2151Seric 
401*2151Seric 
402*2151Seric struct	names {
403*2151Seric 	struct	names	*n_next;
404*2151Seric 	char	n_name[SZLNAM];
405*2151Seric 	short	n_uid;
406*2151Seric };
407*2151Seric 
408*2151Seric struct names *names;
409*2151Seric 
410*2151Seric dousers(up,pkt)
411*2151Seric register char *up;
412*2151Seric struct packet *pkt;
413*2151Seric {
414*2151Seric 	short i, j;
415*2151Seric 	register char mask, c;
416*2151Seric 	char *p;
417*2151Seric 	char str[16];
418*2151Seric 
419*2151Seric 	for (i = 0; i < 32; i++)
420*2151Seric 		if (c = *up++) {
421*2151Seric 			j = 0;
422*2151Seric 			for (mask = 1; mask; mask =<< 1) {
423*2151Seric 				if ((c & mask) && (p = getlnam(i * 8 + j)))
424*2151Seric 					putline(pkt,sprintf(str,"%s\n",p));
425*2151Seric 				j++;
426*2151Seric 			}
427*2151Seric 		}
428*2151Seric }
429*2151Seric 
430*2151Seric 
431*2151Seric getlnam(uid)
432*2151Seric short uid;
433*2151Seric {
434*2151Seric 	char str[128];
435*2151Seric 	register struct names *cur, *prev;
436*2151Seric 	register char *p;
437*2151Seric 
438*2151Seric 	for (cur = &names; cur = (prev = cur)->n_next; )
439*2151Seric 		if (cur->n_uid == uid)
440*2151Seric 			return(cur->n_name);
441*2151Seric 	if (getpw(uid,str))
442*2151Seric 		return(0);
443*2151Seric 	prev->n_next = cur = alloc(sizeof(*cur));
444*2151Seric 	cur->n_next = 0;
445*2151Seric 	cur->n_uid = uid;
446*2151Seric 	for (p = str; *p++ != ':'; )
447*2151Seric 		;
448*2151Seric 	*--p = 0;
449*2151Seric 	str[SZLNAM] = 0;
450*2151Seric 	copy(str,cur->n_name);
451*2151Seric 	return(cur->n_name);
452*2151Seric }
453*2151Seric 
454*2151Seric 
455*2151Seric 
456*2151Seric /*
457*2151Seric 	Routine to process the module header. All that's necessary is
458*2151Seric 	to slide it shorto the packet.
459*2151Seric */
460*2151Seric 
461*2151Seric dohead(pkt)
462*2151Seric register struct Packet *pkt;
463*2151Seric {
464*2151Seric 	register struct Header *hdr;
465*2151Seric 
466*2151Seric 	if(rdrec(pkt) == 1) fatal("premature eof (58)");
467*2151Seric 	hdr = pkt->Pibuf.Irecptr;
468*2151Seric 	if(hdr->Hmagicno != MAGICNO) fatal("not an SCCS file (53)");
469*2151Seric 	move(hdr,&pkt->Phdr,sizeof(*hdr));
470*2151Seric }
471*2151Seric 
472*2151Seric 
473*2151Seric doreltab(pkt,rlp)
474*2151Seric register struct Packet *pkt;
475*2151Seric register short ***rlp;
476*2151Seric {
477*2151Seric 	short n;
478*2151Seric 	short sz;
479*2151Seric 	register struct Reltab *rt;
480*2151Seric 
481*2151Seric 	n = 0;
482*2151Seric 	while (rdrec(pkt) != 1 && (rt = pkt->Pibuf.Irecptr)->Rrel) {
483*2151Seric 		if (n == 0) {
484*2151Seric 			*rlp = alloc(sz = (rt->Rrel + 1) * sizeof(**rlp));
485*2151Seric 			zero(*rlp,sz);
486*2151Seric 			**rlp = rt->Rrel;
487*2151Seric 		}
488*2151Seric 		(*rlp)[rt->Rrel] = alloc((rt->Rlevs + 1) * sizeof(***rlp));
489*2151Seric 		(*rlp)[rt->Rrel][0] = rt->Rlevs;
490*2151Seric 		n =+ rt->Rlevs;
491*2151Seric 	}
492*2151Seric 	return(n);
493*2151Seric }
494*2151Seric 
495*2151Seric 
496*2151Seric dodelt(pkt,dt,hists,ndels)
497*2151Seric struct Packet *pkt;
498*2151Seric register struct deltab *dt;
499*2151Seric char **hists;
500*2151Seric short ndels;
501*2151Seric {
502*2151Seric 	short n;
503*2151Seric 	register struct deltab *ndt;
504*2151Seric 	register struct Deltab *odt;
505*2151Seric 
506*2151Seric 	for (; rdrec(pkt) != 1 && (odt = pkt->Pibuf.Irecptr)->Drel; --ndels) {
507*2151Seric 		if (!(odt->Dtype == 'D' || odt->Dtype == 'P' || odt->Dtype == 'U')) {
508*2151Seric 			++ndels;
509*2151Seric 			continue;
510*2151Seric 		}
511*2151Seric 		if (!ndels)
512*2151Seric 			return(fatal("internal error in dodeltab"));
513*2151Seric 		ndt = &dt[ndels];
514*2151Seric 		ndt->d_type = odt->Dtype;
515*2151Seric 		move(odt->Dpgmr,ndt->d_pgmr,sizeof(ndt->d_pgmr));
516*2151Seric 		ndt->d_datetime = (odt->Ddthi<<16)+(unsigned)odt->Ddtlo;
517*2151Seric 		ndt->d_sid.s_rel = odt->Drel;
518*2151Seric 		ndt->d_sid.s_lev = odt->Dlev;
519*2151Seric 		ndt->d_sid.s_br = 0;
520*2151Seric 		ndt->d_sid.s_seq = 0;
521*2151Seric 		ndt->d_serial = ndels;
522*2151Seric 		ndt->d_pred = 0;
523*2151Seric 		n = size(odt->Dhist);
524*2151Seric 		n++;
525*2151Seric 		n =& ~1;
526*2151Seric 		if (odt->Dtype == 'P' || odt->Dtype == 'U') {
527*2151Seric 			hists[ndels] = alloc(n + 16);
528*2151Seric 			sprintf(hists[ndels],"[was %d.%d] ",odt->Drel,odt->Dlev);
529*2151Seric 		}
530*2151Seric 		else {
531*2151Seric 			hists[ndels] = alloc(n);
532*2151Seric 			hists[ndels][0] = 0;
533*2151Seric 		}
534*2151Seric 		move(odt->Dhist,strend(hists[ndels]),n);
535*2151Seric 	}
536*2151Seric 	if (ndels) {
537*2151Seric 		fatal("in dodelt");
538*2151Seric 	}
539*2151Seric }
540*2151Seric 
541*2151Seric 
542*2151Seric dobod(opkt,npkt,rlp,line)
543*2151Seric struct Packet *opkt;
544*2151Seric struct packet *npkt;
545*2151Seric short **rlp;
546*2151Seric char *line;
547*2151Seric {
548*2151Seric 	register struct Control *octl;
549*2151Seric 	register char *p, c;
550*2151Seric 
551*2151Seric 	while (rdrec(opkt) != 1 && (octl = opkt->Pibuf.Irecptr)->Crel) {
552*2151Seric 		if (octlrec(octl,opkt->Pibuf.Ilen))
553*2151Seric 			putline(npkt,sprintf(line,"%c%c %u\n",CTLCHAR,
554*2151Seric 				"EDI"[octl->Cctl-OEND],
555*2151Seric 				rlp[octl->Crel][octl->Clev]));
556*2151Seric 		else {
557*2151Seric 			c = (p = octl)[opkt->Pibuf.Ilen];
558*2151Seric 			p[opkt->Pibuf.Ilen] = 0;
559*2151Seric 			putline(npkt,sprintf(line,"%s\n",p));
560*2151Seric 			p[opkt->Pibuf.Ilen] = c;
561*2151Seric 		}
562*2151Seric 	}
563*2151Seric }
564*2151Seric 
565*2151Seric 
566*2151Seric octlrec(ctl,len)
567*2151Seric register struct Control *ctl;
568*2151Seric short len;
569*2151Seric {
570*2151Seric 	register short ch;
571*2151Seric 
572*2151Seric 	if (len==SIZEOFCONTROL &&
573*2151Seric 		((ch=ctl->Cctl)==OINS || ch==ODEL || ch==OEND))
574*2151Seric 			return(1);
575*2151Seric 	return(0);
576*2151Seric }
577*2151Seric 
578*2151Seric 
579*2151Seric rdrec(pkt)
580*2151Seric register struct Packet *pkt;
581*2151Seric {
582*2151Seric 	register n;
583*2151Seric 
584*2151Seric 	if ((n = getr(&pkt->Pibuf)) != 1)
585*2151Seric 		pkt->Precno++;
586*2151Seric 	return(n);
587*2151Seric }
588*2151Seric 
589*2151Seric 
590*2151Seric xwrite(a,b,c)
591*2151Seric {
592*2151Seric 	return(write(a,b,c));
593*2151Seric }
594*2151Seric 
595*2151Seric 
596*2151Seric 
597*2151Seric SCCSID(@(#)scv	2.1.1.2);
598*2151Seric 
599*2151Seric # define CALL(p,func,cnt)	Ffile=p; (*func)(p); cnt++;
600*2151Seric short	nfiles;
601*2151Seric char	had_dir;
602*2151Seric char	had_standinp;
603*2151Seric 
604*2151Seric 
605*2151Seric odo_file(p,func)
606*2151Seric register char *p;
607*2151Seric short (*func)();
608*2151Seric {
609*2151Seric 	extern char *Ffile;
610*2151Seric 	char str[FILESIZE];
611*2151Seric 	char ibuf[FILESIZE];
612*2151Seric 	FILE *iop;
613*2151Seric 	struct dir dir[2];
614*2151Seric 	register char *s;
615*2151Seric 	short fd;
616*2151Seric 
617*2151Seric 	if (p[0] == '-') {
618*2151Seric 		had_standinp = 1;
619*2151Seric 		while (gets(ibuf) != NULL) {
620*2151Seric 			if (osccsfile(ibuf)) {
621*2151Seric 				CALL(ibuf,func,nfiles);
622*2151Seric 			}
623*2151Seric 		}
624*2151Seric 	}
625*2151Seric 	else if (exists(p) && (Statbuf.st_mode & S_IFMT) == S_IFDIR) {
626*2151Seric 		had_dir = 1;
627*2151Seric 		Ffile = p;
628*2151Seric 		if((iop = fopen(p,"r")) == NULL)
629*2151Seric 			return;
630*2151Seric 		dir[1].d_ino = 0;
631*2151Seric 		fread(dir,sizeof(dir[0]),1,iop);   /* skip "."  */
632*2151Seric 		fread(dir,sizeof(dir[0]),1,iop);   /* skip ".."  */
633*2151Seric 		while(fread(dir,sizeof(dir[0]),1,iop) == 1) {
634*2151Seric 			if(dir[0].d_ino == 0) continue;
635*2151Seric 			sprintf(str,"%s/%s",p,dir[0].d_name);
636*2151Seric 			if(osccsfile(str)) {
637*2151Seric 				CALL(str,func,nfiles);
638*2151Seric 			}
639*2151Seric 		}
640*2151Seric 		fclose(iop);
641*2151Seric 	}
642*2151Seric 	else {
643*2151Seric 		CALL(p,func,nfiles);
644*2151Seric 	}
645*2151Seric }
646*2151Seric 
647*2151Seric 
648*2151Seric osccsfile(file)
649*2151Seric register char *file;
650*2151Seric {
651*2151Seric 	register short ff, result;
652*2151Seric 	short magic[2];
653*2151Seric 
654*2151Seric 	result = (ff=open(file,0)) > 0
655*2151Seric 	  && read(ff,magic,4) == 4
656*2151Seric 	  && magic[1] == MAGICNO;
657*2151Seric 	close(ff);
658*2151Seric 	return(result);
659*2151Seric }
660*2151Seric 
661*2151Seric 
662*2151Seric 
663*2151Seric /*
664*2151Seric 	Routine to write out either the current line in the packet
665*2151Seric 	(if newline is zero) or the line specified by newline.
666*2151Seric 	A line is actually written (and the x-file is only
667*2151Seric 	opened) if pkt->p_upd is non-zero.  When the current line from
668*2151Seric 	the packet is written, pkt->p_wrttn is set non-zero, and
669*2151Seric 	further attempts to write it are ignored.  When a line is
670*2151Seric 	read shorto the packet, pkt->p_wrttn must be turned off.
671*2151Seric */
672*2151Seric 
673*2151Seric short	Xcreate;
674*2151Seric FILE	*Xiop;
675*2151Seric 
676*2151Seric 
677*2151Seric putline(pkt,newline)
678*2151Seric register struct packet *pkt;
679*2151Seric char *newline;
680*2151Seric {
681*2151Seric 	static char obf[BUFSIZ];
682*2151Seric 	char *xf;
683*2151Seric 	register char *p;
684*2151Seric 
685*2151Seric 	if(pkt->p_upd == 0) return;
686*2151Seric 
687*2151Seric 	if(!Xcreate) {
688*2151Seric 		stat(pkt->p_file,&Statbuf);
689*2151Seric 		xf = auxf(pkt->p_file,'x');
690*2151Seric 		Xiop = xfcreat(xf,Statbuf.st_mode);
691*2151Seric 		setbuf(Xiop,obf);
692*2151Seric 		chown(xf,(Statbuf.st_gid<<8)|Statbuf.st_uid);
693*2151Seric 	}
694*2151Seric 	if (newline)
695*2151Seric 		p = newline;
696*2151Seric 	else {
697*2151Seric 		if(!pkt->p_wrttn++)
698*2151Seric 			p = pkt->p_line;
699*2151Seric 		else
700*2151Seric 			p = 0;
701*2151Seric 	}
702*2151Seric 	if (p) {
703*2151Seric 		fputs(p,Xiop);
704*2151Seric 		if (Xcreate)
705*2151Seric 			while (*p)
706*2151Seric 				pkt->p_nhash =+ *p++;
707*2151Seric 	}
708*2151Seric 	Xcreate = 1;
709*2151Seric }
710*2151Seric 
711*2151Seric 
712*2151Seric convflush(pkt)
713*2151Seric register struct packet *pkt;
714*2151Seric {
715*2151Seric 	register char *p;
716*2151Seric 	char hash[6];
717*2151Seric 
718*2151Seric 	if (pkt->p_upd == 0)
719*2151Seric 		return;
720*2151Seric 	putline(pkt,0);
721*2151Seric 	rewind(Xiop);
722*2151Seric 	sprintf(hash,"%5u",pkt->p_nhash&0xFFFF);
723*2151Seric 	zeropad(hash);
724*2151Seric 	fprintf(Xiop,"%c%c%s\n",CTLCHAR,HEAD,hash);
725*2151Seric 	fclose(Xiop);
726*2151Seric }
727*2151Seric 
728*2151Seric 
729*2151Seric xrm(pkt)
730*2151Seric struct packet *pkt;
731*2151Seric {
732*2151Seric 	if (Xiop)
733*2151Seric 		fclose(Xiop);
734*2151Seric 	if(Xcreate)
735*2151Seric 		unlink(auxf(pkt,'x'));
736*2151Seric 	Xiop = Xcreate = 0;
737*2151Seric }
738*2151Seric 
739*2151Seric 
740*2151Seric char bpf[] "bad p-file (216)";
741*2151Seric 
742*2151Seric rdpfile(f,rp,un)
743*2151Seric char f[], un[];
744*2151Seric short *rp;
745*2151Seric {
746*2151Seric 	register short fd, i;
747*2151Seric 	register char *p;
748*2151Seric 	char s[65], *name;
749*2151Seric 
750*2151Seric 	fd = xopen(f,0);
751*2151Seric 	if ((i=read(fd,s,64))<=0)
752*2151Seric 		fatal(bpf);
753*2151Seric 	close(fd);
754*2151Seric 	p = s;
755*2151Seric 	p[i] = 0;
756*2151Seric 	for (; *p != ' '; p++)
757*2151Seric 		if (*p == 0)
758*2151Seric 			fatal(bpf);
759*2151Seric 	*p = 0;
760*2151Seric 	if ((*rp=patoi(s)) == -1)
761*2151Seric 		fatal(bpf);
762*2151Seric 	++p;
763*2151Seric 	while (*p++ == ' ') ;
764*2151Seric 	name = --p;
765*2151Seric 	for (; *p != '\n'; p++)
766*2151Seric 		if (*p == 0)
767*2151Seric 			fatal(bpf);
768*2151Seric 	*p = 0;
769*2151Seric 	if ((p-name)>SZLNAM)
770*2151Seric 		fatal(bpf);
771*2151Seric 	copy(name,un);
772*2151Seric }
773*2151Seric 
774*2151Seric 
775*2151Seric ckpfile(file)
776*2151Seric register char *file;
777*2151Seric {
778*2151Seric 	short r;
779*2151Seric 	char un[SZLNAM];
780*2151Seric 
781*2151Seric 	if(exists(file)) {
782*2151Seric 		rdpfile(file,&r,un);
783*2151Seric 		fatal(sprintf(Error,"being edited at release %d by `%s' (scv1)",
784*2151Seric 		  r,un));
785*2151Seric 	}
786*2151Seric }
787*2151Seric 
788*2151Seric 
789*2151Seric /*
790*2151Seric 	Bottom level read routines for release 3 SCCS files.
791*2151Seric 
792*2151Seric 	Usage:
793*2151Seric 		struct Ibufr ib;
794*2151Seric 		...
795*2151Seric 		opnr(&ib,"filename");
796*2151Seric 		...
797*2151Seric 		if(getr(&ib) == 1) [end-of-file];
798*2151Seric 		[ib.Irecptr is addr of record (always on word boundary)]
799*2151Seric 		[ib.Ilen is length]
800*2151Seric 
801*2151Seric 	Address HASHADDR of the file must contain a 1-word stored hash count.
802*2151Seric 	If this count is non-zero, then on end-of-file a computed hash count
803*2151Seric 	is compared with it and a fatal error is issued if they aren't equal.
804*2151Seric */
805*2151Seric 
806*2151Seric opnr(buf,file)
807*2151Seric register struct Ibufr *buf;
808*2151Seric char file[];
809*2151Seric {
810*2151Seric 	buf->Ifildes = xopen(file,0);
811*2151Seric 	buf->Irecptr = buf->Ibuff2 + 2;
812*2151Seric 	buf->Iend = buf->Irecptr + 510;
813*2151Seric 	buf->Ilen = 510;
814*2151Seric 	buf->Ibuff3[1] = -128;
815*2151Seric 	buf->Ihcnt = buf->Ihtot = buf->Ihflag = 0;
816*2151Seric }
817*2151Seric 
818*2151Seric 
819*2151Seric getr(buf)
820*2151Seric register struct Ibufr *buf;
821*2151Seric {
822*2151Seric 	register char *p, *q;
823*2151Seric 	short *w;
824*2151Seric 	short i, n;
825*2151Seric 
826*2151Seric 	buf->Irecptr =+ buf->Ilen + !(buf->Ilen & 1);
827*2151Seric 
828*2151Seric 	i = 0;
829*2151Seric 	while(1) {
830*2151Seric 		buf->Ilen = 0;
831*2151Seric 		buf->Ilen = *buf->Irecptr + 128;
832*2151Seric 
833*2151Seric 		if(buf->Irecptr <= buf->Iend - (buf->Ilen+!(buf->Ilen&1)))
834*2151Seric 			return(++buf->Irecptr);
835*2151Seric 
836*2151Seric 		if(i++ == 1) return(1);
837*2151Seric 
838*2151Seric 		q = buf->Irecptr;
839*2151Seric 		p = buf->Irecptr =- 512;
840*2151Seric 
841*2151Seric 		while(q <= buf->Iend) *p++ = *q++;
842*2151Seric 
843*2151Seric 		if((n = read(buf->Ifildes,buf->Ibuff2,512)) <= 0)
844*2151Seric 			return(1);
845*2151Seric 
846*2151Seric 		buf->Iend = buf->Ibuff2 + n - 1;
847*2151Seric 		*(buf->Iend + 1) = -128;
848*2151Seric 
849*2151Seric 		w = buf->Ibuff2;
850*2151Seric 		if(buf->Ihflag == 0) {
851*2151Seric 			buf->Ihflag = 1;
852*2151Seric 			buf->Ihtot = w[HASHADDR>>1];
853*2151Seric 			w[HASHADDR>>1] = 0;
854*2151Seric 		}
855*2151Seric 		if(n < 512) buf->Ibuff2[n] = 0;
856*2151Seric 
857*2151Seric 		buf->Ihcnt =+ sumr(w,&w[(n&1?n-1:n-2)>>1]);
858*2151Seric 
859*2151Seric 		if(n<512 && buf->Ihtot && buf->Ihcnt != buf->Ihtot)
860*2151Seric 			fatal("corrupted file (201)");
861*2151Seric 	}
862*2151Seric }
863*2151Seric 
864*2151Seric 
865*2151Seric sumr(from,to)
866*2151Seric register short *from, *to;
867*2151Seric {
868*2151Seric 	register short sum;
869*2151Seric 
870*2151Seric 	for (sum=0; from<=to; )
871*2151Seric 		sum =+ *from++;
872*2151Seric 	return(sum);
873*2151Seric }
874